More caverns work (#335)

* Add functionality for cavern sentry turrets

* Add missing LastDischarge on Tool

* Fix BuildingControl GUID errors on server startup

* Fix instant REK access to terminals in a cavern facility with a hacked CC

* Simplify CC Amenity matching

* Modify warning to match disabled functionality
This commit is contained in:
Mazo 2020-02-14 15:52:57 +00:00 committed by GitHub
parent 9d67029238
commit 06ef3a08c5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 515 additions and 9 deletions

View file

@ -785,6 +785,8 @@ object GlobalDefinitions {
val phalanx_flakcombo = ToolDefinition(ObjectClass.phalanx_flakcombo)
val vanu_sentry_turret_weapon = ToolDefinition(ObjectClass.vanu_sentry_turret_weapon)
val spitfire_weapon = ToolDefinition(ObjectClass.spitfire_weapon)
val spitfire_aa_weapon = ToolDefinition(ObjectClass.spitfire_aa_weapon)
@ -1002,6 +1004,8 @@ object GlobalDefinitions {
val manned_turret = new FacilityTurretDefinition(480)
val vanu_sentry_turret = new FacilityTurretDefinition(943)
val painbox = new PainboxDefinition(622)
val painbox_continuous = new PainboxDefinition(623)
@ -5081,6 +5085,15 @@ object GlobalDefinitions {
phalanx_flakcombo.FireModes(1).AmmoSlotIndex = 0
phalanx_flakcombo.FireModes(1).Magazine = 4000
vanu_sentry_turret_weapon.Name = "vanu_sentry_turret_weapon"
vanu_sentry_turret_weapon.Size = EquipmentSize.BaseTurretWeapon
vanu_sentry_turret_weapon.AmmoTypes += ancient_ammo_vehicle
vanu_sentry_turret_weapon.ProjectileTypes += vanu_sentry_turret_projectile
vanu_sentry_turret_weapon.FireModes += new FireModeDefinition
vanu_sentry_turret_weapon.FireModes.head.AmmoTypeIndices += 0
vanu_sentry_turret_weapon.FireModes.head.AmmoSlotIndex = 0
vanu_sentry_turret_weapon.FireModes.head.Magazine = 100
spitfire_weapon.Name = "spitfire_weapon"
spitfire_weapon.Size = EquipmentSize.BaseTurretWeapon
spitfire_weapon.AmmoTypes += spitfire_ammo
@ -6268,6 +6281,15 @@ object GlobalDefinitions {
manned_turret.FactionLocked = true
manned_turret.ReserveAmmunition = false
vanu_sentry_turret.Name = "vanu_sentry_turret"
vanu_sentry_turret.MaxHealth = 1500
vanu_sentry_turret.Weapons += 1 -> new mutable.HashMap()
vanu_sentry_turret.Weapons(1) += TurretUpgrade.None -> vanu_sentry_turret_weapon
vanu_sentry_turret.MountPoints += 1 -> 0
vanu_sentry_turret.MountPoints += 2 -> 0
vanu_sentry_turret.FactionLocked = false
vanu_sentry_turret.ReserveAmmunition = false
gen_control.Name = "gen_control"
generator.Name = "generator"

View file

@ -24,6 +24,7 @@ class Tool(private val toolDef : ToolDefinition) extends Equipment
private var fireModeIndex : Int = toolDef.DefaultFireModeIndex
/** current ammunition slot being used by this fire mode */
private var ammoSlots : List[Tool.FireModeSlot] = List.empty
var lastDischarge : Long = 0
Tool.LoadDefinition(this)
@ -97,9 +98,14 @@ class Tool(private val toolDef : ToolDefinition) extends Equipment
}
def Discharge : Int = {
lastDischarge = System.nanoTime()
Magazine = FireMode.Discharge(this)
}
def LastDischarge : Long = {
lastDischarge
}
def AmmoSlot : Tool.FireModeSlot = ammoSlots(FireMode.AmmoSlotIndex)
def AmmoSlots : List[Tool.FireModeSlot] = ammoSlots

View file

@ -76,7 +76,7 @@ class Building(private val name: String,
}
def CaptureConsoleIsHacked : Boolean = {
Amenities.find(x => x.Definition == GlobalDefinitions.capture_terminal).asInstanceOf[Option[CaptureTerminal]] match {
Amenities.find(x => x.isInstanceOf[CaptureTerminal]).asInstanceOf[Option[CaptureTerminal]] match {
case Some(obj: CaptureTerminal) =>
obj.HackedBy.isDefined
case None => false
@ -174,7 +174,7 @@ class Building(private val name: String,
) = {
val ntuLevel : Int = NtuLevel
//if we have a capture terminal, get the hack status & time (in milliseconds) from control console if it exists
val (hacking, hackingFaction, hackTime) : (Boolean, PlanetSideEmpire.Value, Long) = Amenities.find(x => x.Definition == GlobalDefinitions.capture_terminal || x.Definition == GlobalDefinitions.vanu_control_console) match {
val (hacking, hackingFaction, hackTime) : (Boolean, PlanetSideEmpire.Value, Long) = Amenities.find(x => x.isInstanceOf[CaptureTerminal]) match {
case Some(obj: CaptureTerminal with Hackable) =>
obj.HackedBy match {
case Some(Hackable.HackInfo(_, _, hfaction, _, start, length)) =>

View file

@ -68,6 +68,8 @@ object FacilityTurret {
new FacilityTurret(tDef)
}
final case class RechargeAmmo()
import akka.actor.ActorContext
/**
* Instantiate and configure a `FacilityTurret` object

View file

@ -1,8 +1,8 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.turret
import akka.actor.Actor
import net.psforever.objects.Player
import akka.actor.{Actor, Cancellable}
import net.psforever.objects.{DefaultCancellable, GlobalDefinitions, Player}
import net.psforever.objects.ballistics.ResolvedProjectile
import net.psforever.objects.equipment.{JammableMountedWeapons, JammableUnit}
import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior}
@ -12,9 +12,14 @@ import net.psforever.objects.zones.Zone
import net.psforever.types.PlanetSideGUID
import services.Service
import services.avatar.{AvatarAction, AvatarServiceMessage}
import services.local.{LocalAction, LocalServiceMessage}
import services.vehicle.{VehicleAction, VehicleServiceMessage}
import services.vehicle.support.TurretUpgrader
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
/**
* An `Actor` that handles messages being dispatched to a specific `MannedTurret`.<br>
* <br>
@ -28,6 +33,11 @@ class FacilityTurretControl(turret : FacilityTurret) extends Actor
with MountableBehavior.Dismount
with JammableMountedWeapons {
if(turret.Definition == GlobalDefinitions.vanu_sentry_turret) {
// todo: Schedule this to start when weapon is discharged, not all the time
context.system.scheduler.schedule(3 seconds, 200 milliseconds, self, FacilityTurret.RechargeAmmo())
}
def MountableObject = turret
def JammableObject = turret
@ -38,6 +48,18 @@ class FacilityTurretControl(turret : FacilityTurret) extends Actor
.orElse(jammableBehavior)
.orElse(dismountBehavior)
.orElse {
case FacilityTurret.RechargeAmmo() =>
val weapon = turret.ControlledWeapon(1).get.asInstanceOf[net.psforever.objects.Tool]
// recharge when last shot fired 3s delay, +1, 200ms interval
if(weapon.Magazine < weapon.MaxMagazine && System.nanoTime() - weapon.LastDischarge > 3000000000L) {
weapon.Magazine += 1
val seat = turret.Seat(0).get
seat.Occupant match {
case Some(player: Player) => turret.Zone.LocalEvents ! LocalServiceMessage(turret.Zone.Id, LocalAction.RechargeVehicleWeapon(player.GUID, turret.GUID, weapon.GUID))
case _ => ;
}
}
case Mountable.TryMount(user, seat_num) =>
turret.Seat(seat_num) match {
case Some(seat) =>

View file

@ -31,6 +31,8 @@ import scalax.collection.Graph
import scalax.collection.GraphPredef._
import scalax.collection.GraphEdge._
import scala.util.Success
/**
* A server object representing the one-landmass planets as well as the individual subterranean caverns.<br>
* <br>
@ -408,9 +410,12 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
val buildingList = Map.LocalBuildings
buildings = buildingList.map({
case((name, building_guid, map_id), constructor) =>
val building = constructor.Build(name, building_guid, map_id, this)
guid.register(building, building_guid)
building_guid -> building
guid.register(building_guid) match {
case Success(registeredGuid) =>
val building = constructor.Build(name, building_guid, map_id, this)
registeredGuid.Object = building
building_guid -> building
}
})
buildings
}

View file

@ -153,6 +153,10 @@ class LocalService(zone : Zone) extends Actor {
LocalServiceResponse(s"/$forChannel/Local", player_guid, LocalResponse.UpdateForceDomeStatus(building_guid, activated))
)
}
case LocalAction.RechargeVehicleWeapon(player_guid, vehicle_guid, weapon_guid) =>
LocalEvents.publish(
LocalServiceResponse(s"/$forChannel/Local", player_guid, LocalResponse.RechargeVehicleWeapon(vehicle_guid, weapon_guid))
)
case _ => ;
}

View file

@ -40,4 +40,5 @@ object LocalAction {
final case class TriggerEffectLocation(player_guid : PlanetSideGUID, effect : String, pos : Vector3, orient : Vector3) extends Action
final case class TriggerSound(player_guid : PlanetSideGUID, sound : TriggeredSound.Value, pos : Vector3, unk : Int, volume : Float) extends Action
final case class UpdateForceDomeStatus(player_guid : PlanetSideGUID, building_guid : PlanetSideGUID, activated : Boolean) extends Action
final case class RechargeVehicleWeapon(player_guid: PlanetSideGUID, mountable_guid: PlanetSideGUID, weapon_guid: PlanetSideGUID) extends Action
}

View file

@ -36,4 +36,5 @@ object LocalResponse {
final case class TriggerEffect(target: PlanetSideGUID, effect: String, effectInfo: Option[TriggeredEffect] = None, triggeredLocation: Option[TriggeredEffectLocation] = None) extends Response
final case class TriggerSound(sound : TriggeredSound.Value, pos : Vector3, unk : Int, volume : Float) extends Response
final case class UpdateForceDomeStatus(building_guid : PlanetSideGUID, activated : Boolean) extends Response
final case class RechargeVehicleWeapon(mountable_guid: PlanetSideGUID, weapon_guid: PlanetSideGUID) extends Response
}

View file

@ -252,7 +252,7 @@ class FacilityTurretObjectBuilderTest extends ActorTest {
"build" in {
val hub = ServerObjectBuilderTest.NumberPoolHub
val actor = system.actorOf(Props(classOf[ServerObjectBuilderTest.BuilderTestActor], ServerObjectBuilder(1,
FacilityTurret.Constructor(manned_turret)), hub), "spawn-tube")
FacilityTurret.Constructor(manned_turret)), hub), "manned-turret")
actor ! "!"
val reply = receiveOne(Duration.create(1000, "ms"))