mirror of
https://github.com/GTA-ASM/SanAndreasUnity
synced 2024-11-27 14:30:17 +00:00
225 lines
5.1 KiB
C#
225 lines
5.1 KiB
C#
using UnityEngine;
|
|
using SanAndreasUnity.Utilities;
|
|
using SanAndreasUnity.Importing.Animation;
|
|
|
|
namespace SanAndreasUnity.Behaviours.Peds.States
|
|
{
|
|
|
|
public class RollState : BaseMovementState
|
|
{
|
|
public override AnimId movementAnim { get { return m_rollLeft ? new AnimId ("ped", "Crouch_Roll_L") : new AnimId ("ped", "Crouch_Roll_R"); } }
|
|
public override AnimId movementWeaponAnim { get { return this.movementAnim; } }
|
|
|
|
private bool m_rollLeft = false;
|
|
private AnimationState m_animState;
|
|
|
|
const string kRollDirSyncName = "rollDir";
|
|
|
|
|
|
|
|
public bool CanRoll()
|
|
{
|
|
if( this.IsActiveState )
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
public bool Roll(bool left)
|
|
{
|
|
if( !this.CanRoll() )
|
|
return false;
|
|
|
|
m_rollLeft = left;
|
|
m_ped.SwitchState<RollState>();
|
|
|
|
return true;
|
|
}
|
|
|
|
protected override void Start()
|
|
{
|
|
base.Start();
|
|
|
|
// subscribe to dictionary event
|
|
if (m_isClientOnly)
|
|
m_ped.syncDictionaryStringUint.Callback += this.OnDictChanged;
|
|
|
|
}
|
|
|
|
public override void OnBecameActive ()
|
|
{
|
|
base.OnBecameActive();
|
|
|
|
this.PlayAnim();
|
|
|
|
if (m_isServer)
|
|
m_ped.syncDictionaryStringUint[kRollDirSyncName] = m_rollLeft ? (uint) 1 : (uint) 0;
|
|
}
|
|
|
|
public override byte[] GetAdditionalNetworkData()
|
|
{
|
|
var writer = new Mirror.NetworkWriter();
|
|
writer.Write("roll");
|
|
writer.Write(m_rollLeft);
|
|
return writer.ToArray();
|
|
}
|
|
|
|
public override void OnSwitchedStateByServer(byte[] data)
|
|
{
|
|
var reader = new Mirror.NetworkReader(data);
|
|
string magicWord = reader.ReadString();
|
|
if (magicWord != "roll")
|
|
Debug.LogErrorFormat("wrong magic word when switching to roll state: {0}", magicWord);
|
|
m_rollLeft = reader.ReadBoolean();
|
|
|
|
m_ped.SwitchState(this.GetType());
|
|
}
|
|
|
|
void OnDictChanged(Ped.SyncDictionaryStringUint.Operation op, string key, uint value)
|
|
{
|
|
// switch (op)
|
|
// {
|
|
// case Ped.SyncDictionaryStringUint.Operation.OP_ADD:
|
|
// case Ped.SyncDictionaryStringUint.Operation.OP_DIRTY:
|
|
// case Ped.SyncDictionaryStringUint.Operation.OP_SET:
|
|
// break;
|
|
// }
|
|
|
|
//Debug.LogFormat("OnDictChanged() - op: {0}, key: {1}, value: {2}", op, key, value);
|
|
|
|
if (!this.IsActiveState)
|
|
return;
|
|
|
|
if (key != kRollDirSyncName)
|
|
return;
|
|
|
|
F.RunExceptionSafe( () => {
|
|
if (m_ped.syncDictionaryStringUint.ContainsKey(key))
|
|
{
|
|
// roll direction possibly changed
|
|
m_rollLeft = m_ped.syncDictionaryStringUint[key] == 1;
|
|
//Debug.LogFormat("roll dir changed - old left: {0}, new left: {1}", oldLeft, m_rollLeft);
|
|
this.PlayAnim();
|
|
m_animState.time = 0f;
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
|
|
protected override void SwitchToMovementState ()
|
|
{
|
|
// don't switch to any state from here - we'll switch when anim finishes
|
|
}
|
|
|
|
protected override void SwitchToAimState ()
|
|
{
|
|
// don't switch to any state from here - we'll switch when anim finishes
|
|
}
|
|
|
|
|
|
protected override void UpdateHeading ()
|
|
{
|
|
if (m_isServer || m_ped.IsControlledByLocalPlayer)
|
|
m_ped.Heading = m_ped.transform.forward;
|
|
}
|
|
|
|
protected override void UpdateRotation ()
|
|
{
|
|
// don't change rotation
|
|
}
|
|
|
|
protected override void UpdateMovement ()
|
|
{
|
|
// adjust movement input before updating movement
|
|
// because only server performs moving, we'll do this only on server
|
|
|
|
// also, we should preserve movement input - this is needed because, if we exit roll state,
|
|
// we could quickly switch back to it, because we overrided client's movement input
|
|
|
|
Vector3 originalMovementInput = m_ped.Movement;
|
|
|
|
if (m_isServer)
|
|
m_ped.Movement = m_rollLeft ? -m_ped.transform.right : m_ped.transform.right;
|
|
|
|
base.UpdateMovement();
|
|
|
|
m_ped.Movement = originalMovementInput;
|
|
}
|
|
|
|
void PlayAnim()
|
|
{
|
|
m_animState = m_model.PlayAnim( this.movementAnim );
|
|
// clients have wrap mode set to 'Loop', because state can be switched very fast between roll and crouchaim, and
|
|
// server will not update current state syncvar, so client will not start the state again,
|
|
// and roll state will remain
|
|
m_animState.wrapMode = WrapMode.Once;
|
|
m_model.VelocityAxis = 0; // movement will be done along x axis
|
|
|
|
}
|
|
|
|
protected override void UpdateAnims ()
|
|
{
|
|
// correct local x position of root frame
|
|
Vector3 pos = m_model.RootFrame.transform.localPosition;
|
|
pos.x = 0f;
|
|
m_model.RootFrame.transform.localPosition = pos;
|
|
}
|
|
|
|
public override void LateUpdateState ()
|
|
{
|
|
base.LateUpdateState();
|
|
|
|
if( !this.IsActiveState )
|
|
return;
|
|
|
|
if (m_isServer)
|
|
{
|
|
// check if anim is finished
|
|
|
|
if( null == m_animState || !m_animState.enabled )
|
|
{
|
|
// anim finished
|
|
// switch to other state
|
|
|
|
// try to switch to crouch aim state
|
|
CrouchState.SwitchToAimState(m_ped);
|
|
if( !this.IsActiveState )
|
|
return;
|
|
|
|
// switch to crouch state
|
|
m_ped.SwitchState<CrouchState>();
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public override void OnSubmitPressed ()
|
|
{
|
|
// ignore
|
|
}
|
|
|
|
public override void OnJumpPressed ()
|
|
{
|
|
// ignore
|
|
}
|
|
|
|
public override void OnCrouchButtonPressed ()
|
|
{
|
|
// ignore
|
|
}
|
|
|
|
public override void OnFlyButtonPressed ()
|
|
{
|
|
// ignore
|
|
}
|
|
|
|
public override void OnFlyThroughButtonPressed ()
|
|
{
|
|
// ignore
|
|
}
|
|
|
|
}
|
|
|
|
}
|