diff --git a/src/main/scala/net/psforever/actors/session/normal/AvatarHandlerLogic.scala b/src/main/scala/net/psforever/actors/session/normal/AvatarHandlerLogic.scala index 194260de3..586391cf8 100644 --- a/src/main/scala/net/psforever/actors/session/normal/AvatarHandlerLogic.scala +++ b/src/main/scala/net/psforever/actors/session/normal/AvatarHandlerLogic.scala @@ -574,7 +574,7 @@ class AvatarHandlerLogic(val ops: SessionAvatarHandlers, implicit val context: A sessionLogic.actionsToCancel() sessionLogic.terminals.CancelAllProximityUnits() AvatarActor.savePlayerLocation(player) - sessionLogic.zoning.spawn.shiftPosition = Some(player.Position) + sessionLogic.zoning.spawn.ShiftPosition = Some(player.Position) //respawn val respawnTimer = 300000 //milliseconds diff --git a/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala b/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala index af2f9a693..df8a88363 100644 --- a/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala +++ b/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala @@ -169,7 +169,16 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex // val eagleEye: Boolean = ops.canSeeReallyFar val isNotVisible: Boolean = sessionLogic.zoning.zoningStatus == Zoning.Status.Deconstructing || - (player.isAlive && sessionLogic.zoning.spawn.deadState == DeadState.RespawnTime) + (player.isAlive && sessionLogic.zoning.spawn.deadState == DeadState.RespawnTime) || + (sessionLogic.zoning.spawn.ShiftPosition match { + case Some(position) if Vector3.DistanceSquared(position, pos) < 25f => + sessionLogic.zoning.spawn.ShiftPosition = None + false + case Some(_) => + true + case _ => + false + }) continent.AvatarEvents ! AvatarServiceMessage( continent.id, AvatarAction.PlayerState( diff --git a/src/main/scala/net/psforever/actors/session/spectator/AvatarHandlerLogic.scala b/src/main/scala/net/psforever/actors/session/spectator/AvatarHandlerLogic.scala index 160bda390..cebbb5ba2 100644 --- a/src/main/scala/net/psforever/actors/session/spectator/AvatarHandlerLogic.scala +++ b/src/main/scala/net/psforever/actors/session/spectator/AvatarHandlerLogic.scala @@ -467,7 +467,7 @@ class AvatarHandlerLogic(val ops: SessionAvatarHandlers, implicit val context: A sessionLogic.actionsToCancel() sessionLogic.terminals.CancelAllProximityUnits() AvatarActor.savePlayerLocation(player) - sessionLogic.zoning.spawn.shiftPosition = Some(player.Position) + sessionLogic.zoning.spawn.ShiftPosition = Some(player.Position) //respawn sessionLogic.zoning.spawn.reviveTimer.cancel() diff --git a/src/main/scala/net/psforever/actors/session/support/GeneralOperations.scala b/src/main/scala/net/psforever/actors/session/support/GeneralOperations.scala index 76459ff0a..9899a1b2c 100644 --- a/src/main/scala/net/psforever/actors/session/support/GeneralOperations.scala +++ b/src/main/scala/net/psforever/actors/session/support/GeneralOperations.scala @@ -182,7 +182,7 @@ class GeneralOperations( ) extends CommonSessionInterfacingFunctionality { private[session] var progressBarValue: Option[Float] = None private[session] var accessedContainer: Option[PlanetSideGameObject with Container] = None - private[session] var recentTeleportAttempt: Long = 0 + private[session] var recentTeleportAttemptTime: Long = 0 private[session] var kitToBeUsed: Option[PlanetSideGUID] = None // If a special item (e.g. LLU) has been attached to the player the GUID should be stored here, or cleared when dropped, since the drop hotkey doesn't send the GUID of the object to be dropped. private[session] var specialItemSlotGuid: Option[PlanetSideGUID] = None @@ -1210,8 +1210,8 @@ class GeneralOperations( sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use") if (msg.unk3) { msg.object_id match { - case ObjectClass.avatar | ObjectClass.avatar_bot | ObjectClass.avatar_bot_agile | ObjectClass.avatar_bot_agile_no_weapon | - ObjectClass.avatar_bot_max | ObjectClass.avatar_bot_max_no_weapon | ObjectClass.avatar_bot_reinforced | + case ObjectClass.avatar | ObjectClass.avatar_bot | ObjectClass.avatar_bot_agile | ObjectClass.avatar_bot_agile_no_weapon | + ObjectClass.avatar_bot_max | ObjectClass.avatar_bot_max_no_weapon | ObjectClass.avatar_bot_reinforced | ObjectClass.avatar_bot_reinforced_no_weapon | ObjectClass.avatar_bot_standard | ObjectClass.avatar_bot_standard_no_weapon => equipment match { case Some(tool: Tool) if tool.Definition == GlobalDefinitions.bank => @@ -1424,26 +1424,38 @@ class GeneralOperations( dest: PlanetSideGameObject with TelepadLike ): Unit = { val time = System.currentTimeMillis() - if ( - time - recentTeleportAttempt > 2000L && router.DeploymentState == DriveState.Deployed && - internalTelepad.Active && - remoteTelepad.Active - ) { - val pguid = player.GUID - val sguid = src.GUID - val dguid = dest.GUID - sendResponse(PlayerStateShiftMessage(ShiftState(0, dest.Position, player.Orientation.z))) - useRouterTelepadEffect(pguid, sguid, dguid) - continent.LocalEvents ! LocalServiceMessage( - continent.id, - LocalAction.RouterTelepadTransport(pguid, pguid, sguid, dguid) - ) - player.Position = dest.Position - player.LogActivity(TelepadUseActivity(VehicleSource(router), DeployableSource(remoteTelepad), PlayerSource(player))) - } else { - log.warn(s"UseRouterTelepadSystem: ${player.Name} can not teleport") + if (time - recentTeleportAttemptTime > 2000L) { + if (router.DeploymentState == DriveState.Deployed && internalTelepad.Active && remoteTelepad.Active) { + val pguid = player.GUID + val sguid = src.GUID + val dguid = dest.GUID + val events = continent.AvatarEvents + val zoneid = continent.id + val destinationPosition = dest.Position + events ! AvatarServiceMessage(zoneid, AvatarAction.ObjectDelete(pguid, pguid)) + events ! AvatarServiceMessage(player.Name, + AvatarAction.SendResponse(PlanetSideGUID(0), PlayerStateShiftMessage(ShiftState(0, destinationPosition, player.Orientation.z))) + ) + player.Position = destinationPosition + events ! AvatarServiceMessage(zoneid, AvatarAction.LoadPlayer( + pguid, + player.Definition.ObjectId, + pguid, + player.Definition.Packet.ConstructorData(player).get, + None + )) + useRouterTelepadEffect(pguid, sguid, dguid) + continent.LocalEvents ! LocalServiceMessage( + continent.id, + LocalAction.RouterTelepadTransport(pguid, pguid, sguid, dguid) + ) + sessionLogic.zoning.spawn.ShiftPosition = destinationPosition + player.LogActivity(TelepadUseActivity(VehicleSource(router), DeployableSource(remoteTelepad), PlayerSource(player))) + } else { + log.warn(s"UseRouterTelepadSystem: ${player.Name} can not teleport") + } } - recentTeleportAttempt = time + recentTeleportAttemptTime = time } /** @@ -1463,7 +1475,7 @@ class GeneralOperations( ): Unit = { val time = System.currentTimeMillis() if ( - time - recentTeleportAttempt > 2000L && router.DeploymentState == DriveState.Deployed && + time - recentTeleportAttemptTime > 2000L && router.DeploymentState == DriveState.Deployed && internalTelepad.Active && remoteTelepad.Active ) { @@ -1476,7 +1488,7 @@ class GeneralOperations( } else { log.warn(s"UseRouterTelepadSystem: ${player.Name} can not teleport") } - recentTeleportAttempt = time + recentTeleportAttemptTime = time } def handleUseCaptureFlag(obj: CaptureFlag): Unit = { diff --git a/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala b/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala index 12f80e1fc..a69a4a724 100644 --- a/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala +++ b/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala @@ -1998,7 +1998,7 @@ class ZoningOperations( * As they should arrive roughly every 250 milliseconds this allows for a very crude method of scheduling tasks up to four times per second */ private[session] var upstreamMessageCount: Int = 0 - private[session] var shiftPosition: Option[Vector3] = None + private var shiftPosition: Option[Vector3] = None private[session] var shiftOrientation: Option[Vector3] = None private[session] var drawDeloyableIcon: PlanetSideGameObject with Deployable => Unit = RedrawDeployableIcons private[session] var populateAvatarAwardRibbonsFunc: (Int, Long) => Unit = setupAvatarAwardMessageDelivery @@ -4120,6 +4120,18 @@ class ZoningOperations( def clearAllQueuedActivity(): Unit = { queuedActivities = Seq() } + + def ShiftPosition: Option[Vector3] = shiftPosition + + def ShiftPosition_=(toPosition: Option[Vector3]): Option[Vector3] = { + shiftPosition = toPosition + ShiftPosition + } + + def ShiftPosition_=(toPosition: Vector3): Option[Vector3] = { + shiftPosition = Some(toPosition) + ShiftPosition + } } def doorsThatShouldBeClosedOrBeOpenedByRange(