mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-20 02:24:45 +00:00
commit
d6325d8dfc
|
|
@ -45,7 +45,7 @@ object AmmoBox {
|
||||||
*/
|
*/
|
||||||
def Split(box : AmmoBox) : List[AmmoBox] = {
|
def Split(box : AmmoBox) : List[AmmoBox] = {
|
||||||
val ammoDef = box.Definition
|
val ammoDef = box.Definition
|
||||||
var boxCap : Int = box.Capacity
|
val boxCap : Int = box.Capacity
|
||||||
val maxCap : Int = ammoDef.Capacity
|
val maxCap : Int = ammoDef.Capacity
|
||||||
val splitCap : Int = boxCap / maxCap
|
val splitCap : Int = boxCap / maxCap
|
||||||
val list : List[AmmoBox] = List.fill(splitCap)(new AmmoBox(ammoDef))
|
val list : List[AmmoBox] = List.fill(splitCap)(new AmmoBox(ammoDef))
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,12 @@ class Avatar(val name : String, val faction : PlanetSideEmpire.Value, val sex :
|
||||||
private val implants : Array[ImplantSlot] = Array.fill[ImplantSlot](3)(new ImplantSlot)
|
private val implants : Array[ImplantSlot] = Array.fill[ImplantSlot](3)(new ImplantSlot)
|
||||||
/** Loadouts */
|
/** Loadouts */
|
||||||
private val loadouts : Array[Option[Loadout]] = Array.fill[Option[Loadout]](10)(None)
|
private val loadouts : Array[Option[Loadout]] = Array.fill[Option[Loadout]](10)(None)
|
||||||
/** Locker (fifth inventory slot) */
|
/** Locker (inventory slot number five) */
|
||||||
private val locker : LockerContainer = LockerContainer()
|
private val locker : LockerContainer = new LockerContainer() {
|
||||||
|
override def toString : String = {
|
||||||
|
s"$name's ${Definition.Name}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def BEP : Long = bep
|
def BEP : Long = bep
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,11 +28,4 @@ object ConstructionItem {
|
||||||
def apply(cItemDef : ConstructionItemDefinition) : ConstructionItem = {
|
def apply(cItemDef : ConstructionItemDefinition) : ConstructionItem = {
|
||||||
new ConstructionItem(cItemDef)
|
new ConstructionItem(cItemDef)
|
||||||
}
|
}
|
||||||
|
|
||||||
import net.psforever.packet.game.PlanetSideGUID
|
|
||||||
def apply(guid : PlanetSideGUID, cItemDef : ConstructionItemDefinition) : ConstructionItem = {
|
|
||||||
val obj = new ConstructionItem(cItemDef)
|
|
||||||
obj.GUID = guid
|
|
||||||
obj
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -16,11 +16,4 @@ object Kit {
|
||||||
def apply(kitDef : KitDefinition) : Kit = {
|
def apply(kitDef : KitDefinition) : Kit = {
|
||||||
new Kit(kitDef)
|
new Kit(kitDef)
|
||||||
}
|
}
|
||||||
|
|
||||||
import net.psforever.packet.game.PlanetSideGUID
|
|
||||||
def apply(guid : PlanetSideGUID, kitDef : KitDefinition) : Kit = {
|
|
||||||
val obj = new Kit(kitDef)
|
|
||||||
obj.GUID = guid
|
|
||||||
obj
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,6 @@ class LockerContainer extends Equipment with Container {
|
||||||
|
|
||||||
def VisibleSlots : Set[Int] = Set.empty[Int]
|
def VisibleSlots : Set[Int] = Set.empty[Int]
|
||||||
|
|
||||||
def Fit(obj : Equipment) : Option[Int] = inventory.Fit(obj.Definition.Tile)
|
|
||||||
|
|
||||||
def Definition : EquipmentDefinition = GlobalDefinitions.locker_container
|
def Definition : EquipmentDefinition = GlobalDefinitions.locker_container
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ abstract class PlanetSideGameObject extends IdentifiableEntity with WorldEntity
|
||||||
|
|
||||||
object PlanetSideGameObject {
|
object PlanetSideGameObject {
|
||||||
def toString(obj : PlanetSideGameObject) : String = {
|
def toString(obj : PlanetSideGameObject) : String = {
|
||||||
val guid : String = try { obj.GUID.guid.toString } catch { case _ : Exception => "NOGUID" }
|
val guid : String = if(obj.HasGUID) { obj.GUID.toString } else { "NOGUID" }
|
||||||
val P = obj.Position
|
val P = obj.Position
|
||||||
s"[$guid](x,y,z=${P.x%.3f},${P.y%.3f},${P.z%.3f})"
|
s"[$guid](x,y,z=${P.x%.3f},${P.y%.3f},${P.z%.3f})"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ class Player(private val core : Avatar) extends PlanetSideGameObject with Factio
|
||||||
|
|
||||||
def Locker : LockerContainer = core.Locker
|
def Locker : LockerContainer = core.Locker
|
||||||
|
|
||||||
def Fit(obj : Equipment) : Option[Int] = {
|
override def Fit(obj : Equipment) : Option[Int] = {
|
||||||
recursiveHolsterFit(holsters.iterator, obj.Size) match {
|
recursiveHolsterFit(holsters.iterator, obj.Size) match {
|
||||||
case Some(index) =>
|
case Some(index) =>
|
||||||
Some(index)
|
Some(index)
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,4 @@ object SimpleItem {
|
||||||
def apply(simpDef : SimpleItemDefinition) : SimpleItem = {
|
def apply(simpDef : SimpleItemDefinition) : SimpleItem = {
|
||||||
new SimpleItem(simpDef)
|
new SimpleItem(simpDef)
|
||||||
}
|
}
|
||||||
|
|
||||||
import net.psforever.packet.game.PlanetSideGUID
|
|
||||||
def apply(guid : PlanetSideGUID, simpDef : SimpleItemDefinition) : SimpleItem = {
|
|
||||||
val obj = new SimpleItem(simpDef)
|
|
||||||
obj.GUID = guid
|
|
||||||
obj
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,4 +18,14 @@ abstract class Equipment extends PlanetSideGameObject {
|
||||||
def Tile : InventoryTile = Definition.Tile
|
def Tile : InventoryTile = Definition.Tile
|
||||||
|
|
||||||
def Definition : EquipmentDefinition
|
def Definition : EquipmentDefinition
|
||||||
|
|
||||||
|
override def toString : String = {
|
||||||
|
Equipment.toString(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object Equipment {
|
||||||
|
def toString(obj : Equipment) : String = {
|
||||||
|
obj.Definition.Name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,10 @@ trait Container {
|
||||||
*/
|
*/
|
||||||
def Find(guid : PlanetSideGUID) : Option[Int] = Inventory.Find(guid)
|
def Find(guid : PlanetSideGUID) : Option[Int] = Inventory.Find(guid)
|
||||||
|
|
||||||
|
def Fit(obj : Equipment) : Option[Int] = Fit(obj.Definition.Tile)
|
||||||
|
|
||||||
|
def Fit(tile : InventoryTile) : Option[Int] = Inventory.Fit(tile)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A(n imperfect) reference to a generalized pool of the contained objects.<br>
|
* A(n imperfect) reference to a generalized pool of the contained objects.<br>
|
||||||
* <br>
|
* <br>
|
||||||
|
|
|
||||||
|
|
@ -245,7 +245,7 @@ class GridInventory extends Container {
|
||||||
* @param tile the dimensions of the blank space
|
* @param tile the dimensions of the blank space
|
||||||
* @return the grid index of the upper left corner where equipment to which the `tile` belongs should be placed
|
* @return the grid index of the upper left corner where equipment to which the `tile` belongs should be placed
|
||||||
*/
|
*/
|
||||||
def Fit(tile : InventoryTile) : Option[Int] = {
|
override def Fit(tile : InventoryTile) : Option[Int] = {
|
||||||
val tWidth = tile.Width
|
val tWidth = tile.Width
|
||||||
val tHeight = tile.Height
|
val tHeight = tile.Height
|
||||||
val gridIter = (0 until (grid.length - (tHeight - 1) * width))
|
val gridIter = (0 until (grid.length - (tHeight - 1) * width))
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,20 @@ import scodec.Codec
|
||||||
import scodec.codecs._
|
import scodec.codecs._
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* na
|
* Dispatched by the client when the user right-clicks on a piece of `Equipment`
|
||||||
|
* in an inventory that is not his own backpack
|
||||||
|
* in an attempt to quick-swap that `Equipment` into his inventory.
|
||||||
|
* Examples of this "other" inventory include: corpses, lockers, and vehicle trunks.<br>
|
||||||
|
* <br>
|
||||||
|
* Compared to `MoveItemMessage`, the source location where `item` currently resides is not provided.
|
||||||
|
* Additionally, while the over-all destination is provided, the specific insertion point of the destination is not.
|
||||||
|
* @see `MoveItemMessage`
|
||||||
* @param item_guid the item being taken
|
* @param item_guid the item being taken
|
||||||
* @param target_guid what is taking the item;
|
* @param destination_guid where the item will be placed;
|
||||||
* in general, usually the player who is doing the taking
|
* generally, the player is taking the item
|
||||||
*/
|
*/
|
||||||
final case class LootItemMessage(item_guid : PlanetSideGUID,
|
final case class LootItemMessage(item_guid : PlanetSideGUID,
|
||||||
target_guid : PlanetSideGUID
|
destination_guid : PlanetSideGUID
|
||||||
) extends PlanetSideGamePacket {
|
) extends PlanetSideGamePacket {
|
||||||
type Packet = LootItemMessage
|
type Packet = LootItemMessage
|
||||||
def opcode = GamePacketOpcode.LootItemMessage
|
def opcode = GamePacketOpcode.LootItemMessage
|
||||||
|
|
@ -22,6 +29,6 @@ final case class LootItemMessage(item_guid : PlanetSideGUID,
|
||||||
object LootItemMessage extends Marshallable[LootItemMessage] {
|
object LootItemMessage extends Marshallable[LootItemMessage] {
|
||||||
implicit val codec : Codec[LootItemMessage] = (
|
implicit val codec : Codec[LootItemMessage] = (
|
||||||
("item_guid" | PlanetSideGUID.codec) ::
|
("item_guid" | PlanetSideGUID.codec) ::
|
||||||
("target_guid" | PlanetSideGUID.codec)
|
("destination_guid" | PlanetSideGUID.codec)
|
||||||
).as[LootItemMessage]
|
).as[LootItemMessage]
|
||||||
}
|
}
|
||||||
|
|
@ -90,7 +90,8 @@ class ConverterTest extends Specification {
|
||||||
"Kit" should {
|
"Kit" should {
|
||||||
"convert to packet" in {
|
"convert to packet" in {
|
||||||
val kdef = KitDefinition(Kits.medkit)
|
val kdef = KitDefinition(Kits.medkit)
|
||||||
val obj = Kit(PlanetSideGUID(90), kdef)
|
val obj = Kit(kdef)
|
||||||
|
obj.GUID = PlanetSideGUID(90)
|
||||||
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||||
case Success(pkt) =>
|
case Success(pkt) =>
|
||||||
pkt mustEqual DetailedAmmoBoxData(0, 1)
|
pkt mustEqual DetailedAmmoBoxData(0, 1)
|
||||||
|
|
@ -113,7 +114,8 @@ class ConverterTest extends Specification {
|
||||||
cdef.Modes += DeployedItem.deployable_shield_generator
|
cdef.Modes += DeployedItem.deployable_shield_generator
|
||||||
cdef.Tile = InventoryTile.Tile63
|
cdef.Tile = InventoryTile.Tile63
|
||||||
cdef.Packet = new ACEConverter()
|
cdef.Packet = new ACEConverter()
|
||||||
val obj = ConstructionItem(PlanetSideGUID(90), cdef)
|
val obj = ConstructionItem(cdef)
|
||||||
|
obj.GUID = PlanetSideGUID(90)
|
||||||
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||||
case Success(pkt) =>
|
case Success(pkt) =>
|
||||||
pkt mustEqual DetailedACEData(0)
|
pkt mustEqual DetailedACEData(0)
|
||||||
|
|
@ -134,7 +136,8 @@ class ConverterTest extends Specification {
|
||||||
"convert to packet" in {
|
"convert to packet" in {
|
||||||
val sdef = SimpleItemDefinition(SItem.remote_electronics_kit)
|
val sdef = SimpleItemDefinition(SItem.remote_electronics_kit)
|
||||||
sdef.Packet = new REKConverter()
|
sdef.Packet = new REKConverter()
|
||||||
val obj = SimpleItem(PlanetSideGUID(90), sdef)
|
val obj = SimpleItem(sdef)
|
||||||
|
obj.GUID = PlanetSideGUID(90)
|
||||||
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||||
case Success(pkt) =>
|
case Success(pkt) =>
|
||||||
pkt mustEqual DetailedREKData(8)
|
pkt mustEqual DetailedREKData(8)
|
||||||
|
|
|
||||||
|
|
@ -306,9 +306,9 @@ class InventoryTest extends Specification {
|
||||||
sampleDef63.Tile = InventoryTile.Tile63
|
sampleDef63.Tile = InventoryTile.Tile63
|
||||||
|
|
||||||
val obj : GridInventory = GridInventory(9, 9)
|
val obj : GridInventory = GridInventory(9, 9)
|
||||||
obj += 0 -> SimpleItem(PlanetSideGUID(0), sampleDef22)
|
obj += 0 -> SimpleItem(sampleDef22)
|
||||||
obj += 20 -> SimpleItem(PlanetSideGUID(1), sampleDef63)
|
obj += 20 -> SimpleItem(sampleDef63)
|
||||||
obj += 56 -> SimpleItem(PlanetSideGUID(2), sampleDef33)
|
obj += 56 -> SimpleItem(sampleDef33)
|
||||||
obj.Fit(InventoryTile.Tile33) match {
|
obj.Fit(InventoryTile.Tile33) match {
|
||||||
case Some(x) =>
|
case Some(x) =>
|
||||||
x mustEqual 50
|
x mustEqual 50
|
||||||
|
|
@ -329,14 +329,14 @@ class InventoryTest extends Specification {
|
||||||
sampleDef4.Tile = InventoryTile.Tile63
|
sampleDef4.Tile = InventoryTile.Tile63
|
||||||
|
|
||||||
val list : ListBuffer[InventoryItem] = ListBuffer()
|
val list : ListBuffer[InventoryItem] = ListBuffer()
|
||||||
list += new InventoryItem(SimpleItem(PlanetSideGUID(0), sampleDef2), -1)
|
list += new InventoryItem(SimpleItem(sampleDef2), -1)
|
||||||
list += new InventoryItem(SimpleItem(PlanetSideGUID(1), sampleDef3), -1)
|
list += new InventoryItem(SimpleItem(sampleDef3), -1)
|
||||||
list += new InventoryItem(SimpleItem(PlanetSideGUID(2), sampleDef1), -1)
|
list += new InventoryItem(SimpleItem(sampleDef1), -1)
|
||||||
list += new InventoryItem(SimpleItem(PlanetSideGUID(3), sampleDef4), -1)
|
list += new InventoryItem(SimpleItem(sampleDef4), -1)
|
||||||
list += new InventoryItem(SimpleItem(PlanetSideGUID(4), sampleDef1), -1)
|
list += new InventoryItem(SimpleItem(sampleDef1), -1)
|
||||||
list += new InventoryItem(SimpleItem(PlanetSideGUID(5), sampleDef4), -1)
|
list += new InventoryItem(SimpleItem(sampleDef4), -1)
|
||||||
list += new InventoryItem(SimpleItem(PlanetSideGUID(6), sampleDef2), -1)
|
list += new InventoryItem(SimpleItem(sampleDef2), -1)
|
||||||
list += new InventoryItem(SimpleItem(PlanetSideGUID(7), sampleDef3), -1)
|
list += new InventoryItem(SimpleItem(sampleDef3), -1)
|
||||||
val obj : GridInventory = GridInventory(9, 9)
|
val obj : GridInventory = GridInventory(9, 9)
|
||||||
|
|
||||||
val (elements, out) = GridInventory.recoverInventory(list.toList, obj)
|
val (elements, out) = GridInventory.recoverInventory(list.toList, obj)
|
||||||
|
|
|
||||||
|
|
@ -2113,117 +2113,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
false //abort when too many items at destination or other failure case
|
false //abort when too many items at destination or other failure case
|
||||||
}
|
}
|
||||||
} && indexSlot.Equipment.contains(item)) {
|
} && indexSlot.Equipment.contains(item)) {
|
||||||
log.info(s"MoveItem: $item_guid moved from $source_guid @ $index to $destination_guid @ $dest")
|
PerformMoveItem(item, source, index, destination, dest, destItemEntry)
|
||||||
val player_guid = player.GUID
|
|
||||||
val sourceIsNotDestination : Boolean = source != destination //if source is destination, OCDM style is not required
|
|
||||||
//remove item from source
|
|
||||||
indexSlot.Equipment = None
|
|
||||||
source match {
|
|
||||||
case obj : Vehicle =>
|
|
||||||
vehicleService ! VehicleServiceMessage(s"${obj.Actor}", VehicleAction.UnstowEquipment(player_guid, item_guid))
|
|
||||||
case obj : Player =>
|
|
||||||
if(obj.isBackpack || source.VisibleSlots.contains(index)) { //corpse being looted, or item was in hands
|
|
||||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player_guid, item_guid))
|
|
||||||
}
|
|
||||||
case _ => ;
|
|
||||||
}
|
|
||||||
|
|
||||||
destItemEntry match { //do we have a swap item in the destination slot?
|
|
||||||
case Some(InventoryItem(item2, destIndex)) => //yes, swap
|
|
||||||
//cleanly shuffle items around to avoid losing icons
|
|
||||||
//the next ObjectDetachMessage is necessary to avoid icons being lost, but only as part of this swap
|
|
||||||
sendResponse(ObjectDetachMessage(source_guid, item_guid, Vector3.Zero, 0f, 0f, 0f))
|
|
||||||
val item2_guid = item2.GUID
|
|
||||||
destination.Slot(destIndex).Equipment = None //remove the swap item from destination
|
|
||||||
(indexSlot.Equipment = item2) match {
|
|
||||||
case Some(_) => //item and item2 swapped places successfully
|
|
||||||
log.info(s"MoveItem: $item2_guid swapped to $source_guid @ $index")
|
|
||||||
//remove item2 from destination
|
|
||||||
sendResponse(ObjectDetachMessage(destination_guid, item2_guid, Vector3.Zero, 0f, 0f, 0f))
|
|
||||||
destination match {
|
|
||||||
case obj : Vehicle =>
|
|
||||||
vehicleService ! VehicleServiceMessage(s"${obj.Actor}", VehicleAction.UnstowEquipment(player_guid, item2_guid))
|
|
||||||
case obj : Player =>
|
|
||||||
if(obj.isBackpack || destination.VisibleSlots.contains(dest)) { //corpse being looted, or item was in hands
|
|
||||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player_guid, item2_guid))
|
|
||||||
}
|
|
||||||
case _ => ;
|
|
||||||
}
|
|
||||||
//display item2 in source
|
|
||||||
if(sourceIsNotDestination && player == source) {
|
|
||||||
val objDef = item2.Definition
|
|
||||||
sendResponse(
|
|
||||||
ObjectCreateDetailedMessage(
|
|
||||||
objDef.ObjectId,
|
|
||||||
item2_guid,
|
|
||||||
ObjectCreateMessageParent(source_guid, index),
|
|
||||||
objDef.Packet.DetailedConstructorData(item2).get
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sendResponse(ObjectAttachMessage(source_guid, item2_guid, index))
|
|
||||||
}
|
|
||||||
source match {
|
|
||||||
case obj : Vehicle =>
|
|
||||||
vehicleService ! VehicleServiceMessage(s"${obj.Actor}", VehicleAction.StowEquipment(player_guid, source_guid, index, item2))
|
|
||||||
case obj : Player =>
|
|
||||||
if(source.VisibleSlots.contains(index)) { //item is put in hands
|
|
||||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.EquipmentInHand(player_guid, source_guid, index, item2))
|
|
||||||
}
|
|
||||||
else if(obj.isBackpack) { //corpse being given item
|
|
||||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.StowEquipment(player_guid, source_guid, index, item2))
|
|
||||||
}
|
|
||||||
case _ => ;
|
|
||||||
}
|
|
||||||
|
|
||||||
case None => //item2 does not fit; drop on ground
|
|
||||||
log.info(s"MoveItem: $item2_guid can not fit in swap location; dropping on ground @ ${source.Position}")
|
|
||||||
val pos = source.Position
|
|
||||||
val sourceOrientZ = source.Orientation.z
|
|
||||||
val orient : Vector3 = Vector3(0f, 0f, sourceOrientZ)
|
|
||||||
continent.Actor ! Zone.DropItemOnGround(item2, pos, orient)
|
|
||||||
sendResponse(ObjectDetachMessage(destination_guid, item2_guid, pos, 0f, 0f, sourceOrientZ)) //ground
|
|
||||||
val objDef = item2.Definition
|
|
||||||
destination match {
|
|
||||||
case obj : Vehicle =>
|
|
||||||
vehicleService ! VehicleServiceMessage(s"${obj.Actor}", VehicleAction.UnstowEquipment(player_guid, item2_guid))
|
|
||||||
case _ => ;
|
|
||||||
//Player does not require special case; the act of dropping forces the item and icon to change
|
|
||||||
}
|
|
||||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.EquipmentOnGround(player_guid, pos, orient, objDef.ObjectId, item2_guid, objDef.Packet.ConstructorData(item2).get))
|
|
||||||
}
|
|
||||||
|
|
||||||
case None => ;
|
|
||||||
}
|
|
||||||
//move item into destination slot
|
|
||||||
destination.Slot(dest).Equipment = item
|
|
||||||
if(sourceIsNotDestination && player == destination) {
|
|
||||||
val objDef = item.Definition
|
|
||||||
sendResponse(
|
|
||||||
ObjectCreateDetailedMessage(
|
|
||||||
objDef.ObjectId,
|
|
||||||
item_guid,
|
|
||||||
ObjectCreateMessageParent(destination_guid, dest),
|
|
||||||
objDef.Packet.DetailedConstructorData(item).get
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sendResponse(ObjectAttachMessage(destination_guid, item_guid, dest))
|
|
||||||
}
|
|
||||||
destination match {
|
|
||||||
case obj : Vehicle =>
|
|
||||||
vehicleService ! VehicleServiceMessage(s"${obj.Actor}", VehicleAction.StowEquipment(player_guid, destination_guid, dest, item))
|
|
||||||
case obj : Player =>
|
|
||||||
if(destination.VisibleSlots.contains(dest)) { //item is put in hands
|
|
||||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.EquipmentInHand(player_guid, destination_guid, dest, item))
|
|
||||||
}
|
|
||||||
else if(obj.isBackpack) { //corpse being given item
|
|
||||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.StowEquipment(player_guid, destination_guid, dest, item))
|
|
||||||
}
|
|
||||||
case _ => ;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if(!indexSlot.Equipment.contains(item)) {
|
else if(!indexSlot.Equipment.contains(item)) {
|
||||||
log.error(s"MoveItem: wanted to move $item_guid, but found unexpected ${indexSlot.Equipment.get} at source location")
|
log.error(s"MoveItem: wanted to move $item_guid, but found unexpected ${indexSlot.Equipment.get} at source location")
|
||||||
|
|
@ -2250,7 +2140,39 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
}
|
}
|
||||||
|
|
||||||
case msg @ LootItemMessage(item_guid, target_guid) =>
|
case msg @ LootItemMessage(item_guid, target_guid) =>
|
||||||
log.info("LootItem: " + msg)
|
log.info(s"LootItem: $msg")
|
||||||
|
(continent.GUID(item_guid), continent.GUID(target_guid)) match {
|
||||||
|
case (Some(item : Equipment), Some(target : Container)) =>
|
||||||
|
//figure out the source
|
||||||
|
(
|
||||||
|
{
|
||||||
|
val findFunc : PlanetSideGameObject with Container => Option[(PlanetSideGameObject with Container, Option[Int])] = FindInLocalContainer(item_guid)
|
||||||
|
findFunc(player.Locker)
|
||||||
|
.orElse(findFunc(player))
|
||||||
|
.orElse(accessedContainer match {
|
||||||
|
case Some(parent) =>
|
||||||
|
findFunc(parent)
|
||||||
|
case None =>
|
||||||
|
None
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}, target.Fit(item)) match {
|
||||||
|
case (Some((source, Some(index))), Some(dest)) =>
|
||||||
|
PerformMoveItem(item, source, index, target, dest, None)
|
||||||
|
case (None, _) =>
|
||||||
|
log.error(s"LootItem: can not find where $item is put currently")
|
||||||
|
case (_, None) =>
|
||||||
|
log.error(s"LootItem: can not find somwhere to put $item in $target")
|
||||||
|
case _ =>
|
||||||
|
log.error(s"LootItem: wanted to move $item_guid to $target_guid, but multiple problems were encountered")
|
||||||
|
}
|
||||||
|
case (Some(obj), _) =>
|
||||||
|
log.warn(s"LootItem: item $obj is (probably) not lootable")
|
||||||
|
case (None, _) =>
|
||||||
|
log.warn(s"LootItem: can not find $item_guid")
|
||||||
|
case (_, None) =>
|
||||||
|
log.warn(s"LootItem: can not find where to put $item_guid")
|
||||||
|
}
|
||||||
|
|
||||||
case msg @ AvatarImplantMessage(_, _, _, _) => //(player_guid, unk1, unk2, implant) =>
|
case msg @ AvatarImplantMessage(_, _, _, _) => //(player_guid, unk1, unk2, implant) =>
|
||||||
log.info("AvatarImplantMessage: " + msg)
|
log.info("AvatarImplantMessage: " + msg)
|
||||||
|
|
@ -2286,6 +2208,13 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Some(obj : Player) =>
|
||||||
|
if(obj.isBackpack) {
|
||||||
|
log.info(s"UseItem: $player looting the corpse of $obj")
|
||||||
|
sendResponse(UseItemMessage(avatar_guid, unk1, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))
|
||||||
|
accessedContainer = Some(obj)
|
||||||
|
}
|
||||||
|
|
||||||
case Some(obj : Locker) =>
|
case Some(obj : Locker) =>
|
||||||
if(player.Faction == obj.Faction) {
|
if(player.Faction == obj.Faction) {
|
||||||
log.info(s"UseItem: $player accessing a locker")
|
log.info(s"UseItem: $player accessing a locker")
|
||||||
|
|
@ -2385,7 +2314,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
}
|
}
|
||||||
|
|
||||||
case msg @ UnuseItemMessage(player_guid, object_guid) =>
|
case msg @ UnuseItemMessage(player_guid, object_guid) =>
|
||||||
log.info("UnuseItem: " + msg)
|
log.info(s"UnuseItem: $msg")
|
||||||
|
//TODO check for existing accessedContainer value?
|
||||||
continent.GUID(object_guid) match {
|
continent.GUID(object_guid) match {
|
||||||
case Some(obj : Vehicle) =>
|
case Some(obj : Vehicle) =>
|
||||||
if(obj.AccessingTrunk.contains(player.GUID)) {
|
if(obj.AccessingTrunk.contains(player.GUID)) {
|
||||||
|
|
@ -3485,6 +3415,150 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an item, and two places, one where the item currently is and one where the item will be moved,
|
||||||
|
* perform a controlled transfer of the item.
|
||||||
|
* If something exists at the `destination` side of the transfer in the position that `item` will occupy,
|
||||||
|
* resolve its location as well by swapping it with where `item` originally was positioned.<br>
|
||||||
|
* <br>
|
||||||
|
* Parameter checks will not be performed.
|
||||||
|
* Do perform checks before sending data to this function.
|
||||||
|
* Do not call with incorrect or unverified data, e.g., `item` not actually being at `source` @ `index`.
|
||||||
|
* @param item the item being moved
|
||||||
|
* @param source the container in which `item` is currently located
|
||||||
|
* @param index the index position in `source` where `item` is currently located
|
||||||
|
* @param destination the container where `item` is being moved
|
||||||
|
* @param dest the index position in `destination` where `item` is being moved
|
||||||
|
* @param destinationCollisionEntry information about the contents in an area of `destination` starting at index `dest`
|
||||||
|
*/
|
||||||
|
private def PerformMoveItem(item : Equipment,
|
||||||
|
source : PlanetSideGameObject with Container,
|
||||||
|
index : Int,
|
||||||
|
destination : PlanetSideGameObject with Container,
|
||||||
|
dest : Int,
|
||||||
|
destinationCollisionEntry : Option[InventoryItem]) : Unit = {
|
||||||
|
val item_guid = item.GUID
|
||||||
|
val source_guid = source.GUID
|
||||||
|
val destination_guid = destination.GUID
|
||||||
|
val player_guid = player.GUID
|
||||||
|
val indexSlot = source.Slot(index)
|
||||||
|
val sourceIsNotDestination : Boolean = source != destination //if source is destination, explicit OCDM is not required
|
||||||
|
if(sourceIsNotDestination) {
|
||||||
|
log.info(s"MoveItem: $item moved from $source @ $index to $destination @ $dest")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log.info(s"MoveItem: $item moved from $index to $dest in $source")
|
||||||
|
}
|
||||||
|
//remove item from source
|
||||||
|
indexSlot.Equipment = None
|
||||||
|
source match {
|
||||||
|
case obj : Vehicle =>
|
||||||
|
vehicleService ! VehicleServiceMessage(s"${obj.Actor}", VehicleAction.UnstowEquipment(player_guid, item_guid))
|
||||||
|
case obj : Player =>
|
||||||
|
if(obj.isBackpack || source.VisibleSlots.contains(index)) { //corpse being looted, or item was in hands
|
||||||
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player_guid, item_guid))
|
||||||
|
}
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
|
||||||
|
destinationCollisionEntry match { //do we have a swap item in the destination slot?
|
||||||
|
case Some(InventoryItem(item2, destIndex)) => //yes, swap
|
||||||
|
//cleanly shuffle items around to avoid losing icons
|
||||||
|
//the next ObjectDetachMessage is necessary to avoid icons being lost, but only as part of this swap
|
||||||
|
sendResponse(ObjectDetachMessage(source_guid, item_guid, Vector3.Zero, 0f, 0f, 0f))
|
||||||
|
val item2_guid = item2.GUID
|
||||||
|
destination.Slot(destIndex).Equipment = None //remove the swap item from destination
|
||||||
|
(indexSlot.Equipment = item2) match {
|
||||||
|
case Some(_) => //item and item2 swapped places successfully
|
||||||
|
log.info(s"MoveItem: $item2 swapped to $source @ $index")
|
||||||
|
//remove item2 from destination
|
||||||
|
sendResponse(ObjectDetachMessage(destination_guid, item2_guid, Vector3.Zero, 0f, 0f, 0f))
|
||||||
|
destination match {
|
||||||
|
case obj : Vehicle =>
|
||||||
|
vehicleService ! VehicleServiceMessage(s"${obj.Actor}", VehicleAction.UnstowEquipment(player_guid, item2_guid))
|
||||||
|
case obj : Player =>
|
||||||
|
if(obj.isBackpack || destination.VisibleSlots.contains(dest)) { //corpse being looted, or item was in hands
|
||||||
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player_guid, item2_guid))
|
||||||
|
}
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
//display item2 in source
|
||||||
|
if(sourceIsNotDestination && player == source) {
|
||||||
|
val objDef = item2.Definition
|
||||||
|
sendResponse(
|
||||||
|
ObjectCreateDetailedMessage(
|
||||||
|
objDef.ObjectId,
|
||||||
|
item2_guid,
|
||||||
|
ObjectCreateMessageParent(source_guid, index),
|
||||||
|
objDef.Packet.DetailedConstructorData(item2).get
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sendResponse(ObjectAttachMessage(source_guid, item2_guid, index))
|
||||||
|
}
|
||||||
|
source match {
|
||||||
|
case obj : Vehicle =>
|
||||||
|
vehicleService ! VehicleServiceMessage(s"${obj.Actor}", VehicleAction.StowEquipment(player_guid, source_guid, index, item2))
|
||||||
|
case obj : Player =>
|
||||||
|
if(source.VisibleSlots.contains(index)) { //item is put in hands
|
||||||
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.EquipmentInHand(player_guid, source_guid, index, item2))
|
||||||
|
}
|
||||||
|
else if(obj.isBackpack) { //corpse being given item
|
||||||
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.StowEquipment(player_guid, source_guid, index, item2))
|
||||||
|
}
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
|
||||||
|
case None => //item2 does not fit; drop on ground
|
||||||
|
log.info(s"MoveItem: $item2 can not fit in swap location; dropping on ground @ ${source.Position}")
|
||||||
|
val pos = source.Position
|
||||||
|
val sourceOrientZ = source.Orientation.z
|
||||||
|
val orient : Vector3 = Vector3(0f, 0f, sourceOrientZ)
|
||||||
|
continent.Actor ! Zone.DropItemOnGround(item2, pos, orient)
|
||||||
|
sendResponse(ObjectDetachMessage(destination_guid, item2_guid, pos, 0f, 0f, sourceOrientZ)) //ground
|
||||||
|
val objDef = item2.Definition
|
||||||
|
destination match {
|
||||||
|
case obj : Vehicle =>
|
||||||
|
vehicleService ! VehicleServiceMessage(s"${obj.Actor}", VehicleAction.UnstowEquipment(player_guid, item2_guid))
|
||||||
|
case _ => ;
|
||||||
|
//Player does not require special case; the act of dropping forces the item and icon to change
|
||||||
|
}
|
||||||
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.EquipmentOnGround(player_guid, pos, orient, objDef.ObjectId, item2_guid, objDef.Packet.ConstructorData(item2).get))
|
||||||
|
}
|
||||||
|
|
||||||
|
case None => ;
|
||||||
|
}
|
||||||
|
//move item into destination slot
|
||||||
|
destination.Slot(dest).Equipment = item
|
||||||
|
if(sourceIsNotDestination && player == destination) {
|
||||||
|
val objDef = item.Definition
|
||||||
|
sendResponse(
|
||||||
|
ObjectCreateDetailedMessage(
|
||||||
|
objDef.ObjectId,
|
||||||
|
item_guid,
|
||||||
|
ObjectCreateMessageParent(destination_guid, dest),
|
||||||
|
objDef.Packet.DetailedConstructorData(item).get
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sendResponse(ObjectAttachMessage(destination_guid, item_guid, dest))
|
||||||
|
}
|
||||||
|
destination match {
|
||||||
|
case obj : Vehicle =>
|
||||||
|
vehicleService ! VehicleServiceMessage(s"${obj.Actor}", VehicleAction.StowEquipment(player_guid, destination_guid, dest, item))
|
||||||
|
case obj : Player =>
|
||||||
|
if(destination.VisibleSlots.contains(dest)) { //item is put in hands
|
||||||
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.EquipmentInHand(player_guid, destination_guid, dest, item))
|
||||||
|
}
|
||||||
|
else if(obj.isBackpack) { //corpse being given item
|
||||||
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.StowEquipment(player_guid, destination_guid, dest, item))
|
||||||
|
}
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* After a weapon has finished shooting, determine if it needs to be sorted in a special way.
|
* After a weapon has finished shooting, determine if it needs to be sorted in a special way.
|
||||||
* @param tool a weapon
|
* @param tool a weapon
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue