@@ -3301,6 +3380,63 @@
});
});
+ // Always make sure the character has an "On Person" location.
+ // This row is recreated if deleted and normalized if renamed with odd casing/spaces.
+ const ON_PERSON_LOCATION_SECTION = "repeating_locationtotals";
+ const ON_PERSON_LOCATION_NAME = "On Person";
+
+ const normalizeLocationName = function(value) {
+ return String(value || "").trim().toLowerCase();
+ };
+
+ const ensureOnPersonLocation = function() {
+ getSectionIDs(ON_PERSON_LOCATION_SECTION, function(rowIds) {
+ const attrsToGet = rowIds.map(rowId =>
+ `${ON_PERSON_LOCATION_SECTION}_${rowId}_inventoryLocationName`
+ );
+
+ getAttrs(attrsToGet, function(values) {
+ const matchingRows = rowIds.filter(rowId =>
+ normalizeLocationName(values[`${ON_PERSON_LOCATION_SECTION}_${rowId}_inventoryLocationName`]) ===
+ normalizeLocationName(ON_PERSON_LOCATION_NAME)
+ );
+
+ const attrsToSet = {};
+
+ if (matchingRows.length > 0) {
+ const keeperRowId = matchingRows[0];
+
+ attrsToSet[`${ON_PERSON_LOCATION_SECTION}_${keeperRowId}_inventoryLocationName`] = ON_PERSON_LOCATION_NAME;
+ attrsToSet[`${ON_PERSON_LOCATION_SECTION}_${keeperRowId}_locationOnPerson`] = "1";
+
+ // Optional cleanup: "On Person" should be unique.
+ // This prevents the inventory matching logic from having duplicate location names.
+ matchingRows.slice(1).forEach(rowId => {
+ removeRepeatingRow(`${ON_PERSON_LOCATION_SECTION}_${rowId}`);
+ });
+ } else {
+ const rowId = generateRowID();
+
+ attrsToSet[`${ON_PERSON_LOCATION_SECTION}_${rowId}_inventoryLocationName`] = ON_PERSON_LOCATION_NAME;
+ attrsToSet[`${ON_PERSON_LOCATION_SECTION}_${rowId}_locationOnPerson`] = "1";
+ attrsToSet[`${ON_PERSON_LOCATION_SECTION}_${rowId}_locationItemCount`] = "0";
+ attrsToSet[`${ON_PERSON_LOCATION_SECTION}_${rowId}_locationTotalWeight`] = "0";
+ }
+
+ if (Object.keys(attrsToSet).length > 0) {
+ setAttrs(attrsToSet);
+ }
+ });
+ });
+ };
+
+ on(
+ "sheet:opened remove:repeating_locationtotals change:repeating_locationtotals:inventorylocationname",
+ function() {
+ ensureOnPersonLocation();
+ }
+ );
+
// On Person Total Weight
on("change:repeating_locationtotals remove:repeating_locationtotals", function(){
getSectionIDs(`repeating_locationtotals`,function(locationArray) {
@@ -3544,11 +3680,12 @@
});
};
- on(watch(["Specialty", "AttackCurve", "Versatile"]), function(){
- getAttrs(["Specialty", "AttackCurve", "Versatile"], function(values){
+ on(watch(["Specialty", "AttackCurve", "Versatile", "skill_growth_modifier"]), function(){
+ getAttrs(["Specialty", "AttackCurve", "Versatile", "skill_growth_modifier"], function(values){
let attack = 2;
let specialty = 0;
let versatile = 0;
+ let skill_growth_modifier = num(values, "skill_growth_modifier");
if(values.AttackCurve === "Medium") attack = 4;
if(values.Specialty === "Specialist") specialty = 4;
@@ -3556,15 +3693,16 @@
if(values.Versatile === "on") versatile = 1;
setAttrs({
- BaseSkillGrowth: attack + specialty + versatile
+ BaseSkillGrowth: attack + specialty + versatile + skill_growth_modifier
});
});
});
- on(watch(["intelligence", "IntBonus", "IntPen", "BaseSkillGrowth", "HD"]), function() {
- getAttrs(["intelligence", "IntBonus", "IntPen", "BaseSkillGrowth"], function(values) {
+ on(watch(["intelligence", "IntBonus", "IntPen", "BaseSkillGrowth", "HD", "no_intelligence_score"]), function() {
+ getAttrs(["intelligence", "IntBonus", "IntPen", "BaseSkillGrowth", "no_intelligence_score"], function(values) {
+ const noIntelligenceScore = values.no_intelligence_score === "1";
const total = num(values, "intelligence") + num(values, "IntBonus") - num(values, "IntPen");
- const mod = Math.floor((total - 10) / 2);
+ const mod = noIntelligenceScore ? 0 : Math.floor((total - 10) / 2);
setAttrs({
NatIntMod: mod,
SkillsKnown: mod + num(values, "BaseSkillGrowth") + 4
@@ -3703,7 +3841,8 @@
});
});
- const buttonlist = ["main", "skills", "gear", "definitions", "abilities", "spells", "accessories", "inventory", "profitloss"];
+ const buttonlist = ["main", "skills", "gear", "definitions", "abilities", "spells", "accessories", "inventory", "profitloss",
+ "settings"];
buttonlist.forEach(button => {
on(`clicked:${button}`, function() {
setAttrs({
@@ -3801,26 +3940,96 @@
//
//
{
const attrs = [stat.base, stat.bonus, stat.enhancement, stat.penalty];
+ if(stat.noScore) attrs.push(stat.noScore);
+ if(stat.backup) attrs.push(stat.backup);
on(watch(attrs), function() {
getAttrs(attrs, function(values) {
- const total = num(values, stat.base) + num(values, stat.bonus) +
+ const noScore = stat.noScore && values[stat.noScore] === "1";
+ const attrsToSet = {};
+ if(stat.backup && !noScore && values[stat.base] !== "-") {
+ attrsToSet[stat.backup] = values[stat.base];
+ }
+ if(noScore) {
+ attrsToSet[stat.total] = "-";
+ attrsToSet[stat.mod] = 0;
+ if(values[stat.base] !== "-") {
+ if(stat.backup && values[stat.base] !== "") {
+ attrsToSet[stat.backup] = values[stat.base];
+ }
+ attrsToSet[stat.base] = "-";
+ }
+ setAttrs(attrsToSet);
+ return;
+ }
+ if(stat.backup && values[stat.base] === "-") {
+ attrsToSet[stat.base] = values[stat.backup] || 10;
+ }
+ const baseValue = values[stat.base] === "-"
+ ? num(values, stat.backup, 10)
+ : num(values, stat.base);
+ const total = baseValue + num(values, stat.bonus) +
num(values, stat.enhancement) - num(values, stat.penalty);
- setAttrs({
- [stat.total]: total,
- [stat.mod]: Math.floor((total - 10) / 2)
- });
+ attrsToSet[stat.total] = total;
+ attrsToSet[stat.mod] = Math.floor((total - 10) / 2);
+
+ setAttrs(attrsToSet);
});
});
});
@@ -4154,6 +4363,49 @@
//
//
+
+ const buildSingleAttackMacro = function(data) {
+ const attack = data.attacks[0] || { label: "Single Attack", base: 0, slowPenalty: 0 };
+
+ const damageAction = makeFullAttackActionTarget(data.section, data.rowId, "singleattackdamage");
+ const confirmAction = makeFullAttackActionTarget(data.section, data.rowId, "singleattackconfirm");
+
+ let macro = `&{template:custom}{{title=Single Attack}}{{subtitle=${data.characterName}'s ${data.weaponName}}}`;
+ macro += `{{fullattack=1}}{{characterid=@{character_id}}}`;
+ macro += `{{attack1_next=[[0]]}}`;
+ macro += `{{attack1_damage_action=${damageAction}}}`;
+ macro += `{{attack1_confirm_action=${confirmAction}}}`;
+ macro += `{{attack1_label=Attack}}`;
+ macro += `{{attack1=[[${buildFullAttackExpression(data, attack)}]]}}`;
+
+ return macro;
+ };
+
+
+ const rollSingleAttackConfirmation = function(col, eventInfo) {
+ getAttrs(getFullAttackAttrs(col), function(values) {
+ const data = buildFullAttackData(col, values, eventInfo);
+ const attack = data.attacks[0] || { label: "Single Attack", base: 0, slowPenalty: 0 };
+
+ const normalAction = makeFullAttackActionTarget(data.section, data.rowId, "singleattackdamage");
+ const criticalAction = makeFullAttackActionTarget(data.section, data.rowId, "singleattackcritdamage");
+
+ const macro =
+ `&{template:custom}` +
+ `{{title=Critical Confirmation}}` +
+ `{{subtitle=${data.characterName}'s ${data.weaponName} - Single Attack}}` +
+ `{{fullattackconfirm=1}}` +
+ `{{characterid=@{character_id}}}` +
+ `{{confirm_normal_action=${normalAction}}}` +
+ `{{confirm_critical_action=${criticalAction}}}` +
+ `{{confirm=[[${buildFullAttackExpression(data, attack)}]]}}`;
+
+ startRoll(macro, function(roll) {
+ finishRoll(roll.rollId);
+ });
+ });
+ };
+
const getRepeatingRowIdFromEvent = function(eventInfo, section) {
const source = eventInfo && (eventInfo.sourceAttribute || eventInfo.sourceButton || "");
const match = source.match(new RegExp(`repeating_${section}_([^_]+)_`));
@@ -4295,7 +4547,8 @@
};
const buildFullAttackExpression = function(data, attack) {
- let expression = `1d20cs>${data.critLow}+${attack.base}[Base Attack]+${data.attackKey}[Key Attribute]+${data.featAttack}[Feat Bonuses]+${data.enhancement}[Enhancement]+(0?{Do you have any miscellaneous bonuses?|0})[Misc.]`;
+ let expression = `1d20cs>${data.critLow}+${attack.base}[Base Attack]+${data.attackKey}[Key Attribute]+${data.featAttack}`+
+ `[Feat Bonuses]+${data.enhancement}[Enhancement]+(0?{Do you have any miscellaneous bonuses?|0})[Misc.]`;
if(attack.slowPenalty) {
expression += `-${attack.slowPenalty}[Slow]`;
}
@@ -4303,7 +4556,8 @@
};
const buildFullAttackMacro = function(data) {
- let macro = `&{template:custom}{{title=Full Attack}}{{subtitle=${data.characterName}'s ${data.weaponName}}}{{fullattack=1}}{{characterid=@{character_id}}}`;
+ let macro = `&{template:custom}{{title=Full Attack}}{{subtitle=${data.characterName}'s ${data.weaponName}}}`+
+ `{{fullattack=1}}{{characterid=@{character_id}}}`;
data.attacks.forEach((attack, index) => {
const attackNumber = index + 1;
macro += `{{attack${attackNumber}_next=[[0]]}}`;
@@ -4323,9 +4577,11 @@
if(!critical) {
let macro = `&{template:custom}{{title=Damage}}{{subtitle=${data.characterName}'s ${data.weaponName}}}`;
if(data.twoHanded) {
- macro += `{{desc=${data.characterName} deals [[${data.diceNumber}${data.diceType}+[[floor(${data.damageKey}*1.5)]][Ability]+${data.featDamage}[Feats/Other]+${data.enhancement}[Enhancement]+${miscDamage}]] physical damage `;
+ macro += `{{desc=${data.characterName} deals [[${data.diceNumber}${data.diceType}+[[floor(${data.damageKey}*1.5)]]`+
+ `[Ability]+${data.featDamage}[Feats/Other]+${data.enhancement}[Enhancement]+${miscDamage}]] physical damage `;
} else {
- macro += `{{desc=${data.characterName} deals [[${data.diceNumber}${data.diceType}+[[${data.damageKey}]][Ability]+${data.featDamage}[Feats/Other]+${data.enhancement}[Enhancement]+${miscDamage}]] physical damage `;
+ macro += `{{desc=${data.characterName} deals [[${data.diceNumber}${data.diceType}+[[${data.damageKey}]][Ability]+`+
+ `${data.featDamage}[Feats/Other]+${data.enhancement}[Enhancement]+${miscDamage}]] physical damage `;
}
if(data.magicDice) {
macro += ` and [[${data.magicDice}[${magicDamageType}]]] ${magicDamageType} damage`;
@@ -4336,9 +4592,15 @@
let macro = `&{template:custom}{{title=Critical Damage}}{{subtitle=${data.characterName}'s ${data.weaponName}}}`;
if(data.twoHanded) {
- macro += `{{desc=${data.characterName} deals an astonishing [[[[${data.diceNumber}*${data.criticalMultiplier}]]${data.diceType}+[[(floor(${data.damageKey}*1.5)*${data.criticalMultiplier})]][Ability]+[[(${data.featDamage}*${data.criticalMultiplier})]][Feats/Other]+[[(${data.enhancement}*${data.criticalMultiplier})]][Enhancement]+${miscDamage}]]`;
+ macro += `{{desc=${data.characterName} deals an astonishing [[[[${data.diceNumber}*${data.criticalMultiplier}]]`+
+ `${data.diceType}+[[(floor(${data.damageKey}*1.5)*${data.criticalMultiplier})]][Ability]+[[(${data.featDamage}*`+
+ `${data.criticalMultiplier})]][Feats/Other]+[[(${data.enhancement}*${data.criticalMultiplier})]][Enhancement]+`+
+ `${miscDamage}]]`;
} else {
- macro += `{{desc=${data.characterName} deals an astonishing [[[[${data.diceNumber}*${data.criticalMultiplier}]]${data.diceType}+[[(floor(${data.damageKey})*${data.criticalMultiplier})]][Ability]+[[(${data.featDamage}*${data.criticalMultiplier})]][Feats/Other]+[[(${data.enhancement}*${data.criticalMultiplier})]][Enhancement]+${miscDamage}]]`;
+ macro += `{{desc=${data.characterName} deals an astonishing [[[[${data.diceNumber}*${data.criticalMultiplier}]]`+
+ `${data.diceType}+[[(floor(${data.damageKey})*${data.criticalMultiplier})]][Ability]+[[(${data.featDamage}*`+
+ `${data.criticalMultiplier})]][Feats/Other]+[[(${data.enhancement}*${data.criticalMultiplier})]][Enhancement]+`+
+ `${miscDamage}]]`;
}
if(data.magicDice) {
macro += ` + [[${data.magicDice}[${magicDamageType}]]] ${magicDamageType} damage`;
@@ -4366,14 +4628,251 @@
const attack = data.attacks[attackIndex - 1] || data.attacks[0];
const normalAction = makeFullAttackActionTarget(data.section, data.rowId, "fullattackdamage");
const criticalAction = makeFullAttackActionTarget(data.section, data.rowId, "fullattackcritdamage");
- const macro = `&{template:custom}{{title=Critical Confirmation}}{{subtitle=${data.characterName}'s ${data.weaponName} - ${attack.label}}}{{fullattackconfirm=1}}{{characterid=@{character_id}}}{{confirm_normal_action=${normalAction}}}{{confirm_critical_action=${criticalAction}}}{{confirm=[[${buildFullAttackExpression(data, attack)}]]}}`;
+ const macro = `&{template:custom}{{title=Critical Confirmation}}{{subtitle=${data.characterName}'s ${data.weaponName} - `+
+ `${attack.label}}}{{fullattackconfirm=1}}{{characterid=@{character_id}}}{{confirm_normal_action=${normalAction}}}`+
+ `{{confirm_critical_action=${criticalAction}}}{{confirm=[[${buildFullAttackExpression(data, attack)}]]}}`;
startRoll(macro, function(roll) {
finishRoll(roll.rollId);
});
});
};
+ const FOCUS_POINTS_QUERY = "?{Focus Points Spent|1|2|3|4}";
+
+ const clampFocusPoints = function(value) {
+ let focusPoints = parseInt(value, 10);
+ if(isNaN(focusPoints)) focusPoints = 1;
+ focusPoints = Math.max(1, focusPoints);
+ focusPoints = Math.min(4, focusPoints);
+ return focusPoints;
+ };
+
+ const rollResultTotal = function(rollResult, fallback = 0) {
+ if(rollResult && rollResult.result !== undefined) {
+ const parsed = parseFloat(rollResult.result);
+ return isNaN(parsed) ? fallback : parsed;
+ }
+
+ if(rollResult && rollResult.total !== undefined) {
+ const parsed = parseFloat(rollResult.total);
+ return isNaN(parsed) ? fallback : parsed;
+ }
+
+ return fallback;
+ };
+
+ const focusRowAttr = function(data, attr) {
+ if(data.rowId) return `repeating_${data.section}_${data.rowId}_${attr}`;
+ return `repeating_${data.section}_${attr}`;
+ };
+
+ const getFocusAttackAttrs = function(col) {
+ return getFullAttackAttrs(col).concat([
+ `repeating_weapons${col}_focus_points_used`
+ ]);
+ };
+
+ const buildFocusAttackData = function(col, values, eventInfo) {
+ const data = buildFullAttackData(col, values, eventInfo);
+ const prefix = `repeating_weapons${col}_`;
+
+ data.focusPointsUsed = clampFocusPoints(values[`${prefix}focus_points_used`]);
+
+ return data;
+ };
+
+ const buildFocusAttackExpression = function(data, attack, focusPointsTerm) {
+ let expression =
+ `1d20cs>${data.critLow}` +
+ `+${attack.base}[Base Attack]` +
+ `+${data.attackKey}[Key Attribute]` +
+ `+${data.featAttack}[Feat Bonuses]` +
+ `+${data.enhancement}[Enhancement]` +
+ `+(${focusPointsTerm}*3)[Focus]` +
+ `+(0?{Do you have any miscellaneous bonuses?|0})[Misc.]`;
+
+ if(attack.slowPenalty) {
+ expression += `-${attack.slowPenalty}[Slow]`;
+ }
+
+ return expression;
+ };
+
+ const buildFocusAttackMacro = function(data) {
+ const attack = data.attacks[0] || {
+ label: "Focus Attack",
+ base: 0,
+ slowPenalty: 0
+ };
+
+ const damageAction = makeFullAttackActionTarget(data.section, data.rowId, "focusattackdamage");
+ const confirmAction = makeFullAttackActionTarget(data.section, data.rowId, "focusattackconfirm");
+
+ let macro =
+ `&{template:custom}` +
+ `{{title=Focus Attack}}` +
+ `{{subtitle=${data.characterName}'s ${data.weaponName}}}` +
+ `{{fullattack=1}}` +
+ `{{characterid=@{character_id}}}` +
+ `{{Focus Points=[[${FOCUS_POINTS_QUERY}]]}}` +
+ `{{attack1_next=[[0]]}}` +
+ `{{attack1_damage_action=${damageAction}}}` +
+ `{{attack1_confirm_action=${confirmAction}}}` +
+ `{{attack1_label=Focus Attack}}` +
+ `{{attack1=[[${buildFocusAttackExpression(data, attack, FOCUS_POINTS_QUERY)}]]}}`;
+
+ return macro;
+ };
+
+ const buildFocusDamageMacro = function(data, critical = false) {
+ const focusPoints = clampFocusPoints(data.focusPointsUsed);
+ const focusDamageBonus = focusPoints * 3;
+ const focusedDiceNumber = `[[${data.diceNumber}+${focusPoints}]]`;
+ const magicDamageType = data.damageType ? data.damageType : "energy";
+ const miscDamage = `(0?{Do you have any miscellaneous bonuses?|0})[Misc.]`;
+ const focusPointText = focusPoints === 1 ? "focus point" : "focus points";
+
+ if(!critical) {
+ let macro =
+ `&{template:custom}` +
+ `{{title=Focus Damage}}` +
+ `{{subtitle=${data.characterName}'s ${data.weaponName}}}`;
+
+ if(data.twoHanded) {
+ macro +=
+ `{{desc=${data.characterName} spends ${focusPoints} ${focusPointText} and deals ` +
+ `[[${focusedDiceNumber}${data.diceType}` +
+ `+[[floor(${data.damageKey}*1.5)]][Ability]` +
+ `+${data.featDamage}[Feats/Other]` +
+ `+${data.enhancement}[Enhancement]` +
+ `+${focusDamageBonus}[Focus]` +
+ `+${miscDamage}]] physical damage`;
+ } else {
+ macro +=
+ `{{desc=${data.characterName} spends ${focusPoints} ${focusPointText} and deals ` +
+ `[[${focusedDiceNumber}${data.diceType}` +
+ `+[[${data.damageKey}]][Ability]` +
+ `+${data.featDamage}[Feats/Other]` +
+ `+${data.enhancement}[Enhancement]` +
+ `+${focusDamageBonus}[Focus]` +
+ `+${miscDamage}]] physical damage`;
+ }
+
+ if(data.magicDice) {
+ macro += ` and [[${data.magicDice}[${magicDamageType}]]] ${magicDamageType} damage`;
+ }
+
+ macro += ` with ${data.weaponName}.}}`;
+
+ return macro;
+ }
+
+ let macro =
+ `&{template:custom}` +
+ `{{title=Focus Critical Damage}}` +
+ `{{subtitle=${data.characterName}'s ${data.weaponName}}}`;
+
+ if(data.twoHanded) {
+ macro +=
+ `{{desc=${data.characterName} spends ${focusPoints} ${focusPointText} and deals an astonishing ` +
+ `[[[[(${data.diceNumber}+${focusPoints})*${data.criticalMultiplier}]]${data.diceType}` +
+ `+[[(floor(${data.damageKey}*1.5)*${data.criticalMultiplier})]][Ability]` +
+ `+[[(${data.featDamage}*${data.criticalMultiplier})]][Feats/Other]` +
+ `+[[(${data.enhancement}*${data.criticalMultiplier})]][Enhancement]` +
+ `+[[(${focusDamageBonus}*${data.criticalMultiplier})]][Focus]` +
+ `+${miscDamage}]]`;
+ } else {
+ macro +=
+ `{{desc=${data.characterName} spends ${focusPoints} ${focusPointText} and deals an astonishing ` +
+ `[[[[(${data.diceNumber}+${focusPoints})*${data.criticalMultiplier}]]${data.diceType}` +
+ `+[[(floor(${data.damageKey})*${data.criticalMultiplier})]][Ability]` +
+ `+[[(${data.featDamage}*${data.criticalMultiplier})]][Feats/Other]` +
+ `+[[(${data.enhancement}*${data.criticalMultiplier})]][Enhancement]` +
+ `+[[(${focusDamageBonus}*${data.criticalMultiplier})]][Focus]` +
+ `+${miscDamage}]]`;
+ }
+
+ if(data.magicDice) {
+ macro += ` + [[${data.magicDice}[${magicDamageType}]]] ${magicDamageType} damage`;
+ }
+
+ if(data.bonusCriticalDice) {
+ macro += ` + [[${data.bonusCriticalDice}[Bonus Dice]]] bonus damage`;
+ }
+
+ macro += ` with ${data.weaponName}.}}`;
+
+ return macro;
+ };
+
+ const rollFocusDamage = function(col, critical, eventInfo) {
+ getAttrs(getFocusAttackAttrs(col), function(values) {
+ const data = buildFocusAttackData(col, values, eventInfo);
+ const macro = buildFocusDamageMacro(data, critical);
+
+ startRoll(macro, function(roll) {
+ finishRoll(roll.rollId);
+ });
+ });
+ };
+
+ const rollFocusAttackConfirmation = function(col, eventInfo) {
+ getAttrs(getFocusAttackAttrs(col), function(values) {
+ const data = buildFocusAttackData(col, values, eventInfo);
+ const attack = data.attacks[0] || {
+ label: "Focus Attack",
+ base: 0,
+ slowPenalty: 0
+ };
+
+ const normalAction = makeFullAttackActionTarget(data.section, data.rowId, "focusattackdamage");
+ const criticalAction = makeFullAttackActionTarget(data.section, data.rowId, "focusattackcritdamage");
+
+ const macro =
+ `&{template:custom}` +
+ `{{title=Focus Critical Confirmation}}` +
+ `{{subtitle=${data.characterName}'s ${data.weaponName}}}` +
+ `{{fullattackconfirm=1}}` +
+ `{{characterid=@{character_id}}}` +
+ `{{confirm_normal_action=${normalAction}}}` +
+ `{{confirm_critical_action=${criticalAction}}}` +
+ `{{confirm=[[${buildFocusAttackExpression(data, attack, data.focusPointsUsed)}]]}}`;
+
+ startRoll(macro, function(roll) {
+ finishRoll(roll.rollId);
+ });
+ });
+ };
+
WeaponCol.forEach(col => {
+ on(`clicked:repeating_weapons${col}:singleattack`, function(eventInfo) {
+ getAttrs(getFullAttackAttrs(col), function(values) {
+ const data = buildFullAttackData(col, values, eventInfo);
+ const macro = buildSingleAttackMacro(data);
+
+ startRoll(macro, function(roll) {
+ const naturalDie = getFirstDie(roll.results.attack1);
+ const computed = {
+ attack1_next: naturalDie >= data.critLow ? 1 : 0
+ };
+
+ finishRoll(roll.rollId, computed);
+ });
+ });
+ });
+
+ on(`clicked:repeating_weapons${col}:singleattackdamage`, function(eventInfo) {
+ rollWeaponDamageFromFullAttack(col, false, eventInfo);
+ });
+
+ on(`clicked:repeating_weapons${col}:singleattackcritdamage`, function(eventInfo) {
+ rollWeaponDamageFromFullAttack(col, true, eventInfo);
+ });
+
+ on(`clicked:repeating_weapons${col}:singleattackconfirm`, function(eventInfo) {
+ rollSingleAttackConfirmation(col, eventInfo);
+ });
+
on(`clicked:repeating_weapons${col}:fullattackroll`, function(eventInfo) {
getAttrs(getFullAttackAttrs(col), function(values) {
const data = buildFullAttackData(col, values, eventInfo);
@@ -4403,6 +4902,41 @@
rollFullAttackConfirmation(col, attackIndex, eventInfo);
});
}
+ on(`clicked:repeating_weapons${col}:focusattack`, function(eventInfo) {
+ getAttrs(getFocusAttackAttrs(col), function(values) {
+ const data = buildFocusAttackData(col, values, eventInfo);
+ const macro = buildFocusAttackMacro(data);
+
+ startRoll(macro, function(roll) {
+ const naturalDie = getFirstDie(roll.results.attack1);
+ const focusPoints = clampFocusPoints(rollResultTotal(roll.results["Focus Points"], 1));
+
+ const computed = {
+ attack1_next: naturalDie >= data.critLow ? 1 : 0
+ };
+
+ const attrsToSet = {
+ [focusRowAttr(data, "focus_points_used")]: focusPoints
+ };
+
+ setAttrs(attrsToSet, function() {
+ finishRoll(roll.rollId, computed);
+ });
+ });
+ });
+ });
+
+ on(`clicked:repeating_weapons${col}:focusattackdamage`, function(eventInfo) {
+ rollFocusDamage(col, false, eventInfo);
+ });
+
+ on(`clicked:repeating_weapons${col}:focusattackcritdamage`, function(eventInfo) {
+ rollFocusDamage(col, true, eventInfo);
+ });
+
+ on(`clicked:repeating_weapons${col}:focusattackconfirm`, function(eventInfo) {
+ rollFocusAttackConfirmation(col, eventInfo);
+ });
});
//
@@ -4644,85 +5178,102 @@
//Focus
// weapondamage is the name of the damage button
-
- WeaponCol.forEach(col => {
- on(`clicked:repeating_weapons${col}:focusattack`, function(){
- getAttrs([
- `repeating_weapons${col}_bonustoattack`,
- `repeating_weapons${col}_critlow`,
- `repeating_weapons${col}_weaponhaste`,
- `repeating_weapons${col}_weaponbab`,
- `repeating_weapons${col}_enhancetoattack`,
- `repeating_weapons${col}_weapontodamage`,
- `repeating_weapons${col}_bonustodamage`,
- `repeating_weapons${col}_dnum`,
- `repeating_weapons${col}_dtype`,
- `repeating_weapons${col}_enchdamagedice`,
- `repeating_weapons${col}_extraenchdicecrit`,
- `repeating_weapons${col}_weaponcritmod`,
- `repeating_weapons${col}_twohanded`,
- `repeating_weapons${col}_weapontohit`,
- // `repeating_weapons${col}_character_name`,
- // `repeating_weapons${col}_arrayID`,
- `repeating_weapons${col}_weapondamagtype`], function(values){
- // const arrayID = values[`repeating_weapons${col}_arrayID`]
- // const characterName = values[`repeating_weapons${col}_character_name`];
- const featBonusToAttack = values[`repeating_weapons${col}_bonustoattack`] || 0;
- const featBonusToDamage = values[`repeating_weapons${col}_bonustodamage`] || 0;
- const dieQuantity = values[`repeating_weapons${col}_dnum`] || 1;
- const dieType = values[`repeating_weapons${col}_dtype`];
- const weaponEnhancement = values[`repeating_weapons${col}_enhancetoattack`] || 0;
- const baseAttack = values[`repeating_weapons${col}_weaponbab`] || 0;
- const minCritThreshold = values[`repeating_weapons${col}_critlow`]|| 20 ;
- const keyAttackAttribute = values[`repeating_weapons${col}_weapontohit`] || 0;
- const keyDamageAttribute = values[`repeating_weapons${col}_weapontodamage`] ;
- const twoHandedToggle = values[`repeating_weapons${col}_twohanded`];
- const magicDice = values[`repeating_weapons${col}_enchdamagedice`];
- const magicCriticalDice = values[`repeating_weapons${col}_extraenchdicecrit`];
- const magicDamageType = values[`repeating_weapons${col}_weapondamagtype`];
- const criticalModifier = values[`repeating_weapons${col}_weaponcritmod`];
- let macroRoll = `&{template:custom} {{title=Focus Attack}}{{Attack Roll=[[1d20cs>${minCritThreshold}+${baseAttack}`+
- `[BAB]+${keyAttackAttribute}[Key Attribute]+${featBonusToAttack}[Feats]+${weaponEnhancement}[Enhancement]`+
- `-@{slow}[Slow]+((0?{Focus Points Spent})*3)[Focus]+(0?{Miscellaneous attack bonuses?})[Misc.]]]}}`;
- if (twoHandedToggle === "on"){
- macroRoll = macroRoll + `{{Damage=[[[[${dieQuantity}+(0?{Focus Points Spent})]]${dieType}+floor(`+
- `(${keyDamageAttribute})*1.5)[Key Attribute]+${featBonusToDamage}[Feat]+${weaponEnhancement}[Magic]+((`+
- `0?{Focus Points Spent})*3)[Focus]]]}}`;
- }
- if (twoHandedToggle !== "on"){
- macroRoll = macroRoll + `{{Damage=[[[[${dieQuantity}+(0?{Focus Points Spent})]]${dieType}+floor(`+
- `${keyDamageAttribute})[Key Attribute]+${featBonusToDamage}[Feat]+${weaponEnhancement}[Magic]+((0?{`+
- `Focus Points Spent})*3)[Focus]]]}}`;
- }
- if (magicDice){
- macroRoll = macroRoll + `{{${magicDamageType} Damage=[[${magicDice}[${magicDamageType}]]]}}`;
- }
- macroRoll = macroRoll + `{{Critical Confirmation Roll=[[1d20cs>${minCritThreshold}+${baseAttack}`+
- `[BAB]+${keyAttackAttribute}[Key Attribute]+${featBonusToAttack}[Feats]+${weaponEnhancement}[Enhancement]`+
- `-@{slow}[Slow]+((0?{Focus Points Spent})*3)[Focus]+(0?{Miscellaneous attack bonuses?})[Misc.]]]}}`;
- if (twoHandedToggle === "on"){
- macroRoll = macroRoll + `{{Critical Damage=[[[[((${dieQuantity}+(0?{Focus Points Spent}))*${criticalModifier})]]`+
- `${dieType}+(floor(${keyDamageAttribute}*1.5)*${criticalModifier})[Key Attribute]+(`+
- `${featBonusToDamage}*${criticalModifier}[Feat])+(${weaponEnhancement}*${criticalModifier})+(((0?{Focus`+
- ` Points Spent})*3)*${criticalModifier})[Focus]]]}}`;
- }
- if (twoHandedToggle !== "on"){
- macroRoll = macroRoll + `{{Critical Damage=[[[[((${dieQuantity}+(0?{Focus Points Spent}))*${criticalModifier})]]`+
- `${dieType}+(${keyDamageAttribute}*${criticalModifier})[Key Attribute]+(`+
- `${featBonusToDamage}*${criticalModifier}[Feat])+(${weaponEnhancement}*${criticalModifier})+(((0?{Focus`+
- ` Points Spent})*3)*${criticalModifier})[Focus]]]}}`;
- }
- if (magicCriticalDice){
- macroRoll = macroRoll + `{{Bonus Critical Damage = [[${magicCriticalDice}]]}}`
- }
- startRoll(macroRoll,function(roll){
- finishRoll(roll.rollId);
- });
- });
- });
- })
+// Focus
+// WeaponCol.forEach(col => {
+// on(`clicked:repeating_weapons${col}:focusattack`, function(){
+// getAttrs([
+// `repeating_weapons${col}_bonustoattack`,
+// `repeating_weapons${col}_critlow`,
+// `repeating_weapons${col}_weaponhaste`,
+// `repeating_weapons${col}_weaponbab`,
+// `repeating_weapons${col}_enhancetoattack`,
+// `repeating_weapons${col}_weapontodamage`,
+// `repeating_weapons${col}_bonustodamage`,
+// `repeating_weapons${col}_dnum`,
+// `repeating_weapons${col}_dtype`,
+// `repeating_weapons${col}_enchdamagedice`,
+// `repeating_weapons${col}_extraenchdicecrit`,
+// `repeating_weapons${col}_weaponcritmod`,
+// `repeating_weapons${col}_twohanded`,
+// `repeating_weapons${col}_weapontohit`,
+// // `repeating_weapons${col}_character_name`,
+// // `repeating_weapons${col}_arrayID`,
+// `repeating_weapons${col}_weapondamagtype`], function(values){
+// // const arrayID = values[`repeating_weapons${col}_arrayID`]
+// // const characterName = values[`repeating_weapons${col}_character_name`];
+// const featBonusToAttack = values[`repeating_weapons${col}_bonustoattack`] || 0;
+// const featBonusToDamage = values[`repeating_weapons${col}_bonustodamage`] || 0;
+// const dieQuantity = values[`repeating_weapons${col}_dnum`] || 1;
+// const dieType = values[`repeating_weapons${col}_dtype`];
+// const weaponEnhancement = values[`repeating_weapons${col}_enhancetoattack`] || 0;
+// const baseAttack = values[`repeating_weapons${col}_weaponbab`] || 0;
+// const minCritThreshold = values[`repeating_weapons${col}_critlow`]|| 20 ;
+// const keyAttackAttribute = values[`repeating_weapons${col}_weapontohit`] || 0;
+// const keyDamageAttribute = values[`repeating_weapons${col}_weapontodamage`] ;
+// const twoHandedToggle = values[`repeating_weapons${col}_twohanded`];
+// const magicDice = values[`repeating_weapons${col}_enchdamagedice`];
+// const magicCriticalDice = values[`repeating_weapons${col}_extraenchdicecrit`];
+// const magicDamageType = values[`repeating_weapons${col}_weapondamagtype`];
+// const criticalModifier = values[`repeating_weapons${col}_weaponcritmod`];
+// let macroRoll = `&{template:custom} {{title=Focus Attack}}{{Attack Roll=[[1d20cs>${minCritThreshold}+${baseAttack}`+
+// `[BAB]+${keyAttackAttribute}[Key Attribute]+${featBonusToAttack}[Feats]+${weaponEnhancement}[Enhancement]`+
+// `-@{slow}[Slow]+((0?{Focus Points Spent})*3)[Focus]+(0?{Miscellaneous attack bonuses?})[Misc.]]]}}`;
+// if (twoHandedToggle === "on"){
+// macroRoll = macroRoll + `{{Damage=[[[[${dieQuantity}+(0?{Focus Points Spent})]]${dieType}+floor(`+
+// `(${keyDamageAttribute})*1.5)[Key Attribute]+${featBonusToDamage}[Feat]+${weaponEnhancement}[Magic]+((`+
+// `0?{Focus Points Spent})*3)[Focus]]]}}`;
+// }
+// if (twoHandedToggle !== "on"){
+// macroRoll = macroRoll + `{{Damage=[[[[${dieQuantity}+(0?{Focus Points Spent})]]${dieType}+floor(`+
+// `${keyDamageAttribute})[Key Attribute]+${featBonusToDamage}[Feat]+${weaponEnhancement}[Magic]+((0?{`+
+// `Focus Points Spent})*3)[Focus]]]}}`;
+// }
+// if (magicDice){
+// macroRoll = macroRoll + `{{${magicDamageType} Damage=[[${magicDice}[${magicDamageType}]]]}}`;
+// }
+// macroRoll = macroRoll + `{{Critical Confirmation Roll=[[1d20cs>${minCritThreshold}+${baseAttack}`+
+// `[BAB]+${keyAttackAttribute}[Key Attribute]+${featBonusToAttack}[Feats]+${weaponEnhancement}[Enhancement]`+
+// `-@{slow}[Slow]+((0?{Focus Points Spent})*3)[Focus]+(0?{Miscellaneous attack bonuses?})[Misc.]]]}}`;
+// if (twoHandedToggle === "on"){
+// macroRoll = macroRoll + `{{Critical Damage=[[[[((${dieQuantity}+(0?{Focus Points Spent}))*${criticalModifier})]]`+
+// `${dieType}+(floor(${keyDamageAttribute}*1.5)*${criticalModifier})[Key Attribute]+(`+
+// `${featBonusToDamage}*${criticalModifier}[Feat])+(${weaponEnhancement}*${criticalModifier})+(((0?{Focus`+
+// ` Points Spent})*3)*${criticalModifier})[Focus]]]}}`;
+// }
+// if (twoHandedToggle !== "on"){
+// macroRoll = macroRoll + `{{Critical Damage=[[[[((${dieQuantity}+(0?{Focus Points Spent}))*${criticalModifier})]]`+
+// `${dieType}+(${keyDamageAttribute}*${criticalModifier})[Key Attribute]+(`+
+// `${featBonusToDamage}*${criticalModifier}[Feat])+(${weaponEnhancement}*${criticalModifier})+(((0?{Focus`+
+// ` Points Spent})*3)*${criticalModifier})[Focus]]]}}`;
+// }
+// if (magicCriticalDice){
+// macroRoll = macroRoll + `{{Bonus Critical Damage = [[${magicCriticalDice}]]}}`
+// }
+// startRoll(macroRoll,function(roll){
+// finishRoll(roll.rollId);
+// });
+// });
+// });
+// })
//
+ //
+ const CURRENT_SHEET_VERSION = 1;
+
+ on("sheet:opened", function() {
+ getAttrs(["sheet_version"], function(values) {
+ const sheetVersion = int(values, "sheet_version", 0);
+ if(sheetVersion < CURRENT_SHEET_VERSION) {
+ // Future migrations go here.
+
+ setAttrs({
+ sheet_version: CURRENT_SHEET_VERSION
+ });
+ }
+ });
+ });
+ //
+
\ No newline at end of file