mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-03-01 19:23:38 +00:00
More fixes
* Fix !list not distinguishing between players and corpses * Fix /worldkick not working * /silence no longer responds with a message window * Fix 96-99 zone map files * Fix implants not resetting after being jammend * Fix MAXes requiring the wrong certs
This commit is contained in:
parent
8a0a7d8539
commit
08eed0f331
11 changed files with 28599 additions and 28587 deletions
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -168,7 +168,7 @@ object AvatarActor {
|
|||
final case class DeactivateActiveImplants() extends Command
|
||||
|
||||
/** Start implant initialization timers (after zoning or respawn) */
|
||||
final case class InitializeImplants(instant: Boolean = false) extends Command
|
||||
final case class InitializeImplants() extends Command
|
||||
|
||||
/** Deinitialize implants (before zoning or respawning) */
|
||||
final case class DeinitializeImplants() extends Command
|
||||
|
|
@ -582,6 +582,7 @@ class AvatarActor(
|
|||
)
|
||||
case _ => ;
|
||||
}
|
||||
deinitializeImplants()
|
||||
Behaviors.same
|
||||
|
||||
case LearnImplant(terminalGuid, definition) =>
|
||||
|
|
@ -880,8 +881,8 @@ class AvatarActor(
|
|||
)
|
||||
Behaviors.same
|
||||
|
||||
case InitializeImplants(instant) =>
|
||||
initializeImplants(instant)
|
||||
case InitializeImplants() =>
|
||||
initializeImplants()
|
||||
Behaviors.same
|
||||
|
||||
case DeinitializeImplants() =>
|
||||
|
|
@ -890,7 +891,7 @@ class AvatarActor(
|
|||
|
||||
case ResetImplants() =>
|
||||
deinitializeImplants()
|
||||
initializeImplants(instant = false)
|
||||
initializeImplants()
|
||||
Behaviors.same
|
||||
|
||||
case AwardBep(bep) =>
|
||||
|
|
@ -1026,7 +1027,7 @@ class AvatarActor(
|
|||
consumed
|
||||
}
|
||||
|
||||
def initializeImplants(instant: Boolean): Unit = {
|
||||
def initializeImplants(): Unit = {
|
||||
avatar.implants.zipWithIndex.foreach {
|
||||
case (Some(implant), slot) =>
|
||||
// TODO if this implant is Installed but does not have shortcut, add to a free slot or write over slot 61/62/63
|
||||
|
|
@ -1051,7 +1052,7 @@ class AvatarActor(
|
|||
|
||||
implantTimers.get(slot).foreach(_.cancel())
|
||||
implantTimers(slot) = context.system.scheduler.scheduleOnce(
|
||||
if (instant) 0.seconds else implant.definition.InitializationDuration.seconds,
|
||||
implant.definition.InitializationDuration.seconds,
|
||||
() => {
|
||||
avatar = avatar.copy(implants = avatar.implants.map {
|
||||
case Some(implant) => Some(implant.copy(initialized = true))
|
||||
|
|
@ -1071,9 +1072,8 @@ class AvatarActor(
|
|||
avatar = avatar.copy(implants = avatar.implants.zipWithIndex.map {
|
||||
case (Some(implant), slot) =>
|
||||
if (implant.active) {
|
||||
context.self ! DeactivateImplant(implant.definition.implantType)
|
||||
deactivateImplant(implant.definition.implantType)
|
||||
}
|
||||
sessionActor ! SessionActor.SendResponse(ActionProgressMessage(slot + 6, 100))
|
||||
session.get.zone.AvatarEvents ! AvatarServiceMessage(
|
||||
session.get.zone.id,
|
||||
AvatarAction.SendResponse(
|
||||
|
|
|
|||
|
|
@ -318,14 +318,15 @@ class ChatActor(
|
|||
|
||||
(zone.LivePlayers ++ zone.Corpses)
|
||||
.filter(_.CharId != session.player.CharId)
|
||||
.sortBy(_.Name)
|
||||
.sortBy(p => (p.Name, !p.isAlive))
|
||||
.foreach(player => {
|
||||
val color = if (!player.isAlive) "\\#7" else ""
|
||||
sessionActor ! SessionActor.SendResponse(
|
||||
ChatMsg(
|
||||
CMT_GMOPEN,
|
||||
message.wideContents,
|
||||
"Server",
|
||||
s"\\#7${player.Name} (${player.Faction}) [${player.CharId}] at ${player.Position.x.toInt} ${player.Position.y.toInt} ${player.Position.z.toInt}",
|
||||
s"${color}${player.Name} (${player.Faction}) [${player.CharId}] at ${player.Position.x.toInt} ${player.Position.y.toInt} ${player.Position.z.toInt}",
|
||||
message.note
|
||||
)
|
||||
)
|
||||
|
|
@ -824,45 +825,54 @@ class ChatActor(
|
|||
}
|
||||
|
||||
case (CMT_KICK, _, contents) if gmCommandAllowed =>
|
||||
val input = contents.split("\\s+").drop(1)
|
||||
if (input.length > 0) {
|
||||
val numRegex = raw"(\d+)".r
|
||||
val id = input(0)
|
||||
val determination: Player => Boolean = id match {
|
||||
case numRegex(_) => _.CharId == id.toLong
|
||||
case _ => _.Name.equals(id)
|
||||
}
|
||||
session.zone.LivePlayers
|
||||
.find(determination)
|
||||
.orElse(session.zone.Corpses.find(determination)) match {
|
||||
case Some(player) =>
|
||||
input.lift(1) match {
|
||||
case Some(numRegex(time)) =>
|
||||
sessionActor ! SessionActor.Kick(player, Some(time.toLong))
|
||||
case _ =>
|
||||
sessionActor ! SessionActor.Kick(player)
|
||||
}
|
||||
val inputs = contents.split("\\s+").filter(_ != "")
|
||||
inputs.headOption match {
|
||||
case Some(input) =>
|
||||
val determination: Player => Boolean = input.toLongOption match {
|
||||
case Some(id) => _.CharId == id
|
||||
case _ => _.Name.equals(input)
|
||||
}
|
||||
session.zone.LivePlayers
|
||||
.find(determination)
|
||||
.orElse(session.zone.Corpses.find(determination)) match {
|
||||
case Some(player) =>
|
||||
inputs.lift(1).map(_.toLongOption) match {
|
||||
case Some(Some(time)) =>
|
||||
sessionActor ! SessionActor.Kick(player, Some(time))
|
||||
case _ =>
|
||||
sessionActor ! SessionActor.Kick(player)
|
||||
}
|
||||
|
||||
sessionActor ! SessionActor.SendResponse(
|
||||
ChatMsg(
|
||||
CMT_GMOPEN,
|
||||
message.wideContents,
|
||||
"Server",
|
||||
"@kick_o",
|
||||
message.note
|
||||
sessionActor ! SessionActor.SendResponse(
|
||||
ChatMsg(
|
||||
UNK_229,
|
||||
message.wideContents,
|
||||
"Server",
|
||||
"@kick_i",
|
||||
message.note
|
||||
)
|
||||
)
|
||||
)
|
||||
case None =>
|
||||
sessionActor ! SessionActor.SendResponse(
|
||||
ChatMsg(
|
||||
CMT_GMOPEN,
|
||||
message.wideContents,
|
||||
"Server",
|
||||
"@kick_o",
|
||||
message.note
|
||||
case None =>
|
||||
sessionActor ! SessionActor.SendResponse(
|
||||
ChatMsg(
|
||||
UNK_229,
|
||||
message.wideContents,
|
||||
"Server",
|
||||
"@kick_o",
|
||||
message.note
|
||||
)
|
||||
)
|
||||
}
|
||||
case None =>
|
||||
sessionActor ! SessionActor.SendResponse(
|
||||
ChatMsg(
|
||||
UNK_229,
|
||||
message.wideContents,
|
||||
"Server",
|
||||
"@kick_o",
|
||||
message.note
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
case _ =>
|
||||
|
|
@ -874,7 +884,7 @@ class ChatActor(
|
|||
message.messageType match {
|
||||
case CMT_TELL | U_CMT_TELLFROM | CMT_BROADCAST | CMT_SQUAD | CMT_PLATOON | CMT_COMMAND | UNK_45 | UNK_71 |
|
||||
CMT_NOTE | CMT_GMBROADCAST | CMT_GMBROADCAST_NC | CMT_GMBROADCAST_TR | CMT_GMBROADCAST_VS |
|
||||
CMT_GMBROADCASTPOPUP | CMT_GMTELL | U_CMT_GMTELLFROM | UNK_227 =>
|
||||
CMT_GMBROADCASTPOPUP | CMT_GMTELL | U_CMT_GMTELLFROM | UNK_227 | UNK_229 =>
|
||||
sessionActor ! SessionActor.SendResponse(message)
|
||||
case CMT_OPEN =>
|
||||
if (
|
||||
|
|
@ -906,20 +916,20 @@ class ChatActor(
|
|||
if (session.player.silenced) {
|
||||
sessionActor ! SessionActor.SetSilenced(false)
|
||||
sessionActor ! SessionActor.SendResponse(
|
||||
ChatMsg(ChatMessageType.UNK_71, true, "", "@silence_off", None)
|
||||
ChatMsg(ChatMessageType.UNK_229, true, "", "@silence_off", None)
|
||||
)
|
||||
if (!silenceTimer.isCancelled) silenceTimer.cancel()
|
||||
} else {
|
||||
sessionActor ! SessionActor.SetSilenced(true)
|
||||
sessionActor ! SessionActor.SendResponse(
|
||||
ChatMsg(ChatMessageType.UNK_71, true, "", "@silence_on", None)
|
||||
ChatMsg(ChatMessageType.UNK_229, true, "", "@silence_on", None)
|
||||
)
|
||||
silenceTimer = context.system.scheduler.scheduleOnce(
|
||||
time minutes,
|
||||
() => {
|
||||
sessionActor ! SessionActor.SetSilenced(false)
|
||||
sessionActor ! SessionActor.SendResponse(
|
||||
ChatMsg(ChatMessageType.UNK_71, true, "", "@silence_timeout", None)
|
||||
ChatMsg(ChatMessageType.UNK_229, true, "", "@silence_timeout", None)
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1284,6 +1284,8 @@ class SessionActor extends Actor with MDCContextAware {
|
|||
log.info(s"Player ${tplayer.Name} has been loaded")
|
||||
tplayer.avatar = avatar
|
||||
session = session.copy(player = tplayer)
|
||||
avatarActor ! AvatarActor.CreateImplants()
|
||||
avatarActor ! AvatarActor.InitializeImplants()
|
||||
//LoadMapMessage causes the client to send BeginZoningMessage, eventually leading to SetCurrentAvatar
|
||||
val weaponsEnabled =
|
||||
session.zone.map.name != "map11" && session.zone.map.name != "map12" && session.zone.map.name != "map13"
|
||||
|
|
@ -1309,8 +1311,6 @@ class SessionActor extends Actor with MDCContextAware {
|
|||
keepAliveFunc = NormalKeepAlive
|
||||
upstreamMessageCount = 0
|
||||
setAvatar = false
|
||||
avatarActor ! AvatarActor.CreateImplants()
|
||||
avatarActor ! AvatarActor.InitializeImplants()
|
||||
persist()
|
||||
|
||||
case PlayerLoaded(tplayer) =>
|
||||
|
|
@ -1337,24 +1337,24 @@ class SessionActor extends Actor with MDCContextAware {
|
|||
failWithError(s"${tplayer.Name} failed to load anywhere")
|
||||
}
|
||||
|
||||
/*
|
||||
The user is either already in the current zone and merely transporting himself from one location to another,
|
||||
also called "dying", or occasionally "deconstructing,"
|
||||
or is completely switching in between zones.
|
||||
These correspond to the message NewPlayerLoaded for the case of "dying" or the latter zone switching case,
|
||||
and PlayerLoaded for "deconstruction."
|
||||
In the latter case, the user must wait for the zone to be recognized as loaded for the server
|
||||
and this is performed through the send LoadMapMessage, receive BeginZoningMessage exchange
|
||||
The user's player should have already been registered into the new zone
|
||||
and is at some stage of being added to the zone in which they will have control agency in that zone.
|
||||
Whether or not the zone is loaded in the earlier case depends on the destination with respect to the current location.
|
||||
Once all of the following is (assumed) accomplished,
|
||||
the server will attempt to declare that user's player the avatar of the user's client.
|
||||
Reception of certain packets that represent "reported user activity" after that marks the end of avatar loading.
|
||||
If the maximum number of unsuccessful attempts is reached, some course of action is taken.
|
||||
If the player dies, the process does not need to continue.
|
||||
He may or may not be accompanied by a vehicle at any stage of this process.
|
||||
*/
|
||||
/**
|
||||
* The user is either already in the current zone and merely transporting himself from one location to another,
|
||||
* also called "dying", or occasionally "deconstructing,"
|
||||
* or is completely switching in between zones.
|
||||
* These correspond to the message NewPlayerLoaded for the case of "dying" or the latter zone switching case,
|
||||
* and PlayerLoaded for "deconstruction."
|
||||
* In the latter case, the user must wait for the zone to be recognized as loaded for the server
|
||||
* and this is performed through the send LoadMapMessage, receive BeginZoningMessage exchange
|
||||
* The user's player should have already been registered into the new zone
|
||||
* and is at some stage of being added to the zone in which they will have control agency in that zone.
|
||||
* Whether or not the zone is loaded in the earlier case depends on the destination with respect to the current location.
|
||||
* Once all of the following is (assumed) accomplished,
|
||||
* the server will attempt to declare that user's player the avatar of the user's client.
|
||||
* Reception of certain packets that represent "reported user activity" after that marks the end of avatar loading.
|
||||
* If the maximum number of unsuccessful attempts is reached, some course of action is taken.
|
||||
* If the player dies, the process does not need to continue.
|
||||
* He may or may not be accompanied by a vehicle at any stage of this process.
|
||||
*/
|
||||
case SetCurrentAvatar(tplayer, max_attempts, attempt) =>
|
||||
respawnTimer.cancel()
|
||||
val waitingOnUpstream = upstreamMessageCount == 0
|
||||
|
|
@ -3064,6 +3064,7 @@ class SessionActor extends Actor with MDCContextAware {
|
|||
player.Actor ! JammableUnit.ClearJammeredStatus()
|
||||
player.Actor ! JammableUnit.ClearJammeredSound()
|
||||
}
|
||||
// TODO only when respawning after death
|
||||
avatarActor ! AvatarActor.ResetImplants()
|
||||
|
||||
sendResponse(PlanetsideAttributeMessage(PlanetSideGUID(0), 82, 0))
|
||||
|
|
@ -4507,7 +4508,8 @@ class SessionActor extends Actor with MDCContextAware {
|
|||
} else {
|
||||
avatarActor ! AvatarActor.DeactivateImplant(implant.definition.implantType)
|
||||
}
|
||||
case _ => log.error(s"AvatarImplantMessage for unknown or uninitialized implant ${msg}")
|
||||
case Some(implant) if !implant.initialized => ()
|
||||
case _ => log.error(s"AvatarImplantMessage for unknown implant ${msg}")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5683,7 +5685,7 @@ class SessionActor extends Actor with MDCContextAware {
|
|||
log.info("Battleplan: " + msg)
|
||||
|
||||
case msg @ CreateShortcutMessage(player_guid, slot, unk, add, shortcut) =>
|
||||
log.info("CreateShortcutMessage: " + msg)
|
||||
log.debug("CreateShortcutMessage: " + msg)
|
||||
|
||||
case msg @ FriendsRequest(action, friend) =>
|
||||
log.info("FriendsRequest: " + msg)
|
||||
|
|
@ -7116,10 +7118,10 @@ class SessionActor extends Actor with MDCContextAware {
|
|||
*/
|
||||
def RespawnClone(tplayer: Player): Player = {
|
||||
// workaround to make sure player is spawned with full stamina
|
||||
tplayer.avatar = tplayer.avatar.copy(stamina = avatar.maxStamina)
|
||||
val obj = Player.Respawn(tplayer)
|
||||
player.avatar = player.avatar.copy(stamina = avatar.maxStamina)
|
||||
avatarActor ! AvatarActor.RestoreStamina(avatar.maxStamina)
|
||||
avatarActor ! AvatarActor.ResetImplants()
|
||||
val obj = Player.Respawn(tplayer)
|
||||
DefinitionUtil.applyDefaultLoadout(obj)
|
||||
obj.death_by = tplayer.death_by
|
||||
obj
|
||||
|
|
@ -8320,7 +8322,7 @@ class SessionActor extends Actor with MDCContextAware {
|
|||
respawnTime.toMillis,
|
||||
Vector3.Zero,
|
||||
player.Faction,
|
||||
true
|
||||
unk5 = true
|
||||
)
|
||||
)
|
||||
shiftPosition = Some(pos)
|
||||
|
|
|
|||
|
|
@ -726,7 +726,7 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
|
|||
}
|
||||
|
||||
override def CancelJammeredStatus(target: Any): Unit = {
|
||||
avatarActor ! AvatarActor.InitializeImplants(instant = true)
|
||||
avatarActor ! AvatarActor.InitializeImplants()
|
||||
super.CancelJammeredStatus(target)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -115,9 +115,9 @@ object InfantryLoadout {
|
|||
*/
|
||||
def DetermineSubtypeC(subtype: Int): Set[Certification] =
|
||||
subtype match {
|
||||
case 1 => Set(Certification.AIMAX, Certification.UniMAX)
|
||||
case 2 => Set(Certification.AVMAX, Certification.UniMAX)
|
||||
case 3 => Set(Certification.AAMAX, Certification.UniMAX)
|
||||
case 1 => Set(Certification.AAMAX, Certification.UniMAX)
|
||||
case 2 => Set(Certification.AIMAX, Certification.UniMAX)
|
||||
case 3 => Set(Certification.AVMAX, Certification.UniMAX)
|
||||
case _ => Set.empty[Certification]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,30 +164,30 @@ case object MapInfo extends StringEnum[MapInfo] {
|
|||
scale = MapScale.Dim2560
|
||||
)
|
||||
|
||||
case object Map99
|
||||
case object Map96
|
||||
extends MapInfo(
|
||||
value = "map99",
|
||||
value = "map96",
|
||||
checksum = 846603446L,
|
||||
scale = MapScale.Dim4096
|
||||
)
|
||||
|
||||
case object Map98
|
||||
extends MapInfo(
|
||||
value = "map98",
|
||||
checksum = 2810790213L,
|
||||
scale = MapScale.Dim4096
|
||||
)
|
||||
|
||||
case object Map97
|
||||
extends MapInfo(
|
||||
value = "map97",
|
||||
checksum = 2810790213L,
|
||||
scale = MapScale.Dim4096
|
||||
)
|
||||
|
||||
case object Map98
|
||||
extends MapInfo(
|
||||
value = "map98",
|
||||
checksum = 3654267088L,
|
||||
scale = MapScale.Dim4096
|
||||
)
|
||||
|
||||
case object Map96
|
||||
case object Map99
|
||||
extends MapInfo(
|
||||
value = "map96",
|
||||
value = "map99",
|
||||
checksum = 4113726460L,
|
||||
scale = MapScale.Dim4096
|
||||
)
|
||||
|
|
|
|||
|
|
@ -116,13 +116,13 @@ class ChatService(context: ActorContext[ChatService.Command]) extends AbstractBe
|
|||
if (recipient.session.player.silenced) {
|
||||
sender.actor ! MessageResponse(
|
||||
session,
|
||||
ChatMsg(UNK_71, true, "", "@silence_disabled_ack", None),
|
||||
ChatMsg(UNK_229, true, "", "@silence_disabled_ack", None),
|
||||
channel
|
||||
)
|
||||
} else {
|
||||
sender.actor ! MessageResponse(
|
||||
session,
|
||||
ChatMsg(UNK_71, true, "", "@silence_enabled_ack", None),
|
||||
ChatMsg(UNK_229, true, "", "@silence_enabled_ack", None),
|
||||
channel
|
||||
)
|
||||
}
|
||||
|
|
@ -130,14 +130,14 @@ class ChatService(context: ActorContext[ChatService.Command]) extends AbstractBe
|
|||
case None =>
|
||||
sender.actor ! MessageResponse(
|
||||
session,
|
||||
ChatMsg(UNK_71, true, "", s"unknown player '$name'", None),
|
||||
ChatMsg(UNK_229, true, "", s"unknown player '$name'", None),
|
||||
channel
|
||||
)
|
||||
}
|
||||
case (Some(sender), _, _, error) =>
|
||||
sender.actor ! MessageResponse(
|
||||
session,
|
||||
ChatMsg(UNK_71, false, "", error.getOrElse("usage: /silence <name> [<time>]"), None),
|
||||
ChatMsg(UNK_229, false, "", error.getOrElse("usage: /silence <name> [<time>]"), None),
|
||||
channel
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue