mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-16 00:44:43 +00:00
Merge pull request #1271 from ScrawnyRonnie/aircraft-bailing
The Pilot Goes Down With The Plane
This commit is contained in:
commit
b00f4283ab
9 changed files with 148 additions and 8 deletions
|
|
@ -297,6 +297,10 @@ class MountHandlerLogic(val ops: SessionMountHandlers, implicit val context: Act
|
||||||
sendResponse(ChatMsg(ChatMessageType.UNK_224, "@SA_CannotBailAtThisTime"))
|
sendResponse(ChatMsg(ChatMessageType.UNK_224, "@SA_CannotBailAtThisTime"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Mountable.CanNotDismount(obj: Vehicle, _, BailType.Bailed)
|
||||||
|
if obj.Health <= (obj.MaxHealth * .35).round && GlobalDefinitions.isFlightVehicle(obj.Definition) =>
|
||||||
|
sendResponse(ChatMsg(ChatMessageType.UNK_224, "@BailingMechanismFailure_Pilot"))
|
||||||
|
|
||||||
case Mountable.CanNotDismount(obj: Vehicle, _, BailType.Bailed)
|
case Mountable.CanNotDismount(obj: Vehicle, _, BailType.Bailed)
|
||||||
if {
|
if {
|
||||||
continent
|
continent
|
||||||
|
|
|
||||||
|
|
@ -312,6 +312,10 @@ class MountHandlerLogic(val ops: SessionMountHandlers, implicit val context: Act
|
||||||
if obj.DeploymentState == DriveState.AutoPilot =>
|
if obj.DeploymentState == DriveState.AutoPilot =>
|
||||||
sendResponse(ChatMsg(ChatMessageType.UNK_224, "@SA_CannotBailAtThisTime"))
|
sendResponse(ChatMsg(ChatMessageType.UNK_224, "@SA_CannotBailAtThisTime"))
|
||||||
|
|
||||||
|
case Mountable.CanNotDismount(obj: Vehicle, _, BailType.Bailed)
|
||||||
|
if obj.Health <= (obj.MaxHealth * .35).round && GlobalDefinitions.isFlightVehicle(obj.Definition) =>
|
||||||
|
sendResponse(ChatMsg(ChatMessageType.UNK_224, "@BailingMechanismFailure_Pilot"))
|
||||||
|
|
||||||
case Mountable.CanNotDismount(obj: Vehicle, _, BailType.Bailed)
|
case Mountable.CanNotDismount(obj: Vehicle, _, BailType.Bailed)
|
||||||
if {
|
if {
|
||||||
continent
|
continent
|
||||||
|
|
|
||||||
|
|
@ -202,10 +202,10 @@ class SessionMountHandlers(
|
||||||
//until vehicles maintain synchronized momentum without a driver
|
//until vehicles maintain synchronized momentum without a driver
|
||||||
obj match {
|
obj match {
|
||||||
case v: Vehicle
|
case v: Vehicle
|
||||||
if seatNum == 0 && Vector3.MagnitudeSquared(v.Velocity.getOrElse(Vector3.Zero)) > 0f =>
|
if seatNum == 0 =>
|
||||||
sessionLogic.vehicles.serverVehicleControlVelocity.collect { _ =>
|
/*sessionLogic.vehicles.serverVehicleControlVelocity.collect { _ =>
|
||||||
sessionLogic.vehicles.ServerVehicleOverrideStop(v)
|
sessionLogic.vehicles.ServerVehicleOverrideStop(v)
|
||||||
}
|
}*/
|
||||||
v.Velocity = Vector3.Zero
|
v.Velocity = Vector3.Zero
|
||||||
continent.VehicleEvents ! VehicleServiceMessage(
|
continent.VehicleEvents ! VehicleServiceMessage(
|
||||||
continent.id,
|
continent.id,
|
||||||
|
|
@ -213,9 +213,9 @@ class SessionMountHandlers(
|
||||||
tplayer.GUID,
|
tplayer.GUID,
|
||||||
v.GUID,
|
v.GUID,
|
||||||
unk1 = 0,
|
unk1 = 0,
|
||||||
v.Position,
|
tplayer.Position,
|
||||||
v.Orientation,
|
v.Orientation,
|
||||||
vel = None,
|
v.Velocity,
|
||||||
v.Flying,
|
v.Flying,
|
||||||
unk3 = 0,
|
unk3 = 0,
|
||||||
unk4 = 0,
|
unk4 = 0,
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,8 @@ object Players {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
target.Zone.AvatarEvents ! AvatarServiceMessage(name, AvatarAction.Revive(target.GUID))
|
target.Zone.AvatarEvents ! AvatarServiceMessage(name, AvatarAction.Revive(target.GUID))
|
||||||
|
val reviveMessage = s"@YouHaveBeenMessage^revived~^$medicName~"
|
||||||
|
PlayerControl.sendResponse(target.Zone, name, ChatMsg(ChatMessageType.UNK_227, reviveMessage))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import akka.actor.{Actor, ActorRef, Props, typed}
|
||||||
import net.psforever.actors.session.AvatarActor
|
import net.psforever.actors.session.AvatarActor
|
||||||
import net.psforever.login.WorldSession.{DropEquipmentFromInventory, HoldNewEquipmentUp, PutNewEquipmentInInventoryOrDrop, RemoveOldEquipmentFromInventory}
|
import net.psforever.login.WorldSession.{DropEquipmentFromInventory, HoldNewEquipmentUp, PutNewEquipmentInInventoryOrDrop, RemoveOldEquipmentFromInventory}
|
||||||
import net.psforever.objects._
|
import net.psforever.objects._
|
||||||
|
import net.psforever.objects.avatar.PlayerControl.sendResponse
|
||||||
import net.psforever.objects.ce.Deployable
|
import net.psforever.objects.ce.Deployable
|
||||||
import net.psforever.objects.definition.DeployAnimation
|
import net.psforever.objects.definition.DeployAnimation
|
||||||
import net.psforever.objects.definition.converter.OCM
|
import net.psforever.objects.definition.converter.OCM
|
||||||
|
|
@ -147,6 +148,15 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
|
||||||
newHealth - originalHealth
|
newHealth - originalHealth
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
val amount = newHealth - originalHealth
|
||||||
|
val healMessageSelf = s"@SelfHitHealedMessage^healed~^$amount~^health~"
|
||||||
|
val healMessageOther = s"@WereHitByHealedMessage^healed~^$amount~^health~^$uname~"
|
||||||
|
if (player == user) {
|
||||||
|
sendResponse(user.Zone, user.Name, ChatMsg(ChatMessageType.UNK_227, healMessageSelf))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sendResponse(player.Zone, player.Name, ChatMsg(ChatMessageType.UNK_227, healMessageOther))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (player != user) {
|
if (player != user) {
|
||||||
//"Someone is trying to heal you"
|
//"Someone is trying to heal you"
|
||||||
|
|
@ -210,6 +220,15 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
|
||||||
newArmor - originalArmor
|
newArmor - originalArmor
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
val amount = newArmor - originalArmor
|
||||||
|
val repairMessageSelf = s"@SelfHitHealedMessage^repaired~^$amount~^armor~"
|
||||||
|
val repairMessageOther = s"@WereHitByHealedMessage^repaired~^$amount~^armor~^$uname~"
|
||||||
|
if (player == user) {
|
||||||
|
sendResponse(user.Zone, user.Name, ChatMsg(ChatMessageType.UNK_227, repairMessageSelf))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sendResponse(player.Zone, player.Name, ChatMsg(ChatMessageType.UNK_227, repairMessageOther))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (player != user) {
|
if (player != user) {
|
||||||
if (player.isAlive) {
|
if (player.isAlive) {
|
||||||
|
|
|
||||||
|
|
@ -192,6 +192,10 @@ class GeneratorControl(gen: Generator)
|
||||||
if(newHealth == target.Definition.MaxHealth) {
|
if(newHealth == target.Definition.MaxHealth) {
|
||||||
stopAutoRepair()
|
stopAutoRepair()
|
||||||
}
|
}
|
||||||
|
if(gen.Condition == PlanetSideGeneratorState.Critical && newHealth > (target.MaxHealth / 2)) {
|
||||||
|
gen.Condition = PlanetSideGeneratorState.Normal
|
||||||
|
GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Normal))
|
||||||
|
}
|
||||||
newHealth
|
newHealth
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
//Copyright (c) 2020 PSForever
|
//Copyright (c) 2020 PSForever
|
||||||
package net.psforever.objects.serverobject.repair
|
package net.psforever.objects.serverobject.repair
|
||||||
|
|
||||||
|
import net.psforever.objects.avatar.PlayerControl.sendResponse
|
||||||
|
import net.psforever.objects.ce.DeployableCategory
|
||||||
import net.psforever.objects.sourcing.PlayerSource
|
import net.psforever.objects.sourcing.PlayerSource
|
||||||
import net.psforever.objects.vital.RepairFromEquipment
|
import net.psforever.objects.vital.RepairFromEquipment
|
||||||
import net.psforever.objects.{Player, Tool}
|
import net.psforever.objects.{Player, Tool}
|
||||||
import net.psforever.packet.game.{InventoryStateMessage, RepairMessage}
|
import net.psforever.packet.game.{ChatMsg, InventoryStateMessage, RepairMessage}
|
||||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
import net.psforever.types.{ChatMessageType, PlanetSideEmpire, Vector3}
|
||||||
import net.psforever.services.Service
|
import net.psforever.services.Service
|
||||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||||
|
|
||||||
|
|
@ -113,6 +115,27 @@ trait RepairableEntity extends Repairable {
|
||||||
RepairMessage(target.GUID, updatedHealth * 100 / definition.MaxHealth)
|
RepairMessage(target.GUID, updatedHealth * 100 / definition.MaxHealth)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
//if vehicle and vehicle is owned by another player, send repair chat message to the vehicle's owner
|
||||||
|
if (target.Zone.Vehicles.exists(_.GUID == target.GUID)) {
|
||||||
|
val vehicle = target.Zone.Vehicles.filter(_.GUID == target.GUID).head
|
||||||
|
val vehicleOwner = vehicle.OwnerName.getOrElse("someone")
|
||||||
|
val amount = updatedHealth - originalHealth
|
||||||
|
if (vehicleOwner != "someone" && vehicle.OwnerGuid.get != player.GUID && amount > 0) {
|
||||||
|
val repairMessageOther = s"@YourWasHealedMessage^@${vehicle.Definition.Name}~^repaired~^$amount~^armor~^${player.Name}~"
|
||||||
|
sendResponse(vehicle.Zone, vehicleOwner, ChatMsg(ChatMessageType.UNK_227, repairMessageOther))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//same check for field turret
|
||||||
|
if (target.Zone.DeployableList.exists(_.GUID == target.GUID)) {
|
||||||
|
val turret = target.Zone.DeployableList.filter(_.GUID == target.GUID).head
|
||||||
|
val turretOwner = turret.OwnerName.getOrElse("someone")
|
||||||
|
val amount = updatedHealth - originalHealth
|
||||||
|
if (turret.Definition.DeployCategory == DeployableCategory.FieldTurrets && turretOwner != "someone"
|
||||||
|
&& turret.OwnerGuid.get != player.GUID && amount > 0) {
|
||||||
|
val repairMessageOther = s"@YourWasHealedMessage^@${turret.Definition.Name}~^repaired~^$amount~^armor~^${player.Name}~"
|
||||||
|
sendResponse(turret.Zone, turretOwner, ChatMsg(ChatMessageType.UNK_227, repairMessageOther))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected def PerformRepairs(target: Repairable.Target, amount: Int): Int = {
|
protected def PerformRepairs(target: Repairable.Target, amount: Int): Int = {
|
||||||
|
|
|
||||||
|
|
@ -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.{InGameActivity, ShieldCharge, SpawningActivity, VehicleDismountActivity, VehicleMountActivity}
|
import net.psforever.objects.vital.{DamagingActivity, 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._
|
||||||
|
|
@ -39,6 +39,7 @@ import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||||
|
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
|
import scala.util.Random
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An `Actor` that handles messages being dispatched to a specific `Vehicle`.<br>
|
* An `Actor` that handles messages being dispatched to a specific `Vehicle`.<br>
|
||||||
|
|
@ -140,6 +141,36 @@ class VehicleControl(vehicle: Vehicle)
|
||||||
}) =>
|
}) =>
|
||||||
sender() ! Mountable.MountMessages(user, Mountable.CanNotDismount(vehicle, seat_num, bailType))
|
sender() ! Mountable.MountMessages(user, Mountable.CanNotDismount(vehicle, seat_num, bailType))
|
||||||
|
|
||||||
|
case Mountable.TryDismount(user, seat_num, bailType)
|
||||||
|
if vehicle.Health <= (vehicle.Definition.MaxHealth * .1).round && bailType == BailType.Bailed
|
||||||
|
&& GlobalDefinitions.isFlightVehicle(vehicle.Definition)
|
||||||
|
&& (seat_num == 0 || vehicle.SeatPermissionGroup(seat_num).getOrElse(0) == AccessPermissionGroup.Gunner)
|
||||||
|
&& (vehicle.History.findLast { entry => entry.isInstanceOf[DamagingActivity] } match {
|
||||||
|
case Some(entry) if System.currentTimeMillis() - entry.time < 4000L => true
|
||||||
|
case _ if Random.nextInt(10) == 1 => false
|
||||||
|
case _ => true }) =>
|
||||||
|
sender() ! Mountable.MountMessages(user, Mountable.CanNotDismount(vehicle, seat_num, bailType))
|
||||||
|
|
||||||
|
case Mountable.TryDismount(user, seat_num, bailType)
|
||||||
|
if vehicle.Health <= (vehicle.Definition.MaxHealth * .2).round && bailType == BailType.Bailed
|
||||||
|
&& GlobalDefinitions.isFlightVehicle(vehicle.Definition)
|
||||||
|
&& (seat_num == 0 || vehicle.SeatPermissionGroup(seat_num).getOrElse(0) == AccessPermissionGroup.Gunner)
|
||||||
|
&& (vehicle.History.findLast { entry => entry.isInstanceOf[DamagingActivity] } match {
|
||||||
|
case Some(entry) if System.currentTimeMillis() - entry.time < 3500L => true
|
||||||
|
case _ if Random.nextInt(5) == 1 => false
|
||||||
|
case _ => true }) =>
|
||||||
|
sender() ! Mountable.MountMessages(user, Mountable.CanNotDismount(vehicle, seat_num, bailType))
|
||||||
|
|
||||||
|
case Mountable.TryDismount(user, seat_num, bailType)
|
||||||
|
if vehicle.Health <= (vehicle.Definition.MaxHealth * .35).round && bailType == BailType.Bailed
|
||||||
|
&& GlobalDefinitions.isFlightVehicle(vehicle.Definition)
|
||||||
|
&& (seat_num == 0 || vehicle.SeatPermissionGroup(seat_num).getOrElse(0) == AccessPermissionGroup.Gunner)
|
||||||
|
&& (vehicle.History.findLast { entry => entry.isInstanceOf[DamagingActivity] } match {
|
||||||
|
case Some(entry) if System.currentTimeMillis() - entry.time < 3000L => true
|
||||||
|
case _ if Random.nextInt(4) == 1 => false
|
||||||
|
case _ => true }) =>
|
||||||
|
sender() ! Mountable.MountMessages(user, Mountable.CanNotDismount(vehicle, seat_num, bailType))
|
||||||
|
|
||||||
case Mountable.TryDismount(user, seat_num, bailType)
|
case Mountable.TryDismount(user, seat_num, bailType)
|
||||||
if vehicle.DeploymentState == DriveState.AutoPilot =>
|
if vehicle.DeploymentState == DriveState.AutoPilot =>
|
||||||
sender() ! Mountable.MountMessages(user, Mountable.CanNotDismount(vehicle, seat_num, bailType))
|
sender() ! Mountable.MountMessages(user, Mountable.CanNotDismount(vehicle, seat_num, bailType))
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ import net.psforever.services.local.support.HackCaptureActor.GetHackingFaction
|
||||||
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||||
import net.psforever.types.{ChatMessageType, PlanetSideEmpire, PlanetSideGUID}
|
import net.psforever.types.{ChatMessageType, PlanetSideEmpire, PlanetSideGUID}
|
||||||
|
|
||||||
|
import java.util.concurrent.{Executors, TimeUnit}
|
||||||
|
import scala.collection.Seq
|
||||||
import scala.concurrent.duration.{FiniteDuration, _}
|
import scala.concurrent.duration.{FiniteDuration, _}
|
||||||
import scala.util.Random
|
import scala.util.Random
|
||||||
|
|
||||||
|
|
@ -30,6 +32,7 @@ class HackCaptureActor extends Actor {
|
||||||
private var clearTrigger: Cancellable = Default.Cancellable
|
private var clearTrigger: Cancellable = Default.Cancellable
|
||||||
/** list of currently hacked server objects */
|
/** list of currently hacked server objects */
|
||||||
private var hackedObjects: List[HackCaptureActor.HackEntry] = Nil
|
private var hackedObjects: List[HackCaptureActor.HackEntry] = Nil
|
||||||
|
private val scheduler = Executors.newScheduledThreadPool(2)
|
||||||
|
|
||||||
def receive: Receive = {
|
def receive: Receive = {
|
||||||
case HackCaptureActor.StartCaptureTerminalHack(target, _, _, _, _)
|
case HackCaptureActor.StartCaptureTerminalHack(target, _, _, _, _)
|
||||||
|
|
@ -266,6 +269,19 @@ class HackCaptureActor extends Actor {
|
||||||
.collect { case p if p.Faction == hackedByFaction =>
|
.collect { case p if p.Faction == hackedByFaction =>
|
||||||
events ! LocalServiceMessage(p.Name, msg)
|
events ! LocalServiceMessage(p.Name, msg)
|
||||||
}
|
}
|
||||||
|
val zoneBases = building.Zone.Buildings.filter(base =>
|
||||||
|
base._2.BuildingType == StructureType.Facility)
|
||||||
|
val ownedBases = building.Zone.Buildings.filter(base =>
|
||||||
|
base._2.BuildingType == StructureType.Facility && base._2.Faction == hackedByFaction
|
||||||
|
&& base._2.GUID != building.GUID)
|
||||||
|
val zoneTowers = building.Zone.Buildings.filter(tower =>
|
||||||
|
tower._2.BuildingType == StructureType.Tower && tower._2.Faction != hackedByFaction)
|
||||||
|
// All major facilities in zone are now owned by the hacking faction. Capture all towers in the zone
|
||||||
|
// Base that was just hacked is not counted (hence the size - 1) because it wasn't always in ownedBases (async?)
|
||||||
|
if (zoneBases.size - 1 == ownedBases.size && zoneTowers.nonEmpty)
|
||||||
|
{
|
||||||
|
processBuildingsWithDelay(zoneTowers.values.toSeq, hackedByFaction, 1000)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log.info("Base hack completed, but base was out of NTU.")
|
log.info("Base hack completed, but base was out of NTU.")
|
||||||
}
|
}
|
||||||
|
|
@ -283,6 +299,43 @@ class HackCaptureActor extends Actor {
|
||||||
clearTrigger = context.system.scheduler.scheduleOnce(short_timeout, self, HackCaptureActor.ProcessCompleteHacks())
|
clearTrigger = context.system.scheduler.scheduleOnce(short_timeout, self, HackCaptureActor.ProcessCompleteHacks())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def processBuildingsWithDelay(
|
||||||
|
buildings: Seq[Building],
|
||||||
|
faction: PlanetSideEmpire.Value,
|
||||||
|
delayMillis: Long
|
||||||
|
): Unit = {
|
||||||
|
val buildingIterator = buildings.iterator
|
||||||
|
scheduler.scheduleAtFixedRate(
|
||||||
|
() => {
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
delayMillis,
|
||||||
|
TimeUnit.MILLISECONDS
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object HackCaptureActor {
|
object HackCaptureActor {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue