mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-19 18:44:45 +00:00
Gate Spawn Positions (#1004)
* changes to warp gate spawn positioning * added !suicide command; tried to add recovery from NoGUIDException * unnecessary imports * stop some times * integrated supervisory directives
This commit is contained in:
parent
a246fd1244
commit
9d2be17c1c
|
|
@ -508,6 +508,12 @@ class ChatActor(
|
|||
CavernRotationService.HurryNextRotation
|
||||
})
|
||||
|
||||
case (_, _, content) if content.startsWith("!suicide") =>
|
||||
//this is like CMT_SUICIDE but it ignores checks and forces a suicide state
|
||||
val tplayer = session.player
|
||||
tplayer.Revive
|
||||
tplayer.Actor ! Player.Die()
|
||||
|
||||
case _ =>
|
||||
// unknown ! commands are ignored
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import net.psforever.objects.ballistics._
|
|||
import net.psforever.objects.ce._
|
||||
import net.psforever.objects.definition._
|
||||
import net.psforever.objects.definition.converter.{CorpseConverter, DestroyedVehicleConverter}
|
||||
import net.psforever.objects.entity.{SimpleWorldEntity, WorldEntity}
|
||||
import net.psforever.objects.entity.{NoGUIDException, SimpleWorldEntity, WorldEntity}
|
||||
import net.psforever.objects.equipment._
|
||||
import net.psforever.objects.guid._
|
||||
import net.psforever.objects.inventory.{Container, GridInventory, InventoryItem}
|
||||
|
|
@ -293,31 +293,122 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
|
||||
override def supervisorStrategy: SupervisorStrategy = {
|
||||
import net.psforever.objects.inventory.InventoryDisarrayException
|
||||
import java.io.{StringWriter, PrintWriter}
|
||||
OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
|
||||
OneForOneStrategy(maxNrOfRetries = -1, withinTimeRange = 1 minute) {
|
||||
case nge: NoGUIDException =>
|
||||
nge.getEntity match {
|
||||
case p: Player =>
|
||||
continent.GUID(p.VehicleSeated) match {
|
||||
case Some(v: Vehicle) =>
|
||||
attemptRecoveryFromNoGuidExceptionAsVehicle(v, nge)
|
||||
case _ =>
|
||||
attemptRecoveryFromNoGuidExceptionAsPlayer(p, nge)
|
||||
}
|
||||
|
||||
case v: Vehicle =>
|
||||
attemptRecoveryFromNoGuidExceptionAsVehicle(v, nge)
|
||||
|
||||
case e: Equipment =>
|
||||
(
|
||||
player.Holsters().zipWithIndex.flatMap { case (o, i) =>
|
||||
o.Equipment match {
|
||||
case Some(e) => Some((player, InventoryItem(e, i)))
|
||||
case None => None
|
||||
}
|
||||
}.toList ++
|
||||
player.Inventory.Items.map { o => (player, o) } ++
|
||||
{
|
||||
player.FreeHand.Equipment match {
|
||||
case Some(o) => List((player, InventoryItem(e, Player.FreeHandSlot)))
|
||||
case _ => Nil
|
||||
}
|
||||
} ++
|
||||
(ValidObject(player.VehicleSeated) match {
|
||||
case Some(v: Vehicle) => v.Trunk.Items.map{ o => (v, o) }
|
||||
case _ => Nil
|
||||
})
|
||||
)
|
||||
.find { case (_, InventoryItem(o, _)) => o eq e } match {
|
||||
case Some((c: Container, InventoryItem(obj, index))) =>
|
||||
if (!obj.HasGUID) {
|
||||
c.Slot(index).Equipment = None
|
||||
}
|
||||
c match {
|
||||
case _: Player =>
|
||||
attemptRecoveryFromNoGuidExceptionAsPlayer(player, nge)
|
||||
case v: Vehicle =>
|
||||
if (v.PassengerInSeat(player).contains(0)) {
|
||||
attemptRecoveryFromNoGuidExceptionAsPlayer(player, nge)
|
||||
}
|
||||
SupervisorStrategy.resume
|
||||
case _ =>
|
||||
writeLogExceptionAndStop(nge)
|
||||
}
|
||||
case _ =>
|
||||
//did not discover or resolve the situation
|
||||
writeLogExceptionAndStop(nge)
|
||||
}
|
||||
|
||||
case _ =>
|
||||
SupervisorStrategy.resume
|
||||
}
|
||||
|
||||
case ide: InventoryDisarrayException =>
|
||||
attemptRecoverFromInventoryDisarrayException(ide.inventory)
|
||||
attemptRecoveryFromInventoryDisarrayException(ide.inventory)
|
||||
//re-evaluate results
|
||||
if (ide.inventory.ElementsOnGridMatchList() > 0) {
|
||||
val sw = new StringWriter
|
||||
ide.printStackTrace(new PrintWriter(sw))
|
||||
log.error(sw.toString)
|
||||
ImmediateDisconnect()
|
||||
SupervisorStrategy.stop
|
||||
writeLogExceptionAndStop(ide)
|
||||
} else {
|
||||
SupervisorStrategy.resume
|
||||
}
|
||||
|
||||
case e =>
|
||||
val sw = new StringWriter
|
||||
e.printStackTrace(new PrintWriter(sw))
|
||||
log.error(sw.toString)
|
||||
ImmediateDisconnect()
|
||||
SupervisorStrategy.stop
|
||||
writeLogExceptionAndStop(e)
|
||||
}
|
||||
}
|
||||
|
||||
def attemptRecoverFromInventoryDisarrayException(inv: GridInventory): Unit = {
|
||||
def attemptRecoveryFromNoGuidExceptionAsVehicle(v: Vehicle, e: Throwable): SupervisorStrategy.Directive = {
|
||||
val entry = v.Seats.find { case (_, s) => s.occupants.contains(player) }
|
||||
entry match {
|
||||
case Some((index, _)) =>
|
||||
player.VehicleSeated = None
|
||||
v.Seats(0).unmount(player)
|
||||
player.Position = v.Position
|
||||
player.Orientation = v.Orientation
|
||||
interstellarFerry = None
|
||||
interstellarFerryTopLevelGUID = None
|
||||
attemptRecoveryFromNoGuidExceptionAsPlayer(player, e)
|
||||
case None =>
|
||||
writeLogException(e)
|
||||
}
|
||||
}
|
||||
|
||||
def attemptRecoveryFromNoGuidExceptionAsPlayer(p: Player, e: Throwable): SupervisorStrategy.Directive = {
|
||||
if (p eq player) {
|
||||
val hasGUID = p.HasGUID
|
||||
zoneLoaded match {
|
||||
case Some(true) if hasGUID =>
|
||||
AvatarCreate() //this will probably work?
|
||||
SupervisorStrategy.resume
|
||||
case Some(false) =>
|
||||
RequestSanctuaryZoneSpawn(p, continent.Number)
|
||||
SupervisorStrategy.resume
|
||||
case None =>
|
||||
if (player.Zone eq Zone.Nowhere) {
|
||||
RequestSanctuaryZoneSpawn(p, continent.Number)
|
||||
} else {
|
||||
zoneReload = true
|
||||
LoadZoneAsPlayer(player, player.Zone.id)
|
||||
}
|
||||
SupervisorStrategy.resume
|
||||
case _ =>
|
||||
writeLogExceptionAndStop(e)
|
||||
}
|
||||
} else {
|
||||
SupervisorStrategy.resume
|
||||
}
|
||||
}
|
||||
|
||||
def attemptRecoveryFromInventoryDisarrayException(inv: GridInventory): Unit = {
|
||||
inv.ElementsInListCollideInGrid() match {
|
||||
case Nil => ;
|
||||
case overlaps =>
|
||||
|
|
@ -403,6 +494,20 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
}
|
||||
}
|
||||
|
||||
def writeLogException(e: Throwable): SupervisorStrategy.Directive = {
|
||||
import java.io.{PrintWriter, StringWriter}
|
||||
val sw = new StringWriter
|
||||
e.printStackTrace(new PrintWriter(sw))
|
||||
log.error(sw.toString)
|
||||
SupervisorStrategy.Resume
|
||||
}
|
||||
|
||||
def writeLogExceptionAndStop(e: Throwable): SupervisorStrategy.Directive = {
|
||||
writeLogException(e)
|
||||
ImmediateDisconnect()
|
||||
SupervisorStrategy.stop
|
||||
}
|
||||
|
||||
def session: Session = _session
|
||||
|
||||
def session_=(session: Session): Unit = {
|
||||
|
|
|
|||
|
|
@ -1334,7 +1334,7 @@ object GlobalDefinitions {
|
|||
|
||||
val hst = new WarpGateDefinition(402)
|
||||
hst.Name = "hst"
|
||||
hst.UseRadius = 64.96882005f
|
||||
hst.UseRadius = 44.96882005f
|
||||
hst.SOIRadius = 82
|
||||
hst.VehicleAllowance = true
|
||||
hst.NoWarp += dropship
|
||||
|
|
@ -1346,28 +1346,28 @@ object GlobalDefinitions {
|
|||
hst.NoWarp += colossus_flight
|
||||
hst.NoWarp += peregrine_gunner
|
||||
hst.NoWarp += peregrine_flight
|
||||
hst.SpecificPointFunc = SpawnPoint.SmallGate(innerRadius = 5f)
|
||||
hst.SpecificPointFunc = SpawnPoint.CavernGate(innerRadius = 6f)
|
||||
|
||||
val warpgate = new WarpGateDefinition(993)
|
||||
warpgate.Name = "warpgate"
|
||||
warpgate.UseRadius = 67.81070029f //301.8713f
|
||||
warpgate.SOIRadius = 302
|
||||
warpgate.UseRadius = 67.81070029f
|
||||
warpgate.SOIRadius = 302 //301.8713f
|
||||
warpgate.VehicleAllowance = true
|
||||
warpgate.SpecificPointFunc = SpawnPoint.Gate
|
||||
|
||||
val warpgate_cavern = new WarpGateDefinition(994)
|
||||
warpgate_cavern.Name = "warpgate_cavern"
|
||||
warpgate_cavern.UseRadius = 20.72639434f
|
||||
warpgate_cavern.SOIRadius = 52
|
||||
warpgate_cavern.UseRadius = 19.72639434f
|
||||
warpgate_cavern.SOIRadius = 41
|
||||
warpgate_cavern.VehicleAllowance = true
|
||||
warpgate_cavern.SpecificPointFunc = SpawnPoint.CavernGate
|
||||
warpgate_cavern.SpecificPointFunc = SpawnPoint.CavernGate(innerRadius = 4.5f)
|
||||
|
||||
val warpgate_small = new WarpGateDefinition(995)
|
||||
warpgate_small.Name = "warpgate_small"
|
||||
warpgate_small.UseRadius = 69.03687655f
|
||||
warpgate_small.SOIRadius = 103
|
||||
warpgate_small.VehicleAllowance = true
|
||||
warpgate_small.SpecificPointFunc = SpawnPoint.SmallGate(innerRadius = 27.60654127f)
|
||||
warpgate_small.SpecificPointFunc = SpawnPoint.SmallGate(innerRadius = 27.60654127f, flightlessZOffset = 0.5f)
|
||||
|
||||
val bunker_gauntlet = new BuildingDefinition(150) { Name = "bunker_gauntlet" }
|
||||
val bunker_lg = new BuildingDefinition(151) { Name = "bunker_lg" }
|
||||
|
|
@ -1581,7 +1581,7 @@ object GlobalDefinitions {
|
|||
def isMaxArms(tdef: ToolDefinition): Boolean = {
|
||||
tdef match {
|
||||
case `trhev_dualcycler` | `nchev_scattercannon` | `vshev_quasar` | `trhev_pounder` | `nchev_falcon` |
|
||||
`vshev_comet` | `trhev_burster` | `nchev_sparrow` | `vshev_starfire` =>
|
||||
`vshev_comet` | `trhev_burster` | `nchev_sparrow` | `vshev_starfire` =>
|
||||
true
|
||||
case _ =>
|
||||
false
|
||||
|
|
@ -1691,13 +1691,13 @@ object GlobalDefinitions {
|
|||
def isFactionWeapon(edef: EquipmentDefinition): PlanetSideEmpire.Value = {
|
||||
edef match {
|
||||
case `chainblade` | `repeater` | `anniversary_guna` | `cycler` | `mini_chaingun` | `striker` |
|
||||
`trhev_dualcycler` | `trhev_pounder` | `trhev_burster` =>
|
||||
`trhev_dualcycler` | `trhev_pounder` | `trhev_burster` =>
|
||||
PlanetSideEmpire.TR
|
||||
case `magcutter` | `isp` | `anniversary_gun` | `gauss` | `r_shotgun` | `hunterseeker` | `nchev_scattercannon` |
|
||||
`nchev_falcon` | `nchev_sparrow` =>
|
||||
`nchev_falcon` | `nchev_sparrow` =>
|
||||
PlanetSideEmpire.NC
|
||||
case `forceblade` | `beamer` | `anniversary_gunb` | `pulsar` | `lasher` | `lancer` | `vshev_quasar` |
|
||||
`vshev_comet` | `vshev_starfire` =>
|
||||
`vshev_comet` | `vshev_starfire` =>
|
||||
PlanetSideEmpire.VS
|
||||
case _ =>
|
||||
PlanetSideEmpire.NEUTRAL
|
||||
|
|
@ -1713,16 +1713,16 @@ object GlobalDefinitions {
|
|||
def isFactionEquipment(edef: EquipmentDefinition): PlanetSideEmpire.Value = {
|
||||
edef match {
|
||||
case `chainblade` | `repeater` | `anniversary_guna` | `cycler` | `mini_chaingun` | `striker` |
|
||||
`striker_missile_ammo` | `trhev_dualcycler` | `trhev_pounder` | `trhev_burster` | `dualcycler_ammo` |
|
||||
`pounder_ammo` | `burster_ammo` =>
|
||||
`striker_missile_ammo` | `trhev_dualcycler` | `trhev_pounder` | `trhev_burster` | `dualcycler_ammo` |
|
||||
`pounder_ammo` | `burster_ammo` =>
|
||||
PlanetSideEmpire.TR
|
||||
case `magcutter` | `isp` | `anniversary_gun` | `gauss` | `r_shotgun` | `hunterseeker` | `hunter_seeker_missile` |
|
||||
`nchev_scattercannon` | `nchev_falcon` | `nchev_sparrow` | `scattercannon_ammo` | `falcon_ammo` |
|
||||
`sparrow_ammo` =>
|
||||
`nchev_scattercannon` | `nchev_falcon` | `nchev_sparrow` | `scattercannon_ammo` | `falcon_ammo` |
|
||||
`sparrow_ammo` =>
|
||||
PlanetSideEmpire.NC
|
||||
case `forceblade` | `beamer` | `anniversary_gunb` | `pulsar` | `lasher` | `lancer` | `energy_cell` |
|
||||
`lancer_cartridge` | `vshev_quasar` | `vshev_comet` | `vshev_starfire` | `quasar_ammo` | `comet_ammo` |
|
||||
`starfire_ammo` =>
|
||||
`lancer_cartridge` | `vshev_quasar` | `vshev_comet` | `vshev_starfire` | `quasar_ammo` | `comet_ammo` |
|
||||
`starfire_ammo` =>
|
||||
PlanetSideEmpire.VS
|
||||
case _ =>
|
||||
PlanetSideEmpire.NEUTRAL
|
||||
|
|
@ -1905,7 +1905,7 @@ object GlobalDefinitions {
|
|||
def isFlightVehicle(vdef: VehicleDefinition): Boolean = {
|
||||
vdef match {
|
||||
case `mosquito` | `lightgunship` | `wasp` | `liberator` | `vulture` | `phantasm` | `lodestar` | `dropship` |
|
||||
`galaxy_gunship` =>
|
||||
`galaxy_gunship` =>
|
||||
true
|
||||
case _ =>
|
||||
false
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package net.psforever.objects
|
|||
|
||||
import net.psforever.objects.definition.{ObjectDefinition, VehicleDefinition}
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.serverobject.mount.MountableEntity
|
||||
import net.psforever.types.{PlanetSideGUID, Vector3}
|
||||
|
||||
import scala.collection.mutable
|
||||
|
|
@ -93,10 +94,10 @@ object SpawnPoint {
|
|||
) * (3 * side).toFloat //x=sin, y=cos because compass-0 is East, not North
|
||||
(
|
||||
obj.Position + shift + (if (x >= 330) { //ams leaning to the left
|
||||
Vector3.z(xsin)
|
||||
} else { //ams leaning to the right
|
||||
Vector3.z(-xsin)
|
||||
}),
|
||||
Vector3.z(xsin)
|
||||
} else { //ams leaning to the right
|
||||
Vector3.z(-xsin)
|
||||
}),
|
||||
if (side == 1) {
|
||||
Vector3.z(zrot)
|
||||
} else {
|
||||
|
|
@ -111,8 +112,8 @@ object SpawnPoint {
|
|||
val ori = target.Orientation
|
||||
val zrad = math.toRadians(ori.z)
|
||||
val radius =
|
||||
scala.math.random().toFloat * (d.UseRadius - innerRadius) + innerRadius
|
||||
val shift = Vector3(math.sin(zrad).toFloat, math.cos(zrad).toFloat, 0) * radius
|
||||
scala.math.random().toFloat * 0.5f * (d.UseRadius - innerRadius) + innerRadius
|
||||
val shift = Vector3(math.sin(zrad).toFloat, math.cos(zrad).toFloat, 0) * radius
|
||||
val altitudeShift = target.Definition match {
|
||||
case vdef: VehicleDefinition if GlobalDefinitions.isFlightVehicle(vdef) =>
|
||||
Vector3.z(scala.math.random().toFloat * d.UseRadius)
|
||||
|
|
@ -136,23 +137,26 @@ object SpawnPoint {
|
|||
)
|
||||
}
|
||||
|
||||
def CavernGate(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = {
|
||||
val (a, b) = metaGate(obj, target, innerRadius = 5f)
|
||||
def CavernGate(innerRadius: Float)(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = {
|
||||
val (a, b) = metaGate(obj, target, innerRadius)
|
||||
target match {
|
||||
case v: Vehicle if GlobalDefinitions.isFlightVehicle(v.Definition) =>
|
||||
(a.xy + Vector3.z((target.Position.z + a.z) * 0.5f), b)
|
||||
case m: MountableEntity =>
|
||||
m.BailProtection = true
|
||||
(a + Vector3.z(obj.Definition.UseRadius * 0.5f), b)
|
||||
case _ =>
|
||||
(a + Vector3.z(value = 3f), b)
|
||||
(a, b)
|
||||
}
|
||||
}
|
||||
|
||||
def SmallGate(innerRadius: Float)(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = {
|
||||
def SmallGate(innerRadius: Float, flightlessZOffset: Float)(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = {
|
||||
val (a, b) = metaGate(obj, target, innerRadius)
|
||||
target match {
|
||||
case v: Vehicle if GlobalDefinitions.isFlightVehicle(v.Definition) =>
|
||||
(a.xy + Vector3.z((target.Position.z + a.z) * 0.5f), b)
|
||||
case _ =>
|
||||
(a + Vector3.z(value = 0.5f), b)
|
||||
(a + Vector3.z(flightlessZOffset), b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue