From bee1d640b1fbc1bb2ffe416607563fb79997ab17 Mon Sep 17 00:00:00 2001 From: William Barker <87542055+WilliamBarkerCoC@users.noreply.github.com> Date: Sun, 6 Apr 2025 14:46:15 -0400 Subject: [PATCH] A Song of Ice and Fire: Bug fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes and changes were made to the A Song of Ice and Fire sheet in response to a forum post, https://app.roll20.net/forum/post/12223469/asoiaf-character-sheet-minor-fixes 2Feb2025. Changes were made to 1) increase description field sizes, 2) sap two variables to match description and 3) fix army buttons and expand to ‘Add’ armies. This last change blew up the code as it’s legacy and the 50 some odd autocalc fields stopped working. So, more extensive changes were made to convert autocalc to sheet workers. An attempt was made to reach out to Alex-O (3241579), in both English and French, to confirm the validity and integrity of the changes, 25Feb2025. No response has been received. --- A Song of Ice and Fire/SIFRPNew.css | 48 +- A Song of Ice and Fire/SIFRPNew.html | 1097 +++++++++++++++++++++++--- A Song of Ice and Fire/sheet.json | 2 +- 3 files changed, 1028 insertions(+), 119 deletions(-) diff --git a/A Song of Ice and Fire/SIFRPNew.css b/A Song of Ice and Fire/SIFRPNew.css index 20b05f914b..5e1e7cb764 100644 --- a/A Song of Ice and Fire/SIFRPNew.css +++ b/A Song of Ice and Fire/SIFRPNew.css @@ -468,6 +468,9 @@ width: calc(20% - 0.5%); .charsheet .sheet-wrapper textarea.sheet-small { height: 32px; } +.charsheet .sheet-wrapper textarea.sheet-tiny { +height: 16px; +} .charsheet .sheet-wrapper .sheet-item.sheet-med { width: calc(30% - 0.5%); } @@ -591,6 +594,7 @@ float:right; text-align: center; } +input.sheet-arrow2, input.sheet-arrow { float: left; @@ -605,6 +609,7 @@ input.sheet-arrow z-index: 999; } +input.sheet-arrow2 + span::before, input.sheet-arrow + span::before { margin-right: 0px; line-height: 14px; @@ -618,11 +623,13 @@ input.sheet-arrow + span::before { font-weight: bold; } +input.sheet-arrow2:checked ~ div.sheet-hbody2, input.sheet-arrow:checked ~ div.sheet-hbody { display: none; } +input.sheet-arrow2:checked + span::before, input.sheet-arrow:checked + span::before { content: "▸"; } @@ -660,6 +667,7 @@ input:focus, textarea:focus margin-bottom:0px; padding-bottom:0px; } +.charsheet .sheet-wrapper .sheet-unnatural[type="text"], .charsheet .sheet-wrapper .sheet-unnatural[type="number"] { font-size: 1em; height:1.8em; @@ -813,4 +821,42 @@ input.sheet-Custom[type="checkbox"] + span::before color:654018; font-size:16px; font-family: Berylium-Regular; - } \ No newline at end of file + } + +/* Foreign Code */ + +.charsheet input.sheet-toggle-hide:checked ~ div.sheet-army-body { + display: none; +} +/* Web code */ +input[type="radio"]:checked+label{ background-color: khaki; } +/* From https://stackoverflow.com/questions/75992689/change-the-label-background-color-when-a-checkbox-is-checked */ + +input[type="checkbox"].sheet-emphasis { + display: none; + height: 20px; + text-align: left; + font-size: 1.0em !important; + margin: 0px 0px -4px 0px; + opacity: 0; +} + +input[type="checkbox"].sheet-emphasis:checked + label { + color: DarkRed; + height: 20px; + text-align: left; + font-size: 1.1em !important; + margin: 0px 0px -4px 0px; +} + +label.sheet-emphasis { + display: inline-block; + vertical-align: top; + border: 0px solid pink; + text-align: left; + height: 20px; + font-size: 1.0em !important; + margin: 0px 0px -4px 0px; +} + +/* End Web code */ \ No newline at end of file diff --git a/A Song of Ice and Fire/SIFRPNew.html b/A Song of Ice and Fire/SIFRPNew.html index baef811b53..a95038853b 100644 --- a/A Song of Ice and Fire/SIFRPNew.html +++ b/A Song of Ice and Fire/SIFRPNew.html @@ -158,8 +158,7 @@
- +
@@ -236,8 +235,7 @@
- +
@@ -305,8 +303,7 @@
- +
@@ -393,8 +390,7 @@
- +
@@ -444,8 +440,7 @@
- +
@@ -504,8 +499,7 @@
- +
@@ -573,8 +567,7 @@
- +
@@ -624,8 +617,7 @@
- +
@@ -738,8 +730,7 @@
- +
@@ -796,8 +787,7 @@
- +
@@ -857,8 +847,7 @@
- +
@@ -905,8 +894,7 @@
- +
@@ -965,8 +953,7 @@
- +
@@ -1034,8 +1021,7 @@
- +
@@ -1131,8 +1117,7 @@
- +
@@ -1200,8 +1185,7 @@
- +
@@ -1251,8 +1235,7 @@
- +
@@ -1320,8 +1303,7 @@
- +
@@ -1380,8 +1362,7 @@
- +
@@ -1440,8 +1421,7 @@
- +
@@ -1498,8 +1478,7 @@
- +
@@ -1577,8 +1556,8 @@
+ value="6" readonly + style="background: #4A798B !important; color: white !important; font-weight: bold !important; text-align: center !important;">
@@ -1599,8 +1578,8 @@
+ name="attr_composureMax" value="6" + readonly style="background: #4A798B !important; color: white !important; font-weight: bold !important; text-align: center !important;">
@@ -1623,13 +1602,34 @@
+ name="attr_frustrationMax" value="2" readonly style="background: #4A798B !important; color: white !important; font-weight: bold !important; text-align: center !important;">
–1D on Deception and Persuasion
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1649,8 +1649,8 @@
+ value="6" readonly + style="background: #4A798B !important; color: white !important; font-weight: bold !important; text-align: center !important;">
@@ -1671,13 +1671,13 @@
+ name="attr_healthMax" value="6" + readonly style="background: #4A798B !important; color: white !important; font-weight: bold !important; text-align: center !important;">
-
+
@@ -1697,7 +1697,7 @@
+ name="attr_fatigueMax" value="2" readonly style="background: #4A798B !important; color: white !important; font-weight: bold !important; text-align: center !important;">
@@ -1760,7 +1760,7 @@
+ name="attr_injuriesMax" value="2" readonly style="background: #4A798B !important; color: white !important; font-weight: bold !important; text-align: center !important;">
@@ -1785,7 +1785,7 @@
+ name="attr_woundsMax" value="2" readonly style="background: #4A798B !important; color: white !important; font-weight: bold !important; text-align: center !important;">
@@ -1820,17 +1820,17 @@
-
+
-
+
- +
@@ -1872,11 +1872,11 @@
+ value="@{baseMovement} + floor(@{athleticsRun}/2) - (@{bulk}/2)" readonly>
+ readonly style="background: #4A798B !important; color: white !important; font-weight: bold !important; text-align: center !important;">
yds
@@ -1892,18 +1892,18 @@
+ value="(@{movement} * @{sprintMulti}) - @{bulk}" readonly>
+ readonly style="background: #4A798B !important; color: white !important; font-weight: bold !important; text-align: center !important;">
yds
+ name="attr_bulk" value="(@{armorBulk} + @{totalWeaponBulk})"readonly style="background: #4A798B !important; color: white !important; font-weight: bold !important; text-align: center !important;">
@@ -2090,14 +2090,14 @@ Spent:
- +
Available:
- +
@@ -2137,14 +2137,14 @@ Spent:
- +
Available:
- +
@@ -2186,8 +2186,10 @@
-
- + +
+ +
@@ -2206,8 +2208,9 @@
- -
+ + +
@@ -2470,23 +2473,30 @@
-
+ +

