@@ -1766,7 +1766,8 @@ Earthdawn.parseInt2 = function ( i, silent ) {
1766
1766
return x || 0;
1767
1767
*/
1768
1768
try {
1769
- if(( i === undefined ) || ( i === null ) || (i === "" )) return 0; // if it is an empty string, just quietly return a zero.
1769
+ if(( i === undefined ) || ( i === null ) || (i === "" ) || (i === false)) return 0; // if it is an empty string, just quietly return a zero.
1770
+ else if( i === true ) return 1;
1770
1771
let x = parseInt( i );
1771
1772
if( isNaN( x )) {
1772
1773
if( !silent )
@@ -1899,7 +1900,7 @@ Earthdawn.safeString = function( str ) {
1899
1900
// This checks for undefined, writes an error message, and substitutes a default value.
1900
1901
//
1901
1902
// Rats. Can't test for NaN here, because use same routine for string and numbers. But NaN fails as well.
1902
- Earthdawn.set = function( obj, type, val, dflt ) { // type is "current" or "max"
1903
+ Earthdawn.set = function( obj, type, val, dflt ) { // type is often "current" or "max" for attributes, but could be name, bar3_value, bar3_max, or even status_xxx.
1903
1904
'use strict';
1904
1905
try {
1905
1906
// log( "set " + obj.get("name") + " val " + val);
@@ -3316,8 +3317,12 @@ Step/Action Dice Table
3316
3317
armortype;
3317
3318
ssa[ 1 ] = Earthdawn.safeString( ssa[ 1 ] ).toLowerCase();
3318
3319
switch ( ssa[ 1 ] ) {
3320
+ case "sk": {
3321
+ let cls = Earthdawn.getAttrBN( this.charID, pre + "Class", "General");
3322
+ if( cls !== "General" )
3323
+ this.misc[ "skillClass" ] = cls;
3324
+ }
3319
3325
case "t":
3320
- case "sk":
3321
3326
case "skc":
3322
3327
case "nac": {
3323
3328
this.misc[ "result" ] = (this.misc[ "result" ] || 0) + this.getValue( pre + "Result-Mods");
@@ -3350,8 +3355,8 @@ Step/Action Dice Table
3350
3355
this.misc[ "Special" ] = special;
3351
3356
if( special.startsWith( "Recovery" )) {
3352
3357
this.bFlags |= Earthdawn.flags.Recovery;
3353
- if( special === "Recovery-Woodskin " )
3354
- this.misc[ "Recovery-Woodskin " ] = true;
3358
+ if( special === "Recovery-WoodSkin " )
3359
+ this.misc[ "Recovery-WoodSkin " ] = true;
3355
3360
if (Earthdawn.getAttrBN( this.charID, "NPC", "1") != Earthdawn.charType.mook) {
3356
3361
let aobj = Earthdawn.findOrMakeObj({ _type: 'attribute', _characterid: this.charID, name: "Recovery-Tests" }, 0, 2);
3357
3362
if( (aobj.get( "current" ) || 0) <= 0) {
@@ -3368,7 +3373,7 @@ Step/Action Dice Table
3368
3373
3369
3374
switch( special ) {
3370
3375
case "Recovery":
3371
- case "Recovery-Woodskin ": this.misc[ "headcolor" ] = "recovery"; break;
3376
+ case "Recovery-WoodSkin ": this.misc[ "headcolor" ] = "recovery"; break;
3372
3377
case "Initiative": this.misc[ "headcolor" ] = "initrep"; break;
3373
3378
case "Knockdown": this.misc[ "headcolor" ] = "knockdown"; break;
3374
3379
default:
@@ -3911,7 +3916,7 @@ Step/Action Dice Table
3911
3916
// We have a request to display a menu in the chat window.
3912
3917
// attrib, damage, editspell2: (dur, MenuAddExtraThread, AddExtraThread, MenuRemoveExtraThread, RemoveExtraThread),
3913
3918
// fxSet: (sequnce of submenus), gmstate / gmspecial, grimoire, help, languages, link, linkAdd1, linkAdd2, linkRemove, linkRemoveHalf,
3914
- // oppmnvr, RolltypeEdit, skills, spells, stateEdit, status, talents.
3919
+ // oppmnvr, RolltypeEdit, RolltypeMulti, skills, spells, stateEdit, status, talents.
3915
3920
this.ChatMenu = function( ssa ) {
3916
3921
'use strict';
3917
3922
let edParse = this;
@@ -4999,7 +5004,7 @@ Step/Action Dice Table
4999
5004
if( Array.isArray( v ) ) { // This is best practices for building Roll20 nested chat menu queries.
5000
5005
// The innermost query can be of the form ?{}. Inner queires must call Earthdawn.constant for pipe, comma, and braseClose.
5001
5006
str = "?{What do you want to do with array \'" + k + "\'|"
5002
- + "Never mind, nothing| Delete|Add Elements, arrayAdd: "
5007
+ + "Delete|Add Elements, arrayAdd: "
5003
5008
+ "?{Add Where (F for first. L for last. or after a zero based index number)" + Earthdawn.constant( "braceClose", 2 ) + ": "
5004
5009
+ "?{Add What type of element"
5005
5010
+ Earthdawn.constant( "pipe", 2 ) + "Number" + Earthdawn.constant( "comma", 2 )
@@ -5013,7 +5018,7 @@ Step/Action Dice Table
5013
5018
+"|Set to Empty, change}";
5014
5019
tip = "This routine can not do anything with arrays yet except delete them, or set them to empty.";
5015
5020
} else {
5016
- str = "?{What do you want to do with object|Edit|Into object " + k + ",In|Delete|Never mind,nothing }";
5021
+ str = "?{What do you want to do with object|Edit|Into object " + k + ",In|Delete}";
5017
5022
tip = "Make this object the current object, so that you can manipulate (edit or delete) its properties.";
5018
5023
}
5019
5024
break;
@@ -5121,6 +5126,47 @@ Step/Action Dice Table
5121
5126
log( ssa );
5122
5127
} } }
5123
5128
break; // end stateEdit
5129
+ case "rolltypemulti": { // ssa[ 2 ] = state.Earthdawn.Rolltype.NPC, Others are ether exceptionIs or exceptionWouldBe entries.
5130
+ //cdd
5131
+ let except = ssa[ 2 ].endsWith( ".NPC" ) ? state.Earthdawn.Rolltype.NPC.Exceptions : state.Earthdawn.Rolltype.PC.Exceptions,
5132
+ wkey, wname, dname,
5133
+ s = "Do you want to: ";
5134
+ for( let i = 3; i < ssa.length; ++i ) {
5135
+ let tip;
5136
+ switch( ssa[ i ].toLowerCase() ) {
5137
+ case "skillexceptionis":
5138
+ tip = "This display exception is setup by skill type: Knowledge or Artisan. Exceptions can also be setup by skill name.";
5139
+ case "exceptionis":
5140
+ if( tip === undefined ) tip = "This display exception is setup by skill name. They can also be setup by skill type: Knowledge or Artisan.";
5141
+ wname = ssa[ ++i ];
5142
+ if( wname in except ) {
5143
+ dname = except[ wname ][ "name" ];
5144
+ s += "Edit display exception for "
5145
+ + Earthdawn.makeButton( dname, "!Earthdawn~ ChatMenu: RolltypeEdit: " + ssa[ 2 ] + ": " + wname
5146
+ + ": ?{Edit display exception for '" + dname + "'|Change to Public, exceptionEdit: Public|Change to GM Only, exceptionEdit: GM Only"
5147
+ + "| Change to Player and GM, exceptionEdit: Player and GM|Delete exception, exceptionDelete}"
5148
+ , tip, Earthdawn.Colors.action, Earthdawn.Colors.actionfg ) + ".";
5149
+ } else
5150
+ this.chat( "Earthdawn rolltypeMulti data mismatch Error. " + wname + " not found.", Earthdawn.whoFrom.apiWarning );
5151
+ break;
5152
+ case "skillexceptionwouldbe":
5153
+ case "exceptionwouldbe":
5154
+ tip = "You can setup rolltype exceptions for Knowledge and Artisan skills ether by name or type.";
5155
+ wname = ssa[ ++i ];
5156
+ s += "Create a display exception for "
5157
+ + Earthdawn.makeButton( wname, "!Earthdawn~ ChatMenu: RolltypeEdit: " + ssa[ 2 ] + ": " + wname
5158
+ + ": ?{Create a display exception for '" + wname
5159
+ + "'|Public, exceptionAdd: Public|GM Only, exceptionAdd: GM Only|Player and GM, exceptionAdd: Player and GM}"
5160
+ , tip, Earthdawn.Colors.action, Earthdawn.Colors.actionfg ) + ".";
5161
+ break;
5162
+ default:
5163
+ this.chat( "Earthdawn rolltypeMulti Error. Unknown command " + ssa[ i ], Earthdawn.whoFrom.apiWarning );
5164
+ log( ssa );
5165
+ } }
5166
+ this.chat( s.trim(), Earthdawn.whoTo.player | Earthdawn.whoFrom.api | Earthdawn.whoFrom.noArchive, "gmStateEdit" );
5167
+
5168
+ // cdd
5169
+ } break; // end RolltypeMulti
5124
5170
case "status": { // Called from a macro Token action. Visible when any character is selected.
5125
5171
let basic = true;
5126
5172
@@ -5675,8 +5721,8 @@ Step/Action Dice Table
5675
5721
currDmg += dmg;
5676
5722
if( bRecovery ) {
5677
5723
if( currDmg < 0 ) { // If all damage has been healed, we have to know whether this is a wood skin test or not, since those are handled differently.
5678
- if( "Recovery-Woodskin " in this.misc )
5679
- recMsg += " Wood Skin added " + (dmg * -1) + Earthdawn.addIcon( "damage ", "l" ) + " Health. New damage value " + currDmg + ".";
5724
+ if( "Recovery-WoodSkin " in this.misc )
5725
+ recMsg += " Wood Skin added " + (dmg * -1) + Earthdawn.addIcon( "damagehealth ", "l" ) + " Health. New damage value " + currDmg + ".";
5680
5726
else { // We know this is NOT woodskin and we have negative damage, have the leftover heal stun damage.
5681
5727
recMsg += " recovered " + ((dmg - currDmg) * -1) + Earthdawn.addIcon( "damage", "l" ) + " damage. New value 0.";
5682
5728
bStun = true;
@@ -5734,6 +5780,7 @@ Step/Action Dice Table
5734
5780
}
5735
5781
newMsg += ".<br>Takes wound " + currWound;
5736
5782
} // end wound
5783
+ // cdd todo. If stun would have caused a wound, set harried until end of round.
5737
5784
5738
5785
if( currDmg >= Earthdawn.getAttrBN( this.charID, "Damage-Death-Rating", 25 )) {
5739
5786
newMsg += ".<br>Character is DEAD";
@@ -5748,8 +5795,10 @@ Step/Action Dice Table
5748
5795
newMsg += ". Need to make a Knockdown Test";
5749
5796
gmMsg += " TN " + ( dmg - WoundThreshold ) + "<br>" +
5750
5797
Earthdawn.makeButton( "Knockdown",
5751
- "!Earthdawn~ CharID:" + this.charID + "~ TargetNum: " + ( dmg - WoundThreshold )
5752
- + ": Adjust-TN-Auto: Adjust-TN-Misc~ foreach~ modValue: ?{Modification|0} ~ K-ask: @{" + cname + "|KarmaGlobalMode}@{"
5798
+ "!Earthdawn~ " + (( this.tokenInfo !== undefined && this.tokenInfo.tokenObj !== undefined)
5799
+ ? "setToken: " + this.tokenInfo.tokenObj.get( "id" ) : "charID: " + this.charID )
5800
+ + "~ TargetNum: " + ( dmg - WoundThreshold )
5801
+ + ": Adjust-TN-Auto: Adjust-TN-Misc~ modValue: ?{Modification|0} ~ K-ask: @{" + cname + "|KarmaGlobalMode}@{"
5753
5802
+ cname + "|Str-Karma-Ask}: @{" + getAttrByName( this.charID, "character_name") + "|DPGlobalMode}@{"
5754
5803
+ cname + "|Str-DP-Ask}~ Value: Knockdown: Adjust-All-Tests-Total: Defensive: Resistance~ Roll"
5755
5804
,"Make a standard Knockdown test.", Earthdawn.Colors.action, Earthdawn.Colors.actionfg );
@@ -5763,16 +5812,18 @@ Step/Action Dice Table
5763
5812
rid = Earthdawn.repeatSection( 2, att.get( "name") );
5764
5813
//log( "Talent Found " + pre + " " + name + " " + code +" " + rid + " " + cname);
5765
5814
gmMsg += Earthdawn.makeButton( name + " test",
5766
- "!Earthdawn~ CharID:" + po.charID + "~ TargetNum: " + ( dmg - WoundThreshold )
5767
- + ": Adjust-TN-Auto: Adjust-TN-Misc~ foreach:sct:ust:c~ modValue: ?{Modification|0} ~ K-ask: @{" + cname + "|KarmaGlobalMode}@{"
5815
+ "!Earthdawn~ " + (( po.tokenInfo !== undefined && po.tokenInfo.tokenObj !== undefined)
5816
+ ? "setToken: " + po.tokenInfo.tokenObj.get( "id" ) : "charID: " + po.charID )
5817
+ + "~ TargetNum: " + ( dmg - WoundThreshold )
5818
+ + ": Adjust-TN-Auto: Adjust-TN-Misc~ modValue: ?{Modification|0} ~ K-ask: @{" + cname + "|KarmaGlobalMode}@{"
5768
5819
+ cname + "|" + pre + "Karma-Ask}: @{" + cname + "|DPGlobalMode}@{"
5769
5820
+ cname + "|" + pre + "DP-Ask}~ Action: "+ code +":" + rid
5770
5821
,"Make a Knockdown test.", Earthdawn.Colors.action, Earthdawn.Colors.actionfg );
5771
5822
}
5772
5823
}); // End for each attribute.
5773
5824
} }
5774
-
5775
- if(gmMsg && npc == Earthdawn.charType.pc){ //gm message is sent separately to GM for NPCs and appended for PCs
5825
+
5826
+ if(gmMsg && npc == Earthdawn.charType.pc) { //gm message is sent separately to GM for NPCs and appended for PCs
5776
5827
newMsg += gmMsg;
5777
5828
gmMsg = "";
5778
5829
}
@@ -6243,9 +6294,39 @@ log( cnt);
6243
6294
6244
6295
6245
6296
6297
+ // ParseObj.findAllPagesAnyPlayterIsOn()
6298
+ //
6299
+ // Returns an array of pageIDs.
6300
+ // if testOnline is false then list is of all pages, whether players are online or not. Otherwise it is only online players. Defaults to true.
6301
+ this.findAllPagesAnyPlayterIsOn = function( testOnline ) {
6302
+ 'use strict';
6303
+ try {
6304
+ if( testOnline === undefined || testOnline ) testOnline = true; // testOnline defaults to true. Set to native boolean so don't have to convert each loop.
6305
+ else testOnline = false;
6306
+ let pgs = Campaign().get( "playerspecificpages" ), // object of pages that have players on them.
6307
+ players = findObjs({ _type: "player", _online: true }), // array of online players.
6308
+ ret = [ Campaign().get( "playerpageid" ) ]; // the all players page.
6309
+ if( pgs )
6310
+ Object.entries( pgs ).forEach(([key, val]) => {
6311
+ if(( testOnline || ( key in players )) && ( !( key in ret))) // If page is not already in ret, and page is an online player, add it to the list.
6312
+ ret.push( val );
6313
+ });
6314
+ players.forEach( function( item ) {
6315
+ 'use strict';
6316
+ if( playerIsGM( item.get( "_id" )) && !ret.includes( item.get( "_lastpage" ))) // if player is gm and last page they visited is not already in ret, add it.
6317
+ ret.push( item.get( "_lastpage" ));
6318
+ });
6319
+ return ret;
6320
+ } catch(err) { Earthdawn.errorLog( "ED.findAllPagesAnyPlayterIsOn() error caught: " + err, this ); }
6321
+ }; // End ParseObj.findAllPagesAnyPlayterIsOn
6322
+
6323
+
6324
+
6246
6325
// ParseObj.FindPageOfPlayer()
6247
6326
//
6248
6327
// Returns pageID of page this player is on.
6328
+ //
6329
+ // Note that Jun 2024 I think the only routine that called this now calls findAllPagesAnyPlayerIsOn instead. So routine might be useless.
6249
6330
this.FindPageOfPlayer = function( playerID ) {
6250
6331
'use strict';
6251
6332
try {
@@ -6256,7 +6337,7 @@ log( cnt);
6256
6337
else // player is on the all players page.
6257
6338
ret = Campaign().get( "playerpageid" );
6258
6339
return ret;
6259
- } catch(err) { Earthdawn.errorLog( "ED.FindPageOfPlayer() error caught: " + err, playerID ); }
6340
+ } catch(err) { Earthdawn.errorLog( "ED.FindPageOfPlayer() error caught: " + err, this ); }
6260
6341
}; // End ParseObj.FindPageOfPlayer
6261
6342
6262
6343
@@ -6269,18 +6350,18 @@ log( cnt);
6269
6350
let edParse = this;
6270
6351
try {
6271
6352
this.tokenIDs = [];
6272
- let bst = false, // Do we want all selected tokens?
6353
+ let bst = false, // Do we want all selected tokens?
6273
6354
bsct = false, // Do we want all selected character tokens?
6274
6355
bust = false, // Do we want to look in unselected tokens if we can't find with the above?
6275
6356
binmt = false, // Do we want to ignore all selected tokens that do not match the character ID?
6276
- btuc = false, // Token Unique Character - Ignore all except the first token for each unique character.
6357
+ btuc = false, // Token Unique Character - Ignore all except the first token for each unique character.
6277
6358
bc = false, // Do we want character (if found nothing else)?
6278
- flag = 0, // Instead of doing a ForEachToken loop: 1 - return a list of tokens.
6359
+ flag = 0, // Instead of doing a ForEachToken loop: 1 - return a list of tokens.
6279
6360
mooks = false, // Do we want to ignore all selected non-mooks?
6280
6361
notMooks = false, // Do we want to ignore all selected mooks?
6281
6362
PCs = false, // Do we want to ignore all selected NPCs?
6282
6363
NPCs = false, // Do we want to ignore all selected PCs?
6283
- notPCs = false, // Do we want to ignore all selected non-PCs?
6364
+ notPCs = false, // Do we want to ignore all selected non-PCs?
6284
6365
objarr = [];
6285
6366
6286
6367
for ( let i = 1; i < ssa.length; i++) {
@@ -6381,9 +6462,12 @@ log( cnt);
6381
6462
if( bust && ((objarr.length || 0) < 1 )) {
6382
6463
let CharObj = getObj("character", this.charID);
6383
6464
if ((typeof CharObj != 'undefined') && ( this.edClass.msg !== undefined )) {
6384
- let page = this.FindPageOfPlayer( this.edClass.msg.playerid );
6385
- let tkns = findObjs({ _pageid: page, _type: "graphic", _subtype: "token", represents: this.charID });
6386
- _.each( tkns, function (TokObj) { // Check all tokens on the page.
6465
+ let pages = this.findAllPagesAnyPlayterIsOn(),
6466
+ tkns = [];
6467
+ pages.forEach(( page ) => {
6468
+ tkns = _.union( tkns, findObjs({ _pageid: page, _type: "graphic", _subtype: "token", represents: this.charID }));
6469
+ });
6470
+ _.each( tkns, function( TokObj ) { // Check all tokens found
6387
6471
if( btuc && objarr.length > 0 )
6388
6472
return;
6389
6473
let TokenName = TokObj.get("name");
@@ -6422,7 +6506,7 @@ log( cnt);
6422
6506
edParse.tokenInfo = edpS1;
6423
6507
edParse.charID = edpS2;
6424
6508
return ret;
6425
- } else {
6509
+ } else { // This is the more normal case. Call all the rest of the command line, with each token found.
6426
6510
let miscsave = _.clone( edParse.misc ); // Otherwise this gets passed by reference and all copies end up sharing the same object. So save a clone, and explicitly clone the clone back in.
6427
6511
this.indexToken = 0;
6428
6512
_.each( objarr, function ( obj ) {
@@ -7461,8 +7545,6 @@ Get these in pairs, char sheet attrib and token status, get them ORed, then figu
7461
7545
++fnd;
7462
7546
let itm = itma[ 1 ].replace( "\[", "").replace( "\]", "" ); // remove brackets from code.
7463
7547
if( itm !== "0^u" ) { // Unset with value 0 is already in array.
7464
-
7465
-
7466
7548
let kernals = itm.split( "^" ),
7467
7549
kb = kernals[ 1 ],
7468
7550
kb2 = kb;
@@ -7480,7 +7562,7 @@ Get these in pairs, char sheet attrib and token status, get them ORed, then figu
7480
7562
valid[ 0 ].attrib = kernals[ 0 ]; //If we are in this loop, i.e. there is a submenu, but it is not "0^u", we should update the default unset attrib
7481
7563
else
7482
7564
valid.push({ level: Earthdawn.parseInt2( kernals[ 0 ]), attrib: Earthdawn.parseInt2( kernals[ 0 ]), badge: kb2, marker: mark });
7483
- // log("test " + JSON.stringify(valid));
7565
+ // log("test " + JSON.stringify(valid));
7484
7566
} } } }
7485
7567
if( !fnd ) { // A classic submenu was not found, so we seem to have a freeform numeric input.
7486
7568
valid.push({ level: 0, attrib: 0, badge: true, marker: mark });
@@ -7508,7 +7590,7 @@ Get these in pairs, char sheet attrib and token status, get them ORed, then figu
7508
7590
this.chat( "Earthdawn: Markerset Warning. Unable to parse " + JSON.stringify( mia[ i ] ), Earthdawn.whoFrom.apiWarning );
7509
7591
} // end make list of validValues and validBadges
7510
7592
valid = _.sortBy( valid, "level" );
7511
- //log( marker); log( mi); log( JSON.stringify( valid));
7593
+ //log(mi); log( JSON.stringify( valid));
7512
7594
7513
7595
if( ssa.length > 1 ) { // This section sets level and adjust. See the declarations above and the comments at the top of the routine.
7514
7596
if( ssa.length > 2 ) {
@@ -7555,7 +7637,7 @@ Get these in pairs, char sheet attrib and token status, get them ORed, then figu
7555
7637
if( level > 0 && neg )
7556
7638
level *= -1;
7557
7639
// at this point level is -1111 for unset, 0 for set, or a badge between 1 and 9. Adjust might be set, which will modify these these.
7558
-
7640
+ //log("level " + level);
7559
7641
7560
7642
// Given a potential level value, see if it is one of the expected values. If so return that valid item.
7561
7643
// If not, find the closest one.
@@ -7623,7 +7705,6 @@ Get these in pairs, char sheet attrib and token status, get them ORed, then figu
7623
7705
else
7624
7706
setObj = findMenu( level );
7625
7707
}
7626
- //log( setObj);
7627
7708
if( !setObj ) {
7628
7709
this.chat( "Earthdawn: Markerset error. level is undefined.", Earthdawn.whoFrom.apiWarning );
7629
7710
return;
@@ -7633,13 +7714,15 @@ Get these in pairs, char sheet attrib and token status, get them ORed, then figu
7633
7714
//log( "level: " + level + " setObj: " + JSON.stringify( setObj ));
7634
7715
if( "marker" in setObj )
7635
7716
Earthdawn.set( this.tokenInfo.tokenObj, "status_" + setObj[ "marker" ], setObj.badge );
7717
+ //log( "have set 'status_" + setObj[ "marker" ] + "' to " + setObj.badge );
7636
7718
7637
7719
// If this character has not already been done, also change the character sheet.
7638
7720
if( ssa[ 0 ] !== "sheetDirect" && !dupChar && ( attrib != undefined ) && !(mook && attrib === "condition-Health" )) {
7721
+ //log("setting att. old is");
7639
7722
let attribute = Earthdawn.findOrMakeObj({ _type: 'attribute', _characterid: this.charID, name: attrib }, 0);
7723
+ //log(attribute);
7640
7724
if( attribute[ "current" ] != setObj.attrib )
7641
7725
Earthdawn.setWithWorker( attribute, "current", setObj.attrib );
7642
- //log( "set attrib " + setObj.attrib);
7643
7726
} // End update the attribute.
7644
7727
7645
7728
// See if any other menu items share this attribute, and if so, unset those.
@@ -7663,6 +7746,7 @@ Get these in pairs, char sheet attrib and token status, get them ORed, then figu
7663
7746
else if( code === "defensive" )
7664
7747
this.MarkerSet( [ "m", "aggressive", "u" ] );
7665
7748
} } // End tokeninfo type is "Token"
7749
+ //log("end MarkerSet");
7666
7750
} catch(err) { Earthdawn.errorLog( "ParseObj.MarkerSet() error caught: " + err, po ); }
7667
7751
} // End ParseObj.MarkerSet( ssa )
7668
7752
@@ -7783,15 +7867,15 @@ Get these in pairs, char sheet attrib and token status, get them ORed, then figu
7783
7867
case "newday": // Recovery tests and Karma reset. Some systems karma must be bought.
7784
7868
try {
7785
7869
let recov = Earthdawn.findOrMakeObj({ _type: 'attribute', _characterid: this.charID, name: "Recovery-Tests" });
7786
- let rt = (Earthdawn.parseInt2(recov.get( "max" )) || 2) + Earthdawn.parseInt2(Earthdawn. getAttrBN( this.charID, "Misc-NewDayRecoveryOffset", "0", true) );
7870
+ let rt = (Earthdawn.parseInt2(recov.get( "max" )) || 2) + Earthdawn.getAttrBN( this.charID, "Misc-NewDayRecoveryOffset", "0", true);
7787
7871
//log(rt);
7788
7872
Earthdawn.setWithWorker( recov, "current", rt.toString()); // set recovery tests available today to max.
7789
-
7790
- // if( state.Earthdawn.gED && state.Earthdawn.edition == "4" ) {
7791
7873
let karmaObj = Earthdawn.findOrMakeObj({ _type: 'attribute', _characterid: this.charID, name: "Karma" }, 0),
7792
- kparam = ( ssa.length > 2 ) ? Earthdawn.parseInt2( ssa[ 2 ] ) : Earthdawn.getAttrBN( this.charID, "Misc-KarmaRitual", "-1", true), // V3.19 and later karmaritual is passed.
7874
+ kparam = ( ssa.length > 2 ) ? ssa[ 2 ] : Earthdawn.getAttrBN( this.charID, "Misc-KarmaRitual", "-1"), // V3.19 and later karmaritual is passed.
7875
+ dpparam = ( ssa.length > 3 ) ? ssa[ 3 ] : Earthdawn.getAttrBN( this.charID, "Misc-DPRitual", "-1"),
7793
7876
add;
7794
- switch ( kparam ) {
7877
+
7878
+ switch ( Earthdawn.parseInt2( kparam )) {
7795
7879
case -1: // set karma to it's max value
7796
7880
add = karmaObj.get( "max" );
7797
7881
break;
@@ -7822,30 +7906,32 @@ Get these in pairs, char sheet attrib and token status, get them ORed, then figu
7822
7906
} break;
7823
7907
default : // We were passed the number of karma to add.
7824
7908
if( isNaN( kparam ) || ( kparam < 0))
7825
- this.chat( "ED.funcMisc.NewDay Warning, invalid parameter " + kparam + ".", Earthdawn.whoTo.player | Earthdawn.whoFrom.api | Earthdawn.whoFrom.apiWarning)
7909
+ this.chat( "ED.funcMisc.NewDay Warning, invalid karma parameter " + kparam + ".", Earthdawn.whoTo.player | Earthdawn.whoFrom.api | Earthdawn.whoFrom.apiWarning)
7826
7910
else
7827
7911
add = kparam;
7828
7912
};
7829
7913
let newKarma = Math.min( Earthdawn.parseInt2( karmaObj.get( "max" )), Earthdawn.parseInt2(karmaObj.get( "current" )) + Earthdawn.parseInt2( add ))
7830
- + Earthdawn.parseInt2(Earthdawn. getAttrBN( this.charID, "Misc-NewDayKarmaOffset", "0", true) );
7914
+ + Earthdawn.getAttrBN( this.charID, "Misc-NewDayKarmaOffset", "0", true);
7831
7915
Earthdawn.setWithWorker( karmaObj, "current", newKarma.toString());
7832
- this.chat( "New Day: Karma and Recovery tests reset.", this.WhoSendTo() | Earthdawn.whoFrom.character );
7833
- // } // Note: Don't set DP to max! that is not done on a mere new day.
7834
- // Note, we no longer need special code for older editions.
7835
- // else { // 1879, or ED edition other than 4th. Buy Karma.
7836
- // let newKarma = Earthdawn.getAttrBN( this.charID, "Karma_max", "0", true ) - Earthdawn.getAttrBN( this.charID, "Karma", "0", true );
7837
- // CDD ToDo This uses semi-obsolete code so needs to be rewritten once karma is moved to sheetworker, and hopefully the sheetworker will catch the karma changing.
7838
- /*
7839
- this.chat( Earthdawn.makeButton( "Buy Karma?", "!Earthdawn~ charID: " + this.charID + "~ Misc: Add: Karma: ?{How many Karma to buy|" + newKarma + "}"
7840
- + "~ Record: ?{Posting Date|" + today.getFullYear() + "-" + (today.getMonth() +1) + "-" + today.getDate()
7841
- + "}: : LP: ?{How many " + ( state.Earthdawn.gED ? "LP" : "AP" ) +" does that cost|" + newKarma * 10 + "}",
7842
- "Did you do a karma ritual and want to buy karma?", Earthdawn.Colors.param, Earthdawn.Colors.paramfg ),
7843
- Earthdawn.whoTo.player | Earthdawn.whoFrom.character | Earthdawn.whoFrom.noArchive );
7844
- */
7845
- // this.chat( "New Day: " + Earthdawn.makeButton( "Buy Karma?", "!Earthdawn~ charID: " + this.charID + "~ Misc: Add: Karma: ?{How many Karma to buy|" + newKarma + "}",
7846
- // "Did you do a karma ritual and want to buy karma?", Earthdawn.Colors.param, Earthdawn.Colors.paramfg ),
7847
- // Earthdawn.whoTo.player | Earthdawn.whoFrom.character | Earthdawn.whoFrom.noArchive );
7848
- // }
7916
+
7917
+ add = 0;
7918
+ switch ( Earthdawn.parseInt2( dpparam )) {
7919
+ case -1: // set Add questor tier to their current devotion pool
7920
+ add = Earthdawn.getAttrBN( this.charID, "IsQuestor", "0", true);
7921
+ break;
7922
+ default : // We were passed the number of karma to add.
7923
+ if( isNaN( dpparam ) || ( dpparam < 0))
7924
+ this.chat( "ED.funcMisc.NewDay Warning, invalid DP parameter " + dpparam + ".", Earthdawn.whoTo.player | Earthdawn.whoFrom.api | Earthdawn.whoFrom.apiWarning)
7925
+ else
7926
+ add = dpparam;
7927
+ };
7928
+ let added = "";
7929
+ if( add > 0 ) {
7930
+ let newDP = Math.min( Earthdawn.getAttrBN( this.charID, "DP_max", "0", true), Earthdawn.getAttrBN( this.charID, "DP", "0", true) + Earthdawn.parseInt2( add ));
7931
+ Earthdawn.setWithWorker( karmaObj, "current", newDP.toString());
7932
+ added = " " + add + " added to DP.";
7933
+ }
7934
+ this.chat( "New Day: Karma and Recovery tests reset." + added, this.WhoSendTo() | Earthdawn.whoFrom.character );
7849
7935
} catch(err) { Earthdawn.errorLog( "ED.funcMisc.NewDay error caught: " + err, po ); }
7850
7936
break;
7851
7937
case "resetchars": // reset all selected tokens to full health, karma, Recovery Tests, and no modifications or status markers.
@@ -8584,7 +8670,7 @@ log("Record Obsolete code. If you see this except on an 1879 sheet, please repor
8584
8670
else
8585
8671
po.edClass.countFail++;
8586
8672
if( po.misc[ "Special" ] === "Knockdown" ) {
8587
- // po.setWW( "condition-KnockedDown", "1" );
8673
+ // po.setWW( "condition-KnockedDown", "1" ); // MarkerSet does this now.
8588
8674
po.MarkerSet( ["r", "knocked", "s"] );
8589
8675
po.misc[ "endNoteFail" ]="Character Knocked Down";
8590
8676
}
@@ -8857,30 +8943,43 @@ log("Record Obsolete code. If you see this except on an 1879 sheet, please repor
8857
8943
whoString = "public";
8858
8944
Earthdawn.errorLog( "ED.rollFormat invalid recipents value: " + recipients, po );
8859
8945
}
8860
- let k, bis = 0,
8861
- lt = "!Earthdawn~ ChatMenu: RolltypeEdit: state.Earthdawn.Rolltype." + (bpc ? "PC" : "NPC" ) + ": ";
8862
- if( "exceptionIs" in this.misc ) {
8863
- k = this.misc[ "exceptionIs" ];
8864
- let e = bpc ? state.Earthdawn.Rolltype.PC.Exceptions : state.Earthdawn.Rolltype.NPC.Exceptions;
8865
- if( k in e ) {
8866
- bis |= 0x01;
8867
- lt += this.misc[ "exceptionIs" ] + ": "
8868
- +"?{Edit display exception for '" + this.misc[ "exceptionIs" ][ "name" ]
8869
- + "'|Never Mind, nothing|Change to Public, exceptionEdit: Public|Change to GM Only, exceptionEdit: GM Only"
8870
- + "| Change to Player and GM, exceptionEdit: Player and GM|Delete exception, exceptionDelete}"
8871
- } else
8872
- edParse.chat( "Warning! Earthdawn internal data mismatch in rollFormat. key '" + k+ "' not found in exceptions.", Earthdawn.whoFrom.apiError);
8873
- } else if ( "exceptionWouldBe" in this.misc ) {
8874
- bis |= 0x02;
8875
- lt += this.misc[ "exceptionWouldBe" ][ "name" ] + ":?{Create a display exception for '" + this.misc[ "exceptionWouldBe" ][ "name" ]
8876
- + "'|Never mind, nothing|Public, exceptionAdd: Public|GM Only, exceptionAdd: GM Only|Player and GM, exceptionAdd: Player and GM}";
8877
- }
8946
+ let k, bis = 0, lt;
8947
+ if(( "skillExceptionIs" in this.misc) || ( "skillExceptionWouldBe" in this.misc )) { // This is a knowledge or Artisan skill, which have special rolltype catagories. Send user to a special menu to ask which he wants. to set/edit.
8948
+ bis |= 0x04;
8949
+ lt = "!Earthdawn~ ChatMenu: RolltypeMulti: state.Earthdawn.Rolltype." + (bpc ? "PC" : "NPC" );
8950
+ if( "skillExceptionIs" in this.misc )
8951
+ lt += ": skillExceptionIs: " + this.misc[ "skillExceptionIs" ];
8952
+ if( "skillExceptionWouldBe" in this.misc )
8953
+ lt += ": skillExceptionWouldBe: " + this.misc[ "skillExceptionWouldBe" ];
8954
+ if( "exceptionIs" in this.misc )
8955
+ lt += ": exceptionIs: " + this.misc[ "exceptionIs" ];
8956
+ if( "exceptionWouldBe" in this.misc )
8957
+ lt += ": exceptionWouldBe: " + this.misc[ "exceptionWouldBe" ];
8958
+ } else { // only one possible exception (talent name), not two (skill class).
8959
+ lt = "!Earthdawn~ ChatMenu: RolltypeEdit: state.Earthdawn.Rolltype." + (bpc ? "PC" : "NPC" ) + ": ";
8960
+ if( "exceptionIs" in this.misc ) {
8961
+ k = this.misc[ "exceptionIs" ];
8962
+ let e = bpc ? state.Earthdawn.Rolltype.PC.Exceptions : state.Earthdawn.Rolltype.NPC.Exceptions;
8963
+ if( k in e ) {
8964
+ bis |= 0x01;
8965
+ lt += k + ": "
8966
+ +"?{Edit display exception for '" + k
8967
+ + "'|Change to Public, exceptionEdit: Public|Change to GM Only, exceptionEdit: GM Only"
8968
+ + "| Change to Player and GM, exceptionEdit: Player and GM|Delete exception, exceptionDelete}"
8969
+ } else
8970
+ edParse.chat( "Warning! Earthdawn internal data mismatch in rollFormat. key '" + k+ "' not found in exceptions.", Earthdawn.whoFrom.apiError);
8971
+ } else if ( "exceptionWouldBe" in this.misc ) {
8972
+ bis |= 0x02;
8973
+ lt += this.misc[ "exceptionWouldBe" ] + ":?{Create a display exception for '" + this.misc[ "exceptionWouldBe" ]
8974
+ + "'|Public, exceptionAdd: Public|GM Only, exceptionAdd: GM Only|Player and GM, exceptionAdd: Player and GM}";
8975
+ } }
8976
+ // cdd
8977
+ // test for knowledge and/or artisan, and add a dropdown to change for all of those instead of name.
8878
8978
if( bis )
8879
8979
sectMain.append( "span", Earthdawn.makeButton(
8880
8980
Earthdawn.addIcon( whoString, "small" ), lt,
8881
- "This message is being sent to '" + whoString + (( "whoReason" in this.misc) ? "' due to " + this.misc[ "whoReason" ] : ""),
8882
- "white" ),
8883
- { class: "sheet-rolltemplate-floatRight sheet-rolltemplate-RollTypeButton" });
8981
+ "This message is being sent to '" + whoString + (( "whoReason" in this.misc) ? "' due to " + this.misc[ "whoReason" ] : ""), "white" ),
8982
+ { class: "sheet-rolltemplate-floatRight sheet-rolltemplate-RollTypeButton" });
8884
8983
else if( state.Earthdawn.Rolltype.Override )
8885
8984
sectMain.append( "span", Earthdawn.makeButton( " ! ", "!Earthdawn~ ChatMenu: RolltypeEdit: state.Earthdawn.Rolltype: : Display",
8886
8985
"Override is on and being sent to '" + state.Earthdawn.Rolltype.Override + "'" ),
@@ -8890,7 +8989,6 @@ log("Record Obsolete code. If you see this except on an 1879 sheet, please repor
8890
8989
+ this.misc[ "reason" ] + ((bsub || !sh ) ? "" : " -- " + new HtmlBuilder( "span", sh, { class: "sheet-rolltemplate-subheadertext" })), // Main Header
8891
8990
{class : ("sheet-rolltemplate-header" + (("headcolor" in this.misc) ?
8892
8991
" sheet-rolltemplate-header-" + Earthdawn.safeString( this.misc[ "headcolor" ] ).toLowerCase() : "" )) }); // The headers give the right colored thick line at bottom.
8893
- // log(sectMain);
8894
8992
8895
8993
if( bsub ) // This is a subheader. If it was short enough it would have been appended to the main header.
8896
8994
sectMain.append("", sh, { class: "sheet-rolltemplate-subheadertext"});
@@ -9247,7 +9345,6 @@ log("Record Obsolete code. If you see this except on an 1879 sheet, please repor
9247
9345
bodyMain.append( (( ++linenum % 2) ? ".odd" : ".even"), this.misc[ "endNoteFail" ]);
9248
9346
if( playerCard ) playerCardNix.push( bodyMain._children.length );
9249
9347
}
9250
-
9251
9348
if(("cButtons" in this.misc) && this.misc[ "cButtons" ].length > 0) {
9252
9349
let tName;
9253
9350
for( let i = 0; i < this.misc[ "cButtons" ].length; ++i ) {
@@ -10727,8 +10824,8 @@ log("Record Obsolete code. If you see this except on an 1879 sheet, please repor
10727
10824
T_Strain_max is set by the sheetworker and is used in a ~Strain: @{T_STrain_max}. It is either equal to T_Strain or to a query with T_Strain as default
10728
10825
T_StrainAdvanced is a drop-down that right now is either "" (fixed strain) or "Ask". This will become much more complex in the future, especially for 1879.
10729
10826
T_StrainAdvanced_max is the formula to be displayed to the user
10730
- Example Strains from ED and 1879:
10731
- Strain: 6
10827
+ Example Strains from ED and 1879: (ones marked with * are currently supported. All others are not yet supported but will be in the future.
10828
+ * Strain: 6
10732
10829
Strain: 2 + target count
10733
10830
Strain: 4 + TMD
10734
10831
Strain: 4 + 1 per Spellcasting Test success
@@ -11536,23 +11633,36 @@ log("Record Obsolete code. If you see this except on an 1879 sheet, please repor
11536
11633
this.misc[ "whoReason" ] = "Token is on the GM layer.";
11537
11634
} else { // Token is not on gm layer. Check for exceptions, and then default.
11538
11635
let bpc = (Earthdawn.getAttrBN( this.charID, "NPC", "1") == Earthdawn.charType.pc);
11636
+ let except = bpc ? state.Earthdawn.Rolltype.PC.Exceptions : state.Earthdawn.Rolltype.NPC.Exceptions;
11539
11637
let rn; // first, lets see if we can find a rolltype or a reason to check.
11638
+ if( "skillClass" in this.misc ) { // check skill class first, but if there is a named exception, this class exception will be overriden.
11639
+ let rnc = Earthdawn.matchString( this.misc[ "skillClass" ] ); // striped and lowercased
11640
+ if( rnc in except ) {
11641
+ rt = except[ rnc ][ "display" ];
11642
+ this.misc[ "skillExceptionIs" ] = rnc;
11643
+ this.misc[ "whoReason" ] = "an exception for " + this.misc[ "skillClass" ] + " skills.";
11644
+ } else
11645
+ this.misc[ "skillExceptionWouldBe" ] = this.misc[ "skillClass" ];
11646
+ }
11540
11647
if( "rollName" in this.misc )
11541
11648
rn = this.misc[ "rollName" ];
11542
11649
else if( "reason" in this.misc ) // Note that right now we are testing all reasons. We might have to narrow it down.
11543
11650
rn = this.misc[ "reason" ];
11544
11651
if( rn ) {
11545
11652
let rnc = Earthdawn.matchString( rn ); // striped and lowercased
11546
- let except = bpc ? state.Earthdawn.Rolltype.PC.Exceptions : state.Earthdawn.Rolltype.NPC.Exceptions;
11547
11653
if( rnc in except ) {
11548
- rt = except [ rnc ][ "display" ];
11654
+ rt = except[ rnc ][ "display" ];
11549
11655
this.misc[ "exceptionIs" ] = rnc;
11550
11656
this.misc[ "whoReason" ] = "an exception for this name.";
11551
- } else { // no exception, use the default.
11552
- rt = bpc ? state.Earthdawn.Rolltype.PC.Default : state.Earthdawn.Rolltype.NPC.Default
11553
- this.misc[ "exceptionWouldBe" ] = { key: rnc, name: rn }
11554
- this.misc[ "whoReason" ] = "Default for " + (bpc ? "PCs." : "NPCs.");
11555
- } } } // end exceptions or default.
11657
+ } else // no exception, use the default.
11658
+ this.misc[ "exceptionWouldBe" ] = rn;
11659
+ }
11660
+ //cdd
11661
+ if( rt === undefined ) {
11662
+ rt = bpc ? state.Earthdawn.Rolltype.PC.Default : state.Earthdawn.Rolltype.NPC.Default
11663
+ this.misc[ "whoReason" ] = "Default for " + (bpc ? "PCs." : "NPCs.");
11664
+ }
11665
+ } // end exceptions or default.
11556
11666
} else if( state.Earthdawn.Rolltype.Override === "Sheet" ) { // use the old system where things are controled on a per talent basis by the player.
11557
11667
if( "RollType" in this.misc ) // Option was "Ask" and we got an rolltype that way.
11558
11668
rt = this.misc[ "RollType"]; // ?{Who should be able to see the results|Public, |Player & GM,pgm|GM Only,/w gm}
@@ -11579,7 +11689,7 @@ log("Record Obsolete code. If you see this except on an 1879 sheet, please repor
11579
11689
ret = Earthdawn.whoTo.gm;
11580
11690
else if(( r === "controlling only") || r.endsWith("plr" ))
11581
11691
ret = Earthdawn.whoTo.player;
11582
- } }
11692
+ } }
11583
11693
} catch(err) { Earthdawn.errorLog( "ED.WhoSendTo() error caught: " + err, this ); }
11584
11694
return ret;
11585
11695
} // End ParseObj.WhoSendTo()
0 commit comments