created a MeritCommendation Enumeration to use with the ribbon awards

This commit is contained in:
FateJH 2017-05-07 01:34:55 -04:00
parent 684c64679b
commit 2110797790
7 changed files with 576 additions and 41 deletions

View file

@ -1,7 +1,7 @@
// Copyright (c) 2017 PSForever // Copyright (c) 2017 PSForever
package net.psforever.packet.game package net.psforever.packet.game
import net.psforever.packet.game.objectcreate.RibbonBars import net.psforever.types.MeritCommendation
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket} import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
import scodec.Codec import scodec.Codec
import scodec.codecs._ import scodec.codecs._
@ -35,14 +35,15 @@ object RibbonBarsSlot extends Enumeration {
* The last set slot is considered the valid position to which that ribbon will be placed/moved. * The last set slot is considered the valid position to which that ribbon will be placed/moved.
* @param player_guid the player * @param player_guid the player
* @param ribbon the award to be displayed; * @param ribbon the award to be displayed;
* defaults to `RibbonsBars.noRibbon`; * defaults to `MeritCommendation.None`;
* use `RibbonsBars.noRibbon` when indicating "no ribbon" * use `MeritCommendation.None` when indicating "no ribbon"
* @param bar any of the four positions where the award ribbon is to be displayed; * @param bar any of the four positions where the award ribbon is to be displayed;
* defaults to `TermOfService` * defaults to `TermOfService`
* @see `RibbonBars` * @see `RibbonBars`
* @see `MeritCommendation`
*/ */
final case class DisplayedAwardMessage(player_guid : PlanetSideGUID, final case class DisplayedAwardMessage(player_guid : PlanetSideGUID,
ribbon : Long = RibbonBars.noRibbon, ribbon : MeritCommendation.Value = MeritCommendation.None,
bar : RibbonBarsSlot.Value = RibbonBarsSlot.TermOfService) bar : RibbonBarsSlot.Value = RibbonBarsSlot.TermOfService)
extends PlanetSideGamePacket { extends PlanetSideGamePacket {
type Packet = DisplayedAwardMessage type Packet = DisplayedAwardMessage
@ -53,7 +54,7 @@ final case class DisplayedAwardMessage(player_guid : PlanetSideGUID,
object DisplayedAwardMessage extends Marshallable[DisplayedAwardMessage] { object DisplayedAwardMessage extends Marshallable[DisplayedAwardMessage] {
implicit val codec : Codec[DisplayedAwardMessage] = ( implicit val codec : Codec[DisplayedAwardMessage] = (
("player_guid" | PlanetSideGUID.codec) :: ("player_guid" | PlanetSideGUID.codec) ::
("ribbon" | uint32L) :: ("ribbon" | MeritCommendation.codec) ::
("bar" | RibbonBarsSlot.codec) ("bar" | RibbonBarsSlot.codec)
).as[DisplayedAwardMessage] ).as[DisplayedAwardMessage]
} }

View file

@ -55,8 +55,10 @@ object ObjectCreateDetailedMessage extends Marshallable[ObjectCreateDetailedMess
* @param data the data used to construct this type of object * @param data the data used to construct this type of object
* @return an ObjectCreateMessage * @return an ObjectCreateMessage
*/ */
def apply(objectClass : Int, guid : PlanetSideGUID, parentInfo : ObjectCreateMessageParent, data : ConstructorData) : ObjectCreateDetailedMessage = def apply(objectClass : Int, guid : PlanetSideGUID, parentInfo : ObjectCreateMessageParent, data : ConstructorData) : ObjectCreateDetailedMessage = {
ObjectCreateDetailedMessage(0L, objectClass, guid, Some(parentInfo), Some(data)) val parentInfoOpt : Option[ObjectCreateMessageParent] = Some(parentInfo)
ObjectCreateDetailedMessage(ObjectCreateBase.streamLen(parentInfoOpt, data), objectClass, guid, parentInfoOpt, Some(data))
}
/** /**
* An abbreviated constructor for creating `ObjectCreateMessages`, ignoring `parentInfo`. * An abbreviated constructor for creating `ObjectCreateMessages`, ignoring `parentInfo`.
@ -65,8 +67,9 @@ object ObjectCreateDetailedMessage extends Marshallable[ObjectCreateDetailedMess
* @param data the data used to construct this type of object * @param data the data used to construct this type of object
* @return an ObjectCreateMessage * @return an ObjectCreateMessage
*/ */
def apply(objectClass : Int, guid : PlanetSideGUID, data : ConstructorData) : ObjectCreateDetailedMessage = def apply(objectClass : Int, guid : PlanetSideGUID, data : ConstructorData) : ObjectCreateDetailedMessage = {
ObjectCreateDetailedMessage(0L, objectClass, guid, None, Some(data)) ObjectCreateDetailedMessage(ObjectCreateBase.streamLen(None, data), objectClass, guid, None, Some(data))
}
/** /**
* Take the important information of a game piece and transform it into bit data. * Take the important information of a game piece and transform it into bit data.

View file

@ -2,35 +2,33 @@
package net.psforever.packet.game.objectcreate package net.psforever.packet.game.objectcreate
import net.psforever.packet.Marshallable import net.psforever.packet.Marshallable
import net.psforever.types.MeritCommendation
import scodec.Codec import scodec.Codec
import scodec.codecs._ import scodec.codecs._
/** /**
* Enumerate the player-displayed merit commendation awards granted for excellence (or tenacity) in combat. * Enumerate the player-displayed merit commendation awards granted for excellence (or tenacity) in combat.
* These are the medals players wish to brandish on their left pauldron.<br> * These are the medals players wish to brandish on their left pauldron.
* <br>
* All merit commendation ribbons are represented by a 32-bit signature.
* The default "no-ribbon" value is `0xFFFFFFFF`, although some illegal values will also work.
* The term of service ribbon can not be modified by the user and will apply itself to its slot automatically when valid.
* @param upper the "top" configurable merit ribbon * @param upper the "top" configurable merit ribbon
* @param middle the central configurable merit ribbon * @param middle the central configurable merit ribbon
* @param lower the lower configurable merit ribbon * @param lower the lower configurable merit ribbon
* @param tos the top-most term of service merit ribbon * @param tos the top-most term of service merit ribbon
* @see `MeritCommendation`
* @see `DisplayedAwardMessage`
*/ */
final case class RibbonBars(upper : Long = RibbonBars.noRibbon, final case class RibbonBars(upper : MeritCommendation.Value = MeritCommendation.None,
middle : Long = RibbonBars.noRibbon, middle : MeritCommendation.Value = MeritCommendation.None,
lower : Long = RibbonBars.noRibbon, lower : MeritCommendation.Value = MeritCommendation.None,
tos : Long = RibbonBars.noRibbon) extends StreamBitSize { tos : MeritCommendation.Value = MeritCommendation.None
) extends StreamBitSize {
override def bitsize : Long = 128L override def bitsize : Long = 128L
} }
object RibbonBars extends Marshallable[RibbonBars] { object RibbonBars extends Marshallable[RibbonBars] {
val noRibbon : Long = 0xFFFFFFFFL
implicit val codec : Codec[RibbonBars] = ( implicit val codec : Codec[RibbonBars] = (
("upper" | uint32L) :: ("upper" | MeritCommendation.codec) ::
("middle" | uint32L) :: ("middle" | MeritCommendation.codec) ::
("lower" | uint32L) :: ("lower" | MeritCommendation.codec) ::
("tos" | uint32L) ("tos" | MeritCommendation.codec)
).as[RibbonBars] ).as[RibbonBars]
} }

View file

@ -0,0 +1,522 @@
// Copyright (c) 2017 PSForever
package net.psforever.types
import scodec.{Attempt, Err}
import scodec.codecs._
/**
* An `Enumeration` of all merit commendation award categories organized into associated ribbons.
* By astonishing coincidence, with exception of the first ten special awards, the rest of list is in alphabetical order.
*/
object MeritCommendation extends Enumeration {
type Type = Value
val //0
FanFaire2005Commander,
FanFaire2005Soldier,
FanFaire2006Atlanta,
HalloweenMassacre2006NC,
HalloweenMassacre2006TR,
HalloweenMassacre2006VS,
FanFaire2007,
FanFaire2008,
FanFaire2009,
AdvancedMedic1,
//10
AdvancedMedic2,
AdvancedMedic3,
AdvancedMedic4,
AdvancedMedic5,
AdvancedMedic6,
AdvancedMedic7,
AdvancedMedicAssists1,
AdvancedMedicAssists2,
AdvancedMedicAssists3,
AdvancedMedicAssists4,
//20
AdvancedMedicAssists5,
AdvancedMedicAssists6,
AdvancedMedicAssists7,
AirDefender1,
AirDefender2,
AirDefender3,
AirDefender4,
AirDefender5,
AirDefender6,
AirDefender7,
//30
AMSSupport1,
AMSSupport2,
AMSSupport3,
AMSSupport4,
AMSSupport5,
AMSSupport6,
AMSSupport7,
AntiVehicular1,
AntiVehicular2,
AntiVehicular3,
//40
AntiVehicular4,
AntiVehicular5,
AntiVehicular6,
AntiVehicular7,
Avenger1,
Avenger2,
Avenger3,
Avenger4,
Avenger5,
Avenger6,
//50
Avenger7,
AwardColors, //what?
BendingMovieActor,
BFRAdvanced,
BFRAdvanced2,
BFRAdvanced3,
BFRAdvanced4,
BFRAdvanced5,
BFRBuster1,
BFRBuster2,
//60
BFRBuster3,
BFRBuster4,
BFRBuster5,
BFRBuster6,
BFRBuster7,
BlackOpsHunter1,
BlackOpsHunter2,
BlackOpsHunter3,
BlackOpsHunter4,
BlackOpsHunter5,
//70
BlackOpsParticipant,
BlackOpsVictory,
Bombadier1,
Bombadier2,
Bombadier3,
Bombadier4,
Bombadier5,
Bombadier6,
Bombadier7,
BomberAce1,
//80
BomberAce2,
BomberAce3,
BomberAce4,
BomberAce5,
BomberAce6,
BomberAce7,
Boomer1,
Boomer2,
Boomer3,
Boomer4,
//90
Boomer5,
Boomer6,
Boomer7,
CalvaryDriver1,
CalvaryDriver2,
CalvaryDriver3,
CalvaryDriver4,
CalvaryDriver5,
CalvaryDriver6,
CalvaryDriver7,
//100
CalvaryPilot,
CalvaryPilot2,
CalvaryPilot3,
CalvaryPilot4,
CalvaryPilot5,
CalvaryPilot6,
CalvaryPilot7,
CMTopOutfit,
CombatMedic,
CombatMedic2,
//110
CombatMedic3,
CombatMedic4,
CombatMedic5,
CombatMedic6,
CombatMedic7,
CombatRepair1,
CombatRepair2,
CombatRepair3,
CombatRepair4,
CombatRepair5,
//120
CombatRepair6,
CombatRepair7,
ContestFirstBR40,
ContestMovieMaker,
ContestMovieMakerOutfit,
ContestPlayerOfTheMonth,
ContestPlayerOfTheYear,
CSAppreciation,
DefenseNC1,
DefenseNC2,
//130
DefenseNC3,
DefenseNC4,
DefenseNC5,
DefenseNC6,
DefenseNC7,
DefenseTR1,
DefenseTR2,
DefenseTR3,
DefenseTR4,
DefenseTR5,
//40
DefenseTR6,
DefenseTR7,
DefenseVS1,
DefenseVS2,
DefenseVS3,
DefenseVS4,
DefenseVS5,
DefenseVS6,
DefenseVS7,
DevilDogsMovie,
//150
DogFighter1,
DogFighter2,
DogFighter3,
DogFighter4,
DogFighter5,
DogFighter6,
DogFighter7,
DriverGunner1,
DriverGunner2,
DriverGunner3,
//160
DriverGunner4,
DriverGunner5,
DriverGunner6,
DriverGunner7,
EliteAssault0,
EliteAssault1,
EliteAssault2,
EliteAssault3,
EliteAssault4,
EliteAssault5,
//170
EliteAssault6,
EliteAssault7,
EmeraldVeteran,
Engineer1,
Engineer2,
Engineer3,
Engineer4,
Engineer5,
Engineer6,
EquipmentSupport1,
//180
EquipmentSupport2,
EquipmentSupport3,
EquipmentSupport4,
EquipmentSupport5,
EquipmentSupport6,
EquipmentSupport7,
EventNCCommander,
EventNCElite,
EventNCSoldier,
EventTRCommander,
//190
EventTRElite,
EventTRSoldier,
EventVSCommander,
EventVSElite,
EventVSSoldier,
Explorer1,
FiveYearNC,
FiveYearTR,
FiveYearVS,
FourYearNC,
//200
FourYearTR,
FourYearVS,
GalaxySupport1,
GalaxySupport2,
GalaxySupport3,
GalaxySupport4,
GalaxySupport5,
GalaxySupport6,
GalaxySupport7,
Grenade1,
//210
Grenade2,
Grenade3,
Grenade4,
Grenade5,
Grenade6,
Grenade7,
GroundGunner1,
GroundGunner2,
GroundGunner3,
GroundGunner4,
//220
GroundGunner5,
GroundGunner6,
GroundGunner7,
HackingSupport1,
HackingSupport2,
HackingSupport3,
HackingSupport4,
HackingSupport5,
HackingSupport6,
HackingSupport7,
//230
HeavyAssault1,
HeavyAssault2,
HeavyAssault3,
HeavyAssault4,
HeavyAssault5,
HeavyAssault6,
HeavyAssault7,
HeavyInfantry,
HeavyInfantry2,
HeavyInfantry3,
//240
HeavyInfantry4,
InfantryExpert1,
InfantryExpert2,
InfantryExpert3,
Jacking,
Jacking2,
Jacking3,
Jacking4,
Jacking5,
Jacking6,
//250
Jacking7,
KnifeCombat1,
KnifeCombat2,
KnifeCombat3,
KnifeCombat4,
KnifeCombat5,
KnifeCombat6,
KnifeCombat7,
LightInfantry,
LockerCracker1,
//260
LockerCracker2,
LockerCracker3,
LockerCracker4,
LockerCracker5,
LockerCracker6,
LockerCracker7,
LodestarSupport1,
LodestarSupport2,
LodestarSupport3,
LodestarSupport4,
//270
LodestarSupport5,
LodestarSupport6,
LodestarSupport7,
Loser,
Loser2,
Loser3,
Loser4,
MarkovVeteran,
Max1,
Max2,
//280
Max3,
Max4,
Max5,
Max6,
MaxBuster1,
MaxBuster2,
MaxBuster3,
MaxBuster4,
MaxBuster5,
MaxBuster6,
//290
MediumAssault1,
MediumAssault2,
MediumAssault3,
MediumAssault4,
MediumAssault5,
MediumAssault6,
MediumAssault7,
OneYearNC,
OneYearTR,
OneYearVS,
//300
Orion1,
Orion2,
Orion3,
Orion4,
Orion5,
Orion6,
Orion7,
Osprey1,
Osprey2,
Osprey3,
//310
Osprey4,
Osprey5,
Osprey6,
Osprey7,
Phalanx1,
Phalanx2,
Phalanx3,
Phalanx4,
Phalanx5,
Phalanx6,
//320
Phalanx7,
PSUMaAttendee,
PSUMbAttendee,
QAAppreciation,
ReinforcementHackSpecialist,
ReinforcementInfantrySpecialist,
ReinforcementSpecialist,
ReinforcementVehicleSpecialist,
RouterSupport1,
RouterSupport2,
//330
RouterSupport3,
RouterSupport4,
RouterSupport5,
RouterSupport6,
RouterSupport7,
RouterTelepadDeploy1,
RouterTelepadDeploy2,
RouterTelepadDeploy3,
RouterTelepadDeploy4,
RouterTelepadDeploy5,
//340
RouterTelepadDeploy6,
RouterTelepadDeploy7,
ScavengerNC1,
ScavengerNC2,
ScavengerNC3,
ScavengerNC4,
ScavengerNC5,
ScavengerNC6,
ScavengerTR1,
ScavengerTR2,
//350
ScavengerTR3,
ScavengerTR4,
ScavengerTR5,
ScavengerTR6,
ScavengerVS1,
ScavengerVS2,
ScavengerVS3,
ScavengerVS4,
ScavengerVS5,
ScavengerVS6,
//360
SixYearNC,
SixYearTR,
SixYearVS,
Sniper1,
Sniper2,
Sniper3,
Sniper4,
Sniper5,
Sniper6,
Sniper7,
//370
SpecialAssault1,
SpecialAssault2,
SpecialAssault3,
SpecialAssault4,
SpecialAssault5,
SpecialAssault6,
SpecialAssault7,
StandardAssault1,
StandardAssault2,
StandardAssault3,
//380
StandardAssault4,
StandardAssault5,
StandardAssault6,
StandardAssault7,
StracticsHistorian,
Supply1,
Supply2,
Supply3,
Supply4,
Supply5,
//390
Supply6,
Supply7,
TankBuster1,
TankBuster2,
TankBuster3,
TankBuster4,
TankBuster5,
TankBuster6,
TankBuster7,
ThreeYearNC,
//400
ThreeYearTR,
ThreeYearVS,
TinyRoboticSupport1,
TinyRoboticSupport2,
TinyRoboticSupport3,
TinyRoboticSupport4,
TinyRoboticSupport5,
TinyRoboticSupport6,
TinyRoboticSupport7,
Transport1,
//410
Transport2,
Transport3,
Transport4,
Transport5,
Transport6,
Transport7,
TransportationCitation1,
TransportationCitation2,
TransportationCitation3,
TransportationCitation4,
//420
TransportationCitation5,
TwoYearNC,
TwoYearTR,
TwoYearVS,
ValentineFemale,
ValentineMale,
WernerVeteran,
XmasGingerman,
XmasSnowman,
XmasSpirit
= Value
/*
The value None requires special consideration.
- A Long number is required for this Enumeration codec.
- Enumerations are designed to only handle Int numbers.
- A Codec only handles unsigned numbers.
- The value of MeritCommendation.None is intended to be 0xFFFFFFFF, which (a) is 4294967295 as a Long, but (b) is -1 as an Integer.
- Due to (a), an Enumeration can not be used to represent that number.
- Due to (b), a Codec can not be used to convert to that number.
*/
val None = Value(-1)
/**
* Carefully and explicitly convert between `Codec[Long] -> Long -> Int -> MeritCommendation.Value`.
*/
implicit val codec = uint32L.exmap[MeritCommendation.Value] (
{
case 0xFFFFFFFFL =>
Attempt.successful(MeritCommendation.None)
case n =>
if(n > Int.MaxValue) {
Attempt.failure(Err(s"value $n is too high, above maximum integer value ${Int.MaxValue}"))
}
else {
Attempt.successful(MeritCommendation(n.toInt))
}
},
{
case MeritCommendation.None =>
Attempt.successful(0xFFFFFFFFL)
case enum =>
Attempt.successful(enum.id.toLong)
}
)
}

View file

@ -1,6 +1,7 @@
// Copyright (c) 2017 PSForever // Copyright (c) 2017 PSForever
package game package game
import net.psforever.types.MeritCommendation
import org.specs2.mutable._ import org.specs2.mutable._
import net.psforever.packet._ import net.psforever.packet._
import net.psforever.packet.game._ import net.psforever.packet.game._
@ -13,7 +14,7 @@ class DisplayedAwardMessageTest extends Specification {
PacketCoding.DecodePacket(string).require match { PacketCoding.DecodePacket(string).require match {
case DisplayedAwardMessage(player_guid, ribbon, bar) => case DisplayedAwardMessage(player_guid, ribbon, bar) =>
player_guid mustEqual PlanetSideGUID(1695) player_guid mustEqual PlanetSideGUID(1695)
ribbon mustEqual 422L ribbon mustEqual MeritCommendation.TwoYearTR
bar mustEqual RibbonBarsSlot.TermOfService bar mustEqual RibbonBarsSlot.TermOfService
case _ => case _ =>
ko ko
@ -21,7 +22,7 @@ class DisplayedAwardMessageTest extends Specification {
} }
"encode" in { "encode" in {
val msg = DisplayedAwardMessage(PlanetSideGUID(1695), 422L, RibbonBarsSlot.TermOfService) val msg = DisplayedAwardMessage(PlanetSideGUID(1695), MeritCommendation.TwoYearTR, RibbonBarsSlot.TermOfService)
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string pkt mustEqual string

View file

@ -201,10 +201,10 @@ class ObjectCreateDetailedMessageTest extends Specification {
char.appearance.is_cloaking mustEqual false char.appearance.is_cloaking mustEqual false
char.appearance.charging_pose mustEqual false char.appearance.charging_pose mustEqual false
char.appearance.on_zipline mustEqual false char.appearance.on_zipline mustEqual false
char.appearance.ribbons.upper mustEqual 0xFFFFFFFFL //none char.appearance.ribbons.upper mustEqual MeritCommendation.None
char.appearance.ribbons.middle mustEqual 0xFFFFFFFFL //none char.appearance.ribbons.middle mustEqual MeritCommendation.None
char.appearance.ribbons.lower mustEqual 0xFFFFFFFFL //none char.appearance.ribbons.lower mustEqual MeritCommendation.None
char.appearance.ribbons.tos mustEqual 0xFFFFFFFFL //none char.appearance.ribbons.tos mustEqual MeritCommendation.None
char.healthMax mustEqual 100 char.healthMax mustEqual 100
char.health mustEqual 100 char.health mustEqual 100
char.armor mustEqual 50 //standard exosuit value char.armor mustEqual 50 //standard exosuit value

View file

@ -4,7 +4,7 @@ package game
import net.psforever.packet._ import net.psforever.packet._
import net.psforever.packet.game._ import net.psforever.packet.game._
import net.psforever.packet.game.objectcreate._ import net.psforever.packet.game.objectcreate._
import net.psforever.types.{CharacterGender, ExoSuitType, GrenadeState, PlanetSideEmpire, Vector3} import net.psforever.types._
import org.specs2.mutable._ import org.specs2.mutable._
import scodec.bits._ import scodec.bits._
@ -684,10 +684,10 @@ class ObjectCreateMessageTest extends Specification {
pc.appearance.is_cloaking mustEqual false pc.appearance.is_cloaking mustEqual false
pc.appearance.charging_pose mustEqual false pc.appearance.charging_pose mustEqual false
pc.appearance.on_zipline mustEqual false pc.appearance.on_zipline mustEqual false
pc.appearance.ribbons.upper mustEqual 276L pc.appearance.ribbons.upper mustEqual MeritCommendation.Loser4
pc.appearance.ribbons.middle mustEqual 239L pc.appearance.ribbons.middle mustEqual MeritCommendation.HeavyInfantry3
pc.appearance.ribbons.lower mustEqual 397L pc.appearance.ribbons.lower mustEqual MeritCommendation.TankBuster6
pc.appearance.ribbons.tos mustEqual 360L pc.appearance.ribbons.tos mustEqual MeritCommendation.SixYearNC
pc.health mustEqual 255 pc.health mustEqual 255
pc.armor mustEqual 253 pc.armor mustEqual 253
pc.uniform_upgrade mustEqual UniformStyle.ThirdUpgrade pc.uniform_upgrade mustEqual UniformStyle.ThirdUpgrade
@ -780,10 +780,10 @@ class ObjectCreateMessageTest extends Specification {
pc.appearance.is_cloaking mustEqual false pc.appearance.is_cloaking mustEqual false
pc.appearance.charging_pose mustEqual false pc.appearance.charging_pose mustEqual false
pc.appearance.on_zipline mustEqual false pc.appearance.on_zipline mustEqual false
pc.appearance.ribbons.upper mustEqual 244L pc.appearance.ribbons.upper mustEqual MeritCommendation.Jacking
pc.appearance.ribbons.middle mustEqual 353L pc.appearance.ribbons.middle mustEqual MeritCommendation.ScavengerTR6
pc.appearance.ribbons.lower mustEqual 33L pc.appearance.ribbons.lower mustEqual MeritCommendation.AMSSupport4
pc.appearance.ribbons.tos mustEqual 361L pc.appearance.ribbons.tos mustEqual MeritCommendation.SixYearTR
pc.health mustEqual 0 pc.health mustEqual 0
pc.armor mustEqual 0 pc.armor mustEqual 0
pc.uniform_upgrade mustEqual UniformStyle.ThirdUpgrade pc.uniform_upgrade mustEqual UniformStyle.ThirdUpgrade
@ -1107,7 +1107,12 @@ class ObjectCreateMessageTest extends Specification {
false, false,
GrenadeState.None, GrenadeState.None,
false, false, false, false, false, false,
RibbonBars(276L, 239L, 397L, 360L) RibbonBars(
MeritCommendation.Loser4,
MeritCommendation.HeavyInfantry3,
MeritCommendation.TankBuster6,
MeritCommendation.SixYearNC
)
), ),
255, 253, 255, 253,
UniformStyle.ThirdUpgrade, UniformStyle.ThirdUpgrade,
@ -1159,7 +1164,12 @@ class ObjectCreateMessageTest extends Specification {
false, false,
GrenadeState.None, GrenadeState.None,
false, false, false, false, false, false,
RibbonBars(244L, 353L, 33L, 361L) RibbonBars(
MeritCommendation.Jacking,
MeritCommendation.ScavengerTR6,
MeritCommendation.AMSSupport4,
MeritCommendation.SixYearTR
)
), ),
0, 0, 0, 0,
UniformStyle.ThirdUpgrade, UniformStyle.ThirdUpgrade,