mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-20 02:54:46 +00:00
separated router/telepad activity from other vehicular activity, previously all considered a form of mounting/dismounting, and restored support experience rewards
This commit is contained in:
parent
8701cfa3a5
commit
734baacbb5
|
|
@ -408,8 +408,14 @@ game {
|
|||
base = 25
|
||||
}
|
||||
{
|
||||
name = "router"
|
||||
name = "router-driver"
|
||||
base = 15
|
||||
shots-multiplier = 1.0
|
||||
}
|
||||
{
|
||||
name = "telepad-use"
|
||||
base = 20
|
||||
shots-multiplier = 1.0
|
||||
}
|
||||
{
|
||||
name = "hotdrop"
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import net.psforever.objects.serverobject.terminals.capture.CaptureTerminal
|
|||
import net.psforever.objects.serverobject.terminals.{MatrixTerminalDefinition, Terminal}
|
||||
import net.psforever.objects.serverobject.tube.SpawnTube
|
||||
import net.psforever.objects.serverobject.turret.FacilityTurret
|
||||
import net.psforever.objects.sourcing.{PlayerSource, VehicleSource}
|
||||
import net.psforever.objects.sourcing.{DeployableSource, PlayerSource, VehicleSource}
|
||||
import net.psforever.objects.vehicles.Utility.InternalTelepad
|
||||
import net.psforever.objects.zones.blockmap.BlockMapEntity
|
||||
import net.psforever.services.RemoverActor
|
||||
|
|
@ -1372,11 +1372,8 @@ class GeneralOperations(
|
|||
continent.id,
|
||||
LocalAction.RouterTelepadTransport(pguid, pguid, sguid, dguid)
|
||||
)
|
||||
val vSource = VehicleSource(router)
|
||||
val zoneNumber = continent.Number
|
||||
player.LogActivity(VehicleMountActivity(vSource, PlayerSource(player), zoneNumber))
|
||||
player.Position = dest.Position
|
||||
player.LogActivity(VehicleDismountActivity(vSource, PlayerSource(player), zoneNumber))
|
||||
player.LogActivity(TelepadUseActivity(VehicleSource(router), DeployableSource(remoteTelepad), PlayerSource(player)))
|
||||
} else {
|
||||
log.warn(s"UseRouterTelepadSystem: ${player.Name} can not teleport")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ package net.psforever.objects.vital
|
|||
import net.psforever.objects.PlanetSideGameObject
|
||||
import net.psforever.objects.definition.{EquipmentDefinition, KitDefinition, ToolDefinition}
|
||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||
import net.psforever.objects.sourcing.{AmenitySource, PlayerSource, SourceEntry, SourceUniqueness, SourceWithHealthEntry, VehicleSource}
|
||||
import net.psforever.objects.sourcing.{AmenitySource, DeployableSource, PlayerSource, SourceEntry, SourceUniqueness, SourceWithHealthEntry, VehicleSource}
|
||||
import net.psforever.objects.vital.environment.EnvironmentReason
|
||||
import net.psforever.objects.vital.etc.{ExplodingEntityReason, PainboxReason, SuicideReason}
|
||||
import net.psforever.objects.vital.interaction.{DamageInteraction, DamageResult}
|
||||
|
|
@ -82,6 +82,9 @@ final case class ShieldCharge(amount: Int, cause: Option[SourceEntry])
|
|||
final case class TerminalUsedActivity(terminal: AmenitySource, transaction: TransactionType.Value)
|
||||
extends GeneralActivity
|
||||
|
||||
final case class TelepadUseActivity(router: VehicleSource, telepad: DeployableSource, player: PlayerSource)
|
||||
extends GeneralActivity
|
||||
|
||||
sealed trait VehicleMountChange extends GeneralActivity {
|
||||
def vehicle: VehicleSource
|
||||
def zoneNumber: Int
|
||||
|
|
@ -248,7 +251,7 @@ trait InGameHistory {
|
|||
*/
|
||||
def LogActivity(action: Option[InGameActivity]): List[InGameActivity] = {
|
||||
action match {
|
||||
case Some(act: VehicleDismountActivity) =>
|
||||
case Some(act: VehicleDismountActivity) if act.pairedEvent.isEmpty =>
|
||||
history
|
||||
.findLast(_.isInstanceOf[VehicleMountActivity])
|
||||
.collect {
|
||||
|
|
@ -259,6 +262,8 @@ trait InGameHistory {
|
|||
history = history :+ act
|
||||
None
|
||||
}
|
||||
case Some(act: VehicleDismountActivity) =>
|
||||
history = history :+ act
|
||||
case Some(act: VehicleCargoDismountActivity) =>
|
||||
history
|
||||
.findLast(_.isInstanceOf[VehicleCargoMountActivity])
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import akka.actor.ActorRef
|
|||
import net.psforever.objects.GlobalDefinitions
|
||||
import net.psforever.objects.avatar.scoring.{Kill, SupportActivity}
|
||||
import net.psforever.objects.sourcing.{BuildingSource, PlayerSource, SourceEntry, SourceUniqueness, TurretSource, VehicleSource}
|
||||
import net.psforever.objects.vital.{Contribution, HealFromTerminal, InGameActivity, RepairFromTerminal, RevivingActivity, TerminalUsedActivity, VehicleCargoDismountActivity, VehicleCargoMountActivity, VehicleDismountActivity, VehicleMountActivity}
|
||||
import net.psforever.objects.vital.{Contribution, HealFromTerminal, InGameActivity, RepairFromTerminal, RevivingActivity, TelepadUseActivity, TerminalUsedActivity, VehicleCargoDismountActivity, VehicleCargoMountActivity, VehicleDismountActivity, VehicleMountActivity}
|
||||
import net.psforever.objects.vital.projectile.ProjectileReason
|
||||
import net.psforever.objects.zones.exp.rec.{CombinedHealthAndArmorContributionProcess, MachineRecoveryExperienceContributionProcess}
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
|
|
@ -55,6 +55,11 @@ object KillContributions {
|
|||
/** cached for empty collection returns; please do not add anything to it */
|
||||
private val emptyMap: mutable.LongMap[ContributionStats] = mutable.LongMap.empty[ContributionStats]
|
||||
|
||||
/** cached for use with telepad deployable activities, from the perspective of the router */
|
||||
private val routerKillAssist = RouterKillAssist(GlobalDefinitions.router.ObjectId)
|
||||
/** cached for use with telepad deployable activities */
|
||||
private val routerTelepadKillAssist = RouterKillAssist(GlobalDefinitions.router_telepad_deployable.ObjectId)
|
||||
|
||||
/**
|
||||
* Primary landing point for calculating the rewards given for helping one player kill another player.
|
||||
* Rewards in the form of "support experience points" are given
|
||||
|
|
@ -263,6 +268,7 @@ object KillContributions {
|
|||
): mutable.LongMap[ContributionStats] = {
|
||||
contributeWithRevivalActivity(history, existingParticipants)
|
||||
contributeWithTerminalActivity(history, faction, contributions, excludedTargets, existingParticipants)
|
||||
contributeWithRouterTelepadActivity(kill, history, faction, contributions, excludedTargets, existingParticipants)
|
||||
contributeWithVehicleTransportActivity(kill, history, faction, contributions, excludedTargets, existingParticipants)
|
||||
contributeWithVehicleCargoTransportActivity(kill, history, faction, contributions, excludedTargets, existingParticipants)
|
||||
contributeWithKillWhileMountedActivity(kill, faction, contributions, excludedTargets, existingParticipants)
|
||||
|
|
@ -371,10 +377,17 @@ object KillContributions {
|
|||
/*
|
||||
collect the dismount activity of all vehicles from which this player is not the owner
|
||||
make certain all dismount activity can be paired with a mounting activity
|
||||
certain other qualifications of the prior mounting must be met before the support bonus applies
|
||||
other qualifications of the prior mounting must be met before the support bonus applies
|
||||
*/
|
||||
val killerOpt = kill.info.adversarial
|
||||
.map(_.attacker)
|
||||
.collect { case p: PlayerSource => p }
|
||||
val dismountActivity = history
|
||||
.collect {
|
||||
/*
|
||||
the player should not get credit from being the vehicle owner in matters of transportation
|
||||
there are considerations of time and distance traveled before the kill as well
|
||||
*/
|
||||
case out: VehicleDismountActivity
|
||||
if !out.vehicle.owner.contains(out.player.unique) && out.pairedEvent.nonEmpty => (out.pairedEvent.get, out)
|
||||
}
|
||||
|
|
@ -382,29 +395,30 @@ object KillContributions {
|
|||
case (in: VehicleMountActivity, out: VehicleDismountActivity)
|
||||
if in.vehicle.unique == out.vehicle.unique &&
|
||||
out.vehicle.Faction == out.player.Faction &&
|
||||
(in.vehicle.Definition == GlobalDefinitions.router || {
|
||||
val inTime = in.time
|
||||
val outTime = out.time
|
||||
out.player.progress.kills.exists { death =>
|
||||
val deathTime = death.info.interaction.hitTime
|
||||
inTime < deathTime && deathTime <= outTime
|
||||
}
|
||||
} || {
|
||||
val sameZone = in.zoneNumber == out.zoneNumber
|
||||
val distanceTransported = Vector3.DistanceSquared(in.vehicle.Position.xy, out.vehicle.Position.xy)
|
||||
val distanceMoved = {
|
||||
val killLocation = kill.info.adversarial
|
||||
.collect { adversarial => adversarial.attacker.Position.xy }
|
||||
.getOrElse(Vector3.Zero)
|
||||
Vector3.DistanceSquared(killLocation, out.player.Position.xy)
|
||||
}
|
||||
val timeSpent = out.time - in.time
|
||||
distanceMoved < 5625f /* 75m */ &&
|
||||
(timeSpent >= 210000L /* 3:30 */ ||
|
||||
(sameZone && (distanceTransported > 160000f /* 400m */ ||
|
||||
distanceTransported > 10000f /* 100m */ && timeSpent >= 60000L /* 1:00m */)) ||
|
||||
(!sameZone && (distanceTransported > 10000f /* 100m */ || timeSpent >= 120000L /* 2:00 */ )))
|
||||
}) =>
|
||||
/*
|
||||
considerations of time and distance transported before the kill
|
||||
*/
|
||||
({
|
||||
val inTime = in.time
|
||||
val outTime = out.time
|
||||
out.player.progress.kills.exists { death =>
|
||||
val deathTime = death.info.interaction.hitTime
|
||||
inTime < deathTime && deathTime <= outTime
|
||||
}
|
||||
} || {
|
||||
val sameZone = in.zoneNumber == out.zoneNumber
|
||||
val distanceTransported = Vector3.DistanceSquared(in.vehicle.Position.xy, out.vehicle.Position.xy)
|
||||
val distanceMoved = {
|
||||
val killLocation = killerOpt.map(_.Position.xy).getOrElse(Vector3.Zero)
|
||||
Vector3.DistanceSquared(killLocation, out.player.Position.xy)
|
||||
}
|
||||
val timeSpent = out.time - in.time
|
||||
distanceMoved < 5625f /* 75m */ &&
|
||||
(timeSpent >= 210000L /* 3:30 */ ||
|
||||
(sameZone && (distanceTransported > 160000f /* 400m */ ||
|
||||
distanceTransported > 10000f /* 100m */ && timeSpent >= 60000L /* 1:00m */)) ||
|
||||
(!sameZone && (distanceTransported > 10000f /* 100m */ || timeSpent >= 120000L /* 2:00 */ )))
|
||||
}) =>
|
||||
out
|
||||
}
|
||||
//apply
|
||||
|
|
@ -412,25 +426,20 @@ object KillContributions {
|
|||
.groupBy { _.vehicle }
|
||||
.collect { case (mount, dismountsFromVehicle) if mount.owner.nonEmpty =>
|
||||
val promotedOwner = PlayerSource(mount.owner.get, mount.Position)
|
||||
val (equipmentUseContext, equipmentUseEvent) = mount.Definition match {
|
||||
case v @ GlobalDefinitions.router =>
|
||||
(RouterKillAssist(v.ObjectId), "router")
|
||||
case v =>
|
||||
(HotDropKillAssist(v.ObjectId, 0), "hotdrop")
|
||||
}
|
||||
val size = dismountsFromVehicle.size
|
||||
val time = dismountsFromVehicle.maxBy(_.time).time
|
||||
val weaponStat = Support.calculateSupportExperience(
|
||||
equipmentUseEvent,
|
||||
WeaponStats(equipmentUseContext, size, size, time, 1f)
|
||||
)
|
||||
combineStatsInto(
|
||||
out,
|
||||
(
|
||||
promotedOwner.CharId,
|
||||
ContributionStats(promotedOwner, Seq(weaponStat), size, size, size, time)
|
||||
)
|
||||
)
|
||||
List((HotDropKillAssist(mount.Definition.ObjectId, 0), "hotdrop", promotedOwner))
|
||||
.foreach {
|
||||
case (equipmentUseContext, equipmentUseEvent, eventOwner) =>
|
||||
val weaponStat = Support.calculateSupportExperience(
|
||||
equipmentUseEvent,
|
||||
WeaponStats(equipmentUseContext, size, size, time, 1f)
|
||||
)
|
||||
combineStatsInto(
|
||||
out,
|
||||
(eventOwner.CharId, ContributionStats(eventOwner, Seq(weaponStat), size, size, size, time))
|
||||
)
|
||||
}
|
||||
contributions.get(mount.unique).collect {
|
||||
case list =>
|
||||
val mountHistory = dismountsFromVehicle
|
||||
|
|
@ -554,6 +563,86 @@ object KillContributions {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gather and reward use of a telepad deployable in performing a kill.
|
||||
* There are two ways to account for telepad deployable use,
|
||||
* i.e., traveling through s telepad deployable or using the internal telepad system of a Router:
|
||||
* the user that places the telepad deployable unit,
|
||||
* and the user that owns the Router.<br>
|
||||
* na
|
||||
* @param kill the in-game event that maintains information about the other player's death
|
||||
* @param faction empire to target
|
||||
* @param contributions mapping between external entities
|
||||
* the target has interacted with in the form of in-game activity
|
||||
* and history related to the time period in which the interaction ocurred
|
||||
* @param excludedTargets if a potential target is listed here already, skip processing it
|
||||
* @param out quantitative record of activity in relation to the other players and their equipment
|
||||
* @see `combineStatsInto`
|
||||
* @see `extractContributionsForMachineByTarget`
|
||||
*/
|
||||
private def contributeWithRouterTelepadActivity(
|
||||
kill: Kill,
|
||||
history: List[InGameActivity],
|
||||
faction: PlanetSideEmpire.Value,
|
||||
contributions: Map[SourceUniqueness, List[InGameActivity]],
|
||||
excludedTargets: mutable.ListBuffer[SourceUniqueness],
|
||||
out: mutable.LongMap[ContributionStats]
|
||||
): Unit = {
|
||||
/*
|
||||
collect the use of all router telepads from which this player is not the owner (deployer) of the telepad
|
||||
*/
|
||||
val killer = kill.info.adversarial
|
||||
.map(_.attacker)
|
||||
.collect { case p: PlayerSource => p }
|
||||
.getOrElse(PlayerSource.Nobody)
|
||||
history
|
||||
.collect {
|
||||
case event: TelepadUseActivity if !event.player.Name.equals(event.telepad.OwnerName) =>
|
||||
event
|
||||
}
|
||||
.groupBy(_.telepad.unique)
|
||||
.flatMap {
|
||||
case (_, telepadEvents) =>
|
||||
val size = telepadEvents.size
|
||||
val time = telepadEvents.maxBy(_.time).time
|
||||
val firstEvent = telepadEvents.head
|
||||
val telepadOwner = firstEvent.telepad.owner.asInstanceOf[PlayerSource]
|
||||
val mount = firstEvent.router
|
||||
contributions.get(mount.unique).collect {
|
||||
case list =>
|
||||
val mountHistory = telepadEvents
|
||||
.flatMap { event =>
|
||||
val eventTime = event.time
|
||||
val startTime = eventTime - Config.app.game.experience.longContributionTime
|
||||
limitHistoryToThisLife(list, eventTime, startTime)
|
||||
}
|
||||
.distinctBy(_.time)
|
||||
combineStatsInto(
|
||||
out,
|
||||
extractContributionsForMachineByTarget(mount, faction, mountHistory, contributions, excludedTargets, eventOutputType="support-repair")
|
||||
)
|
||||
}
|
||||
telepadEvents
|
||||
.flatMap(_.router.owner)
|
||||
.distinct
|
||||
.filterNot(owner => owner == killer.unique || owner == telepadOwner.unique)
|
||||
.map(p => (WeaponStats(routerKillAssist, size, size, time, 1f), "router-driver", PlayerSource(p, Vector3.Zero))) :+
|
||||
(WeaponStats(routerTelepadKillAssist, size, size, time, 1f), "telepad-use", telepadOwner)
|
||||
}
|
||||
.foreach {
|
||||
case (equipmentUseContext, equipmentUseEventId, eventOwner) =>
|
||||
val size = equipmentUseContext.amount
|
||||
val weaponStat = Support.calculateSupportExperience(equipmentUseEventId, equipmentUseContext)
|
||||
combineStatsInto(
|
||||
out,
|
||||
(
|
||||
eventOwner.CharId,
|
||||
ContributionStats(eventOwner, Seq(weaponStat), size, size, size, equipmentUseContext.time)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gather and reward specific in-game equipment use activity.<br>
|
||||
* na
|
||||
|
|
|
|||
|
|
@ -676,12 +676,14 @@ object Support {
|
|||
val shots = weaponStat.shots
|
||||
val shotsMax = event.shotsMax
|
||||
val shotsMultiplier = event.shotsMultiplier
|
||||
if (shotsMultiplier > 0f && shots < event.shotsCutoff) {
|
||||
val modifiedShotsReward: Float =
|
||||
shotsMultiplier * math.log(math.min(shotsMax, shots).toDouble + 2d).toFloat
|
||||
val modifiedAmountReward: Float =
|
||||
event.amountMultiplier * weaponStat.amount.toFloat
|
||||
event.base.toFloat + modifiedShotsReward + modifiedAmountReward
|
||||
if (shots < event.shotsCutoff) {
|
||||
if (shotsMultiplier > 0f) {
|
||||
val modifiedShotsReward: Float = shotsMultiplier * math.log(math.min(shotsMax, shots).toDouble + 2d).toFloat
|
||||
val modifiedAmountReward: Float = event.amountMultiplier * weaponStat.amount.toFloat
|
||||
event.base.toFloat + modifiedShotsReward + modifiedAmountReward
|
||||
} else {
|
||||
event.base.toFloat
|
||||
}
|
||||
} else {
|
||||
0f
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue