corrected death by force dome contact, for all players; corrected reset of force dome protection field condition

This commit is contained in:
Fate-JH 2026-01-25 19:17:37 -05:00
parent c7368d47a4
commit f5d7fed1cf
10 changed files with 171 additions and 185 deletions

View file

@ -110,7 +110,7 @@ class CustomerServiceRepresentativeMode(data: SessionData) extends ModeLogic {
private def keepAlivePersistanceCSR(): Unit = {
val player = data.player
player.allowInteraction = false
topOffHealthOfPlayer(player)
CustomerServiceRepresentativeMode.topOffHealthOfPlayer(data, player)
data.zoning.spawn.interimUngunnedVehicle = None
data.keepAlivePersistence()
if (player.HasGUID) {
@ -119,63 +119,13 @@ class CustomerServiceRepresentativeMode(data: SessionData) extends ModeLogic {
data.continent
.GUID(player.VehicleSeated)
.collect { case obj: PlanetSideGameObject with Vitality =>
topOffHealth(obj)
CustomerServiceRepresentativeMode.topOffHealth(data, obj)
}
data.squad.updateSquad()
} else {
data.turnCounterFunc(PlanetSideGUID(0))
}
}
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)
)
}
}
}
case object CustomerServiceRepresentativeMode extends PlayerMode {
@ -202,4 +152,66 @@ case object CustomerServiceRepresentativeMode extends PlayerMode {
None
))
}
def topOffHealth(data: SessionData, obj: PlanetSideGameObject with Vitality): Unit = {
obj match {
case p: Player => topOffHealthOfPlayer(data, p)
case v: Vehicle => topOffHealthOfVehicle(data, v)
case o: PlanetSideGameObject with Vitality => topOffHealthOfGeneric(data, o)
case _ => ()
}
}
def topOffHealthOfPlayer(data: SessionData, player: Player): Unit = {
//below half health, full heal
val maxHealthOfPlayer = player.MaxHealth.toLong
val guid = player.GUID
val zoneid = data.zoning.zoneChannel
if (player.Health < maxHealthOfPlayer * 0.5f) {
if (player.Health == 0) {
player.Revive
}
player.Health = maxHealthOfPlayer.toInt
player.LogActivity(player.ClearHistory().head)
data.sendResponse(PlanetsideAttributeMessage(guid, 0, maxHealthOfPlayer))
data.continent.AvatarEvents ! AvatarServiceMessage(zoneid, AvatarAction.PlanetsideAttribute(guid, 0, maxHealthOfPlayer))
}
//below half armor, full armor
val maxArmor = player.MaxArmor.toLong
if (player.Armor < maxArmor) {
player.Armor = maxArmor.toInt
data.sendResponse(PlanetsideAttributeMessage(guid, 4, maxArmor))
data.continent.AvatarEvents ! AvatarServiceMessage(zoneid, AvatarAction.PlanetsideAttribute(guid, 4, maxArmor))
}
}
def topOffHealthOfVehicle(data: SessionData, vehicle: Vehicle): Unit = {
topOffHealthOfGeneric(data, 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)
)
}
}
def topOffHealthOfGeneric(data: SessionData, 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)
)
}
}
}

View file

@ -27,11 +27,8 @@ import net.psforever.objects.serverobject.terminals.{ProximityUnit, Terminal}
import net.psforever.objects.serverobject.terminals.implant.ImplantTerminalMech
import net.psforever.objects.serverobject.tube.SpawnTube
import net.psforever.objects.serverobject.turret.FacilityTurret
import net.psforever.objects.sourcing.{PlayerSource, SourceEntry}
import net.psforever.objects.vehicles.Utility
import net.psforever.objects.vital.Vitality
import net.psforever.objects.vital.etc.ForceDomeExposure
import net.psforever.objects.vital.interaction.DamageInteraction
import net.psforever.objects.zones.{ZoneProjectile, Zoning}
import net.psforever.packet.PlanetSideGamePacket
import net.psforever.packet.game.OutfitEventAction.{Initial, OutfitInfo, OutfitRankNames, Unk1}
@ -40,8 +37,8 @@ import net.psforever.services.RemoverActor
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
import net.psforever.types.{CapacitorStateType, ChatMessageType, Cosmetic, ExoSuitType, PlanetSideEmpire, PlanetSideGUID, Vector3}
import scodec.bits.ByteVector
import scala.concurrent.duration._
import scala.util.Success
object GeneralLogic {
@ -81,28 +78,7 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
sessionLogic.persist()
sessionLogic.turnCounterFunc(avatarGuid)
sessionLogic.updateBlockMap(player, pos)
//below half health, full heal
val maxHealth = player.MaxHealth.toLong
if (player.Health < maxHealth) {
player.Health = maxHealth.toInt
player.LogActivity(player.ClearHistory().head)
sendResponse(PlanetsideAttributeMessage(avatarGuid, 0, maxHealth))
continent.AvatarEvents ! AvatarServiceMessage(continent.id, AvatarAction.PlanetsideAttribute(avatarGuid, 0, maxHealth))
}
//below half stamina, full stamina
val avatar = player.avatar
val maxStamina = avatar.maxStamina
if (avatar.stamina < maxStamina) {
avatarActor ! AvatarActor.RestoreStamina(maxStamina)
sendResponse(PlanetsideAttributeMessage(player.GUID, 2, maxStamina.toLong))
}
//below half armor, full armor
val maxArmor = player.MaxArmor.toLong
if (player.Armor < maxArmor) {
player.Armor = maxArmor.toInt
sendResponse(PlanetsideAttributeMessage(avatarGuid, 4, maxArmor))
continent.AvatarEvents ! AvatarServiceMessage(continent.id, AvatarAction.PlanetsideAttribute(avatarGuid, 4, maxArmor))
}
topOffHealthOfPlayer()
//expected
val isMoving = WorldEntity.isMoving(vel)
val isMovingPlus = isMoving || isJumping || jumpThrust
@ -559,20 +535,19 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
v.BailProtection = false
case (CollisionIs.OfAircraft, Some(v: Vehicle))
if v.Definition.CanFly && v.Seats(0).occupant.contains(player) => ()
case (CollisionIs.BetweenThings, Some(field: ForceDomePhysics)) /*if field.Energized*/ =>
val target = sessionLogic
.vehicles
.findLocalVehicle
.getOrElse(player)
target.Actor ! Vitality.Damage(
DamageInteraction(
PlayerSource(player),
ForceDomeExposure(SourceEntry(field)),
player.Position
).calculate()
)
target.BailProtection = false
player.BailProtection = false
case (CollisionIs.BetweenThings, Some(v: Vehicle)) =>
v.Actor ! Vehicle.Deconstruct(Some(1 millisecond))
continent.GUID(t) match {
case Some(_: ForceDomePhysics) =>
player.Actor ! Player.Die()
case _ => ()
}
case (CollisionIs.BetweenThings, Some(_: Player)) =>
continent.GUID(t) match {
case Some(_: ForceDomePhysics) =>
player.Actor ! Player.Die()
case _ => ()
}
case (CollisionIs.BetweenThings, _) =>
log.warn(s"GenericCollision: CollisionIs.BetweenThings detected - no handling case for obj id:${t.guid}")
case _ => ()
@ -823,4 +798,16 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
player.CapacitorState = CapacitorStateType.Idle
}
}
def topOffHealthOfPlayer(): Unit = {
//below half health, full heal
CustomerServiceRepresentativeMode.topOffHealthOfPlayer(sessionLogic, player)
//below half stamina, full stamina
val avatar = player.avatar
val maxStamina = avatar.maxStamina
if (avatar.stamina < maxStamina) {
avatarActor ! AvatarActor.RestoreStamina(maxStamina)
sendResponse(PlanetsideAttributeMessage(player.GUID, 2, maxStamina.toLong))
}
}
}

View file

@ -5,17 +5,15 @@ 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.{PlanetSideGameObject, Player, 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.objects.zones.interaction.InteractsWithZone
import net.psforever.packet.game.{ChildObjectStateMessage, DeployRequestMessage, FrameVehicleStateMessage, PlanetsideAttributeMessage, VehicleStateMessage, VehicleSubStateMessage}
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
import net.psforever.packet.game.{ChildObjectStateMessage, DeployRequestMessage, FrameVehicleStateMessage, VehicleStateMessage, VehicleSubStateMessage}
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
import net.psforever.types.{DriveState, PlanetSideGUID, Vector3}
import net.psforever.types.{DriveState, Vector3}
object VehicleLogic {
def apply(ops: VehicleOperations): VehicleLogic = {
@ -51,8 +49,8 @@ class VehicleLogic(val ops: VehicleOperations, implicit val context: ActorContex
sessionLogic.zoning.spawn.tryQueuedActivity(vel)
sessionLogic.persist()
sessionLogic.turnCounterFunc(player.GUID)
topOffHealthOfPlayer()
topOffHealth(obj)
CustomerServiceRepresentativeMode.topOffHealthOfPlayer(sessionLogic, player)
CustomerServiceRepresentativeMode.topOffHealth(sessionLogic, obj)
val (position, angle, velocity, notMountedState) = continent.GUID(obj.MountedIn) match {
case Some(v: Vehicle) =>
(pos, v.Orientation - Vector3.z(value = 90f) * Vehicles.CargoOrientation(obj).toFloat, v.Velocity, false)
@ -134,8 +132,8 @@ class VehicleLogic(val ops: VehicleOperations, implicit val context: ActorContex
sessionLogic.zoning.spawn.tryQueuedActivity(vel)
sessionLogic.persist()
sessionLogic.turnCounterFunc(player.GUID)
topOffHealthOfPlayer()
topOffHealth(obj)
CustomerServiceRepresentativeMode.topOffHealthOfPlayer(sessionLogic, player)
CustomerServiceRepresentativeMode.topOffHealth(sessionLogic, obj)
val (position, angle, velocity, notMountedState) = continent.GUID(obj.MountedIn) match {
case Some(v: Vehicle) =>
(pos, v.Orientation - Vector3.z(value = 90f) * Vehicles.CargoOrientation(obj).toFloat, v.Velocity, false)
@ -217,8 +215,8 @@ class VehicleLogic(val ops: VehicleOperations, implicit val context: ActorContex
sessionLogic.zoning.spawn.tryQueuedActivity(player.Velocity)
sessionLogic.persist()
sessionLogic.turnCounterFunc(player.GUID)
topOffHealthOfPlayer()
topOffHealth(entity)
CustomerServiceRepresentativeMode.topOffHealthOfPlayer(sessionLogic, player)
CustomerServiceRepresentativeMode.topOffHealth(sessionLogic, entity)
sessionLogic.squad.updateSquad()
case _ => //we can't disprove that COSM is our primary upstream packet, it's just that we may be missing some details
sessionLogic.zoning.spawn.tryQueuedActivity(player.Velocity)
@ -336,56 +334,4 @@ 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
if (player.Health < maxHealthOfPlayer * 0.5f) {
player.Health = maxHealthOfPlayer.toInt
player.LogActivity(player.ClearHistory().head)
sendResponse(PlanetsideAttributeMessage(player.GUID, 0, maxHealthOfPlayer))
continent.AvatarEvents ! AvatarServiceMessage(sessionLogic.zoning.zoneChannel, AvatarAction.PlanetsideAttribute(player.GUID, 0, maxHealthOfPlayer))
}
}
private def topOffHealthOfVehicle(vehicle: Vehicle): Unit = {
topOffHealthOfPlayer()
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, 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)
)
}
}
}

View file

@ -16,6 +16,7 @@ import net.psforever.objects.inventory.Container
import net.psforever.objects.serverobject.{PlanetSideServerObject, ServerObject}
import net.psforever.objects.serverobject.affinity.FactionAffinity
import net.psforever.objects.serverobject.containable.Containable
import net.psforever.objects.serverobject.damage.Damageable
import net.psforever.objects.serverobject.dome.ForceDomePhysics
import net.psforever.objects.serverobject.doors.Door
import net.psforever.objects.serverobject.generator.Generator
@ -23,6 +24,7 @@ import net.psforever.objects.serverobject.interior.Sidedness.OutsideOf
import net.psforever.objects.serverobject.llu.CaptureFlag
import net.psforever.objects.serverobject.locks.IFFLock
import net.psforever.objects.serverobject.mblocker.Locker
import net.psforever.objects.serverobject.mount.MountableEntity
import net.psforever.objects.serverobject.resourcesilo.ResourceSilo
import net.psforever.objects.serverobject.structures.WarpGate
import net.psforever.objects.serverobject.terminals.capture.CaptureTerminal
@ -637,25 +639,15 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
case (CollisionIs.OfAircraft, out @ Some(v: Vehicle))
if v.Definition.CanFly && v.Seats(0).occupant.contains(player) =>
(out, sessionLogic.validObject(t, decorator = "GenericCollision/Aircraft"), false, pv)
case (CollisionIs.BetweenThings, Some(field: ForceDomePhysics)) /*if field.Energized*/ =>
val target = sessionLogic
.vehicles
.findLocalVehicle
.getOrElse(player)
target.Actor ! Vitality.Damage(
DamageInteraction(
PlayerSource(player),
ForceDomeExposure(SourceEntry(field)),
player.Position
).calculate()
)
case (CollisionIs.BetweenThings, out @ Some(target: PlanetSideServerObject with MountableEntity)) =>
target.BailProtection = false
player.BailProtection = false
(out, sessionLogic.validObject(t, decorator = "GenericCollision/Surface"), false, pv)
case (_, Some(obj)) =>
log.error(s"GenericCollision: $ctype detected: no handling case for ${obj.Definition.Name}")
(None, None, false, Vector3.Zero)
case (CollisionIs.BetweenThings, _) =>
log.warn("GenericCollision: CollisionIs.BetweenThings detected - no handling case")
(None, None, false, Vector3.Zero)
case _ =>
case (_, None) =>
log.error(s"GenericCollision: $ctype detected: no entity detected as 'Primary'")
(None, None, false, Vector3.Zero)
}
val curr = System.currentTimeMillis()
@ -677,6 +669,16 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
}
}
case (Some(us: PlanetSideServerObject with Vitality with FactionAffinity), _, Some(field: ForceDomePhysics)) =>
us.Actor ! Damageable.MakeVulnerable
us.Actor ! Vitality.Damage(
DamageInteraction(
PlayerSource(player),
ForceDomeExposure(SourceEntry(field)),
player.Position
).calculate()
)
case (Some(us: Vehicle), _, Some(victim: SensorDeployable)) =>
collisionBetweenVehicleAndFragileDeployable(us, ppos, victim, tpos, velocity - tv, fallHeight, curr)

