mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-15 08:24:39 +00:00
Merge pull request #141 from Fate-JH/projectile-state
Packet: ProjectileStateMessage
This commit is contained in:
commit
9a1a4a1dd1
4 changed files with 113 additions and 1 deletions
|
|
@ -392,7 +392,7 @@ object GamePacketOpcode extends Enumeration {
|
||||||
case 0x3c => game.GenericCollisionMsg.decode
|
case 0x3c => game.GenericCollisionMsg.decode
|
||||||
case 0x3d => game.QuantityUpdateMessage.decode
|
case 0x3d => game.QuantityUpdateMessage.decode
|
||||||
case 0x3e => game.ArmorChangedMessage.decode
|
case 0x3e => game.ArmorChangedMessage.decode
|
||||||
case 0x3f => noDecoder(ProjectileStateMessage)
|
case 0x3f => game.ProjectileStateMessage.decode
|
||||||
|
|
||||||
// OPCODES 0x40-4f
|
// OPCODES 0x40-4f
|
||||||
case 0x40 => noDecoder(MountVehicleCargoMsg)
|
case 0x40 => noDecoder(MountVehicleCargoMsg)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.packet.game
|
||||||
|
|
||||||
|
import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket}
|
||||||
|
import net.psforever.types.Vector3
|
||||||
|
import scodec.Codec
|
||||||
|
import scodec.codecs._
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatched to deliberately render certain projectiles of a weapon on other players' clients.<br>
|
||||||
|
* <br>
|
||||||
|
* This packet is generated by firing specific weapons in specific fire modes.
|
||||||
|
* For example, the Phoenix (`hunterseeker`) discharged in its primary fire mode generates this packet;
|
||||||
|
* but, the Phoenix in secondary fire mode does not.
|
||||||
|
* The Striker (`striker`) discharged in its primary fire mode generates this packet;
|
||||||
|
* but, the Striker in secondary fire mode does not.
|
||||||
|
* The chosen fire mode(s) are not a straight-fire projectile but one that has special control asserted over it.
|
||||||
|
* For the Phoenix, it is user-operated.
|
||||||
|
* For the Striker, it tracks towards a target while the weapon's reticle hovers over that target.<br>
|
||||||
|
* <br>
|
||||||
|
* This packet will continue to be dispatched by the client for as long as the projectile being tracked is in the air.
|
||||||
|
* All projectiles have a maximum lifespan before they will lose control and either despawn and/or explode.
|
||||||
|
* This number is tracked in the packet for simplicity.
|
||||||
|
* If the projectile strikes a valid target, the count will jump to a significantly enormous value beyond its normal lifespan.
|
||||||
|
* This ensures that the projectile - locally and the shared model - will despawn.
|
||||||
|
* @param projectile_guid the projectile
|
||||||
|
* @param shot_pos the position of the projectile
|
||||||
|
* @param shot_vel the velocity of the projectile
|
||||||
|
* @param unk1 na;
|
||||||
|
* usually 0
|
||||||
|
* @param unk2 na;
|
||||||
|
* will remain consistent for the lifespan of a given projectile in most cases
|
||||||
|
* @param unk3 na;
|
||||||
|
* will remain consistent for the lifespan of a given projectile in most cases
|
||||||
|
* @param unk4 na;
|
||||||
|
* usually false
|
||||||
|
* @param time_alive how long the projectile has been in the air;
|
||||||
|
* often expressed in multiples of 2
|
||||||
|
*/
|
||||||
|
final case class ProjectileStateMessage(projectile_guid : PlanetSideGUID,
|
||||||
|
shot_pos : Vector3,
|
||||||
|
shot_vel : Vector3,
|
||||||
|
unk1 : Int,
|
||||||
|
unk2 : Int,
|
||||||
|
unk3 : Int,
|
||||||
|
unk4 : Boolean,
|
||||||
|
time_alive : Int)
|
||||||
|
extends PlanetSideGamePacket {
|
||||||
|
type Packet = ProjectileStateMessage
|
||||||
|
def opcode = GamePacketOpcode.ProjectileStateMessage
|
||||||
|
def encode = ProjectileStateMessage.encode(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
object ProjectileStateMessage extends Marshallable[ProjectileStateMessage] {
|
||||||
|
implicit val codec : Codec[ProjectileStateMessage] = (
|
||||||
|
("projectile_guid" | PlanetSideGUID.codec) ::
|
||||||
|
("shot_pos" | Vector3.codec_pos) ::
|
||||||
|
("shot_vel" | Vector3.codec_float) ::
|
||||||
|
("unk1" | uint8L) ::
|
||||||
|
("unk2" | uint8L) ::
|
||||||
|
("unk3" | uint8L) ::
|
||||||
|
("unk4" | bool) ::
|
||||||
|
("time_alive" | uint16L)
|
||||||
|
).as[ProjectileStateMessage]
|
||||||
|
}
|
||||||
44
common/src/test/scala/game/ProjectileStateMessageTest.scala
Normal file
44
common/src/test/scala/game/ProjectileStateMessageTest.scala
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package game
|
||||||
|
|
||||||
|
import org.specs2.mutable._
|
||||||
|
import net.psforever.packet._
|
||||||
|
import net.psforever.packet.game._
|
||||||
|
import net.psforever.types.Vector3
|
||||||
|
import scodec.bits._
|
||||||
|
|
||||||
|
class ProjectileStateMessageTest extends Specification {
|
||||||
|
val string = hex"3f 259d c5019 30e4a 9514 c52c9541 d9ba05c2 c5973941 00 f8 ec 020000"
|
||||||
|
|
||||||
|
"decode" in {
|
||||||
|
PacketCoding.DecodePacket(string).require match {
|
||||||
|
case ProjectileStateMessage(projectile, pos, vel, unk1, unk2, unk3, unk4, time_alive) =>
|
||||||
|
projectile mustEqual PlanetSideGUID(40229)
|
||||||
|
pos.x mustEqual 4611.539f
|
||||||
|
pos.y mustEqual 5576.375f
|
||||||
|
pos.z mustEqual 82.328125f
|
||||||
|
vel.x mustEqual 18.64686f
|
||||||
|
vel.y mustEqual -33.43247f
|
||||||
|
vel.z mustEqual 11.599553f
|
||||||
|
unk1 mustEqual 0
|
||||||
|
unk2 mustEqual 248
|
||||||
|
unk3 mustEqual 236
|
||||||
|
unk4 mustEqual false
|
||||||
|
time_alive mustEqual 4
|
||||||
|
case _ =>
|
||||||
|
ko
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"encode" in {
|
||||||
|
val msg = ProjectileStateMessage(
|
||||||
|
PlanetSideGUID(40229),
|
||||||
|
Vector3(4611.539f, 5576.375f, 82.328125f),
|
||||||
|
Vector3(18.64686f, -33.43247f, 11.599553f),
|
||||||
|
0, 248, 236, false, 4
|
||||||
|
)
|
||||||
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
||||||
|
pkt mustEqual string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -255,6 +255,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
case msg @ ChildObjectStateMessage(object_guid : PlanetSideGUID, pitch : Int, yaw : Int) =>
|
case msg @ ChildObjectStateMessage(object_guid : PlanetSideGUID, pitch : Int, yaw : Int) =>
|
||||||
//log.info("ChildObjectState: " + msg)
|
//log.info("ChildObjectState: " + msg)
|
||||||
|
|
||||||
|
case msg @ ProjectileStateMessage(projectile_guid, shot_pos, shot_vector, unk1, unk2, unk3, unk4, time_alive) =>
|
||||||
|
//log.info("ProjectileState: " + msg)
|
||||||
|
|
||||||
case msg @ ChatMsg(messagetype, has_wide_contents, recipient, contents, note_contents) =>
|
case msg @ ChatMsg(messagetype, has_wide_contents, recipient, contents, note_contents) =>
|
||||||
// TODO: Prevents log spam, but should be handled correctly
|
// TODO: Prevents log spam, but should be handled correctly
|
||||||
if (messagetype != ChatMessageType.CMT_TOGGLE_GM) {
|
if (messagetype != ChatMessageType.CMT_TOGGLE_GM) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue