mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-07-16 08:55:18 +00:00
omft jacking functional; omft shields have been wired but remain disabled
This commit is contained in:
parent
306e2a63c0
commit
9070f396d0
9 changed files with 178 additions and 87 deletions
|
|
@ -36,6 +36,7 @@ import net.psforever.objects.vital.{VehicleDismountActivity, VehicleMountActivit
|
||||||
import net.psforever.objects.vital.collision.{CollisionReason, CollisionWithReason}
|
import net.psforever.objects.vital.collision.{CollisionReason, CollisionWithReason}
|
||||||
import net.psforever.objects.vital.etc.SuicideReason
|
import net.psforever.objects.vital.etc.SuicideReason
|
||||||
import net.psforever.objects.vital.interaction.DamageInteraction
|
import net.psforever.objects.vital.interaction.DamageInteraction
|
||||||
|
import net.psforever.objects.zones.blockmap.BlockMapEntity
|
||||||
import net.psforever.objects.zones.{Zone, ZoneProjectile, Zoning}
|
import net.psforever.objects.zones.{Zone, ZoneProjectile, Zoning}
|
||||||
import net.psforever.packet.PlanetSideGamePacket
|
import net.psforever.packet.PlanetSideGamePacket
|
||||||
import net.psforever.packet.game.objectcreate.ObjectClass
|
import net.psforever.packet.game.objectcreate.ObjectClass
|
||||||
|
|
@ -116,9 +117,9 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ops.fallHeightTracker(pos.z)
|
ops.fallHeightTracker(pos.z)
|
||||||
// if (isCrouching && !player.Crouching) {
|
// if (isCrouching && !player.Crouching) {
|
||||||
// //dev stuff goes here
|
// //dev stuff goes here
|
||||||
// }
|
// }
|
||||||
player.Position = pos
|
player.Position = pos
|
||||||
player.Velocity = vel
|
player.Velocity = vel
|
||||||
player.Orientation = Vector3(player.Orientation.x, pitch, yaw)
|
player.Orientation = Vector3(player.Orientation.x, pitch, yaw)
|
||||||
|
|
@ -821,19 +822,18 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
|
||||||
continent
|
continent
|
||||||
.GUID(vehicleGuid)
|
.GUID(vehicleGuid)
|
||||||
.foreach {
|
.foreach {
|
||||||
case obj: Vehicle if !obj.Destroyed && obj.MountedIn.isEmpty => // vehicle will try to charge even if destroyed & cargo vehicles need to be excluded
|
case obj: Vitality if obj.Destroyed => () //some entities will try to charge even if destroyed
|
||||||
obj.Actor ! CommonMessages.ChargeShields(
|
case obj: Vehicle if obj.MountedIn.nonEmpty => () //cargo vehicles need to be excluded
|
||||||
15,
|
case obj: Vehicle =>
|
||||||
Some(continent.blockMap.sector(obj).buildingList.maxBy(_.Definition.SOIRadius))
|
commonFacilityShieldCharging(obj)
|
||||||
)
|
case obj: TurretDeployable =>
|
||||||
case obj: Vehicle if obj.MountedIn.nonEmpty =>
|
commonFacilityShieldCharging(obj)
|
||||||
false
|
|
||||||
case _ if vehicleGuid.nonEmpty =>
|
case _ if vehicleGuid.nonEmpty =>
|
||||||
log.warn(
|
log.warn(
|
||||||
s"FacilityBenefitShieldChargeRequest: ${player.Name} can not find vehicle ${vehicleGuid.get.guid} in zone ${continent.id}"
|
s"FacilityBenefitShieldChargeRequest: ${player.Name} can not find chargeable entity ${vehicleGuid.get.guid} in ${continent.id}"
|
||||||
)
|
)
|
||||||
case _ =>
|
case _ =>
|
||||||
log.warn(s"FacilityBenefitShieldChargeRequest: ${player.Name} is not seated in a vehicle")
|
log.warn(s"FacilityBenefitShieldChargeRequest: ${player.Name} is not seated in anything")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1514,4 +1514,11 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private def commonFacilityShieldCharging(obj: PlanetSideServerObject with BlockMapEntity): Unit = {
|
||||||
|
obj.Actor ! CommonMessages.ChargeShields(
|
||||||
|
15,
|
||||||
|
Some(continent.blockMap.sector(obj).buildingList.maxBy(_.Definition.SOIRadius))
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,25 +2,26 @@
|
||||||
package net.psforever.objects
|
package net.psforever.objects
|
||||||
|
|
||||||
import akka.actor.{Actor, ActorContext, ActorRef, Props}
|
import akka.actor.{Actor, ActorContext, ActorRef, Props}
|
||||||
import net.psforever.objects.ce.{Deployable, DeployableBehavior, DeployedItem, InteractWithTurrets}
|
import net.psforever.objects.ce.{Deployable, DeployableBehavior, DeployableCategory, DeployedItem, InteractWithTurrets}
|
||||||
import net.psforever.objects.definition.DeployableDefinition
|
import net.psforever.objects.definition.{DeployableDefinition, WithShields}
|
||||||
import net.psforever.objects.definition.converter.SmallTurretConverter
|
import net.psforever.objects.definition.converter.SmallTurretConverter
|
||||||
import net.psforever.objects.equipment.JammableUnit
|
import net.psforever.objects.equipment.JammableUnit
|
||||||
import net.psforever.objects.guid.{GUIDTask, TaskWorkflow}
|
import net.psforever.objects.guid.{GUIDTask, TaskWorkflow}
|
||||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
|
||||||
import net.psforever.objects.serverobject.affinity.FactionAffinityBehavior
|
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
|
||||||
import net.psforever.objects.serverobject.damage.Damageable
|
import net.psforever.objects.serverobject.damage.Damageable
|
||||||
import net.psforever.objects.serverobject.hackable.Hackable
|
import net.psforever.objects.serverobject.hackable.{GenericHackables, Hackable}
|
||||||
import net.psforever.objects.serverobject.mount.{InteractWithRadiationCloudsSeatedInEntity, Mountable}
|
import net.psforever.objects.serverobject.mount.{InteractWithRadiationCloudsSeatedInEntity, Mountable}
|
||||||
import net.psforever.objects.serverobject.turret.auto.AutomatedTurret.Target
|
import net.psforever.objects.serverobject.turret.auto.AutomatedTurret.Target
|
||||||
import net.psforever.objects.serverobject.turret.auto.{AffectedByAutomaticTurretFire, AutomatedTurret, AutomatedTurretBehavior}
|
import net.psforever.objects.serverobject.turret.auto.{AffectedByAutomaticTurretFire, AutomatedTurret, AutomatedTurretBehavior}
|
||||||
import net.psforever.objects.serverobject.turret.{MountableTurretControl, TurretDefinition, WeaponTurret}
|
import net.psforever.objects.serverobject.turret.{MountableTurretControl, TurretDefinition, WeaponTurret, WeaponTurrets}
|
||||||
import net.psforever.objects.sourcing.{PlayerSource, SourceEntry}
|
import net.psforever.objects.sourcing.{PlayerSource, SourceEntry}
|
||||||
import net.psforever.objects.vital.damage.DamageCalculations
|
import net.psforever.objects.vital.damage.DamageCalculations
|
||||||
import net.psforever.objects.vital.interaction.DamageResult
|
import net.psforever.objects.vital.interaction.DamageResult
|
||||||
import net.psforever.objects.vital.resistance.StandardResistanceProfile
|
import net.psforever.objects.vital.resistance.StandardResistanceProfile
|
||||||
import net.psforever.objects.vital.{SimpleResolutions, StandardVehicleResistance}
|
import net.psforever.objects.vital.{InGameActivity, ShieldCharge, SimpleResolutions, StandardVehicleResistance}
|
||||||
import net.psforever.objects.zones.InteractsWithZone
|
import net.psforever.objects.zones.InteractsWithZone
|
||||||
|
import net.psforever.packet.game.TriggeredSound
|
||||||
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||||
import net.psforever.types.PlanetSideGUID
|
import net.psforever.types.PlanetSideGUID
|
||||||
|
|
||||||
|
|
@ -34,6 +35,9 @@ class TurretDeployable(tdef: TurretDeployableDefinition)
|
||||||
with InteractsWithZone
|
with InteractsWithZone
|
||||||
with StandardResistanceProfile
|
with StandardResistanceProfile
|
||||||
with Hackable {
|
with Hackable {
|
||||||
|
HackSound = TriggeredSound.HackVehicle
|
||||||
|
HackDuration = Array(0, 20, 10, 5)
|
||||||
|
|
||||||
if (tdef.Seats.nonEmpty) {
|
if (tdef.Seats.nonEmpty) {
|
||||||
interaction(new InteractWithTurrets())
|
interaction(new InteractWithTurrets())
|
||||||
interaction(new InteractWithRadiationCloudsSeatedInEntity(obj = this, range = 100f))
|
interaction(new InteractWithRadiationCloudsSeatedInEntity(obj = this, range = 100f))
|
||||||
|
|
@ -50,6 +54,10 @@ class TurretDeployable(tdef: TurretDeployableDefinition)
|
||||||
.getOrElse(SourceEntry(this))
|
.getOrElse(SourceEntry(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override def MaxShields: Int = {
|
||||||
|
Definition.MaxShields
|
||||||
|
}
|
||||||
|
|
||||||
override def Definition: TurretDeployableDefinition = tdef
|
override def Definition: TurretDeployableDefinition = tdef
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,6 +120,20 @@ class TurretControl(turret: TurretDeployable)
|
||||||
.orElse(automatedTurretBehavior)
|
.orElse(automatedTurretBehavior)
|
||||||
.orElse(takeAutomatedDamage)
|
.orElse(takeAutomatedDamage)
|
||||||
.orElse {
|
.orElse {
|
||||||
|
case CommonMessages.Use(player, Some(item: SimpleItem))
|
||||||
|
if item.Definition == GlobalDefinitions.remote_electronics_kit &&
|
||||||
|
turret.Definition.DeployCategory == DeployableCategory.FieldTurrets &&
|
||||||
|
turret.Faction != player.Faction =>
|
||||||
|
sender() ! CommonMessages.Progress(
|
||||||
|
GenericHackables.GetHackSpeed(player, turret),
|
||||||
|
WeaponTurrets.FinishHackingTurretDeployable(turret, player),
|
||||||
|
GenericHackables.HackingTickAction(progressType = 1, player, turret, item.GUID)
|
||||||
|
)
|
||||||
|
|
||||||
|
case CommonMessages.ChargeShields(amount, motivator)
|
||||||
|
if turret.Definition.DeployCategory == DeployableCategory.FieldTurrets=>
|
||||||
|
chargeShields(amount, motivator.collect { case o: PlanetSideGameObject with FactionAffinity => SourceEntry(o) })
|
||||||
|
|
||||||
case _ => ()
|
case _ => ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -252,4 +274,22 @@ class TurretControl(turret: TurretDeployable)
|
||||||
val zone = obj.Zone
|
val zone = obj.Zone
|
||||||
TaskWorkflow.execute(GUIDTask.unregisterDeployableTurret(zone.GUID, turret))
|
TaskWorkflow.execute(GUIDTask.unregisterDeployableTurret(zone.GUID, turret))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//make certain vehicles don't charge shields too quickly
|
||||||
|
def canChargeShields: Boolean = {
|
||||||
|
val func: InGameActivity => Boolean = WithShields.LastShieldChargeOrDamage(System.currentTimeMillis(), turret.Definition)
|
||||||
|
turret.Health > 0 && turret.Shields < turret.MaxShields &&
|
||||||
|
turret.History.findLast(func).isEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
def chargeShields(amount: Int, motivator: Option[SourceEntry]): Unit = {
|
||||||
|
if (canChargeShields) {
|
||||||
|
turret.LogActivity(ShieldCharge(amount, motivator))
|
||||||
|
turret.Shields = turret.Shields + amount
|
||||||
|
turret.Zone.VehicleEvents ! VehicleServiceMessage(
|
||||||
|
s"${turret.Actor}",
|
||||||
|
VehicleAction.PlanetsideAttribute(PlanetSideGUID(0), turret.GUID, turret.Definition.shieldUiAttribute, turret.Shields)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,7 @@ trait BaseDeployable
|
||||||
Shields
|
Shields
|
||||||
}
|
}
|
||||||
|
|
||||||
def MaxShields: Int = {
|
def MaxShields: Int = 0
|
||||||
0 //Definition.MaxShields
|
|
||||||
}
|
|
||||||
|
|
||||||
def MaxHealth: Int
|
def MaxHealth: Int
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package net.psforever.objects.definition
|
package net.psforever.objects.definition
|
||||||
|
|
||||||
|
import net.psforever.objects.vital.{DamagingActivity, InGameActivity, ShieldCharge}
|
||||||
|
|
||||||
trait WithShields {
|
trait WithShields {
|
||||||
/** ... */
|
/** ... */
|
||||||
var shieldUiAttribute: Int = 68
|
var shieldUiAttribute: Int = 68
|
||||||
|
|
@ -7,6 +9,7 @@ trait WithShields {
|
||||||
private var defaultShields : Option[Int] = None
|
private var defaultShields : Option[Int] = None
|
||||||
/** maximum vehicle shields (generally: 20% of health)
|
/** maximum vehicle shields (generally: 20% of health)
|
||||||
* for normal vehicles, offered through amp station facility benefits
|
* for normal vehicles, offered through amp station facility benefits
|
||||||
|
* for omft, gained in friendly soi (in which the turret may not be constructed)
|
||||||
* for BFR's, it charges naturally
|
* for BFR's, it charges naturally
|
||||||
**/
|
**/
|
||||||
private var maxShields: Int = 0
|
private var maxShields: Int = 0
|
||||||
|
|
@ -79,3 +82,20 @@ trait WithShields {
|
||||||
ShieldDrain
|
ShieldDrain
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object WithShields {
|
||||||
|
/**
|
||||||
|
* Determine if a given activity entry would invalidate the act of charging shields this tick.
|
||||||
|
* @param now the current time (in milliseconds)
|
||||||
|
* @param act a `VitalsActivity` entry to test
|
||||||
|
* @return `true`, if the shield charge would be blocked;
|
||||||
|
* `false`, otherwise
|
||||||
|
*/
|
||||||
|
def LastShieldChargeOrDamage(now: Long, vdef: WithShields)(act: InGameActivity): Boolean = {
|
||||||
|
act match {
|
||||||
|
case dact: DamagingActivity => now - dact.time < vdef.ShieldDamageDelay //damage delays next charge
|
||||||
|
case vsc: ShieldCharge => now - vsc.time < vdef.ShieldPeriodicDelay //previous charge delays next
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -317,6 +317,7 @@ object GlobalDefinitionsDeployable {
|
||||||
portable_manned_turret.Damageable = true
|
portable_manned_turret.Damageable = true
|
||||||
portable_manned_turret.Repairable = true
|
portable_manned_turret.Repairable = true
|
||||||
portable_manned_turret.RepairIfDestroyed = false
|
portable_manned_turret.RepairIfDestroyed = false
|
||||||
|
portable_manned_turret.MaxShields = 0//200
|
||||||
portable_manned_turret.WeaponPaths += 1 -> new mutable.HashMap()
|
portable_manned_turret.WeaponPaths += 1 -> new mutable.HashMap()
|
||||||
portable_manned_turret.WeaponPaths(1) += TurretUpgrade.None -> energy_gun
|
portable_manned_turret.WeaponPaths(1) += TurretUpgrade.None -> energy_gun
|
||||||
portable_manned_turret.Seats += 0 -> new SeatDefinition()
|
portable_manned_turret.Seats += 0 -> new SeatDefinition()
|
||||||
|
|
@ -351,6 +352,7 @@ object GlobalDefinitionsDeployable {
|
||||||
portable_manned_turret_nc.Damageable = true
|
portable_manned_turret_nc.Damageable = true
|
||||||
portable_manned_turret_nc.Repairable = true
|
portable_manned_turret_nc.Repairable = true
|
||||||
portable_manned_turret_nc.RepairIfDestroyed = false
|
portable_manned_turret_nc.RepairIfDestroyed = false
|
||||||
|
portable_manned_turret_nc.MaxShields = 0//200
|
||||||
portable_manned_turret_nc.WeaponPaths += 1 -> new mutable.HashMap()
|
portable_manned_turret_nc.WeaponPaths += 1 -> new mutable.HashMap()
|
||||||
portable_manned_turret_nc.WeaponPaths(1) += TurretUpgrade.None -> energy_gun_nc
|
portable_manned_turret_nc.WeaponPaths(1) += TurretUpgrade.None -> energy_gun_nc
|
||||||
portable_manned_turret_nc.Seats += 0 -> new SeatDefinition()
|
portable_manned_turret_nc.Seats += 0 -> new SeatDefinition()
|
||||||
|
|
@ -384,6 +386,7 @@ object GlobalDefinitionsDeployable {
|
||||||
portable_manned_turret_tr.Damageable = true
|
portable_manned_turret_tr.Damageable = true
|
||||||
portable_manned_turret_tr.Repairable = true
|
portable_manned_turret_tr.Repairable = true
|
||||||
portable_manned_turret_tr.RepairIfDestroyed = false
|
portable_manned_turret_tr.RepairIfDestroyed = false
|
||||||
|
portable_manned_turret_tr.MaxShields = 0//200
|
||||||
portable_manned_turret_tr.WeaponPaths += 1 -> new mutable.HashMap()
|
portable_manned_turret_tr.WeaponPaths += 1 -> new mutable.HashMap()
|
||||||
portable_manned_turret_tr.WeaponPaths(1) += TurretUpgrade.None -> energy_gun_tr
|
portable_manned_turret_tr.WeaponPaths(1) += TurretUpgrade.None -> energy_gun_tr
|
||||||
portable_manned_turret_tr.Seats += 0 -> new SeatDefinition()
|
portable_manned_turret_tr.Seats += 0 -> new SeatDefinition()
|
||||||
|
|
@ -417,6 +420,7 @@ object GlobalDefinitionsDeployable {
|
||||||
portable_manned_turret_vs.Damageable = true
|
portable_manned_turret_vs.Damageable = true
|
||||||
portable_manned_turret_vs.Repairable = true
|
portable_manned_turret_vs.Repairable = true
|
||||||
portable_manned_turret_vs.RepairIfDestroyed = false
|
portable_manned_turret_vs.RepairIfDestroyed = false
|
||||||
|
portable_manned_turret_vs.MaxShields = 0//200
|
||||||
portable_manned_turret_vs.WeaponPaths += 1 -> new mutable.HashMap()
|
portable_manned_turret_vs.WeaponPaths += 1 -> new mutable.HashMap()
|
||||||
portable_manned_turret_vs.WeaponPaths(1) += TurretUpgrade.None -> energy_gun_vs
|
portable_manned_turret_vs.WeaponPaths(1) += TurretUpgrade.None -> energy_gun_vs
|
||||||
portable_manned_turret_vs.Seats += 0 -> new SeatDefinition()
|
portable_manned_turret_vs.Seats += 0 -> new SeatDefinition()
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright (c) 2020 PSForever
|
// Copyright (c) 2020 PSForever
|
||||||
package net.psforever.objects.serverobject.hackable
|
package net.psforever.objects.serverobject.hackable
|
||||||
|
|
||||||
import net.psforever.objects.serverobject.turret.FacilityTurret
|
|
||||||
import net.psforever.objects.{Player, Vehicle}
|
import net.psforever.objects.{Player, Vehicle}
|
||||||
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
|
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
|
||||||
import net.psforever.packet.game.{HackMessage, HackState}
|
import net.psforever.packet.game.{HackMessage, HackState}
|
||||||
|
|
@ -45,18 +44,18 @@ object GenericHackables {
|
||||||
case hackable: Hackable => hackable.HackDuration(playerHackLevel).toFloat
|
case hackable: Hackable => hackable.HackDuration(playerHackLevel).toFloat
|
||||||
case _ =>
|
case _ =>
|
||||||
log.warn(
|
log.warn(
|
||||||
s"${player.Name} tried to hack an object that has no hack time defined - ${obj.Definition.Name}#${obj.GUID} on ${obj.Zone.id}"
|
s"${player.Name} tried to hack an object that has no hack time defined - ${obj.Definition.Name}@${obj.GUID.guid} in ${obj.Zone.id}"
|
||||||
)
|
)
|
||||||
0f
|
0f
|
||||||
}
|
}
|
||||||
if (timeToHack == 0) {
|
if (timeToHack == 0) {
|
||||||
log.warn(
|
log.warn(
|
||||||
s"${player.Name} tried to hack an object that they don't have the correct hacking level for - ${obj.Definition.Name}#${obj.GUID} on ${obj.Zone.id}"
|
s"${player.Name} tried to hack an object that they don't have the correct hacking level for - ${obj.Definition.Name}@${obj.GUID.guid} in ${obj.Zone.id}"
|
||||||
)
|
)
|
||||||
0f
|
0f
|
||||||
} else {
|
} else {
|
||||||
//timeToHack is in seconds; progress is measured in quarters of a second (250ms)
|
//timeToHack is in seconds; progress is measured in quarters of a second (250ms)
|
||||||
(100f / timeToHack) / 4
|
25f / timeToHack
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,43 +107,6 @@ object GenericHackables {
|
||||||
vis != HackState.Cancelled
|
vis != HackState.Cancelled
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluate the progress of the user applying a tool to upgrade a facility turret.
|
|
||||||
* This action is using the nano dispenser and requires separate handling from REK hacking.
|
|
||||||
* Largely a copy/paste of the above, but some of it was removed as it doesn't work/apply with upgrading a turret.
|
|
||||||
* @see `HackMessage`
|
|
||||||
* @see `HackState`
|
|
||||||
* @param progressType 1 - remote electronics kit hack (various ...);
|
|
||||||
* 2 - nano dispenser (upgrade canister) turret upgrade
|
|
||||||
* @param tplayer the player performing the action
|
|
||||||
* @param turret the object being affected
|
|
||||||
* @param tool_guid the tool being used to affest the object
|
|
||||||
* @param progress the current progress value
|
|
||||||
* @return `true`, if the next cycle of progress should occur;
|
|
||||||
* `false`, otherwise
|
|
||||||
*/
|
|
||||||
def TurretUpgradingTickAction(progressType: Int, tplayer: Player, turret: FacilityTurret, tool_guid: PlanetSideGUID)(
|
|
||||||
progress: Float
|
|
||||||
): Boolean = {
|
|
||||||
//hack state for progress bar visibility
|
|
||||||
val vis = if (progress <= 0L) {
|
|
||||||
HackState.Start
|
|
||||||
} else if (progress >= 100L) {
|
|
||||||
HackState.Finished
|
|
||||||
} else {
|
|
||||||
updateTurretUpgradeTime()
|
|
||||||
HackState.Ongoing
|
|
||||||
}
|
|
||||||
turret.Zone.AvatarEvents ! AvatarServiceMessage(
|
|
||||||
tplayer.Name,
|
|
||||||
AvatarAction.SendResponse(
|
|
||||||
Service.defaultPlayerGUID,
|
|
||||||
HackMessage(progressType, turret.GUID, tplayer.GUID, progress.toInt, 0L, vis, 8L)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
vis != HackState.Cancelled
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The process of hacking an object is completed.
|
* The process of hacking an object is completed.
|
||||||
* Pass the message onto the hackable object and onto the local events system.
|
* Pass the message onto the hackable object and onto the local events system.
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ class FacilityTurretControl(turret: FacilityTurret)
|
||||||
sender() ! CommonMessages.Progress(
|
sender() ! CommonMessages.Progress(
|
||||||
1.25f,
|
1.25f,
|
||||||
WeaponTurrets.FinishUpgradingMannedTurret(TurretObject, player, item, upgrade),
|
WeaponTurrets.FinishUpgradingMannedTurret(TurretObject, player, item, upgrade),
|
||||||
GenericHackables.TurretUpgradingTickAction(progressType = 2, player, TurretObject, item.GUID)
|
WeaponTurrets.TurretUpgradingTickAction(progressType = 2, player, TurretObject, item.GUID)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
case TurretUpgrader.UpgradeCompleted(_) =>
|
case TurretUpgrader.UpgradeCompleted(_) =>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,17 @@
|
||||||
// Copyright (c) 2020 PSForever
|
// Copyright (c) 2020 PSForever
|
||||||
package net.psforever.objects.serverobject.turret
|
package net.psforever.objects.serverobject.turret
|
||||||
|
|
||||||
import net.psforever.objects.{Player, Tool}
|
import net.psforever.objects.avatar.Certification
|
||||||
import net.psforever.packet.game.InventoryStateMessage
|
import net.psforever.objects.ce.Deployable
|
||||||
|
import net.psforever.objects.serverobject.hackable.GenericHackables.updateTurretUpgradeTime
|
||||||
|
import net.psforever.objects.{Player, Tool, TurretDeployable}
|
||||||
|
import net.psforever.packet.game.{HackMessage, HackState, InventoryStateMessage}
|
||||||
import net.psforever.services.Service
|
import net.psforever.services.Service
|
||||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||||
import net.psforever.services.vehicle.VehicleServiceMessage
|
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||||
|
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||||
import net.psforever.services.vehicle.support.TurretUpgrader
|
import net.psforever.services.vehicle.support.TurretUpgrader
|
||||||
|
import net.psforever.types.PlanetSideGUID
|
||||||
|
|
||||||
object WeaponTurrets {
|
object WeaponTurrets {
|
||||||
private val log = org.log4s.getLogger("WeaponTurrets")
|
private val log = org.log4s.getLogger("WeaponTurrets")
|
||||||
|
|
@ -52,4 +57,76 @@ object WeaponTurrets {
|
||||||
events ! VehicleServiceMessage.TurretUpgrade(TurretUpgrader.ClearSpecific(List(target), zone))
|
events ! VehicleServiceMessage.TurretUpgrade(TurretUpgrader.ClearSpecific(List(target), zone))
|
||||||
events ! VehicleServiceMessage.TurretUpgrade(TurretUpgrader.AddTask(target, zone, upgrade))
|
events ! VehicleServiceMessage.TurretUpgrade(TurretUpgrader.AddTask(target, zone, upgrade))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate the progress of the user applying a tool to upgrade a facility turret.
|
||||||
|
* This action is using the nano dispenser and requires separate handling from REK hacking.
|
||||||
|
* Largely a copy/paste of the above, but some of it was removed as it doesn't work/apply with upgrading a turret.
|
||||||
|
* @see `HackMessage`
|
||||||
|
* @see `HackState`
|
||||||
|
* @param progressType 1 - remote electronics kit hack (various ...);
|
||||||
|
* 2 - nano dispenser (upgrade canister) turret upgrade
|
||||||
|
* @param tplayer the player performing the action
|
||||||
|
* @param turret the object being affected
|
||||||
|
* @param tool_guid the tool being used to affest the object
|
||||||
|
* @param progress the current progress value
|
||||||
|
* @return `true`, if the next cycle of progress should occur;
|
||||||
|
* `false`, otherwise
|
||||||
|
*/
|
||||||
|
def TurretUpgradingTickAction(progressType: Int, tplayer: Player, turret: FacilityTurret, tool_guid: PlanetSideGUID)(
|
||||||
|
progress: Float
|
||||||
|
): Boolean = {
|
||||||
|
//hack state for progress bar visibility
|
||||||
|
val vis = if (progress <= 0L) {
|
||||||
|
HackState.Start
|
||||||
|
} else if (progress >= 100L) {
|
||||||
|
HackState.Finished
|
||||||
|
} else {
|
||||||
|
updateTurretUpgradeTime()
|
||||||
|
HackState.Ongoing
|
||||||
|
}
|
||||||
|
turret.Zone.AvatarEvents ! AvatarServiceMessage(
|
||||||
|
tplayer.Name,
|
||||||
|
AvatarAction.SendResponse(
|
||||||
|
Service.defaultPlayerGUID,
|
||||||
|
HackMessage(progressType, turret.GUID, tplayer.GUID, progress.toInt, 0L, vis, 8L)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
vis != HackState.Cancelled
|
||||||
|
}
|
||||||
|
|
||||||
|
def FinishHackingTurretDeployable(target: TurretDeployable, hacker: Player)(): Unit = {
|
||||||
|
org.log4s.getLogger("TurretDeployable").info(s"${hacker.Name} has jacked a ${target.Definition.Name}")
|
||||||
|
val zone = target.Zone
|
||||||
|
val certs = hacker.avatar.certifications
|
||||||
|
if (certs.contains(Certification.ExpertHacking) || certs.contains(Certification.ElectronicsExpert)) {
|
||||||
|
// Forcefully dismount all seated occupants from the turret
|
||||||
|
target.Seats.values.foreach { seat =>
|
||||||
|
seat.occupant.collect {
|
||||||
|
player: Player =>
|
||||||
|
seat.unmount(player)
|
||||||
|
player.VehicleSeated = None
|
||||||
|
zone.VehicleEvents ! VehicleServiceMessage(
|
||||||
|
zone.id,
|
||||||
|
VehicleAction.KickPassenger(player.GUID, 4, unk2 = false, target.GUID)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//hacker owns the deployable now
|
||||||
|
target.OwnerGuid = None
|
||||||
|
target.Actor ! Deployable.Ownership(hacker)
|
||||||
|
//convert faction
|
||||||
|
zone.AvatarEvents ! AvatarServiceMessage(
|
||||||
|
zone.id,
|
||||||
|
AvatarAction.SetEmpire(Service.defaultPlayerGUID, target.GUID, hacker.Faction)
|
||||||
|
)
|
||||||
|
zone.LocalEvents ! LocalServiceMessage(
|
||||||
|
zone.id,
|
||||||
|
LocalAction.TriggerSound(hacker.GUID, target.HackSound, target.Position, 30, 0.49803925f)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
//deconstruct
|
||||||
|
target.Actor ! Deployable.Deconstruct()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ package net.psforever.objects.vehicles.control
|
||||||
import akka.actor.Cancellable
|
import akka.actor.Cancellable
|
||||||
import net.psforever.actors.zone.ZoneActor
|
import net.psforever.actors.zone.ZoneActor
|
||||||
import net.psforever.objects._
|
import net.psforever.objects._
|
||||||
import net.psforever.objects.definition.VehicleDefinition
|
import net.psforever.objects.definition.{VehicleDefinition, WithShields}
|
||||||
import net.psforever.objects.definition.converter.OCM
|
import net.psforever.objects.definition.converter.OCM
|
||||||
import net.psforever.objects.entity.WorldEntity
|
import net.psforever.objects.entity.WorldEntity
|
||||||
import net.psforever.objects.equipment.{ArmorSiphonBehavior, Equipment, EquipmentSlot, JammableMountedWeapons}
|
import net.psforever.objects.equipment.{ArmorSiphonBehavior, Equipment, EquipmentSlot, JammableMountedWeapons}
|
||||||
|
|
@ -27,7 +27,7 @@ import net.psforever.objects.sourcing.{PlayerSource, SourceEntry, VehicleSource}
|
||||||
import net.psforever.objects.vehicles._
|
import net.psforever.objects.vehicles._
|
||||||
import net.psforever.objects.vehicles.interaction.WithWater
|
import net.psforever.objects.vehicles.interaction.WithWater
|
||||||
import net.psforever.objects.vital.interaction.DamageResult
|
import net.psforever.objects.vital.interaction.DamageResult
|
||||||
import net.psforever.objects.vital.{DamagingActivity, InGameActivity, ShieldCharge, SpawningActivity, VehicleDismountActivity, VehicleMountActivity}
|
import net.psforever.objects.vital.{InGameActivity, ShieldCharge, SpawningActivity, VehicleDismountActivity, VehicleMountActivity}
|
||||||
import net.psforever.objects.zones._
|
import net.psforever.objects.zones._
|
||||||
import net.psforever.packet.PlanetSideGamePacket
|
import net.psforever.packet.PlanetSideGamePacket
|
||||||
import net.psforever.packet.game._
|
import net.psforever.packet.game._
|
||||||
|
|
@ -571,7 +571,7 @@ class VehicleControl(vehicle: Vehicle)
|
||||||
|
|
||||||
//make certain vehicles don't charge shields too quickly
|
//make certain vehicles don't charge shields too quickly
|
||||||
def canChargeShields: Boolean = {
|
def canChargeShields: Boolean = {
|
||||||
val func: InGameActivity => Boolean = VehicleControl.LastShieldChargeOrDamage(System.currentTimeMillis(), vehicle.Definition)
|
val func: InGameActivity => Boolean = WithShields.LastShieldChargeOrDamage(System.currentTimeMillis(), vehicle.Definition)
|
||||||
vehicle.Health > 0 && vehicle.Shields < vehicle.MaxShields &&
|
vehicle.Health > 0 && vehicle.Shields < vehicle.MaxShields &&
|
||||||
vehicle.History.findLast(func).isEmpty
|
vehicle.History.findLast(func).isEmpty
|
||||||
}
|
}
|
||||||
|
|
@ -714,8 +714,6 @@ class VehicleControl(vehicle: Vehicle)
|
||||||
}
|
}
|
||||||
|
|
||||||
object VehicleControl {
|
object VehicleControl {
|
||||||
import net.psforever.objects.vital.ShieldCharge
|
|
||||||
|
|
||||||
private case class PrepareForDeletion()
|
private case class PrepareForDeletion()
|
||||||
|
|
||||||
final case class Disable(kickPassengers: Boolean = false)
|
final case class Disable(kickPassengers: Boolean = false)
|
||||||
|
|
@ -725,19 +723,4 @@ object VehicleControl {
|
||||||
private case object RadiationTick
|
private case object RadiationTick
|
||||||
|
|
||||||
final case class AssignOwnership(player: Option[Player])
|
final case class AssignOwnership(player: Option[Player])
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if a given activity entry would invalidate the act of charging vehicle shields this tick.
|
|
||||||
* @param now the current time (in milliseconds)
|
|
||||||
* @param act a `VitalsActivity` entry to test
|
|
||||||
* @return `true`, if the shield charge would be blocked;
|
|
||||||
* `false`, otherwise
|
|
||||||
*/
|
|
||||||
def LastShieldChargeOrDamage(now: Long, vdef: VehicleDefinition)(act: InGameActivity): Boolean = {
|
|
||||||
act match {
|
|
||||||
case dact: DamagingActivity => now - dact.time < vdef.ShieldDamageDelay //damage delays next charge
|
|
||||||
case vsc: ShieldCharge => now - vsc.time < vdef.ShieldPeriodicDelay //previous charge delays next
|
|
||||||
case _ => false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue