mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-02-22 16:13:39 +00:00
corrected various issues identified in the comments of PR#1247
This commit is contained in:
parent
186f568c64
commit
720bc97838
21 changed files with 541 additions and 435 deletions
|
|
@ -1131,6 +1131,11 @@ class AvatarActor(
|
|||
var supportExperienceTimer: Cancellable = Default.Cancellable
|
||||
var experienceDebt: Long = 0L
|
||||
|
||||
private def setSession(newSession: Session): Unit = {
|
||||
session = Some(newSession)
|
||||
_avatar = Option(newSession.avatar)
|
||||
}
|
||||
|
||||
def avatar: Avatar = _avatar.get
|
||||
|
||||
def avatar_=(avatar: Avatar): Unit = {
|
||||
|
|
@ -1156,8 +1161,7 @@ class AvatarActor(
|
|||
postLoginBehaviour()
|
||||
|
||||
case SetSession(newSession) =>
|
||||
session = Some(newSession)
|
||||
_avatar = Option(newSession.avatar)
|
||||
setSession(newSession)
|
||||
postLoginBehaviour()
|
||||
|
||||
case other =>
|
||||
|
|
@ -1177,7 +1181,7 @@ class AvatarActor(
|
|||
Behaviors
|
||||
.receiveMessage[Command] {
|
||||
case SetSession(newSession) =>
|
||||
session = Some(newSession)
|
||||
setSession(newSession)
|
||||
Behaviors.same
|
||||
|
||||
case SetLookingForSquad(lfs) =>
|
||||
|
|
@ -1330,7 +1334,7 @@ class AvatarActor(
|
|||
Behaviors
|
||||
.receiveMessagePartial[Command] {
|
||||
case SetSession(newSession) =>
|
||||
session = Some(newSession)
|
||||
setSession(newSession)
|
||||
Behaviors.same
|
||||
|
||||
case ReplaceAvatar(newAvatar) =>
|
||||
|
|
|
|||
|
|
@ -3,9 +3,14 @@ package net.psforever.actors.session.csr
|
|||
|
||||
import akka.actor.{ActorContext, typed}
|
||||
import net.psforever.actors.session.support.AvatarHandlerFunctions
|
||||
import net.psforever.login.WorldSession.PutLoadoutEquipmentInInventory
|
||||
import net.psforever.objects.PlanetSideGameObject
|
||||
import net.psforever.objects.definition.converter.OCM
|
||||
import net.psforever.objects.inventory.Container
|
||||
import net.psforever.objects.serverobject.containable.ContainableBehavior
|
||||
import net.psforever.objects.serverobject.mount.Mountable
|
||||
import net.psforever.packet.game.{AvatarImplantMessage, CreateShortcutMessage, ImplantAction}
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
import net.psforever.types.ImplantType
|
||||
|
||||
//
|
||||
|
|
@ -382,7 +387,9 @@ class AvatarHandlerLogic(val ops: SessionAvatarHandlers, implicit val context: A
|
|||
slot = 0
|
||||
))
|
||||
}
|
||||
sessionLogic.general.applyPurchaseTimersBeforePackingLoadout(player, player, holsters ++ inventory)
|
||||
(holsters ++ inventory).foreach { case InventoryItem(item, slot) =>
|
||||
TaskWorkflow.execute(PutLoadoutEquipmentInInventory(player)(item, slot))
|
||||
}
|
||||
DropLeftovers(player)(drops)
|
||||
|
||||
case AvatarResponse.ChangeLoadout(target, armor, exosuit, subtype, slot, _, oldHolsters, _, _, _, _) =>
|
||||
|
|
@ -431,6 +438,8 @@ class AvatarHandlerLogic(val ops: SessionAvatarHandlers, implicit val context: A
|
|||
sendResponse(ReloadMessage(itemGuid, ammo_clip=1, unk1=0))
|
||||
|
||||
case AvatarResponse.Killed(mount) =>
|
||||
val pguid = player.GUID
|
||||
val avatarId = player.Definition.ObjectId
|
||||
//pure logic
|
||||
sessionLogic.shooting.shotsWhileDead = 0
|
||||
sessionLogic.zoning.CancelZoningProcess()
|
||||
|
|
@ -456,12 +465,16 @@ class AvatarHandlerLogic(val ops: SessionAvatarHandlers, implicit val context: A
|
|||
case obj: Vehicle if obj.Destroyed =>
|
||||
sessionLogic.vehicles.ConditionalDriverVehicleControl(obj)
|
||||
sessionLogic.general.unaccessContainer(obj)
|
||||
player.VehicleSeated = None
|
||||
sendResponse(OCM.detailed(player))
|
||||
case _: Vehicle =>
|
||||
player.VehicleSeated = None
|
||||
sendResponse(OCM.detailed(player))
|
||||
case obj: PlanetSideGameObject with Mountable with Container if obj.Destroyed =>
|
||||
sessionLogic.general.unaccessContainer(obj)
|
||||
case _ => ()
|
||||
}
|
||||
player.VehicleSeated = None
|
||||
sendResponse(OCM.detailed(player))
|
||||
continent.AvatarEvents ! AvatarServiceMessage(
|
||||
continent.id,
|
||||
AvatarAction.LoadPlayer(pguid, avatarId, pguid, player.Definition.Packet.ConstructorData(player).get, None)
|
||||
)
|
||||
sendResponse(ChatMsg(ChatMessageType.UNK_225, "CSR MODE"))
|
||||
|
||||
case AvatarResponse.Release(tplayer) if isNotSameTarget =>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,19 @@
|
|||
// Copyright (c) 2024 PSForever
|
||||
package net.psforever.actors.session.csr
|
||||
|
||||
import net.psforever.actors.session.SessionActor
|
||||
import net.psforever.actors.session.support.{ChatFunctions, GalaxyHandlerFunctions, GeneralFunctions, LocalHandlerFunctions, ModeLogic, MountHandlerFunctions, PlayerMode, SessionData, SquadHandlerFunctions, TerminalHandlerFunctions, VehicleFunctions, VehicleHandlerFunctions, WeaponAndProjectileFunctions}
|
||||
import net.psforever.objects.{Deployables, Session, Vehicle}
|
||||
import net.psforever.objects.{Deployables, PlanetSideGameObject, Player, Session, Vehicle}
|
||||
import net.psforever.objects.avatar.Certification
|
||||
import net.psforever.packet.PlanetSidePacket
|
||||
import net.psforever.packet.game.{ChatMsg, ObjectCreateDetailedMessage}
|
||||
import net.psforever.packet.game.objectcreate.{ObjectCreateMessageParent, RibbonBars}
|
||||
import net.psforever.objects.serverobject.ServerObject
|
||||
import net.psforever.objects.serverobject.mount.Mountable
|
||||
import net.psforever.objects.vital.Vitality
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game.{ChatMsg, ObjectCreateDetailedMessage, PlanetsideAttributeMessage}
|
||||
import net.psforever.packet.game.objectcreate.RibbonBars
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
import net.psforever.services.chat.{CustomerServiceChannel, SpectatorChannel}
|
||||
import net.psforever.types.{ChatMessageType, MeritCommendation}
|
||||
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||
import net.psforever.types.{ChatMessageType, MeritCommendation, PlanetSideGUID}
|
||||
|
||||
class CustomerServiceRepresentativeMode(data: SessionData) extends ModeLogic {
|
||||
val avatarResponse: AvatarHandlerLogic = AvatarHandlerLogic(data.avatarResponse)
|
||||
|
|
@ -32,8 +35,8 @@ class CustomerServiceRepresentativeMode(data: SessionData) extends ModeLogic {
|
|||
val player = session.player
|
||||
val avatar = session.avatar
|
||||
val continent = session.zone
|
||||
val sendResponse: PlanetSidePacket=>Unit = data.sendResponse
|
||||
//
|
||||
data.zoning.displayZoningMessageWhenCancelled = false
|
||||
if (oldCertifications.isEmpty) {
|
||||
oldCertifications = avatar.certifications
|
||||
oldRibbons = avatar.decoration.ribbonBars
|
||||
|
|
@ -47,49 +50,27 @@ class CustomerServiceRepresentativeMode(data: SessionData) extends ModeLogic {
|
|||
))
|
||||
)
|
||||
player.avatar = newAvatar
|
||||
data.context.self ! SessionActor.SetAvatar(newAvatar)
|
||||
data.session = session.copy(avatar = newAvatar, player = player)
|
||||
Deployables.InitializeDeployableQuantities(newAvatar)
|
||||
}
|
||||
val vehicleAndSeat = data.vehicles.GetMountableAndSeat(None, player, continent) match {
|
||||
case (Some(obj: Vehicle), Some(seatNum)) =>
|
||||
Some(ObjectCreateMessageParent(obj.GUID, seatNum))
|
||||
case _ =>
|
||||
None
|
||||
}
|
||||
requireDismount(continent, player)
|
||||
data.keepAlivePersistenceFunc = keepAlivePersistanceCSR
|
||||
//
|
||||
val pguid = player.GUID
|
||||
val definition = player.Definition
|
||||
val objectClass = definition.ObjectId
|
||||
val packet = definition.Packet
|
||||
sendResponse(ObjectCreateDetailedMessage(
|
||||
0L,
|
||||
objectClass,
|
||||
pguid,
|
||||
vehicleAndSeat,
|
||||
packet.DetailedConstructorData(player).get
|
||||
))
|
||||
data.zoning.spawn.HandleSetCurrentAvatar(player)
|
||||
continent.AvatarEvents ! AvatarServiceMessage(continent.id, AvatarAction.LoadPlayer(
|
||||
pguid,
|
||||
objectClass,
|
||||
pguid,
|
||||
packet.ConstructorData(player).get,
|
||||
vehicleAndSeat
|
||||
))
|
||||
CustomerServiceRepresentativeMode.renderPlayer(data, continent, player)
|
||||
if (player.silenced) {
|
||||
data.chat.commandIncomingSilence(session, ChatMsg(ChatMessageType.CMT_SILENCE, "player 0"))
|
||||
}
|
||||
data.chat.JoinChannel(SpectatorChannel)
|
||||
data.chat.JoinChannel(CustomerServiceChannel)
|
||||
sendResponse(ChatMsg(ChatMessageType.UNK_225, "CSR MODE ON"))
|
||||
data.sendResponse(ChatMsg(ChatMessageType.UNK_225, "CSR MODE ON"))
|
||||
}
|
||||
|
||||
override def switchFrom(session: Session): Unit = {
|
||||
val player = session.player
|
||||
val avatar = session.avatar
|
||||
val continent = session.zone
|
||||
val sendResponse: PlanetSidePacket => Unit = data.sendResponse
|
||||
//
|
||||
data.zoning.displayZoningMessageWhenCancelled = true
|
||||
val newAvatar = avatar.copy(
|
||||
certifications = oldCertifications,
|
||||
decoration = avatar.decoration.copy(ribbonBars = oldRibbons)
|
||||
|
|
@ -97,37 +78,90 @@ class CustomerServiceRepresentativeMode(data: SessionData) extends ModeLogic {
|
|||
oldCertifications = Set()
|
||||
oldRibbons = RibbonBars()
|
||||
player.avatar = newAvatar
|
||||
data.context.self ! SessionActor.SetAvatar(newAvatar)
|
||||
val vehicleAndSeat = data.vehicles.GetMountableAndSeat(None, player, continent) match {
|
||||
case (Some(obj: Vehicle), Some(seatNum)) =>
|
||||
Some(ObjectCreateMessageParent(obj.GUID, seatNum))
|
||||
case _ =>
|
||||
None
|
||||
}
|
||||
data.session = session.copy(avatar = newAvatar, player = player)
|
||||
Deployables.InitializeDeployableQuantities(newAvatar)
|
||||
//
|
||||
val pguid = player.GUID
|
||||
val definition = player.Definition
|
||||
val objectClass = definition.ObjectId
|
||||
val packet = definition.Packet
|
||||
sendResponse(ObjectCreateDetailedMessage(
|
||||
0L,
|
||||
objectClass,
|
||||
pguid,
|
||||
vehicleAndSeat,
|
||||
packet.DetailedConstructorData(player).get
|
||||
))
|
||||
data.zoning.spawn.HandleSetCurrentAvatar(player)
|
||||
continent.AvatarEvents ! AvatarServiceMessage(continent.id, AvatarAction.LoadPlayer(
|
||||
pguid,
|
||||
objectClass,
|
||||
pguid,
|
||||
packet.ConstructorData(player).get,
|
||||
vehicleAndSeat
|
||||
))
|
||||
requireDismount(continent, player)
|
||||
data.keepAlivePersistenceFunc = data.keepAlivePersistence
|
||||
//
|
||||
CustomerServiceRepresentativeMode.renderPlayer(data, continent, player)
|
||||
data.chat.LeaveChannel(SpectatorChannel)
|
||||
data.chat.LeaveChannel(CustomerServiceChannel)
|
||||
sendResponse(ChatMsg(ChatMessageType.UNK_225, "CSR MODE OFF"))
|
||||
data.sendResponse(ChatMsg(ChatMessageType.UNK_225, "CSR MODE OFF"))
|
||||
}
|
||||
|
||||
private def requireDismount(zone: Zone, player: Player): Unit = {
|
||||
data.vehicles.GetMountableAndSeat(None, player, zone) match {
|
||||
case (Some(obj: Vehicle), Some(seatNum)) if seatNum == 0 =>
|
||||
data.vehicles.ServerVehicleOverrideStop(obj)
|
||||
obj.Actor ! ServerObject.AttributeMsg(10, 3) //faction-accessible driver seat
|
||||
obj.Actor ! Mountable.TryDismount(player, seatNum)
|
||||
player.VehicleSeated = None
|
||||
case (Some(obj), Some(seatNum)) =>
|
||||
obj.Actor ! Mountable.TryDismount(player, seatNum)
|
||||
player.VehicleSeated = None
|
||||
case _ =>
|
||||
player.VehicleSeated = None
|
||||
}
|
||||
}
|
||||
|
||||
private def keepAlivePersistanceCSR(): Unit = {
|
||||
data.keepAlivePersistence()
|
||||
topOffHealthOfPlayer(data.player)
|
||||
data.continent.GUID(data.player.VehicleSeated)
|
||||
.collect {
|
||||
case obj: PlanetSideGameObject with Vitality => topOffHealth(obj)
|
||||
}
|
||||
}
|
||||
|
||||
private def topOffHealth(obj: PlanetSideGameObject with Vitality): Unit = {
|
||||
obj match {
|
||||
case p: Player => topOffHealthOfPlayer(p)
|
||||
case v: Vehicle => topOffHealthOfVehicle(v)
|
||||
case o: PlanetSideGameObject with Vitality => topOffHealthOfGeneric(o)
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
|
||||
private def topOffHealthOfPlayer(player: Player): Unit = {
|
||||
//driver below half health, full heal
|
||||
val maxHealthOfPlayer = player.MaxHealth.toLong
|
||||
if (player.Health < maxHealthOfPlayer * 0.5f) {
|
||||
player.Health = maxHealthOfPlayer.toInt
|
||||
player.LogActivity(player.ClearHistory().head)
|
||||
data.sendResponse(PlanetsideAttributeMessage(player.GUID, 0, maxHealthOfPlayer))
|
||||
data.continent.AvatarEvents ! AvatarServiceMessage(data.zoning.zoneChannel, AvatarAction.PlanetsideAttribute(player.GUID, 0, maxHealthOfPlayer))
|
||||
}
|
||||
}
|
||||
|
||||
private def topOffHealthOfVehicle(vehicle: Vehicle): Unit = {
|
||||
topOffHealthOfGeneric(vehicle)
|
||||
//vehicle shields below half, full shields
|
||||
val maxShieldsOfVehicle = vehicle.MaxShields.toLong
|
||||
val shieldsUi = vehicle.Definition.shieldUiAttribute
|
||||
if (vehicle.Shields < maxShieldsOfVehicle) {
|
||||
val guid = vehicle.GUID
|
||||
vehicle.Shields = maxShieldsOfVehicle.toInt
|
||||
data.sendResponse(PlanetsideAttributeMessage(guid, shieldsUi, maxShieldsOfVehicle))
|
||||
data.continent.VehicleEvents ! VehicleServiceMessage(
|
||||
data.continent.id,
|
||||
VehicleAction.PlanetsideAttribute(PlanetSideGUID(0), guid, shieldsUi, maxShieldsOfVehicle)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private def topOffHealthOfGeneric(obj: PlanetSideGameObject with Vitality): Unit = {
|
||||
//below half health, full heal
|
||||
val guid = obj.GUID
|
||||
val maxHealthOf = obj.MaxHealth.toLong
|
||||
if (obj.Health < maxHealthOf) {
|
||||
obj.Health = maxHealthOf.toInt
|
||||
data.sendResponse(PlanetsideAttributeMessage(guid, 0, maxHealthOf))
|
||||
data.continent.VehicleEvents ! VehicleServiceMessage(
|
||||
data.continent.id,
|
||||
VehicleAction.PlanetsideAttribute(PlanetSideGUID(0), guid, 0, maxHealthOf)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -135,4 +169,24 @@ case object CustomerServiceRepresentativeMode extends PlayerMode {
|
|||
def setup(data: SessionData): ModeLogic = {
|
||||
new CustomerServiceRepresentativeMode(data)
|
||||
}
|
||||
|
||||
private[csr] def renderPlayer(data: SessionData, zone: Zone, player: Player): Unit = {
|
||||
val pguid = player.GUID
|
||||
val definition = player.Definition
|
||||
val objectClass = definition.ObjectId
|
||||
val packet = definition.Packet
|
||||
data.sendResponse(ObjectCreateDetailedMessage(
|
||||
objectClass,
|
||||
pguid,
|
||||
packet.DetailedConstructorData(player).get
|
||||
))
|
||||
data.zoning.spawn.HandleSetCurrentAvatar(player)
|
||||
zone.AvatarEvents ! AvatarServiceMessage(zone.id, AvatarAction.LoadPlayer(
|
||||
pguid,
|
||||
objectClass,
|
||||
pguid,
|
||||
packet.ConstructorData(player).get,
|
||||
None
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
|
|||
sessionLogic.zoning.CancelZoningProcess()
|
||||
}
|
||||
player.Cloaked = player.ExoSuit == ExoSuitType.Infiltration && isCloaking
|
||||
maxCapacitorTick()
|
||||
maxCapacitorTick(jumpThrust)
|
||||
if (isMovingPlus && sessionLogic.terminals.usingMedicalTerminal.isDefined) {
|
||||
continent.GUID(sessionLogic.terminals.usingMedicalTerminal) match {
|
||||
case Some(term: Terminal with ProximityUnit) =>
|
||||
|
|
@ -297,60 +297,55 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
|
|||
case _ =>
|
||||
None
|
||||
}
|
||||
cancelZoningWhenGeneralHandled(
|
||||
sessionLogic.validObject(pkt.object_guid, decorator = "UseItem") match {
|
||||
case Some(door: Door) =>
|
||||
handleUseDoor(door, equipment)
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case Some(resourceSilo: ResourceSilo) =>
|
||||
ops.handleUseResourceSilo(resourceSilo, equipment)
|
||||
case Some(panel: IFFLock) =>
|
||||
ops.handleUseGeneralEntity(panel, equipment)
|
||||
case Some(obj: Player) =>
|
||||
ops.handleUsePlayer(obj, equipment, pkt)
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case Some(locker: Locker) =>
|
||||
ops.handleUseLocker(locker, equipment, pkt)
|
||||
case Some(gen: Generator) =>
|
||||
ops.handleUseGeneralEntity(gen, equipment)
|
||||
case Some(mech: ImplantTerminalMech) =>
|
||||
ops.handleUseGeneralEntity(mech, equipment)
|
||||
case Some(captureTerminal: CaptureTerminal) =>
|
||||
ops.handleUseCaptureTerminal(captureTerminal, equipment)
|
||||
case Some(obj: FacilityTurret) =>
|
||||
ops.handleUseFacilityTurret(obj, equipment, pkt)
|
||||
case Some(obj: Vehicle) =>
|
||||
ops.handleUseVehicle(obj, equipment, pkt)
|
||||
case Some(terminal: Terminal) =>
|
||||
ops.handleUseTerminal(terminal, equipment, pkt)
|
||||
case Some(obj: SpawnTube) =>
|
||||
ops.handleUseSpawnTube(obj, equipment)
|
||||
case Some(obj: SensorDeployable) =>
|
||||
ops.handleUseGeneralEntity(obj, equipment)
|
||||
case Some(obj: TurretDeployable) =>
|
||||
ops.handleUseGeneralEntity(obj, equipment)
|
||||
case Some(obj: TrapDeployable) =>
|
||||
ops.handleUseGeneralEntity(obj, equipment)
|
||||
case Some(obj: ShieldGeneratorDeployable) =>
|
||||
ops.handleUseGeneralEntity(obj, equipment)
|
||||
case Some(obj: TelepadDeployable) if player.spectator =>
|
||||
ops.handleUseTelepadDeployable(obj, equipment, pkt, ops.useRouterTelepadSystemSecretly)
|
||||
case Some(obj: Utility.InternalTelepad) if player.spectator =>
|
||||
ops.handleUseInternalTelepad(obj, pkt, ops.useRouterTelepadSystemSecretly)
|
||||
case Some(obj: TelepadDeployable) =>
|
||||
ops.handleUseTelepadDeployable(obj, equipment, pkt, ops.useRouterTelepadSystem)
|
||||
case Some(obj: Utility.InternalTelepad) =>
|
||||
ops.handleUseInternalTelepad(obj, pkt, ops.useRouterTelepadSystem)
|
||||
case Some(obj: CaptureFlag) =>
|
||||
ops.handleUseCaptureFlag(obj)
|
||||
case Some(_: WarpGate) =>
|
||||
ops.handleUseWarpGate(equipment)
|
||||
case Some(obj) =>
|
||||
ops.handleUseDefaultEntity(obj, equipment)
|
||||
case None =>
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
}
|
||||
)
|
||||
sessionLogic.validObject(pkt.object_guid, decorator = "UseItem") match {
|
||||
case Some(door: Door) =>
|
||||
handleUseDoor(door, equipment)
|
||||
case Some(resourceSilo: ResourceSilo) =>
|
||||
ops.handleUseResourceSilo(resourceSilo, equipment)
|
||||
case Some(panel: IFFLock) =>
|
||||
ops.handleUseGeneralEntity(panel, equipment)
|
||||
case Some(obj: Player) =>
|
||||
ops.handleUsePlayer(obj, equipment, pkt)
|
||||
case Some(locker: Locker) =>
|
||||
ops.handleUseLocker(locker, equipment, pkt)
|
||||
case Some(gen: Generator) =>
|
||||
ops.handleUseGeneralEntity(gen, equipment)
|
||||
case Some(mech: ImplantTerminalMech) =>
|
||||
ops.handleUseGeneralEntity(mech, equipment)
|
||||
case Some(captureTerminal: CaptureTerminal) =>
|
||||
ops.handleUseCaptureTerminal(captureTerminal, equipment)
|
||||
case Some(obj: FacilityTurret) =>
|
||||
ops.handleUseFacilityTurret(obj, equipment, pkt)
|
||||
case Some(obj: Vehicle) =>
|
||||
ops.handleUseVehicle(obj, equipment, pkt)
|
||||
case Some(terminal: Terminal) =>
|
||||
ops.handleUseTerminal(terminal, equipment, pkt)
|
||||
case Some(obj: SpawnTube) =>
|
||||
ops.handleUseSpawnTube(obj, equipment)
|
||||
case Some(obj: SensorDeployable) =>
|
||||
ops.handleUseGeneralEntity(obj, equipment)
|
||||
case Some(obj: TurretDeployable) =>
|
||||
ops.handleUseGeneralEntity(obj, equipment)
|
||||
case Some(obj: TrapDeployable) =>
|
||||
ops.handleUseGeneralEntity(obj, equipment)
|
||||
case Some(obj: ShieldGeneratorDeployable) =>
|
||||
ops.handleUseGeneralEntity(obj, equipment)
|
||||
case Some(obj: TelepadDeployable) if player.spectator =>
|
||||
ops.handleUseTelepadDeployable(obj, equipment, pkt, ops.useRouterTelepadSystemSecretly)
|
||||
case Some(obj: Utility.InternalTelepad) if player.spectator =>
|
||||
ops.handleUseInternalTelepad(obj, pkt, ops.useRouterTelepadSystemSecretly)
|
||||
case Some(obj: TelepadDeployable) =>
|
||||
ops.handleUseTelepadDeployable(obj, equipment, pkt, ops.useRouterTelepadSystem)
|
||||
case Some(obj: Utility.InternalTelepad) =>
|
||||
ops.handleUseInternalTelepad(obj, pkt, ops.useRouterTelepadSystem)
|
||||
case Some(obj: CaptureFlag) =>
|
||||
ops.handleUseCaptureFlag(obj)
|
||||
case Some(_: WarpGate) =>
|
||||
ops.handleUseWarpGate(equipment)
|
||||
case Some(obj) =>
|
||||
ops.handleUseDefaultEntity(obj, equipment)
|
||||
case None => ()
|
||||
}
|
||||
}
|
||||
|
||||
def handleUnuseItem(pkt: UnuseItemMessage): Unit = {
|
||||
|
|
@ -379,7 +374,7 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
|
|||
case dtype => dtype
|
||||
}
|
||||
sessionLogic.zoning.CancelZoningProcess()
|
||||
ops.handleDeployObject(continent, ammoType, pos, orient, player.WhichSide, PlanetSideEmpire.NEUTRAL, None)
|
||||
ops.handleDeployObject(continent, ammoType, pos, orient, player.WhichSide, PlanetSideEmpire.NEUTRAL)
|
||||
case Some(obj) =>
|
||||
log.warn(s"DeployObject: what is $obj, ${player.Name}? It's not a construction tool!")
|
||||
case None =>
|
||||
|
|
@ -727,16 +722,7 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
|
|||
/* supporting functions */
|
||||
|
||||
def handleUseDoor(door: Door, equipment: Option[Equipment]): Unit = {
|
||||
if (player.spectator) {
|
||||
//opens just for us
|
||||
val guid = door.GUID
|
||||
openDoor.collect {
|
||||
case oldDoor if guid != oldDoor.GUID =>
|
||||
sendResponse(GenericObjectStateMsg(oldDoor.GUID, state=17))
|
||||
}
|
||||
sendResponse(GenericObjectStateMsg(guid, state=16))
|
||||
openDoor = Some(door)
|
||||
} else {
|
||||
if (!player.spectator) {
|
||||
//opens for everyone
|
||||
equipment match {
|
||||
case Some(tool: Tool) if tool.Definition == GlobalDefinitions.medicalapplicator =>
|
||||
|
|
@ -747,39 +733,58 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
|
|||
}
|
||||
}
|
||||
|
||||
private def maxCapacitorTick(): Unit = {
|
||||
private def maxCapacitorTick(jumpThrust: Boolean): Unit = {
|
||||
if (player.ExoSuit == ExoSuitType.MAX) {
|
||||
val activate = (jumpThrust || player.isOverdrived || player.isShielded) && player.Capacitor > 0
|
||||
player.CapacitorState match {
|
||||
case CapacitorStateType.Idle => maxCapacitorTickIdle()
|
||||
case _ => maxCapacitorTickCharging()
|
||||
case CapacitorStateType.Discharging => maxCapacitorTickDischarging(activate)
|
||||
case CapacitorStateType.Charging => maxCapacitorTickCharging(activate)
|
||||
case _ => maxCapacitorTickIdle(activate)
|
||||
}
|
||||
} else if (player.CapacitorState != CapacitorStateType.Idle) {
|
||||
player.CapacitorState = CapacitorStateType.Idle
|
||||
}
|
||||
}
|
||||
|
||||
private def maxCapacitorTickIdle(): Unit = {
|
||||
if (player.Capacitor < player.ExoSuitDef.MaxCapacitor) {
|
||||
private def maxCapacitorTickIdle(activate: Boolean): Unit = {
|
||||
if (activate) {
|
||||
player.CapacitorState = CapacitorStateType.Discharging
|
||||
//maxCapacitorTickDischarging(activate)
|
||||
} else if (player.Capacitor < player.ExoSuitDef.MaxCapacitor) {
|
||||
player.CapacitorState = CapacitorStateType.Charging
|
||||
maxCapacitorTickCharging()
|
||||
}
|
||||
}
|
||||
|
||||
private def maxCapacitorTickCharging(): Unit = {
|
||||
if (player.Capacitor < player.ExoSuitDef.MaxCapacitor) {
|
||||
val timeDiff = (System.currentTimeMillis() - player.CapacitorLastChargedMillis).toFloat / 1000
|
||||
val chargeAmount = player.ExoSuitDef.CapacitorRechargePerSecond * timeDiff
|
||||
player.Capacitor += chargeAmount
|
||||
private def maxCapacitorTickDischarging(activate: Boolean): Unit = {
|
||||
if (activate) {
|
||||
val timeDiff = (System.currentTimeMillis() - player.CapacitorLastUsedMillis).toFloat / 1000
|
||||
val drainAmount = player.ExoSuitDef.CapacitorDrainPerSecond.toFloat * timeDiff
|
||||
player.Capacitor -= drainAmount
|
||||
sendResponse(PlanetsideAttributeMessage(player.GUID, 7, player.Capacitor.toInt))
|
||||
} else if (player.Capacitor == 0) {
|
||||
if (player.Faction == PlanetSideEmpire.TR) {
|
||||
ops.toggleMaxSpecialState(enable = false)
|
||||
}
|
||||
player.Capacitor = player.ExoSuitDef.MaxCapacitor.toFloat
|
||||
sendResponse(PlanetsideAttributeMessage(player.GUID, 7, player.Capacitor.toInt))
|
||||
player.CapacitorState = CapacitorStateType.Idle
|
||||
} else if (player.Capacitor < player.ExoSuitDef.MaxCapacitor) {
|
||||
player.CapacitorState = CapacitorStateType.Charging
|
||||
} else {
|
||||
player.CapacitorState = CapacitorStateType.Idle
|
||||
}
|
||||
}
|
||||
|
||||
private def cancelZoningWhenGeneralHandled(results: GeneralOperations.UseItem.Behavior): Unit = {
|
||||
results match {
|
||||
case GeneralOperations.UseItem.Unhandled => ()
|
||||
case _ => sessionLogic.zoning.CancelZoningProcess()
|
||||
private def maxCapacitorTickCharging(activate: Boolean): Unit = {
|
||||
val maxCapacitor = player.ExoSuitDef.MaxCapacitor
|
||||
if (activate) {
|
||||
player.CapacitorState = CapacitorStateType.Discharging
|
||||
//maxCapacitorTickDischarging(activate)
|
||||
} else if (player.Capacitor < player.ExoSuitDef.MaxCapacitor) {
|
||||
player.Capacitor = maxCapacitor.toFloat
|
||||
sendResponse(PlanetsideAttributeMessage(player.GUID, 7, maxCapacitor))
|
||||
} else {
|
||||
player.CapacitorState = CapacitorStateType.Idle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,14 +67,14 @@ class MountHandlerLogic(val ops: SessionMountHandlers, implicit val context: Act
|
|||
sessionLogic.zoning.CancelZoningProcess()
|
||||
sessionLogic.terminals.CancelAllProximityUnits()
|
||||
ops.MountingAction(tplayer, obj, seatNumber)
|
||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistence
|
||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistenceFunc
|
||||
|
||||
case Mountable.CanMount(obj: Vehicle, seatNumber, _)
|
||||
if obj.Definition == GlobalDefinitions.orbital_shuttle =>
|
||||
sessionLogic.zoning.CancelZoningProcess()
|
||||
sessionLogic.terminals.CancelAllProximityUnits()
|
||||
ops.MountingAction(tplayer, obj, seatNumber)
|
||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistence
|
||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistenceFunc
|
||||
|
||||
case Mountable.CanMount(obj: Vehicle, seatNumber, _)
|
||||
if obj.Definition == GlobalDefinitions.ant =>
|
||||
|
|
@ -141,7 +141,7 @@ class MountHandlerLogic(val ops: SessionMountHandlers, implicit val context: Act
|
|||
sendResponse(PlanetsideAttributeMessage(obj_guid, attribute_type=113, obj.Capacitor))
|
||||
sessionLogic.general.accessContainer(obj)
|
||||
ops.updateWeaponAtSeatPosition(obj, seatNumber)
|
||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistence
|
||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistenceFunc
|
||||
tplayer.Actor ! ResetAllEnvironmentInteractions
|
||||
ops.MountingAction(tplayer, obj, seatNumber)
|
||||
|
||||
|
|
@ -153,7 +153,7 @@ class MountHandlerLogic(val ops: SessionMountHandlers, implicit val context: Act
|
|||
sendResponse(PlanetsideAttributeMessage(obj_guid, obj.Definition.shieldUiAttribute, obj.Shields))
|
||||
sessionLogic.general.accessContainer(obj)
|
||||
ops.updateWeaponAtSeatPosition(obj, seatNumber)
|
||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistence
|
||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistenceFunc
|
||||
tplayer.Actor ! ResetAllEnvironmentInteractions
|
||||
ops.MountingAction(tplayer, obj, seatNumber)
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ package net.psforever.actors.session.csr
|
|||
import net.psforever.actors.session.support.{AvatarHandlerFunctions, ChatFunctions, GalaxyHandlerFunctions, GeneralFunctions, LocalHandlerFunctions, MountHandlerFunctions, SquadHandlerFunctions, TerminalHandlerFunctions, VehicleFunctions, VehicleHandlerFunctions, WeaponAndProjectileFunctions}
|
||||
import net.psforever.actors.zone.ZoneActor
|
||||
import net.psforever.objects.serverobject.ServerObject
|
||||
import net.psforever.objects.{Session, Vehicle}
|
||||
import net.psforever.objects.serverobject.mount.Mountable
|
||||
import net.psforever.objects.{Player, Session, Vehicle}
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.PlanetSidePacket
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
import net.psforever.services.chat.SpectatorChannel
|
||||
|
|
@ -31,24 +33,16 @@ class SpectatorCSRModeLogic(data: SessionData) extends ModeLogic {
|
|||
val player = session.player
|
||||
val continent = session.zone
|
||||
val pguid = player.GUID
|
||||
val sendResponse: PlanetSidePacket=>Unit = data.sendResponse
|
||||
val sendResponse: PlanetSidePacket => Unit = data.sendResponse
|
||||
//
|
||||
data.vehicles.GetMountableAndSeat(None, player, continent) match {
|
||||
case (Some(obj: Vehicle), Some(seatNum)) if seatNum == 0 =>
|
||||
data.vehicles.ServerVehicleOverrideStop(obj)
|
||||
obj.Actor ! ServerObject.AttributeMsg(10, 3) //faction-accessible driver seat
|
||||
obj.Seat(seatNum).foreach(_.unmount(player))
|
||||
player.VehicleSeated = None
|
||||
case (Some(obj), Some(seatNum)) =>
|
||||
obj.Seat(seatNum).foreach(_.unmount(player))
|
||||
player.VehicleSeated = None
|
||||
case _ => ()
|
||||
}
|
||||
data.squadService ! SquadServiceMessage(
|
||||
player,
|
||||
continent,
|
||||
SquadAction.Membership(SquadRequestType.Leave, player.CharId, Some(player.CharId), player.Name, None)
|
||||
)
|
||||
if (requireDismount(data, continent, player)) {
|
||||
CustomerServiceRepresentativeMode.renderPlayer(data, continent, player)
|
||||
}
|
||||
//
|
||||
player.spectator = true
|
||||
//player.bops = true
|
||||
|
|
@ -56,6 +50,7 @@ class SpectatorCSRModeLogic(data: SessionData) extends ModeLogic {
|
|||
data.chat.JoinChannel(SpectatorChannel)
|
||||
continent.actor ! ZoneActor.RemoveFromBlockMap(player)
|
||||
continent.AvatarEvents ! AvatarServiceMessage(continent.id, AvatarAction.ObjectDelete(pguid, pguid))
|
||||
sendResponse(ChatMsg(ChatMessageType.CMT_TOGGLESPECTATORMODE, "on"))
|
||||
sendResponse(ChatMsg(ChatMessageType.UNK_225, "CSR SPECTATOR MODE ON"))
|
||||
}
|
||||
|
||||
|
|
@ -64,7 +59,7 @@ class SpectatorCSRModeLogic(data: SessionData) extends ModeLogic {
|
|||
val pguid = player.GUID
|
||||
val continent = data.continent
|
||||
val avatarId = player.Definition.ObjectId
|
||||
//val sendResponse: PlanetSidePacket => Unit = data.sendResponse
|
||||
val sendResponse: PlanetSidePacket => Unit = data.sendResponse
|
||||
//
|
||||
player.spectator = false
|
||||
player.bops = false
|
||||
|
|
@ -75,6 +70,25 @@ class SpectatorCSRModeLogic(data: SessionData) extends ModeLogic {
|
|||
continent.id,
|
||||
AvatarAction.LoadPlayer(pguid, avatarId, pguid, player.Definition.Packet.ConstructorData(player).get, None)
|
||||
)
|
||||
sendResponse(ChatMsg(ChatMessageType.CMT_TOGGLESPECTATORMODE, "off"))
|
||||
}
|
||||
|
||||
private def requireDismount(data: SessionData, zone: Zone, player: Player): Boolean = {
|
||||
data.vehicles.GetMountableAndSeat(None, player, zone) match {
|
||||
case (Some(obj: Vehicle), Some(seatNum)) if seatNum == 0 =>
|
||||
data.vehicles.ServerVehicleOverrideStop(obj)
|
||||
obj.Actor ! ServerObject.AttributeMsg(10, 3) //faction-accessible driver seat
|
||||
obj.Actor ! Mountable.TryDismount(player, seatNum)
|
||||
player.VehicleSeated = None
|
||||
true
|
||||
case (Some(obj), Some(seatNum)) =>
|
||||
obj.Actor ! Mountable.TryDismount(player, seatNum)
|
||||
player.VehicleSeated = None
|
||||
true
|
||||
case _ =>
|
||||
player.VehicleSeated = None
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import net.psforever.objects.{Player, Vehicle}
|
|||
import net.psforever.objects.guid.TaskWorkflow
|
||||
import net.psforever.objects.serverobject.terminals.{OrderTerminalDefinition, Terminal}
|
||||
import net.psforever.packet.game.{FavoritesRequest, ItemTransactionMessage, ItemTransactionResultMessage, ProximityTerminalUseMessage}
|
||||
import net.psforever.types.TransactionType
|
||||
|
||||
object TerminalHandlerLogic {
|
||||
def apply(ops: SessionTerminalHandlers): TerminalHandlerLogic = {
|
||||
|
|
@ -62,13 +61,7 @@ class TerminalHandlerLogic(val ops: SessionTerminalHandlers, implicit val contex
|
|||
*/
|
||||
def handle(tplayer: Player, msg: ItemTransactionMessage, order: Terminal.Exchange): Unit = {
|
||||
order match {
|
||||
case Terminal.BuyEquipment(item)
|
||||
if tplayer.avatar.purchaseCooldown(item.Definition).nonEmpty =>
|
||||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Buy, success = false))
|
||||
ops.lastTerminalOrderFulfillment = true
|
||||
|
||||
case Terminal.BuyEquipment(item) =>
|
||||
avatarActor ! AvatarActor.UpdatePurchaseTime(item.Definition)
|
||||
TaskWorkflow.execute(BuyNewEquipmentPutInInventory(
|
||||
continent.GUID(tplayer.VehicleSeated) match {
|
||||
case Some(v: Vehicle) => v
|
||||
|
|
@ -97,11 +90,6 @@ class TerminalHandlerLogic(val ops: SessionTerminalHandlers, implicit val contex
|
|||
avatarActor ! AvatarActor.SellImplant(msg.terminal_guid, implant)
|
||||
ops.lastTerminalOrderFulfillment = true
|
||||
|
||||
case Terminal.BuyVehicle(vehicle, _, _)
|
||||
if tplayer.avatar.purchaseCooldown(vehicle.Definition).nonEmpty || player.spectator =>
|
||||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Buy, success = false))
|
||||
ops.lastTerminalOrderFulfillment = true
|
||||
|
||||
case Terminal.BuyVehicle(vehicle, weapons, trunk) =>
|
||||
ops.buyVehicle(msg.terminal_guid, msg.transaction_type, vehicle, weapons, trunk)
|
||||
ops.lastTerminalOrderFulfillment = true
|
||||
|
|
|
|||
|
|
@ -5,10 +5,11 @@ import akka.actor.{ActorContext, typed}
|
|||
import net.psforever.actors.session.AvatarActor
|
||||
import net.psforever.actors.session.support.{SessionData, VehicleFunctions, VehicleOperations}
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.{Vehicle, Vehicles}
|
||||
import net.psforever.objects.{PlanetSideGameObject, Player, Vehicle, Vehicles}
|
||||
import net.psforever.objects.serverobject.deploy.Deployment
|
||||
import net.psforever.objects.serverobject.mount.Mountable
|
||||
import net.psforever.objects.vehicles.control.BfrFlight
|
||||
import net.psforever.objects.vital.Vitality
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game.{ChildObjectStateMessage, DeployRequestMessage, FrameVehicleStateMessage, PlanetsideAttributeMessage, VehicleStateMessage, VehicleSubStateMessage}
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
|
|
@ -47,6 +48,7 @@ class VehicleLogic(val ops: VehicleOperations, implicit val context: ActorContex
|
|||
//we're driving the vehicle
|
||||
sessionLogic.persist()
|
||||
sessionLogic.turnCounterFunc(player.GUID)
|
||||
topOffHealthOfPlayer()
|
||||
topOffHealth(obj)
|
||||
sessionLogic.general.fallHeightTracker(pos.z)
|
||||
if (obj.MountedIn.isEmpty) {
|
||||
|
|
@ -131,6 +133,7 @@ class VehicleLogic(val ops: VehicleOperations, implicit val context: ActorContex
|
|||
//we're driving the vehicle
|
||||
sessionLogic.persist()
|
||||
sessionLogic.turnCounterFunc(player.GUID)
|
||||
topOffHealthOfPlayer()
|
||||
topOffHealth(obj)
|
||||
val (position, angle, velocity, notMountedState) = continent.GUID(obj.MountedIn) match {
|
||||
case Some(v: Vehicle) =>
|
||||
|
|
@ -216,11 +219,16 @@ class VehicleLogic(val ops: VehicleOperations, implicit val context: ActorContex
|
|||
case Some(mount: Mountable) => (o, mount.PassengerInSeat(player))
|
||||
case _ => (None, None)
|
||||
}) match {
|
||||
case (None, None) | (_, None) | (Some(_: Vehicle), Some(0)) => ()
|
||||
case _ =>
|
||||
case (None, None) | (_, None) | (Some(_: Vehicle), Some(0)) =>
|
||||
()
|
||||
case (Some(obj: PlanetSideGameObject with Vitality), _) =>
|
||||
sessionLogic.persist()
|
||||
sessionLogic.turnCounterFunc(player.GUID)
|
||||
topOffHealthOfPlayer()
|
||||
topOffHealth(obj)
|
||||
case _ =>
|
||||
sessionLogic.persist()
|
||||
sessionLogic.turnCounterFunc(player.GUID)
|
||||
}
|
||||
//the majority of the following check retrieves information to determine if we are in control of the child
|
||||
tools.find { _.GUID == object_guid } match {
|
||||
|
|
@ -333,6 +341,15 @@ class VehicleLogic(val ops: VehicleOperations, implicit val context: ActorContex
|
|||
}
|
||||
}
|
||||
|
||||
private def topOffHealth(obj: PlanetSideGameObject with Vitality): Unit = {
|
||||
obj match {
|
||||
case _: Player => topOffHealthOfPlayer()
|
||||
case v: Vehicle => topOffHealthOfVehicle(v)
|
||||
case o: PlanetSideGameObject with Vitality => topOffHealthOfGeneric(o)
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
|
||||
private def topOffHealthOfPlayer(): Unit = {
|
||||
//driver below half health, full heal
|
||||
val maxHealthOfPlayer = player.MaxHealth.toLong
|
||||
|
|
@ -340,32 +357,38 @@ class VehicleLogic(val ops: VehicleOperations, implicit val context: ActorContex
|
|||
player.Health = maxHealthOfPlayer.toInt
|
||||
player.LogActivity(player.ClearHistory().head)
|
||||
sendResponse(PlanetsideAttributeMessage(player.GUID, 0, maxHealthOfPlayer))
|
||||
continent.AvatarEvents ! AvatarServiceMessage(continent.id, AvatarAction.PlanetsideAttribute(player.GUID, 0, maxHealthOfPlayer))
|
||||
continent.AvatarEvents ! AvatarServiceMessage(sessionLogic.zoning.zoneChannel, AvatarAction.PlanetsideAttribute(player.GUID, 0, maxHealthOfPlayer))
|
||||
}
|
||||
}
|
||||
|
||||
private def topOffHealth(vehicle: Vehicle): Unit = {
|
||||
private def topOffHealthOfVehicle(vehicle: Vehicle): Unit = {
|
||||
topOffHealthOfPlayer()
|
||||
//vehicle below half health, full heal
|
||||
val guid = vehicle.GUID
|
||||
val maxHealthOfVehicle = vehicle.MaxHealth.toLong
|
||||
if (vehicle.Health < maxHealthOfVehicle) {
|
||||
vehicle.Health = maxHealthOfVehicle.toInt
|
||||
sendResponse(PlanetsideAttributeMessage(guid, 0, maxHealthOfVehicle))
|
||||
continent.VehicleEvents ! VehicleServiceMessage(
|
||||
continent.id,
|
||||
VehicleAction.PlanetsideAttribute(PlanetSideGUID(0), guid, 0, maxHealthOfVehicle)
|
||||
)
|
||||
}
|
||||
topOffHealthOfGeneric(vehicle)
|
||||
//vehicle shields below half, full shields
|
||||
val maxShieldsOfVehicle = vehicle.MaxShields.toLong
|
||||
val shieldsUi = vehicle.Definition.shieldUiAttribute
|
||||
if (vehicle.Shields < maxShieldsOfVehicle) {
|
||||
val guid = vehicle.GUID
|
||||
vehicle.Shields = maxShieldsOfVehicle.toInt
|
||||
sendResponse(PlanetsideAttributeMessage(guid, shieldsUi, maxShieldsOfVehicle))
|
||||
continent.VehicleEvents ! VehicleServiceMessage(
|
||||
continent.id,
|
||||
VehicleAction.PlanetsideAttribute(PlanetSideGUID(0), guid, shieldsUi, maxHealthOfVehicle)
|
||||
VehicleAction.PlanetsideAttribute(PlanetSideGUID(0), guid, shieldsUi, maxShieldsOfVehicle)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private def topOffHealthOfGeneric(obj: PlanetSideGameObject with Vitality): Unit = {
|
||||
topOffHealthOfPlayer()
|
||||
//vehicle below half health, full heal
|
||||
val guid = obj.GUID
|
||||
val maxHealthOf = obj.MaxHealth.toLong
|
||||
if (obj.Health < maxHealthOf) {
|
||||
obj.Health = maxHealthOf.toInt
|
||||
sendResponse(PlanetsideAttributeMessage(guid, 0, maxHealthOf))
|
||||
continent.VehicleEvents ! VehicleServiceMessage(
|
||||
continent.id,
|
||||
VehicleAction.PlanetsideAttribute(PlanetSideGUID(0), guid, 0, maxHealthOf)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -312,10 +312,14 @@ class AvatarHandlerLogic(val ops: SessionAvatarHandlers, implicit val context: A
|
|||
//redraw
|
||||
if (maxhand) {
|
||||
sendResponse(PlanetsideAttributeMessage(target, attribute_type=7, player.Capacitor.toLong))
|
||||
TaskWorkflow.execute(HoldNewEquipmentUp(player)(
|
||||
Tool(GlobalDefinitions.MAXArms(subtype, player.Faction)),
|
||||
0
|
||||
))
|
||||
val maxArmDefinition = GlobalDefinitions.MAXArms(subtype, player.Faction)
|
||||
TaskWorkflow.execute(HoldNewEquipmentUp(player)(Tool(maxArmDefinition), slot = 0))
|
||||
player.avatar.purchaseCooldown(maxArmDefinition)
|
||||
.collect(a => a)
|
||||
.getOrElse {
|
||||
avatarActor ! AvatarActor.UpdatePurchaseTime(maxArmDefinition)
|
||||
None
|
||||
}
|
||||
}
|
||||
//draw free hand
|
||||
player.FreeHand.Equipment.foreach { obj =>
|
||||
|
|
@ -343,6 +347,8 @@ class AvatarHandlerLogic(val ops: SessionAvatarHandlers, implicit val context: A
|
|||
)
|
||||
}
|
||||
DropLeftovers(player)(drop)
|
||||
//deactivate non-passive implants
|
||||
avatarActor ! AvatarActor.DeactivateActiveImplants
|
||||
|
||||
case AvatarResponse.ChangeExosuit(target, armor, exosuit, subtype, slot, _, oldHolsters, holsters, _, _, drop, delete) =>
|
||||
sendResponse(ArmorChangedMessage(target, exosuit, subtype))
|
||||
|
|
@ -395,14 +401,19 @@ class AvatarHandlerLogic(val ops: SessionAvatarHandlers, implicit val context: A
|
|||
drops.foreach(item => sendResponse(ObjectDeleteMessage(item.obj.GUID, unk1=0)))
|
||||
//redraw
|
||||
if (maxhand) {
|
||||
val maxArmWeapon = GlobalDefinitions.MAXArms(subtype, player.Faction)
|
||||
sendResponse(PlanetsideAttributeMessage(target, attribute_type=7, player.Capacitor.toLong))
|
||||
TaskWorkflow.execute(HoldNewEquipmentUp(player)(
|
||||
Tool(GlobalDefinitions.MAXArms(subtype, player.Faction)),
|
||||
slot = 0
|
||||
))
|
||||
TaskWorkflow.execute(HoldNewEquipmentUp(player)(Tool(maxArmWeapon), slot = 0))
|
||||
val cooldown = player.avatar.purchaseCooldown(maxArmWeapon)
|
||||
if (!oldHolsters.exists { case (e, _) => e.Definition == maxArmWeapon } &&
|
||||
player.avatar.purchaseCooldown(maxArmWeapon).isEmpty) {
|
||||
avatarActor ! AvatarActor.UpdatePurchaseTime(maxArmWeapon) //switching for first time causes cooldown
|
||||
}
|
||||
}
|
||||
sessionLogic.general.applyPurchaseTimersBeforePackingLoadout(player, player, holsters ++ inventory)
|
||||
DropLeftovers(player)(drops)
|
||||
//deactivate non-passive implants
|
||||
avatarActor ! AvatarActor.DeactivateActiveImplants
|
||||
|
||||
case AvatarResponse.ChangeLoadout(target, armor, exosuit, subtype, slot, _, oldHolsters, _, _, _, _) =>
|
||||
//redraw handled by callbacks
|
||||
|
|
|
|||
|
|
@ -333,56 +333,51 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
|
|||
case _ =>
|
||||
None
|
||||
}
|
||||
cancelZoningWhenGeneralHandled(
|
||||
sessionLogic.validObject(pkt.object_guid, decorator = "UseItem") match {
|
||||
case Some(door: Door) =>
|
||||
ops.handleUseDoor(door, equipment)
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case Some(resourceSilo: ResourceSilo) =>
|
||||
ops.handleUseResourceSilo(resourceSilo, equipment)
|
||||
case Some(panel: IFFLock) =>
|
||||
ops.handleUseGeneralEntity(panel, equipment)
|
||||
case Some(obj: Player) =>
|
||||
ops.handleUsePlayer(obj, equipment, pkt)
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case Some(locker: Locker) =>
|
||||
ops.handleUseLocker(locker, equipment, pkt)
|
||||
case Some(gen: Generator) =>
|
||||
ops.handleUseGeneralEntity(gen, equipment)
|
||||
case Some(mech: ImplantTerminalMech) =>
|
||||
ops.handleUseGeneralEntity(mech, equipment)
|
||||
case Some(captureTerminal: CaptureTerminal) =>
|
||||
ops.handleUseCaptureTerminal(captureTerminal, equipment)
|
||||
case Some(obj: FacilityTurret) =>
|
||||
ops.handleUseFacilityTurret(obj, equipment, pkt)
|
||||
case Some(obj: Vehicle) =>
|
||||
ops.handleUseVehicle(obj, equipment, pkt)
|
||||
case Some(terminal: Terminal) =>
|
||||
ops.handleUseTerminal(terminal, equipment, pkt)
|
||||
case Some(obj: SpawnTube) =>
|
||||
ops.handleUseSpawnTube(obj, equipment)
|
||||
case Some(obj: SensorDeployable) =>
|
||||
ops.handleUseGeneralEntity(obj, equipment)
|
||||
case Some(obj: TurretDeployable) =>
|
||||
ops.handleUseGeneralEntity(obj, equipment)
|
||||
case Some(obj: TrapDeployable) =>
|
||||
ops.handleUseGeneralEntity(obj, equipment)
|
||||
case Some(obj: ShieldGeneratorDeployable) =>
|
||||
ops.handleUseGeneralEntity(obj, equipment)
|
||||
case Some(obj: TelepadDeployable) =>
|
||||
ops.handleUseTelepadDeployable(obj, equipment, pkt, ops.useRouterTelepadSystem)
|
||||
case Some(obj: Utility.InternalTelepad) =>
|
||||
ops.handleUseInternalTelepad(obj, pkt, ops.useRouterTelepadSystem)
|
||||
case Some(obj: CaptureFlag) =>
|
||||
ops.handleUseCaptureFlag(obj)
|
||||
case Some(_: WarpGate) =>
|
||||
ops.handleUseWarpGate(equipment)
|
||||
case Some(obj) =>
|
||||
ops.handleUseDefaultEntity(obj, equipment)
|
||||
case None =>
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
}
|
||||
)
|
||||
sessionLogic.validObject(pkt.object_guid, decorator = "UseItem") match {
|
||||
case Some(door: Door) =>
|
||||
ops.handleUseDoor(door, equipment)
|
||||
case Some(resourceSilo: ResourceSilo) =>
|
||||
ops.handleUseResourceSilo(resourceSilo, equipment)
|
||||
case Some(panel: IFFLock) =>
|
||||
ops.handleUseGeneralEntity(panel, equipment)
|
||||
case Some(obj: Player) =>
|
||||
ops.handleUsePlayer(obj, equipment, pkt)
|
||||
case Some(locker: Locker) =>
|
||||
ops.handleUseLocker(locker, equipment, pkt)
|
||||
case Some(gen: Generator) =>
|
||||
ops.handleUseGeneralEntity(gen, equipment)
|
||||
case Some(mech: ImplantTerminalMech) =>
|
||||
ops.handleUseGeneralEntity(mech, equipment)
|
||||
case Some(captureTerminal: CaptureTerminal) =>
|
||||
ops.handleUseCaptureTerminal(captureTerminal, equipment)
|
||||
case Some(obj: FacilityTurret) =>
|
||||
ops.handleUseFacilityTurret(obj, equipment, pkt)
|
||||
case Some(obj: Vehicle) =>
|
||||
ops.handleUseVehicle(obj, equipment, pkt)
|
||||
case Some(terminal: Terminal) =>
|
||||
ops.handleUseTerminal(terminal, equipment, pkt)
|
||||
case Some(obj: SpawnTube) =>
|
||||
ops.handleUseSpawnTube(obj, equipment)
|
||||
case Some(obj: SensorDeployable) =>
|
||||
ops.handleUseGeneralEntity(obj, equipment)
|
||||
case Some(obj: TurretDeployable) =>
|
||||
ops.handleUseGeneralEntity(obj, equipment)
|
||||
case Some(obj: TrapDeployable) =>
|
||||
ops.handleUseGeneralEntity(obj, equipment)
|
||||
case Some(obj: ShieldGeneratorDeployable) =>
|
||||
ops.handleUseGeneralEntity(obj, equipment)
|
||||
case Some(obj: TelepadDeployable) =>
|
||||
ops.handleUseTelepadDeployable(obj, equipment, pkt, ops.useRouterTelepadSystem)
|
||||
case Some(obj: Utility.InternalTelepad) =>
|
||||
ops.handleUseInternalTelepad(obj, pkt, ops.useRouterTelepadSystem)
|
||||
case Some(obj: CaptureFlag) =>
|
||||
ops.handleUseCaptureFlag(obj)
|
||||
case Some(_: WarpGate) =>
|
||||
ops.handleUseWarpGate(equipment)
|
||||
case Some(obj) =>
|
||||
ops.handleUseDefaultEntity(obj, equipment)
|
||||
case None => ()
|
||||
}
|
||||
}
|
||||
|
||||
def handleUnuseItem(pkt: UnuseItemMessage): Unit = {
|
||||
|
|
@ -411,7 +406,7 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
|
|||
}
|
||||
log.info(s"${player.Name} is constructing a $ammoType deployable")
|
||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||
ops.handleDeployObject(continent, ammoType, pos, orient, player.WhichSide, player.Faction, Some((player, obj)))
|
||||
ops.handleDeployObject(continent, ammoType, pos, orient, player.WhichSide, player.Faction, player, obj)
|
||||
case Some(obj) =>
|
||||
log.warn(s"DeployObject: what is $obj, ${player.Name}? It's not a construction tool!")
|
||||
case None =>
|
||||
|
|
@ -976,14 +971,4 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
|
|||
)
|
||||
)
|
||||
}
|
||||
|
||||
private def cancelZoningWhenGeneralHandled(results: GeneralOperations.UseItem.Behavior): Unit = {
|
||||
results match {
|
||||
case GeneralOperations.UseItem.Handled =>
|
||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||
case GeneralOperations.UseItem.HandledPassive =>
|
||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel")
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ class MountHandlerLogic(val ops: SessionMountHandlers, implicit val context: Act
|
|||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||
sessionLogic.terminals.CancelAllProximityUnits()
|
||||
ops.MountingAction(tplayer, obj, seatNumber)
|
||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistence
|
||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistenceFunc
|
||||
|
||||
case Mountable.CanMount(obj: Vehicle, seatNumber, _)
|
||||
if obj.Definition == GlobalDefinitions.orbital_shuttle =>
|
||||
|
|
@ -71,7 +71,7 @@ class MountHandlerLogic(val ops: SessionMountHandlers, implicit val context: Act
|
|||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_mount")
|
||||
sessionLogic.terminals.CancelAllProximityUnits()
|
||||
ops.MountingAction(tplayer, obj, seatNumber)
|
||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistence
|
||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistenceFunc
|
||||
|
||||
case Mountable.CanMount(obj: Vehicle, seatNumber, _)
|
||||
if obj.Definition == GlobalDefinitions.ant =>
|
||||
|
|
@ -148,7 +148,7 @@ class MountHandlerLogic(val ops: SessionMountHandlers, implicit val context: Act
|
|||
sendResponse(PlanetsideAttributeMessage(obj_guid, attribute_type=113, obj.Capacitor))
|
||||
sessionLogic.general.accessContainer(obj)
|
||||
ops.updateWeaponAtSeatPosition(obj, seatNumber)
|
||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistence
|
||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistenceFunc
|
||||
tplayer.Actor ! ResetAllEnvironmentInteractions
|
||||
ops.MountingAction(tplayer, obj, seatNumber)
|
||||
|
||||
|
|
@ -166,7 +166,7 @@ class MountHandlerLogic(val ops: SessionMountHandlers, implicit val context: Act
|
|||
sendResponse(PlanetsideAttributeMessage(obj_guid, obj.Definition.shieldUiAttribute, obj.Shields))
|
||||
sessionLogic.general.accessContainer(obj)
|
||||
ops.updateWeaponAtSeatPosition(obj, seatNumber)
|
||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistence
|
||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistenceFunc
|
||||
tplayer.Actor ! ResetAllEnvironmentInteractions
|
||||
ops.MountingAction(tplayer, obj, seatNumber)
|
||||
|
||||
|
|
|
|||
|
|
@ -5,14 +5,11 @@ import akka.actor.{ActorContext, typed}
|
|||
import net.psforever.actors.session.AvatarActor
|
||||
import net.psforever.actors.session.support.{SessionData, SessionTerminalHandlers, TerminalHandlerFunctions}
|
||||
import net.psforever.login.WorldSession.{BuyNewEquipmentPutInInventory, SellEquipmentFromInventory}
|
||||
import net.psforever.objects.{GlobalDefinitions, Player, Vehicle}
|
||||
import net.psforever.objects.{Player, Vehicle}
|
||||
import net.psforever.objects.guid.TaskWorkflow
|
||||
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.objects.sourcing.AmenitySource
|
||||
import net.psforever.objects.vital.TerminalUsedActivity
|
||||
import net.psforever.packet.game.{FavoritesRequest, ItemTransactionMessage, ItemTransactionResultMessage, ProximityTerminalUseMessage, UnuseItemMessage}
|
||||
import net.psforever.types.{TransactionType, Vector3}
|
||||
import net.psforever.packet.game.{FavoritesRequest, ItemTransactionMessage, ItemTransactionResultMessage, ProximityTerminalUseMessage}
|
||||
import net.psforever.types.TransactionType
|
||||
|
||||
object TerminalHandlerLogic {
|
||||
def apply(ops: SessionTerminalHandlers): TerminalHandlerLogic = {
|
||||
|
|
@ -89,6 +86,10 @@ class TerminalHandlerLogic(val ops: SessionTerminalHandlers, implicit val contex
|
|||
|
||||
case Terminal.BuyVehicle(vehicle, weapons, trunk) =>
|
||||
ops.buyVehicle(msg.terminal_guid, msg.transaction_type, vehicle, weapons, trunk)
|
||||
.collect {
|
||||
case _: Vehicle =>
|
||||
avatarActor ! AvatarActor.UpdatePurchaseTime(vehicle.Definition)
|
||||
}
|
||||
ops.lastTerminalOrderFulfillment = true
|
||||
|
||||
case Terminal.NoDeal() if msg != null =>
|
||||
|
|
|
|||
|
|
@ -5,10 +5,11 @@ import akka.actor.{ActorContext, typed}
|
|||
import net.psforever.actors.session.AvatarActor
|
||||
import net.psforever.actors.session.support.{SessionData, VehicleFunctions, VehicleOperations}
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.{Vehicle, Vehicles}
|
||||
import net.psforever.objects.{PlanetSideGameObject, Vehicle, Vehicles}
|
||||
import net.psforever.objects.serverobject.deploy.Deployment
|
||||
import net.psforever.objects.serverobject.mount.Mountable
|
||||
import net.psforever.objects.vehicles.control.BfrFlight
|
||||
import net.psforever.objects.vital.Vitality
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game.{ChatMsg, ChildObjectStateMessage, DeployRequestMessage, FrameVehicleStateMessage, VehicleStateMessage, VehicleSubStateMessage}
|
||||
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||
|
|
@ -214,7 +215,8 @@ class VehicleLogic(val ops: VehicleOperations, implicit val context: ActorContex
|
|||
case Some(mount: Mountable) => (o, mount.PassengerInSeat(player))
|
||||
case _ => (None, None)
|
||||
}) match {
|
||||
case (None, None) | (_, None) | (Some(_: Vehicle), Some(0)) => ()
|
||||
case (None, None) | (_, None) | (Some(_: Vehicle), Some(0)) =>
|
||||
()
|
||||
case _ =>
|
||||
sessionLogic.persist()
|
||||
sessionLogic.turnCounterFunc(player.GUID)
|
||||
|
|
|
|||
|
|
@ -1058,30 +1058,53 @@ class GeneralOperations(
|
|||
orientation: Vector3,
|
||||
side: Sidedness,
|
||||
faction: PlanetSideEmpire.Value,
|
||||
optionalOwnerBuiltWith: Option[(Player, ConstructionItem)]
|
||||
owner: Player,
|
||||
builtWith: ConstructionItem
|
||||
): Unit = {
|
||||
val deployableEntity: Deployable = Deployables.Make(deployableType)()
|
||||
deployableEntity.Position = position
|
||||
deployableEntity.Orientation = orientation
|
||||
deployableEntity.WhichSide = side
|
||||
deployableEntity.Faction = faction
|
||||
val tasking: TaskBundle = deployableEntity match {
|
||||
case turret: TurretDeployable =>
|
||||
GUIDTask.registerDeployableTurret(zone.GUID, turret)
|
||||
case _ =>
|
||||
GUIDTask.registerObject(zone.GUID, deployableEntity)
|
||||
}
|
||||
val zoneBuildCommand = optionalOwnerBuiltWith
|
||||
.collect { case (owner, tool) =>
|
||||
deployableEntity.AssignOwnership(owner)
|
||||
Zone.Deployable.BuildByOwner(deployableEntity, owner, tool)
|
||||
}
|
||||
.getOrElse(Zone.Deployable.Build(deployableEntity))
|
||||
val (deployableEntity, tasking) = commonHandleDeployObjectSetup(zone, deployableType, position, orientation, side, faction)
|
||||
deployableEntity.AssignOwnership(owner)
|
||||
//execute
|
||||
TaskWorkflow.execute(CallBackForTask(tasking, zone.Deployables, zoneBuildCommand, context.self))
|
||||
TaskWorkflow.execute(CallBackForTask(
|
||||
tasking,
|
||||
zone.Deployables,
|
||||
Zone.Deployable.BuildByOwner(deployableEntity, owner, builtWith),
|
||||
context.self
|
||||
))
|
||||
}
|
||||
|
||||
def handleUseDoor(door: Door, equipment: Option[Equipment]): GeneralOperations.UseItem.Behavior = {
|
||||
def handleDeployObject(
|
||||
zone: Zone,
|
||||
deployableType: DeployedItem.Value,
|
||||
position: Vector3,
|
||||
orientation: Vector3,
|
||||
side: Sidedness,
|
||||
faction: PlanetSideEmpire.Value
|
||||
): Unit = {
|
||||
val (deployableEntity, tasking) = commonHandleDeployObjectSetup(zone, deployableType, position, orientation, side, faction)
|
||||
//execute
|
||||
TaskWorkflow.execute(CallBackForTask(
|
||||
tasking,
|
||||
zone.Deployables,
|
||||
Zone.Deployable.Build(deployableEntity),
|
||||
context.self
|
||||
)).onComplete {
|
||||
_ =>
|
||||
Players.buildCooldownReset(zone, player.Name, deployableEntity.GUID)
|
||||
deployableEntity.Actor ! Deployable.Deconstruct(Some(20.minutes))
|
||||
if (deployableType == DeployedItem.boomer) {
|
||||
val trigger = new BoomerTrigger
|
||||
trigger.Companion = deployableEntity.GUID
|
||||
deployableEntity.asInstanceOf[BoomerDeployable].Trigger = trigger
|
||||
TaskWorkflow.execute(CallBackForTask(
|
||||
GUIDTask.registerEquipment(zone.GUID, trigger),
|
||||
zone.Ground,
|
||||
Zone.Ground.DropItem(trigger, position + Vector3.z(value = 0.5f), Vector3.z(orientation.z))
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def handleUseDoor(door: Door, equipment: Option[Equipment]): Unit = {
|
||||
equipment match {
|
||||
case Some(tool: Tool) if tool.Definition == GlobalDefinitions.medicalapplicator =>
|
||||
val distance: Float = math.max(
|
||||
|
|
@ -1092,88 +1115,72 @@ class GeneralOperations(
|
|||
case _ =>
|
||||
door.Actor ! CommonMessages.Use(player)
|
||||
}
|
||||
GeneralOperations.UseItem.Handled
|
||||
}
|
||||
|
||||
def handleUseResourceSilo(resourceSilo: ResourceSilo, equipment: Option[Equipment]): GeneralOperations.UseItem.Behavior = {
|
||||
def handleUseResourceSilo(resourceSilo: ResourceSilo, equipment: Option[Equipment]): Unit = {
|
||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||
val vehicleOpt = continent.GUID(player.avatar.vehicle)
|
||||
(vehicleOpt, equipment) match {
|
||||
case (Some(vehicle: Vehicle), Some(item))
|
||||
if GlobalDefinitions.isBattleFrameVehicle(vehicle.Definition) &&
|
||||
GlobalDefinitions.isBattleFrameNTUSiphon(item.Definition) =>
|
||||
resourceSilo.Actor ! CommonMessages.Use(player, Some(vehicle))
|
||||
GeneralOperations.UseItem.Handled
|
||||
case (Some(vehicle: Vehicle), _)
|
||||
if vehicle.Definition == GlobalDefinitions.ant &&
|
||||
vehicle.DeploymentState == DriveState.Deployed &&
|
||||
Vector3.DistanceSquared(resourceSilo.Position.xy, vehicle.Position.xy) < math.pow(resourceSilo.Definition.UseRadius, 2) =>
|
||||
resourceSilo.Actor ! CommonMessages.Use(player, Some(vehicle))
|
||||
GeneralOperations.UseItem.Handled
|
||||
case _ =>
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
|
||||
def handleUsePlayer(obj: Player, equipment: Option[Equipment], msg: UseItemMessage): GeneralOperations.UseItem.Behavior = {
|
||||
def handleUsePlayer(obj: Player, equipment: Option[Equipment], msg: UseItemMessage): Unit = {
|
||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||
if (obj.isBackpack) {
|
||||
if (equipment.isEmpty) {
|
||||
log.info(s"${player.Name} is looting the corpse of ${obj.Name}")
|
||||
sendResponse(msg)
|
||||
accessContainer(obj)
|
||||
GeneralOperations.UseItem.Handled
|
||||
} else {
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
}
|
||||
} else if (!msg.unk3 && player.isAlive) { //potential kit use
|
||||
(continent.GUID(msg.item_used_guid), kitToBeUsed) match {
|
||||
case (Some(kit: Kit), None) =>
|
||||
kitToBeUsed = Some(msg.item_used_guid)
|
||||
player.Actor ! CommonMessages.Use(player, Some(kit))
|
||||
GeneralOperations.UseItem.Handled
|
||||
case (Some(_: Kit), Some(_)) | (None, Some(_)) =>
|
||||
//a kit is already queued to be used; ignore this request
|
||||
sendResponse(ChatMsg(ChatMessageType.UNK_225, wideContents=false, "", "Please wait ...", None))
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case (Some(item), _) =>
|
||||
log.error(s"UseItem: ${player.Name} looking for Kit to use, but found $item instead")
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case (None, None) =>
|
||||
log.warn(s"UseItem: anticipated a Kit ${msg.item_used_guid} for ${player.Name}, but can't find it")
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
}
|
||||
log.warn(s"UseItem: anticipated a Kit ${msg.item_used_guid} for ${player.Name}, but can't find it") }
|
||||
} else if (msg.object_id == ObjectClass.avatar && msg.unk3) {
|
||||
equipment match {
|
||||
case Some(tool: Tool) if tool.Definition == GlobalDefinitions.bank =>
|
||||
obj.Actor ! CommonMessages.Use(player, equipment)
|
||||
GeneralOperations.UseItem.Handled
|
||||
|
||||
case Some(tool: Tool) if tool.Definition == GlobalDefinitions.medicalapplicator =>
|
||||
obj.Actor ! CommonMessages.Use(player, equipment)
|
||||
GeneralOperations.UseItem.Handled
|
||||
case _ =>
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case _ => ()
|
||||
}
|
||||
} else {
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
}
|
||||
}
|
||||
|
||||
def handleUseLocker(locker: Locker, equipment: Option[Equipment], msg: UseItemMessage): GeneralOperations.UseItem.Behavior = {
|
||||
def handleUseLocker(locker: Locker, equipment: Option[Equipment], msg: UseItemMessage): Unit = {
|
||||
equipment match {
|
||||
case Some(item) =>
|
||||
sendUseGeneralEntityMessage(locker, item)
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case None if locker.Faction == player.Faction || locker.HackedBy.nonEmpty =>
|
||||
log.info(s"${player.Name} is accessing a locker")
|
||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||
val playerLocker = player.avatar.locker
|
||||
sendResponse(msg.copy(object_guid = playerLocker.GUID, object_id = 456))
|
||||
accessContainer(playerLocker)
|
||||
GeneralOperations.UseItem.Handled
|
||||
case _ =>
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
|
||||
def handleUseCaptureTerminal(captureTerminal: CaptureTerminal, equipment: Option[Equipment]): GeneralOperations.UseItem.Behavior = {
|
||||
def handleUseCaptureTerminal(captureTerminal: CaptureTerminal, equipment: Option[Equipment]): Unit = {
|
||||
equipment match {
|
||||
case Some(item) =>
|
||||
sendUseGeneralEntityMessage(captureTerminal, item)
|
||||
|
|
@ -1182,33 +1189,25 @@ class GeneralOperations(
|
|||
case Some(llu: CaptureFlag) =>
|
||||
if (llu.Target.GUID == captureTerminal.Owner.GUID) {
|
||||
continent.LocalEvents ! LocalServiceMessage(continent.id, LocalAction.LluCaptured(llu))
|
||||
GeneralOperations.UseItem.Handled
|
||||
} else {
|
||||
log.info(
|
||||
s"LLU target is not this base. Target GUID: ${llu.Target.GUID} This base: ${captureTerminal.Owner.GUID}"
|
||||
)
|
||||
}
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case _ =>
|
||||
log.warn("Item in specialItemSlotGuid is not registered with continent or is not a LLU")
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case _ => log.warn("Item in specialItemSlotGuid is not registered with continent or is not a LLU")
|
||||
}
|
||||
case _ =>
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
|
||||
def handleUseFacilityTurret(obj: FacilityTurret, equipment: Option[Equipment], msg: UseItemMessage): GeneralOperations.UseItem.Behavior = {
|
||||
equipment
|
||||
.collect { item =>
|
||||
sendUseGeneralEntityMessage(obj, item)
|
||||
obj.Actor ! CommonMessages.Use(player, Some((item, msg.unk2.toInt))) //try upgrade path
|
||||
GeneralOperations.UseItem.Handled
|
||||
}
|
||||
.getOrElse(GeneralOperations.UseItem.Unhandled)
|
||||
def handleUseFacilityTurret(obj: FacilityTurret, equipment: Option[Equipment], msg: UseItemMessage): Unit = {
|
||||
equipment.foreach { item =>
|
||||
sendUseGeneralEntityMessage(obj, item)
|
||||
obj.Actor ! CommonMessages.Use(player, Some((item, msg.unk2.toInt))) //try upgrade path
|
||||
}
|
||||
}
|
||||
|
||||
def handleUseVehicle(obj: Vehicle, equipment: Option[Equipment], msg: UseItemMessage): GeneralOperations.UseItem.Behavior = {
|
||||
def handleUseVehicle(obj: Vehicle, equipment: Option[Equipment], msg: UseItemMessage): Unit = {
|
||||
equipment match {
|
||||
case Some(item) =>
|
||||
sendUseGeneralEntityMessage(obj, item)
|
||||
|
|
@ -1220,33 +1219,29 @@ class GeneralOperations(
|
|||
.contains(player.GUID))
|
||||
) {
|
||||
log.info(s"${player.Name} is looking in the ${obj.Definition.Name}'s trunk")
|
||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||
obj.AccessingTrunk = player.GUID
|
||||
accessContainer(obj)
|
||||
sendResponse(msg)
|
||||
GeneralOperations.UseItem.Handled
|
||||
} else {
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
}
|
||||
case _ =>
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
|
||||
def handleUseTerminal(terminal: Terminal, equipment: Option[Equipment], msg: UseItemMessage): GeneralOperations.UseItem.Behavior = {
|
||||
def handleUseTerminal(terminal: Terminal, equipment: Option[Equipment], msg: UseItemMessage): Unit = {
|
||||
equipment match {
|
||||
case Some(item) =>
|
||||
sendUseGeneralEntityMessage(terminal, item)
|
||||
GeneralOperations.UseItem.Handled
|
||||
case None
|
||||
if terminal.Owner == Building.NoBuilding || terminal.Faction == player.Faction ||
|
||||
terminal.HackedBy.nonEmpty || terminal.Faction == PlanetSideEmpire.NEUTRAL =>
|
||||
val tdef = terminal.Definition
|
||||
if (tdef.isInstanceOf[MatrixTerminalDefinition]) {
|
||||
//TODO matrix spawn point; for now, just blindly bind to show work (and hope nothing breaks)
|
||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||
sendResponse(
|
||||
BindPlayerMessage(BindStatus.Bind, "", display_icon=true, logging=true, SpawnGroup.Sanctuary, 0, 0, terminal.Position)
|
||||
)
|
||||
GeneralOperations.UseItem.Handled
|
||||
} else if (
|
||||
tdef == GlobalDefinitions.multivehicle_rearm_terminal || tdef == GlobalDefinitions.bfr_rearm_terminal ||
|
||||
tdef == GlobalDefinitions.air_rearm_terminal || tdef == GlobalDefinitions.ground_rearm_terminal
|
||||
|
|
@ -1258,49 +1253,45 @@ class GeneralOperations(
|
|||
)
|
||||
sendResponse(msg)
|
||||
sendResponse(msg.copy(object_guid = vehicle.GUID, object_id = vehicle.Definition.ObjectId))
|
||||
GeneralOperations.UseItem.Handled
|
||||
case None =>
|
||||
log.error(s"UseItem: Expecting a seated vehicle, ${player.Name} found none")
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
}
|
||||
} else if (tdef == GlobalDefinitions.teleportpad_terminal) {
|
||||
//explicit request
|
||||
log.info(s"${player.Name} is purchasing a router telepad")
|
||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||
terminal.Actor ! Terminal.Request(
|
||||
player,
|
||||
ItemTransactionMessage(msg.object_guid, TransactionType.Buy, 0, "router_telepad", 0, PlanetSideGUID(0))
|
||||
)
|
||||
GeneralOperations.UseItem.Handled
|
||||
} else if (tdef == GlobalDefinitions.targeting_laser_dispenser) {
|
||||
//explicit request
|
||||
log.info(s"${player.Name} is purchasing a targeting laser")
|
||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||
terminal.Actor ! Terminal.Request(
|
||||
player,
|
||||
ItemTransactionMessage(msg.object_guid, TransactionType.Buy, 0, "flail_targeting_laser", 0, PlanetSideGUID(0))
|
||||
)
|
||||
GeneralOperations.UseItem.Handled
|
||||
} else {
|
||||
log.info(s"${player.Name} is accessing a ${terminal.Definition.Name}")
|
||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||
sendResponse(msg)
|
||||
GeneralOperations.UseItem.Handled
|
||||
}
|
||||
case _ =>
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
|
||||
def handleUseSpawnTube(obj: SpawnTube, equipment: Option[Equipment]): GeneralOperations.UseItem.Behavior = {
|
||||
def handleUseSpawnTube(obj: SpawnTube, equipment: Option[Equipment]): Unit = {
|
||||
equipment match {
|
||||
case Some(item) =>
|
||||
sendUseGeneralEntityMessage(obj, item)
|
||||
case None if player.Faction == obj.Faction =>
|
||||
//deconstruction
|
||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||
sessionLogic.actionsToCancel()
|
||||
sessionLogic.terminals.CancelAllProximityUnits()
|
||||
sessionLogic.zoning.spawn.startDeconstructing(obj)
|
||||
GeneralOperations.UseItem.Handled
|
||||
case _ =>
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1309,7 +1300,7 @@ class GeneralOperations(
|
|||
equipment: Option[Equipment],
|
||||
msg: UseItemMessage,
|
||||
useTelepadFunc: (Vehicle, InternalTelepad, TelepadDeployable, PlanetSideGameObject with TelepadLike, PlanetSideGameObject with TelepadLike) => Unit
|
||||
): GeneralOperations.UseItem.Behavior = {
|
||||
): Unit = {
|
||||
if (equipment.isEmpty) {
|
||||
(continent.GUID(obj.Router) match {
|
||||
case Some(vehicle: Vehicle) => Some((vehicle, vehicle.Utility(UtilityType.internal_router_telepad_deployable)))
|
||||
|
|
@ -1317,25 +1308,20 @@ class GeneralOperations(
|
|||
case None => None
|
||||
}) match {
|
||||
case Some((vehicle: Vehicle, Some(util: Utility.InternalTelepad))) =>
|
||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel")
|
||||
player.WhichSide = vehicle.WhichSide
|
||||
useTelepadFunc(vehicle, util, obj, obj, util)
|
||||
GeneralOperations.UseItem.HandledPassive
|
||||
case Some((vehicle: Vehicle, None)) =>
|
||||
log.error(
|
||||
s"telepad@${msg.object_guid.guid} is not linked to a router - ${vehicle.Definition.Name}"
|
||||
)
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case Some((o, _)) =>
|
||||
log.error(
|
||||
s"telepad@${msg.object_guid.guid} is linked to wrong kind of object - ${o.Definition.Name}, ${obj.Router}"
|
||||
)
|
||||
obj.Actor ! Deployable.Deconstruct()
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case _ =>
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case _ => ()
|
||||
}
|
||||
} else {
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1343,19 +1329,16 @@ class GeneralOperations(
|
|||
obj: InternalTelepad,
|
||||
msg: UseItemMessage,
|
||||
useTelepadFunc: (Vehicle, InternalTelepad, TelepadDeployable, PlanetSideGameObject with TelepadLike, PlanetSideGameObject with TelepadLike) => Unit
|
||||
): GeneralOperations.UseItem.Behavior = {
|
||||
): Unit = {
|
||||
continent.GUID(obj.Telepad) match {
|
||||
case Some(pad: TelepadDeployable) =>
|
||||
player.WhichSide = pad.WhichSide
|
||||
useTelepadFunc(obj.Owner.asInstanceOf[Vehicle], obj, pad, obj, pad)
|
||||
GeneralOperations.UseItem.HandledPassive
|
||||
case Some(o) =>
|
||||
log.error(
|
||||
s"internal telepad@${msg.object_guid.guid} is not linked to a remote telepad - ${o.Definition.Name}@${o.GUID.guid}"
|
||||
)
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case None =>
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case None => ()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1433,63 +1416,55 @@ class GeneralOperations(
|
|||
recentTeleportAttempt = time
|
||||
}
|
||||
|
||||
def handleUseCaptureFlag(obj: CaptureFlag): GeneralOperations.UseItem.Behavior = {
|
||||
def handleUseCaptureFlag(obj: CaptureFlag): Unit = {
|
||||
// LLU can normally only be picked up the faction that owns it
|
||||
specialItemSlotGuid match {
|
||||
case None if obj.Faction == player.Faction =>
|
||||
specialItemSlotGuid = Some(obj.GUID)
|
||||
player.Carrying = SpecialCarry.CaptureFlag
|
||||
continent.LocalEvents ! CaptureFlagManager.PickupFlag(obj, player)
|
||||
GeneralOperations.UseItem.Handled
|
||||
case None =>
|
||||
log.warn(s"${player.Faction} player ${player.toString} tried to pick up a ${obj.Faction} LLU - ${obj.GUID}")
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case Some(guid) if guid != obj.GUID =>
|
||||
// Ignore duplicate pickup requests
|
||||
log.warn(
|
||||
s"${player.Faction} player ${player.toString} tried to pick up a ${obj.Faction} LLU, but their special slot already contains $guid"
|
||||
)
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case _ =>
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
|
||||
def handleUseWarpGate(equipment: Option[Equipment]): GeneralOperations.UseItem.Behavior = {
|
||||
def handleUseWarpGate(equipment: Option[Equipment]): Unit = {
|
||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||
(continent.GUID(player.VehicleSeated), equipment) match {
|
||||
case (Some(vehicle: Vehicle), Some(item))
|
||||
if GlobalDefinitions.isBattleFrameVehicle(vehicle.Definition) &&
|
||||
GlobalDefinitions.isBattleFrameNTUSiphon(item.Definition) =>
|
||||
vehicle.Actor ! CommonMessages.Use(player, equipment)
|
||||
GeneralOperations.UseItem.Handled
|
||||
case _ =>
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
|
||||
def handleUseGeneralEntity(obj: PlanetSideServerObject, equipment: Option[Equipment]): GeneralOperations.UseItem.Behavior = {
|
||||
equipment
|
||||
.collect { item =>
|
||||
obj.Actor ! CommonMessages.Use(player, Some(item))
|
||||
GeneralOperations.UseItem.Handled
|
||||
}
|
||||
.getOrElse(GeneralOperations.UseItem.Unhandled)
|
||||
def handleUseGeneralEntity(obj: PlanetSideServerObject, equipment: Option[Equipment]): Unit = {
|
||||
equipment.foreach { item =>
|
||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||
obj.Actor ! CommonMessages.Use(player, Some(item))
|
||||
}
|
||||
}
|
||||
|
||||
def sendUseGeneralEntityMessage(obj: PlanetSideServerObject, equipment: Equipment): GeneralOperations.UseItem.Behavior = {
|
||||
def sendUseGeneralEntityMessage(obj: PlanetSideServerObject, equipment: Equipment): Unit = {
|
||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||
obj.Actor ! CommonMessages.Use(player, Some(equipment))
|
||||
GeneralOperations.UseItem.Handled
|
||||
}
|
||||
|
||||
def handleUseDefaultEntity(obj: PlanetSideGameObject, equipment: Option[Equipment]): GeneralOperations.UseItem.Behavior = {
|
||||
def handleUseDefaultEntity(obj: PlanetSideGameObject, equipment: Option[Equipment]): Unit = {
|
||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||
equipment match {
|
||||
case Some(item)
|
||||
if GlobalDefinitions.isBattleFrameArmorSiphon(item.Definition) ||
|
||||
GlobalDefinitions.isBattleFrameNTUSiphon(item.Definition) => ()
|
||||
GeneralOperations.UseItem.Handled
|
||||
case _ =>
|
||||
log.warn(s"UseItem: ${player.Name} does not know how to handle $obj")
|
||||
GeneralOperations.UseItem.Unhandled
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1500,6 +1475,28 @@ class GeneralOperations(
|
|||
)
|
||||
}
|
||||
|
||||
private def commonHandleDeployObjectSetup(
|
||||
zone: Zone,
|
||||
deployableType: DeployedItem.Value,
|
||||
position: Vector3,
|
||||
orientation: Vector3,
|
||||
side: Sidedness,
|
||||
faction: PlanetSideEmpire.Value
|
||||
): (Deployable, TaskBundle) = {
|
||||
val deployableEntity: Deployable = Deployables.Make(deployableType)()
|
||||
deployableEntity.Position = position
|
||||
deployableEntity.Orientation = orientation
|
||||
deployableEntity.WhichSide = side
|
||||
deployableEntity.Faction = faction
|
||||
val tasking: TaskBundle = deployableEntity match {
|
||||
case turret: TurretDeployable =>
|
||||
GUIDTask.registerDeployableTurret(zone.GUID, turret)
|
||||
case _ =>
|
||||
GUIDTask.registerObject(zone.GUID, deployableEntity)
|
||||
}
|
||||
(deployableEntity, tasking)
|
||||
}
|
||||
|
||||
override protected[session] def actionsToCancel(): Unit = {
|
||||
progressBarValue = None
|
||||
kitToBeUsed = None
|
||||
|
|
@ -1519,11 +1516,12 @@ class GeneralOperations(
|
|||
}
|
||||
}
|
||||
|
||||
case Some(o) if player.isAlive =>
|
||||
unaccessContainer(o)
|
||||
sendResponse(UnuseItemMessage(player.GUID, o.GUID))
|
||||
|
||||
case Some(o) =>
|
||||
unaccessContainer(o)
|
||||
if (player.isAlive) {
|
||||
sendResponse(UnuseItemMessage(player.GUID, o.GUID))
|
||||
}
|
||||
|
||||
case None => ()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ class SessionData(
|
|||
private[session] var persistFunc: () => Unit = noPersistence
|
||||
private[session] var persist: () => Unit = updatePersistenceOnly
|
||||
private[session] var keepAliveFunc: () => Unit = keepAlivePersistenceInitial
|
||||
private[session] var keepAlivePersistenceFunc: () => Unit = keepAlivePersistence
|
||||
private[session] var turnCounterFunc: PlanetSideGUID => Unit = SessionData.NoTurnCounterYet
|
||||
private[session] val oldRefsMap: mutable.HashMap[PlanetSideGUID, String] = new mutable.HashMap[PlanetSideGUID, String]()
|
||||
private var contextSafeEntity: PlanetSideGUID = PlanetSideGUID(0)
|
||||
|
|
@ -471,7 +472,7 @@ class SessionData(
|
|||
def keepAlivePersistenceInitial(): Unit = {
|
||||
persist()
|
||||
if (player != null && player.HasGUID) {
|
||||
keepAliveFunc = keepAlivePersistence
|
||||
keepAliveFunc = keepAlivePersistenceFunc
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,12 +30,12 @@ class SessionLocalHandlers(
|
|||
}
|
||||
|
||||
def handleTurretDeployableIsDismissed(obj: TurretDeployable): Unit = {
|
||||
Players.buildCooldownReset(continent, player.Name, obj)
|
||||
Players.buildCooldownReset(continent, player.Name, obj.GUID)
|
||||
TaskWorkflow.execute(GUIDTask.unregisterDeployableTurret(continent.GUID, obj))
|
||||
}
|
||||
|
||||
def handleDeployableIsDismissed(obj: Deployable): Unit = {
|
||||
Players.buildCooldownReset(continent, player.Name, obj)
|
||||
Players.buildCooldownReset(continent, player.Name, obj.GUID)
|
||||
TaskWorkflow.execute(GUIDTask.unregisterObject(continent.GUID, obj))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -90,12 +90,11 @@ class SessionTerminalHandlers(
|
|||
vehicle: Vehicle,
|
||||
weapons: List[InventoryItem],
|
||||
trunk: List[InventoryItem]
|
||||
): Unit = {
|
||||
): Option[Vehicle] = {
|
||||
continent.map.terminalToSpawnPad
|
||||
.find { case (termid, _) => termid == terminalGuid.guid }
|
||||
.map { case (a: Int, b: Int) => (continent.GUID(a), continent.GUID(b)) }
|
||||
.collect { case (Some(term: Terminal), Some(pad: VehicleSpawnPad)) =>
|
||||
avatarActor ! AvatarActor.UpdatePurchaseTime(vehicle.Definition)
|
||||
vehicle.Faction = player.Faction
|
||||
vehicle.Position = pad.Position
|
||||
vehicle.Orientation = pad.Orientation + Vector3.z(pad.Definition.VehicleCreationZOrientOffset)
|
||||
|
|
@ -126,6 +125,7 @@ class SessionTerminalHandlers(
|
|||
sendResponse(UnuseItemMessage(player.GUID, terminalGuid))
|
||||
}
|
||||
player.LogActivity(TerminalUsedActivity(AmenitySource(term), transactionType))
|
||||
vehicle
|
||||
}
|
||||
.orElse {
|
||||
log.error(
|
||||
|
|
|
|||
|
|
@ -202,6 +202,7 @@ class ZoningOperations(
|
|||
private var zoningChatMessageType: ChatMessageType = ChatMessageType.CMT_QUIT
|
||||
private var zoningCounter: Int = 0
|
||||
private var zoningTimer: Cancellable = Default.Cancellable
|
||||
var displayZoningMessageWhenCancelled: Boolean = true
|
||||
|
||||
/* packets */
|
||||
|
||||
|
|
@ -906,7 +907,7 @@ class ZoningOperations(
|
|||
* defaults to `None`
|
||||
*/
|
||||
def CancelZoningProcessWithReason(msg: String, msgType: Option[ChatMessageType] = None): Unit = {
|
||||
if (zoningStatus != Zoning.Status.None) {
|
||||
if (displayZoningMessageWhenCancelled && zoningStatus != Zoning.Status.None) {
|
||||
sendResponse(ChatMsg(msgType.getOrElse(zoningChatMessageType), wideContents=false, "", msg, None))
|
||||
}
|
||||
CancelZoningProcess()
|
||||
|
|
@ -2298,7 +2299,7 @@ class ZoningOperations(
|
|||
* @param zone na
|
||||
*/
|
||||
def HandleReleaseAvatar(tplayer: Player, zone: Zone): Unit = {
|
||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistence
|
||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistenceFunc
|
||||
tplayer.Release
|
||||
tplayer.VehicleSeated match {
|
||||
case None =>
|
||||
|
|
@ -3023,7 +3024,7 @@ class ZoningOperations(
|
|||
sessionLogic.keepAliveFunc = sessionLogic.vehicles.GetMountableAndSeat(None, player, continent) match {
|
||||
case (Some(v: Vehicle), Some(seatNumber))
|
||||
if seatNumber > 0 && v.WeaponControlledFromSeat(seatNumber).isEmpty =>
|
||||
sessionLogic.keepAlivePersistence
|
||||
sessionLogic.keepAlivePersistenceFunc
|
||||
case _ =>
|
||||
NormalKeepAlive
|
||||
}
|
||||
|
|
@ -3476,7 +3477,7 @@ class ZoningOperations(
|
|||
//sit down
|
||||
sendResponse(ObjectAttachMessage(vguid, pguid, seat))
|
||||
sessionLogic.general.accessContainer(vehicle)
|
||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistence
|
||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistenceFunc
|
||||
case _ => ()
|
||||
//we can't find a vehicle? and we're still here? that's bad
|
||||
player.VehicleSeated = None
|
||||
|
|
|
|||
|
|
@ -1067,6 +1067,13 @@ object WorldSession {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a task and, upon completion, dispatch a message.
|
||||
* @param task task to be completed first
|
||||
* @param sendTo where to send the message
|
||||
* @param pass message
|
||||
* @return a `TaskBundle` object
|
||||
*/
|
||||
def CallBackForTask(task: TaskBundle, sendTo: ActorRef, pass: Any): TaskBundle = {
|
||||
TaskBundle(
|
||||
new StraightforwardTask() {
|
||||
|
|
@ -1085,6 +1092,14 @@ object WorldSession {
|
|||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a task and, upon completion, dispatch a message whose origin is specific and different from normal.
|
||||
* @param task task to be completed first
|
||||
* @param sendTo where to send the message
|
||||
* @param pass message
|
||||
* @param replyTo whom to attribute the message being passed (e.g., `tell`)
|
||||
* @return a `TaskBundle` object
|
||||
*/
|
||||
def CallBackForTask(task: TaskBundle, sendTo: ActorRef, pass: Any, replyTo: ActorRef): TaskBundle = {
|
||||
TaskBundle(
|
||||
new StraightforwardTask() {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import net.psforever.objects.vital.projectile.ProjectileReason
|
|||
import net.psforever.objects.vital.{InGameActivity, InGameHistory, RevivingActivity}
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{ChatMessageType, ExoSuitType, Vector3}
|
||||
import net.psforever.types.{ChatMessageType, ExoSuitType, PlanetSideGUID, Vector3}
|
||||
import net.psforever.services.Service
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||
|
|
@ -327,7 +327,7 @@ object Players {
|
|||
*/
|
||||
def successfulBuildActivity(zone: Zone, channel: String, obj: Deployable): Unit = {
|
||||
//sent to avatar event bus to preempt additional tool management
|
||||
buildCooldownReset(zone, channel, obj)
|
||||
buildCooldownReset(zone, channel, obj.GUID)
|
||||
//sent to local event bus to cooperate with deployable management
|
||||
zone.LocalEvents ! LocalServiceMessage(
|
||||
channel,
|
||||
|
|
@ -339,13 +339,13 @@ object Players {
|
|||
* Common actions related to constructing a new `Deployable` object in the game environment.
|
||||
* @param zone in which zone these messages apply
|
||||
* @param channel to whom to send the messages
|
||||
* @param obj the `Deployable` object
|
||||
* @param guid `Deployable` object
|
||||
*/
|
||||
def buildCooldownReset(zone: Zone, channel: String, obj: Deployable): Unit = {
|
||||
def buildCooldownReset(zone: Zone, channel: String, guid: PlanetSideGUID): Unit = {
|
||||
//sent to avatar event bus to preempt additional tool management
|
||||
zone.AvatarEvents ! AvatarServiceMessage(
|
||||
channel,
|
||||
AvatarAction.SendResponse(Service.defaultPlayerGUID, GenericObjectActionMessage(obj.GUID, 21))
|
||||
AvatarAction.SendResponse(Service.defaultPlayerGUID, GenericObjectActionMessage(guid, 21))
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -385,15 +385,13 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
|
|||
}
|
||||
if (Players.CertificationToUseExoSuit(player, exosuit, subtype)) {
|
||||
if (exosuit == ExoSuitType.MAX) {
|
||||
val weapon = GlobalDefinitions.MAXArms(subtype, player.Faction)
|
||||
val cooldown = player.avatar.purchaseCooldown(weapon)
|
||||
val cooldown = player.avatar.purchaseCooldown(GlobalDefinitions.MAXArms(subtype, player.Faction))
|
||||
if (originalSubtype == subtype) {
|
||||
(exosuit, subtype) //same MAX subtype is free
|
||||
(exosuit, subtype) //same MAX subtype
|
||||
} else if (cooldown.nonEmpty) {
|
||||
fallbackSuit //different MAX subtype can not have cooldown
|
||||
fallbackSuit //different MAX subtype
|
||||
} else {
|
||||
avatarActor ! AvatarActor.UpdatePurchaseTime(weapon)
|
||||
(exosuit, subtype) //switching for first time causes cooldown
|
||||
(exosuit, subtype) //switching
|
||||
}
|
||||
} else {
|
||||
(exosuit, subtype)
|
||||
|
|
@ -475,8 +473,6 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
|
|||
case InventoryItem(citem: ConstructionItem, _) =>
|
||||
Deployables.initializeConstructionItem(player.avatar.certifications, citem)
|
||||
}
|
||||
//deactivate non-passive implants
|
||||
avatarActor ! AvatarActor.DeactivateActiveImplants
|
||||
val zone = player.Zone
|
||||
zone.AvatarEvents ! AvatarServiceMessage(
|
||||
Players.ZoneChannelIfSpectating(player),
|
||||
|
|
@ -556,7 +552,7 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
|
|||
//don't know where boomer trigger "should" go
|
||||
TaskWorkflow.execute(PutNewEquipmentInInventoryOrDrop(player)(trigger))
|
||||
}
|
||||
Players.buildCooldownReset(zone, player.Name, obj)
|
||||
Players.buildCooldownReset(zone, player.Name, obj.GUID)
|
||||
case _ => ()
|
||||
}
|
||||
deployablePair = None
|
||||
|
|
@ -573,7 +569,7 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
|
|||
player.Actor ! Player.LoseDeployable(obj)
|
||||
TelepadControl.TelepadError(zone, player.Name, msg = "@Telepad_NoDeploy_RouterLost")
|
||||
}
|
||||
Players.buildCooldownReset(zone, player.Name, obj)
|
||||
Players.buildCooldownReset(zone, player.Name, obj.GUID)
|
||||
case _ => ()
|
||||
}
|
||||
deployablePair = None
|
||||
|
|
@ -581,7 +577,7 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
|
|||
case Zone.Deployable.IsBuilt(obj) =>
|
||||
deployablePair match {
|
||||
case Some((deployable, tool)) if deployable eq obj =>
|
||||
Players.buildCooldownReset(player.Zone, player.Name, obj)
|
||||
Players.buildCooldownReset(player.Zone, player.Name, obj.GUID)
|
||||
player.Find(tool) match {
|
||||
case Some(index) =>
|
||||
Players.commonDestroyConstructionItem(player, tool, index)
|
||||
|
|
@ -613,10 +609,7 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
|
|||
val weapon = GlobalDefinitions.MAXArms(subtype, player.Faction)
|
||||
player.avatar.purchaseCooldown(weapon)
|
||||
.collect(_ => false)
|
||||
.getOrElse {
|
||||
avatarActor ! AvatarActor.UpdatePurchaseTime(weapon)
|
||||
true
|
||||
}
|
||||
.getOrElse(true)
|
||||
} else {
|
||||
true
|
||||
})
|
||||
|
|
@ -671,8 +664,6 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
|
|||
//insert
|
||||
afterHolsters.foreach(elem => player.Slot(elem.start).Equipment = elem.obj)
|
||||
afterInventory.foreach(elem => player.Inventory.InsertQuickly(elem.start, elem.obj))
|
||||
//deactivate non-passive implants
|
||||
avatarActor ! AvatarActor.DeactivateActiveImplants
|
||||
player.Zone.AvatarEvents ! AvatarServiceMessage(
|
||||
Players.ZoneChannelIfSpectating(player),
|
||||
AvatarAction.ChangeExosuit(
|
||||
|
|
@ -744,7 +735,7 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
|
|||
else {
|
||||
log.warn(s"cannot build a ${obj.Definition.Name}")
|
||||
DropEquipmentFromInventory(player)(tool, Some(obj.Position))
|
||||
Players.buildCooldownReset(zone, player.Name, obj)
|
||||
Players.buildCooldownReset(zone, player.Name, obj.GUID)
|
||||
obj.Position = Vector3.Zero
|
||||
obj.AssignOwnership(None)
|
||||
zone.Deployables ! Zone.Deployable.Dismiss(obj)
|
||||
|
|
@ -755,7 +746,7 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
|
|||
obj.AssignOwnership(None)
|
||||
val zone = player.Zone
|
||||
zone.Deployables ! Zone.Deployable.Dismiss(obj)
|
||||
Players.buildCooldownReset(zone, player.Name, obj)
|
||||
Players.buildCooldownReset(zone, player.Name, obj.GUID)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue