diff --git a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala index d52d183bc..924c14ce3 100644 --- a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala +++ b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala @@ -1039,14 +1039,12 @@ object GlobalDefinitions { val warpgate : ObjectDefinition with SpawnPointDefinition = new ObjectDefinition(993) with SpawnPointDefinition warpgate.Name = "warpgate" warpgate.UseRadius = 301.8713f - warpgate.Delay = 10 warpgate.VehicleAllowance = true warpgate.SpecificPointFunc = SpawnPoint.Gate val hst : ObjectDefinition with SpawnPointDefinition = new ObjectDefinition(402) with SpawnPointDefinition hst.Name = "hst" hst.UseRadius = 20.4810f - hst.Delay = 10 hst.VehicleAllowance = true hst.NoWarp += dropship hst.NoWarp += galaxy_gunship @@ -1062,7 +1060,6 @@ object GlobalDefinitions { val warpgate_cavern : ObjectDefinition with SpawnPointDefinition = new ObjectDefinition(994) with SpawnPointDefinition warpgate_cavern.Name = "warpgate_cavern" warpgate_cavern.UseRadius = 55.0522f - warpgate_cavern.Delay = 10 warpgate_cavern.VehicleAllowance = true warpgate_cavern.SpecificPointFunc = SpawnPoint.Gate diff --git a/common/src/main/scala/net/psforever/objects/serverobject/structures/WarpGate.scala b/common/src/main/scala/net/psforever/objects/serverobject/structures/WarpGate.scala index eca8a29f0..25a2255dd 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/structures/WarpGate.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/structures/WarpGate.scala @@ -9,11 +9,15 @@ import net.psforever.objects.zones.Zone import net.psforever.packet.game.{Additional1, Additional2, Additional3, PlanetSideGeneratorState} import net.psforever.types.{PlanetSideEmpire, Vector3} +import scala.collection.mutable + class WarpGate(building_guid : Int, map_id : Int, zone : Zone, buildingDefinition : ObjectDefinition with SpawnPointDefinition) extends Building(building_guid, map_id, zone, StructureType.WarpGate, buildingDefinition) with SpawnPoint { + /** can this building be used as an active warp gate */ private var active : Boolean = true - private var broadcast : Boolean = false + /** what faction views this warp gate as a broadcast gate */ + private var broadcast : mutable.Set[PlanetSideEmpire.Value] = mutable.Set.empty[PlanetSideEmpire.Value] override def Info : ( Int, @@ -48,18 +52,105 @@ class WarpGate(building_guid : Int, map_id : Int, zone : Zone, buildingDefinitio ) } + /** + * If a warp gate is active, it can be used to transport faction-affiliated forces between other gates. + * For transportation of faction-opposed forces, use broadcast logic for that faction. + * @return `true`, if the warp gate can be used for transport; + * `false`, otherwise + */ def Active : Boolean = active + /** + * Control whether a warp gate is usable for transporting faction-affiliated forces between other gates. + * @param state `true`, to activate the gate; + * `false`, otherwise + * @return `true`, if the gate is active; + * `false`, otherwise + */ def Active_=(state : Boolean) : Boolean = { active = state Active } - def Broadcast : Boolean = Active && broadcast + /** + * Determine whether any faction interacts with this warp gate as "broadcast." + * The gate must be active first. + * @return `true`, if some faction sees this warp gate as a "broadcast gate"; + * `false`, otherwise + */ + def Broadcast : Boolean = Active && broadcast.nonEmpty - def Broadcast_=(cast : Boolean) : Boolean = { - broadcast = cast - Broadcast + /** + * Determine whether a specific faction interacts with this warp gate as "broadcast." + * The warp gate being `NEUTRAL` should allow for any polled faction to interact. + * The gate must be active first. + * @return `true`, if the given faction interacts with this warp gate as a "broadcast gate"; + * `false`, otherwise + */ + def Broadcast(faction : PlanetSideEmpire.Value) : Boolean = { + Active && (broadcast.contains(faction) || broadcast.contains(PlanetSideEmpire.NEUTRAL)) + } + + /** + * Toggle whether the warp gate's faction-affiliated force interacts with this warp gate as "broadcast." + * Other "broadcast" associations are not affected. + * The gate must be active first. + * @param bcast `true`, if the faction-affiliated force interacts with this gate as broadcast; + * `false`, if not + * @return the set of all factions who interact with this warp gate as "broadcast" + */ + def Broadcast_=(bcast : Boolean) : Set[PlanetSideEmpire.Value] = { + if(Active) { + if(bcast) { + broadcast += Faction + } + else { + broadcast -= Faction + } + } + broadcast.toSet + } + + /** + * Which factions interact with this warp gate as "broadcast?" + * @return the set of all factions who interact with this warp gate as "broadcast" + */ + def BroadcastFor : Set[PlanetSideEmpire.Value] = broadcast.toSet + + /** + * Allow a faction to interact with a given warp gate as "broadcast" if it is active. + * @param bcast the faction + * @return the set of all factions who interact with this warp gate as "broadcast" + */ + def BroadcastFor_=(bcast : PlanetSideEmpire.Value) : Set[PlanetSideEmpire.Value] = { + (broadcast += bcast).toSet + } + + /** + * Allow some factions to interact with a given warp gate as "broadcast" if it is active. + * @param bcast the factions + * @return the set of all factions who interact with this warp gate as "broadcast" + */ + def BroadcastFor_=(bcast : Set[PlanetSideEmpire.Value]) : Set[PlanetSideEmpire.Value] = { + (broadcast ++= bcast).toSet + } + + /** + * Disallow a faction to interact with a given warp gate as "broadcast." + * @param bcast the faction + * @return the set of all factions who interact with this warp gate as "broadcast" + */ + def StopBroadcastFor_=(bcast : PlanetSideEmpire.Value) : Set[PlanetSideEmpire.Value] = { + (broadcast -= bcast).toSet + } + + /** + * Disallow some factions to interact with a given warp gate as "broadcast." + * @param bcast the factions + * @return the set of all factions who interact with this warp gate as "broadcast" + */ + def StopBroadcastFor_=(bcast : Set[PlanetSideEmpire.Value]) : Set[PlanetSideEmpire.Value] = { + (broadcast --= bcast).toSet } def Owner : PlanetSideServerObject = this diff --git a/common/src/main/scala/net/psforever/packet/game/BroadcastWarpgateUpdateMessage.scala b/common/src/main/scala/net/psforever/packet/game/BroadcastWarpgateUpdateMessage.scala index 89dac67f2..ab6856215 100644 --- a/common/src/main/scala/net/psforever/packet/game/BroadcastWarpgateUpdateMessage.scala +++ b/common/src/main/scala/net/psforever/packet/game/BroadcastWarpgateUpdateMessage.scala @@ -6,28 +6,26 @@ import scodec.Codec import scodec.codecs._ /** - * Promotes a warpgate's "broadcast" functionality.
+ * Dispatched by the server to promote a warp gate's broadcast functionality.
*
- * Change the map name of a warpgate into "Broadcast" when the proper state is set. - * If a proper warpgate is not designated, nothing happens. - * If not set, the map name of the warpgate will default to whatever is normally written on the map. - * The map designation of geowarps is not affected by this packet.
- *
- * Exploration:
- * I believe these `Boolean` values actually indicate some measure of warpgate operation. - * Geowarps, for example, though their appearance does not change, recieve this packet. - * Moreover, they can operate as a receiving-end broadcast gate. - * @param continent_id the zone - * @param building_id the warp gate (see `BuildingInfoUpdateMessage`) - * @param unk1 na - * @param unk2 na - * @param broadcast if true, the gate replaces its destination text with "Broadcast" + * Changes the map name of a warp gate into "Broadcast" + * and allow a given faction to access the gate's intercontinental transport functionality to/from that gate, + * even if the gate is not properly owned. + * If an actual warp gate is not designated, nothing happens. + * If not set, the map name of the warp gate will default to whatever is normally written on the map. + * The map designation of geowarps is not affected by this packet. + * @see `BuildingInfoUpdateMessage` + * @param zone_id the zone ordinal number + * @param building_id the warp gate map id + * @param tr players belonging to the Terran Republic interact with this warp gate as a "broadcast gate" + * @param nc players belonging to the New Conglomerate interact with this warp gate as a "broadcast gate" + * @param vs players belonging to the Vanu Sovereignty interact with this warp gate as a "broadcast gate" */ -final case class BroadcastWarpgateUpdateMessage(continent_id : Int, +final case class BroadcastWarpgateUpdateMessage(zone_id : Int, building_id : Int, - unk1 : Boolean, - unk2 : Boolean, - broadcast : Boolean) + tr : Boolean, + nc : Boolean, + vs : Boolean) extends PlanetSideGamePacket { type Packet = BroadcastWarpgateUpdateMessage def opcode = GamePacketOpcode.BroadcastWarpgateUpdateMessage @@ -36,10 +34,10 @@ final case class BroadcastWarpgateUpdateMessage(continent_id : Int, object BroadcastWarpgateUpdateMessage extends Marshallable[BroadcastWarpgateUpdateMessage] { implicit val codec : Codec[BroadcastWarpgateUpdateMessage] = ( - ("continent_id" | uint16L) :: + ("zone_id" | uint16L) :: ("building_id" | uint16L) :: - ("unk1" | bool) :: - ("unk2" | bool) :: - ("broadcast" | bool) + ("tr" | bool) :: + ("nc" | bool) :: + ("vs" | bool) ).as[BroadcastWarpgateUpdateMessage] } diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index 61b7f6b01..2873338c5 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -164,6 +164,7 @@ class WorldSessionActor extends Actor with MDCContextAware { //quickly and briefly kill player to avoid disembark animation avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player_guid, 0, 0)) DismountVehicleOnLogOut() + DisownVehicle() } avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player_guid, player_guid)) taskResolver ! GUIDTask.UnregisterAvatar(player)(continent.GUID) @@ -207,14 +208,14 @@ class WorldSessionActor extends Actor with MDCContextAware { * Vehicle cleanup that is specific to log out behavior. */ def DismountVehicleOnLogOut() : Unit = { - (player.VehicleSeated match { - case Some(vehicle_guid) => - continent.GUID(vehicle_guid) - case None => - None + (continent.GUID(player.VehicleSeated) match { + case Some(obj : Mountable) => + (Some(obj), obj.PassengerInSeat(player)) + case _ => + (None, None) }) match { - case Some(mobj : Mountable) => - mobj.Seat(mobj.PassengerInSeat(player).get).get.Occupant = None + case (Some(mountObj), Some(seatIndex)) => + mountObj.Seats(seatIndex).Occupant = None case _ => ; } @@ -2733,6 +2734,19 @@ class WorldSessionActor extends Actor with MDCContextAware { }) StopBundlingPackets() drawDeloyableIcon = DontRedrawIcons + //if driver of a vehicle, summon any passengers and cargo vehicles left behind on previous continent + GetVehicleAndSeat() match { + case (Some(vehicle), Some(0)) => + LoadZoneTransferPassengerMessages( + guid, + continent.Id, + TransportVehicleChannelName(vehicle), + vehicle, + interstellarFerryTopLevelGUID.getOrElse(vehicle.GUID) + ) + interstellarFerryTopLevelGUID = None + case _ => ; + } } def handleControlPkt(pkt : PlanetSideControlPacket) = { @@ -3028,16 +3042,7 @@ class WorldSessionActor extends Actor with MDCContextAware { }) //our vehicle would have already been loaded; see NewPlayerLoaded/AvatarCreate usedVehicle.headOption match { - case Some(vehicle) if vehicle.PassengerInSeat(player).contains(0) => - //if driver of vehicle, summon any passengers and cargo vehicles left behind on previous continent - LoadZoneTransferPassengerMessages( - guid, - continentId, - TransportVehicleChannelName(vehicle), - vehicle, - interstellarFerryTopLevelGUID.orElse(player.VehicleSeated).getOrElse(PlanetSideGUID(0)) - ) - case Some(vehicle) => + case Some(vehicle) if !vehicle.PassengerInSeat(player).contains(0) => //if passenger, attempt to depict any other passengers already in this zone val vguid = vehicle.GUID vehicle.Seats @@ -3054,7 +3059,7 @@ class WorldSessionActor extends Actor with MDCContextAware { ) ) }) - case _ => ; //no vehicle + case _ => ; //driver, or no vehicle } //vehicle wreckages wreckages.foreach(vehicle => { @@ -3287,7 +3292,13 @@ class WorldSessionActor extends Actor with MDCContextAware { case msg @ SpawnRequestMessage(u1, spawn_type, u3, u4, zone_number) => log.info(s"SpawnRequestMessage: $msg") - cluster ! Zone.Lattice.RequestSpawnPoint(zone_number.toInt, player, spawn_type.id.toInt) + if(deadState != DeadState.RespawnTime) { + deadState = DeadState.RespawnTime + cluster ! Zone.Lattice.RequestSpawnPoint(zone_number.toInt, player, spawn_type.id.toInt) + } + else { + log.warn("SpawnRequestMessage: request consumed; already respawning ...") + } case msg @ SetChatFilterMessage(send_channel, origin, whitelist) => //log.info("SetChatFilters: " + msg) @@ -3332,18 +3343,22 @@ class WorldSessionActor extends Actor with MDCContextAware { PlayerActionsToCancel() continent.GUID(player.VehicleSeated) match { case Some(vehicle : Vehicle) => - vehicle.Position = pos - vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.UnloadVehicle(player.GUID, continent, vehicle, vehicle.GUID)) - LoadZonePhysicalSpawnPoint(zone, pos, Vector3.Zero, 0) + vehicle.PassengerInSeat(player) match { + case Some(0) => + vehicle.Position = pos + LoadZonePhysicalSpawnPoint(zone, pos, Vector3.Zero, 0) + case _ => //not seated as the driver, in which case we can't move + deadState = DeadState.Alive + } case None => player.Position = pos - avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player.GUID, player.GUID)) + //avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player.GUID, player.GUID)) LoadZonePhysicalSpawnPoint(zone, pos, Vector3.Zero, 0) - case _ => //seated in something that is not a vehicle, in which case we can't move + case _ => //seated in something that is not a vehicle, or we're dead, in which case we can't move deadState = DeadState.Alive } - case (false, _, _) => ; + case (_, _, _) => ; } CSRWarp.read(traveler, msg) match { @@ -3351,17 +3366,23 @@ class WorldSessionActor extends Actor with MDCContextAware { deadState = DeadState.Release //cancel movement updates PlayerActionsToCancel() continent.GUID(player.VehicleSeated) match { - case Some(vehicle : Vehicle) => - LoadZonePhysicalSpawnPoint(continent.Id, pos, Vector3.z(vehicle.Orientation.z), 0) + case Some(vehicle : Vehicle) if player.isAlive => + vehicle.PassengerInSeat(player) match { + case Some(0) => + vehicle.Position = pos + LoadZonePhysicalSpawnPoint(continent.Id, pos, Vector3.z(vehicle.Orientation.z), 0) + case _ => //not seated as the driver, in which case we can't move + deadState = DeadState.Alive + } case None => player.Position = pos sendResponse(PlayerStateShiftMessage(ShiftState(0, pos, player.Orientation.z, None))) deadState = DeadState.Alive //must be set here - case _ => //seated in something that is not a vehicle, in which case we can't move + case _ => //seated in something that is not a vehicle, or we're dead, in which case we can't move deadState = DeadState.Alive } - case (false, _) => ; + case (_, _) => ; } // TODO: Prevents log spam, but should be handled correctly @@ -4485,17 +4506,23 @@ class WorldSessionActor extends Actor with MDCContextAware { case msg @ WarpgateRequest(continent_guid, building_guid, dest_building_guid, dest_continent_guid, unk1, unk2) => log.info(s"WarpgateRequest: $msg") - continent.Buildings.values.find(building => building.GUID == building_guid) match { - case Some(wg : WarpGate) if(wg.Active && (GetKnownVehicleAndSeat() match { - case (Some(vehicle), _) => - wg.Definition.VehicleAllowance && !wg.Definition.NoWarp.contains(vehicle.Definition) - case _ => - true - })) => - cluster ! Zone.Lattice.RequestSpecificSpawnPoint(dest_continent_guid.guid, player, dest_building_guid) + if(deadState != DeadState.RespawnTime) { + deadState = DeadState.RespawnTime + continent.Buildings.values.find(building => building.GUID == building_guid) match { + case Some(wg : WarpGate) if (wg.Active && (GetKnownVehicleAndSeat() match { + case (Some(vehicle), _) => + wg.Definition.VehicleAllowance && !wg.Definition.NoWarp.contains(vehicle.Definition) + case _ => + true + })) => + cluster ! Zone.Lattice.RequestSpecificSpawnPoint(dest_continent_guid.guid, player, dest_building_guid) - case _ => - RequestSanctuaryZoneSpawn(player, continent.Number) + case _ => + RequestSanctuaryZoneSpawn(player, continent.Number) + } + } + else { + log.warn("WarpgateRequest: request consumed; already respawning ...") } case msg @ MountVehicleMsg(player_guid, mountable_guid, entry_point) => @@ -5332,7 +5359,7 @@ class WorldSessionActor extends Actor with MDCContextAware { * @param vehicle the discovered vehicle */ private def SpecialCaseVehicleDespawn(tplayer : Player, vehicle : Vehicle) : Option[Vehicle] = { - if(vehicle.Owner.contains(tplayer.GUID) || !vehicle.Seats(0).isOccupied) { + if(vehicle.Owner.contains(tplayer.GUID)) { vehicle.Owner = None vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(vehicle), continent)) vehicle.CargoHolds.values @@ -5345,7 +5372,7 @@ class WorldSessionActor extends Actor with MDCContextAware { vehicle, ferry.GUID, ferry, - true, + false, false, false ) @@ -6357,7 +6384,16 @@ class WorldSessionActor extends Actor with MDCContextAware { ) ) sendResponse(DensityLevelUpdateMessage(continentNumber, buildingNumber, List(0,0, 0,0, 0,0, 0,0))) - sendResponse(BroadcastWarpgateUpdateMessage(continentNumber, buildingNumber, false, false, wg.Broadcast)) + //TODO one faction knows which gates are broadcast for another faction? + sendResponse( + BroadcastWarpgateUpdateMessage( + continentNumber, + buildingNumber, + wg.Broadcast(PlanetSideEmpire.TR), + wg.Broadcast(PlanetSideEmpire.NC), + wg.Broadcast(PlanetSideEmpire.VS) + ) + ) case _ => ; } } @@ -6598,15 +6634,6 @@ class WorldSessionActor extends Actor with MDCContextAware { case _ => vehicle.MountedIn = None } - //call for passengers across the expanse - LoadZoneTransferPassengerMessages( - player.GUID, - continent.Id, - TransportVehicleChannelName(vehicle), - vehicle, - interstellarFerryTopLevelGUID.orElse(player.VehicleSeated).getOrElse(PlanetSideGUID(0)) - ) - interstellarFerryTopLevelGUID = None } else { //if passenger; @@ -7875,7 +7902,7 @@ class WorldSessionActor extends Actor with MDCContextAware { * does not factor in any time required for loading zone or game objects */ def LoadZonePhysicalSpawnPoint(zone_id : String, pos : Vector3, ori : Vector3, respawnTime : Long) : Unit = { - log.info(s"Load in zone $zone_id at position $pos") + log.info(s"Load in zone $zone_id at position $pos in $respawnTime seconds") respawnTimer.cancel reviveTimer.cancel val backpack = player.isBackpack @@ -7940,7 +7967,7 @@ class WorldSessionActor extends Actor with MDCContextAware { else { LoadZoneCommonTransferActivity() val original = player - if(tplayer.isBackpack) { + if(player.isBackpack) { //unregister avatar locker + GiveWorld player = tplayer (taskResolver, TaskBeforeZoneChange(GUIDTask.UnregisterLocker(original.Locker)(continent.GUID), zone_id)) @@ -8381,7 +8408,12 @@ class WorldSessionActor extends Actor with MDCContextAware { */ def BeforeUnloadVehicle(vehicle : Vehicle) : Unit = { vehicle.Definition match { + case GlobalDefinitions.ams if vehicle.Faction == player.Faction => + log.info("BeforeUnload: cleaning up after a mobile spawn vehicle ...") + vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.UpdateAmsSpawnPoint(continent)) + None case GlobalDefinitions.router => + //this may repeat for multiple players on the same continent but that's okay(?) log.info("BeforeUnload: cleaning up after a router ...") (vehicle.Utility(UtilityType.internal_router_telepad_deployable) match { case Some(util : Utility.InternalTelepad) => @@ -8566,7 +8598,7 @@ class WorldSessionActor extends Actor with MDCContextAware { /** * Given an origin and a destination, determine how long the process of traveling should take in reconstruction time. * For most destinations, the unit of receiving ("spawn point") determines the reconstruction time. - * In a special consideration, travel from any sanctuary or sanctuary-special zone should be as immediate as zone loading. + * In a special consideration, travel to any sanctuary or sanctuary-special zone should be as immediate as zone loading. * @param toZoneId the zone where the target is headed * @param toSpawnPoint the unit the target is using as a destination * @param fromZoneId the zone where the target current is located @@ -8574,12 +8606,9 @@ class WorldSessionActor extends Actor with MDCContextAware { */ def CountSpawnDelay(toZoneId : String, toSpawnPoint : SpawnPoint, fromZoneId : String) : Long = { val sanctuaryZoneId = Zones.SanctuaryZoneId(player.Faction) - if(sanctuaryZoneId.equals(fromZoneId)) { //TODO includes traveing zones + if(sanctuaryZoneId.equals(toZoneId)) { //to sanctuary 0L } - else if(sanctuaryZoneId.equals(toZoneId)) { - 10L - } else if(!player.isAlive) { toSpawnPoint.Definition.Delay //TODO +cumulative death penalty } @@ -8601,8 +8630,10 @@ class WorldSessionActor extends Actor with MDCContextAware { .sortBy(tube => Vector3.DistanceSquared(tube.Position, player.Position)) .headOption match { case Some(tube) => + log.info("DrawCurrentAmsSpawnPoint - new @ams spawn point drawn") sendResponse(BindPlayerMessage(BindStatus.Available, "@ams", true, false, SpawnGroup.AMS, continent.Number, 5, tube.Position)) case None => + log.info("DrawCurrentAmsSpawnPoint - no @ams spawn point drawn") sendResponse(BindPlayerMessage(BindStatus.Unavailable, "@ams", false, false, SpawnGroup.AMS, continent.Number, 0, Vector3.Zero)) } } diff --git a/pslogin/src/main/scala/Zones.scala b/pslogin/src/main/scala/Zones.scala index 3b9598661..15dc2b0a7 100644 --- a/pslogin/src/main/scala/Zones.scala +++ b/pslogin/src/main/scala/Zones.scala @@ -7,7 +7,16 @@ import net.psforever.objects.zones.Zone import net.psforever.types.PlanetSideEmpire object Zones { - val z1 = new Zone("z1", Maps.map1, 1) + val z1 = new Zone("z1", Maps.map1, 1) { + override def Init(implicit context : ActorContext) : Unit = { + super.Init(context) + + BuildingByMapId(1).get.asInstanceOf[WarpGate].BroadcastFor = PlanetSideEmpire.TR + BuildingByMapId(2).get.asInstanceOf[WarpGate].BroadcastFor = PlanetSideEmpire.TR + BuildingByMapId(3).get.asInstanceOf[WarpGate].BroadcastFor = PlanetSideEmpire.TR + BuildingByMapId(4).get.asInstanceOf[WarpGate].BroadcastFor = PlanetSideEmpire.TR + } + } val z2 = new Zone("z2", Maps.map2, 2) @@ -101,10 +110,10 @@ object Zones { } import net.psforever.types.PlanetSideEmpire BuildingByMapId(2).get.Faction = PlanetSideEmpire.VS - BuildingByMapId(10).get.asInstanceOf[WarpGate].Broadcast = true - BuildingByMapId(11).get.asInstanceOf[WarpGate].Broadcast = true - BuildingByMapId(12).get.asInstanceOf[WarpGate].Broadcast = true - BuildingByMapId(13).get.asInstanceOf[WarpGate].Broadcast = true + BuildingByMapId(10).get.asInstanceOf[WarpGate].BroadcastFor = PlanetSideEmpire.VS + BuildingByMapId(11).get.asInstanceOf[WarpGate].BroadcastFor = PlanetSideEmpire.VS + BuildingByMapId(12).get.asInstanceOf[WarpGate].BroadcastFor = PlanetSideEmpire.VS + BuildingByMapId(13).get.asInstanceOf[WarpGate].BroadcastFor = PlanetSideEmpire.VS BuildingByMapId(48).get.Faction = PlanetSideEmpire.VS BuildingByMapId(49).get.Faction = PlanetSideEmpire.VS BuildingByMapId(18657).get.asInstanceOf[WarpGate].Active = false @@ -135,6 +144,9 @@ object Zones { import net.psforever.types.PlanetSideEmpire Buildings.values.foreach { _.Faction = PlanetSideEmpire.TR } + BuildingByMapId(1).get.asInstanceOf[WarpGate].Broadcast = true + BuildingByMapId(2).get.asInstanceOf[WarpGate].Broadcast = true + BuildingByMapId(3).get.asInstanceOf[WarpGate].Broadcast = true } }