mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-20 02:54:46 +00:00
field turrets are neutral-neutral when constructed by a csr; custom bang command 'setempire' will adjust the faction affiliation of a variety of game objects
This commit is contained in:
parent
7e5c923fec
commit
d03954d6a6
|
|
@ -5,13 +5,20 @@ import akka.actor.ActorContext
|
|||
import net.psforever.actors.session.SessionActor
|
||||
import net.psforever.actors.session.normal.NormalMode
|
||||
import net.psforever.actors.session.support.{ChatFunctions, ChatOperations, SessionData}
|
||||
import net.psforever.objects.Session
|
||||
import net.psforever.objects.{GlobalDefinitions, PlanetSideGameObject, Session, TurretDeployable}
|
||||
import net.psforever.objects.ce.{Deployable, DeployableCategory}
|
||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
|
||||
import net.psforever.objects.serverobject.hackable.Hackable
|
||||
import net.psforever.objects.serverobject.structures.Building
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game.{ChatMsg, SetChatFilterMessage}
|
||||
import net.psforever.services.Service
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
import net.psforever.services.chat.{ChatChannel, DefaultChannel, SpectatorChannel}
|
||||
import net.psforever.types.ChatMessageType
|
||||
import net.psforever.types.{ChatMessageType, PlanetSideEmpire}
|
||||
|
||||
import scala.util.Success
|
||||
|
||||
object ChatLogic {
|
||||
def apply(ops: ChatOperations): ChatLogic = {
|
||||
|
|
@ -207,6 +214,7 @@ class ChatLogic(val ops: ChatOperations, implicit val context: ActorContext) ext
|
|||
case "showspectators" => customCommandShowSpectators()
|
||||
case "hidespectators" => customCommandHideSpectators()
|
||||
case "sayspectator" => customCommandSpeakAsSpectator(params, message)
|
||||
case "setempire" => customCommandSetEmpire(params)
|
||||
case _ =>
|
||||
// command was not handled
|
||||
sendResponse(
|
||||
|
|
@ -309,6 +317,78 @@ class ChatLogic(val ops: ChatOperations, implicit val context: ActorContext) ext
|
|||
true
|
||||
}
|
||||
|
||||
private def customCommandSetEmpire(params: Seq[String]): Boolean = {
|
||||
var postUsage: Boolean = false
|
||||
val (entityOpt, foundFaction) = (params.headOption, params.lift(1)) match {
|
||||
case (Some(guid), Some(faction)) if guid.toIntOption.nonEmpty =>
|
||||
try {
|
||||
(continent.GUID(guid.toInt), PlanetSideEmpire.apply(faction))
|
||||
} catch {
|
||||
case _: Exception =>
|
||||
(None, PlanetSideEmpire.NEUTRAL)
|
||||
}
|
||||
case (Some(guid), None) if guid.toIntOption.nonEmpty =>
|
||||
(continent.GUID(guid.toInt), player.Faction)
|
||||
case _ =>
|
||||
postUsage = true
|
||||
(None, PlanetSideEmpire.NEUTRAL)
|
||||
}
|
||||
entityOpt
|
||||
.collect {
|
||||
case f: FactionAffinity if f.Faction != foundFaction && foundFaction != PlanetSideEmpire.NEUTRAL => f
|
||||
}
|
||||
.collect {
|
||||
case o: TurretDeployable
|
||||
if o.Definition.DeployCategory == DeployableCategory.FieldTurrets =>
|
||||
//remove prior turret and construct new one
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
import scala.concurrent.duration._
|
||||
o.Actor ! Deployable.Deconstruct(Some(2.seconds))
|
||||
sessionLogic.general.handleDeployObject(
|
||||
continent,
|
||||
GlobalDefinitions.PortableMannedTurret(foundFaction).Item,
|
||||
o.Position,
|
||||
o.Orientation,
|
||||
o.WhichSide,
|
||||
foundFaction
|
||||
).onComplete {
|
||||
case Success(obj2) => sendResponse(ChatMsg(ChatMessageType.UNK_227, s"${obj2.GUID.guid}"))
|
||||
case _ => ()
|
||||
}
|
||||
true
|
||||
case o: Deployable =>
|
||||
o.Faction = foundFaction
|
||||
continent.AvatarEvents ! AvatarServiceMessage(
|
||||
continent.id,
|
||||
AvatarAction.SetEmpire(Service.defaultPlayerGUID, o.GUID, foundFaction)
|
||||
)
|
||||
true
|
||||
case o: Building =>
|
||||
ops.commandCaptureBaseProcessResults(Some(Seq(o)), Some(foundFaction), Some(1))
|
||||
true
|
||||
case o: PlanetSideServerObject with Hackable =>
|
||||
o.Actor ! CommonMessages.Hack(player, o)
|
||||
true
|
||||
case o: PlanetSideGameObject with FactionAffinity =>
|
||||
o.Faction = foundFaction
|
||||
continent.AvatarEvents ! AvatarServiceMessage(
|
||||
continent.id,
|
||||
AvatarAction.SetEmpire(Service.defaultPlayerGUID, o.GUID, foundFaction)
|
||||
)
|
||||
true
|
||||
}
|
||||
.getOrElse {
|
||||
if (postUsage) {
|
||||
sendResponse(ChatMsg(ChatMessageType.UNK_227, "!setempire guid [faction]"))
|
||||
} else if (entityOpt.nonEmpty) {
|
||||
sendResponse(ChatMsg(ChatMessageType.UNK_227, "set empire entity not supported"))
|
||||
} else {
|
||||
sendResponse(ChatMsg(ChatMessageType.UNK_227, "set empire entity not found"))
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override def stop(): Unit = {
|
||||
super.stop()
|
||||
seeSpectatorsIn.foreach(_ => customCommandHideSpectators())
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import net.psforever.actors.session.support.{GeneralFunctions, GeneralOperations
|
|||
import net.psforever.objects.{Account, BoomerDeployable, BoomerTrigger, ConstructionItem, GlobalDefinitions, LivePlayerList, Player, SensorDeployable, ShieldGeneratorDeployable, SpecialEmp, TelepadDeployable, Tool, TrapDeployable, TurretDeployable, Vehicle}
|
||||
import net.psforever.objects.avatar.{Avatar, PlayerControl}
|
||||
import net.psforever.objects.ballistics.Projectile
|
||||
import net.psforever.objects.ce.{Deployable, DeployedItem}
|
||||
import net.psforever.objects.ce.Deployable
|
||||
import net.psforever.objects.definition.{BasicDefinition, KitDefinition, SpecialExoSuitDefinition}
|
||||
import net.psforever.objects.entity.WorldEntity
|
||||
import net.psforever.objects.equipment.Equipment
|
||||
|
|
@ -30,10 +30,12 @@ import net.psforever.objects.vehicles.Utility
|
|||
import net.psforever.objects.vital.Vitality
|
||||
import net.psforever.objects.zones.{ZoneProjectile, Zoning}
|
||||
import net.psforever.packet.PlanetSideGamePacket
|
||||
import net.psforever.packet.game.{ActionCancelMessage, AvatarFirstTimeEventMessage, AvatarImplantMessage, AvatarJumpMessage, BattleplanMessage, BindPlayerMessage, BugReportMessage, ChangeFireModeMessage, ChangeShortcutBankMessage, CharacterCreateRequestMessage, CharacterRequestMessage, CollisionIs, ConnectToWorldRequestMessage, CreateShortcutMessage, DeadState, DeployObjectMessage, DisplayedAwardMessage, DropItemMessage, EmoteMsg, FacilityBenefitShieldChargeRequestMessage, FriendsRequest, GenericAction, GenericActionMessage, GenericCollisionMsg, GenericObjectActionAtPositionMessage, GenericObjectActionMessage, GenericObjectStateMsg, HitHint, InvalidTerrainMessage, LootItemMessage, MoveItemMessage, ObjectDetectedMessage, ObjectHeldMessage, PickupItemMessage, PlanetsideAttributeMessage, PlayerStateMessageUpstream, RequestDestroyMessage, TargetingImplantRequest, TerrainCondition, TradeMessage, UnuseItemMessage, UseItemMessage, VoiceHostInfo, VoiceHostRequest, ZipLineMessage}
|
||||
import net.psforever.packet.game.{ActionCancelMessage, AvatarFirstTimeEventMessage, AvatarImplantMessage, AvatarJumpMessage, BattleplanMessage, BindPlayerMessage, BugReportMessage, ChangeFireModeMessage, ChangeShortcutBankMessage, CharacterCreateRequestMessage, CharacterRequestMessage, ChatMsg, CollisionIs, ConnectToWorldRequestMessage, CreateShortcutMessage, DeadState, DeployObjectMessage, DisplayedAwardMessage, DropItemMessage, EmoteMsg, FacilityBenefitShieldChargeRequestMessage, FriendsRequest, GenericAction, GenericActionMessage, GenericCollisionMsg, GenericObjectActionAtPositionMessage, GenericObjectActionMessage, GenericObjectStateMsg, HitHint, InvalidTerrainMessage, LootItemMessage, MoveItemMessage, ObjectDetectedMessage, ObjectHeldMessage, PickupItemMessage, PlanetsideAttributeMessage, PlayerStateMessageUpstream, RequestDestroyMessage, TargetingImplantRequest, TerrainCondition, TradeMessage, UnuseItemMessage, UseItemMessage, VoiceHostInfo, VoiceHostRequest, ZipLineMessage}
|
||||
import net.psforever.services.RemoverActor
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
import net.psforever.types.{CapacitorStateType, Cosmetic, ExoSuitType, PlanetSideEmpire, PlanetSideGUID, Vector3}
|
||||
import net.psforever.types.{CapacitorStateType, ChatMessageType, Cosmetic, ExoSuitType, PlanetSideEmpire, PlanetSideGUID, Vector3}
|
||||
|
||||
import scala.util.Success
|
||||
|
||||
object GeneralLogic {
|
||||
def apply(ops: GeneralOperations): GeneralLogic = {
|
||||
|
|
@ -354,15 +356,16 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
|
|||
|
||||
def handleDeployObject(pkt: DeployObjectMessage): Unit = {
|
||||
if (!player.spectator) {
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
val DeployObjectMessage(guid, _, pos, orient, _) = pkt
|
||||
player.Holsters().find(slot => slot.Equipment.nonEmpty && slot.Equipment.get.GUID == guid).flatMap { slot => slot.Equipment } match {
|
||||
case Some(obj: ConstructionItem) =>
|
||||
val ammoType = obj.AmmoType match {
|
||||
case DeployedItem.portable_manned_turret => GlobalDefinitions.PortableMannedTurret(player.Faction).Item
|
||||
case dtype => dtype
|
||||
}
|
||||
sessionLogic.zoning.CancelZoningProcess()
|
||||
ops.handleDeployObject(continent, ammoType, pos, orient, player.WhichSide, PlanetSideEmpire.NEUTRAL)
|
||||
val result = ops.handleDeployObject(continent, obj.AmmoType, pos, orient, player.WhichSide, PlanetSideEmpire.NEUTRAL)
|
||||
result.onComplete {
|
||||
case Success(obj) => sendResponse(ChatMsg(ChatMessageType.UNK_227, s"${obj.GUID.guid}"))
|
||||
case _ => ()
|
||||
}
|
||||
case Some(obj) =>
|
||||
log.warn(s"DeployObject: what is $obj, ${player.Name}? It's not a construction tool!")
|
||||
case None =>
|
||||
|
|
|
|||
|
|
@ -327,6 +327,28 @@ class ChatOperations(
|
|||
}
|
||||
}
|
||||
//evaluate results
|
||||
if (!commandCaptureBaseProcessResults(resolvedFacilities, resolvedFaction, resolvedTimer)) {
|
||||
if (usageMessage) {
|
||||
sendResponse(
|
||||
message.copy(messageType = UNK_229, contents = "@CMT_CAPTUREBASE_usage")
|
||||
)
|
||||
} else {
|
||||
val msg = if (facilityError == 1) { "can not contextually determine building target" }
|
||||
else if (facilityError == 2) { s"\'${foundFacilitiesTag.get}\' is not a valid building name" }
|
||||
else if (factionError) { s"\'${foundFactionTag.get}\' is not a valid faction designation" }
|
||||
else if (timerError) { s"\'${foundTimerTag.get}\' is not a valid timer value" }
|
||||
else { "malformed params; check usage" }
|
||||
sendResponse(ChatMsg(UNK_229, wideContents=true, "", s"\\#FF4040ERROR - $msg", None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def commandCaptureBaseProcessResults(
|
||||
resolvedFacilities: Option[Seq[Building]],
|
||||
resolvedFaction: Option[PlanetSideEmpire.Value],
|
||||
resolvedTimer: Option[Int]
|
||||
): Boolean = {
|
||||
//evaluate results
|
||||
(resolvedFacilities, resolvedFaction, resolvedTimer) match {
|
||||
case (Some(buildings), Some(faction), Some(_)) =>
|
||||
buildings.foreach { building =>
|
||||
|
|
@ -350,19 +372,9 @@ class ChatOperations(
|
|||
//push for map updates again
|
||||
zoneActor ! ZoneActor.ZoneMapUpdate()
|
||||
}
|
||||
true
|
||||
case _ =>
|
||||
if (usageMessage) {
|
||||
sendResponse(
|
||||
message.copy(messageType = UNK_229, contents = "@CMT_CAPTUREBASE_usage")
|
||||
)
|
||||
} else {
|
||||
val msg = if (facilityError == 1) { "can not contextually determine building target" }
|
||||
else if (facilityError == 2) { s"\'${foundFacilitiesTag.get}\' is not a valid building name" }
|
||||
else if (factionError) { s"\'${foundFactionTag.get}\' is not a valid faction designation" }
|
||||
else if (timerError) { s"\'${foundTimerTag.get}\' is not a valid timer value" }
|
||||
else { "malformed params; check usage" }
|
||||
sendResponse(ChatMsg(UNK_229, wideContents=true, "", s"\\#FF4040ERROR - $msg", None))
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@ import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
|||
|
||||
import scala.collection.mutable
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
import scala.concurrent.{Future, Promise}
|
||||
import scala.concurrent.duration._
|
||||
import scala.util.Success
|
||||
//
|
||||
import net.psforever.actors.session.{AvatarActor, SessionActor}
|
||||
import net.psforever.login.WorldSession._
|
||||
|
|
@ -1060,16 +1062,22 @@ class GeneralOperations(
|
|||
faction: PlanetSideEmpire.Value,
|
||||
owner: Player,
|
||||
builtWith: ConstructionItem
|
||||
): Unit = {
|
||||
): Future[Deployable] = {
|
||||
val (deployableEntity, tasking) = commonHandleDeployObjectSetup(zone, deployableType, position, orientation, side, faction)
|
||||
deployableEntity.AssignOwnership(owner)
|
||||
val promisedDeployable: Promise[Deployable] = Promise()
|
||||
//execute
|
||||
TaskWorkflow.execute(CallBackForTask(
|
||||
val result = TaskWorkflow.execute(CallBackForTask(
|
||||
tasking,
|
||||
zone.Deployables,
|
||||
Zone.Deployable.BuildByOwner(deployableEntity, owner, builtWith),
|
||||
context.self
|
||||
))
|
||||
result.onComplete {
|
||||
case Success(_) => promisedDeployable.success(deployableEntity)
|
||||
case _ => ()
|
||||
}
|
||||
promisedDeployable.future
|
||||
}
|
||||
|
||||
def handleDeployObject(
|
||||
|
|
@ -1079,16 +1087,18 @@ class GeneralOperations(
|
|||
orientation: Vector3,
|
||||
side: Sidedness,
|
||||
faction: PlanetSideEmpire.Value
|
||||
): Unit = {
|
||||
): Future[Deployable] = {
|
||||
val (deployableEntity, tasking) = commonHandleDeployObjectSetup(zone, deployableType, position, orientation, side, faction)
|
||||
val promisedDeployable: Promise[Deployable] = Promise()
|
||||
//execute
|
||||
TaskWorkflow.execute(CallBackForTask(
|
||||
val result = TaskWorkflow.execute(CallBackForTask(
|
||||
tasking,
|
||||
zone.Deployables,
|
||||
Zone.Deployable.Build(deployableEntity),
|
||||
context.self
|
||||
)).onComplete {
|
||||
_ =>
|
||||
))
|
||||
result.onComplete {
|
||||
case Success(_) =>
|
||||
Players.buildCooldownReset(zone, player.Name, deployableEntity.GUID)
|
||||
deployableEntity.Actor ! Deployable.Deconstruct(Some(20.minutes))
|
||||
if (deployableType == DeployedItem.boomer) {
|
||||
|
|
@ -1101,7 +1111,10 @@ class GeneralOperations(
|
|||
Zone.Ground.DropItem(trigger, position + Vector3.z(value = 0.5f), Vector3.z(orientation.z))
|
||||
))
|
||||
}
|
||||
promisedDeployable.success(deployableEntity)
|
||||
case _ => ()
|
||||
}
|
||||
promisedDeployable.future
|
||||
}
|
||||
|
||||
def handleUseDoor(door: Door, equipment: Option[Equipment]): Unit = {
|
||||
|
|
|
|||
|
|
@ -158,6 +158,18 @@ object ZoningOperations {
|
|||
events ! LocalServiceMessage(target, soundMessage)
|
||||
}
|
||||
}
|
||||
|
||||
def findBuildingsBySoiOccupancy(zone: Zone, position: Vector3): List[Building] = {
|
||||
val positionxy = position.xy
|
||||
zone
|
||||
.blockMap
|
||||
.sector(positionxy, range=5)
|
||||
.buildingList
|
||||
.filter { building =>
|
||||
val radius = building.Definition.SOIRadius
|
||||
Vector3.DistanceSquared(building.Position.xy, positionxy) < radius * radius
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ZoningOperations(
|
||||
|
|
@ -868,12 +880,7 @@ class ZoningOperations(
|
|||
val location = if (Zones.sanctuaryZoneNumber(player.Faction) == continent.Number) {
|
||||
Zoning.Time.Sanctuary
|
||||
} else {
|
||||
val playerPosition = player.Position.xy
|
||||
continent.Buildings.values
|
||||
.filter { building =>
|
||||
val radius = building.Definition.SOIRadius
|
||||
Vector3.DistanceSquared(building.Position.xy, playerPosition) < radius * radius
|
||||
} match {
|
||||
ZoningOperations.findBuildingsBySoiOccupancy(continent, player.Position) match {
|
||||
case Nil =>
|
||||
Zoning.Time.None
|
||||
case List(building: FactionAffinity) =>
|
||||
|
|
|
|||
Loading…
Reference in a new issue