Created
March 1, 2023 23:09
-
-
Save mrkybe/b086af5e9e80603e8d4e111689baf344 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Assets; | |
using Assets.Scripts; | |
using System.Collections; | |
using UnityEngine; | |
using Random = UnityEngine.Random; | |
public class PlayerController : EntController | |
{ | |
public static PlayerController Instance { get; private set; } | |
[SerializeField] | |
public GameObject ProjectilePrefab; | |
[SerializeField] | |
public AnimationClip _Idle; | |
[SerializeField] | |
public AnimationClip _Walk; | |
[SerializeField] | |
public AnimationClip _Run; | |
[SerializeField] | |
public AnimationClip _Jump; | |
[SerializeField] | |
public AnimationClip _JumpAttack; | |
[SerializeField] | |
public AnimationClip _Hurt; | |
[SerializeField] | |
public AnimationClip _Fall; | |
[SerializeField] | |
public AnimationClip _Basic_Attack_1; | |
[SerializeField] | |
public AnimationClip _Basic_Attack_2; | |
[SerializeField] | |
public AnimationClip _DashAttack; | |
[SerializeField] | |
public AnimationClip _Kick; | |
[SerializeField] | |
public AnimationClip _RoundHouseKick; | |
[SerializeField] | |
public AnimationClip _Smack; | |
[SerializeField] | |
public AnimationClip _Throw; | |
[SerializeField] | |
public AnimationClip _Thrust; | |
[SerializeField] | |
public AnimationClip _Dead; | |
[SerializeField] | |
public float MaxSprintEnergy = 1f; | |
[SerializeField] | |
public float SprintEnergy = 1f; | |
[SerializeField] | |
public float MovementSpeed = 1f; | |
[SerializeField] | |
public float SprintMultiplier = 2f; | |
public float RemainingSprintPercent { get => SprintEnergy / MaxSprintEnergy; } | |
public bool IsSprinting = false; | |
private Transform ReferenceTransform; | |
private Camera ReferenceCamera; | |
private DefaultControls controls; | |
private bool LockInDirection; | |
private Vector3 LockedDirection; | |
private bool CanCancelAttackIntoMovement = false; | |
private bool CanCancelAttackIntoNewAttack = false; | |
private bool WantToCancelAttack = false; | |
public CharHealth CharHealth; | |
[SerializeField] | |
private BoxCollider2D HitboxSword; | |
[SerializeField] | |
private LayerMask HitboxOnlyLayerMask; | |
protected new void Awake() | |
{ | |
base.Awake(); | |
CharHealth = GetComponent<CharHealth>(); | |
CharHealth.TookDamageEvent += MyHealth_TookDamageEvent; | |
CharHealth.DiedEvent += MyHealth_DiedEvent; | |
ZDepthOffset = 5; | |
if (Instance == null) | |
{ | |
Instance = this; | |
ReferenceTransform = Instance.transform; | |
} | |
else | |
{ | |
Debug.LogError("too many players", this); | |
} | |
HitboxSword.enabled = false; | |
CantMoveCauses.Add(() => { return IsFalling; }); | |
CantMoveCauses.Add(() => { return animController.IsPlaying(_Basic_Attack_1); }); | |
CantMoveCauses.Add(() => { return animController.IsPlaying(_Basic_Attack_2); }); | |
CantMoveCauses.Add(() => { return animController.IsPlaying(_Kick); }); | |
CantMoveCauses.Add(() => { return animController.IsPlaying(_RoundHouseKick); }); | |
CantMoveCauses.Add(() => { return animController.IsPlaying(_Smack); }); | |
CantMoveCauses.Add(() => { return animController.IsPlaying(_Throw); }); | |
CantMoveCauses.Add(() => { return animController.IsPlaying(_Thrust); }); | |
CantMoveCauses.Add(() => { return animController.IsPlaying(_Hurt); }); | |
CantMoveCauses.Add(() => { return animController.IsPlaying(_Fall); }); | |
CantMoveCauses.Add(() => { return animController.IsPlaying(_Dead); }); | |
IsAttackingCauses.Add(() => { return animController.IsPlaying(_Basic_Attack_1); }); | |
IsAttackingCauses.Add(() => { return animController.IsPlaying(_Basic_Attack_2); }); | |
IsAttackingCauses.Add(() => { return animController.IsPlaying(_Kick); }); | |
IsAttackingCauses.Add(() => { return animController.IsPlaying(_RoundHouseKick); }); | |
IsAttackingCauses.Add(() => { return animController.IsPlaying(_Smack); }); | |
IsAttackingCauses.Add(() => { return animController.IsPlaying(_Throw); }); | |
IsAttackingCauses.Add(() => { return animController.IsPlaying(_Thrust); }); | |
IsAttackingCauses.Add(() => { return animController.IsPlaying(_DashAttack); }); | |
IsMovingOrIdleCauses.Add(() => { return animController.IsPlaying(_Idle); }); | |
IsMovingOrIdleCauses.Add(() => { return animController.IsPlaying(_Run); }); | |
IsMovingOrIdleCauses.Add(() => { return animController.IsPlaying(_Walk); }); | |
} | |
private void CharHealth_DiedEvent(object sender, CharHealth.DiedArgs e) | |
{ | |
throw new System.NotImplementedException(); | |
} | |
private void Start() | |
{ | |
if (ReferenceCamera == null || ReferenceTransform == null) | |
{ | |
ReferenceCamera = Camera.main; | |
ReferenceTransform = Instance.transform; | |
} | |
controls = ControlFreak.Controls; | |
controls.Player.Sprint.started += Sprint_started; | |
controls.Player.Sprint.canceled += Sprint_canceled; | |
controls.Player.Movement.started += Movement_started; | |
controls.Player.Movement.canceled += Movement_canceled; | |
controls.Player.BasicAttack.performed += BasicAttack_performed; | |
controls.Player.StrongAttack.performed += StrongAttack_performed; | |
controls.Player.KickAttack.performed += KickAttack_performed; | |
controls.Player.ThrowAttack.performed += ThrowAttack_performed; | |
} | |
protected new void Update() | |
{ | |
base.Update(); | |
UpdateAnimator(); | |
} | |
private void CanOrCantCancelIntoMovement(AnimationEvent e) | |
{ | |
if (e.stringParameter == "CanCancel") | |
{ | |
CanCancelAttackIntoMovement = true; | |
} | |
if (e.stringParameter == "CantCancel") | |
{ | |
CanCancelAttackIntoMovement = false; | |
} | |
} | |
protected override void ApplyMovementAndAttacks() | |
{ | |
if (CanMove) | |
{ | |
if (moveDirection != Vector2.zero || (LockInDirection && LockedDirection != Vector3.zero)) | |
{ | |
if (LockInDirection) | |
{ | |
rb.velocity = LockedDirection * MovementSpeed * (IsSprinting ? SprintMultiplier : 1f); | |
SetFlipMode(FlipMode.Velocity); | |
} | |
else | |
{ | |
rb.velocity = moveDirection * MovementSpeed * (IsSprinting ? SprintMultiplier : 1f); | |
SetFlipMode(FlipMode.MovementDirection); | |
} | |
} | |
else | |
{ | |
rb.drag = 20f; | |
} | |
} | |
else | |
{ | |
rb.drag = IsFalling ? 0f : 10f; | |
} | |
if (WantToCancelAttack && CanCancelAttackIntoMovement) | |
{ | |
WantToCancelAttack = false; | |
MovementState(true); | |
} | |
if (InputState.BasicAttackPressed && !IsSprinting) | |
{ | |
if (!animController.IsPlaying(_Basic_Attack_1) && !animController.IsPlaying(_Basic_Attack_2) && !IsAttacking) | |
{ | |
PlayAnimation(Random.value > 0.5f ? _Basic_Attack_1 : _Basic_Attack_2); | |
InputState.MovementKeyWasCancelled = InputState.MovementKeyPressed || InputState.MovementKeyWasCancelled; | |
InputState.MovementKeyPressed = false; | |
LockFlipMode(); | |
_EventReceiver.OnEvent.Set(animState, CanOrCantCancelIntoMovement); | |
CanCancelAttackIntoMovement = true; | |
animState.Events.OnEnd = ExitBasicAttack; | |
} | |
else if (animController.IsPlaying(_Basic_Attack_1)) | |
{ | |
InputState.MovementKeyWasCancelled = InputState.MovementKeyPressed || InputState.MovementKeyWasCancelled; | |
InputState.MovementKeyPressed = false; | |
animState.Events.OnEnd = () => | |
{ | |
PlayAnimation(_Basic_Attack_2); | |
LockFlipMode(); | |
InputState.MovementKeyWasCancelled = InputState.MovementKeyPressed || InputState.MovementKeyWasCancelled; | |
InputState.MovementKeyPressed = false; | |
CanCancelAttackIntoMovement = true; | |
_EventReceiver.OnEvent.Set(animState, CanOrCantCancelIntoMovement); | |
animState.Events.OnEnd = ExitBasicAttack; | |
}; | |
} | |
else if (animController.IsPlaying(_Basic_Attack_2)) | |
{ | |
InputState.MovementKeyWasCancelled = InputState.MovementKeyPressed || InputState.MovementKeyWasCancelled; | |
InputState.MovementKeyPressed = false; | |
animState.Events.OnEnd = () => | |
{ | |
PlayAnimation(_Basic_Attack_1); | |
LockFlipMode(); | |
InputState.MovementKeyWasCancelled = InputState.MovementKeyPressed || InputState.MovementKeyWasCancelled; | |
InputState.MovementKeyPressed = false; | |
CanCancelAttackIntoMovement = true; | |
_EventReceiver.OnEvent.Set(animState, CanOrCantCancelIntoMovement); | |
animState.Events.OnEnd = ExitBasicAttack; | |
}; | |
} | |
else if (IsAttacking) | |
{ | |
animState.Events.OnEnd = () => | |
{ | |
ChainAttackAnimation(Random.value > 0.5f ? _Basic_Attack_1 : _Basic_Attack_2); | |
InputState.MovementKeyWasCancelled = InputState.MovementKeyPressed || InputState.MovementKeyWasCancelled; | |
InputState.MovementKeyPressed = false; | |
_EventReceiver.OnEvent.Set(animState, CanOrCantCancelIntoMovement); | |
CanCancelAttackIntoMovement = true; | |
animState.Events.OnEnd = ExitBasicAttack; | |
}; | |
} | |
InputState.BasicAttackPressed = false; | |
return; | |
} | |
else if (InputState.BasicAttackPressed && IsSprinting && moveDirection != Vector2.zero) | |
{ | |
if (!animController.IsPlaying(_DashAttack) && !IsAttacking) | |
{ | |
PlayAnimation(_DashAttack); | |
InputState.MovementKeyWasCancelled = InputState.MovementKeyPressed || InputState.MovementKeyWasCancelled; | |
InputState.MovementKeyPressed = false; | |
LockInDirection = true; | |
LockedDirection = InputState.MovementDirection; | |
SprintEnergy = MaxSprintEnergy; | |
_EventReceiver.OnEvent.Set(animState, CanOrCantCancelIntoMovement); | |
CanCancelAttackIntoMovement = false; | |
InterruptCurrentAnimationCallback = ExitDashAttack; | |
animState.Events.OnEnd = ExitDashAttack; | |
} | |
InputState.BasicAttackPressed = false; | |
return; | |
} | |
if (InputState.StrongAttackPressed) | |
{ | |
if (!animController.IsPlaying(_Thrust) && !IsAttacking) | |
{ | |
PlayAnimation(_Thrust); | |
InputState.MovementKeyWasCancelled = InputState.MovementKeyPressed || InputState.MovementKeyWasCancelled; | |
InputState.MovementKeyPressed = false; | |
_EventReceiver.OnEvent.Set(animState, CanOrCantCancelIntoMovement); | |
CanCancelAttackIntoMovement = false; | |
animState.Events.OnEnd = ExitBasicAttack; | |
} | |
else if (IsAttacking) | |
{ | |
InputState.MovementKeyWasCancelled = InputState.MovementKeyPressed || InputState.MovementKeyWasCancelled; | |
InputState.MovementKeyPressed = false; | |
animState.Events.OnEnd = () => | |
{ | |
ChainAttackAnimation(_Thrust); | |
InputState.MovementKeyWasCancelled = InputState.MovementKeyPressed || InputState.MovementKeyWasCancelled; | |
InputState.MovementKeyPressed = false; | |
_EventReceiver.OnEvent.Set(animState, CanOrCantCancelIntoMovement); | |
animState.Events.OnEnd = ExitBasicAttack; | |
}; | |
} | |
InputState.StrongAttackPressed = false; | |
return; | |
} | |
if (InputState.KickAttackPressed) | |
{ | |
if (!animController.IsPlaying(_Kick) && !IsAttacking) | |
{ | |
PlayAnimation(_Kick); | |
InputState.MovementKeyWasCancelled = InputState.MovementKeyPressed || InputState.MovementKeyWasCancelled; | |
InputState.MovementKeyPressed = false; | |
_EventReceiver.OnEvent.Set(animState, CanOrCantCancelIntoMovement); | |
CanCancelAttackIntoMovement = false; | |
animState.Events.OnEnd = ExitBasicAttack; | |
} | |
else if (IsAttacking) | |
{ | |
InputState.MovementKeyWasCancelled = InputState.MovementKeyPressed || InputState.MovementKeyWasCancelled; | |
InputState.MovementKeyPressed = false; | |
animState.Events.OnEnd = () => | |
{ | |
ChainAttackAnimation(_Kick); | |
InputState.MovementKeyWasCancelled = InputState.MovementKeyPressed || InputState.MovementKeyWasCancelled; | |
InputState.MovementKeyPressed = false; | |
_EventReceiver.OnEvent.Set(animState, CanOrCantCancelIntoMovement); | |
animState.Events.OnEnd = ExitBasicAttack; | |
}; | |
} | |
InputState.KickAttackPressed = false; | |
return; | |
} | |
if (InputState.ThrowAttackPressed) | |
{ | |
if (!animController.IsPlaying(_Throw) && !IsAttacking) | |
{ | |
PlayAnimation(_Throw); | |
LockFlipMode(); | |
InputState.MovementKeyWasCancelled = InputState.MovementKeyPressed || InputState.MovementKeyWasCancelled; | |
InputState.MovementKeyPressed = false; | |
_EventReceiver.OnEvent.Set(animState, CanOrCantCancelIntoMovement); | |
CanCancelAttackIntoMovement = false; | |
CanCancelAttackIntoNewAttack = false; | |
ThrowAttack(); | |
} | |
else if (IsAttacking) | |
{ | |
InputState.MovementKeyWasCancelled = InputState.MovementKeyPressed || InputState.MovementKeyWasCancelled; | |
InputState.MovementKeyPressed = false; | |
animState.Events.OnEnd = () => | |
{ | |
PlayAnimation(_Throw, resetIfAlreadyPlaying: true); | |
LockFlipMode(); | |
InputState.MovementKeyWasCancelled = InputState.MovementKeyPressed || InputState.MovementKeyWasCancelled; | |
InputState.MovementKeyPressed = false; | |
_EventReceiver.OnEvent.Set(animState, CanOrCantCancelIntoMovement); | |
CanCancelAttackIntoMovement = false; | |
CanCancelAttackIntoNewAttack = false; | |
ThrowAttack(); | |
}; | |
} | |
InputState.ThrowAttackPressed = false; | |
return; | |
} | |
} | |
private void ThrowAttack() | |
{ | |
var throwTrigger = new Animancer.AnimancerEvent { normalizedTime = 0.5f }; | |
throwTrigger.callback = () => | |
{ | |
var go = Instantiate(ProjectilePrefab, transform.position, Quaternion.identity); | |
var projectile = go.GetComponent<Projectile>(); | |
var dmgBox = go.GetComponentInChildren<DamageBox>(); | |
dmgBox.OwnerController = this; | |
dmgBox.OwnerHealth = CharHealth; | |
projectile.Velocity = new Vector2(transform.localScale.x, 0) * 4f; | |
}; | |
animState.Events.Add(throwTrigger); | |
animState.Events.OnEnd = () => | |
{ | |
ExitBasicAttack(); | |
}; | |
} | |
private void ChainAttackAnimation(AnimationClip animation) | |
{ | |
PlayAnimation(animation); | |
LockFlipMode(); | |
} | |
private void ExitDashAttack() | |
{ | |
if (InterruptCurrentAnimationCallback == ExitDashAttack) | |
{ | |
InterruptCurrentAnimationCallback = null; | |
} | |
LockInDirection = false; | |
LockedDirection = Vector3.zero; | |
SprintEnergy = 0f; Debug.Log("On End"); | |
UnlockFlipMode(); | |
MovementState(true); | |
} | |
private void ExitBasicAttack() | |
{ | |
UnlockFlipMode(); | |
MovementState(true); | |
} | |
protected override void GetMovementAndAttacksInput() | |
{ | |
InputState.MovementDirection = controls.Player.Movement.ReadValue<Vector2>(); | |
moveDirection = Vector2.zero; | |
if (InputState.MovementKeyPressed && CanCancelAttackIntoMovement && WantToCancelAttack && IsAttacking) | |
{ | |
MovementState(); | |
} | |
if (InputState.MovementKeyPressed && !InputState.MovementKeyWasCancelled) | |
{ | |
moveDirection = InputState.MovementDirection; | |
rb.drag = 0f; | |
} | |
if (IsSprinting && moveDirection.sqrMagnitude > 0.1f) | |
{ | |
SprintEnergy -= Time.deltaTime; | |
if (SprintEnergy <= 0) | |
{ | |
IsSprinting = false; | |
} | |
} | |
else | |
{ | |
if (SprintEnergy < MaxSprintEnergy) | |
{ | |
SprintEnergy += Time.deltaTime / 2f; | |
} | |
} | |
} | |
protected new void UpdateAnimator() | |
{ | |
base.UpdateAnimator(); | |
if (CanMove && !IsAttacking) | |
{ | |
MovementState(); | |
} | |
} | |
private void MovementState(bool FinishedAttack = false) | |
{ | |
CanCancelAttackIntoMovement = true; | |
if (InputState.MovementKeyWasCancelled) | |
{ | |
InputState.MovementKeyPressed = true; | |
InputState.MovementKeyWasCancelled = false; | |
} | |
if ((!IsAttacking || FinishedAttack) && CharHealth.IsAlive) | |
{ | |
WantToCancelAttack = false; | |
if (moveDirection.magnitude < 0.1f) | |
{ | |
PlayAnimation(_Idle); | |
} | |
else | |
{ | |
if (IsSprinting) | |
{ | |
PlayAnimation(_Run); | |
_EventReceiver.OnEvent.Set(animState, FootstepSounds); | |
} | |
else | |
{ | |
PlayAnimation(_Walk); | |
_EventReceiver.OnEvent.Set(animState, FootstepSounds); | |
} | |
} | |
} | |
} | |
private void FootstepSounds(AnimationEvent e) | |
{ | |
if (e.stringParameter == "Step") | |
{ | |
GetComponent<AudioSource>().PlayOneShot(Common.FootstepSounds.Random()); | |
} | |
} | |
protected override void MyHealth_TookDamageEvent(object sender, CharHealth.TookDamageArgs e) | |
{ | |
if (!animController.IsPlaying(_Hurt) && CharHealth.IsAlive) | |
{ | |
if (animController.IsPlaying(_DashAttack)) | |
{ | |
ExitDashAttack(); | |
} | |
var state = PlayAnimation(_Hurt); | |
Debug.Log(e.Message); | |
CanCancelAttackIntoMovement = false; | |
CanCancelAttackIntoNewAttack = false; | |
state.Events.OnEnd = () => | |
{ | |
AnimationPriorityLevel = 0; | |
MovementState(true); | |
}; | |
} | |
} | |
protected override void MyHealth_DiedEvent(object sender, CharHealth.DiedArgs e) | |
{ | |
controls.Disable(); | |
Debug.Log(e.Message); | |
AnimationPriorityLevel = 10; | |
if (e.Fatality.DamageSource.GetType() != typeof(FallingDamage)) | |
{ | |
var state = PlayAnimation(_Fall); | |
state.Events.OnEnd = () => | |
{ | |
PlayAnimation(_Dead); | |
var feet = transform.root.GetComponent<CircleCollider2D>(); | |
feet.enabled = false; | |
CharHealth.TookDamageEvent -= MyHealth_TookDamageEvent; | |
CharHealth.DiedEvent -= MyHealth_DiedEvent; | |
Destroy(CharHealth); | |
ZDepthOffset = -10; | |
}; | |
} | |
else | |
{ | |
PlayAnimation(_Fall, 0f, true); | |
Debug.Log(rb.velocity); | |
StartCoroutine(SwitchFallAnimationOnNegativeYVelocity()); | |
} | |
} | |
private IEnumerator SwitchFallAnimationOnNegativeYVelocity() | |
{ | |
Transform spriteChild = transform.GetChild(0); | |
spriteChild.localPosition -= new Vector3(0, 0.167f, 0); | |
transform.position += new Vector3(0, 0.167f, 0); | |
Debug.Log("falling coroutine"); | |
rb.constraints = new RigidbodyConstraints2D { }; | |
rb.angularVelocity = Mathf.Sign(rb.velocity.x) * (Random.value + 0.5f) * 200f; | |
yield return new WaitForFixedUpdate(); | |
yield return new WaitForFixedUpdate(); | |
yield return new WaitForFixedUpdate(); | |
while (rb.velocity.y > 0) | |
{ | |
Debug.Log(rb.velocity.y.ToString("00.0000")); | |
yield return new WaitForFixedUpdate(); | |
} | |
var state = PlayAnimation(_Fall, 0f, true); | |
state.NormalizedTime = 1f; | |
} | |
private void Sprint_started(UnityEngine.InputSystem.InputAction.CallbackContext obj) | |
{ | |
InputState.SprintPressed = true; | |
IsSprinting = true; | |
} | |
private void Sprint_canceled(UnityEngine.InputSystem.InputAction.CallbackContext obj) | |
{ | |
InputState.SprintPressed = false; | |
IsSprinting = false; | |
} | |
private void Movement_started(UnityEngine.InputSystem.InputAction.CallbackContext obj) | |
{ | |
InputState.MovementKeyPressed = true; | |
InputState.MovementKeyWasCancelled = false; | |
if (IsAttacking) | |
{ | |
WantToCancelAttack = true; | |
} | |
} | |
private void Movement_canceled(UnityEngine.InputSystem.InputAction.CallbackContext obj) | |
{ | |
InputState.MovementKeyPressed = false; | |
InputState.MovementKeyWasCancelled = false; | |
WantToCancelAttack = false; | |
} | |
private void BasicAttack_performed(UnityEngine.InputSystem.InputAction.CallbackContext obj) | |
{ | |
InputState.BasicAttackPressed = true; | |
} | |
private void StrongAttack_performed(UnityEngine.InputSystem.InputAction.CallbackContext obj) | |
{ | |
InputState.StrongAttackPressed = true; | |
} | |
private void KickAttack_performed(UnityEngine.InputSystem.InputAction.CallbackContext obj) | |
{ | |
InputState.KickAttackPressed = true; | |
} | |
private void ThrowAttack_performed(UnityEngine.InputSystem.InputAction.CallbackContext obj) | |
{ | |
InputState.ThrowAttackPressed = true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment