Created
November 18, 2025 14:09
-
-
Save mrkybe/b0be172de271d902c2730b9319c34609 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 BehaviorDesigner.Runtime; | |
| using BehaviorDesigner.Runtime.Tasks; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| using UnityEngine; | |
| public class MobController : EntController | |
| { | |
| [SerializeField] | |
| public float MovementSpeed; | |
| [SerializeField] | |
| public AnimationClip _Idle; | |
| [SerializeField] | |
| public AnimationClip _Walk; | |
| [SerializeField] | |
| public AnimationClip _Hurt; | |
| [SerializeField] | |
| public AnimationClip _Fall; | |
| [SerializeField] | |
| public AnimationClip _GetUp; | |
| [SerializeField] | |
| public AnimationClip _KnockedOver; | |
| [SerializeField] | |
| public AnimationClip _Attack; | |
| [SerializeField] | |
| public AnimationClip _Dead; | |
| private BehaviorTree bTree; | |
| private CharHealth myHealth; | |
| private SharedVector2 AI_MovementInput; | |
| private SharedFloat AI_MovementSpeedInput; | |
| private SharedBool AI_AttackPressed; | |
| private new void Awake() | |
| { | |
| base.Awake(); | |
| bTree = GetComponent<BehaviorTree>(); | |
| myHealth = GetComponent<CharHealth>(); | |
| DamageBoxesThatHit = new HashSet<DamageBox>(); | |
| CantMoveCauses.Add(() => { return IsFalling; }); | |
| CantMoveCauses.Add(() => { return animController.IsPlaying(_Attack); }); | |
| CantMoveCauses.Add(() => { return animController.IsPlaying(_Hurt); }); | |
| CantMoveCauses.Add(() => { return animController.IsPlaying(_Fall); }); | |
| CantMoveCauses.Add(() => { return animController.IsPlaying(_GetUp); }); | |
| CantMoveCauses.Add(() => { return animController.IsPlaying(_KnockedOver); }); | |
| CantMoveCauses.Add(() => { return myHealth.IsAlive == false; }); | |
| CantAttackCauses.Add(() => { return IsFalling; }); | |
| CantAttackCauses.Add(() => { return animController.IsPlaying(_Hurt); }); | |
| CantAttackCauses.Add(() => { return animController.IsPlaying(_Fall); }); | |
| CantAttackCauses.Add(() => { return animController.IsPlaying(_GetUp); }); | |
| CantAttackCauses.Add(() => { return animController.IsPlaying(_KnockedOver); }); | |
| IsAttackingCauses.Add(() => { return animController.IsPlaying(_Attack); }); | |
| IsMovingOrIdleCauses.Add(() => { return animController.IsPlaying(_Idle); }); | |
| IsMovingOrIdleCauses.Add(() => { return animController.IsPlaying(_Walk); }); | |
| AI_MovementInput = (SharedVector2)bTree.GetVariable(nameof(AI_MovementInput)); | |
| AI_MovementSpeedInput = (SharedFloat)bTree.GetVariable(nameof(AI_MovementSpeedInput)); | |
| AI_AttackPressed = (SharedBool)bTree.GetVariable(nameof(AI_AttackPressed)); | |
| myHealth.TookDamageEvent += MyHealth_TookDamageEvent; | |
| myHealth.DiedEvent += MyHealth_DiedEvent; | |
| } | |
| private void Start() | |
| { | |
| LevelController.Instance.Register(this); | |
| } | |
| private int HurtCombo = 0; | |
| protected override void MyHealth_TookDamageEvent(object sender, CharHealth.TookDamageArgs e) | |
| { | |
| Debug.Log(e.Message); | |
| HurtCombo++; | |
| if (HurtCombo == 1) | |
| { | |
| if (AnimationPriorityLevel < 2) | |
| { | |
| AnimationPriorityLevel = 2; | |
| var state = PlayAnimation(_Hurt); | |
| LockFlipMode(); | |
| state.Events.OnEnd = () => | |
| { | |
| HurtCombo = 0; | |
| AnimationPriorityLevel = 0; | |
| MovementState(true); | |
| UnlockFlipMode(); | |
| }; | |
| } | |
| } | |
| if (HurtCombo >= 2) | |
| { | |
| if (animController.IsPlaying(_Hurt) && e.DamageSource.MonoBehavior.GetType() == typeof(DamageBox)) | |
| { | |
| DamageBox dmgBox = (DamageBox)e.DamageSource.MonoBehavior; | |
| var dmgDir = (transform.position.XY() - dmgBox.transform.root.position.XY()).normalized; | |
| rb.AddForce(dmgDir * 40); | |
| if (HurtCombo == 2) | |
| { | |
| var state = PlayAnimation(_Hurt, resetIfAlreadyPlaying: true); | |
| state.Events.OnEnd = () => | |
| { | |
| HurtCombo = 0; | |
| AnimationPriorityLevel = 0; | |
| MovementState(true); | |
| UnlockFlipMode(); | |
| }; | |
| } | |
| } | |
| } | |
| if (HurtCombo == 3) | |
| { | |
| AnimationPriorityLevel = 3; | |
| var state = PlayAnimation(_Fall); | |
| LockFlipMode(); | |
| rb.drag = 0f; | |
| state.Events.OnEnd = () => | |
| { | |
| rb.drag = 20f; | |
| var state2 = PlayAnimation(_KnockedOver); | |
| state2.Events.OnEnd = () => | |
| { | |
| var state3 = PlayAnimation(_GetUp); | |
| state3.Events.OnEnd = () => | |
| { | |
| rb.isKinematic = false; | |
| HurtCombo = 0; | |
| AnimationPriorityLevel = 0; | |
| MovementState(true); | |
| UnlockFlipMode(); | |
| }; | |
| }; | |
| }; | |
| } | |
| } | |
| protected override void ApplyMovementAndAttacks() | |
| { | |
| if (CanMove) | |
| { | |
| if (moveDirection != Vector2.zero) | |
| { | |
| rb.velocity = moveDirection * MovementSpeed * 1f; | |
| } | |
| else | |
| { | |
| rb.drag = 20f; | |
| } | |
| } | |
| } | |
| private HashSet<DamageBox> DamageBoxesThatHit; | |
| private bool AttackWasInterrupted = false; | |
| public bool StartBasicAttack(Attack action) | |
| { | |
| if (!animController.IsPlaying(_Attack) && !IsAttacking && !CantAttack) | |
| { | |
| PlayAnimation(_Attack); | |
| DamageBoxesThatHit.Clear(); | |
| AttackWasInterrupted = false; | |
| LockFlipMode(); | |
| InterruptCurrentAnimationCallback = () => | |
| { | |
| AttackWasInterrupted = true; | |
| animState.Events.OnEnd(); | |
| }; | |
| animState.Events.OnEnd = () => | |
| { | |
| InterruptCurrentAnimationCallback = null; | |
| if (DamageBoxesThatHit.Any()) | |
| { | |
| action.Done(Attack.AttackResult.HIT); | |
| } | |
| else if (AttackWasInterrupted) | |
| { | |
| action.Done(Attack.AttackResult.INTERRUPTED); | |
| } | |
| else | |
| { | |
| action.Done(Attack.AttackResult.MISSED); | |
| } | |
| UnlockFlipMode(); | |
| MovementState(true); | |
| AttackWasInterrupted = false; | |
| }; | |
| return true; | |
| } | |
| action.Done(Attack.AttackResult.DIDNT_START); | |
| return false; | |
| } | |
| protected new void Update() | |
| { | |
| base.Update(); | |
| UpdateAnimator(); | |
| MovementSpeed = AI_MovementSpeedInput.Value; | |
| } | |
| protected new void UpdateAnimator() | |
| { | |
| if (myHealth.IsAlive) | |
| { | |
| base.UpdateAnimator(); | |
| if (flipMode == FlipMode.NearestEnemy) | |
| { | |
| float a = Mathf.Sign(transform.position.x - PlayerController.Instance.transform.position.x); | |
| transform.localScale = new Vector3(-a, 1, 1); | |
| } | |
| else if (flipMode == FlipMode.Velocity) | |
| { | |
| transform.localScale = new Vector3(Mathf.Sign(rb.velocity.x), 1, 1); | |
| } | |
| if (CanMove) | |
| { | |
| MovementState(); | |
| } | |
| } | |
| } | |
| private void MovementState(bool FinishedAttack = false) | |
| { | |
| if (!IsAttacking || FinishedAttack) | |
| { | |
| if (moveDirection.magnitude < 0.1f) | |
| { | |
| PlayAnimation(_Idle); | |
| } | |
| else | |
| { | |
| if (flipMode == FlipMode.MovementDirection) | |
| { | |
| PlayAnimation(_Walk); | |
| } | |
| else | |
| { | |
| if (moveDirection.x > 0 && transform.localScale.x > 0 || moveDirection.x < 0 && transform.localScale.x < 0) | |
| { | |
| PlayAnimation(_Walk, -1f); | |
| } | |
| else | |
| { | |
| PlayAnimation(_Walk, 1f); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| protected override void GetMovementAndAttacksInput() | |
| { | |
| moveDirection = AI_MovementInput.Value; | |
| } | |
| protected override void MyHealth_DiedEvent(object sender, CharHealth.DiedArgs e) | |
| { | |
| AnimationPriorityLevel = 10; | |
| AIAttackPermissionCoordinator.Instance.FreeAcquiredPositions(this); | |
| var state = PlayAnimation(_Fall); | |
| bTree.DisableBehavior(); | |
| Debug.Log(e.Message); | |
| state.Events.OnEnd = () => | |
| { | |
| PlayAnimation(_Dead); | |
| var feet = transform.root.GetComponent<CircleCollider2D>(); | |
| feet.enabled = false; | |
| myHealth.TookDamageEvent -= MyHealth_TookDamageEvent; | |
| myHealth.DiedEvent -= MyHealth_DiedEvent; | |
| Destroy(myHealth); | |
| rb.isKinematic = true; | |
| rb.velocity = Vector2.zero; | |
| ZDepthOffset = -10; | |
| }; | |
| } | |
| public override void RegisterDamageBoxEnabled(DamageBox dmgBox) | |
| { | |
| base.RegisterDamageBoxEnabled(dmgBox); | |
| dmgBox.DidDamageEvent += DmgBox_DidDamageEvent; | |
| } | |
| private void DmgBox_DidDamageEvent(object sender, DamageBox.DidDamageArgs e) | |
| { | |
| Debug.Log("damage box did damage"); | |
| DamageBoxesThatHit.Add((DamageBox)sender); | |
| } | |
| public override void RegisterDamageBoxDisabled(DamageBox dmgBox) | |
| { | |
| base.RegisterDamageBoxDisabled(dmgBox); | |
| dmgBox.DidDamageEvent -= DmgBox_DidDamageEvent; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment