mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-07-16 08:55:18 +00:00
changes to the session actor handler classes
This commit is contained in:
parent
7e899e9ef3
commit
f012126fae
6 changed files with 852 additions and 938 deletions
|
|
@ -3,6 +3,8 @@ package net.psforever.actors.session.support
|
|||
|
||||
import akka.actor.typed.scaladsl.adapter._
|
||||
import akka.actor.{ActorContext, typed}
|
||||
import net.psforever.services.Service
|
||||
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
import scala.concurrent.duration._
|
||||
//
|
||||
|
|
@ -29,90 +31,99 @@ class SessionAvatarHandlers(
|
|||
chatActor: typed.ActorRef[ChatActor.Command],
|
||||
implicit val context: ActorContext
|
||||
) extends CommonSessionInterfacingFunctionality {
|
||||
private[support] var lastSeenStreamMessage: Array[Long] = Array.fill[Long](65535)(elem=0L)
|
||||
//TODO player characters only exist within a certain range of GUIDs for a given zone; this is overkill
|
||||
private[support] var lastSeenStreamMessage: Array[Long] = Array.fill[Long](65535)(elem = 0L)
|
||||
|
||||
/**
|
||||
* na
|
||||
*
|
||||
* @param toChannel na
|
||||
* @param guid na
|
||||
* @param reply na
|
||||
*/
|
||||
def handle(toChannel: String, guid: PlanetSideGUID, reply: AvatarResponse.Response): Unit = {
|
||||
val tplayer_guid =
|
||||
if (player != null && player.HasGUID) player.GUID
|
||||
else PlanetSideGUID(0)
|
||||
val resolvedPlayerGuid = if (player != null && player.HasGUID) {
|
||||
player.GUID
|
||||
} else {
|
||||
Service.defaultPlayerGUID
|
||||
}
|
||||
val isNotSameTarget = resolvedPlayerGuid != guid
|
||||
reply match {
|
||||
case AvatarResponse.TeardownConnection() =>
|
||||
log.trace(s"ending ${player.Name}'s old session by event system request (relog)")
|
||||
context.stop(context.self)
|
||||
|
||||
case AvatarResponse.PlayerState(
|
||||
pos,
|
||||
vel,
|
||||
yaw,
|
||||
pitch,
|
||||
yawUpper,
|
||||
_,
|
||||
isCrouching,
|
||||
isJumping,
|
||||
jumpThrust,
|
||||
isCloaking,
|
||||
spectating,
|
||||
_
|
||||
) if isNotSameTarget =>
|
||||
val now = System.currentTimeMillis()
|
||||
val (location, time, distanceSq): (Vector3, Long, Float) = if (spectating) {
|
||||
val r = new scala.util.Random
|
||||
val r1 = 2 + r.nextInt(30).toFloat
|
||||
val r2 = 2 + r.nextInt(4000).toFloat
|
||||
(Vector3(r2, r2, r1), 0L, 0f)
|
||||
} else {
|
||||
val before = lastSeenStreamMessage(guid.guid)
|
||||
val dist = Vector3.DistanceSquared(player.Position, pos)
|
||||
(pos, now - before, dist)
|
||||
}
|
||||
if (distanceSq < 302500 || time > 5000) { // Render distance seems to be approx 525m. Reduce update rate at ~550m to be safe
|
||||
sendResponse(
|
||||
PlayerStateMessage(
|
||||
guid,
|
||||
location,
|
||||
vel,
|
||||
yaw,
|
||||
pitch,
|
||||
yawUpper,
|
||||
timestamp=0,
|
||||
isCrouching,
|
||||
isJumping,
|
||||
jumpThrust,
|
||||
isCloaking
|
||||
)
|
||||
)
|
||||
lastSeenStreamMessage(guid.guid) = now
|
||||
}
|
||||
|
||||
case AvatarResponse.SendResponse(msg) =>
|
||||
sendResponse(msg)
|
||||
|
||||
case AvatarResponse.SendResponseTargeted(target_guid, msg) =>
|
||||
if (tplayer_guid == target_guid) {
|
||||
sendResponse(msg)
|
||||
}
|
||||
case AvatarResponse.SendResponseTargeted(targetGuid, msg) if resolvedPlayerGuid == targetGuid =>
|
||||
sendResponse(msg)
|
||||
|
||||
case AvatarResponse.Revive(target_guid) =>
|
||||
if (tplayer_guid == target_guid) {
|
||||
log.info(s"No time for rest, ${player.Name}. Back on your feet!")
|
||||
sessionData.zoning.spawn.reviveTimer.cancel()
|
||||
sessionData.zoning.spawn.deadState = DeadState.Alive
|
||||
player.Revive
|
||||
val health = player.Health
|
||||
sendResponse(PlanetsideAttributeMessage(target_guid, 0, health))
|
||||
sendResponse(AvatarDeadStateMessage(DeadState.Alive, 0, 0, player.Position, player.Faction, unk5=true))
|
||||
continent.AvatarEvents ! AvatarServiceMessage(
|
||||
continent.id,
|
||||
AvatarAction.PlanetsideAttributeToAll(target_guid, 0, health)
|
||||
)
|
||||
}
|
||||
|
||||
case AvatarResponse.ArmorChanged(suit, subtype) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(ArmorChangedMessage(guid, suit, subtype))
|
||||
}
|
||||
|
||||
case AvatarResponse.ChangeAmmo(weapon_guid, weapon_slot, previous_guid, ammo_id, ammo_guid, ammo_data) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(ObjectDetachMessage(weapon_guid, previous_guid, Vector3.Zero, 0))
|
||||
sendResponse(
|
||||
ObjectCreateMessage(
|
||||
ammo_id,
|
||||
ammo_guid,
|
||||
ObjectCreateMessageParent(weapon_guid, weapon_slot),
|
||||
ammo_data
|
||||
)
|
||||
)
|
||||
sendResponse(ChangeAmmoMessage(weapon_guid, 1))
|
||||
}
|
||||
|
||||
case AvatarResponse.ChangeFireMode(item_guid, mode) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(ChangeFireModeMessage(item_guid, mode))
|
||||
}
|
||||
|
||||
case AvatarResponse.ChangeFireState_Start(weapon_guid) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(ChangeFireStateMessage_Start(weapon_guid))
|
||||
}
|
||||
|
||||
case AvatarResponse.ChangeFireState_Stop(weapon_guid) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(ChangeFireStateMessage_Stop(weapon_guid))
|
||||
}
|
||||
case AvatarResponse.Revive(revivalTargetGuid) if resolvedPlayerGuid == revivalTargetGuid =>
|
||||
log.info(s"No time for rest, ${player.Name}. Back on your feet!")
|
||||
sessionData.zoning.spawn.reviveTimer.cancel()
|
||||
sessionData.zoning.spawn.deadState = DeadState.Alive
|
||||
player.Revive
|
||||
val health = player.Health
|
||||
sendResponse(PlanetsideAttributeMessage(revivalTargetGuid, attribute_type=0, health))
|
||||
sendResponse(AvatarDeadStateMessage(DeadState.Alive, timer_max=0, timer=0, player.Position, player.Faction, unk5=true))
|
||||
continent.AvatarEvents ! AvatarServiceMessage(
|
||||
continent.id,
|
||||
AvatarAction.PlanetsideAttributeToAll(revivalTargetGuid, attribute_type=0, health)
|
||||
)
|
||||
|
||||
case AvatarResponse.ConcealPlayer() =>
|
||||
sendResponse(GenericObjectActionMessage(guid, 9))
|
||||
sendResponse(GenericObjectActionMessage(guid, code=9))
|
||||
|
||||
case AvatarResponse.EnvironmentalDamage(_, _, _) =>
|
||||
//TODO damage marker?
|
||||
sessionData.zoning.CancelZoningProcessWithDescriptiveReason("cancel_dmg")
|
||||
//TODO damage marker?
|
||||
|
||||
case AvatarResponse.Destroy(victim, killer, weapon, pos) =>
|
||||
// guid = victim // killer = killer ;)
|
||||
// guid = victim // killer = killer
|
||||
sendResponse(DestroyMessage(victim, killer, weapon, pos))
|
||||
|
||||
case AvatarResponse.DestroyDisplay(killer, victim, method, unk) =>
|
||||
|
|
@ -123,26 +134,18 @@ class SessionAvatarHandlers(
|
|||
avatarActor ! AvatarActor.AwardCep((100 * Config.app.game.cepRate).toLong)
|
||||
}
|
||||
|
||||
case AvatarResponse.DropItem(pkt) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(pkt)
|
||||
}
|
||||
case AvatarResponse.DropItem(pkt) if isNotSameTarget =>
|
||||
sendResponse(pkt)
|
||||
|
||||
case AvatarResponse.EquipmentInHand(pkt) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(pkt)
|
||||
}
|
||||
case AvatarResponse.EquipmentInHand(pkt) if isNotSameTarget =>
|
||||
sendResponse(pkt)
|
||||
|
||||
case AvatarResponse.GenericObjectAction(object_guid, action_code) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(GenericObjectActionMessage(object_guid, action_code))
|
||||
}
|
||||
case AvatarResponse.GenericObjectAction(objectGuid, actionCode) if isNotSameTarget =>
|
||||
sendResponse(GenericObjectActionMessage(objectGuid, actionCode))
|
||||
|
||||
case AvatarResponse.HitHint(source_guid) =>
|
||||
if (player.isAlive) {
|
||||
sendResponse(HitHint(source_guid, guid))
|
||||
sessionData.zoning.CancelZoningProcessWithDescriptiveReason("cancel_dmg")
|
||||
}
|
||||
case AvatarResponse.HitHint(source_guid) if player.isAlive =>
|
||||
sendResponse(HitHint(source_guid, guid))
|
||||
sessionData.zoning.CancelZoningProcessWithDescriptiveReason("cancel_dmg")
|
||||
|
||||
case AvatarResponse.DropSpecialItem() =>
|
||||
sessionData.dropSpecialSlotItem()
|
||||
|
|
@ -159,32 +162,28 @@ class SessionAvatarHandlers(
|
|||
log.info(s"${player.Name} has died, killed by $cause")
|
||||
val respawnTimer = 300.seconds
|
||||
//drop free hand item
|
||||
player.FreeHand.Equipment match {
|
||||
case Some(item) =>
|
||||
DropEquipmentFromInventory(player)(item)
|
||||
case None => ;
|
||||
player.FreeHand.Equipment.foreach { item =>
|
||||
DropEquipmentFromInventory(player)(item)
|
||||
}
|
||||
sessionData.dropSpecialSlotItem()
|
||||
sessionData.toggleMaxSpecialState(enable = false)
|
||||
if (player.LastDamage match {
|
||||
case Some(damage) => damage.interaction.cause match {
|
||||
|
||||
if (player.LastDamage.flatMap { damage =>
|
||||
Some(damage.interaction.cause match {
|
||||
case cause: ExplodingEntityReason => cause.entity.isInstanceOf[VehicleSpawnPad]
|
||||
case _ => false
|
||||
}
|
||||
case None => false
|
||||
}) {
|
||||
}) }.contains(true)
|
||||
) {
|
||||
//also, @SVCP_Killed_TooCloseToPadOnCreate^n~ or "... within n meters of pad ..."
|
||||
sendResponse(ChatMsg(ChatMessageType.UNK_227, wideContents=false, "", "@SVCP_Killed_OnPadOnCreate", None))
|
||||
sendResponse(ChatMsg(ChatMessageType.UNK_227, wideContents = false, "", "@SVCP_Killed_OnPadOnCreate", None))
|
||||
}
|
||||
sessionData.keepAliveFunc = sessionData.zoning.NormalKeepAlive
|
||||
sessionData.zoning.zoningStatus = Zoning.Status.None
|
||||
sessionData.zoning.spawn.deadState = DeadState.Dead
|
||||
continent.GUID(mount) match {
|
||||
case Some(obj: Vehicle) =>
|
||||
sessionData.vehicles.ConditionalDriverVehicleControl(obj)
|
||||
sessionData.vehicles.serverVehicleControlVelocity = None
|
||||
sessionData.unaccessContainer(obj)
|
||||
case _ => ;
|
||||
continent.GUID(mount).collect { case obj: Vehicle =>
|
||||
sessionData.vehicles.ConditionalDriverVehicleControl(obj)
|
||||
sessionData.vehicles.serverVehicleControlVelocity = None
|
||||
sessionData.unaccessContainer(obj)
|
||||
}
|
||||
sessionData.playerActionsToCancel()
|
||||
sessionData.terminals.CancelAllProximityUnits()
|
||||
|
|
@ -211,180 +210,98 @@ class SessionAvatarHandlers(
|
|||
AvatarActor.savePlayerLocation(player)
|
||||
sessionData.renewCharSavedTimer(fixedLen = 1800L, varLen = 0L)
|
||||
|
||||
case AvatarResponse.LoadPlayer(pkt) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(pkt)
|
||||
}
|
||||
case AvatarResponse.LoadPlayer(pkt) if isNotSameTarget =>
|
||||
sendResponse(pkt)
|
||||
|
||||
case AvatarResponse.LoadProjectile(pkt) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(pkt)
|
||||
}
|
||||
case AvatarResponse.LoadProjectile(pkt) if isNotSameTarget =>
|
||||
sendResponse(pkt)
|
||||
|
||||
case AvatarResponse.ObjectDelete(item_guid, unk) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(ObjectDeleteMessage(item_guid, unk))
|
||||
}
|
||||
case AvatarResponse.ObjectDelete(itemGuid, unk) if isNotSameTarget =>
|
||||
sendResponse(ObjectDeleteMessage(itemGuid, unk))
|
||||
|
||||
case AvatarResponse.ObjectHeld(slot, previousSlot) =>
|
||||
if (tplayer_guid == guid) {
|
||||
if (slot > -1) {
|
||||
sendResponse(ObjectHeldMessage(guid, slot, unk1 = true))
|
||||
//Stop using proximity terminals if player unholsters a weapon
|
||||
if (player.VisibleSlots.contains(slot)) {
|
||||
continent.GUID(sessionData.terminals.usingMedicalTerminal) match {
|
||||
case Some(term: Terminal with ProximityUnit) =>
|
||||
sessionData.terminals.StopUsingProximityUnit(term)
|
||||
case _ => ;
|
||||
}
|
||||
}
|
||||
case AvatarResponse.ObjectHeld(slot, _) if resolvedPlayerGuid == guid && slot > -1 =>
|
||||
sendResponse(ObjectHeldMessage(guid, slot, unk1=true))
|
||||
//Stop using proximity terminals if player unholsters a weapon
|
||||
if (player.VisibleSlots.contains(slot)) {
|
||||
continent.GUID(sessionData.terminals.usingMedicalTerminal).collect {
|
||||
case term: Terminal with ProximityUnit =>
|
||||
sessionData.terminals.StopUsingProximityUnit(term)
|
||||
}
|
||||
} else {
|
||||
sendResponse(ObjectHeldMessage(guid, previousSlot, unk1 = false))
|
||||
}
|
||||
|
||||
case AvatarResponse.ObjectHeld(_, previousSlot) =>
|
||||
sendResponse(ObjectHeldMessage(guid, previousSlot, unk1=false))
|
||||
|
||||
case AvatarResponse.OxygenState(player, vehicle) =>
|
||||
sendResponse(
|
||||
OxygenStateMessage(
|
||||
DrowningTarget(player.guid, player.progress, player.state),
|
||||
vehicle match {
|
||||
case Some(vinfo) => Some(DrowningTarget(vinfo.guid, vinfo.progress, vinfo.state))
|
||||
case None => None
|
||||
}
|
||||
)
|
||||
)
|
||||
sendResponse(OxygenStateMessage(
|
||||
DrowningTarget(player.guid, player.progress, player.state),
|
||||
vehicle.flatMap { vinfo => Some(DrowningTarget(vinfo.guid, vinfo.progress, vinfo.state)) }
|
||||
))
|
||||
|
||||
case AvatarResponse.PlanetsideAttribute(attribute_type, attribute_value) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(PlanetsideAttributeMessage(guid, attribute_type, attribute_value))
|
||||
}
|
||||
case AvatarResponse.PlanetsideAttribute(attributeType, attributeValue) if isNotSameTarget =>
|
||||
sendResponse(PlanetsideAttributeMessage(guid, attributeType, attributeValue))
|
||||
|
||||
case AvatarResponse.PlanetsideAttributeToAll(attribute_type, attribute_value) =>
|
||||
sendResponse(PlanetsideAttributeMessage(guid, attribute_type, attribute_value))
|
||||
case AvatarResponse.PlanetsideAttributeToAll(attributeType, attributeValue) =>
|
||||
sendResponse(PlanetsideAttributeMessage(guid, attributeType, attributeValue))
|
||||
|
||||
case AvatarResponse.PlanetsideAttributeSelf(attribute_type, attribute_value) =>
|
||||
if (tplayer_guid == guid) {
|
||||
sendResponse(PlanetsideAttributeMessage(guid, attribute_type, attribute_value))
|
||||
}
|
||||
case AvatarResponse.PlanetsideAttributeSelf(attributeType, attributeValue) if resolvedPlayerGuid == guid =>
|
||||
sendResponse(PlanetsideAttributeMessage(guid, attributeType, attributeValue))
|
||||
|
||||
case AvatarResponse.PlayerState(
|
||||
pos,
|
||||
vel,
|
||||
yaw,
|
||||
pitch,
|
||||
yaw_upper,
|
||||
_,
|
||||
is_crouching,
|
||||
is_jumping,
|
||||
jump_thrust,
|
||||
is_cloaking,
|
||||
spectating,
|
||||
_
|
||||
) =>
|
||||
if (tplayer_guid != guid) {
|
||||
val now = System.currentTimeMillis()
|
||||
val (location, time, distanceSq): (Vector3, Long, Float) = if (spectating) {
|
||||
val r = new scala.util.Random
|
||||
val r1 = 2 + r.nextInt(30).toFloat
|
||||
val r2 = 2 + r.nextInt(4000).toFloat
|
||||
(Vector3(r2, r2, r1), 0L, 0f)
|
||||
} else {
|
||||
val before = lastSeenStreamMessage(guid.guid)
|
||||
val dist = Vector3.DistanceSquared(player.Position, pos)
|
||||
(pos, now - before, dist)
|
||||
}
|
||||
if (distanceSq < 302500 || time > 5000) { // Render distance seems to be approx 525m. Reduce update rate at ~550m to be safe
|
||||
sendResponse(
|
||||
PlayerStateMessage(
|
||||
guid,
|
||||
location,
|
||||
vel,
|
||||
yaw,
|
||||
pitch,
|
||||
yaw_upper,
|
||||
timestamp = 0,
|
||||
is_crouching,
|
||||
is_jumping,
|
||||
jump_thrust,
|
||||
is_cloaking
|
||||
)
|
||||
)
|
||||
lastSeenStreamMessage(guid.guid) = now
|
||||
}
|
||||
}
|
||||
|
||||
case AvatarResponse.ProjectileExplodes(projectile_guid, projectile) =>
|
||||
case AvatarResponse.ProjectileExplodes(projectileGuid, projectile) =>
|
||||
sendResponse(
|
||||
ProjectileStateMessage(
|
||||
projectile_guid,
|
||||
projectileGuid,
|
||||
projectile.Position,
|
||||
Vector3.Zero,
|
||||
shot_vel = Vector3.Zero,
|
||||
projectile.Orientation,
|
||||
0,
|
||||
sequence_num=0,
|
||||
end=true,
|
||||
PlanetSideGUID(0)
|
||||
hit_target_guid=PlanetSideGUID(0)
|
||||
)
|
||||
)
|
||||
sendResponse(ObjectDeleteMessage(projectile_guid, 2))
|
||||
sendResponse(ObjectDeleteMessage(projectileGuid, unk1=2))
|
||||
|
||||
case AvatarResponse.ProjectileAutoLockAwareness(mode) =>
|
||||
sendResponse(GenericActionMessage(mode))
|
||||
|
||||
case AvatarResponse.ProjectileState(projectile_guid, shot_pos, shot_vel, shot_orient, seq, end, target_guid) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(ProjectileStateMessage(projectile_guid, shot_pos, shot_vel, shot_orient, seq, end, target_guid))
|
||||
}
|
||||
case AvatarResponse.ProjectileState(projectileGuid, shotPos, shotVel, shotOrient, seq, end, targetGuid) if isNotSameTarget =>
|
||||
sendResponse(ProjectileStateMessage(projectileGuid, shotPos, shotVel, shotOrient, seq, end, targetGuid))
|
||||
|
||||
case AvatarResponse.PutDownFDU(target) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(GenericObjectActionMessage(target, 53))
|
||||
}
|
||||
case AvatarResponse.PutDownFDU(target) if isNotSameTarget =>
|
||||
sendResponse(GenericObjectActionMessage(target, code=53))
|
||||
|
||||
case AvatarResponse.Release(tplayer) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sessionData.zoning.spawn.DepictPlayerAsCorpse(tplayer)
|
||||
}
|
||||
case AvatarResponse.Release(tplayer) if isNotSameTarget =>
|
||||
sessionData.zoning.spawn.DepictPlayerAsCorpse(tplayer)
|
||||
|
||||
case AvatarResponse.Reload(item_guid) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(ReloadMessage(item_guid, 1, 0))
|
||||
}
|
||||
case AvatarResponse.Reload(itemGuid) if isNotSameTarget =>
|
||||
sendResponse(ReloadMessage(itemGuid, ammo_clip=1, unk1=0))
|
||||
|
||||
case AvatarResponse.SetEmpire(object_guid, faction) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(SetEmpireMessage(object_guid, faction))
|
||||
}
|
||||
case AvatarResponse.SetEmpire(objectGuid, faction) if isNotSameTarget =>
|
||||
sendResponse(SetEmpireMessage(objectGuid, faction))
|
||||
|
||||
case AvatarResponse.StowEquipment(target, slot, item) =>
|
||||
if (tplayer_guid != guid) {
|
||||
val definition = item.Definition
|
||||
sendResponse(
|
||||
ObjectCreateDetailedMessage(
|
||||
definition.ObjectId,
|
||||
item.GUID,
|
||||
ObjectCreateMessageParent(target, slot),
|
||||
definition.Packet.DetailedConstructorData(item).get
|
||||
)
|
||||
case AvatarResponse.StowEquipment(target, slot, item) if isNotSameTarget =>
|
||||
val definition = item.Definition
|
||||
sendResponse(
|
||||
ObjectCreateDetailedMessage(
|
||||
definition.ObjectId,
|
||||
item.GUID,
|
||||
ObjectCreateMessageParent(target, slot),
|
||||
definition.Packet.DetailedConstructorData(item).get
|
||||
)
|
||||
)
|
||||
|
||||
case AvatarResponse.WeaponDryFire(weaponGuid) if isNotSameTarget =>
|
||||
continent.GUID(weaponGuid).collect {
|
||||
case tool: Tool if tool.Magazine == 0 =>
|
||||
// check that the magazine is still empty before sending WeaponDryFireMessage
|
||||
// if it has been reloaded since then, other clients not see it firing
|
||||
sendResponse(WeaponDryFireMessage(weaponGuid))
|
||||
case _ =>
|
||||
sendResponse(WeaponDryFireMessage(weaponGuid))
|
||||
}
|
||||
|
||||
case AvatarResponse.WeaponDryFire(weapon_guid) =>
|
||||
if (tplayer_guid != guid) {
|
||||
continent.GUID(weapon_guid) match {
|
||||
case Some(tool: Tool) =>
|
||||
// check that the magazine is still empty before sending WeaponDryFireMessage
|
||||
// if it has been reloaded since then, other clients not see it firing
|
||||
if (tool.Magazine == 0) {
|
||||
sendResponse(WeaponDryFireMessage(weapon_guid))
|
||||
}
|
||||
case Some(_) =>
|
||||
sendResponse(WeaponDryFireMessage(weapon_guid))
|
||||
case None => ;
|
||||
}
|
||||
}
|
||||
|
||||
case AvatarResponse.TerminalOrderResult(terminal_guid, action, result) =>
|
||||
sendResponse(ItemTransactionResultMessage(terminal_guid, action, result))
|
||||
case AvatarResponse.TerminalOrderResult(terminalGuid, action, result) =>
|
||||
sendResponse(ItemTransactionResultMessage(terminalGuid, action, result))
|
||||
sessionData.terminals.lastTerminalOrderFulfillment = true
|
||||
if (result &&
|
||||
(action == TransactionType.Buy || action == TransactionType.Loadout)) {
|
||||
|
|
@ -400,79 +317,78 @@ class SessionAvatarHandlers(
|
|||
armor,
|
||||
exosuit,
|
||||
subtype,
|
||||
slot,
|
||||
_,
|
||||
maxhand,
|
||||
old_holsters,
|
||||
oldHolsters,
|
||||
holsters,
|
||||
old_inventory,
|
||||
oldInventory,
|
||||
inventory,
|
||||
drop,
|
||||
delete
|
||||
) =>
|
||||
) if resolvedPlayerGuid == target =>
|
||||
sendResponse(ArmorChangedMessage(target, exosuit, subtype))
|
||||
sendResponse(PlanetsideAttributeMessage(target, 4, armor))
|
||||
if (tplayer_guid == target) {
|
||||
//happening to this player
|
||||
//cleanup
|
||||
sendResponse(ObjectHeldMessage(target, Player.HandsDownSlot, unk1=false))
|
||||
(old_holsters ++ old_inventory ++ delete).foreach {
|
||||
case (_, dguid) => sendResponse(ObjectDeleteMessage(dguid, 0))
|
||||
}
|
||||
//functionally delete
|
||||
delete.foreach { case (obj, _) => TaskWorkflow.execute(GUIDTask.unregisterEquipment(continent.GUID, obj)) }
|
||||
//redraw
|
||||
if (maxhand) {
|
||||
TaskWorkflow.execute(HoldNewEquipmentUp(player)(
|
||||
Tool(GlobalDefinitions.MAXArms(subtype, player.Faction)),
|
||||
0
|
||||
))
|
||||
}
|
||||
//draw free hand
|
||||
player.FreeHand.Equipment match {
|
||||
case Some(obj) =>
|
||||
val definition = obj.Definition
|
||||
sendResponse(
|
||||
ObjectCreateDetailedMessage(
|
||||
definition.ObjectId,
|
||||
obj.GUID,
|
||||
ObjectCreateMessageParent(target, Player.FreeHandSlot),
|
||||
definition.Packet.DetailedConstructorData(obj).get
|
||||
)
|
||||
sendResponse(PlanetsideAttributeMessage(target, attribute_type=4, armor))
|
||||
//happening to this player
|
||||
//cleanup
|
||||
sendResponse(ObjectHeldMessage(target, Player.HandsDownSlot, unk1=false))
|
||||
(oldHolsters ++ oldInventory ++ delete).foreach {
|
||||
case (_, dguid) => sendResponse(ObjectDeleteMessage(dguid, unk1=0))
|
||||
}
|
||||
//functionally delete
|
||||
delete.foreach { case (obj, _) => TaskWorkflow.execute(GUIDTask.unregisterEquipment(continent.GUID, obj)) }
|
||||
//redraw
|
||||
if (maxhand) {
|
||||
TaskWorkflow.execute(HoldNewEquipmentUp(player)(
|
||||
Tool(GlobalDefinitions.MAXArms(subtype, player.Faction)),
|
||||
0
|
||||
))
|
||||
}
|
||||
//draw free hand
|
||||
player.FreeHand.Equipment.foreach { obj =>
|
||||
val definition = obj.Definition
|
||||
sendResponse(
|
||||
ObjectCreateDetailedMessage(
|
||||
definition.ObjectId,
|
||||
obj.GUID,
|
||||
ObjectCreateMessageParent(target, Player.FreeHandSlot),
|
||||
definition.Packet.DetailedConstructorData(obj).get
|
||||
)
|
||||
)
|
||||
}
|
||||
//draw holsters and inventory
|
||||
(holsters ++ inventory).foreach {
|
||||
case InventoryItem(obj, index) =>
|
||||
val definition = obj.Definition
|
||||
sendResponse(
|
||||
ObjectCreateDetailedMessage(
|
||||
definition.ObjectId,
|
||||
obj.GUID,
|
||||
ObjectCreateMessageParent(target, index),
|
||||
definition.Packet.DetailedConstructorData(obj).get
|
||||
)
|
||||
case None => ;
|
||||
}
|
||||
//draw holsters and inventory
|
||||
(holsters ++ inventory).foreach {
|
||||
case InventoryItem(obj, index) =>
|
||||
val definition = obj.Definition
|
||||
sendResponse(
|
||||
ObjectCreateDetailedMessage(
|
||||
definition.ObjectId,
|
||||
obj.GUID,
|
||||
ObjectCreateMessageParent(target, index),
|
||||
definition.Packet.DetailedConstructorData(obj).get
|
||||
)
|
||||
)
|
||||
}
|
||||
DropLeftovers(player)(drop)
|
||||
|
||||
case AvatarResponse.ChangeExosuit(target, armor, exosuit, subtype, slot, _, oldHolsters, holsters, _, _, _, delete) =>
|
||||
sendResponse(ArmorChangedMessage(target, exosuit, subtype))
|
||||
sendResponse(PlanetsideAttributeMessage(target, attribute_type=4, armor))
|
||||
//happening to some other player
|
||||
sendResponse(ObjectHeldMessage(target, slot, unk1 = false))
|
||||
//cleanup
|
||||
(oldHolsters ++ delete).foreach { case (_, guid) => sendResponse(ObjectDeleteMessage(guid, unk1=0)) }
|
||||
//draw holsters
|
||||
holsters.foreach {
|
||||
case InventoryItem(obj, index) =>
|
||||
val definition = obj.Definition
|
||||
sendResponse(
|
||||
ObjectCreateMessage(
|
||||
definition.ObjectId,
|
||||
obj.GUID,
|
||||
ObjectCreateMessageParent(target, index),
|
||||
definition.Packet.ConstructorData(obj).get
|
||||
)
|
||||
}
|
||||
DropLeftovers(player)(drop)
|
||||
} else {
|
||||
//happening to some other player
|
||||
sendResponse(ObjectHeldMessage(target, slot, unk1=false))
|
||||
//cleanup
|
||||
(old_holsters ++ delete).foreach { case (_, guid) => sendResponse(ObjectDeleteMessage(guid, 0)) }
|
||||
//draw holsters
|
||||
holsters.foreach {
|
||||
case InventoryItem(obj, index) =>
|
||||
val definition = obj.Definition
|
||||
sendResponse(
|
||||
ObjectCreateMessage(
|
||||
definition.ObjectId,
|
||||
obj.GUID,
|
||||
ObjectCreateMessageParent(target, index),
|
||||
definition.Packet.ConstructorData(obj).get
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
case AvatarResponse.ChangeLoadout(
|
||||
|
|
@ -480,68 +396,69 @@ class SessionAvatarHandlers(
|
|||
armor,
|
||||
exosuit,
|
||||
subtype,
|
||||
slot,
|
||||
_,
|
||||
maxhand,
|
||||
old_holsters,
|
||||
oldHolsters,
|
||||
holsters,
|
||||
old_inventory,
|
||||
oldInventory,
|
||||
inventory,
|
||||
drops
|
||||
) =>
|
||||
) if resolvedPlayerGuid == target =>
|
||||
sendResponse(ArmorChangedMessage(target, exosuit, subtype))
|
||||
sendResponse(PlanetsideAttributeMessage(target, 4, armor))
|
||||
if (tplayer_guid == target) {
|
||||
//happening to this player
|
||||
sendResponse(ObjectHeldMessage(target, Player.HandsDownSlot, unk1=true))
|
||||
//cleanup
|
||||
(old_holsters ++ old_inventory).foreach {
|
||||
case (obj, objGuid) =>
|
||||
sendResponse(ObjectDeleteMessage(objGuid, 0))
|
||||
TaskWorkflow.execute(GUIDTask.unregisterEquipment(continent.GUID, obj))
|
||||
}
|
||||
//redraw
|
||||
if (maxhand) {
|
||||
TaskWorkflow.execute(HoldNewEquipmentUp(player)(
|
||||
Tool(GlobalDefinitions.MAXArms(subtype, player.Faction)),
|
||||
slot = 0
|
||||
))
|
||||
}
|
||||
sessionData.applyPurchaseTimersBeforePackingLoadout(player, player, holsters ++ inventory)
|
||||
DropLeftovers(player)(drops)
|
||||
} else {
|
||||
//happening to some other player
|
||||
sendResponse(ObjectHeldMessage(target, slot, unk1=false))
|
||||
//cleanup
|
||||
old_holsters.foreach { case (_, guid) => sendResponse(ObjectDeleteMessage(guid, 0)) }
|
||||
//redraw handled by callback
|
||||
sendResponse(PlanetsideAttributeMessage(target, attribute_type = 4, armor))
|
||||
//happening to this player
|
||||
sendResponse(ObjectHeldMessage(target, Player.HandsDownSlot, unk1=true))
|
||||
//cleanup
|
||||
(oldHolsters ++ oldInventory).foreach {
|
||||
case (obj, objGuid) =>
|
||||
sendResponse(ObjectDeleteMessage(objGuid, unk1=0))
|
||||
TaskWorkflow.execute(GUIDTask.unregisterEquipment(continent.GUID, obj))
|
||||
}
|
||||
//redraw
|
||||
if (maxhand) {
|
||||
TaskWorkflow.execute(HoldNewEquipmentUp(player)(
|
||||
Tool(GlobalDefinitions.MAXArms(subtype, player.Faction)),
|
||||
slot = 0
|
||||
))
|
||||
}
|
||||
sessionData.applyPurchaseTimersBeforePackingLoadout(player, player, holsters ++ inventory)
|
||||
DropLeftovers(player)(drops)
|
||||
|
||||
case AvatarResponse.ChangeLoadout(target, armor, exosuit, subtype, slot, _, oldHolsters, _, _, _, _) =>
|
||||
sendResponse(ArmorChangedMessage(target, exosuit, subtype))
|
||||
sendResponse(PlanetsideAttributeMessage(target, attribute_type=4, armor))
|
||||
//happening to some other player
|
||||
sendResponse(ObjectHeldMessage(target, slot, unk1=false))
|
||||
//cleanup
|
||||
oldHolsters.foreach { case (_, guid) => sendResponse(ObjectDeleteMessage(guid, unk1=0)) }
|
||||
//redraw handled by callback
|
||||
|
||||
case AvatarResponse.UseKit(kguid, kObjId) =>
|
||||
sendResponse(
|
||||
UseItemMessage(
|
||||
tplayer_guid,
|
||||
resolvedPlayerGuid,
|
||||
kguid,
|
||||
tplayer_guid,
|
||||
4294967295L,
|
||||
unk3=false,
|
||||
Vector3.Zero,
|
||||
Vector3.Zero,
|
||||
126,
|
||||
0, //sequence time?
|
||||
137,
|
||||
resolvedPlayerGuid,
|
||||
unk2 = 4294967295L,
|
||||
unk3 = false,
|
||||
unk4 = Vector3.Zero,
|
||||
unk5 = Vector3.Zero,
|
||||
unk6 = 126,
|
||||
unk7 = 0, //sequence time?
|
||||
unk8 = 137,
|
||||
kObjId
|
||||
)
|
||||
)
|
||||
sendResponse(ObjectDeleteMessage(kguid, 0))
|
||||
sendResponse(ObjectDeleteMessage(kguid, unk1=0))
|
||||
|
||||
case AvatarResponse.KitNotUsed(_, "") =>
|
||||
sessionData.kitToBeUsed = None
|
||||
|
||||
case AvatarResponse.KitNotUsed(_, msg) =>
|
||||
sessionData.kitToBeUsed = None
|
||||
sendResponse(ChatMsg(ChatMessageType.UNK_225, wideContents=false, "", msg, None))
|
||||
sendResponse(ChatMsg(ChatMessageType.UNK_225, wideContents=false, recipient="", msg, note=None))
|
||||
|
||||
case _ => ;
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,12 +19,12 @@ class SessionGalaxyHandlers(
|
|||
) extends CommonSessionInterfacingFunctionality {
|
||||
def handle(reply: GalaxyResponse.Response): Unit = {
|
||||
reply match {
|
||||
case GalaxyResponse.HotSpotUpdate(zone_index, priority, hot_spot_info) =>
|
||||
case GalaxyResponse.HotSpotUpdate(zoneIndex, priority, hotSpotInfo) =>
|
||||
sendResponse(
|
||||
HotSpotUpdateMessage(
|
||||
zone_index,
|
||||
zoneIndex,
|
||||
priority,
|
||||
hot_spot_info.map { spot => PacketHotSpotInfo(spot.DisplayLocation.x, spot.DisplayLocation.y, 40) }
|
||||
hotSpotInfo.map { spot => PacketHotSpotInfo(spot.DisplayLocation.x, spot.DisplayLocation.y, 40) }
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -44,40 +44,33 @@ class SessionGalaxyHandlers(
|
|||
case GalaxyResponse.FlagMapUpdate(msg) =>
|
||||
sendResponse(msg)
|
||||
|
||||
case GalaxyResponse.TransferPassenger(temp_channel, vehicle, _, manifest) =>
|
||||
case GalaxyResponse.TransferPassenger(tempChannel, vehicle, _, manifest) =>
|
||||
val playerName = player.Name
|
||||
log.debug(s"TransferPassenger: $playerName received the summons to transfer to ${vehicle.Zone.id} ...")
|
||||
(manifest.passengers.find { _.name.equals(playerName) } match {
|
||||
case Some(entry) if vehicle.Seats(entry.mount).occupant.isEmpty =>
|
||||
player.VehicleSeated = None
|
||||
vehicle.Seats(entry.mount).mount(player)
|
||||
player.VehicleSeated = vehicle.GUID
|
||||
Some(vehicle)
|
||||
case Some(entry) if vehicle.Seats(entry.mount).occupant.contains(player) =>
|
||||
Some(vehicle)
|
||||
case Some(entry) =>
|
||||
log.warn(
|
||||
s"TransferPassenger: $playerName tried to mount seat ${entry.mount} during summoning, but it was already occupied, and ${player.Sex.pronounSubject} was rebuked"
|
||||
)
|
||||
None
|
||||
case None =>
|
||||
//log.warn(s"TransferPassenger: $playerName is missing from the manifest of a summoning ${vehicle.Definition.Name} from ${vehicle.Zone.id}")
|
||||
None
|
||||
}).orElse {
|
||||
manifest.cargo.find { _.name.equals(playerName) } match {
|
||||
case Some(entry) =>
|
||||
vehicle.CargoHolds(entry.mount).occupant match {
|
||||
case out @ Some(cargo) if cargo.Seats(0).occupants.exists(_.Name.equals(playerName)) =>
|
||||
out
|
||||
case _ =>
|
||||
None
|
||||
}
|
||||
case None =>
|
||||
manifest.passengers
|
||||
.find { _.name.equals(playerName) }
|
||||
.collect {
|
||||
case entry if vehicle.Seats(entry.mount).occupant.isEmpty =>
|
||||
player.VehicleSeated = None
|
||||
vehicle.Seats(entry.mount).mount(player)
|
||||
player.VehicleSeated = vehicle.GUID
|
||||
Some(vehicle)
|
||||
case entry if vehicle.Seats(entry.mount).occupant.contains(player) =>
|
||||
Some(vehicle)
|
||||
case entry =>
|
||||
log.warn(
|
||||
s"TransferPassenger: $playerName tried to mount seat ${entry.mount} during summoning, but it was already occupied, and ${player.Sex.pronounSubject} was rebuked"
|
||||
)
|
||||
None
|
||||
}
|
||||
}.orElse {
|
||||
manifest.cargo.find { _.name.equals(playerName) }.flatMap { entry =>
|
||||
vehicle.CargoHolds(entry.mount).occupant.collect {
|
||||
case cargo if cargo.Seats(0).occupants.exists(_.Name.equals(playerName)) => cargo
|
||||
}
|
||||
}
|
||||
} match {
|
||||
case Some(v: Vehicle) =>
|
||||
galaxyService ! Service.Leave(Some(temp_channel)) //temporary vehicle-specific channel (see above)
|
||||
galaxyService ! Service.Leave(Some(tempChannel)) //temporary vehicle-specific channel (see above)
|
||||
sessionData.zoning.spawn.deadState = DeadState.Release
|
||||
sendResponse(AvatarDeadStateMessage(DeadState.Release, 0, 0, player.Position, player.Faction, unk5=true))
|
||||
sessionData.zoning.interstellarFerry = Some(v) //on the other continent and registered to that continent's GUID system
|
||||
|
|
@ -85,7 +78,7 @@ class SessionGalaxyHandlers(
|
|||
case _ =>
|
||||
sessionData.zoning.interstellarFerry match {
|
||||
case None =>
|
||||
galaxyService ! Service.Leave(Some(temp_channel)) //no longer being transferred between zones
|
||||
galaxyService ! Service.Leave(Some(tempChannel)) //no longer being transferred between zones
|
||||
sessionData.zoning.interstellarFerryTopLevelGUID = None
|
||||
case Some(_) => ;
|
||||
//wait patiently
|
||||
|
|
@ -95,7 +88,7 @@ class SessionGalaxyHandlers(
|
|||
case GalaxyResponse.LockedZoneUpdate(zone, time) =>
|
||||
sendResponse(ZoneInfoMessage(zone.Number, empire_status=false, lock_time=time))
|
||||
|
||||
case GalaxyResponse.UnlockedZoneUpdate(zone) => ;
|
||||
case GalaxyResponse.UnlockedZoneUpdate(zone) =>
|
||||
sendResponse(ZoneInfoMessage(zone.Number, empire_status=true, lock_time=0L))
|
||||
val popBO = 0
|
||||
val popTR = zone.Players.count(_.faction == PlanetSideEmpire.TR)
|
||||
|
|
@ -103,13 +96,13 @@ class SessionGalaxyHandlers(
|
|||
val popVS = zone.Players.count(_.faction == PlanetSideEmpire.VS)
|
||||
sendResponse(ZonePopulationUpdateMessage(zone.Number, 414, 138, popTR, 138, popNC, 138, popVS, 138, popBO))
|
||||
|
||||
case GalaxyResponse.LogStatusChange(name) =>
|
||||
if (avatar.people.friend.exists { _.name.equals(name) }) {
|
||||
avatarActor ! AvatarActor.MemberListRequest(MemberAction.UpdateFriend, name)
|
||||
}
|
||||
case GalaxyResponse.LogStatusChange(name) if avatar.people.friend.exists { _.name.equals(name) } =>
|
||||
avatarActor ! AvatarActor.MemberListRequest(MemberAction.UpdateFriend, name)
|
||||
|
||||
case GalaxyResponse.SendResponse(msg) =>
|
||||
sendResponse(msg)
|
||||
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import net.psforever.objects.vehicles.MountableWeapons
|
|||
import net.psforever.objects._
|
||||
import net.psforever.packet.game.PlanetsideAttributeEnum.PlanetsideAttributeEnum
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.services.Service
|
||||
import net.psforever.services.local.LocalResponse
|
||||
import net.psforever.types.{ChatMessageType, PlanetSideGUID, Vector3}
|
||||
|
||||
|
|
@ -21,97 +22,106 @@ class SessionLocalHandlers(
|
|||
* @param reply na
|
||||
*/
|
||||
def handle(toChannel: String, guid: PlanetSideGUID, reply: LocalResponse.Response): Unit = {
|
||||
val tplayer_guid = if (player.HasGUID) { player.GUID }
|
||||
else { PlanetSideGUID(0) }
|
||||
val resolvedPlayerGuid = if (player.HasGUID) {
|
||||
player.GUID
|
||||
} else {
|
||||
Service.defaultPlayerGUID
|
||||
}
|
||||
val isNotSameTarget = resolvedPlayerGuid != guid
|
||||
reply match {
|
||||
case LocalResponse.DeployableMapIcon(behavior, deployInfo) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(DeployableObjectsInfoMessage(behavior, deployInfo))
|
||||
}
|
||||
case LocalResponse.DeployableMapIcon(behavior, deployInfo) if isNotSameTarget =>
|
||||
sendResponse(DeployableObjectsInfoMessage(behavior, deployInfo))
|
||||
|
||||
case LocalResponse.DeployableUIFor(item) =>
|
||||
sessionData.updateDeployableUIElements(avatar.deployables.UpdateUIElement(item))
|
||||
|
||||
case LocalResponse.Detonate(dguid, _: BoomerDeployable) =>
|
||||
sendResponse(TriggerEffectMessage(dguid, "detonate_boomer"))
|
||||
sendResponse(PlanetsideAttributeMessage(dguid, 29, 1))
|
||||
sendResponse(ObjectDeleteMessage(dguid, 0))
|
||||
sendResponse(PlanetsideAttributeMessage(dguid, attribute_type=29, attribute_value=1))
|
||||
sendResponse(ObjectDeleteMessage(dguid, unk1=0))
|
||||
|
||||
case LocalResponse.Detonate(dguid, _: ExplosiveDeployable) =>
|
||||
sendResponse(GenericObjectActionMessage(dguid, 19))
|
||||
sendResponse(PlanetsideAttributeMessage(dguid, 29, 1))
|
||||
sendResponse(ObjectDeleteMessage(dguid, 0))
|
||||
sendResponse(GenericObjectActionMessage(dguid, code=19))
|
||||
sendResponse(PlanetsideAttributeMessage(dguid, attribute_type=29, attribute_value=1))
|
||||
sendResponse(ObjectDeleteMessage(dguid, unk1=0))
|
||||
|
||||
case LocalResponse.Detonate(_, obj) =>
|
||||
log.warn(s"LocalResponse.Detonate: ${obj.Definition.Name} not configured to explode correctly")
|
||||
|
||||
case LocalResponse.DoorOpens(door_guid) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(GenericObjectStateMsg(door_guid, 16))
|
||||
}
|
||||
case LocalResponse.DoorOpens(doorGuid) if isNotSameTarget =>
|
||||
sendResponse(GenericObjectStateMsg(doorGuid, state=16))
|
||||
|
||||
case LocalResponse.DoorCloses(door_guid) => //door closes for everyone
|
||||
sendResponse(GenericObjectStateMsg(door_guid, 17))
|
||||
case LocalResponse.DoorCloses(doorGuid) => //door closes for everyone
|
||||
sendResponse(GenericObjectStateMsg(doorGuid, state=17))
|
||||
|
||||
case LocalResponse.EliminateDeployable(obj: TurretDeployable, dguid, _, _) if obj.Destroyed =>
|
||||
sendResponse(ObjectDeleteMessage(dguid, unk1=0))
|
||||
|
||||
case LocalResponse.EliminateDeployable(obj: TurretDeployable, dguid, pos, _) =>
|
||||
if (obj.Destroyed) {
|
||||
sendResponse(ObjectDeleteMessage(dguid, 0))
|
||||
} else {
|
||||
obj.Destroyed = true
|
||||
DeconstructDeployable(
|
||||
obj,
|
||||
dguid,
|
||||
pos,
|
||||
obj.Orientation,
|
||||
if (obj.MountPoints.isEmpty) 2 else 1
|
||||
)
|
||||
}
|
||||
obj.Destroyed = true
|
||||
DeconstructDeployable(
|
||||
obj,
|
||||
dguid,
|
||||
pos,
|
||||
obj.Orientation,
|
||||
deletionType= if (obj.MountPoints.isEmpty) { 2 } else { 1 }
|
||||
)
|
||||
|
||||
case LocalResponse.EliminateDeployable(obj: ExplosiveDeployable, dguid, _, _)
|
||||
if obj.Destroyed || obj.Jammed || obj.Health == 0 =>
|
||||
sendResponse(ObjectDeleteMessage(dguid, unk1=0))
|
||||
|
||||
case LocalResponse.EliminateDeployable(obj: ExplosiveDeployable, dguid, pos, effect) =>
|
||||
if (obj.Destroyed || obj.Jammed || obj.Health == 0) {
|
||||
sendResponse(ObjectDeleteMessage(dguid, 0))
|
||||
} else {
|
||||
obj.Destroyed = true
|
||||
DeconstructDeployable(obj, dguid, pos, obj.Orientation, effect)
|
||||
}
|
||||
obj.Destroyed = true
|
||||
DeconstructDeployable(obj, dguid, pos, obj.Orientation, effect)
|
||||
|
||||
case LocalResponse.EliminateDeployable(obj: TelepadDeployable, dguid, _, _) if obj.Active && obj.Destroyed =>
|
||||
//if active, deactivate
|
||||
obj.Active = false
|
||||
sendResponse(GenericObjectActionMessage(dguid, code=29))
|
||||
sendResponse(GenericObjectActionMessage(dguid, code=30))
|
||||
//standard deployable elimination behavior
|
||||
sendResponse(ObjectDeleteMessage(dguid, unk1=0))
|
||||
|
||||
case LocalResponse.EliminateDeployable(obj: TelepadDeployable, dguid, pos, _) if obj.Active =>
|
||||
//if active, deactivate
|
||||
obj.Active = false
|
||||
sendResponse(GenericObjectActionMessage(dguid, code=29))
|
||||
sendResponse(GenericObjectActionMessage(dguid, code=30))
|
||||
//standard deployable elimination behavior
|
||||
obj.Destroyed = true
|
||||
DeconstructDeployable(obj, dguid, pos, obj.Orientation, deletionType=2)
|
||||
|
||||
case LocalResponse.EliminateDeployable(obj: TelepadDeployable, dguid, _, _) if obj.Destroyed =>
|
||||
//standard deployable elimination behavior
|
||||
sendResponse(ObjectDeleteMessage(dguid, unk1=0))
|
||||
|
||||
case LocalResponse.EliminateDeployable(obj: TelepadDeployable, dguid, pos, _) =>
|
||||
//if active, deactivate
|
||||
if (obj.Active) {
|
||||
obj.Active = false
|
||||
sendResponse(GenericObjectActionMessage(dguid, 29))
|
||||
sendResponse(GenericObjectActionMessage(dguid, 30))
|
||||
}
|
||||
//standard deployable elimination behavior
|
||||
if (obj.Destroyed) {
|
||||
sendResponse(ObjectDeleteMessage(dguid, 0))
|
||||
} else {
|
||||
obj.Destroyed = true
|
||||
DeconstructDeployable(obj, dguid, pos, obj.Orientation, deletionType = 2)
|
||||
}
|
||||
obj.Destroyed = true
|
||||
DeconstructDeployable(obj, dguid, pos, obj.Orientation, deletionType=2)
|
||||
|
||||
case LocalResponse.EliminateDeployable(obj, dguid, _, _) if obj.Destroyed =>
|
||||
sendResponse(ObjectDeleteMessage(dguid, unk1=0))
|
||||
|
||||
case LocalResponse.EliminateDeployable(obj, dguid, pos, effect) =>
|
||||
if (obj.Destroyed) {
|
||||
sendResponse(ObjectDeleteMessage(dguid, 0))
|
||||
} else {
|
||||
obj.Destroyed = true
|
||||
DeconstructDeployable(obj, dguid, pos, obj.Orientation, effect)
|
||||
}
|
||||
obj.Destroyed = true
|
||||
DeconstructDeployable(obj, dguid, pos, obj.Orientation, effect)
|
||||
|
||||
case LocalResponse.SendHackMessageHackCleared(target_guid, unk1, unk2) =>
|
||||
sendResponse(HackMessage(0, target_guid, guid, 0, unk1, HackState.HackCleared, unk2))
|
||||
case LocalResponse.SendHackMessageHackCleared(targetGuid, unk1, unk2) =>
|
||||
sendResponse(HackMessage(unk1=0, targetGuid, guid, progress=0, unk1, HackState.HackCleared, unk2))
|
||||
|
||||
case LocalResponse.HackObject(target_guid, unk1, unk2) =>
|
||||
HackObject(target_guid, unk1, unk2)
|
||||
case LocalResponse.HackObject(targetGuid, unk1, unk2) =>
|
||||
HackObject(targetGuid, unk1, unk2)
|
||||
|
||||
case LocalResponse.SendPlanetsideAttributeMessage(target_guid, attribute_number, attribute_value) =>
|
||||
SendPlanetsideAttributeMessage(target_guid, attribute_number, attribute_value)
|
||||
case LocalResponse.SendPlanetsideAttributeMessage(targetGuid, attributeType, attributeValue) =>
|
||||
SendPlanetsideAttributeMessage(targetGuid, attributeType, attributeValue)
|
||||
|
||||
case LocalResponse.SendGenericObjectActionMessage(target_guid, action_number) =>
|
||||
sendResponse(GenericObjectActionMessage(target_guid, action_number))
|
||||
case LocalResponse.SendGenericObjectActionMessage(targetGuid, actionNumber) =>
|
||||
sendResponse(GenericObjectActionMessage(targetGuid, actionNumber))
|
||||
|
||||
case LocalResponse.SendGenericActionMessage(action_number) =>
|
||||
sendResponse(GenericActionMessage(action_number))
|
||||
case LocalResponse.SendGenericActionMessage(actionNumber) =>
|
||||
sendResponse(GenericActionMessage(actionNumber))
|
||||
|
||||
case LocalResponse.SendChatMsg(msg) =>
|
||||
sendResponse(msg)
|
||||
|
|
@ -121,49 +131,43 @@ class SessionLocalHandlers(
|
|||
|
||||
case LocalResponse.LluSpawned(llu) =>
|
||||
// Create LLU on client
|
||||
sendResponse(
|
||||
ObjectCreateMessage(
|
||||
llu.Definition.ObjectId,
|
||||
llu.GUID,
|
||||
llu.Definition.Packet.ConstructorData(llu).get
|
||||
)
|
||||
)
|
||||
sendResponse(TriggerSoundMessage(TriggeredSound.LLUMaterialize, llu.Position, unk = 20, 0.8000001f))
|
||||
sendResponse(ObjectCreateMessage(
|
||||
llu.Definition.ObjectId,
|
||||
llu.GUID,
|
||||
llu.Definition.Packet.ConstructorData(llu).get
|
||||
))
|
||||
sendResponse(TriggerSoundMessage(TriggeredSound.LLUMaterialize, llu.Position, unk=20, volume=0.8000001f))
|
||||
|
||||
case LocalResponse.LluDespawned(lluGuid, position) =>
|
||||
sendResponse(TriggerSoundMessage(TriggeredSound.LLUDeconstruct, position, unk = 20, 0.8000001f))
|
||||
sendResponse(ObjectDeleteMessage(lluGuid, 0))
|
||||
sendResponse(TriggerSoundMessage(TriggeredSound.LLUDeconstruct, position, unk=20, volume=0.8000001f))
|
||||
sendResponse(ObjectDeleteMessage(lluGuid, unk1=0))
|
||||
// If the player was holding the LLU, remove it from their tracked special item slot
|
||||
sessionData.specialItemSlotGuid match {
|
||||
case Some(guid) if guid == lluGuid =>
|
||||
sessionData.specialItemSlotGuid = None
|
||||
player.Carrying = None
|
||||
case _ => ()
|
||||
sessionData.specialItemSlotGuid.foreach { case guid if guid == lluGuid =>
|
||||
sessionData.specialItemSlotGuid = None
|
||||
player.Carrying = None
|
||||
}
|
||||
|
||||
case LocalResponse.ObjectDelete(object_guid, unk) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(ObjectDeleteMessage(object_guid, unk))
|
||||
}
|
||||
case LocalResponse.ObjectDelete(objectGuid, unk) if isNotSameTarget =>
|
||||
sendResponse(ObjectDeleteMessage(objectGuid, unk))
|
||||
|
||||
case LocalResponse.ProximityTerminalEffect(object_guid, true) =>
|
||||
sendResponse(ProximityTerminalUseMessage(PlanetSideGUID(0), object_guid, unk=true))
|
||||
sendResponse(ProximityTerminalUseMessage(Service.defaultPlayerGUID, object_guid, unk=true))
|
||||
|
||||
case LocalResponse.ProximityTerminalEffect(object_guid, false) =>
|
||||
sendResponse(ProximityTerminalUseMessage(PlanetSideGUID(0), object_guid, unk=false))
|
||||
sessionData.terminals.ForgetAllProximityTerminals(object_guid)
|
||||
case LocalResponse.ProximityTerminalEffect(objectGuid, false) =>
|
||||
sendResponse(ProximityTerminalUseMessage(Service.defaultPlayerGUID, objectGuid, unk=false))
|
||||
sessionData.terminals.ForgetAllProximityTerminals(objectGuid)
|
||||
|
||||
case LocalResponse.RouterTelepadMessage(msg) =>
|
||||
sendResponse(ChatMsg(ChatMessageType.UNK_229, wideContents=false, "", msg, None))
|
||||
sendResponse(ChatMsg(ChatMessageType.UNK_229, wideContents=false, recipient="", msg, note=None))
|
||||
|
||||
case LocalResponse.RouterTelepadTransport(passenger_guid, src_guid, dest_guid) =>
|
||||
sessionData.useRouterTelepadEffect(passenger_guid, src_guid, dest_guid)
|
||||
case LocalResponse.RouterTelepadTransport(passengerGuid, srcGuid, destGuid) =>
|
||||
sessionData.useRouterTelepadEffect(passengerGuid, srcGuid, destGuid)
|
||||
|
||||
case LocalResponse.SendResponse(msg) =>
|
||||
sendResponse(msg)
|
||||
|
||||
case LocalResponse.SetEmpire(object_guid, empire) =>
|
||||
sendResponse(SetEmpireMessage(object_guid, empire))
|
||||
case LocalResponse.SetEmpire(objectGuid, empire) =>
|
||||
sendResponse(SetEmpireMessage(objectGuid, empire))
|
||||
|
||||
case LocalResponse.ShuttleEvent(ev) =>
|
||||
val msg = OrbitalShuttleTimeMsg(
|
||||
|
|
@ -172,7 +176,7 @@ class SessionLocalHandlers(
|
|||
ev.t1,
|
||||
ev.t2,
|
||||
ev.t3,
|
||||
ev.pairs.map { case ((a, b), c) => PadAndShuttlePair(a, b, c) }
|
||||
pairs=ev.pairs.map { case ((a, b), c) => PadAndShuttlePair(a, b, c) }
|
||||
)
|
||||
sendResponse(msg)
|
||||
|
||||
|
|
@ -183,42 +187,33 @@ class SessionLocalHandlers(
|
|||
sendResponse(ObjectDetachMessage(pguid, sguid, pos, orient))
|
||||
|
||||
case LocalResponse.ShuttleState(sguid, pos, orient, state) =>
|
||||
sendResponse(VehicleStateMessage(sguid, 0, pos, orient, None, Some(state), 0, 0, 15, is_decelerating=false, is_cloaked=false))
|
||||
sendResponse(VehicleStateMessage(sguid, unk1=0, pos, orient, vel=None, Some(state), unk3=0, unk4=0, wheel_direction=15, is_decelerating=false, is_cloaked=false))
|
||||
|
||||
case LocalResponse.ToggleTeleportSystem(router, system_plan) =>
|
||||
sessionData.toggleTeleportSystem(router, system_plan)
|
||||
case LocalResponse.ToggleTeleportSystem(router, systemPlan) =>
|
||||
sessionData.toggleTeleportSystem(router, systemPlan)
|
||||
|
||||
case LocalResponse.TriggerEffect(target_guid, effect, effectInfo, triggerLocation) =>
|
||||
sendResponse(TriggerEffectMessage(target_guid, effect, effectInfo, triggerLocation))
|
||||
case LocalResponse.TriggerEffect(targetGuid, effect, effectInfo, triggerLocation) =>
|
||||
sendResponse(TriggerEffectMessage(targetGuid, effect, effectInfo, triggerLocation))
|
||||
|
||||
case LocalResponse.TriggerSound(sound, pos, unk, volume) =>
|
||||
sendResponse(TriggerSoundMessage(sound, pos, unk, volume))
|
||||
|
||||
case LocalResponse.UpdateForceDomeStatus(building_guid, activated) =>
|
||||
if (activated) {
|
||||
sendResponse(GenericObjectActionMessage(building_guid, 11))
|
||||
} else {
|
||||
sendResponse(GenericObjectActionMessage(building_guid, 12))
|
||||
}
|
||||
case LocalResponse.UpdateForceDomeStatus(buildingGuid, activated) if activated =>
|
||||
sendResponse(GenericObjectActionMessage(buildingGuid, 11))
|
||||
|
||||
case LocalResponse.RechargeVehicleWeapon(vehicle_guid, weapon_guid) =>
|
||||
if (tplayer_guid == guid) {
|
||||
continent.GUID(vehicle_guid) match {
|
||||
case Some(vehicle: MountableWeapons) =>
|
||||
vehicle.PassengerInSeat(player) match {
|
||||
case Some(seat_num: Int) =>
|
||||
vehicle.WeaponControlledFromSeat(seat_num) foreach {
|
||||
case weapon: Tool if weapon.GUID == weapon_guid =>
|
||||
sendResponse(InventoryStateMessage(weapon.AmmoSlot.Box.GUID, weapon.GUID, weapon.Magazine))
|
||||
case _ => ;
|
||||
}
|
||||
case _ => ;
|
||||
}
|
||||
case _ => ;
|
||||
case LocalResponse.UpdateForceDomeStatus(buildingGuid, _) =>
|
||||
sendResponse(GenericObjectActionMessage(buildingGuid, 12))
|
||||
|
||||
case LocalResponse.RechargeVehicleWeapon(vehicleGuid, weaponGuid) if resolvedPlayerGuid == guid =>
|
||||
continent.GUID(vehicleGuid).collect { case vehicle: MountableWeapons =>
|
||||
vehicle.PassengerInSeat(player).collect { seat_num =>
|
||||
vehicle.WeaponControlledFromSeat(seat_num).collect { case weapon: Tool if weapon.GUID == weaponGuid =>
|
||||
sendResponse(InventoryStateMessage(weapon.AmmoSlot.Box.GUID, weapon.GUID, weapon.Magazine))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case _ => ;
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -244,25 +239,25 @@ class SessionLocalHandlers(
|
|||
|
||||
/**
|
||||
* na
|
||||
* @param target_guid na
|
||||
* @param targetGuid na
|
||||
* @param unk1 na
|
||||
* @param unk2 na
|
||||
*/
|
||||
def HackObject(target_guid: PlanetSideGUID, unk1: Long, unk2: Long): Unit = {
|
||||
sendResponse(HackMessage(0, target_guid, PlanetSideGUID(0), 100, unk1, HackState.Hacked, unk2))
|
||||
def HackObject(targetGuid: PlanetSideGUID, unk1: Long, unk2: Long): Unit = {
|
||||
sendResponse(HackMessage(unk1=0, targetGuid, player_guid=Service.defaultPlayerGUID, progress=100, unk1, HackState.Hacked, unk2))
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a PlanetsideAttributeMessage packet to the client
|
||||
* @param target_guid The target of the attribute
|
||||
* @param attribute_number The attribute number
|
||||
* @param attribute_value The attribute value
|
||||
* @param targetGuid The target of the attribute
|
||||
* @param attributeType The attribute number
|
||||
* @param attributeValue The attribute value
|
||||
*/
|
||||
def SendPlanetsideAttributeMessage(
|
||||
target_guid: PlanetSideGUID,
|
||||
attribute_number: PlanetsideAttributeEnum,
|
||||
attribute_value: Long
|
||||
targetGuid: PlanetSideGUID,
|
||||
attributeType: PlanetsideAttributeEnum,
|
||||
attributeValue: Long
|
||||
): Unit = {
|
||||
sendResponse(PlanetsideAttributeMessage(target_guid, attribute_number, attribute_value))
|
||||
sendResponse(PlanetsideAttributeMessage(targetGuid, attributeType, attributeValue))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,176 +31,177 @@ class SessionMountHandlers(
|
|||
*/
|
||||
def handle(tplayer: Player, reply: Mountable.Exchange): Unit = {
|
||||
reply match {
|
||||
case Mountable.CanMount(obj: ImplantTerminalMech, seat_number, _) =>
|
||||
case Mountable.CanMount(obj: ImplantTerminalMech, seatNumber, _) =>
|
||||
sessionData.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||
log.info(s"${player.Name} mounts an implant terminal")
|
||||
sessionData.terminals.CancelAllProximityUnits()
|
||||
MountingAction(tplayer, obj, seat_number)
|
||||
MountingAction(tplayer, obj, seatNumber)
|
||||
sessionData.keepAliveFunc = sessionData.keepAlivePersistence
|
||||
|
||||
case Mountable.CanMount(obj: Vehicle, seat_number, _) if obj.Definition == GlobalDefinitions.orbital_shuttle =>
|
||||
case Mountable.CanMount(obj: Vehicle, seatNumber, _)
|
||||
if obj.Definition == GlobalDefinitions.orbital_shuttle =>
|
||||
sessionData.zoning.CancelZoningProcessWithDescriptiveReason("cancel_mount")
|
||||
log.info(s"${player.Name} mounts the orbital shuttle")
|
||||
sessionData.terminals.CancelAllProximityUnits()
|
||||
MountingAction(tplayer, obj, seat_number)
|
||||
MountingAction(tplayer, obj, seatNumber)
|
||||
sessionData.keepAliveFunc = sessionData.keepAlivePersistence
|
||||
|
||||
case Mountable.CanMount(obj: Vehicle, seat_number, _) =>
|
||||
case Mountable.CanMount(obj: Vehicle, seatNumber, _) =>
|
||||
sessionData.zoning.CancelZoningProcessWithDescriptiveReason("cancel_mount")
|
||||
log.info(s"${player.Name} mounts the ${obj.Definition.Name} in ${
|
||||
obj.SeatPermissionGroup(seat_number) match {
|
||||
obj.SeatPermissionGroup(seatNumber) match {
|
||||
case Some(AccessPermissionGroup.Driver) => "the driver seat"
|
||||
case Some(seatType) => s"a $seatType seat (#$seat_number)"
|
||||
case Some(seatType) => s"a $seatType seat (#$seatNumber)"
|
||||
case None => "a seat"
|
||||
}
|
||||
}")
|
||||
val obj_guid: PlanetSideGUID = obj.GUID
|
||||
sessionData.terminals.CancelAllProximityUnits()
|
||||
sendResponse(PlanetsideAttributeMessage(obj_guid, 0, obj.Health))
|
||||
sendResponse(PlanetsideAttributeMessage(obj_guid, attribute_type=0, obj.Health))
|
||||
sendResponse(PlanetsideAttributeMessage(obj_guid, obj.Definition.shieldUiAttribute, obj.Shields))
|
||||
if (obj.Definition == GlobalDefinitions.ant) {
|
||||
sendResponse(PlanetsideAttributeMessage(obj_guid, 45, obj.NtuCapacitorScaled))
|
||||
sendResponse(PlanetsideAttributeMessage(obj_guid, attribute_type=45, obj.NtuCapacitorScaled))
|
||||
}
|
||||
if (obj.Definition.MaxCapacitor > 0) {
|
||||
sendResponse(PlanetsideAttributeMessage(obj_guid, 113, obj.Capacitor))
|
||||
sendResponse(PlanetsideAttributeMessage(obj_guid, attribute_type=113, obj.Capacitor))
|
||||
}
|
||||
if (seat_number == 0) {
|
||||
if (seatNumber == 0) {
|
||||
if (obj.Definition == GlobalDefinitions.quadstealth) {
|
||||
//wraith cloak state matches the cloak state of the driver
|
||||
//phantasm doesn't uncloak if the driver is uncloaked and no other vehicle cloaks
|
||||
obj.Cloaked = tplayer.Cloaked
|
||||
}
|
||||
sendResponse(GenericObjectActionMessage(obj_guid, 11))
|
||||
} else if (obj.WeaponControlledFromSeat(seat_number).isEmpty) {
|
||||
sendResponse(GenericObjectActionMessage(obj_guid, code=11))
|
||||
} else if (obj.WeaponControlledFromSeat(seatNumber).isEmpty) {
|
||||
sessionData.keepAliveFunc = sessionData.keepAlivePersistence
|
||||
}
|
||||
sessionData.accessContainer(obj)
|
||||
sessionData.updateWeaponAtSeatPosition(obj, seat_number)
|
||||
MountingAction(tplayer, obj, seat_number)
|
||||
sessionData.updateWeaponAtSeatPosition(obj, seatNumber)
|
||||
MountingAction(tplayer, obj, seatNumber)
|
||||
|
||||
case Mountable.CanMount(obj: FacilityTurret, seat_number, _) =>
|
||||
case Mountable.CanMount(obj: FacilityTurret, seatNumber, _) =>
|
||||
sessionData.zoning.CancelZoningProcessWithDescriptiveReason("cancel_mount")
|
||||
if (!obj.isUpgrading) {
|
||||
log.info(s"${player.Name} mounts the ${obj.Definition.Name}")
|
||||
if (obj.Definition == GlobalDefinitions.vanu_sentry_turret) {
|
||||
obj.Zone.LocalEvents ! LocalServiceMessage(obj.Zone.id, LocalAction.SetEmpire(obj.GUID, player.Faction))
|
||||
}
|
||||
sendResponse(PlanetsideAttributeMessage(obj.GUID, 0, obj.Health))
|
||||
sessionData.updateWeaponAtSeatPosition(obj, seat_number)
|
||||
MountingAction(tplayer, obj, seat_number)
|
||||
sendResponse(PlanetsideAttributeMessage(obj.GUID, attribute_type=0, obj.Health))
|
||||
sessionData.updateWeaponAtSeatPosition(obj, seatNumber)
|
||||
MountingAction(tplayer, obj, seatNumber)
|
||||
} else {
|
||||
log.warn(
|
||||
s"MountVehicleMsg: ${tplayer.Name} wants to mount turret ${obj.GUID.guid}, but needs to wait until it finishes updating"
|
||||
)
|
||||
}
|
||||
|
||||
case Mountable.CanMount(obj: PlanetSideGameObject with WeaponTurret, seat_number, _) =>
|
||||
case Mountable.CanMount(obj: PlanetSideGameObject with WeaponTurret, seatNumber, _) =>
|
||||
sessionData.zoning.CancelZoningProcessWithDescriptiveReason("cancel_mount")
|
||||
log.info(s"${player.Name} mounts the ${obj.Definition.asInstanceOf[BasicDefinition].Name}")
|
||||
sendResponse(PlanetsideAttributeMessage(obj.GUID, 0, obj.Health))
|
||||
sessionData.updateWeaponAtSeatPosition(obj, seat_number)
|
||||
MountingAction(tplayer, obj, seat_number)
|
||||
sendResponse(PlanetsideAttributeMessage(obj.GUID, attribute_type=0, obj.Health))
|
||||
sessionData.updateWeaponAtSeatPosition(obj, seatNumber)
|
||||
MountingAction(tplayer, obj, seatNumber)
|
||||
|
||||
case Mountable.CanMount(obj: Mountable, _, _) =>
|
||||
log.warn(s"MountVehicleMsg: $obj is some mountable object and nothing will happen for ${player.Name}")
|
||||
|
||||
case Mountable.CanDismount(obj: ImplantTerminalMech, seat_num, _) =>
|
||||
case Mountable.CanDismount(obj: ImplantTerminalMech, seatNum, _) =>
|
||||
log.info(s"${tplayer.Name} dismounts the implant terminal")
|
||||
DismountAction(tplayer, obj, seat_num)
|
||||
DismountAction(tplayer, obj, seatNum)
|
||||
|
||||
case Mountable.CanDismount(obj: Vehicle, seat_num, mount_point)
|
||||
if obj.Definition == GlobalDefinitions.orbital_shuttle =>
|
||||
case Mountable.CanDismount(obj: Vehicle, _, mountPoint)
|
||||
if obj.Definition == GlobalDefinitions.orbital_shuttle && obj.MountedIn.nonEmpty =>
|
||||
//dismount to hart lobby
|
||||
val pguid = player.GUID
|
||||
if (obj.MountedIn.nonEmpty) {
|
||||
//dismount to hart lobby
|
||||
log.info(s"${tplayer.Name} dismounts the orbital shuttle into the lobby")
|
||||
val sguid = obj.GUID
|
||||
val (pos, zang) = Vehicles.dismountShuttle(obj, mount_point)
|
||||
tplayer.Position = pos
|
||||
sendResponse(DelayedPathMountMsg(pguid, sguid, 60, u2=true))
|
||||
continent.LocalEvents ! LocalServiceMessage(
|
||||
continent.id,
|
||||
LocalAction.SendResponse(ObjectDetachMessage(sguid, pguid, pos, 0, 0, zang))
|
||||
)
|
||||
} else {
|
||||
log.info(s"${player.Name} is prepped for dropping")
|
||||
//get ready for orbital drop
|
||||
DismountAction(tplayer, obj, seat_num)
|
||||
continent.actor ! ZoneActor.RemoveFromBlockMap(player) //character doesn't need it
|
||||
//DismountAction(...) uses vehicle service, so use that service to coordinate the remainder of the messages
|
||||
continent.VehicleEvents ! VehicleServiceMessage(
|
||||
player.Name,
|
||||
VehicleAction.SendResponse(Service.defaultPlayerGUID, PlayerStasisMessage(pguid)) //the stasis message
|
||||
)
|
||||
//when the player dismounts, they will be positioned where the shuttle was when it disappeared in the sky
|
||||
//the player will fall to the ground and is perfectly vulnerable in this state
|
||||
//additionally, our player must exist in the current zone
|
||||
//having no in-game avatar target will throw us out of the map screen when deploying and cause softlock
|
||||
continent.VehicleEvents ! VehicleServiceMessage(
|
||||
player.Name,
|
||||
VehicleAction.SendResponse(
|
||||
Service.defaultPlayerGUID,
|
||||
PlayerStateShiftMessage(ShiftState(0, obj.Position, obj.Orientation.z, None)) //cower in the shuttle bay
|
||||
)
|
||||
)
|
||||
continent.VehicleEvents ! VehicleServiceMessage(
|
||||
continent.id,
|
||||
VehicleAction.SendResponse(pguid, GenericObjectActionMessage(pguid, 9)) //conceal the player
|
||||
)
|
||||
}
|
||||
log.info(s"${tplayer.Name} dismounts the orbital shuttle into the lobby")
|
||||
val sguid = obj.GUID
|
||||
val (pos, zang) = Vehicles.dismountShuttle(obj, mountPoint)
|
||||
tplayer.Position = pos
|
||||
sendResponse(DelayedPathMountMsg(pguid, sguid, u1=60, u2=true))
|
||||
continent.LocalEvents ! LocalServiceMessage(
|
||||
continent.id,
|
||||
LocalAction.SendResponse(ObjectDetachMessage(sguid, pguid, pos, roll=0, pitch=0, zang))
|
||||
)
|
||||
sessionData.keepAliveFunc = sessionData.zoning.NormalKeepAlive
|
||||
|
||||
case Mountable.CanDismount(obj: Vehicle, seat_num, _) if obj.Definition == GlobalDefinitions.droppod =>
|
||||
case Mountable.CanDismount(obj: Vehicle, seatNum, _)
|
||||
if obj.Definition == GlobalDefinitions.orbital_shuttle =>
|
||||
//get ready for orbital drop
|
||||
val pguid = player.GUID
|
||||
val events = continent.VehicleEvents
|
||||
log.info(s"${player.Name} is prepped for dropping")
|
||||
DismountAction(tplayer, obj, seatNum)
|
||||
continent.actor ! ZoneActor.RemoveFromBlockMap(player) //character doesn't need it
|
||||
//DismountAction(...) uses vehicle service, so use that service to coordinate the remainder of the messages
|
||||
events ! VehicleServiceMessage(
|
||||
player.Name,
|
||||
VehicleAction.SendResponse(Service.defaultPlayerGUID, PlayerStasisMessage(pguid)) //the stasis message
|
||||
)
|
||||
//when the player dismounts, they will be positioned where the shuttle was when it disappeared in the sky
|
||||
//the player will fall to the ground and is perfectly vulnerable in this state
|
||||
//additionally, our player must exist in the current zone
|
||||
//having no in-game avatar target will throw us out of the map screen when deploying and cause softlock
|
||||
events ! VehicleServiceMessage(
|
||||
player.Name,
|
||||
VehicleAction.SendResponse(
|
||||
Service.defaultPlayerGUID,
|
||||
PlayerStateShiftMessage(ShiftState(unk=0, obj.Position, obj.Orientation.z, vel=None)) //cower in the shuttle bay
|
||||
)
|
||||
)
|
||||
events ! VehicleServiceMessage(
|
||||
continent.id,
|
||||
VehicleAction.SendResponse(pguid, GenericObjectActionMessage(pguid, code=9)) //conceal the player
|
||||
)
|
||||
sessionData.keepAliveFunc = sessionData.zoning.NormalKeepAlive
|
||||
|
||||
case Mountable.CanDismount(obj: Vehicle, seatNum, _)
|
||||
if obj.Definition == GlobalDefinitions.droppod =>
|
||||
log.info(s"${tplayer.Name} has landed on ${continent.id}")
|
||||
sessionData.unaccessContainer(obj)
|
||||
DismountAction(tplayer, obj, seat_num)
|
||||
DismountAction(tplayer, obj, seatNum)
|
||||
obj.Actor ! Vehicle.Deconstruct()
|
||||
|
||||
case Mountable.CanDismount(obj: Vehicle, seat_num, _) =>
|
||||
val player_guid: PlanetSideGUID = tplayer.GUID
|
||||
if (player_guid == player.GUID) {
|
||||
//disembarking self
|
||||
log.info(s"${player.Name} dismounts the ${obj.Definition.Name}'s ${
|
||||
obj.SeatPermissionGroup(seat_num) match {
|
||||
case Some(AccessPermissionGroup.Driver) => "driver seat"
|
||||
case Some(seatType) => s"$seatType seat (#$seat_num)"
|
||||
case None => "seat"
|
||||
}
|
||||
}")
|
||||
sessionData.vehicles.ConditionalDriverVehicleControl(obj)
|
||||
sessionData.unaccessContainer(obj)
|
||||
DismountAction(tplayer, obj, seat_num)
|
||||
} else {
|
||||
continent.VehicleEvents ! VehicleServiceMessage(
|
||||
continent.id,
|
||||
VehicleAction.KickPassenger(player_guid, seat_num, unk2=true, obj.GUID)
|
||||
)
|
||||
}
|
||||
case Mountable.CanDismount(obj: Vehicle, seatNum, _)
|
||||
if tplayer.GUID == player.GUID =>
|
||||
//disembarking self
|
||||
log.info(s"${player.Name} dismounts the ${obj.Definition.Name}'s ${
|
||||
obj.SeatPermissionGroup(seatNum) match {
|
||||
case Some(AccessPermissionGroup.Driver) => "driver seat"
|
||||
case Some(seatType) => s"$seatType seat (#$seatNum)"
|
||||
case None => "seat"
|
||||
}
|
||||
}")
|
||||
sessionData.vehicles.ConditionalDriverVehicleControl(obj)
|
||||
sessionData.unaccessContainer(obj)
|
||||
DismountAction(tplayer, obj, seatNum)
|
||||
|
||||
case Mountable.CanDismount(obj: PlanetSideGameObject with WeaponTurret, seat_num, _) =>
|
||||
case Mountable.CanDismount(obj: Vehicle, seat_num, _) =>
|
||||
continent.VehicleEvents ! VehicleServiceMessage(
|
||||
continent.id,
|
||||
VehicleAction.KickPassenger(tplayer.GUID, seat_num, unk2=true, obj.GUID)
|
||||
)
|
||||
|
||||
case Mountable.CanDismount(obj: PlanetSideGameObject with WeaponTurret, seatNum, _) =>
|
||||
log.info(s"${tplayer.Name} dismounts a ${obj.Definition.asInstanceOf[ObjectDefinition].Name}")
|
||||
DismountAction(tplayer, obj, seat_num)
|
||||
DismountAction(tplayer, obj, seatNum)
|
||||
|
||||
case Mountable.CanDismount(obj: Mountable, _, _) =>
|
||||
log.warn(s"DismountVehicleMsg: $obj is some dismountable object but nothing will happen for ${player.Name}")
|
||||
|
||||
case Mountable.CanNotMount(obj: Vehicle, mount_point) =>
|
||||
log.warn(s"MountVehicleMsg: ${tplayer.Name} attempted to mount $obj's mount $mount_point, but was not allowed")
|
||||
obj.GetSeatFromMountPoint(mount_point) match {
|
||||
case Some(seatNum) if obj.SeatPermissionGroup(seatNum).contains(AccessPermissionGroup.Driver) =>
|
||||
case Mountable.CanNotMount(obj: Vehicle, mountPoint) =>
|
||||
log.warn(s"MountVehicleMsg: ${tplayer.Name} attempted to mount $obj's mount $mountPoint, but was not allowed")
|
||||
obj.GetSeatFromMountPoint(mountPoint).collect {
|
||||
case seatNum if obj.SeatPermissionGroup(seatNum).contains(AccessPermissionGroup.Driver) =>
|
||||
sendResponse(
|
||||
ChatMsg(ChatMessageType.CMT_OPEN, wideContents=false, "", "You are not the driver of this vehicle.", None)
|
||||
ChatMsg(ChatMessageType.CMT_OPEN, wideContents=false, recipient="", "You are not the driver of this vehicle.", note=None)
|
||||
)
|
||||
case _ =>
|
||||
}
|
||||
|
||||
case Mountable.CanNotMount(obj: Mountable, mount_point) =>
|
||||
log.warn(s"MountVehicleMsg: ${tplayer.Name} attempted to mount $obj's mount $mount_point, but was not allowed")
|
||||
case Mountable.CanNotMount(obj: Mountable, mountPoint) =>
|
||||
log.warn(s"MountVehicleMsg: ${tplayer.Name} attempted to mount $obj's mount $mountPoint, but was not allowed")
|
||||
|
||||
case Mountable.CanNotDismount(obj, seat_num) =>
|
||||
log.warn(
|
||||
s"DismountVehicleMsg: ${tplayer.Name} attempted to dismount $obj's mount $seat_num, but was not allowed"
|
||||
)
|
||||
case Mountable.CanNotDismount(obj, seatNum) =>
|
||||
log.warn(s"DismountVehicleMsg: ${tplayer.Name} attempted to dismount $obj's mount $seatNum, but was not allowed")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -211,15 +212,15 @@ class SessionMountHandlers(
|
|||
* @param seatNum the mount into which the player is mounting
|
||||
*/
|
||||
def MountingAction(tplayer: Player, obj: PlanetSideGameObject with Mountable, seatNum: Int): Unit = {
|
||||
val player_guid: PlanetSideGUID = tplayer.GUID
|
||||
val obj_guid: PlanetSideGUID = obj.GUID
|
||||
val playerGuid: PlanetSideGUID = tplayer.GUID
|
||||
val objGuid: PlanetSideGUID = obj.GUID
|
||||
sessionData.playerActionsToCancel()
|
||||
avatarActor ! AvatarActor.DeactivateActiveImplants()
|
||||
avatarActor ! AvatarActor.SuspendStaminaRegeneration(3 seconds)
|
||||
sendResponse(ObjectAttachMessage(obj_guid, player_guid, seatNum))
|
||||
avatarActor ! AvatarActor.SuspendStaminaRegeneration(3.seconds)
|
||||
sendResponse(ObjectAttachMessage(objGuid, playerGuid, seatNum))
|
||||
continent.VehicleEvents ! VehicleServiceMessage(
|
||||
continent.id,
|
||||
VehicleAction.MountVehicle(player_guid, obj_guid, seatNum)
|
||||
VehicleAction.MountVehicle(playerGuid, objGuid, seatNum)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -230,17 +231,17 @@ class SessionMountHandlers(
|
|||
* @param seatNum the mount out of which which the player is disembarking
|
||||
*/
|
||||
def DismountAction(tplayer: Player, obj: PlanetSideGameObject with Mountable, seatNum: Int): Unit = {
|
||||
val player_guid: PlanetSideGUID = tplayer.GUID
|
||||
val playerGuid: PlanetSideGUID = tplayer.GUID
|
||||
sessionData.keepAliveFunc = sessionData.zoning.NormalKeepAlive
|
||||
val bailType = if (tplayer.BailProtection) {
|
||||
BailType.Bailed
|
||||
} else {
|
||||
BailType.Normal
|
||||
}
|
||||
sendResponse(DismountVehicleMsg(player_guid, bailType, wasKickedByDriver = false))
|
||||
sendResponse(DismountVehicleMsg(playerGuid, bailType, wasKickedByDriver = false))
|
||||
continent.VehicleEvents ! VehicleServiceMessage(
|
||||
continent.id,
|
||||
VehicleAction.DismountVehicle(player_guid, bailType, unk2=false)
|
||||
VehicleAction.DismountVehicle(playerGuid, bailType, unk2=false)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,14 +45,14 @@ class SessionTerminalHandlers(
|
|||
}
|
||||
|
||||
def handleProximityTerminalUse(pkt: ProximityTerminalUseMessage): Unit = {
|
||||
val ProximityTerminalUseMessage(_, object_guid, _) = pkt
|
||||
continent.GUID(object_guid) match {
|
||||
val ProximityTerminalUseMessage(_, objectGuid, _) = pkt
|
||||
continent.GUID(objectGuid) match {
|
||||
case Some(obj: Terminal with ProximityUnit) =>
|
||||
HandleProximityTerminalUse(obj)
|
||||
case Some(obj) =>
|
||||
log.warn(s"ProximityTerminalUse: $obj does not have proximity effects for ${player.Name}")
|
||||
case None =>
|
||||
log.error(s"ProximityTerminalUse: ${player.Name} can not find an object with guid $object_guid")
|
||||
log.error(s"ProximityTerminalUse: ${player.Name} can not find an object with guid $objectGuid")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -60,26 +60,26 @@ class SessionTerminalHandlers(
|
|||
|
||||
/**
|
||||
* na
|
||||
*
|
||||
* @param tplayer na
|
||||
* @param msg na
|
||||
* @param order na
|
||||
*/
|
||||
def handle(tplayer: Player, msg: ItemTransactionMessage, order: Terminal.Exchange): Unit = {
|
||||
order match {
|
||||
case Terminal.BuyEquipment(item) if tplayer.avatar.purchaseCooldown(item.Definition).nonEmpty =>
|
||||
lastTerminalOrderFulfillment = true
|
||||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Buy, success = false))
|
||||
|
||||
case Terminal.BuyEquipment(item) =>
|
||||
tplayer.avatar.purchaseCooldown(item.Definition) match {
|
||||
case Some(_) =>
|
||||
lastTerminalOrderFulfillment = true
|
||||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Buy, success = false))
|
||||
case None =>
|
||||
avatarActor ! AvatarActor.UpdatePurchaseTime(item.Definition)
|
||||
TaskWorkflow.execute(BuyNewEquipmentPutInInventory(
|
||||
continent.GUID(tplayer.VehicleSeated) match { case Some(v: Vehicle) => v; case _ => player },
|
||||
tplayer,
|
||||
msg.terminal_guid
|
||||
)(item))
|
||||
}
|
||||
avatarActor ! AvatarActor.UpdatePurchaseTime(item.Definition)
|
||||
TaskWorkflow.execute(BuyNewEquipmentPutInInventory(
|
||||
continent.GUID(tplayer.VehicleSeated) match {
|
||||
case Some(v: Vehicle) => v
|
||||
case _ => player
|
||||
},
|
||||
tplayer,
|
||||
msg.terminal_guid
|
||||
)(item))
|
||||
|
||||
case Terminal.SellEquipment() =>
|
||||
SellEquipmentFromInventory(tplayer, tplayer, msg.terminal_guid)(Player.FreeHandSlot)
|
||||
|
|
@ -100,58 +100,56 @@ class SessionTerminalHandlers(
|
|||
avatarActor ! AvatarActor.SellImplant(msg.terminal_guid, implant)
|
||||
lastTerminalOrderFulfillment = true
|
||||
|
||||
case Terminal.BuyVehicle(vehicle, weapons, trunk) =>
|
||||
tplayer.avatar.purchaseCooldown(vehicle.Definition) match {
|
||||
case Some(_) =>
|
||||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Buy, success = false))
|
||||
case None =>
|
||||
continent.map.terminalToSpawnPad
|
||||
.find { case (termid, _) => termid == msg.terminal_guid.guid }
|
||||
.collect {
|
||||
case (a: Int, b: Int) => (continent.GUID(a), continent.GUID(b))
|
||||
case _ => (None, None)
|
||||
}
|
||||
.get match {
|
||||
case (Some(term: Terminal), Some(pad: VehicleSpawnPad)) =>
|
||||
avatarActor ! AvatarActor.UpdatePurchaseTime(vehicle.Definition)
|
||||
vehicle.Faction = tplayer.Faction
|
||||
vehicle.Position = pad.Position
|
||||
vehicle.Orientation = pad.Orientation + Vector3.z(pad.Definition.VehicleCreationZOrientOffset)
|
||||
//default loadout, weapons
|
||||
val vWeapons = vehicle.Weapons
|
||||
weapons.foreach(entry => {
|
||||
vWeapons.get(entry.start) match {
|
||||
case Some(slot) =>
|
||||
entry.obj.Faction = tplayer.Faction
|
||||
slot.Equipment = None
|
||||
slot.Equipment = entry.obj
|
||||
case None =>
|
||||
log.warn(
|
||||
s"BuyVehicle: ${player.Name} tries to apply default loadout to $vehicle on spawn, but can not find a mounted weapon for ${entry.start}"
|
||||
)
|
||||
}
|
||||
})
|
||||
//default loadout, trunk
|
||||
val vTrunk = vehicle.Trunk
|
||||
vTrunk.Clear()
|
||||
trunk.foreach(entry => {
|
||||
entry.obj.Faction = tplayer.Faction
|
||||
vTrunk.InsertQuickly(entry.start, entry.obj)
|
||||
})
|
||||
TaskWorkflow.execute(registerVehicleFromSpawnPad(vehicle, pad, term))
|
||||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Buy, success = true))
|
||||
if (GlobalDefinitions.isBattleFrameVehicle(vehicle.Definition)) {
|
||||
sendResponse(UnuseItemMessage(player.GUID, msg.terminal_guid))
|
||||
}
|
||||
case _ =>
|
||||
log.error(
|
||||
s"${tplayer.Name} wanted to spawn a vehicle, but there was no spawn pad associated with terminal ${msg.terminal_guid} to accept it"
|
||||
)
|
||||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Buy, success = false))
|
||||
}
|
||||
}
|
||||
case Terminal.BuyVehicle(vehicle, _, _) if tplayer.avatar.purchaseCooldown(vehicle.Definition).nonEmpty =>
|
||||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Buy, success = false))
|
||||
lastTerminalOrderFulfillment = true
|
||||
|
||||
case Terminal.BuyVehicle(vehicle, weapons, trunk) =>
|
||||
continent.map.terminalToSpawnPad
|
||||
.find { case (termid, _) => termid == msg.terminal_guid.guid }
|
||||
.map {
|
||||
case (a: Int, b: Int) => (continent.GUID(a), continent.GUID(b))
|
||||
case _ => (None, None)
|
||||
}
|
||||
.get match {
|
||||
case (Some(term: Terminal), Some(pad: VehicleSpawnPad)) =>
|
||||
avatarActor ! AvatarActor.UpdatePurchaseTime(vehicle.Definition)
|
||||
vehicle.Faction = tplayer.Faction
|
||||
vehicle.Position = pad.Position
|
||||
vehicle.Orientation = pad.Orientation + Vector3.z(pad.Definition.VehicleCreationZOrientOffset)
|
||||
//default loadout, weapons
|
||||
val vWeapons = vehicle.Weapons
|
||||
weapons.foreach { entry =>
|
||||
vWeapons.get(entry.start) match {
|
||||
case Some(slot) =>
|
||||
entry.obj.Faction = tplayer.Faction
|
||||
slot.Equipment = None
|
||||
slot.Equipment = entry.obj
|
||||
case None =>
|
||||
log.warn(
|
||||
s"BuyVehicle: ${player.Name} tries to apply default loadout to $vehicle on spawn, but can not find a mounted weapon for ${entry.start}"
|
||||
)
|
||||
}
|
||||
}
|
||||
//default loadout, trunk
|
||||
val vTrunk = vehicle.Trunk
|
||||
vTrunk.Clear()
|
||||
trunk.foreach { entry =>
|
||||
entry.obj.Faction = tplayer.Faction
|
||||
vTrunk.InsertQuickly(entry.start, entry.obj)
|
||||
}
|
||||
TaskWorkflow.execute(registerVehicleFromSpawnPad(vehicle, pad, term))
|
||||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Buy, success = true))
|
||||
if (GlobalDefinitions.isBattleFrameVehicle(vehicle.Definition)) {
|
||||
sendResponse(UnuseItemMessage(player.GUID, msg.terminal_guid))
|
||||
}
|
||||
case _ =>
|
||||
log.error(
|
||||
s"${tplayer.Name} wanted to spawn a vehicle, but there was no spawn pad associated with terminal ${msg.terminal_guid} to accept it"
|
||||
)
|
||||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Buy, success = false))
|
||||
}
|
||||
|
||||
case Terminal.NoDeal() =>
|
||||
val order: String = if (msg == null) {
|
||||
"missing order"
|
||||
|
|
@ -170,7 +168,7 @@ class SessionTerminalHandlers(
|
|||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
/* support */
|
||||
|
||||
/**
|
||||
* Construct tasking that adds a completed and registered vehicle into the scene.
|
||||
|
|
@ -209,7 +207,7 @@ class SessionTerminalHandlers(
|
|||
val term_guid = terminal.GUID
|
||||
val targets = FindProximityUnitTargetsInScope(terminal)
|
||||
val currentTargets = terminal.Targets
|
||||
targets.foreach(target => {
|
||||
targets.foreach { target =>
|
||||
if (!currentTargets.contains(target)) {
|
||||
StartUsingProximityUnit(terminal, target)
|
||||
} else if (targets.isEmpty) {
|
||||
|
|
@ -217,7 +215,7 @@ class SessionTerminalHandlers(
|
|||
s"HandleProximityTerminalUse: ${player.Name} could not find valid targets to give to proximity unit ${terminal.Definition.Name}@${term_guid.guid}"
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -226,7 +224,7 @@ class SessionTerminalHandlers(
|
|||
* @return na
|
||||
*/
|
||||
def FindProximityUnitTargetsInScope(terminal: Terminal with ProximityUnit): Seq[PlanetSideGameObject] = {
|
||||
terminal.Definition.asInstanceOf[ProximityDefinition].TargetValidation.keySet collect {
|
||||
terminal.Definition.asInstanceOf[ProximityDefinition].TargetValidation.keySet.collect {
|
||||
case EffectTarget.Category.Player => Some(player)
|
||||
case EffectTarget.Category.Vehicle | EffectTarget.Category.Aircraft => continent.GUID(player.VehicleSeated)
|
||||
} collect {
|
||||
|
|
@ -256,7 +254,7 @@ class SessionTerminalHandlers(
|
|||
terminal.Definition match {
|
||||
case GlobalDefinitions.adv_med_terminal | GlobalDefinitions.medical_terminal =>
|
||||
usingMedicalTerminal = Some(term_guid)
|
||||
case _ => ;
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -283,10 +281,7 @@ class SessionTerminalHandlers(
|
|||
* @param terminal the proximity-based unit
|
||||
*/
|
||||
def LocalStopUsingProximityUnit(terminal: Terminal with ProximityUnit, target: PlanetSideGameObject): Unit = {
|
||||
val term_guid = terminal.GUID
|
||||
if (usingMedicalTerminal.contains(term_guid)) {
|
||||
usingMedicalTerminal = None
|
||||
}
|
||||
ForgetAllProximityTerminals(terminal.GUID)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -296,21 +291,20 @@ class SessionTerminalHandlers(
|
|||
* @see `postStop`
|
||||
*/
|
||||
def CancelAllProximityUnits(): Unit = {
|
||||
continent.GUID(usingMedicalTerminal) match {
|
||||
case Some(terminal: Terminal with ProximityUnit) =>
|
||||
continent.GUID(usingMedicalTerminal).collect {
|
||||
case terminal: Terminal with ProximityUnit =>
|
||||
FindProximityUnitTargetsInScope(terminal).foreach(target =>
|
||||
terminal.Actor ! CommonMessages.Unuse(player, Some(target))
|
||||
)
|
||||
ForgetAllProximityTerminals(usingMedicalTerminal.get)
|
||||
case _ => ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* na
|
||||
*/
|
||||
def ForgetAllProximityTerminals(term_guid: PlanetSideGUID): Unit = {
|
||||
if (usingMedicalTerminal.contains(term_guid)) {
|
||||
def ForgetAllProximityTerminals(termGuid: PlanetSideGUID): Unit = {
|
||||
if (usingMedicalTerminal.contains(termGuid)) {
|
||||
usingMedicalTerminal = None
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package net.psforever.actors.session.support
|
|||
|
||||
import akka.actor.{ActorContext, ActorRef, typed}
|
||||
import net.psforever.actors.session.AvatarActor
|
||||
import net.psforever.objects.equipment.{JammableMountedWeapons, JammableUnit}
|
||||
import net.psforever.objects.equipment.{Equipment, JammableMountedWeapons, JammableUnit}
|
||||
import net.psforever.objects.guid.{GUIDTask, TaskWorkflow}
|
||||
import net.psforever.objects.serverobject.mount.Mountable
|
||||
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
|
||||
|
|
@ -31,153 +31,34 @@ class SessionVehicleHandlers(
|
|||
* @param reply na
|
||||
*/
|
||||
def handle(toChannel: String, guid: PlanetSideGUID, reply: VehicleResponse.Response): Unit = {
|
||||
val tplayer_guid = if (player.HasGUID) player.GUID else PlanetSideGUID(0)
|
||||
val resolvedPlayerGuid = if (player.HasGUID) {
|
||||
player.GUID
|
||||
} else {
|
||||
Service.defaultPlayerGUID
|
||||
}
|
||||
val isNotSameTarget = resolvedPlayerGuid != guid
|
||||
reply match {
|
||||
case VehicleResponse.AttachToRails(vehicle_guid, pad_guid) =>
|
||||
sendResponse(ObjectAttachMessage(pad_guid, vehicle_guid, 3))
|
||||
|
||||
case VehicleResponse.ChildObjectState(object_guid, pitch, yaw) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(ChildObjectStateMessage(object_guid, pitch, yaw))
|
||||
}
|
||||
|
||||
case VehicleResponse.ConcealPlayer(player_guid) =>
|
||||
sendResponse(GenericObjectActionMessage(player_guid, 9))
|
||||
|
||||
case VehicleResponse.DismountVehicle(bailType, wasKickedByDriver) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(DismountVehicleMsg(guid, bailType, wasKickedByDriver))
|
||||
}
|
||||
|
||||
case VehicleResponse.DeployRequest(object_guid, state, unk1, unk2, pos) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(DeployRequestMessage(guid, object_guid, state, unk1, unk2, pos))
|
||||
}
|
||||
|
||||
case VehicleResponse.DetachFromRails(vehicle_guid, pad_guid, pad_position, pad_orientation_z) =>
|
||||
val pad = continent.GUID(pad_guid).get.asInstanceOf[VehicleSpawnPad].Definition
|
||||
sendResponse(
|
||||
ObjectDetachMessage(
|
||||
pad_guid,
|
||||
vehicle_guid,
|
||||
pad_position + Vector3.z(pad.VehicleCreationZOffset),
|
||||
pad_orientation_z + pad.VehicleCreationZOrientOffset
|
||||
)
|
||||
)
|
||||
|
||||
case VehicleResponse.EquipmentInSlot(pkt) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(pkt)
|
||||
}
|
||||
|
||||
case VehicleResponse.FrameVehicleState(vguid, u1, pos, oient, vel, u2, u3, u4, is_crouched, u6, u7, u8, u9, uA) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(FrameVehicleStateMessage(vguid, u1, pos, oient, vel, u2, u3, u4, is_crouched, u6, u7, u8, u9, uA))
|
||||
}
|
||||
|
||||
case VehicleResponse.GenericObjectAction(object_guid, action) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(GenericObjectActionMessage(object_guid, action))
|
||||
}
|
||||
|
||||
case VehicleResponse.HitHint(source_guid) =>
|
||||
if (player.isAlive) {
|
||||
sendResponse(HitHint(source_guid, player.GUID))
|
||||
}
|
||||
|
||||
case VehicleResponse.InventoryState(obj, parent_guid, start, con_data) =>
|
||||
if (tplayer_guid != guid) {
|
||||
//TODO prefer ObjectDetachMessage, but how to force ammo pools to update properly?
|
||||
val obj_guid = obj.GUID
|
||||
sendResponse(ObjectDeleteMessage(obj_guid, 0))
|
||||
sendResponse(
|
||||
ObjectCreateDetailedMessage(
|
||||
obj.Definition.ObjectId,
|
||||
obj_guid,
|
||||
ObjectCreateMessageParent(parent_guid, start),
|
||||
con_data
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
case VehicleResponse.KickPassenger(_, wasKickedByDriver, vehicle_guid) =>
|
||||
//seat number (first field) seems to be correct if passenger is kicked manually by driver
|
||||
//but always seems to return 4 if user is kicked by mount permissions changing
|
||||
sendResponse(DismountVehicleMsg(guid, BailType.Kicked, wasKickedByDriver))
|
||||
if (tplayer_guid == guid) {
|
||||
val typeOfRide = continent.GUID(vehicle_guid) match {
|
||||
case Some(obj: Vehicle) =>
|
||||
sessionData.unaccessContainer(obj)
|
||||
s"the ${obj.Definition.Name}'s seat by ${obj.OwnerName.getOrElse("the pilot")}"
|
||||
case _ =>
|
||||
s"${player.Sex.possessive} ride"
|
||||
}
|
||||
log.info(s"${player.Name} has been kicked from $typeOfRide!")
|
||||
}
|
||||
|
||||
case VehicleResponse.InventoryState2(obj_guid, parent_guid, value) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(InventoryStateMessage(obj_guid, 0, parent_guid, value))
|
||||
}
|
||||
|
||||
case VehicleResponse.LoadVehicle(vehicle, vtype, vguid, vdata) =>
|
||||
//this is not be suitable for vehicles with people who are seated in it before it spawns (if that is possible)
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(ObjectCreateMessage(vtype, vguid, vdata))
|
||||
Vehicles.ReloadAccessPermissions(vehicle, player.Name)
|
||||
}
|
||||
|
||||
case VehicleResponse.MountVehicle(vehicle_guid, seat) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(ObjectAttachMessage(vehicle_guid, guid, seat))
|
||||
}
|
||||
|
||||
case VehicleResponse.ObjectDelete(itemGuid) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(ObjectDeleteMessage(itemGuid, 0))
|
||||
}
|
||||
|
||||
case VehicleResponse.Ownership(vehicleGuid) =>
|
||||
if (tplayer_guid == guid) { // Only the player that owns this vehicle needs the ownership packet
|
||||
avatarActor ! AvatarActor.SetVehicle(Some(vehicleGuid))
|
||||
sendResponse(PlanetsideAttributeMessage(tplayer_guid, 21, vehicleGuid))
|
||||
}
|
||||
|
||||
case VehicleResponse.PlanetsideAttribute(vehicle_guid, attribute_type, attribute_value) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, attribute_type, attribute_value))
|
||||
}
|
||||
|
||||
case VehicleResponse.ResetSpawnPad(pad_guid) =>
|
||||
sendResponse(GenericObjectActionMessage(pad_guid, 23))
|
||||
|
||||
case VehicleResponse.RevealPlayer(player_guid) =>
|
||||
sendResponse(GenericObjectActionMessage(player_guid, 10))
|
||||
|
||||
case VehicleResponse.SeatPermissions(vehicle_guid, seat_group, permission) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, seat_group, permission))
|
||||
}
|
||||
|
||||
case VehicleResponse.StowEquipment(vehicle_guid, slot, item_type, item_guid, item_data) =>
|
||||
if (tplayer_guid != guid) {
|
||||
//TODO prefer ObjectAttachMessage, but how to force ammo pools to update properly?
|
||||
sendResponse(
|
||||
ObjectCreateDetailedMessage(item_type, item_guid, ObjectCreateMessageParent(vehicle_guid, slot), item_data)
|
||||
)
|
||||
}
|
||||
|
||||
case VehicleResponse.UnloadVehicle(_, vehicle_guid) =>
|
||||
sendResponse(ObjectDeleteMessage(vehicle_guid, 0))
|
||||
|
||||
case VehicleResponse.UnstowEquipment(item_guid) =>
|
||||
if (tplayer_guid != guid) {
|
||||
//TODO prefer ObjectDetachMessage, but how to force ammo pools to update properly?
|
||||
sendResponse(ObjectDeleteMessage(item_guid, 0))
|
||||
}
|
||||
case VehicleResponse.VehicleState(
|
||||
vehicleGuid,
|
||||
unk1,
|
||||
pos,
|
||||
orient,
|
||||
vel,
|
||||
unk2,
|
||||
unk3,
|
||||
unk4,
|
||||
wheelDirection,
|
||||
unk5,
|
||||
unk6
|
||||
) if isNotSameTarget && player.VehicleSeated.contains(vehicleGuid) =>
|
||||
//player who is also in the vehicle (not driver)
|
||||
sendResponse(VehicleStateMessage(vehicleGuid, unk1, pos, orient, vel, unk2, unk3, unk4, wheelDirection, unk5, unk6))
|
||||
player.Position = pos
|
||||
player.Orientation = orient
|
||||
player.Velocity = vel
|
||||
|
||||
case VehicleResponse.VehicleState(
|
||||
vehicle_guid,
|
||||
vehicleGuid,
|
||||
unk1,
|
||||
pos,
|
||||
ang,
|
||||
|
|
@ -185,59 +66,175 @@ class SessionVehicleHandlers(
|
|||
unk2,
|
||||
unk3,
|
||||
unk4,
|
||||
wheel_direction,
|
||||
wheelDirection,
|
||||
unk5,
|
||||
unk6
|
||||
) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sendResponse(
|
||||
VehicleStateMessage(vehicle_guid, unk1, pos, ang, vel, unk2, unk3, unk4, wheel_direction, unk5, unk6)
|
||||
)
|
||||
if (player.VehicleSeated.contains(vehicle_guid)) {
|
||||
player.Position = pos
|
||||
}
|
||||
}
|
||||
) if isNotSameTarget =>
|
||||
//player who is watching the vehicle from the outside
|
||||
sendResponse(VehicleStateMessage(vehicleGuid, unk1, pos, ang, vel, unk2, unk3, unk4, wheelDirection, unk5, unk6))
|
||||
|
||||
case VehicleResponse.ChildObjectState(objectGuid, pitch, yaw) if isNotSameTarget =>
|
||||
sendResponse(ChildObjectStateMessage(objectGuid, pitch, yaw))
|
||||
|
||||
case VehicleResponse.FrameVehicleState(vguid, u1, pos, oient, vel, u2, u3, u4, is_crouched, u6, u7, u8, u9, uA)
|
||||
if isNotSameTarget =>
|
||||
sendResponse(FrameVehicleStateMessage(vguid, u1, pos, oient, vel, u2, u3, u4, is_crouched, u6, u7, u8, u9, uA))
|
||||
|
||||
case VehicleResponse.DismountVehicle(bailType, wasKickedByDriver) if isNotSameTarget =>
|
||||
sendResponse(DismountVehicleMsg(guid, bailType, wasKickedByDriver))
|
||||
|
||||
case VehicleResponse.MountVehicle(vehicleGuid, seat) if isNotSameTarget =>
|
||||
sendResponse(ObjectAttachMessage(vehicleGuid, guid, seat))
|
||||
|
||||
case VehicleResponse.DeployRequest(objectGuid, state, unk1, unk2, pos) if isNotSameTarget =>
|
||||
sendResponse(DeployRequestMessage(guid, objectGuid, state, unk1, unk2, pos))
|
||||
|
||||
case VehicleResponse.SendResponse(msg) =>
|
||||
sendResponse(msg)
|
||||
|
||||
case VehicleResponse.AttachToRails(vehicleGuid, padGuid) =>
|
||||
sendResponse(ObjectAttachMessage(padGuid, vehicleGuid, slot=3))
|
||||
|
||||
case VehicleResponse.ConcealPlayer(playerGuid) =>
|
||||
sendResponse(GenericObjectActionMessage(playerGuid, code=9))
|
||||
|
||||
case VehicleResponse.DetachFromRails(vehicleGuid, padGuid, padPosition, padOrientationZ) =>
|
||||
val pad = continent.GUID(padGuid).get.asInstanceOf[VehicleSpawnPad].Definition
|
||||
sendResponse(
|
||||
ObjectDetachMessage(
|
||||
padGuid,
|
||||
vehicleGuid,
|
||||
padPosition + Vector3.z(pad.VehicleCreationZOffset),
|
||||
padOrientationZ + pad.VehicleCreationZOrientOffset
|
||||
)
|
||||
)
|
||||
|
||||
case VehicleResponse.EquipmentInSlot(pkt) if isNotSameTarget =>
|
||||
sendResponse(pkt)
|
||||
|
||||
case VehicleResponse.GenericObjectAction(objectGuid, action) if isNotSameTarget =>
|
||||
sendResponse(GenericObjectActionMessage(objectGuid, action))
|
||||
|
||||
case VehicleResponse.HitHint(sourceGuid) if player.isAlive =>
|
||||
sendResponse(HitHint(sourceGuid, player.GUID))
|
||||
|
||||
case VehicleResponse.InventoryState(obj, parentGuid, start, conData) if isNotSameTarget =>
|
||||
//TODO prefer ObjectDetachMessage, but how to force ammo pools to update properly?
|
||||
val objGuid = obj.GUID
|
||||
sendResponse(ObjectDeleteMessage(objGuid, unk1=0))
|
||||
sendResponse(ObjectCreateDetailedMessage(
|
||||
obj.Definition.ObjectId,
|
||||
objGuid,
|
||||
ObjectCreateMessageParent(parentGuid, start),
|
||||
conData
|
||||
))
|
||||
|
||||
case VehicleResponse.KickPassenger(_, wasKickedByDriver, vehicleGuid) if resolvedPlayerGuid == guid =>
|
||||
//seat number (first field) seems to be correct if passenger is kicked manually by driver
|
||||
//but always seems to return 4 if user is kicked by mount permissions changing
|
||||
sendResponse(DismountVehicleMsg(guid, BailType.Kicked, wasKickedByDriver))
|
||||
val typeOfRide = continent.GUID(vehicleGuid) match {
|
||||
case Some(obj: Vehicle) =>
|
||||
sessionData.unaccessContainer(obj)
|
||||
s"the ${obj.Definition.Name}'s seat by ${obj.OwnerName.getOrElse("the pilot")}"
|
||||
case _ =>
|
||||
s"${player.Sex.possessive} ride"
|
||||
}
|
||||
log.info(s"${player.Name} has been kicked from $typeOfRide!")
|
||||
|
||||
case VehicleResponse.KickPassenger(_, wasKickedByDriver, _) =>
|
||||
//seat number (first field) seems to be correct if passenger is kicked manually by driver
|
||||
//but always seems to return 4 if user is kicked by mount permissions changing
|
||||
sendResponse(DismountVehicleMsg(guid, BailType.Kicked, wasKickedByDriver))
|
||||
|
||||
case VehicleResponse.InventoryState2(objGuid, parentGuid, value) if isNotSameTarget =>
|
||||
sendResponse(InventoryStateMessage(objGuid, unk=0, parentGuid, value))
|
||||
|
||||
case VehicleResponse.LoadVehicle(vehicle, vtype, vguid, vdata) if isNotSameTarget =>
|
||||
//this is not be suitable for vehicles with people who are seated in it before it spawns (if that is possible)
|
||||
sendResponse(ObjectCreateMessage(vtype, vguid, vdata))
|
||||
Vehicles.ReloadAccessPermissions(vehicle, player.Name)
|
||||
|
||||
case VehicleResponse.ObjectDelete(itemGuid) if isNotSameTarget =>
|
||||
sendResponse(ObjectDeleteMessage(itemGuid, unk1=0))
|
||||
|
||||
case VehicleResponse.Ownership(vehicleGuid) if resolvedPlayerGuid == guid =>
|
||||
//Only the player that owns this vehicle needs the ownership packet
|
||||
avatarActor ! AvatarActor.SetVehicle(Some(vehicleGuid))
|
||||
sendResponse(PlanetsideAttributeMessage(resolvedPlayerGuid, attribute_type=21, vehicleGuid))
|
||||
|
||||
case VehicleResponse.PlanetsideAttribute(vehicleGuid, attributeType, attributeValue) =>
|
||||
if (isNotSameTarget) {
|
||||
sendResponse(PlanetsideAttributeMessage(vehicleGuid, attributeType, attributeValue))
|
||||
}
|
||||
|
||||
case VehicleResponse.ResetSpawnPad(padGuid) =>
|
||||
sendResponse(GenericObjectActionMessage(padGuid, code=23))
|
||||
|
||||
case VehicleResponse.RevealPlayer(playerGuid) =>
|
||||
sendResponse(GenericObjectActionMessage(playerGuid, code=10))
|
||||
|
||||
case VehicleResponse.SeatPermissions(vehicleGuid, seatGroup, permission) if isNotSameTarget =>
|
||||
sendResponse(PlanetsideAttributeMessage(vehicleGuid, seatGroup, permission))
|
||||
|
||||
case VehicleResponse.StowEquipment(vehicleGuid, slot, itemType, itemGuid, itemData) if isNotSameTarget =>
|
||||
//TODO prefer ObjectAttachMessage, but how to force ammo pools to update properly?
|
||||
sendResponse(ObjectCreateDetailedMessage(itemType, itemGuid, ObjectCreateMessageParent(vehicleGuid, slot), itemData))
|
||||
|
||||
case VehicleResponse.UnloadVehicle(_, vehicleGuid) =>
|
||||
sendResponse(ObjectDeleteMessage(vehicleGuid, unk1=0))
|
||||
|
||||
case VehicleResponse.UnstowEquipment(itemGuid) if isNotSameTarget =>
|
||||
//TODO prefer ObjectDetachMessage, but how to force ammo pools to update properly?
|
||||
sendResponse(ObjectDeleteMessage(itemGuid, unk1=0))
|
||||
|
||||
case VehicleResponse.UpdateAmsSpawnPoint(list) =>
|
||||
sessionData.zoning.spawn.amsSpawnPoints = list.filter(tube => tube.Faction == player.Faction)
|
||||
sessionData.zoning.spawn.DrawCurrentAmsSpawnPoint()
|
||||
|
||||
case VehicleResponse.TransferPassengerChannel(old_channel, temp_channel, vehicle, vehicle_to_delete) =>
|
||||
if (tplayer_guid != guid) {
|
||||
sessionData.zoning.interstellarFerry = Some(vehicle)
|
||||
sessionData.zoning.interstellarFerryTopLevelGUID = Some(vehicle_to_delete)
|
||||
continent.VehicleEvents ! Service.Leave(
|
||||
Some(old_channel)
|
||||
) //old vehicle-specific channel (was s"${vehicle.Actor}")
|
||||
galaxyService ! Service.Join(temp_channel) //temporary vehicle-specific channel
|
||||
log.debug(s"TransferPassengerChannel: ${player.Name} now subscribed to $temp_channel for vehicle gating")
|
||||
}
|
||||
case VehicleResponse.TransferPassengerChannel(oldChannel, tempChannel, vehicle, vehicleToDelete) if isNotSameTarget =>
|
||||
sessionData.zoning.interstellarFerry = Some(vehicle)
|
||||
sessionData.zoning.interstellarFerryTopLevelGUID = Some(vehicleToDelete)
|
||||
continent.VehicleEvents ! Service.Leave(Some(oldChannel)) //old vehicle-specific channel (was s"${vehicle.Actor}")
|
||||
galaxyService ! Service.Join(tempChannel) //temporary vehicle-specific channel
|
||||
log.debug(s"TransferPassengerChannel: ${player.Name} now subscribed to $tempChannel for vehicle gating")
|
||||
|
||||
case VehicleResponse.KickCargo(vehicle, speed, delay) =>
|
||||
if (player.VehicleSeated.nonEmpty && sessionData.zoning.spawn.deadState == DeadState.Alive) {
|
||||
if (speed > 0) {
|
||||
val strafe =
|
||||
if (Vehicles.CargoOrientation(vehicle) == 1) 2
|
||||
else 1
|
||||
val reverseSpeed =
|
||||
if (strafe > 1) 0
|
||||
else speed
|
||||
//strafe or reverse, not both
|
||||
sessionData.vehicles.serverVehicleControlVelocity = Some(reverseSpeed)
|
||||
sendResponse(ServerVehicleOverrideMsg(lock_accelerator=true, lock_wheel=true, reverse=true, unk4=false, 0, strafe, reverseSpeed, Some(0)))
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
context.system.scheduler.scheduleOnce(
|
||||
delay milliseconds,
|
||||
context.self,
|
||||
VehicleServiceResponse(toChannel, PlanetSideGUID(0), VehicleResponse.KickCargo(vehicle, 0, delay))
|
||||
)
|
||||
} else {
|
||||
sessionData.vehicles.serverVehicleControlVelocity = None
|
||||
sendResponse(ServerVehicleOverrideMsg(lock_accelerator=false,lock_wheel=false, reverse=false, unk4=false, 0, 0, 0, None))
|
||||
}
|
||||
}
|
||||
case VehicleResponse.KickCargo(vehicle, speed, delay)
|
||||
if player.VehicleSeated.nonEmpty && sessionData.zoning.spawn.deadState == DeadState.Alive && speed > 0 =>
|
||||
val strafe = if (Vehicles.CargoOrientation(vehicle) == 1) { 2 } else { 1 }
|
||||
val reverseSpeed = if (strafe > 1) { 0 } else { speed }
|
||||
//strafe or reverse, not both
|
||||
sessionData.vehicles.serverVehicleControlVelocity = Some(reverseSpeed)
|
||||
sendResponse(ServerVehicleOverrideMsg(
|
||||
lock_accelerator=true,
|
||||
lock_wheel=true,
|
||||
reverse=true,
|
||||
unk4=false,
|
||||
lock_vthrust=0,
|
||||
strafe,
|
||||
reverseSpeed,
|
||||
unk8=Some(0)
|
||||
))
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
context.system.scheduler.scheduleOnce(
|
||||
delay milliseconds,
|
||||
context.self,
|
||||
VehicleServiceResponse(toChannel, PlanetSideGUID(0), VehicleResponse.KickCargo(vehicle, speed=0, delay))
|
||||
)
|
||||
|
||||
case VehicleResponse.KickCargo(_, _, _)
|
||||
if player.VehicleSeated.nonEmpty && sessionData.zoning.spawn.deadState == DeadState.Alive =>
|
||||
sessionData.vehicles.serverVehicleControlVelocity = None
|
||||
sendResponse(ServerVehicleOverrideMsg(
|
||||
lock_accelerator=false,
|
||||
lock_wheel=false,
|
||||
reverse=false,
|
||||
unk4=false,
|
||||
lock_vthrust=0,
|
||||
lock_strafe=0,
|
||||
movement_speed=0,
|
||||
unk8=None
|
||||
))
|
||||
|
||||
case VehicleResponse.StartPlayerSeatedInVehicle(vehicle, _) =>
|
||||
val vehicle_guid = vehicle.GUID
|
||||
|
|
@ -246,28 +243,31 @@ class SessionVehicleHandlers(
|
|||
sessionData.terminals.CancelAllProximityUnits()
|
||||
if (player.VisibleSlots.contains(player.DrawnSlot)) {
|
||||
player.DrawnSlot = Player.HandsDownSlot
|
||||
sendResponse(ObjectHeldMessage(player.GUID, Player.HandsDownSlot, unk1 = true))
|
||||
sendResponse(ObjectHeldMessage(player.GUID, Player.HandsDownSlot, unk1=true))
|
||||
continent.AvatarEvents ! AvatarServiceMessage(
|
||||
continent.id,
|
||||
AvatarAction.SendResponse(player.GUID, ObjectHeldMessage(player.GUID, player.LastDrawnSlot, unk1 = false))
|
||||
AvatarAction.SendResponse(player.GUID, ObjectHeldMessage(player.GUID, player.LastDrawnSlot, unk1=false))
|
||||
)
|
||||
}
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 22, 1L)) //mount points off
|
||||
sendResponse(PlanetsideAttributeMessage(player.GUID, 21, vehicle_guid)) //ownership
|
||||
vehicle.MountPoints.find { case (_, mp) => mp.seatIndex == 0 } match {
|
||||
case Some((mountPoint, _)) => vehicle.Actor ! Mountable.TryMount(player, mountPoint)
|
||||
case _ => ;
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, attribute_type=22, attribute_value=1L)) //mount points off
|
||||
sendResponse(PlanetsideAttributeMessage(player.GUID, attribute_type=21, vehicle_guid)) //ownership
|
||||
vehicle.MountPoints.find { case (_, mp) => mp.seatIndex == 0 }.collect {
|
||||
case (mountPoint, _) => vehicle.Actor ! Mountable.TryMount(player, mountPoint)
|
||||
}
|
||||
|
||||
case VehicleResponse.PlayerSeatedInVehicle(vehicle, _) =>
|
||||
val vehicle_guid = vehicle.GUID
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 22, 0L)) //mount points on
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, attribute_type=22, attribute_value=0L)) //mount points on
|
||||
Vehicles.ReloadAccessPermissions(vehicle, player.Name)
|
||||
sessionData.vehicles.ServerVehicleLock(vehicle)
|
||||
|
||||
case VehicleResponse.ServerVehicleOverrideStart(vehicle, _) =>
|
||||
val vdef = vehicle.Definition
|
||||
sessionData.vehicles.ServerVehicleOverride(vehicle, vdef.AutoPilotSpeed1, if (GlobalDefinitions.isFlightVehicle(vdef)) 1 else 0)
|
||||
sessionData.vehicles.ServerVehicleOverride(
|
||||
vehicle,
|
||||
vdef.AutoPilotSpeed1,
|
||||
flight= if (GlobalDefinitions.isFlightVehicle(vdef)) { 1 } else { 0 }
|
||||
)
|
||||
|
||||
case VehicleResponse.ServerVehicleOverrideEnd(vehicle, _) =>
|
||||
session = session.copy(avatar = avatar.copy(vehicle = Some(vehicle.GUID)))
|
||||
|
|
@ -277,63 +277,77 @@ class SessionVehicleHandlers(
|
|||
sendResponse(ChatMsg(
|
||||
ChatMessageType.CMT_OPEN,
|
||||
wideContents=true,
|
||||
"",
|
||||
recipient="",
|
||||
s"The vehicle spawn where you placed your order is blocked. ${data.getOrElse("")}",
|
||||
None
|
||||
note=None
|
||||
))
|
||||
|
||||
case VehicleResponse.PeriodicReminder(_, data) =>
|
||||
val (isType, flag, msg): (ChatMessageType, Boolean, String) = data match {
|
||||
case Some(msg: String)
|
||||
if msg.startsWith("@") => (ChatMessageType.UNK_227, false, msg)
|
||||
case Some(msg: String) if msg.startsWith("@") => (ChatMessageType.UNK_227, false, msg)
|
||||
case Some(msg: String) => (ChatMessageType.CMT_OPEN, true, msg)
|
||||
case _ => (ChatMessageType.CMT_OPEN, true, "Your vehicle order has been cancelled.")
|
||||
}
|
||||
sendResponse(ChatMsg(isType, flag, "", msg, None))
|
||||
sendResponse(ChatMsg(isType, flag, recipient="", msg, None))
|
||||
|
||||
case VehicleResponse.ChangeLoadout(target, old_weapons, added_weapons, old_inventory, new_inventory) =>
|
||||
case VehicleResponse.ChangeLoadout(target, oldWeapons, addedWeapons, oldInventory, newInventory)
|
||||
if player.avatar.vehicle.contains(target) =>
|
||||
//TODO when vehicle weapons can be changed without visual glitches, rewrite this
|
||||
continent.GUID(target) match {
|
||||
case Some(vehicle: Vehicle) =>
|
||||
if (player.avatar.vehicle.contains(target)) {
|
||||
import net.psforever.login.WorldSession.boolToInt
|
||||
//owner: must unregister old equipment, and register and install new equipment
|
||||
(old_weapons ++ old_inventory).foreach {
|
||||
case (obj, eguid) =>
|
||||
sendResponse(ObjectDeleteMessage(eguid, 0))
|
||||
TaskWorkflow.execute(GUIDTask.unregisterEquipment(continent.GUID, obj))
|
||||
}
|
||||
sessionData.applyPurchaseTimersBeforePackingLoadout(player, vehicle, added_weapons ++ new_inventory)
|
||||
//jammer or unjamm new weapons based on vehicle status
|
||||
val vehicleJammered = vehicle.Jammed
|
||||
added_weapons
|
||||
.map {
|
||||
_.obj
|
||||
}
|
||||
.collect {
|
||||
case jamItem: JammableUnit if jamItem.Jammed != vehicleJammered =>
|
||||
jamItem.Jammed = vehicleJammered
|
||||
JammableMountedWeapons.JammedWeaponStatus(vehicle.Zone, jamItem, vehicleJammered)
|
||||
}
|
||||
} else if (sessionData.accessedContainer.map { _.GUID }.contains(target)) {
|
||||
//external participant: observe changes to equipment
|
||||
(old_weapons ++ old_inventory).foreach { case (_, eguid) => sendResponse(ObjectDeleteMessage(eguid, 0)) }
|
||||
continent.GUID(target).collect { case vehicle: Vehicle =>
|
||||
import net.psforever.login.WorldSession.boolToInt
|
||||
//owner: must unregister old equipment, and register and install new equipment
|
||||
(oldWeapons ++ oldInventory).foreach {
|
||||
case (obj, eguid) =>
|
||||
sendResponse(ObjectDeleteMessage(eguid, unk1=0))
|
||||
TaskWorkflow.execute(GUIDTask.unregisterEquipment(continent.GUID, obj))
|
||||
}
|
||||
sessionData.applyPurchaseTimersBeforePackingLoadout(player, vehicle, addedWeapons ++ newInventory)
|
||||
//jammer or unjamm new weapons based on vehicle status
|
||||
val vehicleJammered = vehicle.Jammed
|
||||
addedWeapons
|
||||
.map { _.obj }
|
||||
.collect {
|
||||
case jamItem: JammableUnit if jamItem.Jammed != vehicleJammered =>
|
||||
jamItem.Jammed = vehicleJammered
|
||||
JammableMountedWeapons.JammedWeaponStatus(vehicle.Zone, jamItem, vehicleJammered)
|
||||
}
|
||||
vehicle.PassengerInSeat(player) match {
|
||||
case Some(seatNum) =>
|
||||
//participant: observe changes to equipment
|
||||
(old_weapons ++ old_inventory).foreach {
|
||||
case (_, eguid) => sendResponse(ObjectDeleteMessage(eguid, 0))
|
||||
}
|
||||
sessionData.updateWeaponAtSeatPosition(vehicle, seatNum)
|
||||
case None =>
|
||||
//observer: observe changes to external equipment
|
||||
old_weapons.foreach { case (_, eguid) => sendResponse(ObjectDeleteMessage(eguid, 0)) }
|
||||
}
|
||||
case _ => ;
|
||||
changeLoadoutDeleteOldEquipment(vehicle, oldWeapons, oldInventory)
|
||||
}
|
||||
|
||||
case _ => ;
|
||||
case VehicleResponse.ChangeLoadout(target, oldWeapons, _, oldInventory, _)
|
||||
if sessionData.accessedContainer.map { _.GUID }.contains(target) =>
|
||||
//TODO when vehicle weapons can be changed without visual glitches, rewrite this
|
||||
continent.GUID(target).collect { case vehicle: Vehicle =>
|
||||
//external participant: observe changes to equipment
|
||||
(oldWeapons ++ oldInventory).foreach { case (_, eguid) => sendResponse(ObjectDeleteMessage(eguid, unk1=0)) }
|
||||
changeLoadoutDeleteOldEquipment(vehicle, oldWeapons, oldInventory)
|
||||
}
|
||||
|
||||
case VehicleResponse.ChangeLoadout(target, oldWeapons, _, oldInventory, _) =>
|
||||
//TODO when vehicle weapons can be changed without visual glitches, rewrite this
|
||||
continent.GUID(target).collect { case vehicle: Vehicle =>
|
||||
changeLoadoutDeleteOldEquipment(vehicle, oldWeapons, oldInventory)
|
||||
}
|
||||
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
|
||||
private def changeLoadoutDeleteOldEquipment(
|
||||
vehicle: Vehicle,
|
||||
oldWeapons: Iterable[(Equipment, PlanetSideGUID)],
|
||||
oldInventory: Iterable[(Equipment, PlanetSideGUID)]
|
||||
): Unit = {
|
||||
vehicle.PassengerInSeat(player) match {
|
||||
case Some(seatNum) =>
|
||||
//participant: observe changes to equipment
|
||||
(oldWeapons ++ oldInventory).foreach {
|
||||
case (_, eguid) => sendResponse(ObjectDeleteMessage(eguid, unk1=0))
|
||||
}
|
||||
sessionData.updateWeaponAtSeatPosition(vehicle, seatNum)
|
||||
case None =>
|
||||
//observer: observe changes to external equipment
|
||||
oldWeapons.foreach { case (_, eguid) => sendResponse(ObjectDeleteMessage(eguid, unk1=0)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue