mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-12 15:04:39 +00:00
using the boomer trigger now causes boomers to explode and harm targets
This commit is contained in:
parent
c22033675e
commit
f557ecc13d
4 changed files with 138 additions and 26 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
add_property ace allowed false
|
add_property ace allowed true
|
||||||
add_property ace equiptime 500
|
add_property ace equiptime 500
|
||||||
add_property ace holstertime 500
|
add_property ace holstertime 500
|
||||||
add_property ace_deployable allowed false
|
add_property ace_deployable allowed true
|
||||||
add_property ace_deployable equiptime 500
|
add_property ace_deployable equiptime 500
|
||||||
add_property ace_deployable holstertime 500
|
add_property ace_deployable holstertime 500
|
||||||
add_property advanced_ace equiptime 750
|
add_property advanced_ace equiptime 750
|
||||||
|
|
|
||||||
|
|
@ -2184,6 +2184,17 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
if (player.HasGUID) player.GUID
|
if (player.HasGUID) player.GUID
|
||||||
else PlanetSideGUID(0)
|
else PlanetSideGUID(0)
|
||||||
reply match {
|
reply match {
|
||||||
|
case LocalResponse.AlertDestroyDeployable(obj: BoomerDeployable) =>
|
||||||
|
//the (former) owner (obj.OwnerName) should process this message
|
||||||
|
obj.Trigger match {
|
||||||
|
case Some(item: BoomerTrigger) =>
|
||||||
|
FindEquipmentToDelete(item.GUID, item)
|
||||||
|
item.Companion = None
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
avatar.deployables.Remove(obj)
|
||||||
|
UpdateDeployableUIElements(avatar.deployables.UpdateUIElement(obj.Definition.Item))
|
||||||
|
|
||||||
case LocalResponse.AlertDestroyDeployable(obj) =>
|
case LocalResponse.AlertDestroyDeployable(obj) =>
|
||||||
//the (former) owner (obj.OwnerName) should process this message
|
//the (former) owner (obj.OwnerName) should process this message
|
||||||
avatar.deployables.Remove(obj)
|
avatar.deployables.Remove(obj)
|
||||||
|
|
@ -2194,17 +2205,17 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
sendResponse(DeployableObjectsInfoMessage(behavior, deployInfo))
|
sendResponse(DeployableObjectsInfoMessage(behavior, deployInfo))
|
||||||
}
|
}
|
||||||
|
|
||||||
case LocalResponse.Detonate(guid, obj: BoomerDeployable) =>
|
case LocalResponse.Detonate(dguid, obj: BoomerDeployable) =>
|
||||||
sendResponse(TriggerEffectMessage(guid, "detonate_boomer"))
|
sendResponse(TriggerEffectMessage(dguid, "detonate_boomer"))
|
||||||
sendResponse(PlanetsideAttributeMessage(guid, 29, 1))
|
sendResponse(PlanetsideAttributeMessage(dguid, 29, 1))
|
||||||
sendResponse(ObjectDeleteMessage(guid, 0))
|
sendResponse(ObjectDeleteMessage(dguid, 0))
|
||||||
|
|
||||||
case LocalResponse.Detonate(guid, obj: ExplosiveDeployable) =>
|
case LocalResponse.Detonate(dguid, obj: ExplosiveDeployable) =>
|
||||||
sendResponse(GenericObjectActionMessage(guid, 19))
|
sendResponse(GenericObjectActionMessage(dguid, 19))
|
||||||
sendResponse(PlanetsideAttributeMessage(guid, 29, 1))
|
sendResponse(PlanetsideAttributeMessage(dguid, 29, 1))
|
||||||
sendResponse(ObjectDeleteMessage(guid, 0))
|
sendResponse(ObjectDeleteMessage(dguid, 0))
|
||||||
|
|
||||||
case LocalResponse.Detonate(guid, obj) =>
|
case LocalResponse.Detonate(_, obj) =>
|
||||||
log.warn(s"LocalResponse.Detonate: ${obj.Definition.Name} not configured to explode correctly")
|
log.warn(s"LocalResponse.Detonate: ${obj.Definition.Name} not configured to explode correctly")
|
||||||
|
|
||||||
case LocalResponse.DoorOpens(door_guid) =>
|
case LocalResponse.DoorOpens(door_guid) =>
|
||||||
|
|
@ -4039,13 +4050,9 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
)
|
)
|
||||||
continent.GUID(trigger.Companion) match {
|
continent.GUID(trigger.Companion) match {
|
||||||
case Some(boomer: BoomerDeployable) =>
|
case Some(boomer: BoomerDeployable) =>
|
||||||
boomer.Destroyed = true
|
boomer.Actor ! CommonMessages.Use(player, Some(trigger))
|
||||||
continent.LocalEvents ! LocalServiceMessage(continent.id, LocalAction.Detonate(boomer.GUID, boomer))
|
|
||||||
Deployables.AnnounceDestroyDeployable(boomer, Some(500 milliseconds))
|
|
||||||
case Some(_) | None => ;
|
case Some(_) | None => ;
|
||||||
}
|
}
|
||||||
FindEquipmentToDelete(item_guid, trigger)
|
|
||||||
trigger.Companion = None
|
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
progressBarUpdate.cancel()
|
progressBarUpdate.cancel()
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,18 @@
|
||||||
package net.psforever.objects
|
package net.psforever.objects
|
||||||
|
|
||||||
import akka.actor.{Actor, ActorContext, Props}
|
import akka.actor.{Actor, ActorContext, Props}
|
||||||
|
import net.psforever.objects.ballistics.{PlayerSource, SourceEntry}
|
||||||
import net.psforever.objects.ce._
|
import net.psforever.objects.ce._
|
||||||
import net.psforever.objects.definition.{ComplexDeployableDefinition, SimpleDeployableDefinition}
|
import net.psforever.objects.definition.{ComplexDeployableDefinition, SimpleDeployableDefinition}
|
||||||
import net.psforever.objects.definition.converter.SmallDeployableConverter
|
import net.psforever.objects.definition.converter.SmallDeployableConverter
|
||||||
import net.psforever.objects.equipment.JammableUnit
|
import net.psforever.objects.equipment.JammableUnit
|
||||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
|
||||||
import net.psforever.objects.serverobject.damage.{Damageable, DamageableEntity}
|
import net.psforever.objects.serverobject.damage.{Damageable, DamageableEntity}
|
||||||
import net.psforever.objects.serverobject.damage.Damageable.Target
|
import net.psforever.objects.serverobject.damage.Damageable.Target
|
||||||
import net.psforever.objects.vital.resolution.ResolutionCalculations.Output
|
import net.psforever.objects.vital.resolution.ResolutionCalculations.Output
|
||||||
import net.psforever.objects.vital.SimpleResolutions
|
import net.psforever.objects.vital.SimpleResolutions
|
||||||
import net.psforever.objects.vital.interaction.DamageResult
|
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.vital.projectile.ProjectileReason
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.types.Vector3
|
import net.psforever.types.Vector3
|
||||||
|
|
@ -21,7 +23,9 @@ import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||||
|
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
|
|
||||||
class ExplosiveDeployable(cdef: ExplosiveDeployableDefinition) extends ComplexDeployable(cdef) with JammableUnit {
|
class ExplosiveDeployable(cdef: ExplosiveDeployableDefinition)
|
||||||
|
extends ComplexDeployable(cdef)
|
||||||
|
with JammableUnit {
|
||||||
|
|
||||||
override def Definition: ExplosiveDeployableDefinition = cdef
|
override def Definition: ExplosiveDeployableDefinition = cdef
|
||||||
}
|
}
|
||||||
|
|
@ -63,6 +67,24 @@ class ExplosiveDeployableControl(mine: ExplosiveDeployable) extends Actor with D
|
||||||
def receive: Receive =
|
def receive: Receive =
|
||||||
takesDamage
|
takesDamage
|
||||||
.orElse {
|
.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 _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -84,9 +106,18 @@ class ExplosiveDeployableControl(mine: ExplosiveDeployable) extends Actor with D
|
||||||
}
|
}
|
||||||
|
|
||||||
object ExplosiveDeployableControl {
|
object ExplosiveDeployableControl {
|
||||||
|
/**
|
||||||
|
* na
|
||||||
|
* @param target na
|
||||||
|
* @param cause na
|
||||||
|
* @param damage na
|
||||||
|
*/
|
||||||
def DamageResolution(target: ExplosiveDeployable, cause: DamageResult, damage: Int): Unit = {
|
def DamageResolution(target: ExplosiveDeployable, cause: DamageResult, damage: Int): Unit = {
|
||||||
target.History(cause)
|
target.History(cause)
|
||||||
if (target.Health == 0) {
|
if (cause.interaction.cause.source.SympatheticExplosion) {
|
||||||
|
explodes(target, cause)
|
||||||
|
DestructionAwareness(target, cause)
|
||||||
|
} else if (target.Health == 0) {
|
||||||
DestructionAwareness(target, cause)
|
DestructionAwareness(target, cause)
|
||||||
} else if (!target.Jammed && Damageable.CanJammer(target, cause.interaction)) {
|
} else if (!target.Jammed && Damageable.CanJammer(target, cause.interaction)) {
|
||||||
if ( {
|
if ( {
|
||||||
|
|
@ -99,17 +130,27 @@ object ExplosiveDeployableControl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
if (cause.interaction.cause.source.SympatheticExplosion || target.Definition.DetonateOnJamming) {
|
if (target.Definition.DetonateOnJamming) {
|
||||||
val zone = target.Zone
|
explodes(target, cause)
|
||||||
zone.Activity ! Zone.HotSpot.Activity(cause)
|
|
||||||
zone.LocalEvents ! LocalServiceMessage(zone.id, LocalAction.Detonate(target.GUID, target))
|
|
||||||
Zone.causeExplosion(zone, target, Some(cause))
|
|
||||||
}
|
}
|
||||||
DestructionAwareness(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
|
* na
|
||||||
* @param target na
|
* @param target na
|
||||||
|
|
@ -118,8 +159,11 @@ object ExplosiveDeployableControl {
|
||||||
def DestructionAwareness(target: ExplosiveDeployable, cause: DamageResult): Unit = {
|
def DestructionAwareness(target: ExplosiveDeployable, cause: DamageResult): Unit = {
|
||||||
val zone = target.Zone
|
val zone = target.Zone
|
||||||
val attribution = DamageableEntity.attributionTo(cause, 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
|
target.Destroyed = true
|
||||||
Deployables.AnnounceDestroyDeployable(target, Some(if (target.Jammed) 0 seconds else 500 milliseconds))
|
|
||||||
zone.AvatarEvents ! AvatarServiceMessage(
|
zone.AvatarEvents ! AvatarServiceMessage(
|
||||||
zone.id,
|
zone.id,
|
||||||
AvatarAction.Destroy(target.GUID, attribution, Service.defaultPlayerGUID, target.Position)
|
AvatarAction.Destroy(target.GUID, attribution, Service.defaultPlayerGUID, target.Position)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
// Copyright (c) 2020 PSForever
|
||||||
|
package net.psforever.objects.vital.etc
|
||||||
|
|
||||||
|
import net.psforever.objects.BoomerTrigger
|
||||||
|
import net.psforever.objects.ballistics.{PlayerSource, SourceEntry}
|
||||||
|
import net.psforever.objects.vital.{NoResistanceSelection, SimpleResolutions}
|
||||||
|
import net.psforever.objects.vital.base.{DamageReason, DamageResolution}
|
||||||
|
import net.psforever.objects.vital.damage.DamageCalculations.AgainstExoSuit
|
||||||
|
import net.psforever.objects.vital.prop.DamageProperties
|
||||||
|
import net.psforever.objects.vital.resolution.{DamageAndResistance, DamageResistanceModel}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper for a "damage source" in damage calculations
|
||||||
|
* that parameterizes information necessary to explain a `BoomerDeployable` being detonated
|
||||||
|
* using its complementary trigger.
|
||||||
|
* Should be applied as the reason applied to the Boomer
|
||||||
|
* in `DamageInteractions` that lead up to the Boomer exploding
|
||||||
|
* which will carry the trigger as the reason and the user as the culprit.
|
||||||
|
* Due to faction affiliation complicity between the user and the Boomer, however,
|
||||||
|
* normal `Damageable` functionality would have to interject in a way where the trigger works anyway.
|
||||||
|
* @see `BoomerDeployable`
|
||||||
|
* @see `BoomerTrigger`
|
||||||
|
* @see `DamageCalculations`
|
||||||
|
* @see `VitalityDefinition.DamageableByFriendlyFire`
|
||||||
|
* @param user the player who is holding the trigger
|
||||||
|
* @param item the trigger
|
||||||
|
*/
|
||||||
|
final case class TriggerUsedReason(user: PlayerSource, item: BoomerTrigger)
|
||||||
|
extends DamageReason {
|
||||||
|
def source: DamageProperties = TriggerUsedReason.triggered
|
||||||
|
|
||||||
|
def resolution: DamageResolution.Value = DamageResolution.Resolved
|
||||||
|
|
||||||
|
def same(test: DamageReason): Boolean = test match {
|
||||||
|
case tur: TriggerUsedReason => tur.item eq item
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
|
||||||
|
/** lay the blame on the player who caused this explosion to occur */
|
||||||
|
def adversary: Option[SourceEntry] = Some(user)
|
||||||
|
|
||||||
|
override def damageModel : DamageAndResistance = TriggerUsedReason.drm
|
||||||
|
|
||||||
|
/** while weird, the trigger was accredited as the method of death on Gemini Live;
|
||||||
|
* even though its icon looks like an misshapen AMS */
|
||||||
|
override def attribution: Int = item.Definition.ObjectId
|
||||||
|
}
|
||||||
|
|
||||||
|
object TriggerUsedReason {
|
||||||
|
private val triggered = new DamageProperties {
|
||||||
|
Damage0 = 1 //token damage
|
||||||
|
SympatheticExplosion = true //sets off a boomer
|
||||||
|
}
|
||||||
|
|
||||||
|
/** basic damage, no resisting, quick and simple */
|
||||||
|
private val drm = new DamageResistanceModel {
|
||||||
|
DamageUsing = AgainstExoSuit
|
||||||
|
ResistUsing = NoResistanceSelection
|
||||||
|
Model = SimpleResolutions.calculate
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue