Implement basic structure for combat system and refactor code

This commit is contained in:
2026-07-03 13:14:36 +02:00
parent 754f81eb4c
commit d98d34ec3f
78 changed files with 1212 additions and 13 deletions
+20
View File
@@ -0,0 +1,20 @@
using KernelPanic.Data;
namespace KernelPanic.Combat
{
/// <summary>
/// Represents one runtime card and its per-combat mutable state.
/// </summary>
public sealed class CardInstance
{
public CardInstance(CardDefinition definition)
{
Definition = definition;
}
public CardDefinition Definition { get; }
public int TemporaryCostDelta { get; set; }
public bool IsBroken { get; set; }
public bool IsLocked { get; set; }
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c05e61a09404ee046a6771f8ac75803c
+21
View File
@@ -0,0 +1,21 @@
using System.Collections.Generic;
namespace KernelPanic.Combat
{
/// <summary>
/// Carries runtime combat references needed by card effects during resolution.
/// </summary>
public sealed class CombatContext
{
public CombatContext(CombatantState source, IReadOnlyList<CombatantState> targets, CombatManager combatManager)
{
Source = source;
Targets = targets;
CombatManager = combatManager;
}
public CombatantState Source { get; }
public IReadOnlyList<CombatantState> Targets { get; }
public CombatManager CombatManager { get; }
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2eed81ad20b42a447858691a49666804
+56
View File
@@ -0,0 +1,56 @@
using KernelPanic.Core;
using UnityEngine;
namespace KernelPanic.Combat
{
/// <summary>
/// Owns the combat turn phase state machine and coordinates combat lifecycle transitions.
/// </summary>
public sealed class CombatManager : MonoBehaviour
{
[SerializeField] private TurnPhase currentPhase = TurnPhase.Boot;
public TurnPhase CurrentPhase => currentPhase;
public void StartCombat()
{
SetPhase(TurnPhase.Boot);
}
public void AdvancePhase()
{
TurnPhase nextPhase = GetNextPhase(currentPhase);
SetPhase(nextPhase);
}
public void EndPlayerTurn()
{
SetPhase(TurnPhase.Interpret);
}
private void SetPhase(TurnPhase nextPhase)
{
TurnPhase previousPhase = currentPhase;
currentPhase = nextPhase;
GameEvents.RaisePhaseChanged(new PhaseChangedEvent(previousPhase, nextPhase));
EnterPhase(nextPhase);
}
private static TurnPhase GetNextPhase(TurnPhase phase)
{
return phase switch
{
TurnPhase.Boot => TurnPhase.Allocate,
TurnPhase.Allocate => TurnPhase.Execute,
TurnPhase.Execute => TurnPhase.Interpret,
TurnPhase.Interpret => TurnPhase.EnemyProcess,
TurnPhase.EnemyProcess => TurnPhase.GarbageCollection,
_ => TurnPhase.Allocate
};
}
private void EnterPhase(TurnPhase phase)
{
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 9f87432412de1ee46bf7d4c9c530d4c6
+28
View File
@@ -0,0 +1,28 @@
using System.Collections.Generic;
using KernelPanic.Core;
namespace KernelPanic.Combat
{
/// <summary>
/// Stores mutable combat stats and statuses for a player or enemy.
/// </summary>
public sealed class CombatantState
{
private readonly Dictionary<StatusType, int> activeStatuses = new();
public CombatantState(int maxUptime, int ram, int cycles)
{
MaxUptime = maxUptime;
CurrentUptime = maxUptime;
Ram = ram;
Cycles = cycles;
}
public int CurrentUptime { get; set; }
public int MaxUptime { get; set; }
public int Shield { get; set; }
public int Ram { get; set; }
public int Cycles { get; set; }
public IReadOnlyDictionary<StatusType, int> ActiveStatuses => activeStatuses;
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 93b1080022652b542903e204d36a64f8
+49
View File
@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
namespace KernelPanic.Combat
{
/// <summary>
/// Manages draw, discard, and exhaust piles for a combat deck.
/// </summary>
public sealed class DeckController
{
private readonly List<CardInstance> drawPile = new();
private readonly List<CardInstance> discardPile = new();
private readonly List<CardInstance> exhaustPile = new();
public IReadOnlyList<CardInstance> DrawPile => drawPile;
public IReadOnlyList<CardInstance> DiscardPile => discardPile;
public IReadOnlyList<CardInstance> ExhaustPile => exhaustPile;
public void Initialize(IEnumerable<CardInstance> cards)
{
throw new NotImplementedException();
}
public IReadOnlyList<CardInstance> Draw(int count)
{
throw new NotImplementedException();
}
public void Discard(CardInstance card)
{
throw new NotImplementedException();
}
public void Exhaust(CardInstance card)
{
throw new NotImplementedException();
}
public void ShuffleDrawPile()
{
throw new NotImplementedException();
}
public void ReshuffleDiscardIntoDraw()
{
throw new NotImplementedException();
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 6683933e853af334ba19e658b13c878d
+41
View File
@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
namespace KernelPanic.Combat
{
/// <summary>
/// Manages cards currently held in hand with a RAM-based capacity.
/// </summary>
public sealed class HandController
{
private readonly List<CardInstance> cards = new();
public HandController(int ramCapacity)
{
RamCapacity = ramCapacity;
}
public int RamCapacity { get; private set; }
public IReadOnlyList<CardInstance> Cards => cards;
public bool CanAdd(CardInstance card)
{
throw new NotImplementedException();
}
public void Add(CardInstance card)
{
throw new NotImplementedException();
}
public bool Remove(CardInstance card)
{
throw new NotImplementedException();
}
public void Clear()
{
throw new NotImplementedException();
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: bece1c6fddc2c63489bf129bf6295a31
+10
View File
@@ -0,0 +1,10 @@
namespace KernelPanic.Combat
{
/// <summary>
/// Represents a runtime card effect that can apply itself to a combat context.
/// </summary>
public interface ICardEffect
{
void Execute(CombatContext context);
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 886be8d59396e5e488eea3ea58445fb4
+11
View File
@@ -0,0 +1,11 @@
namespace KernelPanic.Combat
{
/// <summary>
/// Provides a common contract for card resolution tracks.
/// </summary>
public interface IResolutionTrack
{
void Enqueue(CardInstance card);
void Resolve(CombatContext context);
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 5d296d1160df6d747adaeec9ef68c710
+30
View File
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
namespace KernelPanic.Combat
{
/// <summary>
/// Stores played cards in FIFO order for resolution during the Interpret phase.
/// </summary>
public sealed class InterpreterQueue : IResolutionTrack
{
private readonly Queue<CardInstance> queuedCards = new();
public int Count => queuedCards.Count;
public void Enqueue(CardInstance card)
{
throw new NotImplementedException();
}
public void Resolve(CombatContext context)
{
throw new NotImplementedException();
}
public void Clear()
{
throw new NotImplementedException();
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 13c99cf765e7e8b48a58afbacc8a5440
+30
View File
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
namespace KernelPanic.Combat
{
/// <summary>
/// Stores played cards in LIFO order until explicitly force-evaluated.
/// </summary>
public sealed class LazyStack : IResolutionTrack
{
private readonly Stack<CardInstance> stackedCards = new();
public int Count => stackedCards.Count;
public void Enqueue(CardInstance card)
{
throw new NotImplementedException();
}
public void Resolve(CombatContext context)
{
throw new NotImplementedException();
}
public void ForceEvaluate(CombatContext context)
{
throw new NotImplementedException();
}
}
}
+2
View File
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 556859e6fac10a24bb4a60165fd82157
+20
View File
@@ -0,0 +1,20 @@
using System;
namespace KernelPanic.Combat
{
/// <summary>
/// Resolves cards immediately when they are added to the native track.
/// </summary>
public sealed class NativeTrack : IResolutionTrack
{
public void Enqueue(CardInstance card)
{
throw new NotImplementedException();
}
public void Resolve(CombatContext context)
{
throw new NotImplementedException();
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b662e4e1a38b1554084a063fd3d415e2
@@ -0,0 +1,26 @@
using System;
using KernelPanic.Core;
namespace KernelPanic.Combat
{
/// <summary>
/// Applies, ticks, and expires status effects on a combatant.
/// </summary>
public sealed class StatusEffectController
{
public void Apply(CombatantState target, StatusType statusType, int stacks)
{
throw new NotImplementedException();
}
public void Tick(CombatantState target)
{
throw new NotImplementedException();
}
public void Expire(CombatantState target, StatusType statusType)
{
throw new NotImplementedException();
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 5f91b8d9171889f4996bb3106d97f1f6