Template:HeroDef: Difference between revisions
obelisk-bot: uploading initial Cargo templates |
obelisk-bot: uploading initial Cargo templates |
||
| Line 5: | Line 5: | ||
The bot emits these per-hero blocks at <code>Data:Hero/<id></code>: | The bot emits these per-hero blocks at <code>Data:Hero/<id></code>: | ||
# <code>{{HeroDef | id=… | name=… | motto=… | desc=… | start_skills=… | start_magics=… | …}}</code> — main row. <code>start_skills</code> and <code>start_magics</code> are comma-joined SID lists inline on this row (no side tables for them). | # <code><nowiki>{{HeroDef | id=… | name=… | motto=… | desc=… | start_skills=… | start_magics=… | …}}</nowiki></code> — main row. <code>start_skills</code> and <code>start_magics</code> are comma-joined SID lists inline on this row (no side tables for them). | ||
# <code>{{TranslationDef | type=hero | target_id=<id> | …}}</code> — name/desc translation (per D-026). | # <code><nowiki>{{TranslationDef | type=hero | target_id=<id> | …}}</nowiki></code> — name/desc translation (per D-026). | ||
# <code>{{TranslationDef | type=hero_motto | target_id=<id> | …}}</code> — motto translation (separate row, kept off the schema-specialization path; per D-027). | # <code><nowiki>{{TranslationDef | type=hero_motto | target_id=<id> | …}}</nowiki></code> — motto translation (separate row, kept off the schema-specialization path; per D-027). | ||
# <code>{{HeroStartSquadDef | …}}</code> × N — one per starting squad slot (primary + alt collapsed via <code>variant</code> discriminator). | # <code><nowiki>{{HeroStartSquadDef | …}}</nowiki></code> × N — one per starting squad slot (primary + alt collapsed via <code>variant</code> discriminator). | ||
== Schema == | == Schema == | ||
| Line 15: | Line 15: | ||
| name = String | | name = String | ||
| motto = Wikitext | | motto = Wikitext | ||
| | | description = Wikitext | ||
| name_sid = String | | name_sid = String | ||
| motto_sid = String | | motto_sid = String | ||
| Line 62: | Line 62: | ||
| name = String | | name = String | ||
| motto = Wikitext | | motto = Wikitext | ||
| | | description = Wikitext | ||
| name_sid = String | | name_sid = String | ||
| motto_sid = String | | motto_sid = String | ||
| Line 164: | Line 164: | ||
| name = {{{name|}}} | | name = {{{name|}}} | ||
| motto = {{{motto|}}} | | motto = {{{motto|}}} | ||
| | | description = {{{description|}}} | ||
| name_sid = {{{name_sid|}}} | | name_sid = {{{name_sid|}}} | ||
| motto_sid = {{{motto_sid|}}} | | motto_sid = {{{motto_sid|}}} | ||
Revision as of 00:02, 13 May 2026
One row per hero (~177 in the 2026-05-03 corpus: 108 faction + 46 campaign + 21 tutorial + 2 custom-map). Carries the per-hero identity (name/motto/desc), the link to the parent HeroClass, and any class-default fields the hero diverges on. Faction heroes match their class template exactly, so their override fields are sparse-emitted (absent); campaign and tutorial heroes routinely override stats, start_level, and
attacks_times_before.
The bot emits these per-hero blocks at Data:Hero/<id>:
{{HeroDef | id=… | name=… | motto=… | desc=… | start_skills=… | start_magics=… | …}}— main row.start_skillsandstart_magicsare comma-joined SID lists inline on this row (no side tables for them).{{TranslationDef | type=hero | target_id=<id> | …}}— name/desc translation (per D-026).{{TranslationDef | type=hero_motto | target_id=<id> | …}}— motto translation (separate row, kept off the schema-specialization path; per D-027).{{HeroStartSquadDef | …}}× N — one per starting squad slot (primary + alt collapsed viavariantdiscriminator).
Schema
This template defines the table "Hero". View table.
{{HeroDef
| id = String
| name = String
| motto = Wikitext
| description = Wikitext
| name_sid = String
| motto_sid = String
| desc_sid = String
| class_id = String <!-- joins HeroClass.id (e.g. magic_demon) -->
| faction = String <!-- denormalized from class -->
| class_type = String (allowed values=might,magic)
| icon = String
| specialization_id = String <!-- joins HeroSpecialization.id -->
| source_path = String
<!-- Inline list-of-SID columns (always present; empty when none).
start_skills and start_skill_levels are positionally aligned —
the Nth element of start_skill_levels is the level for the Nth
skill SID in start_skills. -->
| start_skills = List (,) of String <!-- joins future Skill.id -->
| start_skill_levels = List (,) of Integer <!-- positionally aligned with start_skills -->
| start_magics = List (,) of String <!-- joins future Spell.id -->
<!-- Note: spell level / isLearned are dropped (constant in the
2026-05-03 corpus per D-027 revised). Skill level is preserved
because 8/208 entries diverge from the default of 1. -->
<!-- Class-default override fields. Sparse: absent means inherit from
HeroClass. Faction heroes always inherit (no overrides).
Campaign/tutorial heroes routinely override stats + a few others. -->
| cost_gold = Integer
| start_level = Integer
| attacks_times_before = String <!-- comma-joined floats -->
| mesh = String
| mount = String
| native_biome = String
| skills_roll_variant = String
<!-- Stat block overrides -->
| view_radius = Integer
| stats_num = Integer
| magic_casts_per_round = Integer
| enable_tactics = Boolean
| tactics_placement_size = Integer
| enable_hero_native_biome = Boolean
| offence = Integer
| defence = Integer
| spell_power = Integer
| intelligence = Integer
| luck = Integer
| morale = Integer
<!-- statsRolls overrides (named after the four primary stats; see
HeroClass.md for the v=0..3 → attack/defense/power/knowledge
mapping). -->
| roll_lvl1_attack = Integer
| roll_lvl1_defense = Integer
| roll_lvl1_power = Integer
| roll_lvl1_knowledge = Integer
| roll_lvl24_attack = Integer
| roll_lvl24_defense = Integer
| roll_lvl24_power = Integer
| roll_lvl24_knowledge = Integer
}}
Override semantics
Every Cargo query that wants the effective value of a class-shared field on a hero should use:
<syntaxhighlight lang="sql"> COALESCE(Hero.<col>, HeroClass.<col>) AS effective_<col> </syntaxhighlight>
Joining on Hero.class_id = HeroClass.id. Hero wins if present; HeroClass fills in otherwise.
For faction heroes (108): all 11 class-shared columns are absent on the Hero row — every query falls through to HeroClass.
For campaign/tutorial heroes: ~3-5 columns are typically present (empirically: stats_*, start_level, attacks_times_before). Other class-shared columns still inherit from HeroClass.
Field notes
idis the hero's source JSON id (e.g.human_hero_1,campaign_M10_hero_demon_1).name_sid/motto_sid/desc_sidcarry the source SID for traceability and as the join key to the Translation rows. Faction heroes use implicit conventions (<id>/<id>_motto/<id>_description); campaign heroes set them explicitly in source JSON.name/motto/desccarry the resolved English text inline. Translations live on the twoTranslationDefrows (one for name+desc, one for motto).class_idis<class_type>_<faction>— matchesHeroClass.id.faction/class_typeare denormalized from the class so that "all human heroes" / "all might heroes" filters don't need a join.specialization_idpoints at a row inHeroSpecializationDef(one specialization per hero, 1:1 ratio). Schema for that table comes in a follow-up.
Related tables
- HeroClass — joined on
class_id = id(N:1). Carries the class defaults the Hero row may override. - HeroStartSquad — joined on
hero_id = id(1:N). Each row is one slot in primary or alt starting army. SkillDef(future) — joined onstart_skillsLIKE%<sid>%or via Cargo'sHOLDSoperator on the List column.SpellDef(future) — same join pattern viastart_magics.
HeroSpecialization — joined on specialization_id = id (N:1). The hero's unique passive. (Schema lands in a follow-up.)*
TranslationDef— two rows per hero (type=heroandtype=hero_motto).


