Upper Body Angle (#292)

* constrain angles on specialized yaw and pitch fields

* integrated new Angular Codec into OCM and OCDM of avatar; corrected tests; wrote shortcut for whether a unit is moving (under its own power)

* apply clamp

* Accessed containers while moving

Removed unintentional code duplication outside of conditional.
This commit is contained in:
Fate-JH 2019-11-29 11:14:25 -05:00 committed by GitHub
parent 9e99dc75e3
commit a5a85e6cc3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 209 additions and 108 deletions

View file

@ -54,7 +54,7 @@ import services.local.{LocalAction, LocalResponse, LocalServiceMessage, LocalSer
import services.chat._
import services.vehicle.support.TurretUpgrader
import services.vehicle.{VehicleAction, VehicleResponse, VehicleServiceMessage, VehicleServiceResponse}
import services.teamwork.{SquadAction => SquadServiceAction, SquadServiceMessage, SquadServiceResponse, SquadResponse, SquadService}
import services.teamwork.{SquadResponse, SquadService, SquadServiceMessage, SquadServiceResponse, SquadAction => SquadServiceAction}
import scala.collection.mutable.LongMap
import scala.concurrent.duration._
@ -64,6 +64,7 @@ import scala.concurrent.{Await, Future}
import scala.concurrent.duration._
import scala.util.Success
import akka.pattern.ask
import net.psforever.objects.entity.{SimpleWorldEntity, WorldEntity}
import net.psforever.objects.vehicles.Utility.InternalTelepad
import services.local.support.{HackCaptureActor, RouterTelepadActivation}
import services.support.SupportActor
@ -1441,7 +1442,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
(distanceSq < 10000 && time > 500) ||
(distanceSq < 160000 && (
(is_jumping || time < 200)) ||
((vel.isEmpty || Vector3.MagnitudeSquared(vel.get).toInt == 0) && time > 2000) ||
(!WorldEntity.isMoving(vel) && time > 2000) ||
(time > 1000)) ||
(distanceSq > 160000 && time > 5000)) {
sendResponse(
@ -3893,7 +3894,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
timeSurge = 0
}
}
if (vel.isEmpty && player.Stamina != player.MaxStamina) {
val isMoving = WorldEntity.isMoving(vel)
if (!isMoving && player.Stamina < player.MaxStamina) {
player.Stamina = player.Stamina + 1
avatarService ! AvatarServiceMessage(player.Continent, AvatarAction.PlanetsideAttributeSelf(player.GUID, 2, player.Stamina))
}
@ -3907,7 +3909,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
player.Jumping = is_jumping
player.Cloaked = player.ExoSuit == ExoSuitType.Infiltration && is_cloaking
if(vel.isDefined && usingMedicalTerminal.isDefined) {
if(isMoving && usingMedicalTerminal.isDefined) {
continent.GUID(usingMedicalTerminal) match {
case Some(term : Terminal with ProximityUnit) =>
StopUsingProximityUnit(term)
@ -3916,7 +3918,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
accessedContainer match {
case Some(veh : Vehicle) =>
if(vel.isDefined || Vector3.DistanceSquared(player.Position, veh.Position) > 100) {
if(isMoving || Vector3.DistanceSquared(player.Position, veh.Position) > 100) {
val guid = player.GUID
sendResponse(UnuseItemMessage(guid, veh.GUID))
sendResponse(UnuseItemMessage(guid, guid))
@ -3925,7 +3927,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
accessedContainer = None
}
case Some(container) => //just in case
if(vel.isDefined) {
if(isMoving) {
val guid = player.GUID
// If the container is a corpse and gets removed just as this runs it can cause a client disconnect, so we'll check the container has a GUID first.
if(container.HasGUID) {
@ -4885,7 +4887,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
if (tool.Definition == GlobalDefinitions.bank) {
continent.GUID(object_guid) match {
case Some(tplayer: Player) =>
if (player.GUID != tplayer.GUID && Vector3.Distance(player.Position, tplayer.Position) < 5 && player.Faction == tplayer.Faction && player.Velocity.isEmpty && tplayer.MaxArmor > 0 && tplayer.Armor < tplayer.MaxArmor) {
if (player.GUID != tplayer.GUID && Vector3.Distance(player.Position, tplayer.Position) < 5 && player.Faction == tplayer.Faction && !player.isMoving && tplayer.MaxArmor > 0 && tplayer.Armor < tplayer.MaxArmor) {
tplayer.Armor += 15
tool.Discharge
sendResponse(InventoryStateMessage(tool.AmmoSlot.Box.GUID, obj.GUID, tool.Magazine))
@ -4893,7 +4895,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
sendResponse(RepairMessage(object_guid, RepairPercent))
avatarService ! AvatarServiceMessage(tplayer.Continent, AvatarAction.PlanetsideAttributeToAll(tplayer.GUID, 4, tplayer.Armor))
} else if (player.GUID == tplayer.GUID && player.Velocity.isEmpty && tplayer.MaxArmor > 0) {
} else if (player.GUID == tplayer.GUID && !player.isMoving && tplayer.MaxArmor > 0) {
player.Armor += 15
tool.Discharge
sendResponse(InventoryStateMessage(tool.AmmoSlot.Box.GUID, obj.GUID, tool.Magazine))
@ -4904,7 +4906,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
} else if (tool.Definition == GlobalDefinitions.medicalapplicator) {
continent.GUID(object_guid) match {
case Some(tplayer: Player) =>
if (player.GUID != tplayer.GUID && Vector3.Distance(player.Position, tplayer.Position) < 5 && player.Faction == tplayer.Faction && player.Velocity.isEmpty && tplayer.MaxHealth > 0 && tplayer.Health < tplayer.MaxHealth) {
if (player.GUID != tplayer.GUID && Vector3.Distance(player.Position, tplayer.Position) < 5 && player.Faction == tplayer.Faction && !player.isMoving && tplayer.MaxHealth > 0 && tplayer.Health < tplayer.MaxHealth) {
if(tplayer.isAlive) {
tplayer.Health += 10
} else {
@ -4912,7 +4914,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
//todo: @NotEnoughAmmoToRevive=You do not have enough medical energy to revive this corpse.
tplayer.Health += 4 // 4 health per tick = 5 second revive timer from 0 health
}
tool.Discharge
sendResponse(InventoryStateMessage(tool.AmmoSlot.Box.GUID, obj.GUID, tool.Magazine))
val repairPercent: Int = tplayer.Health * 100 / tplayer.MaxHealth
@ -4926,8 +4927,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
if(tplayer.isAlive) {
avatarService ! AvatarServiceMessage(tplayer.Continent, AvatarAction.PlanetsideAttributeToAll(tplayer.GUID, 0, tplayer.Health))
}
} else if (player.GUID == tplayer.GUID && player.Velocity.isEmpty && tplayer.MaxHealth > 0 && player.isAlive) {
tplayer.Health += 10
} else if (player.GUID == tplayer.GUID && !player.isMoving && tplayer.MaxHealth > 0 && player.isAlive) {
player.Health += 10
tool.Discharge
sendResponse(InventoryStateMessage(tool.AmmoSlot.Box.GUID, obj.GUID, tool.Magazine))
avatarService ! AvatarServiceMessage(player.Continent, AvatarAction.PlanetsideAttributeToAll(player.GUID, 0, player.Health))
@ -5059,7 +5060,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
equipment.get.Definition match {
case GlobalDefinitions.nano_dispenser =>
//TODO repairing behavior
if (player.Velocity.isEmpty && Vector3.Distance(player.Position, obj.Position) < 5) {
if (!player.isMoving && Vector3.Distance(player.Position, obj.Position) < 5) {
if (obj.Health < obj.MaxHealth) {
obj.Health += 48
// sendResponse(QuantityUpdateMessage(PlanetSideGUID(8214),ammo_quantity_left))
@ -5434,7 +5435,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
val (angle, attribution, acceptableDistanceToOwner) = obj match {
case p : Player =>
(p.Orientation, tool.Definition.ObjectId, 10f) //TODO upper body facing
(SimpleWorldEntity.validateOrientationEntry(p.Orientation + Vector3.z(p.FacingYawUpper)), tool.Definition.ObjectId, 10f)
case v : Vehicle if v.Definition.CanFly =>
(tool.Orientation, obj.Definition.ObjectId, 1000f) //TODO this is too simplistic to find proper angle
case _ : Vehicle =>

View file

@ -369,8 +369,8 @@ class PacketCodingActorETest extends ActorTest {
"PacketCodingActor" should {
"unwind l-originating hexadecimal data into multiple r-facing packets (MultiPacket -> 2 PlayerStateMessageUpstream)" in {
val string_hex = RawPacket(hex"00 03 18 BD E8 04 5C 02 60 E3 F9 19 0E C1 41 27 00 04 02 60 20 0C 58 0B 20 00 00 18 BD E8 04 86 02 62 13 F9 19 0E D8 40 4D 00 04 02 60 20 0C 78 0A 80 00 00")
val string_obj1 = GamePacket(GamePacketOpcode.PlayerStateMessageUpstream, 0, PlayerStateMessageUpstream(PlanetSideGUID(1256),Vector3(3076.7188f,4734.1094f,56.390625f),Some(Vector3(4.0625f,4.59375f,0.0f)),36.5625f,357.1875f,0.0f,866,0,false,false,false,false,178,0))
val string_obj2 = GamePacket(GamePacketOpcode.PlayerStateMessageUpstream, 0, PlayerStateMessageUpstream(PlanetSideGUID(1256),Vector3(3077.0469f,4734.258f,56.390625f),Some(Vector3(5.5f,1.1875f,0.0f)),36.5625f,357.1875f,0.0f,867,0,false,false,false,false,168,0))
val string_obj1 = GamePacket(GamePacketOpcode.PlayerStateMessageUpstream, 0, PlayerStateMessageUpstream(PlanetSideGUID(1256),Vector3(3076.7188f,4734.1094f,56.390625f),Some(Vector3(4.0625f,4.59375f,0.0f)),36.5625f,-2.8125f,0.0f,866,0,false,false,false,false,178,0))
val string_obj2 = GamePacket(GamePacketOpcode.PlayerStateMessageUpstream, 0, PlayerStateMessageUpstream(PlanetSideGUID(1256),Vector3(3077.0469f,4734.258f,56.390625f),Some(Vector3(5.5f,1.1875f,0.0f)),36.5625f,-2.8125f,0.0f,867,0,false,false,false,false,168,0))
val probe1 = TestProbe()
val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe")
@ -454,7 +454,7 @@ class PacketCodingActorHTest extends ActorTest {
class PacketCodingActorITest extends ActorTest {
import net.psforever.packet.game.objectcreate._
val pos : PlacementData = PlacementData(Vector3.Zero, Vector3.Zero)
val app : (Int)=>CharacterAppearanceData = CharacterAppearanceData(
val app : Int=>CharacterAppearanceData = CharacterAppearanceData(
BasicCharacterData("IlllIIIlllIlIllIlllIllI", PlanetSideEmpire.VS, CharacterGender.Female, 41, CharacterVoice.Voice1),
false,
false,
@ -462,7 +462,7 @@ class PacketCodingActorITest extends ActorTest {
"",
0,
false,
2.8125f, 210.9375f,
2.8125f, 0f,
true,
GrenadeState.None,
false,
@ -470,7 +470,7 @@ class PacketCodingActorITest extends ActorTest {
None,
RibbonBars()
)
var char : (Option[Int])=>DetailedCharacterData = DetailedCharacterData(
var char : Option[Int]=>DetailedCharacterData = DetailedCharacterData(
0,
0,
100, 100,
@ -484,8 +484,9 @@ class PacketCodingActorITest extends ActorTest {
None
)
val obj = DetailedPlayerData(pos, app, char, InventoryData(Nil), DrawnSlot.None)
//println(s"${PacketCoding.EncodePacket(ObjectCreateDetailedMessage(0x79, PlanetSideGUID(75), obj))}")
val pkt = MultiPacketBundle(List(ObjectCreateDetailedMessage(0x79, PlanetSideGUID(75), obj)))
val string_hex = hex"00090000186c060000bc84b000000000000000000002040000097049006c006c006c004900490049006c006c006c0049006c0049006c006c0049006c006c006c0049006c006c00490084524000000000000000000000000000000020000007f35703fffffffffffffffffffffffffffffffc000000000000000000000000000000000000000190019000640000000000c800c80000000000000000000000000000000000000001c00042c54686c7000000000000000000000000000000000000000000000000000000000000100000000400e0"
val string_hex = hex"00090000186c060000bc84b000000000000000000002040000097049006c006c006c004900490049006c006c006c0049006c0049006c006c0049006c006c006c0049006c006c00490084524000000000000000000000000000000020000007f00703fffffffffffffffffffffffffffffffc000000000000000000000000000000000000000190019000640000000000c800c80000000000000000000000000000000000000001c00042c54686c7000000000000000000000000000000000000000000000000000000000000100000000400e0"
"PacketCodingActor" should {
"bundle an r-originating packet into an l-facing SlottedMetaPacket byte stream data (SlottedMetaPacket)" in {
@ -582,7 +583,7 @@ class PacketCodingActorKTest extends ActorTest {
false,
false,
false,
2.8125f, 210.9375f,
2.8125f, 0f,
false,
GrenadeState.None,
false,
@ -593,7 +594,7 @@ class PacketCodingActorKTest extends ActorTest {
None
)
val app : (Int)=>CharacterAppearanceData = CharacterAppearanceData(
val app : Int=>CharacterAppearanceData = CharacterAppearanceData(
aa, ab,
RibbonBars()
)
@ -635,7 +636,7 @@ class PacketCodingActorKTest extends ActorTest {
Nil, Nil, false,
None
)
val char : (Option[Int])=>DetailedCharacterData =
val char : Option[Int]=>DetailedCharacterData =
(pad_length : Option[Int]) => DetailedCharacterData(ba, bb(ba.bep, pad_length))(pad_length)
val obj = DetailedPlayerData(pos, app, char, InventoryData(Nil), DrawnSlot.None)
val list = List(