mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-19 18:14:44 +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 holstertime 500
|
||||
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
|
||||
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 {
|
||||
# How long the shuttle is not boarding passengers (going through the motions)
|
||||
|
|
|
|||
|
|
@ -3039,6 +3039,8 @@ class AvatarActor(
|
|||
if (exp > 0L) {
|
||||
setBep(avatar.bep + exp, msg)
|
||||
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 */
|
||||
|
||||
def handleSquadDefinitionAction(pkt: SquadDefinitionActionMessage): Unit = {
|
||||
if (!player.spectator) {
|
||||
val SquadDefinitionActionMessage(u1, u2, action) = pkt
|
||||
squadService ! SquadServiceMessage(player, continent, SquadServiceAction.Definition(u1, u2, action))
|
||||
}
|
||||
/*if (!player.spectator) {
|
||||
val SquadDefinitionActionMessage(u1, u2, action) = pkt
|
||||
squadService ! SquadServiceMessage(player, continent, SquadServiceAction.Definition(u1, u2, action))
|
||||
}*/
|
||||
}
|
||||
|
||||
def handleSquadMemberRequest(pkt: SquadMembershipRequest): Unit = {
|
||||
if (!player.spectator) {
|
||||
/* if (!player.spectator) {
|
||||
val SquadMembershipRequest(request_type, char_id, unk3, player_name, unk5) = pkt
|
||||
squadService ! SquadServiceMessage(
|
||||
player,
|
||||
continent,
|
||||
SquadServiceAction.Membership(request_type, char_id, unk3, player_name, unk5)
|
||||
)
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
def handleSquadWaypointRequest(pkt: SquadWaypointRequest): Unit = {
|
||||
|
|
|
|||
|
|
@ -473,6 +473,9 @@ class AvatarHandlerLogic(val ops: SessionAvatarHandlers, implicit val context: A
|
|||
case AvatarResponse.FacilityCaptureRewards(buildingId, zoneNumber, cep) =>
|
||||
ops.facilityCaptureRewards(buildingId, zoneNumber, cep)
|
||||
|
||||
case AvatarResponse.ShareKillExperienceWithSquad(killer, exp) =>
|
||||
ops.shareKillExperienceWithSquad(killer, exp)
|
||||
|
||||
case AvatarResponse.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.doors.Door
|
||||
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.locks.IFFLock
|
||||
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")
|
||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||
ops.handleDeployObject(continent, ammoType, pos, orient, player.WhichSide, player.Faction, player, obj)
|
||||
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)
|
||||
}
|
||||
case Some(obj) =>
|
||||
log.warn(s"DeployObject: what is $obj, ${player.Name}? It's not a construction tool!")
|
||||
case None =>
|
||||
|
|
|
|||
|
|
@ -28,17 +28,17 @@ class SquadHandlerLogic(val ops: SessionSquadHandlers, implicit val context: Act
|
|||
/* packet */
|
||||
|
||||
def handleSquadDefinitionAction(pkt: SquadDefinitionActionMessage): Unit = {
|
||||
val SquadDefinitionActionMessage(u1, u2, action) = pkt
|
||||
squadService ! SquadServiceMessage(player, continent, SquadServiceAction.Definition(u1, u2, action))
|
||||
/*val SquadDefinitionActionMessage(u1, u2, action) = pkt
|
||||
squadService ! SquadServiceMessage(player, continent, SquadServiceAction.Definition(u1, u2, action))*/
|
||||
}
|
||||
|
||||
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(
|
||||
player,
|
||||
continent,
|
||||
SquadServiceAction.Membership(request_type, char_id, unk3, player_name, unk5)
|
||||
)
|
||||
)*/
|
||||
}
|
||||
|
||||
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.equipment.{Equipment, JammableMountedWeapons, JammableUnit}
|
||||
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.pad.VehicleSpawnPad
|
||||
import net.psforever.packet.game.objectcreate.ObjectCreateMessageParent
|
||||
|
|
@ -187,6 +188,7 @@ class VehicleHandlerLogic(val ops: SessionVehicleHandlers, implicit val context:
|
|||
s"${player.Sex.possessive} ride"
|
||||
}
|
||||
log.info(s"${player.Name} has been kicked from $typeOfRide!")
|
||||
player.WhichSide = OutsideOf
|
||||
|
||||
case VehicleResponse.KickPassenger(_, wasKickedByDriver, _) =>
|
||||
//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 org.log4s.Logger
|
||||
|
||||
import java.util.concurrent.{Executors, TimeUnit}
|
||||
import scala.annotation.unused
|
||||
import scala.collection.{Seq, mutable}
|
||||
import scala.concurrent.duration._
|
||||
|
|
@ -59,6 +60,7 @@ class ChatOperations(
|
|||
private var channels: List[ChatChannel] = List()
|
||||
private var silenceTimer: Cancellable = Default.Cancellable
|
||||
private[session] var transitoryCommandEntered: Option[ChatMessageType] = None
|
||||
private val scheduler = Executors.newScheduledThreadPool(2)
|
||||
/**
|
||||
* when another player is listed as one of our ignored players,
|
||||
* and that other player sends an emote,
|
||||
|
|
@ -352,8 +354,25 @@ class ChatOperations(
|
|||
//evaluate results
|
||||
(resolvedFacilities, resolvedFaction, resolvedTimer) match {
|
||||
case (Some(buildings), Some(faction), Some(_)) =>
|
||||
buildings.foreach { building =>
|
||||
//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 zone = building.Zone
|
||||
val zoneActor = zone.actor
|
||||
|
|
@ -373,10 +392,11 @@ class ChatOperations(
|
|||
//push for map updates again
|
||||
zoneActor ! ZoneActor.ZoneMapUpdate()
|
||||
}
|
||||
true
|
||||
case _ =>
|
||||
false
|
||||
}
|
||||
},
|
||||
0,
|
||||
delayMillis,
|
||||
TimeUnit.MILLISECONDS
|
||||
)
|
||||
}
|
||||
|
||||
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 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.packet.game.objectcreate.ConstructorData
|
||||
import net.psforever.objects.zones.exp
|
||||
|
|
@ -59,7 +59,7 @@ class SessionAvatarHandlers(
|
|||
//TODO squad services deactivated, participation trophy rewards for now - 11-20-2023
|
||||
//must be in a squad to earn experience
|
||||
val charId = player.CharId
|
||||
val squadUI = sessionLogic.squad.squadUI
|
||||
/*val squadUI = sessionLogic.squad.squadUI
|
||||
val participation = continent
|
||||
.Building(buildingId)
|
||||
.map { building =>
|
||||
|
|
@ -117,7 +117,35 @@ class SessionAvatarHandlers(
|
|||
exp.ToDatabase.reportFacilityCapture(charId, buildingId, zoneNumber, modifiedExp, expType="bep")
|
||||
avatarActor ! AvatarActor.AwardFacilityCaptureBep(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 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.vehicles.{CargoBehavior, MountableWeapons}
|
||||
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 = {
|
||||
DismountAction(tplayer, obj, seatNum)
|
||||
tplayer.WhichSide = OutsideOf
|
||||
//until vehicles maintain synchronized momentum without a driver
|
||||
obj match {
|
||||
case v: Vehicle
|
||||
|
|
|
|||
|
|
@ -343,7 +343,7 @@ class WeaponAndProjectileOperations(
|
|||
case citem: ConstructionItem =>
|
||||
log.info(s"${player.Name} switched ${player.Sex.possessive} ${obj.Definition.Name} to construct ${citem.AmmoType} (mode #$modeIndex)")
|
||||
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))
|
||||
continent.AvatarEvents ! AvatarServiceMessage(
|
||||
|
|
|
|||
|
|
@ -2494,6 +2494,15 @@ class ZoningOperations(
|
|||
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
|
||||
context.system.scheduler.scheduleOnce(delay = 250 millisecond, context.self, SessionActor.SetCurrentAvatar(player, 200))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,7 +182,8 @@ class ZoneActor(
|
|||
|
||||
case ZoneMapUpdate() =>
|
||||
zone.Buildings
|
||||
.filter(_._2.BuildingType == StructureType.Facility)
|
||||
.filter(building =>
|
||||
building._2.BuildingType == StructureType.Facility || building._2.BuildingType == StructureType.Tower)
|
||||
.values
|
||||
.foreach(_.Actor ! BuildingActor.MapUpdate())
|
||||
Behaviors.same
|
||||
|
|
|
|||
|
|
@ -42,11 +42,13 @@ object Vehicles {
|
|||
case Some(tplayer) =>
|
||||
tplayer.avatar.vehicle = Some(vehicle.GUID)
|
||||
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.id,
|
||||
VehicleAction.Ownership(tplayer.GUID, vehicle.GUID)
|
||||
)
|
||||
Vehicles.ReloadAccessPermissions(vehicle, tplayer.Faction.toString)
|
||||
Some(vehicle)
|
||||
case None =>
|
||||
None
|
||||
|
|
|
|||
|
|
@ -68,7 +68,12 @@ trait DeployableBehavior {
|
|||
if DeployableObject.OwnerGuid.nonEmpty =>
|
||||
val obj = DeployableObject
|
||||
if (constructed.contains(true)) {
|
||||
loseOwnership(obj, PlanetSideEmpire.NEUTRAL)
|
||||
if (obj.Definition.DeployCategory == DeployableCategory.Boomers) {
|
||||
loseOwnership(obj, PlanetSideEmpire.NEUTRAL)
|
||||
}
|
||||
else {
|
||||
loseOwnership(obj, obj.Faction)
|
||||
}
|
||||
} else {
|
||||
obj.OwnerGuid = None
|
||||
}
|
||||
|
|
@ -290,11 +295,17 @@ object DeployableBehavior {
|
|||
originalFaction.toString,
|
||||
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
|
||||
localEvents ! LocalServiceMessage(
|
||||
toFaction.toString,
|
||||
LocalAction.DeployableMapIcon(Service.defaultPlayerGUID, DeploymentAction.Build, info)
|
||||
)
|
||||
}
|
||||
//display to the given faction
|
||||
localEvents ! LocalServiceMessage(
|
||||
toFaction.toString,
|
||||
LocalAction.DeployableMapIcon(Service.defaultPlayerGUID, DeploymentAction.Build, info)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ object EffectTarget {
|
|||
def FacilityTurretValidateAircraftTarget(target: PlanetSideGameObject): Boolean =
|
||||
target match {
|
||||
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 pos = v.Position
|
||||
lazy val sector = v.Zone.blockMap.sector(pos, range = 51f)
|
||||
|
|
@ -332,10 +332,10 @@ object EffectTarget {
|
|||
.collect { case t: Tool => now - t.LastDischarge }
|
||||
.exists(_ < 2000L)
|
||||
// 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)
|
||||
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)
|
||||
case _ =>
|
||||
false
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import net.psforever.objects.vital.base.DamageType
|
|||
import net.psforever.objects.vital.etc.ExplodingRadialDegrade
|
||||
import net.psforever.objects.vital.prop.DamageWithPosition
|
||||
import net.psforever.types.{ExoSuitType, Vector3}
|
||||
import net.psforever.util.Config
|
||||
|
||||
import scala.collection.mutable
|
||||
import scala.concurrent.duration._
|
||||
|
|
@ -485,7 +486,7 @@ object GlobalDefinitionsMiscellaneous {
|
|||
repair_silo.TargetValidation += EffectTarget.Category.Vehicle -> EffectTarget.Validation.RepairSilo
|
||||
repair_silo.Damageable = false
|
||||
repair_silo.Repairable = false
|
||||
|
||||
|
||||
recharge_terminal.Name = "recharge_terminal"
|
||||
recharge_terminal.Interval = 1000
|
||||
recharge_terminal.UseRadius = 20
|
||||
|
|
@ -707,7 +708,7 @@ object GlobalDefinitionsMiscellaneous {
|
|||
capture_terminal.Name = "capture_terminal"
|
||||
capture_terminal.Damageable = false
|
||||
capture_terminal.Repairable = false
|
||||
capture_terminal.FacilityHackTime = 15.minutes
|
||||
capture_terminal.FacilityHackTime = Config.app.game.facilityHackTime
|
||||
|
||||
secondary_capture.Name = "secondary_capture"
|
||||
secondary_capture.Damageable = false
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ object EnvironmentAttribute {
|
|||
/** only interact with living player characters or vehicles */
|
||||
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 }
|
||||
.partition { case (p, _) => uniqueList2.contains(p) }
|
||||
}
|
||||
val newParticipaants = list
|
||||
val newParticipants = list
|
||||
.filterNot { p =>
|
||||
playerContribution.exists { case (u, _) => p.CharId == u }
|
||||
}
|
||||
playerContribution =
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,9 @@ final case class MajorFacilityHackParticipation(building: Building) extends Faci
|
|||
|
||||
def TryUpdate(): Unit = {
|
||||
val list = building.PlayersInSOI
|
||||
updatePlayers(list)
|
||||
if (list.nonEmpty) {
|
||||
updatePlayers(list)
|
||||
}
|
||||
val now = System.currentTimeMillis()
|
||||
if (now - lastInfoRequest > 60000L) {
|
||||
updatePopulationOverTime(list, now, before = 900000L)
|
||||
|
|
@ -123,7 +125,7 @@ final case class MajorFacilityHackParticipation(building: Building) extends Faci
|
|||
hackStart,
|
||||
completionTime,
|
||||
opposingFaction,
|
||||
contributionOpposing
|
||||
contributionVictor
|
||||
)
|
||||
)
|
||||
//1) experience from killing opposingFaction across duration of hack
|
||||
|
|
@ -249,11 +251,14 @@ final case class MajorFacilityHackParticipation(building: Building) extends Faci
|
|||
overallTimeMultiplier *
|
||||
Config.app.game.experience.cep.rate + competitionBonus
|
||||
).toLong
|
||||
//8. reward participants
|
||||
//Classically, only players in the SOI are rewarded, and the llu runner too
|
||||
//8. reward participants that are still in the zone
|
||||
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)
|
||||
if (playersInSoi.exists(_.CharId == hackerId) && flagCarrier.map(_.CharId).getOrElse(0L) != hackerId) {
|
||||
if (contributingPlayers.exists(_.CharId == hackerId) && flagCarrier.map(_.CharId).getOrElse(0L) != hackerId) {
|
||||
ToDatabase.reportFacilityCapture(
|
||||
hackerId,
|
||||
zoneNumber,
|
||||
|
|
@ -264,7 +269,7 @@ final case class MajorFacilityHackParticipation(building: Building) extends Faci
|
|||
events ! AvatarServiceMessage(hacker.Name, AvatarAction.AwardCep(hackerId, finalCep))
|
||||
}
|
||||
//bystanders (cep if squad leader, bep otherwise)
|
||||
playersInSoi
|
||||
contributingPlayers
|
||||
.filterNot { _.CharId == hackerId }
|
||||
.foreach { player =>
|
||||
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
|
||||
list
|
||||
.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)
|
||||
}
|
||||
.filter { case (_, _, kills) => kills.nonEmpty }
|
||||
|
|
|
|||
|
|
@ -11,11 +11,14 @@ import net.psforever.util.Config
|
|||
final case class TowerHackParticipation(building: Building) extends FacilityHackParticipation {
|
||||
def TryUpdate(): Unit = {
|
||||
val list = building.PlayersInSOI
|
||||
updatePlayers(building.PlayersInSOI)
|
||||
if (list.nonEmpty) {
|
||||
updatePlayers(list)
|
||||
}
|
||||
val now = System.currentTimeMillis()
|
||||
if (now - lastInfoRequest > 60000L) {
|
||||
updatePopulationOverTime(list, now, before = 300000L)
|
||||
}
|
||||
lastInfoRequest = now
|
||||
}
|
||||
|
||||
def RewardFacilityCapture(
|
||||
|
|
|
|||
|
|
@ -29,8 +29,13 @@ object Support {
|
|||
//setup
|
||||
val historyList = history.toList
|
||||
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 {
|
||||
case (Some(spawn), Some(death)) => death.time - spawn.time
|
||||
*/
|
||||
val fullLifespan = historyList.headOption match {
|
||||
case Some(spawn) => System.currentTimeMillis() - spawn.time
|
||||
case _ => 0L
|
||||
}
|
||||
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 _ => ()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -160,6 +160,7 @@ object AvatarAction {
|
|||
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 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 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 AwardCep(charId: Long, bep: 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)
|
||||
building.Participation.RewardFacilityCapture(
|
||||
target.Faction,
|
||||
faction,
|
||||
HackCaptureActor.GetAttackingFaction(building, faction),
|
||||
hacker,
|
||||
facilityHackTime,
|
||||
hackTime,
|
||||
|
|
@ -347,6 +347,30 @@ object HackCaptureActor {
|
|||
.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] = {
|
||||
terminal.HackedBy.map { a => a.player.Faction }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,7 +163,8 @@ case class GameConfig(
|
|||
doorsCanBeOpenedByMedAppFromThisDistance: Float,
|
||||
experience: Experience,
|
||||
maxBattleRank: Int,
|
||||
promotion: PromotionSystem
|
||||
promotion: PromotionSystem,
|
||||
facilityHackTime: FiniteDuration
|
||||
)
|
||||
|
||||
case class InstantActionConfig(
|
||||
|
|
|
|||
Loading…
Reference in a new issue