383 lines
12 KiB
C#
383 lines
12 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using UnityEngine.Assertions;
|
|
using TMPro;
|
|
|
|
public enum CurrentCommand { defend, moveForward, retreat }
|
|
|
|
// Left is Player, Enemy is right.
|
|
public enum Side { left = 1, right = -1 }
|
|
|
|
public class Unit : MonoBehaviour
|
|
{
|
|
public string unitName;
|
|
public CardData cardData;
|
|
|
|
[SerializeField]
|
|
private int basicAttack;
|
|
private int finalAttack;
|
|
|
|
[SerializeField]
|
|
private int currentDefense;
|
|
|
|
[SerializeField]
|
|
private int basicMaxDefense;
|
|
private int finalMaxDefense;
|
|
|
|
[SerializeField]
|
|
private CardTag[] cardTags;
|
|
|
|
[SerializeField]
|
|
private int attackRange = 1;
|
|
[SerializeField]
|
|
private int movement = 1;
|
|
|
|
[SerializeField]
|
|
private CurrentCommand currentCommand;
|
|
|
|
public Cell standingCell;
|
|
[SerializeField]
|
|
private Cell destinationCell;
|
|
private CellMap cellMap;
|
|
|
|
public Side side;
|
|
|
|
public Transform modelArt;
|
|
public Transform attackText;
|
|
public Transform defenseText;
|
|
|
|
public bool walkingToDestination = false;
|
|
|
|
Camp allyCamp;
|
|
Camp enemyCamp;
|
|
|
|
// Start is called before the first frame update
|
|
void Start()
|
|
{
|
|
cellMap = FindObjectOfType<CellMap>();
|
|
transform.position = standingCell.transform.position;
|
|
transform.position = new Vector3(transform.position.x, transform.position.y, -1);
|
|
standingCell.standingUnit = this;
|
|
|
|
basicAttack = cardData.attack;
|
|
basicMaxDefense = cardData.defense;
|
|
currentDefense = basicMaxDefense;
|
|
cardTags = cardData.cardTags;
|
|
|
|
foreach (var tag in cardData.cardTags)
|
|
{
|
|
if (tag.name == "Archer")
|
|
{
|
|
attackRange += 2;
|
|
}
|
|
else if (tag.name == "Cavalry")
|
|
{
|
|
movement += 1;
|
|
}
|
|
}
|
|
|
|
modelArt.GetComponent<SpriteRenderer>().sprite = cardData.artwork;
|
|
|
|
var camps = FindObjectsOfType<Camp>();
|
|
foreach (var camp in camps)
|
|
{
|
|
if (camp.side == side)
|
|
{
|
|
allyCamp = camp;
|
|
}
|
|
else
|
|
{
|
|
enemyCamp = camp;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void Update()
|
|
{
|
|
if (walkingToDestination && destinationCell && transform.position != destinationCell.transform.position)
|
|
{
|
|
Vector3 moveVec = destinationCell.transform.position - transform.position;
|
|
transform.position = new Vector3(transform.position.x + moveVec.x * 5.0f * Time.deltaTime, transform.position.y + moveVec.y * 5.0f * Time.deltaTime, -1);
|
|
|
|
//Debug.Log("Manitude: " + moveVec.magnitude);
|
|
|
|
if ((Mathf.Approximately(transform.position.x, destinationCell.transform.position.x)
|
|
&& Mathf.Approximately(transform.position.y, destinationCell.transform.position.y))
|
|
|| moveVec.magnitude <= 1)
|
|
{
|
|
walkingToDestination = false;
|
|
transform.position = new Vector3(destinationCell.transform.position.x, destinationCell.transform.position.y, -1);
|
|
destinationCell = null;
|
|
//Debug.Log("Arrived.");
|
|
}
|
|
}
|
|
|
|
finalAttack = basicAttack; // For now.
|
|
|
|
attackText.GetComponent<TextMeshProUGUI>().text = finalAttack.ToString();
|
|
defenseText.GetComponent<TextMeshProUGUI>().text = currentDefense.ToString();
|
|
}
|
|
|
|
public void MoveAndAttack()
|
|
{
|
|
MoveAction();
|
|
AttackAction();
|
|
}
|
|
|
|
public void MoveAction()
|
|
{
|
|
if (walkingToDestination)
|
|
{
|
|
return;
|
|
}
|
|
foreach (var tag in cardData.cardTags)
|
|
{
|
|
if (tag.name == "Archer")
|
|
{
|
|
for (int i = 0; i < attackRange; ++i)
|
|
{
|
|
int attackXPos = standingCell.xPos + (i + 1) * (int)side;
|
|
if (attackXPos >= cellMap.column || attackXPos < 0)
|
|
{
|
|
// Attack Camp
|
|
currentCommand = CurrentCommand.defend;
|
|
break;
|
|
}
|
|
|
|
Cell nextCellInRange = cellMap.GetCell(attackXPos, standingCell.yPos);
|
|
Unit targetUnit = nextCellInRange.standingUnit;
|
|
if (targetUnit)
|
|
{
|
|
if (targetUnit.side != side)
|
|
{
|
|
// Add units to attack list.
|
|
currentCommand = CurrentCommand.defend;
|
|
break;
|
|
}
|
|
}
|
|
|
|
currentCommand = CurrentCommand.moveForward;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
//Debug.Log("Call MoveAction().");
|
|
switch (currentCommand)
|
|
{
|
|
case CurrentCommand.defend:
|
|
break;
|
|
case CurrentCommand.moveForward:
|
|
//Debug.Log("Try Move Forward.");
|
|
|
|
for (int i = 0; i < movement; i++)
|
|
{
|
|
if (checkDestinationCellEmpty())
|
|
{
|
|
// Attack()
|
|
//Debug.Log("Start Moving.");
|
|
MoveToCell(destinationCell);
|
|
walkingToDestination = true;
|
|
}
|
|
else
|
|
{
|
|
//Debug.Log("Can't Move.");
|
|
// Check the unit is facing the camp or unit.
|
|
if (destinationCell)
|
|
{
|
|
// Check the unit is Allie or Enemy.
|
|
if (destinationCell.standingUnit.side == side)
|
|
{
|
|
// Check the Allie is swappable or not.
|
|
if (!inDogFight(destinationCell.standingUnit))
|
|
{
|
|
//standingCell = cell;
|
|
//cell.standingUnit = this;
|
|
destinationCell.standingUnit.walkingToDestination = true;
|
|
standingCell.standingUnit = destinationCell.standingUnit;
|
|
standingCell.standingUnit.standingCell = standingCell;
|
|
standingCell.standingUnit.destinationCell = standingCell;
|
|
|
|
standingCell = destinationCell;
|
|
destinationCell.standingUnit = this;
|
|
walkingToDestination = true;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// Can't move to cell this is standed by enemy.
|
|
destinationCell = standingCell;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Facing the camp.
|
|
break;
|
|
}
|
|
destinationCell = standingCell;
|
|
}
|
|
}
|
|
break;
|
|
case CurrentCommand.retreat:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void AttackAction()
|
|
{
|
|
// Check Attack Range
|
|
if (inDogFight(this))
|
|
{
|
|
foreach (var tag in cardData.cardTags)
|
|
{
|
|
if (tag.name == "Archer")
|
|
{
|
|
// Archer can't dog fight.
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
List<Unit> unitsInRange = new List<Unit>();
|
|
for (int i = 0; i < attackRange; ++i)
|
|
{
|
|
int attackXPos = standingCell.xPos + (i+1) * (int)side;
|
|
if (attackXPos >= cellMap.column || attackXPos < 0)
|
|
{
|
|
// Attack Camp
|
|
enemyCamp.TakeDamage(finalAttack);
|
|
return;
|
|
}
|
|
|
|
Cell nextCellInRange = cellMap.GetCell(attackXPos, standingCell.yPos);
|
|
Unit targetUnit = nextCellInRange.standingUnit;
|
|
if (targetUnit)
|
|
{
|
|
if (targetUnit.side != side)
|
|
{
|
|
// Add units to attack list.
|
|
unitsInRange.Add(targetUnit);
|
|
}
|
|
else
|
|
{
|
|
// It is allies. We don't attack it unless we are under some debuff.
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Nothing to attack.
|
|
//Debug.Log("No unit to attack.");
|
|
}
|
|
}
|
|
|
|
|
|
if (side == Side.left)
|
|
{
|
|
unitsInRange = unitsInRange.OrderBy(x => x.standingCell.xPos).ToList<Unit>();
|
|
}
|
|
else
|
|
{
|
|
unitsInRange = unitsInRange.OrderByDescending(x => x.standingCell.xPos).ToList<Unit>();
|
|
}
|
|
|
|
for (int i = 0; i < unitsInRange.Count; i++)
|
|
{
|
|
//Debug.Log(unitsInRange[i].unitName + ": " + unitsInRange[i].standingCell.xPos + " , " + unitsInRange[i].standingCell.yPos);
|
|
// Do attack
|
|
//Debug.Log("Attack!");
|
|
unitsInRange[i].currentDefense -= finalAttack;
|
|
if (unitsInRange[i].currentDefense <= 0)
|
|
{
|
|
unitsInRange[i].standingCell.standingUnit = null;
|
|
unitsInRange[i].gameObject.SetActive(false); // For now
|
|
Unit unit = unitsInRange[i];
|
|
FindObjectOfType<UnitManager>().handleDiedUnit(unit);
|
|
//Debug.Log("Defeat Enemy");
|
|
}
|
|
|
|
break; // Most of units can only attack one target.
|
|
}
|
|
}
|
|
|
|
public bool isUnitAlive()
|
|
{
|
|
return currentDefense > 0;
|
|
}
|
|
|
|
bool checkDestinationCellEmpty(bool retreat = false)
|
|
{
|
|
int currentXPos = standingCell.xPos;
|
|
int movePath = 0;
|
|
|
|
if (retreat)
|
|
{
|
|
movePath = 1 * -(int)side;
|
|
}
|
|
else
|
|
{
|
|
movePath = 1 * (int)side;
|
|
}
|
|
|
|
int destinationXPos = standingCell.xPos + movePath;
|
|
|
|
// Mean the destination cell is the Camp.
|
|
if (!checkPosInMap(destinationXPos))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
destinationCell = cellMap.GetCell(destinationXPos, standingCell.yPos);
|
|
|
|
if (destinationCell.standingUnit == null)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
// Check privous cell is standable if we have more than 1 movement ability.
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void MoveToCell(Cell cell)
|
|
{
|
|
Assert.IsTrue(destinationCell.standingUnit == null, "Trying to move a cell that is already be standing by another unit.");
|
|
|
|
standingCell.standingUnit = null;
|
|
standingCell = cell;
|
|
cell.standingUnit = this;
|
|
}
|
|
|
|
// Check the allies is near by an enemy or not.
|
|
bool inDogFight(Unit unit)
|
|
{
|
|
int checkPos = unit.standingCell.xPos + (int)side * 1;
|
|
|
|
if (!checkPosInMap(checkPos))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var checkCell = cellMap.GetCell(checkPos, standingCell.yPos);
|
|
if (checkCell.standingUnit && checkCell.standingUnit.side != side)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool checkPosInMap(int pos)
|
|
{
|
|
return pos >= 0 && pos < cellMap.column;
|
|
}
|
|
}
|