mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-13 07:24:53 +00:00
using force psm occlusion to eliminate certain other packets that would be fine if hidden
This commit is contained in:
parent
6f4ceaee29
commit
0628b988fe
9 changed files with 433 additions and 184 deletions
|
|
@ -3,6 +3,7 @@ package net.psforever.actors.session.support
|
||||||
|
|
||||||
import akka.actor.typed.scaladsl.adapter._
|
import akka.actor.typed.scaladsl.adapter._
|
||||||
import akka.actor.{ActorContext, typed}
|
import akka.actor.{ActorContext, typed}
|
||||||
|
import net.psforever.packet.game.objectcreate.ConstructorData
|
||||||
import net.psforever.services.Service
|
import net.psforever.services.Service
|
||||||
|
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
|
|
@ -73,9 +74,9 @@ class SessionAvatarHandlers(
|
||||||
canSeeReallyFar
|
canSeeReallyFar
|
||||||
) if isNotSameTarget =>
|
) if isNotSameTarget =>
|
||||||
val pstateToSave = pstate.copy(timestamp = 0)
|
val pstateToSave = pstate.copy(timestamp = 0)
|
||||||
val (lastMsg, lastTime, lastPosition, wasVisible) = lastSeenStreamMessage.get(guid.guid) match {
|
val (lastMsg, lastTime, lastPosition, wasVisible, wasShooting) = lastSeenStreamMessage.get(guid.guid) match {
|
||||||
case Some(SessionAvatarHandlers.LastUpstream(Some(msg), visible, time)) => (Some(msg), time, msg.pos, visible)
|
case Some(SessionAvatarHandlers.LastUpstream(Some(msg), visible, shooting, time)) => (Some(msg), time, msg.pos, visible, shooting)
|
||||||
case _ => (None, 0L, Vector3.Zero, false)
|
case _ => (None, 0L, Vector3.Zero, false, None)
|
||||||
}
|
}
|
||||||
val drawConfig = Config.app.game.playerDraw //m
|
val drawConfig = Config.app.game.playerDraw //m
|
||||||
val maxRange = drawConfig.rangeMax * drawConfig.rangeMax //sq.m
|
val maxRange = drawConfig.rangeMax * drawConfig.rangeMax //sq.m
|
||||||
|
|
@ -129,10 +130,10 @@ class SessionAvatarHandlers(
|
||||||
isCloaking
|
isCloaking
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
lastSeenStreamMessage.put(guid.guid, SessionAvatarHandlers.LastUpstream(Some(pstateToSave), visible=true, now))
|
lastSeenStreamMessage.put(guid.guid, SessionAvatarHandlers.LastUpstream(Some(pstateToSave), visible=true, wasShooting, now))
|
||||||
} else {
|
} else {
|
||||||
//is visible, but skip reinforcement
|
//is visible, but skip reinforcement
|
||||||
lastSeenStreamMessage.put(guid.guid, SessionAvatarHandlers.LastUpstream(Some(pstateToSave), visible=true, lastTime))
|
lastSeenStreamMessage.put(guid.guid, SessionAvatarHandlers.LastUpstream(Some(pstateToSave), visible=true, wasShooting, lastTime))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//conditions where the target is not currently visible
|
//conditions where the target is not currently visible
|
||||||
|
|
@ -151,10 +152,10 @@ class SessionAvatarHandlers(
|
||||||
is_cloaked = isCloaking
|
is_cloaked = isCloaking
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
lastSeenStreamMessage.put(guid.guid, SessionAvatarHandlers.LastUpstream(Some(pstateToSave), visible=false, now))
|
lastSeenStreamMessage.put(guid.guid, SessionAvatarHandlers.LastUpstream(Some(pstateToSave), visible=false, wasShooting, now))
|
||||||
} else {
|
} else {
|
||||||
//skip drawing altogether
|
//skip drawing altogether
|
||||||
lastSeenStreamMessage.put(guid.guid, SessionAvatarHandlers.LastUpstream(Some(pstateToSave), visible=false, lastTime))
|
lastSeenStreamMessage.put(guid.guid, SessionAvatarHandlers.LastUpstream(Some(pstateToSave), visible=false, wasShooting, lastTime))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -179,10 +180,24 @@ class SessionAvatarHandlers(
|
||||||
case AvatarResponse.ObjectHeld(_, previousSlot) =>
|
case AvatarResponse.ObjectHeld(_, previousSlot) =>
|
||||||
sendResponse(ObjectHeldMessage(guid, previousSlot, unk1=false))
|
sendResponse(ObjectHeldMessage(guid, previousSlot, unk1=false))
|
||||||
|
|
||||||
case AvatarResponse.ChangeFireState_Start(weaponGuid) if isNotSameTarget =>
|
case AvatarResponse.ChangeFireState_Start(weaponGuid)
|
||||||
|
if isNotSameTarget && lastSeenStreamMessage.get(guid.guid).exists { _.visible } =>
|
||||||
|
sendResponse(ChangeFireStateMessage_Start(weaponGuid))
|
||||||
|
val entry = lastSeenStreamMessage(guid.guid)
|
||||||
|
lastSeenStreamMessage.put(guid.guid, entry.copy(shooting = Some(weaponGuid)))
|
||||||
|
|
||||||
|
case AvatarResponse.ChangeFireState_Start(weaponGuid)
|
||||||
|
if isNotSameTarget =>
|
||||||
sendResponse(ChangeFireStateMessage_Start(weaponGuid))
|
sendResponse(ChangeFireStateMessage_Start(weaponGuid))
|
||||||
|
|
||||||
case AvatarResponse.ChangeFireState_Stop(weaponGuid) if isNotSameTarget =>
|
case AvatarResponse.ChangeFireState_Stop(weaponGuid)
|
||||||
|
if isNotSameTarget && lastSeenStreamMessage.get(guid.guid).exists { msg => msg.visible || msg.shooting.nonEmpty } =>
|
||||||
|
sendResponse(ChangeFireStateMessage_Stop(weaponGuid))
|
||||||
|
val entry = lastSeenStreamMessage(guid.guid)
|
||||||
|
lastSeenStreamMessage.put(guid.guid, entry.copy(shooting = None))
|
||||||
|
|
||||||
|
case AvatarResponse.ChangeFireState_Stop(weaponGuid)
|
||||||
|
if isNotSameTarget =>
|
||||||
sendResponse(ChangeFireStateMessage_Stop(weaponGuid))
|
sendResponse(ChangeFireStateMessage_Stop(weaponGuid))
|
||||||
|
|
||||||
case AvatarResponse.LoadPlayer(pkt) if isNotSameTarget =>
|
case AvatarResponse.LoadPlayer(pkt) if isNotSameTarget =>
|
||||||
|
|
@ -388,7 +403,8 @@ class SessionAvatarHandlers(
|
||||||
sendResponse(msg)
|
sendResponse(msg)
|
||||||
|
|
||||||
/* common messages (maybe once every respawn) */
|
/* common messages (maybe once every respawn) */
|
||||||
case AvatarResponse.Reload(itemGuid) if isNotSameTarget =>
|
case AvatarResponse.Reload(itemGuid)
|
||||||
|
if isNotSameTarget && lastSeenStreamMessage.get(guid.guid).exists { _.visible } =>
|
||||||
sendResponse(ReloadMessage(itemGuid, ammo_clip=1, unk1=0))
|
sendResponse(ReloadMessage(itemGuid, ammo_clip=1, unk1=0))
|
||||||
|
|
||||||
case AvatarResponse.Killed(mount) =>
|
case AvatarResponse.Killed(mount) =>
|
||||||
|
|
@ -467,18 +483,14 @@ class SessionAvatarHandlers(
|
||||||
)
|
)
|
||||||
|
|
||||||
/* uncommon messages (utility, or once in a while) */
|
/* uncommon messages (utility, or once in a while) */
|
||||||
|
case AvatarResponse.ChangeAmmo(weapon_guid, weapon_slot, previous_guid, ammo_id, ammo_guid, ammo_data)
|
||||||
|
if isNotSameTarget && lastSeenStreamMessage.get(guid.guid).exists { _.visible } =>
|
||||||
|
changeAmmoProcedures(weapon_guid, previous_guid, ammo_id, ammo_guid, weapon_slot, ammo_data)
|
||||||
|
sendResponse(ChangeAmmoMessage(weapon_guid, 1))
|
||||||
|
|
||||||
case AvatarResponse.ChangeAmmo(weapon_guid, weapon_slot, previous_guid, ammo_id, ammo_guid, ammo_data)
|
case AvatarResponse.ChangeAmmo(weapon_guid, weapon_slot, previous_guid, ammo_id, ammo_guid, ammo_data)
|
||||||
if isNotSameTarget =>
|
if isNotSameTarget =>
|
||||||
sendResponse(ObjectDetachMessage(weapon_guid, previous_guid, Vector3.Zero, 0))
|
changeAmmoProcedures(weapon_guid, previous_guid, ammo_id, ammo_guid, weapon_slot, ammo_data)
|
||||||
sendResponse(
|
|
||||||
ObjectCreateMessage(
|
|
||||||
ammo_id,
|
|
||||||
ammo_guid,
|
|
||||||
ObjectCreateMessageParent(weapon_guid, weapon_slot),
|
|
||||||
ammo_data
|
|
||||||
)
|
|
||||||
)
|
|
||||||
sendResponse(ChangeAmmoMessage(weapon_guid, 1))
|
|
||||||
|
|
||||||
case AvatarResponse.ChangeFireMode(itemGuid, mode) if isNotSameTarget =>
|
case AvatarResponse.ChangeFireMode(itemGuid, mode) if isNotSameTarget =>
|
||||||
sendResponse(ChangeFireModeMessage(itemGuid, mode))
|
sendResponse(ChangeFireModeMessage(itemGuid, mode))
|
||||||
|
|
@ -546,21 +558,45 @@ class SessionAvatarHandlers(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
case AvatarResponse.WeaponDryFire(weaponGuid) if isNotSameTarget =>
|
case AvatarResponse.WeaponDryFire(weaponGuid)
|
||||||
|
if isNotSameTarget && lastSeenStreamMessage.get(guid.guid).exists { _.visible } =>
|
||||||
continent.GUID(weaponGuid).collect {
|
continent.GUID(weaponGuid).collect {
|
||||||
case tool: Tool if tool.Magazine == 0 =>
|
case tool: Tool if tool.Magazine == 0 =>
|
||||||
// check that the magazine is still empty before sending WeaponDryFireMessage
|
// check that the magazine is still empty before sending WeaponDryFireMessage
|
||||||
// if it has been reloaded since then, other clients will not see it firing
|
// if it has been reloaded since then, other clients will not see it firing
|
||||||
sendResponse(WeaponDryFireMessage(weaponGuid))
|
sendResponse(WeaponDryFireMessage(weaponGuid))
|
||||||
case _ =>
|
|
||||||
sendResponse(WeaponDryFireMessage(weaponGuid))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case _ => ()
|
case _ => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private def changeAmmoProcedures(
|
||||||
|
weaponGuid: PlanetSideGUID,
|
||||||
|
previousAmmoGuid: PlanetSideGUID,
|
||||||
|
ammoTypeId: Int,
|
||||||
|
ammoGuid: PlanetSideGUID,
|
||||||
|
ammoSlot: Int,
|
||||||
|
ammoData: ConstructorData
|
||||||
|
): Unit = {
|
||||||
|
sendResponse(ObjectDetachMessage(weaponGuid, previousAmmoGuid, Vector3.Zero, 0))
|
||||||
|
//TODO? sendResponse(ObjectDeleteMessage(previousAmmoGuid, 0))
|
||||||
|
sendResponse(
|
||||||
|
ObjectCreateMessage(
|
||||||
|
ammoTypeId,
|
||||||
|
ammoGuid,
|
||||||
|
ObjectCreateMessageParent(weaponGuid, ammoSlot),
|
||||||
|
ammoData
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object SessionAvatarHandlers {
|
object SessionAvatarHandlers {
|
||||||
private[support] case class LastUpstream(msg: Option[AvatarResponse.PlayerState], visible: Boolean, time: Long)
|
private[support] case class LastUpstream(
|
||||||
|
msg: Option[AvatarResponse.PlayerState],
|
||||||
|
visible: Boolean,
|
||||||
|
shooting: Option[PlanetSideGUID],
|
||||||
|
time: Long
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import net.psforever.objects.equipment.{Equipment, JammableMountedWeapons, Jamma
|
||||||
import net.psforever.objects.guid.{GUIDTask, TaskWorkflow}
|
import net.psforever.objects.guid.{GUIDTask, TaskWorkflow}
|
||||||
import net.psforever.objects.serverobject.mount.Mountable
|
import net.psforever.objects.serverobject.mount.Mountable
|
||||||
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
|
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
|
||||||
import net.psforever.objects.{GlobalDefinitions, Player, Vehicle, Vehicles}
|
import net.psforever.objects.{GlobalDefinitions, Player, Tool, Vehicle, Vehicles}
|
||||||
import net.psforever.packet.game.objectcreate.ObjectCreateMessageParent
|
import net.psforever.packet.game.objectcreate.ObjectCreateMessageParent
|
||||||
import net.psforever.packet.game._
|
import net.psforever.packet.game._
|
||||||
import net.psforever.services.Service
|
import net.psforever.services.Service
|
||||||
|
|
@ -79,6 +79,36 @@ class SessionVehicleHandlers(
|
||||||
if isNotSameTarget =>
|
if isNotSameTarget =>
|
||||||
sendResponse(FrameVehicleStateMessage(vguid, u1, pos, oient, vel, u2, u3, u4, is_crouched, u6, u7, u8, u9, uA))
|
sendResponse(FrameVehicleStateMessage(vguid, u1, pos, oient, vel, u2, u3, u4, is_crouched, u6, u7, u8, u9, uA))
|
||||||
|
|
||||||
|
case VehicleResponse.ChangeFireState_Start(weaponGuid) if isNotSameTarget =>
|
||||||
|
sendResponse(ChangeFireStateMessage_Start(weaponGuid))
|
||||||
|
|
||||||
|
case VehicleResponse.ChangeFireState_Stop(weaponGuid) if isNotSameTarget =>
|
||||||
|
sendResponse(ChangeFireStateMessage_Stop(weaponGuid))
|
||||||
|
|
||||||
|
case VehicleResponse.Reload(itemGuid) if isNotSameTarget =>
|
||||||
|
sendResponse(ReloadMessage(itemGuid, ammo_clip=1, unk1=0))
|
||||||
|
|
||||||
|
case VehicleResponse.ChangeAmmo(weapon_guid, weapon_slot, previous_guid, ammo_id, ammo_guid, ammo_data) if isNotSameTarget =>
|
||||||
|
sendResponse(ObjectDetachMessage(weapon_guid, previous_guid, Vector3.Zero, 0))
|
||||||
|
//TODO? sendResponse(ObjectDeleteMessage(previousAmmoGuid, 0))
|
||||||
|
sendResponse(
|
||||||
|
ObjectCreateMessage(
|
||||||
|
ammo_id,
|
||||||
|
ammo_guid,
|
||||||
|
ObjectCreateMessageParent(weapon_guid, weapon_slot),
|
||||||
|
ammo_data
|
||||||
|
)
|
||||||
|
)
|
||||||
|
sendResponse(ChangeAmmoMessage(weapon_guid, 1))
|
||||||
|
|
||||||
|
case VehicleResponse.WeaponDryFire(weaponGuid) if isNotSameTarget =>
|
||||||
|
continent.GUID(weaponGuid).collect {
|
||||||
|
case tool: Tool if tool.Magazine == 0 =>
|
||||||
|
// check that the magazine is still empty before sending WeaponDryFireMessage
|
||||||
|
// if it has been reloaded since then, other clients will not see it firing
|
||||||
|
sendResponse(WeaponDryFireMessage(weaponGuid))
|
||||||
|
}
|
||||||
|
|
||||||
case VehicleResponse.DismountVehicle(bailType, wasKickedByDriver) if isNotSameTarget =>
|
case VehicleResponse.DismountVehicle(bailType, wasKickedByDriver) if isNotSameTarget =>
|
||||||
sendResponse(DismountVehicleMsg(guid, bailType, wasKickedByDriver))
|
sendResponse(DismountVehicleMsg(guid, bailType, wasKickedByDriver))
|
||||||
|
|
||||||
|
|
@ -330,10 +360,10 @@ class SessionVehicleHandlers(
|
||||||
}
|
}
|
||||||
|
|
||||||
private def changeLoadoutDeleteOldEquipment(
|
private def changeLoadoutDeleteOldEquipment(
|
||||||
vehicle: Vehicle,
|
vehicle: Vehicle,
|
||||||
oldWeapons: Iterable[(Equipment, PlanetSideGUID)],
|
oldWeapons: Iterable[(Equipment, PlanetSideGUID)],
|
||||||
oldInventory: Iterable[(Equipment, PlanetSideGUID)]
|
oldInventory: Iterable[(Equipment, PlanetSideGUID)]
|
||||||
): Unit = {
|
): Unit = {
|
||||||
vehicle.PassengerInSeat(player) match {
|
vehicle.PassengerInSeat(player) match {
|
||||||
case Some(seatNum) =>
|
case Some(seatNum) =>
|
||||||
//participant: observe changes to equipment
|
//participant: observe changes to equipment
|
||||||
|
|
|
||||||
|
|
@ -271,10 +271,6 @@ class VehicleOperations(
|
||||||
sessionData.validObject(mountable_guid, decorator = "MountVehicle").collect {
|
sessionData.validObject(mountable_guid, decorator = "MountVehicle").collect {
|
||||||
case obj: Mountable =>
|
case obj: Mountable =>
|
||||||
obj.Actor ! Mountable.TryMount(player, entry_point)
|
obj.Actor ! Mountable.TryMount(player, entry_point)
|
||||||
case _: Mountable =>
|
|
||||||
log.warn(
|
|
||||||
s"DismountVehicleMsg: ${player.Name} can not mount while server has asserted control; please wait"
|
|
||||||
)
|
|
||||||
case _ =>
|
case _ =>
|
||||||
log.error(s"MountVehicleMsg: object ${mountable_guid.guid} not a mountable thing, ${player.Name}")
|
log.error(s"MountVehicleMsg: object ${mountable_guid.guid} not a mountable thing, ${player.Name}")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,19 +74,28 @@ private[support] class WeaponAndProjectileOperations(
|
||||||
|
|
||||||
def handleWeaponDryFire(pkt: WeaponDryFireMessage): Unit = {
|
def handleWeaponDryFire(pkt: WeaponDryFireMessage): Unit = {
|
||||||
val WeaponDryFireMessage(weapon_guid) = pkt
|
val WeaponDryFireMessage(weapon_guid) = pkt
|
||||||
FindWeapon
|
val (containerOpt, tools) = FindContainedWeapon
|
||||||
|
tools
|
||||||
.find { _.GUID == weapon_guid }
|
.find { _.GUID == weapon_guid }
|
||||||
.orElse { continent.GUID(weapon_guid) } match {
|
.orElse { continent.GUID(weapon_guid) }
|
||||||
case Some(_: Equipment) =>
|
.collect {
|
||||||
continent.AvatarEvents ! AvatarServiceMessage(
|
case _: Equipment if containerOpt.exists(_.isInstanceOf[Player]) =>
|
||||||
continent.id,
|
continent.AvatarEvents ! AvatarServiceMessage(
|
||||||
AvatarAction.WeaponDryFire(player.GUID, weapon_guid)
|
continent.id,
|
||||||
)
|
AvatarAction.WeaponDryFire(player.GUID, weapon_guid)
|
||||||
case _ =>
|
)
|
||||||
|
case _: Equipment =>
|
||||||
|
continent.VehicleEvents ! VehicleServiceMessage(
|
||||||
|
continent.id,
|
||||||
|
VehicleAction.WeaponDryFire(player.GUID, weapon_guid)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.orElse {
|
||||||
log.warn(
|
log.warn(
|
||||||
s"WeaponDryFire: ${player.Name}'s weapon ${weapon_guid.guid} is either not a weapon or does not exist"
|
s"WeaponDryFire: ${player.Name}'s weapon ${weapon_guid.guid} is either not a weapon or does not exist"
|
||||||
)
|
)
|
||||||
}
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def handleWeaponLazeTargetPosition(pkt: WeaponLazeTargetPositionMessage): Unit = {
|
def handleWeaponLazeTargetPosition(pkt: WeaponLazeTargetPositionMessage): Unit = {
|
||||||
|
|
@ -111,45 +120,16 @@ private[support] class WeaponAndProjectileOperations(
|
||||||
val ChangeFireStateMessage_Start(item_guid) = pkt
|
val ChangeFireStateMessage_Start(item_guid) = pkt
|
||||||
if (shooting.isEmpty) {
|
if (shooting.isEmpty) {
|
||||||
sessionData.findEquipment(item_guid) match {
|
sessionData.findEquipment(item_guid) match {
|
||||||
|
case Some(tool: Tool) if player.VehicleSeated.isEmpty =>
|
||||||
|
fireStateStartWhenPlayer(tool, item_guid)
|
||||||
case Some(tool: Tool) =>
|
case Some(tool: Tool) =>
|
||||||
if (tool.FireMode.RoundsPerShot == 0 || tool.Magazine > 0 || prefire.contains(item_guid)) {
|
fireStateStartWhenMounted(tool, item_guid)
|
||||||
prefire -= item_guid
|
case Some(_) if player.VehicleSeated.isEmpty =>
|
||||||
shooting += item_guid
|
fireStateStartSetup(item_guid)
|
||||||
shootingStart += item_guid -> System.currentTimeMillis()
|
fireStateStartPlayerMessages(item_guid)
|
||||||
ongoingShotsFired = 0
|
case Some(_) =>
|
||||||
//special case - suppress the decimator's alternate fire mode, by projectile
|
fireStateStartSetup(item_guid)
|
||||||
if (tool.Projectile != GlobalDefinitions.phoenix_missile_guided_projectile) {
|
fireStateStartMountedMessages(item_guid)
|
||||||
continent.AvatarEvents ! AvatarServiceMessage(
|
|
||||||
continent.id,
|
|
||||||
AvatarAction.ChangeFireState_Start(player.GUID, item_guid)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
//charge ammunition drain
|
|
||||||
tool.FireMode match {
|
|
||||||
case mode: ChargeFireModeDefinition =>
|
|
||||||
sessionData.progressBarValue = Some(0f)
|
|
||||||
sessionData.progressBarUpdate = context.system.scheduler.scheduleOnce(
|
|
||||||
(mode.Time + mode.DrainInterval) milliseconds,
|
|
||||||
context.self,
|
|
||||||
SessionActor.ProgressEvent(1f, () => {}, Tools.ChargeFireMode(player, tool), mode.DrainInterval)
|
|
||||||
)
|
|
||||||
case _ => ;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.warn(
|
|
||||||
s"ChangeFireState_Start: ${player.Name}'s ${tool.Definition.Name} magazine was empty before trying to shoot"
|
|
||||||
)
|
|
||||||
EmptyMagazine(item_guid, tool)
|
|
||||||
}
|
|
||||||
case Some(_) => //permissible, for now
|
|
||||||
prefire -= item_guid
|
|
||||||
shooting += item_guid
|
|
||||||
shootingStart += item_guid -> System.currentTimeMillis()
|
|
||||||
ongoingShotsFired = 0
|
|
||||||
continent.AvatarEvents ! AvatarServiceMessage(
|
|
||||||
continent.id,
|
|
||||||
AvatarAction.ChangeFireState_Start(player.GUID, item_guid)
|
|
||||||
)
|
|
||||||
case None =>
|
case None =>
|
||||||
log.warn(s"ChangeFireState_Start: can not find $item_guid")
|
log.warn(s"ChangeFireState_Start: can not find $item_guid")
|
||||||
}
|
}
|
||||||
|
|
@ -162,48 +142,23 @@ private[support] class WeaponAndProjectileOperations(
|
||||||
prefire -= item_guid
|
prefire -= item_guid
|
||||||
shootingStop += item_guid -> now
|
shootingStop += item_guid -> now
|
||||||
shooting -= item_guid
|
shooting -= item_guid
|
||||||
val pguid = player.GUID
|
|
||||||
sessionData.findEquipment(item_guid) match {
|
sessionData.findEquipment(item_guid) match {
|
||||||
|
case Some(tool: Tool) if player.VehicleSeated.isEmpty =>
|
||||||
|
fireStateStopWhenPlayer(tool, item_guid)
|
||||||
case Some(tool: Tool) =>
|
case Some(tool: Tool) =>
|
||||||
//the decimator does not send a ChangeFireState_Start on the last shot; heaven knows why
|
fireStateStopWhenMounted(tool, item_guid)
|
||||||
if (
|
|
||||||
tool.Definition == GlobalDefinitions.phoenix &&
|
|
||||||
tool.Projectile != GlobalDefinitions.phoenix_missile_guided_projectile
|
|
||||||
) {
|
|
||||||
//suppress the decimator's alternate fire mode, however
|
|
||||||
continent.AvatarEvents ! AvatarServiceMessage(
|
|
||||||
continent.id,
|
|
||||||
AvatarAction.ChangeFireState_Start(pguid, item_guid)
|
|
||||||
)
|
|
||||||
shootingStart += item_guid -> (now - 1L)
|
|
||||||
}
|
|
||||||
avatarActor ! AvatarActor.UpdateToolDischarge(EquipmentStat(tool.Definition.ObjectId,ongoingShotsFired,0,0))
|
|
||||||
tool.FireMode match {
|
|
||||||
case _: ChargeFireModeDefinition =>
|
|
||||||
sendResponse(QuantityUpdateMessage(tool.AmmoSlot.Box.GUID, tool.Magazine))
|
|
||||||
case _ => ;
|
|
||||||
}
|
|
||||||
if (tool.Magazine == 0) {
|
|
||||||
FireCycleCleanup(tool)
|
|
||||||
}
|
|
||||||
continent.AvatarEvents ! AvatarServiceMessage(
|
|
||||||
continent.id,
|
|
||||||
AvatarAction.ChangeFireState_Stop(pguid, item_guid)
|
|
||||||
)
|
|
||||||
|
|
||||||
case Some(trigger: BoomerTrigger) =>
|
case Some(trigger: BoomerTrigger) =>
|
||||||
continent.AvatarEvents ! AvatarServiceMessage(
|
fireStateStopPlayerMessages(item_guid)
|
||||||
continent.id,
|
continent.GUID(trigger.Companion).collect {
|
||||||
AvatarAction.ChangeFireState_Start(pguid, item_guid)
|
case boomer: BoomerDeployable =>
|
||||||
)
|
|
||||||
continent.GUID(trigger.Companion) match {
|
|
||||||
case Some(boomer: BoomerDeployable) =>
|
|
||||||
boomer.Actor ! CommonMessages.Use(player, Some(trigger))
|
boomer.Actor ! CommonMessages.Use(player, Some(trigger))
|
||||||
case Some(_) | None => ;
|
|
||||||
}
|
}
|
||||||
|
case Some(_) if player.VehicleSeated.isEmpty =>
|
||||||
case _ => ;
|
fireStateStopPlayerMessages(item_guid)
|
||||||
//log.warn(s"ChangeFireState_Stop: ${player.Name} never started firing item ${item_guid.guid} in the first place?")
|
case Some(_) =>
|
||||||
|
fireStateStopMountedMessages(item_guid)
|
||||||
|
case _ => ()
|
||||||
|
log.warn(s"ChangeFireState_Stop: can not find $item_guid")
|
||||||
}
|
}
|
||||||
sessionData.progressBarUpdate.cancel()
|
sessionData.progressBarUpdate.cancel()
|
||||||
sessionData.progressBarValue = None
|
sessionData.progressBarValue = None
|
||||||
|
|
@ -212,54 +167,10 @@ private[support] class WeaponAndProjectileOperations(
|
||||||
def handleReload(pkt: ReloadMessage): Unit = {
|
def handleReload(pkt: ReloadMessage): Unit = {
|
||||||
val ReloadMessage(item_guid, _, unk1) = pkt
|
val ReloadMessage(item_guid, _, unk1) = pkt
|
||||||
FindContainedWeapon match {
|
FindContainedWeapon match {
|
||||||
|
case (Some(obj: Player), tools) =>
|
||||||
|
handleReloadWhenPlayer(item_guid, obj, tools, unk1)
|
||||||
case (Some(obj: PlanetSideServerObject with Container), tools) =>
|
case (Some(obj: PlanetSideServerObject with Container), tools) =>
|
||||||
tools.filter { _.GUID == item_guid }.foreach { tool =>
|
handleReloadWhenMountable(item_guid, obj, tools, unk1)
|
||||||
val currentMagazine : Int = tool.Magazine
|
|
||||||
val magazineSize : Int = tool.MaxMagazine
|
|
||||||
val reloadValue : Int = magazineSize - currentMagazine
|
|
||||||
if (magazineSize > 0 && reloadValue > 0) {
|
|
||||||
FindEquipmentStock(obj, FindAmmoBoxThatUses(tool.AmmoType), reloadValue, CountAmmunition).reverse match {
|
|
||||||
case Nil => ;
|
|
||||||
case x :: xs =>
|
|
||||||
val (deleteFunc, modifyFunc) : (Equipment => Future[Any], (AmmoBox, Int) => Unit) = obj match {
|
|
||||||
case veh : Vehicle =>
|
|
||||||
(RemoveOldEquipmentFromInventory(veh)(_), ModifyAmmunitionInVehicle(veh)(_, _))
|
|
||||||
case _ =>
|
|
||||||
(RemoveOldEquipmentFromInventory(obj)(_), ModifyAmmunition(obj)(_, _))
|
|
||||||
}
|
|
||||||
xs.foreach { item => deleteFunc(item.obj) }
|
|
||||||
val box = x.obj.asInstanceOf[AmmoBox]
|
|
||||||
val tailReloadValue : Int = if (xs.isEmpty) {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
xs.map(_.obj.asInstanceOf[AmmoBox].Capacity).sum
|
|
||||||
}
|
|
||||||
val sumReloadValue : Int = box.Capacity + tailReloadValue
|
|
||||||
val actualReloadValue = if (sumReloadValue <= reloadValue) {
|
|
||||||
deleteFunc(box)
|
|
||||||
sumReloadValue
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
modifyFunc(box, reloadValue - tailReloadValue)
|
|
||||||
reloadValue
|
|
||||||
}
|
|
||||||
val finalReloadValue = actualReloadValue + currentMagazine
|
|
||||||
log.info(
|
|
||||||
s"${player.Name} successfully reloaded $reloadValue ${tool.AmmoType} into ${tool.Definition.Name}"
|
|
||||||
)
|
|
||||||
tool.Magazine = finalReloadValue
|
|
||||||
sendResponse(ReloadMessage(item_guid, finalReloadValue, unk1))
|
|
||||||
continent.AvatarEvents ! AvatarServiceMessage(
|
|
||||||
continent.id,
|
|
||||||
AvatarAction.Reload(player.GUID, item_guid)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//the weapon can not reload due to full magazine; the UI for the magazine is obvious bugged, so fix it
|
|
||||||
sendResponse(QuantityUpdateMessage(tool.AmmoSlot.Box.GUID, magazineSize))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case (_, _) =>
|
case (_, _) =>
|
||||||
log.warn(s"ReloadMessage: either can not find $item_guid or the object found was not a Tool")
|
log.warn(s"ReloadMessage: either can not find $item_guid or the object found was not a Tool")
|
||||||
}
|
}
|
||||||
|
|
@ -272,17 +183,19 @@ private[support] class WeaponAndProjectileOperations(
|
||||||
log.warn(s"ChangeAmmo: either can not find $item_guid or the object found was not Equipment")
|
log.warn(s"ChangeAmmo: either can not find $item_guid or the object found was not Equipment")
|
||||||
} else {
|
} else {
|
||||||
equipment foreach {
|
equipment foreach {
|
||||||
case obj : ConstructionItem =>
|
case obj: ConstructionItem =>
|
||||||
if (Deployables.performConstructionItemAmmoChange(player.avatar.certifications, obj, obj.AmmoTypeIndex)) {
|
if (Deployables.performConstructionItemAmmoChange(player.avatar.certifications, obj, obj.AmmoTypeIndex)) {
|
||||||
log.info(
|
log.info(
|
||||||
s"${player.Name} switched ${player.Sex.possessive} ${obj.Definition.Name} to construct ${obj.AmmoType} (option #${obj.FireModeIndex})"
|
s"${player.Name} switched ${player.Sex.possessive} ${obj.Definition.Name} to construct ${obj.AmmoType} (option #${obj.FireModeIndex})"
|
||||||
)
|
)
|
||||||
sendResponse(ChangeAmmoMessage(obj.GUID, obj.AmmoTypeIndex))
|
sendResponse(ChangeAmmoMessage(obj.GUID, obj.AmmoTypeIndex))
|
||||||
}
|
}
|
||||||
case tool : Tool =>
|
case tool: Tool =>
|
||||||
thing match {
|
thing match {
|
||||||
case Some(correctThing: PlanetSideServerObject with Container) =>
|
case Some(player: Player) =>
|
||||||
PerformToolAmmoChange(tool, correctThing)
|
PerformToolAmmoChange(tool, player, ModifyAmmunition(player))
|
||||||
|
case Some(mountable: PlanetSideServerObject with Container) =>
|
||||||
|
PerformToolAmmoChange(tool, mountable, ModifyAmmunitionInMountable(mountable))
|
||||||
case _ =>
|
case _ =>
|
||||||
log.warn(s"ChangeAmmo: the ${thing.get.Definition.Name} in ${player.Name}'s is not the correct type")
|
log.warn(s"ChangeAmmo: the ${thing.get.Definition.Name} in ${player.Name}'s is not the correct type")
|
||||||
}
|
}
|
||||||
|
|
@ -804,7 +717,7 @@ private[support] class WeaponAndProjectileOperations(
|
||||||
* @param reloadValue the value to modify the `AmmoBox`;
|
* @param reloadValue the value to modify the `AmmoBox`;
|
||||||
* subtracted from the current `Capacity` of `Box`
|
* subtracted from the current `Capacity` of `Box`
|
||||||
*/
|
*/
|
||||||
def ModifyAmmunitionInVehicle(obj: Vehicle)(box: AmmoBox, reloadValue: Int): Unit = {
|
def ModifyAmmunitionInMountable(obj: PlanetSideServerObject with Container)(box: AmmoBox, reloadValue: Int): Unit = {
|
||||||
ModifyAmmunition(obj)(box, reloadValue)
|
ModifyAmmunition(obj)(box, reloadValue)
|
||||||
obj.Find(box) match {
|
obj.Find(box) match {
|
||||||
case Some(index) =>
|
case Some(index) =>
|
||||||
|
|
@ -827,19 +740,19 @@ private[support] class WeaponAndProjectileOperations(
|
||||||
* @param tool na
|
* @param tool na
|
||||||
* @param obj na
|
* @param obj na
|
||||||
*/
|
*/
|
||||||
def PerformToolAmmoChange(tool: Tool, obj: PlanetSideServerObject with Container): Unit = {
|
def PerformToolAmmoChange(
|
||||||
|
tool: Tool,
|
||||||
|
obj: PlanetSideServerObject with Container,
|
||||||
|
modifyFunc: (AmmoBox, Int) => Unit
|
||||||
|
): Unit = {
|
||||||
val originalAmmoType = tool.AmmoType
|
val originalAmmoType = tool.AmmoType
|
||||||
do {
|
do {
|
||||||
val requestedAmmoType = tool.NextAmmoType
|
val requestedAmmoType = tool.NextAmmoType
|
||||||
val fullMagazine = tool.MaxMagazine
|
val fullMagazine = tool.MaxMagazine
|
||||||
if (requestedAmmoType != tool.AmmoSlot.Box.AmmoType) {
|
if (requestedAmmoType != tool.AmmoSlot.Box.AmmoType) {
|
||||||
FindEquipmentStock(obj, FindAmmoBoxThatUses(requestedAmmoType), fullMagazine, CountAmmunition).reverse match {
|
FindEquipmentStock(obj, FindAmmoBoxThatUses(requestedAmmoType), fullMagazine, CountAmmunition).reverse match {
|
||||||
case Nil => ;
|
case Nil => ()
|
||||||
case x :: xs =>
|
case x :: xs =>
|
||||||
val modifyFunc: (AmmoBox, Int) => Unit = obj match {
|
|
||||||
case veh: Vehicle => ModifyAmmunitionInVehicle(veh)
|
|
||||||
case _ => ModifyAmmunition(obj)
|
|
||||||
}
|
|
||||||
val stowNewFunc: Equipment => TaskBundle = PutNewEquipmentInInventoryOrDrop(obj)
|
val stowNewFunc: Equipment => TaskBundle = PutNewEquipmentInInventoryOrDrop(obj)
|
||||||
val stowFunc: Equipment => Future[Any] = PutEquipmentInInventoryOrDrop(obj)
|
val stowFunc: Equipment => Future[Any] = PutEquipmentInInventoryOrDrop(obj)
|
||||||
|
|
||||||
|
|
@ -1231,13 +1144,233 @@ private[support] class WeaponAndProjectileOperations(
|
||||||
*/
|
*/
|
||||||
def FindWeapon: Set[Tool] = FindContainedWeapon._2
|
def FindWeapon: Set[Tool] = FindContainedWeapon._2
|
||||||
|
|
||||||
|
/*
|
||||||
|
used by ChangeFireStateMessage_Start handling
|
||||||
|
*/
|
||||||
|
private def fireStateStartSetup(itemGuid: PlanetSideGUID): Unit = {
|
||||||
|
prefire -= itemGuid
|
||||||
|
shooting += itemGuid
|
||||||
|
shootingStart += itemGuid -> System.currentTimeMillis()
|
||||||
|
ongoingShotsFired = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
private def fireStateStartChargeMode(tool: Tool): Unit = {
|
||||||
|
//charge ammunition drain
|
||||||
|
tool.FireMode match {
|
||||||
|
case mode: ChargeFireModeDefinition =>
|
||||||
|
sessionData.progressBarValue = Some(0f)
|
||||||
|
sessionData.progressBarUpdate = context.system.scheduler.scheduleOnce(
|
||||||
|
(mode.Time + mode.DrainInterval) milliseconds,
|
||||||
|
context.self,
|
||||||
|
SessionActor.ProgressEvent(1f, () => {}, Tools.ChargeFireMode(player, tool), mode.DrainInterval)
|
||||||
|
)
|
||||||
|
case _ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def fireStateStartPlayerMessages(itemGuid: PlanetSideGUID): Unit = {
|
||||||
|
continent.AvatarEvents ! AvatarServiceMessage(
|
||||||
|
continent.id,
|
||||||
|
AvatarAction.ChangeFireState_Start(player.GUID, itemGuid)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def fireStateStartMountedMessages(itemGuid: PlanetSideGUID): Unit = {
|
||||||
|
continent.VehicleEvents ! VehicleServiceMessage(
|
||||||
|
continent.id,
|
||||||
|
VehicleAction.ChangeFireState_Start(player.GUID, itemGuid)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def allowFireStateChangeStart(tool: Tool, itemGuid: PlanetSideGUID): Boolean = {
|
||||||
|
tool.FireMode.RoundsPerShot == 0 || tool.Magazine > 0 || prefire.contains(itemGuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def enforceEmptyMagazine(tool: Tool, itemGuid: PlanetSideGUID): Unit = {
|
||||||
|
log.warn(
|
||||||
|
s"ChangeFireState_Start: ${player.Name}'s ${tool.Definition.Name} magazine was empty before trying to shoot"
|
||||||
|
)
|
||||||
|
EmptyMagazine(itemGuid, tool)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def fireStateStartWhenPlayer(tool: Tool, itemGuid: PlanetSideGUID): Unit = {
|
||||||
|
if (allowFireStateChangeStart(tool, itemGuid)) {
|
||||||
|
fireStateStartSetup(itemGuid)
|
||||||
|
//special case - suppress the decimator's alternate fire mode, by projectile
|
||||||
|
if (tool.Projectile != GlobalDefinitions.phoenix_missile_guided_projectile) {
|
||||||
|
fireStateStartPlayerMessages(itemGuid)
|
||||||
|
}
|
||||||
|
fireStateStartChargeMode(tool)
|
||||||
|
} else {
|
||||||
|
enforceEmptyMagazine(tool, itemGuid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def fireStateStartWhenMounted(tool: Tool, itemGuid: PlanetSideGUID): Unit = {
|
||||||
|
if (allowFireStateChangeStart(tool, itemGuid)) {
|
||||||
|
fireStateStartSetup(itemGuid)
|
||||||
|
fireStateStartMountedMessages(itemGuid)
|
||||||
|
fireStateStartChargeMode(tool)
|
||||||
|
} else {
|
||||||
|
enforceEmptyMagazine(tool, itemGuid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
used by ChangeFireStateMessage_Stop handling
|
||||||
|
*/
|
||||||
|
private def fireStateStopUpdateChargeAndCleanup(tool: Tool): Unit = {
|
||||||
|
avatarActor ! AvatarActor.UpdateToolDischarge(EquipmentStat(tool.Definition.ObjectId, ongoingShotsFired, 0, 0))
|
||||||
|
tool.FireMode match {
|
||||||
|
case _: ChargeFireModeDefinition =>
|
||||||
|
sendResponse(QuantityUpdateMessage(tool.AmmoSlot.Box.GUID, tool.Magazine))
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
if (tool.Magazine == 0) {
|
||||||
|
FireCycleCleanup(tool)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def fireStateStopPlayerMessages(itemGuid: PlanetSideGUID): Unit = {
|
||||||
|
continent.AvatarEvents ! AvatarServiceMessage(
|
||||||
|
continent.id,
|
||||||
|
AvatarAction.ChangeFireState_Stop(player.GUID, itemGuid)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def fireStateStopMountedMessages(itemGuid: PlanetSideGUID): Unit = {
|
||||||
|
continent.VehicleEvents ! VehicleServiceMessage(
|
||||||
|
continent.id,
|
||||||
|
VehicleAction.ChangeFireState_Stop(player.GUID, itemGuid)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def fireStateStopWhenPlayer(tool: Tool, itemGuid: PlanetSideGUID): Unit = {
|
||||||
|
//the decimator does not send a ChangeFireState_Start on the last shot; heaven knows why
|
||||||
|
//suppress the decimator's alternate fire mode, however
|
||||||
|
if (
|
||||||
|
tool.Definition == GlobalDefinitions.phoenix &&
|
||||||
|
tool.Projectile != GlobalDefinitions.phoenix_missile_guided_projectile
|
||||||
|
) {
|
||||||
|
fireStateStartPlayerMessages(itemGuid)
|
||||||
|
}
|
||||||
|
fireStateStopUpdateChargeAndCleanup(tool)
|
||||||
|
fireStateStopPlayerMessages(itemGuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def fireStateStopWhenMounted(tool: Tool, itemGuid: PlanetSideGUID): Unit = {
|
||||||
|
fireStateStopUpdateChargeAndCleanup(tool)
|
||||||
|
fireStateStopMountedMessages(itemGuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
used by ReloadMessage handling
|
||||||
|
*/
|
||||||
|
private def reloadPlayerMessages(itemGuid: PlanetSideGUID): Unit = {
|
||||||
|
continent.AvatarEvents ! AvatarServiceMessage(
|
||||||
|
continent.id,
|
||||||
|
AvatarAction.Reload(player.GUID, itemGuid)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def reloadVehicleMessages(itemGuid: PlanetSideGUID): Unit = {
|
||||||
|
continent.VehicleEvents ! VehicleServiceMessage(
|
||||||
|
continent.id,
|
||||||
|
VehicleAction.Reload(player.GUID, itemGuid)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def handleReloadProcedure(
|
||||||
|
itemGuid: PlanetSideGUID,
|
||||||
|
obj: PlanetSideGameObject with Container,
|
||||||
|
tools: Set[Tool],
|
||||||
|
unk1: Int,
|
||||||
|
deleteFunc: Equipment => Future[Any],
|
||||||
|
modifyFunc: (AmmoBox, Int) => Unit,
|
||||||
|
messageFunc: PlanetSideGUID => Unit
|
||||||
|
): Unit = {
|
||||||
|
tools
|
||||||
|
.filter { _.GUID == itemGuid }
|
||||||
|
.foreach { tool =>
|
||||||
|
val currentMagazine : Int = tool.Magazine
|
||||||
|
val magazineSize : Int = tool.MaxMagazine
|
||||||
|
val reloadValue : Int = magazineSize - currentMagazine
|
||||||
|
if (magazineSize > 0 && reloadValue > 0) {
|
||||||
|
FindEquipmentStock(obj, FindAmmoBoxThatUses(tool.AmmoType), reloadValue, CountAmmunition).reverse match {
|
||||||
|
case Nil => ()
|
||||||
|
case x :: xs =>
|
||||||
|
xs.foreach { item => deleteFunc(item.obj) }
|
||||||
|
val box = x.obj.asInstanceOf[AmmoBox]
|
||||||
|
val tailReloadValue : Int = if (xs.isEmpty) {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
xs.map(_.obj.asInstanceOf[AmmoBox].Capacity).sum
|
||||||
|
}
|
||||||
|
val sumReloadValue : Int = box.Capacity + tailReloadValue
|
||||||
|
val actualReloadValue = if (sumReloadValue <= reloadValue) {
|
||||||
|
deleteFunc(box)
|
||||||
|
sumReloadValue
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
modifyFunc(box, reloadValue - tailReloadValue)
|
||||||
|
reloadValue
|
||||||
|
}
|
||||||
|
val finalReloadValue = actualReloadValue + currentMagazine
|
||||||
|
log.info(
|
||||||
|
s"${player.Name} successfully reloaded $reloadValue ${tool.AmmoType} into ${tool.Definition.Name}"
|
||||||
|
)
|
||||||
|
tool.Magazine = finalReloadValue
|
||||||
|
sendResponse(ReloadMessage(itemGuid, finalReloadValue, unk1))
|
||||||
|
messageFunc(itemGuid)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//the weapon can not reload due to full magazine; the UI for the magazine is obvious bugged, so fix it
|
||||||
|
sendResponse(QuantityUpdateMessage(tool.AmmoSlot.Box.GUID, magazineSize))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def handleReloadWhenPlayer(
|
||||||
|
itemGuid: PlanetSideGUID,
|
||||||
|
obj: Player,
|
||||||
|
tools: Set[Tool],
|
||||||
|
unk1: Int
|
||||||
|
): Unit = {
|
||||||
|
handleReloadProcedure(
|
||||||
|
itemGuid,
|
||||||
|
obj,
|
||||||
|
tools,
|
||||||
|
unk1,
|
||||||
|
RemoveOldEquipmentFromInventory(obj)(_),
|
||||||
|
ModifyAmmunition(obj)(_, _),
|
||||||
|
reloadPlayerMessages
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def handleReloadWhenMountable(
|
||||||
|
itemGuid: PlanetSideGUID,
|
||||||
|
obj: PlanetSideServerObject with Container,
|
||||||
|
tools: Set[Tool],
|
||||||
|
unk1: Int
|
||||||
|
): Unit = {
|
||||||
|
handleReloadProcedure(
|
||||||
|
itemGuid,
|
||||||
|
obj,
|
||||||
|
tools,
|
||||||
|
unk1,
|
||||||
|
RemoveOldEquipmentFromInventory(obj)(_),
|
||||||
|
ModifyAmmunitionInMountable(obj)(_, _),
|
||||||
|
reloadVehicleMessages
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override protected[session] def stop(): Unit = {
|
override protected[session] def stop(): Unit = {
|
||||||
if (player != null && player.HasGUID) {
|
if (player != null && player.HasGUID) {
|
||||||
(prefire ++ shooting).foreach { guid =>
|
(prefire ++ shooting).foreach { guid =>
|
||||||
continent.AvatarEvents ! AvatarServiceMessage(
|
//do I need to do this? (maybe)
|
||||||
continent.id,
|
fireStateStopPlayerMessages(guid)
|
||||||
AvatarAction.ChangeFireState_Stop(player.GUID, guid)
|
fireStateStopMountedMessages(guid)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
projectiles.indices.foreach { projectiles.update(_, None) }
|
projectiles.indices.foreach { projectiles.update(_, None) }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8156,7 +8156,7 @@ object GlobalDefinitions {
|
||||||
lightgunship.DrownAtMaxDepth = true
|
lightgunship.DrownAtMaxDepth = true
|
||||||
lightgunship.MaxDepth = 2 //flying vehicles will automatically disable
|
lightgunship.MaxDepth = 2 //flying vehicles will automatically disable
|
||||||
lightgunship.Geometry = GeometryForm.representByCylinder(radius = 2.375f, height = 1.98438f)
|
lightgunship.Geometry = GeometryForm.representByCylinder(radius = 2.375f, height = 1.98438f)
|
||||||
lightgunship.collision.avatarCollisionDamageMax = 750
|
lightgunship.collision.avatarCollisionDamageMax = 75
|
||||||
lightgunship.collision.xy = CollisionXYData(Array((0.1f, 1), (0.25f, 60), (0.5f, 120), (0.75f, 180), (1f, 250)))
|
lightgunship.collision.xy = CollisionXYData(Array((0.1f, 1), (0.25f, 60), (0.5f, 120), (0.75f, 180), (1f, 250)))
|
||||||
lightgunship.collision.z = CollisionZData(Array((3f, 1), (9f, 30), (15f, 60), (18f, 90), (19.5f, 125)))
|
lightgunship.collision.z = CollisionZData(Array((3f, 1), (9f, 30), (15f, 60), (18f, 90), (19.5f, 125)))
|
||||||
lightgunship.maxForwardSpeed = 104f
|
lightgunship.maxForwardSpeed = 104f
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ class AvatarService(zone: Zone) extends Actor {
|
||||||
|
|
||||||
val AvatarEvents = new GenericEventBus[AvatarServiceResponse] //AvatarEventBus
|
val AvatarEvents = new GenericEventBus[AvatarServiceResponse] //AvatarEventBus
|
||||||
|
|
||||||
def receive = {
|
def receive: Receive = {
|
||||||
case Service.Join(channel) =>
|
case Service.Join(channel) =>
|
||||||
val path = s"/$channel/Avatar"
|
val path = s"/$channel/Avatar"
|
||||||
val who = sender()
|
val who = sender()
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ class VehicleService(zone: Zone) extends Actor {
|
||||||
|
|
||||||
val VehicleEvents = new GenericEventBus[VehicleServiceResponse]
|
val VehicleEvents = new GenericEventBus[VehicleServiceResponse]
|
||||||
|
|
||||||
def receive = {
|
def receive: Receive = {
|
||||||
case Service.Join(channel) =>
|
case Service.Join(channel) =>
|
||||||
val path = s"/$channel/Vehicle"
|
val path = s"/$channel/Vehicle"
|
||||||
VehicleEvents.subscribe(sender(), path)
|
VehicleEvents.subscribe(sender(), path)
|
||||||
|
|
@ -33,6 +33,26 @@ class VehicleService(zone: Zone) extends Actor {
|
||||||
|
|
||||||
case VehicleServiceMessage(forChannel, action) =>
|
case VehicleServiceMessage(forChannel, action) =>
|
||||||
action match {
|
action match {
|
||||||
|
case VehicleAction.ChangeAmmo(player_guid, weapon_guid, weapon_slot, old_ammo_guid, ammo_id, ammo_guid, ammo_data) =>
|
||||||
|
VehicleEvents.publish(
|
||||||
|
VehicleServiceResponse(
|
||||||
|
s"/$forChannel/Vehicle",
|
||||||
|
player_guid,
|
||||||
|
VehicleResponse.ChangeAmmo(weapon_guid, weapon_slot, old_ammo_guid, ammo_id, ammo_guid, ammo_data)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
case VehicleAction.ChangeFireState_Start(player_guid, weapon_guid) =>
|
||||||
|
VehicleEvents.publish(
|
||||||
|
VehicleServiceResponse(
|
||||||
|
s"/$forChannel/Vehicle",
|
||||||
|
player_guid,
|
||||||
|
VehicleResponse.ChangeFireState_Start(weapon_guid)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
case VehicleAction.ChangeFireState_Stop(player_guid, weapon_guid) =>
|
||||||
|
VehicleEvents.publish(
|
||||||
|
VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.ChangeFireState_Stop(weapon_guid))
|
||||||
|
)
|
||||||
case VehicleAction.ChildObjectState(player_guid, object_guid, pitch, yaw) =>
|
case VehicleAction.ChildObjectState(player_guid, object_guid, pitch, yaw) =>
|
||||||
VehicleEvents.publish(
|
VehicleEvents.publish(
|
||||||
VehicleServiceResponse(
|
VehicleServiceResponse(
|
||||||
|
|
@ -176,6 +196,11 @@ class VehicleService(zone: Zone) extends Actor {
|
||||||
VehicleResponse.PlanetsideAttribute(target_guid, attribute_type, attribute_value)
|
VehicleResponse.PlanetsideAttribute(target_guid, attribute_type, attribute_value)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
case VehicleAction.Reload(player_guid, weapon_guid) =>
|
||||||
|
VehicleEvents.publish(
|
||||||
|
VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.Reload(weapon_guid))
|
||||||
|
)
|
||||||
case VehicleAction.SeatPermissions(player_guid, vehicle_guid, seat_group, permission) =>
|
case VehicleAction.SeatPermissions(player_guid, vehicle_guid, seat_group, permission) =>
|
||||||
VehicleEvents.publish(
|
VehicleEvents.publish(
|
||||||
VehicleServiceResponse(
|
VehicleServiceResponse(
|
||||||
|
|
@ -199,6 +224,10 @@ class VehicleService(zone: Zone) extends Actor {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
case VehicleAction.WeaponDryFire(player_guid, weapon_guid) =>
|
||||||
|
VehicleEvents.publish(
|
||||||
|
VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.WeaponDryFire(weapon_guid))
|
||||||
|
)
|
||||||
case VehicleAction.UnloadVehicle(player_guid, vehicle, vehicle_guid) =>
|
case VehicleAction.UnloadVehicle(player_guid, vehicle, vehicle_guid) =>
|
||||||
VehicleEvents.publish(
|
VehicleEvents.publish(
|
||||||
VehicleServiceResponse(
|
VehicleServiceResponse(
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,17 @@ object VehicleServiceMessage {
|
||||||
object VehicleAction {
|
object VehicleAction {
|
||||||
trait Action
|
trait Action
|
||||||
|
|
||||||
|
final case class ChangeAmmo(
|
||||||
|
player_guid: PlanetSideGUID,
|
||||||
|
weapon_guid: PlanetSideGUID,
|
||||||
|
weapon_slot: Int,
|
||||||
|
old_ammo_guid: PlanetSideGUID,
|
||||||
|
ammo_id: Int,
|
||||||
|
ammo_guid: PlanetSideGUID,
|
||||||
|
ammo_data: ConstructorData
|
||||||
|
) 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 ChildObjectState(player_guid: PlanetSideGUID, object_guid: PlanetSideGUID, pitch: Float, yaw: Float)
|
final case class ChildObjectState(player_guid: PlanetSideGUID, object_guid: PlanetSideGUID, pitch: Float, yaw: Float)
|
||||||
extends Action
|
extends Action
|
||||||
final case class DeployRequest(
|
final case class DeployRequest(
|
||||||
|
|
@ -89,6 +100,7 @@ object VehicleAction {
|
||||||
attribute_type: Int,
|
attribute_type: Int,
|
||||||
attribute_value: Long
|
attribute_value: Long
|
||||||
) extends Action
|
) extends Action
|
||||||
|
final case class Reload(player_guid: PlanetSideGUID, weapon_guid: PlanetSideGUID) extends Action
|
||||||
final case class SeatPermissions(
|
final case class SeatPermissions(
|
||||||
player_guid: PlanetSideGUID,
|
player_guid: PlanetSideGUID,
|
||||||
vehicle_guid: PlanetSideGUID,
|
vehicle_guid: PlanetSideGUID,
|
||||||
|
|
@ -118,6 +130,7 @@ object VehicleAction {
|
||||||
unk6: Boolean
|
unk6: Boolean
|
||||||
) extends Action
|
) extends Action
|
||||||
final case class SendResponse(player_guid: PlanetSideGUID, msg: PlanetSideGamePacket) extends Action
|
final case class SendResponse(player_guid: PlanetSideGUID, msg: PlanetSideGamePacket) extends Action
|
||||||
|
final case class WeaponDryFire(player_guid: PlanetSideGUID, weapon_guid: PlanetSideGUID) extends Action
|
||||||
final case class UpdateAmsSpawnPoint(zone: Zone) extends Action
|
final case class UpdateAmsSpawnPoint(zone: Zone) extends Action
|
||||||
|
|
||||||
final case class TransferPassengerChannel(
|
final case class TransferPassengerChannel(
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,16 @@ final case class VehicleServiceResponse(
|
||||||
object VehicleResponse {
|
object VehicleResponse {
|
||||||
trait Response
|
trait Response
|
||||||
|
|
||||||
|
final case class ChangeAmmo(
|
||||||
|
weapon_guid: PlanetSideGUID,
|
||||||
|
weapon_slot: Int,
|
||||||
|
old_ammo_guid: PlanetSideGUID,
|
||||||
|
ammo_id: Int,
|
||||||
|
ammo_guid: PlanetSideGUID,
|
||||||
|
ammo_data: ConstructorData
|
||||||
|
) 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 ChildObjectState(object_guid: PlanetSideGUID, pitch: Float, yaw: Float) extends Response
|
final case class ChildObjectState(object_guid: PlanetSideGUID, pitch: Float, yaw: Float) extends Response
|
||||||
final case class ConcealPlayer(player_guid: PlanetSideGUID) extends Response
|
final case class ConcealPlayer(player_guid: PlanetSideGUID) extends Response
|
||||||
final case class DeployRequest(
|
final case class DeployRequest(
|
||||||
|
|
@ -66,8 +76,9 @@ object VehicleResponse {
|
||||||
final case class Ownership(vehicle_guid: PlanetSideGUID) extends Response
|
final case class Ownership(vehicle_guid: PlanetSideGUID) extends Response
|
||||||
final case class PlanetsideAttribute(vehicle_guid: PlanetSideGUID, attribute_type: Int, attribute_value: Long)
|
final case class PlanetsideAttribute(vehicle_guid: PlanetSideGUID, attribute_type: Int, attribute_value: Long)
|
||||||
extends Response
|
extends Response
|
||||||
final case class RevealPlayer(player_guid: PlanetSideGUID) extends Response
|
final case class Reload(weapon_guid: PlanetSideGUID) extends Response
|
||||||
final case class SeatPermissions(vehicle_guid: PlanetSideGUID, seat_group: Int, permission: Long) extends Response
|
final case class RevealPlayer(player_guid: PlanetSideGUID) extends Response
|
||||||
|
final case class SeatPermissions(vehicle_guid: PlanetSideGUID, seat_group: Int, permission: Long) extends Response
|
||||||
final case class StowEquipment(
|
final case class StowEquipment(
|
||||||
vehicle_guid: PlanetSideGUID,
|
vehicle_guid: PlanetSideGUID,
|
||||||
slot: Int,
|
slot: Int,
|
||||||
|
|
@ -75,6 +86,7 @@ object VehicleResponse {
|
||||||
iguid: PlanetSideGUID,
|
iguid: PlanetSideGUID,
|
||||||
idata: ConstructorData
|
idata: ConstructorData
|
||||||
) extends Response
|
) extends Response
|
||||||
|
final case class WeaponDryFire(weapon_guid: PlanetSideGUID) extends Response
|
||||||
final case class UnloadVehicle(vehicle: Vehicle, vehicle_guid: PlanetSideGUID) extends Response
|
final case class UnloadVehicle(vehicle: Vehicle, vehicle_guid: PlanetSideGUID) extends Response
|
||||||
final case class UnstowEquipment(item_guid: PlanetSideGUID) extends Response
|
final case class UnstowEquipment(item_guid: PlanetSideGUID) extends Response
|
||||||
final case class VehicleState(
|
final case class VehicleState(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue