415 lines
12 KiB
C#
415 lines
12 KiB
C#
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Linq;
|
||
|
using System.Text;
|
||
|
using System.Threading.Tasks;
|
||
|
using UnityEngine;
|
||
|
|
||
|
[RequireComponent(typeof(NPC))]
|
||
|
[RequireComponent(typeof(Enemy))]
|
||
|
public class WizardBattle : MonoBehaviour
|
||
|
{
|
||
|
public const string ACTION_KEY = "ATTACKING";
|
||
|
|
||
|
private Rigidbody2D myRigidbody;
|
||
|
public Animator anim;
|
||
|
|
||
|
private Vector2 movement;
|
||
|
public bool shouldRotate;
|
||
|
public Vector3 dir;
|
||
|
|
||
|
[Header("Following Logic")]
|
||
|
public Vector3 homePosition;
|
||
|
public Transform targetPosition;
|
||
|
|
||
|
public AStarPathfindingAgent agent;
|
||
|
|
||
|
public bool isDuringFollowing = false; // var is setted by trigger range
|
||
|
|
||
|
//public GameObject player;
|
||
|
[Header("Core Logic")]
|
||
|
public bool approaching = false;
|
||
|
public bool isAfterAction = false;
|
||
|
public float chasingRadius = 6f; // radious where Npc start attacking ! ! !
|
||
|
|
||
|
[Header("Attacking Logic")] // TRASH - dupplicated from Following Enemy - move params to Enemy
|
||
|
public float attackingRadius = 1.5f; // radious where Npc start attacking ! ! !
|
||
|
|
||
|
public bool hit = false;
|
||
|
|
||
|
public bool firstAttack = false;
|
||
|
|
||
|
public float timerDmg = 0f;
|
||
|
public float waitTime = 1.0f;
|
||
|
|
||
|
public float timerHit = 0f;
|
||
|
public float hitWaitTime = 0.55f;
|
||
|
|
||
|
public float expValue;
|
||
|
public float thrust;
|
||
|
public float knockTime;
|
||
|
|
||
|
//public int isKilled; - movet do Enemy
|
||
|
//isKilled = 0 - mob ALIVE
|
||
|
//isKilled = 1 - mob DEAD
|
||
|
|
||
|
public int isKilled2;
|
||
|
|
||
|
public bool isPanelEnabled = true;
|
||
|
|
||
|
public float waitTimerDeath;
|
||
|
public float timerDeath;
|
||
|
SpriteRenderer sprite;
|
||
|
public float x;
|
||
|
public float y;
|
||
|
public float z;
|
||
|
public string die;
|
||
|
|
||
|
void Awake()
|
||
|
{
|
||
|
agent = GetComponent<AStarPathfindingAgent>();
|
||
|
|
||
|
|
||
|
homePosition = new Vector3(gameObject.transform.position.x, gameObject.transform.position.y, gameObject.transform.position.z);
|
||
|
}
|
||
|
|
||
|
// Start is called before the first frame update
|
||
|
void Start()
|
||
|
{
|
||
|
targetPosition = GameObject.FindWithTag("Player").transform;
|
||
|
|
||
|
//Copy from Eollwoing
|
||
|
if (OnMapAppearanceMethod.IsNewGame())
|
||
|
{
|
||
|
gameObject.GetComponent<Enemy>().isKilled = 0;
|
||
|
}
|
||
|
|
||
|
if (gameObject.GetComponent<Enemy>().health <= 0)
|
||
|
gameObject.GetComponent<Enemy>().isKilled = 1;
|
||
|
else // Else read saved value
|
||
|
gameObject.GetComponent<Enemy>().isKilled = PlayerPrefs.GetInt(gameObject.GetComponent<Enemy>().enemyName + "-S");
|
||
|
|
||
|
|
||
|
if (gameObject.GetComponent<Enemy>().isKilled == 1)
|
||
|
{
|
||
|
gameObject.SetActive(false);
|
||
|
gameObject.GetComponent<Enemy>().isKilled = 0;
|
||
|
}
|
||
|
|
||
|
myRigidbody = GetComponent<Rigidbody2D>();
|
||
|
anim = GetComponent<Animator>();
|
||
|
|
||
|
PlayerPrefs.SetString("WizardDeath", "alive");
|
||
|
timerDeath = 0.0f;
|
||
|
waitTimerDeath = 0.09f;
|
||
|
sprite = GetComponent<SpriteRenderer>();
|
||
|
x = 1;
|
||
|
y = 1;
|
||
|
z = 1;
|
||
|
}
|
||
|
|
||
|
// Update is called once per frame
|
||
|
public void Update()
|
||
|
{
|
||
|
// 0 Cofigure Animator
|
||
|
if (Vector2.Distance(targetPosition.position, transform.position) <= chasingRadius)
|
||
|
{
|
||
|
dir = targetPosition.position - transform.position;
|
||
|
float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
|
||
|
dir.Normalize();
|
||
|
movement = dir;
|
||
|
anim.SetBool("isRunning", movement != Vector2.zero);
|
||
|
|
||
|
if (shouldRotate)
|
||
|
{
|
||
|
anim.SetFloat("Xinfo", dir.x);
|
||
|
anim.SetFloat("Yinfo", dir.y);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// 1. Check range and decide which action do
|
||
|
// Following player detection
|
||
|
if (IsInChassingRadious())
|
||
|
{
|
||
|
// 2'nd state alow us to brak going to hom,e action to follow player again
|
||
|
if (gameObject.GetComponent<NPC>().State == NPCStateEnum.Pending || gameObject.GetComponent<NPC>().State == NPCStateEnum.Walking)
|
||
|
{
|
||
|
approaching = true;
|
||
|
|
||
|
gameObject.GetComponent<NPC>().State = NPCStateEnum.Walking;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Turn around and go to home position
|
||
|
if (approaching)
|
||
|
{
|
||
|
approaching = false;
|
||
|
anim.SetBool("isRunning", true);
|
||
|
gameObject.GetComponent<NPC>().State = NPCStateEnum.Walking;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 2.Take action based on conditions around
|
||
|
HandleState();
|
||
|
|
||
|
// 3.
|
||
|
// COPIED FROM Following Enemy scripts
|
||
|
// Taking hit logic
|
||
|
timerHit += Time.deltaTime;
|
||
|
if (hit == true)
|
||
|
{
|
||
|
if (timerHit >= hitWaitTime)
|
||
|
{
|
||
|
|
||
|
TakeDamage(PlayerPrefs.GetFloat("attackValue"));
|
||
|
hit = false;
|
||
|
timerHit = 0f;
|
||
|
TakeKnockback();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Detecting "is alive" logic
|
||
|
if (gameObject.active == false)
|
||
|
{
|
||
|
gameObject.GetComponent<Enemy>().isKilled = 1;
|
||
|
PlayerPrefs.SetInt(gameObject.GetComponent<Enemy>().enemyName, gameObject.GetComponent<Enemy>().isKilled);
|
||
|
}
|
||
|
|
||
|
die = PlayerPrefs.GetString("WizardDeath");
|
||
|
if (die == "die")
|
||
|
{
|
||
|
timerDeath += Time.deltaTime;
|
||
|
if (timerDeath >= waitTimerDeath)
|
||
|
{
|
||
|
if (x >= 0.3)
|
||
|
{
|
||
|
x = x - 0.04f;
|
||
|
y = y - 0.04f;
|
||
|
|
||
|
sprite.color = new Color(1, x, y, 1);
|
||
|
timerDeath = 0.0f;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
z = z - 0.04f;
|
||
|
sprite.color = new Color(1, x, y, z);
|
||
|
|
||
|
timerDeath = 0.0f;
|
||
|
if (z <= 0)
|
||
|
{
|
||
|
gameObject.active = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void CheckDistance()
|
||
|
{
|
||
|
StopAllCoroutines();
|
||
|
|
||
|
|
||
|
// isDuringFollowing - avr is setted by trigger range
|
||
|
if (approaching && !IsInActionRadious())
|
||
|
{
|
||
|
agent.FindPath();
|
||
|
|
||
|
StartCoroutine(agent.FollowPath());
|
||
|
}
|
||
|
else if (approaching)
|
||
|
{
|
||
|
// in this script we set attacking mode
|
||
|
SetActionAfterMetConditions();
|
||
|
|
||
|
agent.path.Clear(); // if we are able to talgk we dont want go go further player
|
||
|
}
|
||
|
else if (!approaching)
|
||
|
{
|
||
|
if (Vector2.Distance(transform.position, homePosition) > 0.8f) // cont vale - path finding stop moving them before reachin position well..
|
||
|
{
|
||
|
agent.point = homePosition;
|
||
|
|
||
|
agent.FindPoint();
|
||
|
|
||
|
StartCoroutine(agent.FollowPath());
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
anim.SetBool("isRunning", false);
|
||
|
gameObject.GetComponent<NPC>().State = NPCStateEnum.Pending;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#region Taking damage from Player detection
|
||
|
|
||
|
public void OnTriggerEnter2D(Collider2D collision)
|
||
|
{
|
||
|
// Hit logic
|
||
|
if (collision.gameObject.tag == "AttackHitbox" || collision.gameObject.tag == "PickaxeHitbox")
|
||
|
{
|
||
|
hit = true;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
public void OnTriggerExit2D(Collider2D other)
|
||
|
{
|
||
|
// Hit logic
|
||
|
if (other.tag == "AttackHitbox" || other.tag == "PickaxeHitbox")
|
||
|
{
|
||
|
timerDmg = 0f;
|
||
|
|
||
|
hit = false;
|
||
|
}
|
||
|
}
|
||
|
#endregion
|
||
|
|
||
|
public void HandleState()
|
||
|
{
|
||
|
switch (gameObject.GetComponent<NPC>().State)
|
||
|
{
|
||
|
case NPCStateEnum.Walking:
|
||
|
{
|
||
|
CheckDistance();
|
||
|
break;
|
||
|
}
|
||
|
case NPCStateEnum.Talking:
|
||
|
{
|
||
|
TalkingAction();
|
||
|
break;
|
||
|
}
|
||
|
case NPCStateEnum.Pending:
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
case NPCStateEnum.Attacking:
|
||
|
{
|
||
|
AttackingAction();
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
Debug.Log("Nieopisane zachowanie NPC ! ! !");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public bool IsInChassingRadious()
|
||
|
{
|
||
|
if (Vector2.Distance(targetPosition.position, transform.position) >= chasingRadius)
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public bool IsInActionRadious()
|
||
|
{
|
||
|
if (Vector2.Distance(targetPosition.position, transform.position) >= attackingRadius)
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public void SetActionAfterMetConditions()
|
||
|
{
|
||
|
gameObject.GetComponent<NPC>().State = NPCStateEnum.Attacking;
|
||
|
}
|
||
|
|
||
|
public void TalkingAction()
|
||
|
{
|
||
|
// Not required in this script
|
||
|
}
|
||
|
|
||
|
public void AttackingAction()
|
||
|
{
|
||
|
// if during Attacking mode player GO OUT of the attacking radious
|
||
|
if (!IsInActionRadious())
|
||
|
{
|
||
|
gameObject.GetComponent<NPC>().State = NPCStateEnum.Walking;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Attacking logic
|
||
|
if (firstAttack == false)
|
||
|
{
|
||
|
if (timerDmg >= 0.15f)
|
||
|
{
|
||
|
firstAttack = true;
|
||
|
|
||
|
GameObject.FindGameObjectWithTag("Player").GetComponent<Player>().TakeDamage(
|
||
|
gameObject.GetComponent<Enemy>().baseAttack,
|
||
|
isPanelEnabled
|
||
|
);
|
||
|
|
||
|
timerDmg = 0f;
|
||
|
}
|
||
|
}
|
||
|
if (timerDmg >= waitTime)
|
||
|
{
|
||
|
timerDmg = 0f;
|
||
|
|
||
|
GameObject.FindGameObjectWithTag("Player").GetComponent<Player>().TakeDamage(
|
||
|
gameObject.GetComponent<Enemy>().baseAttack,
|
||
|
isPanelEnabled
|
||
|
);
|
||
|
}
|
||
|
|
||
|
timerDmg += Time.deltaTime;
|
||
|
|
||
|
}
|
||
|
|
||
|
#region dupplicated from Following :)
|
||
|
public void TakeDamage(float damage)
|
||
|
{
|
||
|
Debug.Log("TakeDamage");
|
||
|
gameObject.GetComponent<Enemy>().health -= damage;
|
||
|
|
||
|
if (gameObject.GetComponent<Enemy>().health <= 0)
|
||
|
{
|
||
|
attackingRadius = 0f;
|
||
|
chasingRadius = 0f;
|
||
|
|
||
|
PlayerPrefs.SetString("WizardDeath", "die");
|
||
|
gameObject.GetComponent<Enemy>().isKilled = 1;
|
||
|
GameObject.FindGameObjectWithTag("Player").GetComponent<Player>().GetExp(expValue);
|
||
|
|
||
|
// pass info about killing assigned enemy to mission manager listener
|
||
|
// pass enemy name from script NOT object name (thats allow to have many different objects variantsa with this same aggregate key (private name - not preffab name) )
|
||
|
ConditionManager.Instance.UpdateKillCondition(gameObject.GetComponent<Enemy>().MinionName);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void TakeKnockback()
|
||
|
{
|
||
|
Rigidbody2D enemy = gameObject.GetComponent<Rigidbody2D>();
|
||
|
Rigidbody2D player = GameObject.FindGameObjectWithTag("Player").GetComponent<Rigidbody2D>();
|
||
|
|
||
|
if (enemy != null)
|
||
|
{
|
||
|
enemy.isKinematic = false;
|
||
|
Vector2 difference = enemy.transform.position - player.transform.position;
|
||
|
difference = difference.normalized * thrust;
|
||
|
enemy.AddForce(difference, ForceMode2D.Impulse);
|
||
|
//StartCoroutine(KnockCo(enemy));
|
||
|
}
|
||
|
}
|
||
|
#endregion
|
||
|
|
||
|
public void AfterAction()
|
||
|
{
|
||
|
approaching = false;
|
||
|
isAfterAction = true;
|
||
|
//isDuringConversation = false;
|
||
|
//PlayerPrefs.SetInt(gameObject.name + ".FirstDialogue", System.Convert.ToInt32(isAfterAction));
|
||
|
gameObject.GetComponent<NPC>().State = NPCStateEnum.Walking;
|
||
|
}
|
||
|
}
|
||
|
|