mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-19 18:44:45 +00:00
cavern lock benefits, faster capturebase all checkpoint
This commit is contained in:
parent
5b9e0ec384
commit
3f1efefc20
|
|
@ -45,6 +45,13 @@ class GalaxyHandlerLogic(val ops: SessionGalaxyHandlers, implicit val context: A
|
|||
|
||||
case GalaxyResponse.MapUpdate(msg) =>
|
||||
sendResponse(msg)
|
||||
import net.psforever.actors.zone.ZoneActor
|
||||
import net.psforever.zones.Zones
|
||||
Zones.zones.find(_.Number == msg.continent_id) match {
|
||||
case Some(zone) =>
|
||||
zone.actor ! ZoneActor.BuildingInfoState(msg)
|
||||
case None =>
|
||||
}
|
||||
|
||||
case GalaxyResponse.UpdateBroadcastPrivileges(zoneId, gateMapId, fromFactions, toFactions) =>
|
||||
val faction = player.Faction
|
||||
|
|
|
|||
|
|
@ -368,7 +368,8 @@ class ChatOperations(
|
|||
case (Some(buildings), Some(faction), Some(_)) =>
|
||||
//TODO implement timer
|
||||
//schedule processing of buildings with a delay
|
||||
processBuildingsWithDelay(buildings, faction, 1000) { zone =>
|
||||
processBuildingsWithDelay(buildings, faction, 100) { zone =>
|
||||
zone.actor ! ZoneActor.ZoneMapUpdate()
|
||||
zone.actor ! ZoneActor.AssignLockedBy(zone, notifyPlayers=true)
|
||||
}
|
||||
true
|
||||
|
|
@ -382,6 +383,7 @@ class ChatOperations(
|
|||
faction: PlanetSideEmpire.Value,
|
||||
delayMillis: Long
|
||||
)(onComplete: Zone => Unit): Unit = {
|
||||
import net.psforever.objects.serverobject.structures.StructureType
|
||||
val buildingsToProcess = buildings.filter(b => b.CaptureTerminal.isDefined && b.Faction != faction)
|
||||
val iterator = buildingsToProcess.iterator
|
||||
val zone = buildings.head.Zone
|
||||
|
|
@ -391,18 +393,23 @@ class ChatOperations(
|
|||
if (iterator.hasNext) {
|
||||
val building = iterator.next()
|
||||
val terminal = building.CaptureTerminal.get
|
||||
val zoneActor = zone.actor
|
||||
if (building.CaptureTerminalIsHacked) {
|
||||
zone.LocalEvents ! LocalServiceMessage(
|
||||
zone.id,
|
||||
LocalAction.ResecureCaptureTerminal(terminal, PlayerSource.Nobody)
|
||||
)
|
||||
if (building.BuildingType == StructureType.Tower) {
|
||||
building.Actor ! BuildingActor.SetFaction(faction)
|
||||
building.Actor ! BuildingActor.AmenityStateChange(terminal, Some(false))
|
||||
building.Actor ! BuildingActor.MapUpdate()
|
||||
}
|
||||
zoneActor ! ZoneActor.ZoneMapUpdate()
|
||||
building.Actor ! BuildingActor.SetFaction(faction)
|
||||
building.Actor ! BuildingActor.AmenityStateChange(terminal, Some(false))
|
||||
zoneActor ! ZoneActor.ZoneMapUpdate()
|
||||
} else {
|
||||
else {
|
||||
if (building.CaptureTerminalIsHacked) {
|
||||
zone.LocalEvents ! LocalServiceMessage(
|
||||
zone.id,
|
||||
LocalAction.ResecureCaptureTerminal(terminal, PlayerSource.Nobody)
|
||||
)
|
||||
}
|
||||
building.Actor ! BuildingActor.SetFaction(faction)
|
||||
building.Actor ! BuildingActor.AmenityStateChange(terminal, Some(false))
|
||||
}
|
||||
}
|
||||
else {
|
||||
handle.cancel(false)
|
||||
onComplete(zone)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -342,6 +342,13 @@ class ZoningOperations(
|
|||
sendResponse(PlanetsideAttributeMessage(targetPlayer.GUID, 19, 1))
|
||||
}
|
||||
}
|
||||
//adjust for health module benefit so overhead health bar accounts for added health
|
||||
live.filter { tplayer =>
|
||||
tplayer.MaxHealth == 120
|
||||
}
|
||||
.foreach { targetPlayer =>
|
||||
sendResponse(PlanetsideAttributeMessage(targetPlayer.GUID, 1, 120))
|
||||
}
|
||||
//load corpses in zone
|
||||
continent.Corpses.foreach {
|
||||
spawn.DepictPlayerAsCorpse
|
||||
|
|
@ -2943,16 +2950,40 @@ 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) && b.virusId != 1) ||
|
||||
(b.BuildingType == StructureType.Facility && !b.CaptureTerminalIsHacked && searhusBenefit) => 0.5f
|
||||
case _ => 1f
|
||||
val spawnTimeBenefit: Float = toSpawnPoint.Owner match {
|
||||
case b: Building => FasterRespawnBenefits(b)
|
||||
case _ => 1f
|
||||
}
|
||||
//TODO cumulative death penalty
|
||||
(toSpawnPoint.Definition.Delay.toFloat * cryoBenefit).seconds
|
||||
(toSpawnPoint.Definition.Delay.toFloat * spawnTimeBenefit).seconds
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiple benefits can be given to an empire based on global ownership of certain zones or facility types that
|
||||
* are linked to the facility being spawned at.
|
||||
* @return float to potentially lower the respawn time if benefits are available
|
||||
*/
|
||||
def FasterRespawnBenefits(building: Building): Float = {
|
||||
//Searhus lock benefit also gives biolab faster respawn
|
||||
val searhusBenefit = Zones.zones.find(_.Number == 9).exists(_.benefitRecipient == player.Faction)
|
||||
building match {
|
||||
case b: Building
|
||||
if (b.hasLatticeBenefit(LatticeBenefit.BioLaboratory) && b.virusId != 1 &&
|
||||
b.hasCavernLockBenefit) ||
|
||||
(b.BuildingType == StructureType.Facility && !b.CaptureTerminalIsHacked &&
|
||||
searhusBenefit && b.hasCavernLockBenefit) =>
|
||||
0.3f
|
||||
case b: Building
|
||||
if !b.CaptureTerminalIsHacked && b.hasCavernLockBenefit && b.virusId != 1 =>
|
||||
0.5f
|
||||
case b: Building
|
||||
if (b.hasLatticeBenefit(LatticeBenefit.BioLaboratory) && b.virusId != 1) ||
|
||||
(b.BuildingType == StructureType.Facility && !b.CaptureTerminalIsHacked &&
|
||||
searhusBenefit) =>
|
||||
0.5f
|
||||
case _ =>
|
||||
1f
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3228,7 +3259,11 @@ class ZoningOperations(
|
|||
buildingType == StructureType.Bunker
|
||||
}
|
||||
.foreach { case (_, building) =>
|
||||
sendResponse(PlanetsideAttributeMessage(building.GUID, 67, 0 /*building.BuildingType == StructureType.Facility*/))
|
||||
if (building.hasCavernLockBenefit) {
|
||||
sendResponse(PlanetsideAttributeMessage(building.GUID, 67, 1))
|
||||
}
|
||||
else
|
||||
sendResponse(PlanetsideAttributeMessage(building.GUID, 67, 0))
|
||||
}
|
||||
statisticsPacketFunc()
|
||||
if (tplayer.ExoSuit == ExoSuitType.MAX) {
|
||||
|
|
@ -3353,6 +3388,20 @@ class ZoningOperations(
|
|||
}
|
||||
})
|
||||
}
|
||||
nextSpawnPoint.map(_.Owner) match {
|
||||
case Some(b: Building) if b.hasCavernLockBenefit =>
|
||||
tplayer.MaxHealth = 120
|
||||
tplayer.Health = 120
|
||||
tplayer.Zone.AvatarEvents ! AvatarServiceMessage(
|
||||
tplayer.Zone.id,
|
||||
AvatarAction.PlanetsideAttributeToAll(tplayer.GUID, 0, 120)
|
||||
)
|
||||
tplayer.Zone.AvatarEvents ! AvatarServiceMessage(
|
||||
tplayer.Zone.id,
|
||||
AvatarAction.PlanetsideAttributeToAll(tplayer.GUID, 1, 120)
|
||||
)
|
||||
case _ => ()
|
||||
}
|
||||
doorsThatShouldBeOpenInRange(pos, range = 100f)
|
||||
setAvatar = true
|
||||
player.allowInteraction = true
|
||||
|
|
|
|||
|
|
@ -167,7 +167,6 @@ object BuildingActor {
|
|||
val building = details.building
|
||||
val zone = building.Zone
|
||||
building.Faction = faction
|
||||
zone.actor ! ZoneActor.ZoneMapUpdate() // Update entire lattice to show lattice benefits
|
||||
zone.LocalEvents ! LocalServiceMessage(zone.id, LocalAction.SetEmpire(building.GUID, faction))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import net.psforever.objects.serverobject.structures.{StructureType, WarpGate}
|
|||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.objects.zones.blockmap.{BlockMapEntity, SectorGroup}
|
||||
import net.psforever.objects.{ConstructionItem, PlanetSideGameObject, Player, Vehicle}
|
||||
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, Vector3}
|
||||
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, PlanetSideGeneratorState, Vector3}
|
||||
import akka.actor.typed.scaladsl.adapter._
|
||||
import net.psforever.actors.zone.building.MajorFacilityLogic
|
||||
import net.psforever.objects.avatar.scoring.Kill
|
||||
|
|
@ -18,8 +18,10 @@ import net.psforever.objects.serverobject.turret.FacilityTurret
|
|||
import net.psforever.objects.sourcing.SourceEntry
|
||||
import net.psforever.objects.vital.{InGameActivity, InGameHistory}
|
||||
import net.psforever.objects.zones.exp.{ExperienceCalculator, SupportExperienceCalculator}
|
||||
import net.psforever.packet.game.{BuildingInfoUpdateMessage, PlanetsideAttributeMessage}
|
||||
import net.psforever.util.Database._
|
||||
import net.psforever.persistence
|
||||
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||
|
||||
import scala.collection.mutable
|
||||
import scala.util.{Failure, Success}
|
||||
|
|
@ -80,6 +82,8 @@ object ZoneActor {
|
|||
final case class RewardOurSupporters(target: SourceEntry, history: Iterable[InGameActivity], kill: Kill, bep: Long) extends Command
|
||||
|
||||
final case class AssignLockedBy(zone: Zone, notifyPlayers: Boolean) extends Command
|
||||
|
||||
final case class BuildingInfoState(msg: BuildingInfoUpdateMessage) extends Command
|
||||
}
|
||||
|
||||
class ZoneActor(
|
||||
|
|
@ -186,7 +190,7 @@ class ZoneActor(
|
|||
case ZoneMapUpdate() =>
|
||||
zone.Buildings
|
||||
.filter(building =>
|
||||
building._2.BuildingType == StructureType.Facility || building._2.BuildingType == StructureType.Tower)
|
||||
building._2.BuildingType == StructureType.Facility)
|
||||
.values
|
||||
.foreach(_.Actor ! BuildingActor.MapUpdate())
|
||||
Behaviors.same
|
||||
|
|
@ -194,6 +198,10 @@ class ZoneActor(
|
|||
case AssignLockedBy(zone, notifyPlayers) =>
|
||||
AssignLockedBy(zone, notifyPlayers)
|
||||
Behaviors.same
|
||||
|
||||
case BuildingInfoState(msg) =>
|
||||
UpdateBuildingState(msg)
|
||||
Behaviors.same
|
||||
}
|
||||
.receiveSignal {
|
||||
case (_, PostStop) =>
|
||||
|
|
@ -221,4 +229,36 @@ class ZoneActor(
|
|||
zone.benefitRecipient
|
||||
if (facilities.nonEmpty && notifyPlayers) { zone.NotifyContinentalLockBenefits(zone, facilities.head) }
|
||||
}
|
||||
|
||||
def UpdateBuildingState(msg: BuildingInfoUpdateMessage): Unit = {
|
||||
val buildingOpt = zone.Buildings.collectFirst {
|
||||
case (_, b) if b.MapId == msg.building_map_id => b
|
||||
}
|
||||
buildingOpt.foreach { building =>
|
||||
if (msg.generator_state == PlanetSideGeneratorState.Normal && building.hasCavernLockBenefit) {
|
||||
zone.LocalEvents ! LocalServiceMessage(
|
||||
zone.id,
|
||||
LocalAction.SendResponse(PlanetsideAttributeMessage(building.GUID, 67, 1))
|
||||
)
|
||||
}
|
||||
msg.is_hacked match {
|
||||
case true if building.BuildingType == StructureType.Facility && !zone.map.cavern =>
|
||||
zone.LocalEvents ! LocalServiceMessage(
|
||||
zone.id,
|
||||
LocalAction.SendResponse(PlanetsideAttributeMessage(building.GUID, 67, 0))
|
||||
)
|
||||
case false if building.hasCavernLockBenefit =>
|
||||
zone.LocalEvents ! LocalServiceMessage(
|
||||
zone.id,
|
||||
LocalAction.SendResponse(PlanetsideAttributeMessage(building.GUID, 67, 1))
|
||||
)
|
||||
case false if building.BuildingType == StructureType.Facility && !zone.map.cavern && !building.hasCavernLockBenefit =>
|
||||
zone.LocalEvents ! LocalServiceMessage(
|
||||
zone.id,
|
||||
LocalAction.SendResponse(PlanetsideAttributeMessage(building.GUID, 67, 0))
|
||||
)
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ package net.psforever.actors.zone.building
|
|||
import akka.actor.typed.Behavior
|
||||
import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
|
||||
import net.psforever.actors.commands.NtuCommand
|
||||
import net.psforever.actors.zone.{BuildingActor, BuildingControlDetails}
|
||||
import net.psforever.objects.serverobject.structures.{Amenity, Building}
|
||||
import net.psforever.actors.zone.{BuildingActor, BuildingControlDetails, ZoneActor}
|
||||
import net.psforever.objects.serverobject.structures.{Amenity, Building, StructureType}
|
||||
import net.psforever.objects.serverobject.terminals.capture.{CaptureTerminal, CaptureTerminalAware, CaptureTerminalAwareBehavior}
|
||||
import net.psforever.services.galaxy.{GalaxyAction, GalaxyServiceMessage}
|
||||
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||
|
|
@ -84,7 +84,16 @@ case object CavernFacilityLogic
|
|||
): Behavior[Command] = {
|
||||
BuildingActor.setFactionTo(details, faction, log)
|
||||
val building = details.building
|
||||
building.Neighbours.getOrElse(Nil).foreach { _.Actor ! BuildingActor.AlertToFactionChange(building) }
|
||||
val gates: Iterable[Building] = building.Zone.Buildings.values.filter(_.BuildingType == StructureType.WarpGate)
|
||||
gates.foreach { g =>
|
||||
val neighbors = g.Neighbours.getOrElse(Nil)
|
||||
neighbors.collect {
|
||||
case otherWg: Building => otherWg
|
||||
}
|
||||
.filter(_.Zone != g.Zone)
|
||||
.foreach { otherGate => otherGate.Zone.actor ! ZoneActor.ZoneMapUpdate()
|
||||
}
|
||||
}
|
||||
Behaviors.same
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import net.psforever.objects.serverobject.generator.{Generator, GeneratorControl
|
|||
import net.psforever.objects.serverobject.structures.{Amenity, Building}
|
||||
import net.psforever.objects.serverobject.terminals.capture.{CaptureTerminal, CaptureTerminalAware, CaptureTerminalAwareBehavior}
|
||||
import net.psforever.objects.sourcing.PlayerSource
|
||||
import net.psforever.packet.game.PlanetsideAttributeMessage
|
||||
import net.psforever.services.{InterstellarClusterService, Service}
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
import net.psforever.services.galaxy.{GalaxyAction, GalaxyServiceMessage}
|
||||
|
|
@ -244,6 +245,8 @@ case object MajorFacilityLogic
|
|||
}
|
||||
setFactionTo(details, PlanetSideEmpire.NEUTRAL)
|
||||
details.asInstanceOf[MajorFacilityWrapper].hasNtuSupply = false
|
||||
details.building.Zone.lockedBy = PlanetSideEmpire.NEUTRAL
|
||||
details.building.Zone.NotifyContinentalLockBenefits(details.building.Zone, details.building)
|
||||
Behaviors.same
|
||||
}
|
||||
|
||||
|
|
@ -300,6 +303,12 @@ case object MajorFacilityLogic
|
|||
building.PlayersInSOI.foreach { player =>
|
||||
events ! AvatarServiceMessage(player.Name, msg)
|
||||
}
|
||||
if (building.hasCavernLockBenefit) {
|
||||
zone.LocalEvents ! LocalServiceMessage(
|
||||
zone.id,
|
||||
LocalAction.SendResponse(PlanetsideAttributeMessage(building.GUID, 67, 0))
|
||||
)
|
||||
}
|
||||
false
|
||||
case Some(GeneratorControl.Event.Destroyed) =>
|
||||
true
|
||||
|
|
|
|||
|
|
@ -122,9 +122,6 @@ case object WarpGateLogic
|
|||
}
|
||||
updateBroadcastCapabilitiesOfWarpGate(details, wg, setBroadcastTo)
|
||||
updateBroadcastCapabilitiesOfWarpGate(details, otherWg, setBroadcastTo)
|
||||
if (wg.Zone.map.cavern && !otherWg.Zone.map.cavern) {
|
||||
otherWg.Zone.actor ! ZoneActor.ZoneMapUpdate()
|
||||
}
|
||||
|
||||
case (Some(_), Some(wg : WarpGate), Some(otherWg : WarpGate), None) =>
|
||||
handleWarpGateDeadendPair(details, otherWg, wg)
|
||||
|
|
|
|||
|
|
@ -1125,6 +1125,8 @@ object GlobalDefinitions {
|
|||
|
||||
val medical_terminal = new MedicalTerminalDefinition(529)
|
||||
|
||||
val medical_terminal_healing_module = new MedicalTerminalDefinition(530)
|
||||
|
||||
val portable_med_terminal = new MedicalTerminalDefinition(689)
|
||||
|
||||
val pad_landing_frame = new MedicalTerminalDefinition(618)
|
||||
|
|
|
|||
|
|
@ -26,13 +26,23 @@ object EffectTarget {
|
|||
//noinspection ScalaUnusedSymbol
|
||||
def Invalid(target: PlanetSideGameObject): Boolean = false
|
||||
|
||||
def Medical(target: PlanetSideGameObject): Boolean =
|
||||
def Medical(target: PlanetSideGameObject): Boolean = {
|
||||
target match {
|
||||
case p: Player =>
|
||||
p.Health > 0 && (p.Health < p.MaxHealth || p.Armor < p.MaxArmor)
|
||||
case _ =>
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
def HealthModule(target: PlanetSideGameObject): Boolean = {
|
||||
target match {
|
||||
case p: Player =>
|
||||
p.Health > 0 && p.Health < 120
|
||||
case _ =>
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
def HealthCrystal(target: PlanetSideGameObject): Boolean =
|
||||
target match {
|
||||
|
|
|
|||
|
|
@ -370,6 +370,15 @@ object GlobalDefinitionsMiscellaneous {
|
|||
medical_terminal.RepairIfDestroyed = true
|
||||
medical_terminal.Geometry = GeometryForm.representByCylinder(radius = 0.711f, height = 1.75f)
|
||||
|
||||
medical_terminal_healing_module.Name = "medical_terminal_healing_module"
|
||||
medical_terminal_healing_module.Interval = 2000
|
||||
medical_terminal_healing_module.HealAmount = 1
|
||||
medical_terminal_healing_module.ArmorAmount = 0
|
||||
medical_terminal_healing_module.UseRadius = 300
|
||||
medical_terminal_healing_module.TargetValidation += EffectTarget.Category.Player -> EffectTarget.Validation.HealthModule
|
||||
medical_terminal_healing_module.Damageable = false
|
||||
medical_terminal_healing_module.Repairable = false
|
||||
|
||||
adv_med_terminal.Name = "adv_med_terminal"
|
||||
adv_med_terminal.Interval = 500
|
||||
adv_med_terminal.HealAmount = 8
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ class Building(
|
|||
private var participationFunc: ParticipationLogic = NoParticipation
|
||||
var virusId: Long = 8 // 8 default = no virus
|
||||
var virusInstalledBy: Option[Int] = None // faction id
|
||||
var hasCavernLockBenefit: Boolean = false
|
||||
super.Zone_=(zone)
|
||||
super.GUID_=(PlanetSideGUID(building_guid)) //set
|
||||
Invalidate() //unset; guid can be used during setup, but does not stop being registered properly later
|
||||
|
|
@ -206,11 +207,14 @@ class Building(
|
|||
}
|
||||
val cavernBenefit: Set[CavernBenefit] = if (
|
||||
generatorState != PlanetSideGeneratorState.Destroyed &&
|
||||
faction != PlanetSideEmpire.NEUTRAL &&
|
||||
connectedCavern().nonEmpty
|
||||
faction != PlanetSideEmpire.NEUTRAL && !CaptureTerminalIsHacked &&
|
||||
connectedCavern().exists(_.Zone.lockedBy == faction)
|
||||
) {
|
||||
Set(CavernBenefit.VehicleModule, CavernBenefit.EquipmentModule)
|
||||
hasCavernLockBenefit = true
|
||||
Set(CavernBenefit.VehicleModule, CavernBenefit.EquipmentModule, CavernBenefit.ShieldModule,
|
||||
CavernBenefit.SpeedModule, CavernBenefit.HealthModule, CavernBenefit.PainModule)
|
||||
} else {
|
||||
hasCavernLockBenefit = false
|
||||
Set(CavernBenefit.None)
|
||||
}
|
||||
val (installedVirus, installedByFac) = if (virusId == 8) {
|
||||
|
|
|
|||
|
|
@ -247,6 +247,9 @@ object ProximityTerminalControl {
|
|||
target: PlanetSideGameObject
|
||||
): Boolean = {
|
||||
(terminal.Definition, target) match {
|
||||
case (_: MedicalTerminalDefinition, p: Player)
|
||||
if terminal.Definition ==
|
||||
GlobalDefinitions.medical_terminal_healing_module => HealthModule(terminal, p)
|
||||
case (_: MedicalTerminalDefinition, p: Player) => HealthAndArmorTerminal(terminal, p)
|
||||
case (_: WeaponRechargeTerminalDefinition, p: Player) => WeaponRechargeTerminal(terminal, p)
|
||||
case (_: MedicalTerminalDefinition, v: Vehicle) => VehicleRepairTerminal(terminal, v)
|
||||
|
|
@ -269,6 +272,16 @@ object ProximityTerminalControl {
|
|||
fullHeal && fullRepair
|
||||
}
|
||||
|
||||
/**
|
||||
* Activated by a facility having a linked cavern lock or health module installed. Friendly players
|
||||
* within the SOI receive constant healing as requested by the client
|
||||
*/
|
||||
def HealthModule(unit: Terminal with ProximityUnit, target: Player): Boolean = {
|
||||
val medDef = unit.Definition.asInstanceOf[MedicalTerminalDefinition]
|
||||
val fullHeal = HealthModuleAction(unit, target, medDef.HealAmount, PlayerHealthCallback)
|
||||
fullHeal
|
||||
}
|
||||
|
||||
/**
|
||||
* When driving a vehicle close to a rearm/repair silo,
|
||||
* restore the vehicle's health points.
|
||||
|
|
@ -318,6 +331,35 @@ object ProximityTerminalControl {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Heals players and increases their health/max health up to 120 if they enter the SOI this benefit is active in.
|
||||
*/
|
||||
def HealthModuleAction(
|
||||
terminal: Terminal,
|
||||
target: PlanetSideGameObject with Vitality with ZoneAware,
|
||||
healAmount: Int,
|
||||
updateFunc: PlanetSideGameObject with Vitality with ZoneAware => Unit
|
||||
): Boolean = {
|
||||
val maxHealthCap = 120
|
||||
val zone = target.Zone
|
||||
val oldMax = target.MaxHealth
|
||||
val newMax = math.min(oldMax + healAmount, maxHealthCap)
|
||||
|
||||
if (oldMax < maxHealthCap) {
|
||||
target.MaxHealth = newMax
|
||||
zone.AvatarEvents ! AvatarServiceMessage(
|
||||
zone.id,
|
||||
AvatarAction.PlanetsideAttributeToAll(target.GUID, 1, newMax)
|
||||
)
|
||||
}
|
||||
if (target.Health < newMax) {
|
||||
target.Health = math.min(target.Health + healAmount, newMax)
|
||||
target.LogActivity(HealFromTerminal(AmenitySource(terminal), 1))
|
||||
updateFunc(target)
|
||||
}
|
||||
target.Health == newMax
|
||||
}
|
||||
|
||||
def PlayerHealthCallback(target: PlanetSideGameObject with Vitality with ZoneAware): Unit = {
|
||||
val zone = target.Zone
|
||||
zone.AvatarEvents ! AvatarServiceMessage(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
// Copyright (c) 2020 PSForever
|
||||
package net.psforever.objects.vital.etc
|
||||
|
||||
import net.psforever.objects.Vehicle
|
||||
import net.psforever.objects.serverobject.painbox.Painbox
|
||||
import net.psforever.objects.serverobject.structures.Building
|
||||
import net.psforever.objects.sourcing.SourceEntry
|
||||
import net.psforever.objects.vital.{NoResistanceSelection, SimpleResolutions}
|
||||
import net.psforever.objects.vital.base.{DamageReason, DamageResolution}
|
||||
|
|
@ -13,7 +15,18 @@ final case class PainboxReason(entity: Painbox) extends DamageReason {
|
|||
private val definition = entity.Definition
|
||||
assert(definition.innateDamage.nonEmpty, s"causal entity '${definition.Name}' does not emit pain field")
|
||||
|
||||
def source: DamageWithPosition = definition.innateDamage.get
|
||||
def source: DamageWithPosition = {
|
||||
val base = definition.innateDamage.get
|
||||
entity.Owner match {
|
||||
case b: Building if b.hasCavernLockBenefit =>
|
||||
new DamageWithPosition {
|
||||
Damage0 = 5
|
||||
DamageRadius = 0
|
||||
DamageToHealthOnly = true
|
||||
}
|
||||
case _ => base
|
||||
}
|
||||
}
|
||||
|
||||
def resolution: DamageResolution.Value = DamageResolution.Resolved
|
||||
|
||||
|
|
|
|||
|
|
@ -259,7 +259,10 @@ class HackCaptureActor extends Actor {
|
|||
)
|
||||
}
|
||||
// Push map update to clients
|
||||
owner.Zone.actor ! ZoneActor.ZoneMapUpdate()
|
||||
if (owner.BuildingType == StructureType.Tower)
|
||||
owner.Actor ! BuildingActor.MapUpdate()
|
||||
else
|
||||
owner.Zone.actor ! ZoneActor.ZoneMapUpdate()
|
||||
}
|
||||
|
||||
private def HackCompleted(terminal: CaptureTerminal with Hackable, hackedByFaction: PlanetSideEmpire.Value): Unit = {
|
||||
|
|
@ -268,7 +271,6 @@ class HackCaptureActor extends Actor {
|
|||
building.virusId = 8
|
||||
building.virusInstalledBy = None
|
||||
log.info(s"Setting base ${building.GUID} / MapId: ${building.MapId} as owned by $hackedByFaction")
|
||||
building.Actor ! BuildingActor.SetFaction(hackedByFaction)
|
||||
//dispatch to players aligned with the capturing faction within the SOI
|
||||
val events = building.Zone.LocalEvents
|
||||
val msg = LocalAction.SendGenericActionMessage(Service.defaultPlayerGUID, GenericAction.FacilityCaptureFanfare)
|
||||
|
|
@ -304,6 +306,7 @@ class HackCaptureActor extends Actor {
|
|||
building.Zone.lockedBy = PlanetSideEmpire.NEUTRAL
|
||||
building.Zone.NotifyContinentalLockBenefits(building.Zone, building)
|
||||
}
|
||||
building.Actor ! BuildingActor.SetFaction(hackedByFaction)
|
||||
} else {
|
||||
log.info("Base hack completed, but base was out of NTU.")
|
||||
}
|
||||
|
|
@ -333,23 +336,10 @@ class HackCaptureActor extends Actor {
|
|||
if (buildingIterator.hasNext) {
|
||||
val building = buildingIterator.next()
|
||||
val terminal = building.CaptureTerminal.get
|
||||
val zone = building.Zone
|
||||
val zoneActor = zone.actor
|
||||
val buildingActor = building.Actor
|
||||
//clear any previous hack
|
||||
if (building.CaptureTerminalIsHacked) {
|
||||
zone.LocalEvents ! LocalServiceMessage(
|
||||
zone.id,
|
||||
LocalAction.ResecureCaptureTerminal(terminal, PlayerSource.Nobody)
|
||||
)
|
||||
}
|
||||
//push any updates this might cause
|
||||
zoneActor ! ZoneActor.ZoneMapUpdate()
|
||||
//convert faction affiliation
|
||||
buildingActor ! BuildingActor.SetFaction(faction)
|
||||
buildingActor ! BuildingActor.AmenityStateChange(terminal, Some(false))
|
||||
//push for map updates again
|
||||
zoneActor ! ZoneActor.ZoneMapUpdate()
|
||||
buildingActor ! BuildingActor.MapUpdate()
|
||||
}
|
||||
},
|
||||
0,
|
||||
|
|
|
|||
|
|
@ -345,6 +345,15 @@ object Zones {
|
|||
),
|
||||
owningBuildingGuid = buildingGuid
|
||||
)
|
||||
//health module slowly heals friendly players in the soi
|
||||
zoneMap.addLocalObject(
|
||||
buildingGuid + 2,
|
||||
ProximityTerminal.Constructor(
|
||||
structure.position,
|
||||
GlobalDefinitions.medical_terminal_healing_module
|
||||
),
|
||||
owningBuildingGuid = buildingGuid
|
||||
)
|
||||
}
|
||||
}
|
||||
val filteredZoneEntities =
|
||||
|
|
@ -557,7 +566,7 @@ object Zones {
|
|||
|
||||
case "adv_med_terminal" | "repair_silo" | "pad_landing_frame" | "pad_landing_tower_frame" | "medical_terminal" |
|
||||
"crystals_health_a" | "crystals_health_b" | "crystals_repair_a" | "crystals_repair_b" | "crystals_vehicle_a" |
|
||||
"crystals_vehicle_b" | "crystals_energy_a" | "crystals_energy_b" =>
|
||||
"crystals_vehicle_b" | "crystals_energy_a" | "crystals_energy_b" | "medical_terminal_healing_module" =>
|
||||
zoneMap.addLocalObject(
|
||||
obj.guid,
|
||||
ProximityTerminal
|
||||
|
|
|
|||
Loading…
Reference in a new issue