diff --git a/ADnD_2E_Revised/2ESheet.html b/ADnD_2E_Revised/2ESheet.html
index 75408cb1fe..7e22a80b36 100644
--- a/ADnD_2E_Revised/2ESheet.html
+++ b/ADnD_2E_Revised/2ESheet.html
@@ -2054,12 +2054,10 @@
|
-
+
-
-
Special Abilities and Attacks
@@ -2207,6 +2205,9 @@
Damage L |
Knockdown |
Amount |
+ Size |
+ Type |
+ Crit II |
| Spec |
@@ -2214,62 +2215,72 @@
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
-
+
@@ -18299,6 +18310,12 @@
Weapons, Spells, and Proficiencies |
|
+
+ | Player's Option: Combat & Tactics |
+ 1995 June |
+ Weapons, Proficiencies, Talents, and Disadvantages |
+ |
+
Optional rules for spells
@@ -20658,7 +20675,7 @@
-
+
@@ -20705,8 +20722,8 @@
-
-
+
+
@@ -48957,7 +48974,7 @@ const BOOK_FIELDS = [
'book-tom', 'book-aaeg',
'book-dwarves', 'book-bards', 'book-elves', 'book-humanoids', 'book-rangers',
'book-paladins', 'book-druids', 'book-barbarians', 'book-necromancers', 'book-ninjas',
- 'book-combat-and-tacticss',
+ 'book-combat-and-tactics',
];
const SCHOOL_FIELDS = ['school-spells-and-magic'];
@@ -49018,6 +49035,10 @@ const displayWeaponType = function (type) {
}
}
+const getRowId = function (triggerName) {
+ return triggerName.match(/repeating_[^_]+_([^_]+)_[^_]+/)[1];
+}
+
const conditionalLog = function (bool, msg) {
if (bool)
console.log(msg);
@@ -49026,12 +49047,14 @@ const conditionalLog = function (bool, msg) {
const extractQueryResult = async function(query){//Sends a message to query the user for some behavior, returns the selected option.
let queryRoll = await startRoll(`!{{query=[[0[response=${query}]]]}}`);
finishRoll(queryRoll.rollId);
+ console.log(queryRoll);
return queryRoll.results.query.expression.replace(/^.+?response=|\]$/g,'');
};
const extractRoll = async function(rollExpression) {
let queryRoll = await startRoll(`!{{roll=[[${rollExpression}]]}}`);
finishRoll(queryRoll.rollId);
+ console.log(queryRoll);
return queryRoll.results.roll;
};
@@ -49118,8 +49141,8 @@ const getActiveSettings = function (settingFields, values) {
const isBookInactive = function (books, obj) {
let activeBooks = getActiveSettings(BOOK_FIELDS, books);
- if (Array.isArray(obj['book']))
- return !obj['book'].some(b => activeBooks.has(b));
+ if (Array.isArray(obj))
+ return obj.every(b => !activeBooks.has(b));
else
return !activeBooks.has(obj['book']);
}
@@ -49127,9 +49150,9 @@ const isBookInactive = function (books, obj) {
const bookInactiveShowToast = function(books, obj) {
let bookInactive = isBookInactive(books, obj);
if (bookInactive) {
- if (Array.isArray(obj['book'])) {
- let booksString = obj['book'].map(b => '\n* ' + b).join('') + '\n'
- showToast(ERROR, 'Missing Book(s)', `The book(s) ${booksString} are currently not active on your sheet.\nGo to the *Sheet Settings* and activate any of the listed book(s) (if your DM allows for its usage)`);
+ if (Array.isArray(obj)) {
+ let booksString = obj.map(b => '\n* ' + b).join('')
+ showToast(ERROR, 'Missing Book(s)', `The book(s):${booksString}\nAre currently not active on your sheet.\nGo to the *Sheet Settings* and activate any of the listed book(s) (if your DM allows for its usage)`);
} else {
showToast(ERROR, 'Missing Book', `The book *${obj['book']}* is currently not active on your sheet.\nGo to the *Sheet Settings* and activate the book (if your DM allows for its usage)`);
}
@@ -50163,64 +50186,72 @@ on('change:thac0-base-calc', function(eventInfo) {
});
//#region Weapons autofill
-function setWeaponWithBonus(weaponName, setWeaponFunc, thac0Field) {
+const PLAYERS_OPTIONS_FIELD = 'tab81';
+function setWeaponWithBonus(weaponName, setWeaponFunc, comparer, thac0Field, category) {
if (!weaponName)
return;
weaponName = weaponName.toLowerCase();
- let fields = [...BOOK_FIELDS, thac0Field].filter(Boolean);
- getAttrs(fields, function(values) {
+ let fields = [...BOOK_FIELDS, PLAYERS_OPTIONS_FIELD, thac0Field].filter(Boolean);
+ getAttrs(fields, async function (values) {
+ let bonus = 0;
+ let baseWeapons = WEAPONS_TABLE[weaponName]
+ if (!baseWeapons) {
+ let match = weaponName.match(/\s*\+([0-9]+)\s*/);
+ if (!match)
+ return;
+
+ let baseWeaponName = weaponName.replace(match[0], ' ').trim();
+ baseWeapons = WEAPONS_TABLE[baseWeaponName];
+ if (!baseWeapons)
+ return;
+
+ bonus = parseInt(match[1]);
+ if (isNaN(bonus))
+ return;
+ }
+ if (category)
+ baseWeapons = baseWeapons.filter(w => w['category'].includes(category));
+
+ let activeBooks = getActiveSettings(BOOK_FIELDS, values);
+ let activeWeapons = baseWeapons.filter(w => w['book'].some(b => activeBooks.has(b)));
+
+
+ if (activeWeapons.length === 0) {
+ let booksString = baseWeapons.flatMap(w => w['book']).map(b => '\n* ' + b).join('')
+ showToast(ERROR, 'Missing Book(s)', `The book(s):${booksString}\nAre currently not active on your sheet.\nGo to the *Sheet Settings* and activate any of the listed book(s) (if your DM allows for its usage)`);
+ return;
+ }
+
+ let baseWeapon;
+ let isPlayersOptions = values[PLAYERS_OPTIONS_FIELD] === '2';
+ let isAllEqual = activeWeapons.every(w => comparer(w, activeWeapons[0], isPlayersOptions));
+ if (isAllEqual) {
+ baseWeapon = activeWeapons[0];
+ } else {
+ let options = activeWeapons
+ .map((w, i) => `${w.book.join('/')},${i}`)
+ .join('|');
+ let answer = await extractRollResult(`?{Multiple versions of this weapon exists. Please select a version|${options}}`);
+ baseWeapon = activeWeapons[answer];
+ }
+
let thac0 = parseInt(values[thac0Field]);
thac0 = isNaN(thac0) ? 20 : thac0;
- let baseWeapon = weapons[weaponName]
- if (baseWeapon) {
- if (bookInactiveShowToast(values, baseWeapon))
- return;
-
- setWeaponFunc({
- ...baseWeapon,
- 'thac0' : thac0,
- 'bonus' : '0'
- });
- return;
- }
-
- let match = weaponName.match(/\s*\+([0-9]+)\s*/);
- if (!match)
- return;
-
- let baseWeaponName = weaponName.replace(match[0], ' ').trim();
- baseWeapon = weapons[baseWeaponName];
- if (!baseWeapon)
- return;
-
- if (bookInactiveShowToast(values, baseWeapon))
- return;
-
- let bonusString = match[1];
- let bonus = parseInt(bonusString)
- if (isNaN(bonus))
- return;
-
- if (bonus < 1) {
- setWeaponFunc({
- ...baseWeapon,
- 'thac0' : thac0,
- 'bonus' : '0',
- 'bonusInt': 0
- });
- return;
- }
-
- let weaponWithBonus = {
+ let weapon = {
...baseWeapon,
'thac0' : thac0,
- 'speed' : Math.max(baseWeapon['speed'] - bonus, 0),
- 'bonus' : `+${bonus}`,
- 'bonusInt': bonus
+ };
+ if (bonus < 1) {
+ weapon['bonus'] = '0';
+ weapon['bonusInt'] = 0;
+ } else {
+ weapon['bonus'] = `+${bonus}`;
+ weapon['bonusInt'] = bonus;
+ weapon['speed'] = Math.max(weapon['speed'] - bonus, 0)
}
- setWeaponFunc(weaponWithBonus);
+ setWeaponFunc(weapon);
});
}
@@ -50232,21 +50263,21 @@ on('change:repeating_weapons:weaponname', function(eventInfo) {
compareFields.push('reach');
return compareFields.every(f => weapon1[f] === weapon2[f])
}
+ let rowId = getRowId(eventInfo.triggerName);
let setWeaponFunc = function (weapon) {
- let weaponInfo = {
- 'repeating_weapons_attackadj' : weapon['bonus'],
- 'repeating_weapons_ThAC0' : weapon['thac0'],
- 'repeating_weapons_range' : weapon['reach'] || 'Melee',
- 'repeating_weapons_size' : weapon['size'],
- 'repeating_weapons_weapspeed' : weapon['speed'],
- 'repeating_weapons_weaptype-slash' : weapon['type'].includes('S') ? 1 : 0,
- 'repeating_weapons_weaptype-pierce': weapon['type'].includes('P') ? 1 : 0,
- 'repeating_weapons_weaptype-blunt' : weapon['type'].includes('B') ? 1 : 0,
- };
+ let weaponInfo = {};
+ weaponInfo[`repeating_weapons_${rowId}_attackadj`] = weapon['bonus'];
+ weaponInfo[`repeating_weapons_${rowId}_ThAC0`] = weapon['thac0'];
+ weaponInfo[`repeating_weapons_${rowId}_range`] = weapon['reach'] || 'Melee';
+ weaponInfo[`repeating_weapons_${rowId}_size`] = weapon['size'];
+ weaponInfo[`repeating_weapons_${rowId}_weapspeed`] = weapon['speed'];
+ weaponInfo[`repeating_weapons_${rowId}_weaptype-slash`] = weapon['type'].includes('S') ? 1 : 0;
+ weaponInfo[`repeating_weapons_${rowId}_weaptype-pierce`] = weapon['type'].includes('P') ? 1 : 0;
+ weaponInfo[`repeating_weapons_${rowId}_weaptype-blunt`] = weapon['type'].includes('B') ? 1 : 0;
setAttrs(weaponInfo);
};
- setWeaponWithBonus(eventInfo.newValue, comparer, setWeaponFunc, 'thac0-base-calc');
+ setWeaponWithBonus(eventInfo.newValue, setWeaponFunc, comparer, 'thac0-base-calc', 'Melee');
});
//melee damage autofill
@@ -50255,25 +50286,25 @@ on('change:repeating_weapons-damage:weaponname1', function(eventInfo) {
let fisk = ['small-medium','large'];
if (isPlayersOption) {
fisk.push('size');
- fisk.push('type')
+ fisk.push('type');
fisk.push('knockdown');
}
return fisk.every(f => weapon1[f] === weapon2[f])
}
+ let rowId = getRowId(eventInfo.triggerName);
let setWeaponFunc = function (weapon) {
- let weaponInfo = {
- 'repeating_weapons-damage_damadj' : weapon['bonus'],
- 'repeating_weapons-damage_damsm' : weapon['small-medium'],
- 'repeating_weapons-damage_daml' : weapon['large'],
- 'repeating_weapons-damage_damsize' : weapon['size'],
- 'repeating_weapons-damage_damtype' : weapon['type'],
- 'repeating_weapons-damage_knockdown1' : weapon['knockdown'] || ''
- };
+ let weaponInfo = {};
+ weaponInfo[`repeating_weapons-damage_${rowId}_damadj`] = weapon['bonus'];
+ weaponInfo[`repeating_weapons-damage_${rowId}_damsm`] = weapon['small-medium'];
+ weaponInfo[`repeating_weapons-damage_${rowId}_daml`] = weapon['large'];
+ weaponInfo[`repeating_weapons-damage_${rowId}_knockdown1`] = weapon['knockdown'] || '';
+ weaponInfo[`repeating_weapons-damage_${rowId}_size`] = weapon['size'];
+ weaponInfo[`repeating_weapons-damage_${rowId}_type`] = weapon['type'];
setAttrs(weaponInfo);
};
- setWeaponWithBonus(eventInfo.newValue, setWeaponFunc);
+ setWeaponWithBonus(eventInfo.newValue, setWeaponFunc, comparer, '', 'Melee');
});
//range hit autofill
@@ -50281,71 +50312,86 @@ on('change:repeating_weapons2:weaponname2', function(eventInfo) {
let comparer = function (weapon1, weapon2, isPlayersOption) {
return ['strength','rof','range','size','speed','type'].every(f => weapon1[f] === weapon2[f])
}
+ let rowId = getRowId(eventInfo.triggerName);
let setWeaponFunc = function (weapon) {
- let weaponInfo = {
- 'repeating_weapons2_strbonus2' : weapon['strength'] ? 1 : 0,
- 'repeating_weapons2_attacknum2' : weapon['rof'] || '',
- 'repeating_weapons2_attackadj2' : weapon['bonus'],
- 'repeating_weapons2_ThAC02' : weapon['thac0'],
- 'repeating_weapons2_range2' : weapon['range'] || '',
- 'repeating_weapons2_size2' : weapon['size'],
- 'repeating_weapons2_weapspeed2' : weapon['speed'],
- 'repeating_weapons2_weaptype-slash2' : weapon['type'].includes('S') ? 1 : 0,
- 'repeating_weapons2_weaptype-pierce2' : weapon['type'].includes('P') ? 1 : 0,
- 'repeating_weapons2_weaptype-blunt2' : weapon['type'].includes('B') ? 1 : 0,
- };
+ let weaponInfo = {};
+ weaponInfo[`repeating_weapons2_${rowId}_strbonus2`] = weapon['strength'] ? 1 : 0;
+ weaponInfo[`repeating_weapons2_${rowId}_attacknum2`] = weapon['rof'] || '';
+ weaponInfo[`repeating_weapons2_${rowId}_attackadj2`] = weapon['bonus'];
+ weaponInfo[`repeating_weapons2_${rowId}_ThAC02`] = weapon['thac0'];
+ weaponInfo[`repeating_weapons2_${rowId}_range2`] = weapon['range'] || '';
+ weaponInfo[`repeating_weapons2_${rowId}_size2`] = weapon['size'];
+ weaponInfo[`repeating_weapons2_${rowId}_weapspeed2`] = weapon['speed'];
+ weaponInfo[`repeating_weapons2_${rowId}_weaptype-slash2`] = weapon['type'].includes('S') ? 1 : 0;
+ weaponInfo[`repeating_weapons2_${rowId}_weaptype-pierce2`] = weapon['type'].includes('P') ? 1 : 0;
+ weaponInfo[`repeating_weapons2_${rowId}_weaptype-blunt2`] = weapon['type'].includes('B') ? 1 : 0;
setAttrs(weaponInfo);
};
- setWeaponWithBonus(eventInfo.newValue, setWeaponFunc, 'thac0-base-calc');
+ setWeaponWithBonus(eventInfo.newValue, setWeaponFunc, comparer, 'thac0-base-calc', 'Range');
});
//range damage autofill
on('change:repeating_ammo:ammoname', function(eventInfo) {
- let comparer = function (weapon1, weapon2) {
- return ['strength','small-medium','large','size'].every(f => weapon1[f] === weapon2[f])
+ let comparer = function (weapon1, weapon2, isPlayersOption) {
+ let comparerFields = ['strength','small-medium','large'];
+ if (isPlayersOption) {
+ comparerFields.push('knockdown');
+ comparerFields.push('size');
+ comparerFields.push('ammo-size');
+ comparerFields.push('type');
+ }
+ return comparerFields.every(f => weapon1[f] === weapon2[f])
}
+ let rowId = getRowId(eventInfo.triggerName);
let setWeaponFunc = function (weapon) {
- let weaponInfo = {
- 'repeating_weapons2_strbonus3' : weapon['strength'] ? 1 : 0,
- 'repeating_ammo_damadj2' : weapon['bonus'],
- 'repeating_ammo_damsm2' : weapon['small-medium'],
- 'repeating_ammo_daml2' : weapon['large'],
- 'repeating_weapons-damage_knockdown2' : weapon['knockdown'] || ''
- };
+ let weaponInfo = {};
+ weaponInfo[`repeating_ammo_${rowId}_strbonus3`] = weapon['strength'] ? 1 : 0;
+ weaponInfo[`repeating_ammo_${rowId}_damadj2`] = weapon['bonus'];
+ weaponInfo[`repeating_ammo_${rowId}_damsm2`] = weapon['small-medium'];
+ weaponInfo[`repeating_ammo_${rowId}_daml2`] = weapon['large'];
+ weaponInfo[`repeating_ammo_${rowId}_knockdown2`] = weapon['knockdown'] || '';
+ weaponInfo[`repeating_ammo_${rowId}_size`] = weapon['ammo-size'] || weapon['size'];
+ weaponInfo[`repeating_ammo_${rowId}_type`] = weapon['type'];
setAttrs(weaponInfo);
}
- setWeaponWithBonus(eventInfo.newValue, setWeaponFunc);
+ setWeaponWithBonus(eventInfo.newValue, setWeaponFunc, comparer, '', 'Range');
});
//Follower weapons
function setupFollowerWeaponsAutoFill(repeating, sections) {
let prefix = '';
- let onChange = '';
if (repeating !== '') {
- prefix = `repeating_${repeating}_`
- onChange = `repeating_${repeating}:`
+ prefix = `repeating_${repeating}`
}
sections.forEach(section => {
- on(`change:${onChange}weaponnamehench${section}`, function(eventInfo) {
+ on(`change:${prefix}:weaponnamehench${section}`, function(eventInfo) {
+ let comparer = function (weapon1, weapon2, isPlayersOption) {
+ let comparerFields = ['rof','small-medium','large','range','type','speed'];
+ if (isPlayersOption) {
+ comparerFields.push('reach');
+ comparerFields.push('knockdown');
+ }
+ return comparerFields.every(f => weapon1[f] === weapon2[f])
+ }
+ let rowId = getRowId(eventInfo.triggerName);
let setWeaponFunc = function (weapon) {
- let weaponInfo = {
- [`${prefix}attacknumhench${section}`]: weapon['rof'] || '1',
- [`${prefix}attackadjhench${section}`]: weapon['bonus'],
- [`${prefix}damadjhench${section}`]: weapon['bonus'],
- [`${prefix}damsmhench${section}`]: weapon['small-medium'],
- [`${prefix}damlhench${section}`]: weapon['large'],
- [`${prefix}rangehench${section}`]: weapon['range'] || weapon['reach'] || 'Melee',
- [`${prefix}weaptypehench${section}`]: weapon['type'],
- [`${prefix}weapspeedhench${section}`]: weapon['speed'],
- };
+ let weaponInfo = {};
+ weaponInfo[`${prefix}_${rowId}_attacknumhench${section}`] = weapon['rof'] || '1';
+ weaponInfo[`${prefix}_${rowId}_attackadjhench${section}`] = weapon['bonus'];
+ weaponInfo[`${prefix}_${rowId}_damadjhench${section}`] = weapon['bonus'];
+ weaponInfo[`${prefix}_${rowId}_damsmhench${section}`] = weapon['small-medium'];
+ weaponInfo[`${prefix}_${rowId}_damlhench${section}`] = weapon['large'];
+ weaponInfo[`${prefix}_${rowId}_rangehench${section}`] = weapon['range'] || weapon['reach'] || 'Melee';
+ weaponInfo[`${prefix}_${rowId}_weaptypehench${section}`] = weapon['type'];
+ weaponInfo[`${prefix}_${rowId}_weapspeedhench${section}`] = weapon['speed'];
setAttrs(weaponInfo);
};
- setWeaponWithBonus(eventInfo.newValue, setWeaponFunc);
+ setWeaponWithBonus(eventInfo.newValue, setWeaponFunc, comparer);
});
});
}
@@ -50445,105 +50491,97 @@ on('clicked:grenade-miss', async function (eventInfo) {
});
});
-on('clicked:crit-melee', function(eventInfo) {
- TAS.repeating('weapons-damage')
- .attrs(['strengthdmg', 'dexmissile', 'temp-damadj', 'misc-mod', ...BOOK_FIELDS])
- .fields('strbonus1', 'dexbonus1', 'weaponname1', 'specialist-damage', 'mastery-damage', 'damadj', 'damsm', 'daml')
- .map(function (row){
- return row;
- }, async function (rows, _, attrSet){
- let weaponSelect = rows.map(r => `${r['weaponname1']},${r.id}`)
+on('clicked:repeating_weapons-damage:crit2-melee', function(eventInfo) {
+ console.log(eventInfo);
+ let fields = [
+ 'strengthdmg', 'dexmissile', 'temp-damadj', 'misc-mod',
+ 'repeating_weapons-damage_strbonus1','repeating_weapons-damage_dexbonus1','repeating_weapons-damage_weaponname1',
+ 'repeating_weapons-damage_specialist-damage','repeating_weapons-damage_mastery-damage','repeating_weapons-damage_damadj',
+ 'repeating_weapons-damage_damsm','repeating_weapons-damage_daml','repeating_weapons-damage_size','repeating_weapons-damage_type'];
+ getAttrs(fields, async function (values) {
+ let finalRollText = `&{template:2Edefault} {{name=Test Critical hit}} {{Weapon name=${values['repeating_weapons-damage_weaponname1']}}} `;
+
+ let attackType = await extractQueryResult('?{How are you attacking?|Regular Attack|Low Attack|High Attack}');
+ let targetType = await extractQueryResult('?{What are you attacking?|Humanoid|Animal|Monster}');
+ let targetSize = await extractQueryResult('?{Target size?|Tiny|Small|Medium|Large|Huge|Gargantuan}');
+
+ let weaponSize = displaySize(values['repeating_weapons-damage_size']);
+ let weaponType = values['repeating_weapons-damage_type'];
+ if (weaponType.includes('/')) {
+ let displayTypes = weaponType.split('/')
+ .map(s => displayWeaponType(s))
.join('|');
- let rowId = await extractQueryResult(`?{What weapon did you use?|${weaponSelect}}`);
- let row = rows.find(row => row.id === rowId);
- let finalRollText = '&{template:2Edefault} {{name=Test Critical hit}}';
+ weaponType = await extractQueryResult(`?{How are your attack with your weapon?|${displayTypes}}`)
+ } else {
+ weaponType = displayWeaponType(weaponType);
+ }
- let attackType = await extractQueryResult('?{How are you attacking?|Regular Attack|Low Attack|High Attack}');
- let targetType = await extractQueryResult('?{What are you attacking?|Humanoid|Animal|Monster}');
- let targetSize = await extractQueryResult('?{Target size?|Tiny|Small|Medium|Large|Huge|Gargantuan}');
+ finalRollText += `{{Weapon type=${attackType}}} `;
+ finalRollText += `{{Weapon size=${weaponSize}}} `;
+ finalRollText += `{{Target type=${targetType}}} `;
+ finalRollText += `{{Target size=${targetSize}}} `;
- let baseWeapon = getBaseWeapon(row['weaponname1'], attrSet);
- let weaponSize;
- let weaponType;
- if (baseWeapon) {
- weaponSize = displaySize(baseWeapon['size']);
- weaponType = baseWeapon['type'];
- if (weaponType.includes('/')) {
- let displayTypes = weaponType.split('/')
- .map(s => displayWeaponType(s))
- .join('|');
+ let locationDice;
+ switch (attackType) {
+ case 'Regular Attack': locationDice = '1d10'; break;
+ case 'Low Attack': locationDice = '1d6'; break;
+ case 'High Attack': locationDice = '1d6+4'; break;
+ }
+ let locationRoll = await extractRollResult(locationDice);
+ let locationObject = LOCATION_TABLE[targetType][locationRoll];
- weaponType = await extractQueryResult(`?{How are your attack with your weapon?|${displayTypes}}`)
- } else {
- weaponType = displayWeaponType(weaponType);
- }
- } else {
- weaponSize = await extractQueryResult('?{Weapon size?|Small|Medium|Large}');
- weaponType = await extractQueryResult('?{Weapon type?|Slashing|Piercing|Bludgeoning}')
- }
+ let severityEffect;
+ let severityRoll;
+ const sizeDiff = sizeToInt(weaponSize) - sizeToInt(targetSize);
+ if (sizeDiff < 0) {
+ severityEffect = 'Minor';
+ severityRoll = await extractRollResult('1d6');
+ } else if (sizeDiff === 0) {
+ severityEffect = 'Major';
+ severityRoll = await extractRollResult('2d4');
+ } else if (sizeDiff === 1) {
+ severityEffect = 'Severe';
+ severityRoll = await extractRollResult('2d6');
+ } else if (sizeDiff > 1) {
+ severityEffect = 'Mortal';
+ severityRoll = await extractRollResult('2d8');
+ }
- finalRollText += `{{Weapon name=${row['weaponname1']}}} `;
- finalRollText += `{{Weapon type=${attackType}}} `;
- finalRollText += `{{Weapon size=${weaponSize}}} `;
- finalRollText += `{{Target type=${targetType}}} `;
- finalRollText += `{{Target size=${targetSize}}} `;
+ finalRollText += `{{Severity effect=${severityEffect}}} `;
+ finalRollText += `{{Severity roll=${severityRoll}}} `;
- let locationDice;
- switch (attackType) {
- case 'Regular Attack': locationDice = '1d10'; break;
- case 'Low Attack': locationDice = '1d6'; break;
- case 'High Attack': locationDice = '1d6+4'; break;
- }
- let locationResult = await extractRollResult(locationDice);
- let location = LOCATION_TABLE[targetType][locationResult];
+ let weaponDamage = sizeToInt(targetSize) < 3 ? values['repeating_weapons-damage_damsm'] : values['repeating_weapons-damage_daml'];
+ if (weaponDamage.match('/\d/'))
+ if (severityRoll > 12) {
+ finalRollText += `{{Critical damage=[[(${weaponDamage})*3]]}} `;
+ severityRoll = 12;
+ } else {
+ finalRollText += `{{Critical damage=[[(${weaponDamage})*2]]}} `;
+ }
+ finalRollText += `{{Location roll=[[${locationRoll}]]}} `;
+ if (locationObject)
+ finalRollText += `{{Location hit=${locationObject['hitLocation']}}} `;
- const sizeDiff = sizeToInt(weaponSize) - sizeToInt(targetSize);
- let severityEffect;
- let severityResult;
- if (sizeDiff < 0) {
- severityEffect = 'Minor';
- severityResult = await extractRollResult('1d6');
- } else if (sizeDiff === 0) {
- severityEffect = 'Major';
- severityResult = await extractRollResult('2d4');
- } else if (sizeDiff === 1) {
- severityEffect = 'Severe';
- severityResult = await extractRollResult('2d6');
- } else if (sizeDiff > 1) {
- severityEffect = 'Mortal';
- severityResult = await extractRollResult('2d8');
- }
+ let critEffect;
+ if (severityRoll < 4) {
+ critEffect = 'No unusual effect'
+ } else if (CRIT_EFFECT_TABLE[weaponType]) {
+ critEffect = CRIT_EFFECT_TABLE[weaponType][targetType][locationObject['location'][severityRoll]];
+ } else {
+ critEffect = 'No unusual effect';
+ }
- finalRollText += `{{Severity effect=${severityEffect}}} `;
- finalRollText += `{{Severity roll=${severityResult}}} `;
+ finalRollText += `{{Critical effect=${critEffect}}}`;
+ console.log(finalRollText);
- let weaponDamage = sizeToInt(targetSize) < 3 ? row['damsm'] : row['daml'];
- if (severityResult > 12) {
- finalRollText += `{{Critical damage=[[(${weaponDamage})*3]]}} `;
- severityResult = 12;
- } else {
- finalRollText += `{{Critical damage=[[(${weaponDamage})*2]]}} `;
- }
-
- finalRollText += `{{Location roll=[[${locationResult}]]}} `;
- finalRollText += `{{Location hit=${location['hitLocation']}}} `;
-
- let critEffect = severityResult < 4
- ? 'No unusual effect'
- : CRIT_EFFECT_TABLE[weaponType][targetType][location['location']][severityResult];
- finalRollText += `{{Critical effect=${critEffect}}}`;
- console.log(finalRollText)
-
- startRoll(finalRollText, function (roll) {
- console.log(roll);
- let computedRolls = {};
- finishRoll(roll.rollId, computedRolls);
- });
-
- })
- .execute();
+ startRoll(finalRollText, function (roll) {
+ console.log(roll);
+ let computedRolls = {};
+ finishRoll(roll.rollId, computedRolls);
+ });
+ });
});
//#endregion
diff --git a/ADnD_2E_Revised/2EStyle.css b/ADnD_2E_Revised/2EStyle.css
index af2f0ea419..d9f999b131 100644
--- a/ADnD_2E_Revised/2EStyle.css
+++ b/ADnD_2E_Revised/2EStyle.css
@@ -1701,7 +1701,7 @@ img.expandable:hover {
.sheet-toast textarea {
border: 0;
background-color: transparent;
- pointer-events: none;
+ cursor: text;
margin-bottom: 0;
resize: none;
}
diff --git a/ADnD_2E_Revised/css/toast.css b/ADnD_2E_Revised/css/toast.css
index 5a3d533f59..bdd14d387e 100644
--- a/ADnD_2E_Revised/css/toast.css
+++ b/ADnD_2E_Revised/css/toast.css
@@ -48,7 +48,7 @@
.sheet-toast textarea {
border: 0;
background-color: transparent;
- pointer-events: none;
+ cursor: text;
margin-bottom: 0;
resize: none;
}
diff --git a/ADnD_2E_Revised/html/components/dynamicDatalists.html b/ADnD_2E_Revised/html/components/dynamicDatalists.html
index 697c6b0296..3898e82eba 100644
--- a/ADnD_2E_Revised/html/components/dynamicDatalists.html
+++ b/ADnD_2E_Revised/html/components/dynamicDatalists.html
@@ -2029,7 +2029,7 @@
-
+
@@ -2076,8 +2076,8 @@
-
-
+
+
diff --git a/ADnD_2E_Revised/html/tabs/character-tab/weapons-tab/players-option-weapons-tab.html b/ADnD_2E_Revised/html/tabs/character-tab/weapons-tab/players-option-weapons-tab.html
index 847d021604..6a37b79d08 100644
--- a/ADnD_2E_Revised/html/tabs/character-tab/weapons-tab/players-option-weapons-tab.html
+++ b/ADnD_2E_Revised/html/tabs/character-tab/weapons-tab/players-option-weapons-tab.html
@@ -178,12 +178,10 @@
|
-
+
-
-
Special Abilities and Attacks
@@ -331,6 +329,9 @@
Damage L |
Knockdown |
Amount |
+ Size |
+ Type |
+ Crit II |
| Spec |
@@ -338,62 +339,72 @@
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
-
+
diff --git a/ADnD_2E_Revised/html/tabs/sheet-settings.html b/ADnD_2E_Revised/html/tabs/sheet-settings.html
index 49cfe23eb6..b49c700754 100644
--- a/ADnD_2E_Revised/html/tabs/sheet-settings.html
+++ b/ADnD_2E_Revised/html/tabs/sheet-settings.html
@@ -114,6 +114,12 @@
Weapons, Spells, and Proficiencies |
|
+
+ | Player's Option: Combat & Tactics |
+ 1995 June |
+ Weapons, Proficiencies, Talents, and Disadvantages |
+ |
+
Optional rules for spells
diff --git a/ADnD_2E_Revised/javascript/sheetWorkers.js b/ADnD_2E_Revised/javascript/sheetWorkers.js
index 23aeba81cd..7383fcb9cc 100644
--- a/ADnD_2E_Revised/javascript/sheetWorkers.js
+++ b/ADnD_2E_Revised/javascript/sheetWorkers.js
@@ -9,7 +9,7 @@ const BOOK_FIELDS = [
'book-tom', 'book-aaeg',
'book-dwarves', 'book-bards', 'book-elves', 'book-humanoids', 'book-rangers',
'book-paladins', 'book-druids', 'book-barbarians', 'book-necromancers', 'book-ninjas',
- 'book-combat-and-tacticss',
+ 'book-combat-and-tactics',
];
const SCHOOL_FIELDS = ['school-spells-and-magic'];
@@ -70,6 +70,10 @@ const displayWeaponType = function (type) {
}
}
+const getRowId = function (triggerName) {
+ return triggerName.match(/repeating_[^_]+_([^_]+)_[^_]+/)[1];
+}
+
const conditionalLog = function (bool, msg) {
if (bool)
console.log(msg);
@@ -78,12 +82,14 @@ const conditionalLog = function (bool, msg) {
const extractQueryResult = async function(query){//Sends a message to query the user for some behavior, returns the selected option.
let queryRoll = await startRoll(`!{{query=[[0[response=${query}]]]}}`);
finishRoll(queryRoll.rollId);
+ console.log(queryRoll);
return queryRoll.results.query.expression.replace(/^.+?response=|\]$/g,'');
};
const extractRoll = async function(rollExpression) {
let queryRoll = await startRoll(`!{{roll=[[${rollExpression}]]}}`);
finishRoll(queryRoll.rollId);
+ console.log(queryRoll);
return queryRoll.results.roll;
};
@@ -170,8 +176,8 @@ const getActiveSettings = function (settingFields, values) {
const isBookInactive = function (books, obj) {
let activeBooks = getActiveSettings(BOOK_FIELDS, books);
- if (Array.isArray(obj['book']))
- return !obj['book'].some(b => activeBooks.has(b));
+ if (Array.isArray(obj))
+ return obj.every(b => !activeBooks.has(b));
else
return !activeBooks.has(obj['book']);
}
@@ -179,9 +185,9 @@ const isBookInactive = function (books, obj) {
const bookInactiveShowToast = function(books, obj) {
let bookInactive = isBookInactive(books, obj);
if (bookInactive) {
- if (Array.isArray(obj['book'])) {
- let booksString = obj['book'].map(b => '\n* ' + b).join('') + '\n'
- showToast(ERROR, 'Missing Book(s)', `The book(s) ${booksString} are currently not active on your sheet.\nGo to the *Sheet Settings* and activate any of the listed book(s) (if your DM allows for its usage)`);
+ if (Array.isArray(obj)) {
+ let booksString = obj.map(b => '\n* ' + b).join('')
+ showToast(ERROR, 'Missing Book(s)', `The book(s):${booksString}\nAre currently not active on your sheet.\nGo to the *Sheet Settings* and activate any of the listed book(s) (if your DM allows for its usage)`);
} else {
showToast(ERROR, 'Missing Book', `The book *${obj['book']}* is currently not active on your sheet.\nGo to the *Sheet Settings* and activate the book (if your DM allows for its usage)`);
}
@@ -1215,189 +1221,212 @@ on('change:thac0-base-calc', function(eventInfo) {
});
//#region Weapons autofill
-function setWeaponWithBonus(weaponName, setWeaponFunc, thac0Field) {
+const PLAYERS_OPTIONS_FIELD = 'tab81';
+function setWeaponWithBonus(weaponName, setWeaponFunc, comparer, thac0Field, category) {
if (!weaponName)
return;
weaponName = weaponName.toLowerCase();
- let fields = [...BOOK_FIELDS, thac0Field].filter(Boolean);
- getAttrs(fields, function(values) {
+ let fields = [...BOOK_FIELDS, PLAYERS_OPTIONS_FIELD, thac0Field].filter(Boolean);
+ getAttrs(fields, async function (values) {
+ let bonus = 0;
+ let baseWeapons = WEAPONS_TABLE[weaponName]
+ if (!baseWeapons) {
+ let match = weaponName.match(/\s*\+([0-9]+)\s*/);
+ if (!match)
+ return;
+
+ let baseWeaponName = weaponName.replace(match[0], ' ').trim();
+ baseWeapons = WEAPONS_TABLE[baseWeaponName];
+ if (!baseWeapons)
+ return;
+
+ bonus = parseInt(match[1]);
+ if (isNaN(bonus))
+ return;
+ }
+ if (category)
+ baseWeapons = baseWeapons.filter(w => w['category'].includes(category));
+
+ let activeBooks = getActiveSettings(BOOK_FIELDS, values);
+ let activeWeapons = baseWeapons.filter(w => w['book'].some(b => activeBooks.has(b)));
+
+
+ if (activeWeapons.length === 0) {
+ let booksString = baseWeapons.flatMap(w => w['book']).map(b => '\n* ' + b).join('')
+ showToast(ERROR, 'Missing Book(s)', `The book(s):${booksString}\nAre currently not active on your sheet.\nGo to the *Sheet Settings* and activate any of the listed book(s) (if your DM allows for its usage)`);
+ return;
+ }
+
+ let baseWeapon;
+ let isPlayersOptions = values[PLAYERS_OPTIONS_FIELD] === '2';
+ let isAllEqual = activeWeapons.every(w => comparer(w, activeWeapons[0], isPlayersOptions));
+ if (isAllEqual) {
+ baseWeapon = activeWeapons[0];
+ } else {
+ let options = activeWeapons
+ .map((w, i) => `${w.book.join('/')},${i}`)
+ .join('|');
+ let answer = await extractRollResult(`?{Multiple versions of this weapon exists. Please select a version|${options}}`);
+ baseWeapon = activeWeapons[answer];
+ }
+
let thac0 = parseInt(values[thac0Field]);
thac0 = isNaN(thac0) ? 20 : thac0;
- let baseWeapon = weapons[weaponName]
- if (baseWeapon) {
- if (bookInactiveShowToast(values, baseWeapon))
- return;
-
- setWeaponFunc({
- ...baseWeapon,
- 'thac0' : thac0,
- 'bonus' : '0'
- });
- return;
- }
-
- let match = weaponName.match(/\s*\+([0-9]+)\s*/);
- if (!match)
- return;
-
- let baseWeaponName = weaponName.replace(match[0], ' ').trim();
- baseWeapon = weapons[baseWeaponName];
- if (!baseWeapon)
- return;
-
- if (bookInactiveShowToast(values, baseWeapon))
- return;
-
- let bonusString = match[1];
- let bonus = parseInt(bonusString)
- if (isNaN(bonus))
- return;
-
- if (bonus < 1) {
- setWeaponFunc({
- ...baseWeapon,
- 'thac0' : thac0,
- 'bonus' : '0',
- 'bonusInt': 0
- });
- return;
- }
-
- let weaponWithBonus = {
+ let weapon = {
...baseWeapon,
'thac0' : thac0,
- 'speed' : Math.max(baseWeapon['speed'] - bonus, 0),
- 'bonus' : `+${bonus}`,
- 'bonusInt': bonus
+ };
+ if (bonus < 1) {
+ weapon['bonus'] = '0';
+ weapon['bonusInt'] = 0;
+ } else {
+ weapon['bonus'] = `+${bonus}`;
+ weapon['bonusInt'] = bonus;
+ weapon['speed'] = Math.max(weapon['speed'] - bonus, 0)
}
- setWeaponFunc(weaponWithBonus);
+ setWeaponFunc(weapon);
});
}
//melee hit autofill
on('change:repeating_weapons:weaponname', function(eventInfo) {
- let comparer = function (weapon1, weapon2, isPo) {
- if (isPo) {
- let reach = 'reach';
- }
- return ['size','speed','type'].every(f => weapon1[f] === weapon2[f])
+ let comparer = function (weapon1, weapon2, isPlayersOption) {
+ let compareFields = ['size','speed','type'];
+ if (isPlayersOption)
+ compareFields.push('reach');
+ return compareFields.every(f => weapon1[f] === weapon2[f])
}
+ let rowId = getRowId(eventInfo.triggerName);
let setWeaponFunc = function (weapon) {
- let weaponInfo = {
- 'repeating_weapons_attackadj' : weapon['bonus'],
- 'repeating_weapons_ThAC0' : weapon['thac0'],
- 'repeating_weapons_range' : weapon['reach'] || 'Melee',
- 'repeating_weapons_size' : weapon['size'],
- 'repeating_weapons_weapspeed' : weapon['speed'],
- 'repeating_weapons_weaptype-slash' : weapon['type'].includes('S') ? 1 : 0,
- 'repeating_weapons_weaptype-pierce': weapon['type'].includes('P') ? 1 : 0,
- 'repeating_weapons_weaptype-blunt' : weapon['type'].includes('B') ? 1 : 0,
- };
+ let weaponInfo = {};
+ weaponInfo[`repeating_weapons_${rowId}_attackadj`] = weapon['bonus'];
+ weaponInfo[`repeating_weapons_${rowId}_ThAC0`] = weapon['thac0'];
+ weaponInfo[`repeating_weapons_${rowId}_range`] = weapon['reach'] || 'Melee';
+ weaponInfo[`repeating_weapons_${rowId}_size`] = weapon['size'];
+ weaponInfo[`repeating_weapons_${rowId}_weapspeed`] = weapon['speed'];
+ weaponInfo[`repeating_weapons_${rowId}_weaptype-slash`] = weapon['type'].includes('S') ? 1 : 0;
+ weaponInfo[`repeating_weapons_${rowId}_weaptype-pierce`] = weapon['type'].includes('P') ? 1 : 0;
+ weaponInfo[`repeating_weapons_${rowId}_weaptype-blunt`] = weapon['type'].includes('B') ? 1 : 0;
setAttrs(weaponInfo);
};
- setWeaponWithBonus(eventInfo.newValue, comparer, setWeaponFunc, 'thac0-base-calc');
+ setWeaponWithBonus(eventInfo.newValue, setWeaponFunc, comparer, 'thac0-base-calc', 'Melee');
});
//melee damage autofill
on('change:repeating_weapons-damage:weaponname1', function(eventInfo) {
- let comparer = function (weapon1, weapon2) {
+ let comparer = function (weapon1, weapon2, isPlayersOption) {
let fisk = ['small-medium','large'];
- if (isPo) {
+ if (isPlayersOption) {
fisk.push('size');
- fisk.push('type')
+ fisk.push('type');
fisk.push('knockdown');
}
return fisk.every(f => weapon1[f] === weapon2[f])
}
+ let rowId = getRowId(eventInfo.triggerName);
let setWeaponFunc = function (weapon) {
- let weaponInfo = {
- 'repeating_weapons-damage_damadj' : weapon['bonus'],
- 'repeating_weapons-damage_damsm' : weapon['small-medium'],
- 'repeating_weapons-damage_daml' : weapon['large'],
- 'repeating_weapons-damage_damsize' : weapon['size'],
- 'repeating_weapons-damage_damtype' : weapon['type'],
- 'repeating_weapons-damage_knockdown1' : weapon['knockdown'] || ''
- };
+ let weaponInfo = {};
+ weaponInfo[`repeating_weapons-damage_${rowId}_damadj`] = weapon['bonus'];
+ weaponInfo[`repeating_weapons-damage_${rowId}_damsm`] = weapon['small-medium'];
+ weaponInfo[`repeating_weapons-damage_${rowId}_daml`] = weapon['large'];
+ weaponInfo[`repeating_weapons-damage_${rowId}_knockdown1`] = weapon['knockdown'] || '';
+ weaponInfo[`repeating_weapons-damage_${rowId}_size`] = weapon['size'];
+ weaponInfo[`repeating_weapons-damage_${rowId}_type`] = weapon['type'];
setAttrs(weaponInfo);
};
- setWeaponWithBonus(eventInfo.newValue, setWeaponFunc);
+ setWeaponWithBonus(eventInfo.newValue, setWeaponFunc, comparer, '', 'Melee');
});
//range hit autofill
on('change:repeating_weapons2:weaponname2', function(eventInfo) {
- let comparer = function (weapon1, weapon2) {
+ let comparer = function (weapon1, weapon2, isPlayersOption) {
return ['strength','rof','range','size','speed','type'].every(f => weapon1[f] === weapon2[f])
}
+ let rowId = getRowId(eventInfo.triggerName);
let setWeaponFunc = function (weapon) {
- let weaponInfo = {
- 'repeating_weapons2_strbonus2' : weapon['strength'] ? 1 : 0,
- 'repeating_weapons2_attacknum2' : weapon['rof'] || '',
- 'repeating_weapons2_attackadj2' : weapon['bonus'],
- 'repeating_weapons2_ThAC02' : weapon['thac0'],
- 'repeating_weapons2_range2' : weapon['range'] || '',
- 'repeating_weapons2_size2' : weapon['size'],
- 'repeating_weapons2_weapspeed2' : weapon['speed'],
- 'repeating_weapons2_weaptype-slash2' : weapon['type'].includes('S') ? 1 : 0,
- 'repeating_weapons2_weaptype-pierce2' : weapon['type'].includes('P') ? 1 : 0,
- 'repeating_weapons2_weaptype-blunt2' : weapon['type'].includes('B') ? 1 : 0,
- };
+ let weaponInfo = {};
+ weaponInfo[`repeating_weapons2_${rowId}_strbonus2`] = weapon['strength'] ? 1 : 0;
+ weaponInfo[`repeating_weapons2_${rowId}_attacknum2`] = weapon['rof'] || '';
+ weaponInfo[`repeating_weapons2_${rowId}_attackadj2`] = weapon['bonus'];
+ weaponInfo[`repeating_weapons2_${rowId}_ThAC02`] = weapon['thac0'];
+ weaponInfo[`repeating_weapons2_${rowId}_range2`] = weapon['range'] || '';
+ weaponInfo[`repeating_weapons2_${rowId}_size2`] = weapon['size'];
+ weaponInfo[`repeating_weapons2_${rowId}_weapspeed2`] = weapon['speed'];
+ weaponInfo[`repeating_weapons2_${rowId}_weaptype-slash2`] = weapon['type'].includes('S') ? 1 : 0;
+ weaponInfo[`repeating_weapons2_${rowId}_weaptype-pierce2`] = weapon['type'].includes('P') ? 1 : 0;
+ weaponInfo[`repeating_weapons2_${rowId}_weaptype-blunt2`] = weapon['type'].includes('B') ? 1 : 0;
setAttrs(weaponInfo);
};
- setWeaponWithBonus(eventInfo.newValue, setWeaponFunc, 'thac0-base-calc');
+ setWeaponWithBonus(eventInfo.newValue, setWeaponFunc, comparer, 'thac0-base-calc', 'Range');
});
//range damage autofill
on('change:repeating_ammo:ammoname', function(eventInfo) {
- let comparer = function (weapon1, weapon2) {
- return ['strength','small-medium','large','size'].every(f => weapon1[f] === weapon2[f])
+ let comparer = function (weapon1, weapon2, isPlayersOption) {
+ let comparerFields = ['strength','small-medium','large'];
+ if (isPlayersOption) {
+ comparerFields.push('knockdown');
+ comparerFields.push('size');
+ comparerFields.push('ammo-size');
+ comparerFields.push('type');
+ }
+ return comparerFields.every(f => weapon1[f] === weapon2[f])
}
+ let rowId = getRowId(eventInfo.triggerName);
let setWeaponFunc = function (weapon) {
- let weaponInfo = {
- 'repeating_weapons2_strbonus3' : weapon['strength'] ? 1 : 0,
- 'repeating_ammo_damadj2' : weapon['bonus'],
- 'repeating_ammo_damsm2' : weapon['small-medium'],
- 'repeating_ammo_daml2' : weapon['large'],
- 'repeating_weapons-damage_knockdown2' : weapon['knockdown'] || ''
- };
+ let weaponInfo = {};
+ weaponInfo[`repeating_ammo_${rowId}_strbonus3`] = weapon['strength'] ? 1 : 0;
+ weaponInfo[`repeating_ammo_${rowId}_damadj2`] = weapon['bonus'];
+ weaponInfo[`repeating_ammo_${rowId}_damsm2`] = weapon['small-medium'];
+ weaponInfo[`repeating_ammo_${rowId}_daml2`] = weapon['large'];
+ weaponInfo[`repeating_ammo_${rowId}_knockdown2`] = weapon['knockdown'] || '';
+ weaponInfo[`repeating_ammo_${rowId}_size`] = weapon['ammo-size'] || weapon['size'];
+ weaponInfo[`repeating_ammo_${rowId}_type`] = weapon['type'];
setAttrs(weaponInfo);
}
- setWeaponWithBonus(eventInfo.newValue, setWeaponFunc);
+ setWeaponWithBonus(eventInfo.newValue, setWeaponFunc, comparer, '', 'Range');
});
//Follower weapons
function setupFollowerWeaponsAutoFill(repeating, sections) {
let prefix = '';
- let onChange = '';
if (repeating !== '') {
- prefix = `repeating_${repeating}_`
- onChange = `repeating_${repeating}:`
+ prefix = `repeating_${repeating}`
}
sections.forEach(section => {
- on(`change:${onChange}weaponnamehench${section}`, function(eventInfo) {
+ on(`change:${prefix}:weaponnamehench${section}`, function(eventInfo) {
+ let comparer = function (weapon1, weapon2, isPlayersOption) {
+ let comparerFields = ['rof','small-medium','large','range','type','speed'];
+ if (isPlayersOption) {
+ comparerFields.push('reach');
+ comparerFields.push('knockdown');
+ }
+ return comparerFields.every(f => weapon1[f] === weapon2[f])
+ }
+ let rowId = getRowId(eventInfo.triggerName);
let setWeaponFunc = function (weapon) {
- let weaponInfo = {
- [`${prefix}attacknumhench${section}`]: weapon['rof'] || '1',
- [`${prefix}attackadjhench${section}`]: weapon['bonus'],
- [`${prefix}damadjhench${section}`]: weapon['bonus'],
- [`${prefix}damsmhench${section}`]: weapon['small-medium'],
- [`${prefix}damlhench${section}`]: weapon['large'],
- [`${prefix}rangehench${section}`]: weapon['range'] || weapon['reach'] || 'Melee',
- [`${prefix}weaptypehench${section}`]: weapon['type'],
- [`${prefix}weapspeedhench${section}`]: weapon['speed'],
- };
+ let weaponInfo = {};
+ weaponInfo[`${prefix}_${rowId}_attacknumhench${section}`] = weapon['rof'] || '1';
+ weaponInfo[`${prefix}_${rowId}_attackadjhench${section}`] = weapon['bonus'];
+ weaponInfo[`${prefix}_${rowId}_damadjhench${section}`] = weapon['bonus'];
+ weaponInfo[`${prefix}_${rowId}_damsmhench${section}`] = weapon['small-medium'];
+ weaponInfo[`${prefix}_${rowId}_damlhench${section}`] = weapon['large'];
+ weaponInfo[`${prefix}_${rowId}_rangehench${section}`] = weapon['range'] || weapon['reach'] || 'Melee';
+ weaponInfo[`${prefix}_${rowId}_weaptypehench${section}`] = weapon['type'];
+ weaponInfo[`${prefix}_${rowId}_weapspeedhench${section}`] = weapon['speed'];
setAttrs(weaponInfo);
};
- setWeaponWithBonus(eventInfo.newValue, setWeaponFunc);
+ setWeaponWithBonus(eventInfo.newValue, setWeaponFunc, comparer);
});
});
}
@@ -1497,105 +1526,97 @@ on('clicked:grenade-miss', async function (eventInfo) {
});
});
-on('clicked:crit-melee', function(eventInfo) {
- TAS.repeating('weapons-damage')
- .attrs(['strengthdmg', 'dexmissile', 'temp-damadj', 'misc-mod', ...BOOK_FIELDS])
- .fields('strbonus1', 'dexbonus1', 'weaponname1', 'specialist-damage', 'mastery-damage', 'damadj', 'damsm', 'daml')
- .map(function (row){
- return row;
- }, async function (rows, _, attrSet){
- let weaponSelect = rows.map(r => `${r['weaponname1']},${r.id}`)
+on('clicked:repeating_weapons-damage:crit2-melee', function(eventInfo) {
+ console.log(eventInfo);
+ let fields = [
+ 'strengthdmg', 'dexmissile', 'temp-damadj', 'misc-mod',
+ 'repeating_weapons-damage_strbonus1','repeating_weapons-damage_dexbonus1','repeating_weapons-damage_weaponname1',
+ 'repeating_weapons-damage_specialist-damage','repeating_weapons-damage_mastery-damage','repeating_weapons-damage_damadj',
+ 'repeating_weapons-damage_damsm','repeating_weapons-damage_daml','repeating_weapons-damage_size','repeating_weapons-damage_type'];
+ getAttrs(fields, async function (values) {
+ let finalRollText = `&{template:2Edefault} {{name=Test Critical hit}} {{Weapon name=${values['repeating_weapons-damage_weaponname1']}}} `;
+
+ let attackType = await extractQueryResult('?{How are you attacking?|Regular Attack|Low Attack|High Attack}');
+ let targetType = await extractQueryResult('?{What are you attacking?|Humanoid|Animal|Monster}');
+ let targetSize = await extractQueryResult('?{Target size?|Tiny|Small|Medium|Large|Huge|Gargantuan}');
+
+ let weaponSize = displaySize(values['repeating_weapons-damage_size']);
+ let weaponType = values['repeating_weapons-damage_type'];
+ if (weaponType.includes('/')) {
+ let displayTypes = weaponType.split('/')
+ .map(s => displayWeaponType(s))
.join('|');
- let rowId = await extractQueryResult(`?{What weapon did you use?|${weaponSelect}}`);
- let row = rows.find(row => row.id === rowId);
- let finalRollText = '&{template:2Edefault} {{name=Test Critical hit}}';
+ weaponType = await extractQueryResult(`?{How are your attack with your weapon?|${displayTypes}}`)
+ } else {
+ weaponType = displayWeaponType(weaponType);
+ }
- let attackType = await extractQueryResult('?{How are you attacking?|Regular Attack|Low Attack|High Attack}');
- let targetType = await extractQueryResult('?{What are you attacking?|Humanoid|Animal|Monster}');
- let targetSize = await extractQueryResult('?{Target size?|Tiny|Small|Medium|Large|Huge|Gargantuan}');
+ finalRollText += `{{Weapon type=${attackType}}} `;
+ finalRollText += `{{Weapon size=${weaponSize}}} `;
+ finalRollText += `{{Target type=${targetType}}} `;
+ finalRollText += `{{Target size=${targetSize}}} `;
- let baseWeapon = getBaseWeapon(row['weaponname1'], attrSet);
- let weaponSize;
- let weaponType;
- if (baseWeapon) {
- weaponSize = displaySize(baseWeapon['size']);
- weaponType = baseWeapon['type'];
- if (weaponType.includes('/')) {
- let displayTypes = weaponType.split('/')
- .map(s => displayWeaponType(s))
- .join('|');
+ let locationDice;
+ switch (attackType) {
+ case 'Regular Attack': locationDice = '1d10'; break;
+ case 'Low Attack': locationDice = '1d6'; break;
+ case 'High Attack': locationDice = '1d6+4'; break;
+ }
+ let locationRoll = await extractRollResult(locationDice);
+ let locationObject = LOCATION_TABLE[targetType][locationRoll];
- weaponType = await extractQueryResult(`?{How are your attack with your weapon?|${displayTypes}}`)
- } else {
- weaponType = displayWeaponType(weaponType);
- }
- } else {
- weaponSize = await extractQueryResult('?{Weapon size?|Small|Medium|Large}');
- weaponType = await extractQueryResult('?{Weapon type?|Slashing|Piercing|Bludgeoning}')
- }
+ let severityEffect;
+ let severityRoll;
+ const sizeDiff = sizeToInt(weaponSize) - sizeToInt(targetSize);
+ if (sizeDiff < 0) {
+ severityEffect = 'Minor';
+ severityRoll = await extractRollResult('1d6');
+ } else if (sizeDiff === 0) {
+ severityEffect = 'Major';
+ severityRoll = await extractRollResult('2d4');
+ } else if (sizeDiff === 1) {
+ severityEffect = 'Severe';
+ severityRoll = await extractRollResult('2d6');
+ } else if (sizeDiff > 1) {
+ severityEffect = 'Mortal';
+ severityRoll = await extractRollResult('2d8');
+ }
- finalRollText += `{{Weapon name=${row['weaponname1']}}} `;
- finalRollText += `{{Weapon type=${attackType}}} `;
- finalRollText += `{{Weapon size=${weaponSize}}} `;
- finalRollText += `{{Target type=${targetType}}} `;
- finalRollText += `{{Target size=${targetSize}}} `;
+ finalRollText += `{{Severity effect=${severityEffect}}} `;
+ finalRollText += `{{Severity roll=${severityRoll}}} `;
- let locationDice;
- switch (attackType) {
- case 'Regular Attack': locationDice = '1d10'; break;
- case 'Low Attack': locationDice = '1d6'; break;
- case 'High Attack': locationDice = '1d6+4'; break;
- }
- let locationResult = await extractRollResult(locationDice);
- let location = LOCATION_TABLE[targetType][locationResult];
+ let weaponDamage = sizeToInt(targetSize) < 3 ? values['repeating_weapons-damage_damsm'] : values['repeating_weapons-damage_daml'];
+ if (weaponDamage.match('/\d/'))
+ if (severityRoll > 12) {
+ finalRollText += `{{Critical damage=[[(${weaponDamage})*3]]}} `;
+ severityRoll = 12;
+ } else {
+ finalRollText += `{{Critical damage=[[(${weaponDamage})*2]]}} `;
+ }
+ finalRollText += `{{Location roll=[[${locationRoll}]]}} `;
+ if (locationObject)
+ finalRollText += `{{Location hit=${locationObject['hitLocation']}}} `;
- const sizeDiff = sizeToInt(weaponSize) - sizeToInt(targetSize);
- let severityEffect;
- let severityResult;
- if (sizeDiff < 0) {
- severityEffect = 'Minor';
- severityResult = await extractRollResult('1d6');
- } else if (sizeDiff === 0) {
- severityEffect = 'Major';
- severityResult = await extractRollResult('2d4');
- } else if (sizeDiff === 1) {
- severityEffect = 'Severe';
- severityResult = await extractRollResult('2d6');
- } else if (sizeDiff > 1) {
- severityEffect = 'Mortal';
- severityResult = await extractRollResult('2d8');
- }
+ let critEffect;
+ if (severityRoll < 4) {
+ critEffect = 'No unusual effect'
+ } else if (CRIT_EFFECT_TABLE[weaponType]) {
+ critEffect = CRIT_EFFECT_TABLE[weaponType][targetType][locationObject['location'][severityRoll]];
+ } else {
+ critEffect = 'No unusual effect';
+ }
- finalRollText += `{{Severity effect=${severityEffect}}} `;
- finalRollText += `{{Severity roll=${severityResult}}} `;
+ finalRollText += `{{Critical effect=${critEffect}}}`;
+ console.log(finalRollText);
- let weaponDamage = sizeToInt(targetSize) < 3 ? row['damsm'] : row['daml'];
- if (severityResult > 12) {
- finalRollText += `{{Critical damage=[[(${weaponDamage})*3]]}} `;
- severityResult = 12;
- } else {
- finalRollText += `{{Critical damage=[[(${weaponDamage})*2]]}} `;
- }
-
- finalRollText += `{{Location roll=[[${locationResult}]]}} `;
- finalRollText += `{{Location hit=${location['hitLocation']}}} `;
-
- let critEffect = severityResult < 4
- ? 'No unusual effect'
- : CRIT_EFFECT_TABLE[weaponType][targetType][location['location']][severityResult];
- finalRollText += `{{Critical effect=${critEffect}}}`;
- console.log(finalRollText)
-
- startRoll(finalRollText, function (roll) {
- console.log(roll);
- let computedRolls = {};
- finishRoll(roll.rollId, computedRolls);
- });
-
- })
- .execute();
+ startRoll(finalRollText, function (roll) {
+ console.log(roll);
+ let computedRolls = {};
+ finishRoll(roll.rollId, computedRolls);
+ });
+ });
});
//#endregion
diff --git a/ADnD_2E_Revised/pug/weaponsDatalists.pug b/ADnD_2E_Revised/pug/weaponsDatalists.pug
index 6ad37959d4..e765ca8a32 100644
--- a/ADnD_2E_Revised/pug/weaponsDatalists.pug
+++ b/ADnD_2E_Revised/pug/weaponsDatalists.pug
@@ -13,7 +13,7 @@ datalist(id='melee-weapons')
- continue;
if processedWeapons.has(weapon.name.toLowerCase())
- continue
- - books = 'Books: ' + bookShorthand(weaponList.flatMap(w => w.book))
+ - books = 'Books: ' + bookShorthand(weaponList.filter(w => w['category'].includes('Melee')).flatMap(w => w.book))
- processedWeapons.add(weapon.name.toLowerCase())
- let group = weapon.group || ''
- group += (group ? ', ' : '') + books
@@ -30,7 +30,7 @@ datalist(id='ranged-weapons')
- continue;
if processedWeapons.has(weapon.name.toLowerCase())
- continue
- - books = 'Books: ' + bookShorthand(weaponList.flatMap(w => w.book))
+ - books = 'Books: ' + bookShorthand(weaponList.filter(w => w['category'].includes('Range')).flatMap(w => w.book))
- processedWeapons.add(weapon.name.toLowerCase())
- let group = weapon.group || ''
- group += (group ? ', ' : '') + books