Spawn Pad Fix (#394)

* reset pad order queueing system if the player forces a system fix; blocking dismounting of vehicle in certain situations, such as the vehicle just being spawned

* test fixes
This commit is contained in:
Fate-JH 2020-04-27 21:31:53 -04:00 committed by GitHub
parent 9f12cfa625
commit 4e5bb3a252
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 62 additions and 38 deletions

View file

@ -112,6 +112,8 @@ class VehicleSpawnControl(pad : VehicleSpawnPad) extends VehicleSpawnControlBase
case None => ;
}
trackedOrder = None
handleOrderFunc = NewTasking
pad.Zone.VehicleEvents ! VehicleSpawnPad.ResetSpawnPad(pad) //cautious animation reset
concealPlayer ! akka.actor.Kill //should cause the actor to restart, which will abort any trapped messages
case _ => ;

View file

@ -26,7 +26,7 @@ class VehicleSpawnControlConcealPlayer(pad : VehicleSpawnPad) extends VehicleSpa
def receive : Receive = {
case order @ VehicleSpawnControl.Order(driver, _) =>
//TODO how far can the driver stray from the Terminal before his order is cancelled?
if(driver.Continent == pad.Continent && driver.VehicleSeated.isEmpty) {
if(driver.Continent == pad.Continent && driver.VehicleSeated.isEmpty && driver.isAlive) {
trace(s"hiding ${driver.Name}")
pad.Zone.VehicleEvents ! VehicleSpawnPad.ConcealPlayer(driver.GUID)
context.system.scheduler.scheduleOnce(2000 milliseconds, loadVehicle, order)

View file

@ -28,6 +28,7 @@ class VehicleSpawnControlDriverControl(pad : VehicleSpawnPad) extends VehicleSpa
else {
trace(s"${driver.Name} is not seated in ${vehicle.Definition.Name}; vehicle controls might have been locked")
}
vehicle.MountedIn = None
finalClear ! order
case msg @ (VehicleSpawnControl.ProcessControl.Reminder | VehicleSpawnControl.ProcessControl.GetNewOrder) =>

View file

@ -28,7 +28,7 @@ class VehicleSpawnControlLoadVehicle(pad : VehicleSpawnPad) extends VehicleSpawn
def receive : Receive = {
case order @ VehicleSpawnControl.Order(driver, vehicle) =>
if(driver.Continent == pad.Continent && vehicle.Health > 0) {
if(driver.Continent == pad.Continent && vehicle.Health > 0 && driver.isAlive) {
trace(s"loading the ${vehicle.Definition.Name}")
vehicle.Position = vehicle.Position - Vector3.z(if(GlobalDefinitions.isFlightVehicle(vehicle.Definition)) 9 else 5) //appear below the trench and doors
vehicle.Cloaked = vehicle.Definition.CanCloak && driver.Cloaked

View file

@ -26,6 +26,7 @@ class VehicleSpawnControlRailJack(pad : VehicleSpawnPad) extends VehicleSpawnCon
def receive : Receive = {
case order @ VehicleSpawnControl.Order(_, vehicle) =>
vehicle.MountedIn = pad.GUID
pad.Zone.VehicleEvents ! VehicleSpawnPad.AttachToRails(vehicle, pad)
context.system.scheduler.scheduleOnce(10 milliseconds, seatDriver, order)

View file

@ -5024,9 +5024,17 @@ class WorldSessionActor extends Actor
// TODO: Make sure this is the correct response for all cases
ValidObject(object_guid) match {
case Some(vehicle : Vehicle) =>
if((player.VehicleOwned.contains(object_guid) && vehicle.Owner.contains(player.GUID)) ||
(player.Faction == vehicle.Faction &&
((vehicle.Owner.isEmpty || continent.GUID(vehicle.Owner.get).isEmpty) || vehicle.Destroyed))) {
/* line 1a: player is admin (and overrules other access requirements) */
/* line 1b: vehicle and player (as the owner) acknowledge each other */
/* line 1c: vehicle is the same faction as player and either the owner is absent or the vehicle is destroyed */
/* line 2: vehicle is not mounted in anything or, if it is, its seats are empty */
if(
(admin ||
(player.VehicleOwned.contains(object_guid) && vehicle.Owner.contains(player.GUID)) ||
(player.Faction == vehicle.Faction && ((vehicle.Owner.isEmpty || continent.GUID(vehicle.Owner.get).isEmpty) || vehicle.Destroyed))
) &&
(vehicle.MountedIn.isEmpty || !vehicle.Seats.values.exists(_.isOccupied))
) {
vehicle.Actor ! Vehicle.Deconstruct()
log.info(s"RequestDestroy: vehicle $vehicle")
}
@ -5995,45 +6003,56 @@ class WorldSessionActor extends Actor
}
if(player.GUID == player_guid) {
//normally disembarking from a seat
player.VehicleSeated match {
case Some(obj_guid) =>
interstellarFerry.orElse(continent.GUID(obj_guid)) match {
case Some(obj : Mountable) =>
obj.PassengerInSeat(player) match {
case Some(0) if controlled.nonEmpty =>
log.warn(s"DismountVehicleMsg: can not dismount from vehicle as driver while server has asserted control; please wait ...")
case Some(seat_num : Int) =>
obj.Actor ! Mountable.TryDismount(player, seat_num)
if(interstellarFerry.isDefined) {
//short-circuit the temporary channel for transferring between zones, the player is no longer doing that
//see above in VehicleResponse.TransferPassenger case
interstellarFerry = None
}
// Deconstruct the vehicle if the driver has bailed out and the vehicle is capable of flight
//todo: implement auto landing procedure if the pilot bails but passengers are still present instead of deconstructing the vehicle
//todo: continue flight path until aircraft crashes if no passengers present (or no passenger seats), then deconstruct.
//todo: kick cargo passengers out. To be added after PR #216 is merged
obj match {
case v : Vehicle if bailType == BailType.Bailed && seat_num == 0 && v.Flying =>
v.Actor ! Vehicle.Deconstruct() // Immediately deconstruct vehicle
case _ => ;
}
case None =>
dismountWarning(s"DismountVehicleMsg: can not find where player $player_guid is seated in mountable $obj_guid")
}
case _ =>
dismountWarning(s"DismountVehicleMsg: can not find mountable entity $obj_guid")
}
case None =>
(interstellarFerry.orElse(continent.GUID(player.VehicleSeated)) match {
case out @ Some(obj : Vehicle) =>
if(obj.MountedIn.isEmpty) out else None
case out @ Some(_ : Mountable) =>
out
case _ =>
dismountWarning(s"DismountVehicleMsg: player $player_guid not considered seated in a mountable entity")
None
}) match {
case Some(obj : Mountable) =>
obj.PassengerInSeat(player) match {
case Some(0) if controlled.nonEmpty =>
log.warn(s"DismountVehicleMsg: can not dismount from vehicle as driver while server has asserted control; please wait ...")
case Some(seat_num : Int) =>
obj.Actor ! Mountable.TryDismount(player, seat_num)
if(interstellarFerry.isDefined) {
//short-circuit the temporary channel for transferring between zones, the player is no longer doing that
//see above in VehicleResponse.TransferPassenger case
interstellarFerry = None
}
// Deconstruct the vehicle if the driver has bailed out and the vehicle is capable of flight
//todo: implement auto landing procedure if the pilot bails but passengers are still present instead of deconstructing the vehicle
//todo: continue flight path until aircraft crashes if no passengers present (or no passenger seats), then deconstruct.
//todo: kick cargo passengers out. To be added after PR #216 is merged
obj match {
case v : Vehicle if bailType == BailType.Bailed && seat_num == 0 && v.Flying =>
continent.VehicleEvents ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(obj), continent))
continent.VehicleEvents ! VehicleServiceMessage.Decon(RemoverActor.AddTask(obj, continent, Some(0 seconds))) // Immediately deconstruct vehicle
case _ => ;
}
case None =>
dismountWarning(s"DismountVehicleMsg: can not find where player $player_guid is seated in mountable ${player.VehicleSeated}")
}
case _ =>
dismountWarning(s"DismountVehicleMsg: can not find mountable entity ${player.VehicleSeated}")
}
}
else {
//kicking someone else out of a seat; need to own that seat/mountable
player.VehicleOwned match {
case Some(obj_guid) =>
(ValidObject(obj_guid), ValidObject(player_guid)) match {
((ValidObject(obj_guid), ValidObject(player_guid)) match {
case (vehicle @ Some(obj : Vehicle), tplayer) =>
if(obj.MountedIn.isEmpty) (vehicle, tplayer) else (None, None)
case (mount @ Some(obj : Mountable), tplayer) =>
(mount, tplayer)
case _ =>
(None, None)
}) match {
case (Some(obj : Mountable), Some(tplayer : Player)) =>
obj.PassengerInSeat(tplayer) match {
case Some(seat_num : Int) =>

View file

@ -218,7 +218,7 @@ object VehicleSpawnPadControlTest {
val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
val weapon = vehicle.WeaponControlledFromSeat(1).get.asInstanceOf[Tool]
val guid : NumberPoolHub = new NumberPoolHub(LimitedNumberSource(5))
guid.AddPool("test-pool", (0 to 3).toList)
guid.AddPool("test-pool", (0 to 5).toList)
guid.register(vehicle, "test-pool")
guid.register(weapon, "test-pool")
guid.register(weapon.AmmoSlot.Box, "test-pool")
@ -241,6 +241,7 @@ object VehicleSpawnPadControlTest {
pad.Owner = new Building("Building", building_guid = 0, map_id = 0, zone, StructureType.Building, GlobalDefinitions.building)
pad.Owner.Faction = faction
pad.Zone = zone
guid.register(pad, "test-pool")
val player = Player(Avatar("test", faction, CharacterGender.Male, 0, CharacterVoice.Mute))
guid.register(player, "test-pool")
player.Zone = zone