mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-02-27 18:43:39 +00:00
synchronized weapon fire, weapon dry fire, reload cycle, and reload of ammunition from inventory contents
This commit is contained in:
parent
26d388d7ff
commit
b292739b54
8 changed files with 237 additions and 31 deletions
|
|
@ -23,11 +23,11 @@ import net.psforever.objects.serverobject.pad.VehicleSpawnPad
|
|||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.objects.vehicles.{AccessPermissionGroup, VehicleLockState}
|
||||
import net.psforever.objects.zones.{InterstellarCluster, Zone}
|
||||
import net.psforever.packet.game.objectcreate.{DetailedCharacterData, _}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types._
|
||||
import services._
|
||||
import services.avatar._
|
||||
import services.local._
|
||||
import services.avatar.{AvatarAction, AvatarResponse, AvatarServiceMessage, AvatarServiceResponse}
|
||||
import services.local.{LocalAction, LocalResponse, LocalServiceMessage, LocalServiceResponse}
|
||||
import services.vehicle.{VehicleAction, VehicleResponse, VehicleServiceMessage, VehicleServiceResponse}
|
||||
|
||||
import scala.annotation.tailrec
|
||||
|
|
@ -47,6 +47,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
var galaxy : ActorRef = Actor.noSender
|
||||
var continent : Zone = null
|
||||
var progressBarValue : Option[Float] = None
|
||||
var shooting : Option[PlanetSideGUID] = None
|
||||
|
||||
var clientKeepAlive : Cancellable = DefaultCancellable.obj
|
||||
var progressBarUpdate : Cancellable = DefaultCancellable.obj
|
||||
|
|
@ -145,6 +146,16 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
sendResponse(PacketCoding.CreateGamePacket(0, ArmorChangedMessage(guid, suit, subtype)))
|
||||
}
|
||||
|
||||
case AvatarResponse.ChangeFireState_Start(weapon_guid) =>
|
||||
if(player.GUID != guid) {
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ChangeFireStateMessage_Start(weapon_guid)))
|
||||
}
|
||||
|
||||
case AvatarResponse.ChangeFireState_Stop(weapon_guid) =>
|
||||
if(player.GUID != guid) {
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ChangeFireStateMessage_Stop(weapon_guid)))
|
||||
}
|
||||
|
||||
case AvatarResponse.ConcealPlayer() =>
|
||||
if(player.GUID != guid) {
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, GenericObjectActionMessage(guid, 36)))
|
||||
|
|
@ -215,7 +226,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
((distanceSq < 900 || weaponInHand) && time > 200) ||
|
||||
(distanceSq < 10000 && time > 500) ||
|
||||
(distanceSq < 160000 && (msg.is_jumping || time < 200)) ||
|
||||
(distanceSq < 160000 && msg.vel.isEmpty && time > 2000) ||
|
||||
(distanceSq < 160000 && (msg.vel.isEmpty || Vector3.MagnitudeSquared(msg.vel.get).toInt == 0) && time > 2000) ||
|
||||
(distanceSq < 160000 && time > 1000) ||
|
||||
(distanceSq > 160000 && time > 5000))
|
||||
{
|
||||
|
|
@ -240,9 +251,14 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
}
|
||||
|
||||
case AvatarResponse.Reload(mag) =>
|
||||
case AvatarResponse.Reload(item_guid) =>
|
||||
if(player.GUID != guid) {
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ReloadMessage(guid, mag, 0)))
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ReloadMessage(item_guid, 1, 0)))
|
||||
}
|
||||
|
||||
case AvatarResponse.WeaponDryFire(weapon_guid) =>
|
||||
if(player.GUID != guid) {
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, WeaponJammedMessage(weapon_guid)))
|
||||
}
|
||||
|
||||
case _ => ;
|
||||
|
|
@ -283,6 +299,20 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
sendResponse(PacketCoding.CreateGamePacket(0, ChildObjectStateMessage(object_guid, pitch, yaw)))
|
||||
}
|
||||
|
||||
case VehicleResponse.InventoryState(obj, parent_guid, start, con_data) =>
|
||||
if(player.GUID != guid) {
|
||||
//TODO prefer ObjectDetachMessage, but how to force ammo pools to update properly?
|
||||
val obj_guid = obj.GUID
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ObjectDeleteMessage(obj_guid, 0)))
|
||||
sendResponse(PacketCoding.CreateGamePacket(0,
|
||||
ObjectCreateDetailedMessage(
|
||||
obj.Definition.ObjectId,
|
||||
obj_guid,
|
||||
ObjectCreateMessageParent(parent_guid, start),
|
||||
con_data)
|
||||
))
|
||||
}
|
||||
|
||||
case VehicleResponse.DismountVehicle(unk1, unk2) =>
|
||||
if(player.GUID != guid) {
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, DismountVehicleMsg(guid, unk1, unk2)))
|
||||
|
|
@ -1306,10 +1336,19 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
|
||||
case msg @ ChangeFireStateMessage_Start(item_guid) =>
|
||||
log.info("ChangeFireState_Start: " + msg)
|
||||
if(shooting.isEmpty) {
|
||||
//TODO check that player can shoot item_guid?
|
||||
shooting = Some(item_guid)
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ChangeFireState_Start(player.GUID, item_guid))
|
||||
}
|
||||
|
||||
case msg @ ChangeFireStateMessage_Stop(item_guid) =>
|
||||
log.info("ChangeFireState_Stop: " + msg)
|
||||
progressBarUpdate.cancel
|
||||
if(shooting.contains(item_guid)) {
|
||||
shooting = None
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ChangeFireState_Stop(player.GUID, item_guid))
|
||||
}
|
||||
progressBarUpdate.cancel //TODO independent action?
|
||||
|
||||
case msg @ EmoteMsg(avatar_guid, emote) =>
|
||||
log.info("Emote: " + msg)
|
||||
|
|
@ -1339,7 +1378,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
|
||||
case msg @ ReloadMessage(item_guid, ammo_clip, unk1) =>
|
||||
log.info("Reload: " + msg)
|
||||
val reloadValue : Int = player.VehicleSeated match {
|
||||
(player.VehicleSeated match {
|
||||
case Some(vehicle_guid) => //weapon is vehicle turret?
|
||||
continent.GUID(vehicle_guid) match {
|
||||
case Some(vehicle : Vehicle) =>
|
||||
|
|
@ -1347,29 +1386,68 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case Some(seat_num) =>
|
||||
vehicle.WeaponControlledFromSeat(seat_num) match {
|
||||
case Some(item : Tool) =>
|
||||
item.FireMode.Magazine
|
||||
//TODO check that item controlled by seat is item_guid?
|
||||
(Some(vehicle), Some(item))
|
||||
case _ => ;
|
||||
0
|
||||
(None, None)
|
||||
}
|
||||
case None => ;
|
||||
0
|
||||
(None, None)
|
||||
}
|
||||
case _ => ;
|
||||
0
|
||||
(None, None)
|
||||
}
|
||||
case None => //not in vehicle; weapon in hand?
|
||||
log.info(s"${player.DrawnSlot} -> ${player.Slot(player.DrawnSlot).Equipment}")
|
||||
player.Slot(player.DrawnSlot).Equipment match {
|
||||
//TODO check that item in hand is item_guid?
|
||||
case Some(item : Tool) =>
|
||||
item.FireMode.Magazine
|
||||
case Some(_) | None => ;
|
||||
0
|
||||
(Some(player), Some(item))
|
||||
case _ => ;
|
||||
(None, None)
|
||||
}
|
||||
}
|
||||
if(reloadValue > 0) {
|
||||
//TODO hunt for ammunition in backpack/trunk
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ReloadMessage(item_guid, reloadValue, unk1)))
|
||||
}) match {
|
||||
case (Some(obj), Some(tool : Tool)) =>
|
||||
val currentMagazine : Int = tool.Magazine
|
||||
val magazineSize : Int = tool.MaxMagazine
|
||||
val reloadValue : Int = magazineSize - currentMagazine
|
||||
if(magazineSize > 0 && reloadValue > 0) {
|
||||
FindReloadAmmunition(obj, tool.AmmoType, reloadValue).reverse match {
|
||||
case Nil =>
|
||||
log.warn(s"ReloadMessage: no ammunition could be found for $item_guid")
|
||||
case list @ x :: xs =>
|
||||
val (deleteFunc, modifyFunc) : ((Int, PlanetSideGUID)=>Unit, (AmmoBox, Int)=>Unit) = obj match {
|
||||
case (veh : Vehicle) =>
|
||||
(DeleteAmmunitionInVehicle(veh), ModifyAmmunitionInVehicle(veh))
|
||||
case _ =>
|
||||
(DeleteAmmunition(obj), ModifyAmmunition(obj))
|
||||
}
|
||||
xs.foreach(item => {
|
||||
deleteFunc(item.start, item.obj.GUID)
|
||||
})
|
||||
val box = x.obj.asInstanceOf[AmmoBox]
|
||||
val tailReloadValue : Int = if(xs.isEmpty) { 0 } else { xs.map(_.obj.asInstanceOf[AmmoBox].Capacity).reduceLeft(_ + _) }
|
||||
val sumReloadValue : Int = box.Capacity + tailReloadValue
|
||||
val actualReloadValue = (if(sumReloadValue <= reloadValue) {
|
||||
deleteFunc(x.start, box.GUID)
|
||||
sumReloadValue
|
||||
}
|
||||
else {
|
||||
modifyFunc(box, reloadValue - tailReloadValue)
|
||||
reloadValue
|
||||
}) + currentMagazine
|
||||
log.info(s"ReloadMessage: success, $tool <- $actualReloadValue ${tool.AmmoType}")
|
||||
tool.Magazine = actualReloadValue
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ReloadMessage(item_guid, actualReloadValue, unk1)))
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.Reload(player.GUID, item_guid))
|
||||
}
|
||||
}
|
||||
else {
|
||||
log.warn(s"ReloadMessage: item $item_guid can not reload (full=$magazineSize, want=$reloadValue)")
|
||||
}
|
||||
case (_, Some(_)) =>
|
||||
log.error(s"ReloadMessage: the object that was found for $item_guid was not a Tool")
|
||||
case (_, None) =>
|
||||
log.error(s"ReloadMessage: can not find $item_guid")
|
||||
}
|
||||
|
||||
case msg @ ObjectHeldMessage(avatar_guid, held_holsters, unk1) =>
|
||||
|
|
@ -1673,9 +1751,60 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
|
||||
case msg @ WeaponDelayFireMessage(seq_time, weapon_guid) =>
|
||||
log.info("WeaponDelayFire: " + msg)
|
||||
(player.VehicleSeated match {
|
||||
case Some(vehicle_guid) =>
|
||||
continent.GUID(vehicle_guid) match {
|
||||
case Some(obj : Vehicle) =>
|
||||
obj.PassengerInSeat(player) match {
|
||||
case Some(seat_num) =>
|
||||
obj.WeaponControlledFromSeat(seat_num)
|
||||
case None =>
|
||||
None
|
||||
}
|
||||
case _ =>
|
||||
None
|
||||
}
|
||||
case None =>
|
||||
player.Slot(player.DrawnSlot).Equipment
|
||||
}) match {
|
||||
case Some(tool : Tool) =>
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.WeaponDryFire(player.GUID, weapon_guid))
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
case msg @ WeaponFireMessage(seq_time, weapon_guid, projectile_guid, shot_origin, unk1, unk2, unk3, unk4, unk5, unk6, unk7) =>
|
||||
log.info("WeaponFire: " + msg)
|
||||
(player.VehicleSeated match {
|
||||
case Some(vehicle_guid) =>
|
||||
continent.GUID(vehicle_guid) match {
|
||||
case Some(obj : Vehicle) =>
|
||||
obj.PassengerInSeat(player) match {
|
||||
case Some(seat_num) =>
|
||||
obj.WeaponControlledFromSeat(seat_num)
|
||||
case None =>
|
||||
None
|
||||
}
|
||||
case _ =>
|
||||
None
|
||||
}
|
||||
case None =>
|
||||
player.Slot(player.DrawnSlot).Equipment
|
||||
}) match {
|
||||
case Some(tool : Tool) =>
|
||||
if(tool.Magazine <= 0) { //safety: enforce ammunition depletion
|
||||
tool.Magazine = 0
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, InventoryStateMessage(tool.AmmoSlot.Box.GUID, weapon_guid, 0)))
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ChangeFireStateMessage_Stop(weapon_guid)))
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ChangeFireState_Stop(player.GUID, weapon_guid))
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, WeaponDryFireMessage(weapon_guid)))
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.WeaponDryFire(player.GUID, weapon_guid))
|
||||
}
|
||||
else { //shooting
|
||||
tool.Magazine = tool.Magazine - 1
|
||||
//TODO other stuff
|
||||
}
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
case msg @ WeaponLazeTargetPositionMessage(weapon, pos1, pos2) =>
|
||||
log.info("Lazing position: " + pos2.toString)
|
||||
|
|
@ -1727,9 +1856,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
val seats = obj.Seats.values
|
||||
seats.find(seat => seat.Occupant.contains(player)) match {
|
||||
case Some(seat) =>
|
||||
val vel = obj.Velocity.getOrElse(Vector3(0f, 0f, 0f))
|
||||
val has_vel : Int = math.abs(vel.x * vel.y * vel.z).toInt
|
||||
if(seat.Bailable || obj.Velocity.isEmpty || has_vel == 0) { //ugh, float comparison
|
||||
if(seat.Bailable || obj.Velocity.isEmpty || Vector3.MagnitudeSquared(obj.Velocity.get).toInt == 0) { //ugh, float comparison
|
||||
seat.Occupant = None
|
||||
//special actions
|
||||
obj match {
|
||||
|
|
@ -2355,6 +2482,59 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 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`.<br>
|
||||
* <br>
|
||||
* 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.
|
||||
* @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`
|
||||
*/
|
||||
def FindReloadAmmunition(obj : Container, ammoType : Ammo.Value, desiredAmount : Int) : 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
|
||||
}
|
||||
})
|
||||
.toList
|
||||
.sortBy(_.start)
|
||||
.takeWhile(entry => {
|
||||
val previousAmount = currentAmount
|
||||
currentAmount += entry.obj.asInstanceOf[AmmoBox].Capacity
|
||||
previousAmount < desiredAmount
|
||||
})
|
||||
}
|
||||
|
||||
private def DeleteAmmunition(obj : PlanetSideGameObject with Container)(start : Int, item_guid : PlanetSideGUID) : Unit = {
|
||||
obj.Inventory -= start
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ObjectDeleteMessage(item_guid, 0)))
|
||||
}
|
||||
|
||||
private def DeleteAmmunitionInVehicle(obj : Vehicle)(start : Int, item_guid : PlanetSideGUID) : Unit = {
|
||||
DeleteAmmunition(obj)(start, item_guid)
|
||||
vehicleService ! VehicleServiceMessage(s"${obj.Actor}", VehicleAction.UnstowEquipment(player.GUID, item_guid))
|
||||
}
|
||||
|
||||
private def ModifyAmmunition(obj : PlanetSideGameObject with Container)(box : AmmoBox, reloadValue : Int) : Unit = {
|
||||
val capacity = box.Capacity - reloadValue
|
||||
box.Capacity = capacity
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, InventoryStateMessage(box.GUID, obj.GUID, capacity)))
|
||||
}
|
||||
|
||||
private def ModifyAmmunitionInVehicle(obj : Vehicle)(box : AmmoBox, reloadValue : Int) : Unit = {
|
||||
val capacity = ModifyAmmunition(obj)(box, reloadValue)
|
||||
vehicleService ! VehicleServiceMessage(s"${obj.Actor}", VehicleAction.InventoryState(player.GUID, box, obj.GUID, obj.Find(box).get, box.Definition.Packet.DetailedConstructorData(box).get))
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ object AvatarAction {
|
|||
trait Action
|
||||
|
||||
final case class ArmorChanged(player_guid : PlanetSideGUID, suit : ExoSuitType.Value, subtype : Int) extends Action
|
||||
final case class ChangeFireState_Start(player_guid : PlanetSideGUID, weapon_guid : PlanetSideGUID) extends Action
|
||||
final case class ChangeFireState_Stop(player_guid : PlanetSideGUID, weapon_guid : PlanetSideGUID) extends Action
|
||||
final case class ConcealPlayer(player_guid : PlanetSideGUID) extends Action
|
||||
//final case class DropItem(pos : Vector3, orient : Vector3, item : PlanetSideGUID) extends Action
|
||||
final case class EquipmentInHand(player_guid : PlanetSideGUID, slot : Int, item : Equipment) extends Action
|
||||
|
|
@ -21,7 +23,8 @@ object AvatarAction {
|
|||
final case class ObjectHeld(player_guid : PlanetSideGUID, slot : Int) extends Action
|
||||
final case class PlanetsideAttribute(player_guid : PlanetSideGUID, attribute_type : Int, attribute_value : Long) extends Action
|
||||
final case class PlayerState(player_guid : PlanetSideGUID, msg : PlayerStateMessageUpstream, spectator : Boolean, weaponInHand : Boolean) extends Action
|
||||
final case class Reload(player_guid : PlanetSideGUID, mag : Int) extends Action
|
||||
final case class Reload(player_guid : PlanetSideGUID, weapon_guid : PlanetSideGUID) extends Action
|
||||
final case class WeaponDryFire(player_guid : PlanetSideGUID, weapon_guid : PlanetSideGUID) extends Action
|
||||
// final case class PlayerStateShift(killer : PlanetSideGUID, victim : PlanetSideGUID) extends Action
|
||||
// final case class DestroyDisplay(killer : PlanetSideGUID, victim : PlanetSideGUID) extends Action
|
||||
// final case class HitHintReturn(killer : PlanetSideGUID, victim : PlanetSideGUID) extends Action
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ object AvatarResponse {
|
|||
trait Response
|
||||
|
||||
final case class ArmorChanged(suit : ExoSuitType.Value, subtype : Int) extends Response
|
||||
final case class ChangeFireState_Start(weapon_guid : PlanetSideGUID) extends Response
|
||||
final case class ChangeFireState_Stop(weapon_guid : PlanetSideGUID) extends Response
|
||||
final case class ConcealPlayer() extends Response
|
||||
//final case class DropItem(pos : Vector3, orient : Vector3, item : PlanetSideGUID) extends Response
|
||||
final case class EquipmentInHand(slot : Int, item : Equipment) extends Response
|
||||
|
|
@ -21,7 +23,8 @@ object AvatarResponse {
|
|||
final case class ObjectHeld(slot : Int) extends Response
|
||||
final case class PlanetsideAttribute(attribute_type : Int, attribute_value : Long) extends Response
|
||||
final case class PlayerState(msg : PlayerStateMessageUpstream, spectator : Boolean, weaponInHand : Boolean) extends Response
|
||||
final case class Reload(mag : Int) extends Response
|
||||
final case class Reload(weapon_guid : PlanetSideGUID) extends Response
|
||||
final case class WeaponDryFire(weapon_guid : PlanetSideGUID) extends Response
|
||||
// final case class PlayerStateShift(itemID : PlanetSideGUID) extends Response
|
||||
// final case class DestroyDisplay(itemID : PlanetSideGUID) extends Response
|
||||
// final case class HitHintReturn(itemID : PlanetSideGUID) extends Response
|
||||
|
|
|
|||
|
|
@ -39,6 +39,14 @@ class AvatarService extends Actor {
|
|||
AvatarEvents.publish(
|
||||
AvatarServiceResponse(s"/$forChannel/Avatar", player_guid, AvatarResponse.ArmorChanged(suit, subtype))
|
||||
)
|
||||
case AvatarAction.ChangeFireState_Start(player_guid, weapon_guid) =>
|
||||
AvatarEvents.publish(
|
||||
AvatarServiceResponse(s"/$forChannel/Avatar", player_guid, AvatarResponse.ChangeFireState_Start(weapon_guid))
|
||||
)
|
||||
case AvatarAction.ChangeFireState_Stop(player_guid, weapon_guid) =>
|
||||
AvatarEvents.publish(
|
||||
AvatarServiceResponse(s"/$forChannel/Avatar", player_guid, AvatarResponse.ChangeFireState_Stop(weapon_guid))
|
||||
)
|
||||
case AvatarAction.ConcealPlayer(player_guid) =>
|
||||
AvatarEvents.publish(
|
||||
AvatarServiceResponse(s"/$forChannel/Avatar", player_guid, AvatarResponse.ConcealPlayer())
|
||||
|
|
@ -71,9 +79,13 @@ class AvatarService extends Actor {
|
|||
AvatarEvents.publish(
|
||||
AvatarServiceResponse(s"/$forChannel/Avatar", guid, AvatarResponse.PlayerState(msg, spectator, weapon))
|
||||
)
|
||||
case AvatarAction.Reload(player_guid, mag) =>
|
||||
case AvatarAction.Reload(player_guid, weapon_guid) =>
|
||||
AvatarEvents.publish(
|
||||
AvatarServiceResponse(s"/$forChannel/Avatar", player_guid, AvatarResponse.Reload(mag))
|
||||
AvatarServiceResponse(s"/$forChannel/Avatar", player_guid, AvatarResponse.Reload(weapon_guid))
|
||||
)
|
||||
case AvatarAction.WeaponDryFire(player_guid, weapon_guid) =>
|
||||
AvatarEvents.publish(
|
||||
AvatarServiceResponse(s"/$forChannel/Avatar", player_guid, AvatarResponse.WeaponDryFire(weapon_guid))
|
||||
)
|
||||
case _ => ;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package services.vehicle
|
||||
|
||||
import net.psforever.objects.Vehicle
|
||||
import net.psforever.objects.{PlanetSideGameObject, Vehicle}
|
||||
import net.psforever.objects.equipment.Equipment
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
|
|
@ -14,6 +14,7 @@ object VehicleAction {
|
|||
final case class Awareness(player_guid : PlanetSideGUID, vehicle_guid : PlanetSideGUID) extends Action
|
||||
final case class ChildObjectState(player_guid : PlanetSideGUID, object_guid : PlanetSideGUID, pitch : Float, yaw : Float) extends Action
|
||||
final case class DismountVehicle(player_guid : PlanetSideGUID, unk1 : Int, unk2 : Boolean) extends Action
|
||||
final case class InventoryState(player_guid : PlanetSideGUID, obj : PlanetSideGameObject, parent_guid : PlanetSideGUID, start : Int, con_data : ConstructorData) extends Action
|
||||
final case class KickPassenger(player_guid : PlanetSideGUID, unk1 : Int, unk2 : Boolean, vehicle_guid : PlanetSideGUID) extends Action
|
||||
final case class LoadVehicle(player_guid : PlanetSideGUID, vehicle : Vehicle, vtype : Int, vguid : PlanetSideGUID, vdata : ConstructorData) extends Action
|
||||
final case class MountVehicle(player_guid : PlanetSideGUID, object_guid : PlanetSideGUID, seat : Int) extends Action
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package services.vehicle
|
||||
|
||||
import net.psforever.objects.Vehicle
|
||||
import net.psforever.objects.{PlanetSideGameObject, Vehicle}
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.packet.game.objectcreate.ConstructorData
|
||||
import net.psforever.types.Vector3
|
||||
|
|
@ -12,6 +12,7 @@ object VehicleResponse {
|
|||
final case class Awareness(vehicle_guid : PlanetSideGUID) extends Response
|
||||
final case class ChildObjectState(object_guid : PlanetSideGUID, pitch : Float, yaw : Float) extends Response
|
||||
final case class DismountVehicle(unk1 : Int, unk2 : Boolean) extends Response
|
||||
final case class InventoryState(obj : PlanetSideGameObject, parent_guid : PlanetSideGUID, start : Int, con_data : ConstructorData) extends Response
|
||||
final case class KickPassenger(unk1 : Int, unk2 : Boolean, vehicle_guid : PlanetSideGUID) extends Response
|
||||
final case class LoadVehicle(vehicle : Vehicle, vtype : Int, vguid : PlanetSideGUID, vdata : ConstructorData) extends Response
|
||||
final case class MountVehicle(object_guid : PlanetSideGUID, seat : Int) extends Response
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
package services.vehicle
|
||||
|
||||
import akka.actor.{Actor, ActorRef, Props}
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.packet.game.objectcreate.ConstructorData
|
||||
import services.vehicle.support.{DeconstructionActor, DelayedDeconstructionActor, VehicleContextActor}
|
||||
import services.{GenericEventBus, Service}
|
||||
|
||||
|
|
@ -47,6 +49,10 @@ class VehicleService extends Actor {
|
|||
VehicleEvents.publish(
|
||||
VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.ChildObjectState(object_guid, pitch, yaw))
|
||||
)
|
||||
case VehicleAction.InventoryState(player_guid, obj, parent_guid, start, con_data) =>
|
||||
VehicleEvents.publish(
|
||||
VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.InventoryState(obj, parent_guid, start, con_data))
|
||||
)
|
||||
case VehicleAction.DismountVehicle(player_guid, unk1, unk2) =>
|
||||
VehicleEvents.publish(
|
||||
VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.DismountVehicle(unk1, unk2))
|
||||
|
|
|
|||
|
|
@ -176,8 +176,8 @@ class AvatarServiceCTest extends ActorTest {
|
|||
"pass Reload" in {
|
||||
val service = system.actorOf(Props[AvatarService], "service")
|
||||
service ! Service.Join("test")
|
||||
service ! AvatarServiceMessage("test", AvatarAction.Reload(PlanetSideGUID(10), 35))
|
||||
expectMsg(AvatarServiceResponse("/test/Avatar", PlanetSideGUID(10), AvatarResponse.Reload(35)))
|
||||
service ! AvatarServiceMessage("test", AvatarAction.Reload(PlanetSideGUID(10), PlanetSideGUID(40)))
|
||||
expectMsg(AvatarServiceResponse("/test/Avatar", PlanetSideGUID(10), AvatarResponse.Reload(PlanetSideGUID(40))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue