attempting to fix BR24+ characters

This commit is contained in:
FateJH 2017-10-15 23:01:48 -04:00
parent 349ec676d9
commit 47adfef5c8
6 changed files with 201 additions and 21 deletions

View file

@ -13,8 +13,8 @@ import scala.collection.mutable
class Player(private val name : String,
private val faction : PlanetSideEmpire.Value,
private val sex : CharacterGender.Value,
private val voice : Int,
private val head : Int
private val head : Int,
private val voice : Int
) extends PlanetSideGameObject {
private var alive : Boolean = false
private var backpack : Boolean = false
@ -521,11 +521,11 @@ object Player {
final val FreeHandSlot : Int = 250
final val HandsDownSlot : Int = 255
def apply(name : String, faction : PlanetSideEmpire.Value, sex : CharacterGender.Value, voice : Int, head : Int) : Player = {
new Player(name, faction, sex, voice, head)
def apply(name : String, faction : PlanetSideEmpire.Value, sex : CharacterGender.Value, head : Int, voice : Int) : Player = {
new Player(name, faction, sex, head, voice)
}
def apply(guid : PlanetSideGUID, name : String, faction : PlanetSideEmpire.Value, sex : CharacterGender.Value, voice : Int, head : Int) : Player = {
def apply(guid : PlanetSideGUID, name : String, faction : PlanetSideEmpire.Value, sex : CharacterGender.Value, head : Int, voice : Int) : Player = {
val obj = new Player(name, faction, sex, voice, head)
obj.GUID = guid
obj

View file

@ -40,7 +40,7 @@ class AvatarConverter extends ObjectCreateConverter[Player]() {
obj.Stamina,
obj.Certifications.toList.sortBy(_.id), //TODO is sorting necessary?
MakeImplantEntries(obj),
List.empty[String], //TODO fte list
"xpe_battle_rank_10" :: Nil, //TODO fte list
List.empty[String], //TODO tutorial list
InventoryData((MakeHolsters(obj, BuildDetailedEquipment) ++ MakeFifthSlot(obj) ++ MakeInventory(obj)).sortBy(_.parentSlot)),
GetDrawnSlot(obj)
@ -56,7 +56,7 @@ class AvatarConverter extends ObjectCreateConverter[Player]() {
private def MakeAppearanceData(obj : Player) : CharacterAppearanceData = {
CharacterAppearanceData(
PlacementData(obj.Position, obj.Orientation, obj.Velocity),
BasicCharacterData(obj.Name, obj.Faction, obj.Sex, obj.Voice, obj.Head),
BasicCharacterData(obj.Name, obj.Faction, obj.Sex, obj.Head, obj.Voice),
0,
false,
false,
@ -132,7 +132,10 @@ class AvatarConverter extends ObjectCreateConverter[Player]() {
* @see `ImplantEntry` in `DetailedCharacterData`
*/
private def MakeImplantEntries(obj : Player) : List[ImplantEntry] = {
obj.Implants.map(slot => {
val numImplants : Int = NumberOfImplantSlots(obj.BEP)
val implants = obj.Implants
(0 until numImplants).map(index => {
val slot = implants(index)
slot.Installed match {
case Some(_) =>
if(slot.Initialized) {
@ -147,6 +150,27 @@ class AvatarConverter extends ObjectCreateConverter[Player]() {
}).toList
}
/**
* A player's battle rank, determined by their battle experience points, determines how many implants to which they have access.
* Starting with "no implants" at BR1, a player earns one at each of the three ranks: BR6, BR12, and BR18.
* @param bep battle experience points
* @return the number of accessible implant slots
*/
private def NumberOfImplantSlots(bep : Long) : Int = {
if(bep > 754370) { //BR18+
3
}
else if(bep > 197753) { //BR12+
2
}
else if(bep > 29999) { //BR6+
1
}
else { //BR1+
0
}
}
/**
* Find an active implant whose effect will be displayed on this player.
* @param iter an `Iterator` of `ImplantSlot` objects

View file

@ -0,0 +1,144 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.definition.converter
import net.psforever.objects.GlobalDefinitions.{advanced_regen, darklight_vision, personal_shield, surge}
import net.psforever.objects.{EquipmentSlot, GlobalDefinitions, ImplantSlot, Player}
import net.psforever.objects.equipment.Equipment
import net.psforever.packet.game.objectcreate.{BasicCharacterData, CharacterAppearanceData, CharacterData, DetailedCharacterData, DrawnSlot, ImplantEffects, ImplantEntry, InternalSlot, InventoryData, PlacementData, RibbonBars}
import net.psforever.types.{GrenadeState, ImplantType}
import scala.annotation.tailrec
import scala.util.{Failure, Success, Try}
/**
* `CharacterSelectConverter` is based on `AvatarConverter`
* but it is tailored for appearance of the player character on the character selection screen only.
* Details that would not be apparent on that screen such as implants or certifications are ignored.
*/
class CharacterSelectConverter extends ObjectCreateConverter[Player]() {
override def ConstructorData(obj : Player) : Try[CharacterData] = Failure(new Exception("CharacterSelectConverter should not be used to generate CharacterData"))
override def DetailedConstructorData(obj : Player) : Try[DetailedCharacterData] = {
Success(
DetailedCharacterData(
MakeAppearanceData(obj),
obj.BEP,
obj.CEP,
1, 1, 0, 1, 1,
Nil,
MakeImplantEntries(obj),
Nil, Nil,
InventoryData(recursiveMakeHolsters(obj.Holsters().iterator)),
GetDrawnSlot(obj)
)
)
}
/**
* Compose some data from a `Player` into a representation common to both `CharacterData` and `DetailedCharacterData`.
* @param obj the `Player` game object
* @see `AvatarConverter.MakeAppearanceData`
* @return the resulting `CharacterAppearanceData`
*/
private def MakeAppearanceData(obj : Player) : CharacterAppearanceData = {
CharacterAppearanceData(
PlacementData(0f, 0f, 0f),
BasicCharacterData(obj.Name, obj.Faction, obj.Sex, obj.Head, 1),
0,
false,
false,
obj.ExoSuit,
"",
0,
false,
0f,
0f,
true,
GrenadeState.None,
false,
false,
false,
RibbonBars()
)
}
/**
* Transform an `Array` of `Implant` objects into a `List` of `ImplantEntry` objects suitable as packet data.
* @param obj the `Player` game object
* @return the resulting implant `List`
* @see `ImplantEntry` in `DetailedCharacterData`
*/
private def MakeImplantEntries(obj : Player) : List[ImplantEntry] = {
List.fill[ImplantEntry](NumberOfImplantSlots(obj.BEP))(ImplantEntry(ImplantType.None, None))
}
/**
* A player's battle rank, determined by their battle experience points, determines how many implants to which they have access.
* Starting with "no implants" at BR1, a player earns one at each of the three ranks: BR6, BR12, and BR18.
* @param bep battle experience points
* @return the number of accessible implant slots
*/
private def NumberOfImplantSlots(bep : Long) : Int = {
if(bep > 754370) { //BR18+
3
}
else if(bep > 197753) { //BR12+
2
}
else if(bep > 29999) { //BR6+
1
}
else { //BR1+
0
}
}
/**
* A builder method for turning an object into `0x18` decoded packet form.
* @param index the position of the object
* @param equip the game object
* @see `AvatarConverter.BuildDetailedEquipment`
* @return the game object in decoded packet form
*/
private def BuildDetailedEquipment(index : Int, equip : Equipment) : InternalSlot = {
InternalSlot(equip.Definition.ObjectId, equip.GUID, index, equip.Definition.Packet.DetailedConstructorData(equip).get)
}
/**
* Given some equipment holsters, convert the contents of those holsters into converted-decoded packet data.
* @param iter an `Iterator` of `EquipmentSlot` objects that are a part of the player's holsters
* @param list the current `List` of transformed data
* @param index which holster is currently being explored
* @see `AvatarConverter.recursiveMakeHolsters`
* @return the `List` of inventory data created from the holsters
*/
@tailrec private def recursiveMakeHolsters(iter : Iterator[EquipmentSlot], list : List[InternalSlot] = Nil, index : Int = 0) : List[InternalSlot] = {
if(!iter.hasNext) {
list
}
else {
val slot : EquipmentSlot = iter.next
if(slot.Equipment.isDefined) {
val equip : Equipment = slot.Equipment.get
recursiveMakeHolsters(
iter,
list :+ BuildDetailedEquipment(index, equip),
index + 1
)
}
else {
recursiveMakeHolsters(iter, list, index + 1)
}
}
}
/**
* Resolve which holster the player has drawn, if any.
* @param obj the `Player` game object
* @see `AvatarConverter.GetDrawnSlot`
* @return the holster's Enumeration value
*/
private def GetDrawnSlot(obj : Player) : DrawnSlot.Value = {
try { DrawnSlot(obj.DrawnSlot) } catch { case _ : Exception => DrawnSlot.None }
}
}

View file

@ -209,7 +209,7 @@ object DetailedCharacterData extends Marshallable[DetailedCharacterData] {
implantOffset += entry.bitsize.toInt
})
val resultB : Int = resultA - (implantOffset % 8)
if(resultB < 0) { 8 - resultB } else { resultB }
if(resultB < 0) { 8 + resultB } else { resultB }
}
/**
@ -297,8 +297,8 @@ object DetailedCharacterData extends Marshallable[DetailedCharacterData] {
(("tutorial_length" | uint32L) >>:~ { len2 =>
conditional(len2 > 0, "tutorial_firstEntry" | PacketHelpers.encodedStringAligned(tutPadding(len, len2, implantFieldPadding(implants, CharacterAppearanceData.altModelBit(app))))) ::
("tutorial_list" | PacketHelpers.listOfNSized(len2 - 1, PacketHelpers.encodedString)) ::
ignore(207) ::
optional(bool, "inventory" | InventoryData.codec_detailed) ::
ignore(200) ::
conditional(true, "inventory" | InventoryData.codec_detailed) ::
("drawn_slot" | DrawnSlot.codec) ::
bool //usually false
})

View file

@ -23,7 +23,9 @@ import scodec.codecs._
*/
object ImplantType extends Enumeration {
type Type = Value
val AdvancedRegen,
val
AdvancedRegen,
Targeting,
AudioAmplifier,
DarklightVision,

File diff suppressed because one or more lines are too long