Mechanics are rules and live in code, beside Luck and Currency. The skill pools are new — the races/classes spec said only 'the stat-appropriate slice' and never enumerated them; each pool is larger than its pick count so the choice is real. The dwarf's +2 vs poison is exposed separately from save() rather than folded into it: baking a conditional into a flat number is how a sheet starts lying. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QYa9u7Kdxv5gX4AnwWexy8
94 lines
3.3 KiB
GDScript
94 lines
3.3 KiB
GDScript
class_name Callings
|
|
extends RefCounted
|
|
## The 7 callings (races-and-classes spec §4). A calling is what a VILLAGE calls you,
|
|
## not what a rulebook calls you — Cutpurse, not Assassin; Bonesetter, not Priest.
|
|
##
|
|
## The skill POOLS are this spec's addition: the races/classes spec said only "drawn
|
|
## from the class's stat-appropriate slice" and never enumerated them. Each pool is the
|
|
## calling's primary-stat skills plus a small adjacent slice, always larger than the
|
|
## pick count so the choice is real.
|
|
##
|
|
## L1 talents are ID STUBS. M5 implements them. armor is a proficiency CATEGORY; real
|
|
## armor is an item (M7).
|
|
|
|
const IDS := ["sellsword", "reaver", "cutpurse", "trapper", "hedge_mage", "bonesetter", "bloodsworn"]
|
|
|
|
const TABLE := {
|
|
"sellsword": {
|
|
"primary": "str", "hit_die": 10, "saves": ["str", "con"],
|
|
"skill_pool": ["athletics", "intimidation", "endurance", "perception"], "skill_count": 2,
|
|
"casting_stat": "", "armor": "heavy", "talent": "second_wind",
|
|
},
|
|
"reaver": {
|
|
"primary": "str", "hit_die": 12, "saves": ["str", "con"],
|
|
"skill_pool": ["athletics", "intimidation", "endurance", "acrobatics"], "skill_count": 2,
|
|
"casting_stat": "", "armor": "medium", "talent": "blood_fury",
|
|
},
|
|
"cutpurse": {
|
|
"primary": "dex", "hit_die": 8, "saves": ["dex", "mag"],
|
|
"skill_pool": ["stealth", "sleight_of_hand", "acrobatics", "perception", "athletics", "intimidation"],
|
|
"skill_count": 4,
|
|
"casting_stat": "", "armor": "light", "talent": "backstab",
|
|
},
|
|
"trapper": {
|
|
"primary": "dex", "hit_die": 10, "saves": ["dex", "con"],
|
|
"skill_pool": ["stealth", "acrobatics", "perception", "endurance", "athletics"], "skill_count": 3,
|
|
"casting_stat": "", "armor": "light", "talent": "set_snare",
|
|
},
|
|
"hedge_mage": {
|
|
"primary": "mag", "hit_die": 6, "saves": ["mag", "fth"],
|
|
"skill_pool": ["sorcery", "perception", "sleight_of_hand", "faith_lore"], "skill_count": 2,
|
|
"casting_stat": "mag", "armor": "none", "talent": "hexbolt",
|
|
},
|
|
"bonesetter": {
|
|
"primary": "fth", "hit_die": 8, "saves": ["fth", "con"],
|
|
"skill_pool": ["faith_lore", "perception", "endurance", "intimidation"], "skill_count": 2,
|
|
"casting_stat": "fth", "armor": "medium", "talent": "mend",
|
|
},
|
|
"bloodsworn": {
|
|
"primary": "fth", "hit_die": 8, "saves": ["fth", "mag"],
|
|
"skill_pool": ["faith_lore", "sorcery", "intimidation", "perception"], "skill_count": 2,
|
|
"casting_stat": "fth", "armor": "light", "talent": "pact_mark",
|
|
},
|
|
}
|
|
|
|
|
|
static func exists(id: String) -> bool:
|
|
return TABLE.has(id)
|
|
|
|
|
|
static func primary(id: String) -> String:
|
|
return str(TABLE.get(id, {}).get("primary", ""))
|
|
|
|
|
|
static func hit_die(id: String) -> int:
|
|
return int(TABLE.get(id, {}).get("hit_die", 0))
|
|
|
|
|
|
static func saves(id: String) -> Array:
|
|
return TABLE.get(id, {}).get("saves", [])
|
|
|
|
|
|
static func skill_pool(id: String) -> Array:
|
|
return TABLE.get(id, {}).get("skill_pool", [])
|
|
|
|
|
|
static func skill_count(id: String) -> int:
|
|
return int(TABLE.get(id, {}).get("skill_count", 0))
|
|
|
|
|
|
static func casting_stat(id: String) -> String:
|
|
return str(TABLE.get(id, {}).get("casting_stat", ""))
|
|
|
|
|
|
static func is_caster(id: String) -> bool:
|
|
return casting_stat(id) != ""
|
|
|
|
|
|
static func armor(id: String) -> String:
|
|
return str(TABLE.get(id, {}).get("armor", ""))
|
|
|
|
|
|
static func talent(id: String) -> String:
|
|
return str(TABLE.get(id, {}).get("talent", ""))
|