diff --git a/common/src/main/scala/net/psforever/objects/definition/converter/AvatarConverter.scala b/common/src/main/scala/net/psforever/objects/definition/converter/AvatarConverter.scala
index e42c2214..6c97c17c 100644
--- a/common/src/main/scala/net/psforever/objects/definition/converter/AvatarConverter.scala
+++ b/common/src/main/scala/net/psforever/objects/definition/converter/AvatarConverter.scala
@@ -28,6 +28,7 @@ class AvatarConverter extends ObjectCreateConverter[Player]() {
}
override def DetailedConstructorData(obj : Player) : Try[DetailedCharacterData] = {
+ import net.psforever.types.CertificationType._
Success(
DetailedCharacterData(
MakeAppearanceData(obj),
@@ -36,10 +37,9 @@ class AvatarConverter extends ObjectCreateConverter[Player]() {
obj.MaxHealth,
obj.Health,
obj.Armor,
- 1, 7, 7,
obj.MaxStamina,
obj.Stamina,
- List(0, 1, 11, 21, 26, 27, 28), //TODO certification list
+ List(StandardAssault, MediumAssault, ATV, Harasser, StandardExoSuit, AgileExoSuit, ReinforcedExoSuit), //TODO certification list
List(), //TODO implant list
List.empty[String], //TODO fte list
List.empty[String], //TODO tutorial list
diff --git a/common/src/main/scala/net/psforever/packet/game/objectcreate/DetailedCharacterData.scala b/common/src/main/scala/net/psforever/packet/game/objectcreate/DetailedCharacterData.scala
index ffae12a5..e678c3f1 100644
--- a/common/src/main/scala/net/psforever/packet/game/objectcreate/DetailedCharacterData.scala
+++ b/common/src/main/scala/net/psforever/packet/game/objectcreate/DetailedCharacterData.scala
@@ -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.ImplantType
+import net.psforever.types.{CertificationType, ImplantType}
import scodec.{Attempt, Codec}
import scodec.codecs._
import shapeless.{::, HNil}
@@ -12,9 +12,9 @@ import scala.annotation.tailrec
/**
* An entry in the `List` of valid implant slots in `DetailedCharacterData`.
- * "`activation`" is not necessarily the best word for it ...
+ * `activation`, if defined, indicates the time remaining (in seconds?) before an implant can be activated.
* @param implant the type of implant
- * @param activation na
+ * @param activation the activation timer
* @see `ImplantType`
*/
final case class ImplantEntry(implant : ImplantType.Value,
@@ -87,7 +87,7 @@ final case class DetailedCharacterData(appearance : CharacterAppearanceData,
unk3 : Int, //7
staminaMax : Int,
stamina : Int,
- certs : List[Int],
+ certs : List[CertificationType.Value],
implants : List[ImplantEntry],
firstTimeEvents : List[String],
tutorials : List[String],
@@ -98,13 +98,12 @@ final case class DetailedCharacterData(appearance : CharacterAppearanceData,
override def bitsize : Long = {
//factor guard bool values into the base size, not corresponding optional fields, unless contained or enumerated
val appearanceSize = appearance.bitsize
- val varBit : Option[Int] = CharacterAppearanceData.altModelBit(appearance)
val certSize = (certs.length + 1) * 8 //cert list
var implantSize : Long = 0L //implant list
for(entry <- implants) {
implantSize += entry.bitsize
}
- val implantPadding = DetailedCharacterData.implantFieldPadding(implants, varBit)
+ val implantPadding = DetailedCharacterData.implantFieldPadding(implants, CharacterAppearanceData.altModelBit(appearance))
val fteLen = firstTimeEvents.size //fte list
var eventListSize : Long = 32L + DetailedCharacterData.ftePadding(fteLen, implantPadding)
for(str <- firstTimeEvents) {
@@ -127,28 +126,28 @@ final case class DetailedCharacterData(appearance : CharacterAppearanceData,
object DetailedCharacterData extends Marshallable[DetailedCharacterData] {
/**
- * Overloaded constructor for `DetailedCharacterData` that allows for a not-optional inventory.
+ * Overloaded constructor for `DetailedCharacterData` that requires an inventory and drops unknown values.
* @param appearance data about the avatar's basic aesthetics
+ * @param bep the avatar's battle experience points, which determines his Battle Rank
+ * @param cep the avatar's command experience points, which determines his Command Rank
* @param healthMax for `x / y` of hitpoints, this is the avatar's `y` value
* @param health for `x / y` of hitpoints, this is the avatar's `x` value
* @param armor for `x / y` of armor points, this is the avatar's `x` value
- * @param unk1 na
- * @param unk2 na
- * @param unk3 na
* @param staminaMax for `x / y` of stamina points, this is the avatar's `y` value
* @param stamina for `x / y` of stamina points, this is the avatar's `x` value
- * @param certs na
+ * @param certs the `List` of active certifications
+ * @param implants the `List` of implant slots currently possessed by this avatar
* @param firstTimeEvents the list of first time events performed by this avatar
* @param tutorials the list of tutorials completed by this avatar
* @param inventory the avatar's inventory
* @param drawn_slot the holster that is initially drawn
* @return a `DetailedCharacterData` object
*/
- def apply(appearance : CharacterAppearanceData, bep : Long, cep : Long, healthMax : Int, health : Int, armor : Int, unk1 : Int, unk2 : Int, unk3 : Int, staminaMax : Int, stamina : Int, certs : List[Int], implants : List[ImplantEntry], firstTimeEvents : List[String], tutorials : List[String], inventory : InventoryData, drawn_slot : DrawnSlot.Value) : DetailedCharacterData =
- new DetailedCharacterData(appearance, bep, cep, healthMax, health, armor, unk1, unk2, unk3, staminaMax, stamina, certs, implants, firstTimeEvents, tutorials, Some(inventory), drawn_slot)
+ def apply(appearance : CharacterAppearanceData, bep : Long, cep : Long, healthMax : Int, health : Int, armor : Int, staminaMax : Int, stamina : Int, certs : List[CertificationType.Value], implants : List[ImplantEntry], firstTimeEvents : List[String], tutorials : List[String], inventory : InventoryData, drawn_slot : DrawnSlot.Value) : DetailedCharacterData =
+ new DetailedCharacterData(appearance, bep, cep, healthMax, health, armor, 1, 7, 7, staminaMax, stamina, certs, implants, firstTimeEvents, tutorials, Some(inventory), drawn_slot)
/**
- * `Codec` for entires in the list of implants.
+ * `Codec` for entries in the `List` of implants.
*/
private val implant_entry_codec : Codec[ImplantEntry] = (
("implant" | ImplantType.codec) ::
@@ -285,7 +284,7 @@ object DetailedCharacterData extends Marshallable[DetailedCharacterData] {
("staminaMax" | uint16L) ::
("stamina" | uint16L) ::
ignore(147) ::
- ("certs" | listOfN(uint8L, uint8L)) ::
+ ("certs" | listOfN(uint8L, CertificationType.codec)) ::
optional(bool, uint32L) :: //ask about sample CCRIDER
ignore(4) ::
(("implants" | PacketHelpers.listOfNSized(numberOfImplantSlots(bep), implant_entry_codec)) >>:~ { implants =>
diff --git a/common/src/main/scala/net/psforever/types/CertificationType.scala b/common/src/main/scala/net/psforever/types/CertificationType.scala
new file mode 100644
index 00000000..d06e2d19
--- /dev/null
+++ b/common/src/main/scala/net/psforever/types/CertificationType.scala
@@ -0,0 +1,79 @@
+// Copyright (c) 2017 PSForever
+package net.psforever.types
+
+import net.psforever.packet.PacketHelpers
+import scodec.codecs._
+/**
+ * An `Enumeration` of the available certifications.
+ *
+ * As indicated, the following certifications are always enqueued on an avatar's permissions:
+ * `StandardAssault`, `StandardExoSuit`, `AgileExoSuit`.
+ * They must still be included in any formal lists of permitted equipment for a user.
+ * The other noted certifications require all prerequisite certifications listed or they themselves will not be listed:
+ * `ElectronicsExpert` and `AdvancedEngineering`.
+ * No other certification requires its prerequisites explicitly listed to be listed itself.
+ * Any certification that contains multiple other certifications overrides those individual certifications in the list.
+ * There is no certification for the Advanced Nanite Transport.
+ *
+ * In terms of pricing, `StandardAssault`, `StandardExoSuit`, and `AgileExoSuit` are costless.
+ * A certification that contains multiple other certifications acts as the overriding cost.
+ * (Taking `UniMAX` while owning `AAMAX` will refund the `AAMAX` cost and replace it with the `UniMAX` cost.)
+ */
+object CertificationType extends Enumeration {
+ type Type = Value
+ val
+ //0
+ StandardAssault, //always listed
+ MediumAssault,
+ HeavyAssault,
+ SpecialAssault,
+ AntiVehicular,
+ Sniping,
+ EliteAssault,
+ AirCalvaryScout,
+ AirCalvaryInterceptor,
+ AirCalvaryAssault,
+ //10
+ AirSupport,
+ ATV,
+ LightScout,
+ AssaultBuggy,
+ ArmoredAssault1,
+ ArmoredAssault2,
+ GroundTransport,
+ GroundSupport,
+ BattleFrameRobotics,
+ Flail,
+ //20
+ Switchblade,
+ Harasser,
+ Phantasm,
+ GalaxyGunship,
+ BFRAntiAircraft,
+ BFRAntiInfantry,
+ StandardExoSuit, //always listed
+ AgileExoSuit, //always listed
+ ReinforcedExoSuit,
+ InfiltrationSuit,
+ //30
+ AAMAX,
+ AIMAX,
+ AVMAX,
+ UniMAX,
+ Medical,
+ AdvancedMedical,
+ Hacking,
+ AdvancedHacking,
+ ExpertHacking,
+ DataCorruption,
+ //40
+ ElectronicsExpert, //requires Hacking and AdvancedHacking
+ Engineering,
+ CombatEngineering,
+ FortificationEngineering,
+ AssaultEngineering,
+ AdvancedEngineering //requires Engineering and CombatEngineering
+ = Value
+
+ implicit val codec = PacketHelpers.createEnumerationCodec(this, uint8L)
+}
diff --git a/common/src/test/scala/game/ObjectCreateDetailedMessageTest.scala b/common/src/test/scala/game/ObjectCreateDetailedMessageTest.scala
index d585e60a..f6163520 100644
--- a/common/src/test/scala/game/ObjectCreateDetailedMessageTest.scala
+++ b/common/src/test/scala/game/ObjectCreateDetailedMessageTest.scala
@@ -206,6 +206,8 @@ class ObjectCreateDetailedMessageTest extends Specification {
char.appearance.ribbons.middle mustEqual MeritCommendation.None
char.appearance.ribbons.lower mustEqual MeritCommendation.None
char.appearance.ribbons.tos mustEqual MeritCommendation.None
+ char.bep mustEqual 0
+ char.cep mustEqual 0
char.healthMax mustEqual 100
char.health mustEqual 100
char.armor mustEqual 50 //standard exosuit value
@@ -214,7 +216,15 @@ class ObjectCreateDetailedMessageTest extends Specification {
char.unk3 mustEqual 7
char.staminaMax mustEqual 100
char.stamina mustEqual 100
- char.certs mustEqual List(0, 1, 11, 21, 26, 27, 28)
+ char.certs.length mustEqual 7
+ char.certs.head mustEqual CertificationType.StandardAssault
+ char.certs(1) mustEqual CertificationType.MediumAssault
+ char.certs(2) mustEqual CertificationType.ATV
+ char.certs(3) mustEqual CertificationType.Harasser
+ char.certs(4) mustEqual CertificationType.StandardExoSuit
+ char.certs(5) mustEqual CertificationType.AgileExoSuit
+ char.certs(6) mustEqual CertificationType.ReinforcedExoSuit
+ char.implants.length mustEqual 0
char.firstTimeEvents.size mustEqual 4
char.firstTimeEvents.head mustEqual "xpe_sanctuary_help"
char.firstTimeEvents(1) mustEqual "xpe_th_firemodes"
@@ -406,11 +416,19 @@ class ObjectCreateDetailedMessageTest extends Specification {
50,
1, 7, 7,
100, 100,
- List(0, 1, 11, 21, 26, 27, 28),
+ List(
+ CertificationType.StandardAssault,
+ CertificationType.MediumAssault,
+ CertificationType.ATV,
+ CertificationType.Harasser,
+ CertificationType.StandardExoSuit,
+ CertificationType.AgileExoSuit,
+ CertificationType.ReinforcedExoSuit
+ ),
List(),
"xpe_sanctuary_help" :: "xpe_th_firemodes" :: "used_beamer" :: "map13" :: Nil,
List.empty,
- InventoryData(inv),
+ Some(InventoryData(inv)),
DrawnSlot.Pistol1
)
val msg = ObjectCreateDetailedMessage(0x79, PlanetSideGUID(75), obj)
diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala
index 8013b820..56e0024d 100644
--- a/pslogin/src/main/scala/WorldSessionActor.scala
+++ b/pslogin/src/main/scala/WorldSessionActor.scala
@@ -394,8 +394,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
case ListAccountCharacters =>
val gen : AtomicInteger = new AtomicInteger(1)
- log.info(s"${PacketCoding.DecodePacket(objectHex)}")
- sendRawResponse(objectHex)
+ //log.info(s"${PacketCoding.DecodePacket(objectHex)}")
+ sendResponse(objectHex)
sendResponse(PacketCoding.CreateGamePacket(0, CharacterInfoMessage(15,PlanetSideZoneID(10000), 41605313, PlanetSideGUID(75), false, 6404428)))
//load characters
// SetCharacterSelectScreenGUID(player, gen)
@@ -456,7 +456,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
// sendResponse(PacketCoding.CreateGamePacket(0,
// ObjectCreateDetailedMessage(ObjectClass.avatar, tplayer.GUID, tplayer.Definition.Packet.DetailedConstructorData(tplayer).get)
// ))
- sendRawResponse(objectHex)
+ sendResponse(objectHex)
avatarService ! AvatarServiceMessage(tplayer.Continent, AvatarAction.LoadPlayer(tplayer.GUID, tplayer.Definition.Packet.ConstructorData(tplayer).get))
log.debug(s"ObjectCreateDetailedMessage: ${tplayer.Definition.Packet.DetailedConstructorData(tplayer).get}")
@@ -495,47 +495,53 @@ class WorldSessionActor extends Actor with MDCContextAware {
failWithError(s"Invalid packet class received: $default")
}
- val objectHex = hex"18 4a c7 00 00 bc 84 B0 0c 0b 95 59 9a 84 40 b0 00 01 32 00 00 08 70 43 00 43 00 52 00 49 00 44 00 45 00 52 00 82 28 c9 3d 04 40 03 c0 01 40 02 80 00 40 35 18 40 00 25 40 42 00 6c 00 61 00 63 00 6b 00 20 00 41 00 72 00 6d 00 6f 00 72 00 65 00 64 00 20 00 52 00 65 00 61 00 70 00 65 00 72 00 73 00 0f 00 00 03 02 0c 00 00 03 88 00 00 00 d4 00 00 01 9c 04 00 00 09 19 90 02 04 3c 28 00 00 00 00 00 00 00 00 00 00 00 00 01 90 01 90 00 64 00 00 01 00 7e c8 00 c8 00 00 01 b9 53 4c 00 00 00 00 00 00 00 00 00 00 00 00 00 03 40 00 40 81 c6 86 c8 48 88 c9 09 49 8a 67 86 e0 00 01 25 e0 32 d8 09 6c 00 00 3c 04 00 02 30 7870655f626c61636b6f7073917870655f626174746c655f72616e6b5f39927870655f626174746c655f72616e6b5f3233927870655f636f6d6d616e645f72616e6b5f318f7870655f666f726d5f6f75746669748e7870655f6d61696c5f616c657274927870655f626174746c655f72616e6b5f3232927870655f636f6d6d616e645f72616e6b5f33907870655f666f726d5f706c61746f6f6e927870655f626174746c655f72616e6b5f3133927870655f626174746c655f72616e6b5f3132927870655f626174746c655f72616e6b5f3130927870655f626174746c655f72616e6b5f3134927870655f626174746c655f72616e6b5f3135917870655f626174746c655f72616e6b5f38927870655f626174746c655f72616e6b5f3131927870655f626174746c655f72616e6b5f3231927870655f626174746c655f72616e6b5f3230927870655f626174746c655f72616e6b5f3138927870655f626174746c655f72616e6b5f3139907870655f6a6f696e5f706c61746f6f6e927870655f626174746c655f72616e6b5f3137927870655f626174746c655f72616e6b5f31368f7870655f6a6f696e5f6f7574666974927870655f626174746c655f72616e6b5f3235927870655f626174746c655f72616e6b5f3234917870655f626174746c655f72616e6b5f37917870655f62696e645f666163696c6974798c7870655f62696e645f616d73927870655f636f6d6d616e645f72616e6b5f35927870655f636f6d6d616e645f72616e6b5f32927870655f696e7374616e745f616374696f6e8e7870655f666f726d5f7371756164917870655f626174746c655f72616e6b5f34937870655f776172705f676174655f7573616765917870655f626174746c655f72616e6b5f32917870655f626174746c655f72616e6b5f33927870655f73616e6374756172795f68656c708c7870655f64726f705f706f64937870655f6f72626974616c5f73687574746c65917870655f626174746c655f72616e6b5f368e7870655f6a6f696e5f7371756164917870655f626174746c655f72616e6b5f35927870655f74685f737769746368626c6164658d7870655f74685f726f757465728c7870655f74685f666c61696c8a7870655f74685f616e748a7870655f74685f616d738a7870655f74685f62667289757365645f6f69637791757365645f616476616e6365645f61636597766973697465645f73706974666972655f74757272657498766973697465645f73706974666972655f636c6f616b656493766973697465645f73706974666972655f616192766973697465645f74616e6b5f7472617073a1766973697465645f706f727461626c655f6d616e6e65645f7475727265745f6e638e757365645f6d616763757474657293766973697465645f77616c6c5f7475727265748b766973697465645f616d738b766973697465645f616e7490766973697465645f64726f707368697091766973697465645f6c6962657261746f7294766973697465645f6c6967687467756e7368697091766973697465645f6c696768746e696e6790766973697465645f6d616772696465728f766973697465645f70726f776c657293766973697465645f71756164737465616c746890766973697465645f736b7967756172649a766973697465645f74687265656d616e686561767962756767799d766973697465645f74776f5f6d616e5f61737361756c745f627567677998766973697465645f74776f6d616e6865617679627567677998766973697465645f74776f6d616e686f766572627567677990766973697465645f76616e67756172648d766973697465645f666c61696c8e766973697465645f726f7574657293766973697465645f737769746368626c6164658e766973697465645f6175726f726193766973697465645f626174746c657761676f6e8c766973697465645f6675727993766973697465645f7175616461737361756c7496766973697465645f67616c6178795f67756e736869708e766973697465645f6170635f74728e766973697465645f6170635f767390766973697465645f6c6f64657374617290766973697465645f7068616e7461736d91766973697465645f7468756e64657265728e766973697465645f6170635f6e638f766973697465645f76756c747572658c766973697465645f7761737090766973697465645f6d6f73717569746f97766973697465645f617068656c696f6e5f666c6967687497766973697465645f617068656c696f6e5f67756e6e657297766973697465645f636f6c6f737375735f666c6967687497766973697465645f636f6c6f737375735f67756e6e657298766973697465645f706572656772696e655f666c6967687498766973697465645f706572656772696e655f67756e6e657289757365645f62616e6b95766973697465645f7265736f757263655f73696c6f9e766973697465645f63657274696669636174696f6e5f7465726d696e616c94766973697465645f6d65645f7465726d696e616c93757365645f6e616e6f5f64697370656e73657295766973697465645f73656e736f725f736869656c649a766973697465645f62726f6164636173745f77617270676174658c757365645f7068616c616e7894757365645f7068616c616e785f6176636f6d626f96757365645f7068616c616e785f666c616b636f6d626f96766973697465645f77617270676174655f736d616c6c91757365645f666c616d657468726f7765729a757365645f616e6369656e745f7475727265745f776561706f6e92766973697465645f4c4c555f736f636b657492757365645f656e657267795f67756e5f6e6397766973697465645f6d656469756d7472616e73706f72749f757365645f617068656c696f6e5f696d6d6f6c6174696f6e5f63616e6e6f6e93757365645f6772656e6164655f706c61736d6193757365645f6772656e6164655f6a616d6d657298766973697465645f736869656c645f67656e657261746f7295766973697465645f6d6f74696f6e5f73656e736f7296766973697465645f6865616c74685f6372797374616c96766973697465645f7265706169725f6372797374616c97766973697465645f76656869636c655f6372797374616c91757365645f6772656e6164655f6672616788757365645f61636598766973697465645f6164765f6d65645f7465726d696e616c8b757365645f6265616d657290757365645f626f6c745f6472697665728b757365645f6379636c65728a757365645f676175737391757365645f68756e7465727365656b657288757365645f6973708b757365645f6c616e6365728b757365645f6c61736865728e757365645f6d61656c7374726f6d8c757365645f70686f656e69788b757365645f70756c7361728d757365645f70756e69736865728e757365645f725f73686f7467756e8d757365645f7261646961746f7288757365645f72656b8d757365645f72657065617465728c757365645f726f636b6c65748c757365645f737472696b65728f757365645f73757070726573736f728c757365645f7468756d7065729c766973697465645f76616e755f636f6e74726f6c5f636f6e736f6c6598766973697465645f636170747572655f7465726d696e616c92757365645f6d696e695f636861696e67756e91757365645f6c617a655f706f696e7465728c757365645f74656c657061648b757365645f7370696b657291757365645f68656176795f736e6970657293757365645f636f6d6d616e645f75706c696e6b8d757365645f66697265626972648e757365645f666c6563686574746594757365645f68656176795f7261696c5f6265616d89757365645f696c63399a766973697465645f67656e657261746f725f7465726d696e616c8e766973697465645f6c6f636b65729a766973697465645f65787465726e616c5f646f6f725f6c6f636b9c766973697465645f6169725f76656869636c655f7465726d696e616c97766973697465645f67616c6178795f7465726d696e616c98766973697465645f696d706c616e745f7465726d696e616c99766973697465645f7365636f6e646172795f6361707475726590757365645f32356d6d5f63616e6e6f6e99757365645f6c6962657261746f725f626f6d6261726469657293766973697465645f7265706169725f73696c6f93766973697465645f76616e755f6d6f64756c6591757365645f666c61696c5f776561706f6e8b757365645f73637974686598766973697465645f7265737061776e5f7465726d696e616c8c757365645f62616c6c67756e95757365645f616e6e69766572736172795f67756e6195757365645f616e6e69766572736172795f67756e6294757365645f616e6e69766572736172795f67756e90757365645f37356d6d5f63616e6e6f6e92757365645f6170635f6e635f776561706f6e92757365645f6170635f74725f776561706f6e92757365645f6170635f76735f776561706f6e90757365645f666c75785f63616e6e6f6e93757365645f617068656c696f6e5f6c617365729f757365645f617068656c696f6e5f706c61736d615f726f636b65745f706f6491757365645f617068656c696f6e5f70706196757365645f617068656c696f6e5f73746172666972658c757365645f666c7578706f6494766973697465645f6266725f7465726d696e616c95757365645f636f6c6f737375735f6275727374657296757365645f636f6c6f737375735f636861696e67756e9e757365645f636f6c6f737375735f636c75737465725f626f6d625f706f64a0757365645f636f6c6f737375735f6475616c5f3130306d6d5f63616e6e6f6e7399757365645f636f6c6f737375735f74616e6b5f63616e6e6f6e96766973697465645f64616d6167655f6372797374616c96766973697465645f656e657267795f6372797374616c9b757365645f68656176795f6772656e6164655f6c61756e6368657298757365645f33356d6d5f726f74617279636861696e67756e8b757365645f6b6174616e6190757365645f33356d6d5f63616e6e6f6e93757365645f7265617665725f776561706f6e7396757365645f6c696768746e696e675f776561706f6e738c757365645f6d65645f61707090757365645f32306d6d5f63616e6e6f6e98766973697465645f6d6f6e6f6c6974685f616d657269736899766973697465645f6d6f6e6f6c6974685f636572797368656e97766973697465645f6d6f6e6f6c6974685f637973736f7297766973697465645f6d6f6e6f6c6974685f6573616d697299766973697465645f6d6f6e6f6c6974685f666f72736572616c97766973697465645f6d6f6e6f6c6974685f686f7373696e99766973697465645f6d6f6e6f6c6974685f697368756e64617298766973697465645f6d6f6e6f6c6974685f7365617268757397766973697465645f6d6f6e6f6c6974685f736f6c73617292757365645f6e635f6865765f66616c636f6e99757365645f6e635f6865765f7363617474657263616e6e6f6e93757365645f6e635f6865765f73706172726f7791757365645f61726d6f725f736970686f6e9f757365645f706572656772696e655f6475616c5f6d616368696e655f67756e9f757365645f706572656772696e655f6475616c5f726f636b65745f706f647399757365645f706572656772696e655f6d65636868616d6d65728f757365645f6e74755f736970686f6e9e757365645f706572656772696e655f7061727469636c655f63616e6e6f6e96757365645f706572656772696e655f73706172726f7791757365645f3130356d6d5f63616e6e6f6e92757365645f31356d6d5f636861696e67756ea0757365645f70756c7365645f7061727469636c655f616363656c657261746f7293757365645f726f74617279636861696e67756e9f766973697465645f6465636f6e737472756374696f6e5f7465726d696e616c95757365645f736b7967756172645f776561706f6e7391766973697465645f67656e657261746f7291757365645f67617573735f63616e6e6f6e89757365645f7472656b95757365645f76616e67756172645f776561706f6e73a4766973697465645f616e6369656e745f6169725f76656869636c655f7465726d696e616ca2766973697465645f616e6369656e745f65717569706d656e745f7465726d696e616c96766973697465645f6f726465725f7465726d696e616ca7766973697465645f616e6369656e745f67726f756e645f76656869636c655f7465726d696e616c9f766973697465645f67726f756e645f76656869636c655f7465726d696e616c97757365645f76756c747572655f626f6d6261726469657298757365645f76756c747572655f6e6f73655f63616e6e6f6e98757365645f76756c747572655f7461696c5f63616e6e6f6e97757365645f776173705f776561706f6e5f73797374656d91766973697465645f636861726c6965303591766973697465645f636861726c6965303691766973697465645f636861726c6965303791766973697465645f636861726c6965303891766973697465645f636861726c696530398e766973697465645f736c656430348e766973697465645f736c656430358e766973697465645f736c656430368e766973697465645f736c656430378e766973697465645f736c65643038857567643036857567643035857567643034857567643033857567643032857567643031856d61703939856d61703938856d61703937856d61703936856d61703135856d61703134856d61703133856d61703132856d61703131856d61703034856d61703035856d61703033856d61703031856d61703036856d61703032856d61703039856d61703037856d617031300800000092747261696e696e675f776561706f6e73303192747261696e696e675f7761727067617465738c747261696e696e675f6d617092747261696e696e675f696e76656e746f727990747261696e696e675f6865616c696e678d747261696e696e675f686172748f747261696e696e675f61726d6f727390747261696e696e675f77656c636f6d650000000000000000000000000000000000000000ab000480000005000000058000000800000008800000090000000f0000000f8000001000000012800000130000001a0000001a8000001c800000228000002e00000031800000320000003580000036000000368000003700000039000000398000003a0000003a8000003b0000003f800000400000004080000041000000418000004e000000518000005580000059000000598000005a0000005a800000610000006180000063000000648000006b8000006c0000006c8000006f0000006f800000700000007080000071000000718000007280000073000000798000007a0000000080800004808000050080000a8080000b0080000d8080000e0080000e8080000f0080001080800011008000140080001c808000270080002a8080002b00800033808000388080003c0080003c8080004000800043808000440080004480800045008000470080004c0080004f808000520080005400800000002f0a26c9313c024000001000060279a272780c80000100026b271682480000020000c041c0464f019000006400d43541d08900000040001808388946a0320000008019041c821700000008046ce915631018000000400018083822c6a030000019001d2338421b00000008000301070438ac060000032003a4630c466000000100006020e06c1e80c000006400748e01c92c00000020000c041c11e4101800000c800e90a02331800000040001808381b06e030000019001989ec436b000000080003010c81d924060000019003310e87f0600000010000602190d31780c000003200662fa22e6c00000020000c04320a82f018000006400e90683bd9800000040001808381205a030000019000205808bcb000001900040e4908058e0000032006629c1d00b4c00000020000c043209c35018000006400cc480320175800000040001808642084a03000000c80198880540303000000080003010c87d86c060000019000b17e9100636000000100006020e01f2080c00000c800081580f010bc000006400414961a022f800000040001808de0004603000003200082818840477000000080003011bc0a11406000006400040a28680b2e000003200569271a017ac00000020000c041037435018000008c00ce2e04003498000000400018099e6c46e03000004b0019c4483406b70000000800030133cc28ec06000009600040ad8e80dfe0000032006710e1201fec00000020000c04cf2a837018000025800ce37432040f8000000400018099e7586a03000004b00058b18480843000000080003010702f11406000006400040f690010ce0000032000e0222786c8000064001c1d82b13900000c800380205233200001900074559050e40000320079afa0fa4c800002000d84b64f4e9000000400010300380"
-// val objectHex = PacketCoding.CreateGamePacket(0,
-// ObjectCreateDetailedMessage(
-// 121,
-// PlanetSideGUID(75),
-// DetailedCharacterData(
-// CharacterAppearanceData(
-// PlacementData(Vector3(2931.5f,4404.6953f,45.0625f), Vector3(0.0f,0.0f,36.5625f)),
-// BasicCharacterData("psemu2",PlanetSideEmpire.VS,CharacterGender.Male,20,3),
-// 0,
-// false,
-// false,
-// ExoSuitType.Standard,
-// "",
-// 15,
-// false,
-// 0.0f, 0.0f,
-// false,
-// GrenadeState.None,
-// false,
-// false,
-// false,
-// RibbonBars(
-// MeritCommendation.None,MeritCommendation.None,MeritCommendation.None,MeritCommendation.None
-// )
-// ),
-// 31467,
-// 0,
-// 100, 100,
-// 50,
-// 1,7,7,
-// 100,100,
-// 7,
-// CertificationEntries(List(0, 0, 11, 26, 27, 31, 41, 0, 0),Some(0)),
-// List("xpe_blackops"),
-// List(),
-// None,
-// DrawnSlot.None
-// )
-// )
-// )
+// val objectHex = hex"18 57 0C 00 00 BC 84 B0 06 C2 D7 65 53 5C A1 60 00 01 34 40 00 09 70 49 00 6C 00 6C 00 6C 00 49 00 49 00 49 00 6C 00 6C 00 6C 00 49 00 6C 00 49 00 6C 00 6C 00 49 00 6C 00 6C 00 6C 00 49 00 6C 00 6C 00 49 00 84 52 70 76 1E 80 80 00 00 00 00 00 3F FF C0 00 00 00 20 00 00 0F F6 A7 03 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FD 90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 90 01 90 00 64 00 00 01 00 7E C8 00 C8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 C0 00 42 C5 46 86 C7 00 00 00 80 00 00 12 40 78 70 65 5F 73 61 6E 63 74 75 61 72 79 5F 68 65 6C 70 90 78 70 65 5F 74 68 5F 66 69 72 65 6D 6F 64 65 73 8B 75 73 65 64 5F 62 65 61 6D 65 72 85 6D 61 70 31 33 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 0A 23 02 60 04 04 40 00 00 10 00 06 02 08 14 D0 08 0C 80 00 02 00 02 6B 4E 00 82 88 00 00 02 00 00 C0 41 C0 9E 01 01 90 00 00 64 00 44 2A 00 10 91 00 00 00 40 00 18 08 38 94 40 20 32 00 00 00 80 19 05 48 02 17 20 00 00 08 00 70 29 80 43 64 00 00 32 00 0E 05 40 08 9C 80 00 06 40 01 C0 AA 01 19 90 00 00 C8 00 3A 15 80 28 72 00 00 19 00 04 0A B8 05 26 40 00 03 20 06 C2 58 00 A7 88 00 00 02 00 00 80 00 00"
+ val objectHex = PacketCoding.CreateGamePacket(0,
+ ObjectCreateDetailedMessage(
+ 121,
+ PlanetSideGUID(75),
+ DetailedCharacterData(
+ CharacterAppearanceData(
+ PlacementData(Vector3(3674.8438f,2726.789f,91.15625f), Vector3(0.0f,0.0f,36.5625f)),
+ BasicCharacterData("psemu2",PlanetSideEmpire.VS,CharacterGender.Female,41,1),
+ 0,
+ false,
+ false,
+ ExoSuitType.Standard,
+ "",
+ 0,
+ false,
+ 2.8125f, 210.9375f,
+ true,
+ GrenadeState.None,
+ false,
+ false,
+ false,
+ RibbonBars()
+ ),
+ 0,
+ 0,
+ 100, 100,
+ 50,
+ 1,7,7,
+ 100,100,
+ List(
+ CertificationType.StandardAssault,
+ CertificationType.MediumAssault,
+ CertificationType.ATV,
+ CertificationType.Harasser,
+ CertificationType.StandardExoSuit,
+ CertificationType.AgileExoSuit,
+ CertificationType.ReinforcedExoSuit
+ ),
+ List(),
+ List("xpe_blackops"),
+ List(),
+ None,
+ DrawnSlot.None
+ )
+ )
+ )
def handlePkt(pkt : PlanetSidePacket) : Unit = pkt match {
case ctrl : PlanetSideControlPacket =>