Armies

+
-
-
+
+
+
+ + +
- +
+
@@ -2521,6 +2532,7 @@
+
@@ -2544,24 +2557,167 @@
+ +
+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+ +
+
+
+
+
+ + + + +
+
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+ +
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+ +
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+
+ +

Abilities

+
+
+
+

+
-
-
-
+
+
+
+ + +
+
+
-
-
+
+
@@ -2569,15 +2725,15 @@
-
-
+
+
-
-
+
+
@@ -2585,15 +2741,15 @@
-
-
+
+
-
-
+
+
@@ -2601,15 +2757,15 @@
-
-
+
+
-
-
+
+
@@ -2617,18 +2773,34 @@
-
-
+
+
- + +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
-
+

COMBAT

@@ -2638,14 +2810,14 @@
-
-
+
+
-
+
@@ -2654,7 +2826,7 @@
-
+
@@ -2676,14 +2848,14 @@
-
+
-
+
@@ -2692,14 +2864,14 @@
-
-
+
+
-
+
@@ -2708,7 +2880,7 @@
-
+
@@ -2729,14 +2901,14 @@
-
+
-
+
@@ -2745,23 +2917,29 @@
-
+
-
-
+
+
+
+ + +
+

-
-
+ + +
@@ -3441,9 +3619,694 @@ var TAS = TAS || (function(){ log: logLog }; }()); - /* ---- END: TheAaronSheet.js ---- */ +on("change:repeating_army:ArmyStatus", function(eventInfo) { + let NewClass = eventInfo.newValue; + let OldClass = eventInfo.previousValue; + let Source = eventInfo.sourceAttribute; + console.log(" =-=- Change ArmyStatus: " + NewClass + " from " + OldClass + " source " + Source); + getAttrs(['repeating_army_ArmyStatus','repeating_army_ArmyDisorganizeMalus'], function (values) { + let Status = parseInt(values.repeating_army_ArmyStatus) || 0; // "1" Oraganize, "2" Disorganize, "3" Rally, "4" Routed + let DisorganizeMalus = parseInt(values.repeating_army_ArmyDisorganizeMalus) || 0; + console.log(" Army - Status: " + Status + " DisorganizeMalus " + DisorganizeMalus); + + // The Logic: + // If ArmyStatus changed, if not Organized then DisorganizeMalus = 1 + + DisorganizeMalus = 0; + if (Status != 1) // If Army is not Organize, ArmyDisorganizeMalus TRUE which causes +3 Discipline(?) and a penalty die + { + DisorganizeMalus = 1; // ArmyDisorganizeMalus -> Discipline checks at +3 penalty + console.log(" Becomes Status: " + Status + " DisorganizeMalus " + DisorganizeMalus); + } + + setAttrs({ + repeating_army_ArmyDisorganizeMalus: String(DisorganizeMalus) + }); + }); +}); + + +/* Calculate Army Defense */ +on("change:repeating_army:ArmyAgilite change:repeating_army:ArmyAthletisme change:repeating_army:ArmyVigilance change:repeating_army:ArmyMalarm", function(eventInfo) { + let NewFactor = eventInfo.newValue; + let OldFactor = eventInfo.previousValue; + let Source = eventInfo.sourceAttribute; + console.log(" =-=- Change Army Disicpline underlying factor: " + NewFactor + " from " + OldFactor + " source " + Source); + + /* ArmyAgilite}+@{ArmyAthletisme}+@{ArmyVigilance}-@{ArmyMalarm */ + getAttrs(['repeating_army_ArmyAgilite','repeating_army_ArmyAthletisme','repeating_army_ArmyVigilance','repeating_army_ArmyMalarm'], function (values) { + + let Agility = parseInt(values.repeating_army_ArmyAgilite) || 0; + let Athletics = parseInt(values.repeating_army_ArmyAthletisme) || 0; + let Awareness = parseInt(values.repeating_army_ArmyVigilance) || 0; + let Bulk = parseInt(values.repeating_army_ArmyMalarm) || 0; + console.log(" Army: Agility " + Agility + " Athletics " + Athletics + " Awareness " + Awareness + " Bulk " + Bulk); + + let Defense = Agility + Athletics + Awareness - Bulk; + console.log(" Defense becomes: " + Defense); + + setAttrs({ + repeating_army_ArmyDefense: String(Defense) + }); + }); +}); + + +/* Calculate Army Discipline */ +on("change:repeating_army:ArmyTraining change:repeating_army:ArmyDisorganizeMalus change:repeating_army:ArmyHero", function(eventInfo) { + let NewFactor = eventInfo.newValue; + let OldFactor = eventInfo.previousValue; + let Source = eventInfo.sourceAttribute; + console.log(" =-=- Change Army Disicpline underlying factor: " + NewFactor + " from " + OldFactor + " source " + Source); + + getAttrs(['repeating_army_ArmyTraining','repeating_army_ArmyDisorganizeMalus','repeating_army_ArmyHero','repeating_army_ArmyDiscipline'], function (values) { + + let Training = parseInt(values.repeating_army_ArmyTraining) || 0; + let DisorganizeMalus = parseInt(values.repeating_army_ArmyDisorganizeMalus) || 0; + let Hero = parseInt(values.repeating_army_ArmyHero) || 0; + let curDiscipline = parseInt(values.repeating_army_ArmyDiscipline) || 0; + console.log(" Army: Training " + Training + " DisorganizeMalus " + DisorganizeMalus + " Hero " + Hero + " current Discipline " + curDiscipline); + + let Discipline = (Training + DisorganizeMalus - Hero) * 3; + console.log(" Discipine becomes: " + Discipline); + + setAttrs({ + repeating_army_ArmyDiscipline: String(Discipline) + }); + }); +}); + + +on("change:repeating_army:ArmySante", function(eventInfo) { + let NewHealth = eventInfo.newValue; + let OldHealth = eventInfo.previousValue; + let Source = eventInfo.sourceAttribute; + console.log(" =-=- Change ArmyHealth: " + NewHealth + " from " + OldHealth + " source " + Source); + getAttrs(['repeating_army_ArmyStatus','repeating_army_ArmySante','repeating_army_ArmyDisorganizeMalus'], function (values) { + let Status = parseInt(values.repeating_army_ArmyStatus) || 0; // "1" Oraganize, "2" Disorganize, "3" Rally, "4" Routed + let Health = NewHealth; + let DisorganizeMalus = parseInt(values.repeating_army_ArmyDisorganizeMalus) || 0; + console.log(" Army - Status: " + Status + " Health: " + Health + " DisorganizeMalus: " + DisorganizeMalus); + + // The Logic: + // If Health <= 0, then if Status == Organize, Status = Disorganize + + if ((Health <= 0) && (Status == 1)) // If Health is zero or less, army becomes, at least, ArmyDisorganizeMalus -> Disorganize with +3 Discipline(?) penalty + { + Status = 2; // Disorganize + DisorganizeMalus = 1; // ArmyDisorganizeMalus -> Discipline checks at +3 penalty and -1D penalty for all checks + console.log(" Become Disorganize: Status: " + Status + " Health: " + Health + " DisorganizeMalus " + DisorganizeMalus); + } else if ((Health > 0) && (DisorganizeMalus > 1)) { + //DisorganizeMalus = 0; + console.log(" ArmyStatus: " + Status + " don't know if Malus should be removed DisorganizeMalus: " + DisorganizeMalus); + } + + setAttrs({ + repeating_army_ArmyStatus: String(Status), + repeating_army_ArmyDisorganizeMalus: String(DisorganizeMalus) + }); + }); +}); + +/* Special Unit Overwatch - this function just ensures that no more than three abilities are selected for a special unit */ + +on("change:repeating_army:special_agility change:repeating_army:special_fighting change:repeating_army:special_marksmanship change:repeating_army:special_endurance change:repeating_army:special_stealth change:repeating_army:special_survival change:repeating_army:special_warfare change:repeating_army:special_athletics change:repeating_army:special_animal_handling change:repeating_army:special_awareness change:repeating_army:special_healing", function(eventInfo) { + let NewFactor = eventInfo.newValue; + let OldFactor = eventInfo.previousValue; + let Source = eventInfo.sourceAttribute; + let position = Source.search("_special_") + 9; // 9 is length of '_special_' + /* Unmangle the last ability updated and capitalize it */ + let nonCap = Source.substring(position); + let Ability = nonCap.charAt(0).toUpperCase() + nonCap.slice(1); + console.log(" =-=- Change Special Unit Training: " + NewFactor + " from " + OldFactor + " source " + Source + " Ability " + Ability); + + getAttrs(['repeating_army_ArmyTrainingPhase', 'repeating_army_special_agility','repeating_army_special_fighting','repeating_army_special_marksmanship','repeating_army_special_endurance','repeating_army_special_stealth','repeating_army_special_survival','repeating_army_special_warfare','repeating_army_special_athletics','repeating_army_special_animal_handling','repeating_army_special_awareness','repeating_army_special_healing'], function (values) { + + let ArmyTrainingPhase = parseInt(values.repeating_army_ArmyTrainingPhase) || 0; // Either 1 = First Phase or 2 = Second Phase + let Agility = parseInt(values.repeating_army_special_agility) || 0; + let Fighting = parseInt(values.repeating_army_special_fighting) || 0; + let Marksmanship = parseInt(values.repeating_army_special_marksmanship) || 0; + let Endurance = parseInt(values.repeating_army_special_endurance) || 0; + let Stealth = parseInt(values.repeating_army_special_stealth) || 0; + let Survival = parseInt(values.repeating_army_special_survival) || 0; + let Warfare = parseInt(values.repeating_army_special_warfare) || 0; + let Athletics = parseInt(values.repeating_army_special_athletics) || 0; + let Animal_handling = parseInt(values.repeating_army_special_animal_handling) || 0; + let Awareness = parseInt(values.repeating_army_special_awareness) || 0; + let Healing = parseInt(values.repeating_army_special_healing) || 0; + + console.log(" Special Training: Agility " + Agility + " Marksmanship " + Marksmanship + " Endurance " + Endurance + " Stealth " + Stealth); + console.log(" Fighting " + Fighting + " Survival " + Survival + " Warfare " + Warfare + " Athletics " + Athletics); + console.log(" Animal Handling " + Animal_handling + " Awareness " + Awareness + " Healing " + Healing); + + let MaxSkillCount = 3; + let CurrentSkillCount = Agility + Fighting + Marksmanship + Endurance + Stealth + Survival + Warfare + Athletics + Animal_handling + Awareness + Healing; + console.log(" CurrentSkillCount " + CurrentSkillCount); + + if (CurrentSkillCount > MaxSkillCount) { + // Remove the last updated Ability to, poentially, reduce skill count + // Also, this could probably be handled with a clever literal, but that is beyond my ken at thi moment + switch (Ability) { + case "Agility": Agility = 0; break + case "Fighting": Fighting = 0; break + case "Marksmanship": Marksmanship = 0; break + case "Endurance": Endurance = 0; break + case "Stealth": Stealth = 0; break + case "Survival": Survival = 0; break + case "Warfare": Warfare = 0; break + case "Athletics": Athletics = 0; break + case "Animal_handling": Animal_handling = 0; break + case "Awareness": Awareness = 0; break + case "Healing": Healing = 0; break + } + } + + let SkillCount = 0; + // Look for more than MaxSkillCount and suppress the later ones. This paranoid code is brought to you from the + // survivors of the Jumpgate Beta where occassional interrupts were lost so no state validity was guaranteed + + if (Agility != 0) { if (SkillCount >= MaxSkillCount) { Agility = 0; } else { SkillCount += 1; } } + if (Fighting != 0) { if (SkillCount >= MaxSkillCount) { Fighting = 0; } else { SkillCount += 1; } } + if (Marksmanship != 0) { if (SkillCount >= MaxSkillCount) { Marksmanship = 0; } else { SkillCount += 1; } } + if (Endurance != 0) { if (SkillCount >= MaxSkillCount) { Endurance = 0; } else { SkillCount += 1; } } + if (Stealth != 0) { if (SkillCount >= MaxSkillCount) { Stealth = 0; } else { SkillCount += 1; } } + if (Survival != 0) { if (SkillCount >= MaxSkillCount) { Survival = 0; } else { SkillCount += 1; } } + if (Warfare != 0) { if (SkillCount >= MaxSkillCount) { Warfare = 0; } else { SkillCount += 1; } } + if (Athletics != 0) { if (SkillCount >= MaxSkillCount) { Athletics = 0; } else { SkillCount += 1; } } + if (Animal_handling != 0) { if (SkillCount >= MaxSkillCount) { Animal_handling = 0; } else { SkillCount += 1; } } + if (Awareness != 0) { if (SkillCount >= MaxSkillCount) { Awareness = 0; } else { SkillCount += 1; } } + if (Healing != 0) { if (SkillCount >= MaxSkillCount) { Healing = 0; } else { SkillCount += 1; } } + console.log(" final SkillCount " + SkillCount); + + setAttrs({ + repeating_army_special_agility: Agility, + repeating_army_special_fighting: Fighting, + repeating_army_special_marksmanship: Marksmanship, + repeating_army_special_endurance: Endurance, + repeating_army_special_stealth: Stealth, + repeating_army_special_survival: Survival, + repeating_army_special_warfare: Warfare, + repeating_army_special_athletics: Athletics, + repeating_army_special_animal_handling: Animal_handling, + repeating_army_special_awareness: Awareness, + repeating_army_special_healing: Healing + }); + }); +}); + + + +/* When Special Unit clicked, update the keys selected for the phase */ +on("clicked:specialunit", function() { + console.log(" clicked SpecialUnit"); + + getAttrs(['repeating_army_ArmyTrainingPhase', 'repeating_army_ArmySkillFirst', 'repeating_army_ArmySkillSecond', 'repeating_army_ArmyAgiliteKey','repeating_army_ArmyArtmilKey','repeating_army_ArmyCacKey','repeating_army_ArmyAthletismeKey','repeating_army_ArmyTirKey','repeating_army_ArmyDressageKey','repeating_army_ArmyEnduranceKey','repeating_army_ArmyVigilanceKey','repeating_army_ArmyDiscretionKey','repeating_army_ArmyGuerisonKey','repeating_army_ArmySurvieKey', 'repeating_army_special_agility','repeating_army_special_fighting','repeating_army_special_marksmanship','repeating_army_special_endurance','repeating_army_special_stealth','repeating_army_special_survival','repeating_army_special_warfare','repeating_army_special_athletics','repeating_army_special_animal_handling','repeating_army_special_awareness','repeating_army_special_healing' ], function (values) { + + let ArmyTrainingPhase = parseInt(values.repeating_army_ArmyTrainingPhase) || 0; // Either 1 = First Phase or 2 = Second Phase + + let AgiliteKey = values.repeating_army_ArmyAgiliteKey; + let ArtmilKey = values.repeating_army_ArmyArtmilKey; + let CacKey = values.repeating_army_ArmyCacKey; + let AthletismeKey = values.repeating_army_ArmyAthletismeKey; + let TirKey = values.repeating_army_ArmyTirKey; + let DressageKey = values.repeating_army_ArmyDressageKey; + let EnduranceKey = values.repeating_army_ArmyEnduranceKey; + let VigilanceKey = values.repeating_army_ArmyVigilanceKey; + let DiscretionKey = values.repeating_army_ArmyDiscretionKey; + let GuerisonKey = values.repeating_army_ArmyGuerisonKey; + let SurvieKey = values.repeating_army_ArmySurvieKey; + + let Agility = parseInt(values.repeating_army_special_agility) || 0; + let Fighting = parseInt(values.repeating_army_special_fighting) || 0; + let Marksmanship = parseInt(values.repeating_army_special_marksmanship) || 0; + let Endurance = parseInt(values.repeating_army_special_endurance) || 0; + let Stealth = parseInt(values.repeating_army_special_stealth) || 0; + let Survival = parseInt(values.repeating_army_special_survival) || 0; + let Warfare = parseInt(values.repeating_army_special_warfare) || 0; + let Athletics = parseInt(values.repeating_army_special_athletics) || 0; + let Animal_handling = parseInt(values.repeating_army_special_animal_handling) || 0; + let Awareness = parseInt(values.repeating_army_special_awareness) || 0; + let Healing = parseInt(values.repeating_army_special_healing) || 0; + + let ArmySkillFirst = values.repeating_army_ArmySkillFirst; + let ArmySkillSecond = values.repeating_army_ArmySkillSecond; + let Key = ""; + if (ArmyTrainingPhase == 1) { + ArmySkillFirst = UnitType["Special"]; + Key = "K"; + } else { + Key = "&"; + ArmySkillSecond = UnitType["Special"]; + } + // Abilities: Agilite Artmil Cac Athletisme Tir Dressage Endurance Vigilance Discretion Guerison Survie + // Abilities: Agility Warfare Fighting Athletics Marksmanship AnimalHandling Endurance Awareness Stealth Healing Survival + + if (Agility != 0) { AgiliteKey = Key; } else if (AgiliteKey == Key) { AgiliteKey = ""; } + if (Fighting != 0) { CacKey = Key; } else if (CacKey == Key) { CacKey = ""; } + if (Marksmanship != 0) { TirKey = Key; } else if (TirKey == Key) { TirKey = ""; } + if (Endurance != 0) { EnduranceKey = Key; } else if (EnduranceKey == Key) { EnduranceKey = ""; } + if (Stealth != 0) { DiscretionKey = Key; } else if (DiscretionKey == Key) { DiscretionKey = ""; } + if (Survival != 0) { SurvieKey = Key; } else if (SurvieKey == Key) { SurvieKey = ""; } + if (Warfare != 0) { ArtmilKey = Key; } else if (ArtmilKey == Key) { ArtmilKey = ""; } + if (Athletics != 0) { AthletismeKey = Key; } else if (AthletismeKey == Key) { AthletismeKey = ""; } + if (Animal_handling != 0) { DressageKey = Key; } else if (DressageKey == Key) { DressageKey = ""; } + if (Awareness != 0) { VigilanceKey = Key; } else if (VigilanceKey == Key) { VigilanceKey = ""; } + if (Healing != 0) { GuerisonKey = Key; } else if (GuerisonKey == Key) { GuerisonKey = ""; } + + + setAttrs({ + repeating_army_ArmyAgiliteKey: AgiliteKey, + repeating_army_ArmyArtmilKey: ArtmilKey, + repeating_army_ArmyCacKey: CacKey, + repeating_army_ArmyAthletismeKey: AthletismeKey, + repeating_army_ArmyTirKey: TirKey, + repeating_army_ArmyDressageKey: DressageKey, + repeating_army_ArmyEnduranceKey: EnduranceKey, + repeating_army_ArmyVigilanceKey: VigilanceKey, + repeating_army_ArmyDiscretionKey: DiscretionKey, + repeating_army_ArmyGuerisonKey: GuerisonKey, + repeating_army_ArmySurvieKey: SurvieKey, + }); + }); +}); + +/* Perhaps Global Static Array? */ +let UnitType = ["None", "Archers", "Cavalry", "Criminals", "Crusaders", "Engineers", "Garrison", "Guerillas", "Infantry", "Mercenaries", "Peasant Levies", "Personal Guards", "Raiders", "Sailors", "Scouts", "Special", "Support", "Warship"]; + +on("change:repeating_army:ArmyType", function(eventInfo) { + let NewClass = eventInfo.newValue; + let OldClass = eventInfo.previousValue; + let Source = eventInfo.sourceAttribute; + console.log(" =-=-=- Class ArmyType: " + NewClass + " from " + OldClass + " source " + Source); + + getAttrs(['repeating_army_ArmyTrainingPhase', 'repeating_army_ArmySkillFirst', 'repeating_army_ArmySkillSecond', 'repeating_army_ArmyDegtirMod','repeating_army_ArmyDegcacMod','repeating_army_ArmyAthletisme','repeating_army_ArmyValarm','repeating_army_ArmyPenarm','repeating_army_ArmyMalarm','repeating_army_ArmySante', 'repeating_army_ArmyAgiliteKey','repeating_army_ArmyArtmilKey','repeating_army_ArmyCacKey','repeating_army_ArmyAthletismeKey','repeating_army_ArmyTirKey','repeating_army_ArmyDressageKey','repeating_army_ArmyEnduranceKey','repeating_army_ArmyVigilanceKey','repeating_army_ArmyDiscretionKey','repeating_army_ArmyGuerisonKey','repeating_army_ArmySurvieKey' ], function (values) { + + let ArmyTrainingPhase = parseInt(values.repeating_army_ArmyTrainingPhase) || 0; // Either 1 = First Phase or 2 = Second Phase + let MarksmanDamageMod = parseInt(values.repeating_army_ArmyDegtirMod) || 0; + let FightDamageMod = parseInt(values.repeating_army_ArmyDegtirMod) || 0; + let Athletics = parseInt(values.repeating_army_ArmyAthletisme) || 0; + let ArmorRating = parseInt(values.repeating_army_ArmyValarm) || 0; + let ArmorPenalty = parseInt(values.repeating_army_ArmyPenarm) || 0; + let Bulk = parseInt(values.repeating_army_ArmyMalarm) || 0; + let Health = parseInt(values.repeating_army_ArmySante) || 0; + + // Ability Keys Translation + // Abilities: Agilite Artmil Cac Athletisme Tir Dressage Endurance Vigilance Discretion Guerison Survie + // Abilities: Agility Warfare Fighting Athletics Marksmanship AnimalHandling Endurance Awareness Stealth Healing Survival + // Missing: Survival Healing Choose 3 + + let AgiliteKey = values.repeating_army_ArmyAgiliteKey; + let ArtmilKey = values.repeating_army_ArmyArtmilKey; + let CacKey = values.repeating_army_ArmyCacKey; + let AthletismeKey = values.repeating_army_ArmyAthletismeKey; + let TirKey = values.repeating_army_ArmyTirKey; + let DressageKey = values.repeating_army_ArmyDressageKey; + let EnduranceKey = values.repeating_army_ArmyEnduranceKey; + let VigilanceKey = values.repeating_army_ArmyVigilanceKey; + let DiscretionKey = values.repeating_army_ArmyDiscretionKey; + let GuerisonKey = values.repeating_army_ArmyGuerisonKey; + let SurvieKey = values.repeating_army_ArmySurvieKey; + + let ArmySkillFirst = values.repeating_army_ArmySkillFirst; + let ArmySkillSecond = values.repeating_army_ArmySkillSecond; + let Key = ""; + if (ArmyTrainingPhase == 1) { + ArmySkillFirst = UnitType[NewClass]; + Key = "K"; + } else { + Key = "&"; + ArmySkillSecond = UnitType[NewClass]; + } + + console.log(" ArmyType: " + NewClass + " MarksmanDamageMod " + MarksmanDamageMod + " FightDamageMod " + FightDamageMod + " Athletics " + Athletics); + console.log(" ArmorRating: " + ArmorRating + " ArmorPenalty " + ArmorPenalty + " Bulk " + Bulk + " Health " + Health); + console.log(" Keys: " + Key + " ArmyTrainingPhase " + ArmyTrainingPhase + " ArmySkillFirst " + ArmySkillFirst + " ArmySkillSecond " + ArmySkillSecond); + console.log(" Agilite " + AgiliteKey + " Artmil " + ArtmilKey + " Cac " + CacKey + " Athletisme " + AthletismeKey + " Tir " + TirKey + " Dressage " + DressageKey); + console.log(" Endurance " + EnduranceKey + " Vigilance " + VigilanceKey + " Discretion " + DiscretionKey + " Guerison " + GuerisonKey + " Survie " + SurvieKey); + + /* Go through all Keys and remove the ones for that phase */ + + if (AgiliteKey == Key) { AgiliteKey = ""; console.log(" removed " + Key + " AgiliteKey"); } + if (ArtmilKey == Key) { ArtmilKey = ""; console.log(" removed " + Key + " ArtmilKey"); } + if (CacKey == Key) { CacKey = ""; console.log(" removed " + Key + " CacKey"); } + if (AthletismeKey == Key) { AthletismeKey = ""; console.log(" removed " + Key + " AthletismeKey"); } + if (TirKey == Key) { TirKey = ""; console.log(" removed " + Key + " TirKey"); } + if (DressageKey == Key) { DressageKey = ""; console.log(" removed " + Key + " DressageKey"); } + if (EnduranceKey == Key) { EnduranceKey = ""; console.log(" removed " + Key + " EnduranceKey"); } + if (VigilanceKey == Key) { VigilanceKey = ""; console.log(" removed " + Key + " VigilanceKey"); } + if (DiscretionKey == Key) { DiscretionKey = ""; console.log(" removed " + Key + " DiscretionKey"); } + if (GuerisonKey == Key) { GuerisonKey = ""; console.log(" removed " + Key + " GuerisonKey"); } + if (SurvieKey == Key) { SurvieKey = ""; console.log(" removed " + Key + " SurvieKey"); } + + + switch (NewClass) { + case "1": //Archers + ArmorRating = 2; + ArmorPenalty = -1; + Bulk = 0; + FightDamageMod = -1; + MarksmanDamageMod = 2; + AgiliteKey = Key; + VigilanceKey = Key; + TirKey = Key; + break; + case "2": //Cavalry + ArmorRating = 5; + ArmorPenalty = -3; + Bulk = 2; + FightDamageMod = 3; + MarksmanDamageMod = 0; + AgiliteKey = Key; + DressageKey = Key; + CacKey = Key; + break; + case "3": //Criminals + ArmorRating = 1; + ArmorPenalty = 0; + Bulk = 0; + FightDamageMod = 1; + MarksmanDamageMod = 2; + EnduranceKey = Key; + CacKey = Key; + DiscretionKey = Key; + break; + case "4": //Crusaders + ArmorRating = 4; + ArmorPenalty = -1; + Bulk = 0; + FightDamageMod = -1; + MarksmanDamageMod = 0; + AthletismeKey = Key; + EnduranceKey = Key; + CacKey = Key; + case "5": //Engineers + ArmorRating = 2; + ArmorPenalty = -1; + Bulk = 0; + FightDamageMod = -1; + MarksmanDamageMod = 0; + EnduranceKey = Key; + CacKey = Key; + ArtmilKey = Key; + break; + case "6": //Garrison + ArmorRating = 3; + ArmorPenalty = -2; + Bulk = 0; + FightDamageMod = 1; + MarksmanDamageMod = 0; + VigilanceKey = Key; + EnduranceKey = Key; + CacKey = Key; + break; + case "7": //Guerillas + ArmorRating = 1; + ArmorPenalty = 0; + Bulk = 0; + FightDamageMod = 0; + MarksmanDamageMod = 1; + AthletismeKey = Key; + TirKey = Key; + DiscretionKey = Key; + break; + case "8": //Infantry + ArmorRating = 3; + ArmorPenalty = -2; + Bulk = 0; + FightDamageMod = 1; + MarksmanDamageMod = 0; + AthletismeKey = Key; + EnduranceKey = Key; + CacKey = Key; + break; + case "9": //Mercenaries + ArmorRating = 4; + ArmorPenalty = -2; + Bulk = 1; + FightDamageMod = 1; + MarksmanDamageMod = 0; + AthletismeKey = Key; + EnduranceKey = Key; + CacKey = Key; + break; + case "10": //Peasant Levies + ArmorRating = 0; + ArmorPenalty = 0; + Bulk = 0; + FightDamageMod = -1; + MarksmanDamageMod = -1; + DressageKey = Key; + VigilanceKey = Key; + SurvieKey = Key; + break; + case "11": //Personal Guards + ArmorRating = 6; + ArmorPenalty = -3; + Bulk = 2; + FightDamageMod = 1; + MarksmanDamageMod = 0; + AthletismeKey = Key; + EnduranceKey = Key; + CacKey = Key; + break; + case "12": //Raiders + ArmorRating = 2; + ArmorPenalty = -1; + Bulk = 0; + FightDamageMod = 1; + MarksmanDamageMod = 0; + AgiliteKey = Key; + EnduranceKey = Key; + CacKey = Key; + break; + case "14": //Sailors + ArmorRating = 0; + ArmorPenalty = 0; + Bulk = 0; + FightDamageMod = 1; + MarksmanDamageMod = 0; + AgiliteKey = Key; + VigilanceKey = Key; + CacKey = Key; + break; + case "15": //Scouts + ArmorRating = 2; + ArmorPenalty = -1; + Bulk = 0; + FightDamageMod = 0; + MarksmanDamageMod = 0; + VigilanceKey = Key; + EnduranceKey = Key; + DiscretionKey = Key; + break; + case "16": //Special + ArmorRating = 2; + ArmorPenalty = -1; + Bulk = 0; + FightDamageMod = 0; + MarksmanDamageMod = 0; + //Any Three Key Abilities - To Be Handled Later + break; + case "17": //Support + ArmorRating = 0; + ArmorPenalty = 0; + Bulk = 0; + FightDamageMod = -1; + MarksmanDamageMod = 0; + EnduranceKey = Key; + DressageKey = Key; + GuerisonKey = Key; + break; + case "18": //Warship + ArmorRating = 5; + ArmorPenalty = 0; + Bulk = 0; + FightDamageMod = 1; + MarksmanDamageMod = 1; + VigilanceKey = Key; + CacKey = Key; + TirKey = Key; + break; + default: + console.log(" Unknown Unit Tupe: " + String(NewClass)); + } + +console.log(" Keys: Agility = " + AgiliteKey + " Warfare = " + ArtmilKey + " Fighting = " + CacKey + " Athletics = " + AthletismeKey + " Marksmanship = " + TirKey + " Animal Handling = " + DressageKey + " Endurance = " + EnduranceKey + " Awareness= " + VigilanceKey + " Stealth= " + DiscretionKey+ " Healing= " + GuerisonKey + " Stealth= " + SurvieKey); + + setAttrs({ + repeating_army_ArmyDegtirMod: MarksmanDamageMod, + repeating_army_ArmyDegtirMod: FightDamageMod, + repeating_army_ArmyAthletisme: Athletics, + repeating_army_ArmyValarm: ArmorRating, + repeating_army_ArmySkillFirst: ArmySkillFirst, + repeating_army_ArmySkillSecond: ArmySkillSecond, + + repeating_army_ArmyAgiliteKey: AgiliteKey, + repeating_army_ArmyArtmilKey: ArtmilKey, + repeating_army_ArmyCacKey: CacKey, + repeating_army_ArmyAthletismeKey: AthletismeKey, + repeating_army_ArmyTirKey: TirKey, + repeating_army_ArmyDressageKey: DressageKey, + repeating_army_ArmyEnduranceKey: EnduranceKey, + repeating_army_ArmyVigilanceKey: VigilanceKey, + repeating_army_ArmyDiscretionKey: DiscretionKey, + repeating_army_ArmyGuerisonKey: GuerisonKey, + repeating_army_ArmySurvieKey: SurvieKey, + + repeating_army_ArmyPenarm: ArmorPenalty, + repeating_army_ArmyMalarm: Bulk + }); + + }); +}); + +on("change:repeating_army:ArmyEndurance", function(eventInfo) { + let NewEndurance = eventInfo.newValue; + let OldEndurance = eventInfo.previousValue; + let Source = eventInfo.sourceAttribute; + console.log(" =-=- Change ArmyEndurance: " + NewEndurance + " from " + OldEndurance + " source " + Source); + + let ArmySanteMax = NewEndurance * 3; + console.log(" =-=- New ArmySanteMax: " + ArmySanteMax); + setAttrs({ + repeating_army_ArmySanteMax: ArmySanteMax + }); +}); + +/* Combat Calculations */ +on("change:awareness change:cunning change:status change:intrigueDefenseBonus change:will change:composureBonus change:agility change:athletics change:defenseBonus change:armorPenalty", function(eventInfo) { + let NewValue = eventInfo.newValue; + let OldValue = eventInfo.previousValue; + let Source = eventInfo.sourceAttribute; + console.log(" =-=- Change Combat Calculations: " + NewValue + " from " + OldValue + " source " + Source); + + getAttrs(['awareness', 'cunning','status', 'intrigueDefenseBonus','will', 'composureBonus','agility', 'athletics', 'defenseBonus','armorPenalty'], function (values) { + let Awareness = parseInt(values.awareness) || 0; + let Cunning = parseInt(values.cunning) || 0; + let Status = parseInt(values.status) || 0; + let IntrigueDefenseBonus = parseInt(values.intrigueDefenseBonus) || 0; + let Will = parseInt(values.will) || 0; + let ComposureBonus = parseInt(values.composureBonus) || 0; + let Agility = parseInt(values.agility) || 0; + let Athletics = parseInt(values.athletics) || 0; + let DefenseBonus = parseInt(values.defenseBonus) || 0; + let ArmorPenalty = parseInt(values.armorPenalty) || 0; + let IntrigueDefense = Awareness + Cunning + Status + IntrigueDefenseBonus; + let ComposureMax = Will * 3 + ComposureBonus; + let FrustrationMax = Will; + let CombatDefense = Agility + Athletics + DefenseBonus + ArmorPenalty; + + console.log(' IntrigueDefense ' + IntrigueDefense + ' ComposureMax ' + ComposureMax + ' FrustrationMax ' + FrustrationMax + ' CombatDefense ' + CombatDefense); + setAttrs({ + intrigueDefense: IntrigueDefense, composureMax: ComposureMax, frustrationMax: FrustrationMax, combatDefense: CombatDefense + }); + }); +}); + +/* Movement Calculations */ +on("change:baseMovement change:athleticsRun change:bulk change:movementCalc change:movementMin change:movement change:sprintMulti change:sprintCalc change:sprintMin change:armorBulk change:totalWeaponBulk", function(eventInfo) { + let NewValue = eventInfo.newValue; + let OldValue = eventInfo.previousValue; + let Source = eventInfo.sourceAttribute; + console.log(" =-=- Change Movement Calculations: " + NewValue + " from " + OldValue + " source " + Source); + + getAttrs(['baseMovement', 'athleticsRun', 'bulk', 'movementCalc', 'movementMin', 'movement', 'sprintMulti', 'sprintCalc', 'sprintMin', 'armorBulk', 'totalWeaponBulk'], function (values) { + let BaseMovement = parseInt(values.baseMovement) || 0; + let AthleticsRun = parseInt(values.athleticsRun) || 0; + let Bulk = parseInt(values.bulk) || 0; + let MovementCalc = parseInt(values.movementCalc) || 0; + let MovementMin = parseInt(values.movementMin) || 0; /* Always 1? */ + let Movement = parseInt(values.movement) || 0; + let SprintMulti = parseInt(values.sprintMulti) || 0; + let SprintCalc = parseInt(values.sprintCalc) || 0; + let SprintMin = parseInt(values.sprintMin) || 0; /* Always 1? */ + let ArmorBulk = parseInt(values.armorBulk) || 0; + let TotalWeaponBulk = parseInt(values.totalWeaponBulk) || 0; + + MovementCalc = BaseMovement + Math.floor(AthleticsRun/2) - Math.floor(Bulk/2); + Movement = MovementCalc + MovementMin + Math.abs((MovementCalc - MovementMin) / 2); + SprintCalc = Movement + SprintMulti - Bulk; + let Sprint = SprintCalc + SprintMin + Math.abs((SprintCalc - SprintMin) / 2); + Bulk = ArmorBulk + TotalWeaponBulk; + + console.log(' MovementCalc ' + MovementCalc + ' Movement ' + Movement + ' SprintCalc ' + SprintCalc + ' Sprint ' + Sprint + ' Bulk ' + Bulk); + setAttrs({ + movementCalc: MovementCalc, movement: Movement, sprintCalc: SprintCalc, sprint: Sprint, bulk: Bulk + }); + }); +}); + +on("change:endurance change:healthbonus", function(eventInfo) { + let NewValue = eventInfo.newValue; + let OldValue = eventInfo.previousValue; + let Source = eventInfo.sourceAttribute; + console.log(" =-=- Change Endurance or HealthBonus: " + NewValue + " from " + OldValue + " source " + Source); + + getAttrs(['endurance', 'healthbonus'], function (values) { + let Endurance = parseInt(values.endurance) || 0; + let HealthBonus = parseInt(values.healthbonus) || 0; + console.log(` Endurance ` + Endurance + " HealthBonus " + HealthBonus); + let HealthMax = Endurance * 3 + HealthBonus; + let FatigueMax = Endurance ; + let InjuriesMax = Endurance ; + let WoundsMax = Endurance ; + console.log(' healthMax ' + HealthMax + ' fatigueMax ' + FatigueMax + ' injuriesMax ' + InjuriesMax + ' woundsMax ' + WoundsMax); + setAttrs({ + healthmax: HealthMax, fatiguemax: FatigueMax, injuriesmax: InjuriesMax, woundsmax: WoundsMax + }); + }); +}); + +/* Literals? */ +const int = score => parseInt(score, 10) || 0; + +const stats = ["agility", "animalhandling", "athletics", "awareness", "cunning", "deception", "endurance", "fighting", "healing", "custom1", "language", "knowledge", "marksmanship", "persuasion", "status", "stealth", "survival", "thievery", "warfare", "will", "custom2"]; +stats.forEach(stat => { + on(`change:${stat}`, () => { + getAttrs([stat], values => { + + const stat_base = parseInt(values[stat]); + console.log(`${stat} ` + stat_base); + let stat_mod = stat_base * 4; + console.log(`${stat}-passive ` + stat_mod); + setAttrs({ + [`${stat}-passive`]: stat_mod + }); + }); + }); +}); + + +/* Glory, Experience and Destiny Calculations */ +on("change:destinyBase change:destinyBonus change:destinyInvested change:exp change:expSpent change:glory change:glorySpent", function(eventInfo) { + let NewValue = eventInfo.newValue; + let OldValue = eventInfo.previousValue; + let Source = eventInfo.sourceAttribute; + console.log(" =-=- Change Glory,Experience,Destiny Calculations: " + NewValue + " from " + OldValue + " source " + Source); + + getAttrs(['destinyBase', 'destinyBonus', 'destinyInvested', 'exp', 'expSpent', 'glory', 'glorySpent'], function (values) { + let DestinyBase = parseInt(values.destinyBase) || 0; + let DestinyBonus = parseInt(values.destinyBonus) || 0; + let DestinyInvested = parseInt(values.destinyInvested) || 0; + let Exp = parseInt(values.exp) || 0; + let ExpSpent = parseInt(values.expSpent) || 0; /* Always 1? */ + let Glory = parseInt(values.glory) || 0; + let GlorySpent = parseInt(values.glorySpent) || 0; + let DestinyMax = DestinyBase + DestinyBonus - DestinyInvested; + let ExpAvail = Exp - ExpSpent; + let GloryAvail = Glory - GlorySpent; + + console.log(' DestinyMax ' + DestinyMax + ' = DestinyBase ' + DestinyBase + ' + DestinyBonus ' + DestinyBonus + ' - DestinyInvested ' + DestinyInvested); + console.log(' ExpAvail ' + ExpAvail + ' = Exp ' + Exp +' + ExpSpent ' + ExpSpent); + console.log(' GloryAvail ' + GloryAvail + ' = Glory ' + Glory + ' + GlorySpent ' + GlorySpent); + + setAttrs({ + destinyMax: DestinyMax, expAvail: ExpAvail, gloryAvail: GloryAvail + }); + }); +}); diff --git a/A Song of Ice and Fire/sheet.json b/A Song of Ice and Fire/sheet.json index a820553842..9d4f109dee 100644 --- a/A Song of Ice and Fire/sheet.json +++ b/A Song of Ice and Fire/sheet.json @@ -4,6 +4,6 @@ "authors": "Alex Ott", "roll20userid": "3241579", "preview": "SIFRPNew.png", - "instructions": "#A Song of Ice and Fire Roleplaying: Game of Thrones Edition\rAuto-calculated stats, fancy hideable sections, and more", + "instructions": "#A Song of Ice and Fire Roleplaying: Game of Thrones Edition\rAuto-calculated stats, fancy hideable sections, and more.\rTweaks by Vialmada 6055058 regarding armies and autocalc", "legacy": true } \ No newline at end of file