big chunk of rollCheck work, + reloading

This commit is contained in:
Chris Schmalz
2023-09-17 03:05:10 -07:00
parent f68d062cd0
commit 14dcb8b686
2 changed files with 364 additions and 539 deletions
+7 -36
View File
@@ -304,31 +304,23 @@ export class MothershipActorSheet extends ActorSheet {
weapon.sheet.render(true);
});
// Rollable Attribute
html.find('.stat-roll').click(ev => {
const div = $(ev.currentTarget);
const statName = div.data("key");
const attribute = this.actor.system.stats[statName];
var shifted = false;
if (ev.shiftKey) shifted = true;
this.actor.rollStat(attribute, shifted);
this.actor.rollCheck(null,'low',statName,null,null);
});
// Rollable Skill
html.find('.skill-roll').click(ev => {
const li = event.currentTarget.closest(".item");
this.actor.rollSkill(li.dataset.itemId, {
event: event
});
this.actor.rollCheck(null,null,null,li.dataset.itemId,null);
});
// Rollable Weapon
html.find('.weapon-roll').click(ev => {
const li = ev.currentTarget.closest(".item");
this.actor.rollWeapon(li.dataset.itemId, {
event: ev
});
this.actor.rollCheck(null,'low','combat',null,li.dataset.itemId);
});
// Rollable Item/Anything with a description that we want to click on.
@@ -339,11 +331,11 @@ export class MothershipActorSheet extends ActorSheet {
});
});
//increase ammo
html.on('mousedown', '.weapon-ammo', ev => {
const li = ev.currentTarget.closest(".item");
const item = duplicate(this.actor.getEmbeddedDocument("Item", li.dataset.itemId))
let amount = item.system.ammo;
if (event.button == 0) {
if (amount >= 0) {
item.system.ammo = Number(amount) + 1;
@@ -353,35 +345,13 @@ export class MothershipActorSheet extends ActorSheet {
item.system.ammo = Number(amount) - 1;
}
}
this.actor.updateEmbeddedDocuments('Item', [item]);
});
//Reload Shots
html.on('mousedown', '.weapon-reload', ev => {
const li = ev.currentTarget.closest(".item");
const item = duplicate(this.actor.getEmbeddedDocument("Item", li.dataset.itemId))
if (!item.system.useAmmo) {
item.system.curShots = item.system.shots;
} else {
item.system.ammo += item.system.curShots;
let reloadAmount = Math.min(item.system.ammo, item.system.shots);
item.system.curShots = reloadAmount;
item.system.ammo -= reloadAmount;
}
this.actor.updateEmbeddedDocuments('Item', [item]);
let actor = this.actor;
let speaker = ChatMessage.getSpeaker({ actor });
ChatMessage.create({
speaker,
content: `Reloading ` + item.name + "..."
},
{ chatBubble: true });
this.actor.reloadWeapon(li.dataset.itemId);
});
// Rollable Item/Anything with a description that we want to click on.
@@ -390,6 +360,7 @@ export class MothershipActorSheet extends ActorSheet {
attribute.label = "Calm";
this.actor.rollStress(attribute);
});
// Rollable Item/Anything with a description that we want to click on.
html.find('.stress-roll').click(ev => {
//roll hotbar macro for stress
+357 -503
View File
@@ -240,7 +240,6 @@ export class MothershipActor extends Actor {
}
//central roll parsing function | TAKES rollResult: [Foundry roll object], zeroBased: true, checkCrit: true, rollTarget: 41 | RETURNS enriched Foundry roll object
//IN PROGRESS, still translating from macro
parseRollResult(rollString,rollResult,zeroBased,checkCrit,rollTarget,comparison) {
//init vars
let doubles = new Set([0, 11, 22, 33, 44, 55, 66, 77, 88, 99]);
@@ -541,223 +540,328 @@ export class MothershipActor extends Actor {
await game.dice3d.waitFor3DAnimationByMessageID(chatId);
}
/* rollStatSelect(statList) { //REMOVEME? candidate for removal
let selectList = "";
statList.forEach(stat => selectList += "<option value='"+stat[0]+"'>" + stat[1].label + "</option>")
statList.forEach(stat => console.log(stat[0]));
console.log(statList);
let d = new Dialog({
title: "Select Roll Type",
content: "<h2> Stat </h2> <select style='margin-bottom:10px;'name='stat' id='stat'> " + selectList + "</select> <br/>",
//central adding addribute function | TAKES skill | RETURNS player selected attribute
chooseAttribute(rollString,aimFor,attribute,skill,weapon) {
//open dialog asking player to choose a core stat
new Dialog({
title: `Choose a Stat`,
content: `
<style>
.macro_window{
background: rgb(230,230,230);
border-radius: 9px;
}
.macro_img{
display: flex;
justify-content: center; //do I need this
}
.macro_desc{
font-family: "Roboto", sans-serif;
font-size: 10.5pt;
font-weight: 400;
padding-top: 8px;
padding-right: 8px;
padding-bottom: 8px;
}
.grid-2col {
display: grid;
grid-column: span 2 / span 2;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 2px;
padding: 0;
}
</style>
<div class ="macro_window" style="margin-bottom : 7px; padding-left: 8px;">
<div class="macro_desc"><h3>Select a Stat</h3>Choose the Stat that best suits the nature of this Skill Check. You will add your skill bonus to the Stat value for this roll <em>(giving you a higher number to roll under)</em>.</div>
</div>
<label for="str">
<div class ="macro_window" style="margin-bottom : 7px; vertical-align: middle; padding-left: 3px;">
<div class="grid grid-3col" style="grid-template-columns: 20px 60px auto">
<input type="radio" id="str" name="stat" value="strength" checked="checked">
<div class="macro_img" style="padding-top: 5px; padding-left: 0px; padding-right: 0px; padding-bottom: 5px;"><img src="systems/mosh/images/icons/ui/attributes/strength.png" style="border:none"/></div>
<div class="macro_desc" style="display: table;">
<span style="display: table-cell; vertical-align: middle;">
<strong>Strength:</strong> Holding airlocks closed, carrying fallen comrades, climbing, pushing, jumping.
</span>
</div>
</div>
</div>
</label>
<label for="spd">
<div class ="macro_window" style="margin-bottom : 7px; vertical-align: middle; padding-left: 3px;">
<div class="grid grid-3col" style="grid-template-columns: 20px 60px auto">
<input type="radio" id="spd" name="stat" value="speed">
<div class="macro_img" style="padding-top: 5px; padding-left: 0px; padding-right: 0px; padding-bottom: 5px;"><img src="systems/mosh/images/icons/ui/attributes/speed.png" style="border:none"/></div>
<div class="macro_desc" style="display: table;">
<span style="display: table-cell; vertical-align: middle;">
<strong>Speed:</strong> Getting out of the cargo bay before the blast doors close, acting before someone <em>(or something)</em> else, running away.
</span>
</div>
</div>
</div>
</label>
<label for="int">
<div class ="macro_window" style="margin-bottom : 7px; vertical-align: middle; padding-left: 3px;">
<div class="grid grid-3col" style="grid-template-columns: 20px 60px auto">
<input type="radio" id="int" name="stat" value="intellect">
<div class="macro_img" style="padding-top: 5px; padding-left: 0px; padding-right: 0px; padding-bottom: 5px;"><img src="systems/mosh/images/icons/ui/attributes/intellect.png" style="border:none"/></div>
<div class="macro_desc" style="display: table;">
<span style="display: table-cell; vertical-align: middle;">
<strong>Intellect:</strong> Recalling your training and experience under duress, thinking through difficult problems, inventing or fixing things.
</span>
</div>
</div>
</div>
</label>
<label for="com">
<div class ="macro_window" style="margin-bottom : 7px; vertical-align: middle; padding-left: 3px;">
<div class="grid grid-3col" style="grid-template-columns: 20px 60px auto">
<input type="radio" id="com" name="stat" value="combat">
<div class="macro_img" style="padding-top: 5px; padding-left: 0px; padding-right: 0px; padding-bottom: 5px;"><img src="systems/mosh/images/icons/ui/attributes/combat.png" style="border:none"/></div>
<div class="macro_desc" style="display: table;">
<span style="display: table-cell; vertical-align: middle;">
<strong>Combat:</strong> Fighting for your life.
</span>
</div>
</div>
</div>
</label>
`,
buttons: {
roll: {
icon: '<i class="fas fa-check"></i>',
label: "Roll",
callback: (html) => this.rollStat(this.system.stats[html.find('[id=\"stat\"]')[0].value])
button1: {
label: `Advantage`,
callback: (html) => this.rollCheck(`1d100 [+]`,`low`,html.find("input[name='stat']:checked").attr("value"),skill,weapon),
icon: `<i class="fas fa-angle-double-up"></i>`
},
cancel: {
icon: '<i class="fas fa-times"></i>',
label: "Cancel",
callback: () => { }
}
},
default: "roll",
close: () => { }
});
d.render(true);
} */
/* rollStat(attribute, shifted = false) { //REMOVEME? candidate for removal
console.log(attribute);
let attLabel = attribute.label?.charAt(0).toUpperCase() + attribute.label?.toLowerCase().slice(1);
if (!attribute.label && isNaN(attLabel))
attLabel = attribute.charAt(0)?.toUpperCase() + attribute.toLowerCase().slice(1);
//this.rollAttribute(attribute, "none");
if(shifted){
this.rollAttribute(attribute, 'None');
}
else {
let d = new Dialog({
title: "Select Roll Type",
content: "<h2> Advantages/Disadvantage </h2> <select style='margin-bottom:10px;'name='advantage' id='advantage'> <option value='none'>None</option> <option value='advantage'>Advantage/Disadvantage</option></select> <br/>",
buttons: {
roll: {
icon: '<i class="fas fa-check"></i>',
label: "Roll",
callback: (html) => this.rollAttribute(attribute, html.find('[id=\"advantage\"]')[0].value)
},
cancel: {
icon: '<i class="fas fa-times"></i>',
label: "Cancel",
callback: () => { }
}
button2: {
label: `Normal`,
callback: (html) => this.rollCheck(`1d100`,`low`,html.find("input[name='stat']:checked").attr("value"),skill,weapon),
icon: `<i class="fas fa-minus"></i>`
},
default: "roll",
close: () => { }
});
d.render(true);
}
} */
/* rollStress(attribute) { //REMOVEME? candidate for removal
//this.rollAttribute(attribute, "none");
let rollOver = true;
if (attribute.label == "Calm")
rollOver = false;
let attLabel = attribute.label?.charAt(0).toUpperCase() + attribute.label?.toLowerCase().slice(1);
if (!attribute.label && isNaN(attLabel))
attLabel = attribute.charAt(0)?.toUpperCase() + attribute.toLowerCase().slice(1);
let d = new Dialog({
title: "Select Roll Type",
content: "<h2> Advantages/Disadvantage </h2> <select style='margin-bottom:10px;'name='advantage' id='advantage'> <option value='none'>None</option> <option value='advantage'>Advantage/Disadvantage</option></select> <br/>",
buttons: {
roll: {
icon: '<i class="fas fa-check"></i>',
label: "Roll",
callback: (html) => this.rollAttribute(attribute, html.find('[id=\"advantage\"]')[0].value, '', rollOver)
},
cancel: {
icon: '<i class="fas fa-times"></i>',
label: "Cancel",
callback: () => { }
}
},
default: "roll",
close: () => { }
});
d.render(true);
} */
/* rollWeapon(itemId, options = { event: null }) { //REMOVEME? candidate for removal
let item = duplicate(this.getEmbeddedDocument("Item",itemId));
console.log(item);
if (item.system.useAmmo == true || item.system.shots > 0) {
if (item.system.shots == 0) {
if (item.system.ammo > 0) {
item.system.ammo -= 1;
this.updateEmbeddedDocuments('Item', [item]);
} else {
//Select the stat of the roll.
let t = new Dialog({
title: "Reload",
content: "<h2>Out of Ammo</h2><br/>",
buttons: {
cancel: {
icon: '<i class="fas fa-times"></i>',
label: "Cancel",
callback: () => { }
}
},
default: "roll",
close: () => { }
});
t.render(true);
return;
}
} else {
if (item.system.curShots > 0) {
let subAmount = Math.max(item.system.shotsPerFire, 1);
item.system.curShots = Math.max(item.system.curShots - subAmount, 0);
console.log("Unloading Shots");
this.updateEmbeddedDocuments('Item', [item]);
}
else {
if (item.system.ammo > 0 || !item.system.useAmmo) {
//Select the stat of the roll.
let t = new Dialog({
title: "Reload",
content: "<h2> Reload? </h2><br/>",
buttons: {
roll: {
icon: '<i class="fas fa-check"></i>',
label: "Reload",
callback: (html) => this.reloadWeapon(itemId)
},
cancel: {
icon: '<i class="fas fa-times"></i>',
label: "Cancel",
callback: () => { }
}
},
default: "roll",
close: () => { }
});
t.render(true);
} else {
//Select the stat of the roll.
let t = new Dialog({
title: "Reload",
content: "<h2>Out of Ammo</h2><br/>",
buttons: {
cancel: {
icon: '<i class="fas fa-times"></i>',
label: "Cancel",
callback: () => { }
}
},
default: "roll",
close: () => { }
});
t.render(true);
}
// let actor = this;
// let speaker = ChatMessage.getSpeaker({ actor });
// ChatMessage.create({
// speaker,
// content: item.system.ammo > 0 ? `I need to reload my ` + item.name + "!" : "I'm out of ammo!",
// type: CHAT_MESSAGE_TYPES.EMOTE
// },
// { chatBubble: true });
return;
button3: {
label: `Disadvantage`,
callback: (html) => this.rollCheck(`1d100 [-]`,`low`,html.find("input[name='stat']:checked").attr("value"),skill,weapon),
icon: `<i class="fas fa-angle-double-down"></i>`
}
}
}
},{width: 600,height: 475}).render(true);
}
//central adding skill function | TAKES nothing | RETURNS player selected skill
chooseSkill(rollString,aimFor,attribute,skill,weapon) {
//get list of player skills
let playerItems = this.items;
//create header for skill list
let skillHeader = `
<style>
.macro_window{
background: rgb(230,230,230);
border-radius: 9px;
}
.macro_img{
display: flex;
justify-content: center; //do I need this
}
.macro_desc{
font-family: "Roboto", sans-serif;
font-size: 10.5pt;
font-weight: 400;
padding-left: 8px;
padding-top: 8px;
padding-right: 8px;
padding-bottom: 8px;
}
.grid-2col {
display: grid;
grid-column: span 2 / span 2;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 2px;
padding: 0;
}
</style>
<div class ="macro_window" style="margin-bottom : 7px;">
<div class="macro_desc"><h3>Add a Skill?</h3>If you have a Skill that is relevant to the task at hand, you can add the Skill’s bonus to your Stat or Save before making your roll <em>(giving you a higher number to roll under)</em>.</div>
</div>`;
//create footer for skill list
const skillFooter = `<h4>Select your roll type:</h4>`;
//create template for skill row
const skillRow = `
<label for="[RADIO_ID]">
<div class ="macro_window" style="margin-bottom : 7px; vertical-align: middle; padding-left: 3px;">
<div class="grid grid-3col" style="grid-template-columns: 20px 60px auto">
<input type="radio" id="[RADIO_ID]" name="skill" value="[RADIO_VALUE]">
<div class="macro_img" style="padding-top: 5px; padding-left: 0px; padding-right: 0px; padding-bottom: 5px;"><img src="[RADIO_IMG]" style="border:none"/></div>
<div class="macro_desc" style="display: table;">
<span style="display: table-cell; vertical-align: middle;">
[RADIO_NAME][RADIO_DESC]
</span>
</div>
</div>
</div>
</label>`;
//create skillList string
let skillList = ``;
//create skill counter
let skillCount = 0;
//create dialog pixel counter
let dialogHeight = 192;
//loop through and create skill rows
for (let item of playerItems) {
//check if this is a skill
if (item.type === "skill") {
//set temprow as template
let tempRow = skillRow;
//replace ID
tempRow = tempRow.replaceAll("[RADIO_ID]",item.name);
//replace value
tempRow = tempRow.replace("[RADIO_VALUE]",item.system.bonus);
//replace img
tempRow = tempRow.replace("[RADIO_IMG]",item.img);
//replace name
tempRow = tempRow.replace("[RADIO_NAME]",item.name);
//replace desc
tempRow = tempRow.replace("[RADIO_DESC]",item.system.description.replace("<p>","<p><strong>:</strong> "));
//add to skillList
skillList = skillList + tempRow;
//increment skill count
skillCount++;
//increment pixel counter
dialogHeight = dialogHeight + 77;
}
}
//check if there are no skills, and adjust prompt accordingly
if (skillCount === 0) {
//set window height
dialogHeight = 105;
//make skill header blank
skillHeader = ``;
}
//make content string
let skillHtml = skillHeader + skillList + skillFooter;
//make window setting
let dlgTitle = '';
if (attribute === 'sanity' || attribute === 'fear' || attribute === 'body') {
dlgTitle = `Save`;
} else if (weapon) {
dlgTitle = `Attack`;
} else {
dlgTitle = `Stat Check`;
}
//Select the stat of the roll.
let t = new Dialog({
title: "Select Stat",
content: "<h2> Advantage/Disadvantage </h2> <select style='margin-bottom:10px;'name='advantage' id='advantage'>\
<option value='none'>None</option>\
<option value='advantage'>Advantage/Disadvantage</option>\
</select> <br/>\
\
<h2> Skill Bonus </h2> <input style='margin-bottom:10px;' name='bonus' id='bonus' value='"+item.system.bonus+"'></input><br/>",
buttons: {
roll: {
icon: '<i class="fas fa-check"></i>',
label: "Roll",
callback: (html) => this.rollAttribute(this.system.stats["combat"], html.find('[id=\"advantage\"]')[0].value, item, false, html.find('[id=\"bonus\"]')[0].value)
},
cancel: {
icon: '<i class="fas fa-times"></i>',
label: "Cancel",
callback: () => { }
}
},
default: "roll",
close: () => { }
});
t.render(true);
} */
new Dialog({
title: dlgTitle,
content: skillHtml,
buttons: {
button1: {
label: `Advantage`,
callback: (html) => this.rollCheck(`1d100 [+]`,aimFor,attribute,html.find("input[name='skill']:checked").attr("id"),weapon),
icon: `<i class="fas fa-angle-double-up"></i>`
},
button2: {
label: `Normal`,
callback: (html) => this.rollCheck(`1d100`,aimFor,attribute,html.find("input[name='skill']:checked").attr("id"),weapon),
icon: `<i class="fas fa-minus"></i>`
},
button3: {
label: `Disadvantage`,
callback: (html) => this.rollCheck(`1d100 [-]`,aimFor,attribute,html.find("input[name='skill']:checked").attr("id"),weapon),
icon: `<i class="fas fa-angle-double-down"></i>`
}
}
},{width: 600,height: dialogHeight}).render(true);
}
//central adding skill function | TAKES nothing | RETURNS player selected skill
chooseAdvantage(rollString,aimFor,attribute,skill,weapon) {
//create footer for skill list
let advHtml = `<h4>Select your roll type:</h4>`;
//make window setting
let dlgTitle = '';
if (attribute === 'sanity' || attribute === 'fear' || attribute === 'body') {
dlgTitle = `Save`;
} else if (weapon) {
dlgTitle = `Attack`;
} else {
dlgTitle = `Stat Check`;
}
//Select the stat of the roll.
new Dialog({
title: dlgTitle,
content: advHtml,
buttons: {
button1: {
label: `Advantage`,
callback: (html) => this.rollCheck(`1d100 [+]`,aimFor,attribute,skill,weapon),
icon: `<i class="fas fa-angle-double-up"></i>`
},
button2: {
label: `Normal`,
callback: (html) => this.rollCheck(`1d100`,aimFor,attribute,skill,weapon),
icon: `<i class="fas fa-minus"></i>`
},
button3: {
label: `Disadvantage`,
callback: (html) => this.rollCheck(`1d100 [-]`,aimFor,attribute,skill,weapon),
icon: `<i class="fas fa-angle-double-down"></i>`
}
}
},{width: 600,height: 105}).render(true);
}
//central check rolling function | TAKES attribute: [attribute object], skill: [skill item], attack: true, weapon: [weapon item] | RETURNS chat message showing check result
//IN PROGRESS, CONVERTING FROM MOD
async rollCheck(rollString,aimFor,attribute,skill,weapon) {
//first we need to bounce this request away if certain parameters are NULL
//if attribute is blank, redirect player to choose an attribute
if (attribute === undefined) {
//run the choose attribute function
this.chooseAttribute(rollString,aimFor,attribute,skill,weapon);
//exit function
return;
}
//if skill is blank and actor is a character, redirect player to choose a skill
if (skill === undefined && this.actor.type === 'character') {
//run the choose attribute function
this.chooseSkill(rollString,aimFor,attribute,skill,weapon);
//exit function
return;
}
//if rollString is STILL blank, redirect player to choose the roll
if (rollString === undefined) {
//run the choose attribute function
this.chooseAdvantage(rollString,aimFor,attribute,skill,weapon);
//exit function
return;
}
//roll the dice
//parse the roll string
let parsedRollString = this.parseRollString(rollString,aimFor);
//roll the dice
let rollResult = await new Roll(parsedRollString).evaluate();
//interpret the results
let parsedRollResult = this.parseRollResult(rollString,rollResult,zeroBased,checkCrit,rollTarget,comparison);
//all sorts of stuff
//I LEFT OFF HERE :)///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//push chat message
//make message
let macroMsg = await rollResult.toMessage({
id: chatId,
user: game.user.id,
speaker: {actor: this.id, token: this.token, alias: this.name},
content: messageTemplate
},{keepId:true});
//make dice
await game.dice3d.waitFor3DAnimationByMessageID(chatId);
}
reloadWeapon(itemId, options = { event: null }) {
//dupe item to work with
let item = duplicate(this.getEmbeddedDocument("Item",itemId));
//reload
if (event.button == 0) {
if (!item.system.useAmmo) {
item.system.curShots = item.system.shots;
@@ -765,312 +869,62 @@ export class MothershipActor extends Actor {
item.system.ammo += item.system.curShots;
let reloadAmount = Math.min(item.system.ammo, item.system.shots);
item.system.curShots = reloadAmount;
item.system.ammo -= reloadAmount;
}
}
//update the item
this.updateEmbeddedDocuments('Item', [item]);
//define macroresult
let macroResult = '';
//create chat message template
if (item.name.length >= 22) {
macroResult = `
<div class="mosh">
<div class="rollcontainer">
<div class="flexrow" style="margin-bottom : 5px;">
<div class="rollweaponh1" style="font-size: 0.75rem; padding-top: 7px;">${item.name}</div>
<div style="text-align: right"><img class="roll-image" src="${item.img}" /></div>
</div>
<div class="description">
<div class="body">Weapon reloaded.</div>
</div>
<div style="margin-bottom : 16px;"></div>
</div>
</div>
`;
} else {
macroResult = `
<div class="mosh">
<div class="rollcontainer">
<div class="flexrow" style="margin-bottom : 5px;">
<div class="rollweaponh1">${item.name}</div>
<div style="text-align: right"><img class="roll-image" src="modules/fvtt_mosh_1e_psg/icons/macros/reload.png" /></div>
</div>
<div class="description">
<div class="body">Weapon reloaded.</div>
</div>
<div style="margin-bottom : 16px;"></div>
</div>
</div>
`;
}
//push message
ChatMessage.create({
user: game.user._id,
speaker: {
actor: this.id,
token: this.token,
alias: this.name
},
content: macroResult
});
}
printDescription(itemId, options = { event: null }) {
let item = duplicate(this.getEmbeddedDocument("Item",itemId));
this.chatDesc(item);
}
/* rollSkill(itemId, options = { event: null }) { //REMOVEME? candidate for removal
let item = duplicate(this.getEmbeddedDocument("Item",itemId));
// let attLabel = skill.label?.charAt(0).toUpperCase() + skill.label?.toLowerCase().slice(1);
// if (!skill.label && isNaN(attLabel))
// attLabel = skill.charAt(0)?.toUpperCase() + item.name.toLowerCase().slice(1);
//this.rollAttribute(attribute, "none");
//Select the stat of the roll.
let t = new Dialog({
title: "Select Stat",
content: "<h2> Stat </h2> <select style='margin-bottom:10px;'name='stat' id='stat'>\
<option value='strength'>Strength</option>\
<option value='speed'>Speed</option>\
<option value='intellect'>Intellect</option>\
<option value='combat'>Combat</option>\
</select> <br/>\
<h2> Advantage/Disadvantage </h2> <select style='margin-bottom:10px;'name='advantage' id='advantage'>\
<option value='none'>None</option>\
<option value='advantage'>Advantage/Disadvantage</option>\
</select> <br/>",
buttons: {
roll: {
icon: '<i class="fas fa-check"></i>',
label: "Roll",
callback: (html) => this.rollAttribute(this.system.stats[html.find('[id=\"stat\"]')[0].value], html.find('[id=\"advantage\"]')[0].value, item)
},
cancel: {
icon: '<i class="fas fa-times"></i>',
label: "Cancel",
callback: () => { }
}
},
default: "roll",
close: () => { }
});
t.render(true);
} */
/* async rollAttribute(attribute, advantage, item = "", rollOver = false, bonus = 0) { //REMOVEME? candidate for removal
let attributeName = attribute.label?.charAt(0).toUpperCase() + attribute.label?.toLowerCase().slice(1);
if (!attribute.label && isNaN(attributeName))
attributeName = attribute.charAt(0)?.toUpperCase() + attribute.toLowerCase().slice(1);
let isStress = (attribute.label == "Stress" ? true : false);
// Roll
let firstEdition = game.settings.get("mosh", "firstEdition");
let diceformular = (isStress ? (firstEdition ? "1d20" : "2d10") : "1d100");
if(isNaN(bonus)){
bonus = 0;
item.system.bonus = 0;
}
// if (advantage != undefined && advantage != NaN && advantage != 0) {
// diceformular = diceformular + "+" + advantage + "d6kh";
// }
let r = new Roll(diceformular, {});
r.evaluate({async: false});
let rSplit = ("" + r._total).split("");
//Advantage roll
let a = new Roll(diceformular, {});
a.evaluate({async: false});
if (r._total == 100) {
//r.results[0] = 0;
r._total = 0;
}
if (a._total == 100) {
//a.results[0] = 0;
a._total = 0;
}
let range = "N/A";
let damageRoll = 0;
if (item.type == "weapon") {
if(item.system.damage.includes("[+]")){
var newRoll = item.system.damage.replace("[+]", "");
newRoll = "{"+newRoll+", "+newRoll+"}kh";
console.log(newRoll);
damageRoll = new Roll(newRoll);
} else if(item.system.damage.includes("[-]")){
var newRoll = item.system.damage.replace("[-]", "");
newRoll = "{"+newRoll+", "+newRoll+"}kl";
console.log(newRoll);
damageRoll = new Roll(newRoll);
}
else {
damageRoll = new Roll(item.system.damage);
}
damageRoll.evaluate({async: false});
range = item.system.ranges.value;
}
// Format Dice
const diceData = this.formatDice(r);
let mod = 0;
if(item.type == "skill"){
mod += item.system.bonus;
}
if (attribute.mod != 0) mod += attribute.mod;
if(isNaN(mod)) mod = 0;
let targetValue = attribute.value + mod + (item == "" ? 0 : parseInt(bonus));
let critical = false;
if (r._total == 0 && !isStress || rSplit[0] == rSplit[1] && !isStress)
critical = true;
let panic = false;
let panicText = '';
if(isStress && r._total <= attribute.value && firstEdition){
await(async () => {
// const contents = await game.packs.get("Tables").getContent();
// const table= contents.find(i => i.name === `Panic`);
let tableLocation = game.settings.get("mosh", "panicTable");
const documentIndex = game.packs.get(tableLocation).index.getName("Panic");
const doc = await game.packs.get(tableLocation).getDocument(documentIndex._id);
panic = true;
panicText = doc.getResultsForRoll(r._total)[0].data.text;
//then just put your normal table rolling command using `table`
})()
}
//Here's where we handle the result text.
let resultText = "";
if (rollOver == true) {
if (critical)
resultText = (r._total > targetValue ? "Critical Success" : "Critical Failure");
else
resultText = (r._total > targetValue ? "Success" : "Failure");
} else {
if (critical)
resultText = (r._total < targetValue ? "Critical Success" : "Critical Failure");
else
resultText = (r._total < targetValue ? "Success" : "Failure");
}
var templateData = {
actor: this,
stat: {
name: attributeName.toUpperCase()
},
data: {
diceTotal: {
value: r._total,
advantageValue: a._total,
damageValue: damageRoll._total,
damageRoll: damageRoll
},
resultText: {
value: resultText
},
isCreature: {
value: this.type == "creature" ? true : false
},
panic: panic,
panicText : panicText
},
target: attribute.value,
mod: mod,
item: item,
targetValue: targetValue,
useSkill: item.type == "skill" ? true : false,
isWeapon: item.type == "weapon" ? true : false,
range: range,
critical: critical,
advantage: advantage == "advantage" ? true : false,
bonus: bonus,
diceData
};
let chatData = {
user: game.user.id,
speaker: {
actor: this.id,
token: this.token,
alias: this.name
}
};
let rollMode = game.settings.get("core", "rollMode");
if (["gmroll", "blindroll"].includes(rollMode)) chatData["whisper"] = ChatMessage.getWhisperRecipients("GM");
//comment this out:
if (this.data.type == "creature") {
chatData.whisper = game.user._id;
}
let template = 'systems/mosh/templates/chat/statroll.html';
renderTemplate(template, templateData).then(content => {
chatData.content = content;
if (game.dice3d) {
if(!damageRoll)
game.dice3d.showForRoll(r, game.user, true, chatData.whisper, chatData.blind).then(displayed => ChatMessage.create(chatData));
else
game.dice3d.showForRoll(damageRoll, game.user, true, chatData.whisper, chatData.blind).then(displayed => ChatMessage.create(chatData));
} else {
chatData.sound = CONFIG.sounds.dice;
ChatMessage.create(chatData);
}
});
} */
/* formatDice(diceRoll) { //REMOVEME? candidate for removal
let diceData = { dice: [] };
if (diceRoll != null) {
let pushDice = (diceData, total, faces, color) => {
let img = null;
if ([4, 6, 8, 10, 12, 20].indexOf(faces) > -1) {
img = `../icons/svg/d${faces}-grey.svg`;
}
diceData.dice.push({
img: img,
result: total,
dice: true,
color: color
});
};
for (let i = 0; i < diceRoll.terms.length; i++) {
if (diceRoll.terms[i] instanceof Die) {
let pool = diceRoll.terms[i].results;
let faces = diceRoll.terms[i].faces;
pool.forEach((pooldie) => {
if (pooldie.discarded) {
pushDice(diceData, pooldie.result, faces, "#777");
} else {
pushDice(diceData, pooldie.result, faces, "white");
}
});
} else if (typeof diceRoll.terms[i] == 'string') {
const parsed = parseInt(diceRoll.terms[i]);
if (!isNaN(parsed)) {
diceData.dice.push({
img: null,
result: parsed,
dice: false,
color: 'white'
});
} else {
diceData.dice.push({
img: null,
result: diceRoll.terms[i],
dice: false
});
}
}
else if (typeof diceRoll.terms[i] == 'number') {
const parsed = parseInt(diceRoll.terms[i]);
if (!isNaN(parsed)) {
diceData.dice.push({
img: null,
result: parsed,
dice: false,
color: 'white'
});
} else {
diceData.dice.push({
img: null,
result: diceRoll.terms[i],
dice: false
});
}
}
}
}
return diceData;
} */
// Print the item description into the chat.
chatDesc(item) {
let itemName = item.name?.charAt(0).toUpperCase() + item.name?.toLowerCase().slice(1);