mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-19 18:14:44 +00:00
* diversified building management by injecting behavior; allocated entries for the intercontinental lattice and have begun connecting warp gate entities along the intercontinental lattice; beginnings of warp gate broadcast operations; disabled free merit commendations * allow transit across a predetermined warp gate path, i.e., proper zone-to-zone gating * game variables for modifying warp gate behaviors; moved choice of building game logic into overloaded constructor; only handle the capitol fore dome in more realistic conditions; warp gate state restored primarily b y internal game logic; changes to which and how gates are declared inactive or broadcast at startup * initial work on WarpgateLinkOverrideMessage, even if the packet doesn't seem to do anything; added basic service for rotating cavern zone locks via the galaxy messaging service; moved error checking for lattice connectedness * cavern closing warning messages queued * starting to set up ChatActor for /zlock command, and added /setbaseresources; conditions for correcting broadcast conditions of a locking warp gate pair; system for rotating through locking and unlocking cavern zones only uses two timers now and has an advance command that speeds to the next closing warning or cavern opening * expedited cavern rotations available via '/zonerotate' and '!zonerotate [-list]'; '/zonelock' should work for caverns, though distorting the rotation order to accommodate the cavern being unlocked; configuration arguments exist for the setup of cavern rotations and for the rotation itself * populated cavern lattice connections for a specific rotation order; warp gates will properly activate and deactivate and modify their neighborhood information based on which stage of the rotation; fed up with the blockmap going wrong; added a sanity test for the cavern lattice; Spiker damage calculation changes * adjusted local variable requirements of BuildingActor to integrate retained actors more closely with the Behavior; on the other hand, another value is passed around the logic * bug fixes observed from issues found in logs since 20220520; halved the spawn height when gating to a cavern warpgate * cavern benefits are now represented by enumeration classes rather than additive binary numbers; when facilities change state, benefits are evaluated; when caverns rotate, benefits are evaluated; cavern facility logic added; attempted handling for inventory disarray conditions (untested) * broke down tabs for easier navigation; added test to stop spawning of cavern equipment when not otherwise permitted * code comments, everywhere; correcting issues with cavern rotation timing reports * but is it flying?
182 lines
6.1 KiB
Scala
182 lines
6.1 KiB
Scala
// Copyright (c) 2019 PSForever
|
|
package net.psforever.objects
|
|
|
|
import net.psforever.objects.definition.{ObjectDefinition, VehicleDefinition}
|
|
import net.psforever.objects.serverobject.PlanetSideServerObject
|
|
import net.psforever.types.{PlanetSideGUID, Vector3}
|
|
|
|
import scala.collection.mutable
|
|
|
|
trait SpawnPoint {
|
|
psso: PlanetSideServerObject =>
|
|
|
|
/**
|
|
* An element of the contract of `PlanetSideServerObject`;
|
|
* but, this makes it visible to a `SpawnPoint` object without casting.
|
|
* @see `Identifiable.GUID`
|
|
*/
|
|
def GUID: PlanetSideGUID
|
|
|
|
/**
|
|
* An element of the contract of `PlanetSideServerObject`;
|
|
* but, this makes it visible to a `SpawnPoint` object without casting.
|
|
* @see `WorldEntity.GUID`
|
|
* @see `SpecificPoint`
|
|
*/
|
|
def Position: Vector3
|
|
|
|
/**
|
|
* An element of the contract of `PlanetSideServerObject`;
|
|
* but, this makes it visible to a `SpawnPoint` object without casting.
|
|
* @see `WorldEntity.GUID`
|
|
* @see `SpecificPoint`
|
|
*/
|
|
def Orientation: Vector3
|
|
|
|
/**
|
|
* An element of an unspoken contract with `Amenity`.
|
|
* While not all `SpawnPoint` objects will be `Amenity` objects, a subclass of the `PlanetSideServerObject` class,
|
|
* they will all promote having an object owner, or "parent."
|
|
* This should generally be themselves.
|
|
* @see `Amenity.Owner`
|
|
*/
|
|
def Owner: PlanetSideServerObject
|
|
|
|
/**
|
|
* An element of the contract of `PlanetSideServerObject`;
|
|
* but, this makes it visible to a `SpawnPoint` object without casting.
|
|
* @see `PlanetSideGameObject.Definition`
|
|
* @see `SpecificPoint`
|
|
*/
|
|
def Definition: ObjectDefinition with SpawnPointDefinition
|
|
|
|
def isOffline: Boolean = psso.Destroyed
|
|
|
|
/**
|
|
* Determine a specific position and orientation in which to spawn the target.
|
|
* @return a `Tuple` of `Vector3` objects;
|
|
* the first represents the game world position of spawning;
|
|
* the second represents the game world direction of spawning
|
|
*/
|
|
def SpecificPoint(target: PlanetSideGameObject): (Vector3, Vector3) = {
|
|
psso.Definition match {
|
|
case d: SpawnPointDefinition =>
|
|
d.SpecificPoint(this, target)
|
|
case _ =>
|
|
SpawnPoint.Default(this, target)
|
|
}
|
|
}
|
|
}
|
|
|
|
object SpawnPoint {
|
|
def Default(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = (obj.Position, obj.Orientation)
|
|
|
|
def Tube(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) =
|
|
(
|
|
obj.Position + Vector3.z(1.5f),
|
|
obj.Orientation.xy + Vector3.z(obj.Orientation.z + 90 % 360)
|
|
)
|
|
|
|
def AMS(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = {
|
|
//position the player alongside either of the AMS's terminals, facing away from it
|
|
val ori = obj.Orientation
|
|
val side = if (System.currentTimeMillis() % 2 == 0) 1 else -1 //right | left
|
|
val x = ori.x
|
|
val xsin = 3 * side * math.abs(math.sin(math.toRadians(x))).toFloat + 0.5f //sin because 0-degrees is up
|
|
val z = ori.z
|
|
val zrot = (z + 90) % 360
|
|
val zrad = math.toRadians(zrot)
|
|
val shift = Vector3(
|
|
math.sin(zrad).toFloat,
|
|
math.cos(zrad).toFloat,
|
|
0
|
|
) * (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)
|
|
}),
|
|
if (side == 1) {
|
|
Vector3.z(zrot)
|
|
} else {
|
|
Vector3.z((z - 90) % 360)
|
|
}
|
|
)
|
|
}
|
|
|
|
def Gate(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = {
|
|
obj.Definition match {
|
|
case d: SpawnPointDefinition =>
|
|
val ori = target.Orientation
|
|
val zrad = math.toRadians(ori.z)
|
|
val radius =
|
|
scala.math.random().toFloat * d.UseRadius / 2 + 20f //20 is definitely outside of the gating energy field
|
|
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 / 4 + 20f)
|
|
case _ =>
|
|
Vector3.Zero
|
|
}
|
|
(obj.Position + shift + altitudeShift, ori)
|
|
case _ =>
|
|
Default(obj, target)
|
|
}
|
|
}
|
|
|
|
def HalfHighGate(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = {
|
|
val (a, b) = Gate(obj, target)
|
|
target match {
|
|
case v: Vehicle if GlobalDefinitions.isFlightVehicle(v.Definition) =>
|
|
(a.xy + Vector3.z((target.Position.z + a.z) * 0.5f), b)
|
|
case _ =>
|
|
(a, b)
|
|
}
|
|
}
|
|
}
|
|
|
|
trait SpawnPointDefinition {
|
|
private var radius: Float = 0f //m
|
|
private var delay: Long = 0 //s
|
|
private var noWarp: Option[mutable.Set[VehicleDefinition]] = None
|
|
private var spawningFunc: (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3) = SpawnPoint.Default
|
|
|
|
def UseRadius: Float = radius
|
|
|
|
def UseRadius_=(rad: Float): Float = {
|
|
radius = rad
|
|
UseRadius
|
|
}
|
|
|
|
def Delay: Long = delay
|
|
|
|
def Delay_=(toDelay: Long): Long = {
|
|
delay = toDelay
|
|
Delay
|
|
}
|
|
|
|
def VehicleAllowance: Boolean = noWarp.isDefined
|
|
|
|
def VehicleAllowance_=(allow: Boolean): Boolean = {
|
|
if (allow && noWarp.isEmpty) {
|
|
noWarp = Some(mutable.Set.empty[VehicleDefinition])
|
|
} else if (!allow && noWarp.isDefined) {
|
|
noWarp = None
|
|
}
|
|
VehicleAllowance
|
|
}
|
|
|
|
def NoWarp: mutable.Set[VehicleDefinition] = {
|
|
noWarp.getOrElse(mutable.Set.empty[VehicleDefinition])
|
|
}
|
|
|
|
def SpecificPointFunc: (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3) = spawningFunc
|
|
|
|
def SpecificPointFunc_=(func: (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3)): Unit = {
|
|
spawningFunc = func
|
|
}
|
|
|
|
def SpecificPoint(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = spawningFunc(obj, target)
|
|
}
|