mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-20 02:54:46 +00:00
Maxes and Turrets Fixes (#237)
* modified DCData to account for Max suit encoding; modified converters for the avatar that would make use of DCData changes; corrections to enforce that Max/ex-Max always has correct hand showing * separating initialization-time random GUID assignments from initialization-time fixed GUID assignments by performing them all later
This commit is contained in:
parent
5a67fcd88d
commit
7588166ac0
|
|
@ -4,7 +4,7 @@ package net.psforever.objects.definition.converter
|
|||
import net.psforever.objects.{EquipmentSlot, Player}
|
||||
import net.psforever.objects.equipment.Equipment
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types.{GrenadeState, ImplantType}
|
||||
import net.psforever.types.{ExoSuitType, GrenadeState, ImplantType}
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import scala.util.{Success, Try}
|
||||
|
|
@ -124,7 +124,8 @@ object AvatarConverter {
|
|||
}
|
||||
|
||||
def MakeDetailedCharacterData(obj : Player) : (Option[Int])=>DetailedCharacterData = {
|
||||
val bep = obj.BEP
|
||||
val bep : Long = obj.BEP
|
||||
val maxOpt : Option[Long] = if(obj.ExoSuit == ExoSuitType.MAX) { Some(0L) } else { None }
|
||||
val ba : DetailedCharacterA = DetailedCharacterA(
|
||||
bep,
|
||||
obj.CEP,
|
||||
|
|
@ -134,6 +135,7 @@ object AvatarConverter {
|
|||
obj.Armor,
|
||||
0L,
|
||||
obj.MaxStamina, obj.Stamina,
|
||||
maxOpt,
|
||||
0, 0, 0L,
|
||||
List(0, 0, 0, 0, 0, 0),
|
||||
obj.Certifications.toList.sortBy(_.id) //TODO is sorting necessary?
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ package net.psforever.objects.definition.converter
|
|||
import net.psforever.objects.{EquipmentSlot, Player}
|
||||
import net.psforever.objects.equipment.Equipment
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types.{CertificationType, CharacterVoice, GrenadeState, ImplantType}
|
||||
import net.psforever.types._
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import scala.util.{Failure, Success, Try}
|
||||
|
|
@ -77,7 +77,8 @@ class CharacterSelectConverter extends AvatarConverter {
|
|||
}
|
||||
|
||||
private def MakeDetailedCharacterData(obj : Player) : (Option[Int]=>DetailedCharacterData) = {
|
||||
val bep = obj.BEP
|
||||
val bep : Long = obj.BEP
|
||||
val maxOpt : Option[Long] = if(obj.ExoSuit == ExoSuitType.MAX) { Some(0L) } else { None }
|
||||
val ba : DetailedCharacterA = DetailedCharacterA(
|
||||
bep,
|
||||
obj.CEP,
|
||||
|
|
@ -87,6 +88,7 @@ class CharacterSelectConverter extends AvatarConverter {
|
|||
0,
|
||||
0L,
|
||||
1, 1,
|
||||
maxOpt,
|
||||
0, 0, 0L,
|
||||
List(0, 0, 0, 0, 0, 0),
|
||||
certs = List.empty[CertificationType.Value]
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ class CorpseConverter extends AvatarConverter {
|
|||
}
|
||||
|
||||
private def MakeDetailedCharacterData(obj : Player) : (Option[Int]=>DetailedCharacterData) = {
|
||||
val maxOpt : Option[Long] = if(obj.ExoSuit == ExoSuitType.MAX) { Some(0L) } else { None }
|
||||
val ba : DetailedCharacterA = DetailedCharacterA(
|
||||
bep = 0L,
|
||||
cep = 0L,
|
||||
|
|
@ -81,6 +82,7 @@ class CorpseConverter extends AvatarConverter {
|
|||
0,
|
||||
0L,
|
||||
0, 0,
|
||||
maxOpt,
|
||||
0, 0, 0L,
|
||||
List(0, 0, 0, 0, 0, 0),
|
||||
certs = List.empty[CertificationType.Value]
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import akka.routing.RandomPool
|
|||
import net.psforever.objects.ballistics.Projectile
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.ce.Deployable
|
||||
import net.psforever.objects.entity.IdentifiableEntity
|
||||
import net.psforever.objects.equipment.Equipment
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
import net.psforever.objects.guid.actor.UniqueNumberSystem
|
||||
|
|
@ -313,6 +314,7 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
|
|||
|
||||
private def BuildSupportObjects() : Unit = {
|
||||
//guard against errors here, but don't worry about specifics; let ZoneActor.ZoneSetupCheck complain about problems
|
||||
val other : ListBuffer[IdentifiableEntity] = new ListBuffer[IdentifiableEntity]()
|
||||
//turret to weapon
|
||||
Map.TurretToWeapon.foreach({ case ((turret_guid, weapon_guid)) =>
|
||||
((GUID(turret_guid) match {
|
||||
|
|
@ -333,11 +335,13 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
|
|||
}) match {
|
||||
case Some((obj, Some(weapon : Tool))) =>
|
||||
guid.register(weapon, weapon_guid)
|
||||
weapon.AmmoSlots.foreach(slot => guid.register(slot.Box, "dynamic"))
|
||||
obj.Inventory.Items.foreach(item => guid.register(item.obj, "dynamic")) //internal ammunition reserves, if any
|
||||
other ++= weapon.AmmoSlots.map(slot => slot.Box)
|
||||
other ++= obj.Inventory.Items.map(item => item.obj) //internal ammunition reserves, if any
|
||||
case _ => ;
|
||||
}
|
||||
})
|
||||
//after all fixed GUID's are defined ...
|
||||
other.foreach(obj => guid.register(obj, "dynamic"))
|
||||
}
|
||||
|
||||
private def MakeBuildings(implicit context : ActorContext) : PairMap[Int, Building] = {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package net.psforever.packet.game.objectcreate
|
|||
|
||||
import net.psforever.newcodecs.newcodecs
|
||||
import net.psforever.packet.{Marshallable, PacketHelpers}
|
||||
import net.psforever.types.{CertificationType, ImplantType}
|
||||
import net.psforever.types.{CertificationType, ExoSuitType, ImplantType}
|
||||
import scodec.{Attempt, Codec}
|
||||
import scodec.codecs._
|
||||
import shapeless.{::, HNil}
|
||||
|
|
@ -71,6 +71,8 @@ final case class DCDExtra2(unk1 : Int,
|
|||
* range is 0-65535
|
||||
* @param stamina for `x / y` of stamina points, this is the avatar's `x` value;
|
||||
* range is 0-65535
|
||||
* @param max_field unk;
|
||||
* this field exists only when the player is wearing a mechanized assault exo-suit
|
||||
* @param certs the `List` of certifications
|
||||
*/
|
||||
final case class DetailedCharacterA(bep : Long,
|
||||
|
|
@ -85,14 +87,16 @@ final case class DetailedCharacterA(bep : Long,
|
|||
unk5 : Long,
|
||||
staminaMax : Int,
|
||||
stamina : Int,
|
||||
max_field : Option[Long],
|
||||
unk6 : Int,
|
||||
unk7 : Int,
|
||||
unk8 : Long,
|
||||
unk9 : List[Int],
|
||||
certs : List[CertificationType.Value]) extends StreamBitSize {
|
||||
override def bitsize : Long = {
|
||||
val maxFieldSize = max_field match { case Some(_) => 32L ; case None => 0L }
|
||||
val certSize : Long = certs.length * 8
|
||||
428L + certSize
|
||||
428L + maxFieldSize + certSize
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -197,6 +201,7 @@ object DetailedCharacterData extends Marshallable[DetailedCharacterData] {
|
|||
armor : Int,
|
||||
staminaMax : Int,
|
||||
stamina : Int,
|
||||
maxField : Option[Long],
|
||||
certs : List[CertificationType.Value],
|
||||
implants : List[ImplantEntry],
|
||||
firstTimeEvents : List[String],
|
||||
|
|
@ -213,6 +218,7 @@ object DetailedCharacterData extends Marshallable[DetailedCharacterData] {
|
|||
armor,
|
||||
0L,
|
||||
staminaMax, stamina,
|
||||
maxField,
|
||||
0,
|
||||
0,
|
||||
0L,
|
||||
|
|
@ -527,7 +533,7 @@ object DetailedCharacterData extends Marshallable[DetailedCharacterData] {
|
|||
*/
|
||||
def isBR24(bep : Long) : Boolean = bep > 2286230
|
||||
|
||||
val a_codec : Codec[DetailedCharacterA] = (
|
||||
def a_codec(suit : ExoSuitType.Value) : Codec[DetailedCharacterA] = (
|
||||
("bep" | uint32L) ::
|
||||
("cep" | uint32L) ::
|
||||
("unk1" | uint32L) ::
|
||||
|
|
@ -540,7 +546,7 @@ object DetailedCharacterData extends Marshallable[DetailedCharacterData] {
|
|||
("unk5" | uint32) :: //endianness?
|
||||
("staminaMax" | uint16L) ::
|
||||
("stamina" | uint16L) ::
|
||||
conditional(false, uint32L) :: //see ps.c: sub_901150, line#1070692
|
||||
conditional(suit == ExoSuitType.MAX, uint32L) ::
|
||||
("unk6" | uint16L) ::
|
||||
("unk7" | uint(3)) ::
|
||||
("unk8" | uint32L) ::
|
||||
|
|
@ -548,13 +554,13 @@ object DetailedCharacterData extends Marshallable[DetailedCharacterData] {
|
|||
("certs" | listOfN(uint8L, CertificationType.codec))
|
||||
).exmap[DetailedCharacterA] (
|
||||
{
|
||||
case bep :: cep :: u1 :: u2 :: u3 :: healthMax :: health :: u4 :: armor :: u5 :: staminaMax :: stamina :: None :: u6 :: u7 :: u8 :: u9 :: certs :: HNil =>
|
||||
Attempt.successful(DetailedCharacterA(bep, cep, u1, u2, u3, healthMax, health, u4, armor, u5, staminaMax, stamina, u6, u7, u8, u9, certs))
|
||||
case bep :: cep :: u1 :: u2 :: u3 :: healthMax :: health :: u4 :: armor :: u5 :: staminaMax :: stamina :: max :: u6 :: u7 :: u8 :: u9 :: certs :: HNil =>
|
||||
Attempt.successful(DetailedCharacterA(bep, cep, u1, u2, u3, healthMax, health, u4, armor, u5, staminaMax, stamina, max, u6, u7, u8, u9, certs))
|
||||
},
|
||||
{
|
||||
case DetailedCharacterA(bep, cep, u1, u2, u3, healthMax, health, u4, armor, u5, staminaMax, stamina, u6, u7, u8, u9, certs) =>
|
||||
case DetailedCharacterA(bep, cep, u1, u2, u3, healthMax, health, u4, armor, u5, staminaMax, stamina, max, u6, u7, u8, u9, certs) =>
|
||||
Attempt.successful(
|
||||
bep :: cep :: u1 :: u2 :: u3 :: healthMax :: health :: u4 :: armor :: u5 :: staminaMax :: stamina :: None :: u6 :: u7 :: u8 :: u9 :: certs :: HNil
|
||||
bep :: cep :: u1 :: u2 :: u3 :: healthMax :: health :: u4 :: armor :: u5 :: staminaMax :: stamina :: max :: u6 :: u7 :: u8 :: u9 :: certs :: HNil
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
@ -614,8 +620,8 @@ object DetailedCharacterData extends Marshallable[DetailedCharacterData] {
|
|||
}
|
||||
)
|
||||
|
||||
def codec(pad_length : Option[Int]) : Codec[DetailedCharacterData] = (
|
||||
("a" | a_codec) >>:~ { a =>
|
||||
def codec(suit : ExoSuitType.Value, pad_length : Option[Int]) : Codec[DetailedCharacterData] = (
|
||||
("a" | a_codec(suit)) >>:~ { a =>
|
||||
("b" | b_codec(a.bep, pad_length)).hlist
|
||||
}
|
||||
).exmap[DetailedCharacterData] (
|
||||
|
|
@ -629,5 +635,5 @@ object DetailedCharacterData extends Marshallable[DetailedCharacterData] {
|
|||
}
|
||||
)
|
||||
|
||||
implicit val codec : Codec[DetailedCharacterData] = codec(None)
|
||||
implicit val codec : Codec[DetailedCharacterData] = codec(ExoSuitType.Standard, None)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ object DetailedPlayerData extends Marshallable[DetailedPlayerData] {
|
|||
def codec(position_defined : Boolean) : Codec[DetailedPlayerData] = (
|
||||
conditional(position_defined, "pos" | PlacementData.codec) >>:~ { pos =>
|
||||
("basic_appearance" | CharacterAppearanceData.codec(PlayerData.PaddingOffset(pos))) >>:~ { app =>
|
||||
("character_data" | DetailedCharacterData.codec(app.altModelBit)) ::
|
||||
("character_data" | DetailedCharacterData.codec(app.a.exosuit, app.altModelBit)) ::
|
||||
optional(bool, "inventory" | InventoryData.codec_detailed) ::
|
||||
("drawn_slot" | DrawnSlot.codec) ::
|
||||
bool //usually false
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1460,17 +1460,17 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
else {
|
||||
//remove potential MAX weapon
|
||||
tplayer.DrawnSlot = Player.HandsDownSlot
|
||||
sendResponse(ObjectHeldMessage(tplayer.GUID, Player.HandsDownSlot, true))
|
||||
val normalWeapons = if(originalSuit == ExoSuitType.MAX) {
|
||||
val (maxWeapons, normalWeapons) = beforeHolsters.partition(elem => elem.obj.Size == EquipmentSize.Max)
|
||||
maxWeapons.foreach(entry => {
|
||||
taskResolver ! GUIDTask.UnregisterEquipment(entry.obj)(continent.GUID)
|
||||
})
|
||||
avatarService ! AvatarServiceMessage(player.Continent, AvatarAction.ObjectHeld(player.GUID, player.LastDrawnSlot))
|
||||
normalWeapons
|
||||
}
|
||||
else {
|
||||
tplayer.DrawnSlot = Player.HandsDownSlot
|
||||
sendResponse(ObjectHeldMessage(tplayer.GUID, Player.HandsDownSlot, true))
|
||||
avatarService ! AvatarServiceMessage(tplayer.Continent, AvatarAction.ObjectHeld(tplayer.GUID, Player.HandsDownSlot))
|
||||
beforeHolsters
|
||||
}
|
||||
//fill holsters
|
||||
|
|
@ -2879,7 +2879,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
//we're driving the vehicle
|
||||
player.Position = pos //convenient
|
||||
if(seat.ControlledWeapon.isEmpty) {
|
||||
player.Orientation = Vector3(0f, 0f, ang.z) //convenient
|
||||
player.Orientation = Vector3.z(ang.z) //convenient
|
||||
}
|
||||
obj.Position = pos
|
||||
obj.Orientation = ang
|
||||
|
|
|
|||
|
|
@ -476,6 +476,7 @@ class PacketCodingActorITest extends ActorTest {
|
|||
100, 100,
|
||||
50,
|
||||
100, 100,
|
||||
None,
|
||||
List(CertificationType.StandardAssault, CertificationType.MediumAssault, CertificationType.ATV, CertificationType.Harasser, CertificationType.StandardExoSuit, CertificationType.AgileExoSuit, CertificationType.ReinforcedExoSuit),
|
||||
List(),
|
||||
List(),
|
||||
|
|
@ -601,6 +602,7 @@ class PacketCodingActorKTest extends ActorTest {
|
|||
50,
|
||||
32831L,
|
||||
100, 100,
|
||||
None,
|
||||
0, 0, 0L,
|
||||
List(0, 0, 0, 0, 0, 0),
|
||||
List(
|
||||
|
|
|
|||
Loading…
Reference in a new issue