using System.Collections; using System.Collections.Generic; using Com.LuisPedroFonseca.ProCamera2D; using UnityEngine; using UnityEngine.SceneManagement; public class PlayerMovement : MonoBehaviour { public CharacterController2D controller; public PlayerAnimationController animator; public GameObject levelUpEffect; public GameObject deathEffect; public GameObject jumpEffect; public GameObject doubleJumpEffect; public GameObject wallKickEffect; public GameObject doubleJumpUpEffect; public GameObject jumpDownEffect; public GameObject landEffect; public GameObject dashEffect; public GameObject hitboxDashAttack; public GameObject attackEffect; public GameObject hitboxBasicAttack; public GameObject executionEffect; public GameObject executionChargeEffect; public GameObject hitboxExecution; public GameObject stunningStrikeEffect; public GameObject hitboxStunningStrike; public GameObject arrowBarrageEffect; public GameObject arrowBarrageChargeEffect; public GameObject hitboxSpawnerArrowBarrage; public GameObject blowbackEffect; public GameObject hitboxBlowback; [SerializeField] public Transform dashCheckPosition; [SerializeField] public Vector2 dashCollisionCheckSize; [SerializeField] public Transform wallCheckPositionRight; [SerializeField] public Vector2 wallCheckSize; [SerializeField] public Transform damageText; [SerializeField] public AudioClip hurtAudioClip; [SerializeField] public Renderer renderer; public float damageTextTransposeX; public float damageTextTransposeY; public float hurtSpeed = 5f; public float runSpeed = 40f; public float dashDistance = 80f; public Vector2 blowbackForce; public float attackDelay = 0.25f; public float dashDelay = 0.25f; public float pickupRange = 5f; public float delayStunningStrike = 0.3f; public float delayArrowBarrage = 0.6f; public float delayArrowBarrageAttack = 0.6f; public float delayExecution = 0.5f; public float delayExecutionAttack = 0.5f; public float delayBlowback = 0.25f; public float delayJudgment = 1.5f; public Vector2 dashForce = Vector2.zero; public Vector2 wallKickForce = Vector2.zero; public float invincibilityTime = 1.5f; public float deathAnimationTime = 1.25f; float horizontalMove = 0f; bool jump = false; bool attack = false; bool dash = false; bool isFrozen = false; public bool cutscene = false; public bool alreadyJumpedDown = false; public bool alreadyDoubleJumped = false; public bool alreadyBlowbackShot = false; public bool alreadyKicked = false; public bool invincible = false; // Stunning Strike variant of Execution. // Lazy flag so Stunning Strike doesn't need additional choreography... // TODO: Don't do this. public bool stunningStrikeVariant = false; // You can only execute one action/attack/skill at a time. bool busy = false; private static readonly Hashtable isOnCooldownMap = new Hashtable() { { SkillID.BASIC_ATTACK, false }, { SkillID.EXECUTION, false }, { SkillID.DOUBLE_JUMP, false }, { SkillID.BLOWBACK_SHOT, false }, { SkillID.LIGHTNING_DASH, false }, { SkillID.ARROW_BARRAGE, false }, { SkillID.STUNNING_STRIKE, false }, }; private Dictionary inRangeNpcs = new Dictionary(); private Dictionary inRangeUtilityNpcs = new Dictionary(); // Update is called once per frame void Update () { if (cutscene) { // Player gets no control. horizontalMove = 0.0f; animator.Broadcast("Speed", Mathf.Abs(horizontalMove)); return; } if (!busy) { horizontalMove = Input.GetAxisRaw("Horizontal") * runSpeed; } else { horizontalMove = 0.0f; } if (Input.GetButtonDown("Jump") && !attack && !busy) { OnJumpStart(); } if (Input.GetButtonDown("Fire1") && !attack && !busy && !(bool)isOnCooldownMap[SkillID.BASIC_ATTACK] && State.state.skillState.CheckSkillLevel(SkillID.BASIC_ATTACK, 1)) { OnAttackStart(); } //if (Input.GetButtonDown("Fire1") && // !attack && !busy && // !(bool)isOnCooldownMap[SkillID.STUNNING_STRIKE] && // State.state.skillState.CheckSkillLevel(SkillID.STUNNING_STRIKE, 1)) { // OnStunningStrikeStart(); //} if (Input.GetButtonDown("Fire3") && !attack && !dash && !busy && controller.m_Grounded && !(bool)isOnCooldownMap[SkillID.LIGHTNING_DASH] && State.state.skillState.CheckSkillLevel(SkillID.LIGHTNING_DASH, 1) && CheckDashAreaEmpty()) { OnDashStart(); } animator.Broadcast("isFalling", controller.m_Rigidbody2D.velocity.y < -0.01f); animator.Broadcast("Speed", Mathf.Abs(horizontalMove)); // Doublejump or Jumpdown if (Input.GetButtonDown("Fire2")) { if (!attack && !dash && !busy && !controller.m_Grounded && State.state.skillState.CheckSkillLevel(SkillID.DOUBLE_JUMP, 1)) { float inputY = Input.GetAxisRaw("Vertical"); if (inputY < -0.01f && !alreadyJumpedDown) { OnJumpDownStart(); } else if (inputY > -0.01f && !alreadyDoubleJumped) { OnDoubleJumpStart(inputY > 0.01f) ; } } } if (Input.GetButtonDown("Fire4") && !attack && !dash && !busy && !controller.m_Grounded && !alreadyBlowbackShot && !(bool)isOnCooldownMap[SkillID.BLOWBACK_SHOT] && State.state.skillState.CheckSkillLevel(SkillID.BLOWBACK_SHOT, 1)) { OnBlowbackShotStart(); } if (Input.GetButtonDown("Fire5") && !attack && !dash && !busy && !(bool)isOnCooldownMap[SkillID.EXECUTION] && State.state.skillState.CheckSkillLevel(SkillID.EXECUTION, 1)) { OnExecutionStart(); } if (Input.GetButtonDown("Fire6") && !attack && !dash && !busy && !controller.m_Grounded) { if (CheckWallKick()) { WallKick(); } } if (Input.GetButtonDown("Fire7") && !attack && !dash && !busy && controller.m_Grounded && !(bool)isOnCooldownMap[SkillID.ARROW_BARRAGE] && State.state.skillState.CheckSkillLevel(SkillID.ARROW_BARRAGE, 1)) { OnArrowBarrageStart(); } if (Input.GetButtonDown("Pickup") && !busy) { TryPickup(); } if (Input.GetButtonDown("Interact") && !busy && !cutscene && inRangeNpcs.Count > 0) { float distance = float.MaxValue; GameObject choice = null; foreach (KeyValuePair npcPair in inRangeNpcs) { float npcDistance = Vector3.Distance(transform.position, npcPair.Value.transform.position); if (npcDistance < distance) { choice = npcPair.Value; } Debug.Log(npcPair.Key.ToString() + " = choice"); } cutscene = true; choice.GetComponent().parentController.Interact(); } if (Input.GetButtonDown("Utility") && !busy && !cutscene && inRangeUtilityNpcs.Count > 0) { float distance = float.MaxValue; GameObject choice = null; foreach (KeyValuePair npcPair in inRangeUtilityNpcs) { float npcDistance = Vector3.Distance(transform.position, npcPair.Value.transform.position); if (npcDistance < distance) { choice = npcPair.Value; } Debug.Log(npcPair.Key.ToString() + " = choice"); } cutscene = true; choice.GetComponent().parentController.UtilityInteract(); } } public void Aberrate() { StartCoroutine(AberrateDown()); } public IEnumerator AberrateDown() { float amount = 1f; float time = 0.25f; // seconds while (amount > 0f) { Debug.Log("Aberrating amount " + amount.ToString()); renderer.material.SetFloat("_ChromAberrAmount", amount); yield return new WaitForSeconds(0.1f); amount -= 0.1f / time; } renderer.material.SetFloat("_ChromAberrAmount", 0f); } public void TriggerCollision(Collider2D other) { // Retrigger enter in case the NPC is newly a utility NPC. OnTriggerEnter2D(other); } void OnTriggerEnter2D(Collider2D other) { Debug.Log(other.tag.ToString()); // Register NPC interaction boundaries. if (other.gameObject.CompareTag("NpcTrigger")) { NpcID id = other.gameObject.GetComponent().parentController.npcID; if (!inRangeNpcs.ContainsKey(id)) { inRangeNpcs.Add(id, other.gameObject); } Debug.Log(id.ToString() + " enter"); Npc npc = (Npc)(NpcInfo.npcs[id]); if ((npc.shop != null || npc.craftingList != null) && State.state.quests.CheckNpcShopPrerequisites(npc)) { if (!inRangeUtilityNpcs.ContainsKey(id)) { inRangeUtilityNpcs.Add(id, other.gameObject); } Debug.Log(id.ToString() + " utility enter"); } } } void OnTriggerExit2D(Collider2D other) { Debug.Log(other.tag.ToString()); // Register NPC interaction boundaries. if (other.gameObject.CompareTag("NpcTrigger")) { NpcID id = other.gameObject.GetComponent().parentController.npcID; if (inRangeNpcs.ContainsKey(id)) { inRangeNpcs.Remove(id); } Debug.Log(id.ToString() + " exit"); Npc npc = (Npc)(NpcInfo.npcs[id]); if ((npc.shop != null || npc.craftingList != null) && State.state.quests.CheckNpcShopPrerequisites(npc)) { if (inRangeUtilityNpcs.ContainsKey(id)) { inRangeUtilityNpcs.Remove(id); } Debug.Log(id.ToString() + " utility exit"); } } } private void WallKick() { alreadyKicked = true; GameObject effect = Instantiate(wallKickEffect); SetEffectRelativePosition3D(effect); if (!controller.m_FacingRight) { effect.transform.localScale = new Vector3(effect.transform.localScale.x * -1, effect.transform.localScale.y, effect.transform.localScale.z); } controller.PlaySound(controller.audioClipWallKick); float direction = (controller.m_FacingRight) ? -1f : 1f; controller.m_Rigidbody2D.velocity = new Vector3((float)direction * wallKickForce.x, wallKickForce.y, 0f); controller.Flip(); } private bool CheckWallKick() { // Boxcast in the direction of travel must be occupied. Or // In other words, you're running into a wall. Collider2D[] dashCollisions; dashCollisions = Physics2D.OverlapBoxAll( wallCheckPositionRight.transform.position, wallCheckSize, 0, controller.m_WhatIsGround); foreach (Collider2D collision in dashCollisions) { if (!collision.gameObject.CompareTag("Player")) { return true; } } return false; } private bool CheckDashAreaEmpty() { // Boxcast covering the dash area must be clear. Collider2D[] dashCollisions; dashCollisions = Physics2D.OverlapBoxAll( dashCheckPosition.transform.position, dashCollisionCheckSize, 0, controller.m_WhatIsGround); foreach (Collider2D collision in dashCollisions) { if (!collision.gameObject.CompareTag("Player")) { return false; } } return true; } private void SetEffectRelativePosition3D(GameObject effect, float x = 0, float y = 0, float z = 0) { effect.transform.position = new Vector3(controller.m_Rigidbody2D.transform.position.x + x, controller.m_Rigidbody2D.transform.position.y + y, controller.m_Rigidbody2D.transform.position.z + z); } private void TryPickup() { GameObject[] items = GameObject.FindGameObjectsWithTag("Item"); float lowestDistance = pickupRange; GameObject closestObject = null; foreach(GameObject itemObject in items) { float distance = Vector2.Distance(controller.m_Rigidbody2D.transform.position, itemObject.transform.position); if (distance < lowestDistance && !itemObject.GetComponent().fadingOut) { lowestDistance = distance; closestObject = itemObject; } } if (closestObject != null) { if (closestObject.GetComponent().PickUp()) { controller.PlaySound(controller.audioClipPickup); } } } public static SkillStats GetSkillStats(SkillID skillID) { int skillLevel = (int)State.state.skillState.skillLevels[skillID]; return ((Skill)Skill.skillData[skillID]).statsPerLevel[skillLevel - 1]; } public void OnJumpStart() { if (!animator.GetBool("isJumping")) { jump = true; animator.Broadcast("isJumping", true); controller.m_Rigidbody2D.gravityScale = controller.lowGravity; GameObject effect = Instantiate(jumpEffect); SetEffectRelativePosition3D(effect); if (!controller.m_FacingRight) { effect.transform.localScale = new Vector3(effect.transform.localScale.x * -1, effect.transform.localScale.y, effect.transform.localScale.z); } Destroy(effect, 2f); } } public void OnFootstep1() { GameObject effect = Instantiate(landEffect); SetEffectRelativePosition3D(effect); if (!controller.m_FacingRight) { } else { effect.transform.localScale = new Vector3(effect.transform.localScale.x * -1, effect.transform.localScale.y, effect.transform.localScale.z); } controller.PlaySound(controller.audioClipFootstep1); } public void OnFootstep2() { GameObject effect = Instantiate(landEffect); SetEffectRelativePosition3D(effect); if (controller.m_FacingRight) { effect.transform.localScale = new Vector3(effect.transform.localScale.x * -1, effect.transform.localScale.y, effect.transform.localScale.z); } controller.PlaySound(controller.audioClipFootstep2); } public void OnLanding() { dash = false; alreadyDoubleJumped = false; alreadyJumpedDown = false; alreadyBlowbackShot = false; alreadyKicked = false; animator.Broadcast("isJumping", false); GameObject effect = Instantiate(landEffect); SetEffectRelativePosition3D(effect); if (controller.m_FacingRight) { effect.transform.localScale = new Vector3(effect.transform.localScale.x * -1, effect.transform.localScale.y, effect.transform.localScale.z); } controller.PlaySound(controller.audioClipLand); } private IEnumerator Cooldown(SkillID type, float seconds) { isOnCooldownMap[type] = true; Debug.Log("Cooling down " + type.ToString() + " for " + seconds.ToString() + " seconds"); yield return new WaitForSeconds(seconds); isOnCooldownMap[type] = false; } public void OnAttackStart() { attack = true; busy = true; animator.Broadcast("isAttacking", true); SkillStats skillStats = GetSkillStats(SkillID.BASIC_ATTACK); StartCoroutine(Cooldown(SkillID.BASIC_ATTACK, skillStats.cooldown)); Debug.Log("Attacking"); } public void FireStart() { animator.Broadcast("isFiring", true); animator.Broadcast("isExecuting", false); animator.Broadcast("isJudging", false); animator.Broadcast("isArrowBarraging", false); } public void OnFireEnd() { attack = false; busy = false; animator.Broadcast("isFiring", false); } public void OnAttackEnd() { attack = false; busy = false; animator.Broadcast("isAttacking", false); } public void OnStunningStrikeStart() { attack = true; busy = true; stunningStrikeVariant = true; animator.Broadcast("isExecuting", true); SkillStats skillStats = GetSkillStats(SkillID.STUNNING_STRIKE); StartCoroutine(Cooldown(SkillID.STUNNING_STRIKE, skillStats.cooldown)); Invoke("FireStart", delayStunningStrike); SpawnStunningStrikeEffect(); } public void SpawnStunningStrikeEffect() { Debug.Log("Spawning Stunning Strike effect"); controller.PlaySound(controller.audioClipAttack); GameObject effect = Instantiate(stunningStrikeEffect); if (!controller.m_FacingRight) { SetEffectRelativePosition3D(effect); effect.transform.localScale = new Vector3(effect.transform.localScale.x * -1f, effect.transform.localScale.y, effect.transform.localScale.z); } else { SetEffectRelativePosition3D(effect); } effect.transform.SetParent(transform); effect.transform.SetAsLastSibling(); } public void OnExecutionStart() { attack = true; busy = true; SkillStats skillStats = GetSkillStats(SkillID.EXECUTION); StartCoroutine(Cooldown(SkillID.EXECUTION, skillStats.cooldown)); animator.Broadcast("isExecuting", true); Invoke("FireStart", delayExecution); Invoke("SpawnExecutionAttack", delayExecutionAttack); controller.PlaySound(controller.audioClipExecutionCharge); GameObject effect = Instantiate(executionChargeEffect); SetEffectRelativePosition3D(effect, 0, 3); effect.transform.SetParent(transform); if (!controller.m_FacingRight) { effect.transform.localScale = new Vector3(effect.transform.localScale.x * -1, effect.transform.localScale.y, effect.transform.localScale.z); } } public void OnArrowBarrageStart() { attack = true; busy = true; busy = true; SkillStats skillStats = GetSkillStats(SkillID.ARROW_BARRAGE); StartCoroutine(Cooldown(SkillID.ARROW_BARRAGE, skillStats.cooldown)); animator.Broadcast("isArrowBarraging", true); controller.PlaySound(controller.audioClipArrowBarrageCharge); GameObject effect = Instantiate(arrowBarrageChargeEffect); Invoke("FireStart", delayArrowBarrage); Invoke("SpawnArrowBarrageAttack", delayArrowBarrageAttack); SetEffectRelativePosition3D(effect); if (!controller.m_FacingRight) { effect.transform.localScale = new Vector3(effect.transform.localScale.x * -1, effect.transform.localScale.y, effect.transform.localScale.z); } } public void SpawnArrowBarrageAttack() { Debug.Log("Spawning Arrow Barrage"); controller.PlaySound(controller.audioClipExecution); GameObject effect = Instantiate(arrowBarrageEffect); GameObject hitboxSpawner = Instantiate(hitboxSpawnerArrowBarrage); HitboxSpawner hbs = hitboxSpawner.GetComponent(); hbs.Setup(!controller.m_FacingRight, SkillID.ARROW_BARRAGE, 0); SetEffectRelativePosition3D(hitboxSpawner); SetEffectRelativePosition3D(effect); effect.transform.SetParent(transform); if (!controller.m_FacingRight) { effect.transform.localScale = new Vector3(effect.transform.localScale.x * -1, effect.transform.localScale.y, effect.transform.localScale.z); } } public void OnExecutionEnd() { attack = false; busy = false; animator.Broadcast("isExecuting", false); } public void OnArrowBarrageEnd() { attack = false; busy = false; animator.Broadcast("isArrowBarraging", false); } public void SpawnExecutionAttack() { if (stunningStrikeVariant) { SpawnStunningStrike(); stunningStrikeVariant = false; return; } // controller.PlaySound(controller.audioClipExecution); GameObject effect = Instantiate(executionEffect); GameObject hitbox = Instantiate(hitboxExecution); HitboxController hbc = hitbox.GetComponent(); SkillStats stats = GetSkillStats(SkillID.EXECUTION); hbc.Setup(stats.maxMonstersHit, stats.hitboxHitCounts[0], stats.hitboxPowers[0]); SetEffectRelativePosition3D(effect, 0, 3); effect.transform.SetParent(transform); if (!controller.m_FacingRight) { SetEffectRelativePosition3D(hitbox); effect.transform.localScale = new Vector3(effect.transform.localScale.x * -1, effect.transform.localScale.y, effect.transform.localScale.z); hitbox.transform.localScale = new Vector3(hitbox.transform.localScale.x * -1f, hitbox.transform.localScale.y, hitbox.transform.localScale.z); hbc.flip = true; } else { SetEffectRelativePosition3D(hitbox); } } public void OnJumpDownStart() { GameObject effect = Instantiate(jumpDownEffect); SetEffectRelativePosition3D(effect); SkillStats skillStats = GetSkillStats(SkillID.DOUBLE_JUMP); if (!controller.m_FacingRight) { effect.transform.localScale = new Vector3(effect.transform.localScale.x * -1, effect.transform.localScale.y, effect.transform.localScale.z); } controller.m_Rigidbody2D.velocity = new Vector2(controller.m_Rigidbody2D.velocity.x, -1f * dashForce.x * skillStats.speedModifier); alreadyJumpedDown = true; controller.PlaySound(controller.audioClipDoubleJump); } public void OnBlowbackShotStart() { attack = true; busy = true; alreadyBlowbackShot = true; isFrozen = true; animator.Broadcast("isFlipAttacking", true); SkillStats skillStats = GetSkillStats(SkillID.BLOWBACK_SHOT); StartCoroutine(Cooldown(SkillID.BLOWBACK_SHOT, skillStats.cooldown)); Debug.Log("Blowback Shot"); } public void OnBlowbackShotEnd() { attack = false; busy = false; animator.Broadcast("isFlipAttacking", false); } public void SpawnBlowbackEffect() { isFrozen = false; Debug.Log("Spawning blowback effect!"); controller.PlaySound(controller.audioClipBlowback); GameObject hitbox = Instantiate(hitboxBlowback); SetEffectRelativePosition3D(hitbox); HitboxController hbc = hitbox.GetComponent(); SkillStats stats = GetSkillStats(SkillID.BLOWBACK_SHOT); hbc.Setup(stats.maxMonstersHit, stats.hitboxHitCounts[0], stats.hitboxPowers[0]); if (!controller.m_FacingRight) { hitbox.transform.localScale = new Vector3(hitbox.transform.localScale.x * -1f, hitbox.transform.localScale.y, hitbox.transform.localScale.z); hbc.flip = true; } if (controller.m_FacingRight) { controller.m_Rigidbody2D.velocity = new Vector2(-1f * blowbackForce.x * stats.speedModifier, blowbackForce.y); } else { controller.m_Rigidbody2D.velocity = new Vector2(blowbackForce.x * stats.speedModifier, blowbackForce.y); } controller.Flip(); } public void OnBlowbackShot() { GameObject effect = Instantiate(blowbackEffect); SkillStats skillStats = GetSkillStats(SkillID.BLOWBACK_SHOT); if (!controller.m_FacingRight) { SetEffectRelativePosition3D(effect, 16f, 48f); effect.transform.localScale = new Vector3(effect.transform.localScale.x * -1, effect.transform.localScale.y, effect.transform.localScale.z); } else { SetEffectRelativePosition3D(effect, -16f, 48f); } controller.PlaySound(controller.audioClipBlowback); } public void OnDoubleJumpStart(bool jumpUp) { GameObject effect; SkillStats skillStats = GetSkillStats(SkillID.DOUBLE_JUMP); float dashForceX = dashForce.x; float dashForceY = dashForce.y; if (jumpUp) { effect = Instantiate(doubleJumpUpEffect); controller.m_Rigidbody2D.velocity = new Vector2(controller.m_Rigidbody2D.velocity.x, dashForceY * skillStats.speedModifier * 1.5f); controller.m_Rigidbody2D.gravityScale = controller.lowGravity; } else { effect = Instantiate(doubleJumpEffect); if (!controller.m_FacingRight) { effect.transform.localScale = new Vector3(effect.transform.localScale.x * -1, effect.transform.localScale.y, effect.transform.localScale.z); dashForceX *= -1f; } controller.m_Rigidbody2D.velocity = new Vector2(dashForceX * skillStats.speedModifier, dashForceY); } SetEffectRelativePosition3D(effect); alreadyDoubleJumped = true; controller.PlaySound(controller.audioClipDoubleJump); } public void OnDashStart() { dash = true; busy = true; SkillStats skillStats = GetSkillStats(SkillID.LIGHTNING_DASH); controller.PlaySound(controller.audioClipDashStart); animator.Broadcast("isDashing", true); StartCoroutine(Cooldown(SkillID.LIGHTNING_DASH, skillStats.cooldown)); Aberrate(); } public void OnDashTeleport() { GameObject effect = Instantiate(dashEffect); SetEffectRelativePosition3D(effect, 0, -6); if (!controller.m_FacingRight) { effect.transform.localScale = new Vector3(effect.transform.localScale.x * -1, effect.transform.localScale.y, effect.transform.localScale.z); } controller.PlaySound(controller.audioClipDash); if (controller.m_FacingRight) { if (CheckDashAreaEmpty()) { transform.position = new Vector3(transform.position.x + dashDistance, transform.position.y, transform.position.z); } controller.m_Rigidbody2D.velocity = new Vector3(runSpeed, 0f, 0f); } else { if (CheckDashAreaEmpty()) { transform.position = new Vector3(transform.position.x - dashDistance, transform.position.y, transform.position.z); } controller.m_Rigidbody2D.velocity = new Vector3(-1f * runSpeed, 0f, 0f); } } public void OnDashEnd() { animator.Broadcast("isDashing", false); dash = false; busy = false; } public void OnDieStart() { busy = true; isFrozen = true; dash = false; // Spawn death animation GameObject effect = Instantiate(deathEffect); SetEffectRelativePosition3D(effect, 0, 16); // TODO: Replace with "audioClipDeath" controller.PlaySound(controller.audioClipDash); Invoke("OnDieEnd", deathAnimationTime); // TODO: Fade to black and add fade in from black } public void OnDieBoom() { // TODO: Set the opacity of all player animation layers to 0 // TODO: Link this to the death animation effect } public void OnDieEnd() { Debug.Log("lol you died"); State.state.stats.hp = State.state.stats.maxHP; // TODO: Add location history and spawn location management to choose the right scene SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex); } public void OnHurtStart() { // TODO: Re-enable when hurt animation works // busy = true; // Cancel all velocity. if (controller.m_FacingRight) { controller.m_Rigidbody2D.velocity = new Vector2(hurtSpeed * -1, 0); } else { controller.m_Rigidbody2D.velocity = new Vector2(hurtSpeed, 0); } //animation.Broadcast("isHurting", true); } public void OnHurtEnd() { if (State.state.stats.hp < 1) { OnDieStart(); } else { busy = false; } animator.Broadcast("isHurting", false); } void FixedUpdate () { if (controller.m_Rigidbody2D.velocity.y < -0.01f || !Input.GetButton("Jump")) { controller.m_Rigidbody2D.gravityScale = controller.highGravity; } else { controller.m_Rigidbody2D.gravityScale = controller.lowGravity; } if (isFrozen) { controller.m_Rigidbody2D.velocity = Vector2.zero; controller.m_Rigidbody2D.gravityScale = 0f; } else { controller.Move(horizontalMove * Time.fixedDeltaTime, jump, dash); } jump = false; } public void EndAttack() { OnAttackEnd(); } public void SpawnStunningStrike() { stunningStrikeVariant = false; Debug.Log("Spawning Stunning Strike hitbox"); GameObject hitbox = Instantiate(hitboxStunningStrike); SetEffectRelativePosition3D(hitbox); HitboxController hbc = hitbox.GetComponent(); SkillStats stats = GetSkillStats(SkillID.STUNNING_STRIKE); hbc.Setup(stats.maxMonstersHit, stats.hitboxHitCounts[0], stats.hitboxPowers[0]); if (!controller.m_FacingRight) { hitbox.transform.localScale = new Vector3(hitbox.transform.localScale.x * -1f, hitbox.transform.localScale.y, hitbox.transform.localScale.z); hbc.flip = true; } } public void SpawnAttackEffect() { Debug.Log("Spawning attack effect"); controller.PlaySound(controller.audioClipAttack); GameObject effect = Instantiate(attackEffect); if (!controller.m_FacingRight) { SetEffectRelativePosition3D(effect); effect.transform.localScale = new Vector3(effect.transform.localScale.x * -1f, effect.transform.localScale.y, effect.transform.localScale.z); } else { SetEffectRelativePosition3D(effect); } effect.transform.SetParent(transform); effect.transform.SetAsLastSibling(); } public void SpawnAttack() { Debug.Log("Spawning attack hitbox"); GameObject hitbox = Instantiate(hitboxBasicAttack); SetEffectRelativePosition3D(hitbox); HitboxController hbc = hitbox.GetComponent(); SkillStats stats = GetSkillStats(SkillID.BASIC_ATTACK); hbc.Setup(stats.maxMonstersHit, stats.hitboxHitCounts[0], stats.hitboxPowers[0]); if (!controller.m_FacingRight) { hitbox.transform.localScale = new Vector3(hitbox.transform.localScale.x * -1f, hitbox.transform.localScale.y, hitbox.transform.localScale.z); hbc.flip = true; } } public void SpawnDashEffect() { Debug.Log("Spawning dash effect"); GameObject effect = Instantiate(dashEffect); GameObject hitbox = Instantiate(hitboxDashAttack); SetEffectRelativePosition3D(hitbox); HitboxController hbc = hitbox.GetComponent(); SkillStats stats = GetSkillStats(SkillID.LIGHTNING_DASH); hbc.Setup(stats.maxMonstersHit, stats.hitboxHitCounts[0], stats.hitboxPowers[0]); if (!controller.m_FacingRight) { SetEffectRelativePosition3D(effect, -1f); effect.transform.localScale = new Vector3(effect.transform.localScale.x * -1f, effect.transform.localScale.y, effect.transform.localScale.z); hitbox.transform.localScale = new Vector3(hitbox.transform.localScale.x * -1f, hitbox.transform.localScale.y, hitbox.transform.localScale.z); hbc.flip = true; } else { SetEffectRelativePosition3D(effect, 1f); } } public void GainExp(int amount) { if (State.state.stats.gainExp(amount)) { controller.PlaySound(controller.audioClipLevelUp); GameObject effect = Instantiate(levelUpEffect); effect.transform.SetParent(this.transform); SetEffectRelativePosition3D(effect); Destroy(effect, 3f); } } public void BecomeVulnerable() { invincible = false; } public void TakeDamage(int power) { if (invincible) return; ProCamera2DShake.Instance.Shake(0); // playerHit int damageTaken = State.state.stats.takeDamage(power); Vector3 damageTextPosition = new Vector3(gameObject.transform.position.x + damageTextTransposeX, gameObject.transform.position.y + damageTextTransposeY, gameObject.transform.position.z); Transform transform = Instantiate(damageText, damageTextPosition, Quaternion.identity); DamageTextController text = transform.GetComponent(); text.Setup(damageTaken); if (State.state.stats.hp <= 0) { OnDieStart(); } else { if (hurtAudioClip != null) { controller.audioSource.PlayOneShot(hurtAudioClip); } invincible = true; OnHurtStart(); Invoke("BecomeVulnerable", invincibilityTime); } } }