From 39ae77d6f4189394373cff9202919b56494071d9 Mon Sep 17 00:00:00 2001 From: Fate-JH Date: Fri, 17 Apr 2020 18:57:09 -0400 Subject: [PATCH] medkits, and med apps, and respawn tubes, oh my (#368) --- .../psforever/objects/zones/ZoneActor.scala | 134 +++++++++++------- .../src/main/scala/WorldSessionActor.scala | 98 ++++++------- 2 files changed, 119 insertions(+), 113 deletions(-) diff --git a/common/src/main/scala/net/psforever/objects/zones/ZoneActor.scala b/common/src/main/scala/net/psforever/objects/zones/ZoneActor.scala index 9bfc8744..6a708148 100644 --- a/common/src/main/scala/net/psforever/objects/zones/ZoneActor.scala +++ b/common/src/main/scala/net/psforever/objects/zones/ZoneActor.scala @@ -5,7 +5,7 @@ import java.util.concurrent.atomic.AtomicInteger import akka.actor.Actor import net.psforever.objects.{GlobalDefinitions, PlanetSideGameObject, SpawnPoint, Tool} -import net.psforever.objects.serverobject.structures.{StructureType, WarpGate} +import net.psforever.objects.serverobject.structures.{AmenityOwner, StructureType, WarpGate} import net.psforever.objects.serverobject.tube.SpawnTube import net.psforever.objects.vehicles.UtilityType import net.psforever.types.{DriveState, PlanetSideEmpire, Vector3} @@ -84,17 +84,15 @@ class ZoneActor(zone : Zone) extends Actor { case Zone.Lattice.RequestSpawnPoint(zone_number, position, faction, spawn_group) => if(zone_number == zone.Number) { ZoneActor.FindLocalSpawnPointsInZone(zone, position, faction, spawn_group) match { + case Some(Nil) | None => + sender ! Zone.Lattice.NoValidSpawnPoint(zone_number, Some(spawn_group)) + case Some(List(tube)) => sender ! Zone.Lattice.SpawnPoint(zone.Id, tube) case Some(tubes) => - val tube = scala.util.Random.shuffle( - tubes.filter(sp => !sp.Offline) - ).head + val tube = scala.util.Random.shuffle(tubes).head sender ! Zone.Lattice.SpawnPoint(zone.Id, tube) - - case None => - sender ! Zone.Lattice.NoValidSpawnPoint(zone_number, Some(spawn_group)) } } else { //wrong zone_number @@ -225,61 +223,87 @@ object ZoneActor { * @return na */ def FindLocalSpawnPointsInZone(zone : Zone, position : Vector3, faction : PlanetSideEmpire.Value, spawn_group : Int) : Option[List[SpawnPoint]] = { - val playerPosition = position.xy - if(spawn_group == 2) { - //ams - zone.Vehicles - .filter(veh => - veh.Definition == GlobalDefinitions.ams && - veh.DeploymentState == DriveState.Deployed && - veh.Faction == faction - ) - .sortBy(veh => Vector3.DistanceSquared(playerPosition, veh.Position.xy)) - .flatMap(veh => veh.Utilities.values.filter(util => util.UtilType == UtilityType.ams_respawn_tube)) - .headOption match { - case None => - None - case Some(util) => - Some(List(util().asInstanceOf[SpawnTube])) - } + (if(spawn_group == 2) { + FindVehicleSpawnPointsInZone(zone, position, faction) } else { - //facilities, towers, and buildings - val buildingTypeSet = if(spawn_group == 0) { - Set(StructureType.Facility, StructureType.Tower, StructureType.Building) - } - else if(spawn_group == 6) { - Set(StructureType.Tower) - } - else if(spawn_group == 7) { - Set(StructureType.Facility, StructureType.Building) - } - else if(spawn_group == 12) { - Set(StructureType.WarpGate) - } - else { - Set.empty[StructureType.Value] - } - zone.SpawnGroups() - .filter({ case (building, _) => - buildingTypeSet.contains(building.BuildingType) && (building match { - case wg : WarpGate => - building.Faction == faction || building.Faction == PlanetSideEmpire.NEUTRAL || wg.Broadcast - case _ => - building.Faction == faction - }) - }) - .toSeq - .sortBy({ case (building, _) => - Vector3.DistanceSquared(playerPosition, building.Position.xy) - }) - .headOption match { + FindBuildingSpawnPointsInZone(zone, position, faction, spawn_group) + }) + .headOption match { case None | Some((_, Nil)) => None case Some((_, tubes)) => - Some(tubes) + Some(tubes toList) } } + /** + * na + * @param zone na + * @param position na + * @param faction na + * @return na + */ + private def FindVehicleSpawnPointsInZone(zone : Zone, position : Vector3, faction : PlanetSideEmpire.Value) : List[(AmenityOwner, Iterable[SpawnTube])] = { + val xy = position.xy + //ams + zone.Vehicles + .filter(veh => + veh.Definition == GlobalDefinitions.ams && + !veh.Destroyed && + veh.DeploymentState == DriveState.Deployed && + veh.Faction == faction + ) + .sortBy(veh => Vector3.DistanceSquared(xy, veh.Position.xy)) + .map(veh => + ( + veh, + veh.Utilities.values + .filter(util => util.UtilType == UtilityType.ams_respawn_tube) + .map(_().asInstanceOf[SpawnTube]) + ) + ) + } + + /** + * na + * @param zone na + * @param position na + * @param faction na + * @param spawn_group na + * @return na + */ + private def FindBuildingSpawnPointsInZone(zone : Zone, position : Vector3, faction : PlanetSideEmpire.Value, spawn_group : Int) : List[(AmenityOwner, Iterable[SpawnPoint])] = { + val xy = position.xy + //facilities, towers, warp gates, and other buildings + val buildingTypeSet = if(spawn_group == 0) { + Set(StructureType.Facility, StructureType.Tower, StructureType.Building) + } + else if(spawn_group == 6) { + Set(StructureType.Tower) + } + else if(spawn_group == 7) { + Set(StructureType.Facility, StructureType.Building) + } + else if(spawn_group == 12) { + Set(StructureType.WarpGate) + } + else { + Set.empty[StructureType.Value] + } + zone.SpawnGroups() + .collect({ case (building, spawns) if + buildingTypeSet.contains(building.BuildingType) && (building match { + case wg : WarpGate => + building.Faction == faction || building.Faction == PlanetSideEmpire.NEUTRAL || wg.Broadcast + case _ => + building.Faction == faction && spawns.nonEmpty && spawns.exists(_.Offline == false) + }) => (building, spawns.filter(_.Offline == false)) + }) + .toSeq + .sortBy({ case (building, _) => + Vector3.DistanceSquared(xy, building.Position.xy) + }) + .toList } /** diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index a1d9f30f..f26bebbf 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -310,11 +310,13 @@ class WorldSessionActor extends Actor HandleAvatarServiceResponse(toChannel, guid, reply) case CommonMessages.Progress(rate, finishedAction, stepAction) => - progressBarValue = Some(-rate) - self ! ProgressEvent(rate, finishedAction, stepAction) + if(progressBarValue.isEmpty) { + progressBarValue = Some(-rate) + self ! ProgressEvent(rate, finishedAction, stepAction) + } - case ProgressEvent(delta, completeAction, tickAction) => - HandleProgressChange(delta, completeAction, tickAction) + case ProgressEvent(delta, finishedAction, stepAction) => + HandleProgressChange(delta, finishedAction, stepAction) case Door.DoorMessage(tplayer, msg, order) => HandleDoorMessage(tplayer, msg, order) @@ -5259,7 +5261,7 @@ class WorldSessionActor extends Actor accessedContainer = Some(obj) } else if(!unk3 && player.isAlive) { //potential kit use - equipment match { + ValidObject(item_used_guid) match { case Some(kit : Kit) => player.Find(kit) match { case Some(index) => @@ -5271,20 +5273,15 @@ class WorldSessionActor extends Actor sendResponse(ChatMsg(ChatMessageType.UNK_225, false, "", s"@TimeUntilNextUse^${5 - (System.currentTimeMillis - whenUsedLastKit) / 1000}~", None)) } else { - player.Find(kit) match { - case Some(index) => - whenUsedLastKit = System.currentTimeMillis - player.Slot(index).Equipment = None //remove from slot immediately; must exist on client for next packet - sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, 0, unk3, unk4, unk5, unk6, unk7, unk8, itemType)) - sendResponse(ObjectDeleteMessage(kit.GUID, 0)) - taskResolver ! GUIDTask.UnregisterEquipment(kit)(continent.GUID) - player.History(HealFromKit(PlayerSource(player), 25, kit.Definition)) - player.Health = player.Health + 25 - sendResponse(PlanetsideAttributeMessage(avatar_guid, 0, player.Health)) - continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(avatar_guid, 0, player.Health)) - case None => - log.error(s"UseItem: anticipated a $kit, but can't find it") - } + whenUsedLastKit = System.currentTimeMillis + player.Slot(index).Equipment = None //remove from slot immediately; must exist on client for next packet + sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, 0, unk3, unk4, unk5, unk6, unk7, unk8, itemType)) + sendResponse(ObjectDeleteMessage(kit.GUID, 0)) + taskResolver ! GUIDTask.UnregisterEquipment(kit)(continent.GUID) + player.History(HealFromKit(PlayerSource(player), 25, kit.Definition)) + player.Health = player.Health + 25 + sendResponse(PlanetsideAttributeMessage(avatar_guid, 0, player.Health)) + continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(avatar_guid, 0, player.Health)) } } else if(kit.Definition == GlobalDefinitions.super_medkit) { @@ -5295,20 +5292,15 @@ class WorldSessionActor extends Actor sendResponse(ChatMsg(ChatMessageType.UNK_225, false, "", s"@TimeUntilNextUse^${1200 - (System.currentTimeMillis - whenUsedLastSMKit) / 1000}~", None)) } else { - player.Find(kit) match { - case Some(index) => - whenUsedLastSMKit = System.currentTimeMillis - player.Slot(index).Equipment = None //remove from slot immediately; must exist on client for next packet - sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, 0, unk3, unk4, unk5, unk6, unk7, unk8, itemType)) - sendResponse(ObjectDeleteMessage(kit.GUID, 0)) - taskResolver ! GUIDTask.UnregisterEquipment(kit)(continent.GUID) - player.History(HealFromKit(PlayerSource(player), 100, kit.Definition)) - player.Health = player.Health + 100 - sendResponse(PlanetsideAttributeMessage(avatar_guid, 0, player.Health)) - continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(avatar_guid, 0, player.Health)) - case None => - log.error(s"UseItem: anticipated a $kit, but can't find it") - } + whenUsedLastSMKit = System.currentTimeMillis + player.Slot(index).Equipment = None //remove from slot immediately; must exist on client for next packet + sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, 0, unk3, unk4, unk5, unk6, unk7, unk8, itemType)) + sendResponse(ObjectDeleteMessage(kit.GUID, 0)) + taskResolver ! GUIDTask.UnregisterEquipment(kit)(continent.GUID) + player.History(HealFromKit(PlayerSource(player), 100, kit.Definition)) + player.Health = player.Health + 100 + sendResponse(PlanetsideAttributeMessage(avatar_guid, 0, player.Health)) + continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(avatar_guid, 0, player.Health)) } } else if(kit.Definition == GlobalDefinitions.super_armorkit) { @@ -5319,20 +5311,15 @@ class WorldSessionActor extends Actor sendResponse(ChatMsg(ChatMessageType.UNK_225, false, "", s"@TimeUntilNextUse^${1200 - (System.currentTimeMillis - whenUsedLastSAKit) / 1000}~", None)) } else { - player.Find(kit) match { - case Some(index) => - whenUsedLastSAKit = System.currentTimeMillis - player.Slot(index).Equipment = None //remove from slot immediately; must exist on client for next packet - sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, 0, unk3, unk4, unk5, unk6, unk7, unk8, itemType)) - sendResponse(ObjectDeleteMessage(kit.GUID, 0)) - taskResolver ! GUIDTask.UnregisterEquipment(kit)(continent.GUID) - player.History(RepairFromKit(PlayerSource(player), 200, kit.Definition)) - player.Armor = player.Armor + 200 - sendResponse(PlanetsideAttributeMessage(avatar_guid, 4, player.Armor)) - continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(avatar_guid, 4, player.Armor)) - case None => - log.error(s"UseItem: anticipated a $kit, but can't find it") - } + whenUsedLastSAKit = System.currentTimeMillis + player.Slot(index).Equipment = None //remove from slot immediately; must exist on client for next packet + sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, 0, unk3, unk4, unk5, unk6, unk7, unk8, itemType)) + sendResponse(ObjectDeleteMessage(kit.GUID, 0)) + taskResolver ! GUIDTask.UnregisterEquipment(kit)(continent.GUID) + player.History(RepairFromKit(PlayerSource(player), 200, kit.Definition)) + player.Armor = player.Armor + 200 + sendResponse(PlanetsideAttributeMessage(avatar_guid, 4, player.Armor)) + continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(avatar_guid, 4, player.Armor)) } } else if(kit.Definition == GlobalDefinitions.super_staminakit) { @@ -5343,17 +5330,12 @@ class WorldSessionActor extends Actor sendResponse(ChatMsg(ChatMessageType.UNK_225, false, "", s"@TimeUntilNextUse^${300 - (System.currentTimeMillis - whenUsedLastSSKit) / 1200}~", None)) } else { - player.Find(kit) match { - case Some(index) => - whenUsedLastSSKit = System.currentTimeMillis - player.Slot(index).Equipment = None //remove from slot immediately; must exist on client for next packet - sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, 0, unk3, unk4, unk5, unk6, unk7, unk8, itemType)) - sendResponse(ObjectDeleteMessage(kit.GUID, 0)) - taskResolver ! GUIDTask.UnregisterEquipment(kit)(continent.GUID) - player.Stamina = player.Stamina + 100 - case None => - log.error(s"UseItem: anticipated a $kit, but can't find it") - } + whenUsedLastSSKit = System.currentTimeMillis + player.Slot(index).Equipment = None //remove from slot immediately; must exist on client for next packet + sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, 0, unk3, unk4, unk5, unk6, unk7, unk8, itemType)) + sendResponse(ObjectDeleteMessage(kit.GUID, 0)) + taskResolver ! GUIDTask.UnregisterEquipment(kit)(continent.GUID) + player.Stamina = player.Stamina + 100 } } else {