diff --git a/src/main/scala/net/psforever/actors/session/csr/MountHandlerLogic.scala b/src/main/scala/net/psforever/actors/session/csr/MountHandlerLogic.scala index 4e9480d54..d82f03090 100644 --- a/src/main/scala/net/psforever/actors/session/csr/MountHandlerLogic.scala +++ b/src/main/scala/net/psforever/actors/session/csr/MountHandlerLogic.scala @@ -40,7 +40,39 @@ class MountHandlerLogic(val ops: SessionMountHandlers, implicit val context: Act def handleDismountVehicle(pkt: DismountVehicleMsg): Unit = { //can't do this if we're not in vehicle, so also not csr spectator - ops.handleDismountVehicle(pkt.copy(bailType = BailType.Bailed)) + val DismountVehicleMsg(player_guid, _, _) = pkt + player + .avatar + .vehicle + .flatMap { obj_guid => + ( + sessionLogic.validObject(obj_guid, decorator = "csr/DismountVehicle/Vehicle"), + sessionLogic.validObject(player_guid, decorator = "csr/DismountVehicle/Player") + ) match { + case (Some(obj: Vehicle), Some(tplayer: Player)) if obj.MountedIn.isEmpty => + Some((obj, tplayer)) + case (Some(obj: Mountable), Some(tplayer: Player)) => + Some((obj, tplayer)) + case _ => + None + } + }.foreach { case (obj, tplayer) => + obj + .PassengerInSeat(tplayer) + .foreach { seatNum => + if (obj.Seat(seatNum).flatMap(seat => seat.unmount(tplayer)).isEmpty) { + obj.Actor ! Mountable.TryDismount(tplayer, seatNum, BailType.Bailed) //attempt dismount cleanup + context.self ! Mountable.MountMessages( + tplayer, + Mountable.CanDismount( + obj, + seatNum, + obj.MountPoints.find(_._2.seatIndex == seatNum).map(_._1).getOrElse(0) //todo is accurate mount point necessary? + ) + ) + } + } + } } def handleMountVehicleCargo(pkt: MountVehicleCargoMsg): Unit = { @@ -320,7 +352,6 @@ class MountHandlerLogic(val ops: SessionMountHandlers, implicit val context: Act case Mountable.CanNotDismount(obj: Vehicle, _, _) if obj.isMoving(test = 1f) => - ops.handleDismountVehicle(DismountVehicleMsg(player.GUID, BailType.Bailed, wasKickedByDriver=true)) if (!player.spectator) { sendResponse(ChatMsg(ChatMessageType.UNK_224, "@TooFastToDismount")) } diff --git a/src/main/scala/net/psforever/objects/vehicles/control/VehicleControl.scala b/src/main/scala/net/psforever/objects/vehicles/control/VehicleControl.scala index d1d2a355e..d7f521ae7 100644 --- a/src/main/scala/net/psforever/objects/vehicles/control/VehicleControl.scala +++ b/src/main/scala/net/psforever/objects/vehicles/control/VehicleControl.scala @@ -126,58 +126,31 @@ class VehicleControl(vehicle: Vehicle) mountBehavior.apply(msg) mountCleanup(mount_point, player) - // Issue 1133. Todo: There may be a better way to address the issue? - case Mountable.TryDismount(user, seat_num, bailType) if GlobalDefinitions.isFlightVehicle(vehicle.Definition) && - (vehicle.History.find { entry => entry.isInstanceOf[SpawningActivity] } match { - case Some(entry) if System.currentTimeMillis() - entry.time < 3000L => true - case _ => false - }) => - sender() ! Mountable.MountMessages(user, Mountable.CanNotDismount(vehicle, seat_num, bailType)) - - case Mountable.TryDismount(user, seat_num, bailType) if !GlobalDefinitions.isFlightVehicle(vehicle.Definition) && - (vehicle.History.find { entry => entry.isInstanceOf[SpawningActivity] } match { - case Some(entry) if System.currentTimeMillis() - entry.time < 8500L => true - case _ => false - }) => - sender() ! Mountable.MountMessages(user, Mountable.CanNotDismount(vehicle, seat_num, bailType)) - - case Mountable.TryDismount(user, seat_num, bailType) - if vehicle.Health <= (vehicle.Definition.MaxHealth * .1).round && bailType == BailType.Bailed - && GlobalDefinitions.isFlightVehicle(vehicle.Definition) - && (seat_num == 0 || vehicle.SeatPermissionGroup(seat_num).getOrElse(0) == AccessPermissionGroup.Gunner) - && (vehicle.History.findLast { entry => entry.isInstanceOf[DamagingActivity] } match { - case Some(entry) if System.currentTimeMillis() - entry.time < 4000L => true - case _ if Random.nextInt(10) == 1 => false - case _ => true }) => - sender() ! Mountable.MountMessages(user, Mountable.CanNotDismount(vehicle, seat_num, bailType)) - case Mountable.TryDismount(user, seat_num, bailType) - if vehicle.Health <= (vehicle.Definition.MaxHealth * .2).round && bailType == BailType.Bailed - && GlobalDefinitions.isFlightVehicle(vehicle.Definition) - && (seat_num == 0 || vehicle.SeatPermissionGroup(seat_num).getOrElse(0) == AccessPermissionGroup.Gunner) - && (vehicle.History.findLast { entry => entry.isInstanceOf[DamagingActivity] } match { - case Some(entry) if System.currentTimeMillis() - entry.time < 3500L => true - case _ if Random.nextInt(5) == 1 => false - case _ => true }) => + if vehicle.DeploymentState == DriveState.AutoPilot => sender() ! Mountable.MountMessages(user, Mountable.CanNotDismount(vehicle, seat_num, bailType)) + // Issue 1133. Todo: There may be a better way to address the issue? case Mountable.TryDismount(user, seat_num, bailType) - if vehicle.Health <= (vehicle.Definition.MaxHealth * .35).round && bailType == BailType.Bailed - && GlobalDefinitions.isFlightVehicle(vehicle.Definition) - && (seat_num == 0 || vehicle.SeatPermissionGroup(seat_num).getOrElse(0) == AccessPermissionGroup.Gunner) - && (vehicle.History.findLast { entry => entry.isInstanceOf[DamagingActivity] } match { - case Some(entry) if System.currentTimeMillis() - entry.time < 3000L => true - case _ if Random.nextInt(4) == 1 => false - case _ => true }) => + if { + val curr = System.currentTimeMillis() + vehicle.History.find { entry => entry.isInstanceOf[SpawningActivity] } match { + case Some(entry) if curr - entry.time < 3000L => GlobalDefinitions.isFlightVehicle(vehicle.Definition) + case Some(entry) if curr - entry.time < 8500L => !GlobalDefinitions.isFlightVehicle(vehicle.Definition) + case _ => false + } + } => sender() ! Mountable.MountMessages(user, Mountable.CanNotDismount(vehicle, seat_num, bailType)) - case Mountable.TryDismount(user, seat_num, bailType) - if vehicle.DeploymentState == DriveState.AutoPilot => - sender() ! Mountable.MountMessages(user, Mountable.CanNotDismount(vehicle, seat_num, bailType)) + case msg @ Mountable.TryDismount(user, seat_num, BailType.Bailed) + if GlobalDefinitions.isFlightVehicle(vehicle.Definition) && + (seat_num == 0 || vehicle.SeatPermissionGroup(seat_num).contains(AccessPermissionGroup.Gunner)) => + dismountBailFromFlightVehicle(msg) + dismountCleanup(seat_num, user) - case Mountable.TryDismount(user, seat_num, bailType) - if vehicle.isMoving(test = 1f) && bailType == BailType.Normal => - sender() ! Mountable.MountMessages(user, Mountable.CanNotDismount(vehicle, seat_num, bailType)) + case Mountable.TryDismount(user, seat_num, BailType.Normal) //todo this may not be necessary; see MountableBehavior.dismountTest + if vehicle.isMoving(test = 1f) => + sender() ! Mountable.MountMessages(user, Mountable.CanNotDismount(vehicle, seat_num, BailType.Normal)) case msg @ Mountable.TryDismount(player, seat_num, _) => dismountBehavior.apply(msg) @@ -370,6 +343,27 @@ class VehicleControl(vehicle: Vehicle) } } + def dismountBailFromFlightVehicle(msg: Mountable.TryDismount): Unit = { + val Mountable.TryDismount(user, seat_num, bailType) = msg + val health = vehicle.Health + val maxhealth = vehicle.Definition.MaxHealth + val lastdamage = vehicle.History.findLast { entry => entry.isInstanceOf[DamagingActivity] } + if (List((0.1, 4000L, 10), (0.2, 3500L, 5), (0.35, 3000L, 4)).exists { + case (percent, time, randVal) => + health <= (maxhealth * percent).round && + (lastdamage match { + case Some(entry) if System.currentTimeMillis() - entry.time < time => true + case _ if Random.nextInt(randVal) == 1 => false + case _ => true + }) + } + ) { + sender() ! Mountable.MountMessages(user, Mountable.CanNotDismount(vehicle, seat_num, bailType)) + } else { + dismountBehavior.apply(msg) + } + } + override protected def dismountTest( obj: Mountable with WorldEntity, seatNumber: Int,