From ba49b5859ece7bbb53e7085f9478cacec67b63de Mon Sep 17 00:00:00 2001 From: FateJH Date: Tue, 8 May 2018 23:55:01 -0400 Subject: [PATCH 1/2] replenishing supply of thrown grenades from player inventory; pulled in locker search for Player.Find to avoid wrongful indexing --- .../scala/net/psforever/objects/Player.scala | 5 +- .../src/main/scala/WorldSessionActor.scala | 55 ++++++++++++++++++- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/common/src/main/scala/net/psforever/objects/Player.scala b/common/src/main/scala/net/psforever/objects/Player.scala index 1250051b..35e88540 100644 --- a/common/src/main/scala/net/psforever/objects/Player.scala +++ b/common/src/main/scala/net/psforever/objects/Player.scala @@ -200,10 +200,7 @@ class Player(private val core : Avatar) extends PlanetSideGameObject with Factio case Some(index) => Some(index) case None => - if(Locker.Find(guid).isDefined) { - Some(5) - } - else if(freeHand.Equipment.isDefined && freeHand.Equipment.get.GUID == guid) { + if(freeHand.Equipment.isDefined && freeHand.Equipment.get.GUID == guid) { Some(Player.FreeHandSlot) } else { diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index 72b3e1e3..d0735260 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -3263,6 +3263,29 @@ class WorldSessionActor extends Actor with MDCContextAware { previousAmount < desiredAmount }) } + def FindRestock(obj : Container, filterTest : (Equipment)=>Boolean, desiredAmount : Int) : List[InventoryItem] = { + var currentAmount : Int = 0 + obj.Inventory.Items + .map({ case ((_, item)) => item }) + .filter(obj => filterTest(obj.obj)) + .toList + .sortBy(_.start) + .takeWhile(entry => { + val previousAmount = currentAmount + currentAmount += (entry.obj match { + case obj : AmmoBox => + obj.Capacity + case obj : Tool => + if(GlobalDefinitions.isGrenade(obj.Definition)) { + obj.Magazine + } + else { + 1 + } + }) + previousAmount < desiredAmount + }) + } /** * Given an object that contains a box of amunition in its `Inventory` at a certain location, @@ -3404,13 +3427,43 @@ class WorldSessionActor extends Actor with MDCContextAware { //TODO this is temporary and will be replaced by more appropriate functionality in the future. val tdef = tool.Definition if(GlobalDefinitions.isGrenade(tdef)) { - taskResolver ! RemoveEquipmentFromSlot(player, tool, player.Find(tool).get) + val findGrenades : (Equipment)=>Boolean = FindGrenadesLike(tool.AmmoType) + FindRestock(player, findGrenades, 3) match { + case Nil => + taskResolver ! RemoveEquipmentFromSlot(player, tool, player.Find(tool).get) + + case x :: xs => //this is similar to ReloadMessage + val box = x.obj.asInstanceOf[Tool] + val tailReloadValue : Int = if(xs.isEmpty) { 0 } else { xs.map(_.obj.asInstanceOf[Tool].Magazine).reduce(_ + _) } + val sumReloadValue : Int = box.Magazine + tailReloadValue + val actualReloadValue = (if(sumReloadValue <= 3) { + taskResolver ! RemoveEquipmentFromSlot(player, x.obj, x.start) + sumReloadValue + } + else { + ModifyAmmunition(player)(box.AmmoSlot.Box, 3 - tailReloadValue) + 3 + }) + ModifyAmmunition(player)(tool.AmmoSlot.Box, -actualReloadValue) //grenades already in holster (negative because empty) + xs.foreach(item => { + taskResolver ! RemoveEquipmentFromSlot(player, item.obj, item.start) + }) + } } else if(tdef == GlobalDefinitions.phoenix) { taskResolver ! RemoveEquipmentFromSlot(player, tool, player.Find(tool).get) } } + def FindGrenadesLike(grenadeType : Ammo.Value)(e : Equipment) : Boolean = { + e match { + case t : Tool => + t.AmmoType == grenadeType + case _ => + false + } + } + /** * A predicate used to determine if an `InventoryItem` object contains `Equipment` that should be dropped. * Used to filter through lists of object data before it is placed into a player's inventory. From 526ab7d5ec7238ce0d9e37e02a2cb6667446d88b Mon Sep 17 00:00:00 2001 From: FateJH Date: Wed, 9 May 2018 11:50:20 -0400 Subject: [PATCH 2/2] Removed duplicate code by moving the logic of Container around; removed duplicate code by producing a functional inventory search algorithm that handles both ammunition and weapon magazine options; corrected tests --- .../psforever/objects/LockerContainer.scala | 39 +---- .../scala/net/psforever/objects/Player.scala | 21 +-- .../scala/net/psforever/objects/Vehicle.scala | 37 +---- .../objects/inventory/Container.scala | 21 ++- .../objects/inventory/GridInventory.scala | 17 +- .../test/scala/objects/ContainerTest.scala | 28 +--- .../src/test/scala/objects/PlayerTest.scala | 2 +- .../src/main/scala/WorldSessionActor.scala | 148 +++++++++++------- 8 files changed, 140 insertions(+), 173 deletions(-) diff --git a/common/src/main/scala/net/psforever/objects/LockerContainer.scala b/common/src/main/scala/net/psforever/objects/LockerContainer.scala index 0282b8a3..f8b0de83 100644 --- a/common/src/main/scala/net/psforever/objects/LockerContainer.scala +++ b/common/src/main/scala/net/psforever/objects/LockerContainer.scala @@ -3,10 +3,7 @@ package net.psforever.objects import net.psforever.objects.definition.EquipmentDefinition import net.psforever.objects.equipment.Equipment -import net.psforever.objects.inventory.{Container, GridInventory, InventoryItem} -import net.psforever.packet.game.PlanetSideGUID - -import scala.annotation.tailrec +import net.psforever.objects.inventory.{Container, GridInventory} /** * The companion of a `Locker` that is carried with a player @@ -21,42 +18,8 @@ class LockerContainer extends Equipment with Container { def VisibleSlots : Set[Int] = Set.empty[Int] - override def Slot(slot : Int) : EquipmentSlot = { - if(inventory.Offset <= slot && slot <= inventory.LastIndex) { - inventory.Slot(slot) - } - else { - OffhandEquipmentSlot.BlockedSlot - } - } - - def Fit(obj : Equipment) : Option[Int] = inventory.Fit(obj.Definition.Tile) - def Find(guid : PlanetSideGUID) : Option[Int] = { - findInInventory(inventory.Items.values.iterator, guid) match { - case Some(index) => - Some(index) - case None => - None - } - } - - @tailrec private def findInInventory(iter : Iterator[InventoryItem], guid : PlanetSideGUID) : Option[Int] = { - if(!iter.hasNext) { - None - } - else { - val item = iter.next - if(item.obj.GUID == guid) { - Some(item.start) - } - else { - findInInventory(iter, guid) - } - } - } - def Definition : EquipmentDefinition = GlobalDefinitions.locker_container } diff --git a/common/src/main/scala/net/psforever/objects/Player.scala b/common/src/main/scala/net/psforever/objects/Player.scala index 35e88540..3a36445c 100644 --- a/common/src/main/scala/net/psforever/objects/Player.scala +++ b/common/src/main/scala/net/psforever/objects/Player.scala @@ -192,11 +192,9 @@ class Player(private val core : Avatar) extends PlanetSideGameObject with Factio FreeHand.Equipment } - def Find(obj : Equipment) : Option[Int] = Find(obj.GUID) - - def Find(guid : PlanetSideGUID) : Option[Int] = { + override def Find(guid : PlanetSideGUID) : Option[Int] = { findInHolsters(holsters.iterator, guid) - .orElse(findInInventory(inventory.Items.values.iterator, guid)) match { + .orElse(inventory.Find(guid)) match { case Some(index) => Some(index) case None => @@ -224,21 +222,6 @@ class Player(private val core : Avatar) extends PlanetSideGameObject with Factio } } - @tailrec private def findInInventory(iter : Iterator[InventoryItem], guid : PlanetSideGUID) : Option[Int] = { - if(!iter.hasNext) { - None - } - else { - val item = iter.next - if(item.obj.GUID == guid) { - Some(item.start) - } - else { - findInInventory(iter, guid) - } - } - } - override def Collisions(dest : Int, width : Int, height : Int) : Try[List[InventoryItem]] = { if(-1 < dest && dest < 5) { holsters(dest).Equipment match { diff --git a/common/src/main/scala/net/psforever/objects/Vehicle.scala b/common/src/main/scala/net/psforever/objects/Vehicle.scala index 13854707..3aaa32eb 100644 --- a/common/src/main/scala/net/psforever/objects/Vehicle.scala +++ b/common/src/main/scala/net/psforever/objects/Vehicle.scala @@ -3,7 +3,7 @@ package net.psforever.objects import net.psforever.objects.definition.VehicleDefinition import net.psforever.objects.equipment.{Equipment, EquipmentSize} -import net.psforever.objects.inventory.{Container, GridInventory, InventoryItem, InventoryTile} +import net.psforever.objects.inventory.{Container, GridInventory, InventoryTile} import net.psforever.objects.serverobject.mount.Mountable import net.psforever.objects.serverobject.PlanetSideServerObject import net.psforever.objects.serverobject.affinity.FactionAffinity @@ -347,43 +347,8 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends PlanetSideServ def Inventory : GridInventory = trunk - def Find(obj : Equipment) : Option[Int] = Find(obj.GUID) - - def Find(guid : PlanetSideGUID) : Option[Int] = { - findInInventory(Inventory.Items.values.iterator, guid) match { - case Some(index) => - Some(index) - case None => - None - } - } - - @tailrec private def findInInventory(iter : Iterator[InventoryItem], guid : PlanetSideGUID) : Option[Int] = { - if(!iter.hasNext) { - None - } - else { - val item = iter.next - if(item.obj.GUID == guid) { - Some(item.start) - } - else { - findInInventory(iter, guid) - } - } - } - def VisibleSlots : Set[Int] = weapons.keySet - override def Slot(slot : Int) : EquipmentSlot = { - if(Inventory.Offset <= slot && slot <= Inventory.LastIndex) { - Inventory.Slot(slot) - } - else { - OffhandEquipmentSlot.BlockedSlot - } - } - /** * A reference to the `Vehicle` `Trunk` space. * @return this `Vehicle` `Trunk` diff --git a/common/src/main/scala/net/psforever/objects/inventory/Container.scala b/common/src/main/scala/net/psforever/objects/inventory/Container.scala index 4520e35c..e216c5fd 100644 --- a/common/src/main/scala/net/psforever/objects/inventory/Container.scala +++ b/common/src/main/scala/net/psforever/objects/inventory/Container.scala @@ -1,6 +1,7 @@ // Copyright (c) 2017 PSForever package net.psforever.objects.inventory +import net.psforever.objects.equipment.Equipment import net.psforever.objects.{EquipmentSlot, OffhandEquipmentSlot} import net.psforever.packet.game.PlanetSideGUID @@ -20,17 +21,26 @@ trait Container { * A(n imperfect) reference to a generalized pool of the contained objects. * Having access to all of the available positions is not required. * The entries in this reference should definitely include all unseen positions. + * The `GridInventory` returned by this accessor is also an implementation of `Container`. * @see `VisibleSlots` */ def Inventory : GridInventory + /** + * Given an object, attempt to locate its slot. + * All positions, `VisibleSlot` and `Inventory`, and wherever else, should be searchable. + * @param obj the `Equipment` object + * @return the index of the `EquipmentSlot`, or `None` + */ + def Find(obj : Equipment) : Option[Int] = Find(obj.GUID) + /** * Given globally unique identifier, if the object using it is stowed, attempt to locate its slot. * All positions, `VisibleSlot` and `Inventory`, and wherever else, should be searchable. * @param guid the GUID of the `Equipment` * @return the index of the `EquipmentSlot`, or `None` */ - def Find(guid : PlanetSideGUID) : Option[Int] + def Find(guid : PlanetSideGUID) : Option[Int] = Inventory.Find(guid) /** * A(n imperfect) reference to a generalized pool of the contained objects.
@@ -53,7 +63,14 @@ trait Container { * @param slotNum an index * @return the searchable position identified by that index */ - def Slot(slotNum : Int) : EquipmentSlot = OffhandEquipmentSlot.BlockedSlot + def Slot(slotNum : Int) : EquipmentSlot = { + if(Inventory.Offset <= slotNum && slotNum <= Inventory.LastIndex) { + Inventory.Slot(slotNum) + } + else { + OffhandEquipmentSlot.BlockedSlot + } + } /** * Given a region of "searchable unit positions" considered as stowable, diff --git a/common/src/main/scala/net/psforever/objects/inventory/GridInventory.scala b/common/src/main/scala/net/psforever/objects/inventory/GridInventory.scala index f5db0b38..a6008cb9 100644 --- a/common/src/main/scala/net/psforever/objects/inventory/GridInventory.scala +++ b/common/src/main/scala/net/psforever/objects/inventory/GridInventory.scala @@ -28,7 +28,7 @@ import scala.util.{Failure, Success, Try} * The `Array` of spatial GUIDs is used for quick collision lookup. * Use of the `Array` only is hitherto referred as "using the inventory as a grid." */ -class GridInventory { +class GridInventory extends Container { private var width : Int = 1 private var height : Int = 1 private var offset : Int = 0 //the effective index of the first cell in the inventory where offset >= 0 @@ -83,12 +83,21 @@ class GridInventory { */ def LastIndex : Int = Offset + TotalCapacity - 1 + override def Find(guid : PlanetSideGUID) : Option[Int] = { + items.values.find({ case InventoryItem(obj, _) => obj.HasGUID && obj.GUID == guid}) match { + case Some(InventoryItem(_, index)) => + Some(index) + case None => + None + } + } + /** * Get whatever is stowed in the inventory at the given index. * @param slot the cell index * @return an `EquipmentSlot` that contains whatever `Equipment` was stored in `slot` */ - def Slot(slot : Int) : EquipmentSlot = { + override def Slot(slot : Int) : EquipmentSlot = { val actualSlot = slot - offset if(actualSlot < 0 || actualSlot > grid.length) { throw new IndexOutOfBoundsException(s"requested indices not in bounds of grid inventory - $actualSlot") @@ -426,6 +435,10 @@ class GridInventory { height = h grid = Array.fill[Int](w * h)(-1) } + + def VisibleSlots : Set[Int] = Set.empty[Int] + + def Inventory = this } object GridInventory { diff --git a/common/src/test/scala/objects/ContainerTest.scala b/common/src/test/scala/objects/ContainerTest.scala index 2ace560c..a34e6693 100644 --- a/common/src/test/scala/objects/ContainerTest.scala +++ b/common/src/test/scala/objects/ContainerTest.scala @@ -1,8 +1,9 @@ // Copyright (c) 2017 PSForever package objects -import net.psforever.objects.inventory.{Container, GridInventory, InventoryItem} -import net.psforever.objects.{GlobalDefinitions, OffhandEquipmentSlot, Tool} +import net.psforever.objects.equipment.EquipmentSize +import net.psforever.objects.inventory.{Container, GridInventory, InventoryEquipmentSlot} +import net.psforever.objects.{EquipmentSlot, GlobalDefinitions, OffhandEquipmentSlot, Tool} import net.psforever.packet.game.PlanetSideGUID import org.specs2.mutable._ @@ -16,7 +17,11 @@ class ContainerTest extends Specification { obj.Inventory.Size mustEqual 0 obj.Inventory.Capacity mustEqual 9 obj.Find(PlanetSideGUID(0)) mustEqual None - obj.Slot(0) mustEqual OffhandEquipmentSlot.BlockedSlot + obj.Slot(0).isInstanceOf[OffhandEquipmentSlot] mustEqual true + obj.Slot(0).isInstanceOf[InventoryEquipmentSlot] mustEqual true + obj.Slot(0).isInstanceOf[EquipmentSlot] mustEqual true + obj.Slot(0).Size mustEqual EquipmentSize.Inventory + obj.Slot(0).Equipment mustEqual None obj.Collisions(0, 2, 2) mustEqual Success(List()) } @@ -49,23 +54,6 @@ object ContainerTest { def Inventory : GridInventory = inv - def Find(guid : PlanetSideGUID) : Option[Int] = { - Inventory.Items.find({ - case((_, item)) => - if(item.obj.HasGUID) { - item.obj.GUID == guid - } - else { - false - } - }) match { - case Some((index, _)) => - Some(index) - case None => - None - } - } - def VisibleSlots :Set[Int] = Set[Int](0,1,2, 3,4,5, 6,7,8) } } diff --git a/common/src/test/scala/objects/PlayerTest.scala b/common/src/test/scala/objects/PlayerTest.scala index dd9771cb..ff9501be 100644 --- a/common/src/test/scala/objects/PlayerTest.scala +++ b/common/src/test/scala/objects/PlayerTest.scala @@ -303,7 +303,7 @@ class PlayerTest extends Specification { obj.Find(PlanetSideGUID(1)) mustEqual Some(0) //holsters obj.Find(PlanetSideGUID(2)) mustEqual Some(4) //holsters, melee obj.Find(PlanetSideGUID(3)) mustEqual Some(6) //inventory - obj.Find(PlanetSideGUID(4)) mustEqual Some(Player.LockerSlot) //locker-space + obj.Find(PlanetSideGUID(4)) mustEqual None //can not find in locker-space obj.Find(PlanetSideGUID(5)) mustEqual Some(Player.FreeHandSlot) //free hand obj.Find(PlanetSideGUID(6)) mustEqual None //not here } diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index d0735260..4b55c25d 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -1728,7 +1728,7 @@ class WorldSessionActor extends Actor with MDCContextAware { do { val requestedAmmoType = tool.NextAmmoType if(requestedAmmoType != tool.AmmoSlot.Box.AmmoType) { - FindReloadAmmunition(obj, requestedAmmoType, fullMagazine).reverse match { + FindEquipmentStock(obj, FindAmmoBoxThatUses(requestedAmmoType), fullMagazine, CountAmmunition).reverse match { case Nil => ; case x :: xs => val (deleteFunc, modifyFunc) : ((Int, AmmoBox)=>Unit, (AmmoBox, Int)=>Unit) = obj match { @@ -1947,10 +1947,10 @@ class WorldSessionActor extends Actor with MDCContextAware { val magazineSize : Int = tool.MaxMagazine val reloadValue : Int = magazineSize - currentMagazine if(magazineSize > 0 && reloadValue > 0) { - FindReloadAmmunition(obj, tool.AmmoType, reloadValue).reverse match { + FindEquipmentStock(obj, FindAmmoBoxThatUses(tool.AmmoType), reloadValue, CountAmmunition).reverse match { case Nil => log.warn(s"ReloadMessage: no ammunition could be found for $item_guid") - case list @ x :: xs => + case x :: xs => val (deleteFunc, modifyFunc) : ((Int, AmmoBox)=>Unit, (AmmoBox, Int)=>Unit) = obj match { case (veh : Vehicle) => (DeleteAmmunitionInVehicle(veh), ModifyAmmunitionInVehicle(veh)) @@ -3233,58 +3233,103 @@ class WorldSessionActor extends Actor with MDCContextAware { def FindWeapon : Option[Tool] = FindContainedWeapon._2 /** - * Within a specified `Container`, find the smallest number of `AmmoBox` objects of a certain type of `Ammo` - * whose sum capacities is greater than, or equal to, a `desiredAmount`.
+ * Within a specified `Container`, find the smallest number of `Equipment` objects of a certain qualifying type + * whose sum count is greater than, or equal to, a `desiredAmount` based on an accumulator method.
*
- * In an occupied `List` of returned `Inventory` entries, all but the last entry is considered emptied. - * The last entry may require having its `Capacity` be set to a non-zero number. + * In an occupied `List` of returned `Inventory` entries, all but the last entry is typically considered "emptied." + * For objects with contained quantities, the last entry may require having that quantity be set to a non-zero number. * @param obj the `Container` to search - * @param ammoType the type of `Ammo` to search for - * @param desiredAmount how much ammunition is requested to be found - * @return a `List` of all discovered entries totaling approximately the amount of the requested `Ammo` + * @param filterTest test used to determine inclusivity of `Equipment` collection + * @param desiredAmount how much is requested + * @param counting test used to determine value of found `Equipment`; + * defaults to one per entry + * @return a `List` of all discovered entries totaling approximately the amount requested */ - def FindReloadAmmunition(obj : Container, ammoType : Ammo.Value, desiredAmount : Int) : List[InventoryItem] = { + def FindEquipmentStock(obj : Container, + filterTest : (Equipment)=>Boolean, + desiredAmount : Int, + counting : (Equipment)=>Int = DefaultCount) : List[InventoryItem] = { var currentAmount : Int = 0 obj.Inventory.Items .map({ case ((_, item)) => item }) - .filter(obj => { - obj.obj match { - case (box : AmmoBox) => - box.AmmoType == ammoType - case _ => - false - } - }) + .filter(item => filterTest(item.obj)) .toList .sortBy(_.start) .takeWhile(entry => { val previousAmount = currentAmount - currentAmount += entry.obj.asInstanceOf[AmmoBox].Capacity + currentAmount += counting(entry.obj) previousAmount < desiredAmount }) } - def FindRestock(obj : Container, filterTest : (Equipment)=>Boolean, desiredAmount : Int) : List[InventoryItem] = { - var currentAmount : Int = 0 - obj.Inventory.Items - .map({ case ((_, item)) => item }) - .filter(obj => filterTest(obj.obj)) - .toList - .sortBy(_.start) - .takeWhile(entry => { - val previousAmount = currentAmount - currentAmount += (entry.obj match { - case obj : AmmoBox => - obj.Capacity - case obj : Tool => - if(GlobalDefinitions.isGrenade(obj.Definition)) { - obj.Magazine - } - else { - 1 - } - }) - previousAmount < desiredAmount - }) + + /** + * The default counting function for an item. + * Counts the number of item(s). + * @param e the `Equipment` object + * @return the quantity; + * always one + */ + def DefaultCount(e : Equipment) : Int = 1 + + /** + * The counting function for an item of `AmmoBox`. + * Counts the `Capacity` of the ammunition. + * @param e the `Equipment` object + * @return the quantity + */ + def CountAmmunition(e : Equipment) : Int = { + e match { + case a : AmmoBox => + a.Capacity + case _ => + 0 + } + } + + /** + * The counting function for an item of `Tool` where the item is also a grenade. + * Counts the number of grenades. + * @see `GlobalDefinitions.isGrenade` + * @param e the `Equipment` object + * @return the quantity + */ + def CountGrenades(e : Equipment) : Int = { + e match { + case t : Tool => + (GlobalDefinitions.isGrenade(t.Definition):Int) * t.Magazine + case _ => + 0 + } + } + + /** + * Flag an `AmmoBox` object that matches for the given ammunition type. + * @param ammo the type of `Ammo` to check + * @param e the `Equipment` object + * @return `true`, if the object is an `AmmoBox` of the correct ammunition type; `false`, otherwise + */ + def FindAmmoBoxThatUses(ammo : Ammo.Value)(e : Equipment) : Boolean = { + e match { + case t : AmmoBox => + t.AmmoType == ammo + case _ => + false + } + } + + /** + * Flag a `Tool` object that matches for loading the given ammunition type. + * @param ammo the type of `Ammo` to check + * @param e the `Equipment` object + * @return `true`, if the object is a `Tool` that loads the correct ammunition type; `false`, otherwise + */ + def FindToolThatUses(ammo : Ammo.Value)(e : Equipment) : Boolean = { + e match { + case t : Tool => + t.Definition.AmmoTypes.map { _.AmmoType }.contains(ammo) + case _ => + false + } } /** @@ -3427,9 +3472,10 @@ class WorldSessionActor extends Actor with MDCContextAware { //TODO this is temporary and will be replaced by more appropriate functionality in the future. val tdef = tool.Definition if(GlobalDefinitions.isGrenade(tdef)) { - val findGrenades : (Equipment)=>Boolean = FindGrenadesLike(tool.AmmoType) - FindRestock(player, findGrenades, 3) match { + val ammoType = tool.AmmoType + FindEquipmentStock(player, FindToolThatUses(ammoType), 3, CountGrenades).reverse match { //do not search sidearm holsters case Nil => + log.info(s"no more $ammoType grenades") taskResolver ! RemoveEquipmentFromSlot(player, tool, player.Find(tool).get) case x :: xs => //this is similar to ReloadMessage @@ -3444,7 +3490,8 @@ class WorldSessionActor extends Actor with MDCContextAware { ModifyAmmunition(player)(box.AmmoSlot.Box, 3 - tailReloadValue) 3 }) - ModifyAmmunition(player)(tool.AmmoSlot.Box, -actualReloadValue) //grenades already in holster (negative because empty) + log.info(s"found $actualReloadValue more $ammoType grenades to throw") + ModifyAmmunition(player)(tool.AmmoSlot.Box, -actualReloadValue) //grenade item already in holster (negative because empty) xs.foreach(item => { taskResolver ! RemoveEquipmentFromSlot(player, item.obj, item.start) }) @@ -3455,15 +3502,6 @@ class WorldSessionActor extends Actor with MDCContextAware { } } - def FindGrenadesLike(grenadeType : Ammo.Value)(e : Equipment) : Boolean = { - e match { - case t : Tool => - t.AmmoType == grenadeType - case _ => - false - } - } - /** * A predicate used to determine if an `InventoryItem` object contains `Equipment` that should be dropped. * Used to filter through lists of object data before it is placed into a player's inventory. @@ -3679,7 +3717,7 @@ class WorldSessionActor extends Actor with MDCContextAware { /** * An event has occurred that would cause the player character to stop certain stateful activities. - * These activities include shooting, weapon drawing, hacking, accessing (a container), flying, and running. + * These activities include shooting, the weapon being drawn, hacking, accessing (a container), flying, and running. * Other players in the same zone must be made aware that the player has stopped as well.
*
* Things whose configuration should not be changed: