mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-19 18:14:44 +00:00
recovery from original angles branch, mostly concerning changes with ChangeFireStateMessage_Stop and WeaponFireMessage field info
This commit is contained in:
parent
2216958d72
commit
42db02f576
|
|
@ -4120,46 +4120,24 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
case msg @ ChangeFireStateMessage_Stop(item_guid) =>
|
case msg @ ChangeFireStateMessage_Stop(item_guid) =>
|
||||||
prefire = None
|
prefire = None
|
||||||
shootingStop = System.currentTimeMillis()
|
shootingStop = System.currentTimeMillis()
|
||||||
val weapon: Option[Equipment] = if (shooting.contains(item_guid)) {
|
if (shooting.contains(item_guid)) {
|
||||||
shooting = None
|
shooting = None
|
||||||
continent.AvatarEvents ! AvatarServiceMessage(
|
|
||||||
continent.id,
|
|
||||||
AvatarAction.ChangeFireState_Stop(player.GUID, item_guid)
|
|
||||||
)
|
|
||||||
FindEquipment
|
|
||||||
} else {
|
|
||||||
FindEquipment match {
|
|
||||||
case Some(tool: Tool) => //special cases
|
|
||||||
//the decimator does not send a ChangeFireState_Start on the last shot
|
|
||||||
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(player.GUID, item_guid)
|
|
||||||
)
|
|
||||||
shootingStart = System.currentTimeMillis() - 1L
|
|
||||||
}
|
|
||||||
continent.AvatarEvents ! AvatarServiceMessage(
|
|
||||||
continent.id,
|
|
||||||
AvatarAction.ChangeFireState_Stop(player.GUID, item_guid)
|
|
||||||
)
|
|
||||||
Some(tool)
|
|
||||||
case Some(tool) => //permissible, for now
|
|
||||||
continent.AvatarEvents ! AvatarServiceMessage(
|
|
||||||
continent.id,
|
|
||||||
AvatarAction.ChangeFireState_Stop(player.GUID, item_guid)
|
|
||||||
)
|
|
||||||
Some(tool)
|
|
||||||
case _ =>
|
|
||||||
//log.warn(s"ChangeFireState_Stop: ${player.Name} never started firing item ${item_guid.guid} in the first place?")
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
weapon match {
|
val pguid = player.GUID
|
||||||
|
FindEquipment match {
|
||||||
case Some(tool: Tool) =>
|
case Some(tool: Tool) =>
|
||||||
|
//the decimator does not send a ChangeFireState_Start on the last shot; heaven knows why
|
||||||
|
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 = System.currentTimeMillis() - 1L
|
||||||
|
}
|
||||||
tool.FireMode match {
|
tool.FireMode match {
|
||||||
case mode: ChargeFireModeDefinition =>
|
case mode: ChargeFireModeDefinition =>
|
||||||
sendResponse(QuantityUpdateMessage(tool.AmmoSlot.Box.GUID, tool.Magazine))
|
sendResponse(QuantityUpdateMessage(tool.AmmoSlot.Box.GUID, tool.Magazine))
|
||||||
|
|
@ -4168,18 +4146,24 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
if (tool.Magazine == 0) {
|
if (tool.Magazine == 0) {
|
||||||
FireCycleCleanup(tool)
|
FireCycleCleanup(tool)
|
||||||
}
|
}
|
||||||
case Some(trigger: BoomerTrigger) =>
|
|
||||||
val playerGUID = player.GUID
|
|
||||||
continent.AvatarEvents ! AvatarServiceMessage(
|
continent.AvatarEvents ! AvatarServiceMessage(
|
||||||
continent.id,
|
continent.id,
|
||||||
AvatarAction.ChangeFireState_Start(playerGUID, item_guid)
|
AvatarAction.ChangeFireState_Stop(pguid, item_guid)
|
||||||
|
)
|
||||||
|
|
||||||
|
case Some(trigger: BoomerTrigger) =>
|
||||||
|
continent.AvatarEvents ! AvatarServiceMessage(
|
||||||
|
continent.id,
|
||||||
|
AvatarAction.ChangeFireState_Start(pguid, item_guid)
|
||||||
)
|
)
|
||||||
continent.GUID(trigger.Companion) match {
|
continent.GUID(trigger.Companion) match {
|
||||||
case Some(boomer: BoomerDeployable) =>
|
case Some(boomer: BoomerDeployable) =>
|
||||||
boomer.Actor ! CommonMessages.Use(player, Some(trigger))
|
boomer.Actor ! CommonMessages.Use(player, Some(trigger))
|
||||||
case Some(_) | None => ;
|
case Some(_) | None => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
case _ => ;
|
case _ => ;
|
||||||
|
//log.warn(s"ChangeFireState_Stop: ${player.Name} never started firing item ${item_guid.guid} in the first place?")
|
||||||
}
|
}
|
||||||
progressBarUpdate.cancel()
|
progressBarUpdate.cancel()
|
||||||
progressBarValue = None
|
progressBarValue = None
|
||||||
|
|
@ -5128,19 +5112,19 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
}
|
}
|
||||||
|
|
||||||
case msg @ WeaponFireMessage(
|
case msg @ WeaponFireMessage(
|
||||||
seq_time,
|
_,
|
||||||
weapon_guid,
|
weapon_guid,
|
||||||
projectile_guid,
|
projectile_guid,
|
||||||
shot_origin,
|
shot_origin,
|
||||||
unk1,
|
_,
|
||||||
unk2,
|
_,
|
||||||
unk3,
|
_,
|
||||||
unk4,
|
_, //max_distance,
|
||||||
unk5,
|
_,
|
||||||
unk6,
|
_, //projectile_type,
|
||||||
unk7
|
thrown_projectile_vel
|
||||||
) =>
|
) =>
|
||||||
HandleWeaponFire(weapon_guid, projectile_guid, shot_origin)
|
HandleWeaponFire(weapon_guid, projectile_guid, shot_origin, thrown_projectile_vel.flatten)
|
||||||
|
|
||||||
case msg @ WeaponLazeTargetPositionMessage(_, _, pos2) =>
|
case msg @ WeaponLazeTargetPositionMessage(_, _, pos2) =>
|
||||||
log.info(s"${player.Name} is lazing the position ${continent.id}@(${pos2.x},${pos2.y},${pos2.z})")
|
log.info(s"${player.Name} is lazing the position ${continent.id}@(${pos2.x},${pos2.y},${pos2.z})")
|
||||||
|
|
@ -9009,7 +8993,12 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
middlewareActor ! MiddlewareActor.Teardown()
|
middlewareActor ! MiddlewareActor.Teardown()
|
||||||
}
|
}
|
||||||
|
|
||||||
def HandleWeaponFire(weaponGUID: PlanetSideGUID, projectileGUID: PlanetSideGUID, shotOrigin: Vector3): Unit = {
|
def HandleWeaponFire(
|
||||||
|
weaponGUID: PlanetSideGUID,
|
||||||
|
projectileGUID: PlanetSideGUID,
|
||||||
|
shotOrigin: Vector3,
|
||||||
|
shotVelocity: Option[Vector3]
|
||||||
|
): Unit = {
|
||||||
HandleWeaponFireAccountability(weaponGUID, projectileGUID) match {
|
HandleWeaponFireAccountability(weaponGUID, projectileGUID) match {
|
||||||
case (Some(obj), Some(tool)) =>
|
case (Some(obj), Some(tool)) =>
|
||||||
val projectileIndex = projectileGUID.guid - Projectile.baseUID
|
val projectileIndex = projectileGUID.guid - Projectile.baseUID
|
||||||
|
|
@ -9054,10 +9043,11 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
projectile_info,
|
projectile_info,
|
||||||
tool.Definition,
|
tool.Definition,
|
||||||
tool.FireMode,
|
tool.FireMode,
|
||||||
player,
|
PlayerSource(player),
|
||||||
attribution,
|
attribution,
|
||||||
shotOrigin,
|
shotOrigin,
|
||||||
angle
|
angle,
|
||||||
|
shotVelocity
|
||||||
)
|
)
|
||||||
val initialQuality = tool.FireMode match {
|
val initialQuality = tool.FireMode match {
|
||||||
case mode: ChargeFireModeDefinition =>
|
case mode: ChargeFireModeDefinition =>
|
||||||
|
|
@ -9071,18 +9061,14 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
s"WeaponFireMessage: ${player.Name}'s ${projectile_info.Name} is a remote projectile"
|
s"WeaponFireMessage: ${player.Name}'s ${projectile_info.Name} is a remote projectile"
|
||||||
)
|
)
|
||||||
continent.tasks ! (if (projectile.HasGUID) {
|
continent.tasks ! (if (projectile.HasGUID) {
|
||||||
continent.AvatarEvents ! AvatarServiceMessage(
|
continent.AvatarEvents ! AvatarServiceMessage(
|
||||||
continent.id,
|
continent.id,
|
||||||
AvatarAction.ProjectileExplodes(
|
AvatarAction.ProjectileExplodes(player.GUID, projectile.GUID, projectile)
|
||||||
player.GUID,
|
)
|
||||||
projectile.GUID,
|
ReregisterProjectile(projectile)
|
||||||
projectile
|
} else {
|
||||||
)
|
RegisterProjectile(projectile)
|
||||||
)
|
})
|
||||||
ReregisterProjectile(projectile)
|
|
||||||
} else {
|
|
||||||
RegisterProjectile(projectile)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
projectilesToCleanUp(projectileIndex) = false
|
projectilesToCleanUp(projectileIndex) = false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import net.psforever.objects.vital.base.DamageResolution
|
||||||
import net.psforever.types.Vector3
|
import net.psforever.types.Vector3
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A summation of weapon (`Tool`) discharge.
|
* A summation of weapon discharge.
|
||||||
* @see `ProjectileDefinition`
|
* @see `ProjectileDefinition`
|
||||||
* @see `ToolDefinition`
|
* @see `ToolDefinition`
|
||||||
* @see `FireModeDefinition`
|
* @see `FireModeDefinition`
|
||||||
|
|
@ -28,9 +28,10 @@ import net.psforever.types.Vector3
|
||||||
* if not, then it is a type of vehicle (and owner should have a positive `seated` field)
|
* if not, then it is a type of vehicle (and owner should have a positive `seated` field)
|
||||||
* @param shot_origin where the projectile started
|
* @param shot_origin where the projectile started
|
||||||
* @param shot_angle in which direction the projectile was aimed when it was discharged
|
* @param shot_angle in which direction the projectile was aimed when it was discharged
|
||||||
|
* @param shot_velocity the initial velocity coordinates of the projectile according to its world directions
|
||||||
* @param quality na
|
* @param quality na
|
||||||
* @param id an exclusive identifier for this projectile;
|
* @param id an exclusive identifier for this projectile;
|
||||||
* normally generated internally, but can be manually set
|
* normally generated internally, but can be manually set (for modifying a continuous projectile reference)
|
||||||
* @param fire_time when the weapon discharged was recorded;
|
* @param fire_time when the weapon discharged was recorded;
|
||||||
* defaults to `System.currentTimeMillis()`
|
* defaults to `System.currentTimeMillis()`
|
||||||
*/
|
*/
|
||||||
|
|
@ -42,18 +43,20 @@ final case class Projectile(
|
||||||
attribute_to: Int,
|
attribute_to: Int,
|
||||||
shot_origin: Vector3,
|
shot_origin: Vector3,
|
||||||
shot_angle: Vector3,
|
shot_angle: Vector3,
|
||||||
|
shot_velocity: Option[Vector3],
|
||||||
quality: ProjectileQuality = ProjectileQuality.Normal,
|
quality: ProjectileQuality = ProjectileQuality.Normal,
|
||||||
id: Long = Projectile.idGenerator.getAndIncrement(),
|
id: Long = Projectile.idGenerator.getAndIncrement(),
|
||||||
fire_time: Long = System.currentTimeMillis()
|
fire_time: Long = System.currentTimeMillis()
|
||||||
) extends PlanetSideGameObject {
|
) extends PlanetSideGameObject {
|
||||||
Position = shot_origin
|
Position = shot_origin
|
||||||
Orientation = shot_angle
|
Orientation = shot_angle
|
||||||
Velocity = {
|
Velocity = shot_velocity.getOrElse {
|
||||||
val initVel: Int = profile.InitialVelocity //initial velocity
|
val radz = math.toRadians(shot_angle.z)
|
||||||
val radAngle: Double = math.toRadians(shot_angle.y) //angle of elevation
|
Vector3.Unit(Vector3(
|
||||||
val rise: Float = initVel * math.sin(radAngle).toFloat //z
|
math.sin(radz).toFloat,
|
||||||
val ground: Float = initVel * math.cos(radAngle).toFloat //base
|
math.cos(radz).toFloat,
|
||||||
Vector3.Rz(Vector3(0, -ground, 0), shot_angle.z) + Vector3.z(rise)
|
math.sin(math.toRadians(shot_angle.y)).toFloat
|
||||||
|
)) * profile.InitialVelocity.toFloat
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Information about the current world coordinates and orientation of the projectile */
|
/** Information about the current world coordinates and orientation of the projectile */
|
||||||
|
|
@ -77,6 +80,7 @@ final case class Projectile(
|
||||||
attribute_to,
|
attribute_to,
|
||||||
shot_origin,
|
shot_origin,
|
||||||
shot_angle,
|
shot_angle,
|
||||||
|
shot_velocity,
|
||||||
value,
|
value,
|
||||||
id,
|
id,
|
||||||
fire_time
|
fire_time
|
||||||
|
|
@ -127,14 +131,14 @@ object Projectile {
|
||||||
* @return the `Projectile` object
|
* @return the `Projectile` object
|
||||||
*/
|
*/
|
||||||
def apply(
|
def apply(
|
||||||
profile: ProjectileDefinition,
|
profile: ProjectileDefinition,
|
||||||
tool_def: ToolDefinition,
|
tool_def: ToolDefinition,
|
||||||
fire_mode: FireModeDefinition,
|
fire_mode: FireModeDefinition,
|
||||||
owner: PlanetSideGameObject with FactionAffinity,
|
owner: PlanetSideGameObject with FactionAffinity,
|
||||||
shot_origin: Vector3,
|
shot_origin: Vector3,
|
||||||
shot_angle: Vector3
|
shot_angle: Vector3
|
||||||
): Projectile = {
|
): Projectile = {
|
||||||
Projectile(profile, tool_def, fire_mode, SourceEntry(owner), tool_def.ObjectId, shot_origin, shot_angle)
|
Projectile(profile, tool_def, fire_mode, SourceEntry(owner), tool_def.ObjectId, shot_origin, shot_angle, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -149,14 +153,26 @@ object Projectile {
|
||||||
* @return the `Projectile` object
|
* @return the `Projectile` object
|
||||||
*/
|
*/
|
||||||
def apply(
|
def apply(
|
||||||
profile: ProjectileDefinition,
|
profile: ProjectileDefinition,
|
||||||
tool_def: ToolDefinition,
|
tool_def: ToolDefinition,
|
||||||
fire_mode: FireModeDefinition,
|
fire_mode: FireModeDefinition,
|
||||||
owner: PlanetSideGameObject with FactionAffinity,
|
owner: PlanetSideGameObject with FactionAffinity,
|
||||||
attribute_to: Int,
|
attribute_to: Int,
|
||||||
shot_origin: Vector3,
|
shot_origin: Vector3,
|
||||||
shot_angle: Vector3
|
shot_angle: Vector3
|
||||||
): Projectile = {
|
): Projectile = {
|
||||||
Projectile(profile, tool_def, fire_mode, SourceEntry(owner), attribute_to, shot_origin, shot_angle)
|
Projectile(profile, tool_def, fire_mode, SourceEntry(owner), attribute_to, shot_origin, shot_angle, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
def apply(
|
||||||
|
profile: ProjectileDefinition,
|
||||||
|
tool_def: ToolDefinition,
|
||||||
|
fire_mode: FireModeDefinition,
|
||||||
|
owner: SourceEntry,
|
||||||
|
attribute_to: Int,
|
||||||
|
shot_origin: Vector3,
|
||||||
|
shot_angle: Vector3
|
||||||
|
): Projectile = {
|
||||||
|
Projectile(profile, tool_def, fire_mode, owner, attribute_to, shot_origin, shot_angle, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,79 @@
|
||||||
// Copyright (c) 2017 PSForever
|
// Copyright (c) 2017 PSForever
|
||||||
package net.psforever.packet.game
|
package net.psforever.packet.game
|
||||||
|
|
||||||
import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket}
|
import enumeratum.values.{IntEnum, IntEnumEntry}
|
||||||
|
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
|
||||||
import net.psforever.types.{PlanetSideGUID, Vector3}
|
import net.psforever.types.{PlanetSideGUID, Vector3}
|
||||||
import scodec.Codec
|
import scodec.Codec
|
||||||
import scodec.codecs._
|
import scodec.codecs._
|
||||||
|
|
||||||
|
sealed abstract class ProjectileCharacteristics(val value: Int) extends IntEnumEntry
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WeaponFireMessage seems to be sent each time a weapon actually shoots.
|
* Characteristics about the projectile being produced by a `WeaponFireMessage` packet.
|
||||||
|
* Not really useful outside of `WeaponFireMessage`?
|
||||||
|
*/
|
||||||
|
object ProjectileCharacteristics extends IntEnum[ProjectileCharacteristics] {
|
||||||
|
val values = findValues
|
||||||
|
|
||||||
|
/** most common characteristic;
|
||||||
|
* utilized for both straight-fire and various arcing projectiles
|
||||||
|
*/
|
||||||
|
case object Standard extends ProjectileCharacteristics(value = 0)
|
||||||
|
/** some arcing explosive projectiles such as the Thumper's alternate fire and the Leviathan's fluxpod launcher;
|
||||||
|
* exceptions include: Punisher grenade cartridges, Grenade alternate fire (see `Thrown`), Pounder alternate fire
|
||||||
|
*/
|
||||||
|
case object DelayedExplosion extends ProjectileCharacteristics(value = 1)
|
||||||
|
/** remote client projectiles (those constructed through packets) */
|
||||||
|
case object Guided extends ProjectileCharacteristics(value = 2)
|
||||||
|
/** grenades, and only grenades */
|
||||||
|
case object Thrown extends ProjectileCharacteristics(value = 3)
|
||||||
|
|
||||||
|
/** unused? */
|
||||||
|
case object u4 extends ProjectileCharacteristics(value = 4)
|
||||||
|
/** unused? */
|
||||||
|
case object u5 extends ProjectileCharacteristics(value = 5)
|
||||||
|
/** unused? */
|
||||||
|
case object u6 extends ProjectileCharacteristics(value = 6)
|
||||||
|
/** unused? */
|
||||||
|
case object u7 extends ProjectileCharacteristics(value = 7)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatched form the client each time a weapon discharges.
|
||||||
*
|
*
|
||||||
* @param seq_time See [[PlayerStateMessageUpstream]] for explanation of seq_time.
|
* @param seq_time see [[PlayerStateMessageUpstream]] for explanation of seq_time
|
||||||
* @param weapon_guid
|
* @param weapon_guid the weapon of discharge;
|
||||||
* @param projectile_guid
|
* when dispatched to a client, an unreferenced entity results in the projectile not being rendered
|
||||||
* @param shot_origin
|
* @param projectile_guid the (client-local) projectile unique identifier;
|
||||||
* @param unk1 Always zero from testing so far
|
* when dispatched to a client, can be unreferenced (or blanked)
|
||||||
* @param unk2 Seems semi-random
|
* @param shot_origin the position where the projectile is first spawned
|
||||||
* @param unk3 Seems semi-random
|
* @param unk1 na;
|
||||||
* @param unk4 Maximum travel distance in meters - seems to be zero for decimator rockets
|
* always 0?
|
||||||
* @param unk5 Possibly always 255 from testing
|
* @param spread_a related to the spread of the discharge;
|
||||||
* @param unk6 0 for bullet
|
* works with `spread_b` field in unknown way;
|
||||||
* 1 for possibly delayed explosion (thumper alt fire) or thresher/leviathan flux cannon
|
* the unmodified value is high (65535) when accurate, low (0) when not
|
||||||
* 2 for vs starfire (lockon type?)
|
* @param spread_b related to the spread of the discharge;
|
||||||
* 3 for thrown (e.g. grenades)
|
* works with `spread_a` field in unknown way
|
||||||
* @param unk7 Seems to be thrown weapon velocity/direction
|
* @param max_distance maximum travel distance (m), with exceptions, e.g., decimator rockets are always 0
|
||||||
|
* @param unk5 na;
|
||||||
|
* always 255?
|
||||||
|
* @param projectile_type the sort of projectile produced
|
||||||
|
* @param thrown_projectile_vel if a thrown projectile, its velocity
|
||||||
*/
|
*/
|
||||||
final case class WeaponFireMessage(
|
final case class WeaponFireMessage(
|
||||||
seq_time: Int,
|
seq_time: Int,
|
||||||
weapon_guid: PlanetSideGUID,
|
weapon_guid: PlanetSideGUID,
|
||||||
projectile_guid: PlanetSideGUID,
|
projectile_guid: PlanetSideGUID,
|
||||||
shot_origin: Vector3,
|
shot_origin: Vector3,
|
||||||
unk1: Int,
|
unk1: Int,
|
||||||
unk2: Int,
|
spread_a: Int,
|
||||||
unk3: Int,
|
spread_b: Int,
|
||||||
unk4: Int,
|
max_distance: Int,
|
||||||
unk5: Int,
|
unk5: Int,
|
||||||
unk6: Int,
|
projectile_type: ProjectileCharacteristics,
|
||||||
unk7: Option[Option[Vector3]]
|
thrown_projectile_vel: Option[Option[Vector3]]
|
||||||
) extends PlanetSideGamePacket {
|
) extends PlanetSideGamePacket {
|
||||||
type Packet = WeaponFireMessage
|
type Packet = WeaponFireMessage
|
||||||
def opcode = GamePacketOpcode.WeaponFireMessage
|
def opcode = GamePacketOpcode.WeaponFireMessage
|
||||||
def encode = WeaponFireMessage.encode(this)
|
def encode = WeaponFireMessage.encode(this)
|
||||||
|
|
@ -44,17 +81,17 @@ final case class WeaponFireMessage(
|
||||||
|
|
||||||
object WeaponFireMessage extends Marshallable[WeaponFireMessage] {
|
object WeaponFireMessage extends Marshallable[WeaponFireMessage] {
|
||||||
implicit val codec: Codec[WeaponFireMessage] = (
|
implicit val codec: Codec[WeaponFireMessage] = (
|
||||||
("seq_time" | uintL(10)) ::
|
("seq_time" | uintL(bits = 10)) ::
|
||||||
("weapon_guid" | PlanetSideGUID.codec) ::
|
("weapon_guid" | PlanetSideGUID.codec) ::
|
||||||
("projectile_guid" | PlanetSideGUID.codec) ::
|
("projectile_guid" | PlanetSideGUID.codec) ::
|
||||||
("shot_origin" | Vector3.codec_pos) ::
|
("shot_origin" | Vector3.codec_pos) ::
|
||||||
("unk1" | uint16L) ::
|
("unk1" | uint16L) ::
|
||||||
("unk2" | uint16L) ::
|
("spread_a" | uint16L.xmap[Int]( { x => 65535 - x }, { x => 65535 - x })) :: //low when accurate, high when not
|
||||||
("unk3" | uint16L) ::
|
("spread_b" | uint16L) ::
|
||||||
("unk4" | uint16L) ::
|
("max_distance" | uint16L) ::
|
||||||
("unk5" | uint8L) ::
|
("unk5" | uint8L) ::
|
||||||
(("unk6" | uintL(3)) >>:~ { unk6_value =>
|
("projectile_type" | PacketHelpers.createIntEnumCodec(ProjectileCharacteristics, uint(bits = 3)) >>:~ { ptype =>
|
||||||
conditional(unk6_value == 3, "unk7" | optional(bool, Vector3.codec_vel)).hlist
|
("thrown_projectile_vel" | conditional(ptype == ProjectileCharacteristics.Thrown, optional(bool, Vector3.codec_vel))).hlist
|
||||||
})
|
})
|
||||||
).as[WeaponFireMessage]
|
).as[WeaponFireMessage]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,12 @@ class WeaponFireMessageTest extends Specification {
|
||||||
projectile_guid mustEqual PlanetSideGUID(40100)
|
projectile_guid mustEqual PlanetSideGUID(40100)
|
||||||
shot_origin mustEqual Vector3(3675.4688f, 2726.9922f, 92.921875f)
|
shot_origin mustEqual Vector3(3675.4688f, 2726.9922f, 92.921875f)
|
||||||
unk1 mustEqual 0
|
unk1 mustEqual 0
|
||||||
unk2 mustEqual 64294
|
unk2 mustEqual 1241
|
||||||
unk3 mustEqual 1502
|
unk3 mustEqual 1502
|
||||||
unk4 mustEqual 200
|
unk4 mustEqual 200
|
||||||
unk5 mustEqual 255
|
unk5 mustEqual 255
|
||||||
unk6 mustEqual 0
|
unk6 mustEqual ProjectileCharacteristics.Standard
|
||||||
unk7 mustEqual None
|
unk7.isEmpty mustEqual true
|
||||||
case _ =>
|
case _ =>
|
||||||
ko
|
ko
|
||||||
}
|
}
|
||||||
|
|
@ -48,11 +48,11 @@ class WeaponFireMessageTest extends Specification {
|
||||||
PlanetSideGUID(40100),
|
PlanetSideGUID(40100),
|
||||||
Vector3(3675.4688f, 2726.9922f, 92.921875f),
|
Vector3(3675.4688f, 2726.9922f, 92.921875f),
|
||||||
0,
|
0,
|
||||||
64294,
|
1241,
|
||||||
1502,
|
1502,
|
||||||
200,
|
200,
|
||||||
255,
|
255,
|
||||||
0,
|
ProjectileCharacteristics.Standard,
|
||||||
None
|
None
|
||||||
)
|
)
|
||||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue