full turns

This commit is contained in:
reisenlol 2026-01-11 04:22:09 -08:00
parent 7bd61df481
commit 6ff1531662
No known key found for this signature in database
15 changed files with 879 additions and 100 deletions

View file

@ -20,46 +20,85 @@ public class ActionUIHandler : MonoBehaviour
#endregion
private PlayerEntity selectedEntity;
private RangedWeapon possibleRanged;
public bool opened;
[Header("UI")]
[SerializeField] private Vector3 offset;
[SerializeField] private GameObject actionUI;
[SerializeField] private Button moveButton;
[SerializeField] private Button attackButton;
[SerializeField] private Button reloadButton;
//500 if statements in this script lol
public void ShowUI(PlayerEntity target)
{
opened = true;
possibleRanged = null;
selectedEntity = target;
transform.position = Input.mousePosition + offset;
if (target.currentWeapon.TryGetComponent(out RangedWeapon isRanged))
actionUI.SetActive(true);
UpdateUI();
}
public void UpdateUI()
{
if (!selectedEntity.hasAttacked)
{
possibleRanged = isRanged;
reloadButton.gameObject.SetActive(true);
if (selectedEntity.currentWeapon.TryGetComponent(out RangedWeapon isRanged))
{
possibleRanged = isRanged;
}
if (!isRanged || !isRanged.fired)
{
reloadButton.gameObject.SetActive(false);
attackButton.gameObject.SetActive(true);
}
else
{
reloadButton.gameObject.SetActive(true);
attackButton.gameObject.SetActive(false);
}
}
else
{
reloadButton.gameObject.SetActive(false);
attackButton.gameObject.SetActive(false);
}
if (!selectedEntity.hasMoved || !selectedEntity.hasAttacked)
{
moveButton.gameObject.SetActive(true);
}
else
{
moveButton.gameObject.SetActive(false);
}
if (selectedEntity.hasAttacked && selectedEntity.hasMoved)
{
HideUI();
}
actionUI.SetActive(true);
}
public void HideUI()
{
opened = false;
actionUI.SetActive(false);
}
public void ReloadGun()
{
possibleRanged.Reload();
selectedEntity.hasAttacked = true;
UpdateUI();
}
public void Attack()
{
selectedEntity.Attack();
HideUI();
}
public void SkipTurn()
{
selectedEntity.SkipTurn();
HideUI();
}
public void MoveEntity()
{

View file

@ -3,9 +3,10 @@ using UnityEngine;
public class Enemy : Entity
{
public int turnSpeed;
public int minimumAttackRange;
public float minimumAttackRange;
private PlayerEntity closestPlayer;
//no weapons yet for enemies so...
public float damage;
void Start()
{
turnSpeed = Random.Range(0, 100);
@ -14,10 +15,22 @@ public class Enemy : Entity
[ContextMenu("ForceTurn")]
public void StartTurn()
{
TurnHandler.instance.UpdateTurns();
closestPlayer = FindClosestPlayer();
Debug.Log(closestPlayer);
EnemyMovement.instance.PathfindToTarget(closestPlayer.currentTile.neighbors[Random.Range(0, closestPlayer.currentTile.neighbors.Count)], this);
if (Vector3.Distance(transform.position, closestPlayer.transform.position) > minimumAttackRange)
{
EnemyMovement.instance.PathfindToTarget(closestPlayer.currentTile.neighbors[Random.Range(0, closestPlayer.currentTile.neighbors.Count)], this);
}
else
{
Attack(closestPlayer);
TurnHandler.instance.UpdateTurns();
}
}
protected override void FinishedMovement()
{
base.FinishedMovement();
TurnHandler.instance.UpdateTurns();
}
private PlayerEntity FindClosestPlayer()
@ -32,4 +45,13 @@ public class Enemy : Entity
}
return currentClosestPlayer;
}
protected override void OnKillEffects()
{
TurnHandler.instance.enemyEntities.Remove(this);
Destroy(gameObject);
}
public void Attack(PlayerEntity target)
{
target.TakeDamage(damage);
}
}

View file

@ -21,16 +21,17 @@ public class EnemyMovement : MonoBehaviour
private Queue<TileObject> frontier = new();
private HashSet<TileObject> visited = new();
private Dictionary<TileObject, TileObject> currentPaths = new();
public List<TileObject> pathRequested;
public void PathfindToTarget(TileObject target, Entity selectedEntity)
{
frontier.Clear();
visited.Clear();
currentPaths.Clear();
GetTilesInRange(selectedEntity);
TileObject requestedTile = GetPathToTarget(target, selectedEntity);
selectedEntity.currentTile = requestedTile;
selectedEntity.transform.position = requestedTile.transform.position;
GetPathToTarget(GridManager.instance.FindClosestEmptyTile(target), selectedEntity);
selectedEntity.currentTile.hasUnit = null;
selectedEntity.currentTile.hasUnit = selectedEntity;
StartCoroutine(selectedEntity.MoveToLocation(pathRequested.ToArray()));
}
private void GetTilesInRange(Entity selectedEntity)
{
@ -40,7 +41,7 @@ public class EnemyMovement : MonoBehaviour
TileObject currentTile = frontier.Dequeue();
foreach (TileObject neighboringTiles in currentTile.neighbors)
{
if (!visited.Contains(neighboringTiles))
if (!visited.Contains(neighboringTiles) && (!neighboringTiles.hasUnit && !neighboringTiles.blocked))
{
visited.Add(neighboringTiles);
frontier.Enqueue(neighboringTiles);
@ -48,20 +49,23 @@ public class EnemyMovement : MonoBehaviour
}
}
}
Debug.Log(frontier.Count);
}
private TileObject GetPathToTarget(TileObject target, Entity selectedEntity)
private void GetPathToTarget(TileObject target, Entity selectedEntity)
{
TileObject currentTile = target;
List<TileObject> pathToTarget = new();
pathRequested.Clear();
while (currentTile != selectedEntity.currentTile)
{
pathToTarget.Add(currentTile);
pathRequested.Add(currentTile);
currentTile = currentPaths[currentTile];
}
pathToTarget.Reverse();
int validMovementRange = Mathf.Min(pathToTarget.Count, selectedEntity.maxMovement) - 1;
return pathToTarget[validMovementRange];
pathRequested.Reverse();
int validMovementRange = Mathf.Min(pathRequested.Count, selectedEntity.maxMovement) - 1;
if (pathRequested.Count > selectedEntity.maxMovement)
{
int tilesToRemove = pathRequested.Count - selectedEntity.maxMovement;
pathRequested.RemoveRange(selectedEntity.maxMovement, tilesToRemove);
}
}
}

View file

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;
public class EnemySpawner : MonoBehaviour
{
#region Statication
public static EnemySpawner instance;
private void Awake()
{
if (instance != null && instance != this)
{
Destroy(gameObject);
return;
}
instance = this;
}
#endregion
[SerializeField] private Transform enemyFolder;
[SerializeField] private Enemy[] spawnableEnemies;
public List<Transform> spawnLocationPos;
public List<TileObject> spawnLocations;
public void SpawnEnemy(int amount)//Enemy requestedEnemy)
{
while (amount > 0)
{
Enemy newEnemy = Instantiate(spawnableEnemies[Random.Range(0, spawnableEnemies.Length)], enemyFolder);
TileObject spawnLocation = GridManager.instance.FindClosestEmptyTile(spawnLocations[Random.Range(0, spawnLocations.Count)]);
newEnemy.transform.position = spawnLocation.transform.position;
newEnemy.currentTile = spawnLocation;
newEnemy.currentTile.hasUnit = newEnemy;
TurnHandler.instance.enemyEntities.Add(newEnemy);
amount--;
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f5f6dfe086e56c56f9a2aaa37a63c506

View file

@ -24,6 +24,7 @@ public class Entity : MonoBehaviour
{
OnKillEffects();
}
Debug.Log($"{name} took {damage} damage");
}
public void Heal(float healing)
@ -37,6 +38,11 @@ public class Entity : MonoBehaviour
}
protected virtual void FinishedMovement()
{
currentTile.hasUnit = this;
}
public virtual IEnumerator MoveToLocation(TileObject[] pathToMove)
{
float currentState = 0;
@ -53,5 +59,6 @@ public class Entity : MonoBehaviour
}
yield return null;
}
FinishedMovement();
}
}

View file

@ -28,17 +28,24 @@ public class GridManager : MonoBehaviour
[SerializeField] Camera cam;
private Dictionary<Vector2, TileObject> allTiles = new();
[SerializeField] private Transform grid;
private void Start()
{
GenerateGrid();
cam.transform.position = new Vector3((float)width / 2, (float)height / 2, 0);
foreach (PlayerEntity player in TurnHandler.instance.playerEntities)
{
player.currentTile = GetTile(player.transform.position);
player.currentTile = GetTileFromWorldPos(player.transform.position);
player.currentTile.hasUnit = player;
}
foreach (Enemy enemy in TurnHandler.instance.enemyEntities)
{
enemy.currentTile = GetTile(enemy.transform.position);
enemy.currentTile = GetTileFromWorldPos(enemy.transform.position);
enemy.currentTile.hasUnit = enemy;
}
foreach (Transform spawnLocation in EnemySpawner.instance.spawnLocationPos)
{
EnemySpawner.instance.spawnLocations.Add(GetTileFromWorldPos(spawnLocation.position));
}
}
@ -52,6 +59,7 @@ public class GridManager : MonoBehaviour
TileObject newTile = Instantiate(tilePrefab, pos, Quaternion.identity);
newTile.name = $"Tile {x} {y}";
allTiles[pos] = newTile;
newTile.transform.SetParent(grid);
}
}
GetTileNeighbors();
@ -65,15 +73,15 @@ public class GridManager : MonoBehaviour
{
Vector2 pos = new Vector2(x - ((float)width / 2) + 0.5f, y - ((float)height / 2) + 0.5f);
TileObject currentTile = allTiles[pos];
if (GetTile(pos + Vector2.up)) { currentTile.neighbors.Add(GetTile(pos+Vector2.up));}
if (GetTile(pos + Vector2.down)) { currentTile.neighbors.Add(GetTile(pos+Vector2.down));}
if (GetTile(pos + Vector2.left)) { currentTile.neighbors.Add(GetTile(pos+Vector2.left));}
if (GetTile(pos + Vector2.right)) { currentTile.neighbors.Add(GetTile(pos+Vector2.right));}
if (GetTileFromWorldPos(pos + Vector2.up)) { currentTile.neighbors.Add(GetTileFromWorldPos(pos+Vector2.up));}
if (GetTileFromWorldPos(pos + Vector2.down)) { currentTile.neighbors.Add(GetTileFromWorldPos(pos+Vector2.down));}
if (GetTileFromWorldPos(pos + Vector2.left)) { currentTile.neighbors.Add(GetTileFromWorldPos(pos+Vector2.left));}
if (GetTileFromWorldPos(pos + Vector2.right)) { currentTile.neighbors.Add(GetTileFromWorldPos(pos+Vector2.right));}
}
}
}
public TileObject GetTile(Vector2 pos)
public TileObject GetTileFromWorldPos(Vector2 pos)
{
if (allTiles.TryGetValue(pos, out TileObject tile))
{
@ -81,4 +89,31 @@ public class GridManager : MonoBehaviour
}
return null;
}
public TileObject FindClosestEmptyTile(TileObject requestedTile)
{
if (!requestedTile.hasUnit)
{
return requestedTile;
}
Queue<TileObject> frontier = new();
List<TileObject> visited = new();
frontier.Enqueue(requestedTile);
while (frontier.Count > 0)
{
TileObject currentTile = frontier.Dequeue();
foreach (TileObject neighbor in currentTile.neighbors)
{
if (!visited.Contains(neighbor))
{
if (!neighbor.hasUnit && !neighbor.blocked)
{
return neighbor;
}
visited.Add(neighbor);
frontier.Enqueue(neighbor);
}
}
}
return null;
}
}

View file

@ -42,9 +42,20 @@ public class PlayerEntity : Entity
{
}
protected override void FinishedMovement()
{
base.FinishedMovement();
TurnHandler.instance.UpdateTurns();
if (!ActionUIHandler.instance.opened)
{
ActionUIHandler.instance.ShowUI(this);
}
}
private void OnMouseDown()
{
if ((!hasMoved) && !PlayerEntityMovement.instance.isMoving)
if ((!hasMoved || !hasAttacked) && !PlayerEntityMovement.instance.isMoving)
{
ActionUIHandler.instance.ShowUI(this);
}

View file

@ -60,7 +60,7 @@ public class PlayerEntityMovement : MonoBehaviour
{
Deselect();
}
TileObject newTile = GridManager.instance.GetTile(mouseGridPos);
TileObject newTile = GridManager.instance.GetTileFromWorldPos(mouseGridPos);
if (requestedTile != newTile)
{
requestedTile = newTile;
@ -154,12 +154,19 @@ public class PlayerEntityMovement : MonoBehaviour
{
return false;
}
selectedEntity.currentTile.hasUnit = false;
requestedTile.hasUnit = true;
selectedEntity.currentTile.hasUnit = null;
requestedTile.hasUnit = selectedEntity;
StartCoroutine(selectedEntity.MoveToLocation(pathRequested.ToArray()));
templateObject.SetActive(false);
UncolorGrid();
ActionUIHandler.instance.ShowUI(selectedEntity);
if (!selectedEntity.hasMoved)
{
selectedEntity.hasMoved = true;
}
else
{
selectedEntity.hasAttacked = true;
}
return true;
}

View file

@ -17,7 +17,6 @@ public class RangedWeapon : Weapon
{
if (!fired)
{
fired = true;
AttackEffects();
}
}
@ -39,6 +38,13 @@ public class RangedWeapon : Weapon
if (Input.GetMouseButtonDown(0))
{
CreateProjectile(mousePos);
fired = true;
isAiming = false;
thisEntity.hasAttacked = true;
TurnHandler.instance.UpdateTurns();
}
else if (Input.GetMouseButtonDown(1))
{
isAiming = false;
}
}

View file

@ -9,7 +9,7 @@ public class TileObject : MonoBehaviour
public SpriteRenderer sprite;
[Header("Status")]
public bool blocked = false;
public bool hasUnit = false;
public Entity hasUnit;
private void OnMouseEnter()
{
//highlight.SetActive(true);

View file

@ -21,6 +21,7 @@ public class TurnHandler : MonoBehaviour
#endregion
[Header("Entity Lists")]
public List<PlayerEntity> playerEntities = new();
public List<Enemy> enemyEntities = new();
public enum GameState {PlayerTurn, EnemyTurn}
@ -28,6 +29,9 @@ public class TurnHandler : MonoBehaviour
private int currentEnemy = 0;
[Header("Spawning")]
[SerializeField] private int enemySpawnAmount;
private void SortEnemies()
{
enemyEntities = enemyEntities.OrderBy(o=>o.turnSpeed).ToList();
@ -42,33 +46,59 @@ public class TurnHandler : MonoBehaviour
{
if (currentGameState == GameState.PlayerTurn)
{
bool allDone = true;
foreach (PlayerEntity player in playerEntities)
{
if (!player.hasMoved || !player.hasAttacked)
{
allDone = false;
return;
}
}
if (allDone)
currentGameState = GameState.EnemyTurn;
if (!enemyEntities[0])
{
EndRound();
}
else
{
currentGameState = GameState.EnemyTurn;
enemyEntities[0].StartTurn();
}
}
else if (currentGameState == GameState.EnemyTurn)
{
enemyEntities[currentEnemy].StartTurn();
currentEnemy++;
if (currentEnemy > enemyEntities.Count - 1)
{
currentGameState = GameState.PlayerTurn;
foreach (PlayerEntity player in playerEntities)
{
player.hasMoved = false;
player.hasAttacked = false;
}
EndRound();
return;
}
enemyEntities[currentEnemy].StartTurn();
}
}
private void EndRound()
{
EnvironmentTurn();
currentEnemy = 0;
currentGameState = GameState.PlayerTurn;
foreach (PlayerEntity player in playerEntities)
{
player.hasMoved = false;
player.hasAttacked = false;
}
}
public void EnvironmentTurn()
{
EnemySpawner.instance.SpawnEnemy(enemySpawnAmount);
}
public void SkipAll()
{
foreach (PlayerEntity player in playerEntities)
{
player.hasMoved = true;
player.hasAttacked = true;
}
UpdateTurns();
}
}