diff --git a/src/main/scala/net/psforever/objects/GlobalDefinitions.scala b/src/main/scala/net/psforever/objects/GlobalDefinitions.scala index ad5bfc40c..9d04fcf12 100644 --- a/src/main/scala/net/psforever/objects/GlobalDefinitions.scala +++ b/src/main/scala/net/psforever/objects/GlobalDefinitions.scala @@ -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" } diff --git a/src/main/scala/net/psforever/objects/SpawnPoint.scala b/src/main/scala/net/psforever/objects/SpawnPoint.scala index 30bd138c9..3a762c683 100644 --- a/src/main/scala/net/psforever/objects/SpawnPoint.scala +++ b/src/main/scala/net/psforever/objects/SpawnPoint.scala @@ -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) } } } diff --git a/src/main/scala/net/psforever/objects/zones/MapInfo.scala b/src/main/scala/net/psforever/objects/zones/MapInfo.scala index c5c19dff7..8bab99216 100644 --- a/src/main/scala/net/psforever/objects/zones/MapInfo.scala +++ b/src/main/scala/net/psforever/objects/zones/MapInfo.scala @@ -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 diff --git a/src/main/scala/net/psforever/objects/zones/blockmap/BlockMap.scala b/src/main/scala/net/psforever/objects/zones/blockmap/BlockMap.scala index 7cc1c2e81..f63a10c7a 100644 --- a/src/main/scala/net/psforever/objects/zones/blockmap/BlockMap.scala +++ b/src/main/scala/net/psforever/objects/zones/blockmap/BlockMap.scala @@ -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]() + } + } } diff --git a/src/main/scala/net/psforever/objects/zones/blockmap/BlockMapEntity.scala b/src/main/scala/net/psforever/objects/zones/blockmap/BlockMapEntity.scala index ef33dfcf3..c3d09eb0a 100644 --- a/src/main/scala/net/psforever/objects/zones/blockmap/BlockMapEntity.scala +++ b/src/main/scala/net/psforever/objects/zones/blockmap/BlockMapEntity.scala @@ -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 diff --git a/src/main/scala/net/psforever/objects/zones/blockmap/Sector.scala b/src/main/scala/net/psforever/objects/zones/blockmap/Sector.scala index 1a605e33b..126f7d35b 100644 --- a/src/main/scala/net/psforever/objects/zones/blockmap/Sector.scala +++ b/src/main/scala/net/psforever/objects/zones/blockmap/Sector.scala @@ -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. diff --git a/src/main/scala/net/psforever/util/PointOfInterest.scala b/src/main/scala/net/psforever/util/PointOfInterest.scala index 4c04f4d92..ae841fe5e 100644 --- a/src/main/scala/net/psforever/util/PointOfInterest.scala +++ b/src/main/scala/net/psforever/util/PointOfInterest.scala @@ -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),