mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-04-29 16:25:30 +00:00
Instant Action, Just Add ... (#1065)
* modified the instant action algorithm; added configuration flags for ams instant actioning and crashing third party activity * experimental droppod feature that was abandoned as too complicated
This commit is contained in:
parent
5b0203850d
commit
24ee12294a
3 changed files with 49 additions and 41 deletions
|
|
@ -67,8 +67,13 @@ database {
|
||||||
|
|
||||||
# Enable non-standard game properties
|
# Enable non-standard game properties
|
||||||
game {
|
game {
|
||||||
# Allow instant action to AMS
|
instant-action = {
|
||||||
instant-action-ams = no
|
# Allow instant action to direct a player to a hotspot-local friendly AMS
|
||||||
|
spawn-on-ams = no
|
||||||
|
|
||||||
|
# If no ally hotspots can be found during instant action, find a friendly spawn closest to an enemy hot spot
|
||||||
|
third-party = no
|
||||||
|
}
|
||||||
|
|
||||||
# Battle experience rate
|
# Battle experience rate
|
||||||
bep-rate = 1.0
|
bep-rate = 1.0
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
// Copyright (c) 2020 PSForever
|
||||||
package net.psforever.services
|
package net.psforever.services
|
||||||
|
|
||||||
import akka.actor.typed.receptionist.{Receptionist, ServiceKey}
|
import akka.actor.typed.receptionist.{Receptionist, ServiceKey}
|
||||||
|
|
@ -7,7 +8,7 @@ import net.psforever.actors.zone.ZoneActor
|
||||||
import net.psforever.objects.avatar.Avatar
|
import net.psforever.objects.avatar.Avatar
|
||||||
import net.psforever.objects.{Player, SpawnPoint, Vehicle}
|
import net.psforever.objects.{Player, SpawnPoint, Vehicle}
|
||||||
import net.psforever.objects.serverobject.structures.{Building, WarpGate}
|
import net.psforever.objects.serverobject.structures.{Building, WarpGate}
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.{HotSpotInfo, Zone}
|
||||||
import net.psforever.packet.game.DroppodError
|
import net.psforever.packet.game.DroppodError
|
||||||
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, SpawnGroup, Vector3}
|
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, SpawnGroup, Vector3}
|
||||||
import net.psforever.util.Config
|
import net.psforever.util.Config
|
||||||
|
|
@ -101,8 +102,8 @@ class InterstellarClusterService(context: ActorContext[InterstellarClusterServic
|
||||||
import InterstellarClusterService._
|
import InterstellarClusterService._
|
||||||
|
|
||||||
private[this] val log = org.log4s.getLogger
|
private[this] val log = org.log4s.getLogger
|
||||||
var intercontinentalSetup: Boolean = false
|
private var intercontinentalSetup: Boolean = false
|
||||||
var cavernRotation: Option[ActorRef[CavernRotationService.Command]] = None
|
private var cavernRotation: Option[ActorRef[CavernRotationService.Command]] = None
|
||||||
|
|
||||||
val zoneActors: mutable.Map[String, (ActorRef[ZoneActor.Command], Zone)] = {
|
val zoneActors: mutable.Map[String, (ActorRef[ZoneActor.Command], Zone)] = {
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
|
@ -164,47 +165,44 @@ class InterstellarClusterService(context: ActorContext[InterstellarClusterServic
|
||||||
replyTo ! ZonesResponse(zones.filter(predicate))
|
replyTo ! ZonesResponse(zones.filter(predicate))
|
||||||
|
|
||||||
case GetInstantActionSpawnPoint(faction, replyTo) =>
|
case GetInstantActionSpawnPoint(faction, replyTo) =>
|
||||||
val res = zones
|
val spawnTarget: Seq[SpawnGroup] = if (Config.app.game.instantAction.spawnOnAms) {
|
||||||
.filter(_.Players.nonEmpty)
|
Seq(SpawnGroup.Tower, SpawnGroup.Facility, SpawnGroup.AMS)
|
||||||
.flatMap { zone =>
|
} else {
|
||||||
zone.HotSpotData.collect {
|
Seq(SpawnGroup.Tower, SpawnGroup.Facility)
|
||||||
case spot => (zone, spot)
|
}
|
||||||
|
val hotspotsAndSpawnsInZones: Iterable[(Zone, HotSpotInfo, List[SpawnPoint])] = zones
|
||||||
|
.collect {
|
||||||
|
case zone if !zone.map.cavern && zone.Players.nonEmpty =>
|
||||||
|
zone.HotSpotData
|
||||||
|
.map {
|
||||||
|
info => (zone, info, zone.findNearestSpawnPoints(faction, info.DisplayLocation, spawnTarget))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.flatten
|
||||||
|
.collect {
|
||||||
|
case (zone, info, Some(spawns)) if spawns.nonEmpty => (zone, info, spawns)
|
||||||
|
}
|
||||||
|
val spawnResults: Option[(Zone, SpawnPoint)] = hotspotsAndSpawnsInZones
|
||||||
|
.maxByOption {
|
||||||
|
case (_, info, _) => info.ActivityFor(faction).map(_.Heat).getOrElse(0) //heat by target faction
|
||||||
|
}
|
||||||
|
.orElse {
|
||||||
|
if (Config.app.game.instantAction.thirdParty) {
|
||||||
|
hotspotsAndSpawnsInZones
|
||||||
|
.maxByOption {
|
||||||
|
case (_, info, _) => info.Activity.values.foldLeft(0)(_ + _.Heat) //sum of heat for all factions
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.map {
|
.map {
|
||||||
case (zone, spot) =>
|
|
||||||
(
|
|
||||||
zone,
|
|
||||||
spot,
|
|
||||||
zone.findNearestSpawnPoints(
|
|
||||||
faction,
|
|
||||||
spot.DisplayLocation,
|
|
||||||
if (Config.app.game.instantActionAms) Seq(SpawnGroup.Tower, SpawnGroup.Facility, SpawnGroup.AMS)
|
|
||||||
else Seq(SpawnGroup.Tower, SpawnGroup.Facility)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.collect {
|
|
||||||
case (zone, info, Some(spawns)) => (zone, info, spawns)
|
|
||||||
}
|
|
||||||
.toList
|
|
||||||
.sortBy { case (_, spot, _) => spot.Activity.values.foldLeft(0)(_ + _.Heat) }(
|
|
||||||
Ordering[Int].reverse
|
|
||||||
) // greatest > least
|
|
||||||
.sortWith {
|
|
||||||
case ((_, spot1, _), (_, _, _)) =>
|
|
||||||
spot1.ActivityBy().contains(faction) // prefer own faction activity
|
|
||||||
}
|
|
||||||
.headOption
|
|
||||||
.flatMap {
|
|
||||||
case (zone, info, spawns) =>
|
case (zone, info, spawns) =>
|
||||||
val pos = info.DisplayLocation
|
val pos = info.DisplayLocation
|
||||||
val spawnPoint = spawns.minBy(point => Vector3.DistanceSquared(point.Position, pos))
|
val spawnPoint = spawns.minBy(point => Vector3.DistanceSquared(point.Position, pos))
|
||||||
//Some(zone, pos, spawnPoint)
|
(zone, spawnPoint)
|
||||||
Some(zone, spawnPoint)
|
|
||||||
case _ => None
|
|
||||||
}
|
}
|
||||||
replyTo ! SpawnPointResponse(res)
|
replyTo ! SpawnPointResponse(spawnResults)
|
||||||
|
|
||||||
case GetRandomSpawnPoint(zoneNumber, faction, spawnGroups, replyTo) =>
|
case GetRandomSpawnPoint(zoneNumber, faction, spawnGroups, replyTo) =>
|
||||||
val response = zones.find(_.Number == zoneNumber) match {
|
val response = zones.find(_.Number == zoneNumber) match {
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,7 @@ case class SessionConfig(
|
||||||
)
|
)
|
||||||
|
|
||||||
case class GameConfig(
|
case class GameConfig(
|
||||||
instantActionAms: Boolean,
|
instantAction: InstantActionConfig,
|
||||||
amenityAutorepairRate: Float,
|
amenityAutorepairRate: Float,
|
||||||
amenityAutorepairDrainRate: Float,
|
amenityAutorepairDrainRate: Float,
|
||||||
bepRate: Double,
|
bepRate: Double,
|
||||||
|
|
@ -161,6 +161,11 @@ case class GameConfig(
|
||||||
doorsCanBeOpenedByMedAppFromThisDistance: Float
|
doorsCanBeOpenedByMedAppFromThisDistance: Float
|
||||||
)
|
)
|
||||||
|
|
||||||
|
case class InstantActionConfig(
|
||||||
|
spawnOnAms: Boolean,
|
||||||
|
thirdParty: Boolean
|
||||||
|
)
|
||||||
|
|
||||||
case class NewAvatar(
|
case class NewAvatar(
|
||||||
br: BattleRank,
|
br: BattleRank,
|
||||||
cr: CommandRank
|
cr: CommandRank
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue