Repository navigation
Cool Down System
Each card in the the player deck is now has a unique card ID attached to it via the cardInstanceFactory
public void addCard(String cardId) {
if (!canAddCard(cardId)) {
throw new IllegalArgumentException("cardId must be registered");
}
cards.add(cardInstanceFactory.create(cardId));
}
This allow the cards to have a "cool down" that disable the card when played for x amount of runs.
This disablement of card is done through the UI level; the status and tracking is stored in CardPlayService (specifically its internal CardCooldownTracker, backed by BattleDeck's discard pile). The UI never queries the tracker directly, it just checks whether a card's exact instance is currently in the discard pile, and renders that slot as dimmed and non-interactive if so.
New, instance-aware methods sit alongside them for code that actually needs to tell copies apart:
| Method | Purpose |
|---|---|
PlayerDeck.getCards() |
every owned card, as instances |
BattleDeck.getHandInstances() / getDiscardPileInstances() / getDrawPileInstances()
|
per-pile snapshots, as instances |
BattleDeck.getAllInstances() |
every card in the battle deck, any pile |
BattleDeck.discardCardInstance(cardId) |
discards the first match and returns which instance moved |
BattleDeck.retrieveInstanceFromDiscard(instance) |
moves one exact instance back to hand, not "first match by ID" |
BattleDeck.setHandInstances(instances) |
replaces the hand with an exact set of instances (used by deck rearrange) |
All of these return/accept com.csse3200.game.cards.runtime.CardInstance.
sequenceDiagram
participant Player
participant CardPlayService
participant BattleDeck
participant CardCooldownTracker
Player->>CardPlayService: playCard("strike")
CardPlayService->>BattleDeck: discardCardInstance("strike")
BattleDeck-->>CardPlayService: the exact CardInstance that moved
CardPlayService->>CardCooldownTracker: trackDiscard(instance, rounds)
Note over CardCooldownTracker: entries: [instance → roundsRemaining]
loop Every player round start
CardPlayService->>CardCooldownTracker: tickRoundAndRetrieve()
CardCooldownTracker->>CardCooldownTracker: roundsRemaining-- for every entry
alt roundsRemaining <= 0
CardCooldownTracker->>BattleDeck: retrieveInstanceFromDiscard(instance)
BattleDeck-->>CardCooldownTracker: moved back to hand
CardCooldownTracker-->>CardPlayService: cardId retrieved
end
end
graph LR
A["Card played"] --> B["BattleDeck.discardCardInstance"]
B --> C["Instance moves: hand → discard"]
C --> D["CardCooldownTracker starts counting"]
D --> E{"Round tick:<br/>roundsRemaining reaches 0?"}
E -- no --> D
E -- yes --> F["BattleDeck.retrieveInstanceFromDiscard"]
F --> G["Instance moves: discard → hand"]
G --> H["BattleScreen slot for that instance<br/>renders enabled again"]
The deck-rearrange popup (DeckEditorComponent) lets the player pick which 5 CardInstances make
up their hand from their entire pool (draw pile + hand + discard pile combined). A card currently
on cooldown can be selected too, but since it can't physically be "in hand" while still cooling
down, CardPlayService.rearrangeHand:
- moves only the not-currently-discarded part of the selection into the real battle-deck hand
(
BattleDeck.setHandInstances), and - leaves any selected-but-discarded instances exactly where they are, cooldown untouched.
The full selection (including the still-cooling-down picks) becomes the new handRowOrder in
BattleScreen, so a reserved cooldown card shows up dimmed in its slot and automatically
un-dims itself the moment CardCooldownTracker retrieves it. No special-casing needed, because
that's just the normal dimming check described above.