block mounting while vehicle in motion, or in control (2)

This commit is contained in:
Fate-JH 2023-05-15 14:09:59 -04:00
parent a41bb4e86f
commit f1a31dd82f
8 changed files with 131 additions and 128 deletions

View file

@ -425,8 +425,7 @@ class SessionAvatarHandlers(
sessionData.zoning.zoningStatus = Zoning.Status.None
sessionData.zoning.spawn.deadState = DeadState.Dead
continent.GUID(mount).collect { case obj: Vehicle =>
sessionData.vehicles.ConditionalDriverVehicleControl(obj)
sessionData.vehicles.serverVehicleControlVelocity = None
sessionData.vehicles.DriverVehicleControl(obj)
sessionData.unaccessContainer(obj)
}
sessionData.playerActionsToCancel()

View file

@ -302,7 +302,7 @@ class SessionMountHandlers(
case v: Vehicle
if seatNum == 0 && Vector3.MagnitudeSquared(v.Velocity.getOrElse(Vector3.Zero)) > 0f =>
sessionData.vehicles.serverVehicleControlVelocity.collect { _ =>
sessionData.vehicles.ServerVehicleOverrideEnd(v)
sessionData.vehicles.ServerVehicleOverrideStop(v)
}
v.Velocity = Vector3.Zero
continent.VehicleEvents ! VehicleServiceMessage(

View file

@ -202,17 +202,19 @@ class SessionVehicleHandlers(
val strafe = 1 + Vehicles.CargoOrientation(vehicle)
val reverseSpeed = if (strafe > 1) { 0 } else { speed }
//strafe or reverse, not both
sessionData.vehicles.serverVehicleControlVelocity = Some(reverseSpeed)
sendResponse(ServerVehicleOverrideMsg(
lock_accelerator=true,
lock_wheel=true,
reverse=true,
unk4=false,
lock_vthrust=0,
strafe,
reverseSpeed,
unk8=Some(0)
))
sessionData.vehicles.ServerVehicleOverrideWithPacket(
vehicle,
ServerVehicleOverrideMsg(
lock_accelerator=true,
lock_wheel=true,
reverse=true,
unk4=false,
lock_vthrust=0,
strafe,
reverseSpeed,
unk8=Some(0)
)
)
import scala.concurrent.ExecutionContext.Implicits.global
context.system.scheduler.scheduleOnce(
delay milliseconds,
@ -220,25 +222,27 @@ class SessionVehicleHandlers(
VehicleServiceResponse(toChannel, PlanetSideGUID(0), VehicleResponse.KickCargo(vehicle, speed=0, delay))
)
case VehicleResponse.KickCargo(_, _, _)
case VehicleResponse.KickCargo(cargo, _, _)
if player.VehicleSeated.nonEmpty && sessionData.zoning.spawn.deadState == DeadState.Alive =>
sessionData.vehicles.serverVehicleControlVelocity = None
sendResponse(ServerVehicleOverrideMsg(
lock_accelerator=false,
lock_wheel=false,
reverse=false,
unk4=false,
lock_vthrust=0,
lock_strafe=0,
movement_speed=0,
unk8=None
))
sessionData.vehicles.TotalDriverVehicleControl(cargo)
case VehicleResponse.StartPlayerSeatedInVehicle(vehicle, _)
if player.VisibleSlots.contains(player.DrawnSlot) =>
val vehicle_guid = vehicle.GUID
sessionData.playerActionsToCancel()
sessionData.vehicles.serverVehicleControlVelocity = Some(0)
sessionData.vehicles.ServerVehicleOverrideWithPacket(
vehicle,
ServerVehicleOverrideMsg(
lock_accelerator=false,
lock_wheel=false,
reverse=false,
unk4=false,
lock_vthrust=0,
lock_strafe=0,
movement_speed=0,
unk8=None
)
)
sessionData.terminals.CancelAllProximityUnits()
player.DrawnSlot = Player.HandsDownSlot
sendResponse(ObjectHeldMessage(player.GUID, Player.HandsDownSlot, unk1=true))
@ -256,7 +260,6 @@ class SessionVehicleHandlers(
val vehicleGuid = vehicle.GUID
val playerGuid = player.GUID
sessionData.playerActionsToCancel()
sessionData.vehicles.serverVehicleControlVelocity = Some(0)
sessionData.terminals.CancelAllProximityUnits()
sendResponse(PlanetsideAttributeMessage(vehicleGuid, attribute_type=22, attribute_value=1L)) //mount points off
sendResponse(PlanetsideAttributeMessage(playerGuid, attribute_type=21, vehicleGuid)) //ownership
@ -266,18 +269,39 @@ class SessionVehicleHandlers(
case VehicleResponse.PlayerSeatedInVehicle(vehicle, _) =>
Vehicles.ReloadAccessPermissions(vehicle, player.Name)
sessionData.vehicles.ServerVehicleLock(vehicle)
sessionData.vehicles.ServerVehicleOverrideWithPacket(
vehicle,
ServerVehicleOverrideMsg(
lock_accelerator=true,
lock_wheel=true,
reverse=false,
unk4=false,
lock_vthrust=0,
lock_strafe=0,
movement_speed=0,
unk8=Some(0)
)
)
sessionData.vehicles.serverVehicleControlVelocity = Some(-1)
case VehicleResponse.ServerVehicleOverrideStart(vehicle, _) =>
val vdef = vehicle.Definition
sessionData.vehicles.ServerVehicleOverride(
sessionData.vehicles.ServerVehicleOverrideWithPacket(
vehicle,
vdef.AutoPilotSpeed1,
flight= if (GlobalDefinitions.isFlightVehicle(vdef)) { 1 } else { 0 }
ServerVehicleOverrideMsg(
lock_accelerator=true,
lock_wheel=true,
reverse=false,
unk4=false,
lock_vthrust=if (GlobalDefinitions.isFlightVehicle(vdef)) { 1 } else { 0 },
lock_strafe=0,
movement_speed=vdef.AutoPilotSpeed1,
unk8=Some(0)
)
)
case VehicleResponse.ServerVehicleOverrideEnd(vehicle, _) =>
sessionData.vehicles.ServerVehicleOverrideEnd(vehicle)
sessionData.vehicles.ServerVehicleOverrideStop(vehicle)
case VehicleResponse.PeriodicReminder(VehicleSpawnPad.Reminders.Blocked, data) =>
sendResponse(ChatMsg(

View file

@ -269,7 +269,7 @@ class VehicleOperations(
def handleMountVehicle(pkt: MountVehicleMsg): Unit = {
val MountVehicleMsg(_, mountable_guid, entry_point) = pkt
sessionData.validObject(mountable_guid, decorator = "MountVehicle").collect {
case obj: Mountable if serverVehicleControlVelocity.isEmpty =>
case obj: Mountable =>
obj.Actor ! Mountable.TryMount(player, entry_point)
case _: Mountable =>
log.warn(
@ -299,10 +299,6 @@ class VehicleOperations(
dError(s"DismountVehicleMsg: player ${player.Name} not considered seated in a mountable entity", player)
None
}) match {
case Some(_) if serverVehicleControlVelocity.nonEmpty =>
log.warn(
s"DismountVehicleMsg: ${player.Name} can not dismount from vehicle while server has asserted control; please wait"
)
case Some(obj: Mountable) =>
obj.PassengerInSeat(player) match {
case Some(seat_num) =>
@ -535,97 +531,27 @@ class VehicleOperations(
}
/**
* This function is applied to vehicles that are leaving a cargo vehicle's cargo hold to auto reverse them out
* Lock all applicable controls of the current vehicle
* Set the vehicle to move in reverse
* Place the current vehicle under the control of the driver's commands,
* but leave it in a cancellable auto-drive.
* @param vehicle the vehicle
*/
def ServerVehicleLockReverse(): Unit = {
serverVehicleControlVelocity = Some(-1)
sendResponse(
ServerVehicleOverrideMsg(
lock_accelerator = true,
lock_wheel = true,
reverse = true,
unk4 = true,
lock_vthrust = 0,
lock_strafe = 1,
movement_speed = 2,
unk8 = Some(0)
)
)
}
/**
* This function is applied to vehicles that are leaving a cargo vehicle's cargo hold to strafe right out of the cargo hold for vehicles that are mounted sideways e.g. router/BFR
* Lock all applicable controls of the current vehicle
* Set the vehicle to strafe right
*/
def ServerVehicleLockStrafeRight(): Unit = {
serverVehicleControlVelocity = Some(-1)
sendResponse(
ServerVehicleOverrideMsg(
lock_accelerator = true,
lock_wheel = true,
reverse = false,
unk4 = true,
lock_vthrust = 0,
lock_strafe = 3,
movement_speed = 0,
unk8 = Some(0)
)
)
}
/**
* This function is applied to vehicles that are leaving a cargo vehicle's cargo hold to strafe left out of the cargo hold for vehicles that are mounted sideways e.g. router/BFR
* Lock all applicable controls of the current vehicle
* Set the vehicle to strafe left
*/
def ServerVehicleLockStrafeLeft(): Unit = {
serverVehicleControlVelocity = Some(-1)
sendResponse(
ServerVehicleOverrideMsg(
lock_accelerator = true,
lock_wheel = true,
reverse = false,
unk4 = true,
lock_vthrust = 0,
lock_strafe = 2,
movement_speed = 0,
unk8 = Some(0)
)
)
}
/**
*
*/
def ServerVehicleOverrideEnd(vehicle: Vehicle): Unit = {
def ServerVehicleOverrideStop(vehicle: Vehicle): Unit = {
val vehicleGuid = vehicle.GUID
session = session.copy(avatar = avatar.copy(vehicle = Some(vehicleGuid)))
sessionData.vehicles.DriverVehicleControl(vehicle, vehicle.Definition.AutoPilotSpeed2)
sendResponse(PlanetsideAttributeMessage(vehicleGuid, attribute_type=22, attribute_value=0L)) //mount points on
}
/**
* Lock all applicable controls of the current vehicle.
* This includes forward motion, turning, and, if applicable, strafing.
* @param vehicle the vehicle being controlled
*/
def ServerVehicleLock(vehicle: Vehicle): Unit = {
serverVehicleControlVelocity = Some(-1)
sendResponse(ServerVehicleOverrideMsg(lock_accelerator=true, lock_wheel=true, reverse=false, unk4=false, 0, 1, 0, Some(0)))
}
/**
* Place the current vehicle under the control of the server's commands.
* @param vehicle the vehicle
* @param speed how fast the vehicle is moving forward
* @param flight whether the vehicle is ascending or not, if the vehicle is an applicable type
* @param vehicle vehicle to be controlled;
* the client's player who is receiving this packet should be mounted as its driver, but this is not explicitly tested
* @param pkt packet to instigate server control
*/
def ServerVehicleOverride(vehicle: Vehicle, speed: Int = 0, flight: Int = 0): Unit = {
serverVehicleControlVelocity = Some(speed)
sendResponse(ServerVehicleOverrideMsg(lock_accelerator=true, lock_wheel=true, reverse=false, unk4=false, flight, 0, speed, Some(0)))
def ServerVehicleOverrideWithPacket(vehicle: Vehicle, pkt: ServerVehicleOverrideMsg): Unit = {
serverVehicleControlVelocity = Some(pkt.movement_speed)
vehicle.DeploymentState = DriveState.AutoPilot
sendResponse(pkt)
}
/**
@ -636,9 +562,20 @@ class VehicleOperations(
* @param flight whether the vehicle is ascending or not, if the vehicle is an applicable type
*/
def DriverVehicleControl(vehicle: Vehicle, speed: Int = 0, flight: Int = 0): Unit = {
if (serverVehicleControlVelocity.nonEmpty) {
serverVehicleControlVelocity = None
sendResponse(ServerVehicleOverrideMsg(lock_accelerator=false, lock_wheel=false, reverse=false, unk4=true, flight, 0, speed, None))
if (vehicle.DeploymentState == DriveState.AutoPilot) {
TotalDriverVehicleControlWithPacket(
vehicle,
ServerVehicleOverrideMsg(
lock_accelerator=false,
lock_wheel=false,
reverse=false,
unk4=true,
lock_vthrust=flight,
lock_strafe=0,
movement_speed=speed,
unk8=None
)
)
}
}
@ -649,15 +586,45 @@ class VehicleOperations(
* @param vehicle the vehicle
*/
def ConditionalDriverVehicleControl(vehicle: Vehicle): Unit = {
if (serverVehicleControlVelocity.nonEmpty && !serverVehicleControlVelocity.contains(0)) {
if (vehicle.DeploymentState == DriveState.AutoPilot) {
TotalDriverVehicleControl(vehicle)
}
}
//noinspection ScalaUnusedSymbol
/**
* Place the current vehicle under the control of the driver's commands,
* but leave it in a cancellable auto-drive.
* Stop all movement entirely.
* @param vehicle the vehicle
*/
def TotalDriverVehicleControl(vehicle: Vehicle): Unit = {
TotalDriverVehicleControlWithPacket(
vehicle,
ServerVehicleOverrideMsg(
lock_accelerator=false,
lock_wheel=false,
reverse=false,
unk4=false,
lock_vthrust=0,
lock_strafe=0,
movement_speed=0,
unk8=None
)
)
}
/**
* Place the current vehicle under the control of the driver's commands,
* but leave it in a cancellable auto-drive.
* Stop all movement entirely.
* @param vehicle the vehicle;
* the client's player who is receiving this packet should be mounted as its driver, but this is not explicitly tested
* @param pkt packet to instigate cancellable control
*/
def TotalDriverVehicleControlWithPacket(vehicle: Vehicle, pkt: ServerVehicleOverrideMsg): Unit = {
serverVehicleControlVelocity = None
sendResponse(ServerVehicleOverrideMsg(lock_accelerator=false, lock_wheel=false, reverse=false, unk4=false, 0, 0, 0, None))
vehicle.DeploymentState = DriveState.Mobile
sendResponse(pkt)
}
/**

View file

@ -36,7 +36,7 @@ class VehicleConverter extends ObjectCreateConverter[Vehicle]() {
health,
unk4 = false,
no_mount_points = false,
obj.DeploymentState,
SterilizedDeploymentState(obj),
unk5 = false,
unk6 = false,
obj.Cloaked,
@ -105,6 +105,13 @@ class VehicleConverter extends ObjectCreateConverter[Vehicle]() {
.toList
}
private def SterilizedDeploymentState(obj: Vehicle): DriveState.Value = {
obj.DeploymentState match {
case state if state.id < 0 => DriveState.Mobile
case state => state
}
}
protected def SpecificFormatModifier: VehicleFormat.Value = VehicleFormat.Normal
protected def SpecificFormatData(obj: Vehicle): Option[SpecificVehicleData] = None

View file

@ -121,6 +121,9 @@ class VehicleControl(vehicle: Vehicle)
case Vehicle.Ownership(Some(player)) =>
GainOwnership(player)
case Mountable.TryMount(user, mountPoint) if vehicle.DeploymentState == DriveState.AutoPilot =>
sender() ! Mountable.MountMessages(user, Mountable.CanNotMount(vehicle, mountPoint))
case msg @ Mountable.TryMount(player, mount_point) =>
mountBehavior.apply(msg)
mountCleanup(mount_point, player)

View file

@ -31,7 +31,8 @@ import scodec.codecs._
* For flight vehicles, for `n`, the forward air speed for the value in this packet will be at least `1.18 * n`.
* This approximation is not always going to be accurate but serves as a good rule of thumb.
* @param lock_accelerator driver has no control over vehicle acceleration
* @param lock_wheel driver has no control over vehicle turning
* @param lock_wheel driver has no control over vehicle turning;
* generally, the driver never has turning control
* @param reverse move in reverse
* 0 = forward
* 1 = reverse

View file

@ -21,5 +21,7 @@ object DriveState extends Enumeration {
val State7 = Value(7) //unknown; not encountered on a vehicle that can deploy; functions like Mobile
val State127 = Value(127) //unknown
val Kneeling = Value(-1) //flag bfr kneeling state; should not not encode
//the following values should never be encoded
val Kneeling = Value(-1) //flag bfr kneeling state
val AutoPilot = Value(-2) //when emerging from spawn pad, or being kicked from a ferry, during server guidance
}