mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-19 18:44:45 +00:00
Merge branch 'master' into fix-some-commands
This commit is contained in:
commit
66362b38d7
|
|
@ -96,3 +96,12 @@ add_property suppressor holstertime 600
|
||||||
add_property trek equiptime 500
|
add_property trek equiptime 500
|
||||||
add_property trek holstertime 500
|
add_property trek holstertime 500
|
||||||
add_property vulture requirement_award0 false
|
add_property vulture requirement_award0 false
|
||||||
|
add_property aphelion allowed false
|
||||||
|
add_property aphelion_flight allowed false
|
||||||
|
add_property aphelion_gunner allowed false
|
||||||
|
add_property colossus allowed false
|
||||||
|
add_property colossus_flight allowed false
|
||||||
|
add_property colossus_gunner allowed false
|
||||||
|
add_property peregrine allowed false
|
||||||
|
add_property peregrine_flight allowed false
|
||||||
|
add_property peregrine_gunner allowed false
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,9 @@ game {
|
||||||
# Purchases timers for the battleframe robotics vehicles all update at the same time when either of them would update
|
# Purchases timers for the battleframe robotics vehicles all update at the same time when either of them would update
|
||||||
shared-bfr-cooldown = yes
|
shared-bfr-cooldown = yes
|
||||||
|
|
||||||
|
# How long the countdown timer is when a facility (main overworld base) is hacked
|
||||||
|
facility-hack-time = 15.minutes
|
||||||
|
|
||||||
# HART system, shuttles and facilities
|
# HART system, shuttles and facilities
|
||||||
hart {
|
hart {
|
||||||
# How long the shuttle is not boarding passengers (going through the motions)
|
# How long the shuttle is not boarding passengers (going through the motions)
|
||||||
|
|
|
||||||
|
|
@ -3039,6 +3039,8 @@ class AvatarActor(
|
||||||
if (exp > 0L) {
|
if (exp > 0L) {
|
||||||
setBep(avatar.bep + exp, msg)
|
setBep(avatar.bep + exp, msg)
|
||||||
zone.actor ! ZoneActor.RewardOurSupporters(playerSource, historyTranscript, killStat, exp)
|
zone.actor ! ZoneActor.RewardOurSupporters(playerSource, historyTranscript, killStat, exp)
|
||||||
|
zone.AvatarEvents ! AvatarServiceMessage(
|
||||||
|
player.Name, AvatarAction.ShareKillExperienceWithSquad(player, exp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,21 +28,21 @@ class SquadHandlerLogic(val ops: SessionSquadHandlers, implicit val context: Act
|
||||||
/* packet */
|
/* packet */
|
||||||
|
|
||||||
def handleSquadDefinitionAction(pkt: SquadDefinitionActionMessage): Unit = {
|
def handleSquadDefinitionAction(pkt: SquadDefinitionActionMessage): Unit = {
|
||||||
if (!player.spectator) {
|
/*if (!player.spectator) {
|
||||||
val SquadDefinitionActionMessage(u1, u2, action) = pkt
|
val SquadDefinitionActionMessage(u1, u2, action) = pkt
|
||||||
squadService ! SquadServiceMessage(player, continent, SquadServiceAction.Definition(u1, u2, action))
|
squadService ! SquadServiceMessage(player, continent, SquadServiceAction.Definition(u1, u2, action))
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
def handleSquadMemberRequest(pkt: SquadMembershipRequest): Unit = {
|
def handleSquadMemberRequest(pkt: SquadMembershipRequest): Unit = {
|
||||||
if (!player.spectator) {
|
/* if (!player.spectator) {
|
||||||
val SquadMembershipRequest(request_type, char_id, unk3, player_name, unk5) = pkt
|
val SquadMembershipRequest(request_type, char_id, unk3, player_name, unk5) = pkt
|
||||||
squadService ! SquadServiceMessage(
|
squadService ! SquadServiceMessage(
|
||||||
player,
|
player,
|
||||||
continent,
|
continent,
|
||||||
SquadServiceAction.Membership(request_type, char_id, unk3, player_name, unk5)
|
SquadServiceAction.Membership(request_type, char_id, unk3, player_name, unk5)
|
||||||
)
|
)
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
def handleSquadWaypointRequest(pkt: SquadWaypointRequest): Unit = {
|
def handleSquadWaypointRequest(pkt: SquadWaypointRequest): Unit = {
|
||||||
|
|
|
||||||
|
|
@ -473,6 +473,9 @@ class AvatarHandlerLogic(val ops: SessionAvatarHandlers, implicit val context: A
|
||||||
case AvatarResponse.FacilityCaptureRewards(buildingId, zoneNumber, cep) =>
|
case AvatarResponse.FacilityCaptureRewards(buildingId, zoneNumber, cep) =>
|
||||||
ops.facilityCaptureRewards(buildingId, zoneNumber, cep)
|
ops.facilityCaptureRewards(buildingId, zoneNumber, cep)
|
||||||
|
|
||||||
|
case AvatarResponse.ShareKillExperienceWithSquad(killer, exp) =>
|
||||||
|
ops.shareKillExperienceWithSquad(killer, exp)
|
||||||
|
|
||||||
case AvatarResponse.SendResponse(msg) =>
|
case AvatarResponse.SendResponse(msg) =>
|
||||||
sendResponse(msg)
|
sendResponse(msg)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||||
import net.psforever.objects.serverobject.containable.Containable
|
import net.psforever.objects.serverobject.containable.Containable
|
||||||
import net.psforever.objects.serverobject.doors.Door
|
import net.psforever.objects.serverobject.doors.Door
|
||||||
import net.psforever.objects.serverobject.generator.Generator
|
import net.psforever.objects.serverobject.generator.Generator
|
||||||
|
import net.psforever.objects.serverobject.interior.Sidedness.OutsideOf
|
||||||
import net.psforever.objects.serverobject.llu.CaptureFlag
|
import net.psforever.objects.serverobject.llu.CaptureFlag
|
||||||
import net.psforever.objects.serverobject.locks.IFFLock
|
import net.psforever.objects.serverobject.locks.IFFLock
|
||||||
import net.psforever.objects.serverobject.mblocker.Locker
|
import net.psforever.objects.serverobject.mblocker.Locker
|
||||||
|
|
@ -406,7 +407,13 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
|
||||||
}
|
}
|
||||||
log.info(s"${player.Name} is constructing a $ammoType deployable")
|
log.info(s"${player.Name} is constructing a $ammoType deployable")
|
||||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||||
|
if (ammoType == DeployedItem.spitfire_turret || ammoType == DeployedItem.spitfire_cloaked ||
|
||||||
|
ammoType == DeployedItem.spitfire_aa) {
|
||||||
|
ops.handleDeployObject(continent, ammoType, pos, orient, OutsideOf, player.Faction, player, obj)
|
||||||
|
}
|
||||||
|
else {
|
||||||
ops.handleDeployObject(continent, ammoType, pos, orient, player.WhichSide, player.Faction, player, obj)
|
ops.handleDeployObject(continent, ammoType, pos, orient, player.WhichSide, player.Faction, player, obj)
|
||||||
|
}
|
||||||
case Some(obj) =>
|
case Some(obj) =>
|
||||||
log.warn(s"DeployObject: what is $obj, ${player.Name}? It's not a construction tool!")
|
log.warn(s"DeployObject: what is $obj, ${player.Name}? It's not a construction tool!")
|
||||||
case None =>
|
case None =>
|
||||||
|
|
|
||||||
|
|
@ -28,17 +28,17 @@ class SquadHandlerLogic(val ops: SessionSquadHandlers, implicit val context: Act
|
||||||
/* packet */
|
/* packet */
|
||||||
|
|
||||||
def handleSquadDefinitionAction(pkt: SquadDefinitionActionMessage): Unit = {
|
def handleSquadDefinitionAction(pkt: SquadDefinitionActionMessage): Unit = {
|
||||||
val SquadDefinitionActionMessage(u1, u2, action) = pkt
|
/*val SquadDefinitionActionMessage(u1, u2, action) = pkt
|
||||||
squadService ! SquadServiceMessage(player, continent, SquadServiceAction.Definition(u1, u2, action))
|
squadService ! SquadServiceMessage(player, continent, SquadServiceAction.Definition(u1, u2, action))*/
|
||||||
}
|
}
|
||||||
|
|
||||||
def handleSquadMemberRequest(pkt: SquadMembershipRequest): Unit = {
|
def handleSquadMemberRequest(pkt: SquadMembershipRequest): Unit = {
|
||||||
val SquadMembershipRequest(request_type, char_id, unk3, player_name, unk5) = pkt
|
/*val SquadMembershipRequest(request_type, char_id, unk3, player_name, unk5) = pkt
|
||||||
squadService ! SquadServiceMessage(
|
squadService ! SquadServiceMessage(
|
||||||
player,
|
player,
|
||||||
continent,
|
continent,
|
||||||
SquadServiceAction.Membership(request_type, char_id, unk3, player_name, unk5)
|
SquadServiceAction.Membership(request_type, char_id, unk3, player_name, unk5)
|
||||||
)
|
)*/
|
||||||
}
|
}
|
||||||
|
|
||||||
def handleSquadWaypointRequest(pkt: SquadWaypointRequest): Unit = {
|
def handleSquadWaypointRequest(pkt: SquadWaypointRequest): Unit = {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import net.psforever.objects.avatar.SpecialCarry
|
||||||
import net.psforever.objects.{GlobalDefinitions, Player, Tool, Vehicle, Vehicles}
|
import net.psforever.objects.{GlobalDefinitions, Player, Tool, Vehicle, Vehicles}
|
||||||
import net.psforever.objects.equipment.{Equipment, JammableMountedWeapons, JammableUnit}
|
import net.psforever.objects.equipment.{Equipment, JammableMountedWeapons, JammableUnit}
|
||||||
import net.psforever.objects.guid.{GUIDTask, TaskWorkflow}
|
import net.psforever.objects.guid.{GUIDTask, TaskWorkflow}
|
||||||
|
import net.psforever.objects.serverobject.interior.Sidedness.OutsideOf
|
||||||
import net.psforever.objects.serverobject.mount.Mountable
|
import net.psforever.objects.serverobject.mount.Mountable
|
||||||
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
|
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
|
||||||
import net.psforever.packet.game.objectcreate.ObjectCreateMessageParent
|
import net.psforever.packet.game.objectcreate.ObjectCreateMessageParent
|
||||||
|
|
@ -187,6 +188,7 @@ class VehicleHandlerLogic(val ops: SessionVehicleHandlers, implicit val context:
|
||||||
s"${player.Sex.possessive} ride"
|
s"${player.Sex.possessive} ride"
|
||||||
}
|
}
|
||||||
log.info(s"${player.Name} has been kicked from $typeOfRide!")
|
log.info(s"${player.Name} has been kicked from $typeOfRide!")
|
||||||
|
player.WhichSide = OutsideOf
|
||||||
|
|
||||||
case VehicleResponse.KickPassenger(_, wasKickedByDriver, _) =>
|
case VehicleResponse.KickPassenger(_, wasKickedByDriver, _) =>
|
||||||
//seat number (first field) seems to be correct if passenger is kicked manually by driver
|
//seat number (first field) seems to be correct if passenger is kicked manually by driver
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||||
import net.psforever.types.ChatMessageType.CMT_QUIT
|
import net.psforever.types.ChatMessageType.CMT_QUIT
|
||||||
import org.log4s.Logger
|
import org.log4s.Logger
|
||||||
|
|
||||||
|
import java.util.concurrent.{Executors, TimeUnit}
|
||||||
import scala.annotation.unused
|
import scala.annotation.unused
|
||||||
import scala.collection.{Seq, mutable}
|
import scala.collection.{Seq, mutable}
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
|
|
@ -59,6 +60,7 @@ class ChatOperations(
|
||||||
private var channels: List[ChatChannel] = List()
|
private var channels: List[ChatChannel] = List()
|
||||||
private var silenceTimer: Cancellable = Default.Cancellable
|
private var silenceTimer: Cancellable = Default.Cancellable
|
||||||
private[session] var transitoryCommandEntered: Option[ChatMessageType] = None
|
private[session] var transitoryCommandEntered: Option[ChatMessageType] = None
|
||||||
|
private val scheduler = Executors.newScheduledThreadPool(2)
|
||||||
/**
|
/**
|
||||||
* when another player is listed as one of our ignored players,
|
* when another player is listed as one of our ignored players,
|
||||||
* and that other player sends an emote,
|
* and that other player sends an emote,
|
||||||
|
|
@ -352,8 +354,25 @@ class ChatOperations(
|
||||||
//evaluate results
|
//evaluate results
|
||||||
(resolvedFacilities, resolvedFaction, resolvedTimer) match {
|
(resolvedFacilities, resolvedFaction, resolvedTimer) match {
|
||||||
case (Some(buildings), Some(faction), Some(_)) =>
|
case (Some(buildings), Some(faction), Some(_)) =>
|
||||||
buildings.foreach { building =>
|
|
||||||
//TODO implement timer
|
//TODO implement timer
|
||||||
|
//schedule processing of buildings with a delay
|
||||||
|
processBuildingsWithDelay(buildings, faction, 1000) //delay of 1000ms between each building operation
|
||||||
|
true
|
||||||
|
case _ =>
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 terminal = building.CaptureTerminal.get
|
||||||
val zone = building.Zone
|
val zone = building.Zone
|
||||||
val zoneActor = zone.actor
|
val zoneActor = zone.actor
|
||||||
|
|
@ -373,10 +392,11 @@ class ChatOperations(
|
||||||
//push for map updates again
|
//push for map updates again
|
||||||
zoneActor ! ZoneActor.ZoneMapUpdate()
|
zoneActor ! ZoneActor.ZoneMapUpdate()
|
||||||
}
|
}
|
||||||
true
|
},
|
||||||
case _ =>
|
0,
|
||||||
false
|
delayMillis,
|
||||||
}
|
TimeUnit.MILLISECONDS
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
def commandVoice(session: Session, message: ChatMsg, contents: String, toChannel: ChatChannel): Unit = {
|
def commandVoice(session: Session, message: ChatMsg, contents: String, toChannel: ChatChannel): Unit = {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package net.psforever.actors.session.support
|
||||||
|
|
||||||
import akka.actor.{ActorContext, typed}
|
import akka.actor.{ActorContext, typed}
|
||||||
import net.psforever.objects.serverobject.mount.Mountable
|
import net.psforever.objects.serverobject.mount.Mountable
|
||||||
import net.psforever.objects.{Default, PlanetSideGameObject}
|
import net.psforever.objects.{Default, PlanetSideGameObject, Player}
|
||||||
import net.psforever.objects.sourcing.{PlayerSource, SourceEntry}
|
import net.psforever.objects.sourcing.{PlayerSource, SourceEntry}
|
||||||
import net.psforever.packet.game.objectcreate.ConstructorData
|
import net.psforever.packet.game.objectcreate.ConstructorData
|
||||||
import net.psforever.objects.zones.exp
|
import net.psforever.objects.zones.exp
|
||||||
|
|
@ -59,7 +59,7 @@ class SessionAvatarHandlers(
|
||||||
//TODO squad services deactivated, participation trophy rewards for now - 11-20-2023
|
//TODO squad services deactivated, participation trophy rewards for now - 11-20-2023
|
||||||
//must be in a squad to earn experience
|
//must be in a squad to earn experience
|
||||||
val charId = player.CharId
|
val charId = player.CharId
|
||||||
val squadUI = sessionLogic.squad.squadUI
|
/*val squadUI = sessionLogic.squad.squadUI
|
||||||
val participation = continent
|
val participation = continent
|
||||||
.Building(buildingId)
|
.Building(buildingId)
|
||||||
.map { building =>
|
.map { building =>
|
||||||
|
|
@ -117,6 +117,34 @@ class SessionAvatarHandlers(
|
||||||
exp.ToDatabase.reportFacilityCapture(charId, buildingId, zoneNumber, modifiedExp, expType="bep")
|
exp.ToDatabase.reportFacilityCapture(charId, buildingId, zoneNumber, modifiedExp, expType="bep")
|
||||||
avatarActor ! AvatarActor.AwardFacilityCaptureBep(modifiedExp)
|
avatarActor ! AvatarActor.AwardFacilityCaptureBep(modifiedExp)
|
||||||
Some(modifiedExp)
|
Some(modifiedExp)
|
||||||
|
}*/
|
||||||
|
//if not in squad (temporary)
|
||||||
|
exp.ToDatabase.reportFacilityCapture(charId, zoneNumber, buildingId, cep, expType="bep")
|
||||||
|
avatarActor ! AvatarActor.AwardFacilityCaptureBep(cep)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param killer the player who got the kill
|
||||||
|
* @param exp the amount of bep they received for the kill
|
||||||
|
* Squad members of a "killer" will receive a split of the experience if they are both alive
|
||||||
|
* and in the same zone as the killer. The amount received is
|
||||||
|
* based on the size of the squad. Each squad member that meets the criteria will receive a fractional split.
|
||||||
|
*/
|
||||||
|
def shareKillExperienceWithSquad(killer: Player, exp: Long): Unit = {
|
||||||
|
//TODO consider squad experience waypoint in exp calculation
|
||||||
|
val squadUI = sessionLogic.squad.squadUI
|
||||||
|
val squadSize = squadUI.size
|
||||||
|
if (squadSize > 1) {
|
||||||
|
val expSplit = exp / squadSize
|
||||||
|
val squadMembers = squadUI.filterNot(_._1 == killer.CharId).map { case (_, member) => member }.toList.map(_.name)
|
||||||
|
val playersInZone = killer.Zone.Players.map { avatar => (avatar.id, avatar.basic.name) }
|
||||||
|
val squadMembersHere = playersInZone.filter(member => squadMembers.contains(member._2))
|
||||||
|
squadMembersHere.foreach { member =>
|
||||||
|
killer.Zone.AvatarEvents ! AvatarServiceMessage(
|
||||||
|
member._2,
|
||||||
|
AvatarAction.AwardBep(member._1, expSplit, ExperienceType.Normal))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package net.psforever.actors.session.support
|
||||||
|
|
||||||
import akka.actor.{ActorContext, typed}
|
import akka.actor.{ActorContext, typed}
|
||||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||||
|
import net.psforever.objects.serverobject.interior.Sidedness.OutsideOf
|
||||||
import net.psforever.objects.{PlanetSideGameObject, Tool, Vehicle}
|
import net.psforever.objects.{PlanetSideGameObject, Tool, Vehicle}
|
||||||
import net.psforever.objects.vehicles.{CargoBehavior, MountableWeapons}
|
import net.psforever.objects.vehicles.{CargoBehavior, MountableWeapons}
|
||||||
import net.psforever.objects.vital.InGameHistory
|
import net.psforever.objects.vital.InGameHistory
|
||||||
|
|
@ -197,6 +198,7 @@ class SessionMountHandlers(
|
||||||
*/
|
*/
|
||||||
def DismountVehicleAction(tplayer: Player, obj: PlanetSideGameObject with FactionAffinity with InGameHistory, seatNum: Int): Unit = {
|
def DismountVehicleAction(tplayer: Player, obj: PlanetSideGameObject with FactionAffinity with InGameHistory, seatNum: Int): Unit = {
|
||||||
DismountAction(tplayer, obj, seatNum)
|
DismountAction(tplayer, obj, seatNum)
|
||||||
|
tplayer.WhichSide = OutsideOf
|
||||||
//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
|
||||||
|
|
|
||||||
|
|
@ -343,7 +343,7 @@ class WeaponAndProjectileOperations(
|
||||||
case citem: ConstructionItem =>
|
case citem: ConstructionItem =>
|
||||||
log.info(s"${player.Name} switched ${player.Sex.possessive} ${obj.Definition.Name} to construct ${citem.AmmoType} (mode #$modeIndex)")
|
log.info(s"${player.Name} switched ${player.Sex.possessive} ${obj.Definition.Name} to construct ${citem.AmmoType} (mode #$modeIndex)")
|
||||||
case _ =>
|
case _ =>
|
||||||
log.info(s"${player.Name} changed ${player.Sex.possessive} her ${obj.Definition.Name}'s fire mode to #$modeIndex")
|
log.info(s"${player.Name} changed ${player.Sex.possessive} ${obj.Definition.Name}'s fire mode to #$modeIndex")
|
||||||
}
|
}
|
||||||
sendResponse(ChangeFireModeMessage(item_guid, modeIndex))
|
sendResponse(ChangeFireModeMessage(item_guid, modeIndex))
|
||||||
continent.AvatarEvents ! AvatarServiceMessage(
|
continent.AvatarEvents ! AvatarServiceMessage(
|
||||||
|
|
|
||||||
|
|
@ -2494,6 +2494,15 @@ class ZoningOperations(
|
||||||
reclaimOurDeployables(continent.DeployableList, player.Name, reassignDeployablesTo(player.GUID))
|
reclaimOurDeployables(continent.DeployableList, player.Name, reassignDeployablesTo(player.GUID))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
//do this to make my deployed telepad appear that way
|
||||||
|
if (continent.DeployableList.exists(telepad => telepad.Definition == GlobalDefinitions.router_telepad_deployable
|
||||||
|
&& telepad.OwnerName.contains(player.Name)))
|
||||||
|
{
|
||||||
|
continent.Vehicles.filter(router => router.Definition == GlobalDefinitions.router && router.Faction == player.Faction)
|
||||||
|
.foreach { obj =>
|
||||||
|
sessionLogic.general.toggleTeleportSystem(obj, TelepadLike.AppraiseTeleportationSystem(obj, continent))
|
||||||
|
}
|
||||||
|
}
|
||||||
//begin looking for conditions to set the avatar
|
//begin looking for conditions to set the avatar
|
||||||
context.system.scheduler.scheduleOnce(delay = 250 millisecond, context.self, SessionActor.SetCurrentAvatar(player, 200))
|
context.system.scheduler.scheduleOnce(delay = 250 millisecond, context.self, SessionActor.SetCurrentAvatar(player, 200))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,8 @@ class ZoneActor(
|
||||||
|
|
||||||
case ZoneMapUpdate() =>
|
case ZoneMapUpdate() =>
|
||||||
zone.Buildings
|
zone.Buildings
|
||||||
.filter(_._2.BuildingType == StructureType.Facility)
|
.filter(building =>
|
||||||
|
building._2.BuildingType == StructureType.Facility || building._2.BuildingType == StructureType.Tower)
|
||||||
.values
|
.values
|
||||||
.foreach(_.Actor ! BuildingActor.MapUpdate())
|
.foreach(_.Actor ! BuildingActor.MapUpdate())
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
|
|
|
||||||
|
|
@ -42,11 +42,13 @@ object Vehicles {
|
||||||
case Some(tplayer) =>
|
case Some(tplayer) =>
|
||||||
tplayer.avatar.vehicle = Some(vehicle.GUID)
|
tplayer.avatar.vehicle = Some(vehicle.GUID)
|
||||||
vehicle.AssignOwnership(playerOpt)
|
vehicle.AssignOwnership(playerOpt)
|
||||||
|
val locked = VehicleLockState.Locked.id
|
||||||
|
Array(0, 3).foreach(group => vehicle.PermissionGroup(group, locked))
|
||||||
|
Vehicles.ReloadAccessPermissions(vehicle, tplayer.Faction.toString)
|
||||||
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(
|
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(
|
||||||
vehicle.Zone.id,
|
vehicle.Zone.id,
|
||||||
VehicleAction.Ownership(tplayer.GUID, vehicle.GUID)
|
VehicleAction.Ownership(tplayer.GUID, vehicle.GUID)
|
||||||
)
|
)
|
||||||
Vehicles.ReloadAccessPermissions(vehicle, tplayer.Faction.toString)
|
|
||||||
Some(vehicle)
|
Some(vehicle)
|
||||||
case None =>
|
case None =>
|
||||||
None
|
None
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,12 @@ trait DeployableBehavior {
|
||||||
if DeployableObject.OwnerGuid.nonEmpty =>
|
if DeployableObject.OwnerGuid.nonEmpty =>
|
||||||
val obj = DeployableObject
|
val obj = DeployableObject
|
||||||
if (constructed.contains(true)) {
|
if (constructed.contains(true)) {
|
||||||
|
if (obj.Definition.DeployCategory == DeployableCategory.Boomers) {
|
||||||
loseOwnership(obj, PlanetSideEmpire.NEUTRAL)
|
loseOwnership(obj, PlanetSideEmpire.NEUTRAL)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
loseOwnership(obj, obj.Faction)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
obj.OwnerGuid = None
|
obj.OwnerGuid = None
|
||||||
}
|
}
|
||||||
|
|
@ -290,6 +295,11 @@ object DeployableBehavior {
|
||||||
originalFaction.toString,
|
originalFaction.toString,
|
||||||
LocalAction.DeployableMapIcon(Service.defaultPlayerGUID, DeploymentAction.Dismiss, info)
|
LocalAction.DeployableMapIcon(Service.defaultPlayerGUID, DeploymentAction.Dismiss, info)
|
||||||
)
|
)
|
||||||
|
//remove deployable from original owner's toolbox and UI counter
|
||||||
|
zone.AllPlayers.filter(p => obj.OriginalOwnerName.contains(p.Name))
|
||||||
|
.foreach { originalOwner =>
|
||||||
|
originalOwner.avatar.deployables.Remove(obj)
|
||||||
|
originalOwner.Zone.LocalEvents ! LocalServiceMessage(originalOwner.Name, LocalAction.DeployableUIFor(obj.Definition.Item))
|
||||||
}
|
}
|
||||||
//display to the given faction
|
//display to the given faction
|
||||||
localEvents ! LocalServiceMessage(
|
localEvents ! LocalServiceMessage(
|
||||||
|
|
@ -298,3 +308,4 @@ object DeployableBehavior {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -324,7 +324,7 @@ object EffectTarget {
|
||||||
def FacilityTurretValidateAircraftTarget(target: PlanetSideGameObject): Boolean =
|
def FacilityTurretValidateAircraftTarget(target: PlanetSideGameObject): Boolean =
|
||||||
target match {
|
target match {
|
||||||
case v: Vehicle
|
case v: Vehicle
|
||||||
if GlobalDefinitions.isFlightVehicle(v.Definition) && v.Seats.values.exists(_.isOccupied) =>
|
if GlobalDefinitions.isFlightVehicle(v.Definition) && v.Seats.values.exists(_.isOccupied) && v.Definition != GlobalDefinitions.mosquito =>
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
val pos = v.Position
|
val pos = v.Position
|
||||||
lazy val sector = v.Zone.blockMap.sector(pos, range = 51f)
|
lazy val sector = v.Zone.blockMap.sector(pos, range = 51f)
|
||||||
|
|
@ -332,10 +332,10 @@ object EffectTarget {
|
||||||
.collect { case t: Tool => now - t.LastDischarge }
|
.collect { case t: Tool => now - t.LastDischarge }
|
||||||
.exists(_ < 2000L)
|
.exists(_ < 2000L)
|
||||||
// from the perspective of a mosquito, at 5th gauge, forward velocity is 59~60
|
// from the perspective of a mosquito, at 5th gauge, forward velocity is 59~60
|
||||||
lazy val movingFast = Vector3.MagnitudeSquared(v.Velocity.getOrElse(Vector3.Zero).xy) > 3721f //61
|
//lazy val movingFast = Vector3.MagnitudeSquared(v.Velocity.getOrElse(Vector3.Zero).xy) > 3721f //61
|
||||||
lazy val isMoving = v.isMoving(test = 1d)
|
lazy val isMoving = v.isMoving(test = 1d)
|
||||||
if (v.Cloaked || radarCloakedAms(sector, pos) || radarCloakedAegis(sector, pos)) false
|
if (v.Cloaked || radarCloakedAms(sector, pos) || radarCloakedAegis(sector, pos)) false
|
||||||
else if (v.Definition == GlobalDefinitions.mosquito) movingFast
|
//else if (v.Definition == GlobalDefinitions.mosquito) movingFast
|
||||||
else v.isFlying && (isMoving || entityTookDamage(v, now) || usedEquipment)
|
else v.isFlying && (isMoving || entityTookDamage(v, now) || usedEquipment)
|
||||||
case _ =>
|
case _ =>
|
||||||
false
|
false
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import net.psforever.objects.vital.base.DamageType
|
||||||
import net.psforever.objects.vital.etc.ExplodingRadialDegrade
|
import net.psforever.objects.vital.etc.ExplodingRadialDegrade
|
||||||
import net.psforever.objects.vital.prop.DamageWithPosition
|
import net.psforever.objects.vital.prop.DamageWithPosition
|
||||||
import net.psforever.types.{ExoSuitType, Vector3}
|
import net.psforever.types.{ExoSuitType, Vector3}
|
||||||
|
import net.psforever.util.Config
|
||||||
|
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
|
|
@ -707,7 +708,7 @@ object GlobalDefinitionsMiscellaneous {
|
||||||
capture_terminal.Name = "capture_terminal"
|
capture_terminal.Name = "capture_terminal"
|
||||||
capture_terminal.Damageable = false
|
capture_terminal.Damageable = false
|
||||||
capture_terminal.Repairable = false
|
capture_terminal.Repairable = false
|
||||||
capture_terminal.FacilityHackTime = 15.minutes
|
capture_terminal.FacilityHackTime = Config.app.game.facilityHackTime
|
||||||
|
|
||||||
secondary_capture.Name = "secondary_capture"
|
secondary_capture.Name = "secondary_capture"
|
||||||
secondary_capture.Damageable = false
|
secondary_capture.Damageable = false
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ object EnvironmentAttribute {
|
||||||
/** only interact with living player characters or vehicles */
|
/** only interact with living player characters or vehicles */
|
||||||
def canInteractWith(obj: PlanetSideGameObject): Boolean = canInteractWithPlayersAndVehicles(obj)
|
def canInteractWith(obj: PlanetSideGameObject): Boolean = canInteractWithPlayersAndVehicles(obj)
|
||||||
|
|
||||||
def testingDepth(obj: _root_.net.psforever.objects.PlanetSideGameObject): Float = 0f
|
def testingDepth(obj: _root_.net.psforever.objects.PlanetSideGameObject): Float = 4f
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -41,13 +41,13 @@ trait FacilityHackParticipation extends ParticipationLogic {
|
||||||
.filterNot { case (_, (_, _, t)) => curr - t > hackTime }
|
.filterNot { case (_, (_, _, t)) => curr - t > hackTime }
|
||||||
.partition { case (p, _) => uniqueList2.contains(p) }
|
.partition { case (p, _) => uniqueList2.contains(p) }
|
||||||
}
|
}
|
||||||
val newParticipaants = list
|
val newParticipants = list
|
||||||
.filterNot { p =>
|
.filterNot { p =>
|
||||||
playerContribution.exists { case (u, _) => p.CharId == u }
|
playerContribution.exists { case (u, _) => p.CharId == u }
|
||||||
}
|
}
|
||||||
playerContribution =
|
playerContribution =
|
||||||
vanguardParticipants.map { case (u, (p, d, _)) => (u, (p, d + 1, curr)) } ++
|
vanguardParticipants.map { case (u, (p, d, _)) => (u, (p, d + 1, curr)) } ++
|
||||||
newParticipaants.map { p => (p.CharId, (p, 1, curr)) } ++
|
newParticipants.map { p => (p.CharId, (p, 1, curr)) } ++
|
||||||
missingParticipants
|
missingParticipants
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,9 @@ final case class MajorFacilityHackParticipation(building: Building) extends Faci
|
||||||
|
|
||||||
def TryUpdate(): Unit = {
|
def TryUpdate(): Unit = {
|
||||||
val list = building.PlayersInSOI
|
val list = building.PlayersInSOI
|
||||||
|
if (list.nonEmpty) {
|
||||||
updatePlayers(list)
|
updatePlayers(list)
|
||||||
|
}
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
if (now - lastInfoRequest > 60000L) {
|
if (now - lastInfoRequest > 60000L) {
|
||||||
updatePopulationOverTime(list, now, before = 900000L)
|
updatePopulationOverTime(list, now, before = 900000L)
|
||||||
|
|
@ -123,7 +125,7 @@ final case class MajorFacilityHackParticipation(building: Building) extends Faci
|
||||||
hackStart,
|
hackStart,
|
||||||
completionTime,
|
completionTime,
|
||||||
opposingFaction,
|
opposingFaction,
|
||||||
contributionOpposing
|
contributionVictor
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
//1) experience from killing opposingFaction across duration of hack
|
//1) experience from killing opposingFaction across duration of hack
|
||||||
|
|
@ -249,11 +251,14 @@ final case class MajorFacilityHackParticipation(building: Building) extends Faci
|
||||||
overallTimeMultiplier *
|
overallTimeMultiplier *
|
||||||
Config.app.game.experience.cep.rate + competitionBonus
|
Config.app.game.experience.cep.rate + competitionBonus
|
||||||
).toLong
|
).toLong
|
||||||
//8. reward participants
|
//8. reward participants that are still in the zone
|
||||||
//Classically, only players in the SOI are rewarded, and the llu runner too
|
|
||||||
val hackerId = hacker.CharId
|
val hackerId = hacker.CharId
|
||||||
|
val contributingPlayers = contributionVictor
|
||||||
|
.filter { case (player, _, _) => player.Zone.id == building.Zone.id }
|
||||||
|
.map { case (player, _, _) => player }
|
||||||
|
.toList
|
||||||
//terminal hacker (always cep)
|
//terminal hacker (always cep)
|
||||||
if (playersInSoi.exists(_.CharId == hackerId) && flagCarrier.map(_.CharId).getOrElse(0L) != hackerId) {
|
if (contributingPlayers.exists(_.CharId == hackerId) && flagCarrier.map(_.CharId).getOrElse(0L) != hackerId) {
|
||||||
ToDatabase.reportFacilityCapture(
|
ToDatabase.reportFacilityCapture(
|
||||||
hackerId,
|
hackerId,
|
||||||
zoneNumber,
|
zoneNumber,
|
||||||
|
|
@ -264,7 +269,7 @@ final case class MajorFacilityHackParticipation(building: Building) extends Faci
|
||||||
events ! AvatarServiceMessage(hacker.Name, AvatarAction.AwardCep(hackerId, finalCep))
|
events ! AvatarServiceMessage(hacker.Name, AvatarAction.AwardCep(hackerId, finalCep))
|
||||||
}
|
}
|
||||||
//bystanders (cep if squad leader, bep otherwise)
|
//bystanders (cep if squad leader, bep otherwise)
|
||||||
playersInSoi
|
contributingPlayers
|
||||||
.filterNot { _.CharId == hackerId }
|
.filterNot { _.CharId == hackerId }
|
||||||
.foreach { player =>
|
.foreach { player =>
|
||||||
val charId = player.CharId
|
val charId = player.CharId
|
||||||
|
|
@ -336,7 +341,7 @@ final case class MajorFacilityHackParticipation(building: Building) extends Faci
|
||||||
val towerRadius = math.pow(tower.Definition.SOIRadius.toDouble * 0.7d, 2d).toFloat
|
val towerRadius = math.pow(tower.Definition.SOIRadius.toDouble * 0.7d, 2d).toFloat
|
||||||
list
|
list
|
||||||
.map { case (p, f, kills) =>
|
.map { case (p, f, kills) =>
|
||||||
val filteredKills = kills.filter { kill => Vector3.DistanceSquared(kill.victim.Position.xy, towerPosition) <= towerRadius }
|
val filteredKills = kills.filter { kill => Vector3.DistanceSquared(kill.victim.Position.xy, towerPosition) >= towerRadius }
|
||||||
(p, f, filteredKills)
|
(p, f, filteredKills)
|
||||||
}
|
}
|
||||||
.filter { case (_, _, kills) => kills.nonEmpty }
|
.filter { case (_, _, kills) => kills.nonEmpty }
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,14 @@ import net.psforever.util.Config
|
||||||
final case class TowerHackParticipation(building: Building) extends FacilityHackParticipation {
|
final case class TowerHackParticipation(building: Building) extends FacilityHackParticipation {
|
||||||
def TryUpdate(): Unit = {
|
def TryUpdate(): Unit = {
|
||||||
val list = building.PlayersInSOI
|
val list = building.PlayersInSOI
|
||||||
updatePlayers(building.PlayersInSOI)
|
if (list.nonEmpty) {
|
||||||
|
updatePlayers(list)
|
||||||
|
}
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
if (now - lastInfoRequest > 60000L) {
|
if (now - lastInfoRequest > 60000L) {
|
||||||
updatePopulationOverTime(list, now, before = 300000L)
|
updatePopulationOverTime(list, now, before = 300000L)
|
||||||
}
|
}
|
||||||
|
lastInfoRequest = now
|
||||||
}
|
}
|
||||||
|
|
||||||
def RewardFacilityCapture(
|
def RewardFacilityCapture(
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,13 @@ object Support {
|
||||||
//setup
|
//setup
|
||||||
val historyList = history.toList
|
val historyList = history.toList
|
||||||
val withKills = victim.progress.kills.nonEmpty
|
val withKills = victim.progress.kills.nonEmpty
|
||||||
|
//TODO Issue #1259 - Use another method to capture time of death than current time ("kill shots" aren't working)
|
||||||
|
/*
|
||||||
val fullLifespan = (historyList.headOption, historyList.lastOption) match {
|
val fullLifespan = (historyList.headOption, historyList.lastOption) match {
|
||||||
case (Some(spawn), Some(death)) => death.time - spawn.time
|
case (Some(spawn), Some(death)) => death.time - spawn.time
|
||||||
|
*/
|
||||||
|
val fullLifespan = historyList.headOption match {
|
||||||
|
case Some(spawn) => System.currentTimeMillis() - spawn.time
|
||||||
case _ => 0L
|
case _ => 0L
|
||||||
}
|
}
|
||||||
val recordOfWornTimes = countTimeWhileExoSuitOrMounted(historyList)
|
val recordOfWornTimes = countTimeWhileExoSuitOrMounted(historyList)
|
||||||
|
|
|
||||||
|
|
@ -458,6 +458,15 @@ class AvatarService(zone: Zone) extends Actor {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
case AvatarAction.ShareKillExperienceWithSquad(killer, exp) =>
|
||||||
|
AvatarEvents.publish(
|
||||||
|
AvatarServiceResponse(
|
||||||
|
s"/$forChannel/Avatar",
|
||||||
|
Service.defaultPlayerGUID,
|
||||||
|
AvatarResponse.ShareKillExperienceWithSquad(killer, exp)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
case _ => ()
|
case _ => ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -160,6 +160,7 @@ object AvatarAction {
|
||||||
final case class AwardBep(charId: Long, bep: Long, expType: ExperienceType) extends Action
|
final case class AwardBep(charId: Long, bep: Long, expType: ExperienceType) extends Action
|
||||||
final case class AwardCep(charId: Long, bep: Long) extends Action
|
final case class AwardCep(charId: Long, bep: Long) extends Action
|
||||||
final case class FacilityCaptureRewards(building_id: Int, zone_number: Int, exp: Long) extends Action
|
final case class FacilityCaptureRewards(building_id: Int, zone_number: Int, exp: Long) extends Action
|
||||||
|
final case class ShareKillExperienceWithSquad(killer: Player, exp: Long) extends Action
|
||||||
|
|
||||||
final case class TeardownConnection() extends Action
|
final case class TeardownConnection() extends Action
|
||||||
// final case class PlayerStateShift(killer : PlanetSideGUID, victim : PlanetSideGUID) extends Action
|
// final case class PlayerStateShift(killer : PlanetSideGUID, victim : PlanetSideGUID) extends Action
|
||||||
|
|
|
||||||
|
|
@ -132,4 +132,5 @@ object AvatarResponse {
|
||||||
final case class AwardBep(charId: Long, bep: Long, expType: ExperienceType) extends Response
|
final case class AwardBep(charId: Long, bep: Long, expType: ExperienceType) extends Response
|
||||||
final case class AwardCep(charId: Long, bep: Long) extends Response
|
final case class AwardCep(charId: Long, bep: Long) extends Response
|
||||||
final case class FacilityCaptureRewards(building_id: Int, zone_number: Int, exp: Long) extends Response
|
final case class FacilityCaptureRewards(building_id: Int, zone_number: Int, exp: Long) extends Response
|
||||||
|
final case class ShareKillExperienceWithSquad(killer: Player, exp: Long) extends Response
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ class HackCaptureActor extends Actor {
|
||||||
NotifyHackStateChange(target, isResecured = true)
|
NotifyHackStateChange(target, isResecured = true)
|
||||||
building.Participation.RewardFacilityCapture(
|
building.Participation.RewardFacilityCapture(
|
||||||
target.Faction,
|
target.Faction,
|
||||||
faction,
|
HackCaptureActor.GetAttackingFaction(building, faction),
|
||||||
hacker,
|
hacker,
|
||||||
facilityHackTime,
|
facilityHackTime,
|
||||||
hackTime,
|
hackTime,
|
||||||
|
|
@ -347,6 +347,30 @@ object HackCaptureActor {
|
||||||
.get
|
.get
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def GetAttackingFaction(
|
||||||
|
building: Building,
|
||||||
|
excludeThisFaction: PlanetSideEmpire.Value
|
||||||
|
): PlanetSideEmpire.Value = {
|
||||||
|
// Use PlayerContributionRaw to calculate attacking faction
|
||||||
|
val factionEfforts = building.Participation
|
||||||
|
.PlayerContributionRaw
|
||||||
|
.values
|
||||||
|
.foldLeft(Array.fill(4)(0L)) { case (efforts, (player, duration, _)) =>
|
||||||
|
val factionId = player.Faction.id
|
||||||
|
efforts.update(factionId, efforts(factionId) + duration)
|
||||||
|
efforts
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exclude the specified faction
|
||||||
|
factionEfforts.update(excludeThisFaction.id, Long.MinValue)
|
||||||
|
|
||||||
|
// Find the faction with the highest contribution
|
||||||
|
factionEfforts.indices
|
||||||
|
.maxByOption(factionEfforts)
|
||||||
|
.map(PlanetSideEmpire.apply)
|
||||||
|
.getOrElse(PlanetSideEmpire.NEUTRAL)
|
||||||
|
}
|
||||||
|
|
||||||
def GetHackingFaction(terminal: CaptureTerminal): Option[PlanetSideEmpire.Value] = {
|
def GetHackingFaction(terminal: CaptureTerminal): Option[PlanetSideEmpire.Value] = {
|
||||||
terminal.HackedBy.map { a => a.player.Faction }
|
terminal.HackedBy.map { a => a.player.Faction }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,8 @@ case class GameConfig(
|
||||||
doorsCanBeOpenedByMedAppFromThisDistance: Float,
|
doorsCanBeOpenedByMedAppFromThisDistance: Float,
|
||||||
experience: Experience,
|
experience: Experience,
|
||||||
maxBattleRank: Int,
|
maxBattleRank: Int,
|
||||||
promotion: PromotionSystem
|
promotion: PromotionSystem,
|
||||||
|
facilityHackTime: FiniteDuration
|
||||||
)
|
)
|
||||||
|
|
||||||
case class InstantActionConfig(
|
case class InstantActionConfig(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue