mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-20 02:24:45 +00:00
attempting to fix BR24+ characters
This commit is contained in:
parent
349ec676d9
commit
47adfef5c8
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in a new issue