Skip to content

Card System Diagrams

josie268 edited this page Sep 22, 2026 · 3 revisions

Card System Diagrams

Maintained by hezhenyu (Member 1). Diagrams verified against main on 16 September 2026.

Card data layer

The card data layer deserialises each JSON card into one CardConfig, whose ordered effects and optional embedded upgrade are represented by EffectConfig and CardUpgradeConfig. The loader owns file/JSON structure checks and collection-wide duplicate-ID detection, while CardValidator owns per-card validation; a successfully loaded base card therefore has one or more effects and may contain one upgrade, whose own effects are also ordered and non-empty.

classDiagram
direction LR

namespace com_csse3200_game_cards_configs {
  class CardConfig {
    +String id
    +String name
    +String description
    +int cost
    +CardType type
    +Rarity rarity
    +TargetType target
    +EffectConfig[] effects
    +String texturePath
    +CardUpgradeConfig upgrade
  }

  class EffectConfig {
    +EffectType type
    +int value
    +int duration
  }

  class CardUpgradeConfig {
    +String name
    +String description
    +int cost
    +Rarity rarity
    +EffectConfig[] effects
  }
}

namespace com_csse3200_game_cards {
  class CardType {
    <<enumeration>>
    ATTACK
    SKILL
    POWER
    STATUS
    CURSE
  }

  class Rarity {
    <<enumeration>>
    COMMON
    UNCOMMON
    RARE
  }

  class TargetType {
    <<enumeration>>
    SELF
    SINGLE_ENEMY
    ALL_ENEMIES
  }

  class EffectType {
    <<enumeration>>
    DAMAGE
    BLOCK
    HEAL
    POISON
    VULNERABLE
    FEEBLE
    STRENGTH
    SUNDER
    ENERGY_GAIN
    PIERCE
    CLEANSE
    +boolean usesDuration()
  }

  class CardValidator {
    <<utility>>
    +List~String~ validate(CardConfig card)
    +boolean isValid(CardConfig card)
  }

  class CardConfigLoader {
    <<utility>>
    +String DEFAULT_CARD_FILE
    +List~CardConfig~ loadCards()
    +List~CardConfig~ loadCards(String filename)
  }
}

CardConfig "1" *-- "1..*" EffectConfig : effects
CardConfig "1" *-- "0..1" CardUpgradeConfig : upgrade
CardUpgradeConfig "1" *-- "1..*" EffectConfig : effects

CardConfig --> CardType : type
CardConfig --> Rarity : rarity
CardConfig --> TargetType : target
EffectConfig --> EffectType : type
CardUpgradeConfig --> Rarity : rarity

CardConfigLoader ..> CardConfig : parses and returns
CardConfigLoader ..> CardValidator : delegates validate(card)
CardValidator ..> CardConfig : validates

note for CardConfig "Package: com.csse3200.game.cards.configs<br/>upgrade is an embedded field, not a separate card entry."
note for CardUpgradeConfig "Package: com.csse3200.game.cards.configs<br/>The upgraded variant inherits id, type, target and texturePath from its containing CardConfig."
note for EffectConfig "Package: com.csse3200.game.cards.configs"
note for CardType "Package: com.csse3200.game.cards"
note for Rarity "Package: com.csse3200.game.cards"
note for TargetType "Package: com.csse3200.game.cards"
note for EffectType "Package: com.csse3200.game.cards<br/>usesDuration() is true for POISON, VULNERABLE and FEEBLE; false for every other constant."
note for CardConfigLoader "Package: com.csse3200.game.cards<br/>Checks required base and upgrade fields; parses JSON into CardConfig; detects duplicate card IDs; delegates each parsed card to CardValidator.validate(card)."
note for CardValidator "Package: com.csse3200.game.cards<br/>Validates one CardConfig independently; collection-level checks such as duplicate IDs belong to the loader or card library."
Loading

unseal_the_breach resolution and application

CardEffectResolver.resolve(...) walks card.effects by index, so unseal_the_breach resolves SUNDER (sequence 0) before DAMAGE (sequence 1). Application therefore strips armour with the SUNDER value before passing the DAMAGE value to takeDamage(value); the diagram does not assert who invokes either application implementation.

sequenceDiagram
  actor Caller
  participant Resolver as CardEffectResolver
  participant Executor as EffectExecutor
  participant Resolved as ResolvedCardEffect
  participant Application as Effect application
  participant Stats as CombatStatsComponent

  Caller->>Resolver: resolve(card, context)
  Note over Resolver,Resolved: card.effects[0] = SUNDER(value)<br/>card.effects[1] = DAMAGE(value)
  loop each effect index i in array order
    Resolver->>Executor: resolve(card.id, card.effects[i], card.target, i, context)
    alt i = 0: SUNDER
      Executor-->>Resolver: ResolvedCardEffect(..., SUNDER, ..., value, 0, 0)
    else i = 1: DAMAGE
      Executor-->>Resolver: ResolvedCardEffect(..., DAMAGE, ..., value, 0, 1)
    end
  end

  Note over Application,Stats: SUNDER handling is duplicated in<br/>BattleController at line 795 and<br/>Team1EnemyStateAdapter at line 85:<br/>setArmour(getArmour() - effect.value())<br/>See note 2 for their differing effect-set support.
  Application->>Stats: getArmour()
  Stats-->>Application: armour
  Application->>Stats: setArmour(armour - value)
  Note over Stats: setArmour(int armour) stores Math.max(armour, 0)
  Application->>Stats: takeDamage(value)
  Stats->>Stats: absorbDamageWithBlock(value)
  Stats->>Stats: absorbDamageWithArmour(afterBlock)
  Stats->>Stats: setHealth(Math.max(health - remainingDamage, 0))
Loading
  1. Ordering: takeDamage() resolves block, then armour, then health, so [DAMAGE, SUNDER] would let armour absorb the hit before SUNDER stripped it. Commit 6cfc7249 reordered the array to [SUNDER, DAMAGE].
  2. Known divergence: The paths support different effect sets and handle unsupported types differently: BattleController silently ignores them, while Team1EnemyStateAdapter throws an IllegalArgumentException. FEEBLE is accepted by the adapter and silently dropped by the legacy controller.
  3. PIERCE and SUNDER: takePiercingDamage() bypasses block and armour and changes health directly, so stripping armour first gives PIERCE no benefit.

Table of Contents

Home

Game Engine

Getting Started

Entities and Components

Service Locator

Loading Resources

Logging

Unit Testing

Debug Terminal

Input Handling

UI

Animations

Audio

AI

Physics

Game Screens and Areas

Terrain

Concurrency & Threading

Settings

Encounters
Tutorials and Contextual Help (Team 2)
Cards (Team 6)
Story (Team 6)
Level design, battle system, turn order, spawn (Team 3)
Cards, Save/Load & Bestiary (Team 5)
Rewards and Battle Settlement (Team 7)

Troubleshooting

MacOS Setup Guide

Clone this wiki locally