Merge pull request #1336 from ScrawnyRonnie/empire_benefits_message_packet

Global Domination Has Its Perks
This commit is contained in:
Resaec 2025-12-17 02:51:37 +00:00 committed by GitHub
commit 3c074bbd70
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 90 additions and 14 deletions

View file

@ -2924,9 +2924,11 @@ class ZoningOperations(
0 seconds
} else {
//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
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
}
//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.packet.game.objectcreate._
import net.psforever.types.{DriveState, PlanetSideGUID, VehicleFormat}
import net.psforever.zones.Zones
import scala.util.{Failure, Success, Try}
@ -14,6 +15,8 @@ class VehicleConverter extends ObjectCreateConverter[Vehicle]() {
override def ConstructorData(obj: Vehicle): Try[VehicleData] = {
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
Success(
VehicleData(
@ -32,7 +35,7 @@ class VehicleConverter extends ObjectCreateConverter[Vehicle]() {
case None => PlanetSideGUID(0)
}
),
unk3 = false,
boostMaxHealth = boosted,
health,
unk4 = false,
no_mount_points = false,
@ -59,7 +62,7 @@ class VehicleConverter extends ObjectCreateConverter[Vehicle]() {
v5 = None,
guid = PlanetSideGUID(0)
),
unk3 = false,
boostMaxHealth = boosted,
health = 0,
unk4 = false,
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.vehicle.{VehicleAction, VehicleServiceMessage}
import net.psforever.types.Vector3
import net.psforever.zones.Zones
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
@ -44,6 +45,12 @@ class VehicleSpawnControlLoadVehicle(pad: VehicleSpawnPad) extends VehicleSpawnC
) //appear below the trench and doors
vehicle.WhichSide = pad.WhichSide
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)
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 = {
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 &&
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.Vitality
import net.psforever.objects.zones.blockmap.{BlockMap, SectorPopulation}
import net.psforever.packet.game.PropertyOverrideMessage
import net.psforever.packet.game.EmpireBenefitsMessage.{ZoneBenefits, ZoneLocks}
import net.psforever.packet.game.{EmpireBenefitsMessage, PropertyOverrideMessage}
import net.psforever.services.Service
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*/}
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)),
PropertyOverrideMessage.GameProperty("purchase_exempt_tr", perks(PlanetSideEmpire.TR)),
PropertyOverrideMessage.GameProperty("purchase_exempt_nc", perks(PlanetSideEmpire.NC))))))))
building.Actor ! BuildingActor.HomeLockBenefits(msg)
building.Actor ! BuildingActor.HomeLockBenefits(overrideMsg)
}
val benefitMsg = BuildEmpireBenefits()
if (benefitMsg.entriesA.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*/}
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)),
PropertyOverrideMessage.GameProperty("purchase_exempt_tr", perks(PlanetSideEmpire.TR)),
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.entriesA.nonEmpty) {
PlayerControl.sendResponse(player.Zone, player.Name, benefitMsg)
}
}
def BuildEmpireBenefits(): EmpireBenefitsMessage = {
val locks = scala.collection.mutable.ArrayBuffer[ZoneLocks]()
val benefits = scala.collection.mutable.ArrayBuffer[ZoneBenefits]()
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 += ZoneLocks(empire.id, s"lock-${owner.toString.toLowerCase}-homes")
benefits += ZoneBenefits(empire.id, homePerkBenefits(owner))
}
}
}
benefitOfZones.foreach { case (zoneNum, benefitId) =>
Zones.zones.find(_.Number == zoneNum).foreach { z =>
z.benefitRecipient match {
case PlanetSideEmpire.NEUTRAL =>
//nothing
case empire =>
locks += ZoneLocks(empire.id, s"lock-z$zoneNum")
benefits += ZoneBenefits(empire.id, 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 += ZoneLocks(empire.id, "lock-i1-i2-i3-i4")
benefits += ZoneBenefits(empire.id, islandBenefit)
}
}
EmpireBenefitsMessage(locks.toVector, benefits.toVector)
}
}

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>
* -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
* @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 unk4 na
* @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(
pos: PlacementData,
data: CommonFieldData,
unk3: Boolean,
boostMaxHealth: Boolean,
health: Int,
unk4: Boolean,
no_mount_points: Boolean,
@ -106,7 +106,7 @@ object VehicleData extends Marshallable[VehicleData] {
cloak: Boolean,
inventory: Option[InventoryData]
): 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
)
}
@ -128,7 +128,7 @@ object VehicleData extends Marshallable[VehicleData] {
format: UtilityVehicleData,
inventory: Option[InventoryData]
): 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
)
}
@ -150,7 +150,7 @@ object VehicleData extends Marshallable[VehicleData] {
format: VariantVehicleData,
inventory: Option[InventoryData]
): 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
)
}