originally just implemented drive-away speeds and timings for boarding vehicles manually; then attempted a trick where vehicles would be moved up out of the trench manually; finally, discovered how spawn platform rails work and how to find their guids easily and incorporated a nearly fully-functional vehicle spawn system(!); added examples of the 'railless' spawn pads to the East and Southeast of home3 HART C

This commit is contained in:
FateJH 2018-04-13 23:10:52 -04:00
parent fde49773cd
commit c87273c351
16 changed files with 314 additions and 90 deletions

View file

@ -845,6 +845,20 @@ object GlobalDefinitions {
} }
} }
/**
* Using the definition for a piece of `Equipment` determine whether it can fly.
* @param vdef the `VehicleDefinition` of the vehicle
* @return `true`, if it is; `false`, otherwise
*/
def isFlightVehicle(vdef : VehicleDefinition) : Boolean = {
vdef match {
case `mosquito` | `lightgunship` | `wasp` | `liberator` | `vulture` | `phantasm` | `lodestar` | `dropship` | `galaxy_gunship` =>
true
case _ =>
false
}
}
/** /**
* Initialize `AmmoBoxDefinition` globals. * Initialize `AmmoBoxDefinition` globals.
*/ */
@ -2034,6 +2048,7 @@ object GlobalDefinitions {
* Initialize `VehicleDefinition` globals. * Initialize `VehicleDefinition` globals.
*/ */
private def init_vehicles() : Unit = { private def init_vehicles() : Unit = {
fury.Name = "fury"
fury.Seats += 0 -> new SeatDefinition() fury.Seats += 0 -> new SeatDefinition()
fury.Seats(0).Bailable = true fury.Seats(0).Bailable = true
fury.Seats(0).ControlledWeapon = 1 fury.Seats(0).ControlledWeapon = 1
@ -2042,7 +2057,9 @@ object GlobalDefinitions {
fury.MountPoints += 2 -> 0 fury.MountPoints += 2 -> 0
fury.TrunkSize = InventoryTile.Tile1111 fury.TrunkSize = InventoryTile.Tile1111
fury.TrunkOffset = 30 fury.TrunkOffset = 30
fury.AutoPilotSpeeds = (24, 10)
quadassault.Name = "quadassault"
quadassault.Seats += 0 -> new SeatDefinition() quadassault.Seats += 0 -> new SeatDefinition()
quadassault.Seats(0).Bailable = true quadassault.Seats(0).Bailable = true
quadassault.Seats(0).ControlledWeapon = 1 quadassault.Seats(0).ControlledWeapon = 1
@ -2051,7 +2068,9 @@ object GlobalDefinitions {
quadassault.MountPoints += 2 -> 0 quadassault.MountPoints += 2 -> 0
quadassault.TrunkSize = InventoryTile.Tile1111 quadassault.TrunkSize = InventoryTile.Tile1111
quadassault.TrunkOffset = 30 quadassault.TrunkOffset = 30
quadassault.AutoPilotSpeeds = (24, 10)
quadstealth.Name = "quadstealth"
quadstealth.CanCloak = true quadstealth.CanCloak = true
quadstealth.Seats += 0 -> new SeatDefinition() quadstealth.Seats += 0 -> new SeatDefinition()
quadstealth.Seats(0).Bailable = true quadstealth.Seats(0).Bailable = true
@ -2060,7 +2079,9 @@ object GlobalDefinitions {
quadstealth.MountPoints += 2 -> 0 quadstealth.MountPoints += 2 -> 0
quadstealth.TrunkSize = InventoryTile.Tile1111 quadstealth.TrunkSize = InventoryTile.Tile1111
quadstealth.TrunkOffset = 30 quadstealth.TrunkOffset = 30
quadstealth.AutoPilotSpeeds = (24, 10)
two_man_assault_buggy.Name = "two_man_assault_buggy"
two_man_assault_buggy.Seats += 0 -> new SeatDefinition() two_man_assault_buggy.Seats += 0 -> new SeatDefinition()
two_man_assault_buggy.Seats(0).Bailable = true two_man_assault_buggy.Seats(0).Bailable = true
two_man_assault_buggy.Seats += 1 -> new SeatDefinition() two_man_assault_buggy.Seats += 1 -> new SeatDefinition()
@ -2071,7 +2092,9 @@ object GlobalDefinitions {
two_man_assault_buggy.MountPoints += 2 -> 1 two_man_assault_buggy.MountPoints += 2 -> 1
two_man_assault_buggy.TrunkSize = InventoryTile.Tile1511 two_man_assault_buggy.TrunkSize = InventoryTile.Tile1511
two_man_assault_buggy.TrunkOffset = 30 two_man_assault_buggy.TrunkOffset = 30
two_man_assault_buggy.AutoPilotSpeeds = (22, 8)
skyguard.Name = "skyguard"
skyguard.Seats += 0 -> new SeatDefinition() skyguard.Seats += 0 -> new SeatDefinition()
skyguard.Seats(0).Bailable = true skyguard.Seats(0).Bailable = true
skyguard.Seats += 1 -> new SeatDefinition() skyguard.Seats += 1 -> new SeatDefinition()
@ -2083,7 +2106,9 @@ object GlobalDefinitions {
skyguard.MountPoints += 3 -> 1 skyguard.MountPoints += 3 -> 1
skyguard.TrunkSize = InventoryTile.Tile1511 skyguard.TrunkSize = InventoryTile.Tile1511
skyguard.TrunkOffset = 30 skyguard.TrunkOffset = 30
skyguard.AutoPilotSpeeds = (22, 8)
threemanheavybuggy.Name = "threemanheavybuggy"
threemanheavybuggy.Seats += 0 -> new SeatDefinition() threemanheavybuggy.Seats += 0 -> new SeatDefinition()
threemanheavybuggy.Seats(0).Bailable = true threemanheavybuggy.Seats(0).Bailable = true
threemanheavybuggy.Seats += 1 -> new SeatDefinition() threemanheavybuggy.Seats += 1 -> new SeatDefinition()
@ -2099,7 +2124,9 @@ object GlobalDefinitions {
threemanheavybuggy.MountPoints += 3 -> 2 threemanheavybuggy.MountPoints += 3 -> 2
threemanheavybuggy.TrunkSize = InventoryTile.Tile1511 threemanheavybuggy.TrunkSize = InventoryTile.Tile1511
threemanheavybuggy.TrunkOffset = 30 threemanheavybuggy.TrunkOffset = 30
threemanheavybuggy.AutoPilotSpeeds = (22, 8)
twomanheavybuggy.Name = "twomanheavybuggy"
twomanheavybuggy.Seats += 0 -> new SeatDefinition() twomanheavybuggy.Seats += 0 -> new SeatDefinition()
twomanheavybuggy.Seats(0).Bailable = true twomanheavybuggy.Seats(0).Bailable = true
twomanheavybuggy.Seats += 1 -> new SeatDefinition() twomanheavybuggy.Seats += 1 -> new SeatDefinition()
@ -2110,7 +2137,9 @@ object GlobalDefinitions {
twomanheavybuggy.MountPoints += 2 -> 1 twomanheavybuggy.MountPoints += 2 -> 1
twomanheavybuggy.TrunkSize = InventoryTile.Tile1511 twomanheavybuggy.TrunkSize = InventoryTile.Tile1511
twomanheavybuggy.TrunkOffset = 30 twomanheavybuggy.TrunkOffset = 30
twomanheavybuggy.AutoPilotSpeeds = (22, 8)
twomanhoverbuggy.Name = "twomanhoverbuggy"
twomanhoverbuggy.Seats += 0 -> new SeatDefinition() twomanhoverbuggy.Seats += 0 -> new SeatDefinition()
twomanhoverbuggy.Seats(0).Bailable = true twomanhoverbuggy.Seats(0).Bailable = true
twomanhoverbuggy.Seats += 1 -> new SeatDefinition() twomanhoverbuggy.Seats += 1 -> new SeatDefinition()
@ -2121,7 +2150,9 @@ object GlobalDefinitions {
twomanhoverbuggy.MountPoints += 2 -> 1 twomanhoverbuggy.MountPoints += 2 -> 1
twomanhoverbuggy.TrunkSize = InventoryTile.Tile1511 twomanhoverbuggy.TrunkSize = InventoryTile.Tile1511
twomanhoverbuggy.TrunkOffset = 30 twomanhoverbuggy.TrunkOffset = 30
twomanhoverbuggy.AutoPilotSpeeds = (22, 10)
mediumtransport.Name = "mediumtransport"
mediumtransport.Seats += 0 -> new SeatDefinition() mediumtransport.Seats += 0 -> new SeatDefinition()
mediumtransport.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax mediumtransport.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
mediumtransport.Seats += 1 -> new SeatDefinition() mediumtransport.Seats += 1 -> new SeatDefinition()
@ -2139,7 +2170,9 @@ object GlobalDefinitions {
mediumtransport.MountPoints += 5 -> 4 mediumtransport.MountPoints += 5 -> 4
mediumtransport.TrunkSize = InventoryTile.Tile1515 mediumtransport.TrunkSize = InventoryTile.Tile1515
mediumtransport.TrunkOffset = 30 mediumtransport.TrunkOffset = 30
mediumtransport.AutoPilotSpeeds = (18, 6)
battlewagon.Name = "battlewagon"
battlewagon.Seats += 0 -> new SeatDefinition() battlewagon.Seats += 0 -> new SeatDefinition()
battlewagon.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax battlewagon.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
battlewagon.Seats += 1 -> new SeatDefinition() battlewagon.Seats += 1 -> new SeatDefinition()
@ -2161,7 +2194,9 @@ object GlobalDefinitions {
battlewagon.MountPoints += 5 -> 4 battlewagon.MountPoints += 5 -> 4
battlewagon.TrunkSize = InventoryTile.Tile1515 battlewagon.TrunkSize = InventoryTile.Tile1515
battlewagon.TrunkOffset = 30 battlewagon.TrunkOffset = 30
battlewagon.AutoPilotSpeeds = (18, 6)
thunderer.Name = "thunderer"
thunderer.Seats += 0 -> new SeatDefinition() thunderer.Seats += 0 -> new SeatDefinition()
thunderer.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax thunderer.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
thunderer.Seats += 1 -> new SeatDefinition() thunderer.Seats += 1 -> new SeatDefinition()
@ -2179,7 +2214,9 @@ object GlobalDefinitions {
thunderer.MountPoints += 5 -> 4 thunderer.MountPoints += 5 -> 4
thunderer.TrunkSize = InventoryTile.Tile1515 thunderer.TrunkSize = InventoryTile.Tile1515
thunderer.TrunkOffset = 30 thunderer.TrunkOffset = 30
thunderer.AutoPilotSpeeds = (18, 6)
aurora.Name = "aurora"
aurora.Seats += 0 -> new SeatDefinition() aurora.Seats += 0 -> new SeatDefinition()
aurora.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax aurora.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
aurora.Seats += 1 -> new SeatDefinition() aurora.Seats += 1 -> new SeatDefinition()
@ -2197,7 +2234,9 @@ object GlobalDefinitions {
aurora.MountPoints += 5 -> 4 aurora.MountPoints += 5 -> 4
aurora.TrunkSize = InventoryTile.Tile1515 aurora.TrunkSize = InventoryTile.Tile1515
aurora.TrunkOffset = 30 aurora.TrunkOffset = 30
aurora.AutoPilotSpeeds = (18, 6)
apc_tr.Name = "apc_tr"
apc_tr.Seats += 0 -> new SeatDefinition() apc_tr.Seats += 0 -> new SeatDefinition()
apc_tr.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax apc_tr.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
apc_tr.Seats += 1 -> new SeatDefinition() apc_tr.Seats += 1 -> new SeatDefinition()
@ -2238,7 +2277,9 @@ object GlobalDefinitions {
apc_tr.MountPoints += 12 -> 10 apc_tr.MountPoints += 12 -> 10
apc_tr.TrunkSize = InventoryTile.Tile2016 apc_tr.TrunkSize = InventoryTile.Tile2016
apc_tr.TrunkOffset = 30 apc_tr.TrunkOffset = 30
apc_tr.AutoPilotSpeeds = (16, 6)
apc_nc.Name = "apc_nc"
apc_nc.Seats += 0 -> new SeatDefinition() apc_nc.Seats += 0 -> new SeatDefinition()
apc_nc.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax apc_nc.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
apc_nc.Seats += 1 -> new SeatDefinition() apc_nc.Seats += 1 -> new SeatDefinition()
@ -2279,7 +2320,9 @@ object GlobalDefinitions {
apc_nc.MountPoints += 12 -> 10 apc_nc.MountPoints += 12 -> 10
apc_nc.TrunkSize = InventoryTile.Tile2016 apc_nc.TrunkSize = InventoryTile.Tile2016
apc_nc.TrunkOffset = 30 apc_nc.TrunkOffset = 30
apc_nc.AutoPilotSpeeds = (16, 6)
apc_vs.Name = "apc_vs"
apc_vs.Seats += 0 -> new SeatDefinition() apc_vs.Seats += 0 -> new SeatDefinition()
apc_vs.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax apc_vs.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
apc_vs.Seats += 1 -> new SeatDefinition() apc_vs.Seats += 1 -> new SeatDefinition()
@ -2320,7 +2363,9 @@ object GlobalDefinitions {
apc_vs.MountPoints += 12 -> 10 apc_vs.MountPoints += 12 -> 10
apc_vs.TrunkSize = InventoryTile.Tile2016 apc_vs.TrunkSize = InventoryTile.Tile2016
apc_vs.TrunkOffset = 30 apc_vs.TrunkOffset = 30
apc_vs.AutoPilotSpeeds = (16, 6)
lightning.Name = "lightning"
lightning.Seats += 0 -> new SeatDefinition() lightning.Seats += 0 -> new SeatDefinition()
lightning.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax lightning.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
lightning.Seats(0).ControlledWeapon = 1 lightning.Seats(0).ControlledWeapon = 1
@ -2329,7 +2374,9 @@ object GlobalDefinitions {
lightning.MountPoints += 2 -> 0 lightning.MountPoints += 2 -> 0
lightning.TrunkSize = InventoryTile.Tile1511 lightning.TrunkSize = InventoryTile.Tile1511
lightning.TrunkOffset = 30 lightning.TrunkOffset = 30
lightning.AutoPilotSpeeds = (20, 8)
prowler.Name = "prowler"
prowler.Seats += 0 -> new SeatDefinition() prowler.Seats += 0 -> new SeatDefinition()
prowler.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax prowler.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
prowler.Seats += 1 -> new SeatDefinition() prowler.Seats += 1 -> new SeatDefinition()
@ -2343,7 +2390,9 @@ object GlobalDefinitions {
prowler.MountPoints += 3 -> 2 prowler.MountPoints += 3 -> 2
prowler.TrunkSize = InventoryTile.Tile1511 prowler.TrunkSize = InventoryTile.Tile1511
prowler.TrunkOffset = 30 prowler.TrunkOffset = 30
prowler.AutoPilotSpeeds = (14, 6)
vanguard.Name = "vanguard"
vanguard.Seats += 0 -> new SeatDefinition() vanguard.Seats += 0 -> new SeatDefinition()
vanguard.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax vanguard.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
vanguard.Seats += 1 -> new SeatDefinition() vanguard.Seats += 1 -> new SeatDefinition()
@ -2353,7 +2402,9 @@ object GlobalDefinitions {
vanguard.MountPoints += 2 -> 1 vanguard.MountPoints += 2 -> 1
vanguard.TrunkSize = InventoryTile.Tile1511 vanguard.TrunkSize = InventoryTile.Tile1511
vanguard.TrunkOffset = 30 vanguard.TrunkOffset = 30
vanguard.AutoPilotSpeeds = (16, 6)
magrider.Name = "magrider"
magrider.Seats += 0 -> new SeatDefinition() magrider.Seats += 0 -> new SeatDefinition()
magrider.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax magrider.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
magrider.Seats(0).ControlledWeapon = 2 magrider.Seats(0).ControlledWeapon = 2
@ -2365,14 +2416,18 @@ object GlobalDefinitions {
magrider.MountPoints += 2 -> 1 magrider.MountPoints += 2 -> 1
magrider.TrunkSize = InventoryTile.Tile1511 magrider.TrunkSize = InventoryTile.Tile1511
magrider.TrunkOffset = 30 magrider.TrunkOffset = 30
magrider.AutoPilotSpeeds = (18, 6)
val utilityConverter = new UtilityVehicleConverter val utilityConverter = new UtilityVehicleConverter
ant.Name = "ant"
ant.Seats += 0 -> new SeatDefinition() ant.Seats += 0 -> new SeatDefinition()
ant.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax ant.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
ant.MountPoints += 1 -> 0 ant.MountPoints += 1 -> 0
ant.MountPoints += 2 -> 0 ant.MountPoints += 2 -> 0
ant.AutoPilotSpeeds = (18, 6)
ant.Packet = utilityConverter ant.Packet = utilityConverter
ams.Name = "ams"
ams.Seats += 0 -> new SeatDefinition() ams.Seats += 0 -> new SeatDefinition()
ams.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax ams.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
ams.MountPoints += 1 -> 0 ams.MountPoints += 1 -> 0
@ -2384,9 +2439,11 @@ object GlobalDefinitions {
ams.Deployment = true ams.Deployment = true
ams.DeployTime = 2000 ams.DeployTime = 2000
ams.UndeployTime = 2000 ams.UndeployTime = 2000
ams.AutoPilotSpeeds = (18, 6)
ams.Packet = utilityConverter ams.Packet = utilityConverter
val variantConverter = new VariantVehicleConverter val variantConverter = new VariantVehicleConverter
router.Name = "router"
router.Seats += 0 -> new SeatDefinition() router.Seats += 0 -> new SeatDefinition()
router.MountPoints += 1 -> 0 router.MountPoints += 1 -> 0
router.TrunkSize = InventoryTile.Tile1511 router.TrunkSize = InventoryTile.Tile1511
@ -2394,8 +2451,10 @@ object GlobalDefinitions {
router.Deployment = true router.Deployment = true
router.DeployTime = 2000 router.DeployTime = 2000
router.UndeployTime = 2000 router.UndeployTime = 2000
router.AutoPilotSpeeds = (16, 6)
router.Packet = variantConverter router.Packet = variantConverter
switchblade.Name = "switchblade"
switchblade.Seats += 0 -> new SeatDefinition() switchblade.Seats += 0 -> new SeatDefinition()
switchblade.Seats(0).ControlledWeapon = 1 switchblade.Seats(0).ControlledWeapon = 1
switchblade.Weapons += 1 -> scythe switchblade.Weapons += 1 -> scythe
@ -2406,8 +2465,10 @@ object GlobalDefinitions {
switchblade.Deployment = true switchblade.Deployment = true
switchblade.DeployTime = 2000 switchblade.DeployTime = 2000
switchblade.UndeployTime = 2000 switchblade.UndeployTime = 2000
switchblade.AutoPilotSpeeds = (22, 8)
switchblade.Packet = variantConverter switchblade.Packet = variantConverter
flail.Name = "flail"
flail.Seats += 0 -> new SeatDefinition() flail.Seats += 0 -> new SeatDefinition()
flail.Seats(0).ControlledWeapon = 1 flail.Seats(0).ControlledWeapon = 1
flail.Weapons += 1 -> flail_weapon flail.Weapons += 1 -> flail_weapon
@ -2417,8 +2478,10 @@ object GlobalDefinitions {
flail.Deployment = true flail.Deployment = true
flail.DeployTime = 2000 flail.DeployTime = 2000
flail.UndeployTime = 2000 flail.UndeployTime = 2000
flail.AutoPilotSpeeds = (14, 6)
flail.Packet = variantConverter flail.Packet = variantConverter
mosquito.Name = "mosquito"
mosquito.Seats += 0 -> new SeatDefinition() mosquito.Seats += 0 -> new SeatDefinition()
mosquito.Seats(0).Bailable = true mosquito.Seats(0).Bailable = true
mosquito.Seats(0).ControlledWeapon = 1 mosquito.Seats(0).ControlledWeapon = 1
@ -2427,8 +2490,10 @@ object GlobalDefinitions {
mosquito.MountPoints += 2 -> 0 mosquito.MountPoints += 2 -> 0
mosquito.TrunkSize = InventoryTile.Tile1111 mosquito.TrunkSize = InventoryTile.Tile1111
mosquito.TrunkOffset = 30 mosquito.TrunkOffset = 30
mosquito.AutoPilotSpeeds = (0, 6)
mosquito.Packet = variantConverter mosquito.Packet = variantConverter
lightgunship.Name = "lightgunship"
lightgunship.Seats += 0 -> new SeatDefinition() lightgunship.Seats += 0 -> new SeatDefinition()
lightgunship.Seats(0).Bailable = true lightgunship.Seats(0).Bailable = true
lightgunship.Seats(0).ControlledWeapon = 1 lightgunship.Seats(0).ControlledWeapon = 1
@ -2437,8 +2502,10 @@ object GlobalDefinitions {
lightgunship.MountPoints += 2 -> 0 lightgunship.MountPoints += 2 -> 0
lightgunship.TrunkSize = InventoryTile.Tile1511 lightgunship.TrunkSize = InventoryTile.Tile1511
lightgunship.TrunkOffset = 30 lightgunship.TrunkOffset = 30
lightgunship.AutoPilotSpeeds = (0, 4)
lightgunship.Packet = variantConverter lightgunship.Packet = variantConverter
wasp.Name = "wasp"
wasp.Seats += 0 -> new SeatDefinition() wasp.Seats += 0 -> new SeatDefinition()
wasp.Seats(0).Bailable = true wasp.Seats(0).Bailable = true
wasp.Seats(0).ControlledWeapon = 1 wasp.Seats(0).ControlledWeapon = 1
@ -2447,8 +2514,10 @@ object GlobalDefinitions {
wasp.MountPoints += 2 -> 0 wasp.MountPoints += 2 -> 0
wasp.TrunkSize = InventoryTile.Tile1111 wasp.TrunkSize = InventoryTile.Tile1111
wasp.TrunkOffset = 30 wasp.TrunkOffset = 30
wasp.AutoPilotSpeeds = (0, 6)
wasp.Packet = variantConverter wasp.Packet = variantConverter
liberator.Name = "liberator"
liberator.Seats += 0 -> new SeatDefinition() liberator.Seats += 0 -> new SeatDefinition()
liberator.Seats(0).ControlledWeapon = 3 liberator.Seats(0).ControlledWeapon = 3
liberator.Seats += 1 -> new SeatDefinition() liberator.Seats += 1 -> new SeatDefinition()
@ -2464,8 +2533,10 @@ object GlobalDefinitions {
liberator.MountPoints += 4 -> 2 liberator.MountPoints += 4 -> 2
liberator.TrunkSize = InventoryTile.Tile1515 liberator.TrunkSize = InventoryTile.Tile1515
liberator.TrunkOffset = 30 liberator.TrunkOffset = 30
liberator.AutoPilotSpeeds = (0, 4)
liberator.Packet = variantConverter liberator.Packet = variantConverter
vulture.Name = "vulture"
vulture.Seats += 0 -> new SeatDefinition() vulture.Seats += 0 -> new SeatDefinition()
vulture.Seats(0).ControlledWeapon = 3 vulture.Seats(0).ControlledWeapon = 3
vulture.Seats += 1 -> new SeatDefinition() vulture.Seats += 1 -> new SeatDefinition()
@ -2481,8 +2552,10 @@ object GlobalDefinitions {
vulture.MountPoints += 4 -> 2 vulture.MountPoints += 4 -> 2
vulture.TrunkSize = InventoryTile.Tile1611 vulture.TrunkSize = InventoryTile.Tile1611
vulture.TrunkOffset = 30 vulture.TrunkOffset = 30
vulture.AutoPilotSpeeds = (0, 4)
vulture.Packet = variantConverter vulture.Packet = variantConverter
dropship.Name = "dropship"
dropship.Seats += 0 -> new SeatDefinition() dropship.Seats += 0 -> new SeatDefinition()
dropship.Seats += 1 -> new SeatDefinition() dropship.Seats += 1 -> new SeatDefinition()
dropship.Seats(1).Bailable = true dropship.Seats(1).Bailable = true
@ -2528,8 +2601,10 @@ object GlobalDefinitions {
dropship.MountPoints += 12 -> 10 dropship.MountPoints += 12 -> 10
dropship.TrunkSize = InventoryTile.Tile1612 dropship.TrunkSize = InventoryTile.Tile1612
dropship.TrunkOffset = 30 dropship.TrunkOffset = 30
dropship.AutoPilotSpeeds = (0, 4)
dropship.Packet = variantConverter dropship.Packet = variantConverter
galaxy_gunship.Name = "galaxy_gunship"
galaxy_gunship.Seats += 0 -> new SeatDefinition() galaxy_gunship.Seats += 0 -> new SeatDefinition()
galaxy_gunship.Seats += 1 -> new SeatDefinition() galaxy_gunship.Seats += 1 -> new SeatDefinition()
galaxy_gunship.Seats(1).ControlledWeapon = 6 galaxy_gunship.Seats(1).ControlledWeapon = 6
@ -2554,14 +2629,18 @@ object GlobalDefinitions {
galaxy_gunship.MountPoints += 6 -> 5 galaxy_gunship.MountPoints += 6 -> 5
galaxy_gunship.TrunkSize = InventoryTile.Tile1816 galaxy_gunship.TrunkSize = InventoryTile.Tile1816
galaxy_gunship.TrunkOffset = 30 galaxy_gunship.TrunkOffset = 30
galaxy_gunship.AutoPilotSpeeds = (0, 4)
galaxy_gunship.Packet = variantConverter galaxy_gunship.Packet = variantConverter
lodestar.Name = "lodestar"
lodestar.Seats += 0 -> new SeatDefinition() lodestar.Seats += 0 -> new SeatDefinition()
lodestar.MountPoints += 1 -> 0 lodestar.MountPoints += 1 -> 0
lodestar.TrunkSize = InventoryTile.Tile1612 lodestar.TrunkSize = InventoryTile.Tile1612
lodestar.TrunkOffset = 30 lodestar.TrunkOffset = 30
lodestar.AutoPilotSpeeds = (0, 4)
lodestar.Packet = variantConverter lodestar.Packet = variantConverter
phantasm.Name = "phantasm"
phantasm.CanCloak = true phantasm.CanCloak = true
phantasm.Seats += 0 -> new SeatDefinition() phantasm.Seats += 0 -> new SeatDefinition()
phantasm.Seats += 1 -> new SeatDefinition() phantasm.Seats += 1 -> new SeatDefinition()
@ -2579,6 +2658,7 @@ object GlobalDefinitions {
phantasm.MountPoints += 5 -> 4 phantasm.MountPoints += 5 -> 4
phantasm.TrunkSize = InventoryTile.Tile1107 phantasm.TrunkSize = InventoryTile.Tile1107
phantasm.TrunkOffset = 30 phantasm.TrunkOffset = 30
phantasm.AutoPilotSpeeds = (0, 6)
phantasm.Packet = variantConverter phantasm.Packet = variantConverter
} }
} }

View file

@ -28,6 +28,7 @@ class VehicleDefinition(objectId : Int) extends ObjectDefinition(objectId) {
private var trunkOffset : Int = 0 private var trunkOffset : Int = 0
private var canCloak : Boolean = false private var canCloak : Boolean = false
private var canBeOwned : Boolean = true private var canBeOwned : Boolean = true
private var serverVehicleOverrideSpeeds : (Int, Int) = (0, 0)
Name = "vehicle" Name = "vehicle"
Packet = VehicleDefinition.converter Packet = VehicleDefinition.converter
@ -102,6 +103,17 @@ class VehicleDefinition(objectId : Int) extends ObjectDefinition(objectId) {
trunkOffset = offset trunkOffset = offset
TrunkOffset TrunkOffset
} }
def AutoPilotSpeeds : (Int, Int) = serverVehicleOverrideSpeeds
def AutoPilotSpeeds_=(speeds : (Int, Int)) : (Int, Int) = {
serverVehicleOverrideSpeeds = speeds
AutoPilotSpeeds
}
def AutoPilotSpeed1 : Int = serverVehicleOverrideSpeeds._1
def AutoPilotSpeed2 : Int = serverVehicleOverrideSpeeds._2
} }
object VehicleDefinition { object VehicleDefinition {

View file

@ -156,7 +156,6 @@ object VehicleSpawnControl {
final case class AwaitDriverInSeat(entry : VehicleSpawnControl.Order) extends Order(entry) final case class AwaitDriverInSeat(entry : VehicleSpawnControl.Order) extends Order(entry)
final case class DriverInSeat(entry : VehicleSpawnControl.Order) extends Order(entry) final case class DriverInSeat(entry : VehicleSpawnControl.Order) extends Order(entry)
final case class RailJackAction(entry : VehicleSpawnControl.Order) extends Order(entry) final case class RailJackAction(entry : VehicleSpawnControl.Order) extends Order(entry)
final case class RailJackRelease(entry : VehicleSpawnControl.Order) extends Order(entry)
final case class ServerVehicleOverride(entry : VehicleSpawnControl.Order) extends Order(entry) final case class ServerVehicleOverride(entry : VehicleSpawnControl.Order) extends Order(entry)
final case class DriverVehicleControl(entry : VehicleSpawnControl.Order) extends Order(entry) final case class DriverVehicleControl(entry : VehicleSpawnControl.Order) extends Order(entry)
final case class FinalClearance(entry : VehicleSpawnControl.Order) extends Order(entry) final case class FinalClearance(entry : VehicleSpawnControl.Order) extends Order(entry)
@ -172,12 +171,12 @@ object VehicleSpawnControl {
/** /**
* Properly clean up a vehicle that has been registered, but not yet been spawned into the game world. * Properly clean up a vehicle that has been registered, but not yet been spawned into the game world.
* @param vehicle the vehicle * @see `VehicleSpawnControl.emergencyResolver`
* @param player the driver * @param entry the order being cancelled
* @param zone the continent on which the vehicle was registered * @param zone the continent on which the vehicle was registered
* @param context an `ActorContext` object for which to create the `TaskResolver` object * @param context an `ActorContext` object for which to create the `TaskResolver` object
*/ */
def DisposeVehicle(vehicle : Vehicle, player : Player, zone: Zone)(implicit context : ActorContext) : Unit = { def DisposeVehicle(entry : VehicleSpawnControl.Order, zone: Zone)(implicit context : ActorContext) : Unit = {
import net.psforever.objects.guid.GUIDTask import net.psforever.objects.guid.GUIDTask
emergencyResolver.getOrElse({ emergencyResolver.getOrElse({
import akka.routing.SmallestMailboxPool import akka.routing.SmallestMailboxPool
@ -185,18 +184,18 @@ object VehicleSpawnControl {
val resolver = context.actorOf(SmallestMailboxPool(10).props(Props[TaskResolver]), "vehicle-spawn-control-emergency-decon-resolver") val resolver = context.actorOf(SmallestMailboxPool(10).props(Props[TaskResolver]), "vehicle-spawn-control-emergency-decon-resolver")
emergencyResolver = Some(resolver) emergencyResolver = Some(resolver)
resolver resolver
}) ! GUIDTask.UnregisterVehicle(vehicle)(zone.GUID) }) ! GUIDTask.UnregisterVehicle(entry.vehicle)(zone.GUID)
zone.VehicleEvents ! VehicleSpawnPad.RevealPlayer(player.GUID, zone.Id) zone.VehicleEvents ! VehicleSpawnPad.RevealPlayer(entry.driver.GUID, zone.Id)
} }
/** /**
* Properly clean up a vehicle that has been registered and spawned into the game world. * Properly clean up a vehicle that has been registered and spawned into the game world.
* @param vehicle the vehicle * @param entry the order being cancelled
* @param player the driver
* @param zone the continent on which the vehicle was registered * @param zone the continent on which the vehicle was registered
*/ */
def DisposeSpawnedVehicle(vehicle : Vehicle, player : Player, zone: Zone) : Unit = { def DisposeSpawnedVehicle(entry : VehicleSpawnControl.Order, zone: Zone) : Unit = {
zone.VehicleEvents ! VehicleSpawnPad.DisposeVehicle(vehicle, zone) //TODO this cleanup will handle the vehicle; but, the former driver may be thrown into the void
zone.VehicleEvents ! VehicleSpawnPad.RevealPlayer(player.GUID, zone.Id) zone.VehicleEvents ! VehicleSpawnPad.DisposeVehicle(entry.vehicle, zone)
zone.VehicleEvents ! VehicleSpawnPad.RevealPlayer(entry.driver.GUID, zone.Id)
} }
/** /**

View file

@ -13,10 +13,28 @@ import net.psforever.packet.game.PlanetSideGUID
* maintain the operative queue that introduces the vehicle into the game world and applies initial activity to it and * maintain the operative queue that introduces the vehicle into the game world and applies initial activity to it and
* maintain a position and a direction where the vehicle will be made to appear (as a `PlanetSideServerObject`). * maintain a position and a direction where the vehicle will be made to appear (as a `PlanetSideServerObject`).
* The actual functionality managed by this object is wholly found on its accompanying `Actor`. * The actual functionality managed by this object is wholly found on its accompanying `Actor`.
* @param spDef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
* @see `VehicleSpawnControl` * @see `VehicleSpawnControl`
* @param spDef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
*/ */
class VehicleSpawnPad(spDef : VehicleSpawnPadDefinition) extends Amenity { class VehicleSpawnPad(spDef : VehicleSpawnPadDefinition) extends Amenity {
/**
* USE THIS BOOLEAN FOR DEVELOPMENT PURPOSES!<br>
* Purpose: use the ingame railed platform to lift the spawned vehicle out of the trench.
* When set, the client performs the standard vehicle entry procedure, including rail animations.
* When unset, the client depicts the player manually boarding the new vehicle within the trench area.
* Eventually, the vehicle is then hoisted out into the open.
* The main reason to disable this feature is to avoid an `ObjectAttachMessage` that may be dispatched for an incorrect object.
* Unset if not guaranteed to have the correct ingame globally unique id of the spawn pad.
*/
private var onRails : Boolean = true
def Railed : Boolean = onRails
def Railed_=(useRails : Boolean) : Boolean = {
onRails = useRails
Railed
}
def Definition : VehicleSpawnPadDefinition = spDef def Definition : VehicleSpawnPadDefinition = spDef
} }
@ -53,7 +71,11 @@ object VehicleSpawnPad {
*/ */
final case class LoadVehicle(vehicle : Vehicle, zone : Zone) final case class LoadVehicle(vehicle : Vehicle, zone : Zone)
final case class StartPlayerSeatedInVehicle(vehicle : Vehicle) final case class AttachToRails(vehicle : Vehicle, pad : VehicleSpawnPad, zone_id : String)
final case class DetachFromRails(vehicle : Vehicle, pad : VehicleSpawnPad, zone_id : String)
final case class StartPlayerSeatedInVehicle(vehicle : Vehicle, pad : VehicleSpawnPad)
/** /**
* A TEMPORARY callback step in spawning the vehicle. * A TEMPORARY callback step in spawning the vehicle.
@ -62,11 +84,13 @@ object VehicleSpawnPad {
* This message is the next step after that. * This message is the next step after that.
* @param vehicle the vehicle being spawned * @param vehicle the vehicle being spawned
*/ */
final case class PlayerSeatedInVehicle(vehicle : Vehicle) final case class PlayerSeatedInVehicle(vehicle : Vehicle, pad : VehicleSpawnPad) //TODO while using fake rails
final case class ServerVehicleOverrideStart(speed : Int) final case class ServerVehicleOverrideStart(vehicle : Vehicle, pad : VehicleSpawnPad)
final case class ServerVehicleOverrideEnd(speed : Int) final case class ServerVehicleOverrideEnd(vehicle : Vehicle, pad : VehicleSpawnPad)
final case class ResetSpawnPad(pad : VehicleSpawnPad, zone_id : String)
final case class PeriodicReminder(msg : String) final case class PeriodicReminder(msg : String)

View file

@ -55,7 +55,7 @@ abstract class VehicleSpawnControlBase(pad : VehicleSpawnPad) extends Actor {
* No important messages should processed by this agent; only consume general vehicle spawn status. * No important messages should processed by this agent; only consume general vehicle spawn status.
* @param msg the message * @param msg the message
*/ */
def trace(msg : String) : Unit = log.info(msg) def trace(msg : String) : Unit = log.trace(msg)
protected def Pad : VehicleSpawnPad = pad protected def Pad : VehicleSpawnPad = pad

View file

@ -34,7 +34,7 @@ class VehicleSpawnControlConcealPlayer(pad : VehicleSpawnPad) extends VehicleSpa
} }
else { else {
trace(s"integral component lost; abort order fulfillment") trace(s"integral component lost; abort order fulfillment")
VehicleSpawnControl.DisposeVehicle(entry.vehicle, driver, Continent) VehicleSpawnControl.DisposeVehicle(entry, Continent)
context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder
} }

View file

@ -2,7 +2,9 @@
package net.psforever.objects.serverobject.pad.process package net.psforever.objects.serverobject.pad.process
import akka.actor.Props import akka.actor.Props
import net.psforever.objects.GlobalDefinitions
import net.psforever.objects.serverobject.pad.{VehicleSpawnControl, VehicleSpawnPad} import net.psforever.objects.serverobject.pad.{VehicleSpawnControl, VehicleSpawnPad}
import net.psforever.types.Vector3
import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._ import scala.concurrent.duration._
@ -28,12 +30,13 @@ class VehicleSpawnControlLoadVehicle(pad : VehicleSpawnPad) extends VehicleSpawn
val vehicle = entry.vehicle val vehicle = entry.vehicle
if(entry.driver.Continent == Continent.Id) { if(entry.driver.Continent == Continent.Id) {
trace(s"loading the ${vehicle.Definition.Name}") trace(s"loading the ${vehicle.Definition.Name}")
vehicle.Position = vehicle.Position - Vector3(0, 0, if(GlobalDefinitions.isFlightVehicle(vehicle.Definition)) 9 else 5)
Continent.VehicleEvents ! VehicleSpawnPad.LoadVehicle(vehicle, Continent) Continent.VehicleEvents ! VehicleSpawnPad.LoadVehicle(vehicle, Continent)
context.system.scheduler.scheduleOnce(100 milliseconds, seatDriver, VehicleSpawnControl.Process.SeatDriver(entry)) context.system.scheduler.scheduleOnce(100 milliseconds, seatDriver, VehicleSpawnControl.Process.SeatDriver(entry))
} }
else { else {
trace("owner lost; abort order fulfillment") trace("owner lost; abort order fulfillment")
VehicleSpawnControl.DisposeVehicle(vehicle, entry.driver, Continent) VehicleSpawnControl.DisposeVehicle(entry, Continent)
context.parent ! VehicleSpawnControl.ProcessControl.GetOrder context.parent ! VehicleSpawnControl.ProcessControl.GetOrder
} }

View file

@ -14,12 +14,13 @@ import scala.concurrent.duration._
* <br> * <br>
* When the vehicle is added into the environment, it is attached to the spawn pad platform. * When the vehicle is added into the environment, it is attached to the spawn pad platform.
* On cue, the trapdoor of the platform will open, and the vehicle will be raised up into plain sight on a group of rails. * On cue, the trapdoor of the platform will open, and the vehicle will be raised up into plain sight on a group of rails.
* It has failure cases should the driver be in an incorrect state.<br> * These actions are actually integrated into previous stages and into later stages of the process.
* __It currently does not work__. * The primary objective to be completed is a specific place to start a frequent message to the other customers.
* It has failure cases should the driver be in an incorrect state.
* @param pad the `VehicleSpawnPad` object being governed * @param pad the `VehicleSpawnPad` object being governed
*/ */
class VehicleSpawnControlRailJack(pad : VehicleSpawnPad) extends VehicleSpawnControlBase(pad) { class VehicleSpawnControlRailJack(pad : VehicleSpawnPad) extends VehicleSpawnControlBase(pad) {
def LogId = "-jacker" def LogId = "-lifter"
val vehicleOverride = context.actorOf(Props(classOf[VehicleSpawnControlServerVehicleOverride], pad), s"${context.parent.path.name}-override") val vehicleOverride = context.actorOf(Props(classOf[VehicleSpawnControlServerVehicleOverride], pad), s"${context.parent.path.name}-override")
@ -27,8 +28,8 @@ class VehicleSpawnControlRailJack(pad : VehicleSpawnPad) extends VehicleSpawnCon
case VehicleSpawnControl.Process.RailJackAction(entry) => case VehicleSpawnControl.Process.RailJackAction(entry) =>
if(entry.vehicle.Health == 0) { if(entry.vehicle.Health == 0) {
//TODO detach vehicle from pad rails if necessary //TODO detach vehicle from pad rails if necessary
trace(s"vehicle was already destroyed; clean it up") trace(s"vehicle was already destroyed")
VehicleSpawnControl.DisposeSpawnedVehicle(entry.vehicle, entry.driver, Continent) VehicleSpawnControl.DisposeSpawnedVehicle(entry, Continent)
context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder
} }
else { else {

View file

@ -35,29 +35,32 @@ class VehicleSpawnControlSeatDriver(pad : VehicleSpawnPad) extends VehicleSpawnC
else { else {
val driver = entry.driver val driver = entry.driver
if(entry.vehicle.Health == 0) { if(entry.vehicle.Health == 0) {
//TODO detach vehicle from pad rails if necessary
trace("vehicle was already destroyed; clean it up") trace("vehicle was already destroyed; clean it up")
VehicleSpawnControl.DisposeSpawnedVehicle(entry.vehicle, driver, Continent) VehicleSpawnControl.DisposeSpawnedVehicle(entry, Continent)
context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder
} }
else if(entry.sendTo != ActorRef.noSender && driver.isAlive && driver.Continent == Continent.Id && driver.VehicleSeated.isEmpty) {
trace("driver to be made seated in vehicle")
entry.sendTo ! VehicleSpawnPad.StartPlayerSeatedInVehicle(entry.vehicle)
entry.vehicle.Actor.tell(Mountable.TryMount(driver, 0), entry.sendTo) //entry.sendTo should handle replies to TryMount
context.system.scheduler.scheduleOnce(1000 milliseconds, self, VehicleSpawnControl.Process.AwaitDriverInSeat(entry))
}
else { else {
trace("driver lost; vehicle stranded on pad") if(entry.sendTo != ActorRef.noSender && driver.isAlive && driver.Continent == Continent.Id && driver.VehicleSeated.isEmpty) {
context.system.scheduler.scheduleOnce(1000 milliseconds, railJack, VehicleSpawnControl.Process.RailJackAction(entry)) trace("driver to be made seated in vehicle")
entry.sendTo ! VehicleSpawnPad.StartPlayerSeatedInVehicle(entry.vehicle, pad)
entry.vehicle.Actor.tell(Mountable.TryMount(driver, 0), entry.sendTo) //entry.sendTo should handle replies to TryMount
context.system.scheduler.scheduleOnce(1000 milliseconds, self, VehicleSpawnControl.Process.AwaitDriverInSeat(entry))
}
else {
if(pad.Railed) {
Continent.VehicleEvents ! VehicleSpawnPad.AttachToRails(entry.vehicle, pad, Continent.Id)
}
trace("driver lost; vehicle stranded on pad")
context.system.scheduler.scheduleOnce(1000 milliseconds, railJack, VehicleSpawnControl.Process.RailJackAction(entry))
}
} }
} }
case VehicleSpawnControl.Process.AwaitDriverInSeat(entry) => case VehicleSpawnControl.Process.AwaitDriverInSeat(entry) =>
val driver = entry.driver val driver = entry.driver
if(entry.vehicle.Health == 0) { if(entry.vehicle.Health == 0) {
//TODO detach vehicle from pad rails if necessary
trace("vehicle was already destroyed; clean it up") trace("vehicle was already destroyed; clean it up")
VehicleSpawnControl.DisposeSpawnedVehicle(entry.vehicle, driver, Continent) VehicleSpawnControl.DisposeSpawnedVehicle(entry, Continent)
context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder
} }
else if(entry.sendTo == ActorRef.noSender) { else if(entry.sendTo == ActorRef.noSender) {
@ -65,23 +68,27 @@ class VehicleSpawnControlSeatDriver(pad : VehicleSpawnPad) extends VehicleSpawnC
self ! VehicleSpawnControl.Process.RailJackAction(entry) self ! VehicleSpawnControl.Process.RailJackAction(entry)
} }
else if(driver.isAlive && driver.Continent == Continent.Id && driver.VehicleSeated.isEmpty) { else if(driver.isAlive && driver.Continent == Continent.Id && driver.VehicleSeated.isEmpty) {
context.system.scheduler.scheduleOnce(1000 milliseconds, self, VehicleSpawnControl.Process.AwaitDriverInSeat(entry)) context.system.scheduler.scheduleOnce(100 milliseconds, self, VehicleSpawnControl.Process.AwaitDriverInSeat(entry))
} }
else { else {
trace(s"driver is sitting down") trace(s"driver is sitting down")
context.system.scheduler.scheduleOnce(1000 milliseconds, self, VehicleSpawnControl.Process.DriverInSeat(entry)) context.system.scheduler.scheduleOnce(
VehicleSpawnControlSeatDriver.RaillessSeatAnimationTimes(entry.vehicle.Definition.Name) milliseconds,
self,
VehicleSpawnControl.Process.DriverInSeat(entry)
)
} }
case VehicleSpawnControl.Process.DriverInSeat(entry) => case VehicleSpawnControl.Process.DriverInSeat(entry) =>
if(entry.vehicle.Health == 0) { if(entry.vehicle.Health == 0) {
//TODO detach vehicle from pad rails if necessary //TODO detach vehicle from pad rails if necessary
trace(s"vehicle was already destroyed; clean it up") trace(s"vehicle was already destroyed; clean it up")
VehicleSpawnControl.DisposeSpawnedVehicle(entry.vehicle, entry.driver, Continent) VehicleSpawnControl.DisposeSpawnedVehicle(entry, Continent)
context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder
} }
else if(entry.sendTo != ActorRef.noSender) { else if(entry.sendTo != ActorRef.noSender) {
trace(s"driver ${entry.driver.Name} has taken the wheel") trace(s"driver ${entry.driver.Name} has taken the wheel")
entry.sendTo ! VehicleSpawnPad.PlayerSeatedInVehicle(entry.vehicle) entry.sendTo ! VehicleSpawnPad.PlayerSeatedInVehicle(entry.vehicle, pad)
context.system.scheduler.scheduleOnce(10 milliseconds, railJack, VehicleSpawnControl.Process.RailJackAction(entry)) context.system.scheduler.scheduleOnce(10 milliseconds, railJack, VehicleSpawnControl.Process.RailJackAction(entry))
} }
else { else {
@ -98,3 +105,44 @@ class VehicleSpawnControlSeatDriver(pad : VehicleSpawnPad) extends VehicleSpawnC
case _ => ; case _ => ;
} }
} }
object VehicleSpawnControlSeatDriver {
/**
* If the spawn pad associated with this `Actor` chain is not `Railed` -
* not guaranteed to have the correct ingame globally unique id of the spawn pad -
* then the animation of the driver boarding their vehicle will be displayed.
* Although the network is finicky, these times should compensate a beneficial visual delay.
* The BFRs, the Switchblade, and the Flail are all untested.
*/
private val RaillessSeatAnimationTimes : Map[String, Int] = Map(
"fury" -> 600,
"quadassault" -> 600,
"quadstealth" -> 600,
"skyguard" -> 1300,
"threemanheavybuggy" -> 1000,
"twomanheavybuggy" -> 1800,
"twomanhoverbuggy" -> 1800,
"mediumtransport" -> 1300,
"battlewagon" -> 1300,
"thunderer" -> 1300,
"aurora" -> 1300,
"apc_tr" -> 2300,
"apc_nc" -> 2300,
"apc_vs" -> 2300,
"prowler" -> 1000,
"vanguard" -> 2000,
"magrider" -> 1800,
"ant" -> 2500,
"ams" -> 1000,
"router" -> 2500,
"mosquito" -> 2000,
"lightgunship" -> 2000,
"wasp" -> 2000,
"liberator" -> 1800,
"vulture" -> 1800,
"dropship" -> 2000,
"galaxy_gunship" -> 2000,
"lodestar" -> 2000,
"phantasm" -> 1800
).withDefaultValue(1000)
}

View file

@ -33,31 +33,35 @@ class VehicleSpawnControlServerVehicleOverride(pad : VehicleSpawnPad) extends Ve
} }
else if(entry.sendTo != ActorRef.noSender && entry.driver.VehicleSeated.contains(vehicle.GUID)) { else if(entry.sendTo != ActorRef.noSender && entry.driver.VehicleSeated.contains(vehicle.GUID)) {
trace(s"telling ${entry.driver.Name} that the server is assuming control of the ${vehicle.Definition.Name}") trace(s"telling ${entry.driver.Name} that the server is assuming control of the ${vehicle.Definition.Name}")
entry.sendTo ! VehicleSpawnPad.ServerVehicleOverrideStart(22) entry.sendTo ! VehicleSpawnPad.ServerVehicleOverrideStart(vehicle, pad)
context.system.scheduler.scheduleOnce(3000 milliseconds, self, VehicleSpawnControl.Process.DriverVehicleControl(entry)) context.system.scheduler.scheduleOnce(3000 milliseconds, self, VehicleSpawnControl.Process.DriverVehicleControl(entry))
} }
else { else {
if(pad.Railed) {
Continent.VehicleEvents ! VehicleSpawnPad.DetachFromRails(vehicle, pad, Continent.Id)
}
finalClear ! VehicleSpawnControl.Process.FinalClearance(entry) finalClear ! VehicleSpawnControl.Process.FinalClearance(entry)
} }
case VehicleSpawnControl.Process.DriverVehicleControl(entry) => case VehicleSpawnControl.Process.DriverVehicleControl(entry) =>
val vehicle = entry.vehicle val vehicle = entry.vehicle
if(vehicle.Health == 0) {
trace(s"vehicle was already destroyed; but, everything is fine")
}
if(entry.sendTo != ActorRef.noSender) { if(entry.sendTo != ActorRef.noSender) {
if(vehicle.Health == 0) { val driver = entry.driver
trace(s"vehicle was already destroyed; but, everything is fine") entry.sendTo ! VehicleSpawnPad.ServerVehicleOverrideEnd(vehicle, pad)
if(driver.VehicleSeated.contains(vehicle.GUID)) {
trace(s"returning control of ${vehicle.Definition.Name} to ${driver.Name}")
} }
else { else {
val driver = entry.driver trace(s"${driver.Name} is not seated in ${vehicle.Definition.Name}; can not properly return control to driver")
entry.sendTo ! VehicleSpawnPad.ServerVehicleOverrideEnd(8)
if(driver.VehicleSeated.contains(vehicle.GUID)) {
trace(s"returning control of ${vehicle.Definition.Name} to ${driver.Name}")
}
else {
trace(s"${driver.Name} is no longer seated in new ${vehicle.Definition.Name}; can not properly return control to driver")
}
} }
} }
else { else {
if(pad.Railed) {
Continent.VehicleEvents ! VehicleSpawnPad.ResetSpawnPad(pad, Continent.Id)
}
trace("can not properly return control to driver") trace("can not properly return control to driver")
} }
finalClear ! VehicleSpawnControl.Process.FinalClearance(entry) finalClear ! VehicleSpawnControl.Process.FinalClearance(entry)

View file

@ -10,9 +10,13 @@ import scodec.codecs._
* <br> * <br>
* The "vehicle" counts as any mobile platform where the user's character is currently sitting. * The "vehicle" counts as any mobile platform where the user's character is currently sitting.
* If the player is not sitting in what the game considers a "vehicle," the packet is wasted. * If the player is not sitting in what the game considers a "vehicle," the packet is wasted.
* Either of the first two parameters - `lock_accelerator` or `lock_wheel` - constitutes the vehicle being overrode. * Either of the first two parameters - `lock_accelerator` or `lock_wheel` - constitutes any vehicle being overrode.
* No message is displayed if the vehicle is placed under server control. * Either of the latter two parameters - `lock_thrust` or `lock_strafe` - constitutes a flight vehicle being overrode.
* The vehicle will operate as if accelerating.<br> * No message is displayed if the vehicle is placed under any form of server control.
* During server control, this is an acceleration value (?);
* during cancellable auto-drive, a constant velocity value.
* Vertical thrust control for aircraft is either on or off;
* the amount of that thrust can not be controlled.<br>
* <br> * <br>
* After being controlled, when the vehicle is no longer under control, * After being controlled, when the vehicle is no longer under control,
* it will transition into a state of constant speed auto-drive. * it will transition into a state of constant speed auto-drive.
@ -22,33 +26,30 @@ import scodec.codecs._
* the player will behave like they are bailing from it. * the player will behave like they are bailing from it.
* (The vehicle actually has to be "bailable" first, of course.)<br> * (The vehicle actually has to be "bailable" first, of course.)<br>
* <br> * <br>
* Speed samples follow (from AMS):<br> * "Something like speed:"<br>
* 1 -> 3<br> * For ground vehicles, for `n`, the calculated in-game speed for the value in this packet will be at least `3.45 x n`.
* 2 -> 7<br> * For flight vehicles, for `n`, the forward air speed for the value in this packet will be at least `1.18 * n`.
* 3 -> 10<br> * This approximation is not always going to be accurate but serves as a good rule of thumb.
* 10 -> 35<br> * @param lock_accelerator driver has no control over vehicle acceleration
* 15 -> 52<br> * @param lock_wheel driver has no control over vehicle turning
* 20 -> 68 * @param reverse move in reverse
* @param lock_accelerator driver has no control over whether vehicle accelerates
* @param lock_wheel driver has no control over whether the vehicle turns
* @param reverse drive in reverse
* @param unk4 na * @param unk4 na
* @param unk5 na * @param lock_vthrust pilot has no control over vertical thrust;
* @param unk6 na * asserts a constant positive vertical thrust;
* @param speed "something like speed;" * the only valid setting appears to be 1
* for `n`, the pattern to calculate a constant in-game speed is `floor(3.5 x n)`; * @param lock_strafe pilot has no control over strafing thrust;
* during server control, an acceleration value (?); * the only valid setting appears to be 1
* during auto-drive, a velocity value * @param forward_speed "something like speed"
* @param unk8 na; * @param unk8 na;
* set `lock_wheel` to `true` to expose value * set `lock_wheel` to `true` to expose this value
*/ */
final case class ServerVehicleOverrideMsg(lock_accelerator : Boolean, final case class ServerVehicleOverrideMsg(lock_accelerator : Boolean,
lock_wheel : Boolean, lock_wheel : Boolean,
reverse : Boolean, reverse : Boolean,
unk4 : Boolean, unk4 : Boolean,
unk5 : Int, lock_vthrust : Int,
unk6 : Int, lock_strafe : Int,
speed : Int, forward_speed : Int,
unk8 : Option[Long] unk8 : Option[Long]
) extends PlanetSideGamePacket { ) extends PlanetSideGamePacket {
type Packet = ServerVehicleOverrideMsg type Packet = ServerVehicleOverrideMsg
@ -58,20 +59,22 @@ final case class ServerVehicleOverrideMsg(lock_accelerator : Boolean,
object ServerVehicleOverrideMsg extends Marshallable[ServerVehicleOverrideMsg] { object ServerVehicleOverrideMsg extends Marshallable[ServerVehicleOverrideMsg] {
/** /**
* Common assert control packet format. * Common lock control packet format.
* Strafing is always treated as unlocked.
* @param flight vehicle flies and should move vertically
* @param speed "something like speed" * @param speed "something like speed"
* @return a `ServerVehicleOverrideMsg` packet * @return a `ServerVehicleOverrideMsg` packet
*/ */
def On(speed : Int) : ServerVehicleOverrideMsg = { def Lock(flight : Int, speed : Int) : ServerVehicleOverrideMsg = {
ServerVehicleOverrideMsg(true, true, false, false, 0, 0, speed, Some(0)) ServerVehicleOverrideMsg(true, true, false, false, flight, 0, speed, Some(0))
} }
/** /**
* Common relinquish control packet format. * Common cancellable auto-drive packet format.
* @param speed "something like speed" * @param speed "something like speed"
* @return a `ServerVehicleOverrideMsg` packet * @return a `ServerVehicleOverrideMsg` packet
*/ */
def Off(speed : Int) : ServerVehicleOverrideMsg = { def Auto(speed : Int) : ServerVehicleOverrideMsg = {
ServerVehicleOverrideMsg(false, false, false, true, 0, 0, speed, None) ServerVehicleOverrideMsg(false, false, false, true, 0, 0, speed, None)
} }
@ -80,9 +83,9 @@ object ServerVehicleOverrideMsg extends Marshallable[ServerVehicleOverrideMsg] {
(("lock_wheel" | bool) >>:~ { test => (("lock_wheel" | bool) >>:~ { test =>
("reverse" | bool) :: ("reverse" | bool) ::
("unk4" | bool) :: ("unk4" | bool) ::
("unk5" | uint2L) :: ("lock_vthrust" | uint2L) ::
("unk6" | uint2L) :: ("lock_strafe" | uint2L) ::
("speed" | uintL(9)) :: ("forward_speed" | uintL(9)) ::
conditional(test, "unk8" | uint32L) conditional(test, "unk8" | uint32L)
}) })
).as[ServerVehicleOverrideMsg] ).as[ServerVehicleOverrideMsg]

View file

@ -58,14 +58,14 @@ class ServerVehicleOverrideMsgTest extends Specification {
} }
"encode (3)" in { "encode (3)" in {
val msg = ServerVehicleOverrideMsg.On(12) val msg = ServerVehicleOverrideMsg.Lock(0, 12)
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string1 pkt mustEqual string1
} }
"encode (4)" in { "encode (4)" in {
val msg = ServerVehicleOverrideMsg.Off(5) val msg = ServerVehicleOverrideMsg.Auto(5)
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string2 pkt mustEqual string2

View file

@ -74,6 +74,14 @@ class WorldSessionActor extends Actor with MDCContextAware {
var progressBarUpdate : Cancellable = DefaultCancellable.obj var progressBarUpdate : Cancellable = DefaultCancellable.obj
var reviveTimer : Cancellable = DefaultCancellable.obj var reviveTimer : Cancellable = DefaultCancellable.obj
/**
* Convert a boolean value into an integer value.
* Use: `true:Int` or `false:Int`
* @param b `true` or `false` (or `null`)
* @return 1 for `true`; 0 for `false`
*/
implicit def boolToInt(b : Boolean) : Int = if(b) 1 else 0
override def postStop() = { override def postStop() = {
clientKeepAlive.cancel clientKeepAlive.cancel
reviveTimer.cancel reviveTimer.cancel
@ -404,6 +412,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
//resets exclamation point fte marker (once) //resets exclamation point fte marker (once)
sendResponse(PlanetsideAttributeMessage(guid, 21, vehicle_guid.guid.toLong)) sendResponse(PlanetsideAttributeMessage(guid, 21, vehicle_guid.guid.toLong))
case VehicleResponse.AttachToRails(vehicle_guid, pad_guid) =>
sendResponse(ObjectAttachMessage(pad_guid, vehicle_guid, 3))
case VehicleResponse.ChildObjectState(object_guid, pitch, yaw) => case VehicleResponse.ChildObjectState(object_guid, pitch, yaw) =>
if(tplayer_guid != guid) { if(tplayer_guid != guid) {
sendResponse(ChildObjectStateMessage(object_guid, pitch, yaw)) sendResponse(ChildObjectStateMessage(object_guid, pitch, yaw))
@ -422,6 +433,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
sendResponse(DeployRequestMessage(guid, object_guid, state, unk1, unk2, pos)) sendResponse(DeployRequestMessage(guid, object_guid, state, unk1, unk2, pos))
} }
case VehicleResponse.DetachFromRails(vehicle_guid, pad_guid, pad_position, pad_orientation_z) =>
sendResponse(ObjectDetachMessage(pad_guid, vehicle_guid, pad_position + Vector3(0,0,0.5f), 0, 0, pad_orientation_z))
case VehicleResponse.InventoryState(obj, parent_guid, start, con_data) => case VehicleResponse.InventoryState(obj, parent_guid, start, con_data) =>
if(tplayer_guid != guid) { if(tplayer_guid != guid) {
//TODO prefer ObjectDetachMessage, but how to force ammo pools to update properly? //TODO prefer ObjectDetachMessage, but how to force ammo pools to update properly?
@ -459,6 +473,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
sendResponse(ObjectAttachMessage(vehicle_guid, guid, seat)) sendResponse(ObjectAttachMessage(vehicle_guid, guid, seat))
} }
case VehicleResponse.ResetSpawnPad(pad_guid) =>
sendResponse(GenericObjectActionMessage(pad_guid, 92))
case VehicleResponse.RevealPlayer(player_guid) => case VehicleResponse.RevealPlayer(player_guid) =>
//TODO any action will cause the player to appear after the effects of ConcealPlayer //TODO any action will cause the player to appear after the effects of ConcealPlayer
@ -1006,12 +1023,15 @@ class WorldSessionActor extends Actor with MDCContextAware {
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, msg.transaction_type, false)) sendResponse(ItemTransactionResultMessage(msg.terminal_guid, msg.transaction_type, false))
} }
case VehicleSpawnPad.StartPlayerSeatedInVehicle(vehicle) => case VehicleSpawnPad.StartPlayerSeatedInVehicle(vehicle, pad) =>
val vehicle_guid = vehicle.GUID val vehicle_guid = vehicle.GUID
if(pad.Railed) {
sendResponse(ObjectAttachMessage(pad.GUID, vehicle_guid, 3))
}
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 22, 1L)) //mount points off? sendResponse(PlanetsideAttributeMessage(vehicle_guid, 22, 1L)) //mount points off?
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 21, player.GUID.guid)) //fte and ownership? sendResponse(PlanetsideAttributeMessage(vehicle_guid, 21, player.GUID.guid)) //fte and ownership?
case VehicleSpawnPad.PlayerSeatedInVehicle(vehicle) => case VehicleSpawnPad.PlayerSeatedInVehicle(vehicle, pad) =>
val vehicle_guid = vehicle.GUID val vehicle_guid = vehicle.GUID
if(player.VehicleSeated.nonEmpty) { if(player.VehicleSeated.nonEmpty) {
vehicleService ! VehicleServiceMessage.UnscheduleDeconstruction(vehicle_guid) vehicleService ! VehicleServiceMessage.UnscheduleDeconstruction(vehicle_guid)
@ -1022,11 +1042,16 @@ class WorldSessionActor extends Actor with MDCContextAware {
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 113, 0L)) //??? sendResponse(PlanetsideAttributeMessage(vehicle_guid, 113, 0L)) //???
ReloadVehicleAccessPermissions(vehicle) ReloadVehicleAccessPermissions(vehicle)
case VehicleSpawnPad.ServerVehicleOverrideStart(speed) => case VehicleSpawnPad.ServerVehicleOverrideStart(vehicle, pad) =>
sendResponse(ServerVehicleOverrideMsg.On(speed)) val vdef = vehicle.Definition
if(vehicle.Seats(0).isOccupied) {
sendResponse(ObjectDetachMessage(pad.GUID, vehicle.GUID, pad.Position + Vector3(0, 0, 0.5f), 0, 0, pad.Orientation.z))
}
sendResponse(ServerVehicleOverrideMsg.Lock(GlobalDefinitions.isFlightVehicle(vdef):Int, vdef.AutoPilotSpeed1))
case VehicleSpawnPad.ServerVehicleOverrideEnd(speed) => case VehicleSpawnPad.ServerVehicleOverrideEnd(vehicle, pad) =>
sendResponse(ServerVehicleOverrideMsg.Off(speed)) sendResponse(GenericObjectActionMessage(pad.GUID, 92)) //reset spawn pad
sendResponse(ServerVehicleOverrideMsg.Auto(vehicle.Definition.AutoPilotSpeed2))
case VehicleSpawnPad.PeriodicReminder(msg) => case VehicleSpawnPad.PeriodicReminder(msg) =>
sendResponse(ChatMsg(ChatMessageType.CMT_OPEN, true, "", msg, None)) sendResponse(ChatMsg(ChatMessageType.CMT_OPEN, true, "", msg, None))

View file

@ -1,5 +1,6 @@
// Copyright (c) 2017 PSForever // Copyright (c) 2017 PSForever
import akka.actor.ActorContext import akka.actor.ActorContext
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
import net.psforever.objects.zones.Zone import net.psforever.objects.zones.Zone
import net.psforever.types.PlanetSideEmpire import net.psforever.types.PlanetSideEmpire
@ -49,6 +50,9 @@ object Zones {
import net.psforever.types.PlanetSideEmpire import net.psforever.types.PlanetSideEmpire
Buildings.values.foreach { _.Faction = PlanetSideEmpire.VS } Buildings.values.foreach { _.Faction = PlanetSideEmpire.VS }
Building(29).get.Faction = PlanetSideEmpire.NC //South Villa Gun Tower Building(29).get.Faction = PlanetSideEmpire.NC //South Villa Gun Tower
GUID(293).get.asInstanceOf[VehicleSpawnPad].Railed = false //building 52
GUID(710).get.asInstanceOf[VehicleSpawnPad].Railed = false //building 79
GUID(712).get.asInstanceOf[VehicleSpawnPad].Railed = false //building 81
} }
} }

View file

@ -9,15 +9,18 @@ import net.psforever.types.{DriveState, Vector3}
object VehicleResponse { object VehicleResponse {
trait Response trait Response
final case class AttachToRails(vehicle_guid : PlanetSideGUID, rails_guid : PlanetSideGUID) extends Response
final case class Awareness(vehicle_guid : PlanetSideGUID) extends Response final case class Awareness(vehicle_guid : PlanetSideGUID) extends Response
final case class ChildObjectState(object_guid : PlanetSideGUID, pitch : Float, yaw : Float) extends Response final case class ChildObjectState(object_guid : PlanetSideGUID, pitch : Float, yaw : Float) extends Response
final case class ConcealPlayer(player_guid : PlanetSideGUID) extends Response final case class ConcealPlayer(player_guid : PlanetSideGUID) extends Response
final case class DeployRequest(object_guid : PlanetSideGUID, state : DriveState.Value, unk1 : Int, unk2 : Boolean, pos : Vector3) extends Response final case class DeployRequest(object_guid : PlanetSideGUID, state : DriveState.Value, unk1 : Int, unk2 : Boolean, pos : Vector3) extends Response
final case class DetachFromRails(vehicle_guid : PlanetSideGUID, rails_guid : PlanetSideGUID, rails_pos : Vector3, rails_rot : Float) extends Response
final case class DismountVehicle(unk1 : Int, unk2 : Boolean) extends Response final case class DismountVehicle(unk1 : Int, unk2 : Boolean) extends Response
final case class InventoryState(obj : PlanetSideGameObject, parent_guid : PlanetSideGUID, start : Int, con_data : ConstructorData) extends Response final case class InventoryState(obj : PlanetSideGameObject, parent_guid : PlanetSideGUID, start : Int, con_data : ConstructorData) extends Response
final case class KickPassenger(unk1 : Int, unk2 : Boolean, vehicle_guid : PlanetSideGUID) extends Response final case class KickPassenger(unk1 : Int, unk2 : Boolean, vehicle_guid : PlanetSideGUID) extends Response
final case class LoadVehicle(vehicle : Vehicle, vtype : Int, vguid : PlanetSideGUID, vdata : ConstructorData) extends Response final case class LoadVehicle(vehicle : Vehicle, vtype : Int, vguid : PlanetSideGUID, vdata : ConstructorData) extends Response
final case class MountVehicle(object_guid : PlanetSideGUID, seat : Int) extends Response final case class MountVehicle(object_guid : PlanetSideGUID, seat : Int) extends Response
final case class ResetSpawnPad(pad_guid : PlanetSideGUID) extends Response
final case class RevealPlayer(player_guid : PlanetSideGUID) extends Response final case class RevealPlayer(player_guid : PlanetSideGUID) extends Response
final case class SeatPermissions(vehicle_guid : PlanetSideGUID, seat_group : Int, permission : Long) extends Response final case class SeatPermissions(vehicle_guid : PlanetSideGUID, seat_group : Int, permission : Long) extends Response
final case class StowEquipment(vehicle_guid : PlanetSideGUID, slot : Int, itype : Int, iguid : PlanetSideGUID, idata : ConstructorData) extends Response final case class StowEquipment(vehicle_guid : PlanetSideGUID, slot : Int, itype : Int, iguid : PlanetSideGUID, idata : ConstructorData) extends Response

View file

@ -116,6 +116,24 @@ class VehicleService extends Actor {
VehicleServiceResponse(s"/$zone_id/Vehicle", Service.defaultPlayerGUID, VehicleResponse.ConcealPlayer(player_guid)) VehicleServiceResponse(s"/$zone_id/Vehicle", Service.defaultPlayerGUID, VehicleResponse.ConcealPlayer(player_guid))
) )
//from VehicleSpawnControl
case VehicleSpawnPad.AttachToRails(vehicle, pad, zone_id) =>
VehicleEvents.publish(
VehicleServiceResponse(s"/$zone_id/Vehicle", Service.defaultPlayerGUID, VehicleResponse.AttachToRails(vehicle.GUID, pad.GUID))
)
//from VehicleSpawnControl
case VehicleSpawnPad.DetachFromRails(vehicle, pad, zone_id) =>
VehicleEvents.publish(
VehicleServiceResponse(s"/$zone_id/Vehicle", Service.defaultPlayerGUID, VehicleResponse.DetachFromRails(vehicle.GUID, pad.GUID, pad.Position, pad.Orientation.z))
)
//from VehicleSpawnControl
case VehicleSpawnPad.ResetSpawnPad(pad, zone_id) =>
VehicleEvents.publish(
VehicleServiceResponse(s"/$zone_id/Vehicle", Service.defaultPlayerGUID, VehicleResponse.ResetSpawnPad(pad.GUID))
)
case VehicleSpawnPad.RevealPlayer(player_guid, zone_id) => case VehicleSpawnPad.RevealPlayer(player_guid, zone_id) =>
VehicleEvents.publish( VehicleEvents.publish(
VehicleServiceResponse(s"/$zone_id/Vehicle", Service.defaultPlayerGUID, VehicleResponse.RevealPlayer(player_guid)) VehicleServiceResponse(s"/$zone_id/Vehicle", Service.defaultPlayerGUID, VehicleResponse.RevealPlayer(player_guid))