diff --git a/src/main/scala/net/psforever/actors/session/normal/AvatarHandlerLogic.scala b/src/main/scala/net/psforever/actors/session/normal/AvatarHandlerLogic.scala index bdda54dab..042a3551e 100644 --- a/src/main/scala/net/psforever/actors/session/normal/AvatarHandlerLogic.scala +++ b/src/main/scala/net/psforever/actors/session/normal/AvatarHandlerLogic.scala @@ -3,6 +3,7 @@ package net.psforever.actors.session.normal import akka.actor.{ActorContext, typed} import net.psforever.actors.session.support.AvatarHandlerFunctions +import net.psforever.objects.serverobject.containable.ContainableBehavior import net.psforever.packet.game.{AvatarImplantMessage, CreateShortcutMessage, ImplantAction} import net.psforever.types.ImplantType @@ -295,6 +296,17 @@ class AvatarHandlerLogic(val ops: SessionAvatarHandlers, implicit val context: A case (_, dguid) => sendResponse(ObjectDeleteMessage(dguid, unk1=0)) } //functionally delete + if (delete.size > 1 || delete.nonEmpty && !delete.exists { + case (e: Tool, _) => GlobalDefinitions.isMaxArms(e.Definition) + case _ => false + }) { + /* + if going x -> max, you will have enough space in max inventory for any displaced holster equipment + for max -> max, don't care about the max weapon arm being deleted (allow for 1) + for any other x -> x, any deleted equipment will raise this comment + */ + sendResponse(ChatMsg(ChatMessageType.UNK_227, "@ItemsDeconstructed")) + } delete.foreach { case (obj, _) => TaskWorkflow.execute(GUIDTask.unregisterEquipment(continent.GUID, obj)) } //redraw if (maxhand) { @@ -330,13 +342,17 @@ class AvatarHandlerLogic(val ops: SessionAvatarHandlers, implicit val context: A } DropLeftovers(player)(drop) - case AvatarResponse.ChangeExosuit(target, armor, exosuit, subtype, slot, _, oldHolsters, holsters, _, _, _, delete) => + case AvatarResponse.ChangeExosuit(target, armor, exosuit, subtype, slot, _, oldHolsters, holsters, _, _, drop, delete) => sendResponse(ArmorChangedMessage(target, exosuit, subtype)) sendResponse(PlanetsideAttributeMessage(target, attribute_type=4, armor)) //happening to some other player sendResponse(ObjectHeldMessage(target, slot, unk1 = false)) //cleanup - (oldHolsters ++ delete).foreach { case (_, guid) => sendResponse(ObjectDeleteMessage(guid, unk1=0)) } + val dropPred = ContainableBehavior.DropPredicate(player) + val deleteFromDrop = drop.filterNot(dropPred) + (oldHolsters ++ delete ++ deleteFromDrop.map(f =>(f.obj, f.GUID))) + .distinctBy(_._2) + .foreach { case (_, guid) => sendResponse(ObjectDeleteMessage(guid, unk1=0)) } //draw holsters holsters.foreach { case InventoryItem(obj, index) => diff --git a/src/main/scala/net/psforever/actors/session/normal/ChatLogic.scala b/src/main/scala/net/psforever/actors/session/normal/ChatLogic.scala index dc599e017..e701c0a55 100644 --- a/src/main/scala/net/psforever/actors/session/normal/ChatLogic.scala +++ b/src/main/scala/net/psforever/actors/session/normal/ChatLogic.scala @@ -145,8 +145,11 @@ class ChatLogic(val ops: ChatOperations, implicit val context: ActorContext) ext case (CMT_KICK, _, contents) if gmCommandAllowed => ops.commandKick(session, message, contents) + case (CMT_REPORTUSER, _, contents) => + ops.commandReportUser(session, message, contents) + case _ => - log.warn(s"Unhandled chat message $message") + sendResponse(ChatMsg(ChatMessageType.UNK_227, "@no_permission")) } } diff --git a/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala b/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala index d0a6e8e96..7f9c26c89 100644 --- a/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala +++ b/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala @@ -120,8 +120,9 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex ops.fallHeightTracker(pos.z) if (isCrouching && !player.Crouching) { //dev stuff goes here - sendResponse(ChatMsg(ChatMessageType.UNK_229, "@PadDeconstruct_secsA^23~")) - sendResponse(ChatMsg(ChatMessageType.UNK_227, "@InventoryPickupNoRoom")) + sendResponse(ChatMsg(ChatMessageType.UNK_227, "@NoMount_Permission")) + //sendResponse(ChatMsg(ChatMessageType.UNK_227, "@ArmorShieldOff")) + //sendResponse(ChatMsg(ChatMessageType.UNK_227, "@ArmorShieldOverride")) } player.Position = pos player.Velocity = vel diff --git a/src/main/scala/net/psforever/actors/session/spectator/ChatLogic.scala b/src/main/scala/net/psforever/actors/session/spectator/ChatLogic.scala index 3b7d10edd..a7e5884e2 100644 --- a/src/main/scala/net/psforever/actors/session/spectator/ChatLogic.scala +++ b/src/main/scala/net/psforever/actors/session/spectator/ChatLogic.scala @@ -85,7 +85,11 @@ class ChatLogic(val ops: ChatOperations, implicit val context: ActorContext) ext case (CMT_WARP, _, contents) => ops.commandWarp(session, message, contents) - case _ => () + case (CMT_REPORTUSER, _, contents) => + ops.commandReportUser(session, message, contents) + + case _ => + sendResponse(ChatMsg(ChatMessageType.UNK_227, "@no_permission")) } } diff --git a/src/main/scala/net/psforever/actors/session/support/ChatOperations.scala b/src/main/scala/net/psforever/actors/session/support/ChatOperations.scala index d33fb870e..02efbc7e4 100644 --- a/src/main/scala/net/psforever/actors/session/support/ChatOperations.scala +++ b/src/main/scala/net/psforever/actors/session/support/ChatOperations.scala @@ -649,6 +649,11 @@ class ChatOperations( } } + def commandReportUser(@unused session: Session, @unused message: ChatMsg, @unused contents: String): Unit = { + //todo get user from contents + sendResponse(ChatMsg(ChatMessageType.UNK_227, "@rpt_i")) + } + def commandIncomingSendAllIfOnline(session: Session, message: ChatMsg): Unit = { if (AvatarActor.onlineIfNotIgnored(session.avatar, message.recipient)) { sendResponse(message) diff --git a/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala b/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala index 92655d631..2ef4fa023 100644 --- a/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala +++ b/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala @@ -637,6 +637,7 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm if (player.DrawnSlot != Player.HandsDownSlot) { player.DrawnSlot = Player.HandsDownSlot } + val dropPred = ContainableBehavior.DropPredicate(player) val (toDelete, toDrop, afterHolsters, afterInventory) = if (originalSuit == ExoSuitType.MAX) { //was max val (delete, insert) = beforeHolsters.partition(elem => elem.obj.Size == EquipmentSize.Max) @@ -647,18 +648,21 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm //changing to a vanilla exo-suit val (newHolsters, unplacedHolsters) = Players.fillEmptyHolsters(player.Holsters().iterator, insert ++ beforeInventory) val (inventory, unplacedInventory) = GridInventory.recoverInventory(unplacedHolsters, player.Inventory) - (delete, unplacedInventory.map(InventoryItem(_, -1)), newHolsters, inventory) + val (dropFromUnplaced, deleteFromUnplaced) = unplacedInventory.map(InventoryItem(_, -1)).partition(dropPred) + (delete ++ deleteFromUnplaced, dropFromUnplaced, newHolsters, inventory) } } else if (willBecomeMax) { //will be max, drop everything but melee slot val (melee, other) = beforeHolsters.partition(elem => elem.obj.Size == EquipmentSize.Melee) val (inventory, unplacedInventory) = GridInventory.recoverInventory(beforeInventory ++ other, player.Inventory) - (Nil, unplacedInventory.map(InventoryItem(_, -1)), melee, inventory) + val (dropFromUnplaced, deleteFromUnplaced) = unplacedInventory.map(InventoryItem(_, -1)).partition(dropPred) + (deleteFromUnplaced, dropFromUnplaced, melee, inventory) } else { //was not a max nor will become a max; vanilla exo-suit to a vanilla-exo-suit val (insert, unplacedHolsters) = Players.fillEmptyHolsters(player.Holsters().iterator, beforeHolsters ++ beforeInventory) val (inventory, unplacedInventory) = GridInventory.recoverInventory(unplacedHolsters, player.Inventory) - (Nil, unplacedInventory.map(InventoryItem(_, -1)), insert, inventory) + val (dropFromUnplaced, deleteFromUnplaced) = unplacedInventory.map(InventoryItem(_, -1)).partition(dropPred) + (deleteFromUnplaced, dropFromUnplaced, insert, inventory) } //insert afterHolsters.foreach(elem => player.Slot(elem.start).Equipment = elem.obj) diff --git a/src/main/scala/net/psforever/objects/serverobject/containable/ContainableBehavior.scala b/src/main/scala/net/psforever/objects/serverobject/containable/ContainableBehavior.scala index 76be594b3..d3680de99 100644 --- a/src/main/scala/net/psforever/objects/serverobject/containable/ContainableBehavior.scala +++ b/src/main/scala/net/psforever/objects/serverobject/containable/ContainableBehavior.scala @@ -676,6 +676,7 @@ object ContainableBehavior { entry => { val objDef = entry.obj.Definition val faction = GlobalDefinitions.isFactionEquipment(objDef) + GlobalDefinitions.isCavernEquipment(objDef) || objDef == GlobalDefinitions.router_telepad || entry.obj.isInstanceOf[BoomerTrigger] || (faction != tplayer.Faction && faction != PlanetSideEmpire.NEUTRAL)