mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-19 18:14:44 +00:00
179 lines
6.1 KiB
Scala
179 lines
6.1 KiB
Scala
// Copyright (c) 2018 PSForever
|
|
package net.psforever.objects
|
|
|
|
import akka.actor.{Actor, ActorContext, Props}
|
|
import net.psforever.objects.ballistics.{PlayerSource, SourceEntry}
|
|
import net.psforever.objects.ce._
|
|
import net.psforever.objects.definition.{ComplexDeployableDefinition, SimpleDeployableDefinition}
|
|
import net.psforever.objects.definition.converter.SmallDeployableConverter
|
|
import net.psforever.objects.equipment.JammableUnit
|
|
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
|
|
import net.psforever.objects.serverobject.damage.{Damageable, DamageableEntity}
|
|
import net.psforever.objects.serverobject.damage.Damageable.Target
|
|
import net.psforever.objects.vital.resolution.ResolutionCalculations.Output
|
|
import net.psforever.objects.vital.SimpleResolutions
|
|
import net.psforever.objects.vital.etc.TriggerUsedReason
|
|
import net.psforever.objects.vital.interaction.{DamageInteraction, DamageResult}
|
|
import net.psforever.objects.vital.projectile.ProjectileReason
|
|
import net.psforever.objects.zones.Zone
|
|
import net.psforever.types.Vector3
|
|
import net.psforever.services.Service
|
|
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
|
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
|
|
|
import scala.concurrent.duration._
|
|
|
|
class ExplosiveDeployable(cdef: ExplosiveDeployableDefinition)
|
|
extends ComplexDeployable(cdef)
|
|
with JammableUnit {
|
|
|
|
override def Definition: ExplosiveDeployableDefinition = cdef
|
|
}
|
|
|
|
class ExplosiveDeployableDefinition(private val objectId: Int) extends ComplexDeployableDefinition(objectId) {
|
|
Name = "explosive_deployable"
|
|
DeployCategory = DeployableCategory.Mines
|
|
Model = SimpleResolutions.calculate
|
|
Packet = new SmallDeployableConverter
|
|
|
|
private var detonateOnJamming: Boolean = true
|
|
|
|
def DetonateOnJamming: Boolean = detonateOnJamming
|
|
|
|
def DetonateOnJamming_=(detonate: Boolean): Boolean = {
|
|
detonateOnJamming = detonate
|
|
DetonateOnJamming
|
|
}
|
|
|
|
override def Initialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
|
|
obj.Actor =
|
|
context.actorOf(Props(classOf[ExplosiveDeployableControl], obj), PlanetSideServerObject.UniqueActorName(obj))
|
|
}
|
|
|
|
override def Uninitialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
|
|
SimpleDeployableDefinition.SimpleUninitialize(obj, context)
|
|
}
|
|
}
|
|
|
|
object ExplosiveDeployableDefinition {
|
|
def apply(dtype: DeployedItem.Value): ExplosiveDeployableDefinition = {
|
|
new ExplosiveDeployableDefinition(dtype.id)
|
|
}
|
|
}
|
|
|
|
class ExplosiveDeployableControl(mine: ExplosiveDeployable) extends Actor with Damageable {
|
|
def DamageableObject = mine
|
|
|
|
def receive: Receive =
|
|
takesDamage
|
|
.orElse {
|
|
case CommonMessages.Use(player, Some(trigger: BoomerTrigger)) if {
|
|
mine match {
|
|
case boomer: BoomerDeployable => boomer.Trigger.contains(trigger) && mine.Definition.Damageable
|
|
case _ => false
|
|
}
|
|
} =>
|
|
// the mine damages itself, which sets it off, which causes an explosion
|
|
// think of this as an initiator to the proper explosion
|
|
mine.Destroyed = true
|
|
ExplosiveDeployableControl.DamageResolution(
|
|
mine,
|
|
DamageInteraction(
|
|
SourceEntry(mine),
|
|
TriggerUsedReason(PlayerSource(player), trigger),
|
|
mine.Position
|
|
).calculate()(mine),
|
|
damage = 0
|
|
)
|
|
case _ => ;
|
|
}
|
|
|
|
override protected def PerformDamage(
|
|
target: Target,
|
|
applyDamageTo: Output
|
|
): Unit = {
|
|
if (mine.CanDamage) {
|
|
val originalHealth = mine.Health
|
|
val cause = applyDamageTo(mine)
|
|
val damage = originalHealth - mine.Health
|
|
if (Damageable.CanDamageOrJammer(mine, damage, cause.interaction)) {
|
|
ExplosiveDeployableControl.DamageResolution(mine, cause, damage)
|
|
} else {
|
|
mine.Health = originalHealth
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
object ExplosiveDeployableControl {
|
|
/**
|
|
* na
|
|
* @param target na
|
|
* @param cause na
|
|
* @param damage na
|
|
*/
|
|
def DamageResolution(target: ExplosiveDeployable, cause: DamageResult, damage: Int): Unit = {
|
|
target.History(cause)
|
|
if (cause.interaction.cause.source.SympatheticExplosion) {
|
|
explodes(target, cause)
|
|
DestructionAwareness(target, cause)
|
|
} else if (target.Health == 0) {
|
|
DestructionAwareness(target, cause)
|
|
} else if (!target.Jammed && Damageable.CanJammer(target, cause.interaction)) {
|
|
if ( {
|
|
target.Jammed = cause.interaction.cause match {
|
|
case o: ProjectileReason =>
|
|
val radius = o.projectile.profile.DamageRadius
|
|
Vector3.DistanceSquared(cause.interaction.hitPos, cause.interaction.target.Position) < radius * radius
|
|
case _ =>
|
|
true
|
|
}
|
|
}
|
|
) {
|
|
if (target.Definition.DetonateOnJamming) {
|
|
explodes(target, cause)
|
|
}
|
|
DestructionAwareness(target, cause)
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* na
|
|
* @param target na
|
|
* @param cause na
|
|
*/
|
|
def explodes(target: Damageable.Target, cause: DamageResult): Unit = {
|
|
target.Health = 1 // short-circuit logic in DestructionAwareness
|
|
val zone = target.Zone
|
|
zone.Activity ! Zone.HotSpot.Activity(cause)
|
|
zone.LocalEvents ! LocalServiceMessage(zone.id, LocalAction.Detonate(target.GUID, target))
|
|
Zone.causeExplosion(zone, target, Some(cause))
|
|
}
|
|
|
|
/**
|
|
* na
|
|
* @param target na
|
|
* @param cause na
|
|
*/
|
|
def DestructionAwareness(target: ExplosiveDeployable, cause: DamageResult): Unit = {
|
|
val zone = target.Zone
|
|
val attribution = DamageableEntity.attributionTo(cause, target.Zone)
|
|
Deployables.AnnounceDestroyDeployable(
|
|
target,
|
|
Some(if (target.Jammed || target.Destroyed) 0 seconds else 500 milliseconds)
|
|
)
|
|
target.Destroyed = true
|
|
zone.AvatarEvents ! AvatarServiceMessage(
|
|
zone.id,
|
|
AvatarAction.Destroy(target.GUID, attribution, Service.defaultPlayerGUID, target.Position)
|
|
)
|
|
if (target.Health == 0) {
|
|
zone.LocalEvents ! LocalServiceMessage(
|
|
zone.id,
|
|
LocalAction.TriggerEffect(Service.defaultPlayerGUID, "detonate_damaged_mine", target.GUID)
|
|
)
|
|
}
|
|
}
|
|
}
|