View file

@ -9,15 +9,18 @@ import net.psforever.objects.avatar.{Avatar, Implant}
import net.psforever.objects.ballistics.Projectile
import net.psforever.objects.definition.{BasicDefinition, KitDefinition, SpecialExoSuitDefinition}
import net.psforever.objects.serverobject.containable.Containable
import net.psforever.objects.serverobject.dome.ForceDomePhysics
import net.psforever.objects.serverobject.doors.Door
import net.psforever.objects.vehicles.Utility
import net.psforever.objects.zones.ZoneProjectile
import net.psforever.packet.PlanetSideGamePacket
import net.psforever.packet.game.{ActionCancelMessage, AvatarFirstTimeEventMessage, AvatarImplantMessage, AvatarJumpMessage, BattleplanMessage, BindPlayerMessage, BugReportMessage, ChangeFireModeMessage, ChangeShortcutBankMessage, CharacterCreateRequestMessage, CharacterRequestMessage, ConnectToWorldRequestMessage, CreateShortcutMessage, DeployObjectMessage, DisplayedAwardMessage, DropItemMessage, EmoteMsg, FacilityBenefitShieldChargeRequestMessage, FriendsRequest, GenericAction, GenericActionMessage, GenericCollisionMsg, GenericObjectActionAtPositionMessage, GenericObjectActionMessage, GenericObjectStateMsg, HitHint, ImplantAction, InvalidTerrainMessage, LootItemMessage, MoveItemMessage, ObjectDetectedMessage, ObjectHeldMessage, OutfitMembershipRequest, OutfitMembershipResponse, OutfitRequest, PickupItemMessage, PlanetsideAttributeMessage, PlayerStateMessageUpstream, RequestDestroyMessage, TargetingImplantRequest, TradeMessage, UnuseItemMessage, UseItemMessage, VoiceHostInfo, VoiceHostRequest, ZipLineMessage}
import net.psforever.packet.game.{ActionCancelMessage, AvatarFirstTimeEventMessage, AvatarImplantMessage, AvatarJumpMessage, BattleplanMessage, BindPlayerMessage, BugReportMessage, ChangeFireModeMessage, ChangeShortcutBankMessage, CharacterCreateRequestMessage, CharacterRequestMessage, CollisionIs, ConnectToWorldRequestMessage, CreateShortcutMessage, DeployObjectMessage, DisplayedAwardMessage, DropItemMessage, EmoteMsg, FacilityBenefitShieldChargeRequestMessage, FriendsRequest, GenericAction, GenericActionMessage, GenericCollisionMsg, GenericObjectActionAtPositionMessage, GenericObjectActionMessage, GenericObjectStateMsg, HitHint, ImplantAction, InvalidTerrainMessage, LootItemMessage, MoveItemMessage, ObjectDetectedMessage, ObjectHeldMessage, OutfitMembershipRequest, OutfitMembershipResponse, OutfitRequest, PickupItemMessage, PlanetsideAttributeMessage, PlayerStateMessageUpstream, RequestDestroyMessage, TargetingImplantRequest, TradeMessage, UnuseItemMessage, UseItemMessage, VoiceHostInfo, VoiceHostRequest, ZipLineMessage}
import net.psforever.services.account.AccountPersistenceService
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
import net.psforever.types.{ExoSuitType, Vector3}
import scala.concurrent.duration.DurationInt
object GeneralLogic {
def apply(ops: GeneralOperations): GeneralLogic = {
new GeneralLogic(ops, ops.context)
@ -283,7 +286,34 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
}
}
def handleGenericCollision(pkt: GenericCollisionMsg): Unit = { /* intentionally blank */ }
def handleGenericCollision(pkt: GenericCollisionMsg): Unit = {
player.BailProtection = false
val GenericCollisionMsg(ctype, p, _, _, pv, t, _, _, _, _, _, _) = pkt
if (pv.z * pv.z >= (pv.x * pv.x + pv.y * pv.y) * 0.5f) {
if (ops.heightTrend) {
ops.heightHistory = ops.heightLast
}
else {
ops.heightLast = ops.heightHistory
}
}
(ctype, sessionLogic.validObject(p, decorator = "GenericCollision/Primary")) match {
case (CollisionIs.BetweenThings, Some(v: Vehicle)) =>
v.Actor ! Vehicle.Deconstruct(Some(1 millisecond))
continent.GUID(t) match {
case Some(_: ForceDomePhysics) =>
player.Actor ! Player.Die()
case _ => ()
}
case (CollisionIs.BetweenThings, Some(_: Player)) =>
continent.GUID(t) match {
case Some(_: ForceDomePhysics) =>
player.Actor ! Player.Die()
case _ => ()
}
case _ => ()
}
}
def handleAvatarFirstTimeEvent(pkt: AvatarFirstTimeEventMessage): Unit = { /* intentionally blank */ }

