mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-03-23 22:29:10 +00:00
adding entity to represent force dome, and wiring force dome to capitol facility; touching the force dome while it is active causes death on both server and client
This commit is contained in:
parent
8f1badb862
commit
1d57cca1d3
8 changed files with 190 additions and 17 deletions
|
|
@ -14,6 +14,7 @@ import net.psforever.objects.equipment.Equipment
|
|||
import net.psforever.objects.inventory.Container
|
||||
import net.psforever.objects.serverobject.{CommonMessages, ServerObject}
|
||||
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.serverobject.generator.Generator
|
||||
import net.psforever.objects.serverobject.llu.CaptureFlag
|
||||
|
|
@ -26,11 +27,14 @@ 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.{OutfitInfo, OutfitRankNames, Initial, Unk1}
|
||||
import net.psforever.packet.game.OutfitEventAction.{Initial, OutfitInfo, OutfitRankNames, Unk1}
|
||||
import net.psforever.packet.game.{ActionCancelMessage, AvatarFirstTimeEventMessage, AvatarImplantMessage, AvatarJumpMessage, BattleplanMessage, BindPlayerMessage, BugReportMessage, ChangeFireModeMessage, ChangeShortcutBankMessage, CharacterCreateRequestMessage, CharacterRequestMessage, ChatMsg, CollisionIs, ConnectToWorldRequestMessage, CreateShortcutMessage, DeadState, DeployObjectMessage, DisplayedAwardMessage, DropItemMessage, EmoteMsg, FacilityBenefitShieldChargeRequestMessage, FriendsRequest, GenericAction, GenericActionMessage, GenericCollisionMsg, GenericObjectActionAtPositionMessage, GenericObjectActionMessage, GenericObjectStateMsg, HitHint, InvalidTerrainMessage, LootItemMessage, MoveItemMessage, ObjectDetectedMessage, ObjectHeldMessage, OutfitEvent, OutfitMemberEvent, OutfitMembershipRequest, OutfitMembershipResponse, OutfitRequest, OutfitRequestAction, PickupItemMessage, PlanetsideAttributeMessage, PlayerStateMessageUpstream, RequestDestroyMessage, TargetingImplantRequest, TerrainCondition, TradeMessage, UnuseItemMessage, UseItemMessage, VoiceHostInfo, VoiceHostRequest, ZipLineMessage}
|
||||
import net.psforever.services.RemoverActor
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
|
|
@ -538,7 +542,7 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
|
|||
|
||||
def handleGenericCollision(pkt: GenericCollisionMsg): Unit = {
|
||||
player.BailProtection = false
|
||||
val GenericCollisionMsg(ctype, p, _, _, pv, _, _, _, _, _, _, _) = pkt
|
||||
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
|
||||
|
|
@ -555,8 +559,22 @@ 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, _) =>
|
||||
log.warn("GenericCollision: CollisionIs.BetweenThings detected - no handling case")
|
||||
log.warn(s"GenericCollision: CollisionIs.BetweenThings detected - no handling case for obj id:${t.guid}")
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.dome.ForceDomePhysics
|
||||
import net.psforever.objects.serverobject.doors.Door
|
||||
import net.psforever.objects.serverobject.generator.Generator
|
||||
import net.psforever.objects.serverobject.interior.Sidedness.OutsideOf
|
||||
|
|
@ -29,11 +30,11 @@ 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.SourceEntry
|
||||
import net.psforever.objects.sourcing.{PlayerSource, SourceEntry}
|
||||
import net.psforever.objects.vehicles.Utility
|
||||
import net.psforever.objects.vital.Vitality
|
||||
import net.psforever.objects.vital.collision.{CollisionReason, CollisionWithReason}
|
||||
import net.psforever.objects.vital.etc.SuicideReason
|
||||
import net.psforever.objects.vital.etc.{ForceDomeExposure, SuicideReason}
|
||||
import net.psforever.objects.vital.interaction.DamageInteraction
|
||||
import net.psforever.objects.zones.{ZoneProjectile, Zoning}
|
||||
import net.psforever.packet.PlanetSideGamePacket
|
||||
|
|
@ -636,6 +637,21 @@ 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()
|
||||
)
|
||||
target.BailProtection = false
|
||||
player.BailProtection = false
|
||||
(None, None, false, Vector3.Zero)
|
||||
case (CollisionIs.BetweenThings, _) =>
|
||||
log.warn("GenericCollision: CollisionIs.BetweenThings detected - no handling case")
|
||||
(None, None, false, Vector3.Zero)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import net.psforever.objects.definition.converter._
|
|||
import net.psforever.objects.equipment._
|
||||
import net.psforever.objects.global.{GlobalDefinitionsAmmo, GlobalDefinitionsBuilding, GlobalDefinitionsDeployable, GlobalDefinitionsExoSuit, GlobalDefinitionsImplant, GlobalDefinitionsKit, GlobalDefinitionsMiscellaneous, GlobalDefinitionsProjectile, GlobalDefinitionsTool, GlobalDefinitionsVehicle}
|
||||
import net.psforever.objects.locker.LockerContainerDefinition
|
||||
import net.psforever.objects.serverobject.dome.ForceDomeDefinition
|
||||
import net.psforever.objects.serverobject.doors.DoorDefinition
|
||||
import net.psforever.objects.serverobject.generator.GeneratorDefinition
|
||||
import net.psforever.objects.serverobject.locks.IFFLockDefinition
|
||||
|
|
@ -1286,6 +1287,18 @@ object GlobalDefinitions {
|
|||
|
||||
val zipline = new GenericTeleportationDefinition(1047)
|
||||
|
||||
val force_dome_generator = new ForceDomeDefinition(322)
|
||||
|
||||
val force_dome_amp_physics = new ForceDomeDefinition(313)
|
||||
|
||||
val force_dome_comm_physics = new ForceDomeDefinition(316)
|
||||
|
||||
val force_dome_cryo_physics = new ForceDomeDefinition(319)
|
||||
|
||||
val force_dome_dsp_physics = new ForceDomeDefinition(321)
|
||||
|
||||
val force_dome_tech_physics = new ForceDomeDefinition(323)
|
||||
|
||||
/*
|
||||
Buildings
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
// Copyright (c) 2025 PSForever
|
||||
package net.psforever.objects.serverobject.dome
|
||||
|
||||
import net.psforever.objects.serverobject.structures.AmenityDefinition
|
||||
|
||||
class ForceDomeDefinition(objectId: Int)
|
||||
extends AmenityDefinition(objectId) {
|
||||
Name = "force_dome"
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) 2025 PSForever
|
||||
package net.psforever.objects.serverobject.dome
|
||||
|
||||
import net.psforever.objects.serverobject.structures.Amenity
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
class ForceDomePhysics(private val cfddef: ForceDomeDefinition)
|
||||
extends Amenity {
|
||||
private var energized: Boolean = false
|
||||
|
||||
def Energized: Boolean = energized
|
||||
|
||||
def Energized_=(state: Boolean): Boolean = {
|
||||
energized = state
|
||||
Energized
|
||||
}
|
||||
|
||||
def Definition: ForceDomeDefinition = cfddef
|
||||
}
|
||||
|
||||
object ForceDomePhysics {
|
||||
import akka.actor.ActorContext
|
||||
|
||||
/**
|
||||
* Instantiate and configure a `CapitolForceDome` object.
|
||||
* @param pos positon of the object in the zone's coordinate system
|
||||
* @param id the unique id that will be assigned to this entity
|
||||
* @param context a context to allow the object to properly set up `ActorSystem` functionality
|
||||
* @return the `CapitolForceDome` object
|
||||
*/
|
||||
def Constructor(pos: Vector3)(id: Int, context: ActorContext): ForceDomePhysics = {
|
||||
//import akka.actor.Props
|
||||
import net.psforever.objects.GlobalDefinitions
|
||||
|
||||
val obj = new ForceDomePhysics(GlobalDefinitions.force_dome_generator)
|
||||
obj.Position = pos
|
||||
//obj.Actor = context.actorOf(Props(classOf[null], obj), s"${GlobalDefinitions.door.Name}_$id")
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright (c) 2025 PSForever
|
||||
package net.psforever.objects.vital.etc
|
||||
|
||||
import net.psforever.objects.sourcing.{AmenitySource, SourceEntry}
|
||||
import net.psforever.objects.vital.{NoResistanceSelection, SimpleResolutions}
|
||||
import net.psforever.objects.vital.base.{DamageReason, DamageResolution}
|
||||
import net.psforever.objects.vital.damage.DamageCalculations
|
||||
import net.psforever.objects.vital.prop.DamageProperties
|
||||
import net.psforever.objects.vital.resolution.{DamageAndResistance, DamageResistanceModel}
|
||||
|
||||
/**
|
||||
* A wrapper for a "damage source" in damage calculations that indicates a harmful interaction from a capitol force dome.
|
||||
* @param field the target of the field in question
|
||||
*/
|
||||
final case class ForceDomeExposure(field: SourceEntry)
|
||||
extends DamageReason {
|
||||
def resolution: DamageResolution.Value = DamageResolution.Collision
|
||||
|
||||
def same(test: DamageReason): Boolean = test match {
|
||||
case eer: ForceDomeExposure => eer.field eq field
|
||||
case _ => false
|
||||
}
|
||||
|
||||
/**
|
||||
* Want to blame the capitol facility that is being protected.
|
||||
*/
|
||||
override def attribution: Int = field match {
|
||||
case a: AmenitySource => a.installation.Definition.ObjectId
|
||||
case _ => field.Definition.ObjectId
|
||||
}
|
||||
|
||||
/**
|
||||
* A direct connection to the damage information, numbers and properties.
|
||||
*/
|
||||
override def source: DamageProperties = ForceDomeExposure.damageProperties
|
||||
|
||||
/**
|
||||
* The functionality that is necessary for interaction of a vital game object with the rest of the hostile game world.
|
||||
*/
|
||||
override def damageModel: DamageAndResistance = ForceDomeExposure.drm
|
||||
|
||||
/**
|
||||
* The person to be blamed for this.
|
||||
*/
|
||||
override def adversary: Option[SourceEntry] = None
|
||||
}
|
||||
|
||||
object ForceDomeExposure {
|
||||
final val drm = new DamageResistanceModel {
|
||||
DamageUsing = DamageCalculations.AgainstExoSuit
|
||||
ResistUsing = NoResistanceSelection
|
||||
Model = SimpleResolutions.calculate
|
||||
}
|
||||
|
||||
final val damageProperties = new DamageProperties {
|
||||
Damage0 = 99999
|
||||
DamageToHealthOnly = true
|
||||
DamageToVehicleOnly = true
|
||||
DamageToBattleframeOnly = true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ final case class SuicideReason()
|
|||
eventually, they stop logging in.
|
||||
|
||||
Anyway, this has nothing to do with that.
|
||||
Most playes probably just want to jump to the next base over.
|
||||
Most players probably just want to jump to the next base over.
|
||||
*/
|
||||
def source: DamageProperties = SuicideReason.damageProperties
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import io.circe.parser._
|
|||
import net.psforever.objects.{GlobalDefinitions, LocalLockerItem, LocalProjectile}
|
||||
import net.psforever.objects.definition.BasicDefinition
|
||||
import net.psforever.objects.guid.selector.{NumberSelector, RandomSelector, SpecificSelector}
|
||||
import net.psforever.objects.serverobject.dome.ForceDomePhysics
|
||||
import net.psforever.objects.serverobject.doors.{Door, DoorDefinition, SpawnTubeDoor}
|
||||
import net.psforever.objects.serverobject.generator.Generator
|
||||
import net.psforever.objects.serverobject.llu.{CaptureFlagSocket, CaptureFlagSocketDefinition}
|
||||
|
|
@ -100,17 +101,9 @@ object Zones {
|
|||
"PathPoints"
|
||||
)(ZipLinePath.apply)
|
||||
|
||||
// monolith, hst, warpgate are ignored for now as the scala code isn't ready to handle them.
|
||||
// BFR terminals/doors are ignored as top level elements as sanctuaries have them with no associated building. (repair_silo also has this problem, but currently is ignored in the AmenityExtrator project)
|
||||
// Force domes have GUIDs but are currently classed as separate entities. The dome is controlled by sending GOAM 44 / 48 / 52 to the building GUID
|
||||
private val ignoredEntities = Seq(
|
||||
"monolith",
|
||||
"force_dome_dsp_physics",
|
||||
"force_dome_comm_physics",
|
||||
"force_dome_cryo_physics",
|
||||
"force_dome_tech_physics",
|
||||
"force_dome_amp_physics"
|
||||
)
|
||||
private val ignoredEntities = Seq("monolith")
|
||||
|
||||
private val towerTypes = Seq("tower_a", "tower_b", "tower_c")
|
||||
private val facilityTypes = Seq("amp_station", "cryo_facility", "comm_station", "comm_station_dsp", "tech_plant")
|
||||
|
|
@ -127,6 +120,13 @@ object Zones {
|
|||
"vt_spawn",
|
||||
"vt_vehicle"
|
||||
)
|
||||
private val forceDomeTypes = Seq(
|
||||
"force_dome_dsp_physics",
|
||||
"force_dome_comm_physics",
|
||||
"force_dome_cryo_physics",
|
||||
"force_dome_tech_physics",
|
||||
"force_dome_amp_physics"
|
||||
)
|
||||
private val cavernBuildingTypes = Seq(
|
||||
"ceiling_bldg_a",
|
||||
"ceiling_bldg_b",
|
||||
|
|
@ -380,11 +380,27 @@ object Zones {
|
|||
|
||||
createObjects(
|
||||
zoneMap,
|
||||
zoneObjects.filterNot { _.objectType.startsWith("bfr_") },
|
||||
zoneObjects.filterNot { obj => obj.objectType.startsWith("bfr_") || forceDomeTypes.contains(obj.objectType) },
|
||||
ownerGuid = 0,
|
||||
None,
|
||||
turretWeaponGuid
|
||||
)
|
||||
//force dome physics object are not owned
|
||||
//for our benefit, we can attach them as amenities to the zone's capitol facility
|
||||
zoneObjects
|
||||
.find { obj => forceDomeTypes.contains(obj.objectType) }
|
||||
.foreach { forceDome =>
|
||||
structures
|
||||
.find { structure => Building.Capitols.contains(structure.objectName) }
|
||||
.foreach { capitol =>
|
||||
zoneMap
|
||||
.addLocalObject(
|
||||
forceDome.guid,
|
||||
ForceDomePhysics.Constructor(forceDome.position),
|
||||
owningBuildingGuid = capitol.guid
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
lattice.asObject.get(mapid).foreach { obj =>
|
||||
obj.asArray.get.foreach { entry =>
|
||||
|
|
@ -710,7 +726,6 @@ object Zones {
|
|||
|
||||
case _ => ()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue