Merge pull request #1335 from psforever/empire_benefits_message_packet
Some checks failed
Publish Docs / docs (push) Has been cancelled
Publish Docker Image / docker (push) Has been cancelled
Test / test (push) Has been cancelled

EmpireBenefitsMessage packet
This commit is contained in:
Resaec 2025-12-18 13:27:44 +01:00 committed by GitHub
commit b8ea569b1c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 388 additions and 20 deletions

View file

@ -2924,9 +2924,11 @@ class ZoningOperations(
0 seconds 0 seconds
} else { } else {
//for other zones ... //for other zones ...
//Searhus lock benefit also gives biolab faster respawn
val searhusBenefit = Zones.zones.find(_.Number == 9).exists(_.benefitRecipient == player.Faction)
//biolabs have/grant benefits //biolabs have/grant benefits
val cryoBenefit: Float = toSpawnPoint.Owner match { val cryoBenefit: Float = toSpawnPoint.Owner match {
case b: Building if b.hasLatticeBenefit(LatticeBenefit.BioLaboratory) => 0.5f case b: Building if b.hasLatticeBenefit(LatticeBenefit.BioLaboratory) || (b.BuildingType == StructureType.Facility && !b.CaptureTerminalIsHacked && searhusBenefit) => 0.5f
case _ => 1f case _ => 1f
} }
//TODO cumulative death penalty //TODO cumulative death penalty

View file

@ -5,6 +5,7 @@ import net.psforever.objects.equipment.{Equipment, EquipmentSlot}
import net.psforever.objects.{PlanetSideGameObject, Vehicle} import net.psforever.objects.{PlanetSideGameObject, Vehicle}
import net.psforever.packet.game.objectcreate._ import net.psforever.packet.game.objectcreate._
import net.psforever.types.{DriveState, PlanetSideGUID, VehicleFormat} import net.psforever.types.{DriveState, PlanetSideGUID, VehicleFormat}
import net.psforever.zones.Zones
import scala.util.{Failure, Success, Try} import scala.util.{Failure, Success, Try}
@ -14,6 +15,8 @@ class VehicleConverter extends ObjectCreateConverter[Vehicle]() {
override def ConstructorData(obj: Vehicle): Try[VehicleData] = { override def ConstructorData(obj: Vehicle): Try[VehicleData] = {
val health = StatConverter.Health(obj.Health, obj.MaxHealth) val health = StatConverter.Health(obj.Health, obj.MaxHealth)
val boosted = if (Zones.zones.find(_.Number == 3).exists(_.benefitRecipient == obj.Faction)) true
else false
if (health > 0) { //active if (health > 0) { //active
Success( Success(
VehicleData( VehicleData(
@ -32,7 +35,7 @@ class VehicleConverter extends ObjectCreateConverter[Vehicle]() {
case None => PlanetSideGUID(0) case None => PlanetSideGUID(0)
} }
), ),
unk3 = false, boostMaxHealth = boosted,
health, health,
unk4 = false, unk4 = false,
no_mount_points = false, no_mount_points = false,
@ -59,7 +62,7 @@ class VehicleConverter extends ObjectCreateConverter[Vehicle]() {
v5 = None, v5 = None,
guid = PlanetSideGUID(0) guid = PlanetSideGUID(0)
), ),
unk3 = false, boostMaxHealth = boosted,
health = 0, health = 0,
unk4 = false, unk4 = false,
no_mount_points = true, no_mount_points = true,

View file

@ -10,6 +10,7 @@ import net.psforever.objects.zones.Zone
import net.psforever.services.Service import net.psforever.services.Service
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage} import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
import net.psforever.types.Vector3 import net.psforever.types.Vector3
import net.psforever.zones.Zones
import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._ import scala.concurrent.duration._
@ -44,6 +45,12 @@ class VehicleSpawnControlLoadVehicle(pad: VehicleSpawnPad) extends VehicleSpawnC
) //appear below the trench and doors ) //appear below the trench and doors
vehicle.WhichSide = pad.WhichSide vehicle.WhichSide = pad.WhichSide
vehicle.Cloaked = vehicle.Definition.CanCloak && driver.Cloaked vehicle.Cloaked = vehicle.Definition.CanCloak && driver.Cloaked
// increase MaxHealth by 10% if driver has Cyssor empire armor benefit
if (Zones.zones.find(_.Number == 3).exists(_.benefitRecipient == driver.Faction)) {
val boosted = Math.round(vehicle.MaxHealth * 1.1).toInt
vehicle.MaxHealth = boosted
vehicle.Health = boosted
}
temp = Some(order) temp = Some(order)
val result = ask(pad.Zone.Transport, Zone.Vehicle.Spawn(vehicle)) val result = ask(pad.Zone.Transport, Zone.Vehicle.Spawn(vehicle))

View file

@ -58,7 +58,7 @@ trait RepairableEntity extends Repairable {
*/ */
protected def CanPerformRepairs(target: Repairable.Target, player: Player, item: Tool): Boolean = { protected def CanPerformRepairs(target: Repairable.Target, player: Player, item: Tool): Boolean = {
val definition = target.Definition val definition = target.Definition
definition.Repairable && target.Health < definition.MaxHealth && (definition.RepairIfDestroyed || !target.Destroyed) && definition.Repairable && target.Health < target.MaxHealth && (definition.RepairIfDestroyed || !target.Destroyed) &&
(target.Faction == player.Faction || target.Faction == PlanetSideEmpire.NEUTRAL) && item.Magazine > 0 && (target.Faction == player.Faction || target.Faction == PlanetSideEmpire.NEUTRAL) && item.Magazine > 0 &&
player.isAlive && Vector3.Distance(target.Position, player.Position) < definition.RepairDistance player.isAlive && Vector3.Distance(target.Position, player.Position) < definition.RepairDistance
} }

View file

@ -56,7 +56,8 @@ import net.psforever.objects.vital.interaction.{DamageInteraction, DamageResult}
import net.psforever.objects.vital.prop.DamageWithPosition import net.psforever.objects.vital.prop.DamageWithPosition
import net.psforever.objects.vital.Vitality import net.psforever.objects.vital.Vitality
import net.psforever.objects.zones.blockmap.{BlockMap, SectorPopulation} import net.psforever.objects.zones.blockmap.{BlockMap, SectorPopulation}
import net.psforever.packet.game.PropertyOverrideMessage import net.psforever.packet.game.EmpireBenefitsMessage.{ZoneBenefit, ZoneLock, ZoneLockBenefit, ZoneLockZone}
import net.psforever.packet.game.{EmpireBenefitsMessage, PropertyOverrideMessage}
import net.psforever.services.Service import net.psforever.services.Service
import net.psforever.zones.Zones import net.psforever.zones.Zones
@ -682,11 +683,15 @@ class Zone(val id: String, val map: ZoneMap, zoneNumber: Int) {
if (perks.values.forall(_.isEmpty)) {/*do nothing*/} if (perks.values.forall(_.isEmpty)) {/*do nothing*/}
else { else {
val msg = PropertyOverrideMessage(List(PropertyOverrideMessage.GamePropertyScope(0, List(PropertyOverrideMessage.GamePropertyTarget(343, val overrideMsg = PropertyOverrideMessage(List(PropertyOverrideMessage.GamePropertyScope(0, List(PropertyOverrideMessage.GamePropertyTarget(343,
List(PropertyOverrideMessage.GameProperty("purchase_exempt_vs", perks(PlanetSideEmpire.VS)), List(PropertyOverrideMessage.GameProperty("purchase_exempt_vs", perks(PlanetSideEmpire.VS)),
PropertyOverrideMessage.GameProperty("purchase_exempt_tr", perks(PlanetSideEmpire.TR)), PropertyOverrideMessage.GameProperty("purchase_exempt_tr", perks(PlanetSideEmpire.TR)),
PropertyOverrideMessage.GameProperty("purchase_exempt_nc", perks(PlanetSideEmpire.NC)))))))) PropertyOverrideMessage.GameProperty("purchase_exempt_nc", perks(PlanetSideEmpire.NC))))))))
building.Actor ! BuildingActor.HomeLockBenefits(msg) building.Actor ! BuildingActor.HomeLockBenefits(overrideMsg)
}
val benefitMsg = BuildEmpireBenefits()
if (benefitMsg.zoneLocks.nonEmpty) {
building.Actor ! BuildingActor.HomeLockBenefits(benefitMsg)
} }
} }
@ -716,12 +721,71 @@ class Zone(val id: String, val map: ZoneMap, zoneNumber: Int) {
if (perks.values.forall(_.isEmpty)) {/*do nothing*/} if (perks.values.forall(_.isEmpty)) {/*do nothing*/}
else { else {
val msg = PropertyOverrideMessage(List(PropertyOverrideMessage.GamePropertyScope(0, List(PropertyOverrideMessage.GamePropertyTarget(343, val overrideMsg = PropertyOverrideMessage(List(PropertyOverrideMessage.GamePropertyScope(0, List(PropertyOverrideMessage.GamePropertyTarget(343,
List(PropertyOverrideMessage.GameProperty("purchase_exempt_vs", perks(PlanetSideEmpire.VS)), List(PropertyOverrideMessage.GameProperty("purchase_exempt_vs", perks(PlanetSideEmpire.VS)),
PropertyOverrideMessage.GameProperty("purchase_exempt_tr", perks(PlanetSideEmpire.TR)), PropertyOverrideMessage.GameProperty("purchase_exempt_tr", perks(PlanetSideEmpire.TR)),
PropertyOverrideMessage.GameProperty("purchase_exempt_nc", perks(PlanetSideEmpire.NC)))))))) PropertyOverrideMessage.GameProperty("purchase_exempt_nc", perks(PlanetSideEmpire.NC))))))))
PlayerControl.sendResponse(player.Zone, player.Name, msg) PlayerControl.sendResponse(player.Zone, player.Name, overrideMsg)
} }
val benefitMsg = BuildEmpireBenefits()
if (benefitMsg.zoneLocks.nonEmpty) {
PlayerControl.sendResponse(player.Zone, player.Name, benefitMsg)
}
}
def BuildEmpireBenefits(): EmpireBenefitsMessage = {
val locks = scala.collection.mutable.ArrayBuffer[ZoneLock]()
val benefits = scala.collection.mutable.ArrayBuffer[ZoneBenefit]()
val homeSets: Map[PlanetSideEmpire.Value, Set[Int]] = Map(
PlanetSideEmpire.TR -> Set(1, 2),
PlanetSideEmpire.VS -> Set(5, 6),
PlanetSideEmpire.NC -> Set(7, 10)
)
val benefitOfZones: Map[Int, Int] = Map(
3 -> 6, // Cyssor gives benefit 6 (+10% armor bonus to vehicles)
4 -> 1, // Ishundar gives benefit 1 (vehicle shields)
9 -> 3 // Searhus gives benefit 3 (faster respawn)
)
val homePerkBenefits: Map[PlanetSideEmpire.Value, Int] = Map(
PlanetSideEmpire.TR -> 7,
PlanetSideEmpire.NC -> 8,
PlanetSideEmpire.VS -> 9
)
def isLockedBy(homeSet: Set[Int], empire: PlanetSideEmpire.Value): Boolean =
Zones.zones.filter(z => homeSet.contains(z.Number)).forall(_.benefitRecipient == empire)
// home zone perks
homeSets.foreach { case (owner, set) =>
PlanetSideEmpire.values.filterNot(_ == PlanetSideEmpire.NEUTRAL).foreach { empire =>
if (owner != empire && isLockedBy(set, empire)) {
locks += ZoneLock(empire, s"lock-${owner.toString.toLowerCase}-homes")
benefits += ZoneBenefit(empire, ZoneLockBenefit(homePerkBenefits(owner)))
}
}
}
benefitOfZones.foreach { case (zoneNum, benefitId) =>
Zones.zones.find(_.Number == zoneNum).foreach { z =>
z.benefitRecipient match {
case PlanetSideEmpire.NEUTRAL =>
//nothing
case empire =>
locks += ZoneLock(empire, s"lock-z$zoneNum")
benefits += ZoneBenefit(empire, ZoneLockBenefit(benefitId))
}
}
}
// all four islands together give benefit 4 (vehicle repair)
val islandZones: Set[Int] = Set(29, 30, 31, 32)
val islandBenefit: Int = 4
PlanetSideEmpire.values.filterNot(_ == PlanetSideEmpire.NEUTRAL).foreach { empire =>
if (isLockedBy(islandZones, empire)) {
locks += ZoneLock(empire, ZoneLockZone.i1_i2_i3_i4)
benefits += ZoneBenefit(empire, ZoneLockBenefit(islandBenefit))
}
}
EmpireBenefitsMessage(locks.toVector, benefits.toVector)
} }
} }

