TacticsUnit
namespace Griff.Modules.Tactics;
public sealed class TacticsUnit : Component, IGridDriver, ITurnReady, IPlaytestReportA unit in a tactics game, with no code: on its team’s turn you pick it, see the cells it can walk to (and the cells it can hit from them), then click one to walk there and click an enemy in reach to attack it. Each turn it moves up to Move cells, around walls and other units, then attacks something MinRange to Range steps away for Damage, or waits. Give it a TurnTaker with 1 action naming its team: attacking or waiting uses the action, so once every unit on a team has had its go, the turn passes. A TacticsControls in the scene does the picking and draws the ranges. On a team the computer plays (the turn order’s Computer Teams), the computer takes each unit’s go in turn, the way its Stance says: the best attack it can make (a foe it can finish off first, then the weakest), or a walk toward the nearest foe.
Its enemies are the units on other teams (with no teams, every other unit) and anything else with a Health on another team (see Teams), or whatever with Health is on its Layers. Ranges are counted in steps and reach over walls. Units block each other, friend or foe. In a network game the host moves the units: a player’s clicks are sent to it.
This is a component: its saved properties are on its component page.
Properties
Section titled “Properties”AttackSound
Section titled “AttackSound”public string? AttackSound { get; set; }A sound played with each attack, e.g. “Sounds/hit.wav”.
CanAct
Section titled “CanAct”public bool CanAct { get; }True while it can take its go: it’s its team’s turn (if it takes turns) and it hasn’t used its action.
Damage
Section titled “Damage”public float Damage { get; set; }Hit points each attack takes away.
DamageRoll
Section titled “DamageRoll”public string? DamageRoll { get; set; }Dice rolled for each hit’s damage in place of Damage, e.g. “1d8+2”; empty hits for Damage every time. Table Values sets it from a dice column given for Damage.
HasMoved
Section titled “HasMoved”public bool HasMoved { get; set; }True once it has walked this go and has yet to attack or wait. The game clears it as its go ends and as each of its team’s turns starts.
HitEffect
Section titled “HitEffect”public string? HitEffect { get; set; }A prefab spawned on what it hits, e.g. “Sparkle”: a burst of particles, a damage number.
HitStop
Section titled “HitStop”public float HitStop { get; set; }Freezes the game for this many seconds when an attack lands, so it hits hard. 0 for none.
IsDone
Section titled “IsDone”public bool IsDone { get; }True on its team’s turn once it has had its go: drawn dimmed until its team’s next turn.
IsWalking
Section titled “IsWalking”public bool IsWalking { get; }True while it’s walking to where it was sent.
Layers
Section titled “Layers”public string? Layers { get; set; }The collision layers it attacks, e.g. “Enemy”. Empty attacks the units on other teams (see TurnTaker).
MinRange
Section titled “MinRange”public int MinRange { get; set; }How close something has to be at least for it to hit it: 2 for an archer that can’t hit what’s next to it.
public int Move { get; set; }How many cells it can walk in a turn, around walls and other units.
public int Range { get; set; }How many steps away it can hit: 1 is next to it, more for an archer or a mage.
Reachable
Section titled “Reachable”public IReadOnlyList<ValueTuple<int, int>> Reachable { get; }The cells it can walk to on its go, column then row on its map (row 0 at the top), not counting the one it stands in. The game keeps it up to date while it can act and hasn’t moved; empty otherwise.
Stance
Section titled “Stance”public TacticsStance Stance { get; set; }How it plays when the computer plays its team (see ComputerTeams): Charge goes after the nearest foe, Guard stays put until a foe comes within a walk and a hit, Hold never walks and only attacks from where it stands.
Targets
Section titled “Targets”public IReadOnlyList<Entity> Targets { get; }What it can attack from where it stands now. The game keeps it up to date while it can act.
Methods
Section titled “Methods”Attack
Section titled “Attack”public void Attack(Entity target)Attacks target at the start of the next frame, as a click on it does: from where it stands if it’s in reach, else walking first to the nearest cell it can hit it from (if it hasn’t moved yet).
AttacksLayer
Section titled “AttacksLayer”public bool AttacksLayer(string? layer)True if it attacks things on collision layer layer (always, with no Layers).
MoveTo
Section titled “MoveTo”public void MoveTo(ValueTuple<int, int> cell)Walks to cell (one of its Reachable cells) at the start of the next frame, as a click there does. It still has to attack or wait afterwards; with nothing in reach from there, its go ends by itself.
RollDamage
Section titled “RollDamage”public float RollDamage()The damage of one hit: DamageRoll rolled, or Damage.
UndoMove
Section titled “UndoMove”public void UndoMove()Takes back the walk it took this go, if it hasn’t attacked or waited yet, putting it back where it was.
public void Wait()Ends its go where it stands, without attacking, at the start of the next frame.
Events
Section titled “Events”Attacked
Section titled “Attacked”public event Action<TacticsUnit, Entity>? AttackedRaised as it attacks, with what it attacks.
public event Action<TacticsUnit>? DoneRaised as its go ends, after it attacks or waits.
public event Action<TacticsUnit, ValueTuple<int, int>>? MovedRaised as it sets off on a walk, with the cell it’s going to.