fix autofixable ESLint errors and format js files

This commit is contained in:
jalensailin
2023-09-28 22:54:24 -04:00
parent bb32f9e2d6
commit 5d95aeb98b
10 changed files with 1515 additions and 1087 deletions
File diff suppressed because it is too large Load Diff
+180 -180
View File
@@ -3,7 +3,6 @@
* @extends {Actor}
*/
export class DeltaGreenActor extends Actor {
/**
* Augment the basic actor data with additional dynamic data.
*/
@@ -11,41 +10,38 @@ export class DeltaGreenActor extends Actor {
super.prepareData();
const actorData = this;
const system = actorData.system;
const flags = actorData.flags;
const { system } = actorData;
const { flags } = actorData;
//console.log('actor.js prepareData');
//console.log(this);
// console.log('actor.js prepareData');
// console.log(this);
// Make separate methods for each Actor type (character, npc, etc.) to keep
// things organized.
if (actorData.type === 'agent'){
if (actorData.type === "agent") {
this._prepareAgentData(this);
}
else if(actorData.type === 'unnatural'){
} else if (actorData.type === "unnatural") {
this._prepareUnnaturalData(this);
}
else if(actorData.type === 'npc'){
} else if (actorData.type === "npc") {
this._prepareNpcData(this);
}
else if(actorData.type === 'vehicle'){
} else if (actorData.type === "vehicle") {
this._prepareVehicleData(this);
}
}
/**
*
* @param {*} agent
*
* @param {*} agent
*/
_prepareVehicleData(actor){
let actorData = actor;
_prepareVehicleData(actor) {
const actorData = actor;
// calculate total armor rating
// calculate total armor rating
let protection = 0;
for (let i of actor.items) {
if (i.type === 'armor') {
if(i.system.equipped === true){
for (const i of actor.items) {
if (i.type === "armor") {
if (i.system.equipped === true) {
protection += i.system.protection;
}
}
@@ -56,74 +52,76 @@ export class DeltaGreenActor extends Actor {
console.log(actor);
}
_prepareNpcData(actor){
const { system } = actor;
// Loop through ability scores, and add their modifiers to our sheet output.
for (let [key, statistic] of Object.entries(system.statistics)) {
// the x5 is just whatever the raw statistic is x 5 to turn it into a d100 percentile
statistic.x5 = statistic.value * 5;
}
// initialize sanity, don't set these afterwards, as they need to be manually edited
if(system.sanity.value >= 100){
system.sanity.value = system.statistics.pow.x5
system.sanity.currentBreakingPoint = system.sanity.value - system.statistics.pow.value;
};
system.sanity.max = 99 - system.skills.unnatural.proficiency;
system.wp.max = system.statistics.pow.value;
system.health.max = Math.ceil((system.statistics.con.value + system.statistics.str.value) / 2);
system.skills.ritual = {
label: "Ritual",
proficiency: 99 - system.sanity.value,
cannotBeImprovedByFailure: true,
failure: false
};
if(system.skills.ritual.proficiency > 99){
system.skills.ritual.proficiency = 99
}
else if(system.skills.ritual.proficiency < 1){
system.skills.ritual.proficiency = 1
}
// calculate total armor rating
let protection = 0;
for (let i of actor.items) {
if (i.type === 'armor') {
if(i.system.equipped === true){
protection += i.system.protection;
}
}
}
system.health.protection = protection;
console.log(actor);
}
/**
*
* @param {*} agent
*/
_prepareUnnaturalData(actor){
_prepareNpcData(actor) {
const { system } = actor;
// Loop through ability scores, and add their modifiers to our sheet output.
for (let [key, statistic] of Object.entries(system.statistics)) {
for (const [key, statistic] of Object.entries(system.statistics)) {
// the x5 is just whatever the raw statistic is x 5 to turn it into a d100 percentile
statistic.x5 = statistic.value * 5;
}
// initialize sanity, don't set these afterwards, as they need to be manually edited
if (system.sanity.value >= 100) {
system.sanity.value = system.statistics.pow.x5;
system.sanity.currentBreakingPoint =
system.sanity.value - system.statistics.pow.value;
}
system.sanity.max = 99 - system.skills.unnatural.proficiency;
system.wp.max = system.statistics.pow.value;
system.health.max = Math.ceil(
(system.statistics.con.value + system.statistics.str.value) / 2,
);
system.skills.ritual = {
label: "Ritual",
proficiency: 99 - system.sanity.value,
cannotBeImprovedByFailure: true,
failure: false,
};
if (system.skills.ritual.proficiency > 99) {
system.skills.ritual.proficiency = 99;
} else if (system.skills.ritual.proficiency < 1) {
system.skills.ritual.proficiency = 1;
}
// calculate total armor rating
let protection = 0;
for (const i of actor.items) {
if (i.type === "armor") {
if (i.system.equipped === true) {
protection += i.system.protection;
}
}
}
system.health.protection = protection;
console.log(actor);
}
/**
*
* @param {*} agent
*/
_prepareUnnaturalData(actor) {
const { system } = actor;
// Loop through ability scores, and add their modifiers to our sheet output.
for (const [key, statistic] of Object.entries(system.statistics)) {
// the x5 is just whatever the raw statistic is x 5 to turn it into a d100 percentile
statistic.x5 = statistic.value * 5;
}
// calculate total armor rating
let protection = 0;
for (let i of actor.items) {
if (i.type === 'armor') {
if(i.system.equipped === true){
for (const i of actor.items) {
if (i.type === "armor") {
if (i.system.equipped === true) {
protection += i.system.protection;
}
}
@@ -138,94 +136,96 @@ export class DeltaGreenActor extends Actor {
* Prepare Agent type specific data
*/
_prepareAgentData(agent) {
const { system } = agent;
// Make modifications to data here. For example:
// Loop through ability scores, and add their modifiers to our sheet output.
for (let [key, statistic] of Object.entries(system.statistics)) {
for (const [key, statistic] of Object.entries(system.statistics)) {
// the x5 is just whatever the raw statistic is x 5 to turn it into a d100 percentile
statistic.x5 = statistic.value * 5;
}
// The ritual skill is from the Handler's Guide, it is for activating a ritual and is always equal to 99 - current sanity.
// The rules can be found on page 166, under 'Ritual Activation'.
system.skills.ritual = {
label: "Ritual",
proficiency: 99 - system.sanity.value,
cannotBeImprovedByFailure: true,
failure: false
failure: false,
};
if(system.skills.ritual.proficiency > 99){
system.skills.ritual.proficiency = 99
}
else if(system.skills.ritual.proficiency < 1){
system.skills.ritual.proficiency = 1
if (system.skills.ritual.proficiency > 99) {
system.skills.ritual.proficiency = 99;
} else if (system.skills.ritual.proficiency < 1) {
system.skills.ritual.proficiency = 1;
}
// The unnatural skill is sort of special
// It cannot be improved via failure, so add in a special property to reflect this
// Mostly to make it easy to deactivate the failure checkbox in the GUI
for (let [key, skill] of Object.entries(system.skills)){
if(key === 'unnatural'){
for (const [key, skill] of Object.entries(system.skills)) {
if (key === "unnatural") {
skill.cannotBeImprovedByFailure = true;
}
else if(key === 'luck'){
} else if (key === "luck") {
skill.cannotBeImprovedByFailure = true;
}
else if(key === 'ritual'){
} else if (key === "ritual") {
skill.cannotBeImprovedByFailure = true;
}
else{
} else {
skill.cannotBeImprovedByFailure = false;
}
// For ritual skill, it's calculated, so add some logic to turn off changing that entirely.
if(key === 'ritual'){
if (key === "ritual") {
skill.isCalculatedValue = true;
}
else{
} else {
skill.isCalculatedValue = false;
}
}
system.wp.max = system.statistics.pow.value;
system.health.max = Math.ceil((system.statistics.con.value + system.statistics.str.value) / 2);
system.health.max = Math.ceil(
(system.statistics.con.value + system.statistics.str.value) / 2,
);
// initialize sanity, don't set these afterwards, as they need to be manually edited
if(system.sanity.value >= 100){
system.sanity.value = system.statistics.pow.x5
system.sanity.currentBreakingPoint = system.sanity.value - system.statistics.pow.value;
};
if (system.sanity.value >= 100) {
system.sanity.value = system.statistics.pow.x5;
system.sanity.currentBreakingPoint =
system.sanity.value - system.statistics.pow.value;
}
system.sanity.max = 99 - system.skills.unnatural.proficiency;
// Sanity Loss Adaptations Logic
let adaptations = system.sanity.adaptations;
const { adaptations } = system.sanity;
if (adaptations.violence.incident1 && adaptations.violence.incident2 && adaptations.violence.incident3){
if (
adaptations.violence.incident1 &&
adaptations.violence.incident2 &&
adaptations.violence.incident3
) {
system.sanity.adaptations.violence.isAdapted = true;
}
else{
} else {
system.sanity.adaptations.violence.isAdapted = false;
}
if (adaptations.helplessness.incident1 && adaptations.helplessness.incident2 && adaptations.helplessness.incident3){
if (
adaptations.helplessness.incident1 &&
adaptations.helplessness.incident2 &&
adaptations.helplessness.incident3
) {
system.sanity.adaptations.helplessness.isAdapted = true;
}
else{
} else {
system.sanity.adaptations.helplessness.isAdapted = false;
}
// calculate total armor rating
let protection = 0;
for (let i of agent.items) {
if (i.type === 'armor') {
if(i.system.equipped === true){
for (const i of agent.items) {
if (i.type === "armor") {
if (i.system.equipped === true) {
protection += i.system.protection;
}
}
@@ -236,25 +236,22 @@ export class DeltaGreenActor extends Actor {
// Damage Bonus/Malus From Strength in Hand-to-hand Combat (melee/unarmed)
let bonus = 0;
let sbonus = "";
let strength = system.statistics.str;
const strength = system.statistics.str;
if(strength.value < 5){
if (strength.value < 5) {
sbonus = "-2";
bonus = -2;
}
else if(strength.value < 9){
} else if (strength.value < 9) {
sbonus = "-1";
bonus = -1;
}
else if(strength.value > 12 && strength.value < 17){
} else if (strength.value > 12 && strength.value < 17) {
sbonus = "+1";
bonus = 1;
}
else if(strength.value > 16){
} else if (strength.value > 16) {
sbonus = "+2";
bonus = 2;
}
system.statistics.str.meleeDamageBonus = bonus;
system.statistics.str.meleeDamageBonusFormula = sbonus;
@@ -262,95 +259,98 @@ export class DeltaGreenActor extends Actor {
}
/** @override */
static async create(data, options={}) {
static async create(data, options = {}) {
data.prototypeToken = data.prototypeToken || {};
if ( data.type === "agent" ) {
mergeObject(data.prototypeToken, {
actorLink: true // this will make the 'Link Actor Data' option for a token is checked by default. So changes to the token sheet will reflect to the actor sheet.
}, {overwrite: false});
if (data.type === "agent") {
mergeObject(
data.prototypeToken,
{
actorLink: true, // this will make the 'Link Actor Data' option for a token is checked by default. So changes to the token sheet will reflect to the actor sheet.
},
{ overwrite: false },
);
}
return super.create(data, options);
}
async AddUnarmedAttackItemIfMissing(){
try{
async AddUnarmedAttackItemIfMissing() {
try {
let alreadyAdded = false;
for(let item of this.items){
let flag = await item.getFlag('deltagreen', 'SystemName');
for (const item of this.items) {
const flag = await item.getFlag("deltagreen", "SystemName");
if(flag === 'unarmed-attack' || item.name === 'Unarmed Attack'){
if (flag === "unarmed-attack" || item.name === "Unarmed Attack") {
alreadyAdded = true;
break;
}
}
if(alreadyAdded === true){ return; };
if (alreadyAdded === true) {
return;
}
let handToHandPack = await game.packs.get('deltagreen.hand-to-hand-weapons');
let itemIndex = await handToHandPack.getIndex();
let toAdd = []; // createEmbeddedDocument expects an array
const handToHandPack = await game.packs.get(
"deltagreen.hand-to-hand-weapons",
);
const itemIndex = await handToHandPack.getIndex();
const toAdd = []; // createEmbeddedDocument expects an array
for(let idx of itemIndex){
let _temp = await handToHandPack.getDocument(idx._id);
if(_temp.name === 'Unarmed Attack'){
for (const idx of itemIndex) {
const _temp = await handToHandPack.getDocument(idx._id);
if (_temp.name === "Unarmed Attack") {
toAdd.push(_temp);
}
}
let newItems = await this.createEmbeddedDocuments("Item", toAdd);
for(let item of newItems){
await item.setFlag('deltagreen','AutoAdded', true);
if(item.name === 'Unarmed Attack'){
await item.setFlag('deltagreen','SystemName', 'unarmed-attack');
}
}
}
catch(ex){
console.log('Error adding unarmed strike item to Actor.')
const newItems = await this.createEmbeddedDocuments("Item", toAdd);
for (const item of newItems) {
await item.setFlag("deltagreen", "AutoAdded", true);
if (item.name === "Unarmed Attack") {
await item.setFlag("deltagreen", "SystemName", "unarmed-attack");
}
}
} catch (ex) {
console.log("Error adding unarmed strike item to Actor.");
console.log(ex);
}
}
async AddBaseVehicleItemsIfMissing(){
try{
let flag = await this.getFlag('deltagreen', 'DefaultVehicleArmorAdded');
async AddBaseVehicleItemsIfMissing() {
try {
const flag = await this.getFlag("deltagreen", "DefaultVehicleArmorAdded");
if(flag !== null && flag !== undefined && flag !== true){
console.log('found a flag');
if (flag !== null && flag !== undefined && flag !== true) {
console.log("found a flag");
console.log(flag);
}
else{
} else {
// mark the actor so that we don't accidently do this again later, or if we want to fix/change something on it in the future
this.setFlag('deltagreen', 'DefaultVehicleArmorAdded', true);
let toAdd = []; // createEmbeddedDocument expects an array
this.setFlag("deltagreen", "DefaultVehicleArmorAdded", true);
let armor = await Item.create({type:"armor", name:"Vehicle Frame"});
const toAdd = []; // createEmbeddedDocument expects an array
const armor = await Item.create({
type: "armor",
name: "Vehicle Frame",
});
// this is the current default, but set it anyways in case it gets changed later.
armor.system.protection = 3;
toAdd.push(armor);
// create the item on the actor
let newItems = await this.createEmbeddedDocuments("Item", toAdd);
for(let item of newItems){
await item.setFlag('deltagreen','AutoAdded', true);
}
// create the item on the actor
const newItems = await this.createEmbeddedDocuments("Item", toAdd);
for (const item of newItems) {
await item.setFlag("deltagreen", "AutoAdded", true);
}
}
}
catch(ex){
} catch (ex) {
console.log(ex);
}
}
}
}
+205 -203
View File
@@ -6,20 +6,19 @@ import { DeltaGreenActorSheet } from "./actor/actor-sheet.js";
import { DeltaGreenItem } from "./item/item.js";
import { DeltaGreenItemSheet } from "./item/item-sheet.js";
import * as DGRolls from "./roll/roll.js";
import { registerSystemSettings } from "./settings.js"
import { registerSystemSettings } from "./settings.js";
import { preloadHandlebarsTemplates } from "./templates.js";
import { ParseDeltaGreenStatBlock } from "./other/stat-parser-macro.js";
import DGUtils from "./other/utility-functions.js";
Hooks.once('init', async function() {
Hooks.once("init", async function () {
game.deltagreen = {
DeltaGreenActor,
DeltaGreenItem,
rollItemMacro,
rollItemSkillCheckMacro,
rollSkillMacro,
ParseDeltaGreenStatBlock
ParseDeltaGreenStatBlock,
};
/**
@@ -28,11 +27,11 @@ Hooks.once('init', async function() {
*/
CONFIG.Combat.initiative = {
formula: "@statistics.dex.value",
decimals: 0
decimals: 0,
};
// Register custom dice rolls
Object.values(DGRolls).forEach((cls) => CONFIG.Dice.rolls.push(cls))
Object.values(DGRolls).forEach((cls) => CONFIG.Dice.rolls.push(cls));
// Register System Settings
registerSystemSettings();
@@ -44,28 +43,33 @@ Hooks.once('init', async function() {
// Register sheet application classes
Actors.unregisterSheet("core", ActorSheet);
Items.unregisterSheet("core", ItemSheet);
Actors.registerSheet("deltagreen", DeltaGreenActorSheet, { makeDefault: true });
Actors.registerSheet("deltagreen", DeltaGreenActorSheet, {
makeDefault: true,
});
Items.registerSheet("deltagreen", DeltaGreenItemSheet, { makeDefault: true });
// Preload Handlebars Templates
preloadHandlebarsTemplates();
// Add Handlebars helpers
Handlebars.registerHelper('localizeWithFallback', function(value, fallbackValue) {
return DGUtils.localizeWithFallback(value, fallbackValue);
});
Handlebars.registerHelper(
"localizeWithFallback",
function (value, fallbackValue) {
return DGUtils.localizeWithFallback(value, fallbackValue);
},
);
Handlebars.registerHelper('concat', function() {
var outStr = '';
for (var arg in arguments) {
if (typeof arguments[arg] != 'object') {
Handlebars.registerHelper("concat", function () {
let outStr = "";
for (let arg in arguments) {
if (typeof arguments[arg] !== "object") {
outStr += arguments[arg];
}
}
return outStr;
});
Handlebars.registerHelper('toLowerCase', function(str) {
Handlebars.registerHelper("toLowerCase", function (str) {
try {
return str.toLowerCase();
} catch (error) {
@@ -73,7 +77,7 @@ Hooks.once('init', async function() {
}
});
Handlebars.registerHelper('toUpperCase', function(str) {
Handlebars.registerHelper("toUpperCase", function (str) {
try {
return str.toUpperCase();
} catch (error) {
@@ -81,62 +85,62 @@ Hooks.once('init', async function() {
}
});
Handlebars.registerHelper('if_eq', function(a, b, opts) {
Handlebars.registerHelper("if_eq", function (a, b, opts) {
if (a == b) {
return opts.fn(this);
return opts.fn(this);
} else {
return opts.inverse(this);
return opts.inverse(this);
}
});
Handlebars.registerHelper('if_not_eq', function(a, b, opts) {
if (a != b) { return opts.fn(this); }
Handlebars.registerHelper("if_not_eq", function (a, b, opts) {
if (a != b) {
return opts.fn(this);
}
return opts.inverse(this);
});
Handlebars.registerHelper('if_gt', function(a, b, trueVal, falseVal) {
Handlebars.registerHelper("if_gt", function (a, b, trueVal, falseVal) {
if (a > b) {
return trueVal;
return trueVal;
} else {
return falseVal;
return falseVal;
}
});
Handlebars.registerHelper('cite_ahb', function(page) {
Handlebars.registerHelper("cite_ahb", function (page) {
return `See page ${page} of the Agent's Handbook.`;
});
Handlebars.registerHelper('formatLethality', function(lethality) {
Handlebars.registerHelper("formatLethality", function (lethality) {
if (lethality > 0) {
return lethality.toString() + "%";
}
else {
return `${lethality.toString() }%`;
} else {
return "";
}
});
// Is this used anywhere?
Handlebars.registerHelper('getActorSkillProp', function(actorData, skillName, prop) {
try{
if(skillName != "" && prop != ""){
let skills = actorData.data.skills;
let skill = skills[skillName];
let propVal = skill[prop];
return propVal;
}
else{
Handlebars.registerHelper(
"getActorSkillProp",
function (actorData, skillName, prop) {
try {
if (skillName != "" && prop != "") {
const skills = actorData.data.skills;
let skill = skills[skillName];
const propVal = skill[prop];
return propVal;
} else {
return "";
}
} catch (ex) {
console.log(ex);
return "";
}
}
catch(ex){
console.log(ex);
return "";
}
});
},
);
Handlebars.registerHelper('getAvailableRollModes', function() {
Handlebars.registerHelper("getAvailableRollModes", function () {
try {
return CONFIG.Dice.rollModes;
} catch (error) {
@@ -144,7 +148,7 @@ Hooks.once('init', async function() {
}
});
Handlebars.registerHelper('getDefaultRollMode', function() {
Handlebars.registerHelper("getDefaultRollMode", function () {
try {
return game.settings.get("core", "rollMode");
} catch (error) {
@@ -152,44 +156,41 @@ Hooks.once('init', async function() {
}
});
Handlebars.registerHelper('calculateHandToHandCombatDamageFormulaBonus', function(strength) {
try {
let bonus = "";
Handlebars.registerHelper(
"calculateHandToHandCombatDamageFormulaBonus",
function (strength) {
try {
let bonus = "";
if(strength.value < 5){
bonus = " - 2";
}
else if(strength.value < 9){
bonus = " - 1";
}
else if(strength.value > 12 && strength < 17){
bonus = " + 1";
}
else if(strength.value > 16){
bonus = " + 2";
}
return bonus;
if (strength.value < 5) {
bonus = " - 2";
} else if (strength.value < 9) {
bonus = " - 1";
} else if (strength.value > 12 && strength < 17) {
bonus = " + 1";
} else if (strength.value > 16) {
bonus = " + 2";
}
} catch (error) {
console.log(error);
}
});
return bonus;
} catch (error) {
console.log(error);
}
},
);
Handlebars.registerHelper('localizeWeaponSkill', function(skill) {
Handlebars.registerHelper("localizeWeaponSkill", function (skill) {
let label = skill;
try {
if(skill === 'dex'){
if (skill === "dex") {
label = game.i18n.localize("DG.Attributes.dex");
}
if(skill === 'DG.Skills.custom'){
label = game.i18n.localize('DG.ItemWindow.Custom');
if (skill === "DG.Skills.custom") {
label = game.i18n.localize("DG.ItemWindow.Custom");
} else {
label = game.i18n.localize(`DG.Skills.${ skill}`);
}
else{
label = game.i18n.localize("DG.Skills." + skill);
}
} catch (error) {
console.log(error);
}
@@ -197,37 +198,37 @@ Hooks.once('init', async function() {
return label;
});
Handlebars.registerHelper('hideSkillBasedOnProficiencyAndUserChoice', function(hideUntrainedSkills, proficiency) {
let showValue = true;
Handlebars.registerHelper(
"hideSkillBasedOnProficiencyAndUserChoice",
function (hideUntrainedSkills, proficiency) {
let showValue = true;
try {
if(hideUntrainedSkills === false){
showValue = true;
}
else{
if(proficiency > 0){
try {
if (hideUntrainedSkills === false) {
showValue = true;
} else {
if (proficiency > 0) {
showValue = true;
} else {
showValue = false;
}
}
else{
showValue = false;
}
}
} catch (error) {
console.log(error);
}
} catch (error) {
console.log(error);
}
return showValue;
return showValue;
},
);
});
// looks at system setting for what font to use and returns the class that is then used in the handlebars template that
// looks at system setting for what font to use and returns the class that is then used in the handlebars template that
// generates the character sheet.
Handlebars.registerHelper('getFontFamilySystemSettingClass', function() {
let setting = game.settings.get("deltagreen", "characterSheetFont");
Handlebars.registerHelper("getFontFamilySystemSettingClass", function () {
const setting = game.settings.get("deltagreen", "characterSheetFont");
const characterSheetStyle = game.settings.get("deltagreen", "characterSheetStyle");
);
let characterSheetStyle = game.settings.get("deltagreen", "characterSheetStyle");
/*
if(setting === "TypeWriterCondensed"){
return "typewriter-condensed-font";
@@ -251,7 +252,7 @@ Hooks.once('init', async function() {
return "martel-font";
}
*/
/*
if(characterSheetStyle === "cowboy"){
return "special-elite-font";
@@ -262,35 +263,29 @@ Hooks.once('init', async function() {
*/
});
Handlebars.registerHelper('getCharacterSheetStyle', function() {
Handlebars.registerHelper("getCharacterSheetStyle", function () {
const characterSheetStyle = game.settings.get("deltagreen", "characterSheetStyle");
);
let characterSheetStyle = game.settings.get("deltagreen", "characterSheetStyle");
if(characterSheetStyle === "cowboy"){
if (characterSheetStyle === "cowboy") {
return "cowboy-style";
}
else if(characterSheetStyle === "outlaw"){
} else if (characterSheetStyle === "outlaw") {
return "outlaw-style";
}
else{
} else {
return "program-style";
}
});
Handlebars.registerHelper('keepSanityPrivate', function() {
Handlebars.registerHelper("keepSanityPrivate", function () {
let setting = false;
try{
try {
setting = game.settings.get("deltagreen", "keepSanityPrivate");
if(game.user.isGM){
if (game.user.isGM) {
setting = false;
}
}
catch(ex){
} catch (ex) {
setting = false;
}
@@ -298,37 +293,34 @@ Hooks.once('init', async function() {
});
});
Handlebars.registerHelper('playerHasGamemasterPrivileges', function(){
Handlebars.registerHelper("playerHasGamemasterPrivileges", function () {
return game.user.isGM;
});
Handlebars.registerHelper('showImpossibleLandscapesContent', function() {
Handlebars.registerHelper("showImpossibleLandscapesContent", function () {
let result = false;
let setting = game.settings.get("deltagreen", "showImpossibleLandscapesContent");
const setting = game.settings.get("deltagreen", "showImpossibleLandscapesContent");
if(game.user.isGM === true && setting === true){
if (game.user.isGM === true && setting === true) {
result = true;
}
return result
return result;
});
Hooks.once("ready", async function() {
Hooks.once("ready", async function () {
// Wait to register hotbar drop hook on ready so that modules could register earlier if they want to
Hooks.on("hotbarDrop", (bar, data, slot) => createDeltaGreenMacro(data, slot));
Hooks.on("hotbarDrop", (bar, data, slot) =>
createDeltaGreenMacro(data, slot),
);
});
Hooks.on("ready", ()=> {
//let backgroundImageSetting = game.settings.get("deltagreen", "characterSheetBackgroundImageSetting");
//let characterSheetStyle = game.settings.get("deltagreen", "characterSheetStyle");
Hooks.on("ready", () => {
// let backgroundImageSetting = game.settings.get("deltagreen", "characterSheetBackgroundImageSetting");
// let characterSheetStyle = game.settings.get("deltagreen", "characterSheetStyle");
//let customCss = "";
//let customStyle = document.createElement("style");
//customStyle.id = "dg-custom-css";
// let customStyle = document.createElement("style");
// customStyle.id = "dg-custom-css";
/*
if(backgroundImageSetting === "OldPaper1"){
customCss += `div.deltagreen.sheet.actor section.window-content{
@@ -341,7 +333,6 @@ Hooks.on("ready", ()=> {
}`;
}
*/
/*
if(characterSheetStyle === "cowboy"){
customCss += `div.deltagreen.sheet.actor section.window-content{
@@ -360,7 +351,6 @@ Hooks.on("ready", ()=> {
//document.querySelector("head").appendChild(customStyle);
}
*/
});
Hooks.on("preCreateItem", (item) => {
@@ -368,68 +358,62 @@ Hooks.on("preCreateItem", (item) => {
console.log(item.img);
console.log(item.type);
if(item.img === 'icons/svg/item-bag.svg'){
if(item.type === 'bond'){
item.updateSource({ img: 'systems/deltagreen/assets/icons/person-black-bg.svg'});
}
else{
item.updateSource({ img: 'systems/deltagreen/assets/icons/swap-bag-black-bg.svg'});
if (item.img === "icons/svg/item-bag.svg") {
if (item.type === "bond") {
item.updateSource({
img: "systems/deltagreen/assets/icons/person-black-bg.svg",
});
} else {
item.updateSource({
img: "systems/deltagreen/assets/icons/swap-bag-black-bg.svg",
});
}
}
});
Hooks.on("renderSidebarTab", async (app, html) => {
if (app.options.id == "actors") {
let button = $("<button class='import-cd'><i class='fas fa-file-import'></i> Parse Stat Block</button>")
const button = $("<button class='import-cd'><i class='fas fa-file-import'></i> Parse Stat Block</button>")
button.click(function () {
ParseDeltaGreenStatBlock()
ParseDeltaGreenStatBlock();
});
html.find(".directory-footer").append(button);
}
})
});
// Note - this event is fired on ALL connected clients...
Hooks.on('createActor', async function(actor, options, userId){
try{
Hooks.on("createActor", async function (actor, options, userId) {
try {
// use this to trap on if this hook is firing for the same user that triggered the create
// can put logic specific to a particular user session below
if (userId !== game.user.id) return;
if (actor !== null){
if(actor.type === 'agent'){
if (actor !== null) {
if (actor.type === "agent") {
// update the default type skill of Art - Painting's labels to try to be localized
// since I really backed myself into a corner on this with my implementation of it...
console.log('createActor Hook');
console.log("createActor Hook");
let artLabel = game.i18n.translations.DG?.TypeSkills?.Art ?? "Art";
let paintingLabel = game.i18n.translations.DG?.TypeSkills?.Subskills?.Painting ?? "Painting";
const artLabel = game.i18n.translations.DG?.TypeSkills?.Art ?? "Art";
const paintingLabel = game.i18n.translations.DG?.TypeSkills?.Subskills?.Painting ?? "Painting";
let updatedData = duplicate(actor.system);
const updatedData = duplicate(actor.system);
updatedData.typedSkills.tskill_01.group = artLabel;
updatedData.typedSkills.tskill_01.label = paintingLabel;
actor.update({"data": updatedData});
actor.update({ data: updatedData });
// throw on an unarmed strike item for convenience
actor.AddUnarmedAttackItemIfMissing();
}
else if(actor.type === 'unnatural'){
} else if (actor.type === "unnatural") {
// Do nothing.
}
else if(actor.type === 'vehicle'){
} else if (actor.type === "vehicle") {
actor.AddBaseVehicleItemsIfMissing();
}
}
}
catch(ex){
} catch (ex) {
console.log(ex);
}
});
@@ -448,25 +432,25 @@ Hooks.on('createActor', async function(actor, options, userId){
async function createDeltaGreenMacro(data, slot) {
// Definitely should not be doing assignments in conditionals but if we fix this, it breaks macro creation.
// eslint-disable-next-line no-cond-assign
if (data.type = "Item" && data.itemData.type !== "weapon") return;
//if (!("data" in data)) return ui.notifications.warn("You can only create macro buttons for owned Items");
if ((data.type = "Item" && data.itemData.type !== "weapon")) return;
// if (!("data" in data)) return ui.notifications.warn("You can only create macro buttons for owned Items");
const item = data.itemData;
// Create the macro command
let command = '// Uncomment line below to also roll skill check if desired.'
command += '\n' + `//game.deltagreen.rollItemSkillCheckMacro("${item._id}");`;
command += '\n' + `game.deltagreen.rollItemMacro("${item._id}");`;
let command = "// Uncomment line below to also roll skill check if desired.";
command += "\n" + `//game.deltagreen.rollItemSkillCheckMacro("${item._id}");`;
command += "\n" + `game.deltagreen.rollItemMacro("${item._id}");`;
//let macro = game.macros.entities.find(m => (m.name === data.name) && (m.command === command));
//if (!macro) {
let macro = await Macro.create({
// let macro = game.macros.entities.find(m => (m.name === data.name) && (m.command === command));
// if (!macro) {
const macro = await Macro.create({
name: data.itemData.name,
type: "script",
img: data.itemData.img,
command: command,
flags: { "deltagreen.itemMacro": true }
});
//}
// }
game.user.assignHotbarMacro(macro, slot);
return false;
@@ -483,17 +467,21 @@ async function rollItemMacro(itemId) {
let actor;
if (speaker.token) actor = game.actors.tokens[speaker.token];
if (!actor) actor = game.actors.get(speaker.actor);
if(!actor) return ui.notifications.warn('Must have an Actor selected first.');
let item = actor ? actor.items.find(i => i._id === itemId) : null;
if (!actor)
return ui.notifications.warn("Must have an Actor selected first.");
let item = actor ? actor.items.find((i) => i._id === itemId) : null;
// for backwards compatibility with older macros, where I unwisely set it to use name instead of id
if(!item){
item = actor ? actor.items.find(i => i.name === itemId) : null;
}
if (!item) {
item = actor ? actor.items.find((i) => i.name === itemId) : null;
}
if (!item) return ui.notifications.warn(`Your controlled Actor does not have an item named ${itemId}`);
if (!item)
return ui.notifications.warn(
`Your controlled Actor does not have an item named ${itemId}`,
);
// Trigger the item roll
const r = await item.roll();
@@ -507,35 +495,49 @@ function rollItemSkillCheckMacro(itemId) {
if (speaker.token) actor = game.actors.tokens[speaker.token];
if (!actor) actor = game.actors.get(speaker.actor);
if (!actor) return ui.notifications.warn('Must have an Actor selected first.');
if (!actor)
return ui.notifications.warn("Must have an Actor selected first.");
let item = actor ? actor.items.find(i => i._id === itemId) : null;
let item = actor ? actor.items.find((i) => i._id === itemId) : null;
// for backwards compatibility with older macros, where I unwisely set it to use name instead of id
if(!item){
item = actor ? actor.items.find(i => i.name === itemId) : null;
}
if (!item) {
item = actor ? actor.items.find((i) => i.name === itemId) : null;
}
if (!item) return ui.notifications.warn(`Your controlled Actor does not have an item '${item.name}'`);
if (!item)
return ui.notifications.warn(
`Your controlled Actor does not have an item '${item.name}'`,
);
let skillName = item.system.skill.toString();
const skillName = item.system.skill.toString();
const roll = new DGRolls.DGPercentileRoll("1D100", {}, { rollType: "weapon", key: skillName, actor, item });
return actor.sheet.processRoll({}, roll)}
const roll = new DGRolls.DGPercentileRoll(
"1D100",
{},
{ rollType: "weapon", key: skillName, actor, item },
);
return actor.sheet.processRoll({}, roll);
}
function rollSkillMacro(skillName) {
const speaker = ChatMessage.getSpeaker();
let actor;
if (speaker.token) actor = game.actors.tokens[speaker.token];
if (!actor) actor = game.actors.get(speaker.actor);
if(!actor) return ui.notifications.warn('Must have an Actor selected first.');
let skill = actor.system.skills[skillName];
if (!actor)
return ui.notifications.warn("Must have an Actor selected first.");
if(!skill) return ui.notifications.warn('Bad skill name passed to macro.');
const skill = actor.system.skills[skillName];
const roll = new DGRolls.DGPercentileRoll("1D100", {}, { rollType: "skill", key: skillName, actor });
actor.sheet.processRoll({}, roll)
if (!skill) return ui.notifications.warn("Bad skill name passed to macro.");
const roll = new DGRolls.DGPercentileRoll(
"1D100",
{},
{ rollType: "skill", key: skillName, actor },
);
actor.sheet.processRoll({}, roll);
// sendPercentileTestToChat(actor, translatedSkillLabel, skill.proficiency);
}
}
+12 -4
View File
@@ -3,21 +3,26 @@
* @extends {ItemSheet}
*/
export class DeltaGreenItemSheet extends ItemSheet {
/** @override */
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
classes: ["deltagreen", "sheet", "item"],
width: 520,
height: 600,
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "attributes" }]
tabs: [
{
navSelector: ".sheet-tabs",
contentSelector: ".sheet-body",
initial: "attributes",
},
],
});
}
/** @override */
get template() {
const path = "systems/deltagreen/templates/item";
// unique item sheet by type, like `weapon-sheet.html`.
return `${path}/item-${this.item.type}-sheet.html`;
}
@@ -27,7 +32,10 @@ export class DeltaGreenItemSheet extends ItemSheet {
/** @override */
async getData() {
const data = super.getData();
data.enrichedDescription = await TextEditor.enrichHTML(this.object.system.description, {async: true});
data.enrichedDescription = await TextEditor.enrichHTML(
this.object.system.description,
{ async: true },
);
return data;
}
+13 -5
View File
@@ -16,7 +16,7 @@ export class DeltaGreenItem extends Item {
// Get the Item's data
const itemData = this;
const actorData = this.actor || {};
const system = itemData.system;
const { system } = itemData;
}
/**
@@ -32,17 +32,25 @@ export class DeltaGreenItem extends Item {
let roll;
if (item.system.isLethal) {
roll = new DGLethalityRoll("1D100", {}, { rollType: "lethality", actor, item })
roll = new DGLethalityRoll(
"1D100",
{},
{ rollType: "lethality", actor, item },
);
} else {
// regular damage roll
let diceFormula = item.system.damage;
let skillType = item.system.skill;
const skillType = item.system.skill;
if (skillType === 'unarmed_combat' || skillType === 'melee_weapons') {
if (skillType === "unarmed_combat" || skillType === "melee_weapons") {
diceFormula += actorSystemData.statistics.str.meleeDamageBonusFormula;
}
roll = new DGDamageRoll(diceFormula, {}, { rollType: "damage", actor, item })
roll = new DGDamageRoll(
diceFormula,
{},
{ rollType: "damage", actor, item },
);
}
return actor.sheet.processRoll({}, roll);
}
+363 -176
View File
@@ -1,185 +1,372 @@
// call this within a world as: game.deltagreen.ParseDeltaGreenStatBlock()
function GetTypeSkillRatingsFromInput(inputText){
let matchStr = "(Art|Craft|Foreign Language|Native Language|Military Science|Pilot|Science)\\s?\\((\\w.*?)\\)\\s?(\\d?\\d)%";
function GetTypeSkillRatingsFromInput(inputText) {
const matchStr =
"(Art|Craft|Foreign Language|Native Language|Military Science|Pilot|Science)\\s?\\((\\w.*?)\\)\\s?(\\d?\\d)%";
inputText = inputText.replace(/[\n\r]/g, ' ')
inputText = inputText.replace(/[\n\r]/g, " ");
let re = new RegExp(matchStr, "gi");
let matches = [];
let match;
try{
while(match = re.exec(inputText)){
matches.push({group: match[1], label: match[2], proficiency: parseInt(match[3]), failure: false});
}
const re = new RegExp(matchStr, "gi");
const matches = [];
let match;
try {
while ((match = re.exec(inputText))) {
matches.push({
group: match[1],
label: match[2],
proficiency: parseInt(match[3]),
failure: false,
});
}
catch(ex){
console.log('GetAttributeFromInput Error');
console.log(ex);
}
return matches;
} catch (ex) {
console.log("GetAttributeFromInput Error");
console.log(ex);
}
return matches;
}
function GetAttributeFromInput(inputText, attribute){
let matchStr = "(?:" + attribute + "\\s)(\\d\\d?)";
let re = new RegExp(matchStr, "i");
let results = inputText.match(re);
let attributeScore = 10;
try{
if(results != null && results.length > 1){
attributeScore = parseInt(results[1]);
}
else{
attributeScore = 0;
}
function GetAttributeFromInput(inputText, attribute) {
const matchStr = `(?:${attribute}\\s)(\\d\\d?)`;
const re = new RegExp(matchStr, "i");
const results = inputText.match(re);
let attributeScore = 10;
try {
if (results != null && results.length > 1) {
attributeScore = parseInt(results[1]);
} else {
attributeScore = 0;
}
catch(ex){
console.log('GetAttributeFromInput Error');
console.log(ex);
}
return attributeScore;
} catch (ex) {
console.log("GetAttributeFromInput Error");
console.log(ex);
}
return attributeScore;
}
function GetSkillRatingsFromInput(inputText, skill){
let matchStr = "(?:" + skill + "\\s)(\\d\\d?)";
let re = new RegExp(matchStr, "i");
let results = inputText.match(re);
let skillValue = 0;
try{
if(results != null && results.length > 1){
skillValue = parseInt(results[1]);
}
function GetSkillRatingsFromInput(inputText, skill) {
const matchStr = `(?:${skill}\\s)(\\d\\d?)`;
const re = new RegExp(matchStr, "i");
const results = inputText.match(re);
let skillValue = 0;
try {
if (results != null && results.length > 1) {
skillValue = parseInt(results[1]);
}
catch(ex){
console.log('GetAttributeFromInput Error');
console.log(ex);
}
return skillValue;
} catch (ex) {
console.log("GetAttributeFromInput Error");
console.log(ex);
}
return skillValue;
}
async function RegexParseNpcStatBlock(inputStr, actorType){
let actorData = {};
async function RegexParseNpcStatBlock(inputStr, actorType) {
const actorData = {};
let shortDescription = "";
actorData.type = actorType;
actorData.data = {};
actorData.data.statistics = {};
actorData.data.skills = {};
actorData.data.typedSkills = {};
actorData.data.physical = {};
let shortDescription = "";
actorData.data.health = {value: 10, min: 0, max: 10};
actorData.data.wp = {value: 10, min: 0, max: 10};
let tempStr = "";
let arr = [];
tempStr = inputStr.split(/\r?\n/);
if(tempStr.length > 1){
actorData.name = tempStr[0];
shortDescription = tempStr[1];
}
else{
actorData.name = "Unknown";
}
actorData.type = actorType;
actorData.data = {};
actorData.data.statistics = {};
actorData.data.skills = {};
actorData.data.typedSkills = {};
actorData.data.physical = {};
if(actorType === 'agent'){
actorData.data.physical = {description: shortDescription, wounds: "", firstAidAttempted: false}
}
else if(actorType === 'npc' || actorType === 'unnatural'){
actorData.data.shortDescription = shortDescription;
}
actorData.data.statistics.str = {value: GetAttributeFromInput(inputStr, "STR"), distinguishing_feature: ""};
actorData.data.statistics.con = {value: GetAttributeFromInput(inputStr, "CON"), distinguishing_feature: ""};
actorData.data.statistics.dex = {value: GetAttributeFromInput(inputStr, "DEX"), distinguishing_feature: ""};
actorData.data.statistics.int = {value: GetAttributeFromInput(inputStr, "INT"), distinguishing_feature: ""};
actorData.data.statistics.pow = {value: GetAttributeFromInput(inputStr, "POW"), distinguishing_feature: ""};
actorData.data.statistics.cha = {value: GetAttributeFromInput(inputStr, "CHA"), distinguishing_feature: ""};
actorData.data.health = { value: 10, min: 0, max: 10 };
actorData.data.wp = { value: 10, min: 0, max: 10 };
if(actorType === 'npc' || actorType === 'unnatural'){
// don't want to try to set HP/SAN for player characters
actorData.data.health = {min: 0, max: GetAttributeFromInput(inputStr, "HP"), value: GetAttributeFromInput(inputStr, "HP")};
actorData.data.sanity = {max: actorData.data.statistics.pow.value * 5, value: GetAttributeFromInput(inputStr, "SAN"), currentBreakingPoint: GetAttributeFromInput(inputStr, "BREAKING POINT")};
actorData.data.wp = {max: actorData.data.statistics.pow.value, value: GetAttributeFromInput(inputStr, "WP"), min: 0};
}
let tempStr = "";
let arr = [];
actorData.data.skills.accounting = {"label": "Accounting", proficiency: GetSkillRatingsFromInput(inputStr, "ACCOUNTING"), failure: false};
actorData.data.skills.alertness = {"label": "Alertness", proficiency: GetSkillRatingsFromInput(inputStr, "ALERTNESS"), failure: false};
actorData.data.skills.anthropology = {"label": "Anthropology", proficiency: GetSkillRatingsFromInput(inputStr, "ANTHROPOLOGY"), failure: false};
actorData.data.skills.archeology = {"label": "Archeology", proficiency: GetSkillRatingsFromInput(inputStr, "ARCHEOLOGY|ARCHAEOLOGY"), failure: false}; // damn you british spellings
actorData.data.skills.artillery = {"label": "Artillery", proficiency: GetSkillRatingsFromInput(inputStr, "ARTILLERY"), failure: false};
actorData.data.skills.athletics = {"label": "Athletics", proficiency: GetSkillRatingsFromInput(inputStr, "ATHLETICS"), failure: false};
actorData.data.skills.bureaucracy = {"label": "Bureaucracy", proficiency: GetSkillRatingsFromInput(inputStr, "BUREAUCRACY"), failure: false};
actorData.data.skills.computer_science = {"label": "Computer Science", proficiency: GetSkillRatingsFromInput(inputStr, "COMPUTER SCIENCE"), failure: false};
actorData.data.skills.criminology = {"label": "Criminology", proficiency: GetSkillRatingsFromInput(inputStr, "CRIMINOLOGY"), failure: false};
actorData.data.skills.demolitions = {"label": "Demolitions", proficiency: GetSkillRatingsFromInput(inputStr, "DEMOLITIONS"), failure: false};
actorData.data.skills.disguise = {"label": "Disguise", proficiency: GetSkillRatingsFromInput(inputStr, "DISGUISE"), failure: false};
actorData.data.skills.dodge = {"label": "Dodge", proficiency: GetSkillRatingsFromInput(inputStr, "DODGE"), failure: false};
actorData.data.skills.drive = {"label": "Drive", proficiency: GetSkillRatingsFromInput(inputStr, "DRIVE"), failure: false};
tempStr = inputStr.split(/\r?\n/);
// Impossible Landscapes seems to favor 'Driving' as the name for this instead for some
if(actorData.data.skills.drive.proficiency === 0){
actorData.data.skills.drive = {"label": "Drive", proficiency: GetSkillRatingsFromInput(inputStr, "DRIVING"), failure: false};
}
if (tempStr.length > 1) {
actorData.name = tempStr[0];
shortDescription = tempStr[1];
} else {
actorData.name = "Unknown";
}
actorData.data.skills.firearms = {"label": "Firearms", proficiency: GetSkillRatingsFromInput(inputStr, "FIREARMS"), failure: false};
actorData.data.skills.first_aid = {"label": "First Adi", proficiency: GetSkillRatingsFromInput(inputStr, "FIRST AID"), failure: false};
actorData.data.skills.forensics = {"label": "Forensics", proficiency: GetSkillRatingsFromInput(inputStr, "FORENSICS"), failure: false};
actorData.data.skills.heavy_machinery = {"label": "Heavy Machinery", proficiency: GetSkillRatingsFromInput(inputStr, "HEAVY MACHINERY"), failure: false}; // template.json has typo on heavy machinery...
actorData.data.skills.heavy_weapons = {"label": "Heavy Weapons", proficiency: GetSkillRatingsFromInput(inputStr, "HEAVY WEAPONS"), failure: false};
actorData.data.skills.history = {"label": "History", proficiency: GetSkillRatingsFromInput(inputStr, "HISTORY"), failure: false};
actorData.data.skills.humint = {"label": "HUMINT", proficiency: GetSkillRatingsFromInput(inputStr, "HUMINT"), failure: false};
actorData.data.skills.law = {"label": "Law", proficiency: GetSkillRatingsFromInput(inputStr, "LAW"), failure: false};
actorData.data.skills.medicine = {"label": "Medicine", proficiency: GetSkillRatingsFromInput(inputStr, "MEDICINE"), failure: false};
actorData.data.skills.melee_weapons = {"label": "Melee Weapons", proficiency: GetSkillRatingsFromInput(inputStr, "MELEE WEAPONS"), failure: false};
actorData.data.skills.navigate = {"label": "Navigate", proficiency: GetSkillRatingsFromInput(inputStr, "NAVIGATE"), failure: false};
actorData.data.skills.occult = {"label": "Occult", proficiency: GetSkillRatingsFromInput(inputStr, "OCCULT"), failure: false};
actorData.data.skills.persuade = {"label": "Persuade", proficiency: GetSkillRatingsFromInput(inputStr, "PERSUADE"), failure: false};
actorData.data.skills.pharmacy = {"label": "Pharmacy", proficiency: GetSkillRatingsFromInput(inputStr, "PHARMACY"), failure: false};
actorData.data.skills.psychotherapy = {"label": "Psychotherapy", proficiency: GetSkillRatingsFromInput(inputStr, "PSYCHOTHERAPY"), failure: false};
actorData.data.skills.ride = {"label": "Ride", proficiency: GetSkillRatingsFromInput(inputStr, "RIDE"), failure: false};
actorData.data.skills.search = {"label": "Search", proficiency: GetSkillRatingsFromInput(inputStr, "SEARCH"), failure: false};
actorData.data.skills.sigint = {"label": "SIGINT", proficiency: GetSkillRatingsFromInput(inputStr, "SIGINT"), failure: false};
actorData.data.skills.stealth = {"label": "Stealth", proficiency: GetSkillRatingsFromInput(inputStr, "STEALTH"), failure: false};
actorData.data.skills.surgery = {"label": "Surgery", proficiency: GetSkillRatingsFromInput(inputStr, "SURGERY"), failure: false};
actorData.data.skills.survival = {"label": "Survival", proficiency: GetSkillRatingsFromInput(inputStr, "SURVIVAL"), failure: false};
actorData.data.skills.swim = {"label": "Swim", proficiency: GetSkillRatingsFromInput(inputStr, "SWIM"), failure: false};
actorData.data.skills.unarmed_combat = {"label": "Unarmed Combat", proficiency: GetSkillRatingsFromInput(inputStr, "UNARMED COMBAT"), failure: false};
actorData.data.skills.unnatural = {"label": "Unnatural", proficiency: GetSkillRatingsFromInput(inputStr, "UNNATURAL"), failure: false};
if (actorType === "agent") {
actorData.data.physical = {
description: shortDescription,
wounds: "",
firstAidAttempted: false,
};
} else if (actorType === "npc" || actorType === "unnatural") {
actorData.data.shortDescription = shortDescription;
}
// some npcs/unnatural have other skills
if(GetSkillRatingsFromInput(inputStr, "FLIGHT") > 0){
actorData.data.skills.flight = {"label": "Flight", proficiency: GetSkillRatingsFromInput(inputStr, "FLIGHT"), failure: false};
}
arr = GetTypeSkillRatingsFromInput(inputStr);
actorData.data.statistics.str = {
value: GetAttributeFromInput(inputStr, "STR"),
distinguishing_feature: "",
};
actorData.data.statistics.con = {
value: GetAttributeFromInput(inputStr, "CON"),
distinguishing_feature: "",
};
actorData.data.statistics.dex = {
value: GetAttributeFromInput(inputStr, "DEX"),
distinguishing_feature: "",
};
actorData.data.statistics.int = {
value: GetAttributeFromInput(inputStr, "INT"),
distinguishing_feature: "",
};
actorData.data.statistics.pow = {
value: GetAttributeFromInput(inputStr, "POW"),
distinguishing_feature: "",
};
actorData.data.statistics.cha = {
value: GetAttributeFromInput(inputStr, "CHA"),
distinguishing_feature: "",
};
for (let index = 0; index < arr.length; ++index) {
const element = arr[index];
actorData.data.typedSkills['tskill_' + index.toString()] = element;
}
console.log(actorData);
if (actorType === "npc" || actorType === "unnatural") {
// don't want to try to set HP/SAN for player characters
actorData.data.health = {
min: 0,
max: GetAttributeFromInput(inputStr, "HP"),
value: GetAttributeFromInput(inputStr, "HP"),
};
actorData.data.sanity = {
max: actorData.data.statistics.pow.value * 5,
value: GetAttributeFromInput(inputStr, "SAN"),
currentBreakingPoint: GetAttributeFromInput(inputStr, "BREAKING POINT"),
};
actorData.data.wp = {
max: actorData.data.statistics.pow.value,
value: GetAttributeFromInput(inputStr, "WP"),
min: 0,
};
}
const newActors = await Actor.createDocuments([actorData]);
actorData.data.skills.accounting = {
label: "Accounting",
proficiency: GetSkillRatingsFromInput(inputStr, "ACCOUNTING"),
failure: false,
};
actorData.data.skills.alertness = {
label: "Alertness",
proficiency: GetSkillRatingsFromInput(inputStr, "ALERTNESS"),
failure: false,
};
actorData.data.skills.anthropology = {
label: "Anthropology",
proficiency: GetSkillRatingsFromInput(inputStr, "ANTHROPOLOGY"),
failure: false,
};
actorData.data.skills.archeology = {
label: "Archeology",
proficiency: GetSkillRatingsFromInput(inputStr, "ARCHEOLOGY|ARCHAEOLOGY"),
failure: false,
}; // damn you british spellings
actorData.data.skills.artillery = {
label: "Artillery",
proficiency: GetSkillRatingsFromInput(inputStr, "ARTILLERY"),
failure: false,
};
actorData.data.skills.athletics = {
label: "Athletics",
proficiency: GetSkillRatingsFromInput(inputStr, "ATHLETICS"),
failure: false,
};
actorData.data.skills.bureaucracy = {
label: "Bureaucracy",
proficiency: GetSkillRatingsFromInput(inputStr, "BUREAUCRACY"),
failure: false,
};
actorData.data.skills.computer_science = {
label: "Computer Science",
proficiency: GetSkillRatingsFromInput(inputStr, "COMPUTER SCIENCE"),
failure: false,
};
actorData.data.skills.criminology = {
label: "Criminology",
proficiency: GetSkillRatingsFromInput(inputStr, "CRIMINOLOGY"),
failure: false,
};
actorData.data.skills.demolitions = {
label: "Demolitions",
proficiency: GetSkillRatingsFromInput(inputStr, "DEMOLITIONS"),
failure: false,
};
actorData.data.skills.disguise = {
label: "Disguise",
proficiency: GetSkillRatingsFromInput(inputStr, "DISGUISE"),
failure: false,
};
actorData.data.skills.dodge = {
label: "Dodge",
proficiency: GetSkillRatingsFromInput(inputStr, "DODGE"),
failure: false,
};
actorData.data.skills.drive = {
label: "Drive",
proficiency: GetSkillRatingsFromInput(inputStr, "DRIVE"),
failure: false,
};
newActors[0].sheet.render(true);
// Impossible Landscapes seems to favor 'Driving' as the name for this instead for some
if (actorData.data.skills.drive.proficiency === 0) {
actorData.data.skills.drive = {
label: "Drive",
proficiency: GetSkillRatingsFromInput(inputStr, "DRIVING"),
failure: false,
};
}
actorData.data.skills.firearms = {
label: "Firearms",
proficiency: GetSkillRatingsFromInput(inputStr, "FIREARMS"),
failure: false,
};
actorData.data.skills.first_aid = {
label: "First Adi",
proficiency: GetSkillRatingsFromInput(inputStr, "FIRST AID"),
failure: false,
};
actorData.data.skills.forensics = {
label: "Forensics",
proficiency: GetSkillRatingsFromInput(inputStr, "FORENSICS"),
failure: false,
};
actorData.data.skills.heavy_machinery = {
label: "Heavy Machinery",
proficiency: GetSkillRatingsFromInput(inputStr, "HEAVY MACHINERY"),
failure: false,
}; // template.json has typo on heavy machinery...
actorData.data.skills.heavy_weapons = {
label: "Heavy Weapons",
proficiency: GetSkillRatingsFromInput(inputStr, "HEAVY WEAPONS"),
failure: false,
};
actorData.data.skills.history = {
label: "History",
proficiency: GetSkillRatingsFromInput(inputStr, "HISTORY"),
failure: false,
};
actorData.data.skills.humint = {
label: "HUMINT",
proficiency: GetSkillRatingsFromInput(inputStr, "HUMINT"),
failure: false,
};
actorData.data.skills.law = {
label: "Law",
proficiency: GetSkillRatingsFromInput(inputStr, "LAW"),
failure: false,
};
actorData.data.skills.medicine = {
label: "Medicine",
proficiency: GetSkillRatingsFromInput(inputStr, "MEDICINE"),
failure: false,
};
actorData.data.skills.melee_weapons = {
label: "Melee Weapons",
proficiency: GetSkillRatingsFromInput(inputStr, "MELEE WEAPONS"),
failure: false,
};
actorData.data.skills.navigate = {
label: "Navigate",
proficiency: GetSkillRatingsFromInput(inputStr, "NAVIGATE"),
failure: false,
};
actorData.data.skills.occult = {
label: "Occult",
proficiency: GetSkillRatingsFromInput(inputStr, "OCCULT"),
failure: false,
};
actorData.data.skills.persuade = {
label: "Persuade",
proficiency: GetSkillRatingsFromInput(inputStr, "PERSUADE"),
failure: false,
};
actorData.data.skills.pharmacy = {
label: "Pharmacy",
proficiency: GetSkillRatingsFromInput(inputStr, "PHARMACY"),
failure: false,
};
actorData.data.skills.psychotherapy = {
label: "Psychotherapy",
proficiency: GetSkillRatingsFromInput(inputStr, "PSYCHOTHERAPY"),
failure: false,
};
actorData.data.skills.ride = {
label: "Ride",
proficiency: GetSkillRatingsFromInput(inputStr, "RIDE"),
failure: false,
};
actorData.data.skills.search = {
label: "Search",
proficiency: GetSkillRatingsFromInput(inputStr, "SEARCH"),
failure: false,
};
actorData.data.skills.sigint = {
label: "SIGINT",
proficiency: GetSkillRatingsFromInput(inputStr, "SIGINT"),
failure: false,
};
actorData.data.skills.stealth = {
label: "Stealth",
proficiency: GetSkillRatingsFromInput(inputStr, "STEALTH"),
failure: false,
};
actorData.data.skills.surgery = {
label: "Surgery",
proficiency: GetSkillRatingsFromInput(inputStr, "SURGERY"),
failure: false,
};
actorData.data.skills.survival = {
label: "Survival",
proficiency: GetSkillRatingsFromInput(inputStr, "SURVIVAL"),
failure: false,
};
actorData.data.skills.swim = {
label: "Swim",
proficiency: GetSkillRatingsFromInput(inputStr, "SWIM"),
failure: false,
};
actorData.data.skills.unarmed_combat = {
label: "Unarmed Combat",
proficiency: GetSkillRatingsFromInput(inputStr, "UNARMED COMBAT"),
failure: false,
};
actorData.data.skills.unnatural = {
label: "Unnatural",
proficiency: GetSkillRatingsFromInput(inputStr, "UNNATURAL"),
failure: false,
};
// some npcs/unnatural have other skills
if (GetSkillRatingsFromInput(inputStr, "FLIGHT") > 0) {
actorData.data.skills.flight = {
label: "Flight",
proficiency: GetSkillRatingsFromInput(inputStr, "FLIGHT"),
failure: false,
};
}
arr = GetTypeSkillRatingsFromInput(inputStr);
for (let index = 0; index < arr.length; ++index) {
const element = arr[index];
actorData.data.typedSkills[`tskill_${index.toString()}`] = element;
}
console.log(actorData);
const newActors = await Actor.createDocuments([actorData]);
newActors[0].sheet.render(true);
}
async function GetUserInput(){
const content = `<form>
async function GetUserInput() {
const content = `<form>
<div class="form-group">
<label>Actor Type: </label>
<div class="form-fields">
@@ -197,25 +384,25 @@ async function GetUserInput(){
</div>
</div>
</form>`;
new Dialog({
title: "Stat Block Parser", // Change the title if you want.
content,
buttons: {
roll: {
label: "PARSE",
callback: async (html) => {
const textInput = html.find("[name=parse-input]")[0].value;
const actorType = html.find("[name=actor-type]")[0].value;
RegexParseNpcStatBlock(textInput, actorType);
}
}
}
}).render(true);
new Dialog({
title: "Stat Block Parser", // Change the title if you want.
content,
buttons: {
roll: {
label: "PARSE",
callback: async (html) => {
const textInput = html.find("[name=parse-input]")[0].value;
const actorType = html.find("[name=actor-type]")[0].value;
RegexParseNpcStatBlock(textInput, actorType);
},
},
},
}).render(true);
}
export async function ParseDeltaGreenStatBlock(){
GetUserInput();
}
export async function ParseDeltaGreenStatBlock() {
GetUserInput();
}
+17 -19
View File
@@ -1,27 +1,25 @@
/* globals game */
export default class DGUtils {
/**
* Attempt to localize a keyword, and gracefully fallback to something else if the key does not exist.
* This way people using incomplete translations will not as many crashes or bugs when playing against a newly updated system.
*
* @param {String} key - localization key
*
* @param {String} key - localization key
* @param {String} fallback - string to fall back to if translation does not exist for key
* @returns
* @returns
*/
static localizeWithFallback(key, fallback){
static localizeWithFallback(key, fallback) {
try {
let translatedValue = game.i18n.localize(key);
const translatedValue = game.i18n.localize(key);
if (translatedValue != key) {
return translatedValue;
} else {
console.warn(`Untranslated localization key '${key}'.`);
// can't have single quotes in a handlebars string literal input, so sort of hack in an escape character for them.
fallback = fallback.replace("&#39;", "'");
return fallback;
return translatedValue;
}
} catch(ex) {
console.warn(`Untranslated localization key '${key}'.`);
// can't have single quotes in a handlebars string literal input, so sort of hack in an escape character for them.
fallback = fallback.replace("&#39;", "'");
return fallback;
} catch (ex) {
console.warn(ex);
return fallback;
}
@@ -29,12 +27,12 @@ export default class DGUtils {
/**
* Format a number with a leading plus.
*
* @param {Number} number
*
* @param {Number} number
* @returns {String} - the stringified number with a leading plus if applicable
*
*
*/
static formatStringWithLeadingPlus(number){
return number > 0 ? `+${number}` : number.toString() ;
static formatStringWithLeadingPlus(number) {
return number > 0 ? `+${number}` : number.toString();
}
}
}
+227 -177
View File
@@ -1,13 +1,13 @@
/* globals game Roll ChatMessage AudioHelper renderTemplate Dialog */
import DGUtils from "../other/utility-functions.js"
import DGUtils from "../other/utility-functions.js";
export class DGRoll extends Roll {
/**
* NOTE: This class will rarely be called on its own. It should generally be extended. Look to DGPercentileRoll as an example.
*
*
* Customize our roll with some useful information, passed in the `options` Object.
*
*
* @param {string} formula Unused - The string formula to parse (from Foundry)
* @param {Object} data Unused - The data object against which to parse attributes within the formula
* @param {Object} [options] Additional data which is preserved in the database
@@ -27,24 +27,27 @@ export class DGRoll extends Roll {
}
/**
* Simple function that actually creates the message and sends it to chat.
*
* Simple function that actually creates the message and sends it to chat.
*
* Broke this out so multiple functions can use it.
*
*
* @returns {Promise<ChatMessage>} - the created chat message.
*/
async createMessage(content, flavor, rollMode) {
let chatData = {
const chatData = {
speaker: ChatMessage.getSpeaker({ actor: this.actor }),
content,
flavor,
type: 5, //CHAT_MESSAGE_TYPES.ROLL,
type: 5, // CHAT_MESSAGE_TYPES.ROLL,
roll: this,
rollMode
rollMode,
};
// play the dice rolling sound, like a regular in-chat roll
AudioHelper.play({src: "sounds/dice.wav", volume: 0.8, autoplay: true, loop: false}, true);
AudioHelper.play(
{ src: "sounds/dice.wav", volume: 0.8, autoplay: true, loop: false },
true,
);
return ChatMessage.create(chatData);
}
}
@@ -52,15 +55,15 @@ export class DGRoll extends Roll {
export class DGPercentileRoll extends DGRoll {
/**
* Creates D100 rolls, the base die of the system.
*
* This constructor embeds the following info into the roll:
* 1. Target number that the roll needs to beat.
* 2. Localized name for the roll.
*
*
* This constructor embeds the following info into the roll:
* 1. Target number that the roll needs to beat.
* 2. Localized name for the roll.
*
* Note: In order for all of our custom data to persist, our constructor must use the same parameters as its parent class.
* So, even though percentile rolls will always have a formula of "1d100" and we don't use the `data` object,
* we still have to keep them as parameters.
*
*
* @param {string} formula Unused - The string formula to parse (from Foundry) - Always "1d100" for percentile rolls.
* @param {Object} data Unused - The data object against which to parse attributes within the formula
* @param {Object} [options] Additional data which is preserved in the database
@@ -81,7 +84,7 @@ export class DGPercentileRoll extends DGRoll {
this.target = this.actor.system.statistics[this.key].x5;
this.localizedKey = game.i18n.localize(`DG.Attributes.${this.key}`);
break;
case "skill":
case "skill":
// Set up a target number and localized roll based on whether the skill is regular or typed.
if (skillKeys.includes(this.key)) {
this.target = this.actor.system.skills[this.key].proficiency;
@@ -113,7 +116,7 @@ export class DGPercentileRoll extends DGRoll {
// Add a the weapon's internal modifier.
this.modifier += this.item.system.skillModifier;
break;
case "luck":
case "luck":
this.target = 50;
this.localizedKey = game.i18n.localize("DG.Luck");
break;
@@ -124,59 +127,64 @@ export class DGPercentileRoll extends DGRoll {
/**
* Shows a dialog that can modify the roll.
*
*
* @returns {Promise<Object|void>} - the results of the dialog.
*/
async showDialog() {
async showDialog() {
let isSanCheck = false;
const hideSanTarget = !game.user.isGM && game.settings.get("deltagreen", "keepSanityPrivate");
if (this.key === 'sanity' || this.key === 'ritual') {
const hideSanTarget =
!game.user.isGM && game.settings.get("deltagreen", "keepSanityPrivate");
if (this.key === "sanity" || this.key === "ritual") {
isSanCheck = true;
}
let backingData = {
data:{
const backingData = {
data: {
label: this.localizedKey,
originalTarget: this.target,
targetModifier: 20,
isSanCheck: isSanCheck,
hideTarget: hideSanTarget
isSanCheck,
hideTarget: hideSanTarget,
},
};
let template = "systems/deltagreen/templates/dialog/modify-percentile-roll.html";
let html = await renderTemplate(template, backingData);
const template =
"systems/deltagreen/templates/dialog/modify-percentile-roll.html";
const html = await renderTemplate(template, backingData);
return new Promise((resolve, reject) => {
new Dialog({
content: html,
title: DGUtils.localizeWithFallback("DG.ModifySkillRollDialogue.Title", "Modify Roll"),
title: DGUtils.localizeWithFallback(
"DG.ModifySkillRollDialogue.Title",
"Modify Roll",
),
default: "roll",
buttons: {
roll:{
roll: {
label: DGUtils.localizeWithFallback("DG.Roll.Roll", "Roll"),
callback: html => {
callback: (html) => {
try {
let targetModifier = html.find("[name='targetModifier']").val(); // this is text as a heads up
let rollMode = html.find("[name='rollMode']").val();
let plusMinus = html.find("[name='plusOrMinus']").val();
if (targetModifier.trim() != "" && !isNaN(targetModifier)){
let targetModifier = html.find("[name='targetModifier']").val(); // this is text as a heads up
const rollMode = html.find("[name='rollMode']").val();
const plusMinus = html.find("[name='plusOrMinus']").val();
if (targetModifier.trim() != "" && !isNaN(targetModifier)) {
targetModifier = Math.abs(parseInt(targetModifier));
if(plusMinus === "-"){
if (plusMinus === "-") {
targetModifier = -1 * targetModifier;
}
}
resolve({targetModifier, rollMode})
} catch(ex) {
resolve({ targetModifier, rollMode });
} catch (ex) {
reject(console.log(ex));
}
}
}
}
},
},
},
}).render(true);
});
}
@@ -184,74 +192,93 @@ export class DGPercentileRoll extends DGRoll {
/**
* Prepares data for a chat message and then passes that data
* to a method that actually creates a ChatMessage.
*
*
* Lays out and styles message based on outcome of the roll.
*
*
* @returns {Promise<ChatMessage>} - the created chat message.
*/
async toChat() {
let rollMode = this.options.rollMode || game.settings.get("core", "rollMode");
let rollMode =
this.options.rollMode || game.settings.get("core", "rollMode");
// if using private san rolls, must hide any SAN roll unless user is a GM
const privateSanSetting = game.settings.get("deltagreen", "keepSanityPrivate");
if (privateSanSetting && (this.key === 'sanity' || this.key === 'ritual') && !game.user.isGM){
rollMode = 'blindroll';
const privateSanSetting = game.settings.get(
"deltagreen",
"keepSanityPrivate",
);
if (
privateSanSetting &&
(this.key === "sanity" || this.key === "ritual") &&
!game.user.isGM
) {
rollMode = "blindroll";
}
let label = `${game.i18n.localize("DG.Roll.Rolling")} <b>${this.localizedKey}</b> ${game.i18n.localize("DG.Roll.Target")} ${this.target + this.modifier}`;
let label = `${game.i18n.localize("DG.Roll.Rolling")} <b>${
this.localizedKey
}</b> ${game.i18n.localize("DG.Roll.Target")} ${
this.target + this.modifier
}`;
// "Inhuman" stat being rolled. See function for details.
if (this.isInhuman) {
label = `${game.i18n.localize("DG.Roll.Rolling")} <b>${this.localizedKey} [${game.i18n.localize("DG.Roll.Inhuman").toUpperCase()}]</b> ${game.i18n.localize("DG.Roll.Target")} ${this.target + this.modifier}`;
label = `${game.i18n.localize("DG.Roll.Rolling")} <b>${
this.localizedKey
} [${game.i18n
.localize("DG.Roll.Inhuman")
.toUpperCase()}]</b> ${game.i18n.localize("DG.Roll.Target")} ${
this.target + this.modifier
}`;
}
if (this.modifier) {
label += ` (${DGUtils.formatStringWithLeadingPlus(this.modifier)}%)`
label += ` (${DGUtils.formatStringWithLeadingPlus(this.modifier)}%)`;
}
let resultString = '', styleOverride = '';
let resultString = "";
let styleOverride = "";
if (this.isCritical) {
resultString = `${game.i18n.localize("DG.Roll.Critical")} `;
}
if (this.isSuccess) {
resultString += `${game.i18n.localize("DG.Roll.Success")}`;
if (this.isCritical){
resultString = resultString.toUpperCase() + '!';
styleOverride="color: green";
if (this.isCritical) {
resultString = `${resultString.toUpperCase()}!`;
styleOverride = "color: green";
}
} else {
} else {
resultString += `${game.i18n.localize("DG.Roll.Failure")}`;
if(this.isCritical){
resultString = resultString.toUpperCase() + '!';
styleOverride="color: red";
if (this.isCritical) {
resultString = `${resultString.toUpperCase()}!`;
styleOverride = "color: red";
}
}
let html = '';
html += `<div class="dice-roll">`
html += ` <div class="dice-result">`
html += ` <div style="${styleOverride}" class="dice-formula">${resultString}</div>`
html += ` <div class="dice-tooltip">`
html += ` <section class="tooltip-part">`
html += ` <div class="dice">`
html += ` <header class="part-header flexrow">`
html += ` <span class="part-formula">`
html += ` ${this.formula}`
html += ` </span>`
html += ` <span class="part-total">`
html += ` ${this.total}`
html += ` </span>`
html += ` </header>`
html += ` <ol class="dice-rolls">`
html += ` <li class="roll die ${this.formula}">${this.total}</li>`
html += ` </ol>`
html += ` </div>`
html += ` </section>`
html += ` </div>`
html += ` <h4 class="dice-total">${this.total}</h4>`
html += `</div>`
let html = "";
html += `<div class="dice-roll">`;
html += ` <div class="dice-result">`;
html += ` <div style="${styleOverride}" class="dice-formula">${resultString}</div>`;
html += ` <div class="dice-tooltip">`;
html += ` <section class="tooltip-part">`;
html += ` <div class="dice">`;
html += ` <header class="part-header flexrow">`;
html += ` <span class="part-formula">`;
html += ` ${this.formula}`;
html += ` </span>`;
html += ` <span class="part-total">`;
html += ` ${this.total}`;
html += ` </span>`;
html += ` </header>`;
html += ` <ol class="dice-rolls">`;
html += ` <li class="roll die ${this.formula}">${this.total}</li>`;
html += ` </ol>`;
html += ` </div>`;
html += ` </section>`;
html += ` </div>`;
html += ` <h4 class="dice-total">${this.total}</h4>`;
html += `</div>`;
return this.createMessage(html, label, rollMode);
}
@@ -261,28 +288,28 @@ export class DGPercentileRoll extends DGRoll {
* For an inhuman check, the roll succeeds except on a roll of 100 which fails AND fumbles.
* If the roll is a matching digit roll, it is a critical as normal.
* Also, if the roll is below the regular (non-x5) value of the stat, it is a critical. E.g. a CON of 25, a d100 roll of 21 would be a critical.
*
* @returns {Boolean}
*
* @returns {Boolean}
*/
get isInhuman() {
if (this.target + this.modifier > 99 && this.type === "stat") {
return true;
}
return false;
return false;
}
/**
* Determines if a roll result is critical.
* If roll has not been evaluated, return null.
*
* @returns {null|Boolean}
*
* @returns {null|Boolean}
*/
get isCritical() {
// If roll isn't evaluated, return null.
if (!this.total) {
return null;
}
let isCritical = false
let isCritical = false;
// 1, 100, or any matching dice are a crit, i.e. 11, 22, 33...99.
if (this.total === 1 || this.total === 100 || this.total % 11 === 0) {
@@ -290,9 +317,9 @@ export class DGPercentileRoll extends DGRoll {
isCritical = true;
}
// If inhuman and the roll is below the regular (non-x5) value of the stat, it is a critical.
// If inhuman and the roll is below the regular (non-x5) value of the stat, it is a critical.
// E.g. a CON of 25, a d100 roll of 21 would be a critical.
if (this.isInhuman && this.total <= ((this.target + this.modifier) / 5)) {
if (this.isInhuman && this.total <= (this.target + this.modifier) / 5) {
isCritical = true;
}
@@ -302,8 +329,8 @@ export class DGPercentileRoll extends DGRoll {
/**
* Determines if a roll succeeded.
* If roll has not been evaluated, return null.
*
* @returns {null|Boolean}
*
* @returns {null|Boolean}
*/
get isSuccess() {
// If roll isn't evaluated, return null.
@@ -313,7 +340,7 @@ export class DGPercentileRoll extends DGRoll {
// A roll of 100 always (critically) fails, even for inhuman rolls.
if (this.total === 100) return false;
return this.total <= (this.target + this.modifier);
return this.total <= this.target + this.modifier;
}
}
@@ -321,11 +348,11 @@ export class DGLethalityRoll extends DGPercentileRoll {
/**
* See constructor for DGPercentileRoll. This theoretically could be done in the parent class'
* constructor, but since Lethality rolls needs its own class for custom methods anyway,
* we will set the target and localized key here.
*
* @param {String} formula
* @param {Object} data
* @param {Object} options
* we will set the target and localized key here.
*
* @param {String} formula
* @param {Object} data
* @param {Object} options
*/
constructor(formula, data, options) {
super(formula, data, options);
@@ -335,34 +362,40 @@ export class DGLethalityRoll extends DGPercentileRoll {
/**
* Prepares data for a chat message and then passes that data
* to a method that actually creates a ChatMessage.
*
* to a method that actually creates a ChatMessage.
*
* Lays out and styles message based on outcome of the roll.
*
*
* Overrides `DGPercentileRoll.toChat()`
*
*
* @returns {Promise<ChatMessage>} - the created chat message.
* @override
*/
async toChat() {
const rollMode = this.options.rollMode || game.settings.get("core", "rollMode");
let resultString = '';
let styleOverride = '';
if(this.total <= this.target){
async toChat() {
const rollMode =
this.options.rollMode || game.settings.get("core", "rollMode");
let resultString = "";
let styleOverride = "";
if (this.total <= this.target) {
resultString = `${game.i18n.localize("DG.Roll.Lethal").toUpperCase()}`;
styleOverride="color: red";
}
else{
styleOverride = "color: red";
} else {
resultString = `${game.i18n.localize("DG.Roll.Failure")}`;
}
const { nonLethalDamage } = this;
let label = `${game.i18n.localize("DG.Roll.Rolling")} <b>${game.i18n.localize("DG.Roll.Lethality").toUpperCase()}</b> ${game.i18n.localize("DG.Roll.For")} <b>${this.item.name.toUpperCase()}</b> ${game.i18n.localize("DG.Roll.Target")} ${this.target + this.modifier}`;
let label = `${game.i18n.localize("DG.Roll.Rolling")} <b>${game.i18n
.localize("DG.Roll.Lethality")
.toUpperCase()}</b> ${game.i18n.localize(
"DG.Roll.For",
)} <b>${this.item.name.toUpperCase()}</b> ${game.i18n.localize(
"DG.Roll.Target",
)} ${this.target + this.modifier}`;
if (this.modifier) {
label += ` (${DGUtils.formatStringWithLeadingPlus(this.modifier)}%)`
label += ` (${DGUtils.formatStringWithLeadingPlus(this.modifier)}%)`;
}
let html = '';
let html = "";
html += `<div class="dice-roll">`;
html += ` <div class="dice-result">`;
html += ` <div style="${styleOverride}" class="dice-formula">${resultString}</div>`;
@@ -396,7 +429,9 @@ export class DGLethalityRoll extends DGPercentileRoll {
html += ` </div>`;
html += ` </section>`;
html += ` </div>`;
html += ` <h4 class="dice-total">${this.total} (${nonLethalDamage.total} ${game.i18n.localize("DG.Roll.Damage")})</h4>`;
html += ` <h4 class="dice-total">${this.total} (${
nonLethalDamage.total
} ${game.i18n.localize("DG.Roll.Damage")})</h4>`;
html += `</div>`;
return this.createMessage(html, label, rollMode);
@@ -405,12 +440,12 @@ export class DGLethalityRoll extends DGPercentileRoll {
/**
* Calculates the damage for when a lethality roll fails.
* If roll has not been evaluated, return null.
*
*
* See full rules on page 57 of agent's handbook.
*
*
* Note, this getter does not actually care if the roll has failed.
*
* @returns {null|Object} - return data about the non-lethal damage.
*
* @returns {null|Object} - return data about the non-lethal damage.
*/
get nonLethalDamage() {
if (!this.total) {
@@ -420,7 +455,8 @@ export class DGLethalityRoll extends DGPercentileRoll {
// Try to determine what the d100 result would be as if it was two d10's being rolled.
const totalString = this.total.toString();
const digits = totalString.length;
let die1, die2;
let die1;
let die2;
switch (digits) {
case 1:
// If one digit in the result, one die is a 10, and the other is the result.
@@ -428,7 +464,10 @@ export class DGLethalityRoll extends DGPercentileRoll {
break;
case 2:
// If two digits in the result, each die is the value of one of the digits. If one of those digits is 0, make it 10.
[die1, die2] = totalString.split("").map((digit) => parseInt(digit)).map((digit) => digit || 10);
[die1, die2] = totalString
.split("")
.map((digit) => parseInt(digit))
.map((digit) => digit || 10);
break;
case 3:
// If three digits in the result (aka result === 100), each die is a 10.
@@ -439,7 +478,7 @@ export class DGLethalityRoll extends DGPercentileRoll {
}
const total = die1 + die2;
return { die1, die2, total }
return { die1, die2, total };
}
}
@@ -447,70 +486,77 @@ export class DGDamageRoll extends DGRoll {
/**
* Prepares data for a chat message and then passes that data
* to a method that actually creates a ChatMessage.
*
*
* @returns {Promise<ChatMessage>} - the created chat message.
* @override
*/
async toChat() {
const rollMode = this.options.rollMode || game.settings.get("core", "rollMode");
const rollMode =
this.options.rollMode || game.settings.get("core", "rollMode");
let label = this.formula;
try{
label = `${this.item.name}: ${game.i18n.localize("DG.Roll.Rolling")} <b>${game.i18n.localize("DG.Roll.Damage").toUpperCase()}</b> ${game.i18n.localize("DG.Roll.For")} <b>${label.toUpperCase()}</b>`;
}
catch{
try {
label = `${this.item.name}: ${game.i18n.localize(
"DG.Roll.Rolling",
)} <b>${game.i18n
.localize("DG.Roll.Damage")
.toUpperCase()}</b> ${game.i18n.localize(
"DG.Roll.For",
)} <b>${label.toUpperCase()}</b>`;
} catch {
label = `Rolling <b>DAMAGE</b> for <b>${label.toUpperCase()}</b>`;
}
return this.createMessage(this.total, label, rollMode);
}
async showDialog() {
let template = "systems/deltagreen/templates/dialog/modify-damage-roll.html";
let backingData = {
data:{
const template =
"systems/deltagreen/templates/dialog/modify-damage-roll.html";
const backingData = {
data: {
label: this.item?.name,
originalFormula: this.formula,
outerModifier: "2 * ",
innerModifier: "+ 0"
innerModifier: "+ 0",
},
};
let html = await renderTemplate(template, backingData);
const html = await renderTemplate(template, backingData);
return new Promise((resolve, reject) => {
new Dialog({
content: html,
title: game.i18n.localize("DG.ModifySkillRollDialogue.Title"),
default: "roll",
buttons: {
roll:{
roll: {
label: game.i18n.translations.DG.Roll.Roll,
callback: html => {
try{
let outerModifier = html.find("[name='outerModifier']").val(); // this is text as a heads up
let innerModifier = html.find("[name='innerModifier']").val(); // this is text as a heads up
let modifiedBaseRoll = html.find("[name='originalFormula']").val(); // this is text as a heads up
let rollMode = html.find("[name='targetRollMode']").val();
callback: (html) => {
try {
const outerModifier = html.find("[name='outerModifier']").val(); // this is text as a heads up
let innerModifier = html.find("[name='innerModifier']").val(); // this is text as a heads up
const modifiedBaseRoll = html
.find("[name='originalFormula']")
.val(); // this is text as a heads up
const rollMode = html.find("[name='targetRollMode']").val();
if(innerModifier.replace(" ", "") === "+0"){
if (innerModifier.replace(" ", "") === "+0") {
innerModifier = "";
}
let newFormula = "";
if(outerModifier.trim() != ""){
newFormula += outerModifier + "(" + modifiedBaseRoll + innerModifier.trim() + ")";
}
else{
if (outerModifier.trim() != "") {
newFormula += `${outerModifier}(${modifiedBaseRoll}${innerModifier.trim()})`;
} else {
newFormula += modifiedBaseRoll + innerModifier.trim();
}
resolve({newFormula, rollMode})
}
catch(ex){
resolve({ newFormula, rollMode });
} catch (ex) {
reject(console.log(ex));
}
}
}
}
},
},
},
}).render(true);
});
}
@@ -520,22 +566,26 @@ export class DGSanityDamageRoll extends DGRoll {
/**
* Prepares data for a chat message and then passes that data
* to a method that actually creates a ChatMessage.
*
*
* @returns {Promise<ChatMessage>} - the created chat message.
* @override
*/
async toChat() {
const rollMode = this.options.rollMode || game.settings.get("core", "rollMode");
const rollMode =
this.options.rollMode || game.settings.get("core", "rollMode");
const [lowDie, highDie] = this.terms[0].terms.map((formula) => {
return Roll.parse(formula)[0] || { faces: parseInt(formula), number: 1 };
});
const [lowResult, highResult] = this.damageResults;
const flavor = `Rolling <b>${DGUtils.localizeWithFallback('DG.Generic.SanDamage', 'SAN DAMAGE')}</b> For <b>${lowDie.formula} / ${highDie.formula}</b>`;
let html = '';
const flavor = `Rolling <b>${DGUtils.localizeWithFallback(
"DG.Generic.SanDamage",
"SAN DAMAGE",
)}</b> For <b>${lowDie.formula} / ${highDie.formula}</b>`;
let html = "";
html += `<div class="dice-roll">`;
html += ` <div class="dice-result">`;
html += ` <div class="dice-formula">${lowDie.formula} / ${highDie.formula}</div>`;
@@ -568,22 +618,22 @@ export class DGSanityDamageRoll extends DGRoll {
html += ` </div>`;
html += ` </section>`;
html += ` </div>`;
html += ` <h4 class="dice-total">${lowResult} / ${highResult}</h4>`
html += ` <h4 class="dice-total">${lowResult} / ${highResult}</h4>`;
html += `</div>`;
return this.createMessage(html, flavor, rollMode);
}
/**
* Returns the two results for a sanity damage roll.
*
*
* Returns null if the roll has not been evaluated.
*
*
* @returns {null|Array<Number>} - Array of result numbers
*/
get damageResults() {
if (!this.total) return null;
const [lowResult, highResult] = this.terms[0].results;
return [lowResult?.result, highResult?.result]
return [lowResult?.result, highResult?.result];
}
}
}
+5 -6
View File
@@ -15,7 +15,7 @@ export const registerSystemSettings = function () {
default: "program", // The default value for the setting
onChange: (value) => {
// A callback function which triggers when the setting is changed
//console.log(value)
// console.log(value)
},
});
@@ -44,11 +44,10 @@ export const registerSystemSettings = function () {
default: "1d4", // The default value for the setting, per the most recent errata.
onChange: (value) => {
// A callback function which triggers when the setting is changed
//console.log(value)
// console.log(value)
},
});
// These two settings are obsolete now
game.settings.register("deltagreen", "showImpossibleLandscapesContent", {
name: "Show Impossible Landscapes Content",
@@ -73,12 +72,12 @@ export const registerSystemSettings = function () {
TypeWriterCondensed:
"Condensed Typewriter (Modern, Small Typewriter Font)",
PublicSans: "Public Sans (US Government-style sans serif font)",
//"atwriter": "Another Typewriter (Alternate Old-style Typewriter Font)"
// "atwriter": "Another Typewriter (Alternate Old-style Typewriter Font)"
},
default: "SpecialElite", // The default value for the setting
onChange: (value) => {
// A callback function which triggers when the setting is changed
//console.log(value)
// console.log(value)
},
});
@@ -97,7 +96,7 @@ export const registerSystemSettings = function () {
default: "OldPaper1", // The default value for the setting
onChange: (value) => {
// A callback function which triggers when the setting is changed
//console.log(value)
// console.log(value)
},
});
};
+12 -12
View File
@@ -3,15 +3,15 @@
* Pre-loaded templates are compiled and cached for fast access when rendering
* @return {Promise}
*/
export const preloadHandlebarsTemplates = async function() {
return loadTemplates([
"systems/deltagreen/templates/actor/actor-sheet.html",
"systems/deltagreen/templates/actor/limited-sheet.html",
"systems/deltagreen/templates/actor/unnatural-sheet.html",
"systems/deltagreen/templates/actor/npc-sheet.html",
"systems/deltagreen/templates/actor/cv-partial.html",
"systems/deltagreen/templates/dialog/modify-percentile-roll.html",
"systems/deltagreen/templates/actor/vehicle-sheet.html",
"systems/deltagreen/templates/actor/help-and-licensing-partial.html"
]);
};
export const preloadHandlebarsTemplates = async function () {
return loadTemplates([
"systems/deltagreen/templates/actor/actor-sheet.html",
"systems/deltagreen/templates/actor/limited-sheet.html",
"systems/deltagreen/templates/actor/unnatural-sheet.html",
"systems/deltagreen/templates/actor/npc-sheet.html",
"systems/deltagreen/templates/actor/cv-partial.html",
"systems/deltagreen/templates/dialog/modify-percentile-roll.html",
"systems/deltagreen/templates/actor/vehicle-sheet.html",
"systems/deltagreen/templates/actor/help-and-licensing-partial.html",
]);
};