diff --git a/Earthdawn (FASA Official)/Earthdawn.css b/Earthdawn (FASA Official)/Earthdawn.css index 2d311631e2..7a0e39ed7c 100644 --- a/Earthdawn (FASA Official)/Earthdawn.css +++ b/Earthdawn (FASA Official)/Earthdawn.css @@ -1,5 +1,5 @@ /* Earthdawn.css */ -/*v3 released 22 11 19*/ +/*v3 released 23 01 14*/ /* ############################################ css Reset ######################################################################### */ @@ -209,10 +209,10 @@ xxxxx { .sheet-testNum[value="12"]~div .sheet-HideIfLessThan13, .sheet-testNum[value="13"]~div .sheet-HideIfLessThan14, .sheet-testNum[value="14"]~div .sheet-HideIfLessThan15, -.sheet-testModType[value="(0)"]~span>.sheet-HideIfNoRoll, -.sheet-testModType[value="(0)"]~.sheet-HideIfNoRoll, -.sheet-testModType:not([value="(0)"])~span>.sheet-HideIfRoll, -.sheet-testModType:not([value="(0)"])~.sheet-HideIfRoll, +.sheet-testModType[value="NoRoll"]~span>.sheet-HideIfNoRoll, +.sheet-testModType[value="NoRoll"]~.sheet-HideIfNoRoll, +.sheet-testModType:not([value="NoRoll"])~span>.sheet-HideIfRoll, +.sheet-testModType:not([value="NoRoll"])~.sheet-HideIfRoll, .sheet-testRecord[value="LP"]~.sheet-HideIfLP, .sheet-testRecord[value="SP"]~.sheet-HideIfSP, .sheet-testRecord[value="Other"]~.sheet-HideIfOther, @@ -234,6 +234,8 @@ xxxxx { .sheet-testRepOption2:not(:checked)~.repcontainer .sheet-HideIfNotOption2, .sheet-testRepOption3:not(:checked)~.repcontainer .sheet-HideIfNotOption3, .sheet-testRepOption4:not(:checked)~.repcontainer .sheet-HideIfNotOption4, +.sheet-testRepOption5:not(:checked)~.repcontainer .sheet-HideIfNotOption5, +.sheet-testRepOption5:not(:checked)~div .sheet-HideIfNotOption5, .sheet-testFreeOrThread[value*="-link"]+.sheet-HideIfFreeOrThread, .sheet-testFreeOrThread:not([value*="-link"])+.sheet-HideIfNotFreeOrThread, .sheet-testFreeOrThread:not([value*="-link"])+.sheet-HideIfFreeOrThread+.sheet-HideIfNotFreeOrThread, @@ -964,7 +966,7 @@ span:hover .sheet-buffRight{ background-image: url(https://raw.githubusercontent.com/roll20/roll20-character-sheets/master/Earthdawn%20%28FASA%20Official%29/Images/Border-left-nobottom.png),url(https://raw.githubusercontent.com/roll20/roll20-character-sheets/master/Earthdawn%20%28FASA%20Official%29/Images/Border-right-nobottom.png),url(https://raw.githubusercontent.com/roll20/roll20-character-sheets/master/Earthdawn%20%28FASA%20Official%29/Images/Border-left-nobottom3.png),url(https://raw.githubusercontent.com/roll20/roll20-character-sheets/master/Earthdawn%20%28FASA%20Official%29/Images/Border-right-nobottom3.png); background-repeat: no-repeat, no-repeat,no-repeat, no-repeat; background-blend-mode: multiply, multiply,multiply, multiply; - background-position: -17px -15px,calc(100% + 23px) -10px,-17px 1356px,calc(100% + 23px) 1362px; + background-position: -17px -15px,calc(100% + 23px) -10px,-17px 1357px,calc(100% + 23px) 1362px; background-size : 250px 1372px, 250px 1372px,250px 1372px, 250px 1372px; padding-left: 13px; padding-right: 13px; @@ -1287,7 +1289,7 @@ margin: 1%; border-radius: 10px; text-align: center; display: inline-block; - width: 130px; + width: 120px; margin-bottom: 3px; min-height: 80px; } @@ -1299,6 +1301,7 @@ margin: 1%; vertical-align: top; text-align: center; background-color: var(--outline-color); + border-radius:10px; } .sheet-Defense-box { @@ -1341,7 +1344,7 @@ margin: 1%; } .sheet-AttribValueDiv { - margin-top: 8px; + margin-top: 3px; } .charsheet input[type="number"].sheet-AttribStep, @@ -2498,14 +2501,40 @@ margin-bottom: 0.2em; /* ####################### Print Format ################# */ +/* .sheet-PrintSpacer{ + display:none; +} */ + /* For some weird Reason, the Print format must be in between the roll templates and the API buttons. DO NOT MOVE */ @media print { /* All your print styles go here */ +.sheet-user-root{ + background-color: white !important; +} + +.sheet-Attrib-box{ + width:100px; +} + +.sheet-Defense-box{ + width:90px; +} + +.sheet-PrintNoBreak{ +page-break-inside: avoid; +} + +.sheet-PrintNoFlex{ +display : inline-block !important; +} - +/* .sheet-PrintSpacer{ + height:200px; + display:inline-block; +} */ .sheet-buffSignLeft, .sheet-buffSignRight, @@ -2513,6 +2542,9 @@ margin-bottom: 0.2em; .sheet-buffRight { display: none !important; } + + .sheet-testRepOption5:not(:checked)~div .sheet-HideIfNotOption5, + .sheet-testRepOption5:not(:checked)~.repcontainer .sheet-HideIfNotOption5, /*These are the step dice, always show if print*/ .sheet-ShowIfPrint { display: inline-block !important; } @@ -2624,6 +2656,7 @@ margin-bottom: 0.2em; /* font-family: Papyrus, fantasy; */ font-family: 'Aladin', "Helvetica Neue", Helvetica, sans-serif; font-weight: normal !important; + border-radius:10px; } diff --git a/Earthdawn (FASA Official)/Earthdawn.html b/Earthdawn (FASA Official)/Earthdawn.html index 05b761ea43..7a0831c614 100644 --- a/Earthdawn (FASA Official)/Earthdawn.html +++ b/Earthdawn (FASA Official)/Earthdawn.html @@ -3,7 +3,7 @@ -
+
@@ -432,7 +432,7 @@ Comments JBF@CD are action/reminders to Chris
+ value="!Earthdawn~ charID: @{character_id}~ ForEach~ Damage : ?{Damage to be applied : |1} : ?{Armor| Physical,PA| Mystic,MA| Nat PA,PA-Nat| Nat MA,MA-Nat| None,NA} : ?{Apply Damage - Type of damage |Damage|Stun|Strain}" >Damage Damage
@@ -498,7 +498,7 @@ Comments JBF@CD are action/reminders to Chris
+ value="!Earthdawn~ charID: @{character_id}~ ForEach~ Damage : ?{Damage to be applied : |1} : ?{Armor| Physical,PA| Mystic,MA| Nat PA,PA-Nat| Nat MA,MA-Nat| None,NA} : Stun" >Stun Stun
@@ -607,7 +607,7 @@ Comments JBF@CD are action/reminders to Chris
--> + + +
+
CREATION MODE
+
In this mode you can easily modify all attributes / characteristics of your PC/NPC. Follow the step by step creation, or modify the values directly, and exit this mode with the buttons at the end of the page.
+
+ @@ -936,14 +943,14 @@ Comments JBF@CD are action/reminders to Chris
2- Generate Attributes.
-
+
Attribute Points:
Karma Points :   
- Spend Attributes points or set the Step
+
Spend Attributes points or set the Step
Attributes: directly set the Attribute Steps @@ -964,13 +971,13 @@ Comments JBF@CD are action/reminders to Chris title="@{Attrib-Dex-Race} Base Racial Dexterity attribute." type="number">
-
+ Creation Pts:
+
+ Creation:
= + type="number">   = 
@@ -978,7 +985,7 @@ Comments JBF@CD are action/reminders to Chris
-
@@ -1170,13 +1177,13 @@ Comments JBF@CD are action/reminders to Chris title="@{Attrib-Str-Race} Base Racial Strength attribute." type="number">
-
+ Creation Pts:
+
+ Creation:
= + type="number">   = 
@@ -1184,7 +1191,7 @@ Comments JBF@CD are action/reminders to Chris
-
@@ -1372,13 +1379,13 @@ Comments JBF@CD are action/reminders to Chris title="@{Attrib-Tou-Race} Base Racial Toughness attribute." type="number">
-
+ Creation Pts:
+
+ Creation:
= + type="number">   = 
@@ -1386,7 +1393,7 @@ Comments JBF@CD are action/reminders to Chris
-
@@ -1575,20 +1582,20 @@ Comments JBF@CD are action/reminders to Chris title="@{Attrib-Per-Race} Base Racial Perception attribute." type="number">
-
+ Creation Pts:
+
+ Creation:
= + type="number">   = 
-
@@ -1775,13 +1782,13 @@ Comments JBF@CD are action/reminders to Chris title="@{Attrib-Wil-Race} Base Racial Willpower attribute." type="number">
-
+ Creation Pts:
+
+ Creation:
= + type="number">   = 
@@ -1789,7 +1796,7 @@ Comments JBF@CD are action/reminders to Chris
-
@@ -1975,13 +1982,13 @@ Comments JBF@CD are action/reminders to Chris title="@{Attrib-Cha-Race} Base Racial Charisma attribute." type="number">
-
+ Creation Pts:
+
+ Creation:
= + type="number">   = 
@@ -1989,7 +1996,7 @@ Comments JBF@CD are action/reminders to Chris
-
@@ -2171,7 +2178,7 @@ Comments JBF@CD are action/reminders to Chris
3- Characteristics.
-
+
Automatically Calculated
Charact. @@ -2370,15 +2377,17 @@ Comments JBF@CD are action/reminders to Chris -
- + + + +
@@ -2386,11 +2395,18 @@ Comments JBF@CD are action/reminders to Chris + JumpUp + + + + value="@{RollType} &{template:rolltargetnumber} {{header=@{charName}: Jump Up}} {{target_number=[[6]]}} {{Step=[[?{Step|@{Dex}+(@{condition-KnockedDown}*3)+ @{Jumpup-Adjust} -@{Armor-IP}}]] + [[?{Bonus or Karma Step|0}]]}} {{Result=[[ [[floor({?{Step}-8,0}kh1 / 11)]]d20! + [[ [[{1e3, 7}=[[{?{Step}, 0}kh1]] ]] + [[{6, 7, 7, 8, 9, 10, 11}=[[{((?{Step}-8) % 11)+1,0}kh1]] ]] ]]d12! + [[ [[{1e3, 6}=[[{?{Step}, 0}kh1]] ]] + [[{4, 5, 5, 6, 11}=[[{((?{Step}-8) % 11)+1,0}kh1]] ]] ]]d10! + [[ [[{1e3, 5}=[[{?{Step}, 0}kh1]] ]] + [[{2, 3, 3, 4, 9, 10, 10, 11}=[[{((?{Step}-8) % 11)+1,0}kh1]] ]] ]]d8! + [[ [[{1e3, 4}=[[{?{Step}, 0}kh1]] ]] + [[{1, 1, 2, 8, 8, 9}=[[{((?{Step}-8) % 11)+1,0}kh1]] ]] ]]d6! + [[{1, 2, 3}=[[{?{Step}, 0}kh1]] ]]d4! - [[{1, 2}=[[{?{Step}, 0}kh1]] * (3 - [[{?{Step}, 0}kh1]])]] + [[floor({?{Bonus or Karma Step}-8,0}kh1 / 11)]]d20! + [[ [[{1e3, 7}=[[{?{Bonus or Karma Step}, 0}kh1]] ]] + [[{6, 7, 7, 8, 9, 10, 11}=[[{((?{Bonus or Karma Step}-8) % 11)+1,0}kh1]] ]] ]]d12! + [[ [[{1e3, 6}=[[{?{Bonus or Karma Step}, 0}kh1]] ]] + [[{4, 5, 5, 6, 11}=[[{((?{Bonus or Karma Step}-8) % 11)+1,0}kh1]] ]] ]]d10! + [[ [[{1e3, 5}=[[{?{Bonus or Karma Step}, 0}kh1]] ]] + [[{2, 3, 3, 4, 9, 10, 10, 11}=[[{((?{Bonus or Karma Step}-8) % 11)+1,0}kh1]] ]] ]]d8! + [[ [[{1e3, 4}=[[{?{Bonus or Karma Step}, 0}kh1]] ]] + [[{1, 1, 2, 8, 8, 9}=[[{((?{Bonus or Karma Step}-8) % 11)+1,0}kh1]] ]] ]]d6! + [[{1, 2, 3}=[[{?{Bonus or Karma Step}, 0}kh1]] ]]d4! - [[{1, 2}=[[{?{Bonus or Karma Step}, 0}kh1]] * (3 - [[{?{Bonus or Karma Step}, 0}kh1]])]] ]]}}"> + JumpUp + + + +
@@ -3014,7 +3030,7 @@ Comments JBF@CD are action/reminders to Chris
-
To Import a Creature and/or a Mask from Book copy and Paste description (starting with name) into this tiny text box. Note that for Spirits, once imported, you can adjust the Spirit Strength rating to adjust some of the characteristics.
+
To Import a Creature from Book copy and Paste description (starting with name) into this tiny text box. Note that for Spirits, once imported, you can adjust the Spirit Strength rating to adjust some of the characteristics.
@@ -3026,7 +3042,7 @@ Comments JBF@CD are action/reminders to Chris
Masks:
- This section tracks the masks and other automatic modifiers, so that you can delete them. + This section records the masks and other automatic modifiers, so that you can add / import / delete them. Deleting will reverse the modifications to values (Attributes, Characteristics, Ranks), but doesn't delete Powers and Maneuvers
@@ -3042,13 +3058,13 @@ Comments JBF@CD are action/reminders to Chris
- +
-
+
@@ -3059,6 +3075,19 @@ Comments JBF@CD are action/reminders to Chris
+
+ + + +
+ +
Overview
Talents, Knacks and Skills
Powers
@@ -3173,7 +3202,7 @@ Comments JBF@CD are action/reminders to Chris
1- Choose a Race and Discipline
-
Racial Abilities will be automatically added
+
Racial Abilities will be automatically added
@@ -3392,8 +3421,10 @@ Comments JBF@CD are action/reminders to Chris - + + + @@ -3512,12 +3543,16 @@ Comments JBF@CD are action/reminders to Chris
4- Assign Power Ranks
4- Assign Talent Ranks
-
Add below the Talents of your discipline, and spend 8 Ranks. Remaining Points : +
+ Add below the Talents of your discipline, and spend 8 Ranks. Remaining Points :
+
Discipline Talents can quickly be added by the "Add Talents" button. Note that with API, the links for Free Talents will be automatically created, but may not appear until the sheet is closed and reopened.
+
Talent Options are added manually. Remember to set their Origin to "TO-Novice".
+
Matrixes are set in the "Spells" Section
For NPCs and Creatures, quickly set all Talent/Power Ranks to :
Repeating Sections Parameters
+
+ Step Dice : + + +
+
Modifier Exceptions : + +
@@ -3690,17 +3736,18 @@ Comments JBF@CD are action/reminders to Chris  Type  -  Rank  +  Rank   Rank  Add SR  Attribute   Step  + Dice  Target   Origin  - Actn + Actn Stn - Kma - DP + Kma + DP
@@ -3956,7 +4003,7 @@ Comments JBF@CD are action/reminders to Chris - + @@ -4067,6 +4114,11 @@ Comments JBF@CD are action/reminders to Chris + + + + + @@ -4242,7 +4294,7 @@ Comments JBF@CD are action/reminders to Chris - + @@ -4403,7 +4455,6 @@ Comments JBF@CD are action/reminders to Chris - @@ -4439,23 +4490,23 @@ Comments JBF@CD are action/reminders to Chris
-
- +
+ Max Karma Allowed - + Karma Required: - + Max DP Allowed - + DP Required: @@ -4663,6 +4714,7 @@ Comments JBF@CD are action/reminders to Chris +
@@ -4699,12 +4751,13 @@ Comments JBF@CD are action/reminders to Chris  Rank   Attribute   Step  + Dice  Target   Origin  Actn Stn - Kma - DP + Kma + DP
@@ -4777,7 +4830,7 @@ Comments JBF@CD are action/reminders to Chris - + @@ -4862,6 +4915,10 @@ Comments JBF@CD are action/reminders to Chris + + + + @@ -4982,7 +5039,7 @@ Comments JBF@CD are action/reminders to Chris - + @@ -5122,6 +5179,11 @@ Comments JBF@CD are action/reminders to Chris + + + + + @@ -5137,7 +5199,7 @@ Comments JBF@CD are action/reminders to Chris
-
+
Max Karma Allowed : @@ -5333,6 +5395,7 @@ Comments JBF@CD are action/reminders to Chris +
@@ -5344,12 +5407,13 @@ Comments JBF@CD are action/reminders to Chris  Rank   Attribute   Step  + Dice  Target   Origin  Actn Stn - Kma - DP + Kma + DP
@@ -5357,7 +5421,9 @@ Comments JBF@CD are action/reminders to Chris + + @@ -5445,7 +5511,9 @@ Comments JBF@CD are action/reminders to Chris + + @@ -5839,7 +5907,7 @@ Comments JBF@CD are action/reminders to Chris - + @@ -5908,6 +5976,10 @@ Comments JBF@CD are action/reminders to Chris + + + + @@ -6024,7 +6096,7 @@ Comments JBF@CD are action/reminders to Chris - + @@ -6187,7 +6259,7 @@ Comments JBF@CD are action/reminders to Chris
-
+
Max Karma Allowed : @@ -6502,7 +6574,9 @@ Comments JBF@CD are action/reminders to Chris -
+
+ +
@@ -6530,12 +6604,17 @@ Comments JBF@CD are action/reminders to Chris
4b- Spells, Spell Talents, and Matrixes
-
As a spellcaster, you have 2 Free Matrixes that do not count for your 8 Talent points. Go to your Grimoire (click Spell Tab, and then Grimoire subtab), choose +
As a spellcaster, you have 2 Free Matrixes that do not count for your 8 Talent points. Note that with API, the links for Free Talents will be automatically created, but may not appear until the sheet is closed and reopened.
+
System also created a Dummy Talent "Wil" that is used for the Effect test. Do not delete it.
+
+ You have to choose + + - Spells of Circle 1 and 2 + Spells of Circle 1 and 2. Go to your Grimoire (click Spell Tab, and then Grimoire subtab) to add them.
@@ -6548,10 +6627,12 @@ Comments JBF@CD are action/reminders to Chris  Power Name    Rank   Step  + Dice +  Target  Stn - Kma - DP + Kma + DP
@@ -6577,6 +6658,7 @@ Comments JBF@CD are action/reminders to Chris + @@ -6611,6 +6693,11 @@ Comments JBF@CD are action/reminders to Chris + + + + + @@ -7150,6 +7237,19 @@ Comments JBF@CD are action/reminders to Chris
Grimoire
+ + + + + + + + + + + + + @@ -7166,7 +7266,7 @@ Comments JBF@CD are action/reminders to Chris up to Circle - +
-
+
All In Matrix Cir. 1 @@ -7194,7 +7294,7 @@ Comments JBF@CD are action/reminders to Chris - Matrix + Matrix Circle Disc. @@ -7204,8 +7304,8 @@ Comments JBF@CD are action/reminders to Chris Target Range - Duration - Duration + Duration + Duration Duration Description @@ -7484,7 +7584,7 @@ Comments JBF@CD are action/reminders to Chris
- + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Armor/Shield + Phys + Myst + IP + Equip + + +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + X + + + + + + + + + + + + + +
+ + + + + Shatter : + + + + Notes : +
+ +
+
+
+ + + + +
+ + + Size Restrictions: + + +
+ + +           + Weapon + Weapon + Dmg + Dmg + Add SR + Step + Dice + Size + Stn + Kma + DP + + + +
+
+ + + + + + + + + + + + + + + +     + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + Type : + + + + + + + + + Max Karma : + + + Max DP : + + +
+ + + +
+ Staging : +
+ +
+ Link : + + + + + + + + + + +
+
+ +
+
+
+
+ + + +
+
+ Thread Items and Woven Threads +
+ +
+
+
+ +

Note that most of these will require adjusting entries either in stats, talents, or miscellaneous adjustments on the last tab.

+  Items  +  Rank  +  Tier  +  Effects  +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ Ranks known (Item History) : + + + +
+ + + + +
+
+ + + # + Key/Test Knowledge + Done + Rank Effect +
+
+ + +
+ + + + 1- + + + + + + + + + +
+ +
+ + + + 2- + + + + + + + + + + +
+ + + + 3- + + + + + + + + + + +
+ + + + 4- + + + + + + + + + + +
+ + + + 5- + + + + + + + + + + +
+ + + + 6- + + + + + + + + + + +
+ + + + 7- + + + + + + + + + + +
+ + + + 8- + + + + + + + + + + +
+ + + + 9- + + + + + + + + + + +
+ + + + 10- + + + + + + + + + + +
+ + + + 11- + + + + + + + + + + +
+ + + + 12- + + + + + + + + + + +
+ + + + 13- + + + + + + + + + + +
+ + + + 14- + + + + + + + + + + +
+ + + + 15- + + + + + + + + + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + +
+
+ + + +
+
+
+ Blood Magic : +
+ +
+
+
+ +  Items     +  Dmg        +  Effects  + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+
+
+ + + +
+
Mounts and other Animals +
+ +
+
+
+ + Name + Animal + Speed + Carry + Feed + Stable + Weight +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ Equipment Weight: + + + +
Lifestyle
+ Lifestyle + + + LS Adjust: + + + Prepaid Through: + + +
+
+ + +
-
-
- - - -
- Inventory -
-
+
Inventory
@@ -8000,1112 +9209,13 @@ Comments JBF@CD are action/reminders to Chris Est. other weight: - +
- -
- -
-
Equipment -
- - -
-
- - - -
-
Equipment and Inventory Parameters
-
- Container Management : - - -
-
- Blood Magic : - - -
-
- Mounts & Companions : - - -
-
- LifeStyle : - - -
-
- Optional Displays : - - -
-
- - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Armor/Shield - Phys - Myst - IP - Equip - - -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - X - - - - - - - - - - - - - -
- - - - - Shatter : - - - - Notes : -
- -
-
-
- - - - -
- - - Size Restrictions: - - -
- - -           - Weapon - Weapon - Dmg - Dmg - Add SR - Step - Size - Stn - Kma - DP - - - -
-
- - - - - - - - - - - - - - - -     - - - - - - - + - - - - - - - + - - - - - - - - - - + - - - - - - + - - - - - - - - - - - - - - - - - - - + - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - Type : - - - - - - - - - Max Karma : - - - Max DP : - - -
- - - -
- Staging : -
- -
- Link : - - - - - - - - - - -
-
- -
-
-
-
- - - -
-
- Thread Items and Woven Threads -
- -
-
-
- -

Note that most of these will require adjusting entries either in stats, talents, or miscellaneous adjustments on the last tab.

-  Items  -  Rank  -  Tier  -  Effects  -
- - - - - - - - - - - - - - - - - - - -
- Ranks known (Item History) : - - - -
- - - - -
-
- - - # - Key/Test Knowledge - Done - Rank Effect -
-
- - -
- - - - 1- - - - - - - - - - -
- -
- - - - 2- - - - - - - - - - - -
- - - - 3- - - - - - - - - - - -
- - - - 4- - - - - - - - - - - -
- - - - 5- - - - - - - - - - - -
- - - - 6- - - - - - - - - - - -
- - - - 7- - - - - - - - - - - -
- - - - 8- - - - - - - - - - - -
- - - - 9- - - - - - - - - - - -
- - - - 10- - - - - - - - - - - -
- - - - 11- - - - - - - - - - - -
- - - - 12- - - - - - - - - - - -
- - - - 13- - - - - - - - - - - -
- - - - 14- - - - - - - - - - - -
- - - - 15- - - - - - - - - - -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- - -
-
- - - -
-
-
- Blood Magic : -
- -
-
-
- -  Items     -  Dmg        -  Effects  - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -
-
-
- - - -
-
Mounts and other Animals -
- -
-
-
- - Name - Animal - Speed - Carry - Feed - Stable - Weight -
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- - - -
- Equipment Weight: - - - -
Lifestyle
- Lifestyle - - - LS Adjust: - - - Prepaid Through: - - -
-
+
@@ -9242,9 +9352,9 @@ Comments JBF@CD are action/reminders to Chris - + - + @@ -9288,6 +9398,7 @@ Comments JBF@CD are action/reminders to Chris + @@ -9333,7 +9444,6 @@ Comments JBF@CD are action/reminders to Chris -
@@ -9353,8 +9463,8 @@ Comments JBF@CD are action/reminders to Chris
4- Common Powers and Maneuvers
To be set in Parameters/Maneuvers.
-
6- Racial Abilities
-
Automatically Determined by your Race.
+
6- Racial & Karma Abilities
+
Automatically Determined by your Race and Discipline.
+ +
@@ -9479,7 +9591,7 @@ Comments JBF@CD are action/reminders to Chris
7- Equip Your Character
-
Basic Equipment and silver as per the Player Guide p72 has been initialized in the Equipment tab. Don't forget to pick Artisan's kit per your artisan skill
+
Basic Equipment and silver as per the Player Guide p72 has been initialized in the Equipment tab. Don't forget to pick Artisan's kit per your artisan skill
8- Flesh Out your character
Describe how he looks, and his personally traits
@@ -9905,6 +10017,21 @@ Comments JBF@CD are action/reminders to Chris 10- Play the Game !
+
+
+ The sheet offers a certain number of optional displays for advanced user or special cases. The default for these displays is set in the Game Default, but you can here override the default to hide/show them all +
+ Optional Displays : + + +
+
If you created the character per the Rules, click here to exit creation and store the Free Ranks for Legend Point Tracking.
@@ -10221,7 +10349,8 @@ Comments JBF@CD are action/reminders to Chris - + +
@@ -10687,6 +10816,7 @@ Comments JBF@CD are action/reminders to Chris +
@@ -10804,9 +10934,11 @@ Comments JBF@CD are action/reminders to Chris + +
@@ -10836,9 +10968,9 @@ Comments JBF@CD are action/reminders to Chris
-
+
- +
Sheet and API parameters
@@ -10991,16 +11123,37 @@ Comments JBF@CD are action/reminders to Chris Sheet Version :
-
+
Release Notes
-
+
This section will sometimes give important instructions about actions that must be taken to keep the character sheet working correctly with the new version.
- + Note that by principle, upon release of a new version, the sheet only updates parameters that are necessary to keep the sheet working. It doesn't lookup in the compendium or local database for updates of your existing Talents, Skills, Knacks and Spells. This avoids to overwrite any personal setting or note that you would have taken. +
If you want to lookup in the compendium for any of your existing Talents, Knacks, Skills or Spells, just drop them from the compendium, or add a space at the end of the name. + Entries that have been looked up in the compendium are recognizeable by the (i) button that opens their compendium page. +
If you want the sheet to lookup all your Talents, Knacks, Skills and Spells, and overwrite the settings by the data of the compendium, press the following button (this can be useful after importing a character from an older version, buying a new compendium expansion, or switching to the API mode). Beware of the Claw Shape Talent where the Rank-Adjust will be set back to 3. +
+ + + +
-
+ +
@@ -11210,6 +11363,7 @@ Comments JBF@CD are action/reminders to Chris
+
@@ -12770,14 +12924,15 @@ var updateRace = function fnUpdateRace(eventInfo,data,cb) { // Race based modifi found=true; vals[ "Race-buttonInfo"]= "Races:" + race; } else if(compsearch && compendium_pages && compendium_pages.id){ //We found a unique page - log("Earthdawn-updateRace :Found one page in the compendium " + compendium_pages.id); + //log("Earthdawn-updateRace :Found one page in the compendium " + compendium_pages.id); rjson=compendium_pages.data; found=true; vals[ "Race-buttonInfo"]= "Races:" + race; - } else { - if(race!=="" && race!=="Creature" && race!=="Spirit") - log("Earthdawn-updateRace :No match in Compendium for " + race + " Using local database"); } + // else { + // //if(race!=="" && race!=="Creature" && race!=="Spirit") + // log("Earthdawn-updateRace :No match in Compendium for " + race + " Using local database"); + // } if(values["NPC"]=="-1"){ //Objects : reset everything rjson={roll20_isNamegiver:0 , roll20_Attrib_Dex_Race: 10, roll20_Attrib_Str_Race: 0, roll20_Attrib_Tou_Race:0, roll20_Attrib_Per_Race:10, roll20_Attrib_Wil_Race:0, roll20_Attrib_Cha_Race:0, roll20_RacialAbilities:""}; @@ -12798,7 +12953,7 @@ var updateRace = function fnUpdateRace(eventInfo,data,cb) { // Race based modifi case "Windling" : rjson={roll20_isNamegiver:1 , roll20_Attrib_Dex_Race: 11, roll20_Attrib_Str_Race: 4, roll20_Attrib_Tou_Race:8, roll20_Attrib_Per_Race:11, roll20_Attrib_Wil_Race:10, roll20_Attrib_Cha_Race:12, roll20_Movement_Race:6,roll20_Fly_Movement_Race:16, roll20_Karma_Modifier:6,roll20_Creature_ResistPain:0, onehandmin:1, onehandmax:1, twohandmax: 2 ,roll20_Fly_max:"1", roll20_TailAttack_max:"0", roll20_WeightAdjustment: "0.2" , roll20_RacialAbilities:"Flight, Increased PD, Astral Sight", abilityadd:"{\"names\": \"Astral Sight (Racial)\",\"code\":\"T\",\"rep\":\"repeating_talents\",\"roll20_Type\":\"Racial\"}"}; break; case "Blood Elf" : rjson={roll20_isNamegiver:1 , roll20_Attrib_Dex_Race: 11, roll20_Attrib_Str_Race: 10, roll20_Attrib_Tou_Race:8, roll20_Attrib_Per_Race:11, roll20_Attrib_Wil_Race:12, roll20_Attrib_Cha_Race:11, roll20_Movement_Race:14, roll20_Karma_Modifier:4,roll20_Creature_ResistPain:1, onehandmin:1, onehandmax:3, twohandmax: 6 ,roll20_Fly_max:"0", roll20_TailAttack_max:"0", roll20_WeightAdjustment: "1" , roll20_RacialAbilities:"Low-Light Vision, Longing, Pain Resistance, Protected, Thorned"}; break; case "" : rjson={roll20_isNamegiver:1 , roll20_Attrib_Dex_Race: 10, roll20_Attrib_Str_Race: 10, roll20_Attrib_Tou_Race:10, roll20_Attrib_Per_Race:10, roll20_Attrib_Wil_Race:10, roll20_Attrib_Cha_Race:10, roll20_Movement_Race:12, roll20_Karma_Modifier:0,roll20_Creature_ResistPain:0, onehandmin:1, onehandmax:3, twohandmax: 6 ,roll20_Fly_max:"0", roll20_TailAttack_max:"0", roll20_WeightAdjustment: "1" , roll20_RacialAbilities:""}; break; - case "Spirit" : case "Creature": + case "Spirit" : case "Creature": case "Horror": case "Dragon": case "Other": rjson={roll20_isNamegiver:0 , roll20_WeightAdjustment: "1" , roll20_RacialAbilities:""}; break; default: rjson=""; } else @@ -12814,7 +12969,7 @@ var updateRace = function fnUpdateRace(eventInfo,data,cb) { // Race based modifi case "Windling" : rjson={roll20_isNamegiver:1 , roll20_Attrib_Dex_Race: 11, roll20_Attrib_Str_Race: 4, roll20_Attrib_Tou_Race:8, roll20_Attrib_Per_Race:11, roll20_Attrib_Wil_Race:10, roll20_Attrib_Cha_Race:12, roll20_Movement_Race:6,roll20_Fly_Movement_Race:16, roll20_Karma_Modifier:6,roll20_Creature_ResistPain:0, onehandmin:1, onehandmax:1, twohandmax: 2 ,roll20_Fly_max:"1", roll20_TailAttack_max:"0", roll20_WeightAdjustment: "0.2" , roll20_RacialAbilities:"Flight, Increased PD, Astral Sight", abilityadd:"{\"names\": \"Astral Sight (Racial)\",\"code\":\"T\",\"rep\":\"repeating_talents\",\"roll20_Type\":\"Racial\"}"}; break; case "Blood Elf" : rjson={roll20_isNamegiver:1 , roll20_Attrib_Dex_Race: 11, roll20_Attrib_Str_Race: 10, roll20_Attrib_Tou_Race:8, roll20_Attrib_Per_Race:11, roll20_Attrib_Wil_Race:12, roll20_Attrib_Cha_Race:11, roll20_Movement_Race:14, roll20_Karma_Modifier:4,roll20_Creature_ResistPain:1, onehandmin:1, onehandmax:3, twohandmax: 6 ,roll20_Fly_max:"0", roll20_TailAttack_max:"0", roll20_WeightAdjustment: "1" , roll20_RacialAbilities:"Low-Light Vision, Longing, Pain Resistance, Protected, Thorned"}; break; case "" : rjson={roll20_isNamegiver:1 , roll20_Attrib_Dex_Race: 10, roll20_Attrib_Str_Race: 10, roll20_Attrib_Tou_Race:10, roll20_Attrib_Per_Race:10, roll20_Attrib_Wil_Race:10, roll20_Attrib_Cha_Race:10, roll20_Movement_Race:12, roll20_Karma_Modifier:0,roll20_Creature_ResistPain:0, onehandmin:1, onehandmax:3, twohandmax: 6 ,roll20_Fly_max:"0", roll20_TailAttack_max:"0", roll20_WeightAdjustment: "1" , roll20_RacialAbilities:""}; break; - case "Spirit" : case "Creature": + case "Spirit" : case "Creature": case "Horror": case "Dragon": case "Other": rjson={roll20_isNamegiver:0 , roll20_WeightAdjustment: "1" , roll20_RacialAbilities:""}; break; default: rjson=""; } @@ -12827,7 +12982,7 @@ var updateRace = function fnUpdateRace(eventInfo,data,cb) { // Race based modifi if(found){ - vals["Creature-Durability"] = (race=="Creature" ? "5" : "0"); //Creatures have a fake durability to help scaling them with Challenge Rating + vals["Creature-Durability"] = ((race=="Creature" ||race=="Horror" || race=="Dragon") ? "5" : "0"); //Creatures have a fake durability to help scaling them with Challenge Rating vals["Race_max"]=""; let fields=["isNamegiver","Attrib-Dex-Race","Attrib-Str-Race","Attrib-Tou-Race","Attrib-Per-Race","Attrib-Wil-Race","Attrib-Cha-Race","Movement-Race","Creature-ResistPain","RacialAbilities","Karma-Modifier","Fly-Movement-Race","Fly_max","TailAttack_max","WeightAdjustment"]; @@ -12840,7 +12995,7 @@ var updateRace = function fnUpdateRace(eventInfo,data,cb) { // Race based modifi if(rjson.abilityadd){ //log(rjson.abilityadd); let newdata=parseJSON(rjson.abilityadd); - // log("processing new data " + JSON.stringify(newdata)); + //log("processing new data " + JSON.stringify(newdata)); if( newdata.names && newdata.code && newdata.rep) AbilityDrop(newdata.names,newdata.rep,newdata.code,"",newdata,"AbilityAdd"); } @@ -13980,6 +14135,69 @@ on("change:repeating_talents:t_mod-type change:repeating_knacks:nac_mod-type cha + +// Takes an Earthdawn step number, and returns a string containing the dice to be rolled. +// If step is less than 1, returns an empty string. +StepToDice = function( stepNum , edition) { +'use strict'; +try { +let dice = ""; + +if ( stepNum < 0 ) +stepNum = 0; +if ( stepNum < 8 ) { // The step numbers less than 8 don't follow the same pattern as the rest of the table and should just be set to the correct value. +switch( stepNum ) { +case 1: dice = ((edition == 3) ? "{{1d6!-3}+d1}kh1+" : "{{1d4!-2}+d1}kh1+" ); break; // Roll a d4 minus something, but also roll a "d1" and keep only the highest one. +case 2: dice = ((edition == 3) ? "{{1d6!-2}+d1}kh1+" : "{{1d4!-1}+d1}kh1+" ); break; +case 3: dice = ((edition == 3) ? "{{1d6!-1}+d1}kh1+" : "d4!+" ); break; +case 4: dice = "d6!+"; break; +case 5: dice = "d8!+"; break; +case 6: dice = "d10!+"; break; +case 7: dice = "d12!+"; break; +} +} // end step 7 or less +else if( edition == 3 ) { // Earthdawn 3rd edition. +var baseNum = stepNum - 6; +var twelves = 0; +if( stepNum > 12 ) // Calculate the number of d12's we need to roll. +twelves = Math.floor( baseNum / 7); +baseNum = ( baseNum % 7 ) + 6; // We now have a number between 6 and 12. The chart repeats the same sequence, differing only in the number of d12's, which we have already calculated. + +switch( baseNum ) { +case 6: dice = "d10!+"; break; +case 7: ++twelves; break; +case 8: dice = "2d6!+"; break; +case 9: dice = "d8!+d6!+"; break; +case 10: dice = "2d8!+"; break; +case 11: dice = "d10!+d8!+"; break; +case 12: dice = "2d10!+"; break; +} +if( twelves > 0 ) +dice = ((twelves === 1) ? "" : twelves.toString()) + "d12!+" + dice; +} else { // This is Earthdawn 4th edition. +var baseNum = stepNum - 8; +if( stepNum > 18 ) // Calculate the number of d20's we need to roll. +dice = Math.floor( baseNum / 11).toString() + "d20!+"; +baseNum = ( baseNum % 11 ) + 8; // We now have a number between 8 and 18. The chart repeats the same sequence, differing only in the number of d2o's, which we have already calculated. +switch( baseNum ) { +case 8: dice += "2d6!+"; break; +case 9: dice += "d8!+d6!+"; break; +case 10: dice += "2d8!+"; break; +case 11: dice += "d10!+d8!+"; break; +case 12: dice += "2d10!+"; break; +case 13: dice += "d12!+d10!+"; break; +case 14: dice += "2d12!+"; break; +case 15: dice += "d12!+2d6!+"; break; +case 16: dice += "d12!+d8!+d6!+"; break; +case 17: dice += "d12!+2d8!+"; break; +case 18: dice += "d12!+d10!+d8!+"; break; +} +} // End 4th edition +return dice.slice(0,-1); // Trim off the trailing "+" +} catch(err) { log( "ED.StepToDice() error caught: " + err); } +}; // End StepToDice() + + // updateRepStep // When anything changes that a repeating section (talents, knacks, skills, weapons) step number is based upon, // Go through all the step numbers and recalculate them! @@ -14035,6 +14253,7 @@ var updateRepStep = function fnupdateRepStep( eventInfo ) { let step = baseStep + getInt( values, pre + "Mods" ) + modAuto; // if( step !== getInt( values, pre + "Step" )) vals[ preWrite + "Step" ] = step; + vals[ preWrite + "Step_max" ] = StepToDice(step); } catch(err) { log( "Earthdawn:updateRepStep-doRow() error caught: " + err + " for code: " + code + " rid: " + rid + "values: "); log( values ); } } // end of function doRow() @@ -14182,7 +14401,7 @@ var updateSkillType = function fnupdateSkillType( eventInfo ) { vals[pre+"Target-NoAPI"]="None"; break; case "Artisan" : - if(!values[pre+"Attribute"]) vals[pre+"Attribute"]="Cha"; + if(!values[pre+"Attribute"] || values[pre+"Attribute"]=="0") vals[pre+"Attribute"]="Cha"; vals[pre+"Target"]="None"; vals[pre+"Target-NoAPI"]="None"; break; @@ -14273,6 +14492,7 @@ on("change:repeating_talents:t_target change:repeating_knacks:nac_target change: var sanitize = function fnsanitize( name, value) { 'use strict'; try { + //log("sanitize " + value + " for " + name); let beg = value, end = ""; if( name.endsWith( "_DisplayText" ) || name.endsWith( "_SuccessText" ) || name.endsWith( "_FailText" )) { let i = value.indexOf( "~" ); // These three have a display part and a code part. Only sanitize them up to the first Tilda. @@ -14289,7 +14509,7 @@ var sanitize = function fnsanitize( name, value) { let vals = {}; vals[ name ] = newVal; setAttrsLog( vals ); - if(["T","SK","SP","ARM","WPN","INV","BL","MNT"].includes(repeatSection(3,name)) && name.endsWith("Name")) AutoFill(name,"sanitize",newVal); + if(name.endsWith("_Name") && ["T","SK","SP","ARM","WPN","INV","BL","MNT","NAC"].includes(repeatSection(3,name))) AutoFill(name,"sanitize",newVal); //JBF@JBF compendium : should call directly Autofill } } catch(err) {log("Earthdawn:sanitize() error caught: " + err );} @@ -14366,7 +14586,7 @@ var spellsanitize2 = function fnspellsanitize2( eventInfo ) { newAtt = pre + "FailText"; else if( att.search( /basetalent/gi ) !== -1) newAtt = pre + "BaseTalent"; - else if( att.search( /restrictuions/gi ) !== -1) + else if( att.search( /restrictions/gi ) !== -1) newAtt = pre + "Restrictions"; else if( att.search( /range/gi ) !== -1) newAtt = pre + "Range"; @@ -14394,7 +14614,7 @@ var spellsanitize2 = function fnspellsanitize2( eventInfo ) { } catch(err) {log("Earthdawn:preSanitize() error caught: " + err );} }; // End preSanitize() on("change:player-name change:charname change:misc-poolname-1 change:misc-poolname-2 change:misc-poolname-3 change:armor-name change:shield-name change:record-date-real change:record-date-throalic change:record-reason change:wealth_other change:repeating_talents:t_name change:repeating_talents:t_displaytext change:repeating_talents:t_successtext change:repeating_talents:t_failtext change:repeating_knacks:nac_name change:repeating_knacks:nac_displaytext change:repeating_knacks:nac_successtext change:repeating_knacks:nac_failtext change:repeating_knacks:nac_basetalent change:repeating_knacks:nac_restrictions change:repeating_skills:sk_name change:repeating_skills:sk_displaytext change:repeating_skills:sk_successtext change:repeating_skills:sk_failtext change:repeating_skilll:skl_name ", fn( preSanitize )); - on("change:repeating_spell:sp_name change:repeating_spell:sp_displaytext change:repeating_spell:sp_successtext change:repeating_spell:sp_failtext change:repeating_spell:sp_range change:repeating_spell:sp_aoe change:repeating_weapons:wpn_name change:repeating_weapons:wpn_range change:repeating_weapons:wpn_date change:repeating_mount:mnt_name change:repeating_threads:ti_name change:repeating_maneuvers:man_name change:repeating_maneuvers:man_desc", fn( preSanitize )); + on("change:repeating_spell:sp_name change:repeating_spell:sp_displaytext change:repeating_spell:sp_successtext change:repeating_spell:sp_failtext change:repeating_spell:sp_range change:repeating_spell:sp_aoe change:repeating_weapons:wpn_name change:repeating_weapons:wpn_range change:repeating_weapons:wpn_date change:repeating_mount:mnt_name change:repeating_threads:ti_name change:repeating_maneuvers:man_name change:repeating_maneuvers:man_desc change:repeating_armor:arm_name", fn( preSanitize )); @@ -14758,6 +14978,7 @@ on("clicked:setalloptions clicked:resetalloptions", fn(function ocSetAllOptions( vals["show_repeating_success"]= m; vals["show_repeating_links"]= m; vals["show_repeating_special"]= m; + vals["show_repeating_step_dice"]= m; vals["show_container"]= m; vals["show_blood"]= m; vals["show_mounts"]= m; @@ -15655,7 +15876,8 @@ on("clicked:settalentdefault", fn(function ocSetTalentDefault() { + "Alternatively the url is 'https://wiki.roll20.net/Earthdawn_-_FASA_Official'. Read it.\n" + "If you have a Pro roll20 account, it is highly recommended to install the Earthdawn API and Custom Token Marker Set (WIKI Section 4.1.2).\n" + "\n" - + "- New Version with Compendium Compatibility\n" + + "- New Version is print friendly (now that the function is available at roll20)... Ready for in person games !\n" + + "- New Version with Compendium Compatibility !!\n" + "- Compendium books will be available from the roll20 marketplace\n" + "- With the player's guide, drag and drop talents, skills, spells, equipments ...etc to the sheet to update/add to character\n" + "- Look for the (i) button to open the compendium page\n" @@ -16275,7 +16497,7 @@ on("clicked:repeating_discipline:createtalents", fn(function ocCreateTalents(eve } nbdisc=Math.min(nbdisc,4); - for( let i = 0; i < tarray.length; i++) {//Create an array of all pre-existing Talents to detected duplicates + for( let i = 0; i < tarray.length; i++) {//Create an array of all pre-existing Talents to detect duplicates let ty="D1-Novice"; if(values[buildPre( "T", tarray[ i ] ) + "Type"]) ty=values[buildPre( "T", tarray[ i ] ) + "Type"]; if( !ty.startsWith("V") && !ty.startsWith("QD")){ //Talents learned through Versatility will actually be duplicated, and Devotions are just not Talents @@ -16294,7 +16516,7 @@ on("clicked:repeating_discipline:createtalents", fn(function ocCreateTalents(eve //Circle 1 Free Talents except spellcaster : create the free talent only if processing the circle 1 if(getInt(values,pre+"Circle")>=1 && cmin <=1 && ddata["Free_C1"] ) { - if(ddata["issc"]=="1" && nbsc==1){ // Spellcaster case : Deal with the Free Matrix only if it is the first and only Matrix + if(ddata["issc"]=="1"){ // Spellcaster case : Deal with the Free Matrix only if it is the first and only Matrix if(nbsc==1){ log("Entering First SC"); for(let i=0; i<2; i++ ){ @@ -16348,6 +16570,19 @@ on("clicked:repeating_discipline:createtalents", fn(function ocCreateTalents(eve } //End creation of Circle 5 Enhanced Matrix + //Discipline Talents, first pull them all from the compendium + + let comp_query_array=[]; + for(let j=cmin; j<=cmax;j++) { + if(ddata["DT_C" + j]) { + dtarr=ddata["DT_C" + j].split(","); + for( let i = 0; i < dtarr.length; i++) + comp_query_array.push("Category:Talents Name:"+dtarr[i].trim()); + } + } + getCompendiumQuery(comp_query_array, function(comp_data) { + + //Discipline Talents for(let j=cmin; j<=cmax;j++) { if(ddata["DT_C" + j]) { @@ -16359,12 +16594,12 @@ on("clicked:repeating_discipline:createtalents", fn(function ocCreateTalents(eve vals[newInfo+"RowID"]=newId; vals[newInfo+"Name"]=dtarr[i].trim(); if(values["NPC"]!=="0") vals[newInfo+"Rank"]=cmax; //When creating an NPC, make the rank==Circle for faster NPC creation - AutoFill(newInfo+"Name","CreateTalents",dtarr[i].trim()); + AutoFill(newInfo+"Name","CreateTalents",dtarr[i].trim(),null,comp_data); vals[newInfo+"Type"]="D"+nbdisc+"-"+(j>=13 ? "Master" : (j>=9?"Warden":(j>=5?"Journeyman":"Novice"))); if(j==1) multinb++; } } } if(ddata["abilityadd_C" + j]){ - log(ddata["abilityadd_C" + j]); + //log(ddata["abilityadd_C" + j]); let newdata=parseJSON(ddata["abilityadd_C" + j]) // log("processing new data " + JSON.stringify(newdata)); if( newdata.names && newdata.code && newdata.rep) @@ -16417,6 +16652,7 @@ on("clicked:repeating_discipline:createtalents", fn(function ocCreateTalents(eve }); }); }); + }); }); } catch(err) {log("Earthdawn:ocCreateTalents() error caught: " + err );} })); //End ocCreateTalents() @@ -16855,7 +17091,7 @@ on("clicked:endcreation_nopost", fn(function ocEndAndNoPost() { // +Player drops a creature/NPC from compendium // +FillDataCreature is called and then it is like a text import -var AutoFill = function fnAutoFill(eventInfo,trigger,nm,data) { +var AutoFill = function fnAutoFill(eventInfo,trigger,nm,data,comp_data) { 'use strict'; try{ let att =getAttrib(eventInfo); @@ -16872,10 +17108,14 @@ var AutoFill = function fnAutoFill(eventInfo,trigger,nm,data) { //log("AutoFill nm "+ nm+ " JSON " + JSON.stringify(eventInfo) + " from trigger " + trigger + " rowid " +rowid ); + if(nm && nm.toLowerCase().includes("thread")) log("Autofill "+nm+ " from trigger " + trigger); + + if(_.isString(eventInfo)){ switch(trigger){ case "API" : trigger2="API"; fromAPI=true; break; case "CreateTalents" : trigger2="CreateTalents"; break; + case "Import" : trigger2="Import"; break; case "AbilityAdd" : trigger2="AbilityAdd"; fromAPI=true; break; case "sanitize" : trigger2="player"; break; default : log("Autofill unknown call from trigger " + trigger); trigger2="unknown"; @@ -16900,52 +17140,83 @@ var AutoFill = function fnAutoFill(eventInfo,trigger,nm,data) { let entry, names=[], - exactmatch,found=false,cat,vals={}; + exactmatch,found=false,cat,vals={},catarray; let compsearch=true; //This is a test switch to bypass the compendium search to test without compendium let tname=nm?nm :values[pre+"Name"].replace(APItrigger,"").trim(); //If a name was passed as parameter, we can use it, if not we get the name from getAttrs if(fromAPI) vals[pre+"Name"] = tname; - switch(code){ - case "T" : cat="Talents:"; break; - case "SK": cat="Skills:"; break; - case "SKL": cat=""; break; - case "SP": cat=""; break; - case "ARM": - case "WPN": - case "INV": - case "BL": cat="Goods and Services:"; break; - case "MNT": cat="Mounts:"; break; - case "SPM": cat="Magic:"; break; - case "NAC": cat="Knacks:"; break; - case "MAN": cat=""; break; - case "TI": cat="Magic"; break; - default : log("Earthdawn:AutoFill() unknown code: " + code ); return; - } + // //JBF@JBF : some thoughts to be given : I have included all categories, but I believe some categories are actually moot. + // switch(code){ + // case "T" : //For Talents/Powers, the place we look in the database depends on the Race + // if(values["Race"]=="Creature"){ cat=""; catarray=["Creature Powers","Skills","Talents"];} //This is the list of Category we will look at in order + // else if(values["Race"]=="Spirit"){ cat=""; catarray=["Spirit Powers","Talents","Skills"];} + // else if(values["Race"]=="Dragon"){ cat=""; catarray=["Dragon Powers","Talents","Skills","Creature Powers"];} + // else if(values["Race"]=="Horror"){ cat=""; catarray=["Horror Powers","Talents","Skills","Creature Powers"];} + // else cat="Talents:"; break; + // case "SK": cat="Skills:"; break; + // case "SKL": cat="NA:"; break; + // case "SP": cat=""; catarray=["Spells - Illusionist", "Spells - Nethermancer", "Spells - Elementalist", "Spells - Wizard", "Spells - Shaman"]; break; //Spells are in various categories, we can't filter the category + // case "ARM": + // case "WPN": + // case "INV": + // case "BL": cat="Goods and Services:"; break; + // case "MNT": cat="Mounts:"; break; + // case "SPM": cat="Magic:"; break; + // case "NAC": cat="Knacks:"; break; + // case "MAN": cat="NA:"; break;//There is no category for maneuver, and it is not supported + // case "TI": cat="Thread Items:"; break; + // default : log("Earthdawn:AutoFill() unknown code: " + code ); return; + // } + // + // + // getCompendiumPage(cat + tname.replace("\'","%E2%80%99"), compendium_pages => { + // - getCompendiumPage(cat + tname.replace("\'","%E2%80%99"), compendium_pages => { + getCompendiumQuery2(BuildCompendiumQuery(tname,code),comp_data, compendium_pages => { - // log( "Earthdawn-Autofill : Compendium Search result for " + cat + tname + " \n" + JSON.stringify(compendium_pages)); - if(compsearch && compendium_pages && compendium_pages[0] && compendium_pages[0].id){ //We have an array instead of a JSON, so multiple matches - log("Earthdawn-Autofill :Found multiple pages in the compendium, using the first one ??"); - entry=compendium_pages[0].data; - found=true; - source="compendium"; - vals[ pre+"buttonInfo"]= entry.Category+":" + tname; - } else if(compsearch && compendium_pages && compendium_pages.id){ //We found a unique page - //log("Earthdawn-Autofill :Found one page in the compendium id " + compendium_pages.data.id); - entry=compendium_pages.data; + //log( "Earthdawn-Autofill : Compendium Search result for " + code + ": " + tname + " \n" + JSON.stringify(compendium_pages)); + + if(compsearch && compendium_pages && compendium_pages[0] && compendium_pages[0].data && compendium_pages[0].data.Category){ + //log("Earthdawn-Autofill :Found " + compendium_pages.length + " page(s) in the compendium for"+ code + ": " + tname + " \n"); + let ind=0; //Index of the page we will use... Default is 0, but in some cases, we can make less randomly + if(code=="T"){ //for talents, we will have to chose between different categories... + let catarray; + if(values["Race"]=="Creature") catarray=["Creature Powers","Skills","Talents","Devotions","Spirit Powers","Dragon Powers","Horror Powers"]; //This is the list of Category we will look at in order + else if(values["Race"]=="Spirit") catarray=["Spirit Powers","Creature Powers","Talents","Skills","Devotions","Dragon Powers","Horror Powers"]; + else if(values["Race"]=="Dragon") catarray=["Dragon Powers","Creature Powers","Talents","Skills","Devotions","Spirit Powers","Horror Powers"]; + else if(values["Race"]=="Horror") catarray=["Horror Powers","Creature Powers","Talents","Skills","Devotions","Spirit Powers","Dragon Powers"]; + else catarray=["Talents","Skills","Devotions","Horror Powers","Dragon Powers","Spirit Powers","Creature Powers"]; + + for(let i=0;i page.data.Category.replace(/\s/,"%20")==catarray[i].replace(/\s/,"%20")); + if(ind!==-1) { + //log("Earthdawn-Autofill : Compendium Search result for " + code + ": " + tname + " using "+ JSON.stringify(compendium_pages[ind].data)); + break; //we found it + } + } + + if(ind==-1) { + log("Earthdawn-Autofill : Compendium Search result for " + code + ": " + tname + " didn't find entry in preferred categories "+ JSON.stringify(catarray) + " defaulting to " + compendium_pages[0].data.Category); + ind=0; + } + } + entry=compendium_pages[ind].data; found=true; source="compendium"; vals[ pre+"buttonInfo"]= entry.Category+":" + tname; + + } else { - //log("Earthdawn-Autofill :No match in Compendium. for " + cat+tname + " Using local database"); + log("Earthdawn-Autofill :No match in Compendium. for "+ tname + " Using local database"); } + if(!found) { //Using the local database - vals[ pre+"buttonInfo"]= ""; //If there was a button info, reset it. + if(trigger2=="player") vals[ pre+"buttonInfo"]= ""; //If there was a button info, reset it. + //if(nm && nm.toLowerCase().includes("thread")) log("Autofill "+nm+ "no match in compendium" ) // if (att==="" || eventInfo["sourceType"] !=="player") return; @@ -16960,8 +17231,11 @@ var AutoFill = function fnAutoFill(eventInfo,trigger,nm,data) { "SK":[ //Skills-PG {names: "Acrobatic Defense" ,roll20_Attribute:"Dex" ,roll20_Action:"Simple" ,roll20_Strain:"1" ,roll20_Mod_Type:"Action" ,roll20_Target:"PDh" ,roll20_MoveBased:"1" ,roll20_CombatSlot:"1" ,roll20_extra_note: "Talent Autofilled - PG124"} , + {names: "Acting" ,roll20_Attribute:"Cha" ,roll20_Action:"Sustained" ,roll20_Strain:"0" ,roll20_Mod_Type:"Action" ,roll20_extra_note: "Autofilled - PG191"} , {names: "Air Sailing" ,roll20_Attribute:"Wil" ,roll20_Action:"Sustained" ,roll20_Strain:"0" ,roll20_Target:"6" ,roll20_extra_note: "Talent Autofilled - PG125"} , + {names: "Alchemy" ,roll20_Attribute:"Per" ,roll20_Action:"Sustained" ,roll20_Strain:"0" ,roll20_Mod_Type:"Action" ,roll20_extra_note: "Autofilled"} , {names: "Animal Bond" ,roll20_Attribute:"Cha" ,roll20_Action:"Standard" ,roll20_Strain:"0" ,roll20_extra_note: "Talent Autofilled - PG125"} , + {names: "Animal Handling" ,roll20_Attribute:"Wil" ,roll20_Action:"Standard" ,roll20_Strain:"0" ,roll20_Mod_Type:"Action" ,roll20_extra_note: "Autofilled"} , {names: "Animal Training" ,roll20_Attribute:"Cha" ,roll20_Action:"Sustained" ,roll20_Strain:"0" ,roll20_extra_note: "Talent Autofilled - PG127"} , {names: "Anticipate Blow" ,roll20_Attribute:"Per" ,roll20_Action:"Simple" ,roll20_Strain:"1" ,roll20_Mod_Type:"Action" ,roll20_Target:"MD1: @{target|Target|token_id}" ,roll20_CombatSlot:"1" ,roll20_extra_note: "Talent Autofilled - PG128"} , {names: "Arcane Mutterings" ,roll20_Attribute:"Cha" ,roll20_Action:"Standard" ,roll20_Strain:"0" ,roll20_Mod_Type:"Action" ,roll20_Target:"SDh" ,roll20_CombatSlot:"1" ,roll20_extra_note: "Talent Autofilled - PG128"} , @@ -17053,7 +17327,7 @@ var AutoFill = function fnAutoFill(eventInfo,trigger,nm,data) { {names: "Ambush" ,Race:"Creature" ,Hardcoded:"Creature-Ambushing_max" ,roll20_extra_note:"This Power is hardcoded in the character sheet and can be found in the Parameters/Maneuvers. It can be activated like the combat options via the icons on top of the sheet" }, {names: "Charge" ,Race:"Creature" ,Hardcoded:"Creature-DivingCharging_max" ,roll20_extra_note:"This Power is hardcoded in the character sheet and can be found in the Parameters/Maneuvers. It can be activated like the combat options via the icons on top of the sheet" }, {names: "Climbing" ,Race:"Creature" ,roll20_Mod_Type:"NoRoll" }, - {names: "Creature Power" ,Race:"Creature" ,roll20_Mod_Type:"Action" ,roll20_Target:"MD1: @{target|Target|token_id}" }, + {names: "Creature Power" ,Race:"Creature" ,roll20_Mod_Type:"Action" }, {names: "Dive" ,Race:"Creature" ,Hardcoded:"Creature-DivingCharging_max" ,roll20_extra_note:"This Power is hardcoded in the character sheet and can be found in the Parameters/Maneuvers. It can be activated like the combat options via the icons on top of the sheet" }, {names: "Enhanced Sense" ,Race:"Creature" ,roll20_Attribute:"Per" ,roll20_Mod_Type:"Action" }, {names: "Fury" ,Race:"Creature" ,Hardcoded:"Creature-Fury" ,roll20_extra_note:"This Power is hardcoded in the character sheet and can be found in the Parameters/Maneuvers." }, @@ -17088,63 +17362,50 @@ var AutoFill = function fnAutoFill(eventInfo,trigger,nm,data) { {names: "Share Knowledge" ,Race:"Spirit" ,roll20_Attribute:"PER" ,roll20_Action:"Standard" ,roll20_Mod_Type:"Action" ,roll20_extra_note: "Autofilled"} , {names: "Soothe" ,Race:"Spirit" ,roll20_Attribute:"CHA" ,roll20_Action:"Standard" ,roll20_Mod_Type:"Action" ,roll20_extra_note: "Autofilled"} , {names: "Spear" ,Race:"Spirit" ,roll20_Attribute:"STR" ,roll20_Action:"Standard" ,roll20_Mod_Type:"Damage" ,roll20_extra_note: "Autofilled"} , - //{names: "Spells" ,Race:"Spirit" ,roll20_Action:"NA" ,roll20_extra_note: "Autofilled"} , - //{names: "Talents" ,Race:"Spirit" ,roll20_extra_note: "Autofilled"} , {names: "Temperature" ,Race:"Spirit" ,roll20_Attribute:"WIL" ,roll20_Action:"Standard" ,roll20_Mod_Type:"Action" ,roll20_extra_note: "Autofilled"} , //Dragon Powers - GM - - {names: "Armored Scales" ,roll20_Action:"NA" ,roll20_extra_note: "Autofilled"} , - {names: "Dispel Magic" ,roll20_Attribute:"Wil" ,roll20_Action:"Simple" ,roll20_extra_note: "Autofilled"} , - {names: "Disrupt Fate" ,roll20_Attribute:"Wil" ,roll20_Action:"Free" ,roll20_extra_note: "Autofilled"} , - {names: "Dominate Beast" ,roll20_Attribute:"Wil" ,roll20_Action:"Standard" ,roll20_extra_note: "Autofilled"} , - {names: "Dragon Breath" ,roll20_Rank_Adjust:"15" ,roll20_Action:"Simple" ,roll20_extra_note: "Autofilled"} , - {names: "Dragonsight" ,roll20_Attribute:"Per" ,roll20_Action:"Simple" ,roll20_extra_note: "Autofilled"} , - {names: "Dragonspeech" ,roll20_Attribute:"Cha" ,roll20_Action:"Free" ,roll20_extra_note: "Autofilled"} , - {names: "Fear" ,roll20_Attribute:"Cha" ,roll20_Action:"Simple" ,roll20_extra_note: "Autofilled"} , - {names: "Horror Power" ,roll20_Mod_Type:"Action" ,roll20_Target:"MD1: @{target|Target|token_id}" }, - - {names: "Karma Cancel" ,roll20_Attribute:"Wil" ,roll20_Action:"Simple" ,roll20_extra_note: "Autofilled"} , - //{names: "Karma Points" ,roll20_Action:"NA" ,roll20_extra_note: "Autofilled"} , - {names: "Lair Sense" ,roll20_Attribute:"Per" ,roll20_Action:"Free" ,roll20_extra_note: "Autofilled"} , - {names: "Poison" ,roll20_Attribute:"Tou" ,roll20_Action:"NA" ,roll20_ArmorType : "None" ,roll20_extra_note: "Autofilled"} , - {names: "Regeneration" ,roll20_Attribute:"Tou" ,roll20_Action:"Simple" ,roll20_extra_note: "Autofilled"} , - //{names: "Skills" ,roll20_Action:"Special" ,roll20_extra_note: "Autofilled"} , - {names: "Spellcasting" ,roll20_Attribute:"Per" ,roll20_Action:"Standard" ,roll20_extra_note: "Autofilled"} , - //{names: "Spells" ,roll20_Action:"NA" ,roll20_extra_note: "Autofilled"} , - {names: "Suppress Magic" ,roll20_Attribute:"Wil" ,roll20_Action:"Standard" ,roll20_extra_note: "Autofilled"} , - //{names: "Talents" ,roll20_Action:"NA" ,roll20_extra_note: "Autofilled"} , - {names: "Wingbeat" ,roll20_Attribute:"Str" ,roll20_Action:"Standard" ,roll20_extra_note: "Autofilled"} , + {names: "Armored Scales" ,Race:"Dragon" ,Hardcoded:"Dragon-HardenedArmor" ,Checkbox:"1" ,roll20_Action:"NA" ,roll20_extra_note: "Autofilled"} , + {names: "Dispel Magic" ,Race:"Dragon" ,roll20_Attribute:"Wil" ,roll20_Action:"Simple" ,roll20_Mod_Type:"Action" ,roll20_extra_note: "Autofilled"} , + {names: "Disrupt Fate" ,Race:"Dragon" ,roll20_Attribute:"Wil" ,roll20_Action:"Free" ,roll20_Mod_Type:"Action" ,roll20_Target:"MD1: @{target|Target|token_id}" ,roll20_extra_note: "Autofilled"} , + {names: "Dominate Beast" ,Race:"Dragon" ,roll20_Attribute:"Wil" ,roll20_Action:"Standard" ,roll20_Mod_Type:"Action" ,roll20_Target:"MDh" ,roll20_extra_note: "Autofilled"} , + {names: "Dragon Breath" ,Race:"Dragon" ,roll20_Rank_Adjust:"15" ,roll20_Action:"Simple" ,Strain:"1" ,roll20_Strain:"1" ,roll20_Mod_Type:"Action" ,roll20_Target:"MDh" ,roll20_extra_note: "Autofilled"} , + {names: "Dragonsight" ,Race:"Dragon" ,roll20_Attribute:"Per" ,roll20_Action:"Simple" ,roll20_Mod_Type:"Action" ,roll20_extra_note: "Autofilled"} , + {names: "Dragonspeech" ,Race:"Dragon" ,roll20_Attribute:"Cha" ,roll20_Action:"Free" ,roll20_Mod_Type:"Action" ,roll20_extra_note: "Autofilled"} , + {names: "Fear" ,Race:"Dragon" ,roll20_Attribute:"Cha" ,roll20_Action:"Simple" ,roll20_Mod_Type:"Action" ,roll20_Target:"MDh" ,roll20_extra_note: "Autofilled"} , + {names: "Karma Cancel" ,Race:"Dragon" ,roll20_Attribute:"Wil" ,roll20_Action:"Simple" ,roll20_Mod_Type:"Action" ,roll20_Target:"MD1: @{target|Target|token_id}" ,roll20_extra_note: "Autofilled"} , + {names: "Lair Sense" ,Race:"Dragon" ,roll20_Attribute:"Per" ,roll20_Action:"Free" ,roll20_Mod_Type:"Action" ,roll20_Target:"MD1: @{target|Target|token_id}" ,roll20_extra_note: "Autofilled"} , + {names: "Poison" ,Race:"Dragon" ,roll20_Attribute:"Tou" ,roll20_Action:"NA" ,roll20_Mod_Type:"Damage" ,roll20_ArmorType:"None" ,roll20_extra_note: "Autofilled"} , + {names: "Regeneration" ,Race:"Dragon" ,roll20_Attribute:"Tou" ,roll20_Action:"Simple" ,roll20_DisplayText:"costs 1 Karma ~Decrement:Karma:Min:0" ,roll20_Mod_Type:"Effect" ,roll20_Special:"Recovery" ,roll20_extra_note: "Autofilled"} , + {names: "Suppress Magic" ,Race:"Dragon" ,roll20_Attribute:"Wil" ,roll20_Action:"Standard" ,roll20_Mod_Type:"Action" ,roll20_Target:"MD1: @{target|Target|token_id}" ,roll20_extra_note: "Autofilled"} , + {names: "Wingbeat" ,Race:"Dragon" ,roll20_Attribute:"Str" ,roll20_Action:"Standard" ,roll20_Mod_Type:"Effect" ,roll20_extra_note: "Autofilled"} , //Horror Powers - GM - {names: "Animate Dead" ,roll20_Action:"Standard" }, - {names: "Astral Camouflage" ,roll20_Action:"Standard" }, - {names: "Aura of Awe" ,roll20_Action:"Standard" }, - {names: "Corrupt Compromise" ,roll20_Action:"Standard" }, - {names: "Corrupt Karma" ,roll20_Action:"Standard" ,roll20_Mod_Type:"Attack" ,roll20_Special:"CorruptKarma" ,roll20_extra_note:"Corrupt Karma Power is coded in the roll20 Sheet. See Wiki" }, - {names: "Corrupt Reality" ,roll20_Action:"Standard" }, - {names: "Cursed Luck" ,roll20_Action:"Free" ,roll20_Mod_Type:"Attack" ,roll20_Special:"CursedLuck" ,roll20_extra_note:"Cursed Luck Power is coded in the roll20 Sheet. See Wiki" }, - {names: "Damage Shift" ,roll20_Action:"Simple" }, - {names: "Disease" ,roll20_Action:"NA" }, - {names: "Displace" ,roll20_Action:"Standard" }, - {names: "Disrupt Magic" ,roll20_Action:"Standard" }, - {names: "Forge Construct" ,roll20_Action:"Sustained" }, - {names: "Forge Trap" ,roll20_Action:"Standard" }, - {names: "Harvest Energy" ,roll20_Action:"Free" }, - {names: "Horror Power" ,roll20_Action:"NA" }, - {names: "Horror Mark" ,roll20_Action:"Standard" }, - {names: "Horror Thread" ,roll20_Action:"Standard" }, - {names: "Karma Boost" ,roll20_Action:"Free" }, - {names: "Karma Drain" ,roll20_Action:"Standard" }, - {names: "Karma Points" ,roll20_Action:"NA" }, - {names: "Poison" ,roll20_Action:"NA" }, - {names: "Skills" ,roll20_Action:"NA" }, - {names: "Skin Shift" ,roll20_Action:"Simple" }, - {names: "Suppress Mark" ,roll20_Action:"Standard" }, - {names: "Terror" ,roll20_Action:"Standard" }, - {names: "Unnatural Life" ,roll20_Action:"Standard" }, - + {names: "Animate Dead" ,Race:"Horror" ,roll20_Action:"Standard" ,roll20_Mod_Type:"Action" ,roll20_Target:"MD1: @{target|Target|token_id}" }, + {names: "Astral Camouflage" ,Race:"Horror" ,roll20_Action:"Standard" }, + {names: "Aura of Awe" ,Race:"Horror" ,roll20_Action:"Standard" ,roll20_Mod_Type:"Action" ,roll20_Target:"SDh" }, + {names: "Corrupt Compromise" ,Race:"Horror" ,roll20_Action:"Standard" ,roll20_DisplayText:"Used one Karma Points~Decrement:Karma:1" ,roll20_Mod_Type:"NoRoll" }, + {names: "Corrupt Karma" ,Race:"Horror" ,roll20_Action:"Standard" ,roll20_Mod_Type:"Action" ,roll20_Target:"MD1: @{target|Target|token_id}" ,roll20_Special:"CorruptKarma" ,roll20_extra_note:"Corrupt Karma Power is coded in the roll20 Sheet. See Wiki" }, + {names: "Corrupt Reality" ,Race:"Horror" ,roll20_Action:"Standard" ,roll20_Mod_Type:"Action" ,roll20_Target:"MDh" }, + {names: "Cursed Luck" ,Race:"Horror" ,roll20_Action:"Free" ,roll20_Mod_Type:"Action" ,roll20_Target:"MD1: @{target|Target|token_id}" ,roll20_Special:"CursedLuck" ,roll20_extra_note:"Cursed Luck Power is coded in the roll20 Sheet. See Wiki" }, + {names: "Damage Shift" ,Race:"Horror" ,roll20_Action:"Simple" ,roll20_Mod_Type:"Damage" ,roll20_ArmorType:"None" }, + {names: "Disease" ,Race:"Horror" ,roll20_Action:"NA" ,roll20_Mod_Type:"NoRoll" }, + {names: "Displace" ,Race:"Horror" ,roll20_Action:"Standard" ,roll20_Mod_Type:"NoRoll" }, + {names: "Disrupt Magic" ,Race:"Horror" ,roll20_Action:"Standard" ,roll20_Mod_Type:"Action" }, + {names: "Forge Construct" ,Race:"Horror" ,roll20_Action:"Sustained" ,roll20_DisplayText:"Used five Karma Points~Decrement:Karma:5" ,roll20_Mod_Type:"Action" }, + {names: "Forge Trap" ,Race:"Horror" ,roll20_Action:"Standard" ,roll20_Mod_Type:"Effect" }, + {names: "Harvest Energy" ,Race:"Horror" ,roll20_Action:"Free" ,roll20_Mod_Type:"Action" ,roll20_Target:"SD1: @{target|Target|token_id}" }, + {names: "Horror Power" ,Race:"Horror" ,roll20_Action:"NA" ,roll20_Mod_Type:"Action" }, + {names: "Horror Mark" ,Race:"Horror" ,roll20_Action:"Standard" ,roll20_Mod_Type:"Action" ,roll20_Target:"MD1: @{target|Target|token_id}" }, + {names: "Horror Thread" ,Race:"Horror" ,roll20_Action:"Standard" ,roll20_DisplayText:"costs 1 Karma ~Decrement:Karma:Min:0" ,roll20_Mod_Type:"Action" ,roll20_Target:"MD1: @{target|Target|token_id}" }, + {names: "Karma Boost" ,Race:"Horror" ,roll20_Action:"Free" ,roll20_Mod_Type:"NoRoll" }, + {names: "Karma Drain" ,Race:"Horror" ,roll20_Action:"Standard" ,roll20_Mod_Type:"Action" ,roll20_Target:"MD1: @{target|Target|token_id}" }, + {names: "Poison" ,Race:"Horror" ,roll20_Action:"NA" ,roll20_Mod_Type:"Damage" ,roll20_ArmorType:"None" }, + {names: "Skin Shift" ,Race:"Horror" ,roll20_Action:"Simple" ,roll20_Mod_Type:"Damage" ,roll20_ArmorType:"None" }, + {names: "Suppress Mark" ,Race:"Horror" ,roll20_Action:"Standard" }, + {names: "Terror" ,Race:"Horror" ,roll20_Action:"Standard" ,roll20_Mod_Type:"Action" ,roll20_Target:"MDh" }, + {names: "Unnatural Life" ,Race:"Horror" ,roll20_Action:"Standard" ,roll20_Mod_Type:"Action" ,roll20_Target:"MD1: @{target|Target|token_id}" }, //Talents -PG {names: "Acrobatic Defense" ,roll20_Attribute:"Dex" ,roll20_Action:"Simple" ,roll20_Strain:"1" ,roll20_Mod_Type:"Action" ,roll20_Target:"PDh" ,roll20_MoveBased:"1" ,roll20_CombatSlot:"1" ,roll20_extra_note: "Talent Autofilled - PG124"} , {names: "Air Dance" ,roll20_Attribute:"Dex" ,roll20_Action:"Free" ,roll20_Strain:"2" ,roll20_Mod_Type:"Init" ,roll20_Target:"None" ,roll20_Special:"Initiative" ,roll20_MoveBased:"1" ,roll20_CombatSlot:"1" ,roll20_extra_note: "Talent Autofilled - PG124"} , @@ -17327,7 +17588,7 @@ var AutoFill = function fnAutoFill(eventInfo,trigger,nm,data) { //Other Abilities //SpecialFunction - {names: "Wil" ,roll20_Attribute:"Wil" ,roll20_Action:"Free" ,roll20_Mod_Type:"Effect" ,roll20_Special:"SPL-Willforce" ,roll20_Type:"Special" ,roll20_extra_note: "This is a Dummy Talent created by roll20 to hold the raw Wil attribute for spell effects. Do not delete"}, + {names: "Wil" ,roll20_Attribute:"Wil" ,roll20_Action:"Free" ,roll20_Mod_Type:"Effect" ,roll20_Special:"SPL-Willforce",roll20_Karma_Limit_max:"0" ,roll20_Type:"Special" ,roll20_extra_note: "This is a Dummy Talent created by roll20 to hold the raw Wil attribute for spell effects. Do not delete"}, {names: "Atk" ,roll20_Attribute:"Dex" ,roll20_Action:"Standard" ,roll20_Strain:"0" ,roll20_Mod_Type:"Attack CC" ,roll20_Target:"PD1: @{target|Target|token_id}" ,roll20_CombatSlot:"1"} , {names: "Attack,Attacks" ,roll20_Attribute:"Dex" ,roll20_Action:"Standard" ,roll20_Strain:"0" ,roll20_Mod_Type:"Attack CC" ,roll20_Target:"PD1: @{target|Target|token_id}" , roll20_exactmatch:"1" ,roll20_CombatSlot:"1"}, @@ -17552,7 +17813,7 @@ var AutoFill = function fnAutoFill(eventInfo,trigger,nm,data) { {names: "Call" ,roll20_Discipline:"Wizardry" ,roll20_sThreads:"2" ,roll20_Circle:"7" ,roll20_Casting:"MD1: @{target|Target|token_id}" ,roll20_Range:"100 miles" ,roll20_Duration:"1 rd" ,roll20_Effect:"Delivers a message" ,roll20_SuccessLevels:"Inc Efct (Other)" ,roll20_ExtraThreads:"Inc Efect (Other) (+Rank words), Inc Rng (20 miles)" } , {names: "Confusing Weave" ,roll20_Discipline:"Wizardry" ,roll20_sThreads:"1" ,roll20_Circle:"7" ,roll20_Casting:"MDhp1p" ,roll20_Range:"20 yards" ,roll20_Duration:"1 rd" ,roll20_AoE:"4-yard radius" ,roll20_Effect:"WIL" ,roll20_WilSelect:"Wil" ,roll20_SuccessLevels:"Inc Efct Step (+2)" ,roll20_ExtraThreads:"Inc Efct Step (2), Inc Rng (10 yards), Inc Area (2 yards)," } , {names: "Dislodge Spell" ,roll20_Discipline:"Wizardry" ,roll20_sThreads:"2" ,roll20_Circle:"7" ,roll20_Casting:"MD1: @{target|Target|token_id}" ,roll20_Range:"10 yards" ,roll20_Duration:"1 rd" ,roll20_Effect:"WIL+5" ,roll20_WilSelect:"Wil" ,roll20_WilEffect:"5" ,roll20_SuccessLevels:"Inc Efct Step (+2)" ,roll20_ExtraThreads:"Inc Efct Step (2), Inc Rng (10 yards), Add Tgt (+1)" } , - {names: "Hypervelocity" ,roll20_Discipline:"Wizardry" ,roll20_sThreads:"1" ,roll20_Circle:"7" ,roll20_Casting:"MD1: @{target|Target|token_id}" ,roll20_Range:"20 yards" ,roll20_Duration:"1 rd" ,roll20_Effect:"WIL+2/NA" ,roll20_WilSelect:"Wil" ,roll20_WilEffect:"2" ,roll20_SuccessLevels:"Inc Efct Step (+2)" ,roll20_ExtraThreads:"Inc Efct Step (2), Inc Rng (10 yards), Add Tgt (+1)" } , + {names: "Hypervelocity" ,roll20_Discipline:"Wizardry" ,roll20_sThreads:"1" ,roll20_Circle:"7" ,roll20_Casting:"MD1: @{target|Target|token_id}" ,roll20_Range:"20 yards" ,roll20_Duration:"1 rd" ,roll20_Effect:"WIL+2/NA" ,roll20_EffectArmor:"NoArmor" ,roll20_WilSelect:"Wil" ,roll20_WilEffect:"2" ,roll20_SuccessLevels:"Inc Efct Step (+2)" ,roll20_ExtraThreads:"Inc Efct Step (2), Inc Rng (10 yards), Add Tgt (+1)" } , {names: "Mystic Net" ,roll20_Discipline:"Wizardry" ,roll20_sThreads:"3" ,roll20_Circle:"7" ,roll20_Casting:"MDh" ,roll20_Range:"Self" ,roll20_Duration:"Rk+5 rd" ,roll20_AoE:"16-yard radius" ,roll20_Effect:"WIL+3" ,roll20_WilSelect:"Wil" ,roll20_WilEffect:"3" ,roll20_SuccessLevels:"Inc Dur (+2)" ,roll20_ExtraThreads:"Inc Dur (2), Inc Efct Step (2), Inc Area (2 yards)" } , {names: "Spellstore" ,roll20_Discipline:"Wizardry" ,roll20_sThreads:"2" ,roll20_Circle:"7" ,roll20_Casting:"Ask: ?{Target Number|0}" ,roll20_Range:"Touch" ,roll20_Duration:"Rk hr" ,roll20_Effect:"Temporarily store a spell within an object" ,roll20_SuccessLevels:"Inc Dur (+2)" ,roll20_ExtraThreads:"Inc Dur (2) " } , {names: "Astral Catastrophe" ,roll20_Discipline:"Wizardry" ,roll20_sThreads:"2" ,roll20_Circle:"8" ,roll20_Casting:"MDh" ,roll20_Range:"30 yards" ,roll20_Duration:"1 Rd" ,roll20_AoE:"6-yard radius" ,roll20_Effect:"WIL+5/Mystic and -2 to all Action tests" ,roll20_WilSelect:"Wil" ,roll20_WilEffect:"5" ,roll20_EffectArmor:"MA" ,roll20_SuccessLevels:"Inc Efct Step (+2)" ,roll20_ExtraThreads:"Inc Dur (2), Inc Efct Step (2), Inc Efect (Other) (-2 penalties), Inc Rng (10 yards), Inc Area (2 yards)" } , @@ -17700,9 +17961,10 @@ var AutoFill = function fnAutoFill(eventInfo,trigger,nm,data) { for(let i=0; i< database.length;i++){ entry=database[i]; - let matchrace= !entry.Race || (race = entry.Race); //if the entry has a race like Creature, Spirit, Dragon or Horror, it is a power specific to this race, and only applies if the character is from this race + let matchrace= !entry.Race || (race == entry.Race); //if the entry has a race like Creature, Spirit, Dragon or Horror, it is a power specific to this race, and only applies if the character is from this race. Note that Horrors and Dragons are in fact race==Creature names=entry.names.toLowerCase().replace(/\s/g, '').split(","); //Array of possible names for the database entry - exactmatch=(entry.roll20_exactmatch=="1" || entry.exactmatch=="1"); //If true we want an exact match, if not an include is sufficient + //exactmatch=(entry.roll20_exactmatch=="1" || entry.exactmatch=="1"); //If true we want an exact match, if not an include is sufficient + exactmatch=true; //JBF@JBF : turning back to only exact matches if( matchrace && (names.find(element => ((tname == element) || ( !exactmatch && tname.includes(element)))))){ found=true; i=database.length; @@ -17711,14 +17973,19 @@ var AutoFill = function fnAutoFill(eventInfo,trigger,nm,data) { if(found) { //log("Earthdawn Autofill found it in local database" + JSON.stringify(entry)); + //if(nm && nm.toLowerCase().includes("thread")) log("Autofill "+nm+ " found match in local database" ) + source="local"; } + //if(nm && nm.toLowerCase().includes("thread")) log("Autofill "+nm+ " testing the Abilityadd " + found + " trigger "+trigger + " data "+JSON.stringify(data)); + if(!found && trigger=="AbilityAdd" && data) //For an add ability, fall back to the JSON if not found somewhere else { { entry=data; source="AbilityAdd"; found=true; + //log("Didn't find it, but falling back to the passed data!! "+tname); } } //End of search in local database @@ -17762,14 +18029,19 @@ var AutoFill = function fnAutoFill(eventInfo,trigger,nm,data) { let att =getAttrib(eventInfo); //log("Fillentry att " +att); - if (att==="") return; + if (att==="" || !entry) return; //after this line, because eventInfo is either a roll20 eventInfo, or a fullname string substitute, we know for a fact that we have att in the full name format let code = repeatSection(3,att); let rowid = repeatSection(2,att); let pre = buildPre(code,rowid); let vals={}; - //log("Earthdawn - FillEntryData " + eventInfo+ " trigger " + trigger + " tf " + tname + " data "+ JSON.stringify(entry) ); + //if(tname && tname.toLowerCase().includes("thread")) log("FillEntry "+tname+ "no match in compendium" ) + + + //log("Earthdawn - FillEntryData " + eventInfo+ " trigger " + trigger + " tf " + tname);// + " data "+ JSON.stringify(entry) ); + + //log("Earthdawn - FillEntryData "+ " tf " + tname);// + " data "+ JSON.stringify(entry) ); //compendium list of fields for which we will push data from the database let fields=[],notesnm=""; @@ -17785,7 +18057,7 @@ var AutoFill = function fnAutoFill(eventInfo,trigger,nm,data) { notesnm=""; break; case "NAC": - fields=["Requirement","Restrictions","SuccessText","DisplayText","FailText","Attribute","Rank-Adjust","Action","Strain","Mod-Type","Target","ArmorType","Special","Karma-Limit","Karma-Limit_max","Defensive","MoveBased","CombatSlot","DP-Limit","Type","Duration"]; + fields=["Restrictions","SuccessText","DisplayText","FailText","Attribute","Rank-Adjust","Action","Strain","Mod-Type","Target","ArmorType","Special","Karma-Limit","Karma-Limit_max","Defensive","MoveBased","CombatSlot","DP-Limit","Type","Duration"]; notesnm="Notes"; break; case "SP": @@ -17793,7 +18065,7 @@ var AutoFill = function fnAutoFill(eventInfo,trigger,nm,data) { notesnm="Notes"; break; case "WPN": - fields=["Rank","Size","CloseCombat","CloseCombat_max","Rank-Adjust","CombatSlot"]; + fields=["Rank","Size","CloseCombat","CloseCombat_max","Rank-Adjust","CombatSlot","Karma-Limit_max"]; notesnm="Date"; break; case "INV": @@ -17813,7 +18085,7 @@ var AutoFill = function fnAutoFill(eventInfo,trigger,nm,data) { notesnm="Notes"; break; case "TI": - fields=["Type","RankKnown","Rank","Effects"]; + fields=["Type","Effects"]; notesnm="Description"; break; case "SPM": @@ -17827,7 +18099,10 @@ var AutoFill = function fnAutoFill(eventInfo,trigger,nm,data) { default : log("Earthdawn:FillEntryData() unknown code: " + code ); return; } - getAttrs( ["Race", "Movement","SrRating",pre+"Name",pre+"Notes",pre+"Rank",pre+"Rank-Adjust",pre+"Attribute",pre+"RowID","edition","APIflag","isNamegiver","Dex-Step","Str-Step","Tou-Step","Per-Step","Wil-Step","Cha-Step","WeightAdjustment"], function gaFillEntryData(values) { + let attarray=["Adjustment-Notes","Race", "Movement","SrRating",pre+"Name",pre+"Notes",pre+"Rank",pre+"Rank-Adjust",pre+"Attribute",pre+"RowID","edition","APIflag","isNamegiver","Dex-Step","Str-Step","Tou-Step","Per-Step","Wil-Step","Cha-Step","WeightAdjustment"]; + if(entry.roll20_attmodnm) attarray.push(entry.roll20_attmodnm); + + getAttrs(attarray , function gaFillEntryData(values) { function singleAttr( key, val) { //let vals={}; @@ -17836,10 +18111,17 @@ var AutoFill = function fnAutoFill(eventInfo,trigger,nm,data) { } let notes="",stepisrank; + //Certain abilities do a direct adjustment to values + if(entry.roll20_attmodnm && !values["Adjustment-Notes"].includes(entry.roll20_attmodnm)){ + vals[entry.roll20_attmodnm]=getInt(values,entry.roll20_attmodnm)+parseInt2(entry.roll20_attmodval) + vals["Adjustment-Notes"]=tname + " : " + entry.roll20_attmodnm + " Adjusted by " + parseInt2(entry.roll20_attmodval) + " to value " +vals[entry.roll20_attmodnm] + +"\n"+values["Adjustment-Notes"]; + } + //Some exceptions need to be taken into account if(["tigerspring","truesight"].includes(tname.toLowerCase().replace(/\s/,""))) stepisrank=true; //This talents are defined in the books with no attribute, but are used with an attribute, so the listed step - if( values["isNamegiver"] == "0" && (["climbing","swimming","greatleap"].includes(tname.toLowerCase().replace(/\s/,"")))) { //Those correspond to Talents, but are in fact slightly different + if( values["isNamegiver"] == "0" && (["swimming","greatleap"].includes(tname.toLowerCase().replace(/\s/,"")))) { //Those correspond to Talents, but are in fact slightly different stepisrank=true; entry.roll20_Attribute=undefined; entry.roll20_Mod_Type="NoRoll"; @@ -17851,11 +18133,53 @@ var AutoFill = function fnAutoFill(eventInfo,trigger,nm,data) { if(code=="ARM") singleAttr("Type", (entry.Type =="Shield") ? -1 : 1); + if(code=="NAC" && entry.roll20_Requirements ){ //for Knacks, requirements are in the form of "Rank X", sometimes with "Rank X, somethingelse" + let m=entry.roll20_Requirements.match(/Rank\s*(\d+)/i); + if(m) singleAttr("Requirements", m[1]); + else log("Earthdawn.FillEntrydata unrecognized Requirement for Knacks" + JSON.stringify(entry)); + } + if(code=="SK" && entry.Class=="Knowledge") entry.roll20_Attribute="Per"; if(code=="SK" && entry.Class=="Artisan" && !entry.roll20_Attribute) entry.roll20_Attribute="Cha"; if(entry.Rank) singleAttr("Rank",entry.Rank); + if(entry.roll20_Target) { + switch(entry.roll20_Target){ +//PD + case "PD" : + case "PDh" : + case "PDhp1p" : + case "PD-Nat" : + case "PD1: @{target|Target|token_id}" : singleAttr("Target-NoAPI","{{target_name=@{target|Target|token_name}}} {{target_number=[[@{target|Target|PD}]]}} {{target_defense=PD}}"); break; +//MD + case "MD" : + case "MDh" : + case "MDhp1p" : + case "MD-Nat" : + case "MD1: @{target|Target|token_id}" : singleAttr("Target-NoAPI","{{target_name=@{target|Target|token_name}}} {{target_number=[[@{target|Target|MD}]]}} {{target_defense=MD}}"); break; +//SD + case "SD" : + case "SDh" : + case "SDhp1p" : + case "SD-Nat" : + case "SD1: @{target|Target|token_id}" : singleAttr("{{target_name=@{target|Target|token_name}}} {{target_number=[[@{target|Target|SD}]]}} {{target_defense=SD}}"); break; +//ASK + case "Ask: ?{Target Number|0}" : + case "Ask: PD: ?{Target Number, maybe relative to PD|0}" : + case "Ask: MD: ?{Target Number, maybe relative to MD|0}" : + case "Ask: SD: ?{Target Number, maybe relative to SD|0}" : + case "Riposte: @{target|Counter-attack Target|token_id}: PD: ?{Target Number, maybe relative to PD|0}" : singleAttr("{{target_number=?{Target Number|0}}}"); break; +//None + case "None" : + case "2" : + case "5" : + case "6" : + case "10" : break; + } + } + + if(entry.Step){ // We have a step that we want to use, possibly we come from a Creature Import. This step has been parsed with rgStep, so it can come from many different formats //log("Processing " +entry.Name + " Step is " + entry.Step); @@ -17938,9 +18262,9 @@ var AutoFill = function fnAutoFill(eventInfo,trigger,nm,data) { for (const field of fields) {//We look first if there is a value prefixed by roll20 and second without the prefix to be more modular //log(" for tname " +tname + " and field " + field + " value1 (roll20) " + entry["roll20_"+field.replace(/\-/g,"_")]+ " value2 " + entry[field.replace(/\-/g,"_")]); - if(entry["roll20_"+field.replace(/\-/g,"_")]!=undefined){ + if(entry["roll20_"+field.replace(/\-/g,"_")]){ singleAttr( field,field=="UnitWeight" ? entry["roll20_"+field.replace(/\-/g,"_")].replace(/\,/g,".") : entry["roll20_"+field.replace(/\-/g,"_")] ); //the replace is necessary because JSON doesn't take - as separator. The second replace is necessary to get rid of issue with . or , as separators - } else if(entry[field.replace(/\-/g,"_")]!=undefined){ + } else if(entry[field.replace(/\-/g,"_")]){ singleAttr( field,field=="UnitWeight" ? entry[field.replace(/\-/g,"_")].replace(/\,/g,".") : entry[field.replace(/\-/g,"_")] ); //the replace is necessary because JSON doesn't take - as separator. The second replace is necessary to get rid of issue with . or , as separators } } @@ -17948,14 +18272,29 @@ var AutoFill = function fnAutoFill(eventInfo,trigger,nm,data) { // singleAttr( field,entry["roll20_"+field.replace(/\-/g,"_")] ); //the replace is necessary because JSON doesn't take - as separator. The parsefloat is necessary to get rid of issue with . or , as separators - if(entry.linkadd || (code=="NAC" && entry.roll20_BaseTalent)){ - setAttrsLog( { "APIflag" : addAPIflag( "", "LinkAdd1", code + " : " + (values[pre+"RowID"]||rowid) + " : T : " + ((code=="NAC") ? entry.roll20_BaseTalent :entry.linkadd)) }); //APIFlag syntax is LinkAdd1,code,rowid,code,name, the first set being the attribute Getting the value, and the second the one providing - log("trying to create link " ); + if(entry.linkadd || entry.roll20_linkadd || (code=="NAC" && entry.roll20_BaseTalent)){ //Either just a name in which case it is a talent, or code;name + let code2,nm2,m; + if(code=="NAC" && entry.roll20_BaseTalent){ + code2="T"; + nm2=entry.roll20_BaseTalent; + } else if(m=entry.linkadd.match(/(.*)\;(.*)/)){ + code2=m[1]; + nm2=m[2]; + } else if(m=entry.roll20_linkadd.match(/(.*)\;(.*)/)){ + code2=m[1]; + nm2=m[2]; + }else { + code2="T"; + nm2=entry.roll20_linkadd || entry.linkadd; + } + setAttrsLog( { "APIflag" : addAPIflag( "", "LinkAdd1", code + " : " + (values[pre+"RowID"]||rowid) + " : "+code2+" : " + nm2) }); //APIFlag syntax is LinkAdd1,code,rowid,code,name, the first set being the attribute Getting the value, and the second the one providing + log("trying to create link to " +nm2); } - if(code=="TI" && entry.Thread && entry.MaxThreadRank){ + if(code=="TI" && entry.Thread){ let tarray= parseJSON(entry.Thread); - for(let i=0;i0) + for(let i=0;i ( ) : ? detected with val1=rank, val2=ranktxt and val3=Step //In an ED4 format we will have ( ) so val1=Step if(val3){ @@ -19808,6 +20190,8 @@ var CompendiumDropMgt = function fnCompendiumDropMgt(eventInfo) { let entry={}; entry.Name=pwr; + if(!data["Race"] && HorrorPowerArray.includes(pwr)) data["Race"]="Horror"; //Test if the power is in the restricted list of Dragons/Horror to guess the Race + if(!data["Race"] && DragonPowerArray.includes(pwr)) data["Race"]="Dragon"; if(rnk) entry.Step=rnk; if(ptxt) entry.Description=ptxt; if(info) entry.Step_Info=info; @@ -19945,7 +20329,7 @@ var CompendiumDropMgt = function fnCompendiumDropMgt(eventInfo) { case "mask" : case "creature": { removePageNumbers(); - vals["NPC"]="1"; //it is an NPC + //vals["NPC"]="1"; //it is an NPC JBF@CD: can't understand why, but this makes a double trigger with UpdateRace that interferes with other stuff... let name = getName(); blockOffset = locTextStart; block = fullText.slice( blockOffset ).trim(); // Everything but name. JBF : I have put the name back to deal sith the Spirit Rating... To be discussed @@ -20075,7 +20459,7 @@ var CompendiumDropMgt = function fnCompendiumDropMgt(eventInfo) { break; case "talent": { // Knacks. let x = statBlock( i, tf, "roll20_BaseTalent" ); - data["roll20_linkadd"]=x; //to be checked when we do the actual Autofill for Knacks + if(x) data["roll20_linkadd"]=x.field; //to be checked when we do the actual Autofill for Knacks } break; case "tier": { // 1879 let x = statBlock( i, tf, null, "Word" ); @@ -20303,7 +20687,7 @@ var CompendiumDropMgt = function fnCompendiumDropMgt(eventInfo) { vals[pre+"Details"]=JSON.stringify(data); } - //textExport(data,code); + // textExport(data,code); //log("textImport returning with data " + JSON.stringify(data)); @@ -20317,29 +20701,31 @@ var CompendiumDropMgt = function fnCompendiumDropMgt(eventInfo) { var textExport = function(data,code){ let exp=""; let tags = -["Name","SrRating","Dex_Step" , "Str_Step" , "Tou_Step" , "Per_Step" , "Wil_Step" , "Cha_Step" , "Initiative" , "PD" , "MD" , "SD" , "PA" , "MA" , "Damage_Unc_Rating" , "Damage_Death_Rating" , "Wound_Threshold", "Knockdown","Recovery_Tests_max" , "Movement" ,"Movement2","Movement2_Rate","Description", "Karma_max", "KarmaStep", "loot" ,"Actions"], +["Name","CreatureSize","SrRating","Dex_Step" , "Str_Step" , "Tou_Step" , "Per_Step" , "Wil_Step" , "Cha_Step" , "Initiative" , "PD" , "MD" , "SD" , "PA" , "MA" , "Damage_Unc_Rating" , "Damage_Death_Rating" , "Wound_Threshold", "Knockdown","Recovery_Tests_max" , "Movement" ,"Movement2","Movement2_Rate","Movement3","Movement3_Rate","Description", "Karma_max", "KarmaStep", "loot" ,"Actions"], atktags=["Name","Atk_Step","Dmg_Step","Atk_Info"], mantags=["Name","Type","Info","Description"], -pwrtags=["Name","Rank","Step","Step_Info","Description"], +pwrtags=["Name","Rank","Step","Step_Info","ModType","ArmorType","Target","Description"], sptags=["Name"]; //log("textExport " + code + " "+tags); +data["CreatureSize"]=Math.ceil((getInt(data,"Str_Step") +1)/ 10 ); + for(let i=0;i elements.name==fnd[1]); + log("results for " + fnd[1] + " are "+JSON.stringify(results)); + cb(results); + } +} catch(err) {log("Earthdawn:getCompendiumQuery2() error caught: " + err );} +}; //end GetCompendiumQuery2() + + + +on("clicked:import_talents clicked:import_knacks clicked:import_skills clicked:import_spells", fn(function ocImportAll(eventInfo) { + 'use strict'; + try{ + let comp_query_array=[]; + let attarray=[]; + let rep,code; + switch(eventInfo.triggerName){ + case "clicked:import_talents" : rep="repeating_talents"; code="T"; break; + case "clicked:import_skills" : rep="repeating_skills"; code="SK"; break; + case "clicked:import_spells" : rep="repeating_spell"; code="SP"; break; + case "clicked:import_knacks" : rep="repeating_knacks"; code="NAC"; break; + default : log("Earthdawn:ocImportAll() unknown eventInfo: " + JSON.stringify(eventInfo) ); return; + } + + getSectionIDs(rep, function gsIdRepeatingTalents(tarray) { + for( let i = 0; i < tarray.length; i++) { + attarray.push( buildPre( code, tarray[ i ] ) + "Name"); + } + getAttrs( attarray , function gaTalentSummary(values) { + 'use strict'; + + for( let i = 0; i < tarray.length; i++) { + let compq= BuildCompendiumQuery(values[buildPre( code, tarray[ i ] ) + "Name"],code); + if(compq!=="") comp_query_array.push(compq); + } + + //log("compqueryarray " + JSON.stringify(comp_query_array)); + + getCompendiumQuery(comp_query_array, function(comp_data) { + //log("received the query" + JSON.stringify(comp_data)) + for( let i = 0; i < tarray.length; i++) { + AutoFill(buildPre( code, tarray[ i ] )+"Name","Import",values[buildPre( code, tarray[ i ] )+"Name"],null,comp_data); + } + +}); +}); + }); +} catch(err) {log("Earthdawn:ocImportAll() error caught: " + err );} +}));//end ocImportAll + + + + // // //v3 textImport transferred from API to Sheetworker // // //This Routine actually processes the data @@ -20412,7 +20897,7 @@ setAttrsLog({"textExport" : exp}); - setAttrsLog(vals,null,function(){ + setAttrsLog(vals,{"silent" : true},function(){ vals={}; repDiscipline(newId,null,null,function(){ updateDurability(null,function(){ @@ -20460,8 +20945,9 @@ setAttrsLog({"textExport" : exp}); function AdjustAtt(att){ if(data["Attrib_" + att + "_Curr"]){ //For Namegivers we usually have the Value and the step, sometimes we have an increase - if(data["Attrib_" + att + "_Increases"] )vals["Attrib-" + att + "-Increases"]= getInt(data,"Attrib_" + att + "_Increases"); - vals["Attrib-" + att + "-Orig"]= getInt(data,"Attrib_" + att + "_Curr") - getInt(values,"Attrib-" + att + "-Race") - getInt(data,"Attrib_" + att + "_Increase"); //backfill Orig + //log("FillDataCreature, calculating " + att + " Race " + getInt(values,"Attrib-" + att + "-Race") + " Curr (data) " + getInt(data,"Attrib_" + att + "_Curr") + " Increases (data) " + getInt(data,"Attrib_" + att + "_Increases")); + if(data["Attrib_" + att + "_Increases"]) vals["Attrib-" + att + "-Increases"]= getInt(data,"Attrib_" + att + "_Increases"); + vals["Attrib-" + att + "-Orig"]= getInt(data,"Attrib_" + att + "_Curr") - getInt(values,"Attrib-" + att + "-Race") - getInt(data,"Attrib_" + att + "_Increases"); //backfill Orig vals["Attrib-" + att + "-Curr"]= getInt(data,"Attrib_" + att + "_Curr"); //FIll the current let step= Math.floor(( getInt( data, "Attrib_" + att + "_Curr") - 1) / 3 ) + 2; vals[att+"-Step"]=getInt(data,att+"_Step"); @@ -20489,7 +20975,7 @@ setAttrsLog({"textExport" : exp}); //log("FillCreature2 result" + JSON.stringify(vals)); - setAttrsLog(vals,null,function(){ + setAttrsLog(vals,{"silent" : true},function(){ updateInitiative(null,function(){ updateKnockdown(null,function(){ updateKarma(null,function(){ @@ -20607,20 +21093,31 @@ setAttrsLog({"textExport" : exp}); if(data["Karma_max"] || data["KarmaStep"]) vals["KarmaGlobalMode"]="?"; + if(data["Misc_AggStance_Strain"]) vals["Misc-AggStance-Strain"]=data["Misc_AggStance_Strain"]; + + for(let i=0; i<3; i++){ + let nm=["Cha","Initiative","Recovery"][i]; + if(data[nm+"_Karma_Limit_Max"]) vals[nm+"-Karma-Limit_max"] = data[nm+"_Karma_Limit_Max"]; //Did the mistake of making a capped _Max... won't rake the data again + if(data[nm+"_Karma_Limit_max"]) vals[nm+"-Karma-Limit_max"] = data[nm+"_Karma_Limit_max"]; + + } + AdjustChar("Movement","Movement-Race"); //Alternative Movement Movement2 - if(data["Movement2"]){ // - if(data["Movement2"].match(/fly/i)){ //The creature is flying, + for(let i=2;i<4;i++){ + if(data["Movement"+i]){ // + if(data["Movement"+i].match(/fly/i)){ //The creature is flying, vals["Fly_max"]= "1"; - vals["Fly-Movement-Race"]=data["Movement2_Rate"] ? data["Movement2_Rate"] : data["Movement"]; + vals["Fly-Movement-Race"]=data["Movement" + i + "_Rate"] ? data["Movement" + i +"_Rate"] : data["Movement"]; } else { //Non Flying movement will be added as a Power with Step as the rate let movdata={}; - movdata.Name=data["Movement2"]; + movdata.Name=data["Movement"+i] + " (Movement)"; movdata.Mod_Type="NoRoll"; - if(data["Movement2_Rate"]) movdata.Step = data["Movement2_Rate"]; + if(data["Movement" + i + "_Rate"]) movdata.Step = data["Movement" + i + "_Rate"]; AbilityDrop(movdata.Name,"repeating_talents","T",null,movdata); } } + } if(data["Attacks"]){ @@ -20648,7 +21145,6 @@ setAttrsLog({"textExport" : exp}); } }//end attacks - //Talents AbilityArrayDrop (data["Talents"],"repeating_talents","T"); //SKILLS @@ -20656,15 +21152,18 @@ setAttrsLog({"textExport" : exp}); //SPELLS AbilityArrayDrop (data["Spells"],"repeating_spell","SP"); if(data["Spells"]) vals["Hide-Spells-Tab"]="0"; - //LANGUAGES - AbilityArrayDrop (data["Language"],"repeating_language","SKL"); - //Weapons - AbilityArrayDrop (data["Weapons"],"repeating_weapons","WPN",null,true); //Default all Weapons to CombatSlot=1 //Powers AbilityArrayDrop (data["Powers"],"repeating_talents","T",null,true,"Power"); //Default all Powers to CombatSlot=1 //Maneuvers AbilityArrayDrop (data["Maneuvers"],"repeating_maneuvers","MAN"); + + + //LANGUAGES + AbilityArrayDrop (data["Language"],"repeating_language","SKL"); + //Weapons + AbilityArrayDrop (data["Weapons"],"repeating_weapons","WPN",null,true); //Default all Weapons to CombatSlot=1 + AbilityArrayDrop (data["TI"],"repeating_threads","TI"); @@ -20672,7 +21171,7 @@ setAttrsLog({"textExport" : exp}); if(data["SuggPowers"]){ let arr,lst=""; arr=(typeof data["SuggPowers"] =="string") ? parseJSON(data["SuggPowers"]) : data["SuggPowers"]; - log("dealing with SuggPower " + JSON.stringify(arr)); + //log("dealing with SuggPower " + JSON.stringify(arr)); for(let j=0; j0) lst+=", "; lst+=arr[j].Name; @@ -20680,7 +21179,7 @@ setAttrsLog({"textExport" : exp}); } vals["SuggPowers"]=lst; vals["SuggPowers_max"]=JSON.stringify(arr); - log("writing SuggPowers " +lst); + //log("writing SuggPowers " +lst); } @@ -20695,7 +21194,7 @@ setAttrsLog({"textExport" : exp}); //log("FillCreature3 result" + JSON.stringify(vals)); - setAttrsLog(vals,null,function(){ + setAttrsLog(vals,{"silent" : true},function(){ recalc(); }); }); @@ -20776,13 +21275,16 @@ setAttrsLog({"textExport" : exp}); return; } + let data2=[]; + for(let i=1; i<=Math.min(8,getInt(values,"addspells_Circle")); i++){ let datac=data[i].split(","); for(let j=0; j0) { // We need to deal with a very special case where it is referred as highest attack and highest damage @@ -20948,13 +21450,23 @@ setAttrsLog({"textExport" : exp}); datacopy["Step"]= arr[j]["Dmg_Step"]; dmgadj=parseInt2(arr[j]["Dmg_Step"].replace(/highest\s*damage/i,"").replace(/highest\s*attack/i,"").replace(/\(\s*\)/,"").trim())||0; datacopy["Rank"]= JSON.stringify(dmgmax + dmgadj); + // if(arr[j]["Dmg_Step"].match(/highest\s*damage/i,"") || arr[j]["Dmg_Step"].match(/highest\s*attack/i,"")){ + // dmgadj=parseInt2(arr[j]["Dmg_Step"].replace(/highest\s*damage/i,"").replace(/highest\s*attack/i,"").replace(/\(\s*\)/,"").trim())||0; + // datacopy["Step"]= JSON.stringify(dmgmax + dmgadj); + // } else datacopy["Step"]= arr[j]["Dmg_Step"]; + datacopy["CombatSlot"]="1"; AbilityDrop("Dmg-" + nm,"repeating_weapons","WPN",null,datacopy); - datacopy2["Name"]="Atk-" + nm; + datacopy2["Step"]= arr[j]["Atk_Step"]; atkadj=parseInt2(arr[j]["Atk_Step"].replace(/highest\s*damage/i,"").replace(/highest\s*attack/i,"").replace(/\(\s*\)/,"").trim())||0; datacopy2["Rank"]= JSON.stringify(atkmax + atkadj); + // if(arr[j]["Atk_Step"].match(/highest\s*damage/i,"") || arr[j]["Atk_Step"].match(/highest\s*attack/i,"")){ + // atkadj=parseInt2(arr[j]["Atk_Step"].replace(/highest\s*damage/i,"").replace(/highest\s*attack/i,"").replace(/\(\s*\)/,"").trim())||0; + // datacopy2["Step"]= JSON.stringify(atkmax + atkadj); + // } else datacopy2["Step"]= arr[j]["Atk_Step"]; + datacopy2["Mod_Type"]="Attack CC"; datacopy2["roll20_Attribute"]="Dex"; datacopy2["roll20_Target"]="PD1: @{target|Target|token_id}"; @@ -20969,10 +21481,10 @@ setAttrsLog({"textExport" : exp}); //SPELLS AbilityArrayDrop (data["Spells"],"repeating_spell","SP"); if(data["Spells"]) vals["Hide-Spells-Tab"]="0"; - //LANGUAGES + //Weapons AbilityArrayDrop (data["Weapons"],"repeating_weapons","WPN",null,true); //Powers - AbilityArrayDrop (data["Powers"],"repeating_talents","T",null,true,"Power"); + AbilityArrayDrop (data["Powers"],"repeating_talents","T",atkmax,true,"Power"); //Maneuvers AbilityArrayDrop (data["Maneuvers"],"repeating_maneuvers","MAN"); @@ -20988,6 +21500,62 @@ setAttrsLog({"textExport" : exp}); + //This Routine actually processes the data of traps + var FillDataTrap = function fnFillDataTrap(data) { + 'use strict'; + try{ + let vals={}; + let attarray=["Damage-Death-Rating" , "Damage-Death-Rating-Adjust","Initiative","Misc-Initiative-Adjust","PD","PD-Nat","Defense-Phys-Nat-Adjust","PA","PA-Nat","Armor-Phys-Nat-Adjust","MD","MD-Nat","Defense-Myst-Nat-Adjust","MA","MA-Nat","Armor-Myst-Nat-Adjust",]; + + log("FillTrap data " + JSON.stringify(data)); + getAttrs(attarray, function gaFillDataTrap(values) { + + + function AdjustChar(attdata,att,attadj,adj2){ + if(data[attdata] && ["immune","na","-"].includes(data[attdata].trim().toLowerCase())) //Dealing with immunities + vals[ attadj ? attadj : att] = "999"; + else if(data[attdata]){ + let adj=getInt(data,attdata) - getInt(values,att)-(adj2||0); + if(adj!==0){ + if(attadj) vals[attadj] = adj + getInt(values,attadj); //Adjust via adjustment + else vals[att]=getInt(data,attdata)-(adj2||0); //Adjustment directly in the target value + } + //log("AdjustChar " + att + " value to reach " + getInt(data,attdata) + " value before " + getInt(values,att) + " adj2 is " +adj2 + " adj is " + adj); + if(data[attdata].match(rgSR)) vals[att + "-addSR"]="1"; + } + } //end AdjustChar + + + + AdjustChar("Initiative","Initiative","Misc-Initiative-Adjust",0); + AdjustChar("PD","PD-Nat","Defense-Phys-Nat-Adjust",0); + AdjustChar("PA","PA-Nat","Armor-Phys-Nat-Adjust",0); + AdjustChar("MD","MD-Nat","Defense-Myst-Nat-Adjust",0); + AdjustChar("MA","MA-Nat","Armor-Myst-Nat-Adjust",0); + //Health Ratings + AdjustChar("Damage_Death_Rating","Damage-Death-Rating","Damage-Death-Rating-Adjust"); + + //Powers + AbilityArrayDrop (data["Powers"],"repeating_talents","T",null,true,"Power"); + //log("FillMask "+ JSON.stringify(vals)); + + let note=""; + if(data.Detection) note+="Detection : " + data.Detection + "\n"; + if(data.Disarm) note+="Disarm : " + data.Disarm + "\n"; + if(data.Description) note+="Description : \n" + data.Description + "\n"; + if(data.Trigger) note+="Trigger : \n" + data.Trigger + "\n"; + if(data.Effect) note+="Effect : \n" + data.Effect + "\n"; + + vals["general-notes"]=note; + + + setAttrsLog(vals); + + }); + } catch(err) {log("Earthdawn:FillDataTrap() error caught: " + err );} + }; //end FillDataTrap() + + //For Any array like Talents, Power etc in the JSON for textimport or creature drop, fills in the array //if combatslot is set, set it for all var AbilityArrayDrop = function fnAbilityArrayDrop (data,rep,code,atkmax,combatslot,type) { @@ -20997,7 +21565,20 @@ var AbilityArrayDrop = function fnAbilityArrayDrop (data,rep,code,atkmax,combats if(typeof data =="string") arr=parseJSON(data); else arr=data; if(!arr) return; - for(let j=0; j