Files
pgs/Assets/Scripts/Physics/PlayerMovement.cs
2026-02-21 16:58:22 -08:00

892 lines
29 KiB
C#

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<NpcID, GameObject> inRangeNpcs = new Dictionary<NpcID, GameObject>();
private Dictionary<NpcID, GameObject> inRangeUtilityNpcs = new Dictionary<NpcID, GameObject>();
// 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<NpcID, GameObject> 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<NpcPlayerTriggerController>().parentController.Interact();
}
if (Input.GetButtonDown("Utility") && !busy && !cutscene && inRangeUtilityNpcs.Count > 0) {
float distance = float.MaxValue;
GameObject choice = null;
foreach (KeyValuePair<NpcID, GameObject> 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<NpcPlayerTriggerController>().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<NpcPlayerTriggerController>().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<NpcPlayerTriggerController>().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<ItemController>().fadingOut) {
lowestDistance = distance;
closestObject = itemObject;
}
}
if (closestObject != null) {
if (closestObject.GetComponent<ItemController>().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<HitboxSpawner>();
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<HitboxController>();
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<HitboxController>();
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<HitboxController>();
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<HitboxController>();
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<HitboxController>();
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<DamageTextController>();
text.Setup(damageTaken);
if (State.state.stats.hp <= 0) {
OnDieStart();
} else {
if (hurtAudioClip != null) {
controller.audioSource.PlayOneShot(hurtAudioClip);
}
invincible = true;
OnHurtStart();
Invoke("BecomeVulnerable", invincibilityTime);
}
}
}