mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-02-28 18:53:37 +00:00
* pattern for applying damage to player avatar and player-controlled vehicle collisions * pattern for applying damage to targets due to collisions, falling damage and crashing damage individually; fields to support these calculations are provided * modifiers to translate 'small step velocity' to real game velocity, as reported by the HUD; corrections for velocity; corrections for velocity in other packets * fall damage calculations moved to function * basic two-body collisions between GUID-identified game entities and a ward against too many collisions in a short amount of time * bailing mechanics * vssm for non-driven vehicles * comment about vehicle state message field * comments and minor refactoring for current collision damage calc; tank_traps modifier; potential fix for blockmap indexing issue * fixed cargo/carrier vehicle ops * corrections to initialization of ce construction items; adjustments to handling of modifiers for collision damage * modifier change, protection against flight speed and spectator crashes; submerged status is once again known only to the actor * appeasing the automated tests * hopefully paced collisions better; re-did how Infantry collisions are calculated, incorporating mass and exo-suit data; kill feed reporting should be better * adjusted damage values again, focusing on the lesser of or middling results; collision killfeed attribution attempt * kicking offers bail protection; lowered the artificial modifier for one kind of collision damage calculation * correction to the local reference map functions * fixed tests; attempt to zero fall damage distance based on velocity; attempt to block mine damage when spectating
139 lines
5.1 KiB
Scala
139 lines
5.1 KiB
Scala
// Copyright (c) 2017 PSForever
|
|
package net.psforever.objects
|
|
|
|
import akka.actor.{Actor, ActorContext, Props}
|
|
import net.psforever.objects.ce.{Deployable, DeployableBehavior, DeployedItem}
|
|
import net.psforever.objects.definition.DeployableDefinition
|
|
import net.psforever.objects.definition.converter.SmallTurretConverter
|
|
import net.psforever.objects.equipment.{JammableMountedWeapons, JammableUnit}
|
|
import net.psforever.objects.guid.{GUIDTask, TaskWorkflow}
|
|
import net.psforever.objects.serverobject.PlanetSideServerObject
|
|
import net.psforever.objects.serverobject.affinity.FactionAffinityBehavior
|
|
import net.psforever.objects.serverobject.damage.Damageable.Target
|
|
import net.psforever.objects.serverobject.damage.DamageableWeaponTurret
|
|
import net.psforever.objects.serverobject.hackable.Hackable
|
|
import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior}
|
|
import net.psforever.objects.serverobject.repair.RepairableWeaponTurret
|
|
import net.psforever.objects.serverobject.turret.{TurretDefinition, WeaponTurret}
|
|
import net.psforever.objects.vital.damage.DamageCalculations
|
|
import net.psforever.objects.vital.interaction.DamageResult
|
|
import net.psforever.objects.vital.{SimpleResolutions, StandardVehicleResistance}
|
|
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
|
|
|
import scala.concurrent.duration.FiniteDuration
|
|
|
|
class TurretDeployable(tdef: TurretDeployableDefinition)
|
|
extends Deployable(tdef)
|
|
with WeaponTurret
|
|
with JammableUnit
|
|
with Hackable {
|
|
WeaponTurret.LoadDefinition(this)
|
|
|
|
override def Definition = tdef
|
|
}
|
|
|
|
class TurretDeployableDefinition(private val objectId: Int)
|
|
extends DeployableDefinition(objectId)
|
|
with TurretDefinition {
|
|
Name = "turret_deployable"
|
|
Packet = new SmallTurretConverter
|
|
DamageUsing = DamageCalculations.AgainstVehicle
|
|
ResistUsing = StandardVehicleResistance
|
|
Model = SimpleResolutions.calculate
|
|
|
|
//override to clarify inheritance conflict
|
|
override def MaxHealth: Int = super[DeployableDefinition].MaxHealth
|
|
//override to clarify inheritance conflict
|
|
override def MaxHealth_=(max: Int): Int = super[DeployableDefinition].MaxHealth_=(max)
|
|
|
|
override def Initialize(obj: Deployable, context: ActorContext) = {
|
|
obj.Actor = context.actorOf(Props(classOf[TurretControl], obj), PlanetSideServerObject.UniqueActorName(obj))
|
|
}
|
|
}
|
|
|
|
object TurretDeployableDefinition {
|
|
def apply(dtype: DeployedItem.Value): TurretDeployableDefinition = {
|
|
new TurretDeployableDefinition(dtype.id)
|
|
}
|
|
}
|
|
|
|
/** control actors */
|
|
|
|
class TurretControl(turret: TurretDeployable)
|
|
extends Actor
|
|
with DeployableBehavior
|
|
with FactionAffinityBehavior.Check
|
|
with JammableMountedWeapons //note: jammable status is reported as vehicle events, not local events
|
|
with MountableBehavior
|
|
with DamageableWeaponTurret
|
|
with RepairableWeaponTurret {
|
|
def DeployableObject = turret
|
|
def MountableObject = turret
|
|
def JammableObject = turret
|
|
def FactionObject = turret
|
|
def DamageableObject = turret
|
|
def RepairableObject = turret
|
|
|
|
override def postStop(): Unit = {
|
|
super.postStop()
|
|
deployableBehaviorPostStop()
|
|
damageableWeaponTurretPostStop()
|
|
}
|
|
|
|
def receive: Receive =
|
|
deployableBehavior
|
|
.orElse(checkBehavior)
|
|
.orElse(jammableBehavior)
|
|
.orElse(mountBehavior)
|
|
.orElse(dismountBehavior)
|
|
.orElse(takesDamage)
|
|
.orElse(canBeRepairedByNanoDispenser)
|
|
.orElse {
|
|
case _ => ;
|
|
}
|
|
|
|
override protected def mountTest(
|
|
obj: PlanetSideServerObject with Mountable,
|
|
seatNumber: Int,
|
|
player: Player): Boolean = {
|
|
(!turret.Definition.FactionLocked || player.Faction == obj.Faction) && !obj.Destroyed
|
|
}
|
|
|
|
override protected def DestructionAwareness(target: Target, cause: DamageResult): Unit = {
|
|
super.DestructionAwareness(target, cause)
|
|
CancelJammeredSound(target)
|
|
CancelJammeredStatus(target)
|
|
Deployables.AnnounceDestroyDeployable(turret, None)
|
|
}
|
|
|
|
override def deconstructDeployable(time: Option[FiniteDuration]) : Unit = {
|
|
val zone = turret.Zone
|
|
val seats = turret.Seats.values
|
|
//either we have no seats or no one gets to sit
|
|
val retime = if (seats.count(_.isOccupied) > 0) {
|
|
//unlike with vehicles, it's possible to request deconstruction of one's own field turret while seated in it
|
|
val wasKickedByDriver = false
|
|
seats.foreach { seat =>
|
|
seat.occupant match {
|
|
case Some(tplayer) =>
|
|
seat.unmount(tplayer)
|
|
tplayer.VehicleSeated = None
|
|
zone.VehicleEvents ! VehicleServiceMessage(
|
|
zone.id,
|
|
VehicleAction.KickPassenger(tplayer.GUID, 4, wasKickedByDriver, turret.GUID)
|
|
)
|
|
case None => ;
|
|
}
|
|
}
|
|
Some(time.getOrElse(Deployable.cleanup) + Deployable.cleanup)
|
|
} else {
|
|
time
|
|
}
|
|
super.deconstructDeployable(retime)
|
|
}
|
|
|
|
override def unregisterDeployable(obj: Deployable): Unit = {
|
|
val zone = obj.Zone
|
|
TaskWorkflow.execute(GUIDTask.unregisterDeployableTurret(zone.GUID, turret))
|
|
}
|
|
}
|