diff --git a/character-builder/data/index.json b/character-builder/data/index.json index 0839683..a70199b 100644 --- a/character-builder/data/index.json +++ b/character-builder/data/index.json @@ -16,36 +16,61 @@ "id": "benegesserit", "name": "Bene Gesserit", "file": "skills-benegesserit.json", + "subtrees": [ + "Weirding Way", + "The Voice", + "Body Control" + ], "nodes": 22, - "edges": 23 + "edges": 29 }, { "id": "mentat", "name": "Mentat", "file": "skills-mentat.json", + "subtrees": [ + "Mental Calculus", + "Assassination", + "Tactician" + ], "nodes": 22, - "edges": 22 + "edges": 28 }, { "id": "planetologist", "name": "Planetologist", "file": "skills-planetologist.json", + "subtrees": [ + "Scientist", + "Explorer", + "Mechanic" + ], "nodes": 20, - "edges": 10 + "edges": 26 }, { "id": "swordmaster", "name": "Swordmaster", "file": "skills-swordmaster.json", + "subtrees": [ + "The Blade", + "The Will", + "The Way" + ], "nodes": 22, - "edges": 22 + "edges": 28 }, { "id": "trooper", "name": "Trooper", "file": "skills-trooper.json", + "subtrees": [ + "Gunnery", + "Suspensor Training", + "Tactical Tech" + ], "nodes": 22, - "edges": 22 + "edges": 28 } ], "icons": { diff --git a/character-builder/data/skills-benegesserit.json b/character-builder/data/skills-benegesserit.json index 819775d..57bc5bc 100644 --- a/character-builder/data/skills-benegesserit.json +++ b/character-builder/data/skills-benegesserit.json @@ -1,342 +1,388 @@ { "id": "benegesserit", "name": "Bene Gesserit", - "nodes": [ + "subtrees": [ { - "tag": "Skills.Spice.BinduDodge", - "id": "BinduDodge", - "name": "Bindu Dodge", - "kind": "Spice", - "row": 1, - "col": 2, - "maxPoints": 1, - "icon": "t_ui_iconskilltreebindudodge_d.webp", - "url": "https://dune.gaming.tools/skills/skills-spice-bindudodge" + "name": "Weirding Way", + "cols": 3, + "nodes": [ + { + "tag": "Skills.Spice.BinduDodge", + "id": "BinduDodge", + "name": "Bindu Dodge", + "kind": "Spice", + "row": 1, + "col": 2, + "maxPoints": 1, + "icon": "t_ui_iconskilltreebindudodge_d.webp", + "url": "https://dune.gaming.tools/skills/skills-spice-bindudodge" + }, + { + "tag": "Skills.Ability.BinduNerveStrike", + "id": "BinduNerveStrike", + "name": "Prana-Bindu Strikes", + "kind": "Ability", + "row": 2, + "col": 1, + "maxPoints": 1, + "icon": "t_ui_iconabilitybindunervestrike_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-bindunervestrike" + }, + { + "tag": "Skills.Ability.WeirdingStep", + "id": "WeirdingStep", + "name": "Weirding Step", + "kind": "Ability", + "row": 2, + "col": 3, + "maxPoints": 1, + "icon": "t_ui_iconabilityweirdingstep_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-weirdingstep" + }, + { + "tag": "Skills.Attribute.WeirdingWay2", + "id": "WeirdingWay2", + "name": "Short Blade Damage", + "kind": "Attribute", + "row": 3, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeskillbrawler_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-weirdingway2" + }, + { + "tag": "Skills.Perk.Backstabber", + "id": "Backstabber", + "name": "Manipulate Instability", + "kind": "Perk", + "row": 4, + "col": 1, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeperkbackstabber_d.webp", + "url": "https://dune.gaming.tools/skills/skills-perk-backstabber" + }, + { + "tag": "Skills.Attribute.WeirdingWay1", + "id": "WeirdingWay1", + "name": "Blade Damage", + "kind": "Attribute", + "row": 4, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeskillbrawler_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-weirdingway1" + }, + { + "tag": "Skills.Ability.Hypersprint", + "id": "Hypersprint", + "name": "Bindu Sprint", + "kind": "Ability", + "row": 5, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_iconabilitydash_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-hypersprint" + } + ], + "edges": [ + { + "from": "Skills.Ability.BinduNerveStrike", + "to": "Skills.Spice.BinduDodge" + }, + { + "from": "Skills.Ability.WeirdingStep", + "to": "Skills.Spice.BinduDodge" + }, + { + "from": "Skills.Ability.BinduNerveStrike", + "to": "Skills.Attribute.WeirdingWay2" + }, + { + "from": "Skills.Ability.BinduNerveStrike", + "to": "Skills.Perk.Backstabber" + }, + { + "from": "Skills.Ability.WeirdingStep", + "to": "Skills.Attribute.WeirdingWay2" + }, + { + "from": "Skills.Ability.WeirdingStep", + "to": "Skills.Attribute.WeirdingWay1" + }, + { + "from": "Skills.Attribute.WeirdingWay2", + "to": "Skills.Perk.Backstabber" + }, + { + "from": "Skills.Attribute.WeirdingWay1", + "to": "Skills.Attribute.WeirdingWay2" + }, + { + "from": "Skills.Ability.Hypersprint", + "to": "Skills.Perk.Backstabber" + }, + { + "from": "Skills.Attribute.WeirdingWay1", + "to": "Skills.Perk.Backstabber" + }, + { + "from": "Skills.Ability.Hypersprint", + "to": "Skills.Attribute.WeirdingWay1" + } + ] }, { - "tag": "Skills.Ability.BinduNerveStrike", - "id": "BinduNerveStrike", - "name": "Prana-Bindu Strikes", - "kind": "Ability", - "row": 2, - "col": 1, - "maxPoints": 1, - "icon": "t_ui_iconabilitybindunervestrike_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-bindunervestrike" + "name": "The Voice", + "cols": 3, + "nodes": [ + { + "tag": "Skills.Spice.VoiceSplash", + "id": "VoiceSplash", + "name": "Screech", + "kind": "Spice", + "row": 1, + "col": 2, + "maxPoints": 1, + "icon": "t_ui_iconskilltreescreech_d.webp", + "url": "https://dune.gaming.tools/skills/skills-spice-voicesplash" + }, + { + "tag": "Skills.Perk.VoiceAnalysis", + "id": "VoiceAnalysis", + "name": "Rapid Register", + "kind": "Perk", + "row": 2, + "col": 1, + "maxPoints": 1, + "icon": "t_ui_iconskilltreevoiceanalysis_d.webp", + "url": "https://dune.gaming.tools/skills/skills-perk-voiceanalysis" + }, + { + "tag": "Skills.Ability.VoiceStop", + "id": "VoiceStop", + "name": "Stop", + "kind": "Ability", + "row": 2, + "col": 3, + "maxPoints": 1, + "icon": "t_ui_iconabilityvoicestop_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-voicestop" + }, + { + "tag": "Skills.Ability.Blindspot", + "id": "Blindspot", + "name": "Ignore", + "kind": "Ability", + "row": 4, + "col": 1, + "maxPoints": 1, + "icon": "t_ui_iconabilityblindspot_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-blindspot" + }, + { + "tag": "Skills.Attribute.Manipulation1", + "id": "Manipulation1", + "name": "Voice Training", + "kind": "Attribute", + "row": 4, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconskilltreebenegesseritcooldown_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-manipulation1" + }, + { + "tag": "Skills.Ability.VoiceCompel", + "id": "VoiceCompel", + "name": "Compel", + "kind": "Ability", + "row": 5, + "col": 2, + "maxPoints": 1, + "icon": "t_ui_iconabilitythevoicecompel_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-voicecompel" + } + ], + "edges": [ + { + "from": "Skills.Perk.VoiceAnalysis", + "to": "Skills.Spice.VoiceSplash" + }, + { + "from": "Skills.Ability.VoiceStop", + "to": "Skills.Spice.VoiceSplash" + }, + { + "from": "Skills.Ability.Blindspot", + "to": "Skills.Perk.VoiceAnalysis" + }, + { + "from": "Skills.Ability.VoiceStop", + "to": "Skills.Attribute.Manipulation1" + }, + { + "from": "Skills.Ability.Blindspot", + "to": "Skills.Ability.VoiceCompel" + }, + { + "from": "Skills.Ability.VoiceCompel", + "to": "Skills.Attribute.Manipulation1" + } + ] }, { - "tag": "Skills.Ability.WeirdingStep", - "id": "WeirdingStep", - "name": "Weirding Step", - "kind": "Ability", - "row": 2, - "col": 3, - "maxPoints": 1, - "icon": "t_ui_iconabilityweirdingstep_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-weirdingstep" - }, - { - "tag": "Skills.Attribute.WeirdingWay2", - "id": "WeirdingWay2", - "name": "Short Blade Damage", - "kind": "Attribute", - "row": 3, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeskillbrawler_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-weirdingway2" - }, - { - "tag": "Skills.Perk.Backstabber", - "id": "Backstabber", - "name": "Manipulate Instability", - "kind": "Perk", - "row": 4, - "col": 1, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeperkbackstabber_d.webp", - "url": "https://dune.gaming.tools/skills/skills-perk-backstabber" - }, - { - "tag": "Skills.Attribute.WeirdingWay1", - "id": "WeirdingWay1", - "name": "Blade Damage", - "kind": "Attribute", - "row": 4, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeskillbrawler_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-weirdingway1" - }, - { - "tag": "Skills.Ability.Hypersprint", - "id": "Hypersprint", - "name": "Bindu Sprint", - "kind": "Ability", - "row": 5, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_iconabilitydash_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-hypersprint" - }, - { - "tag": "Skills.Spice.VoiceSplash", - "id": "VoiceSplash", - "name": "Screech", - "kind": "Spice", - "row": 1, - "col": 2, - "maxPoints": 1, - "icon": "t_ui_iconskilltreescreech_d.webp", - "url": "https://dune.gaming.tools/skills/skills-spice-voicesplash" - }, - { - "tag": "Skills.Perk.VoiceAnalysis", - "id": "VoiceAnalysis", - "name": "Rapid Register", - "kind": "Perk", - "row": 2, - "col": 1, - "maxPoints": 1, - "icon": "t_ui_iconskilltreevoiceanalysis_d.webp", - "url": "https://dune.gaming.tools/skills/skills-perk-voiceanalysis" - }, - { - "tag": "Skills.Ability.VoiceStop", - "id": "VoiceStop", - "name": "Stop", - "kind": "Ability", - "row": 2, - "col": 3, - "maxPoints": 1, - "icon": "t_ui_iconabilityvoicestop_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-voicestop" - }, - { - "tag": "Skills.Ability.Blindspot", - "id": "Blindspot", - "name": "Ignore", - "kind": "Ability", - "row": 4, - "col": 1, - "maxPoints": 1, - "icon": "t_ui_iconabilityblindspot_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-blindspot" - }, - { - "tag": "Skills.Attribute.Manipulation1", - "id": "Manipulation1", - "name": "Voice Training", - "kind": "Attribute", - "row": 4, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconskilltreebenegesseritcooldown_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-manipulation1" - }, - { - "tag": "Skills.Ability.VoiceCompel", - "id": "VoiceCompel", - "name": "Compel", - "kind": "Ability", - "row": 5, - "col": 2, - "maxPoints": 1, - "icon": "t_ui_iconabilitythevoicecompel_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-voicecompel" - }, - { - "tag": "Skills.Ability.LitanyAgainstFear", - "id": "LitanyAgainstFear", - "name": "Litany Against Fear", - "kind": "Ability", - "row": 1, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconabilitylitanyagainstfear_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-litanyagainstfear" - }, - { - "tag": "Skills.Perk.BinduStability", - "id": "BinduStability", - "name": "Prana-Bindu Stability", - "kind": "Perk", - "row": 2, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_iconskilltreebindustability_d.webp", - "url": "https://dune.gaming.tools/skills/skills-perk-bindustability" - }, - { - "tag": "Skills.Perk.MetabolizePoison", - "id": "MetabolizePoison", - "name": "Metabolize Poison", - "kind": "Perk", - "row": 2, - "col": 4, - "maxPoints": 1, - "icon": "t_ui_iconskilltreemetabolizeposion_d.webp", - "url": "https://dune.gaming.tools/skills/skills-perk-metabolizepoison" - }, - { - "tag": "Skills.Attribute.SelfControl3", - "id": "SelfControl3", - "name": "Vitality", - "kind": "Attribute", - "row": 3, - "col": 1, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributemaxhpbonus_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-selfcontrol3" - }, - { - "tag": "Skills.Attribute.SelfControl4", - "id": "SelfControl4", - "name": "Self-Healing", - "kind": "Attribute", - "row": 3, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeskillmaxhealth_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-selfcontrol4" - }, - { - "tag": "Skills.Attribute.SelfControl5", - "id": "SelfControl5", - "name": "Poison Tolerance", - "kind": "Attribute", - "row": 3, - "col": 5, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributepoisondefense_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-selfcontrol5" - }, - { - "tag": "Skills.Perk.RegenCap", - "id": "RegenCap", - "name": "Trauma Recovery", - "kind": "Perk", - "row": 4, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeperkhealingfactor_d.webp", - "url": "https://dune.gaming.tools/skills/skills-perk-regencap" - }, - { - "tag": "Skills.Attribute.SelfControl2", - "id": "SelfControl2", - "name": "Sun Tolerance", - "kind": "Attribute", - "row": 4, - "col": 4, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributesundefense_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-selfcontrol2" - }, - { - "tag": "Skills.Attribute.SelfControl1", - "id": "SelfControl1", - "name": "Recovery", - "kind": "Attribute", - "row": 5, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeskillhealingmultiplier_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-selfcontrol1" - } - ], - "edges": [ - { - "from": "Skills.Ability.BinduNerveStrike", - "to": "Skills.Spice.BinduDodge" - }, - { - "from": "Skills.Ability.WeirdingStep", - "to": "Skills.Spice.BinduDodge" - }, - { - "from": "Skills.Ability.BinduNerveStrike", - "to": "Skills.Attribute.WeirdingWay2" - }, - { - "from": "Skills.Ability.BinduNerveStrike", - "to": "Skills.Perk.Backstabber" - }, - { - "from": "Skills.Ability.WeirdingStep", - "to": "Skills.Attribute.WeirdingWay2" - }, - { - "from": "Skills.Ability.WeirdingStep", - "to": "Skills.Attribute.WeirdingWay1" - }, - { - "from": "Skills.Attribute.WeirdingWay2", - "to": "Skills.Perk.Backstabber" - }, - { - "from": "Skills.Attribute.WeirdingWay1", - "to": "Skills.Attribute.WeirdingWay2" - }, - { - "from": "Skills.Ability.Hypersprint", - "to": "Skills.Perk.Backstabber" - }, - { - "from": "Skills.Attribute.WeirdingWay1", - "to": "Skills.Perk.Backstabber" - }, - { - "from": "Skills.Ability.Hypersprint", - "to": "Skills.Attribute.WeirdingWay1" - }, - { - "from": "Skills.Ability.LitanyAgainstFear", - "to": "Skills.Perk.BinduStability" - }, - { - "from": "Skills.Ability.LitanyAgainstFear", - "to": "Skills.Perk.MetabolizePoison" - }, - { - "from": "Skills.Attribute.SelfControl3", - "to": "Skills.Perk.BinduStability" - }, - { - "from": "Skills.Attribute.SelfControl4", - "to": "Skills.Perk.BinduStability" - }, - { - "from": "Skills.Attribute.SelfControl4", - "to": "Skills.Perk.MetabolizePoison" - }, - { - "from": "Skills.Attribute.SelfControl5", - "to": "Skills.Perk.MetabolizePoison" - }, - { - "from": "Skills.Attribute.SelfControl3", - "to": "Skills.Perk.RegenCap" - }, - { - "from": "Skills.Attribute.SelfControl4", - "to": "Skills.Perk.RegenCap" - }, - { - "from": "Skills.Attribute.SelfControl2", - "to": "Skills.Attribute.SelfControl4" - }, - { - "from": "Skills.Attribute.SelfControl2", - "to": "Skills.Attribute.SelfControl5" - }, - { - "from": "Skills.Attribute.SelfControl1", - "to": "Skills.Perk.RegenCap" - }, - { - "from": "Skills.Attribute.SelfControl1", - "to": "Skills.Attribute.SelfControl2" + "name": "Body Control", + "cols": 5, + "nodes": [ + { + "tag": "Skills.Ability.LitanyAgainstFear", + "id": "LitanyAgainstFear", + "name": "Litany Against Fear", + "kind": "Ability", + "row": 1, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconabilitylitanyagainstfear_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-litanyagainstfear" + }, + { + "tag": "Skills.Perk.BinduStability", + "id": "BinduStability", + "name": "Prana-Bindu Stability", + "kind": "Perk", + "row": 2, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_iconskilltreebindustability_d.webp", + "url": "https://dune.gaming.tools/skills/skills-perk-bindustability" + }, + { + "tag": "Skills.Perk.MetabolizePoison", + "id": "MetabolizePoison", + "name": "Metabolize Poison", + "kind": "Perk", + "row": 2, + "col": 4, + "maxPoints": 1, + "icon": "t_ui_iconskilltreemetabolizeposion_d.webp", + "url": "https://dune.gaming.tools/skills/skills-perk-metabolizepoison" + }, + { + "tag": "Skills.Attribute.SelfControl3", + "id": "SelfControl3", + "name": "Vitality", + "kind": "Attribute", + "row": 3, + "col": 1, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributemaxhpbonus_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-selfcontrol3" + }, + { + "tag": "Skills.Attribute.SelfControl4", + "id": "SelfControl4", + "name": "Self-Healing", + "kind": "Attribute", + "row": 3, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeskillmaxhealth_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-selfcontrol4" + }, + { + "tag": "Skills.Attribute.SelfControl5", + "id": "SelfControl5", + "name": "Poison Tolerance", + "kind": "Attribute", + "row": 3, + "col": 5, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributepoisondefense_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-selfcontrol5" + }, + { + "tag": "Skills.Perk.RegenCap", + "id": "RegenCap", + "name": "Trauma Recovery", + "kind": "Perk", + "row": 4, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeperkhealingfactor_d.webp", + "url": "https://dune.gaming.tools/skills/skills-perk-regencap" + }, + { + "tag": "Skills.Attribute.SelfControl2", + "id": "SelfControl2", + "name": "Sun Tolerance", + "kind": "Attribute", + "row": 4, + "col": 4, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributesundefense_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-selfcontrol2" + }, + { + "tag": "Skills.Attribute.SelfControl1", + "id": "SelfControl1", + "name": "Recovery", + "kind": "Attribute", + "row": 5, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeskillhealingmultiplier_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-selfcontrol1" + } + ], + "edges": [ + { + "from": "Skills.Ability.LitanyAgainstFear", + "to": "Skills.Perk.BinduStability" + }, + { + "from": "Skills.Ability.LitanyAgainstFear", + "to": "Skills.Perk.MetabolizePoison" + }, + { + "from": "Skills.Attribute.SelfControl3", + "to": "Skills.Perk.BinduStability" + }, + { + "from": "Skills.Attribute.SelfControl4", + "to": "Skills.Perk.BinduStability" + }, + { + "from": "Skills.Attribute.SelfControl4", + "to": "Skills.Perk.MetabolizePoison" + }, + { + "from": "Skills.Attribute.SelfControl5", + "to": "Skills.Perk.MetabolizePoison" + }, + { + "from": "Skills.Attribute.SelfControl3", + "to": "Skills.Perk.RegenCap" + }, + { + "from": "Skills.Attribute.SelfControl4", + "to": "Skills.Perk.RegenCap" + }, + { + "from": "Skills.Attribute.SelfControl2", + "to": "Skills.Attribute.SelfControl4" + }, + { + "from": "Skills.Attribute.SelfControl2", + "to": "Skills.Attribute.SelfControl5" + }, + { + "from": "Skills.Attribute.SelfControl1", + "to": "Skills.Perk.RegenCap" + }, + { + "from": "Skills.Attribute.SelfControl1", + "to": "Skills.Attribute.SelfControl2" + } + ] } ] } \ No newline at end of file diff --git a/character-builder/data/skills-mentat.json b/character-builder/data/skills-mentat.json index 74e1c26..32226e7 100644 --- a/character-builder/data/skills-mentat.json +++ b/character-builder/data/skills-mentat.json @@ -1,338 +1,384 @@ { "id": "mentat", "name": "Mentat", - "nodes": [ + "subtrees": [ { - "tag": "Skills.Perk.ShieldWeakpoint", - "id": "ShieldWeakpoint", - "name": "Shield Overcharge", - "kind": "Perk", - "row": 1, - "col": 3, - "maxPoints": 1, - "icon": "t_ui_iconskilltreeshieldovercharge_d.webp", - "url": "https://dune.gaming.tools/skills/skills-perk-shieldweakpoint" + "name": "Mental Calculus", + "cols": 5, + "nodes": [ + { + "tag": "Skills.Perk.ShieldWeakpoint", + "id": "ShieldWeakpoint", + "name": "Shield Overcharge", + "kind": "Perk", + "row": 1, + "col": 3, + "maxPoints": 1, + "icon": "t_ui_iconskilltreeshieldovercharge_d.webp", + "url": "https://dune.gaming.tools/skills/skills-perk-shieldweakpoint" + }, + { + "tag": "Skills.Perk.ExploitWeakness", + "id": "ExploitWeakness", + "name": "Exploit Weakness", + "kind": "Perk", + "row": 2, + "col": 2, + "maxPoints": 1, + "icon": "t_ui_iconskilltreespiceeffectexploitweakness_d.webp", + "url": "https://dune.gaming.tools/skills/skills-perk-exploitweakness" + }, + { + "tag": "Skills.Attribute.MentalCalculus5", + "id": "MentalCalculus5", + "name": "Rifle Damage", + "kind": "Attribute", + "row": 2, + "col": 4, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributedamagebonusscattergun_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-mentalcalculus5" + }, + { + "tag": "Skills.Attribute.MentalCalculus3", + "id": "MentalCalculus3", + "name": "Tailoring", + "kind": "Attribute", + "row": 3, + "col": 1, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributerepairefficiency_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-mentalcalculus3" + }, + { + "tag": "Skills.Perk.HeadShots", + "id": "HeadShots", + "name": "Marksman", + "kind": "Perk", + "row": 3, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeperkmarksman_d.webp", + "url": "https://dune.gaming.tools/skills/skills-perk-headshots" + }, + { + "tag": "Skills.Attribute.MentalCalculus4", + "id": "MentalCalculus4", + "name": "Pistol Damage", + "kind": "Attribute", + "row": 3, + "col": 5, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributedamagebonusgun_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-mentalcalculus4" + }, + { + "tag": "Skills.Attribute.MentalCalculus1", + "id": "MentalCalculus1", + "name": "Garment Keeper", + "kind": "Attribute", + "row": 4, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributerepair_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-mentalcalculus1" + }, + { + "tag": "Skills.Attribute.MentalCalculus2", + "id": "MentalCalculus2", + "name": "Ranged Damage", + "kind": "Attribute", + "row": 4, + "col": 4, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributedamage_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-mentalcalculus2" + }, + { + "tag": "Skills.Ability.TurretSeeker", + "id": "TurretSeeker", + "name": "The Sentinel", + "kind": "Ability", + "row": 5, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconabilityturretseeker_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-turretseeker" + } + ], + "edges": [ + { + "from": "Skills.Perk.ExploitWeakness", + "to": "Skills.Perk.ShieldWeakpoint" + }, + { + "from": "Skills.Attribute.MentalCalculus5", + "to": "Skills.Perk.ShieldWeakpoint" + }, + { + "from": "Skills.Attribute.MentalCalculus3", + "to": "Skills.Perk.ExploitWeakness" + }, + { + "from": "Skills.Perk.ExploitWeakness", + "to": "Skills.Perk.HeadShots" + }, + { + "from": "Skills.Attribute.MentalCalculus5", + "to": "Skills.Perk.HeadShots" + }, + { + "from": "Skills.Attribute.MentalCalculus4", + "to": "Skills.Attribute.MentalCalculus5" + }, + { + "from": "Skills.Attribute.MentalCalculus1", + "to": "Skills.Attribute.MentalCalculus3" + }, + { + "from": "Skills.Attribute.MentalCalculus1", + "to": "Skills.Perk.HeadShots" + }, + { + "from": "Skills.Attribute.MentalCalculus2", + "to": "Skills.Perk.HeadShots" + }, + { + "from": "Skills.Attribute.MentalCalculus2", + "to": "Skills.Attribute.MentalCalculus4" + }, + { + "from": "Skills.Ability.TurretSeeker", + "to": "Skills.Attribute.MentalCalculus1" + }, + { + "from": "Skills.Ability.TurretSeeker", + "to": "Skills.Attribute.MentalCalculus2" + } + ] }, { - "tag": "Skills.Perk.ExploitWeakness", - "id": "ExploitWeakness", - "name": "Exploit Weakness", - "kind": "Perk", - "row": 2, - "col": 2, - "maxPoints": 1, - "icon": "t_ui_iconskilltreespiceeffectexploitweakness_d.webp", - "url": "https://dune.gaming.tools/skills/skills-perk-exploitweakness" + "name": "Assassination", + "cols": 3, + "nodes": [ + { + "tag": "Skills.Ability.HunterSeeker", + "id": "HunterSeeker", + "name": "Hunter-Seeker", + "kind": "Ability", + "row": 1, + "col": 2, + "maxPoints": 1, + "icon": "t_ui_icongadgethunterseeker_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-hunterseeker" + }, + { + "tag": "Skills.Perk.PoisonTooth", + "id": "PoisonTooth", + "name": "Poison Tooth", + "kind": "Perk", + "row": 2, + "col": 1, + "maxPoints": 3, + "icon": "t_ui_iconskilltreepoisontooth_d.webp", + "url": "https://dune.gaming.tools/skills/skills-perk-poisontooth" + }, + { + "tag": "Skills.Ability.StunDart", + "id": "StunDart", + "name": "Stunner", + "kind": "Ability", + "row": 2, + "col": 3, + "maxPoints": 1, + "icon": "t_ui_iconabilitystunnerdart_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-stundart" + }, + { + "tag": "Skills.Attribute.Assassination2", + "id": "Assassination2", + "name": "Assassin's Shot", + "kind": "Attribute", + "row": 3, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributedamage_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-assassination2" + }, + { + "tag": "Skills.Ability.PoisonMine", + "id": "PoisonMine", + "name": "Poison Mine", + "kind": "Ability", + "row": 4, + "col": 1, + "maxPoints": 3, + "icon": "t_ui_iconabilitypoisonmine_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-poisonmine" + }, + { + "tag": "Skills.Attribute.Assassination1", + "id": "Assassination1", + "name": "Headshot Damage", + "kind": "Attribute", + "row": 4, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributeheadshotbonus_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-assassination1" + }, + { + "tag": "Skills.Ability.PoisonCapsuleLauncher", + "id": "PoisonCapsuleLauncher", + "name": "Poison Capsule", + "kind": "Ability", + "row": 5, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_icongadgetpoisoncapsulelauncher_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-poisoncapsulelauncher" + } + ], + "edges": [ + { + "from": "Skills.Ability.HunterSeeker", + "to": "Skills.Perk.PoisonTooth" + }, + { + "from": "Skills.Ability.HunterSeeker", + "to": "Skills.Ability.StunDart" + }, + { + "from": "Skills.Attribute.Assassination2", + "to": "Skills.Perk.PoisonTooth" + }, + { + "from": "Skills.Ability.PoisonMine", + "to": "Skills.Perk.PoisonTooth" + }, + { + "from": "Skills.Ability.StunDart", + "to": "Skills.Attribute.Assassination2" + }, + { + "from": "Skills.Ability.StunDart", + "to": "Skills.Attribute.Assassination1" + }, + { + "from": "Skills.Ability.PoisonMine", + "to": "Skills.Attribute.Assassination2" + }, + { + "from": "Skills.Attribute.Assassination1", + "to": "Skills.Attribute.Assassination2" + }, + { + "from": "Skills.Ability.PoisonCapsuleLauncher", + "to": "Skills.Ability.PoisonMine" + }, + { + "from": "Skills.Ability.PoisonCapsuleLauncher", + "to": "Skills.Attribute.Assassination1" + } + ] }, { - "tag": "Skills.Attribute.MentalCalculus5", - "id": "MentalCalculus5", - "name": "Rifle Damage", - "kind": "Attribute", - "row": 2, - "col": 4, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributedamagebonusscattergun_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-mentalcalculus5" - }, - { - "tag": "Skills.Attribute.MentalCalculus3", - "id": "MentalCalculus3", - "name": "Tailoring", - "kind": "Attribute", - "row": 3, - "col": 1, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributerepairefficiency_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-mentalcalculus3" - }, - { - "tag": "Skills.Perk.HeadShots", - "id": "HeadShots", - "name": "Marksman", - "kind": "Perk", - "row": 3, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeperkmarksman_d.webp", - "url": "https://dune.gaming.tools/skills/skills-perk-headshots" - }, - { - "tag": "Skills.Attribute.MentalCalculus4", - "id": "MentalCalculus4", - "name": "Pistol Damage", - "kind": "Attribute", - "row": 3, - "col": 5, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributedamagebonusgun_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-mentalcalculus4" - }, - { - "tag": "Skills.Attribute.MentalCalculus1", - "id": "MentalCalculus1", - "name": "Garment Keeper", - "kind": "Attribute", - "row": 4, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributerepair_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-mentalcalculus1" - }, - { - "tag": "Skills.Attribute.MentalCalculus2", - "id": "MentalCalculus2", - "name": "Ranged Damage", - "kind": "Attribute", - "row": 4, - "col": 4, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributedamage_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-mentalcalculus2" - }, - { - "tag": "Skills.Ability.TurretSeeker", - "id": "TurretSeeker", - "name": "The Sentinel", - "kind": "Ability", - "row": 5, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconabilityturretseeker_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-turretseeker" - }, - { - "tag": "Skills.Ability.HunterSeeker", - "id": "HunterSeeker", - "name": "Hunter-Seeker", - "kind": "Ability", - "row": 1, - "col": 2, - "maxPoints": 1, - "icon": "t_ui_icongadgethunterseeker_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-hunterseeker" - }, - { - "tag": "Skills.Perk.PoisonTooth", - "id": "PoisonTooth", - "name": "Poison Tooth", - "kind": "Perk", - "row": 2, - "col": 1, - "maxPoints": 3, - "icon": "t_ui_iconskilltreepoisontooth_d.webp", - "url": "https://dune.gaming.tools/skills/skills-perk-poisontooth" - }, - { - "tag": "Skills.Ability.StunDart", - "id": "StunDart", - "name": "Stunner", - "kind": "Ability", - "row": 2, - "col": 3, - "maxPoints": 1, - "icon": "t_ui_iconabilitystunnerdart_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-stundart" - }, - { - "tag": "Skills.Attribute.Assassination2", - "id": "Assassination2", - "name": "Assassin's Shot", - "kind": "Attribute", - "row": 3, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributedamage_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-assassination2" - }, - { - "tag": "Skills.Ability.PoisonMine", - "id": "PoisonMine", - "name": "Poison Mine", - "kind": "Ability", - "row": 4, - "col": 1, - "maxPoints": 3, - "icon": "t_ui_iconabilitypoisonmine_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-poisonmine" - }, - { - "tag": "Skills.Attribute.Assassination1", - "id": "Assassination1", - "name": "Headshot Damage", - "kind": "Attribute", - "row": 4, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributeheadshotbonus_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-assassination1" - }, - { - "tag": "Skills.Ability.PoisonCapsuleLauncher", - "id": "PoisonCapsuleLauncher", - "name": "Poison Capsule", - "kind": "Ability", - "row": 5, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_icongadgetpoisoncapsulelauncher_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-poisoncapsulelauncher" - }, - { - "tag": "Skills.Ability.PortableGenerator", - "id": "PortableGenerator", - "name": "Source of Power", - "kind": "Ability", - "row": 1, - "col": 2, - "maxPoints": 1, - "icon": "t_ui_iconabilityportablegenerator_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-portablegenerator" - }, - { - "tag": "Skills.Ability.SuspensorMine_Reduction", - "id": "SuspensorMine_Reduction", - "name": "Anti-gravity Mine", - "kind": "Ability", - "row": 2, - "col": 1, - "maxPoints": 1, - "icon": "t_ui_icongadgetreductionremotemine_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-suspensormine_reduction" - }, - { - "tag": "Skills.Perk.IronWill", - "id": "IronWill", - "name": "Iron Will", - "kind": "Perk", - "row": 2, - "col": 3, - "maxPoints": 1, - "icon": "t_ui_iconskilltreeironwill_d.webp", - "url": "https://dune.gaming.tools/skills/skills-perk-ironwill" - }, - { - "tag": "Skills.Ability.SuspensorMine_Amplification", - "id": "SuspensorMine_Amplification", - "name": "Gravity Mine", - "kind": "Ability", - "row": 4, - "col": 1, - "maxPoints": 1, - "icon": "t_ui_icongadgetamplificationremotemine_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-suspensormine_amplification" - }, - { - "tag": "Skills.Ability.SolidoDecoy", - "id": "SolidoDecoy", - "name": "Solido Decoy", - "kind": "Ability", - "row": 4, - "col": 3, - "maxPoints": 1, - "icon": "t_ui_iconabilitysolidodecoy_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-solidodecoy" - }, - { - "tag": "Skills.Ability.SuspensorWall", - "id": "SuspensorWall", - "name": "Shield Wall", - "kind": "Ability", - "row": 5, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_iconabilitysuspensorwall_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-suspensorwall" - } - ], - "edges": [ - { - "from": "Skills.Perk.ExploitWeakness", - "to": "Skills.Perk.ShieldWeakpoint" - }, - { - "from": "Skills.Attribute.MentalCalculus5", - "to": "Skills.Perk.ShieldWeakpoint" - }, - { - "from": "Skills.Attribute.MentalCalculus3", - "to": "Skills.Perk.ExploitWeakness" - }, - { - "from": "Skills.Perk.ExploitWeakness", - "to": "Skills.Perk.HeadShots" - }, - { - "from": "Skills.Attribute.MentalCalculus5", - "to": "Skills.Perk.HeadShots" - }, - { - "from": "Skills.Attribute.MentalCalculus4", - "to": "Skills.Attribute.MentalCalculus5" - }, - { - "from": "Skills.Attribute.MentalCalculus1", - "to": "Skills.Attribute.MentalCalculus3" - }, - { - "from": "Skills.Attribute.MentalCalculus1", - "to": "Skills.Perk.HeadShots" - }, - { - "from": "Skills.Attribute.MentalCalculus2", - "to": "Skills.Perk.HeadShots" - }, - { - "from": "Skills.Attribute.MentalCalculus2", - "to": "Skills.Attribute.MentalCalculus4" - }, - { - "from": "Skills.Ability.TurretSeeker", - "to": "Skills.Attribute.MentalCalculus1" - }, - { - "from": "Skills.Ability.TurretSeeker", - "to": "Skills.Attribute.MentalCalculus2" - }, - { - "from": "Skills.Ability.HunterSeeker", - "to": "Skills.Perk.PoisonTooth" - }, - { - "from": "Skills.Ability.HunterSeeker", - "to": "Skills.Ability.StunDart" - }, - { - "from": "Skills.Attribute.Assassination2", - "to": "Skills.Perk.PoisonTooth" - }, - { - "from": "Skills.Ability.PoisonMine", - "to": "Skills.Perk.PoisonTooth" - }, - { - "from": "Skills.Ability.StunDart", - "to": "Skills.Attribute.Assassination2" - }, - { - "from": "Skills.Ability.StunDart", - "to": "Skills.Attribute.Assassination1" - }, - { - "from": "Skills.Ability.PoisonMine", - "to": "Skills.Attribute.Assassination2" - }, - { - "from": "Skills.Attribute.Assassination1", - "to": "Skills.Attribute.Assassination2" - }, - { - "from": "Skills.Ability.PoisonCapsuleLauncher", - "to": "Skills.Ability.PoisonMine" - }, - { - "from": "Skills.Ability.PoisonCapsuleLauncher", - "to": "Skills.Attribute.Assassination1" + "name": "Tactician", + "cols": 3, + "nodes": [ + { + "tag": "Skills.Ability.PortableGenerator", + "id": "PortableGenerator", + "name": "Source of Power", + "kind": "Ability", + "row": 1, + "col": 2, + "maxPoints": 1, + "icon": "t_ui_iconabilityportablegenerator_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-portablegenerator" + }, + { + "tag": "Skills.Ability.SuspensorMine_Reduction", + "id": "SuspensorMine_Reduction", + "name": "Anti-gravity Mine", + "kind": "Ability", + "row": 2, + "col": 1, + "maxPoints": 1, + "icon": "t_ui_icongadgetreductionremotemine_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-suspensormine_reduction" + }, + { + "tag": "Skills.Perk.IronWill", + "id": "IronWill", + "name": "Iron Will", + "kind": "Perk", + "row": 2, + "col": 3, + "maxPoints": 1, + "icon": "t_ui_iconskilltreeironwill_d.webp", + "url": "https://dune.gaming.tools/skills/skills-perk-ironwill" + }, + { + "tag": "Skills.Ability.SuspensorMine_Amplification", + "id": "SuspensorMine_Amplification", + "name": "Gravity Mine", + "kind": "Ability", + "row": 4, + "col": 1, + "maxPoints": 1, + "icon": "t_ui_icongadgetamplificationremotemine_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-suspensormine_amplification" + }, + { + "tag": "Skills.Ability.SolidoDecoy", + "id": "SolidoDecoy", + "name": "Solido Decoy", + "kind": "Ability", + "row": 4, + "col": 3, + "maxPoints": 1, + "icon": "t_ui_iconabilitysolidodecoy_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-solidodecoy" + }, + { + "tag": "Skills.Ability.SuspensorWall", + "id": "SuspensorWall", + "name": "Shield Wall", + "kind": "Ability", + "row": 5, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_iconabilitysuspensorwall_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-suspensorwall" + } + ], + "edges": [ + { + "from": "Skills.Ability.PortableGenerator", + "to": "Skills.Ability.SuspensorMine_Reduction" + }, + { + "from": "Skills.Ability.PortableGenerator", + "to": "Skills.Perk.IronWill" + }, + { + "from": "Skills.Ability.SuspensorMine_Amplification", + "to": "Skills.Ability.SuspensorMine_Reduction" + }, + { + "from": "Skills.Ability.SolidoDecoy", + "to": "Skills.Perk.IronWill" + }, + { + "from": "Skills.Ability.SuspensorMine_Amplification", + "to": "Skills.Ability.SuspensorWall" + }, + { + "from": "Skills.Ability.SolidoDecoy", + "to": "Skills.Ability.SuspensorWall" + } + ] } ] } \ No newline at end of file diff --git a/character-builder/data/skills-planetologist.json b/character-builder/data/skills-planetologist.json index 7ea223a..f58b356 100644 --- a/character-builder/data/skills-planetologist.json +++ b/character-builder/data/skills-planetologist.json @@ -1,268 +1,354 @@ { "id": "planetologist", "name": "Planetologist", - "nodes": [ + "subtrees": [ { - "tag": "Skills.Perk.BatteryExpert", - "id": "BatteryExpert", - "name": "Conservation of Energy", - "kind": "Perk", - "row": 1, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeperkbatteryexpert_d.webp", - "url": "https://dune.gaming.tools/skills/skills-perk-batteryexpert" + "name": "Scientist", + "cols": 3, + "nodes": [ + { + "tag": "Skills.Perk.BatteryExpert", + "id": "BatteryExpert", + "name": "Conservation of Energy", + "kind": "Perk", + "row": 1, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeperkbatteryexpert_d.webp", + "url": "https://dune.gaming.tools/skills/skills-perk-batteryexpert" + }, + { + "tag": "Skills.Attribute.Scientist5", + "id": "Scientist5", + "name": "Compaction", + "kind": "Attribute", + "row": 2, + "col": 1, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributespiceyield_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-scientist5" + }, + { + "tag": "Skills.Science.m_PowerMax", + "id": "m_PowerMax", + "name": "Overcharge", + "kind": "Science", + "row": 2, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributemineralyield_d.webp", + "url": "https://dune.gaming.tools/skills/skills-science-m_powermax" + }, + { + "tag": "Skills.Attribute.Scientist4", + "id": "Scientist4", + "name": "Deep Analysis", + "kind": "Attribute", + "row": 3, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributemineralyield_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-scientist4" + }, + { + "tag": "Skills.Attribute.Scientist2", + "id": "Scientist2", + "name": "Dew Gathering", + "kind": "Attribute", + "row": 4, + "col": 1, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributewatheryield_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-scientist2" + }, + { + "tag": "Skills.Attribute.Scientist3", + "id": "Scientist3", + "name": "Rerouting", + "kind": "Attribute", + "row": 4, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeskillpowerefficiency_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-scientist3" + }, + { + "tag": "Skills.Attribute.Scientist1", + "id": "Scientist1", + "name": "Cutteray Mining", + "kind": "Attribute", + "row": 5, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributemineralyield_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-scientist1" + } + ], + "edges": [ + { + "from": "Skills.Attribute.Scientist5", + "to": "Skills.Perk.BatteryExpert" + }, + { + "from": "Skills.Perk.BatteryExpert", + "to": "Skills.Science.m_PowerMax" + }, + { + "from": "Skills.Attribute.Scientist4", + "to": "Skills.Attribute.Scientist5" + }, + { + "from": "Skills.Attribute.Scientist2", + "to": "Skills.Attribute.Scientist5" + }, + { + "from": "Skills.Attribute.Scientist4", + "to": "Skills.Science.m_PowerMax" + }, + { + "from": "Skills.Attribute.Scientist3", + "to": "Skills.Science.m_PowerMax" + }, + { + "from": "Skills.Attribute.Scientist2", + "to": "Skills.Attribute.Scientist4" + }, + { + "from": "Skills.Attribute.Scientist3", + "to": "Skills.Attribute.Scientist4" + }, + { + "from": "Skills.Attribute.Scientist1", + "to": "Skills.Attribute.Scientist2" + }, + { + "from": "Skills.Attribute.Scientist1", + "to": "Skills.Attribute.Scientist3" + } + ] }, { - "tag": "Skills.Attribute.Scientist5", - "id": "Scientist5", - "name": "Compaction", - "kind": "Attribute", - "row": 2, - "col": 1, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributespiceyield_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-scientist5" + "name": "Explorer", + "cols": 3, + "nodes": [ + { + "tag": "Skills.Attribute.Explorer5", + "id": "Explorer5", + "name": "Spice Surveyor", + "kind": "Attribute", + "row": 1, + "col": 2, + "maxPoints": 1, + "icon": "t_ui_iconskilltreeattributespice_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-explorer5" + }, + { + "tag": "Skills.Attribute.Explorer3", + "id": "Explorer3", + "name": "Scanner Mastery", + "kind": "Attribute", + "row": 2, + "col": 1, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributescanningbonus_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-explorer3" + }, + { + "tag": "Skills.Attribute.Explorer4", + "id": "Explorer4", + "name": "Stillsuit Seals", + "kind": "Attribute", + "row": 2, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeskillhydration_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-explorer4" + }, + { + "tag": "Skills.Attribute.Explorer1", + "id": "Explorer1", + "name": "Cartographer", + "kind": "Attribute", + "row": 4, + "col": 1, + "maxPoints": 1, + "icon": "t_ui_iconskilltreeskillobservation_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-explorer1" + }, + { + "tag": "Skills.Attribute.Explorer2", + "id": "Explorer2", + "name": "Mountaineer", + "kind": "Attribute", + "row": 4, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeskillclimber_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-explorer2" + }, + { + "tag": "Skills.Ability.SuspensorPad", + "id": "SuspensorPad", + "name": "Suspensor Pad", + "kind": "Ability", + "row": 5, + "col": 2, + "maxPoints": 1, + "icon": "t_ui_iconabilitysuspensorpad_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-suspensorpad" + } + ], + "edges": [ + { + "from": "Skills.Attribute.Explorer3", + "to": "Skills.Attribute.Explorer5" + }, + { + "from": "Skills.Attribute.Explorer4", + "to": "Skills.Attribute.Explorer5" + }, + { + "from": "Skills.Attribute.Explorer1", + "to": "Skills.Attribute.Explorer3" + }, + { + "from": "Skills.Attribute.Explorer2", + "to": "Skills.Attribute.Explorer4" + }, + { + "from": "Skills.Ability.SuspensorPad", + "to": "Skills.Attribute.Explorer1" + }, + { + "from": "Skills.Ability.SuspensorPad", + "to": "Skills.Attribute.Explorer2" + } + ] }, { - "tag": "Skills.Science.m_PowerMax", - "id": "m_PowerMax", - "name": "Overcharge", - "kind": "Science", - "row": 2, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributemineralyield_d.webp", - "url": "https://dune.gaming.tools/skills/skills-science-m_powermax" - }, - { - "tag": "Skills.Attribute.Scientist4", - "id": "Scientist4", - "name": "Deep Analysis", - "kind": "Attribute", - "row": 3, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributemineralyield_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-scientist4" - }, - { - "tag": "Skills.Attribute.Scientist2", - "id": "Scientist2", - "name": "Dew Gathering", - "kind": "Attribute", - "row": 4, - "col": 1, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributewatheryield_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-scientist2" - }, - { - "tag": "Skills.Attribute.Scientist3", - "id": "Scientist3", - "name": "Rerouting", - "kind": "Attribute", - "row": 4, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeskillpowerefficiency_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-scientist3" - }, - { - "tag": "Skills.Attribute.Scientist1", - "id": "Scientist1", - "name": "Cutteray Mining", - "kind": "Attribute", - "row": 5, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributemineralyield_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-scientist1" - }, - { - "tag": "Skills.Attribute.Explorer5", - "id": "Explorer5", - "name": "Spice Surveyor", - "kind": "Attribute", - "row": 1, - "col": 2, - "maxPoints": 1, - "icon": "t_ui_iconskilltreeattributespice_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-explorer5" - }, - { - "tag": "Skills.Attribute.Explorer3", - "id": "Explorer3", - "name": "Scanner Mastery", - "kind": "Attribute", - "row": 2, - "col": 1, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributescanningbonus_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-explorer3" - }, - { - "tag": "Skills.Attribute.Explorer4", - "id": "Explorer4", - "name": "Stillsuit Seals", - "kind": "Attribute", - "row": 2, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeskillhydration_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-explorer4" - }, - { - "tag": "Skills.Attribute.Explorer1", - "id": "Explorer1", - "name": "Cartographer", - "kind": "Attribute", - "row": 4, - "col": 1, - "maxPoints": 1, - "icon": "t_ui_iconskilltreeskillobservation_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-explorer1" - }, - { - "tag": "Skills.Attribute.Explorer2", - "id": "Explorer2", - "name": "Mountaineer", - "kind": "Attribute", - "row": 4, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeskillclimber_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-explorer2" - }, - { - "tag": "Skills.Ability.SuspensorPad", - "id": "SuspensorPad", - "name": "Suspensor Pad", - "kind": "Ability", - "row": 5, - "col": 2, - "maxPoints": 1, - "icon": "t_ui_iconabilitysuspensorpad_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-suspensorpad" - }, - { - "tag": "Skills.Spice.VehicleHeat", - "id": "VehicleHeat", - "name": "Heat Management", - "kind": "Spice", - "row": 1, - "col": 2, - "maxPoints": 1, - "icon": "t_ui_iconskilltreeheatmanagement_d.webp", - "url": "https://dune.gaming.tools/skills/skills-spice-vehicleheat" - }, - { - "tag": "Skills.Attribute.Driver5", - "id": "Driver5", - "name": "Fuel Efficient Pilot", - "kind": "Attribute", - "row": 2, - "col": 1, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributevehicle_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-driver5" - }, - { - "tag": "Skills.Attribute.Driver6", - "id": "Driver6", - "name": "Sandcrawler Yield", - "kind": "Attribute", - "row": 2, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributespiceyield_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-driver6" - }, - { - "tag": "Skills.Attribute.Driver4", - "id": "Driver4", - "name": "Vehicle Scanning", - "kind": "Attribute", - "row": 3, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributescanningbonus_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-driver4" - }, - { - "tag": "Skills.Attribute.Driver2", - "id": "Driver2", - "name": "Fuel Efficient Driver", - "kind": "Attribute", - "row": 4, - "col": 1, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributevehicle_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-driver2" - }, - { - "tag": "Skills.Attribute.Driver3", - "id": "Driver3", - "name": "Vehicle Mining", - "kind": "Attribute", - "row": 4, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributemineralyield_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-driver3" - }, - { - "tag": "Skills.Attribute.Driver1", - "id": "Driver1", - "name": "Vehicle Repair", - "kind": "Attribute", - "row": 5, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributerepairefficiency_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-driver1" - } - ], - "edges": [ - { - "from": "Skills.Attribute.Scientist5", - "to": "Skills.Perk.BatteryExpert" - }, - { - "from": "Skills.Perk.BatteryExpert", - "to": "Skills.Science.m_PowerMax" - }, - { - "from": "Skills.Attribute.Scientist4", - "to": "Skills.Attribute.Scientist5" - }, - { - "from": "Skills.Attribute.Scientist2", - "to": "Skills.Attribute.Scientist5" - }, - { - "from": "Skills.Attribute.Scientist4", - "to": "Skills.Science.m_PowerMax" - }, - { - "from": "Skills.Attribute.Scientist3", - "to": "Skills.Science.m_PowerMax" - }, - { - "from": "Skills.Attribute.Scientist2", - "to": "Skills.Attribute.Scientist4" - }, - { - "from": "Skills.Attribute.Scientist3", - "to": "Skills.Attribute.Scientist4" - }, - { - "from": "Skills.Attribute.Scientist1", - "to": "Skills.Attribute.Scientist2" - }, - { - "from": "Skills.Attribute.Scientist1", - "to": "Skills.Attribute.Scientist3" + "name": "Mechanic", + "cols": 3, + "nodes": [ + { + "tag": "Skills.Spice.VehicleHeat", + "id": "VehicleHeat", + "name": "Heat Management", + "kind": "Spice", + "row": 1, + "col": 2, + "maxPoints": 1, + "icon": "t_ui_iconskilltreeheatmanagement_d.webp", + "url": "https://dune.gaming.tools/skills/skills-spice-vehicleheat" + }, + { + "tag": "Skills.Attribute.Driver5", + "id": "Driver5", + "name": "Fuel Efficient Pilot", + "kind": "Attribute", + "row": 2, + "col": 1, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributevehicle_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-driver5" + }, + { + "tag": "Skills.Attribute.Driver6", + "id": "Driver6", + "name": "Sandcrawler Yield", + "kind": "Attribute", + "row": 2, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributespiceyield_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-driver6" + }, + { + "tag": "Skills.Attribute.Driver4", + "id": "Driver4", + "name": "Vehicle Scanning", + "kind": "Attribute", + "row": 3, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributescanningbonus_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-driver4" + }, + { + "tag": "Skills.Attribute.Driver2", + "id": "Driver2", + "name": "Fuel Efficient Driver", + "kind": "Attribute", + "row": 4, + "col": 1, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributevehicle_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-driver2" + }, + { + "tag": "Skills.Attribute.Driver3", + "id": "Driver3", + "name": "Vehicle Mining", + "kind": "Attribute", + "row": 4, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributemineralyield_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-driver3" + }, + { + "tag": "Skills.Attribute.Driver1", + "id": "Driver1", + "name": "Vehicle Repair", + "kind": "Attribute", + "row": 5, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributerepairefficiency_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-driver1" + } + ], + "edges": [ + { + "from": "Skills.Attribute.Driver5", + "to": "Skills.Spice.VehicleHeat" + }, + { + "from": "Skills.Attribute.Driver6", + "to": "Skills.Spice.VehicleHeat" + }, + { + "from": "Skills.Attribute.Driver4", + "to": "Skills.Attribute.Driver5" + }, + { + "from": "Skills.Attribute.Driver2", + "to": "Skills.Attribute.Driver5" + }, + { + "from": "Skills.Attribute.Driver4", + "to": "Skills.Attribute.Driver6" + }, + { + "from": "Skills.Attribute.Driver3", + "to": "Skills.Attribute.Driver6" + }, + { + "from": "Skills.Attribute.Driver2", + "to": "Skills.Attribute.Driver4" + }, + { + "from": "Skills.Attribute.Driver3", + "to": "Skills.Attribute.Driver4" + }, + { + "from": "Skills.Attribute.Driver1", + "to": "Skills.Attribute.Driver2" + }, + { + "from": "Skills.Attribute.Driver1", + "to": "Skills.Attribute.Driver3" + } + ] } ] } \ No newline at end of file diff --git a/character-builder/data/skills-swordmaster.json b/character-builder/data/skills-swordmaster.json index 81def91..c3f1aee 100644 --- a/character-builder/data/skills-swordmaster.json +++ b/character-builder/data/skills-swordmaster.json @@ -1,338 +1,384 @@ { "id": "swordmaster", "name": "Swordmaster", - "nodes": [ + "subtrees": [ { - "tag": "Skills.Spice.ParryBoost", - "id": "ParryBoost", - "name": "Precise Parry", - "kind": "Spice", - "row": 1, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_iconskilltreepreciseparry_d.webp", - "url": "https://dune.gaming.tools/skills/skills-spice-parryboost" + "name": "The Blade", + "cols": 3, + "nodes": [ + { + "tag": "Skills.Spice.ParryBoost", + "id": "ParryBoost", + "name": "Precise Parry", + "kind": "Spice", + "row": 1, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_iconskilltreepreciseparry_d.webp", + "url": "https://dune.gaming.tools/skills/skills-spice-parryboost" + }, + { + "tag": "Skills.Ability.Whirlwind", + "id": "Whirlwind", + "name": "Eye of the Storm", + "kind": "Ability", + "row": 2, + "col": 1, + "maxPoints": 3, + "icon": "t_ui_iconabilitywhirlwind_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-whirlwind" + }, + { + "tag": "Skills.Ability.RiposteBreak", + "id": "RiposteBreak", + "name": "Foil", + "kind": "Ability", + "row": 2, + "col": 3, + "maxPoints": 1, + "icon": "t_ui_iconabilitybreakingreposte_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-ripostebreak" + }, + { + "tag": "Skills.Attribute.Blade2", + "id": "Blade2", + "name": "Long Blade Damage", + "kind": "Attribute", + "row": 3, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeskillbrawler_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-blade2" + }, + { + "tag": "Skills.Perk.MeleeChain", + "id": "MeleeChain", + "name": "Dance of Blades", + "kind": "Perk", + "row": 4, + "col": 1, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeperkbladechaining_d.webp", + "url": "https://dune.gaming.tools/skills/skills-perk-meleechain" + }, + { + "tag": "Skills.Ability.RiposteInjure", + "id": "RiposteInjure", + "name": "Retaliate", + "kind": "Ability", + "row": 4, + "col": 3, + "maxPoints": 1, + "icon": "t_ui_iconabilityinjuringreposte_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-riposteinjure" + }, + { + "tag": "Skills.Attribute.Blade1", + "id": "Blade1", + "name": "Blade Damage", + "kind": "Attribute", + "row": 5, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeskillbrawler_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-blade1" + } + ], + "edges": [ + { + "from": "Skills.Ability.Whirlwind", + "to": "Skills.Spice.ParryBoost" + }, + { + "from": "Skills.Ability.RiposteBreak", + "to": "Skills.Spice.ParryBoost" + }, + { + "from": "Skills.Ability.Whirlwind", + "to": "Skills.Attribute.Blade2" + }, + { + "from": "Skills.Ability.Whirlwind", + "to": "Skills.Perk.MeleeChain" + }, + { + "from": "Skills.Ability.RiposteBreak", + "to": "Skills.Attribute.Blade2" + }, + { + "from": "Skills.Ability.RiposteBreak", + "to": "Skills.Ability.RiposteInjure" + }, + { + "from": "Skills.Attribute.Blade2", + "to": "Skills.Perk.MeleeChain" + }, + { + "from": "Skills.Ability.RiposteInjure", + "to": "Skills.Attribute.Blade2" + }, + { + "from": "Skills.Attribute.Blade1", + "to": "Skills.Perk.MeleeChain" + }, + { + "from": "Skills.Ability.RiposteInjure", + "to": "Skills.Attribute.Blade1" + } + ] }, { - "tag": "Skills.Ability.Whirlwind", - "id": "Whirlwind", - "name": "Eye of the Storm", - "kind": "Ability", - "row": 2, - "col": 1, - "maxPoints": 3, - "icon": "t_ui_iconabilitywhirlwind_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-whirlwind" + "name": "The Will", + "cols": 3, + "nodes": [ + { + "tag": "Skills.Perk.ThriveOnDanger", + "id": "ThriveOnDanger", + "name": "Thrive on Danger", + "kind": "Perk", + "row": 1, + "col": 2, + "maxPoints": 1, + "icon": "t_ui_iconskilltreethriveondanger_d.webp", + "url": "https://dune.gaming.tools/skills/skills-perk-thriveondanger" + }, + { + "tag": "Skills.Attribute.Resolve2", + "id": "Resolve2", + "name": "Solid Stance", + "kind": "Attribute", + "row": 2, + "col": 1, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributepoisedefense_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-resolve2" + }, + { + "tag": "Skills.Attribute.UnstoppableAttacks", + "id": "UnstoppableAttacks", + "name": "Confidence", + "kind": "Attribute", + "row": 2, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributedamagemitigation_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-unstoppableattacks" + }, + { + "tag": "Skills.Attribute.Resolve1", + "id": "Resolve1", + "name": "Bleed Tolerance", + "kind": "Attribute", + "row": 4, + "col": 1, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeskillmaxhealth_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-resolve1" + }, + { + "tag": "Skills.Perk.ToughLunge", + "id": "ToughLunge", + "name": "Reckless Lunge", + "kind": "Perk", + "row": 4, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconskilltreetoughlunge_d.webp", + "url": "https://dune.gaming.tools/skills/skills-perk-toughlunge" + }, + { + "tag": "Skills.Ability.DeflectionSlow", + "id": "DeflectionSlow", + "name": "Deflection", + "kind": "Ability", + "row": 5, + "col": 2, + "maxPoints": 1, + "icon": "t_ui_iconabilitydeflection_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-deflectionslow" + } + ], + "edges": [ + { + "from": "Skills.Attribute.Resolve2", + "to": "Skills.Perk.ThriveOnDanger" + }, + { + "from": "Skills.Attribute.UnstoppableAttacks", + "to": "Skills.Perk.ThriveOnDanger" + }, + { + "from": "Skills.Attribute.Resolve1", + "to": "Skills.Attribute.Resolve2" + }, + { + "from": "Skills.Attribute.UnstoppableAttacks", + "to": "Skills.Perk.ToughLunge" + }, + { + "from": "Skills.Ability.DeflectionSlow", + "to": "Skills.Attribute.Resolve1" + }, + { + "from": "Skills.Ability.DeflectionSlow", + "to": "Skills.Perk.ToughLunge" + } + ] }, { - "tag": "Skills.Ability.RiposteBreak", - "id": "RiposteBreak", - "name": "Foil", - "kind": "Ability", - "row": 2, - "col": 3, - "maxPoints": 1, - "icon": "t_ui_iconabilitybreakingreposte_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-ripostebreak" - }, - { - "tag": "Skills.Attribute.Blade2", - "id": "Blade2", - "name": "Long Blade Damage", - "kind": "Attribute", - "row": 3, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeskillbrawler_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-blade2" - }, - { - "tag": "Skills.Perk.MeleeChain", - "id": "MeleeChain", - "name": "Dance of Blades", - "kind": "Perk", - "row": 4, - "col": 1, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeperkbladechaining_d.webp", - "url": "https://dune.gaming.tools/skills/skills-perk-meleechain" - }, - { - "tag": "Skills.Ability.RiposteInjure", - "id": "RiposteInjure", - "name": "Retaliate", - "kind": "Ability", - "row": 4, - "col": 3, - "maxPoints": 1, - "icon": "t_ui_iconabilityinjuringreposte_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-riposteinjure" - }, - { - "tag": "Skills.Attribute.Blade1", - "id": "Blade1", - "name": "Blade Damage", - "kind": "Attribute", - "row": 5, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeskillbrawler_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-blade1" - }, - { - "tag": "Skills.Perk.ThriveOnDanger", - "id": "ThriveOnDanger", - "name": "Thrive on Danger", - "kind": "Perk", - "row": 1, - "col": 2, - "maxPoints": 1, - "icon": "t_ui_iconskilltreethriveondanger_d.webp", - "url": "https://dune.gaming.tools/skills/skills-perk-thriveondanger" - }, - { - "tag": "Skills.Attribute.Resolve2", - "id": "Resolve2", - "name": "Solid Stance", - "kind": "Attribute", - "row": 2, - "col": 1, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributepoisedefense_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-resolve2" - }, - { - "tag": "Skills.Attribute.UnstoppableAttacks", - "id": "UnstoppableAttacks", - "name": "Confidence", - "kind": "Attribute", - "row": 2, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributedamagemitigation_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-unstoppableattacks" - }, - { - "tag": "Skills.Attribute.Resolve1", - "id": "Resolve1", - "name": "Bleed Tolerance", - "kind": "Attribute", - "row": 4, - "col": 1, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeskillmaxhealth_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-resolve1" - }, - { - "tag": "Skills.Perk.ToughLunge", - "id": "ToughLunge", - "name": "Reckless Lunge", - "kind": "Perk", - "row": 4, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconskilltreetoughlunge_d.webp", - "url": "https://dune.gaming.tools/skills/skills-perk-toughlunge" - }, - { - "tag": "Skills.Ability.DeflectionSlow", - "id": "DeflectionSlow", - "name": "Deflection", - "kind": "Ability", - "row": 5, - "col": 2, - "maxPoints": 1, - "icon": "t_ui_iconabilitydeflection_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-deflectionslow" - }, - { - "tag": "Skills.Spice.ShadowStrike", - "id": "ShadowStrike", - "name": "Prescient Strike", - "kind": "Spice", - "row": 1, - "col": 3, - "maxPoints": 1, - "icon": "t_ui_iconskilltreeprescientstrike_d.webp", - "url": "https://dune.gaming.tools/skills/skills-spice-shadowstrike" - }, - { - "tag": "Skills.Attribute.Aggression3", - "id": "Aggression3", - "name": "General Conditioning", - "kind": "Attribute", - "row": 2, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributestamina_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-aggression3" - }, - { - "tag": "Skills.Attribute.Aggression4", - "id": "Aggression4", - "name": "Desert Conditioning", - "kind": "Attribute", - "row": 2, - "col": 4, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributewatherdefense_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-aggression4" - }, - { - "tag": "Skills.Ability.CripplingStrike", - "id": "CripplingStrike", - "name": "Crippling Strike", - "kind": "Ability", - "row": 3, - "col": 1, - "maxPoints": 1, - "icon": "t_ui_iconabilitycripplingstrike_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-cripplingstrike" - }, - { - "tag": "Skills.Perk.SprintStamina", - "id": "SprintStamina", - "name": "Disciplined Breathing", - "kind": "Perk", - "row": 3, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeperkrunner_d.webp", - "url": "https://dune.gaming.tools/skills/skills-perk-sprintstamina" - }, - { - "tag": "Skills.Ability.BattleCry", - "id": "BattleCry", - "name": "Inspiration", - "kind": "Ability", - "row": 3, - "col": 5, - "maxPoints": 3, - "icon": "t_ui_iconabilitybattlecry_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-battlecry" - }, - { - "tag": "Skills.Attribute.Aggression1", - "id": "Aggression1", - "name": "Field Medicine", - "kind": "Attribute", - "row": 4, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeskillhealingmultiplier_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-aggression1" - }, - { - "tag": "Skills.Attribute.Aggression2", - "id": "Aggression2", - "name": "Optimized Hydration", - "kind": "Attribute", - "row": 4, - "col": 4, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributewatherbonus_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-aggression2" - }, - { - "tag": "Skills.Ability.KneeCharge", - "id": "KneeCharge", - "name": "Knee Charge", - "kind": "Ability", - "row": 5, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconabilitykneecharge_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-kneecharge" - } - ], - "edges": [ - { - "from": "Skills.Ability.Whirlwind", - "to": "Skills.Spice.ParryBoost" - }, - { - "from": "Skills.Ability.RiposteBreak", - "to": "Skills.Spice.ParryBoost" - }, - { - "from": "Skills.Ability.Whirlwind", - "to": "Skills.Attribute.Blade2" - }, - { - "from": "Skills.Ability.Whirlwind", - "to": "Skills.Perk.MeleeChain" - }, - { - "from": "Skills.Ability.RiposteBreak", - "to": "Skills.Attribute.Blade2" - }, - { - "from": "Skills.Ability.RiposteBreak", - "to": "Skills.Ability.RiposteInjure" - }, - { - "from": "Skills.Attribute.Blade2", - "to": "Skills.Perk.MeleeChain" - }, - { - "from": "Skills.Ability.RiposteInjure", - "to": "Skills.Attribute.Blade2" - }, - { - "from": "Skills.Attribute.Blade1", - "to": "Skills.Perk.MeleeChain" - }, - { - "from": "Skills.Ability.RiposteInjure", - "to": "Skills.Attribute.Blade1" - }, - { - "from": "Skills.Attribute.Aggression3", - "to": "Skills.Spice.ShadowStrike" - }, - { - "from": "Skills.Attribute.Aggression4", - "to": "Skills.Spice.ShadowStrike" - }, - { - "from": "Skills.Ability.CripplingStrike", - "to": "Skills.Attribute.Aggression3" - }, - { - "from": "Skills.Attribute.Aggression3", - "to": "Skills.Perk.SprintStamina" - }, - { - "from": "Skills.Attribute.Aggression4", - "to": "Skills.Perk.SprintStamina" - }, - { - "from": "Skills.Ability.BattleCry", - "to": "Skills.Attribute.Aggression4" - }, - { - "from": "Skills.Ability.CripplingStrike", - "to": "Skills.Attribute.Aggression1" - }, - { - "from": "Skills.Attribute.Aggression1", - "to": "Skills.Perk.SprintStamina" - }, - { - "from": "Skills.Attribute.Aggression2", - "to": "Skills.Perk.SprintStamina" - }, - { - "from": "Skills.Ability.BattleCry", - "to": "Skills.Attribute.Aggression2" - }, - { - "from": "Skills.Ability.KneeCharge", - "to": "Skills.Attribute.Aggression1" - }, - { - "from": "Skills.Ability.KneeCharge", - "to": "Skills.Attribute.Aggression2" + "name": "The Way", + "cols": 5, + "nodes": [ + { + "tag": "Skills.Spice.ShadowStrike", + "id": "ShadowStrike", + "name": "Prescient Strike", + "kind": "Spice", + "row": 1, + "col": 3, + "maxPoints": 1, + "icon": "t_ui_iconskilltreeprescientstrike_d.webp", + "url": "https://dune.gaming.tools/skills/skills-spice-shadowstrike" + }, + { + "tag": "Skills.Attribute.Aggression3", + "id": "Aggression3", + "name": "General Conditioning", + "kind": "Attribute", + "row": 2, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributestamina_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-aggression3" + }, + { + "tag": "Skills.Attribute.Aggression4", + "id": "Aggression4", + "name": "Desert Conditioning", + "kind": "Attribute", + "row": 2, + "col": 4, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributewatherdefense_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-aggression4" + }, + { + "tag": "Skills.Ability.CripplingStrike", + "id": "CripplingStrike", + "name": "Crippling Strike", + "kind": "Ability", + "row": 3, + "col": 1, + "maxPoints": 1, + "icon": "t_ui_iconabilitycripplingstrike_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-cripplingstrike" + }, + { + "tag": "Skills.Perk.SprintStamina", + "id": "SprintStamina", + "name": "Disciplined Breathing", + "kind": "Perk", + "row": 3, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeperkrunner_d.webp", + "url": "https://dune.gaming.tools/skills/skills-perk-sprintstamina" + }, + { + "tag": "Skills.Ability.BattleCry", + "id": "BattleCry", + "name": "Inspiration", + "kind": "Ability", + "row": 3, + "col": 5, + "maxPoints": 3, + "icon": "t_ui_iconabilitybattlecry_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-battlecry" + }, + { + "tag": "Skills.Attribute.Aggression1", + "id": "Aggression1", + "name": "Field Medicine", + "kind": "Attribute", + "row": 4, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeskillhealingmultiplier_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-aggression1" + }, + { + "tag": "Skills.Attribute.Aggression2", + "id": "Aggression2", + "name": "Optimized Hydration", + "kind": "Attribute", + "row": 4, + "col": 4, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributewatherbonus_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-aggression2" + }, + { + "tag": "Skills.Ability.KneeCharge", + "id": "KneeCharge", + "name": "Knee Charge", + "kind": "Ability", + "row": 5, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconabilitykneecharge_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-kneecharge" + } + ], + "edges": [ + { + "from": "Skills.Attribute.Aggression3", + "to": "Skills.Spice.ShadowStrike" + }, + { + "from": "Skills.Attribute.Aggression4", + "to": "Skills.Spice.ShadowStrike" + }, + { + "from": "Skills.Ability.CripplingStrike", + "to": "Skills.Attribute.Aggression3" + }, + { + "from": "Skills.Attribute.Aggression3", + "to": "Skills.Perk.SprintStamina" + }, + { + "from": "Skills.Attribute.Aggression4", + "to": "Skills.Perk.SprintStamina" + }, + { + "from": "Skills.Ability.BattleCry", + "to": "Skills.Attribute.Aggression4" + }, + { + "from": "Skills.Ability.CripplingStrike", + "to": "Skills.Attribute.Aggression1" + }, + { + "from": "Skills.Attribute.Aggression1", + "to": "Skills.Perk.SprintStamina" + }, + { + "from": "Skills.Attribute.Aggression2", + "to": "Skills.Perk.SprintStamina" + }, + { + "from": "Skills.Ability.BattleCry", + "to": "Skills.Attribute.Aggression2" + }, + { + "from": "Skills.Ability.KneeCharge", + "to": "Skills.Attribute.Aggression1" + }, + { + "from": "Skills.Ability.KneeCharge", + "to": "Skills.Attribute.Aggression2" + } + ] } ] } \ No newline at end of file diff --git a/character-builder/data/skills-trooper.json b/character-builder/data/skills-trooper.json index 15f8828..6a2c3fd 100644 --- a/character-builder/data/skills-trooper.json +++ b/character-builder/data/skills-trooper.json @@ -1,338 +1,384 @@ { "id": "trooper", "name": "Trooper", - "nodes": [ + "subtrees": [ { - "tag": "Skills.Ability.EnergyCapsule", - "id": "EnergyCapsule", - "name": "Energy Capsule", - "kind": "Ability", - "row": 1, - "col": 3, - "maxPoints": 1, - "icon": "t_ui_iconabilityenergycapsule_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-energycapsule" + "name": "Gunnery", + "cols": 5, + "nodes": [ + { + "tag": "Skills.Ability.EnergyCapsule", + "id": "EnergyCapsule", + "name": "Energy Capsule", + "kind": "Ability", + "row": 1, + "col": 3, + "maxPoints": 1, + "icon": "t_ui_iconabilityenergycapsule_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-energycapsule" + }, + { + "tag": "Skills.Attribute.Weaponry5", + "id": "Weaponry5", + "name": "Heavy Weapon Damage", + "kind": "Attribute", + "row": 2, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributedamagebonusheavyweapon_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-weaponry5" + }, + { + "tag": "Skills.Attribute.Weaponry6", + "id": "Weaponry6", + "name": "Gunsmith", + "kind": "Attribute", + "row": 2, + "col": 4, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributerepairefficiency_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-weaponry6" + }, + { + "tag": "Skills.Perk.HeavyWeaponNaib", + "id": "HeavyWeaponNaib", + "name": "Heavy Weapon Agility", + "kind": "Perk", + "row": 3, + "col": 1, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeperkheavyweaponnaib_d.webp", + "url": "https://dune.gaming.tools/skills/skills-perk-heavyweaponnaib" + }, + { + "tag": "Skills.Attribute.Weaponry3", + "id": "Weaponry3", + "name": "Scattergun Damage", + "kind": "Attribute", + "row": 3, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributedamagebonusrifle_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-weaponry3" + }, + { + "tag": "Skills.Attribute.Weaponry4", + "id": "Weaponry4", + "name": "Field Maintenance", + "kind": "Attribute", + "row": 3, + "col": 5, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributerepair_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-weaponry4" + }, + { + "tag": "Skills.Attribute.Weaponry2", + "id": "Weaponry2", + "name": "Disruptor Damage", + "kind": "Attribute", + "row": 4, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributedamagebonussmg_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-weaponry2" + }, + { + "tag": "Skills.Perk.BodyShots", + "id": "BodyShots", + "name": "Center of Mass", + "kind": "Perk", + "row": 4, + "col": 4, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeperkcentralaim_d.webp", + "url": "https://dune.gaming.tools/skills/skills-perk-bodyshots" + }, + { + "tag": "Skills.Attribute.Weaponry1", + "id": "Weaponry1", + "name": "Ranged Damage", + "kind": "Attribute", + "row": 5, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeattributedamage_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-weaponry1" + } + ], + "edges": [ + { + "from": "Skills.Ability.EnergyCapsule", + "to": "Skills.Attribute.Weaponry5" + }, + { + "from": "Skills.Ability.EnergyCapsule", + "to": "Skills.Attribute.Weaponry6" + }, + { + "from": "Skills.Attribute.Weaponry5", + "to": "Skills.Perk.HeavyWeaponNaib" + }, + { + "from": "Skills.Attribute.Weaponry3", + "to": "Skills.Attribute.Weaponry5" + }, + { + "from": "Skills.Attribute.Weaponry3", + "to": "Skills.Attribute.Weaponry6" + }, + { + "from": "Skills.Attribute.Weaponry4", + "to": "Skills.Attribute.Weaponry6" + }, + { + "from": "Skills.Attribute.Weaponry2", + "to": "Skills.Perk.HeavyWeaponNaib" + }, + { + "from": "Skills.Attribute.Weaponry2", + "to": "Skills.Attribute.Weaponry3" + }, + { + "from": "Skills.Attribute.Weaponry3", + "to": "Skills.Perk.BodyShots" + }, + { + "from": "Skills.Attribute.Weaponry4", + "to": "Skills.Perk.BodyShots" + }, + { + "from": "Skills.Attribute.Weaponry1", + "to": "Skills.Attribute.Weaponry2" + }, + { + "from": "Skills.Attribute.Weaponry1", + "to": "Skills.Perk.BodyShots" + } + ] }, { - "tag": "Skills.Attribute.Weaponry5", - "id": "Weaponry5", - "name": "Heavy Weapon Damage", - "kind": "Attribute", - "row": 2, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributedamagebonusheavyweapon_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-weaponry5" + "name": "Suspensor Training", + "cols": 3, + "nodes": [ + { + "tag": "Skills.Ability.SuspensorBlast", + "id": "SuspensorBlast", + "name": "Suspensor Blast", + "kind": "Ability", + "row": 1, + "col": 2, + "maxPoints": 1, + "icon": "t_ui_iconabilitysuspensorblast_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-suspensorblast" + }, + { + "tag": "Skills.Perk.DeathFromAbove", + "id": "DeathFromAbove", + "name": "Death from Above", + "kind": "Perk", + "row": 2, + "col": 1, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeperkdeathfromabove_d.webp", + "url": "https://dune.gaming.tools/skills/skills-perk-deathfromabove" + }, + { + "tag": "Skills.Ability.CollapseGrenade", + "id": "CollapseGrenade", + "name": "Collapse Grenade", + "kind": "Ability", + "row": 2, + "col": 3, + "maxPoints": 1, + "icon": "t_ui_iconabilitycollapsegrenade_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-collapsegrenade" + }, + { + "tag": "Skills.Attribute.SuspensorTech1", + "id": "SuspensorTech1", + "name": "Suspensor Efficiency", + "kind": "Attribute", + "row": 3, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_iconskilltreeskillpowerefficiency_d.webp", + "url": "https://dune.gaming.tools/skills/skills-attribute-suspensortech1" + }, + { + "tag": "Skills.Perk.SuspensorDash", + "id": "SuspensorDash", + "name": "Suspensor Dash", + "kind": "Perk", + "row": 4, + "col": 1, + "maxPoints": 1, + "icon": "t_ui_iconskilltreesuspensordash_d.webp", + "url": "https://dune.gaming.tools/skills/skills-perk-suspensordash" + }, + { + "tag": "Skills.Ability.SuspensorGrenade_Amplification", + "id": "SuspensorGrenade_Amplification", + "name": "Gravity Field", + "kind": "Ability", + "row": 4, + "col": 3, + "maxPoints": 1, + "icon": "t_ui_icongadgetamplificationgrenade_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-suspensorgrenade_amplification" + }, + { + "tag": "Skills.Ability.SuspensorGrenade_Reduction", + "id": "SuspensorGrenade_Reduction", + "name": "Anti-gravity Field", + "kind": "Ability", + "row": 5, + "col": 2, + "maxPoints": 1, + "icon": "t_ui_icongadgetreductionsuspensorgrenade_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-suspensorgrenade_reduction" + } + ], + "edges": [ + { + "from": "Skills.Ability.SuspensorBlast", + "to": "Skills.Perk.DeathFromAbove" + }, + { + "from": "Skills.Ability.CollapseGrenade", + "to": "Skills.Ability.SuspensorBlast" + }, + { + "from": "Skills.Attribute.SuspensorTech1", + "to": "Skills.Perk.DeathFromAbove" + }, + { + "from": "Skills.Perk.DeathFromAbove", + "to": "Skills.Perk.SuspensorDash" + }, + { + "from": "Skills.Ability.CollapseGrenade", + "to": "Skills.Attribute.SuspensorTech1" + }, + { + "from": "Skills.Ability.CollapseGrenade", + "to": "Skills.Ability.SuspensorGrenade_Amplification" + }, + { + "from": "Skills.Attribute.SuspensorTech1", + "to": "Skills.Perk.SuspensorDash" + }, + { + "from": "Skills.Ability.SuspensorGrenade_Amplification", + "to": "Skills.Attribute.SuspensorTech1" + }, + { + "from": "Skills.Ability.SuspensorGrenade_Reduction", + "to": "Skills.Perk.SuspensorDash" + }, + { + "from": "Skills.Ability.SuspensorGrenade_Amplification", + "to": "Skills.Ability.SuspensorGrenade_Reduction" + } + ] }, { - "tag": "Skills.Attribute.Weaponry6", - "id": "Weaponry6", - "name": "Gunsmith", - "kind": "Attribute", - "row": 2, - "col": 4, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributerepairefficiency_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-weaponry6" - }, - { - "tag": "Skills.Perk.HeavyWeaponNaib", - "id": "HeavyWeaponNaib", - "name": "Heavy Weapon Agility", - "kind": "Perk", - "row": 3, - "col": 1, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeperkheavyweaponnaib_d.webp", - "url": "https://dune.gaming.tools/skills/skills-perk-heavyweaponnaib" - }, - { - "tag": "Skills.Attribute.Weaponry3", - "id": "Weaponry3", - "name": "Scattergun Damage", - "kind": "Attribute", - "row": 3, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributedamagebonusrifle_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-weaponry3" - }, - { - "tag": "Skills.Attribute.Weaponry4", - "id": "Weaponry4", - "name": "Field Maintenance", - "kind": "Attribute", - "row": 3, - "col": 5, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributerepair_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-weaponry4" - }, - { - "tag": "Skills.Attribute.Weaponry2", - "id": "Weaponry2", - "name": "Disruptor Damage", - "kind": "Attribute", - "row": 4, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributedamagebonussmg_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-weaponry2" - }, - { - "tag": "Skills.Perk.BodyShots", - "id": "BodyShots", - "name": "Center of Mass", - "kind": "Perk", - "row": 4, - "col": 4, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeperkcentralaim_d.webp", - "url": "https://dune.gaming.tools/skills/skills-perk-bodyshots" - }, - { - "tag": "Skills.Attribute.Weaponry1", - "id": "Weaponry1", - "name": "Ranged Damage", - "kind": "Attribute", - "row": 5, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeattributedamage_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-weaponry1" - }, - { - "tag": "Skills.Ability.SuspensorBlast", - "id": "SuspensorBlast", - "name": "Suspensor Blast", - "kind": "Ability", - "row": 1, - "col": 2, - "maxPoints": 1, - "icon": "t_ui_iconabilitysuspensorblast_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-suspensorblast" - }, - { - "tag": "Skills.Perk.DeathFromAbove", - "id": "DeathFromAbove", - "name": "Death from Above", - "kind": "Perk", - "row": 2, - "col": 1, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeperkdeathfromabove_d.webp", - "url": "https://dune.gaming.tools/skills/skills-perk-deathfromabove" - }, - { - "tag": "Skills.Ability.CollapseGrenade", - "id": "CollapseGrenade", - "name": "Collapse Grenade", - "kind": "Ability", - "row": 2, - "col": 3, - "maxPoints": 1, - "icon": "t_ui_iconabilitycollapsegrenade_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-collapsegrenade" - }, - { - "tag": "Skills.Attribute.SuspensorTech1", - "id": "SuspensorTech1", - "name": "Suspensor Efficiency", - "kind": "Attribute", - "row": 3, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_iconskilltreeskillpowerefficiency_d.webp", - "url": "https://dune.gaming.tools/skills/skills-attribute-suspensortech1" - }, - { - "tag": "Skills.Perk.SuspensorDash", - "id": "SuspensorDash", - "name": "Suspensor Dash", - "kind": "Perk", - "row": 4, - "col": 1, - "maxPoints": 1, - "icon": "t_ui_iconskilltreesuspensordash_d.webp", - "url": "https://dune.gaming.tools/skills/skills-perk-suspensordash" - }, - { - "tag": "Skills.Ability.SuspensorGrenade_Amplification", - "id": "SuspensorGrenade_Amplification", - "name": "Gravity Field", - "kind": "Ability", - "row": 4, - "col": 3, - "maxPoints": 1, - "icon": "t_ui_icongadgetamplificationgrenade_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-suspensorgrenade_amplification" - }, - { - "tag": "Skills.Ability.SuspensorGrenade_Reduction", - "id": "SuspensorGrenade_Reduction", - "name": "Anti-gravity Field", - "kind": "Ability", - "row": 5, - "col": 2, - "maxPoints": 1, - "icon": "t_ui_icongadgetreductionsuspensorgrenade_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-suspensorgrenade_reduction" - }, - { - "tag": "Skills.Spice.GadgetReload", - "id": "GadgetReload", - "name": "Reflexive Reload", - "kind": "Spice", - "row": 1, - "col": 2, - "maxPoints": 1, - "icon": "t_ui_iconskilltreereflexivereload_d.webp", - "url": "https://dune.gaming.tools/skills/skills-spice-gadgetreload" - }, - { - "tag": "Skills.Ability.AssaultSeeker", - "id": "AssaultSeeker", - "name": "Assault Seeker", - "kind": "Ability", - "row": 2, - "col": 1, - "maxPoints": 3, - "icon": "t_ui_iconabilityassaultseeker_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-assaultseeker" - }, - { - "tag": "Skills.Ability.MagneticAttractor", - "id": "MagneticAttractor", - "name": "Attractor Field", - "kind": "Ability", - "row": 2, - "col": 3, - "maxPoints": 1, - "icon": "t_ui_icongadgetshigmultitoolmagneticattractor_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-magneticattractor" - }, - { - "tag": "Skills.Ability.FragGrenade", - "id": "FragGrenade", - "name": "Explosive Grenade", - "kind": "Ability", - "row": 4, - "col": 1, - "maxPoints": 3, - "icon": "t_ui_icongadgetfraggrenades_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-fraggrenade" - }, - { - "tag": "Skills.Perk.TrooperCooldowns", - "id": "TrooperCooldowns", - "name": "Battle Hardened", - "kind": "Perk", - "row": 4, - "col": 3, - "maxPoints": 3, - "icon": "t_ui_iconskilltreetroopercooldown_d.webp", - "url": "https://dune.gaming.tools/skills/skills-perk-troopercooldowns" - }, - { - "tag": "Skills.Ability.CablePull", - "id": "CablePull", - "name": "Shigawire Claw", - "kind": "Ability", - "row": 5, - "col": 2, - "maxPoints": 3, - "icon": "t_ui_icongadgetshigmultitoolsardaukarpull_d.webp", - "url": "https://dune.gaming.tools/skills/skills-ability-cablepull" - } - ], - "edges": [ - { - "from": "Skills.Ability.EnergyCapsule", - "to": "Skills.Attribute.Weaponry5" - }, - { - "from": "Skills.Ability.EnergyCapsule", - "to": "Skills.Attribute.Weaponry6" - }, - { - "from": "Skills.Attribute.Weaponry5", - "to": "Skills.Perk.HeavyWeaponNaib" - }, - { - "from": "Skills.Attribute.Weaponry3", - "to": "Skills.Attribute.Weaponry5" - }, - { - "from": "Skills.Attribute.Weaponry3", - "to": "Skills.Attribute.Weaponry6" - }, - { - "from": "Skills.Attribute.Weaponry4", - "to": "Skills.Attribute.Weaponry6" - }, - { - "from": "Skills.Attribute.Weaponry2", - "to": "Skills.Perk.HeavyWeaponNaib" - }, - { - "from": "Skills.Attribute.Weaponry2", - "to": "Skills.Attribute.Weaponry3" - }, - { - "from": "Skills.Attribute.Weaponry3", - "to": "Skills.Perk.BodyShots" - }, - { - "from": "Skills.Attribute.Weaponry4", - "to": "Skills.Perk.BodyShots" - }, - { - "from": "Skills.Attribute.Weaponry1", - "to": "Skills.Attribute.Weaponry2" - }, - { - "from": "Skills.Attribute.Weaponry1", - "to": "Skills.Perk.BodyShots" - }, - { - "from": "Skills.Ability.SuspensorBlast", - "to": "Skills.Perk.DeathFromAbove" - }, - { - "from": "Skills.Ability.CollapseGrenade", - "to": "Skills.Ability.SuspensorBlast" - }, - { - "from": "Skills.Attribute.SuspensorTech1", - "to": "Skills.Perk.DeathFromAbove" - }, - { - "from": "Skills.Perk.DeathFromAbove", - "to": "Skills.Perk.SuspensorDash" - }, - { - "from": "Skills.Ability.CollapseGrenade", - "to": "Skills.Attribute.SuspensorTech1" - }, - { - "from": "Skills.Ability.CollapseGrenade", - "to": "Skills.Ability.SuspensorGrenade_Amplification" - }, - { - "from": "Skills.Attribute.SuspensorTech1", - "to": "Skills.Perk.SuspensorDash" - }, - { - "from": "Skills.Ability.SuspensorGrenade_Amplification", - "to": "Skills.Attribute.SuspensorTech1" - }, - { - "from": "Skills.Ability.SuspensorGrenade_Reduction", - "to": "Skills.Perk.SuspensorDash" - }, - { - "from": "Skills.Ability.SuspensorGrenade_Amplification", - "to": "Skills.Ability.SuspensorGrenade_Reduction" + "name": "Tactical Tech", + "cols": 3, + "nodes": [ + { + "tag": "Skills.Spice.GadgetReload", + "id": "GadgetReload", + "name": "Reflexive Reload", + "kind": "Spice", + "row": 1, + "col": 2, + "maxPoints": 1, + "icon": "t_ui_iconskilltreereflexivereload_d.webp", + "url": "https://dune.gaming.tools/skills/skills-spice-gadgetreload" + }, + { + "tag": "Skills.Ability.AssaultSeeker", + "id": "AssaultSeeker", + "name": "Assault Seeker", + "kind": "Ability", + "row": 2, + "col": 1, + "maxPoints": 3, + "icon": "t_ui_iconabilityassaultseeker_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-assaultseeker" + }, + { + "tag": "Skills.Ability.MagneticAttractor", + "id": "MagneticAttractor", + "name": "Attractor Field", + "kind": "Ability", + "row": 2, + "col": 3, + "maxPoints": 1, + "icon": "t_ui_icongadgetshigmultitoolmagneticattractor_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-magneticattractor" + }, + { + "tag": "Skills.Ability.FragGrenade", + "id": "FragGrenade", + "name": "Explosive Grenade", + "kind": "Ability", + "row": 4, + "col": 1, + "maxPoints": 3, + "icon": "t_ui_icongadgetfraggrenades_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-fraggrenade" + }, + { + "tag": "Skills.Perk.TrooperCooldowns", + "id": "TrooperCooldowns", + "name": "Battle Hardened", + "kind": "Perk", + "row": 4, + "col": 3, + "maxPoints": 3, + "icon": "t_ui_iconskilltreetroopercooldown_d.webp", + "url": "https://dune.gaming.tools/skills/skills-perk-troopercooldowns" + }, + { + "tag": "Skills.Ability.CablePull", + "id": "CablePull", + "name": "Shigawire Claw", + "kind": "Ability", + "row": 5, + "col": 2, + "maxPoints": 3, + "icon": "t_ui_icongadgetshigmultitoolsardaukarpull_d.webp", + "url": "https://dune.gaming.tools/skills/skills-ability-cablepull" + } + ], + "edges": [ + { + "from": "Skills.Ability.AssaultSeeker", + "to": "Skills.Spice.GadgetReload" + }, + { + "from": "Skills.Ability.MagneticAttractor", + "to": "Skills.Spice.GadgetReload" + }, + { + "from": "Skills.Ability.AssaultSeeker", + "to": "Skills.Ability.FragGrenade" + }, + { + "from": "Skills.Ability.MagneticAttractor", + "to": "Skills.Perk.TrooperCooldowns" + }, + { + "from": "Skills.Ability.CablePull", + "to": "Skills.Ability.FragGrenade" + }, + { + "from": "Skills.Ability.CablePull", + "to": "Skills.Perk.TrooperCooldowns" + } + ] } ] } \ No newline at end of file diff --git a/character-builder/frontend/public/icons/slot-ability.png b/character-builder/frontend/public/icons/slot-ability.png new file mode 100644 index 0000000..2017cfc Binary files /dev/null and b/character-builder/frontend/public/icons/slot-ability.png differ diff --git a/character-builder/frontend/public/icons/slot-technique.png b/character-builder/frontend/public/icons/slot-technique.png new file mode 100644 index 0000000..214b328 Binary files /dev/null and b/character-builder/frontend/public/icons/slot-technique.png differ diff --git a/character-builder/frontend/src/App.vue b/character-builder/frontend/src/App.vue index ef79cb3..1fc43f6 100644 --- a/character-builder/frontend/src/App.vue +++ b/character-builder/frontend/src/App.vue @@ -4,6 +4,7 @@ import XpProgressCard from './components/XpProgressCard.vue'; import FactionTrack from './components/FactionTrack.vue'; import SkillTree from './components/SkillTree.vue'; import CharacterSummary from './components/CharacterSummary.vue'; +import LoadoutSlots from './components/LoadoutSlots.vue'; import { applyBuild, build, @@ -143,8 +144,10 @@ const spentByClass = computed>(() => { for (const c of CLASSES) { const tree = skillTrees.value[c.id]; if (!tree) continue; - for (const node of tree.nodes) { - out[c.id] += build.skills[node.tag] || 0; + for (const st of tree.subtrees) { + for (const node of st.nodes) { + out[c.id] += build.skills[node.tag] || 0; + } } } return out; @@ -433,6 +436,14 @@ const specMeta: Record = { @update:allocations="(a) => (build.skills = a)" @reset="resetAllSkills" /> + + diff --git a/character-builder/frontend/src/components/CharacterSummary.vue b/character-builder/frontend/src/components/CharacterSummary.vue index 82f7726..969162f 100644 --- a/character-builder/frontend/src/components/CharacterSummary.vue +++ b/character-builder/frontend/src/components/CharacterSummary.vue @@ -104,17 +104,19 @@ const skillsByClass = computed(() => { const allocations: ClassSkillSummary['allocations'] = []; let spent = 0; if (tree) { - for (const node of tree.nodes) { - const pts = props.build.skills[node.tag] || 0; - if (pts > 0) { - spent += pts; - allocations.push({ - tag: node.tag, - name: node.name, - kind: node.kind, - points: pts, - max: node.maxPoints, - }); + for (const st of tree.subtrees) { + for (const node of st.nodes) { + const pts = props.build.skills[node.tag] || 0; + if (pts > 0) { + spent += pts; + allocations.push({ + tag: node.tag, + name: node.name, + kind: node.kind, + points: pts, + max: node.maxPoints, + }); + } } } } diff --git a/character-builder/frontend/src/components/LoadoutSlots.vue b/character-builder/frontend/src/components/LoadoutSlots.vue new file mode 100644 index 0000000..c1623d5 --- /dev/null +++ b/character-builder/frontend/src/components/LoadoutSlots.vue @@ -0,0 +1,424 @@ + + + + + diff --git a/character-builder/frontend/src/components/SkillTree.vue b/character-builder/frontend/src/components/SkillTree.vue index 6b36638..5dbf7be 100644 --- a/character-builder/frontend/src/components/SkillTree.vue +++ b/character-builder/frontend/src/components/SkillTree.vue @@ -1,6 +1,6 @@ + + diff --git a/character-builder/frontend/src/store.ts b/character-builder/frontend/src/store.ts index a9bfaec..995fd23 100644 --- a/character-builder/frontend/src/store.ts +++ b/character-builder/frontend/src/store.ts @@ -19,9 +19,20 @@ export function defaultBuild(): BuildState { specs, faction: { tier: 0, standingInto: 0 }, skills: {}, + loadout: { abilities: [null, null, null], techniques: [null, null, null] }, }; } +function normalizeSlots(raw: unknown, len: number): (string | null)[] { + const arr = Array.isArray(raw) ? raw : []; + const out: (string | null)[] = []; + for (let i = 0; i < len; i++) { + const v = arr[i]; + out.push(typeof v === 'string' && v.length > 0 ? v : null); + } + return out; +} + function migrate(raw: any): BuildState { const def = defaultBuild(); if (!raw || typeof raw !== 'object') return def; @@ -33,6 +44,10 @@ function migrate(raw: any): BuildState { specs: { ...def.specs }, faction: { ...def.faction, ...(raw.faction || {}) }, skills: { ...(raw.skills || {}) }, + loadout: { + abilities: normalizeSlots(raw.loadout?.abilities, 3), + techniques: normalizeSlots(raw.loadout?.techniques, 3), + }, }; if (raw.specs && typeof raw.specs === 'object') { for (const k of Object.keys(out.specs) as SpecId[]) { diff --git a/character-builder/frontend/src/types.ts b/character-builder/frontend/src/types.ts index 5ab33f6..fb39d26 100644 --- a/character-builder/frontend/src/types.ts +++ b/character-builder/frontend/src/types.ts @@ -66,11 +66,17 @@ export interface SkillEdge { to: string; } +export interface SkillSubtree { + name: string; + cols: number; + nodes: SkillNode[]; + edges: SkillEdge[]; +} + export interface SkillTree { id: ClassId; name: string; - nodes: SkillNode[]; - edges: SkillEdge[]; + subtrees: SkillSubtree[]; } export interface SpecProgress { @@ -78,6 +84,14 @@ export interface SpecProgress { xpInto: number; } +// Loadout: 3 active Ability slots + 3 active Technique slots, both pulled +// from the union of all allocated skills across all 5 trees (the cap is +// global, not per-tree). +export interface Loadout { + abilities: (string | null)[]; // length 3 — element is a skill tag, or null + techniques: (string | null)[]; // length 3 +} + export interface BuildState { v: 1; // schema version house: House; @@ -95,4 +109,5 @@ export interface BuildState { // Allocated skill points keyed by full tag (e.g. Skills.Ability.BattleCry). // Tags are globally unique across classes, so one flat map works for all 5. skills: Record; + loadout: Loadout; } diff --git a/character-builder/scripts/extract.py b/character-builder/scripts/extract.py index 9a6c3d5..fede12f 100644 --- a/character-builder/scripts/extract.py +++ b/character-builder/scripts/extract.py @@ -216,109 +216,123 @@ LINE_RE = re.compile( ) +SUBTREE_H3_RE = re.compile( + r']*class="[^"]*text-xl[^"]*"[^>]*>([^<]+)' +) +GRID_COLS_RE = re.compile(r"grid-template-columns:\s*repeat\((\d+),\s*72px\)") + + +def _extract_node(chunk: str, tag: str) -> dict | None: + gm = GRID_RE.search(chunk) + if not gm: + return None + row, col = int(gm.group(1)), int(gm.group(2)) + alt = ALT_RE.search(chunk) + href = HREF_RE.search(chunk) + icon = ICON_RE.search(chunk) + max_pts = MAX_PTS_RE.search(chunk) + kind = tag.split(".")[1] if "." in tag else "Unknown" + return { + "tag": tag, + "id": tag.split(".")[-1], + "name": alt.group(1) if alt else tag.split(".")[-1], + "kind": kind, # Ability | Attribute | Perk | Spice + "row": row, + "col": col, + "maxPoints": int(max_pts.group(1)) if max_pts else 1, + "icon": icon.group(1) if icon else None, + "url": href.group(1) if href else None, + } + + +def _map_edges(html_slice: str, nodes: list[dict]) -> list[dict]: + """Pixel-match connector endpoints to the nearest nodes in this + subtree. Returns deduped edge list.""" + lines = list(LINE_RE.finditer(html_slice)) + if not lines or not nodes: + return [] + all_x = [int(x) for ln in lines for x in (ln.group("x1"), ln.group("x2"))] + all_y = [int(y) for ln in lines for y in (ln.group("y1"), ln.group("y2"))] + min_x, max_x = min(all_x), max(all_x) + min_y, max_y = min(all_y), max(all_y) + cols = [n["col"] for n in nodes] + rows_ = [n["row"] for n in nodes] + min_c, max_c = min(cols), max(cols) + min_r, max_r = min(rows_), max(rows_) + sx = (max_x - min_x) / max(1, (max_c - min_c)) + sy = (max_y - min_y) / max(1, (max_r - min_r)) + + centers = { + n["tag"]: (min_x + (n["col"] - min_c) * sx, min_y + (n["row"] - min_r) * sy) + for n in nodes + } + + def nearest(x: int, y: int) -> str | None: + best, best_d = None, float("inf") + for tag, (cx, cy) in centers.items(): + d = (cx - x) ** 2 + (cy - y) ** 2 + if d < best_d: + best_d, best = d, tag + return best + + seen, edges = set(), [] + for ln in lines: + x1, y1, x2, y2 = (int(ln.group(k)) for k in ("x1", "y1", "x2", "y2")) + a, b = nearest(x1, y1), nearest(x2, y2) + if a and b and a != b: + key = tuple(sorted((a, b))) + if key not in seen: + seen.add(key) + edges.append({"from": key[0], "to": key[1]}) + return edges + + def extract_skill_tree(path: Path, class_id: str, class_name: str) -> dict: + """Parse a class skill tree into its named subtrees. + + Each class is composed of 3 subtrees (e.g. Swordmaster has "The Blade", + "The Will", "The Way"). Each subtree is its own CSS grid with its own + column count, node positions, and connectors. Treating them as one big + grid (the prior behavior) collapsed all 22 nodes on top of each other. + """ html = path.read_text() - nodes = [] - # We need to also find the alt text + href + icon WITHIN each node's HTML. - # Strategy: walk through all data-tag="Skills..." occurrences, slice from - # opening of the node
to a balanced close. Simple slice: take 2000 chars - # after the tag and parse first alt/href/icon/max within it. - for m in re.finditer(r'data-tag="(Skills\.[^"]+)"', html): - tag = m.group(1) - start = m.start() - chunk = html[start : start + 2500] - gm = GRID_RE.search(chunk) - if not gm: + # Split on subtree H3 headers; first chunk is preamble. + chunks = SUBTREE_H3_RE.split(html) + preamble, pairs = chunks[0], chunks[1:] + + subtrees: list[dict] = [] + for i in range(0, len(pairs), 2): + name = pairs[i].strip() + body = pairs[i + 1] if i + 1 < len(pairs) else "" + # Slice off anything that belongs to the next subtree (already handled + # by split) or to trailing page chrome — search for the closing of the + # graph div by counting from the start of the graph element. + graph_start = body.find('
node lookup. Grid is roughly square with ~73px cells based - # on observed example (grid 3/5 -> center 364,220 means col*~73, row*~73 with offset). - # We'll learn cell size from the data: if there are connectors, we map each (x,y) to - # the nearest node by Euclidean distance. - # First compute approximate node centers via grid math, calibrated from any node - # we can pin: actually a more reliable approach is to use the connector geometry. - edges = [] - lines = list(LINE_RE.finditer(html)) - if lines and nodes: - # Calibrate: find scale by looking at min/max grid coords vs min/max line coords. - all_x = [int(x) for ln in lines for x in (ln.group("x1"), ln.group("x2"))] - all_y = [int(y) for ln in lines for y in (ln.group("y1"), ln.group("y2"))] - min_x, max_x = min(all_x), max(all_x) - min_y, max_y = min(all_y), max(all_y) - cols = [n["col"] for n in nodes] - rows = [n["row"] for n in nodes] - min_c, max_c = min(cols), max(cols) - min_r, max_r = min(rows), max(rows) - # avoid div by zero - sx = (max_x - min_x) / max(1, (max_c - min_c)) - sy = (max_y - min_y) / max(1, (max_r - min_r)) - - def center(n): - return ( - min_x + (n["col"] - min_c) * sx, - min_y + (n["row"] - min_r) * sy, - ) - - centers = {n["tag"]: center(n) for n in nodes} - - def nearest(x, y): - best_tag, best_d = None, float("inf") - for t, (cx, cy) in centers.items(): - d = (cx - x) ** 2 + (cy - y) ** 2 - if d < best_d: - best_d = d - best_tag = t - return best_tag - - seen_edges = set() - for ln in lines: - x1, y1, x2, y2 = ( - int(ln.group("x1")), - int(ln.group("y1")), - int(ln.group("x2")), - int(ln.group("y2")), - ) - a = nearest(x1, y1) - b = nearest(x2, y2) - if a and b and a != b: - key = tuple(sorted((a, b))) - if key not in seen_edges: - seen_edges.add(key) - edges.append({"from": key[0], "to": key[1]}) - - return { - "id": class_id, - "name": class_name, - "nodes": nodes, - "edges": edges, - } + return {"id": class_id, "name": class_name, "subtrees": subtrees} # ---------- main ---------- @@ -413,13 +427,16 @@ def main(): continue tree = extract_skill_tree(path, cls_id, cls_name) (OUT / f"skills-{cls_id}.json").write_text(json.dumps(tree, indent=2)) + total_nodes = sum(len(st["nodes"]) for st in tree["subtrees"]) + total_edges = sum(len(st["edges"]) for st in tree["subtrees"]) manifest["skills"].append( { "id": cls_id, "name": cls_name, "file": f"skills-{cls_id}.json", - "nodes": len(tree["nodes"]), - "edges": len(tree["edges"]), + "subtrees": [st["name"] for st in tree["subtrees"]], + "nodes": total_nodes, + "edges": total_edges, } ) @@ -429,9 +446,10 @@ def main(): path = OUT / f"skills-{cls_id}.json" if path.exists(): tree = json.loads(path.read_text()) - for n in tree["nodes"]: - if n.get("icon"): - icon_names.add(n["icon"]) + for st in tree["subtrees"]: + for n in st["nodes"]: + if n.get("icon"): + icon_names.add(n["icon"]) for spec in specs: slug = spec.lower() spec_data = json.loads((OUT / f"spec-{slug}.json").read_text()) @@ -440,6 +458,18 @@ def main(): if p.get("icon"): icon_names.add(p["icon"]) copied, missing = copy_icons(icon_names) + + # Slot background images for the global Abilities + Techniques loadout — + # the source HTML references them from a CDN, but local copies live in + # the per-class _files directories. + for src_name, dst_name in [ + ("ability.png", "slot-ability.png"), + ("technique.png", "slot-technique.png"), + ]: + src = find_icon_source(src_name) + if src: + shutil.copy2(src, ICONS_OUT / dst_name) + manifest["icons"] = { "directory": "frontend/public/icons", "served_at": "/icons/",