892 lines
29 KiB
C#
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);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|