Card Design and Naming Standards - UQcsse3200/2026-studio-3 GitHub Wiki
Shared standards for authoring Team 6 card configurations.
Maintainer: Team 6 Member 1.
Task: #160 — Guardian Cards and Card Library Standards
Related pages:
- Card Data Model
- Card Loading and Validation
- Round 2 Master Card List
- Card Art Specification
- Card Upgrade Standard
Artwork standards are not covered here. Dimensions, format, file size, the shared prompt and the asset audit all live on Card Art Specification, owned by Member 4. This page covers IDs, configuration fields and effect/target rules only.
Last verified against the repository: 15 September 2026.
- Card IDs are lowercase
snake_case, with no spaces and no surrounding whitespace — for examplewarding_sweep. - IDs must be unique across the whole library. Check against every card already in
cards.json, not just your own set. - No theme prefix is used. Introducing one would require group agreement first.
- The artwork filename must match the card ID exactly, including case:
images/cards/<card_id>.png. - All card configurations live in a single file,
source/core/assets/configs/cards.json. Multi-file loading is not supported.
| Field | Type | Rule |
|---|---|---|
id |
String | Non-blank, unique, lowercase snake_case
|
name |
String | Non-blank; English display name |
description |
String | Rules text matching the effects, values, targets and durations |
cost |
int | Zero or greater; energy cost |
type |
CardType |
ATTACK, SKILL, POWER, STATUS or CURSE
|
rarity |
Rarity |
COMMON, UNCOMMON or RARE
|
target |
TargetType |
SELF, SINGLE_ENEMY or ALL_ENEMIES
|
effects |
EffectConfig[] | Non-empty; listed in intended resolution order |
texturePath |
String | Non-blank; images/cards/ + card ID + .png
|
The image field is named texturePath, not artworkPath.
Each entry in effects has three fields:
| Field | Type | Rule |
|---|---|---|
type |
EffectType | See the table below |
value |
int | Strictly positive |
duration |
int | Positive if the effect uses duration; otherwise exactly 0
|
duration is per effect. target is per card — there is no per-effect target, and every effect on a card must be valid for that card's target.
The EffectType enum currently has ten constants. usesDuration() determines whether duration must be positive or zero.
| Effect | usesDuration() |
Behaviour |
|---|---|---|
DAMAGE |
false |
Immediate damage |
BLOCK |
false |
Immediate block |
HEAL |
false |
Immediate healing |
STRENGTH |
false |
Increases damage dealt for the rest of combat |
SUNDER |
false |
Immediate reduction of the target's armour pool |
PIERCE |
false |
Immediate damage ignoring block and armour |
ENERGY_GAIN |
false |
Restores player energy, capped at maximum |
POISON |
true |
Damage over time at the start of the target's turn |
VULNERABLE |
true |
Increases damage the target receives while active |
FEEBLE |
true |
Reduces the target's damage output by 25% while active |
CLEANSE arrives with the Survival set and removes negative statuses; see Survival Cards.
value does not mean the same thing for every effect.
- For
DAMAGE,BLOCK,HEAL,PIERCE,SUNDERandENERGY_GAINit is the magnitude. - For
VULNERABLEandFEEBLEit is not a multiplier or a stack count. Their modifiers are fixed —VULNERABLEat ×1.5 andFEEBLEat ×0.75. The schema still requires a strictly positive value, but raising it does not strengthen the effect. Do not write rules text implying that a higher value means a larger percentage.
Every effect on a card must be valid for that card's target.
| Target | Valid effects |
|---|---|
SELF |
BLOCK, HEAL, STRENGTH, ENERGY_GAIN, CLEANSE, FORTIFY
|
SINGLE_ENEMY or ALL_ENEMIES
|
DAMAGE, PIERCE, SUNDER, POISON, VULNERABLE, FEEBLE
|
A single card cannot mix enemy damage with self block under the current schema, because there is one target for the whole card.
CardValidator.isCompatibleWithTarget() now runs on base effects and upgrade effects alike, using the table above. For enemy targets it accepts DAMAGE, PIERCE, SUNDER and any effect that uses a duration; for SELF it accepts BLOCK, HEAL, STRENGTH, ENERGY_GAIN, CLEANSE and FORTIFY. Verified against main at d06674fb, 13 October 2026.
Upgrades use an inline upgrade object nested in the card's config, with name, description, cost, rarity and effects. There is no separate <id>_upgraded config entry. Upgraded card names use a + suffix — Strike+, not strike_upgraded. Upgrade state is tracked by CardInstance.isUpgraded().
What an upgrade may and may not change is on Card Upgrade Standard.
Effects resolve in the order they appear in the effects array, so the order is a design decision rather than a formatting choice.
takeDamage() processes block → armour → health. A card combining SUNDER with DAMAGE should therefore list SUNDER first, or the damage will be absorbed by the armour that is about to be removed. unseal_the_breach is ordered [SUNDER, DAMAGE] for this reason.
updateStatusEffects() in CombatStatsComponent has no production caller anywhere in source/core/src/main — verified 15 September 2026, with a TODO at CombatStatsComponent.java:340 recording that it still needs wiring to Team 3's turn event.
POISON, VULNERABLE and FEEBLE therefore do not expire. Treat any card whose balance depends on a status running out as provisional. The same root cause means armour removed by SUNDER does not return, because clearArmour() and resetBlock() also have no production call sites.
Tracked as Team 7's #161. Affected cards are listed on Round 2 Master Card List.
Adding a constant to EffectType requires sign-off from Team 5, who own combat resolution. A new effect is not delivered when the enum constant exists — it also needs handling in the combat paths, validator acceptance, and test coverage.
Three new effects were added during Round 2: SUNDER (Guardian), PIERCE (Corruption) and ENERGY_GAIN (Astral). CLEANSE (Survival) is implemented but not yet merged.
Do
- Use exact field and enum names, and valid effect/target combinations.
- Check ID uniqueness against the whole library before committing.
- Order the
effectsarray to match intended resolution. - Make rules text match what the effects actually do, including the fixed
VULNERABLEandFEEBLEmodifiers. - Record any integration behaviour you could not verify.
- Keep local test examples out of the official card count.
Don't
- Don't invent card draw, energy refunds, conditional triggers or per-effect targets — none are supported by the current schema.
- Don't combine enemy damage and self block on one card.
- Don't infer executable behaviour from
CardTypenames or flavour text. - Don't treat a proposed texture path, an agreed design, or a row in a tracking table as completed implementation.