diff --git a/common/src/main/scala/net/psforever/objects/serverobject/turret/FacilityTurret.scala b/common/src/main/scala/net/psforever/objects/serverobject/turret/FacilityTurret.scala index bcb5fc6a5..3faa62027 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/turret/FacilityTurret.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/turret/FacilityTurret.scala @@ -11,6 +11,7 @@ class FacilityTurret(tDef : TurretDefinition) extends Amenity with StandardResistanceProfile { /** some turrets can be updated; they all start without updates */ private var upgradePath : TurretUpgrade.Value = TurretUpgrade.None + private var middleOfUpgrade : Boolean = false WeaponTurret.LoadDefinition(this) @@ -23,16 +24,33 @@ class FacilityTurret(tDef : TurretDefinition) extends Amenity def Upgrade : TurretUpgrade.Value = upgradePath def Upgrade_=(upgrade : TurretUpgrade.Value) : TurretUpgrade.Value = { - upgradePath = upgrade + middleOfUpgrade = true //blocking flag; block early + var updated = false //upgrade each weapon as long as that weapon has a valid option for that upgrade Definition.Weapons.foreach({ case(index, upgradePaths) => if(upgradePaths.contains(upgrade)) { + updated = true weapons(index).Equipment.get.asInstanceOf[TurretWeapon].Upgrade = upgrade } }) + if(updated) { + upgradePath = upgrade + } + else { + middleOfUpgrade = false //reset + } Upgrade } + def ConfirmUpgrade(upgrade : TurretUpgrade.Value) : TurretUpgrade.Value = { + if(middleOfUpgrade && upgradePath == upgrade) { + middleOfUpgrade = false + } + upgradePath + } + + def isUpgrading : Boolean = middleOfUpgrade + def DamageModel = Definition.asInstanceOf[DamageResistanceModel] def Definition : TurretDefinition = tDef diff --git a/common/src/main/scala/services/vehicle/support/TurretUpgrader.scala b/common/src/main/scala/services/vehicle/support/TurretUpgrader.scala index c5b55eb14..46e2ba6ae 100644 --- a/common/src/main/scala/services/vehicle/support/TurretUpgrader.scala +++ b/common/src/main/scala/services/vehicle/support/TurretUpgrader.scala @@ -176,11 +176,13 @@ class TurretUpgrader extends SupportActor[TurretUpgrader.Entry] { }) info(s"Converting manned wall turret weapon to $upgrade") - val oldBoxesTask = AllMountedWeaponMagazines(target) - .map(box => GUIDTask.UnregisterEquipment(box)(guid)) - .toList + val oldBoxes = AllMountedWeaponMagazines(target) target.Upgrade = upgrade //perform upgrade + val newBoxes = AllMountedWeaponMagazines(target) + val oldBoxesTask = oldBoxes + .filterNot { box => newBoxes.exists(_ eq box) } + .map(box => GUIDTask.UnregisterEquipment(box)(guid)).toList val newBoxesTask = TaskResolver.GiveTask( new Task() { private val localFunc : ()=>Unit = FinishUpgradingTurret(entry) @@ -188,17 +190,27 @@ class TurretUpgrader extends SupportActor[TurretUpgrader.Entry] { override def isComplete = Task.Resolution.Success def Execute(resolver : ActorRef) : Unit = { - localFunc() resolver ! scala.util.Success(this) } - }, AllMountedWeaponMagazines(target).map(box => GUIDTask.RegisterEquipment(box)(guid)).toList + + override def onSuccess() : Unit = { + super.onSuccess() + localFunc() + } + }, + newBoxes + .filterNot { box => oldBoxes.exists(_ eq box) } + .map(box => GUIDTask.RegisterEquipment(box)(guid)).toList ) taskResolver ! TaskResolver.GiveTask( new Task() { + private val tasks = oldBoxesTask + def Execute(resolver : ActorRef) : Unit = { + tasks.foreach { resolver ! _ } resolver ! scala.util.Success(this) } - }, oldBoxesTask :+ newBoxesTask + }, List(newBoxesTask) ) } @@ -225,15 +237,18 @@ class TurretUpgrader extends SupportActor[TurretUpgrader.Entry] { val target = entry.obj.asInstanceOf[FacilityTurret] val zone = entry.zone info(s"Wall turret finished ${target.Upgrade} upgrade") + target.ConfirmUpgrade(entry.upgrade) val targetGUID = target.GUID - target.Weapons - .map({ case (index, slot) => (index, slot.Equipment) }) - .collect { case (index, Some(tool : Tool)) => - context.parent ! VehicleServiceMessage( - zone.Id, - VehicleAction.EquipmentInSlot(PlanetSideGUID(0), targetGUID, index, tool) - ) - } + if(target.Health > 0) { + target.Weapons + .map({ case (index, slot) => (index, slot.Equipment) }) + .collect { case (index, Some(tool : Tool)) => + context.parent ! VehicleServiceMessage( + zone.Id, + VehicleAction.EquipmentInSlot(PlanetSideGUID(0), targetGUID, index, tool) + ) + } + } } } diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index dcad667fc..03007aa28 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -1409,6 +1409,16 @@ class WorldSessionActor extends Actor with MDCContextAware { UpdateWeaponAtSeatPosition(obj, seat_num) MountingAction(tplayer, obj, seat_num) + case Mountable.CanMount(obj : FacilityTurret, seat_num) => + if(!obj.isUpgrading) { + sendResponse(PlanetsideAttributeMessage(obj.GUID, 0, obj.Health)) + UpdateWeaponAtSeatPosition(obj, seat_num) + MountingAction(tplayer, obj, seat_num) + } + else { + log.warn(s"MountVehicleMsg: ${tplayer.Name} wants to mount turret ${obj.GUID.guid}, but needs to wait until it finishes updating") + } + case Mountable.CanMount(obj : PlanetSideGameObject with WeaponTurret, seat_num) => sendResponse(PlanetsideAttributeMessage(obj.GUID, 0, obj.Health)) UpdateWeaponAtSeatPosition(obj, seat_num) @@ -3225,43 +3235,43 @@ class WorldSessionActor extends Actor with MDCContextAware { }) //base turrets - continent.Map.TurretToWeapon.foreach({ case((turret_guid, weapon_guid)) => - val parent_guid = PlanetSideGUID(turret_guid) - continent.GUID(turret_guid) match { - case Some(turret : FacilityTurret) => - //attached weapon - turret.ControlledWeapon(1) match { + continent.Map.TurretToWeapon + .map { case((turret_guid, _)) => continent.GUID(turret_guid) } + .collect { case Some(turret : FacilityTurret) => + val pguid = turret.GUID + //attached weapon + if(!turret.isUpgrading) { + turret.ControlledWeapon(wepNumber = 1) match { case Some(obj : Tool) => val objDef = obj.Definition sendResponse( ObjectCreateMessage( objDef.ObjectId, obj.GUID, - ObjectCreateMessageParent(parent_guid, 1), + ObjectCreateMessageParent(pguid, 1), objDef.Packet.ConstructorData(obj).get ) ) case _ => ; } - //reserved ammunition? - //TODO need to register if it exists - //seat turret occupant - turret.Seats(0).Occupant match { - case Some(tplayer) => - val tdefintion = tplayer.Definition - sendResponse( - ObjectCreateMessage( - tdefintion.ObjectId, - tplayer.GUID, - ObjectCreateMessageParent(parent_guid, 0), - tdefintion.Packet.ConstructorData(tplayer).get - ) + } + //reserved ammunition? + //TODO need to register if it exists + //seat turret occupant + turret.Seats(0).Occupant match { + case Some(tplayer) => + val tdefintion = tplayer.Definition + sendResponse( + ObjectCreateMessage( + tdefintion.ObjectId, + tplayer.GUID, + ObjectCreateMessageParent(pguid, 0), + tdefintion.Packet.ConstructorData(tplayer).get ) - case None => ; - } - case _ => ; + ) + case None => ; + } } - }) vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.UpdateAmsSpawnPoint(continent)) self ! SetCurrentAvatar(player) @@ -3506,10 +3516,12 @@ class WorldSessionActor extends Actor with MDCContextAware { } if(messagetype == ChatMessageType.CMT_DESTROY) { val guid = contents.toInt - continent.Map.TerminalToSpawnPad.get(guid) match { - case Some(padGUID) => - continent.GUID(padGUID).get.asInstanceOf[VehicleSpawnPad].Actor ! VehicleSpawnControl.ProcessControl.Flush - case None => + continent.GUID(continent.Map.TerminalToSpawnPad.getOrElse(guid, guid)) match { + case Some(pad : VehicleSpawnPad) => + pad.Actor ! VehicleSpawnControl.ProcessControl.Flush + case Some(turret : FacilityTurret) if turret.isUpgrading => + FinishUpgradingMannedTurret(turret, TurretUpgrade.None) + case _ => self ! PacketCoding.CreateGamePacket(0, RequestDestroyMessage(PlanetSideGUID(guid))) } } @@ -5500,9 +5512,13 @@ class WorldSessionActor extends Actor with MDCContextAware { * @param upgrade the new upgrade state */ private def FinishUpgradingMannedTurret(target : FacilityTurret, tool : Tool, upgrade : TurretUpgrade.Value)() : Unit = { - log.info(s"Converting manned wall turret weapon to $upgrade") tool.Magazine = 0 sendResponse(InventoryStateMessage(tool.AmmoSlot.Box.GUID, tool.GUID, 0)) + FinishUpgradingMannedTurret(target, upgrade) + } + + private def FinishUpgradingMannedTurret(target : FacilityTurret, upgrade : TurretUpgrade.Value) : Unit = { + log.info(s"Converting manned wall turret weapon to $upgrade") vehicleService ! VehicleServiceMessage.TurretUpgrade(TurretUpgrader.ClearSpecific(List(target), continent)) vehicleService ! VehicleServiceMessage.TurretUpgrade(TurretUpgrader.AddTask(target, continent, upgrade)) } @@ -6210,7 +6226,7 @@ class WorldSessionActor extends Actor with MDCContextAware { sendResponse(ObjectDetachMessage(tool.GUID, previousBox.GUID, Vector3.Zero, 0f)) sendResponse(ObjectDetachMessage(player.GUID, box.GUID, Vector3.Zero, 0f)) obj.Inventory -= x.start //remove replacement ammo from inventory - val ammoSlotIndex = tool.FireMode.AmmoSlotIndex + val ammoSlotIndex = tool.FireMode.AmmoSlotIndex tool.AmmoSlots(ammoSlotIndex).Box = box //put replacement ammo in tool sendResponse(ObjectAttachMessage(tool.GUID, box.GUID, ammoSlotIndex))