WUT_Computer_Science/theProject/Assets/Scripts/Soldier.cs

172 lines
5.2 KiB
C#
Raw Normal View History

2022-05-16 13:39:57 +02:00
using System.Collections;
using System.Collections.Generic;
2022-05-17 22:22:04 +02:00
using TMPro;
2022-05-16 13:39:57 +02:00
using UnityEngine;
using UnityEngine.Events;
2022-05-16 13:39:57 +02:00
2022-05-23 13:18:37 +02:00
public class Soldier : Base
2022-05-16 13:39:57 +02:00
{
private Queue<Action> actions = new Queue<Action>();
private Queue<Action> interrupts = new Queue<Action>();
#region Action Queue Items
abstract class Action // action "template"
{
public virtual void Execute(Soldier soldier, TickSystem.OnTickEventArgs tickEventArgs) { } // called by Soldier when action is supposed to be done
}
private class Movement : Action
{
public override void Execute(Soldier soldier, TickSystem.OnTickEventArgs tickEventArgs)
{//TO DO: CALL PROPER FUNCTION TO MOVE
throw new System.NotImplementedException($"(tick: {tickEventArgs.tickNumber}) Trying to teleport to {soldier.movementDestination}");
//??tileMap.Teleport(movementDestination)
}
}
private class TryAttack : Action
{
public override void Execute(Soldier soldier, TickSystem.OnTickEventArgs tickEventArgs)
{
//Debug.LogWarning($"(tick: {tickEventArgs.tickNumber}) Looking for enemy in range");
if(soldier.TryAttackEnemy())
soldier.lastAttackTick = tickEventArgs.tickNumber;
}
}
#endregion
#region Handling Incoming Orders (Interrupts)
public void HandleMovementOrder(Vector2Int destination)
{
movementDestination = destination;
interrupts.Enqueue(new Movement()); // force soldier to find path to the new destination
}
#endregion
2022-05-23 13:18:37 +02:00
[Header("Values")]
2022-05-17 22:22:04 +02:00
[SerializeField] private float rangeAttack = 100;
[SerializeField] private float rangeView = 1;
[SerializeField] private float damageAttack = 1;
[SerializeField] private int speedAttack = 1; // ticks between attacks
[SerializeField] private int lastAttackTick = -1;
[Header("References")]
[Header("Do-not-change-in-game values")]
[SerializeField] private Soldier target;
[SerializeField] private SoldierType enemyType;
[SerializeField] private Vector2Int movementDestination = Vector2Int.zero;
// variables not visible in inspector
2022-05-23 13:20:08 +02:00
[HideInInspector] public UnityEvent<Soldier> onDeath = new UnityEvent<Soldier>();
2022-05-23 12:57:50 +02:00
public SoldierType GetOwnType()
{
return ourType;
}
2022-05-16 13:39:57 +02:00
// Start is called before the first frame update
void Start(){
2022-05-23 13:18:37 +02:00
base.Start();
setEnemyTag();
}
public void setEnemyTag()
{
2022-05-16 15:09:43 +02:00
if(ourType == SoldierType.Ally) enemyType = SoldierType.Enemy;
else enemyType = SoldierType.Ally;
2022-05-16 13:39:57 +02:00
}
void Awake()
{
TickSystem.OnTick += HandleTick;
}
2022-05-17 22:22:04 +02:00
2022-05-23 13:20:08 +02:00
private void Die()
{
2022-05-17 22:22:04 +02:00
TickSystem.OnTick -= HandleTick;
2022-05-23 13:20:08 +02:00
onDeath.Invoke(this);
Destroy(gameObject);
}
2022-05-17 22:22:04 +02:00
2022-05-23 13:20:08 +02:00
private void OnDestroy()
{
2022-05-17 22:22:04 +02:00
Debug.Log("Soldier: " + ourType.ToString() + " has died", gameObject);
}
private void HandleTick(TickSystem.OnTickEventArgs tickEventArgs)
{
ref Queue<Action> queueToHandle = ref interrupts;
if (interrupts.Count < 1) // if no interrupt actions to do, handle regular queue
queueToHandle = actions;
if(queueToHandle.Count > 0)
queueToHandle.Dequeue().Execute(this, tickEventArgs);
else
{
if(lastAttackTick + speedAttack <= tickEventArgs.tickNumber)
{
queueToHandle.Enqueue(new TryAttack());
queueToHandle.Dequeue().Execute(this, tickEventArgs);
}
}
}
bool TryAttackEnemy () //returns true if an enemy was attacked
2022-05-16 13:39:57 +02:00
{
// Enemies are the game objects tagged with the "Enemy"
2022-05-16 15:23:39 +02:00
//GameObject[] enemies = GameObject.FindGameObjectsWithTag(enemyType);
Soldier[] soldiers = GameObject.FindObjectsOfType<Soldier>();
2022-05-17 22:22:04 +02:00
List<Soldier> enemiesList = new List<Soldier>();
2022-05-16 15:23:39 +02:00
foreach (Soldier obj in soldiers)
{
if (obj.ourType == enemyType)
2022-05-17 22:22:04 +02:00
enemiesList.Add(obj);
2022-05-16 15:23:39 +02:00
}
2022-05-17 22:22:04 +02:00
Soldier[] enemies = enemiesList.ToArray();
2022-05-16 15:23:39 +02:00
2022-05-16 13:39:57 +02:00
// We have not found enemy yet so the distance to enemy is "infinite"
float shortestDistance = Mathf.Infinity;
2022-05-17 22:22:04 +02:00
Soldier nearestEnemy = null;
foreach ( Soldier enemy in enemies)
2022-05-16 13:39:57 +02:00
{
// Go through each enemy existing
// Calculate distance to this enemy
float distanceToEnemy = Vector3.Distance(transform.position, enemy.transform.position);
if (distanceToEnemy < shortestDistance)
{
shortestDistance = distanceToEnemy;
nearestEnemy = enemy;
}
}
if (nearestEnemy != null && shortestDistance <= rangeAttack)
{
2022-05-17 22:22:04 +02:00
target = nearestEnemy;
2022-05-16 13:39:57 +02:00
}
2022-05-17 22:22:04 +02:00
else
target = null;
if (target != null)
target.ReduceHP(damageAttack);
return target != null;
2022-05-16 13:39:57 +02:00
}
// Update is called once per frame
void Update()
{
2022-05-17 22:22:04 +02:00
//if (target == null) return;
2022-05-16 13:39:57 +02:00
}
/* https://www.youtube.com/watch?v=QKhn2kl9_8I 08:54 Soldier attack
void OnDrawGizmosSelected ()
{
}
*/
}