mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-14 07:55:07 +00:00
Merge pull request #1146 from ScrawnyRonnie/jammer
Keep the jam going & other misc fixes
This commit is contained in:
commit
c99e170a26
15 changed files with 133 additions and 49 deletions
|
|
@ -8926,7 +8926,7 @@
|
||||||
"AbsY": 3742.29175,
|
"AbsY": 3742.29175,
|
||||||
"AbsZ": 42.3043633,
|
"AbsZ": 42.3043633,
|
||||||
"Yaw": 198.0,
|
"Yaw": 198.0,
|
||||||
"GUID": 713,
|
"GUID": 715,
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
|
|
@ -8939,7 +8939,7 @@
|
||||||
"AbsY": 3729.643,
|
"AbsY": 3729.643,
|
||||||
"AbsZ": 42.3043633,
|
"AbsZ": 42.3043633,
|
||||||
"Yaw": 288.0,
|
"Yaw": 288.0,
|
||||||
"GUID": 714,
|
"GUID": 713,
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
|
|
@ -8952,7 +8952,7 @@
|
||||||
"AbsY": 3729.643,
|
"AbsY": 3729.643,
|
||||||
"AbsZ": 49.8043633,
|
"AbsZ": 49.8043633,
|
||||||
"Yaw": 108.0,
|
"Yaw": 108.0,
|
||||||
"GUID": 715,
|
"GUID": 714,
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import net.psforever.actors.zone.ZoneActor
|
||||||
import net.psforever.objects.avatar.scoring.{Assist, Death, EquipmentStat, KDAStat, Kill, Life, ScoreCard, SupportActivity}
|
import net.psforever.objects.avatar.scoring.{Assist, Death, EquipmentStat, KDAStat, Kill, Life, ScoreCard, SupportActivity}
|
||||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||||
import net.psforever.objects.sourcing.VehicleSource
|
import net.psforever.objects.sourcing.VehicleSource
|
||||||
import net.psforever.objects.vital.InGameHistory
|
import net.psforever.objects.vital.{InGameHistory, ReconstructionActivity}
|
||||||
import net.psforever.objects.vehicles.MountedWeapons
|
import net.psforever.objects.vehicles.MountedWeapons
|
||||||
import net.psforever.types.{ChatMessageType, StatisticalCategory, StatisticalElement}
|
import net.psforever.types.{ChatMessageType, StatisticalCategory, StatisticalElement}
|
||||||
import org.joda.time.{LocalDateTime, Seconds}
|
import org.joda.time.{LocalDateTime, Seconds}
|
||||||
|
|
@ -235,7 +235,7 @@ object AvatarActor {
|
||||||
|
|
||||||
final case class SetStamina(stamina: Int) extends Command
|
final case class SetStamina(stamina: Int) extends Command
|
||||||
|
|
||||||
private case class SetImplantInitialized(implantType: ImplantType) extends Command
|
final case class SetImplantInitialized(implantType: ImplantType) extends Command
|
||||||
|
|
||||||
final case class MemberListRequest(action: MemberAction.Value, name: String) extends Command
|
final case class MemberListRequest(action: MemberAction.Value, name: String) extends Command
|
||||||
|
|
||||||
|
|
@ -1588,8 +1588,68 @@ class AvatarActor(
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
|
|
||||||
case ResetImplants() =>
|
case ResetImplants() =>
|
||||||
deinitializeImplants()
|
val player = session.get.player
|
||||||
initializeImplants()
|
// Get time of when you spawned after a deconstruction or zoning activity.
|
||||||
|
val lastDecon: Long = player.History.findLast {entry => entry.isInstanceOf[ReconstructionActivity]} match {
|
||||||
|
case Some(entry) => entry.time
|
||||||
|
case _ => 0L
|
||||||
|
}
|
||||||
|
// Get time of when you entered the world or respawned after death.
|
||||||
|
val lastRespawn: Long = player.History.findLast {entry => entry.isInstanceOf[SpawningActivity]} match {
|
||||||
|
case Some(entry) => entry.time
|
||||||
|
case _ => 0L
|
||||||
|
}
|
||||||
|
// You didn't die. You deconstructed or changed zones via warpgate/IA/recall.
|
||||||
|
// When you respawn after death, it does both recon and spawn activities, hence the minus 3000 to make sure
|
||||||
|
// this doesn't happen at respawn after death.
|
||||||
|
if (lastDecon - 3000 > lastRespawn) {
|
||||||
|
deinitializeImplants()
|
||||||
|
val implants = avatar.implants
|
||||||
|
implants.zipWithIndex.foreach {
|
||||||
|
case (Some(implant), slot) =>
|
||||||
|
sessionActor ! SessionActor.SendResponse(
|
||||||
|
CreateShortcutMessage(
|
||||||
|
session.get.player.GUID,
|
||||||
|
slot + 2,
|
||||||
|
Some(implant.definition.implantType.shortcut)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
// If the amount of time that has passed since you entered the world or died is > how long it takes to
|
||||||
|
// initialize this implant, initialize it after 1 second.
|
||||||
|
if ((System.currentTimeMillis() / 1000) - (lastRespawn / 1000) > implant.definition.InitializationDuration) {
|
||||||
|
implantTimers.get(slot).foreach(_.cancel())
|
||||||
|
implantTimers(slot) = context.scheduleOnce(
|
||||||
|
1.seconds,
|
||||||
|
context.self,
|
||||||
|
SetImplantInitialized(implant.definition.implantType)
|
||||||
|
)
|
||||||
|
session.get.zone.AvatarEvents ! AvatarServiceMessage(
|
||||||
|
avatar.name,
|
||||||
|
AvatarAction.SendResponse(Service.defaultPlayerGUID, ActionProgressMessage(slot + 6, 0))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// If the implant initialization timer hasn't quite finished, calculate a reduced timer based on last spawn activity
|
||||||
|
else {
|
||||||
|
val remainingTime = (lastRespawn / 1000).seconds - (System.currentTimeMillis() / 1000).seconds + implant.definition.InitializationDuration.seconds
|
||||||
|
implantTimers.get(slot).foreach(_.cancel())
|
||||||
|
implantTimers(slot) = context.scheduleOnce(
|
||||||
|
remainingTime,
|
||||||
|
context.self,
|
||||||
|
SetImplantInitialized(implant.definition.implantType)
|
||||||
|
)
|
||||||
|
session.get.zone.AvatarEvents ! AvatarServiceMessage(
|
||||||
|
avatar.name,
|
||||||
|
AvatarAction.SendResponse(Service.defaultPlayerGUID, ActionProgressMessage(slot + 6, 0))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
case (None, _) =>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// You just entered the world or died. Implants reset and timers start from scratch
|
||||||
|
else {
|
||||||
|
deinitializeImplants()
|
||||||
|
initializeImplants()
|
||||||
|
}
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
|
|
||||||
case UpdateToolDischarge(stats) =>
|
case UpdateToolDischarge(stats) =>
|
||||||
|
|
|
||||||
|
|
@ -219,7 +219,7 @@ class SessionData(
|
||||||
if (isMovingPlus) {
|
if (isMovingPlus) {
|
||||||
if (zoning.zoningStatus == Zoning.Status.Deconstructing) {
|
if (zoning.zoningStatus == Zoning.Status.Deconstructing) {
|
||||||
stopDeconstructing()
|
stopDeconstructing()
|
||||||
} else {
|
} else if (zoning.zoningStatus != Zoning.Status.None) {
|
||||||
zoning.CancelZoningProcessWithDescriptiveReason("cancel_motion")
|
zoning.CancelZoningProcessWithDescriptiveReason("cancel_motion")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
package net.psforever.actors.session.support
|
package net.psforever.actors.session.support
|
||||||
|
|
||||||
import akka.actor.{ActorContext, typed}
|
import akka.actor.{ActorContext, typed}
|
||||||
|
import net.psforever.objects.zones.Zoning
|
||||||
import net.psforever.objects.zones.exp.ToDatabase
|
import net.psforever.objects.zones.exp.ToDatabase
|
||||||
|
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
|
|
@ -50,7 +51,8 @@ private[support] class WeaponAndProjectileOperations(
|
||||||
private[support] var shotsWhileDead: Int = 0
|
private[support] var shotsWhileDead: Int = 0
|
||||||
private val projectiles: Array[Option[Projectile]] =
|
private val projectiles: Array[Option[Projectile]] =
|
||||||
Array.fill[Option[Projectile]](Projectile.rangeUID - Projectile.baseUID)(None)
|
Array.fill[Option[Projectile]](Projectile.rangeUID - Projectile.baseUID)(None)
|
||||||
|
private var zoningOpt: Option[ZoningOperations] = None
|
||||||
|
def zoning: ZoningOperations = zoningOpt.orNull
|
||||||
/* packets */
|
/* packets */
|
||||||
|
|
||||||
def handleWeaponFire(pkt: WeaponFireMessage): Unit = {
|
def handleWeaponFire(pkt: WeaponFireMessage): Unit = {
|
||||||
|
|
@ -536,7 +538,9 @@ private[support] class WeaponAndProjectileOperations(
|
||||||
weaponGUID: PlanetSideGUID,
|
weaponGUID: PlanetSideGUID,
|
||||||
projectileGUID: PlanetSideGUID
|
projectileGUID: PlanetSideGUID
|
||||||
): (Option[PlanetSideGameObject with Container], Option[Tool]) = {
|
): (Option[PlanetSideGameObject with Container], Option[Tool]) = {
|
||||||
sessionData.zoning.CancelZoningProcessWithDescriptiveReason("cancel_fire")
|
if (player.ZoningRequest != Zoning.Method.None) {
|
||||||
|
sessionData.zoning.CancelZoningProcessWithDescriptiveReason("cancel_fire")
|
||||||
|
}
|
||||||
if (player.isShielded) {
|
if (player.isShielded) {
|
||||||
// Cancel NC MAX shield if it's active
|
// Cancel NC MAX shield if it's active
|
||||||
sessionData.toggleMaxSpecialState(enable = false)
|
sessionData.toggleMaxSpecialState(enable = false)
|
||||||
|
|
|
||||||
|
|
@ -889,7 +889,7 @@ class ZoningOperations(
|
||||||
def beginZoningCountdown(runnable: Runnable): Unit = {
|
def beginZoningCountdown(runnable: Runnable): Unit = {
|
||||||
val descriptor = zoningType.toString.toLowerCase
|
val descriptor = zoningType.toString.toLowerCase
|
||||||
if (zoningStatus == Zoning.Status.Request) {
|
if (zoningStatus == Zoning.Status.Request) {
|
||||||
avatarActor ! AvatarActor.DeinitializeImplants()
|
avatarActor ! AvatarActor.DeactivateActiveImplants()
|
||||||
zoningStatus = Zoning.Status.Countdown
|
zoningStatus = Zoning.Status.Countdown
|
||||||
val (time, origin) = ZoningStartInitialMessageAndTimer()
|
val (time, origin) = ZoningStartInitialMessageAndTimer()
|
||||||
zoningCounter = time
|
zoningCounter = time
|
||||||
|
|
@ -2300,18 +2300,8 @@ class ZoningOperations(
|
||||||
//vehicle and driver/passenger
|
//vehicle and driver/passenger
|
||||||
val vdef = vehicle.Definition
|
val vdef = vehicle.Definition
|
||||||
val vguid = vehicle.GUID
|
val vguid = vehicle.GUID
|
||||||
val vdata = if (seat == 0) {
|
val vdata = vdef.Packet.ConstructorData(vehicle).get
|
||||||
val seat = vehicle.Seats(0)
|
sendResponse(ObjectCreateMessage(vehicle.Definition.ObjectId, vguid, vdata))
|
||||||
seat.unmount(player)
|
|
||||||
val _vdata = vdef.Packet.ConstructorData(vehicle).get
|
|
||||||
sendResponse(ObjectCreateMessage(vehicle.Definition.ObjectId, vguid, _vdata))
|
|
||||||
seat.mount(player)
|
|
||||||
_vdata
|
|
||||||
} else {
|
|
||||||
val _vdata = vdef.Packet.ConstructorData(vehicle).get
|
|
||||||
sendResponse(ObjectCreateMessage(vehicle.Definition.ObjectId, vguid, _vdata))
|
|
||||||
_vdata
|
|
||||||
}
|
|
||||||
Vehicles.ReloadAccessPermissions(vehicle, continent.id)
|
Vehicles.ReloadAccessPermissions(vehicle, continent.id)
|
||||||
log.debug(s"AvatarCreate (vehicle): ${player.Name}'s ${vehicle.Definition.Name}")
|
log.debug(s"AvatarCreate (vehicle): ${player.Name}'s ${vehicle.Definition.Name}")
|
||||||
log.trace(s"AvatarCreate (vehicle): ${player.Name}'s ${vehicle.Definition.Name} - $vguid -> $vdata")
|
log.trace(s"AvatarCreate (vehicle): ${player.Name}'s ${vehicle.Definition.Name} - $vguid -> $vdata")
|
||||||
|
|
@ -2777,10 +2767,7 @@ class ZoningOperations(
|
||||||
}
|
}
|
||||||
val originalDeadState = deadState
|
val originalDeadState = deadState
|
||||||
deadState = DeadState.Alive
|
deadState = DeadState.Alive
|
||||||
if (originalDeadState != DeadState.Alive) {
|
avatarActor ! AvatarActor.ResetImplants()
|
||||||
avatarActor ! AvatarActor.ResetImplants()
|
|
||||||
}
|
|
||||||
|
|
||||||
sendResponse(PlanetsideAttributeMessage(PlanetSideGUID(0), 82, 0))
|
sendResponse(PlanetsideAttributeMessage(PlanetSideGUID(0), 82, 0))
|
||||||
initializeShortcutsAndBank(guid)
|
initializeShortcutsAndBank(guid)
|
||||||
//Favorites lists
|
//Favorites lists
|
||||||
|
|
|
||||||
|
|
@ -7568,7 +7568,7 @@ object GlobalDefinitions {
|
||||||
apc_tr.UnderwaterLifespan(suffocation = 15000L, recovery = 7500L)
|
apc_tr.UnderwaterLifespan(suffocation = 15000L, recovery = 7500L)
|
||||||
apc_tr.Geometry = apcForm
|
apc_tr.Geometry = apcForm
|
||||||
apc_tr.MaxCapacitor = 300
|
apc_tr.MaxCapacitor = 300
|
||||||
apc_tr.CapacitorRecharge = 10
|
apc_tr.CapacitorRecharge = 1
|
||||||
apc_tr.collision.avatarCollisionDamageMax = 300
|
apc_tr.collision.avatarCollisionDamageMax = 300
|
||||||
apc_tr.collision.xy = CollisionXYData(Array((0.1f, 1), (0.25f, 10), (0.5f, 40), (0.75f, 70), (1f, 110)))
|
apc_tr.collision.xy = CollisionXYData(Array((0.1f, 1), (0.25f, 10), (0.5f, 40), (0.75f, 70), (1f, 110)))
|
||||||
apc_tr.collision.z = CollisionZData(Array((2f, 1), (6f, 50), (10f, 300), (12f, 1000), (13f, 3000)))
|
apc_tr.collision.z = CollisionZData(Array((2f, 1), (6f, 50), (10f, 300), (12f, 1000), (13f, 3000)))
|
||||||
|
|
@ -7638,7 +7638,7 @@ object GlobalDefinitions {
|
||||||
apc_nc.UnderwaterLifespan(suffocation = 15000L, recovery = 7500L)
|
apc_nc.UnderwaterLifespan(suffocation = 15000L, recovery = 7500L)
|
||||||
apc_nc.Geometry = apcForm
|
apc_nc.Geometry = apcForm
|
||||||
apc_nc.MaxCapacitor = 300
|
apc_nc.MaxCapacitor = 300
|
||||||
apc_nc.CapacitorRecharge = 10
|
apc_nc.CapacitorRecharge = 1
|
||||||
apc_nc.collision.avatarCollisionDamageMax = 300
|
apc_nc.collision.avatarCollisionDamageMax = 300
|
||||||
apc_nc.collision.xy = CollisionXYData(Array((0.1f, 1), (0.25f, 10), (0.5f, 40), (0.75f, 70), (1f, 110)))
|
apc_nc.collision.xy = CollisionXYData(Array((0.1f, 1), (0.25f, 10), (0.5f, 40), (0.75f, 70), (1f, 110)))
|
||||||
apc_nc.collision.z = CollisionZData(Array((2f, 1), (6f, 50), (10f, 300), (12f, 1000), (13f, 3000)))
|
apc_nc.collision.z = CollisionZData(Array((2f, 1), (6f, 50), (10f, 300), (12f, 1000), (13f, 3000)))
|
||||||
|
|
@ -7708,7 +7708,7 @@ object GlobalDefinitions {
|
||||||
apc_vs.UnderwaterLifespan(suffocation = 15000L, recovery = 7500L)
|
apc_vs.UnderwaterLifespan(suffocation = 15000L, recovery = 7500L)
|
||||||
apc_vs.Geometry = apcForm
|
apc_vs.Geometry = apcForm
|
||||||
apc_vs.MaxCapacitor = 300
|
apc_vs.MaxCapacitor = 300
|
||||||
apc_vs.CapacitorRecharge = 10
|
apc_vs.CapacitorRecharge = 1
|
||||||
apc_vs.collision.avatarCollisionDamageMax = 300
|
apc_vs.collision.avatarCollisionDamageMax = 300
|
||||||
apc_vs.collision.xy = CollisionXYData(Array((0.1f, 1), (0.25f, 10), (0.5f, 40), (0.75f, 70), (1f, 110)))
|
apc_vs.collision.xy = CollisionXYData(Array((0.1f, 1), (0.25f, 10), (0.5f, 40), (0.75f, 70), (1f, 110)))
|
||||||
apc_vs.collision.z = CollisionZData(Array((2f, 1), (6f, 50), (10f, 300), (12f, 1000), (13f, 3000)))
|
apc_vs.collision.z = CollisionZData(Array((2f, 1), (6f, 50), (10f, 300), (12f, 1000), (13f, 3000)))
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ class SensorDeployableControl(sensor: SensorDeployable)
|
||||||
|
|
||||||
override def StartJammeredStatus(target: Any, dur: Int): Unit =
|
override def StartJammeredStatus(target: Any, dur: Int): Unit =
|
||||||
target match {
|
target match {
|
||||||
case obj: PlanetSideServerObject with JammableUnit if !obj.Jammed =>
|
case obj: PlanetSideServerObject with JammableUnit =>
|
||||||
val zone = obj.Zone
|
val zone = obj.Zone
|
||||||
zone.LocalEvents ! LocalServiceMessage(
|
zone.LocalEvents ! LocalServiceMessage(
|
||||||
zone.id,
|
zone.id,
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ class ShieldGeneratorControl(gen: ShieldGeneratorDeployable)
|
||||||
|
|
||||||
override def StartJammeredStatus(target: Any, dur: Int): Unit =
|
override def StartJammeredStatus(target: Any, dur: Int): Unit =
|
||||||
target match {
|
target match {
|
||||||
case obj: PlanetSideServerObject with JammableUnit if !obj.Jammed =>
|
case obj: PlanetSideServerObject with JammableUnit =>
|
||||||
obj.Zone.VehicleEvents ! VehicleServiceMessage(
|
obj.Zone.VehicleEvents ! VehicleServiceMessage(
|
||||||
obj.Zone.id,
|
obj.Zone.id,
|
||||||
VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 27, 1)
|
VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 27, 1)
|
||||||
|
|
|
||||||
|
|
@ -76,10 +76,10 @@ object Vehicles {
|
||||||
val factionChannel = s"${vehicle.Faction}"
|
val factionChannel = s"${vehicle.Faction}"
|
||||||
(0 to 2).foreach(group => {
|
(0 to 2).foreach(group => {
|
||||||
vehicle.PermissionGroup(group, empire)
|
vehicle.PermissionGroup(group, empire)
|
||||||
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(
|
/*vehicle.Zone.VehicleEvents ! VehicleServiceMessage(
|
||||||
factionChannel,
|
factionChannel,
|
||||||
VehicleAction.SeatPermissions(Service.defaultPlayerGUID, guid, group, empire)
|
VehicleAction.SeatPermissions(Service.defaultPlayerGUID, guid, group, empire)
|
||||||
)
|
)*/
|
||||||
})
|
})
|
||||||
ReloadAccessPermissions(vehicle, player.Name)
|
ReloadAccessPermissions(vehicle, player.Name)
|
||||||
Some(vehicle)
|
Some(vehicle)
|
||||||
|
|
@ -135,10 +135,10 @@ object Vehicles {
|
||||||
val empire = VehicleLockState.Empire.id
|
val empire = VehicleLockState.Empire.id
|
||||||
(0 to 2).foreach(group => {
|
(0 to 2).foreach(group => {
|
||||||
vehicle.PermissionGroup(group, empire)
|
vehicle.PermissionGroup(group, empire)
|
||||||
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(
|
/*vehicle.Zone.VehicleEvents ! VehicleServiceMessage(
|
||||||
s"${vehicle.Faction}",
|
s"${vehicle.Faction}",
|
||||||
VehicleAction.SeatPermissions(pguid, vguid, group, empire)
|
VehicleAction.SeatPermissions(pguid, vguid, group, empire)
|
||||||
)
|
)*/
|
||||||
})
|
})
|
||||||
ReloadAccessPermissions(vehicle, player.Name)
|
ReloadAccessPermissions(vehicle, player.Name)
|
||||||
Some(vehicle)
|
Some(vehicle)
|
||||||
|
|
|
||||||
|
|
@ -1309,7 +1309,10 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
|
||||||
* @param data additional interaction information, if applicable
|
* @param data additional interaction information, if applicable
|
||||||
*/
|
*/
|
||||||
def doInteractingWithDeath(obj: PlanetSideServerObject, body: PieceOfEnvironment, data: Option[OxygenStateTarget]): Unit = {
|
def doInteractingWithDeath(obj: PlanetSideServerObject, body: PieceOfEnvironment, data: Option[OxygenStateTarget]): Unit = {
|
||||||
suicide()
|
player.History.findLast { entry => entry.isInstanceOf[ReconstructionActivity] } match {
|
||||||
|
case Some(entry) if System.currentTimeMillis() - entry.time > 4000L => suicide()
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//noinspection ScalaUnusedSymbol
|
//noinspection ScalaUnusedSymbol
|
||||||
|
|
|
||||||
|
|
@ -253,7 +253,7 @@ trait JammableMountedWeapons extends JammableBehavior {
|
||||||
|
|
||||||
override def StartJammeredStatus(target: Any, dur: Int): Unit = {
|
override def StartJammeredStatus(target: Any, dur: Int): Unit = {
|
||||||
target match {
|
target match {
|
||||||
case obj: PlanetSideServerObject with MountedWeapons with JammableUnit if !obj.Jammed =>
|
case obj: PlanetSideServerObject with MountedWeapons with JammableUnit =>
|
||||||
JammableMountedWeaponsJammeredStatus(obj, statusCode = 1)
|
JammableMountedWeaponsJammeredStatus(obj, statusCode = 1)
|
||||||
super.StartJammeredStatus(target, dur)
|
super.StartJammeredStatus(target, dur)
|
||||||
case _ => ;
|
case _ => ;
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,8 @@ object DamageableMountable {
|
||||||
.values
|
.values
|
||||||
.flatMap { _.occupant }
|
.flatMap { _.occupant }
|
||||||
.collect { case player if player.isAlive =>
|
.collect { case player if player.isAlive =>
|
||||||
|
//make llu visible to others in zone if passenger is carrying one
|
||||||
|
player.Zone.AvatarEvents ! AvatarServiceMessage(player.Name, AvatarAction.DropSpecialItem())
|
||||||
//player.LogActivity(cause)
|
//player.LogActivity(cause)
|
||||||
player.Actor ! Player.Die(
|
player.Actor ! Player.Die(
|
||||||
DamageInteraction(interaction.resolution, SourceEntry(player), interaction.cause, interaction.hitPos)
|
DamageInteraction(interaction.resolution, SourceEntry(player), interaction.cause, interaction.hitPos)
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ import net.psforever.objects.serverobject.terminals.Terminal
|
||||||
import net.psforever.objects.sourcing.{PlayerSource, SourceEntry, VehicleSource}
|
import net.psforever.objects.sourcing.{PlayerSource, SourceEntry, VehicleSource}
|
||||||
import net.psforever.objects.vehicles._
|
import net.psforever.objects.vehicles._
|
||||||
import net.psforever.objects.vital.interaction.{DamageInteraction, DamageResult}
|
import net.psforever.objects.vital.interaction.{DamageInteraction, DamageResult}
|
||||||
import net.psforever.objects.vital.{DamagingActivity, InGameActivity, ShieldCharge, SpawningActivity, VehicleDismountActivity, VehicleMountActivity}
|
import net.psforever.objects.vital.{DamagingActivity, InGameActivity, ReconstructionActivity, ShieldCharge, SpawningActivity, VehicleDismountActivity, VehicleMountActivity}
|
||||||
import net.psforever.objects.vital.environment.EnvironmentReason
|
import net.psforever.objects.vital.environment.EnvironmentReason
|
||||||
import net.psforever.objects.vital.etc.SuicideReason
|
import net.psforever.objects.vital.etc.SuicideReason
|
||||||
import net.psforever.objects.zones._
|
import net.psforever.objects.zones._
|
||||||
|
|
@ -679,14 +679,18 @@ class VehicleControl(vehicle: Vehicle)
|
||||||
*/
|
*/
|
||||||
def doInteractingWithDeath(obj: PlanetSideServerObject, body: PieceOfEnvironment, data: Option[OxygenStateTarget]): Unit = {
|
def doInteractingWithDeath(obj: PlanetSideServerObject, body: PieceOfEnvironment, data: Option[OxygenStateTarget]): Unit = {
|
||||||
if (!obj.Destroyed) {
|
if (!obj.Destroyed) {
|
||||||
PerformDamage(
|
vehicle.History.findLast { entry => entry.isInstanceOf[ReconstructionActivity] } match {
|
||||||
vehicle,
|
case Some(entry) if System.currentTimeMillis() - entry.time > 4000L =>
|
||||||
DamageInteraction(
|
PerformDamage(
|
||||||
VehicleSource(vehicle),
|
vehicle,
|
||||||
SuicideReason(),
|
DamageInteraction(
|
||||||
vehicle.Position
|
VehicleSource(vehicle),
|
||||||
).calculate()
|
SuicideReason(),
|
||||||
)
|
vehicle.Position
|
||||||
|
).calculate()
|
||||||
|
)
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -859,10 +863,8 @@ class VehicleControl(vehicle: Vehicle)
|
||||||
override def StartJammeredStatus(target: Any, dur: Int): Unit = {
|
override def StartJammeredStatus(target: Any, dur: Int): Unit = {
|
||||||
super.StartJammeredStatus(target, dur)
|
super.StartJammeredStatus(target, dur)
|
||||||
val subsystems = vehicle.Subsystems()
|
val subsystems = vehicle.Subsystems()
|
||||||
if (!subsystems.exists { _.Jammed }) {
|
|
||||||
subsystems.foreach { _.jam() }
|
subsystems.foreach { _.jam() }
|
||||||
vehicleSubsystemMessages(subsystems.flatMap { _.changedMessages(vehicle) })
|
vehicleSubsystemMessages(subsystems.flatMap { _.changedMessages(vehicle) })
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override def CancelJammeredStatus(target: Any): Unit = {
|
override def CancelJammeredStatus(target: Any): Unit = {
|
||||||
|
|
|
||||||
|
|
@ -365,6 +365,8 @@ class PersistenceMonitor(
|
||||||
def PerformLogout(): Unit = {
|
def PerformLogout(): Unit = {
|
||||||
(inZone.Players.find(p => p.name == name), inZone.LivePlayers.find(p => p.Name == name)) match {
|
(inZone.Players.find(p => p.name == name), inZone.LivePlayers.find(p => p.Name == name)) match {
|
||||||
case (Some(avatar), Some(player)) if player.VehicleSeated.nonEmpty =>
|
case (Some(avatar), Some(player)) if player.VehicleSeated.nonEmpty =>
|
||||||
|
//in case the player is holding the llu and disconnects
|
||||||
|
player.Zone.AvatarEvents ! AvatarServiceMessage(player.Name, AvatarAction.DropSpecialItem())
|
||||||
//alive or dead in a vehicle
|
//alive or dead in a vehicle
|
||||||
//if the avatar is dead while in a vehicle, they haven't released yet
|
//if the avatar is dead while in a vehicle, they haven't released yet
|
||||||
AvatarActor.saveAvatarData(avatar)
|
AvatarActor.saveAvatarData(avatar)
|
||||||
|
|
@ -381,6 +383,8 @@ class PersistenceMonitor(
|
||||||
PlayerAvatarLogout(avatar, player)
|
PlayerAvatarLogout(avatar, player)
|
||||||
|
|
||||||
case (Some(avatar), Some(player)) =>
|
case (Some(avatar), Some(player)) =>
|
||||||
|
//in case the player is holding the llu and disconnects
|
||||||
|
player.Zone.AvatarEvents ! AvatarServiceMessage(player.Name, AvatarAction.DropSpecialItem())
|
||||||
//alive or dead, as standard Infantry
|
//alive or dead, as standard Infantry
|
||||||
AvatarActor.saveAvatarData(avatar)
|
AvatarActor.saveAvatarData(avatar)
|
||||||
AvatarActor.finalSavePlayerData(player)
|
AvatarActor.finalSavePlayerData(player)
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,7 @@ class CaptureFlagManager(zone: Zone) extends Actor {
|
||||||
case CaptureFlagManager.DropFlag(flag: CaptureFlag) =>
|
case CaptureFlagManager.DropFlag(flag: CaptureFlag) =>
|
||||||
flag.Carrier match {
|
flag.Carrier match {
|
||||||
case Some(player: Player) =>
|
case Some(player: Player) =>
|
||||||
|
val newFlag = flag
|
||||||
// Set the flag position to where the player is that dropped it
|
// Set the flag position to where the player is that dropped it
|
||||||
flag.Position = player.Position
|
flag.Position = player.Position
|
||||||
// Remove attached player from flag
|
// Remove attached player from flag
|
||||||
|
|
@ -121,6 +122,27 @@ class CaptureFlagManager(zone: Zone) extends Actor {
|
||||||
flag.Zone.LocalEvents ! LocalServiceMessage(flag.Zone.id, LocalAction.SendPacket(ObjectDetachMessage(player.GUID, flag.GUID, player.Position, 0, 0, 0)))
|
flag.Zone.LocalEvents ! LocalServiceMessage(flag.Zone.id, LocalAction.SendPacket(ObjectDetachMessage(player.GUID, flag.GUID, player.Position, 0, 0, 0)))
|
||||||
// Send dropped chat message
|
// Send dropped chat message
|
||||||
ChatBroadcast(flag.Zone, CaptureFlagChatMessageStrings.CTF_FlagDropped(player.Name, player.Faction, flag.Owner.asInstanceOf[Building].Name), fanfare = false)
|
ChatBroadcast(flag.Zone, CaptureFlagChatMessageStrings.CTF_FlagDropped(player.Name, player.Faction, flag.Owner.asInstanceOf[Building].Name), fanfare = false)
|
||||||
|
HandleFlagDespawn(flag)
|
||||||
|
// Register LLU object create task and callback to create on clients
|
||||||
|
val replacementLlu = CaptureFlag.Constructor(
|
||||||
|
newFlag.Position,
|
||||||
|
newFlag.Orientation,
|
||||||
|
newFlag.Target,
|
||||||
|
newFlag.Owner,
|
||||||
|
player.Faction
|
||||||
|
)
|
||||||
|
// Add the flag as an amenity and track it internally
|
||||||
|
val socket = newFlag.Owner.asInstanceOf[Building].GetFlagSocket.get
|
||||||
|
socket.captureFlag = replacementLlu
|
||||||
|
TrackFlag(replacementLlu)
|
||||||
|
TaskWorkflow.execute(WorldSession.CallBackForTask(
|
||||||
|
GUIDTask.registerObject(socket.Zone.GUID, replacementLlu),
|
||||||
|
socket.Zone.LocalEvents,
|
||||||
|
LocalServiceMessage(
|
||||||
|
socket.Zone.id,
|
||||||
|
LocalAction.LluSpawned(Service.defaultPlayerGUID, replacementLlu)
|
||||||
|
)
|
||||||
|
))
|
||||||
case _ =>
|
case _ =>
|
||||||
log.warn("Tried to drop flag but flag has no carrier")
|
log.warn("Tried to drop flag but flag has no carrier")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue