added an Enumeration of certifications

This commit is contained in:
FateJH 2017-09-06 08:26:28 -04:00
parent db8d3fc7ca
commit 69af5124ba
5 changed files with 166 additions and 64 deletions

View file

@ -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

View file

@ -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 =>

View file

@ -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.<br>
* <br>
* 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.<br>
* <br>
* 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)
}

View file

@ -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)

File diff suppressed because one or more lines are too long