View file

@ -40,7 +40,7 @@ class InteractWithForceDomeProtection
case Some(dome)
if dome.Perimeter.isEmpty ||
target.Zone != dome.Zone ||
!ForceDomeControl.TargetUnderForceDome(dome.Perimeter)(target, dome, maxDistance = 0f) =>
!ForceDomeControl.TargetUnderForceDome(dome.Perimeter)(dome, target, maxDistance = 0f) =>
resetInteraction(target)
case Some(_) =>
() //no action
@ -69,7 +69,7 @@ class InteractWithForceDomeProtection
case _ => None
}
.find { dome =>
ForceDomeControl.TargetUnderForceDome(dome.Perimeter)(target, dome, maxDistance = 0f)
ForceDomeControl.TargetUnderForceDome(dome.Perimeter)(dome, target, maxDistance = 0f)
}
.map { dome =>
applyProtection(target, dome)

View file

@ -43,7 +43,7 @@ object ArmorSiphonBehavior {
val after = item.Discharge()
if (before > after) {
v.Actor ! ArmorSiphonBehavior.Recharge(iguid)
PerformDamage(
PerformDamageIfVulnerable(
obj,
DamageInteraction(
VehicleSource(obj),

View file

@ -38,10 +38,7 @@ trait Damageable {
isVulnerable = false
case Vitality.Damage(damage_func) =>
val obj = DamageableObject
if (isVulnerable && obj.CanDamage) {
PerformDamage(obj, damage_func)
}
PerformDamageIfVulnerable(DamageableObject, damage_func)
}
/** a duplicate of the core implementation for the default mixin hook, for use in overriding */
@ -53,10 +50,20 @@ trait Damageable {
isVulnerable = false
case Vitality.Damage(damage_func) =>
val obj = DamageableObject
if (isVulnerable && obj.CanDamage) {
PerformDamage(obj, damage_func)
}
PerformDamageIfVulnerable(DamageableObject, damage_func)
}
/**
* Assess if the target is vulnerable to damage.
* If so, attempt damage calculations.
* @see `ResolutionCalculations.Output`
* @param obj the entity to be damaged
* @param applyDamageTo the function that applies the damage to the target in a target-tailored fashion
*/
def PerformDamageIfVulnerable(obj: Damageable.Target, applyDamageTo: ResolutionCalculations.Output): Unit = {
if (isVulnerable && obj.CanDamage) {
PerformDamage(obj, applyDamageTo)
}
}
/**

View file

@ -479,6 +479,8 @@ class ForceDomeControl(dome: ForceDomePhysics)
//dome activating
context.system.scheduler.scheduleOnce(delay = 1500 milliseconds, self, ForceDomeControl.Purge)
context.system.scheduler.scheduleOnce(delay = 4000 milliseconds, self, ForceDomeControl.ApplyProtection)
} else if (oldState && !newState) {
context.system.scheduler.scheduleOnce(delay = 1500 milliseconds, self, ForceDomeControl.RemoveProtection)
}
newState
case Some(state)

View file

@ -60,7 +60,7 @@ trait AffectedByAutomaticTurretFire extends Damageable {
ProjectileReason(DamageResolution.Hit, modProjectile, target.DamageModel),
correctedTargetPosition
)
PerformDamage(target, resolvedProjectile.calculate())
PerformDamageIfVulnerable(target, resolvedProjectile.calculate())
}
}
}