2020-05-31 17:07:22 +00:00
using UnityEngine ;
using SanAndreasUnity.Utilities ;
using SanAndreasUnity.Behaviours.Vehicles ;
namespace SanAndreasUnity.Behaviours.Peds.States
{
public class BaseVehicleState : BaseScriptState , IVehicleState
{
private Vehicle m_currentVehicle ;
public Vehicle CurrentVehicle { get { return m_currentVehicle ; } protected set { m_currentVehicle = value ; } }
2019-07-11 20:54:48 +00:00
public Vehicle . Seat CurrentVehicleSeat { get = > this . CurrentVehicle ! = null ? this . CurrentVehicle . GetSeat ( this . CurrentVehicleSeatAlignment ) : null ; }
public Vehicle . SeatAlignment CurrentVehicleSeatAlignment { get ; protected set ; }
protected uint m_currentVehicleNetId = 0 ;
2020-05-31 17:07:22 +00:00
2019-05-25 19:50:07 +00:00
public override void OnSwitchedStateByServer ( byte [ ] data )
2019-05-27 00:36:52 +00:00
{
2019-07-11 22:51:52 +00:00
// we need to wait for end of frame, because vehicle may not be spawned yet
//this.StartCoroutine(this.SwitchStateAtEndOfFrame(data));
// check if this state was already activated
// it can happen when, among other things, syncvar hooks get invoked twice when creating the ped
if ( this . IsActiveState )
return ;
this . ReadNetworkData ( data ) ;
m_ped . SwitchState ( this . GetType ( ) ) ;
if ( this . CurrentVehicle ! = null )
this . OnVehicleAssigned ( ) ;
2019-05-27 00:36:52 +00:00
}
protected void ReadNetworkData ( byte [ ] data )
2019-07-13 16:29:14 +00:00
{
var reader = new Mirror . NetworkReader ( data ) ;
this . ReadNetworkData ( reader ) ;
}
protected virtual void ReadNetworkData ( Mirror . NetworkReader reader )
2019-05-25 19:50:07 +00:00
{
2019-07-11 22:51:52 +00:00
// first reset params
this . CurrentVehicle = null ;
this . CurrentVehicleSeatAlignment = Vehicle . SeatAlignment . None ;
m_currentVehicleNetId = 0 ;
2019-05-25 19:50:07 +00:00
// extract vehicle and seat from data
2019-07-11 20:54:48 +00:00
int magicNumber = reader . ReadInt32 ( ) ;
m_currentVehicleNetId = reader . ReadUInt32 ( ) ;
this . CurrentVehicleSeatAlignment = ( Vehicle . SeatAlignment ) reader . ReadSByte ( ) ;
// assign current vehicle
GameObject vehicleGo = Net . NetManager . GetNetworkObjectById ( m_currentVehicleNetId ) ;
2019-05-25 19:50:07 +00:00
this . CurrentVehicle = vehicleGo ! = null ? vehicleGo . GetComponent < Vehicle > ( ) : null ;
2019-07-11 20:54:48 +00:00
if ( magicNumber ! = 123456789 )
2019-07-13 16:29:14 +00:00
Debug . LogErrorFormat ( "magicNumber {0}, m_currentVehicleNetId {1}, data size {2} - this should not happen" , magicNumber , m_currentVehicleNetId , reader . Length ) ;
2019-05-25 19:50:07 +00:00
}
2019-05-25 21:38:12 +00:00
public override byte [ ] GetAdditionalNetworkData ( )
{
var writer = new Mirror . NetworkWriter ( ) ;
2019-07-13 15:48:52 +00:00
this . GetAdditionalNetworkData ( writer ) ;
return writer . ToArray ( ) ;
}
protected virtual void GetAdditionalNetworkData ( Mirror . NetworkWriter writer )
{
2019-07-11 20:54:48 +00:00
writer . Write ( ( int ) 123456789 ) ;
2019-05-25 21:38:12 +00:00
if ( this . CurrentVehicle ! = null ) {
2019-07-11 20:54:48 +00:00
writer . Write ( ( uint ) this . CurrentVehicle . NetTransform . netId ) ;
2019-05-25 21:38:12 +00:00
writer . Write ( ( sbyte ) this . CurrentVehicleSeatAlignment ) ;
} else {
2019-07-11 20:54:48 +00:00
writer . Write ( ( uint ) 0 ) ;
2019-05-25 21:38:12 +00:00
writer . Write ( ( sbyte ) Vehicle . SeatAlignment . None ) ;
}
}
2019-05-27 00:36:52 +00:00
System . Collections . IEnumerator SwitchStateAtEndOfFrame ( byte [ ] data )
{
var oldState = m_ped . CurrentState ;
yield return new WaitForEndOfFrame ( ) ;
2019-05-27 18:27:47 +00:00
if ( oldState ! = m_ped . CurrentState )
2019-05-27 00:36:52 +00:00
{
2019-05-27 18:27:47 +00:00
// state changed in the meantime
// did server change it ? or syncvar hooks invoked twice ? either way, we should stop here
// Debug.LogFormat("state changed in the meantime, old: {0}, new: {1}", oldState != null ? oldState.GetType().Name : "",
// m_ped.CurrentState != null ? m_ped.CurrentState.GetType().Name : "");
2019-05-27 00:36:52 +00:00
yield break ;
}
2019-05-27 18:27:47 +00:00
// read current vehicle here - it should've been spawned by now
2019-05-27 00:36:52 +00:00
this . ReadNetworkData ( data ) ;
2019-05-27 18:27:47 +00:00
// Debug.LogFormat("Switching to state {0}, vehicle: {1}, seat: {2}", this.GetType().Name, this.CurrentVehicle, this.CurrentVehicleSeat);
2019-05-27 00:36:52 +00:00
// now we can enter this state
m_ped . SwitchState ( this . GetType ( ) ) ;
}
2019-07-11 22:51:52 +00:00
protected virtual void OnVehicleAssigned ( )
{
}
2019-07-11 23:04:41 +00:00
public static void PreparePedForVehicle ( Ped ped , Vehicle vehicle , Vehicle . Seat seat )
{
seat . OccupyingPed = ped ;
ped . characterController . enabled = false ;
ped . transform . SetParent ( seat . Parent ) ;
ped . transform . localPosition = Vector3 . zero ;
ped . transform . localRotation = Quaternion . identity ;
ped . PlayerModel . IsInVehicle = true ;
if ( ! VehicleManager . Instance . syncPedTransformWhileInVehicle ) {
if ( ped . NetTransform ! = null )
ped . NetTransform . enabled = false ;
}
2020-05-04 23:39:16 +00:00
F . RunExceptionSafe ( ( ) = > vehicle . OnPedPreparedForVehicle ( ped , seat ) ) ;
2019-07-11 23:04:41 +00:00
}
2019-04-28 23:15:24 +00:00
protected void Cleanup ( )
{
if ( ! m_ped . IsInVehicle )
{
m_ped . characterController . enabled = true ;
m_ped . transform . SetParent ( null , true ) ;
m_model . IsInVehicle = false ;
2019-05-24 22:28:09 +00:00
// enable network transform
2019-05-06 00:00:53 +00:00
if ( m_ped . NetTransform ! = null )
2019-05-24 22:28:09 +00:00
m_ped . NetTransform . enabled = true ;
2020-05-04 23:39:16 +00:00
if ( this . CurrentVehicle ! = null )
F . RunExceptionSafe ( ( ) = > this . CurrentVehicle . OnPedRemovedFromVehicle ( m_ped , this . CurrentVehicleSeat ) ) ;
2019-04-28 23:15:24 +00:00
}
2019-04-29 00:04:45 +00:00
2019-04-29 00:06:44 +00:00
if ( this . CurrentVehicleSeat ! = null & & this . CurrentVehicleSeat . OccupyingPed = = m_ped )
2019-04-29 00:04:45 +00:00
this . CurrentVehicleSeat . OccupyingPed = null ;
this . CurrentVehicle = null ;
2019-07-11 20:54:48 +00:00
this . CurrentVehicleSeatAlignment = Vehicle . SeatAlignment . None ;
2019-07-11 22:51:52 +00:00
m_currentVehicleNetId = 0 ;
2019-07-11 23:04:41 +00:00
2019-07-11 22:51:52 +00:00
}
public override void UpdateState ( )
{
base . UpdateState ( ) ;
if ( ! this . IsActiveState )
return ;
if ( Net . NetStatus . IsClientOnly )
{
if ( null = = this . CurrentVehicle )
{
// check if vehicle was spawned in the meantime
GameObject vehicleGo = Net . NetManager . GetNetworkObjectById ( m_currentVehicleNetId ) ;
if ( vehicleGo ! = null )
{
// vehicle is spawned
this . CurrentVehicle = vehicleGo . GetComponent < Vehicle > ( ) ;
this . OnVehicleAssigned ( ) ;
}
}
}
2019-04-28 23:15:24 +00:00
}
2020-05-31 17:07:22 +00:00
protected override void UpdateHeading ( )
{
}
protected override void UpdateRotation ( )
{
}
protected override void UpdateMovement ( )
{
}
protected override void ConstrainRotation ( )
{
}
public bool CanEnterVehicle ( Vehicle vehicle , Vehicle . SeatAlignment seatAlignment )
{
if ( m_ped . IsInVehicle )
return false ;
2019-05-27 18:27:47 +00:00
// this should be removed
2020-05-31 17:07:22 +00:00
if ( m_ped . IsAiming | | m_ped . WeaponHolder . IsFiring )
return false ;
var seat = vehicle . GetSeat ( seatAlignment ) ;
if ( null = = seat )
return false ;
// check if specified seat is taken
if ( seat . IsTaken )
return false ;
// everything is ok, we can enter vehicle
return true ;
}
2021-02-06 20:12:41 +00:00
public override void KillPed ( )
{
if ( m_ped . CurrentVehicle ! = null & & m_ped . CurrentVehicle . ExplodedThisFrame )
{
base . KillPed ( ) ;
return ;
}
// don't detach ragdoll, because it will collide with vehicle and vehicle will fly away
Object . Destroy ( m_ped . gameObject ) ;
}
2020-05-31 17:07:22 +00:00
}
}