View file

@ -557,7 +557,7 @@ object GamePacketOpcode extends Enumeration {
case 0xd4 => game.GenericObjectActionAtPositionMessage.decode case 0xd4 => game.GenericObjectActionAtPositionMessage.decode
case 0xd5 => game.PropertyOverrideMessage.decode case 0xd5 => game.PropertyOverrideMessage.decode
case 0xd6 => game.WarpgateLinkOverrideMessage.decode case 0xd6 => game.WarpgateLinkOverrideMessage.decode
case 0xd7 => noDecoder(EmpireBenefitsMessage) case 0xd7 => game.EmpireBenefitsMessage.decode
// 0xd8 // 0xd8
case 0xd8 => noDecoder(ForceEmpireMessage) case 0xd8 => noDecoder(ForceEmpireMessage)
case 0xd9 => game.BroadcastWarpgateUpdateMessage.decode case 0xd9 => game.BroadcastWarpgateUpdateMessage.decode

View file

@ -0,0 +1,110 @@
// Copyright (c) 2025 PSForever
package net.psforever.packet.game
import net.psforever.packet.game.EmpireBenefitsMessage.{ZoneBenefit, ZoneLock}
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
import net.psforever.types.PlanetSideEmpire
import scodec.Codec
import scodec.codecs._
import scala.language.implicitConversions
/**
* EmpireBenefitsMessage
*
* zoneLocks gives the client information about which empire locks what continent.
* This produces a chat message.
* zoneBenefits tells the client what empire has which benefits enabled.
* This has to match zoneLocks to work properly.
*/
final case class EmpireBenefitsMessage(
zoneLocks: Vector[ZoneLock],
zoneBenefits: Vector[ZoneBenefit]
) extends PlanetSideGamePacket {
type Packet = EmpireBenefitsMessage
def opcode = GamePacketOpcode.EmpireBenefitsMessage
def encode = EmpireBenefitsMessage.encode(this)
}
object EmpireBenefitsMessage extends Marshallable[EmpireBenefitsMessage] {
/**
* ZoneLockZone
*
* Available Types of Zones
*
* These zones can be used to notify the client of a lock.
*/
object ZoneLockZone extends Enumeration {
type Type = String
val i1: ZoneLockZone.Value = Value("lock-i1") // Extinction Continental Lock
val i2: ZoneLockZone.Value = Value("lock-i2") // Ascension Continental Lock
val i3: ZoneLockZone.Value = Value("lock-i3") // Desolation Continental Lock
val i4: ZoneLockZone.Value = Value("lock-i4") // Nexus Continental Lock
val i1_i2_i3_i4: ZoneLockZone.Value = Value("lock-i1-i2-i3-i4") // Oshur Cluster Lock
val z3: ZoneLockZone.Value = Value("lock-z3") // Cyssor Continental Lock
val z4: ZoneLockZone.Value = Value("lock-z4") // Ishundar Continental Lock
val z9: ZoneLockZone.Value = Value("lock-z9") // Searhus Continental Lock
val tr_homes: ZoneLockZone.Value = Value("lock-tr-homes") // TR Home Continent Lock
val nc_homes: ZoneLockZone.Value = Value("lock-nc-homes") // NC Home Continent Lock
val vs_homes: ZoneLockZone.Value = Value("lock-vs-homes") // VS Home Continent Lock
implicit def valueToType(v: ZoneLockZone.Value): Type = v.toString
implicit val codec: Codec[Type] = PacketHelpers.encodedStringAligned(6)
}
/**
* ZoneLockBenefit
*
* Available Types of Benefits
*
* Benefits 0, 2 and 5 are unknown. Benefits for i1 to i4 are unknown and mapped incorrectly here.
*/
object ZoneLockBenefit extends Enumeration {
type Type = Value
val i1: ZoneLockBenefit.Value = Value(-1) // Extinction Continental Lock
val i2: ZoneLockBenefit.Value = Value(-2) // Ascension Continental Lock
val i3: ZoneLockBenefit.Value = Value(-3) // Desolation Continental Lock
val i4: ZoneLockBenefit.Value = Value(-4) // Nexus Continental Lock
// val unk0: ZoneLockBenefit.Value = Value(0)
val z4: ZoneLockBenefit.Value = Value(1) // Ishundar Continental Lock
// val unk2: ZoneLockBenefit.Value = Value(2)
val z9: ZoneLockBenefit.Value = Value(3) // Searhus Continental Lock
val i1_i2_i3_i4: ZoneLockBenefit.Value = Value(4) // Oshur Cluster Lock
// val unk5: ZoneLockBenefit.Value = Value(5)
val z3: ZoneLockBenefit.Value = Value(6) // Cyssor Continental Lock
val tr_homes: ZoneLockBenefit.Value = Value(7) // TR Home Continent Lock
val nc_homes: ZoneLockBenefit.Value = Value(8) // NC Home Continent Lock
val vs_homes: ZoneLockBenefit.Value = Value(9) // VS Home Continent Lock
implicit val codec: Codec[Type] = PacketHelpers.createEnumerationCodec(this, uint16L)
}
final case class ZoneLock(
empire: PlanetSideEmpire.Type,
zone: ZoneLockZone.Type,
)
final case class ZoneBenefit(
empire: PlanetSideEmpire.Type,
value: ZoneLockBenefit.Type
)
private implicit val zoneLockCodec: Codec[ZoneLock] = (
("empire" | PlanetSideEmpire.codec) ::
("zone" | ZoneLockZone.codec)
).as[ZoneLock]
private implicit val zoneBenefitCodec: Codec[ZoneBenefit] = (
("empire" | PlanetSideEmpire.codec) ::
("benefit" | ZoneLockBenefit.codec)
).as[ZoneBenefit]
implicit val codec: Codec[EmpireBenefitsMessage] = (
("zoneLocks" | vectorOfN(uint32L.xmap(_.toInt, _.toLong), zoneLockCodec)) ::
("zoneBenefits" | vectorOfN(uint32L.xmap(_.toInt, _.toLong), zoneBenefitCodec))
).as[EmpireBenefitsMessage]
}

View file

@ -44,7 +44,7 @@ final case class VariantVehicleData(unk: Int) extends SpecificVehicleData(Vehicl
* -jammered - vehicles will not be jammered by setting this field<br> * -jammered - vehicles will not be jammered by setting this field<br>
* -player_guid the vehicle's (official) owner; * -player_guid the vehicle's (official) owner;
* a living player in the game world on the same continent as the vehicle who may mount the driver mount * a living player in the game world on the same continent as the vehicle who may mount the driver mount
* @param unk3 na * @param boostMaxHealth vehicle gets 10% more armor from vehicle armor benefit given by Cyssor empire lock
* @param health the amount of health the vehicle has, as a percentage of a filled bar (255) * @param health the amount of health the vehicle has, as a percentage of a filled bar (255)
* @param unk4 na * @param unk4 na
* @param no_mount_points do not display entry points for the seats * @param no_mount_points do not display entry points for the seats
@ -65,7 +65,7 @@ final case class VariantVehicleData(unk: Int) extends SpecificVehicleData(Vehicl
final case class VehicleData( final case class VehicleData(
pos: PlacementData, pos: PlacementData,
data: CommonFieldData, data: CommonFieldData,
unk3: Boolean, boostMaxHealth: Boolean,
health: Int, health: Int,
unk4: Boolean, unk4: Boolean,
no_mount_points: Boolean, no_mount_points: Boolean,
@ -106,7 +106,7 @@ object VehicleData extends Marshallable[VehicleData] {
cloak: Boolean, cloak: Boolean,
inventory: Option[InventoryData] inventory: Option[InventoryData]
): VehicleData = { ): VehicleData = {
VehicleData(pos, basic, unk3 = false, health, unk4 = false, no_mount_points = false, driveState, unk5 = false, unk6 = false, cloak = cloak, None, inventory)( VehicleData(pos, basic, boostMaxHealth = false, health, unk4 = false, no_mount_points = false, driveState, unk5 = false, unk6 = false, cloak = cloak, None, inventory)(
VehicleFormat.Normal VehicleFormat.Normal
) )
} }
@ -128,7 +128,7 @@ object VehicleData extends Marshallable[VehicleData] {
format: UtilityVehicleData, format: UtilityVehicleData,
inventory: Option[InventoryData] inventory: Option[InventoryData]
): VehicleData = { ): VehicleData = {
VehicleData(pos, basic, unk3 = false, health, unk4 = false, no_mount_points = false, driveState, unk5 = false, unk6 = false, cloak = cloak, Some(format), inventory)( VehicleData(pos, basic, boostMaxHealth = false, health, unk4 = false, no_mount_points = false, driveState, unk5 = false, unk6 = false, cloak = cloak, Some(format), inventory)(
VehicleFormat.Utility VehicleFormat.Utility
) )
} }
@ -150,7 +150,7 @@ object VehicleData extends Marshallable[VehicleData] {
format: VariantVehicleData, format: VariantVehicleData,
inventory: Option[InventoryData] inventory: Option[InventoryData]
): VehicleData = { ): VehicleData = {
VehicleData(pos, basic, unk3 = false, health, unk4 = false, no_mount_points = false, driveState, unk5 = false, unk6 = false, cloak = cloak, Some(format), inventory)( VehicleData(pos, basic, boostMaxHealth = false, health, unk4 = false, no_mount_points = false, driveState, unk5 = false, unk6 = false, cloak = cloak, Some(format), inventory)(
VehicleFormat.Variant VehicleFormat.Variant
) )
} }

View file

@ -0,0 +1,182 @@
// Copyright (c) 2025 PSForever
package game
import net.psforever.packet._
import net.psforever.packet.game.EmpireBenefitsMessage
import net.psforever.packet.game.EmpireBenefitsMessage.{ZoneBenefit, ZoneLock, ZoneLockBenefit, ZoneLockZone}
import net.psforever.types.PlanetSideEmpire
import org.specs2.mutable._
import scodec.bits._
class EmpireBenefitsMessageTest extends Specification {
val sample1: ByteVector = ByteVector.fromValidHex(
"d7" + // header
"04000000" + // count uint32L
"21c06c6f636b2d7a3321c06c6f636b2d7a3464006c6f636b2d69312d69322d69332d6934a1c06c6f636b2d7a39" +
"04000000" + // count uint32L
"004000600410020300"
)
val sample2: ByteVector = ByteVector.fromValidHex(
"d7" +
"05000000 23406c6f636b2d76732d686f6d657321c06c6f636b2d7a3321c06c6f636b2d7a3461c06c6f636b2d7a3964006c6f636b2d69312d69322d69332d6934" +
"05000000 004000600024010300410000"
)
val sample3: ByteVector = ByteVector.fromValidHex(
"d7" +
"05000000 21c06c6f636b2d7a3321c06c6f636b2d7a3423406c6f636b2d6e632d686f6d657361c06c6f636b2d7a39a4006c6f636b2d69312d69322d69332d6934" +
"05000000 004000600020010300810000"
)
val sample4: ByteVector = ByteVector.fromValidHex(
"d7" +
"06000000 a3406c6f636b2d6e632d686f6d6573a3406c6f636b2d74722d686f6d6573a1c06c6f636b2d7a33a1c06c6f636b2d7a34a1c06c6f636b2d7a39a4006c6f636b2d69312d69322d69332d6934" +
"06000000 80402030081002060081c0208000"
)
private val sample1_expectedLocks = Vector(
ZoneLock(PlanetSideEmpire.TR, ZoneLockZone.z3),
ZoneLock(PlanetSideEmpire.TR, ZoneLockZone.z4),
ZoneLock(PlanetSideEmpire.NC, ZoneLockZone.i1_i2_i3_i4),
ZoneLock(PlanetSideEmpire.VS, ZoneLockZone.z9)
)
private val sample1_expectedBenefits = Vector(
ZoneBenefit(PlanetSideEmpire.TR, ZoneLockBenefit.z4),
ZoneBenefit(PlanetSideEmpire.TR, ZoneLockBenefit.z3),
ZoneBenefit(PlanetSideEmpire.NC, ZoneLockBenefit.i1_i2_i3_i4),
ZoneBenefit(PlanetSideEmpire.VS, ZoneLockBenefit.z9)
)
private val sample2_expectedLocks = Vector(
ZoneLock(PlanetSideEmpire.TR, ZoneLockZone.vs_homes),
ZoneLock(PlanetSideEmpire.TR, ZoneLockZone.z3),
ZoneLock(PlanetSideEmpire.TR, ZoneLockZone.z4),
ZoneLock(PlanetSideEmpire.NC, ZoneLockZone.z9),
ZoneLock(PlanetSideEmpire.NC, ZoneLockZone.i1_i2_i3_i4)
)
private val sample2_expectedBenefits = Vector(
ZoneBenefit(PlanetSideEmpire.TR, ZoneLockBenefit.z4),
ZoneBenefit(PlanetSideEmpire.TR, ZoneLockBenefit.z3),
ZoneBenefit(PlanetSideEmpire.TR, ZoneLockBenefit.vs_homes),
ZoneBenefit(PlanetSideEmpire.NC, ZoneLockBenefit.z9),
ZoneBenefit(PlanetSideEmpire.NC, ZoneLockBenefit.i1_i2_i3_i4)
)
private val sample3_expectedLocks = Vector(
ZoneLock(PlanetSideEmpire.TR, ZoneLockZone.z3),
ZoneLock(PlanetSideEmpire.TR, ZoneLockZone.z4),
ZoneLock(PlanetSideEmpire.TR, ZoneLockZone.nc_homes),
ZoneLock(PlanetSideEmpire.NC, ZoneLockZone.z9),
ZoneLock(PlanetSideEmpire.VS, ZoneLockZone.i1_i2_i3_i4)
)
private val sample3_expectedBenefits = Vector(
ZoneBenefit(PlanetSideEmpire.TR, ZoneLockBenefit.z4),
ZoneBenefit(PlanetSideEmpire.TR, ZoneLockBenefit.z3),
ZoneBenefit(PlanetSideEmpire.TR, ZoneLockBenefit.nc_homes),
ZoneBenefit(PlanetSideEmpire.NC, ZoneLockBenefit.z9),
ZoneBenefit(PlanetSideEmpire.VS, ZoneLockBenefit.i1_i2_i3_i4)
)
private val sample4_expectedLocks = Vector(
ZoneLock(PlanetSideEmpire.VS, ZoneLockZone.nc_homes),
ZoneLock(PlanetSideEmpire.VS, ZoneLockZone.tr_homes),
ZoneLock(PlanetSideEmpire.VS, ZoneLockZone.z3),
ZoneLock(PlanetSideEmpire.VS, ZoneLockZone.z4),
ZoneLock(PlanetSideEmpire.VS, ZoneLockZone.z9),
ZoneLock(PlanetSideEmpire.VS, ZoneLockZone.i1_i2_i3_i4)
)
private val sample4_expectedBenefits = Vector(
ZoneBenefit(PlanetSideEmpire.VS, ZoneLockBenefit.z4),
ZoneBenefit(PlanetSideEmpire.VS, ZoneLockBenefit.z9),
ZoneBenefit(PlanetSideEmpire.VS, ZoneLockBenefit.i1_i2_i3_i4),
ZoneBenefit(PlanetSideEmpire.VS, ZoneLockBenefit.z3),
ZoneBenefit(PlanetSideEmpire.VS, ZoneLockBenefit.tr_homes),
ZoneBenefit(PlanetSideEmpire.VS, ZoneLockBenefit.nc_homes)
)
"decode sample1" in {
PacketCoding.decodePacket(sample1).require match {
case EmpireBenefitsMessage(a, b) =>
a mustEqual sample1_expectedLocks
b mustEqual sample1_expectedBenefits
case _ =>
ko
}
}
"encode sample1" in {
val msg = EmpireBenefitsMessage(
zoneLocks = sample1_expectedLocks,
zoneBenefits = sample1_expectedBenefits
)
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
pkt mustEqual sample1
}
"decode sample2" in {
PacketCoding.decodePacket(sample2).require match {
case EmpireBenefitsMessage(a, b) =>
a mustEqual sample2_expectedLocks
b mustEqual sample2_expectedBenefits
case _ =>
ko
}
}
"encode sample2" in {
val msg = EmpireBenefitsMessage(
zoneLocks = sample2_expectedLocks,
zoneBenefits = sample2_expectedBenefits
)
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
pkt mustEqual sample2
}
"decode sample3" in {
PacketCoding.decodePacket(sample3).require match {
case EmpireBenefitsMessage(a, b) =>
a mustEqual sample3_expectedLocks
b mustEqual sample3_expectedBenefits
case _ =>
ko
}
}
"encode sample3" in {
val msg = EmpireBenefitsMessage(
zoneLocks = sample3_expectedLocks,
zoneBenefits = sample3_expectedBenefits
)
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
pkt mustEqual sample3
}
"decode sample4" in {
PacketCoding.decodePacket(sample4).require match {
case EmpireBenefitsMessage(a, b) =>
a mustEqual sample4_expectedLocks
b mustEqual sample4_expectedBenefits
case _ =>
ko
}
}
"encode sample4" in {
val msg = EmpireBenefitsMessage(
zoneLocks = sample4_expectedLocks,
zoneBenefits = sample4_expectedBenefits
)
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
pkt mustEqual sample4
}
}

View file

@ -39,7 +39,7 @@ class MountedVehiclesTest extends Specification {
vdata.no_mount_points mustEqual false vdata.no_mount_points mustEqual false
vdata.driveState mustEqual DriveState.Mobile vdata.driveState mustEqual DriveState.Mobile
vdata.cloak mustEqual false vdata.cloak mustEqual false
vdata.unk3 mustEqual false vdata.boostMaxHealth mustEqual false
vdata.unk4 mustEqual false vdata.unk4 mustEqual false
vdata.unk5 mustEqual false vdata.unk5 mustEqual false
vdata.unk6 mustEqual false vdata.unk6 mustEqual false

View file

@ -36,7 +36,7 @@ class UtilityVehiclesTest extends Specification {
ant.driveState mustEqual DriveState.Mobile ant.driveState mustEqual DriveState.Mobile
ant.health mustEqual 255 ant.health mustEqual 255
ant.cloak mustEqual false ant.cloak mustEqual false
ant.unk3 mustEqual false ant.boostMaxHealth mustEqual false
ant.unk4 mustEqual false ant.unk4 mustEqual false
ant.unk5 mustEqual false ant.unk5 mustEqual false
ant.unk6 mustEqual false ant.unk6 mustEqual false
@ -67,7 +67,7 @@ class UtilityVehiclesTest extends Specification {
ams.vehicle_format_data mustEqual Some(UtilityVehicleData(60)) ams.vehicle_format_data mustEqual Some(UtilityVehicleData(60))
ams.health mustEqual 236 ams.health mustEqual 236
ams.cloak mustEqual true ams.cloak mustEqual true
ams.unk3 mustEqual false ams.boostMaxHealth mustEqual false
ams.unk4 mustEqual false ams.unk4 mustEqual false
ams.unk5 mustEqual false ams.unk5 mustEqual false
ams.unk6 mustEqual true ams.unk6 mustEqual true
@ -120,7 +120,7 @@ class UtilityVehiclesTest extends Specification {
case _ => case _ =>
ko ko
} }
ams.unk3 mustEqual false ams.boostMaxHealth mustEqual false
ams.health mustEqual 255 ams.health mustEqual 255
ams.unk4 mustEqual false ams.unk4 mustEqual false
ams.no_mount_points mustEqual false ams.no_mount_points mustEqual false
@ -320,7 +320,7 @@ class UtilityVehiclesTest extends Specification {
Some(Vector3(27.3375f, -0.78749996f, 0.1125f)) Some(Vector3(27.3375f, -0.78749996f, 0.1125f))
), ),
CommonFieldData(PlanetSideEmpire.TR, false, false, false, None, false, Some(false), None, PlanetSideGUID(3087)), CommonFieldData(PlanetSideEmpire.TR, false, false, false, None, false, Some(false), None, PlanetSideGUID(3087)),
unk3 = false, boostMaxHealth = false,
health = 255, health = 255,
unk4 = false, unk4 = false,
no_mount_points = false, no_mount_points = false,