mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-11 14:34:40 +00:00
events for future expansion; added custom projectile remote client data for OCM packet creation; initial projectile velocity calculation; (too many) details when it comes to Enumerations for projectiles; hooked up theoretical projectile creatiuon, management, and deletion
This commit is contained in:
parent
f1c73688f7
commit
8952ab86f6
10 changed files with 258 additions and 65 deletions
|
|
@ -630,9 +630,7 @@ object GlobalDefinitions {
|
||||||
|
|
||||||
val maelstrom = ToolDefinition(ObjectClass.maelstrom)
|
val maelstrom = ToolDefinition(ObjectClass.maelstrom)
|
||||||
|
|
||||||
val phoenix = new ToolDefinition(ObjectClass.phoenix) {
|
val phoenix = ToolDefinition(ObjectClass.phoenix) //decimator
|
||||||
override def NextFireModeIndex(index : Int) : Int = index
|
|
||||||
} //decimator
|
|
||||||
|
|
||||||
val striker = new ToolDefinition(ObjectClass.striker) {
|
val striker = new ToolDefinition(ObjectClass.striker) {
|
||||||
override def NextFireModeIndex(index : Int) : Int = index
|
override def NextFireModeIndex(index : Int) : Int = index
|
||||||
|
|
@ -640,8 +638,8 @@ object GlobalDefinitions {
|
||||||
}
|
}
|
||||||
|
|
||||||
val hunterseeker = new ToolDefinition(ObjectClass.hunterseeker) {
|
val hunterseeker = new ToolDefinition(ObjectClass.hunterseeker) {
|
||||||
// override def NextFireModeIndex(index : Int) : Int = index
|
override def NextFireModeIndex(index : Int) : Int = index
|
||||||
// DefaultFireModeIndex = 1
|
DefaultFireModeIndex = 1
|
||||||
} //phoenix
|
} //phoenix
|
||||||
|
|
||||||
val lancer = ToolDefinition(ObjectClass.lancer)
|
val lancer = ToolDefinition(ObjectClass.lancer)
|
||||||
|
|
@ -2221,6 +2219,7 @@ object GlobalDefinitions {
|
||||||
aphelion_starfire_projectile.Lifespan = 7f
|
aphelion_starfire_projectile.Lifespan = 7f
|
||||||
aphelion_starfire_projectile.ProjectileDamageType = DamageType.Aggravated
|
aphelion_starfire_projectile.ProjectileDamageType = DamageType.Aggravated
|
||||||
aphelion_starfire_projectile.ExistsOnRemoteClients = true
|
aphelion_starfire_projectile.ExistsOnRemoteClients = true
|
||||||
|
aphelion_starfire_projectile.RemoteClientData = (39577, 249) //starfire_projectile data
|
||||||
aphelion_starfire_projectile.Packet = projectileConverter
|
aphelion_starfire_projectile.Packet = projectileConverter
|
||||||
ProjectileDefinition.CalculateDerivedFields(aphelion_starfire_projectile)
|
ProjectileDefinition.CalculateDerivedFields(aphelion_starfire_projectile)
|
||||||
|
|
||||||
|
|
@ -2699,6 +2698,7 @@ object GlobalDefinitions {
|
||||||
hunter_seeker_missile_projectile.InitialVelocity = 40
|
hunter_seeker_missile_projectile.InitialVelocity = 40
|
||||||
hunter_seeker_missile_projectile.Lifespan = 6.3f
|
hunter_seeker_missile_projectile.Lifespan = 6.3f
|
||||||
hunter_seeker_missile_projectile.ExistsOnRemoteClients = true
|
hunter_seeker_missile_projectile.ExistsOnRemoteClients = true
|
||||||
|
hunter_seeker_missile_projectile.RemoteClientData = (39577, 201)
|
||||||
hunter_seeker_missile_projectile.Packet = projectileConverter
|
hunter_seeker_missile_projectile.Packet = projectileConverter
|
||||||
ProjectileDefinition.CalculateDerivedFields(hunter_seeker_missile_projectile)
|
ProjectileDefinition.CalculateDerivedFields(hunter_seeker_missile_projectile)
|
||||||
|
|
||||||
|
|
@ -2986,6 +2986,7 @@ object GlobalDefinitions {
|
||||||
oicw_projectile.InitialVelocity = 5
|
oicw_projectile.InitialVelocity = 5
|
||||||
oicw_projectile.Lifespan = 6.1f
|
oicw_projectile.Lifespan = 6.1f
|
||||||
oicw_projectile.ExistsOnRemoteClients = true
|
oicw_projectile.ExistsOnRemoteClients = true
|
||||||
|
oicw_projectile.RemoteClientData = (13107, 195)
|
||||||
oicw_projectile.Packet = projectileConverter
|
oicw_projectile.Packet = projectileConverter
|
||||||
ProjectileDefinition.CalculateDerivedFields(oicw_projectile)
|
ProjectileDefinition.CalculateDerivedFields(oicw_projectile)
|
||||||
|
|
||||||
|
|
@ -2997,7 +2998,7 @@ object GlobalDefinitions {
|
||||||
oicw_little_buddy.ProjectileDamageType = DamageType.Splash
|
oicw_little_buddy.ProjectileDamageType = DamageType.Splash
|
||||||
oicw_little_buddy.InitialVelocity = 40
|
oicw_little_buddy.InitialVelocity = 40
|
||||||
oicw_little_buddy.Lifespan = 0.5f
|
oicw_little_buddy.Lifespan = 0.5f
|
||||||
oicw_little_buddy.ExistsOnRemoteClients = true
|
oicw_little_buddy.ExistsOnRemoteClients = false //TODO true
|
||||||
oicw_little_buddy.Packet = projectileConverter
|
oicw_little_buddy.Packet = projectileConverter
|
||||||
//add_property oicw_little_buddy multi_stage_spawn_server_side true ...
|
//add_property oicw_little_buddy multi_stage_spawn_server_side true ...
|
||||||
ProjectileDefinition.CalculateDerivedFields(oicw_little_buddy)
|
ProjectileDefinition.CalculateDerivedFields(oicw_little_buddy)
|
||||||
|
|
@ -3080,6 +3081,7 @@ object GlobalDefinitions {
|
||||||
peregrine_sparrow_projectile.InitialVelocity = 45
|
peregrine_sparrow_projectile.InitialVelocity = 45
|
||||||
peregrine_sparrow_projectile.Lifespan = 7.5f
|
peregrine_sparrow_projectile.Lifespan = 7.5f
|
||||||
peregrine_sparrow_projectile.ExistsOnRemoteClients = true
|
peregrine_sparrow_projectile.ExistsOnRemoteClients = true
|
||||||
|
peregrine_sparrow_projectile.RemoteClientData = (13107, 187) //sparrow_projectile data
|
||||||
peregrine_sparrow_projectile.Packet = projectileConverter
|
peregrine_sparrow_projectile.Packet = projectileConverter
|
||||||
ProjectileDefinition.CalculateDerivedFields(peregrine_sparrow_projectile)
|
ProjectileDefinition.CalculateDerivedFields(peregrine_sparrow_projectile)
|
||||||
|
|
||||||
|
|
@ -3133,6 +3135,7 @@ object GlobalDefinitions {
|
||||||
phoenix_missile_guided_projectile.InitialVelocity = 0
|
phoenix_missile_guided_projectile.InitialVelocity = 0
|
||||||
phoenix_missile_guided_projectile.Lifespan = 3f
|
phoenix_missile_guided_projectile.Lifespan = 3f
|
||||||
phoenix_missile_guided_projectile.ExistsOnRemoteClients = true
|
phoenix_missile_guided_projectile.ExistsOnRemoteClients = true
|
||||||
|
phoenix_missile_guided_projectile.RemoteClientData = (39577, 201) //hunter_seeker_missile_projectile data
|
||||||
phoenix_missile_guided_projectile.Packet = projectileConverter
|
phoenix_missile_guided_projectile.Packet = projectileConverter
|
||||||
ProjectileDefinition.CalculateDerivedFields(phoenix_missile_guided_projectile)
|
ProjectileDefinition.CalculateDerivedFields(phoenix_missile_guided_projectile)
|
||||||
|
|
||||||
|
|
@ -3411,6 +3414,7 @@ object GlobalDefinitions {
|
||||||
sparrow_projectile.InitialVelocity = 60
|
sparrow_projectile.InitialVelocity = 60
|
||||||
sparrow_projectile.Lifespan = 5.85f
|
sparrow_projectile.Lifespan = 5.85f
|
||||||
sparrow_projectile.ExistsOnRemoteClients = true
|
sparrow_projectile.ExistsOnRemoteClients = true
|
||||||
|
sparrow_projectile.RemoteClientData = (13107, 187)
|
||||||
sparrow_projectile.Packet = projectileConverter
|
sparrow_projectile.Packet = projectileConverter
|
||||||
ProjectileDefinition.CalculateDerivedFields(sparrow_projectile)
|
ProjectileDefinition.CalculateDerivedFields(sparrow_projectile)
|
||||||
|
|
||||||
|
|
@ -3427,6 +3431,7 @@ object GlobalDefinitions {
|
||||||
sparrow_secondary_projectile.InitialVelocity = 60
|
sparrow_secondary_projectile.InitialVelocity = 60
|
||||||
sparrow_secondary_projectile.Lifespan = 5.85f
|
sparrow_secondary_projectile.Lifespan = 5.85f
|
||||||
sparrow_secondary_projectile.ExistsOnRemoteClients = true
|
sparrow_secondary_projectile.ExistsOnRemoteClients = true
|
||||||
|
sparrow_secondary_projectile.RemoteClientData = (13107, 187)
|
||||||
sparrow_secondary_projectile.Packet = projectileConverter
|
sparrow_secondary_projectile.Packet = projectileConverter
|
||||||
ProjectileDefinition.CalculateDerivedFields(sparrow_secondary_projectile)
|
ProjectileDefinition.CalculateDerivedFields(sparrow_secondary_projectile)
|
||||||
|
|
||||||
|
|
@ -3479,6 +3484,7 @@ object GlobalDefinitions {
|
||||||
starfire_projectile.InitialVelocity = 45
|
starfire_projectile.InitialVelocity = 45
|
||||||
starfire_projectile.Lifespan = 7.8f
|
starfire_projectile.Lifespan = 7.8f
|
||||||
starfire_projectile.ExistsOnRemoteClients = true
|
starfire_projectile.ExistsOnRemoteClients = true
|
||||||
|
starfire_projectile.RemoteClientData = (39577, 249)
|
||||||
starfire_projectile.Packet = projectileConverter
|
starfire_projectile.Packet = projectileConverter
|
||||||
ProjectileDefinition.CalculateDerivedFields(starfire_projectile)
|
ProjectileDefinition.CalculateDerivedFields(starfire_projectile)
|
||||||
|
|
||||||
|
|
@ -3512,6 +3518,7 @@ object GlobalDefinitions {
|
||||||
striker_missile_targeting_projectile.InitialVelocity = 30
|
striker_missile_targeting_projectile.InitialVelocity = 30
|
||||||
striker_missile_targeting_projectile.Lifespan = 4.2f
|
striker_missile_targeting_projectile.Lifespan = 4.2f
|
||||||
striker_missile_targeting_projectile.ExistsOnRemoteClients = true
|
striker_missile_targeting_projectile.ExistsOnRemoteClients = true
|
||||||
|
striker_missile_targeting_projectile.RemoteClientData = (26214, 134)
|
||||||
striker_missile_targeting_projectile.Packet = projectileConverter
|
striker_missile_targeting_projectile.Packet = projectileConverter
|
||||||
ProjectileDefinition.CalculateDerivedFields(striker_missile_targeting_projectile)
|
ProjectileDefinition.CalculateDerivedFields(striker_missile_targeting_projectile)
|
||||||
|
|
||||||
|
|
@ -3601,6 +3608,7 @@ object GlobalDefinitions {
|
||||||
wasp_rocket_projectile.InitialVelocity = 60
|
wasp_rocket_projectile.InitialVelocity = 60
|
||||||
wasp_rocket_projectile.Lifespan = 6.5f
|
wasp_rocket_projectile.Lifespan = 6.5f
|
||||||
wasp_rocket_projectile.ExistsOnRemoteClients = true
|
wasp_rocket_projectile.ExistsOnRemoteClients = true
|
||||||
|
wasp_rocket_projectile.RemoteClientData = (0, 208)
|
||||||
wasp_rocket_projectile.Packet = projectileConverter
|
wasp_rocket_projectile.Packet = projectileConverter
|
||||||
ProjectileDefinition.CalculateDerivedFields(wasp_rocket_projectile)
|
ProjectileDefinition.CalculateDerivedFields(wasp_rocket_projectile)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,15 @@ final case class Projectile(profile : ProjectileDefinition,
|
||||||
shot_origin : Vector3,
|
shot_origin : Vector3,
|
||||||
shot_angle : Vector3,
|
shot_angle : Vector3,
|
||||||
fire_time: Long = System.nanoTime) extends PlanetSideGameObject {
|
fire_time: Long = System.nanoTime) extends PlanetSideGameObject {
|
||||||
|
Position = shot_origin
|
||||||
|
Orientation = shot_angle
|
||||||
|
Velocity = {
|
||||||
|
val initVel : Int = profile.InitialVelocity //initial velocity
|
||||||
|
val radAngle : Double = math.toRadians(shot_angle.y) //angle of elevation
|
||||||
|
val rise : Float = initVel * math.sin(radAngle).toFloat //z
|
||||||
|
val ground : Float = initVel * math.cos(radAngle).toFloat //base
|
||||||
|
Vector3.Rz(Vector3(0, -ground, 0), shot_angle.z) + Vector3.z(rise)
|
||||||
|
}
|
||||||
/** Information about the current world coordinates and orientation of the projectile */
|
/** Information about the current world coordinates and orientation of the projectile */
|
||||||
val current : SimpleWorldEntity = new SimpleWorldEntity()
|
val current : SimpleWorldEntity = new SimpleWorldEntity()
|
||||||
private var resolved : ProjectileResolution.Value = ProjectileResolution.Unresolved
|
private var resolved : ProjectileResolution.Value = ProjectileResolution.Unresolved
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ class ProjectileDefinition(objectId : Int) extends ObjectDefinition(objectId)
|
||||||
private var damageRadius : Float = 1f
|
private var damageRadius : Float = 1f
|
||||||
private var useDamage1Subtract : Boolean = false
|
private var useDamage1Subtract : Boolean = false
|
||||||
private var existsOnRemoteClients : Boolean = false //`true` spawns a server-managed object
|
private var existsOnRemoteClients : Boolean = false //`true` spawns a server-managed object
|
||||||
|
private var remoteClientData : (Int, Int) = (0, 0) //artificial values; for ObjectCreateMessage packet (oicw_little_buddy is undefined)
|
||||||
//derived calculations
|
//derived calculations
|
||||||
private var distanceMax : Float = 0f
|
private var distanceMax : Float = 0f
|
||||||
private var distanceFromAcceleration : Float = 0f
|
private var distanceFromAcceleration : Float = 0f
|
||||||
|
|
@ -117,6 +118,13 @@ class ProjectileDefinition(objectId : Int) extends ObjectDefinition(objectId)
|
||||||
ExistsOnRemoteClients
|
ExistsOnRemoteClients
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def RemoteClientData : (Int, Int) = remoteClientData
|
||||||
|
|
||||||
|
def RemoteClientData_=(remoteClientData : (Int, Int)) : (Int, Int) = {
|
||||||
|
this.remoteClientData = remoteClientData
|
||||||
|
RemoteClientData
|
||||||
|
}
|
||||||
|
|
||||||
def DistanceMax : Float = distanceMax //accessor only
|
def DistanceMax : Float = distanceMax //accessor only
|
||||||
|
|
||||||
def DistanceFromAcceleration : Float = distanceFromAcceleration //accessor only
|
def DistanceFromAcceleration : Float = distanceFromAcceleration //accessor only
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ class ProjectileConverter extends ObjectCreateConverter[Projectile]() {
|
||||||
PlacementData(
|
PlacementData(
|
||||||
obj.Position,
|
obj.Position,
|
||||||
obj.Orientation,
|
obj.Orientation,
|
||||||
obj.Velocity
|
None
|
||||||
),
|
),
|
||||||
CommonFieldData(
|
CommonFieldData(
|
||||||
obj.owner.Faction,
|
obj.owner.Faction,
|
||||||
|
|
@ -29,11 +29,11 @@ class ProjectileConverter extends ObjectCreateConverter[Projectile]() {
|
||||||
PlanetSideGUID(0)
|
PlanetSideGUID(0)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
obj.profile.RemoteClientData._1,
|
||||||
|
obj.profile.RemoteClientData._2,
|
||||||
|
FlightPhysics.State4,
|
||||||
0,
|
0,
|
||||||
0,
|
0
|
||||||
FlightPhysics.State3,
|
|
||||||
7,
|
|
||||||
2
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,56 @@
|
||||||
package net.psforever.packet.game.objectcreate
|
package net.psforever.packet.game.objectcreate
|
||||||
|
|
||||||
import net.psforever.packet.{Marshallable, PacketHelpers}
|
import net.psforever.packet.{Marshallable, PacketHelpers}
|
||||||
import scodec.{Attempt, Codec, Err}
|
import scodec.{Attempt, Codec}
|
||||||
import scodec.codecs._
|
import scodec.codecs._
|
||||||
import shapeless.{::, HNil}
|
import shapeless.{::, HNil}
|
||||||
|
|
||||||
|
object TrackedProjectile extends Enumeration {
|
||||||
|
type Type = Value
|
||||||
|
|
||||||
|
val OICWLittleBuddy = Value(-1) //?, ?
|
||||||
|
val Meteor = Value(32) //0, 32
|
||||||
|
val Wasp = Value(208) //0, 208
|
||||||
|
val Sparrow = Value(3355579) //13107, 187
|
||||||
|
val OICW = Value(3355587) //13107, 195
|
||||||
|
val Striker = Value(6710918) //26214, 134
|
||||||
|
val HunterSeeker = Value(10131913) //39577, 201
|
||||||
|
val Starfire = Value(10131961) //39577, 249
|
||||||
|
|
||||||
|
implicit val codec = PacketHelpers.createEnumerationCodec(this, uint24)
|
||||||
|
}
|
||||||
|
|
||||||
|
object TrackedProjectiles {
|
||||||
|
abstract class Data(val is : TrackedProjectile.Value, val a : Int, val b : Int)
|
||||||
|
|
||||||
|
final case object Meteor extends Data(TrackedProjectile.Meteor, 0, 32)
|
||||||
|
final case object Wasp extends Data(TrackedProjectile.Wasp, 0, 208)
|
||||||
|
final case object Sparrow extends Data(TrackedProjectile.Sparrow, 13107, 187)
|
||||||
|
final case object OICW extends Data(TrackedProjectile.OICW, 13107, 195)
|
||||||
|
final case object Striker extends Data(TrackedProjectile.Striker, 26214, 134)
|
||||||
|
final case object HunterSeeker extends Data(TrackedProjectile.HunterSeeker, 39577, 201)
|
||||||
|
final case object Starfire extends Data(TrackedProjectile.Starfire, 39577, 249)
|
||||||
|
class OICWLittleBuddy(x : Int, y : Int) extends Data(TrackedProjectile.OICWLittleBuddy, x, y)
|
||||||
|
|
||||||
|
val values: Seq[TrackedProjectiles.Data] = Seq(Meteor, Wasp, Sparrow, OICW, Striker, HunterSeeker, Starfire)
|
||||||
|
|
||||||
|
def apply(x : Int, y : Int) : TrackedProjectiles.Data = {
|
||||||
|
values.find(p => p.a == x && p.b == y) match {
|
||||||
|
case Some(projectileData) => projectileData
|
||||||
|
case None =>
|
||||||
|
throw new IllegalArgumentException("no combination of projectile data equates to a defined projectile type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def apply(is : TrackedProjectile.Value) : TrackedProjectiles.Data = {
|
||||||
|
values.find(p => p.is == is) match {
|
||||||
|
case Some(projectileData) => projectileData
|
||||||
|
case None =>
|
||||||
|
throw new IllegalArgumentException("unknown projectile type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object FlightPhysics extends Enumeration {
|
object FlightPhysics extends Enumeration {
|
||||||
type Type = Value
|
type Type = Value
|
||||||
|
|
||||||
|
|
@ -27,41 +73,38 @@ object FlightPhysics extends Enumeration {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A representation of a projectile that the server must intentionally convey to players other than the shooter.
|
* A representation of a projectile that the server must intentionally convey to players other than the shooter.
|
||||||
* @param data common game object information
|
* @param common_data common game object information
|
||||||
* @param unk2 na
|
|
||||||
* @param unit_distance_limit how quickly the projectile travels before naturally being destroyed
|
|
||||||
* `FlightPhysics` needs to be
|
|
||||||
* @param unk3 na
|
* @param unk3 na
|
||||||
*/
|
*/
|
||||||
final case class TrackedProjectileData(data : CommonFieldDataWithPlacement,
|
final case class TrackedProjectileData(common_data : CommonFieldDataWithPlacement,
|
||||||
unk2 : Int,
|
u1 : Int,
|
||||||
unit_distance_limit : Int,
|
u2 : Int,
|
||||||
unk3 : FlightPhysics.Value,
|
unk3 : FlightPhysics.Value,
|
||||||
unk4 : Int,
|
unk4 : Int,
|
||||||
unk5 : Int
|
unk5 : Int
|
||||||
) extends ConstructorData {
|
) extends ConstructorData {
|
||||||
override def bitsize : Long = 33L + data.bitsize
|
override def bitsize : Long = 33L + common_data.bitsize
|
||||||
}
|
}
|
||||||
|
|
||||||
object TrackedProjectileData extends Marshallable[TrackedProjectileData] {
|
object TrackedProjectileData extends Marshallable[TrackedProjectileData] {
|
||||||
implicit val codec : Codec[TrackedProjectileData] = (
|
implicit val codec : Codec[TrackedProjectileData] = (
|
||||||
("data" | CommonFieldDataWithPlacement.codec) ::
|
("data" | CommonFieldDataWithPlacement.codec) ::
|
||||||
("unk2" | uint16) ::
|
("u1" | uint16) ::
|
||||||
("unit_distance_limit" | uint8) ::
|
("u2" | uint8) ::
|
||||||
("unk3" | FlightPhysics.codec) ::
|
("unk3" | FlightPhysics.codec) ::
|
||||||
("unk4" | uint(3)) ::
|
("unk4" | uint(3)) ::
|
||||||
("unk5" | uint2)
|
("unk5" | uint2)
|
||||||
).exmap[TrackedProjectileData] (
|
).exmap[TrackedProjectileData] (
|
||||||
{
|
{
|
||||||
case data :: unk2 :: lim :: unk3 :: unk4 :: unk5 :: HNil =>
|
case data :: u1 :: u2 :: unk3 :: unk4 :: unk5 :: HNil =>
|
||||||
Attempt.successful(TrackedProjectileData(data, unk2, lim, unk3, unk4, unk5))
|
Attempt.successful(TrackedProjectileData(data, u1, u2, unk3, unk4, unk5))
|
||||||
|
|
||||||
case data =>
|
// case data =>
|
||||||
Attempt.failure(Err(s"invalid projectile data format - $data"))
|
// Attempt.failure(Err(s"invalid projectile data format - $data"))
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
case TrackedProjectileData(data, unk2, lim, unk3, unk4, unk5) =>
|
case TrackedProjectileData(data, u1, u2, unk3, unk4, unk5) =>
|
||||||
Attempt.successful(data :: unk2 :: lim :: unk3 :: unk4 :: unk5 :: HNil)
|
Attempt.successful(data :: u1 :: u2 :: unk3 :: unk4 :: unk5 :: HNil)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,10 @@ class AvatarService extends Actor {
|
||||||
AvatarResponse.EquipmentInHand(ObjectCreateMessage(definition.ObjectId, item.GUID, containerData, objectData))
|
AvatarResponse.EquipmentInHand(ObjectCreateMessage(definition.ObjectId, item.GUID, containerData, objectData))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
case AvatarAction.GenericObjectAction(player_guid, object_guid, action_code) =>
|
||||||
|
AvatarEvents.publish(
|
||||||
|
AvatarServiceResponse(s"/$forChannel/Avatar", player_guid, AvatarResponse.GenericObjectAction(object_guid, action_code))
|
||||||
|
)
|
||||||
case AvatarAction.HitHint(source_guid, player_guid) =>
|
case AvatarAction.HitHint(source_guid, player_guid) =>
|
||||||
AvatarEvents.publish(
|
AvatarEvents.publish(
|
||||||
AvatarServiceResponse(s"/$forChannel/Avatar", player_guid, AvatarResponse.HitHint(source_guid))
|
AvatarServiceResponse(s"/$forChannel/Avatar", player_guid, AvatarResponse.HitHint(source_guid))
|
||||||
|
|
@ -129,7 +133,7 @@ class AvatarService extends Actor {
|
||||||
)
|
)
|
||||||
case AvatarAction.LoadProjectile(player_guid, object_id, obj, cdata) =>
|
case AvatarAction.LoadProjectile(player_guid, object_id, obj, cdata) =>
|
||||||
AvatarEvents.publish(
|
AvatarEvents.publish(
|
||||||
AvatarServiceResponse(s"/$forChannel/Avatar", player_guid, AvatarResponse.LoadPlayer(
|
AvatarServiceResponse(s"/$forChannel/Avatar", player_guid, AvatarResponse.LoadProjectile(
|
||||||
ObjectCreateMessage(object_id, obj.GUID, cdata)
|
ObjectCreateMessage(object_id, obj.GUID, cdata)
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ object AvatarAction {
|
||||||
final case class DestroyDisplay(killer : SourceEntry, victim : SourceEntry, method : Int, unk : Int = 121) extends Action
|
final case class DestroyDisplay(killer : SourceEntry, victim : SourceEntry, method : Int, unk : Int = 121) extends Action
|
||||||
final case class DropItem(player_guid : PlanetSideGUID, item : Equipment, zone : Zone) extends Action
|
final case class DropItem(player_guid : PlanetSideGUID, item : Equipment, zone : Zone) extends Action
|
||||||
final case class EquipmentInHand(player_guid : PlanetSideGUID, target_guid : PlanetSideGUID, slot : Int, item : Equipment) extends Action
|
final case class EquipmentInHand(player_guid : PlanetSideGUID, target_guid : PlanetSideGUID, slot : Int, item : Equipment) extends Action
|
||||||
|
final case class GenericObjectAction(player_guid : PlanetSideGUID, object_guid : PlanetSideGUID, action_code : Int) extends Action
|
||||||
final case class HitHint(source_guid : PlanetSideGUID, player_guid : PlanetSideGUID) extends Action
|
final case class HitHint(source_guid : PlanetSideGUID, player_guid : PlanetSideGUID) extends Action
|
||||||
final case class KilledWhileInVehicle(player_guid : PlanetSideGUID) extends Action
|
final case class KilledWhileInVehicle(player_guid : PlanetSideGUID) extends Action
|
||||||
final case class LoadPlayer(player_guid : PlanetSideGUID, object_id : Int, target_guid : PlanetSideGUID, cdata : ConstructorData, pdata : Option[ObjectCreateMessageParent]) extends Action
|
final case class LoadPlayer(player_guid : PlanetSideGUID, object_id : Int, target_guid : PlanetSideGUID, cdata : ConstructorData, pdata : Option[ObjectCreateMessageParent]) extends Action
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ object AvatarResponse {
|
||||||
final case class DestroyDisplay(killer : SourceEntry, victim : SourceEntry, method : Int, unk : Int) extends Response
|
final case class DestroyDisplay(killer : SourceEntry, victim : SourceEntry, method : Int, unk : Int) extends Response
|
||||||
final case class DropItem(pkt : ObjectCreateMessage) extends Response
|
final case class DropItem(pkt : ObjectCreateMessage) extends Response
|
||||||
final case class EquipmentInHand(pkt : ObjectCreateMessage) extends Response
|
final case class EquipmentInHand(pkt : ObjectCreateMessage) extends Response
|
||||||
|
final case class GenericObjectAction(object_guid : PlanetSideGUID, action_code : Int) extends Response
|
||||||
final case class HitHint(source_guid : PlanetSideGUID) extends Response
|
final case class HitHint(source_guid : PlanetSideGUID) extends Response
|
||||||
final case class KilledWhileInVehicle() extends Response
|
final case class KilledWhileInVehicle() extends Response
|
||||||
final case class LoadPlayer(pkt : ObjectCreateMessage) extends Response
|
final case class LoadPlayer(pkt : ObjectCreateMessage) extends Response
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,10 @@ import scodec.bits._
|
||||||
|
|
||||||
class TrackedProjectileDataTest extends Specification {
|
class TrackedProjectileDataTest extends Specification {
|
||||||
val string_striker_projectile = hex"17 C5000000 A4B 009D 4C129 0CB0A 9814 00 F5 E3 040000666686400"
|
val string_striker_projectile = hex"17 C5000000 A4B 009D 4C129 0CB0A 9814 00 F5 E3 040000666686400"
|
||||||
|
val string_hunter_seeker_missile_projectile = hex"17 c5000000 ca9 ab9e af127 ec465 3723 00 15 c4 2400009a99c9400"
|
||||||
|
|
||||||
"TrackedProjectileData" should {
|
"TrackedProjectileData" should {
|
||||||
"decode" in {
|
"decode (striker_missile_targeting_projectile)" in {
|
||||||
PacketCoding.DecodePacket(string_striker_projectile).require match {
|
PacketCoding.DecodePacket(string_striker_projectile).require match {
|
||||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||||
len mustEqual 197
|
len mustEqual 197
|
||||||
|
|
@ -46,7 +47,41 @@ class TrackedProjectileDataTest extends Specification {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"encode" in {
|
"decode (hunter_seeker_missile_projectile)" in {
|
||||||
|
PacketCoding.DecodePacket(string_hunter_seeker_missile_projectile).require match {
|
||||||
|
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||||
|
len mustEqual 197
|
||||||
|
cls mustEqual ObjectClass.hunter_seeker_missile_projectile
|
||||||
|
guid mustEqual PlanetSideGUID(40619)
|
||||||
|
parent.isDefined mustEqual false
|
||||||
|
data match {
|
||||||
|
case TrackedProjectileData(CommonFieldDataWithPlacement(pos, deploy), unk2, lim, unk3, unk4, unk5) =>
|
||||||
|
pos.coord mustEqual Vector3(3621.3672f, 2701.8438f, 140.85938f)
|
||||||
|
pos.orient mustEqual Vector3(0, 300.9375f, 258.75f)
|
||||||
|
deploy.faction mustEqual PlanetSideEmpire.NC
|
||||||
|
deploy.bops mustEqual false
|
||||||
|
deploy.alternate mustEqual false
|
||||||
|
deploy.v1 mustEqual true
|
||||||
|
deploy.v2.isEmpty mustEqual true
|
||||||
|
deploy.v3 mustEqual false
|
||||||
|
deploy.v4.isEmpty mustEqual true
|
||||||
|
deploy.v5.isEmpty mustEqual true
|
||||||
|
deploy.guid mustEqual PlanetSideGUID(0)
|
||||||
|
|
||||||
|
unk2 mustEqual 39577
|
||||||
|
lim mustEqual 201
|
||||||
|
unk3 mustEqual FlightPhysics.State4
|
||||||
|
unk4 mustEqual 0
|
||||||
|
unk5 mustEqual 0
|
||||||
|
case _ =>
|
||||||
|
ko
|
||||||
|
}
|
||||||
|
case _ =>
|
||||||
|
ko
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"encode (striker_missile_targeting_projectile)" in {
|
||||||
val obj = TrackedProjectileData(
|
val obj = TrackedProjectileData(
|
||||||
CommonFieldDataWithPlacement(
|
CommonFieldDataWithPlacement(
|
||||||
PlacementData(4644.5938f, 5472.0938f, 82.375f, 0f, 30.9375f, 171.5625f),
|
PlacementData(4644.5938f, 5472.0938f, 82.375f, 0f, 30.9375f, 171.5625f),
|
||||||
|
|
@ -63,4 +98,21 @@ class TrackedProjectileDataTest extends Specification {
|
||||||
pkt.toBitVector.drop(141) mustEqual string_striker_projectile.toBitVector.drop(141)
|
pkt.toBitVector.drop(141) mustEqual string_striker_projectile.toBitVector.drop(141)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"encode (hunter_seeker_missile_projectile)" in {
|
||||||
|
val obj = TrackedProjectileData(
|
||||||
|
CommonFieldDataWithPlacement(
|
||||||
|
PlacementData(3621.3672f, 2701.8438f, 140.85938f, 0, 300.9375f, 258.75f),
|
||||||
|
CommonFieldData(PlanetSideEmpire.NC, false, false, true, None, false, None, None, PlanetSideGUID(0))
|
||||||
|
),
|
||||||
|
39577, 201, FlightPhysics.State4, 0, 0
|
||||||
|
)
|
||||||
|
val msg = ObjectCreateMessage(ObjectClass.hunter_seeker_missile_projectile, PlanetSideGUID(40619), obj)
|
||||||
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
//pkt mustEqual string_hunter_seeker_missile_projectile
|
||||||
|
|
||||||
|
pkt.toBitVector.take(132) mustEqual string_hunter_seeker_missile_projectile.toBitVector.take(132)
|
||||||
|
pkt.toBitVector.drop(133).take(7) mustEqual string_hunter_seeker_missile_projectile.toBitVector.drop(133).take(7)
|
||||||
|
pkt.toBitVector.drop(141) mustEqual string_hunter_seeker_missile_projectile.toBitVector.drop(141)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1364,6 +1364,11 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
sendResponse(pkt)
|
sendResponse(pkt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case AvatarResponse.GenericObjectAction(object_guid, action_code) =>
|
||||||
|
if(tplayer_guid != guid) {
|
||||||
|
sendResponse(GenericObjectActionMessage(object_guid, action_code))
|
||||||
|
}
|
||||||
|
|
||||||
case AvatarResponse.HitHint(source_guid) =>
|
case AvatarResponse.HitHint(source_guid) =>
|
||||||
if(player.isAlive) {
|
if(player.isAlive) {
|
||||||
sendResponse(HitHint(source_guid, guid))
|
sendResponse(HitHint(source_guid, guid))
|
||||||
|
|
@ -3453,6 +3458,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
//all head features, faction, and sex also match that test character
|
//all head features, faction, and sex also match that test character
|
||||||
import net.psforever.objects.GlobalDefinitions._
|
import net.psforever.objects.GlobalDefinitions._
|
||||||
import net.psforever.types.CertificationType._
|
import net.psforever.types.CertificationType._
|
||||||
|
|
||||||
val faction = PlanetSideEmpire.VS
|
val faction = PlanetSideEmpire.VS
|
||||||
val avatar = new Avatar(41605313L+sessionId, s"TestCharacter$sessionId", faction, CharacterGender.Female, 41, CharacterVoice.Voice1)
|
val avatar = new Avatar(41605313L+sessionId, s"TestCharacter$sessionId", faction, CharacterGender.Female, 41, CharacterVoice.Voice1)
|
||||||
avatar.Certifications += StandardAssault
|
avatar.Certifications += StandardAssault
|
||||||
|
|
@ -3893,6 +3899,27 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
avatarService ! AvatarServiceMessage(player.Continent, AvatarAction.PlanetsideAttributeSelf(player.GUID, 2, player.Stamina))
|
avatarService ! AvatarServiceMessage(player.Continent, AvatarAction.PlanetsideAttributeSelf(player.GUID, 2, player.Stamina))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!player.Crouching && is_crouching) {
|
||||||
|
sendResponse(
|
||||||
|
ObjectCreateMessage(
|
||||||
|
405,
|
||||||
|
PlanetSideGUID(40288),
|
||||||
|
TrackedProjectileData(
|
||||||
|
CommonFieldDataWithPlacement(
|
||||||
|
PlacementData(Vector3(3561.0f, 2854.0f, 92.859375f), Vector3(0f, 348.75f, 267.1875f), None),
|
||||||
|
CommonFieldData(PlanetSideEmpire.NC, false, false, true, None, false, None, None, PlanetSideGUID(0))
|
||||||
|
),
|
||||||
|
39577, 201, FlightPhysics.State4, 0, 0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else if(player.Crouching && !is_crouching) {
|
||||||
|
sendResponse(
|
||||||
|
ObjectDeleteMessage(PlanetSideGUID(40288), 2)
|
||||||
|
//ProjectileStateMessage(PlanetSideGUID(40288),Vector3(3561.0f, 2854.0f, 92.859375f),Vector3(-38.814934f,-2.578959f,-9.313708f),Vector3(0,348.75f,267.1875f),false,0)
|
||||||
|
)
|
||||||
|
}
|
||||||
player.Position = pos
|
player.Position = pos
|
||||||
player.Velocity = vel
|
player.Velocity = vel
|
||||||
player.Orientation = Vector3(player.Orientation.x, pitch, yaw)
|
player.Orientation = Vector3(player.Orientation.x, pitch, yaw)
|
||||||
|
|
@ -4001,19 +4028,16 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
|
|
||||||
case msg @ ProjectileStateMessage(projectile_guid, shot_pos, shot_vel, shot_orient, unk, time_alive) =>
|
case msg @ ProjectileStateMessage(projectile_guid, shot_pos, shot_vel, shot_orient, unk, time_alive) =>
|
||||||
log.info(s"ProjectileState: $msg")
|
log.info(s"ProjectileState: $msg")
|
||||||
projectiles
|
projectiles(projectile_guid.guid - Projectile.BaseUID) match {
|
||||||
.collect {
|
case Some(projectile) if projectile.HasGUID =>
|
||||||
case Some(projectile) if projectile.HasGUID =>
|
val projectileGlobalUID = projectile.GUID
|
||||||
projectile
|
log.info(s"ProjectileState: mapped local uid ${projectile_guid.guid} to global uid ${projectileGlobalUID.guid}; updating object ...")
|
||||||
}
|
|
||||||
.find(_.GUID == projectile_guid) match {
|
|
||||||
case Some(projectile) =>
|
|
||||||
projectile.Position = shot_pos
|
projectile.Position = shot_pos
|
||||||
projectile.Orientation = shot_orient
|
projectile.Orientation = shot_orient
|
||||||
projectile.Velocity = shot_vel
|
projectile.Velocity = shot_vel
|
||||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ProjectileState(player.GUID, projectile_guid, shot_pos, shot_vel, shot_orient, unk, time_alive))
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ProjectileState(player.GUID, projectile.GUID, shot_pos, shot_vel, shot_orient, unk, time_alive))
|
||||||
case None =>
|
case _ =>
|
||||||
log.info(s"ProjectileState: the projectile GUID#${projectile_guid.guid} can not be found")
|
log.error(s"ProjectileState: the projectile@${projectile_guid.guid} can not be found")
|
||||||
}
|
}
|
||||||
|
|
||||||
case msg @ ReleaseAvatarRequestMessage() =>
|
case msg @ ReleaseAvatarRequestMessage() =>
|
||||||
|
|
@ -5454,6 +5478,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
val projectile = Projectile(projectile_info, tool.Definition, tool.FireMode, player, attribution, shot_origin, angle)
|
val projectile = Projectile(projectile_info, tool.Definition, tool.FireMode, player, attribution, shot_origin, angle)
|
||||||
projectiles(projectileIndex) = Some(projectile)
|
projectiles(projectileIndex) = Some(projectile)
|
||||||
if(projectile_info.ExistsOnRemoteClients) {
|
if(projectile_info.ExistsOnRemoteClients) {
|
||||||
|
log.trace(s"WeaponFireMessage: ${projectile_info.Name} is a remote projectile")
|
||||||
taskResolver ! ReregisterProjectile(projectile)
|
taskResolver ! ReregisterProjectile(projectile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5491,26 +5516,34 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
|
|
||||||
case msg @ SplashHitMessage(seq_time, projectile_guid, explosion_pos, direct_victim_uid, unk3, projectile_vel, unk4, targets) =>
|
case msg @ SplashHitMessage(seq_time, projectile_guid, explosion_pos, direct_victim_uid, unk3, projectile_vel, unk4, targets) =>
|
||||||
log.info(s"Splash: $msg")
|
log.info(s"Splash: $msg")
|
||||||
continent.GUID(direct_victim_uid) match {
|
FindProjectileEntry(projectile_guid) match {
|
||||||
case Some(target : PlanetSideGameObject with FactionAffinity with Vitality) =>
|
case Some(projectile) =>
|
||||||
ResolveProjectileEntry(projectile_guid, ProjectileResolution.Splash, target, target.Position) match {
|
continent.GUID(direct_victim_uid) match {
|
||||||
case Some(projectile) =>
|
case Some(target : PlanetSideGameObject with FactionAffinity with Vitality) =>
|
||||||
HandleDealingDamage(target, projectile)
|
ResolveProjectileEntry(projectile, ProjectileResolution.Splash, target, target.Position) match {
|
||||||
case None => ;
|
case Some(projectile) =>
|
||||||
|
HandleDealingDamage(target, projectile)
|
||||||
|
case None => ;
|
||||||
|
}
|
||||||
|
case _ => ;
|
||||||
}
|
}
|
||||||
case _ => ;
|
targets.foreach(elem => {
|
||||||
}
|
continent.GUID(elem.uid) match {
|
||||||
targets.foreach(elem => {
|
case Some(target : PlanetSideGameObject with FactionAffinity with Vitality) =>
|
||||||
continent.GUID(elem.uid) match {
|
ResolveProjectileEntry(projectile, ProjectileResolution.Splash, target, explosion_pos) match {
|
||||||
case Some(target : PlanetSideGameObject with FactionAffinity with Vitality) =>
|
case Some(projectile) =>
|
||||||
ResolveProjectileEntry(projectile_guid, ProjectileResolution.Splash, target, explosion_pos) match {
|
HandleDealingDamage(target, projectile)
|
||||||
case Some(projectile) =>
|
case None => ;
|
||||||
HandleDealingDamage(target, projectile)
|
}
|
||||||
case None => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
case _ => ;
|
})
|
||||||
}
|
if(projectile.profile.ExistsOnRemoteClients) {
|
||||||
})
|
//cleanup
|
||||||
|
taskResolver ! UnregisterProjectile(projectile)
|
||||||
|
}
|
||||||
|
case None => ;
|
||||||
|
}
|
||||||
|
|
||||||
case msg @ LashMessage(seq_time, killer_guid, victim_guid, projectile_guid, pos, unk1) =>
|
case msg @ LashMessage(seq_time, killer_guid, victim_guid, projectile_guid, pos, unk1) =>
|
||||||
log.info(s"Lash: $msg")
|
log.info(s"Lash: $msg")
|
||||||
|
|
@ -6077,6 +6110,13 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
}, List(GUIDTask.RegisterAvatar(driver)(continent.GUID), GUIDTask.RegisterVehicle(obj)(continent.GUID)))
|
}, List(GUIDTask.RegisterAvatar(driver)(continent.GUID), GUIDTask.RegisterVehicle(obj)(continent.GUID)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct tasking that adds a completed but unregistered projectile into the scene.
|
||||||
|
* After the projectile is registered to the curent zone's global unique identifier system,
|
||||||
|
* all connected clients save for the one that registered it will be informed about the projectile's "creation."
|
||||||
|
* @param obj the projectile to be registered
|
||||||
|
* @return a `TaskResolver.GiveTask` message
|
||||||
|
*/
|
||||||
def RegisterProjectile(obj : Projectile) : TaskResolver.GiveTask = {
|
def RegisterProjectile(obj : Projectile) : TaskResolver.GiveTask = {
|
||||||
val definition = obj.Definition
|
val definition = obj.Definition
|
||||||
TaskResolver.GiveTask(
|
TaskResolver.GiveTask(
|
||||||
|
|
@ -6126,12 +6166,19 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
}, List(GUIDTask.UnregisterAvatar(driver)(continent.GUID), GUIDTask.UnregisterVehicle(obj)(continent.GUID)))
|
}, List(GUIDTask.UnregisterAvatar(driver)(continent.GUID), GUIDTask.UnregisterVehicle(obj)(continent.GUID)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct tasking that removes a formerly complete and currently registered projectile from the scene.
|
||||||
|
* After the projectile is unregistered from the curent zone's global unique identifier system,
|
||||||
|
* all connected clients save for the one that registered it will be informed about the projectile's "destruction."
|
||||||
|
* @param obj the projectile to be unregistered
|
||||||
|
* @return a `TaskResolver.GiveTask` message
|
||||||
|
*/
|
||||||
def UnregisterProjectile(obj : Projectile) : TaskResolver.GiveTask = {
|
def UnregisterProjectile(obj : Projectile) : TaskResolver.GiveTask = {
|
||||||
TaskResolver.GiveTask(
|
TaskResolver.GiveTask(
|
||||||
new Task() {
|
new Task() {
|
||||||
private val globalProjectile = obj
|
private val globalProjectile = obj
|
||||||
private val localAnnounce = avatarService
|
private val localAnnounce = avatarService
|
||||||
private val localMsg = AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player.GUID, obj.GUID))
|
private val localMsg = AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player.GUID, obj.GUID, 2))
|
||||||
|
|
||||||
override def isComplete : Task.Resolution.Value = {
|
override def isComplete : Task.Resolution.Value = {
|
||||||
if(!globalProjectile.HasGUID) {
|
if(!globalProjectile.HasGUID) {
|
||||||
|
|
@ -6192,6 +6239,14 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the projectile object is unregistered, register it.
|
||||||
|
* If the projectile object is already registered, unregister it and then register it again.
|
||||||
|
* @see `RegisterProjectile(Projectile)`
|
||||||
|
* @see `UnregisterProjectile(Projectile)`
|
||||||
|
* @param obj the projectile to be registered (a second time?)
|
||||||
|
* @return a `TaskResolver.GiveTask` message
|
||||||
|
*/
|
||||||
def ReregisterProjectile(obj : Projectile) : TaskResolver.GiveTask = {
|
def ReregisterProjectile(obj : Projectile) : TaskResolver.GiveTask = {
|
||||||
val reg = RegisterProjectile(obj)
|
val reg = RegisterProjectile(obj)
|
||||||
if(obj.HasGUID) {
|
if(obj.HasGUID) {
|
||||||
|
|
@ -8406,9 +8461,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a projectile with the given globally unique identifier and mark it as a resolved shot.
|
* Find a projectile with the given globally unique identifier and mark it as a resolved shot.
|
||||||
* A `Resolved` shot has either encountered an obstacle or is being cleaned up for not finding an obstacle.
|
|
||||||
* The internal copy of the projectile is retained as merely `Resolved`
|
|
||||||
* while the observed projectile is promoted to the suggested resolution status.
|
|
||||||
* @param projectile the projectile object
|
* @param projectile the projectile object
|
||||||
* @param index where the projectile was found
|
* @param index where the projectile was found
|
||||||
* @param resolution the resolution status to promote the projectile
|
* @param resolution the resolution status to promote the projectile
|
||||||
|
|
@ -8419,8 +8471,23 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
log.error(s"expected projectile could not be found at $index; can not resolve")
|
log.error(s"expected projectile could not be found at $index; can not resolve")
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
else if(projectile.isMiss) {
|
else {
|
||||||
log.error(s"expected projectile at $index was already counted as a missed shot; can not resolve any further")
|
ResolveProjectileEntry(projectile, resolution, target, pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a projectile with the given globally unique identifier and mark it as a resolved shot.
|
||||||
|
* A `Resolved` shot has either encountered an obstacle or is being cleaned up for not finding an obstacle.
|
||||||
|
* The internal copy of the projectile is retained as merely `Resolved`
|
||||||
|
* while the observed projectile is promoted to the suggested resolution status.
|
||||||
|
* @param projectile the projectile object
|
||||||
|
* @param resolution the resolution status to promote the projectile
|
||||||
|
* @return a copy of the projectile
|
||||||
|
*/
|
||||||
|
def ResolveProjectileEntry(projectile : Projectile, resolution : ProjectileResolution.Value, target : PlanetSideGameObject with FactionAffinity with Vitality, pos : Vector3) : Option[ResolvedProjectile] = {
|
||||||
|
if(projectile.isMiss) {
|
||||||
|
log.error("expected projectile was already counted as a missed shot; can not resolve any further")
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue