Spawn Update (#1002)

* changes to spawn point selection for warp gates; updating coordinates for a few /warp destinations; just block map things

* additional securities against wrong blockmap domain
This commit is contained in:
Fate-JH 2022-06-24 22:07:44 -04:00 committed by GitHub
parent ced228509c
commit 229777559f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 106 additions and 35 deletions

View file

@ -1334,8 +1334,8 @@ object GlobalDefinitions {
val hst = new WarpGateDefinition(402)
hst.Name = "hst"
hst.UseRadius = 20.4810f
hst.SOIRadius = 21
hst.UseRadius = 64.96882005f
hst.SOIRadius = 82
hst.VehicleAllowance = true
hst.NoWarp += dropship
hst.NoWarp += galaxy_gunship
@ -1346,28 +1346,28 @@ object GlobalDefinitions {
hst.NoWarp += colossus_flight
hst.NoWarp += peregrine_gunner
hst.NoWarp += peregrine_flight
hst.SpecificPointFunc = SpawnPoint.Gate
hst.SpecificPointFunc = SpawnPoint.SmallGate(innerRadius = 5f)
val warpgate = new WarpGateDefinition(993)
warpgate.Name = "warpgate"
warpgate.UseRadius = 301.8713f
warpgate.UseRadius = 67.81070029f //301.8713f
warpgate.SOIRadius = 302
warpgate.VehicleAllowance = true
warpgate.SpecificPointFunc = SpawnPoint.Gate
val warpgate_cavern = new WarpGateDefinition(994)
warpgate_cavern.Name = "warpgate_cavern"
warpgate_cavern.UseRadius = 51.0522f
warpgate_cavern.UseRadius = 20.72639434f
warpgate_cavern.SOIRadius = 52
warpgate_cavern.VehicleAllowance = true
warpgate_cavern.SpecificPointFunc = SpawnPoint.HalfHighGate
warpgate_cavern.SpecificPointFunc = SpawnPoint.CavernGate
val warpgate_small = new WarpGateDefinition(995)
warpgate_small.Name = "warpgate_small"
warpgate_small.UseRadius = 103f
warpgate_small.UseRadius = 69.03687655f
warpgate_small.SOIRadius = 103
warpgate_small.VehicleAllowance = true
warpgate_small.SpecificPointFunc = SpawnPoint.Gate
warpgate_small.SpecificPointFunc = SpawnPoint.SmallGate(innerRadius = 27.60654127f)
val bunker_gauntlet = new BuildingDefinition(150) { Name = "bunker_gauntlet" }
val bunker_lg = new BuildingDefinition(151) { Name = "bunker_lg" }

View file

@ -105,17 +105,17 @@ object SpawnPoint {
)
}
def Gate(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = {
private def metaGate(obj: SpawnPoint, target: PlanetSideGameObject, innerRadius: Float): (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
scala.math.random().toFloat * (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 / 4 + 20f)
Vector3.z(scala.math.random().toFloat * d.UseRadius)
case _ =>
Vector3.Zero
}
@ -125,13 +125,34 @@ object SpawnPoint {
}
}
def HalfHighGate(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = {
val (a, b) = Gate(obj, target)
def Gate(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = {
val (pos, ori) = metaGate(obj, target, innerRadius = 10f)
(
target.Definition match {
case vdef: VehicleDefinition if GlobalDefinitions.isFlightVehicle(vdef) => pos
case _ => pos + Vector3.z(value = 9.328125f)
},
ori
)
}
def CavernGate(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = {
val (a, b) = metaGate(obj, target, innerRadius = 5f)
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)
(a + Vector3.z(value = 3f), b)
}
}
def SmallGate(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 _ =>
(a + Vector3.z(value = 0.5f), b)
}
}
}

View file

@ -353,7 +353,7 @@ case object MapInfo extends StringEnum[MapInfo] {
value = "ugd03",
checksum = 1673539651L,
scale = MapScale.Dim2048,
environment = List(SeaLevel(EnvironmentAttribute.Death, 30)) //not actually lava, but a kill plane if you fall beneath the map
environment = List(SeaLevel(EnvironmentAttribute.Death, 10)) //not actually lava, but a kill plane if you fall beneath the map
)
case object Ugd04
@ -361,7 +361,7 @@ case object MapInfo extends StringEnum[MapInfo] {
value = "ugd04",
checksum = 3797992164L,
scale = MapScale.Dim2048,
environment = List(SeaLevel(EnvironmentAttribute.Death, 51.215f)) //ADB: 51.414f
environment = List(SeaLevel(EnvironmentAttribute.Death, 51f)) //ADB: 51.414f
)
case object Ugd05
@ -377,7 +377,7 @@ case object MapInfo extends StringEnum[MapInfo] {
value = "ugd06",
checksum = 4274683970L,
scale = MapScale.Dim2560,
environment = List(SeaLevel(EnvironmentAttribute.Death, 55)) //not actually lava, but a kill plane if you fall beneath the map
environment = List(SeaLevel(EnvironmentAttribute.Death, 30)) //not actually lava, but a kill plane if you fall beneath the map
)
case object Map96

View file

@ -62,8 +62,10 @@ class BlockMap(fullMapWidth: Int, fullMapHeight: Int, desiredSpanSize: Int) {
*/
def sector(entity: BlockMapEntity): SectorPopulation = {
entity.blockMapEntry match {
case Some(entry) => BlockMap.quickToSectorGroup(entry.sectors.map { blocks })
case None => SectorGroup(Nil)
case Some(entry) =>
BlockMap.quickToSectorGroup(BlockMap.sectorsOnlyWithinBlockStructure(entry.sectors, entry.map.blocks))
case None =>
SectorGroup(Nil)
}
}
@ -78,8 +80,9 @@ class BlockMap(fullMapWidth: Int, fullMapHeight: Int, desiredSpanSize: Int) {
*/
def sector(p: Vector3, range: Float): SectorPopulation = {
val indices = BlockMap.findSectorIndices(blockMap = this, p, range)
if (indices.max < blocks.size) {
BlockMap.quickToSectorGroup(range, indices.map { blocks } )
BlockMap.quickToSectorGroup(range, BlockMap.sectorsOnlyWithinBlockStructure(indices, blocks) )
} else {
SectorGroup(Nil)
}
@ -146,9 +149,9 @@ class BlockMap(fullMapWidth: Int, fullMapHeight: Int, desiredSpanSize: Int) {
*/
def addTo(target: BlockMapEntity, toPosition: Vector3, rangeX: Float, rangeY: Float): SectorPopulation = {
val to = BlockMap.findSectorIndices(blockMap = this, toPosition, rangeX, rangeY)
val toSectors = to.toSet.map { blocks }
val toSectors = BlockMap.sectorsOnlyWithinBlockStructure(to, blocks)
toSectors.foreach { block => block.addTo(target) }
target.blockMapEntry = Some(BlockMapEntry(toPosition, rangeX, rangeY, to.toSet))
target.blockMapEntry = Some(BlockMapEntry(this, toPosition, rangeX, rangeY, to.toSet))
BlockMap.quickToSectorGroup(rangeX, rangeY, toSectors)
}
@ -220,7 +223,7 @@ class BlockMap(fullMapWidth: Int, fullMapHeight: Int, desiredSpanSize: Int) {
target.blockMapEntry match {
case Some(entry) =>
target.blockMapEntry = None
val from = entry.sectors.map { blocks }
val from = BlockMap.sectorsOnlyWithinBlockStructure(entry.sectors, entry.map.blocks)
from.foreach { block => block.removeFrom(target) }
BlockMap.quickToSectorGroup(rangeX, rangeY, from)
case None =>
@ -293,10 +296,10 @@ class BlockMap(fullMapWidth: Int, fullMapHeight: Int, desiredSpanSize: Int) {
case Some(entry) =>
val from = entry.sectors
val to = BlockMap.findSectorIndices(blockMap = this, toPosition, rangeX, rangeY).toSet
to.diff(from).foreach { index => blocks(index).addTo(target) }
from.diff(to).foreach { index => blocks(index).removeFrom(target) }
target.blockMapEntry = Some(BlockMapEntry(toPosition, rangeX, rangeY, to))
BlockMap.quickToSectorGroup(rangeX, rangeY, to.map { blocks })
to.diff(from).foreach { index => BlockMap.sectorOnlyWithinBlockStructure(index, blocks).addTo(target) }
from.diff(to).foreach { index => BlockMap.sectorOnlyWithinBlockStructure(index, entry.map.blocks).removeFrom(target) }
target.blockMapEntry = Some(BlockMapEntry(this, toPosition, rangeX, rangeY, to))
BlockMap.quickToSectorGroup(rangeX, rangeY, BlockMap.sectorsOnlyWithinBlockStructure(to, blocks))
case None =>
SectorGroup(Nil)
}
@ -482,4 +485,40 @@ object BlockMap {
SectorGroup(rangeX, rangeY, to)
}
}
/**
* Find a blockmap sector that most closely corresponds to the index.
* @see `sectorsOnlyWithinBlockStructure`
* @param index the index of the sector
* @param structure the collection of sectors
* @return the sector at the index position, or a blank sector
*/
private def sectorOnlyWithinBlockStructure(
index: Int,
structure: Iterable[Sector]
): Sector = {
if (index < structure.size) {
structure.toSeq(index)
} else {
Sector.Empty
}
}
/**
* Find a collection of blockmap sectors that most closely corresponds to the indices.
* @see `sectorOnlyWithinBlockStructure`
* @param list the indices of sectors
* @param structure the collection of sectors
* @return the collection of sectors at the index positions, or a blank collection
*/
private def sectorsOnlyWithinBlockStructure(
list: Iterable[Int],
structure: Iterable[Sector]
): Iterable[Sector] = {
if (list.max < structure.size) {
list.toSet.map { structure.toSeq }
} else {
List[Sector]()
}
}
}

View file

@ -5,7 +5,7 @@ import net.psforever.objects.entity.WorldEntity
import net.psforever.objects.zones.Zone
import net.psforever.types.Vector3
sealed case class BlockMapEntry(coords: Vector3, rangeX: Float, rangeY: Float, sectors: Set[Int])
sealed case class BlockMapEntry(map: BlockMap, coords: Vector3, rangeX: Float, rangeY: Float, sectors: Set[Int])
/**
* An game object that can be represented on a blockmap.
@ -71,8 +71,8 @@ object BlockMapEntity {
* @param sectors the indices of sectors on the blockmap
* @return a `BlockMapEntry` entity
*/
def apply(coords: Vector3, range: Float, sectors: Set[Int]): BlockMapEntry =
BlockMapEntry(coords, range, range, sectors)
def apply(blocks: BlockMap, coords: Vector3, range: Float, sectors: Set[Int]): BlockMapEntry =
BlockMapEntry(blocks, coords, range, range, sectors)
/**
* The entity is currently excluded from being represented on a blockmap structure.
@ -97,7 +97,9 @@ object BlockMapEntity {
private def updateBlockMap(target: BlockMapEntity, newCoords: Vector3): Boolean = {
target.blockMapEntry match {
case Some(oldEntry) =>
target.blockMapEntry = Some(BlockMapEntry(newCoords, oldEntry.rangeX, oldEntry.rangeY, oldEntry.sectors))
target.blockMapEntry = Some(
BlockMapEntry(oldEntry.map, newCoords, oldEntry.rangeX, oldEntry.rangeY, oldEntry.sectors)
)
true
case None =>
false

View file

@ -239,6 +239,15 @@ class Sector(val longitude: Int, val latitude: Int, val span: Int)
}
}
object Sector {
/**
* An sector that is empty forever.
*/
final val Empty = new Sector(longitude = 0, latitude = 0, span = 0) {
override def addTo(o : BlockMapEntity): Boolean = false
}
}
/**
* The specific datastructure that is mentioned when using the term "sector conglomerate".
* Typically used to compose the lists of entities from various individual sectors.

View file

@ -532,7 +532,7 @@ object PointOfInterest {
"geowarp1" -> Vector3(902, 1811, 93),
"geowarp2" -> Vector3(185, 922, 113),
"geowarp3" -> Vector3(1696, 1188, 92),
"geowarp4" -> Vector3(887, 227, 115)
"geowarp4" -> Vector3(887, 218, 117)
)
zones("c5").gates ++= Map(
"geowarp1" -> Vector3(1195, 1752, 244),
@ -541,10 +541,10 @@ object PointOfInterest {
"geowarp4" -> Vector3(1042, 225, 246)
)
zones("c6").gates ++= Map(
"geowarp1" -> Vector3(1067, 2044, 95),
"geowarp1" -> Vector3(1066, 2053, 97),
"geowarp2" -> Vector3(290, 693, 73),
"geowarp3" -> Vector3(1922, 928, 33),
"geowarp4" -> Vector3(1174, 249, 114)
"geowarp4" -> Vector3(1172, 249, 114)
)
zones("i3").gates ++= Map(
"gate1" -> Vector3(1219, 2580, 30),