From 8c35c0295933c6475b855f1acfa1ff0c3cd11489 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Tue, 23 Jul 2024 01:35:51 +0200 Subject: [PATCH 01/55] New feature: AutoEffects, part 1 Implements the general AutoScript parsing structure as well as the Gain Ailment AutoEffect --- ProjectMoonTRPG/ProjectMoonTRPG.html | 310 ++++++++++++++++++++++++++- 1 file changed, 309 insertions(+), 1 deletion(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index cc87fc21b7..3b7a1b8967 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -1534,7 +1534,10 @@ -

Roll helpers

+

Roll helpers

+ + +
@@ -14477,6 +14480,311 @@ getAttrs(["settingEditMode"], function(values) { }); }); + +/*--- AutoScript functions ---*/ + + + +on("clicked:autoEffectTest", function() { + AutoScriptMain(`(Gain 5 Burn) /* Test comment */ (Gain 2 Fragile, Next Turn, TestCondition2)`, "Combat start") + +}); + +/* Main function for using AutoScripts. Called by actions through on click events */ +/* inputAutoScript: AutoScript provided by the action. Can be an empty string */ +/* trigger: "Combat start", "Round start", "Round end", "Damaged", "Staggered", "Defeated", "Panic", + "Permanent", "Offensive", "Defensive", "Block", "Evade" or "None". + Selects which type of AutoEffects to collect and append to an AutoScript. + Block and Evade also include Defensive */ +function AutoScriptMain(inputAutoScript, triggerType="None") { + + /* Converts the input AutoScript to to an array if it isn't one already */ + let AutoScript = []; + if (inputAutoScript != "") { + try { AutoScript = JSON.parse(inputAutoScript); } + catch(e) { AutoScript = AutoScriptToArray(inputAutoScript); } + } + + /* Appends one or more AutoScripts based on the trigger type */ + AutoScript.push(collectAutoScripts(triggerType)); + + + /* Get relevant attributes */ + getAttrs(["settingMuteMessage", "settingWhisperRolls", "settingWhisperTarget", "settingLimbusStyle", "settingHideNextTurn", + "HP", "HP_max", "StagRes", "StagRes_max", "SP", "SP_max", + "StaggerState", "distortState", "egoActiveState", "egoType"], function(values) { + + let settingMuteMessage = values.settingMuteMessage; + let settingWhisperRolls = values.settingWhisperRolls; + let settingWhisperTarget = values.settingWhisperTarget; + let settingLimbusStyle = values.settingLimbusStyle; + let settingHideNextTurn = values.settingHideNextTurn; + + let HP = values.HP; + let HPdamage = values.HP_max - HP; + let ST = values.StagRes; + let STdamage = values.StagRes_max - ST; + let SP = values.SP; + let SPdamage = values.SP_max - SP; + + let StaggerState = values.StaggerState; + let distortState = values.distortState; + let egoActiveState = values.egoActiveState; + let egoType = values.egoType; + + let scaling = 2; + + let output = {}; + let tempOutput = {}; + let ailmentList = {}; + + + /* Get all ailments */ + getAttrs(["burnNextTurnSetting", "bleedNextTurnSetting", "smokeNextTurnSetting", "chargeNextTurnSetting", + "Burn", "Bleed", "Paralysis", "Protection", "StaggerProtection", "Fragile", "Strength", "Feeble", "Endurance", "Disarm", "Haste", "Bind", "Smoke", "Charge", "Fortune", + "BurnNextTurn", "BleedNextTurn", "ParalysisNextTurn", "ProtectionNextTurn", "StaggerProtectionNextTurn", "FragileNextTurn", "StrengthNextTurn", "FeebleNextTurn", "EnduranceNextTurn", "DisarmNextTurn", "HasteNextTurn", "BindNextTurn", "SmokeNextTurn", "ChargeNextTurn", "FortuneNextTurn"], function(values) { + + const HasNextTurn = settingHideNextTurn == true ? 'false' : 'true'; + + let ailmentNames = ["Burn", "Bleed", "Paralysis", "Protection", "StaggerProtection", "Fragile", "Strength", "Feeble", "Endurance", "Disarm", "Haste", "Bind", "Smoke", "Charge", "Fortune"] + ailmentNames.forEach(ailment => { + if (["Burn", "Bleed", "Smoke", "Charge"].includes(ailment)) { + ailmentList[ailment] = [values[ailment.toLowerCase()+"NextTurnSetting"], values[ailment], values[`${ailment}NextTurn`]]; + } else { + ailmentList[ailment] = [HasNextTurn, values[ailment], values[`${ailment}NextTurn`]]; + } + }); + + /* Get all custom ailments */ + getSectionIDs(`repeating_ailments`, idarray => { + const fieldnames = idarray.reduce((rows,id) => + [...rows, `repeating_ailments_${id}_ailName`, `repeating_ailments_${id}_ailNextTurn`, + `repeating_ailments_${id}_ailNum`, `repeating_ailments_${id}_ailNumNextTurn`, ], ''); + + let ailName = ""; + let ailHasNextTurn = ""; + let ailNum = 0; + let ailNumNextTurn = 0; + + getAttrs([...fieldnames], v => { + idarray.forEach(id => { + ailName = v[`repeating_ailments_${id}_ailName`]; + ailHasNextTurn = v[`repeating_ailments_${id}_ailNextTurn`]; + ailNum = v[`repeating_ailments_${id}_ailNum`]; + ailNumNextTurn = v[`repeating_ailments_${id}_ailNumNextTurn`] + + ailmentList[ailName] = [ailHasNextTurn, ailNum, ailNumNextTurn, id]; + }); + + + /* Execute each AutoEffect in the AutoScript */ + AutoScript.forEach(AutoEffect => { + switch (AutoEffect[0][0]) { + case "Gain": tempOutput = autoEffectGainAilment(AutoEffect, ailmentList, scaling); break; + default: autoEffectErrorMessage(`${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); + } + for (const property in tempOutput) { + if (output.hasOwnProperty(property)) { + output[property] += tempOutput[property]; + } else { + output[property] = tempOutput[property]; + } + } + }); + + // console.log(output) + setAttrs(output); + + + /* Message handling */ + + + + }); + }); + }); + }); +} + + + + +/* Checks all nested AutoScripts and generated one non-nested AutoScript from all scripts matching a type */ +function AutoScriptCombiner(AutoEffectType) { + return; +} + +/* Gathers all AutoScripts that match a certain trigger type */ +function collectAutoScripts(triggerType) { + if (triggerType != "None") { + switch (triggerType) { + case "Permanent": break; /* Triggers with all other triggers. Useful for stuff like Status Quo */ + case "Combat start": return [["Gain","3","Rupture"],"This turn"]; + case "Round start": break; + case "Round end": break; + case "Damaged": break; + case "Staggered": break; + case "Defeated": break; + case "Panic": break; + case "Offensive": break; + case "Defensive": break; + case "Block": break; /* Also adds Defensive*/ + case "Evade": break; /* Also adds Defensive*/ + default: autoEffectErrorMessage(`${triggerType} is not a recognised trigger type`); break; + } + } + /* + getAttr augmentAutoScript outfitAutoScript egoAutoScript + only use egoAutoScript is distiortion or egoActive + remove all newlines and tab characters + convert autoscripts to an object using json + will be in format {triggerType1:'AutoScript', triggerType2:'AutoScript', ...} + switch (triggerType). If any key matches the triggerType, convert the AutoScript to an array + switch default: "trigger" is not a valid trigger type + return an array containing all generated AutoScript arrays + */ +} + +/* Removes all newline and tab characters as well as JavaScript comments from an AutoScript */ +function cleanAutoScript(AutoScript) { + let cleanAutoScript = AutoScript.replace(/(\r\n|\n|\r|\t)/gm, ""); + cleanAutoScript = cleanAutoScript.replace(/\/\*[\s\S]*?\*\/|(?<=[^:])\/\/.*|^\/\/.*/g,''); + return cleanAutoScript; +} + +/* Converts an AutoScript from a string to an array */ +function AutoScriptToArray(inputAutoScript) { + let AutoScript = inputAutoScript; + let AutoEffect = ""; + let AutoEffectArray = []; + let AutoScriptArray = []; + + /* Remove all newlines, tab spaces and comments */ + AutoScript = cleanAutoScript(AutoScript); + + do { + AutoScript = AutoScript.trim(); + + /* Checks if an AutoEffect still remains in the AutoScript */ + if (AutoScript.indexOf("(") == 0 && AutoScript.indexOf(")")) { + + /* Removes the next AutoEffect from the AutoScript. Removes the parentheses */ + AutoEffect = AutoScript.substring(1, AutoScript.indexOf(")")); + AutoScript = AutoScript.substring(AutoScript.indexOf(")")+1); + + /* Structures the AutoEffect into an array and stores it */ + AutoEffectArray = AutoEffect.trim().split(","); + AutoEffectArray = AutoEffectArray.map(e => e.trim()); + AutoEffectArray[0] = AutoEffectArray[0].split(/\s+/); + + AutoScriptArray.push(AutoEffectArray); + } else { + break; + } + } while (AutoScript.length > 1) + + /* Return the converted AutoScript */ + return AutoScriptArray; +} + +/* Checks that an AutoScript in array form is correctly formatted. Returns false upon detecting an error + let barValid = []; + let barValid = []; + + + inputAutoScript.forEach(AutoEffect => { + if (["Gain", "Require", "Consume", "Action", "Set", "Add", "ChallengeRoll"].includes(AutoEffect[0][0])) { + if (["Set", "Add"].includes(AutoEffect[0][0])) { + if (AutoEffect.length != 2) { + autoEffectErrorMessage(`Expected format: (${AutoEffect[0][0]} #Bar N)`, AutoEffect); return false; + } + } + if (AutoEffect[0][0] == "ChallengeRoll") { + if (AutoEffect.length != 2) { + autoEffectErrorMessage(`Expected format: (${AutoEffect[0][0]} #Stat N)`, AutoEffect); return false; + } + } + } + }); + else if (isNaN(parseInt(autoEffectArray[0][1]))) { autoEffectErrorMessage(`Value "${autoEffectArray[0][1]}" is not a number`, autoEffect); return null; } + else if (getAilmentAttribute(autoEffectArray[0][2]) == false) { autoEffectErrorMessage(`"Ailment "${autoEffectArray[0][2]}" does not exist`, autoEffect); return null; } + */ + +/*--- AutoScript functions end ---*/ + + +/*--- AutoEffect functions ---*/ + +/* Whispers an error message to the user detailing an AutoEffect error */ +function autoEffectErrorMessage(errorString, autoEffect) { + console.log(errorString + autoEffect) +} + + +/* Sets up a condition button with an AutoEffect, or appends the AutoEffect to the button if it already exists*/ +function conditionButton(conditional, AutoEffect) { + console.log("Creating conditionButton " + conditional + " with effect " + JSON.stringify(AutoEffect)); +} + +function autoEffectGainAilment(AutoEffect, ailmentList, scaling) { + /* Check format */ + if (AutoEffect[0].length != 3) { autoEffectErrorMessage(`Expected format: (Gain N #Ailment)`, AutoEffect); return {error: true}; } + + /* Handle scaling */ + AutoEffect[0][1] *= scaling; + if (scaling == 0) { return null } + + /* Get ailment name */ + let effectAilment = AutoEffect[0][2]; + if (!ailmentList.hasOwnProperty(effectAilment)) { autoEffectErrorMessage(`Ailment "${effectAilment}" does not exist`, AutoEffect); return {error: true}; } + + /* Get values */ + let effectVal = parseInt(Math.abs(AutoEffect[0][1])); + if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[0][1]}" is not a number`, AutoEffect); return {error: true}; } + let count = ailmentList[effectAilment][1]; + + /* Get conditionals */ + let forceTarget = ""; + if (AutoEffect.length > 1) { + let conditionalReturn = false; + AutoEffect.slice(1).forEach(conditional => { + switch (conditional.toLowerCase()) { + case "this turn": forceTarget = "This turn"; break; + case "next turn": forceTarget = "Next turn"; break; + default: + conditionButton(conditional, AutoEffect.slice(0,2)); + conditionalReturn = true; break; + } + }); + if (conditionalReturn) { return null; } + } + + /* Get target attribute */ + let effectTarget = ""; + let effectRepeatingId = ailmentList[effectAilment][3]; + let effectHasNextTurn = ailmentList[effectAilment][0]; + if (effectRepeatingId == undefined) { effectTarget = effectAilment; } /* If standard ailment */ + else { effectTarget = `repeating_ailments_${ailmentList[effectAilment][3]}_ailNum`; } /* If custom ailment */ + + /* Effect changes target to the next turn field if it's enabled */ + /* Is ignored if "This turn" conditional is included */ + if (effectHasNextTurn == 'true' && forceTarget != "This turn") { + effectTarget += "NextTurn"; + count = ailmentList[effectAilment][2]; + } + + /* Execute AutoEffect */ + return { [effectTarget]: parseInt(count) + parseInt(effectVal) } +} + + + + + + +/*--- AutoEffect functions end ---*/ + + /*--- Export/Import functions ---*/ let attrkeyCharacter = ["character_nameBase", "instinct", "wisdom", "justice", "charm", "insight", "temperance", "EXP", "character_job", "age", "height", "character_origin", "character_residence", "character_assets", "character_ahn", "character_url", "character_summary", "character_combatnote", "character_history", "character_relations", "character_notes", "character_desc", "character_personality", "character_background"]; From 9402071205a09023c78f3138c6824439cd98833e Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Tue, 23 Jul 2024 12:21:39 +0200 Subject: [PATCH 02/55] Feature modification: The Gain ailment AutoEffect now specifies its turn override as a property, not as a conditional --- ProjectMoonTRPG/ProjectMoonTRPG.html | 35 ++++++++++++++-------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 3b7a1b8967..797a2b9781 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -14486,7 +14486,7 @@ getAttrs(["settingEditMode"], function(values) { on("clicked:autoEffectTest", function() { - AutoScriptMain(`(Gain 5 Burn) /* Test comment */ (Gain 2 Fragile, Next Turn, TestCondition2)`, "Combat start") + AutoScriptMain(`(Gain 5 Burn) /* Test comment */ (Gain 2 Fragile Next Turn, TestCondition2)`, "Combat start") }); @@ -14619,7 +14619,7 @@ function collectAutoScripts(triggerType) { if (triggerType != "None") { switch (triggerType) { case "Permanent": break; /* Triggers with all other triggers. Useful for stuff like Status Quo */ - case "Combat start": return [["Gain","3","Rupture"],"This turn"]; + case "Combat start": return [["Gain","3","Rupture","This turn"]]; case "Round start": break; case "Round end": break; case "Damaged": break; @@ -14728,12 +14728,22 @@ function conditionButton(conditional, AutoEffect) { function autoEffectGainAilment(AutoEffect, ailmentList, scaling) { /* Check format */ - if (AutoEffect[0].length != 3) { autoEffectErrorMessage(`Expected format: (Gain N #Ailment)`, AutoEffect); return {error: true}; } + if (AutoEffect[0].length < 3 || AutoEffect[0].length > 6) { autoEffectErrorMessage(`Expected format: (Gain N #Ailment #Round(optional))`, AutoEffect); return {error: true}; } /* Handle scaling */ AutoEffect[0][1] *= scaling; if (scaling == 0) { return null } + /* Handle conditionals */ + if (AutoEffect.length > 1) { + let conditionalReturn = false; + AutoEffect.slice(1).forEach(conditional => { + conditionButton(conditional, AutoEffect.slice(0,2)); + conditionalReturn = true; + }); + if (conditionalReturn) { return null; } + } + /* Get ailment name */ let effectAilment = AutoEffect[0][2]; if (!ailmentList.hasOwnProperty(effectAilment)) { autoEffectErrorMessage(`Ailment "${effectAilment}" does not exist`, AutoEffect); return {error: true}; } @@ -14743,20 +14753,11 @@ function autoEffectGainAilment(AutoEffect, ailmentList, scaling) { if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[0][1]}" is not a number`, AutoEffect); return {error: true}; } let count = ailmentList[effectAilment][1]; - /* Get conditionals */ + /* Handle the optional turn override */ + /* This is between you and me, but "Next turn" doesn't actually do anything ;) */ let forceTarget = ""; - if (AutoEffect.length > 1) { - let conditionalReturn = false; - AutoEffect.slice(1).forEach(conditional => { - switch (conditional.toLowerCase()) { - case "this turn": forceTarget = "This turn"; break; - case "next turn": forceTarget = "Next turn"; break; - default: - conditionButton(conditional, AutoEffect.slice(0,2)); - conditionalReturn = true; break; - } - }); - if (conditionalReturn) { return null; } + if (AutoEffect[0][3] != undefined) { + if (["this", "thisturn", "this turn"].includes(AutoEffect[0][3].toLowerCase())) { forceTarget = "This turn"; } } /* Get target attribute */ @@ -14767,7 +14768,7 @@ function autoEffectGainAilment(AutoEffect, ailmentList, scaling) { else { effectTarget = `repeating_ailments_${ailmentList[effectAilment][3]}_ailNum`; } /* If custom ailment */ /* Effect changes target to the next turn field if it's enabled */ - /* Is ignored if "This turn" conditional is included */ + /* Is ignored if "This turn" override is included */ if (effectHasNextTurn == 'true' && forceTarget != "This turn") { effectTarget += "NextTurn"; count = ailmentList[effectAilment][2]; From bda673d5742e6efa6741930f393bca1026c41ee4 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Tue, 23 Jul 2024 15:54:28 +0200 Subject: [PATCH 03/55] New feature: AutoEffects, part 2 Added the Require and Consume AutoEffect as well as scaling support --- ProjectMoonTRPG/ProjectMoonTRPG.html | 448 +++++++++++++++++---------- 1 file changed, 284 insertions(+), 164 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 797a2b9781..c4d9dc4892 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -13074,7 +13074,6 @@ on('clicked:applyDamage', (info) => { if (ailmentArray["effect"] == "StagRes" || ailmentArray["effect"] == "HPStagRes") { stDamageBody += generateDamageHelperBodyEffect(ailmentArray["name"], ailmentArray["effectVal"], ailmentArray["type"], ailmentArray["customRes"], getIcon("ailments", ailmentArray["icon"]), ailmentArray["beforeRes"], stResistance, resSTIcon); } - console.log(ailmentArray["effect"]) if (ailmentArray["effect"] == "SP") { spDamageBody += generateDamageHelperBodyEffect(ailmentArray["name"], ailmentArray["effectVal"], ailmentArray["type"], ailmentArray["customRes"], getIcon("ailments", ailmentArray["icon"])); } @@ -14483,143 +14482,12 @@ getAttrs(["settingEditMode"], function(values) { /*--- AutoScript functions ---*/ - - -on("clicked:autoEffectTest", function() { - AutoScriptMain(`(Gain 5 Burn) /* Test comment */ (Gain 2 Fragile Next Turn, TestCondition2)`, "Combat start") - -}); - -/* Main function for using AutoScripts. Called by actions through on click events */ -/* inputAutoScript: AutoScript provided by the action. Can be an empty string */ -/* trigger: "Combat start", "Round start", "Round end", "Damaged", "Staggered", "Defeated", "Panic", - "Permanent", "Offensive", "Defensive", "Block", "Evade" or "None". - Selects which type of AutoEffects to collect and append to an AutoScript. - Block and Evade also include Defensive */ -function AutoScriptMain(inputAutoScript, triggerType="None") { - - /* Converts the input AutoScript to to an array if it isn't one already */ - let AutoScript = []; - if (inputAutoScript != "") { - try { AutoScript = JSON.parse(inputAutoScript); } - catch(e) { AutoScript = AutoScriptToArray(inputAutoScript); } - } - - /* Appends one or more AutoScripts based on the trigger type */ - AutoScript.push(collectAutoScripts(triggerType)); - - - /* Get relevant attributes */ - getAttrs(["settingMuteMessage", "settingWhisperRolls", "settingWhisperTarget", "settingLimbusStyle", "settingHideNextTurn", - "HP", "HP_max", "StagRes", "StagRes_max", "SP", "SP_max", - "StaggerState", "distortState", "egoActiveState", "egoType"], function(values) { - - let settingMuteMessage = values.settingMuteMessage; - let settingWhisperRolls = values.settingWhisperRolls; - let settingWhisperTarget = values.settingWhisperTarget; - let settingLimbusStyle = values.settingLimbusStyle; - let settingHideNextTurn = values.settingHideNextTurn; - - let HP = values.HP; - let HPdamage = values.HP_max - HP; - let ST = values.StagRes; - let STdamage = values.StagRes_max - ST; - let SP = values.SP; - let SPdamage = values.SP_max - SP; - - let StaggerState = values.StaggerState; - let distortState = values.distortState; - let egoActiveState = values.egoActiveState; - let egoType = values.egoType; - - let scaling = 2; - - let output = {}; - let tempOutput = {}; - let ailmentList = {}; - - - /* Get all ailments */ - getAttrs(["burnNextTurnSetting", "bleedNextTurnSetting", "smokeNextTurnSetting", "chargeNextTurnSetting", - "Burn", "Bleed", "Paralysis", "Protection", "StaggerProtection", "Fragile", "Strength", "Feeble", "Endurance", "Disarm", "Haste", "Bind", "Smoke", "Charge", "Fortune", - "BurnNextTurn", "BleedNextTurn", "ParalysisNextTurn", "ProtectionNextTurn", "StaggerProtectionNextTurn", "FragileNextTurn", "StrengthNextTurn", "FeebleNextTurn", "EnduranceNextTurn", "DisarmNextTurn", "HasteNextTurn", "BindNextTurn", "SmokeNextTurn", "ChargeNextTurn", "FortuneNextTurn"], function(values) { - - const HasNextTurn = settingHideNextTurn == true ? 'false' : 'true'; - - let ailmentNames = ["Burn", "Bleed", "Paralysis", "Protection", "StaggerProtection", "Fragile", "Strength", "Feeble", "Endurance", "Disarm", "Haste", "Bind", "Smoke", "Charge", "Fortune"] - ailmentNames.forEach(ailment => { - if (["Burn", "Bleed", "Smoke", "Charge"].includes(ailment)) { - ailmentList[ailment] = [values[ailment.toLowerCase()+"NextTurnSetting"], values[ailment], values[`${ailment}NextTurn`]]; - } else { - ailmentList[ailment] = [HasNextTurn, values[ailment], values[`${ailment}NextTurn`]]; - } - }); - - /* Get all custom ailments */ - getSectionIDs(`repeating_ailments`, idarray => { - const fieldnames = idarray.reduce((rows,id) => - [...rows, `repeating_ailments_${id}_ailName`, `repeating_ailments_${id}_ailNextTurn`, - `repeating_ailments_${id}_ailNum`, `repeating_ailments_${id}_ailNumNextTurn`, ], ''); - - let ailName = ""; - let ailHasNextTurn = ""; - let ailNum = 0; - let ailNumNextTurn = 0; - - getAttrs([...fieldnames], v => { - idarray.forEach(id => { - ailName = v[`repeating_ailments_${id}_ailName`]; - ailHasNextTurn = v[`repeating_ailments_${id}_ailNextTurn`]; - ailNum = v[`repeating_ailments_${id}_ailNum`]; - ailNumNextTurn = v[`repeating_ailments_${id}_ailNumNextTurn`] - - ailmentList[ailName] = [ailHasNextTurn, ailNum, ailNumNextTurn, id]; - }); - - - /* Execute each AutoEffect in the AutoScript */ - AutoScript.forEach(AutoEffect => { - switch (AutoEffect[0][0]) { - case "Gain": tempOutput = autoEffectGainAilment(AutoEffect, ailmentList, scaling); break; - default: autoEffectErrorMessage(`${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); - } - for (const property in tempOutput) { - if (output.hasOwnProperty(property)) { - output[property] += tempOutput[property]; - } else { - output[property] = tempOutput[property]; - } - } - }); - - // console.log(output) - setAttrs(output); - - - /* Message handling */ - - - - }); - }); - }); - }); -} - - - - -/* Checks all nested AutoScripts and generated one non-nested AutoScript from all scripts matching a type */ -function AutoScriptCombiner(AutoEffectType) { - return; -} - /* Gathers all AutoScripts that match a certain trigger type */ function collectAutoScripts(triggerType) { if (triggerType != "None") { switch (triggerType) { case "Permanent": break; /* Triggers with all other triggers. Useful for stuff like Status Quo */ - case "Combat start": return [["Gain","3","Rupture","This turn"]]; + case "Combat start": return [["Gain","3","Tremor","This turn"]]; case "Round start": break; case "Round end": break; case "Damaged": break; @@ -14687,29 +14555,182 @@ function AutoScriptToArray(inputAutoScript) { return AutoScriptArray; } -/* Checks that an AutoScript in array form is correctly formatted. Returns false upon detecting an error - let barValid = []; - let barValid = []; +on("clicked:autoEffectTest", function() { + AutoScriptMain(`(Require 1 Rupture Scaling) /* Test comment */ (Gain 2 Fragile Next Turn, TestCondition2)`, "Combat start") + +}); + +/* Main function for using AutoScripts. Called by actions through on click events */ +/* inputAutoScript: AutoScript provided by the action. Can be an empty string */ +/* trigger: "Combat start", "Round start", "Round end", "Damaged", "Staggered", "Defeated", "Panic", + "Permanent", "Offensive", "Defensive", "Block", "Evade" or "None". + Selects which type of AutoEffects to collect and append to an AutoScript. + Block and Evade also include Defensive */ +function AutoScriptMain(inputAutoScript, triggerType="None") { + + /* Converts the input AutoScript to to an array if it isn't one already */ + let AutoScript = []; + if (inputAutoScript != "") { + try { AutoScript = JSON.parse(inputAutoScript); } + catch(e) { AutoScript = AutoScriptToArray(inputAutoScript); } + } + + /* Appends one or more AutoScripts based on the trigger type */ + AutoScript.push(collectAutoScripts(triggerType)); + + + /* Get relevant attributes */ + getAttrs(["settingMuteMessage", "settingWhisperRolls", "settingWhisperTarget", "settingLimbusStyle", "settingHideNextTurn", + "HP", "HP_max", "StagRes", "StagRes_max", "SP", "SP_max", + "StaggerState", "distortState", "egoActiveState", "egoType"], function(values) { + + let settingMuteMessage = values.settingMuteMessage; + let settingWhisperRolls = values.settingWhisperRolls; + let settingWhisperTarget = values.settingWhisperTarget; + let settingLimbusStyle = values.settingLimbusStyle; + let settingHideNextTurn = values.settingHideNextTurn; + let HP = values.HP; + let ST = values.StagRes; + let SP = values.SP; + let barList = { HP: parseInt(HP), ST:parseInt(ST), SP:parseInt(SP) }; + + let HPdamage = values.HP_max - HP; + let STdamage = values.StagRes_max - ST; + let SPdamage = values.SP_max - SP; + let barDamageList = { "-HP": HPdamage, "-ST":STdamage, "-SP":SPdamage } + + let StaggerState = values.StaggerState; + let distortState = values.distortState; + let egoActiveState = values.egoActiveState; + let egoType = values.egoType; - inputAutoScript.forEach(AutoEffect => { - if (["Gain", "Require", "Consume", "Action", "Set", "Add", "ChallengeRoll"].includes(AutoEffect[0][0])) { - if (["Set", "Add"].includes(AutoEffect[0][0])) { - if (AutoEffect.length != 2) { - autoEffectErrorMessage(`Expected format: (${AutoEffect[0][0]} #Bar N)`, AutoEffect); return false; - } - } - if (AutoEffect[0][0] == "ChallengeRoll") { - if (AutoEffect.length != 2) { - autoEffectErrorMessage(`Expected format: (${AutoEffect[0][0]} #Stat N)`, AutoEffect); return false; - } + let scaling = 1; + let checkResult = "success"; + + let output = {}; + let tempOutput = {}; + let returnValues = { checkResult:"success", error:false, }; + let ailmentList = {}; + + + /* Get all ailments */ + getAttrs(["burnNextTurnSetting", "bleedNextTurnSetting", "smokeNextTurnSetting", "chargeNextTurnSetting", + "Burn", "Bleed", "Paralysis", "Protection", "StaggerProtection", "Fragile", "Strength", "Feeble", "Endurance", "Disarm", "Haste", "Bind", "Smoke", "Charge", "Fortune", + "BurnNextTurn", "BleedNextTurn", "ParalysisNextTurn", "ProtectionNextTurn", "StaggerProtectionNextTurn", "FragileNextTurn", "StrengthNextTurn", "FeebleNextTurn", "EnduranceNextTurn", "DisarmNextTurn", "HasteNextTurn", "BindNextTurn", "SmokeNextTurn", "ChargeNextTurn", "FortuneNextTurn"], function(values) { + + const HasNextTurn = settingHideNextTurn == true ? 'false' : 'true'; + + let ailmentNames = ["Burn", "Bleed", "Paralysis", "Protection", "StaggerProtection", "Fragile", "Strength", "Feeble", "Endurance", "Disarm", "Haste", "Bind", "Smoke", "Charge", "Fortune"] + ailmentNames.forEach(ailment => { + if (["Burn", "Bleed", "Smoke", "Charge"].includes(ailment)) { + ailmentList[ailment] = [values[ailment.toLowerCase()+"NextTurnSetting"], values[ailment], values[`${ailment}NextTurn`]]; + } else { + ailmentList[ailment] = [HasNextTurn, values[ailment], values[`${ailment}NextTurn`]]; + } + }); + + /* Get all custom ailments */ + getSectionIDs(`repeating_ailments`, idarray => { + const fieldnames = idarray.reduce((rows,id) => + [...rows, `repeating_ailments_${id}_ailName`, `repeating_ailments_${id}_ailNextTurn`, + `repeating_ailments_${id}_ailNum`, `repeating_ailments_${id}_ailNumNextTurn`, ], ''); + + let ailName = ""; + let ailHasNextTurn = ""; + let ailNum = 0; + let ailNumNextTurn = 0; + + getAttrs([...fieldnames], v => { + idarray.forEach(id => { + ailName = v[`repeating_ailments_${id}_ailName`]; + ailHasNextTurn = v[`repeating_ailments_${id}_ailNextTurn`]; + ailNum = v[`repeating_ailments_${id}_ailNum`]; + ailNumNextTurn = v[`repeating_ailments_${id}_ailNumNextTurn`] + + ailmentList[ailName] = [ailHasNextTurn, ailNum, ailNumNextTurn, id]; + }); + + + /* Execute each AutoEffect in the AutoScript */ + AutoScript.forEach(AutoEffect => { + /* Checks are always processed. Other AutoEffects are not processed if the last check failed */ + switch (AutoEffect[0][0]) { + case "Require": tempOutput = autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList); break; + case "Consume": tempOutput = autoEffectConsume(AutoEffect, ailmentList, barList); break; + default: tempOutput = {}; break; + } + if (checkResult != "failure") { + switch (AutoEffect[0][0]) { + case "Require": break; /* Already executed above */ + case "Consume": break; + case "Gain": tempOutput = autoEffectGainAilment(AutoEffect, ailmentList, scaling); break; + default: tempOutput = {error:true}; autoEffectErrorMessage(`${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); break; } } - }); - else if (isNaN(parseInt(autoEffectArray[0][1]))) { autoEffectErrorMessage(`Value "${autoEffectArray[0][1]}" is not a number`, autoEffect); return null; } - else if (getAilmentAttribute(autoEffectArray[0][2]) == false) { autoEffectErrorMessage(`"Ailment "${autoEffectArray[0][2]}" does not exist`, autoEffect); return null; } - */ + console.log(tempOutput) + /* Handle errors. Continues executing AutoEffects for the sake of finding additional errors, */ + /* but does not apply any changes to attributes */ + if (tempOutput.hasOwnProperty("error") || returnValues.error == true) { + returnValues.error == true; + output = {}; + return; + } + + /* Handle changes to scaling */ + if (tempOutput.hasOwnProperty("scaling")) { + scaling = parseInt(tempOutput.scaling); + delete tempOutput.scaling; + } + + /* Handle check results from Require and Consume */ + /* For the returnValues, the worst result is returned */ + if (tempOutput.checkResult != undefined) { + checkResult = tempOutput.checkResult; + if (returnValues.checkResult == "success") { + returnValues.checkResult = tempOutput.checkResult; + } + else if (returnValues.checkResult == "last success" && tempOutput.checkResult == "failure") { + returnValues.checkResult = tempOutput.checkResult; + } + delete tempOutput.checkResult; + } + + /* Add attribute changes from AutoEffect to output */ + /* The first time a attribute is modified, add it's count */ + /* For example, if Gain 3 Burn is used and current Burn is 2, output Burn is set to 5 */ + /* If Consume 4 Burn is used later, this amount will be removed without adding count */ + for (const property in tempOutput) { + if (output.hasOwnProperty(property)) { + output[property] += tempOutput[property]; + } else { + output[property] = tempOutput[property] + tempOutput.count; + } + } + }); + + // console.log(output) + setAttrs(output); + + console.log(returnValues) + + + /* Message handling */ + + + /* Error handling */ + if (returnValues.error == true) { + /* Run function that clears all condition buttons */ + } + + + + }); + }); + }); + }); +} /*--- AutoScript functions end ---*/ @@ -14720,10 +14741,116 @@ function autoEffectErrorMessage(errorString, autoEffect) { console.log(errorString + autoEffect) } +/* Checks if an AutoEffect has conditionals */ +/* If true, creates a condition button for each conditional and returns true */ +/* If the condition button already exists, append the AutoEffect to the existing button */ +/* If false, returns false */ +function processConditionals(AutoEffect) { + if (AutoEffect.length > 1) { + AutoEffect.slice(1).forEach(conditional => { + /* Remember to apply AutoEffect.slice(0,2)) */ + console.log("Creating conditionButton " + conditional + " with effect " + JSON.stringify(AutoEffect.slice(0,2))); + }); + return true; + } + return false; +} -/* Sets up a condition button with an AutoEffect, or appends the AutoEffect to the button if it already exists*/ -function conditionButton(conditional, AutoEffect) { - console.log("Creating conditionButton " + conditional + " with effect " + JSON.stringify(AutoEffect)); + +function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { + /* Check format */ + if (AutoEffect[0].length < 3 || AutoEffect[0].length > 4) { autoEffectErrorMessage(`Expected format: (Require N #Ailment/#Bar/#BarDamage #Scaling(optional))`, AutoEffect); return {error: true}; } + + /* Handle conditionals */ + if (processConditionals(AutoEffect) == true) { return {}; } + + /* Get required value */ + let effectVal = parseInt(Math.abs(AutoEffect[0][1])); + if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[0][1]}" is not a number`, AutoEffect); return {error: true}; } + + /* Get target count */ + let effectName = AutoEffect[0][2]; + + /* Handle ailment count */ + if (ailmentList.hasOwnProperty(effectName)) { count = ailmentList[effectName][1]; } + /* Handle bar count */ + else if (barList.hasOwnProperty(effectName)) { count = barList[effectName]; } + /* Handle bar damage count */ + else if (barDamageList.hasOwnProperty(effectName)) { count = barDamageList[effectName]; } + else { autoEffectErrorMessage(`Ailment, Bar or BarDamage "${effectName}" does not exist`, AutoEffect); return {error: true}; } + + /* Handle the optional scaling property */ + let scaling = 1; + let returnValues = {}; + if (AutoEffect[0][3] != undefined) { + if (AutoEffect[0][3].toLowerCase() == "scaling") { + scaling = Math.floor(count/effectVal); + returnValues.scaling = scaling; + } + } + + /* Execute AutoEffect check */ + if (count >= effectVal) { + returnValues.checkResult = "success"; + } else { + returnValues.checkResult = "failure"; + } + return returnValues; +} + +function autoEffectConsume(AutoEffect, ailmentList, barList) { + /* Check format */ + if (AutoEffect[0].length < 3 || AutoEffect[0].length > 4) { autoEffectErrorMessage(`Expected format: (Consume N #Ailment/#Bar #Scaling(optional))`, AutoEffect); return {error: true}; } + + /* Handle conditionals */ + if (processConditionals(AutoEffect) == true) { return {}; } + + /* Get consumed value */ + let effectVal = parseInt(Math.abs(AutoEffect[0][1])); + if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[0][1]}" is not a number`, AutoEffect); return {error: true}; } + let count = 0; + + /* Get target */ + let effectName = AutoEffect[0][2]; + let effectTarget = ""; + let effectRepeatingId = ailmentList[effectName][3]; + + /* Handle ailment target */ + if (ailmentList.hasOwnProperty(effectName)) { + if (effectRepeatingId == undefined) { effectTarget = effectName; } /* If standard ailment */ + else { effectTarget = `repeating_ailments_${ailmentList[effectName][3]}_ailNum`; } /* If custom ailment */ + count = ailmentList[effectName][1]; + } + /* Handle bar target */ + else if (barList.hasOwnProperty(effectName)) { + effectTarget = effectName; + count = barList[effectName]; + } + else { autoEffectErrorMessage(`Ailment or Bar "${effectName}" does not exist`, AutoEffect); return {error: true}; } + + /* Handle the optional scaling property */ + let scaling = 1; + let returnValues = {}; + if (AutoEffect[0][3] != undefined) { + if (AutoEffect[0][3].toLowerCase() == "scaling") { + scaling = Math.floor(count/effectVal); + returnValues.scaling = scaling; + } + } + + /* Execute AutoEffect check */ + if (count >= effectVal) { + returnValues[effectTarget] = -effectVal*scaling; + returnValues.count = parseInt(count); + if (!(count >= 2*effectVal)) { + returnValues.checkResult = "last success"; + } else { + returnValues.checkResult = "success"; + } + } else { + returnValues.checkResult = "failure"; + } + return returnValues; } function autoEffectGainAilment(AutoEffect, ailmentList, scaling) { @@ -14732,17 +14859,10 @@ function autoEffectGainAilment(AutoEffect, ailmentList, scaling) { /* Handle scaling */ AutoEffect[0][1] *= scaling; - if (scaling == 0) { return null } + if (scaling == 0) { return {}; } /* Handle conditionals */ - if (AutoEffect.length > 1) { - let conditionalReturn = false; - AutoEffect.slice(1).forEach(conditional => { - conditionButton(conditional, AutoEffect.slice(0,2)); - conditionalReturn = true; - }); - if (conditionalReturn) { return null; } - } + if (processConditionals(AutoEffect) == true) { return {}; } /* Get ailment name */ let effectAilment = AutoEffect[0][2]; @@ -14775,7 +14895,7 @@ function autoEffectGainAilment(AutoEffect, ailmentList, scaling) { } /* Execute AutoEffect */ - return { [effectTarget]: parseInt(count) + parseInt(effectVal) } + return { [effectTarget]: parseInt(effectVal), count:parseInt(count) } } From 8834f2adc050a27696ed8823cf793080277ca037 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Tue, 23 Jul 2024 17:21:26 +0200 Subject: [PATCH 04/55] New feature: AutoEffect, part 3 Added edit AutoScript button to all UI elements Skills still need buttons --- ProjectMoonTRPG/ProjectMoonTRPG.html | 70 ++++++++++-------- ProjectMoonTRPG/ProjectMoonTRPGStyle.css | 30 +++++++- ProjectMoonTRPG/images/icons/script.png | Bin 0 -> 2682 bytes .../imagesResized/icons/script.png | Bin 0 -> 873 bytes 4 files changed, 69 insertions(+), 31 deletions(-) create mode 100644 ProjectMoonTRPG/images/icons/script.png create mode 100644 ProjectMoonTRPG/imagesResized/icons/script.png diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index c4d9dc4892..adc0319503 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -251,8 +251,8 @@
- +
@@ -845,9 +845,8 @@
- - +
@@ -6186,7 +6185,8 @@ - + +
@@ -6309,7 +6309,8 @@ - + +
@@ -6437,7 +6438,8 @@ - + +
@@ -6561,7 +6563,8 @@ - + +
@@ -6687,6 +6690,7 @@ +
@@ -6741,8 +6745,8 @@
- - + +
@@ -7333,14 +7337,14 @@
-
Icon:
- +
Icon:
+
-
Uses:
+
Uses:
/ - +
@@ -7351,7 +7355,8 @@
- + +
@@ -7398,14 +7403,14 @@
-
Icon:
- +
Icon:
+
-
Uses:
+
Uses:
/ - +
@@ -7416,7 +7421,8 @@
- + +
@@ -7470,14 +7476,14 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects.">
-
Icon:
- +
Icon:
+
-
Uses:
+
Uses:
/ - +
@@ -7488,7 +7494,8 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects.">
- + +
@@ -7537,14 +7544,14 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects.">
-
Icon:
- +
Icon:
+
-
Uses:
+
Uses:
/ - +
@@ -7555,7 +7562,8 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects.">
- + +
@@ -7593,6 +7601,7 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects."> +
@@ -7665,6 +7674,7 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects."> +
@@ -14556,7 +14566,7 @@ function AutoScriptToArray(inputAutoScript) { } on("clicked:autoEffectTest", function() { - AutoScriptMain(`(Require 1 Rupture Scaling) /* Test comment */ (Gain 2 Fragile Next Turn, TestCondition2)`, "Combat start") + AutoScriptMain(`(Require 20 -HP Scaling) /* Test comment */ (Gain 2 Fragile Next Turn, TestCondition2)`, "Combat start") }); diff --git a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css index 26c84ff5e0..b2d8655d69 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css +++ b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css @@ -1320,6 +1320,10 @@ button[type=roll].NDice, button[type=action].NDice{ /* Outfit custom resistance display */ +.outfitCustomResistDisplay { + width: 300px; +} + :is(.outfitContainer, .egoContainer, .distortionContainer) .editCover .hide-toggle:checked ~ .hide-item { display: flex; } @@ -1377,6 +1381,12 @@ opacity: 30%; .tool input[type=checkbox], .profileHeader input[type=checkbox] { display:none; } +.toolMaxInput:not(:hover):not(:focus)::-webkit-inner-spin-button, +.toolMaxInput:not(:hover):not(:focus)::-webkit-outer-spin-button, +.toolMaxInput:not(:hover):not(:focus)::-webkit-inner-spin-button, +.toolMaxInput:not(:hover):not(:focus)::-webkit-outer-spin-button { + display: none; +} .portableIcon { background-image: url("https://raw.githubusercontent.com/punibird/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/icons/Portable.png"); } @@ -2498,7 +2508,7 @@ justify-content: center; .editButton { position: absolute; bottom: 5px; - right: 40px; + right: 35px; z-index: 20; height: 25px; width: 25px; @@ -2509,6 +2519,24 @@ justify-content: center; background-repeat: no-repeat; } +.autoScriptButton { + position: absolute; + bottom: 5px; + right: 65px; + z-index: 20; + height: 25px; + width: 25px; + border-radius: 5px; + background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/icons/script.png'); + background-size: contain; + background-position: center; + background-repeat: no-repeat; +} + +:is(.augmentBlock, .specialBlock) .autoScriptButton { + right: 35px; +} + .copyButton { position: absolute; top: 5px; diff --git a/ProjectMoonTRPG/images/icons/script.png b/ProjectMoonTRPG/images/icons/script.png new file mode 100644 index 0000000000000000000000000000000000000000..7a68976da9d679d96738c7b25f26d75bc63af7a7 GIT binary patch literal 2682 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 literal 0 HcmV?d00001 From 57223ac6d4efb7a7b18d5d9901a2abd7b7c7b247 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Tue, 23 Jul 2024 22:05:46 +0200 Subject: [PATCH 05/55] Change AutoScript button icon Also fixes some AutoScript bugs --- ProjectMoonTRPG/ProjectMoonTRPG.html | 8 ++++++-- ProjectMoonTRPG/ProjectMoonTRPGStyle.css | 2 +- ProjectMoonTRPG/images/icons/script.png | Bin 2682 -> 6700 bytes .../imagesResized/icons/script.png | Bin 873 -> 3397 bytes 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index adc0319503..2174e1dbc5 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -14566,7 +14566,7 @@ function AutoScriptToArray(inputAutoScript) { } on("clicked:autoEffectTest", function() { - AutoScriptMain(`(Require 20 -HP Scaling) /* Test comment */ (Gain 2 Fragile Next Turn, TestCondition2)`, "Combat start") + AutoScriptMain(`(Require 2 Charge) (Consume 2 Charge)`, "Combat start") }); @@ -14653,13 +14653,15 @@ function AutoScriptMain(inputAutoScript, triggerType="None") { getAttrs([...fieldnames], v => { idarray.forEach(id => { - ailName = v[`repeating_ailments_${id}_ailName`]; + ailName = v[`repeating_ailments_${id}_ailName`].replace(" ","_"); ailHasNextTurn = v[`repeating_ailments_${id}_ailNextTurn`]; ailNum = v[`repeating_ailments_${id}_ailNum`]; ailNumNextTurn = v[`repeating_ailments_${id}_ailNumNextTurn`] ailmentList[ailName] = [ailHasNextTurn, ailNum, ailNumNextTurn, id]; }); + + console.log(ailmentList) /* Execute each AutoEffect in the AutoScript */ @@ -14888,6 +14890,8 @@ function autoEffectGainAilment(AutoEffect, ailmentList, scaling) { let forceTarget = ""; if (AutoEffect[0][3] != undefined) { if (["this", "thisturn", "this turn"].includes(AutoEffect[0][3].toLowerCase())) { forceTarget = "This turn"; } + } else { + autoEffectErrorMessage(`"${AutoEffect[0][1]}". Expected "This turn" or "Next turn"`, AutoEffect); return {error: true}; } /* Get target attribute */ diff --git a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css index b2d8655d69..63f1d3c605 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css +++ b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css @@ -2527,7 +2527,7 @@ justify-content: center; height: 25px; width: 25px; border-radius: 5px; - background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/icons/script.png'); + background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/AutoEffects-Functionality/ProjectMoonTRPG/imagesResized/icons/script.png'); background-size: contain; background-position: center; background-repeat: no-repeat; diff --git a/ProjectMoonTRPG/images/icons/script.png b/ProjectMoonTRPG/images/icons/script.png index 7a68976da9d679d96738c7b25f26d75bc63af7a7..4acdb1a9a675d6d7565a986fb4d6786226372b66 100644 GIT binary patch literal 6700 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 IRE1;y15M5~+5i9m delta 2671 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 delta 824 zcmV-81IPTu8tDd*865-w006W$Kso>b010qNS#tmYxQqY*xQqeJ_PZ~WwF)YK^hrcP zR9J=W*h_3wRTu!^Z>ER^wY32((x}vuun?MPOkA+25=EgJlQ!Mx!bD>tq=I2*kVFld zxG)wKt1L{^$bu;9qE=!M7n-orpo!pv##b$cff7?6CGCuhxgGAb_uhGQy0ZW3KmR@V zd~@%)uQREf`H$2BvVcs-a@#$BsJ@EPCLHjxGo_KedZnuXrXy>=t;xt<+vfmG#~U7t zN0u9vM#fg>su;XUziW`S%4i(&tlh|HmaT$-lo8F?r#B8c)uSx>CypJJmamcV$ z*y!jSkUM;aKeYVckT%y>F!-<^Dn~XtQUL*-KCTqmp|3(@r4>I}MnsRH7pyG>S# zR2vJ({34~^D^ZWpb-vV4F0#U~%Myt*?(ubyFOrru8MHQgL3=sKlb%l`p0nHZ&fVU! z$fOO92bFaADC3dqoUkMYm~y|tQ2PrTz<_(Bx+l#^oy9Ro&cC5ny|Li4W5N}tDnrVP zl#kq3Xua*B+99{OOTTe{?G9@y+H%$=Cp3COzu)G9EO9P&zAnW-8uHg$b;vGzN)pg( zUow*Rj@2`EO6hYDr!|*_e3yTY$0OVFzoIB|ZuJ!!{i-2Uzi7V!T^?2!s$S6I?_^|) zfmz6utBr$JLxt+3R=gaY5oAZ)Id|lI;r<9eOpdxe$bPwW*%Tu~TG8!LNn)*&g*>ax&tQ!o zLw%MxABF6(3umn?@xgtqpDYcvryOuhhn~>1Gwy~wQ;e)|S{kFa8H*e~<6GfVl^mz6 znT_z;%vI8i_){Z)c6zZa Date: Tue, 23 Jul 2024 22:15:35 +0200 Subject: [PATCH 06/55] Change AutoScript button icon again --- ProjectMoonTRPG/images/icons/script.png | Bin 6700 -> 10683 bytes .../imagesResized/icons/script.png | Bin 3397 -> 3934 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/ProjectMoonTRPG/images/icons/script.png b/ProjectMoonTRPG/images/icons/script.png index 4acdb1a9a675d6d7565a986fb4d6786226372b66..1387aaf69198e2b936c46f1bd3d58d8fe2afd6eb 100644 GIT binary patch delta 7971 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 OyQpQLS*&qA?0*0`n)w|7 delta 3956 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 jT+FB>1#3lU8K000R9NkvXXu0mjft*|hX delta 627 zcmV-(0*w9M9>p54-U@#LQAtEWRA_SLRpXyJMjgGP#-`< zEYwbd5GxWdv9KgataL|2EG1$i7Gft7Arcb05V5L;Rw(UQoZfWqbf%qqr_5;PznVES z&pFTko;h>QxziCvk@-MJEmAS6Cb9r4F^kS6_Pl{r z61j!`MA>G%%@bUfNG}fKKDuxd+cNIGf&p~nJa(nsRF=pX7PT2WfFsGmRzwb^x%{5YK+iPAc02gD3+&O|Ao8QgdG`e-NXKA73UE7idA_t zorOkXOYkFcZ5)3KW9M7&I&ses)}&UPL*$z`p6ncj+0J~F?oxrn{y7tA6ljGzJ zF3-?5T*QU6BwH0J@>nGq!HU@VG2BSpGo<;4I*F@km6a)yYof@VowQkOA}>?^b50iyF^%w-|@n-dZd5IEc_TdlZ9o8^x=}wGrc&f zdEhsQgjeu&Y!xQuwGzESxr05)OU>)82#0VxPjHn)Xny2AU}N6Es)@u`5hrjhZ(!9# zRttNOF}x5~2)(8joS9TjBuO70m|7BLQe}~I!rChGpNo9NI Date: Tue, 23 Jul 2024 22:23:53 +0200 Subject: [PATCH 07/55] Change AutoScript button icon... again. Forgot to remove the black background --- ProjectMoonTRPG/images/icons/script.png | Bin 10683 -> 7753 bytes .../imagesResized/icons/script.png | Bin 3934 -> 3736 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/ProjectMoonTRPG/images/icons/script.png b/ProjectMoonTRPG/images/icons/script.png index 1387aaf69198e2b936c46f1bd3d58d8fe2afd6eb..442726417f8e5923cf728ab4e22fc65c9ab66f69 100644 GIT binary patch delta 5018 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 OcTvkgvsmML*#7{z-T6WQ diff --git a/ProjectMoonTRPG/imagesResized/icons/script.png b/ProjectMoonTRPG/imagesResized/icons/script.png index cad739f22d0bea64d338c59b013d6f5e3e1074d1..36063ecbedaa58fc59a601c7700292f9102faa5f 100644 GIT binary patch delta 969 zcmV;)12+8L9+(}l-U@#Mq)9|URA_=v`%Tj#yL_dYXk+Gffz#^8St*8qu`8X$2~1EiWV4CAM!X-R(ofK)0ajgF3zs4-#z z0swnO5JDb^qIfrIfVzWhZEc-vYioP6d(9XFj^ntfaiV}sMGX!BV4CJvRaIXE*|OQ} zU}tCN2Y=ldV+$dah?1uy2xDxR(B9Ryo1fl4SJ3Bi-2>Gb% z`k?E&Aj@*Wl?s2eB4ziUZQGv|ML7uofH5Wrq2iU7P&S)A)z#JYF~}AP#4rqpQuYo6{7+98dDUnFL`djQ5Ns^8S z>>CduBo>NaGY|lP&CShc?d|P1^2aR8y4cjzl-ie&F&2NY;ze`U6l8XGmYDWdoCMZ*R}G zwzgi*AIs%(x0;)q9~a3P80#Nn1uGKfDYWOmw6vrQ4GmfU1ZNC3Ha2c{baXtOo15dt z$H!^V1eJe!fq|mmM9E}wra+vsWZO0>Ami1ZJ^%EFlKnPX8wW^`j)zzM!o}M56 zag4Ep5JFL6)fEH)V10f4Y%-aA>l;3h&-g%)TrPiih2ywuVG~hGpR}~JESAdQy6!_s zlJ10!yI0r&KYsVgFpNiaM$=IyFzSlbOO=CAN{2yto?on1MN#Ft?q^Ao21@xI_>Z1S#29-Y r_TNn1f4x;p4Uo900TMSgK;ov~rxXjj%r{y500000NkvXXu0mjf)2Y#a delta 1169 zcmV;C1aAA79o`TofsSgHRpZEGQxh;s@BpL90cin$nN7vAM(LAO5l5 zxwV#y&vxE(&hx&%llJ5!Apmgr2SnfpB)9Yfl55Ht5RxRpaU6d*PFy)T0YcL>6bc0Z zU}$Iv>+9=jdwe@cUS1wTp%CA`xw%1YZEe~<-wv{}vVzgkQNGP_98@Y5XqryTCnb>b z@^TCh4}&C0L?V%tj7gFN0Qh`9EG#Sl0JK^y9v>h1F>`Zsn4g~qK@ftu!C(+|b#-t$ zoqSBCQsM3GO+0@{e}6x=x3^O&K9&py1Fo*F(Ae0BlamvKLLtyJ4YgVgiA0icuHWxR zAP|6BtwuN;Mt**N+_6bP#O@*h;PH5%R;vO0S>;59q$0D~42#7Qvo9?Wuh$EfWua23 zqJ9ps=2cf$!|8NFtJUJ+;UWFXKgsX+qoAN5W?xz$$%=nZq^_5GyS$h1=~G#P;|1(b3T%EHp`O(I5mtKqiwVG-nt_&>kBb z!}9X7Af|uSYT@$td8tyU`>4o82+w%=ed2#TU&_GRtQ9tZ>=m&--Z z2Y{)mDOj!6n0;9Tsjsic#l;0Uj>F5#3p5%HIF3u`$+9fo-``POTnvU`Kv7iOlSWpz z-=d--csw57%VaWPad9zf9K$fEs;a{C^D}@y_ZEtx;Pd(7dS?|RmX?;5U^1BmF{M%o zuh)N@mXBzV-Q8WZw6vt0$Y!%)e0)4A{&@$yzP^TDuTR;RuMHwV41`ax$4L?(zLU z}%b=LYDg+d|B%*^olvH~KJNWikJ*qY<& z`1lyj&CLL^ct!r^?MggZEEbr}W&l|PAqWCWrBY12F%^kK1jmxBfqb?88IarCThxEl z)TEp@XF=RE0qN`OgUx2kR847%rfC!w7A76{WgmJnq37r4s8_7<^zEPCGNm7o jT+FB>1#3lU8K000R9NkvXXu0mjf?bI-6 From bd9b7851cb6bce0ce5b7807d60100a43bc939d6e Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Wed, 24 Jul 2024 00:39:05 +0200 Subject: [PATCH 08/55] New functionality: AutoScript, part 4 Added AutoScript editor functionality. All skills and equipment have a new edit AutoScript button which opens the editor. Writing text into the editor modifies the AutoScript of the skill/equipment --- ProjectMoonTRPG/ProjectMoonTRPG.html | 125 +++++++++++++++---- ProjectMoonTRPG/ProjectMoonTRPGStyle.css | 38 +++++- ProjectMoonTRPG/images/icons/exit.png | Bin 0 -> 5101 bytes ProjectMoonTRPG/imagesResized/icons/exit.png | Bin 0 -> 3093 bytes ProjectMoonTRPG/translation.json | 3 + 5 files changed, 141 insertions(+), 25 deletions(-) create mode 100644 ProjectMoonTRPG/images/icons/exit.png create mode 100644 ProjectMoonTRPG/imagesResized/icons/exit.png diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 2174e1dbc5..26f6f97bc0 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -104,6 +104,16 @@
+ + +
+ + + + +
+ +
@@ -251,8 +261,8 @@
- - + +
@@ -845,8 +855,9 @@
- - + + +
@@ -6186,7 +6197,8 @@ - + +
@@ -6310,7 +6322,8 @@ - + +
@@ -6439,7 +6452,8 @@ - + +
@@ -6564,7 +6578,8 @@ - + +
@@ -6689,8 +6704,9 @@
- - + + +
@@ -6746,7 +6762,8 @@ - + +
@@ -7356,7 +7373,8 @@ - + +
@@ -7422,7 +7440,8 @@ - + +
@@ -7495,7 +7514,8 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects."> - + +
@@ -7563,7 +7583,8 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects."> - + +
@@ -7601,7 +7622,8 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects."> - + +
@@ -7674,7 +7696,8 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects."> - + +
@@ -7762,7 +7785,8 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects."> - + +
@@ -7850,7 +7874,8 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects."> - + +
@@ -7938,7 +7963,8 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects."> - + +
@@ -8026,7 +8052,8 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects."> - + +
@@ -8119,7 +8146,8 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects."> - + +
@@ -8207,7 +8235,8 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects."> - + +
@@ -8307,6 +8336,9 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects.">
+ + +
@@ -8396,6 +8428,9 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects.">
+ + +
@@ -8485,6 +8520,9 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects.">
+ + +
@@ -8574,6 +8612,9 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects.">
+ + +
@@ -8668,6 +8709,8 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects.">
+ +
@@ -8757,6 +8800,8 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects.">
+ +
@@ -14565,6 +14610,40 @@ function AutoScriptToArray(inputAutoScript) { return AutoScriptArray; } +/* AutoScript editor */ +on("clicked:autoScriptEdit", function(info) { + let newEditorTarget = info.htmlAttributes.id; + getAttrs([`${newEditorTarget}`,"autoScriptEditorTarget", "autoScriptEditorInput"], function(values) { + let oldEditorTarget = values.autoScriptEditorTarget; + let newEditorInput = values[`${newEditorTarget}`]; + let oldEditorInput = values.autoScriptEditorInput; + setAttrs({ + [oldEditorTarget]: oldEditorInput, + autoScriptEditorInput: newEditorInput, + autoScriptEditorTarget: newEditorTarget, + autoScriptEditor_display: "true" + }); + }); +}); +on("clicked:closeAutoScriptEdit", function(info) { + getAttrs(["autoScriptEditorTarget", "autoScriptEditorInput"], function(values) { + let editorTarget = values.autoScriptEditorTarget; + let editorInput = values.autoScriptEditorInput; + setAttrs({ + [editorTarget]: editorInput, + autoScriptEditor_display: "0" + }); + }); +}); + + + + + + + + + on("clicked:autoEffectTest", function() { AutoScriptMain(`(Require 2 Charge) (Consume 2 Charge)`, "Combat start") diff --git a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css index 63f1d3c605..5d694c661d 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css +++ b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css @@ -2487,7 +2487,27 @@ justify-content: center; } - +/* Autoscript Editor */ +.autoscriptEditorContainer { + position: fixed; + top: 0px; + left: 0px; + width: 99%; + z-index: 999; +} +#autoScriptEditorToggle + .autoscriptEditorContainer { + display:none !important; +} +#autoScriptEditorToggle:checked + .autoscriptEditorContainer { + display:block !important; +} +.autoScriptEditorTarget { + position: absolute; + top: 2px; + left: 145px; + color: #999; + pointer-events: none +} /* Assorted buttons */ @@ -2533,7 +2553,21 @@ justify-content: center; background-repeat: no-repeat; } -:is(.augmentBlock, .specialBlock) .autoScriptButton { +.closeAutoScriptButton { + position: absolute; + top: 4px; + right: 6px; + z-index: 20; + height: 25px; + width: 25px; + border-radius: 5px; + background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/AutoEffects-Functionality/ProjectMoonTRPG/imagesResized/icons/exit.png'); + background-size: contain; + background-position: center; + background-repeat: no-repeat; +} + +:is(.augmentBlock, .specialBlock, .skillBlock) .autoScriptButton { right: 35px; } diff --git a/ProjectMoonTRPG/images/icons/exit.png b/ProjectMoonTRPG/images/icons/exit.png new file mode 100644 index 0000000000000000000000000000000000000000..eb1457706bf0faaa553ac3ce2649a91f23626f9a GIT binary patch literal 5101 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 literal 0 HcmV?d00001 diff --git a/ProjectMoonTRPG/imagesResized/icons/exit.png b/ProjectMoonTRPG/imagesResized/icons/exit.png new file mode 100644 index 0000000000000000000000000000000000000000..4f554847badd605b836fb1a631d00057fd1b7c81 GIT binary patch literal 3093 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%0Dy!50Qvv` z0D$NK0Cg|`0P0`>06Lfe02gqax=}m;000SaNLh0L01FZT01FZU(%pXi0000RbVXQn zQ*UN;cVTj607GSLb9r+hQ*?D?X>TA@Z*OeDr{R1600ALML_t(&f$dq#3Iah4i{GZO zUi4%2qM+Zlo(5!Popzc+36py}$vo4}VO>`!;4p<0!xT~tQ%E&d4wDR zyjq--loyTE3BcPDU=?x!aNEY(dAYD9bOmtl1zCiAuf$J$pO*`JWV$QU6S4q!bOvXM z>CNaFf6k0$MJ#(SDkeOJ^^9bSq2%`5S{Y(!Ilb=)Qw()tMqYLX0s88WT9gQpl=Bwx zS|fzgE{&*Z^bkwE#u@IHWuHTD5zEF$lZ4#?vmO~uM6o#R!pfVBW;!z}L~BB-bDlzW zAhES14!gwlEAb#oSQH7sb` literal 0 HcmV?d00001 diff --git a/ProjectMoonTRPG/translation.json b/ProjectMoonTRPG/translation.json index aad87ab2f4..46fc6dc116 100644 --- a/ProjectMoonTRPG/translation.json +++ b/ProjectMoonTRPG/translation.json @@ -242,6 +242,9 @@ "export-type-Settings":"Settings only", "import-type-replace":"Replace", "import-type-add":"Add", + "autoscript-edit":"Edit AutoScript", + "autoscript-editor":"AutoScript Editor", + "autoscript-close-editor":"Close AutoScript Editor", "equip-weapon1-name":"Weapon Name (1)", "equip-weapon2-name":"Weapon Name (2)", "equip-weapon3-name":"Weapon Name (3)", From 3d67ccbe419fe73f402b397505cc85b40f1a4e5e Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Sat, 27 Jul 2024 00:50:04 +0200 Subject: [PATCH 09/55] New functionality: AutoScript, part 5 Conditional buttons added. Added code to collect AutoScripts from outfit, augment and ego --- ProjectMoonTRPG/ProjectMoonTRPG.html | 492 +++++++++++++---------- ProjectMoonTRPG/ProjectMoonTRPGStyle.css | 56 ++- 2 files changed, 327 insertions(+), 221 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 26f6f97bc0..f45dfda779 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -2731,6 +2731,19 @@
+ +
+
+ +
+ + + +
+
+
+ +
@@ -14536,38 +14549,6 @@ getAttrs(["settingEditMode"], function(values) { /*--- AutoScript functions ---*/ - -/* Gathers all AutoScripts that match a certain trigger type */ -function collectAutoScripts(triggerType) { - if (triggerType != "None") { - switch (triggerType) { - case "Permanent": break; /* Triggers with all other triggers. Useful for stuff like Status Quo */ - case "Combat start": return [["Gain","3","Tremor","This turn"]]; - case "Round start": break; - case "Round end": break; - case "Damaged": break; - case "Staggered": break; - case "Defeated": break; - case "Panic": break; - case "Offensive": break; - case "Defensive": break; - case "Block": break; /* Also adds Defensive*/ - case "Evade": break; /* Also adds Defensive*/ - default: autoEffectErrorMessage(`${triggerType} is not a recognised trigger type`); break; - } - } - /* - getAttr augmentAutoScript outfitAutoScript egoAutoScript - only use egoAutoScript is distiortion or egoActive - remove all newlines and tab characters - convert autoscripts to an object using json - will be in format {triggerType1:'AutoScript', triggerType2:'AutoScript', ...} - switch (triggerType). If any key matches the triggerType, convert the AutoScript to an array - switch default: "trigger" is not a valid trigger type - return an array containing all generated AutoScript arrays - */ -} - /* Removes all newline and tab characters as well as JavaScript comments from an AutoScript */ function cleanAutoScript(AutoScript) { let cleanAutoScript = AutoScript.replace(/(\r\n|\n|\r|\t)/gm, ""); @@ -14576,12 +14557,24 @@ function cleanAutoScript(AutoScript) { } /* Converts an AutoScript from a string to an array */ -function AutoScriptToArray(inputAutoScript) { +/* mode: normal is for strings of type (AutoEffect...) (AutoEffect...) ... */ +/* mode: nested is for strings of type [#Offensive, (AutoEffect...) ... #] [#Round start, (AutoEffect...) ... ]*/ +function AutoScriptToArray(inputAutoScript, mode="normal") { let AutoScript = inputAutoScript; let AutoEffect = ""; let AutoEffectArray = []; let AutoScriptArray = []; + let beginChar = "("; + let endChar = ")"; + let charOffset = 1; + + if (mode == "nested") { + beginChar = "[#"; + endChar = "#]"; + charOffset = 2; + } + /* Remove all newlines, tab spaces and comments */ AutoScript = cleanAutoScript(AutoScript); @@ -14589,16 +14582,22 @@ function AutoScriptToArray(inputAutoScript) { AutoScript = AutoScript.trim(); /* Checks if an AutoEffect still remains in the AutoScript */ - if (AutoScript.indexOf("(") == 0 && AutoScript.indexOf(")")) { + if (AutoScript.indexOf(beginChar) == 0 && AutoScript.indexOf(endChar)) { /* Removes the next AutoEffect from the AutoScript. Removes the parentheses */ - AutoEffect = AutoScript.substring(1, AutoScript.indexOf(")")); - AutoScript = AutoScript.substring(AutoScript.indexOf(")")+1); + AutoEffect = AutoScript.substring(charOffset, AutoScript.indexOf(endChar)); + AutoScript = AutoScript.substring(AutoScript.indexOf(endChar)+charOffset); /* Structures the AutoEffect into an array and stores it */ - AutoEffectArray = AutoEffect.trim().split(","); - AutoEffectArray = AutoEffectArray.map(e => e.trim()); - AutoEffectArray[0] = AutoEffectArray[0].split(/\s+/); + if (mode == "nested") { + AutoEffect = AutoEffect.trim().replace(",","£"); + AutoEffectArray = AutoEffect.split("£"); + AutoEffectArray = AutoEffectArray.map(e => e.trim()); + } else { + AutoEffectArray = AutoEffect.trim().split(","); + AutoEffectArray = AutoEffectArray.map(e => e.trim()); + AutoEffectArray[0] = AutoEffectArray[0].split(/\s+/); + } AutoScriptArray.push(AutoEffectArray); } else { @@ -14645,158 +14644,229 @@ on("clicked:closeAutoScriptEdit", function(info) { on("clicked:autoEffectTest", function() { - AutoScriptMain(`(Require 2 Charge) (Consume 2 Charge)`, "Combat start") - + /* All buttons except conditional buttons must have resetConditionals */ + resetConditionals(); + AutoScriptMain(`(Gain 3 Burn) (Gain 2 Fragile Next turn, TestConditional) (Gain 4 Fragile, TestConditional)`, "Combat start") }); + +/* Executes a conditional button. Hides the button if at least one check fails */ +/* Also hides the button if a Consume check would fail after using the button again */ +on("clicked:repeating_conditionalButtons:activate", function(info) { + let buttonid = info.sourceAttribute.split("_")[2]; + let buttonAutoScript = ""; + let returnValues = {}; + getAttrs([`repeating_conditionalButtons_${buttonid}_buttonAutoScript`], function(values) { + buttonAutoScript = values[`repeating_conditionalButtons_${buttonid}_buttonAutoScript`] + AutoScriptMain(buttonAutoScript, "None", function(returnValues) { + if (returnValues.checkResult != "success") { + setAttrs({[`repeating_conditionalButtons_${buttonid}_hideButton`]: "true"}) + } + }); + }); +}); + + /* Main function for using AutoScripts. Called by actions through on click events */ /* inputAutoScript: AutoScript provided by the action. Can be an empty string */ /* trigger: "Combat start", "Round start", "Round end", "Damaged", "Staggered", "Defeated", "Panic", "Permanent", "Offensive", "Defensive", "Block", "Evade" or "None". Selects which type of AutoEffects to collect and append to an AutoScript. Block and Evade also include Defensive */ -function AutoScriptMain(inputAutoScript, triggerType="None") { - - /* Converts the input AutoScript to to an array if it isn't one already */ - let AutoScript = []; +/* callback: Function to be run on returnValues. Defaults to an empty function */ +function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}) { + + /* Adds the input AutoScript */ + let AutoScript = ""; if (inputAutoScript != "") { - try { AutoScript = JSON.parse(inputAutoScript); } - catch(e) { AutoScript = AutoScriptToArray(inputAutoScript); } + AutoScript = inputAutoScript; } - + /* Appends one or more AutoScripts based on the trigger type */ - AutoScript.push(collectAutoScripts(triggerType)); + let autoScriptTypes = [triggerType]; + if (triggerType != "None") { + if (autoScriptTypes.includes("Block") || autoScriptTypes.includes("Evade")) { + autoScriptTypes.push("Defensive"); + } + } + if (!autoScriptTypes.includes("Permanent")) { + autoScriptTypes.push("Permanent") + } + console.log(autoScriptTypes) + + getAttrs(["augmentAutoScript", "outfitAutoScript", "egoAutoScript", "distortState", "egoActiveState"], function(values) { + + let augmentAutoScript = ""; + let outfitAutoScript = ""; + let egoAutoScript = ""; + let collectedAutoScript = []; + /* Finds all substrings that begin with "[#" and end with "#]" */ + augmentAutoScript = values.augmentAutoScript.match(/\[([#][^]+[#])\]/g); + if (augmentAutoScript == null) { augmentAutoScript = ""; } + outfitAutoScript = values.outfitAutoScript.match(/\[([#][^]+[#])\]/g); + if (outfitAutoScript == null) { outfitAutoScript = ""; } + if (values.distortState == "true" || values.egoActiveState == "true") { + egoAutoScript = values.egoAutoScript.match(/\[([#][^]+[#])\]/g); + if (egoAutoScript == null) { egoAutoScript = ""; } + } + + let TypedAutoScript = AutoScriptToArray(augmentAutoScript + outfitAutoScript + egoAutoScript, "nested"); + + TypedAutoScript.forEach((autoScriptType) => { + if (autoScriptTypes.includes(autoScriptType[0])) { + AutoScript += autoScriptType[1]; + } + }); + + /* Convert AutoScript to an array */ + AutoScript = AutoScriptToArray(AutoScript); /* Get relevant attributes */ getAttrs(["settingMuteMessage", "settingWhisperRolls", "settingWhisperTarget", "settingLimbusStyle", "settingHideNextTurn", - "HP", "HP_max", "StagRes", "StagRes_max", "SP", "SP_max", - "StaggerState", "distortState", "egoActiveState", "egoType"], function(values) { - - let settingMuteMessage = values.settingMuteMessage; - let settingWhisperRolls = values.settingWhisperRolls; - let settingWhisperTarget = values.settingWhisperTarget; - let settingLimbusStyle = values.settingLimbusStyle; - let settingHideNextTurn = values.settingHideNextTurn; - - let HP = values.HP; - let ST = values.StagRes; - let SP = values.SP; - let barList = { HP: parseInt(HP), ST:parseInt(ST), SP:parseInt(SP) }; - - let HPdamage = values.HP_max - HP; - let STdamage = values.StagRes_max - ST; - let SPdamage = values.SP_max - SP; - let barDamageList = { "-HP": HPdamage, "-ST":STdamage, "-SP":SPdamage } - - let StaggerState = values.StaggerState; - let distortState = values.distortState; - let egoActiveState = values.egoActiveState; - let egoType = values.egoType; - - let scaling = 1; - let checkResult = "success"; - - let output = {}; - let tempOutput = {}; - let returnValues = { checkResult:"success", error:false, }; - let ailmentList = {}; - + "HP", "HP_max", "StagRes", "StagRes_max", "SP", "SP_max", + "StaggerState", "distortState", "egoActiveState", "egoType"], function(values) { + + let settingMuteMessage = values.settingMuteMessage; + let settingWhisperRolls = values.settingWhisperRolls; + let settingWhisperTarget = values.settingWhisperTarget; + let settingLimbusStyle = values.settingLimbusStyle; + let settingHideNextTurn = values.settingHideNextTurn; + + let HP = values.HP; + let ST = values.StagRes; + let SP = values.SP; + let barList = { HP: parseInt(HP), ST:parseInt(ST), SP:parseInt(SP) }; + + let HPdamage = values.HP_max - HP; + let STdamage = values.StagRes_max - ST; + let SPdamage = values.SP_max - SP; + let barDamageList = { "-HP": HPdamage, "-ST":STdamage, "-SP":SPdamage } + + let StaggerState = values.StaggerState; + let distortState = values.distortState; + let egoActiveState = values.egoActiveState; + let egoType = values.egoType; + + let scaling = 1; + let checkResult = "success"; + + let output = {}; + let tempOutput = {}; + let returnValues = { checkResult:"success", error:false, }; + let conditionalList = {} + + let ailmentList = {}; + /* Get all ailments */ getAttrs(["burnNextTurnSetting", "bleedNextTurnSetting", "smokeNextTurnSetting", "chargeNextTurnSetting", - "Burn", "Bleed", "Paralysis", "Protection", "StaggerProtection", "Fragile", "Strength", "Feeble", "Endurance", "Disarm", "Haste", "Bind", "Smoke", "Charge", "Fortune", - "BurnNextTurn", "BleedNextTurn", "ParalysisNextTurn", "ProtectionNextTurn", "StaggerProtectionNextTurn", "FragileNextTurn", "StrengthNextTurn", "FeebleNextTurn", "EnduranceNextTurn", "DisarmNextTurn", "HasteNextTurn", "BindNextTurn", "SmokeNextTurn", "ChargeNextTurn", "FortuneNextTurn"], function(values) { - - const HasNextTurn = settingHideNextTurn == true ? 'false' : 'true'; - - let ailmentNames = ["Burn", "Bleed", "Paralysis", "Protection", "StaggerProtection", "Fragile", "Strength", "Feeble", "Endurance", "Disarm", "Haste", "Bind", "Smoke", "Charge", "Fortune"] - ailmentNames.forEach(ailment => { - if (["Burn", "Bleed", "Smoke", "Charge"].includes(ailment)) { - ailmentList[ailment] = [values[ailment.toLowerCase()+"NextTurnSetting"], values[ailment], values[`${ailment}NextTurn`]]; - } else { - ailmentList[ailment] = [HasNextTurn, values[ailment], values[`${ailment}NextTurn`]]; - } - }); + "Burn", "Bleed", "Paralysis", "Protection", "StaggerProtection", "Fragile", "Strength", "Feeble", "Endurance", "Disarm", "Haste", "Bind", "Smoke", "Charge", "Fortune", + "BurnNextTurn", "BleedNextTurn", "ParalysisNextTurn", "ProtectionNextTurn", "StaggerProtectionNextTurn", "FragileNextTurn", "StrengthNextTurn", "FeebleNextTurn", "EnduranceNextTurn", "DisarmNextTurn", "HasteNextTurn", "BindNextTurn", "SmokeNextTurn", "ChargeNextTurn", "FortuneNextTurn"], function(values) { + + const HasNextTurn = settingHideNextTurn == true ? 'false' : 'true'; + let ailmentNames = ["Burn", "Bleed", "Paralysis", "Protection", "StaggerProtection", "Fragile", "Strength", "Feeble", "Endurance", "Disarm", "Haste", "Bind", "Smoke", "Charge", "Fortune"] + ailmentNames.forEach(ailment => { + if (["Burn", "Bleed", "Smoke", "Charge"].includes(ailment)) { + ailmentList[ailment] = [values[ailment.toLowerCase()+"NextTurnSetting"], values[ailment], values[`${ailment}NextTurn`]]; + } else { + ailmentList[ailment] = [HasNextTurn, values[ailment], values[`${ailment}NextTurn`]]; + } + }); + /* Get all custom ailments */ getSectionIDs(`repeating_ailments`, idarray => { const fieldnames = idarray.reduce((rows,id) => [...rows, `repeating_ailments_${id}_ailName`, `repeating_ailments_${id}_ailNextTurn`, `repeating_ailments_${id}_ailNum`, `repeating_ailments_${id}_ailNumNextTurn`, ], ''); - let ailName = ""; - let ailHasNextTurn = ""; - let ailNum = 0; - let ailNumNextTurn = 0; - - getAttrs([...fieldnames], v => { - idarray.forEach(id => { - ailName = v[`repeating_ailments_${id}_ailName`].replace(" ","_"); - ailHasNextTurn = v[`repeating_ailments_${id}_ailNextTurn`]; - ailNum = v[`repeating_ailments_${id}_ailNum`]; - ailNumNextTurn = v[`repeating_ailments_${id}_ailNumNextTurn`] + let ailName = ""; + let ailHasNextTurn = ""; + let ailNum = 0; + let ailNumNextTurn = 0; - ailmentList[ailName] = [ailHasNextTurn, ailNum, ailNumNextTurn, id]; - }); - - console.log(ailmentList) + getAttrs([...fieldnames], v => { + idarray.forEach(id => { + ailName = v[`repeating_ailments_${id}_ailName`].replace(" ","_"); + ailHasNextTurn = v[`repeating_ailments_${id}_ailNextTurn`]; + ailNum = v[`repeating_ailments_${id}_ailNum`]; + ailNumNextTurn = v[`repeating_ailments_${id}_ailNumNextTurn`] + + ailmentList[ailName] = [ailHasNextTurn, ailNum, ailNumNextTurn, id]; + }); /* Execute each AutoEffect in the AutoScript */ AutoScript.forEach(AutoEffect => { - /* Checks are always processed. Other AutoEffects are not processed if the last check failed */ - switch (AutoEffect[0][0]) { - case "Require": tempOutput = autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList); break; - case "Consume": tempOutput = autoEffectConsume(AutoEffect, ailmentList, barList); break; - default: tempOutput = {}; break; - } - if (checkResult != "failure") { - switch (AutoEffect[0][0]) { - case "Require": break; /* Already executed above */ - case "Consume": break; - case "Gain": tempOutput = autoEffectGainAilment(AutoEffect, ailmentList, scaling); break; - default: tempOutput = {error:true}; autoEffectErrorMessage(`${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); break; - } - } - console.log(tempOutput) - - /* Handle errors. Continues executing AutoEffects for the sake of finding additional errors, */ - /* but does not apply any changes to attributes */ - if (tempOutput.hasOwnProperty("error") || returnValues.error == true) { - returnValues.error == true; - output = {}; + if (AutoEffect == undefined) { return; } - - /* Handle changes to scaling */ - if (tempOutput.hasOwnProperty("scaling")) { - scaling = parseInt(tempOutput.scaling); - delete tempOutput.scaling; + /* If conditional, add AutoEffect to either a new conditional button or a existing one */ + if (AutoEffect.length > 1) { + AutoEffect.slice(1).forEach(conditional => { + if (conditionalList.hasOwnProperty(conditional)) { + conditionalList[conditional] += " (" + AutoEffect[0].toString().replaceAll(","," ") + ")"; + } else { + conditionalList[conditional] = "(" + AutoEffect[0].toString().replaceAll(","," ") + ")"; + } + }); } - - /* Handle check results from Require and Consume */ - /* For the returnValues, the worst result is returned */ - if (tempOutput.checkResult != undefined) { - checkResult = tempOutput.checkResult; - if (returnValues.checkResult == "success") { - returnValues.checkResult = tempOutput.checkResult; + /* If not conditional, process AutoEffect as normal */ + else { + /* Checks are always processed. Other AutoEffects are not processed if the last check failed */ + switch (AutoEffect[0][0]) { + case "Require": tempOutput = autoEffectRequire(AutoEffect[0], ailmentList, barList, barDamageList); break; + case "Consume": tempOutput = autoEffectConsume(AutoEffect[0], ailmentList, barList); break; + default: tempOutput = {}; break; } - else if (returnValues.checkResult == "last success" && tempOutput.checkResult == "failure") { - returnValues.checkResult = tempOutput.checkResult; + if (checkResult != "failure") { + switch (AutoEffect[0][0]) { + case "Require": break; /* Already executed above */ + case "Consume": break; + case "Gain": tempOutput = autoEffectGainAilment(AutoEffect[0], ailmentList, scaling); break; + default: tempOutput = {error:true}; autoEffectErrorMessage(`${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); break; + } } - delete tempOutput.checkResult; - } - - /* Add attribute changes from AutoEffect to output */ - /* The first time a attribute is modified, add it's count */ - /* For example, if Gain 3 Burn is used and current Burn is 2, output Burn is set to 5 */ - /* If Consume 4 Burn is used later, this amount will be removed without adding count */ - for (const property in tempOutput) { - if (output.hasOwnProperty(property)) { - output[property] += tempOutput[property]; - } else { - output[property] = tempOutput[property] + tempOutput.count; + console.log(tempOutput) + + /* Handle errors. Continues executing AutoEffects for the sake of finding additional errors, */ + /* but does not apply any changes to attributes */ + if (tempOutput.hasOwnProperty("error") || returnValues.error == true) { + returnValues.error == true; + output = {}; + return; + } + + /* Handle changes to scaling */ + if (tempOutput.hasOwnProperty("scaling")) { + scaling = parseInt(tempOutput.scaling); + delete tempOutput.scaling; + } + + /* Handle check results from Require and Consume */ + /* For the returnValues, the worst result is returned */ + if (tempOutput.checkResult != undefined) { + checkResult = tempOutput.checkResult; + if (returnValues.checkResult == "success") { + returnValues.checkResult = tempOutput.checkResult; + } + else if (returnValues.checkResult == "last success" && tempOutput.checkResult == "failure") { + returnValues.checkResult = tempOutput.checkResult; + } + delete tempOutput.checkResult; + } + + /* Add attribute changes from AutoEffect to output */ + /* The first time a attribute is modified, add its count */ + /* For example, if Gain 3 Burn is used and current Burn is 2, output Burn is set to 5 */ + /* If Consume 4 Burn is used later, this amount will be removed without adding count */ + for (const property in tempOutput) { + if (output.hasOwnProperty(property)) { + output[property] += tempOutput[property]; + } else { + output[property] = tempOutput[property] + tempOutput.count; + } } } }); @@ -14804,19 +14874,27 @@ function AutoScriptMain(inputAutoScript, triggerType="None") { // console.log(output) setAttrs(output); - console.log(returnValues) - - - /* Message handling */ - - - /* Error handling */ - if (returnValues.error == true) { - /* Run function that clears all condition buttons */ + /* Create conditional buttons */ + for (const [buttonName, buttonAutoScript] of Object.entries(conditionalList)) { + createConditionalButton(buttonName, buttonAutoScript); } + + + + + /* Message handling */ + + + /* Error handling */ + if (returnValues.error == true) { + /* Run function that clears all condition buttons */ + } + + callback(returnValues); + }); }); }); }); @@ -14832,35 +14910,35 @@ function autoEffectErrorMessage(errorString, autoEffect) { console.log(errorString + autoEffect) } -/* Checks if an AutoEffect has conditionals */ -/* If true, creates a condition button for each conditional and returns true */ -/* If the condition button already exists, append the AutoEffect to the existing button */ -/* If false, returns false */ -function processConditionals(AutoEffect) { - if (AutoEffect.length > 1) { - AutoEffect.slice(1).forEach(conditional => { - /* Remember to apply AutoEffect.slice(0,2)) */ - console.log("Creating conditionButton " + conditional + " with effect " + JSON.stringify(AutoEffect.slice(0,2))); - }); - return true; - } - return false; +/* Creates a new conditional button*/ +function createConditionalButton(buttonName, buttonAutoScript) { + let output = {} + let newrowid = generateRowID(); + output[`repeating_conditionalButtons_${newrowid}_buttonName`] = buttonName; + output[`repeating_conditionalButtons_${newrowid}_buttonAutoScript`] = buttonAutoScript; + setAttrs(output); +} + +/* Removes all conditional buttons */ +function resetConditionals() { + getSectionIDs("conditionalButtons", function(idarray) { + for(var i=0; i < idarray.length; i++) { + removeRepeatingRow("repeating_conditionalButtons_" + idarray[i]); + } + }); } function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { /* Check format */ - if (AutoEffect[0].length < 3 || AutoEffect[0].length > 4) { autoEffectErrorMessage(`Expected format: (Require N #Ailment/#Bar/#BarDamage #Scaling(optional))`, AutoEffect); return {error: true}; } - - /* Handle conditionals */ - if (processConditionals(AutoEffect) == true) { return {}; } + if (AutoEffect.length < 3 || AutoEffect.length > 4) { autoEffectErrorMessage(`Expected format: (Require N #Ailment/#Bar/#BarDamage #Scaling(optional))`, AutoEffect); return {error: true}; } /* Get required value */ - let effectVal = parseInt(Math.abs(AutoEffect[0][1])); - if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[0][1]}" is not a number`, AutoEffect); return {error: true}; } + let effectVal = parseInt(Math.abs(AutoEffect[1])); + if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } /* Get target count */ - let effectName = AutoEffect[0][2]; + let effectName = AutoEffect[2]; /* Handle ailment count */ if (ailmentList.hasOwnProperty(effectName)) { count = ailmentList[effectName][1]; } @@ -14873,8 +14951,8 @@ function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { /* Handle the optional scaling property */ let scaling = 1; let returnValues = {}; - if (AutoEffect[0][3] != undefined) { - if (AutoEffect[0][3].toLowerCase() == "scaling") { + if (AutoEffect[3] != undefined) { + if (AutoEffect[3].toLowerCase() == "scaling") { scaling = Math.floor(count/effectVal); returnValues.scaling = scaling; } @@ -14891,18 +14969,15 @@ function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { function autoEffectConsume(AutoEffect, ailmentList, barList) { /* Check format */ - if (AutoEffect[0].length < 3 || AutoEffect[0].length > 4) { autoEffectErrorMessage(`Expected format: (Consume N #Ailment/#Bar #Scaling(optional))`, AutoEffect); return {error: true}; } - - /* Handle conditionals */ - if (processConditionals(AutoEffect) == true) { return {}; } + if (AutoEffect.length < 3 || AutoEffect.length > 4) { autoEffectErrorMessage(`Expected format: (Consume N #Ailment/#Bar #Scaling(optional))`, AutoEffect); return {error: true}; } /* Get consumed value */ - let effectVal = parseInt(Math.abs(AutoEffect[0][1])); - if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[0][1]}" is not a number`, AutoEffect); return {error: true}; } + let effectVal = parseInt(Math.abs(AutoEffect[1])); + if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } let count = 0; /* Get target */ - let effectName = AutoEffect[0][2]; + let effectName = AutoEffect[2]; let effectTarget = ""; let effectRepeatingId = ailmentList[effectName][3]; @@ -14922,8 +14997,8 @@ function autoEffectConsume(AutoEffect, ailmentList, barList) { /* Handle the optional scaling property */ let scaling = 1; let returnValues = {}; - if (AutoEffect[0][3] != undefined) { - if (AutoEffect[0][3].toLowerCase() == "scaling") { + if (AutoEffect[3] != undefined) { + if (AutoEffect[3].toLowerCase() == "scaling") { scaling = Math.floor(count/effectVal); returnValues.scaling = scaling; } @@ -14946,31 +15021,26 @@ function autoEffectConsume(AutoEffect, ailmentList, barList) { function autoEffectGainAilment(AutoEffect, ailmentList, scaling) { /* Check format */ - if (AutoEffect[0].length < 3 || AutoEffect[0].length > 6) { autoEffectErrorMessage(`Expected format: (Gain N #Ailment #Round(optional))`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 3 || AutoEffect.length > 6) { autoEffectErrorMessage(`Expected format: (Gain N #Ailment #Round(optional))`, AutoEffect); return {error: true}; } /* Handle scaling */ - AutoEffect[0][1] *= scaling; + AutoEffect[1] *= scaling; if (scaling == 0) { return {}; } - /* Handle conditionals */ - if (processConditionals(AutoEffect) == true) { return {}; } - /* Get ailment name */ - let effectAilment = AutoEffect[0][2]; + let effectAilment = AutoEffect[2]; if (!ailmentList.hasOwnProperty(effectAilment)) { autoEffectErrorMessage(`Ailment "${effectAilment}" does not exist`, AutoEffect); return {error: true}; } /* Get values */ - let effectVal = parseInt(Math.abs(AutoEffect[0][1])); - if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[0][1]}" is not a number`, AutoEffect); return {error: true}; } + let effectVal = parseInt(Math.abs(AutoEffect[1])); + if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } let count = ailmentList[effectAilment][1]; /* Handle the optional turn override */ /* This is between you and me, but "Next turn" doesn't actually do anything ;) */ let forceTarget = ""; - if (AutoEffect[0][3] != undefined) { - if (["this", "thisturn", "this turn"].includes(AutoEffect[0][3].toLowerCase())) { forceTarget = "This turn"; } - } else { - autoEffectErrorMessage(`"${AutoEffect[0][1]}". Expected "This turn" or "Next turn"`, AutoEffect); return {error: true}; + if (AutoEffect[3] != undefined) { + if (["this", "thisturn", "this turn"].includes(AutoEffect[3].toLowerCase())) { forceTarget = "This turn"; } } /* Get target attribute */ @@ -14990,12 +15060,6 @@ function autoEffectGainAilment(AutoEffect, ailmentList, scaling) { /* Execute AutoEffect */ return { [effectTarget]: parseInt(effectVal), count:parseInt(count) } } - - - - - - /*--- AutoEffect functions end ---*/ diff --git a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css index 5d694c661d..2d76721679 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css +++ b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css @@ -829,9 +829,6 @@ opacity: 20%; width: 23px !important; position: absolute; top: 3px; right: 0px; } -.skillSelectionElement { - position: relative; -} .blocker { position: absolute; top: 0; @@ -1836,7 +1833,9 @@ background-image: linear-gradient(to bottom, rgba(0,0,0,0.8), rgba(0,0,0,0)), ur flex-wrap: wrap; overflow: hidden; } -.ailmentCustomDisplay .repcontrol, .outfitCustomResistDisplay .repcontrol { +.ailmentCustomDisplay .repcontrol, +.outfitCustomResistDisplay .repcontrol, +.conditionalButtonDisplay .repcontrol { display: none; } .ailmentCustomDisplay .repitem { @@ -2487,12 +2486,12 @@ justify-content: center; } -/* Autoscript Editor */ +/* AutoScript Editor */ .autoscriptEditorContainer { position: fixed; top: 0px; - left: 0px; - width: 99%; + left: 2%; + width: 95%; z-index: 999; } #autoScriptEditorToggle + .autoscriptEditorContainer { @@ -2510,6 +2509,49 @@ justify-content: center; } +/* AutoEffect conditional buttons */ +.conditionalButtonDisplay .repcontainer { + display: flex; + flex-wrap: wrap; + justify-content: space-around; +} +.conditionalButtonDisplay .repitem { + width: 49%; +} +.conditionalButton { + display: flex; + align-items: center; + justify-content: center; + position: relative; + border-radius: 100px; + border: 1px #555 solid; + background-color: #85a874; + margin-left: 2px; + margin-right: 2px; + width: 100%; + height: 32px; +} +.conditionalButtonAct { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: #000; + opacity: 0.2; +} +.conditionalButtonAct:hover { + opacity: 0; +} +.conditionalButtonName { + max-width: 95%; + font-size: 10pt; + font-weight: bold; + color: #fff; + background-color: rgba(0, 0, 0, 0) !important; +} + + /* Assorted buttons */ .shareButton { position: absolute; From 7861e75c81832779202810c6a28e00a428f87abc Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Sat, 27 Jul 2024 03:07:40 +0200 Subject: [PATCH 10/55] New feature: AutoEffects, part 6 Configures all autorolls use to use AutoEffects, including all attack/block/evade rolls, Defeated, Staggered, Damaged, Panic, Combat start, Round start and Skills --- ProjectMoonTRPG/ProjectMoonTRPG.html | 669 +++++++++++++++------------ 1 file changed, 362 insertions(+), 307 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index f45dfda779..ecb4889945 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -10690,6 +10690,10 @@ on("change:StagRes", function() { setAttrs({"StaggerState":"Staggered"}); + /* AutoScripts */ + resetConditionals(); + AutoScriptMain("", "Staggered"); + } /* Value check end */ @@ -10788,6 +10792,10 @@ on("change:SP", function() { if(currentsan <= 0 && panicstate == "0"){ setAttrs({"PanicState":"Panic"}); + + /* AutoScripts */ + resetConditionals(); + AutoScriptMain("", "Panic"); } else if(currentsan > 0 && panicstate != "0"){ @@ -10798,7 +10806,7 @@ on("change:SP", function() { } /* AutoDetect check end */ - }); + }); }); /* Auto: HP related updates (Detect Defeat, Detect EGO activation) */ @@ -10824,6 +10832,10 @@ on("change:HP", function() { setAttrs({"DefeatState":"Defeated"}); + /* AutoScripts */ + resetConditionals(); + AutoScriptMain("", "Defeated"); + } /* Defeat check end */ }); @@ -11621,7 +11633,7 @@ on("change:skillSelect", function() { /* Get IDs/names */ getAttrs(["skillSelect"], function(values){ - let buttonid = values.skillSelect; + let buttonid = values.skillSelect; let skillcat = buttonid.split('S')[0]; let name = buttonid + "Name"; @@ -11929,6 +11941,9 @@ getSectionIDs(`repeating_global`, idarray => { }); }); + /* AutoScripts */ + resetConditionals(); + AutoScriptMain("", "Round start"); }); @@ -12109,9 +12124,9 @@ getAttrs(["Bleed", "bleedResist", "bleedResist_ego", "distortState", "egoActiveS on('clicked:rollCombat', (info) => { /* Preparing values */ /* Get IDs/names */ - let buttonid = info.htmlAttributes.id.split('_')[1]; - let rawcheck = info.htmlAttributes.id.split('_')[2]; - let numcheck = info.htmlAttributes.id.split('_')[3]; + let buttonid = info.htmlAttributes.id.split('_')[1]; + let rawcheck = info.htmlAttributes.id.split('_')[2]; + let numcheck = info.htmlAttributes.id.split('_')[3]; let name = buttonid + "Name"; let type = buttonid + "Type"; @@ -12198,7 +12213,11 @@ on('clicked:rollCombat', (info) => { getSectionIDs(`repeating_global`, idarray => { let id = `repeating_global_${idarray[0]}`; - getAttrs(["egoActiveState", "settingSimpleDisplay", "settingWhisperRolls", "settingWhisperTarget", "settingMultihitFull", `${id}_multiPenalty`, `${id}_multiStyle`, "character_name", "advState", "difficulty", "skillSelect", "baseActNum", "Light", "difficulty", "Endurance", "Disarm", "Strength", "Feeble", "evdPositive", "evdNegative", "advNum", "disadvNum", "attPower", "defPower", "evdPower", "selectName", "selectLight", "selectType", "selectDice1", "selectDice2", "selectDice3", "selectEffect", "distortWeaponDice1", "distortWeaponDice2", "distortWeaponDice3", "distortDefDice1", "distortDefDice2", "distortDefDice3", "distortEvdDice1", "distortEvdDice2", "distortEvdDice3", "distortEffect", "distortEffect2", "settingMultihitUses", "settingHideUses", `${name}`, `${type}`, `${range}`, `${effect}`, `${diceA}`, `${diceB}`, `${diceC}`, `${uses}`, `${usesmax}`, `${usetype}`], function(values) { + getAttrs(["egoActiveState", "settingSimpleDisplay", "settingWhisperRolls", "settingWhisperTarget", "settingMultihitFull", `${id}_multiPenalty`, `${id}_multiStyle`, "character_name", "advState", "difficulty", "skillSelect", "baseActNum", "Light", + "difficulty", "Endurance", "Disarm", "Strength", "Feeble", "evdPositive", "evdNegative", "advNum", "disadvNum", "attPower", "defPower", "evdPower", + "selectName", "selectLight", "selectType", "selectDice1", "selectDice2", "selectDice3", "selectEffect", + "distortWeaponDice1", "distortWeaponDice2", "distortWeaponDice3", "distortDefDice1", "distortDefDice2", "distortDefDice3", "distortEvdDice1", "distortEvdDice2", "distortEvdDice3", "distortEffect", "distortEffect2", "settingMultihitUses", "settingHideUses", + `${name}`, `${type}`, `${range}`, `${effect}`, `${diceA}`, `${diceB}`, `${diceC}`, `${uses}`, `${usesmax}`, `${usetype}`,], function(values) { let currentlight = parseInt(values.Light); let newlight = parseInt(values.Light); @@ -12353,20 +12372,51 @@ getSectionIDs(`repeating_global`, idarray => { } } + getAttrs([`${buttonid}AutoScript`, "outfitAutoScript", "egoAutoScript", `${skillselect}AutoScript`], function(values) { + + /* AutoScripts */ + let AutoScript = ""; + let triggerType = "None"; + + /* Get AutoScript from taken action */ + switch (buttonid) { + case "def": AutoScript = values.outfitAutoScript; break; + case "evd": AutoScript = values.outfitAutoScript; break; + case "egoDef": AutoScript = values.egoAutoScript; break; + case "egoEvd": AutoScript = values.egoAutoScript; break; + default: AutoScript = values[`${buttonid}AutoScript`]; break; + } + + /* Get trigger type if any */ + switch (basetype) { + case "Attack": triggerType = "Offensive"; break; + case "Defend": triggerType = "Block"; break; + case "Evade": triggerType = "Evade"; break; + } + + /* Get skill AutoAcript if any */ + if (skillselect != undefined || skillselect != "0") { + AutoScript += values[`${skillselect}AutoScript`]; + } + + /* Clean AutoScript. Remove nested and undefined */ + AutoScript = AutoScript.replace(/\[([#][^]+[#])\]/g, ""); + AutoScript = AutoScript.replace("undefined", ""); + + resetConditionals(); + AutoScriptMain(AutoScript, triggerType); + /* Power */ let activepower = "0"; if(basetype == "Attack"){ - activepower = parseInt(values.attPower) + parseInt(values.Strength) - parseInt(values.Feeble); - - attackmessage = weapontype + " | " + weaponrange + weaponuse + skillmass + "
"; - + activepower = parseInt(values.attPower) + parseInt(values.Strength) - parseInt(values.Feeble); + attackmessage = weapontype + " | " + weaponrange + weaponuse + skillmass + "
"; } else if(basetype == "Defend"){ - activepower = parseInt(values.defPower) + parseInt(values.Endurance) - parseInt(values.Disarm); - + activepower = parseInt(values.defPower) + parseInt(values.Endurance) - parseInt(values.Disarm); } else if(basetype == "Evade"){ - activepower = parseInt(values.evdPower) + parseInt(values.evdPositive) - parseInt(values.evdNegative); + activepower = parseInt(values.evdPower) + parseInt(values.evdPositive) - parseInt(values.evdNegative); } /* Distortion modifiers */ @@ -12577,7 +12627,7 @@ getSectionIDs(`repeating_global`, idarray => { setAttrs({"dummy":" ", "skillSelect":"0", [`${uses}`]:newuses}); }); - + }); }); }); @@ -12728,6 +12778,10 @@ on('clicked:rollChallenge', (info) => { } else if(statn == "Speed"){ setAttrs({"baseSpeed": total }); + + /* AutoScripts */ + resetConditionals(); + AutoScriptMain("", "Combat start"); } finishRoll( @@ -13057,6 +13111,12 @@ on('clicked:applyDamage', (info) => { if (newSP > maxSP) { newSP = maxSP } output["HP"] = newHP; output["StagRes"] = newST; output["SP"] = newSP; setAttrs(output); + + /* AutoScripts */ + if (newHP < oldHP || newST < oldST) { + resetConditionals(); + AutoScriptMain("", "Damaged"); + } /* console.log("HP base: " + sumBothBefore + ". HP after resistance: " + Math.ceil(Math.min((hpResistance * (sumBothBefore + sumHpBefore)) + hpProtection + damageResistance, 0))) console.log("ST base: " + sumBothBefore + ". ST after resistance: " + Math.ceil(Math.min((stResistance * (sumBothBefore + sumStBefore)) + stProtection + damageResistance, 0))) @@ -14548,7 +14608,291 @@ getAttrs(["settingEditMode"], function(values) { }); + + /*--- AutoScript functions ---*/ + +/* AutoScript editor open button */ +on("clicked:autoScriptEdit", function(info) { + let newEditorTarget = info.htmlAttributes.id; + getAttrs([`${newEditorTarget}`,"autoScriptEditorTarget", "autoScriptEditorInput"], function(values) { + let oldEditorTarget = values.autoScriptEditorTarget; + let newEditorInput = values[`${newEditorTarget}`]; + let oldEditorInput = values.autoScriptEditorInput; + setAttrs({ + [oldEditorTarget]: oldEditorInput, + autoScriptEditorInput: newEditorInput, + autoScriptEditorTarget: newEditorTarget, + autoScriptEditor_display: "true" + }); + }); +}); +/* AutoScript editor close button */ +on("clicked:closeAutoScriptEdit", function(info) { + getAttrs(["autoScriptEditorTarget", "autoScriptEditorInput"], function(values) { + let editorTarget = values.autoScriptEditorTarget; + let editorInput = values.autoScriptEditorInput; + setAttrs({ + [editorTarget]: editorInput, + autoScriptEditor_display: "0" + }); + }); +}); + +/* Temp testing button */ +on("clicked:autoEffectTest", function() { + /* All buttons except conditional buttons must have resetConditionals */ + resetConditionals(); + AutoScriptMain(`(Gain 3 Burn) (Gain 2 Fragile Next turn, TestConditional) (Gain 4 Fragile, TestConditional)`, "Combat start") +}); + +/* Executes a conditional button. Hides the button if at least one check fails */ +/* Also hides the button if a Consume check would fail after using the button again */ +on("clicked:repeating_conditionalButtons:activate", function(info) { + let buttonid = info.sourceAttribute.split("_")[2]; + let buttonAutoScript = ""; + let returnValues = {}; + getAttrs([`repeating_conditionalButtons_${buttonid}_buttonAutoScript`], function(values) { + buttonAutoScript = values[`repeating_conditionalButtons_${buttonid}_buttonAutoScript`] + AutoScriptMain(buttonAutoScript, "None", function(returnValues) { + if (returnValues.checkResult != "success") { + setAttrs({[`repeating_conditionalButtons_${buttonid}_hideButton`]: "true"}) + } + }, "false"); + }); +}); + +/* Main function for using AutoScripts. Called by actions through on click events */ +/* inputAutoScript: AutoScript provided by the action. Can be an empty string */ +/* trigger: "Combat start", "Round start", "Damaged", "Staggered", "Defeated", "Panic", +"Permanent", "Offensive", "Defensive", "Block", "Evade" or "None". +Selects which type of AutoEffects to collect and append to an AutoScript. +Block and Evade also include Defensive */ +/* callback: Function to be run on returnValues. Defaults to an empty function */ +/* collect: If the function should collect augment/outfit/etc. AutoEffects or not*/ +function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, collect="true") { + + /* Adds the input AutoScript */ + let AutoScript = ""; + if (inputAutoScript != "") { + AutoScript = inputAutoScript; + } + + /* Appends one or more AutoScripts based on the trigger type */ + let autoScriptTypes = []; + if (collect == "true") { + autoScriptTypes.push(triggerType) + if (triggerType != "None") { + if (autoScriptTypes.includes("Block") || autoScriptTypes.includes("Evade")) { + autoScriptTypes.push("Defensive"); + } + } + if (!autoScriptTypes.includes("Permanent")) { + autoScriptTypes.push("Permanent") + } + } + + getAttrs(["augmentAutoScript", "outfitAutoScript", "egoAutoScript", "distortState", "egoActiveState"], function(values) { + + let augmentAutoScript = ""; + let outfitAutoScript = ""; + let egoAutoScript = ""; + let collectedAutoScript = []; + + /* Finds all substrings that begin with "[#" and end with "#]" */ + augmentAutoScript = values.augmentAutoScript.match(/\[([#][^]+[#])\]/g); + if (augmentAutoScript == null) { augmentAutoScript = ""; } + outfitAutoScript = values.outfitAutoScript.match(/\[([#][^]+[#])\]/g); + if (outfitAutoScript == null) { outfitAutoScript = ""; } + if (values.distortState == "true" || values.egoActiveState == "true") { + egoAutoScript = values.egoAutoScript.match(/\[([#][^]+[#])\]/g); + if (egoAutoScript == null) { egoAutoScript = ""; } + } + + let TypedAutoScript = AutoScriptToArray(augmentAutoScript + outfitAutoScript + egoAutoScript, "nested"); + + TypedAutoScript.forEach((autoScriptType) => { + if (autoScriptTypes.includes(autoScriptType[0])) { + AutoScript += autoScriptType[1]; + } + }); + + /* Convert AutoScript to an array */ + AutoScript = AutoScriptToArray(AutoScript); + + /* Get relevant attributes */ + getAttrs(["settingMuteMessage", "settingWhisperRolls", "settingWhisperTarget", "settingLimbusStyle", "settingHideNextTurn", + "HP", "HP_max", "StagRes", "StagRes_max", "SP", "SP_max", + "StaggerState", "distortState", "egoActiveState", "egoType"], function(values) { + + let settingMuteMessage = values.settingMuteMessage; + let settingWhisperRolls = values.settingWhisperRolls; + let settingWhisperTarget = values.settingWhisperTarget; + let settingLimbusStyle = values.settingLimbusStyle; + let settingHideNextTurn = values.settingHideNextTurn; + + let HP = values.HP; + let ST = values.StagRes; + let SP = values.SP; + let barList = { HP: parseInt(HP), ST:parseInt(ST), SP:parseInt(SP) }; + + let HPdamage = values.HP_max - HP; + let STdamage = values.StagRes_max - ST; + let SPdamage = values.SP_max - SP; + let barDamageList = { "-HP": HPdamage, "-ST":STdamage, "-SP":SPdamage } + + let StaggerState = values.StaggerState; + let distortState = values.distortState; + let egoActiveState = values.egoActiveState; + let egoType = values.egoType; + + let scaling = 1; + let checkResult = "success"; + + let output = {}; + let tempOutput = {}; + let returnValues = { checkResult:"success", error:false, }; + let conditionalList = {} + + let ailmentList = {}; + + + /* Get all ailments */ + getAttrs(["burnNextTurnSetting", "bleedNextTurnSetting", "smokeNextTurnSetting", "chargeNextTurnSetting", + "Burn", "Bleed", "Paralysis", "Protection", "StaggerProtection", "Fragile", "Strength", "Feeble", "Endurance", "Disarm", "Haste", "Bind", "Smoke", "Charge", "Fortune", + "BurnNextTurn", "BleedNextTurn", "ParalysisNextTurn", "ProtectionNextTurn", "StaggerProtectionNextTurn", "FragileNextTurn", "StrengthNextTurn", "FeebleNextTurn", "EnduranceNextTurn", "DisarmNextTurn", "HasteNextTurn", "BindNextTurn", "SmokeNextTurn", "ChargeNextTurn", "FortuneNextTurn"], function(values) { + + const HasNextTurn = settingHideNextTurn == true ? 'false' : 'true'; + + let ailmentNames = ["Burn", "Bleed", "Paralysis", "Protection", "StaggerProtection", "Fragile", "Strength", "Feeble", "Endurance", "Disarm", "Haste", "Bind", "Smoke", "Charge", "Fortune"] + ailmentNames.forEach(ailment => { + if (["Burn", "Bleed", "Smoke", "Charge"].includes(ailment)) { + ailmentList[ailment] = [values[ailment.toLowerCase()+"NextTurnSetting"], values[ailment], values[`${ailment}NextTurn`]]; + } else { + ailmentList[ailment] = [HasNextTurn, values[ailment], values[`${ailment}NextTurn`]]; + } + }); + + /* Get all custom ailments */ + getSectionIDs(`repeating_ailments`, idarray => { + const fieldnames = idarray.reduce((rows,id) => + [...rows, `repeating_ailments_${id}_ailName`, `repeating_ailments_${id}_ailNextTurn`, + `repeating_ailments_${id}_ailNum`, `repeating_ailments_${id}_ailNumNextTurn`, ], ''); + + let ailName = ""; + let ailHasNextTurn = ""; + let ailNum = 0; + let ailNumNextTurn = 0; + + getAttrs([...fieldnames], v => { + idarray.forEach(id => { + ailName = v[`repeating_ailments_${id}_ailName`].replace(" ","_"); + ailHasNextTurn = v[`repeating_ailments_${id}_ailNextTurn`]; + ailNum = v[`repeating_ailments_${id}_ailNum`]; + ailNumNextTurn = v[`repeating_ailments_${id}_ailNumNextTurn`] + + ailmentList[ailName] = [ailHasNextTurn, ailNum, ailNumNextTurn, id]; + }); + + + /* Execute each AutoEffect in the AutoScript */ + AutoScript.forEach(AutoEffect => { + if (AutoEffect == undefined) { + return; + } + /* If conditional, add AutoEffect to either a new conditional button or a existing one */ + if (AutoEffect.length > 1) { + AutoEffect.slice(1).forEach(conditional => { + if (conditionalList.hasOwnProperty(conditional)) { + conditionalList[conditional] += " (" + AutoEffect[0].toString().replaceAll(","," ") + ")"; + } else { + conditionalList[conditional] = "(" + AutoEffect[0].toString().replaceAll(","," ") + ")"; + } + }); + } + /* If not conditional, process AutoEffect as normal */ + else { + /* Checks are always processed. Other AutoEffects are not processed if the last check failed */ + switch (AutoEffect[0][0]) { + case "Require": tempOutput = autoEffectRequire(AutoEffect[0], ailmentList, barList, barDamageList); break; + case "Consume": tempOutput = autoEffectConsume(AutoEffect[0], ailmentList, barList); break; + default: tempOutput = {}; break; + } + if (checkResult != "failure") { + switch (AutoEffect[0][0]) { + case "Require": break; /* Already executed above */ + case "Consume": break; + case "Gain": tempOutput = autoEffectGainAilment(AutoEffect[0], ailmentList, scaling); break; + default: tempOutput = {error:true}; autoEffectErrorMessage(`${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); break; + } + } + console.log(tempOutput) + + /* Handle errors. Continues executing AutoEffects for the sake of finding additional errors, */ + /* but does not apply any changes to attributes */ + if (tempOutput.hasOwnProperty("error") || returnValues.error == true) { + returnValues.error == true; + output = {}; + return; + } + + /* Handle changes to scaling */ + if (tempOutput.hasOwnProperty("scaling")) { + scaling = parseInt(tempOutput.scaling); + delete tempOutput.scaling; + } + + /* Handle check results from Require and Consume */ + /* For the returnValues, the worst result is returned */ + if (tempOutput.checkResult != undefined) { + checkResult = tempOutput.checkResult; + if (returnValues.checkResult == "success") { + returnValues.checkResult = tempOutput.checkResult; + } + else if (returnValues.checkResult == "last success" && tempOutput.checkResult == "failure") { + returnValues.checkResult = tempOutput.checkResult; + } + delete tempOutput.checkResult; + } + + /* Add attribute changes from AutoEffect to output */ + /* The first time a attribute is modified, add its count */ + /* For example, if Gain 3 Burn is used and current Burn is 2, output Burn is set to 5 */ + /* If Consume 4 Burn is used later, this amount will be removed without adding count */ + for (const property in tempOutput) { + if (output.hasOwnProperty(property)) { + output[property] += tempOutput[property]; + } else { + output[property] = tempOutput[property] + tempOutput.count; + } + } + } + }); + + // console.log(output) + setAttrs(output); + + /* Create conditional buttons */ + for (const [buttonName, buttonAutoScript] of Object.entries(conditionalList)) { + createConditionalButton(buttonName, buttonAutoScript); + } + + + /* Message handling */ + + /* Error handling */ + if (returnValues.error == true) { + /* Run function that clears all condition buttons */ + } + + callback(returnValues); + }); + }); + }); + }); + }); +} + /* Removes all newline and tab characters as well as JavaScript comments from an AutoScript */ function cleanAutoScript(AutoScript) { let cleanAutoScript = AutoScript.replace(/(\r\n|\n|\r|\t)/gm, ""); @@ -14608,301 +14952,11 @@ function AutoScriptToArray(inputAutoScript, mode="normal") { /* Return the converted AutoScript */ return AutoScriptArray; } - -/* AutoScript editor */ -on("clicked:autoScriptEdit", function(info) { - let newEditorTarget = info.htmlAttributes.id; - getAttrs([`${newEditorTarget}`,"autoScriptEditorTarget", "autoScriptEditorInput"], function(values) { - let oldEditorTarget = values.autoScriptEditorTarget; - let newEditorInput = values[`${newEditorTarget}`]; - let oldEditorInput = values.autoScriptEditorInput; - setAttrs({ - [oldEditorTarget]: oldEditorInput, - autoScriptEditorInput: newEditorInput, - autoScriptEditorTarget: newEditorTarget, - autoScriptEditor_display: "true" - }); - }); -}); -on("clicked:closeAutoScriptEdit", function(info) { - getAttrs(["autoScriptEditorTarget", "autoScriptEditorInput"], function(values) { - let editorTarget = values.autoScriptEditorTarget; - let editorInput = values.autoScriptEditorInput; - setAttrs({ - [editorTarget]: editorInput, - autoScriptEditor_display: "0" - }); - }); -}); - - - - - - - - - -on("clicked:autoEffectTest", function() { - /* All buttons except conditional buttons must have resetConditionals */ - resetConditionals(); - AutoScriptMain(`(Gain 3 Burn) (Gain 2 Fragile Next turn, TestConditional) (Gain 4 Fragile, TestConditional)`, "Combat start") -}); - - -/* Executes a conditional button. Hides the button if at least one check fails */ -/* Also hides the button if a Consume check would fail after using the button again */ -on("clicked:repeating_conditionalButtons:activate", function(info) { - let buttonid = info.sourceAttribute.split("_")[2]; - let buttonAutoScript = ""; - let returnValues = {}; - getAttrs([`repeating_conditionalButtons_${buttonid}_buttonAutoScript`], function(values) { - buttonAutoScript = values[`repeating_conditionalButtons_${buttonid}_buttonAutoScript`] - AutoScriptMain(buttonAutoScript, "None", function(returnValues) { - if (returnValues.checkResult != "success") { - setAttrs({[`repeating_conditionalButtons_${buttonid}_hideButton`]: "true"}) - } - }); - }); -}); - - -/* Main function for using AutoScripts. Called by actions through on click events */ -/* inputAutoScript: AutoScript provided by the action. Can be an empty string */ -/* trigger: "Combat start", "Round start", "Round end", "Damaged", "Staggered", "Defeated", "Panic", - "Permanent", "Offensive", "Defensive", "Block", "Evade" or "None". - Selects which type of AutoEffects to collect and append to an AutoScript. - Block and Evade also include Defensive */ -/* callback: Function to be run on returnValues. Defaults to an empty function */ -function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}) { - - /* Adds the input AutoScript */ - let AutoScript = ""; - if (inputAutoScript != "") { - AutoScript = inputAutoScript; - } - - /* Appends one or more AutoScripts based on the trigger type */ - let autoScriptTypes = [triggerType]; - if (triggerType != "None") { - if (autoScriptTypes.includes("Block") || autoScriptTypes.includes("Evade")) { - autoScriptTypes.push("Defensive"); - } - } - if (!autoScriptTypes.includes("Permanent")) { - autoScriptTypes.push("Permanent") - } - console.log(autoScriptTypes) - - getAttrs(["augmentAutoScript", "outfitAutoScript", "egoAutoScript", "distortState", "egoActiveState"], function(values) { - - let augmentAutoScript = ""; - let outfitAutoScript = ""; - let egoAutoScript = ""; - let collectedAutoScript = []; - - /* Finds all substrings that begin with "[#" and end with "#]" */ - augmentAutoScript = values.augmentAutoScript.match(/\[([#][^]+[#])\]/g); - if (augmentAutoScript == null) { augmentAutoScript = ""; } - outfitAutoScript = values.outfitAutoScript.match(/\[([#][^]+[#])\]/g); - if (outfitAutoScript == null) { outfitAutoScript = ""; } - if (values.distortState == "true" || values.egoActiveState == "true") { - egoAutoScript = values.egoAutoScript.match(/\[([#][^]+[#])\]/g); - if (egoAutoScript == null) { egoAutoScript = ""; } - } - - let TypedAutoScript = AutoScriptToArray(augmentAutoScript + outfitAutoScript + egoAutoScript, "nested"); - - TypedAutoScript.forEach((autoScriptType) => { - if (autoScriptTypes.includes(autoScriptType[0])) { - AutoScript += autoScriptType[1]; - } - }); - - /* Convert AutoScript to an array */ - AutoScript = AutoScriptToArray(AutoScript); - - /* Get relevant attributes */ - getAttrs(["settingMuteMessage", "settingWhisperRolls", "settingWhisperTarget", "settingLimbusStyle", "settingHideNextTurn", - "HP", "HP_max", "StagRes", "StagRes_max", "SP", "SP_max", - "StaggerState", "distortState", "egoActiveState", "egoType"], function(values) { - - let settingMuteMessage = values.settingMuteMessage; - let settingWhisperRolls = values.settingWhisperRolls; - let settingWhisperTarget = values.settingWhisperTarget; - let settingLimbusStyle = values.settingLimbusStyle; - let settingHideNextTurn = values.settingHideNextTurn; - - let HP = values.HP; - let ST = values.StagRes; - let SP = values.SP; - let barList = { HP: parseInt(HP), ST:parseInt(ST), SP:parseInt(SP) }; - - let HPdamage = values.HP_max - HP; - let STdamage = values.StagRes_max - ST; - let SPdamage = values.SP_max - SP; - let barDamageList = { "-HP": HPdamage, "-ST":STdamage, "-SP":SPdamage } - - let StaggerState = values.StaggerState; - let distortState = values.distortState; - let egoActiveState = values.egoActiveState; - let egoType = values.egoType; - - let scaling = 1; - let checkResult = "success"; - - let output = {}; - let tempOutput = {}; - let returnValues = { checkResult:"success", error:false, }; - let conditionalList = {} - - let ailmentList = {}; - - - /* Get all ailments */ - getAttrs(["burnNextTurnSetting", "bleedNextTurnSetting", "smokeNextTurnSetting", "chargeNextTurnSetting", - "Burn", "Bleed", "Paralysis", "Protection", "StaggerProtection", "Fragile", "Strength", "Feeble", "Endurance", "Disarm", "Haste", "Bind", "Smoke", "Charge", "Fortune", - "BurnNextTurn", "BleedNextTurn", "ParalysisNextTurn", "ProtectionNextTurn", "StaggerProtectionNextTurn", "FragileNextTurn", "StrengthNextTurn", "FeebleNextTurn", "EnduranceNextTurn", "DisarmNextTurn", "HasteNextTurn", "BindNextTurn", "SmokeNextTurn", "ChargeNextTurn", "FortuneNextTurn"], function(values) { - - const HasNextTurn = settingHideNextTurn == true ? 'false' : 'true'; - - let ailmentNames = ["Burn", "Bleed", "Paralysis", "Protection", "StaggerProtection", "Fragile", "Strength", "Feeble", "Endurance", "Disarm", "Haste", "Bind", "Smoke", "Charge", "Fortune"] - ailmentNames.forEach(ailment => { - if (["Burn", "Bleed", "Smoke", "Charge"].includes(ailment)) { - ailmentList[ailment] = [values[ailment.toLowerCase()+"NextTurnSetting"], values[ailment], values[`${ailment}NextTurn`]]; - } else { - ailmentList[ailment] = [HasNextTurn, values[ailment], values[`${ailment}NextTurn`]]; - } - }); - - /* Get all custom ailments */ - getSectionIDs(`repeating_ailments`, idarray => { - const fieldnames = idarray.reduce((rows,id) => - [...rows, `repeating_ailments_${id}_ailName`, `repeating_ailments_${id}_ailNextTurn`, - `repeating_ailments_${id}_ailNum`, `repeating_ailments_${id}_ailNumNextTurn`, ], ''); - - let ailName = ""; - let ailHasNextTurn = ""; - let ailNum = 0; - let ailNumNextTurn = 0; - - getAttrs([...fieldnames], v => { - idarray.forEach(id => { - ailName = v[`repeating_ailments_${id}_ailName`].replace(" ","_"); - ailHasNextTurn = v[`repeating_ailments_${id}_ailNextTurn`]; - ailNum = v[`repeating_ailments_${id}_ailNum`]; - ailNumNextTurn = v[`repeating_ailments_${id}_ailNumNextTurn`] - - ailmentList[ailName] = [ailHasNextTurn, ailNum, ailNumNextTurn, id]; - }); - - - /* Execute each AutoEffect in the AutoScript */ - AutoScript.forEach(AutoEffect => { - if (AutoEffect == undefined) { - return; - } - /* If conditional, add AutoEffect to either a new conditional button or a existing one */ - if (AutoEffect.length > 1) { - AutoEffect.slice(1).forEach(conditional => { - if (conditionalList.hasOwnProperty(conditional)) { - conditionalList[conditional] += " (" + AutoEffect[0].toString().replaceAll(","," ") + ")"; - } else { - conditionalList[conditional] = "(" + AutoEffect[0].toString().replaceAll(","," ") + ")"; - } - }); - } - /* If not conditional, process AutoEffect as normal */ - else { - /* Checks are always processed. Other AutoEffects are not processed if the last check failed */ - switch (AutoEffect[0][0]) { - case "Require": tempOutput = autoEffectRequire(AutoEffect[0], ailmentList, barList, barDamageList); break; - case "Consume": tempOutput = autoEffectConsume(AutoEffect[0], ailmentList, barList); break; - default: tempOutput = {}; break; - } - if (checkResult != "failure") { - switch (AutoEffect[0][0]) { - case "Require": break; /* Already executed above */ - case "Consume": break; - case "Gain": tempOutput = autoEffectGainAilment(AutoEffect[0], ailmentList, scaling); break; - default: tempOutput = {error:true}; autoEffectErrorMessage(`${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); break; - } - } - console.log(tempOutput) - - /* Handle errors. Continues executing AutoEffects for the sake of finding additional errors, */ - /* but does not apply any changes to attributes */ - if (tempOutput.hasOwnProperty("error") || returnValues.error == true) { - returnValues.error == true; - output = {}; - return; - } - - /* Handle changes to scaling */ - if (tempOutput.hasOwnProperty("scaling")) { - scaling = parseInt(tempOutput.scaling); - delete tempOutput.scaling; - } - - /* Handle check results from Require and Consume */ - /* For the returnValues, the worst result is returned */ - if (tempOutput.checkResult != undefined) { - checkResult = tempOutput.checkResult; - if (returnValues.checkResult == "success") { - returnValues.checkResult = tempOutput.checkResult; - } - else if (returnValues.checkResult == "last success" && tempOutput.checkResult == "failure") { - returnValues.checkResult = tempOutput.checkResult; - } - delete tempOutput.checkResult; - } - - /* Add attribute changes from AutoEffect to output */ - /* The first time a attribute is modified, add its count */ - /* For example, if Gain 3 Burn is used and current Burn is 2, output Burn is set to 5 */ - /* If Consume 4 Burn is used later, this amount will be removed without adding count */ - for (const property in tempOutput) { - if (output.hasOwnProperty(property)) { - output[property] += tempOutput[property]; - } else { - output[property] = tempOutput[property] + tempOutput.count; - } - } - } - }); - - // console.log(output) - setAttrs(output); - - /* Create conditional buttons */ - for (const [buttonName, buttonAutoScript] of Object.entries(conditionalList)) { - createConditionalButton(buttonName, buttonAutoScript); - } - - - - - - - - /* Message handling */ - - - /* Error handling */ - if (returnValues.error == true) { - /* Run function that clears all condition buttons */ - } - - callback(returnValues); - }); - }); - }); - }); - }); -} /*--- AutoScript functions end ---*/ + + /*--- AutoEffect functions ---*/ /* Whispers an error message to the user detailing an AutoEffect error */ @@ -14928,7 +14982,6 @@ function resetConditionals() { }); } - function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { /* Check format */ if (AutoEffect.length < 3 || AutoEffect.length > 4) { autoEffectErrorMessage(`Expected format: (Require N #Ailment/#Bar/#BarDamage #Scaling(optional))`, AutoEffect); return {error: true}; } @@ -15063,6 +15116,8 @@ function autoEffectGainAilment(AutoEffect, ailmentList, scaling) { /*--- AutoEffect functions end ---*/ + + /*--- Export/Import functions ---*/ let attrkeyCharacter = ["character_nameBase", "instinct", "wisdom", "justice", "charm", "insight", "temperance", "EXP", "character_job", "age", "height", "character_origin", "character_residence", "character_assets", "character_ahn", "character_url", "character_summary", "character_combatnote", "character_history", "character_relations", "character_notes", "character_desc", "character_personality", "character_background"]; From b96e416c473d0c26b1ab843d263be94511b56ab4 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Tue, 30 Jul 2024 17:50:42 +0200 Subject: [PATCH 11/55] Nre feature: AutoEffects, part 7 Added support for AutoEffects on tools and special items Fixed a few bugs with the AutoEffect implementation Removed the testing button --- ProjectMoonTRPG/ProjectMoonTRPG.html | 67 ++++++++++++++++++---------- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index ecb4889945..8c88d5443c 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -1544,10 +1544,7 @@ -

Roll helpers

- - -
+

Roll helpers

@@ -12213,11 +12210,16 @@ on('clicked:rollCombat', (info) => { getSectionIDs(`repeating_global`, idarray => { let id = `repeating_global_${idarray[0]}`; - getAttrs(["egoActiveState", "settingSimpleDisplay", "settingWhisperRolls", "settingWhisperTarget", "settingMultihitFull", `${id}_multiPenalty`, `${id}_multiStyle`, "character_name", "advState", "difficulty", "skillSelect", "baseActNum", "Light", + /* Get skillSelect first as it's used to gather further values */ + getAttrs(["skillSelect"], function(values) { + let skillselect = values.skillSelect; + + getAttrs(["egoActiveState", "settingSimpleDisplay", "settingWhisperRolls", "settingWhisperTarget", "settingMultihitFull", `${id}_multiPenalty`, `${id}_multiStyle`, "character_name", "advState", "difficulty", "baseActNum", "Light", "difficulty", "Endurance", "Disarm", "Strength", "Feeble", "evdPositive", "evdNegative", "advNum", "disadvNum", "attPower", "defPower", "evdPower", "selectName", "selectLight", "selectType", "selectDice1", "selectDice2", "selectDice3", "selectEffect", "distortWeaponDice1", "distortWeaponDice2", "distortWeaponDice3", "distortDefDice1", "distortDefDice2", "distortDefDice3", "distortEvdDice1", "distortEvdDice2", "distortEvdDice3", "distortEffect", "distortEffect2", "settingMultihitUses", "settingHideUses", - `${name}`, `${type}`, `${range}`, `${effect}`, `${diceA}`, `${diceB}`, `${diceC}`, `${uses}`, `${usesmax}`, `${usetype}`,], function(values) { + `${name}`, `${type}`, `${range}`, `${effect}`, `${diceA}`, `${diceB}`, `${diceC}`, `${uses}`, `${usesmax}`, `${usetype}`, + `${buttonid}AutoScript`, "outfitAutoScript", "egoAutoScript", `${skillselect}AutoScript`], function(values) { let currentlight = parseInt(values.Light); let newlight = parseInt(values.Light); @@ -12242,7 +12244,6 @@ getSectionIDs(`repeating_global`, idarray => { let distortstate = values.distortState; - let skillselect = values.skillSelect; let advstate = values.advState; let difficulty = parseInt(values.difficulty); let lightmessage = ""; @@ -12372,18 +12373,14 @@ getSectionIDs(`repeating_global`, idarray => { } } - getAttrs([`${buttonid}AutoScript`, "outfitAutoScript", "egoAutoScript", `${skillselect}AutoScript`], function(values) { - /* AutoScripts */ let AutoScript = ""; let triggerType = "None"; /* Get AutoScript from taken action */ switch (buttonid) { - case "def": AutoScript = values.outfitAutoScript; break; - case "evd": AutoScript = values.outfitAutoScript; break; - case "egoDef": AutoScript = values.egoAutoScript; break; - case "egoEvd": AutoScript = values.egoAutoScript; break; + case "def": case "evd": AutoScript = values.outfitAutoScript; break; + case "egoWeapon": case "egoDef": case "egoEvd": AutoScript = values.egoAutoScript; break; default: AutoScript = values[`${buttonid}AutoScript`]; break; } @@ -13379,8 +13376,12 @@ on('clicked:declareAction', (info) => { headercolor = "#8e7cc3"; newicon = "/"; + /* Get toolSelect first as it's used to gather further values */ + getAttrs(["toolSelect"], function(values) { + let toolselect = values.toolSelect; + /* Get attributes */ - getAttrs(["actionType", "settingSimpleDisplay", "settingWhisperRolls", "settingWhisperTarget", "character_name", "Light", "selectName", "selectLight", "selectType", "selectDice1", "selectDice2", "selectDice3", "selectEffect", "selectDescription", "baseActNum", "distortState", "toolSelect", "tool1Name", "tool1Reusable", "tool1Uses", "tool1Uses_max", "tool1Effect", "tool1Description", "tool2Name", "tool2Reusable", "tool2Uses", "tool2Uses_max", "tool2Effect", "tool2Description", "tool3Name", "tool3Reusable", "tool3Uses", "tool3Uses_max", "tool3Effect", "tool3Description", "tool4Name", "tool4Reusable", "tool4Uses", "tool4Uses_max", "tool4Effect", "tool4Description", "special1Name","special1Description", "special1Range", "special1Duration", "special1Risk", "special2Name", "special2Description", "special2Range", "special2Duration", "special2Risk", "egoName", "egoType", "egoDescription", "egoUses", "egoUses_max", "egoUseType", "egoEffect", "egoRisk", "egoRange", "egoDuration", "settingHideUses"], function(values) { + getAttrs(["actionType", "settingSimpleDisplay", "settingWhisperRolls", "settingWhisperTarget", "character_name", "Light", "selectName", "selectLight", "selectType", "selectDice1", "selectDice2", "selectDice3", "selectEffect", "selectDescription", "baseActNum", "distortState", "tool1Name", "tool1Reusable", "tool1Uses", "tool1Uses_max", "tool1Effect", "tool1Description", "tool2Name", "tool2Reusable", "tool2Uses", "tool2Uses_max", "tool2Effect", "tool2Description", "tool3Name", "tool3Reusable", "tool3Uses", "tool3Uses_max", "tool3Effect", "tool3Description", "tool4Name", "tool4Reusable", "tool4Uses", "tool4Uses_max", "tool4Effect", "tool4Description", "special1Name","special1Description", "special1Range", "special1Duration", "special1Risk", "special2Name", "special2Description", "special2Range", "special2Duration", "special2Risk", "egoName", "egoType", "egoDescription", "egoUses", "egoUses_max", "egoUseType", "egoEffect", "egoRisk", "egoRange", "egoDuration", "settingHideUses", `${toolselect}AutoScript`], function(values) { let charname = values.character_name; let simpledisplay = values.settingSimpleDisplay; @@ -13395,8 +13396,6 @@ on('clicked:declareAction', (info) => { let newlight = values.Light; let actcounter = parseInt(values.baseActNum) + 1; - let toolselect = values.toolSelect; - let output = {}; if(distortstate == "true"){ @@ -13537,6 +13536,16 @@ on('clicked:declareAction', (info) => { let lightmessage = ""; + /* AutoScripts */ + let AutoScript = values[`${toolselect}AutoScript`]; + + /* Clean AutoScript. Remove nested and undefined */ + AutoScript = AutoScript.replace(/\[([#][^]+[#])\]/g, ""); + AutoScript = AutoScript.replace("undefined", ""); + + resetConditionals(); + AutoScriptMain(AutoScript, "None"); + /* Translation prep */ let langFrom = "From"; let langUse = "Use Tool"; @@ -13648,7 +13657,7 @@ on('clicked:declareAction', (info) => { setAttrs(output); - + }); }); }); @@ -14639,13 +14648,6 @@ on("clicked:closeAutoScriptEdit", function(info) { }); }); -/* Temp testing button */ -on("clicked:autoEffectTest", function() { - /* All buttons except conditional buttons must have resetConditionals */ - resetConditionals(); - AutoScriptMain(`(Gain 3 Burn) (Gain 2 Fragile Next turn, TestConditional) (Gain 4 Fragile, TestConditional)`, "Combat start") -}); - /* Executes a conditional button. Hides the button if at least one check fails */ /* Also hides the button if a Consume check would fail after using the button again */ on("clicked:repeating_conditionalButtons:activate", function(info) { @@ -14686,6 +14688,9 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, if (autoScriptTypes.includes("Block") || autoScriptTypes.includes("Evade")) { autoScriptTypes.push("Defensive"); } + else if (autoScriptTypes.includes("Combat start")) { + autoScriptTypes.push("Round start"); + } } if (!autoScriptTypes.includes("Permanent")) { autoScriptTypes.push("Permanent") @@ -14808,6 +14813,18 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, } else { conditionalList[conditional] = "(" + AutoEffect[0].toString().replaceAll(","," ") + ")"; } + + /* If AutoEffect is Require or Consume, do not display the button if the check will fail */ + if (AutoEffect[0][0] == "Require" || AutoEffect[0][0] == "Consume") { + switch (AutoEffect[0][0]) { + case "Require": tempOutput = autoEffectRequire(AutoEffect[0], ailmentList, barList, barDamageList); break; + case "Consume": tempOutput = autoEffectConsume(AutoEffect[0], ailmentList, barList); break; + default: tempOutput = {}; break; + } + if (tempOutput.checkResult == "failure") { + conditionalList[conditional] = "#Do not display#"; + } + } }); } /* If not conditional, process AutoEffect as normal */ @@ -14874,6 +14891,8 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, /* Create conditional buttons */ for (const [buttonName, buttonAutoScript] of Object.entries(conditionalList)) { + /* Checks if any checks failed and the button should not be displayed */ + if (buttonAutoScript.indexOf("#Do not display#") != -1) { continue; } createConditionalButton(buttonName, buttonAutoScript); } From 05dadd4d2ed417d716f2f5108e465d700f199c52 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Tue, 30 Jul 2024 22:31:01 +0200 Subject: [PATCH 12/55] New feature: AutoEffects, part 8 - Add Reset AutoEffect. Sets checkResult and scaling back to their default values - When collecting AutoScripts, adds a Reset AutoEffect before each new imported section to hinder interference between the scripts - Added a save button to the AutoScript editor allowing changes to be saved without closing the editor - Expanded Damaged trigger to now include DamagedHP, DamagedST, DamagedSP and Damaged. Damaged triggers on any damage taken - Added Challenge trigger which triggers when using a Challenge roll --- ProjectMoonTRPG/ProjectMoonTRPG.html | 46 ++++++++++----- ProjectMoonTRPG/ProjectMoonTRPGStyle.css | 75 +++++++++--------------- ProjectMoonTRPG/translation.json | 1 + 3 files changed, 58 insertions(+), 64 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 8c88d5443c..948e357472 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -107,6 +107,7 @@
+ @@ -12662,6 +12663,10 @@ on('clicked:rollChallenge', (info) => { let rollformat = "2d6" + "+" + parseInt(stat) + "+(" + parseInt(difficulty) + ")"; + /* AutoScripts */ + resetConditionals(); + AutoScriptMain("", "Challenge"); + /* Type Formatting */ if(buttonid == "instinct"){ newicon = "https://raw.githubusercontent.com/punibird/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/stats/Instinct.png"; @@ -13110,10 +13115,9 @@ on('clicked:applyDamage', (info) => { setAttrs(output); /* AutoScripts */ - if (newHP < oldHP || newST < oldST) { - resetConditionals(); - AutoScriptMain("", "Damaged"); - } + if (newHP < oldHP) { resetConditionals(); AutoScriptMain("", "DamagedHP"); } + if (newST < oldST) { resetConditionals(); AutoScriptMain("", "DamagedST"); } + if (newSP < oldSP) { resetConditionals(); AutoScriptMain("", "DamagedSP"); } /* console.log("HP base: " + sumBothBefore + ". HP after resistance: " + Math.ceil(Math.min((hpResistance * (sumBothBefore + sumHpBefore)) + hpProtection + damageResistance, 0))) console.log("ST base: " + sumBothBefore + ". ST after resistance: " + Math.ceil(Math.min((stResistance * (sumBothBefore + sumStBefore)) + stProtection + damageResistance, 0))) @@ -14636,16 +14640,23 @@ on("clicked:autoScriptEdit", function(info) { }); }); }); -/* AutoScript editor close button */ -on("clicked:closeAutoScriptEdit", function(info) { +/* AutoScript editor save button */ +function saveAutoScriptEditor() { getAttrs(["autoScriptEditorTarget", "autoScriptEditorInput"], function(values) { let editorTarget = values.autoScriptEditorTarget; let editorInput = values.autoScriptEditorInput; setAttrs({ - [editorTarget]: editorInput, - autoScriptEditor_display: "0" + [editorTarget]: editorInput }); }); +} +on("clicked:saveAutoScriptEdit", function(info) { + saveAutoScriptEditor(); +}); +/* AutoScript editor close button */ +on("clicked:closeAutoScriptEdit", function(info) { + saveAutoScriptEditor(); + setAttrs({autoScriptEditor_display: "0"}); }); /* Executes a conditional button. Hides the button if at least one check fails */ @@ -14666,8 +14677,8 @@ on("clicked:repeating_conditionalButtons:activate", function(info) { /* Main function for using AutoScripts. Called by actions through on click events */ /* inputAutoScript: AutoScript provided by the action. Can be an empty string */ -/* trigger: "Combat start", "Round start", "Damaged", "Staggered", "Defeated", "Panic", -"Permanent", "Offensive", "Defensive", "Block", "Evade" or "None". +/* trigger: "Combat start", "Round start", "Permanent", "Damaged", "DamagedHP", "DamagedST", "DamagedSP", +"Staggered", "Defeated", "Panic", "Challenge", "Offensive", "Defensive", "Block", "Evade" or "None". Selects which type of AutoEffects to collect and append to an AutoScript. Block and Evade also include Defensive */ /* callback: Function to be run on returnValues. Defaults to an empty function */ @@ -14691,6 +14702,9 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, else if (autoScriptTypes.includes("Combat start")) { autoScriptTypes.push("Round start"); } + else if (autoScriptTypes.some(item => ["DamagedHP", "DamagedST", "DamagedSP"].includes(item))) { + autoScriptTypes.push("Damaged"); + } } if (!autoScriptTypes.includes("Permanent")) { autoScriptTypes.push("Permanent") @@ -14718,7 +14732,7 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, TypedAutoScript.forEach((autoScriptType) => { if (autoScriptTypes.includes(autoScriptType[0])) { - AutoScript += autoScriptType[1]; + AutoScript += "(Reset)" + autoScriptType[1]; } }); @@ -14778,7 +14792,7 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, } }); - /* Get all custom ailments */ + /* Get all custom ailments */ getSectionIDs(`repeating_ailments`, idarray => { const fieldnames = idarray.reduce((rows,id) => [...rows, `repeating_ailments_${id}_ailName`, `repeating_ailments_${id}_ailNextTurn`, @@ -14829,16 +14843,16 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, } /* If not conditional, process AutoEffect as normal */ else { - /* Checks are always processed. Other AutoEffects are not processed if the last check failed */ + /* Checks and Reset are always processed. Other AutoEffects are not processed if the last check failed */ switch (AutoEffect[0][0]) { case "Require": tempOutput = autoEffectRequire(AutoEffect[0], ailmentList, barList, barDamageList); break; case "Consume": tempOutput = autoEffectConsume(AutoEffect[0], ailmentList, barList); break; + case "Reset": tempOutput = {checkResult: "success", scaling: 1}; break; default: tempOutput = {}; break; } if (checkResult != "failure") { switch (AutoEffect[0][0]) { - case "Require": break; /* Already executed above */ - case "Consume": break; + case "Require": case "Consume": case "Reset": break; /* Already executed above */ case "Gain": tempOutput = autoEffectGainAilment(AutoEffect[0], ailmentList, scaling); break; default: tempOutput = {error:true}; autoEffectErrorMessage(`${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); break; } @@ -15912,7 +15926,7 @@ function updateCustomAilment(rowid) { } output[`repeating_ailments_${rowid}_ailNum`] = parseInt(newcount) + parseInt(countnextturn); - } + } else if (countnextturn > 0) { output[`repeating_ailments_${rowid}_ailNum`] = countnextturn; } diff --git a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css index 2d76721679..51e8fa7492 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css +++ b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css @@ -1553,7 +1553,6 @@ margin-bottom: 2px !important;} .applyDamageInput { opacity: 60%; cursor: default; - height: 50px; min-width: 50px; background-size: contain; @@ -2553,60 +2552,58 @@ justify-content: center; /* Assorted buttons */ -.shareButton { +.shareButton, .editButton, .autoScriptButton, .closeAutoScriptButton, .saveAutoScriptButton, .copyButton, .displayButton, .lockButton { position: absolute; + height: 25px; + width: 25px; + border-radius: 5px; + background-size: contain; + background-position: center; + background-repeat: no-repeat; +} + + + +:is(.closeAutoScriptButton, .saveAutoScriptButton):hover { + background-color: #000 !important; +} + +.shareButton { bottom: 5px; right: 5px; z-index: 20; - height: 25px; - width: 25px; - border-radius: 5px; background-image: url('https://raw.githubusercontent.com/punibird/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/icons/share.png'); - background-size: contain; - background-position: center; - background-repeat: no-repeat; + } .editButton { - position: absolute; bottom: 5px; right: 35px; z-index: 20; - height: 25px; - width: 25px; - border-radius: 5px; background-image: url('https://raw.githubusercontent.com/punibird/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/icons/edit.png'); - background-size: contain; - background-position: center; - background-repeat: no-repeat; } .autoScriptButton { - position: absolute; bottom: 5px; right: 65px; z-index: 20; - height: 25px; - width: 25px; - border-radius: 5px; background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/AutoEffects-Functionality/ProjectMoonTRPG/imagesResized/icons/script.png'); - background-size: contain; - background-position: center; - background-repeat: no-repeat; } .closeAutoScriptButton { - position: absolute; top: 4px; right: 6px; z-index: 20; - height: 25px; - width: 25px; - border-radius: 5px; background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/AutoEffects-Functionality/ProjectMoonTRPG/imagesResized/icons/exit.png'); - background-size: contain; - background-position: center; - background-repeat: no-repeat; +} + +.saveAutoScriptButton { + top: 4px; + right: 36px; + z-index: 20; + padding-left: 4px; + padding-right: 4px; + width: auto; } :is(.augmentBlock, .specialBlock, .skillBlock) .autoScriptButton { @@ -2614,55 +2611,37 @@ justify-content: center; } .copyButton { - position: absolute; top: 5px; right: 5px; z-index: 1; - height: 25px; - width: 25px; - border-radius: 5px; background-color: transparent; background-image: url('https://raw.githubusercontent.com/punibird/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/icons/copy.png'); - background-size: contain; - background-position: center; - background-repeat: no-repeat; opacity: 50%; } .displayButton { - position: absolute; top: 5px; right: 35px; z-index: 1; - height: 25px; - width: 25px; - border-radius: 5px; background-color: transparent; background-image: url('https://raw.githubusercontent.com/punibird/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/icons/view-hide.png'); - background-size: contain; - background-position: center; - background-repeat: no-repeat; opacity: 50%; } .lockButton { height: 30px; width: 30px; - position: absolute; top: 3px; left: 5px; + border-radius: 0px; background-color: transparent; background-image: url('https://raw.githubusercontent.com/punibird/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/icons/lock-unlock.png'); - background-size: contain; - background-position: center; - background-repeat: no-repeat; opacity: 50%; } .syncIcon { height: 5px; width: 5px; - position: absolute; top: 7px; left: 29px; background-color: #cc4125; diff --git a/ProjectMoonTRPG/translation.json b/ProjectMoonTRPG/translation.json index 46fc6dc116..f0a819e1ab 100644 --- a/ProjectMoonTRPG/translation.json +++ b/ProjectMoonTRPG/translation.json @@ -245,6 +245,7 @@ "autoscript-edit":"Edit AutoScript", "autoscript-editor":"AutoScript Editor", "autoscript-close-editor":"Close AutoScript Editor", + "autoscript-save-changes":"Save AutoScript changes", "equip-weapon1-name":"Weapon Name (1)", "equip-weapon2-name":"Weapon Name (2)", "equip-weapon3-name":"Weapon Name (3)", From dabb626dfb7586983ce88ee609a1597b6423f264 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Tue, 30 Jul 2024 22:31:19 +0200 Subject: [PATCH 13/55] Styling: Added a hover effect to most buttons (was previously only some buttons) --- ProjectMoonTRPG/ProjectMoonTRPGStyle.css | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css index 51e8fa7492..11148a5ebc 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css +++ b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css @@ -907,9 +907,8 @@ opacity: 20%; .skillSelectionLabel input { color: #fff; } -.skillSelector:checked ~ .skillSelectionLabel { - background-color: #555; - opacity: 100%; +.skillSelector:not(:checked) + .skillSelectionLabel:hover { + background-color: rgba(0, 0, 0, 0.3) !important; } .skillSelector:checked ~ .skillSelectionLabel { background-color: #555; @@ -1356,8 +1355,7 @@ button[type=roll].NDice, button[type=action].NDice{ /* Tools */ -.tool input[type=checkbox] + label -{ +.tool input[type=checkbox] + label { background-size: cover; background-position: center; background-repeat: no-repeat; @@ -1368,6 +1366,9 @@ padding: 0 0 0 0px; margin: 0px; opacity: 30%; } +.tool input[type=checkbox] + label:hover { +opacity: 50%; +} .tool input[type=checkbox]:checked + label { opacity: 100%; } @@ -2562,6 +2563,9 @@ justify-content: center; background-repeat: no-repeat; } +:is(.shareButton, .editButton, .autoScriptButton, .copyButton, .displayButton, .lockButton):hover { + background-color: rgba(0, 0, 0, 0.3) !important; +} :is(.closeAutoScriptButton, .saveAutoScriptButton):hover { From 8a50e809c8256c68c316bfb9839291463c1e90ff Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Tue, 30 Jul 2024 22:31:56 +0200 Subject: [PATCH 14/55] Bugfix: Decay when hit wasn't updating correctly when next turn count was present --- ProjectMoonTRPG/ProjectMoonTRPG.html | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 948e357472..958362ec32 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -13145,8 +13145,8 @@ on('clicked:applyDamage', (info) => { langBaseDamage = getTranslationByKey("helper-text-basedamage"); langFlatDamageHP= getTranslationByKey("helper-text-flatdamagehp"); langFlatDamageST = getTranslationByKey("helper-text-flatdamagest"); - langDamage = getTranslationByKey("message-damage-calculation"); - langDealt = getTranslationByKey("message dealt"); + langDamage = getTranslationByKey("message-damage"); + langDealt = getTranslationByKey("message-dealt"); langIncreasedHPDamageBy = getTranslationByKey("message-increased-HP-damage-by"); langSmoke = getTranslationByKey("ailments-smoke"); langFragile = getTranslationByKey("ailments-fragile"); @@ -15773,7 +15773,7 @@ getSectionIDs(`repeating_global`, idarray => { /* Function: Update custom ailment */ function updateCustomAilment(rowid) { - getAttrs(["distortState", "egoActiveState", "egoType", `repeating_ailments_${rowid}_ailNum`, `repeating_ailments_${rowid}_ailNumNextTurn`, `repeating_ailments_${rowid}_ailName`, `repeating_ailments_${rowid}_ailIcon`, `repeating_ailments_${rowid}_ailTrigger`, `repeating_ailments_${rowid}_ailEffect`, `repeating_ailments_${rowid}_ailEffectMode`, `repeating_ailments_${rowid}_ailEffectVal`, `repeating_ailments_${rowid}_ailCustomResistanceNum`, `repeating_ailments_${rowid}_ailCustomResistanceNumEgo`, `repeating_ailments_${rowid}_ailDecayMode`, `repeating_ailments_${rowid}_ailDecayVal`, `repeating_ailments_${rowid}_ailDecayMin`, `repeating_ailments_${rowid}_ailMax`, `repeating_ailments_${rowid}_ailMaxBehavior`, `repeating_ailments_${rowid}_ailMessageCheck`, `repeating_ailments_${rowid}_ailMessage`, "HP", "StagRes", "SP", "Light", "distortCounter", "difficulty", "baseSpeed", "baseLuckNum", "settingWhisperRolls", "settingWhisperTarget", "settingMuteMessage", "character_name"], function(values) { + getAttrs(["distortState", "egoActiveState", "egoType", `repeating_ailments_${rowid}_ailNum`, `repeating_ailments_${rowid}_ailNumNextTurn`, `repeating_ailments_${rowid}_ailName`, `repeating_ailments_${rowid}_ailIcon`, `repeating_ailments_${rowid}_ailTrigger`, `repeating_ailments_${rowid}_ailEffect`, `repeating_ailments_${rowid}_ailEffectMode`, `repeating_ailments_${rowid}_ailEffectVal`, `repeating_ailments_${rowid}_ailDecayWhenHit`, `repeating_ailments_${rowid}_ailCustomResistanceNum`, `repeating_ailments_${rowid}_ailCustomResistanceNumEgo`, `repeating_ailments_${rowid}_ailDecayMode`, `repeating_ailments_${rowid}_ailDecayVal`, `repeating_ailments_${rowid}_ailDecayMin`, `repeating_ailments_${rowid}_ailMax`, `repeating_ailments_${rowid}_ailMaxBehavior`, `repeating_ailments_${rowid}_ailMessageCheck`, `repeating_ailments_${rowid}_ailMessage`, "HP", "StagRes", "SP", "Light", "distortCounter", "difficulty", "baseSpeed", "baseLuckNum", "settingWhisperRolls", "settingWhisperTarget", "settingMuteMessage", "character_name"], function(values) { let charname = values.character_name; let nomessage = values.settingMuteMessage; @@ -15783,6 +15783,7 @@ function updateCustomAilment(rowid) { let icon = values[`repeating_ailments_${rowid}_ailIcon`]; let count = values[`repeating_ailments_${rowid}_ailNum`]; let countnextturn = values[`repeating_ailments_${rowid}_ailNumNextTurn`]; + let decayWhenhit = values[`repeating_ailments_${rowid}_ailDecayWhenHit`]; let trigger = values[`repeating_ailments_${rowid}_ailTrigger`]; @@ -15925,9 +15926,12 @@ function updateCustomAilment(rowid) { newcount = 0; } - output[`repeating_ailments_${rowid}_ailNum`] = parseInt(newcount) + parseInt(countnextturn); + output[`repeating_ailments_${rowid}_ailNum`] = parseInt(newcount); + if (decayWhenhit != "true") { + output[`repeating_ailments_${rowid}_ailNum`] += parseInt(countnextturn); } - else if (countnextturn > 0) { + } + else if (countnextturn > 0 && trigger != "WhenHit") { output[`repeating_ailments_${rowid}_ailNum`] = countnextturn; } From 62083963c09872bdae98488227f916d94e802fb7 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Wed, 31 Jul 2024 03:46:43 +0200 Subject: [PATCH 15/55] New feature: AutoScript, part 9 - Removed scaling option for all non-check AutoEffects. Reset can be used to control scaling so this option is redundant. Scaling is now always enabled for these effects - Added DicePower, DiceMax and DiceCount effects. Support Challenge rolls, Attacks, Blocks and Evades. Cannot be conditional - Added Speed effect. Has durations Combat, This turn and Next turn, which modifies the initiative for either the entire combat or a round - Added percentage value to Require. When used, checks if the user has at least N% of a bars max remaining, or if at least N% of a bars max has been lost to damage --- ProjectMoonTRPG/ProjectMoonTRPG.html | 337 ++++++++++++++++++++++----- ProjectMoonTRPG/translation.json | 1 + 2 files changed, 285 insertions(+), 53 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 958362ec32..d5ca8b8b72 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -1561,7 +1561,8 @@ - + +
@@ -11240,23 +11241,22 @@ getSectionIDs(`repeating_global`, idarray => { }); /* Auto: Update calculated speed | Update Evd power (Haste/Bind) */ -on("change:Haste change:Bind change:dynamicSpeed change:baseSpeed", function() { - +on("change:Haste change:Bind change:thisRoundSpeed change:baseSpeed", function() { getSectionIDs(`repeating_global`, idarray => { - let id = `repeating_global_${idarray[0]}`; + let id = `repeating_global_${idarray[0]}`; - getAttrs(["settingTurnUpdate", "baseSpeed", "prevSpeed", "Haste", "Bind", "character_name", "settingEvdInfluence", `${id}_evdAilment`, "evdPositive", "evdNegative"], function(values) { + getAttrs(["settingTurnUpdate", "baseSpeed", "prevSpeed", "thisRoundSpeed", "Haste", "Bind", "character_name", "settingEvdInfluence", `${id}_evdAilment`, "evdPositive", "evdNegative"], function(values) { let turnupdate = values.settingTurnUpdate; let evdinfluence = values[`${id}_evdAilment`]; let basespeed = parseInt(values.baseSpeed); let prevspeed = parseInt(values.prevSpeed); - let dynamicspeed = parseInt(values.dynamicSpeed); + let thisRoundSpeed = parseInt(values.thisRoundSpeed); let hastenum = parseInt(values.Haste); let bindnum = parseInt(values.Bind); let name = values.character_name; - let newspeed = basespeed + hastenum - bindnum; + let newspeed = basespeed + hastenum - bindnum + thisRoundSpeed; let command = "[[" + newspeed + "&{tracker} ]]"; let message = "Speed update: "; @@ -11277,7 +11277,7 @@ getSectionIDs(`repeating_global`, idarray => { } - }); + }); }); }); @@ -11702,7 +11702,7 @@ on('clicked:updateAilments', function() { getSectionIDs(`repeating_global`, idarray => { let id = `repeating_global_${idarray[0]}`; - getAttrs(["settingMuteMessage", "settingWhisperRolls", "settingWhisperTarget", "settingBurnImmune", + getAttrs(["settingMuteMessage", "settingWhisperRolls", "settingWhisperTarget", "settingBurnImmune", "nextRoundSpeed", "StaggerState", "SealState", "ImmobileState", "Burn", "burnResist", "burnResist_ego", "distortState", "egoActiveState", "egoType", "Smoke", "Charge", "HP", "StagRes_max", "settingLimbusStyle", `${id}_staggerRecoverPercent`, `${id}_staggerRecoverBase`, `${id}_burnDecayMode`, `${id}_burnDecayVal`, `${id}_smokeDecayMode`, `${id}_smokeDecayVal`, `${id}_chargeDecayMode`, `${id}_chargeDecayVal`, "Bleed", "BurnNextTurn", "BleedNextTurn", "ParalysisNextTurn", "ProtectionNextTurn", "StaggerProtectionNextTurn", "FragileNextTurn", "StrengthNextTurn", "FeebleNextTurn", "EnduranceNextTurn", "DisarmNextTurn", "HasteNextTurn", "BindNextTurn", "SmokeNextTurn", "ChargeNextTurn", "FortuneNextTurn"], function(values) { @@ -11749,6 +11749,8 @@ getSectionIDs(`repeating_global`, idarray => { style = style + "limbus/"; } + let nextRoundSpeed = parseInt(values.nextRoundSpeed); + let burnresist = values.burnResist; let distortstate = values.distortState; let egostate = values.egoActiveState; @@ -11769,6 +11771,10 @@ getSectionIDs(`repeating_global`, idarray => { whisper = "/w " + whispertarget; } + /* AutoScripts */ + resetConditionals(); + AutoScriptMain("", "Round start"); + /* Burn processing */ if (parseInt(values.Burn) > 0){ @@ -11900,11 +11906,10 @@ getSectionIDs(`repeating_global`, idarray => { setAttrs({ - "Bleed":bleednew, "BleedNextTurn":"0", "Burn": burnnew, "BurnNextTurn":"0", "Paralysis": paralysisnew, "ParalysisNextTurn":"0", "Protection": protectionnew, "ProtectionNextTurn":"0", "StaggerProtection": staggerprotectionnew, "StaggerProtectionNextTurn":"0", "Fragile": fragilenew, "FragileNextTurn":"0", "Strength": strengthnew, "StrengthNextTurn":"0", "Feeble": feeblenew, "FeebleNextTurn":"0", "Endurance": endurancenew, "EnduranceNextTurn":"0", "Disarm": disarmnew, "DisarmNextTurn":"0", "Haste": hastenew, "HasteNextTurn":"0", "Bind": bindnew, "BindNextTurn":"0", "Smoke": smokenew, "SmokeNextTurn":"0", "Charge":chargenew, "ChargeNextTurn":"0", "Fortune":fortunenew, "FortuneNextTurn":"0", "baseActNum":"0"}); + "thisRoundSpeed":nextRoundSpeed, "nextRoundSpeed":0, "Bleed":bleednew, "BleedNextTurn":"0", "Burn": burnnew, "BurnNextTurn":"0", "Paralysis": paralysisnew, "ParalysisNextTurn":"0", "Protection": protectionnew, "ProtectionNextTurn":"0", "StaggerProtection": staggerprotectionnew, "StaggerProtectionNextTurn":"0", "Fragile": fragilenew, "FragileNextTurn":"0", "Strength": strengthnew, "StrengthNextTurn":"0", "Feeble": feeblenew, "FeebleNextTurn":"0", "Endurance": endurancenew, "EnduranceNextTurn":"0", "Disarm": disarmnew, "DisarmNextTurn":"0", "Haste": hastenew, "HasteNextTurn":"0", "Bind": bindnew, "BindNextTurn":"0", "Smoke": smokenew, "SmokeNextTurn":"0", "Charge":chargenew, "ChargeNextTurn":"0", "Fortune":fortunenew, "FortuneNextTurn":"0", "baseActNum":"0"}); }); - /* Custom Ailments */ getSectionIDs(`repeating_ailments`, idarray => { const fieldnames = idarray.reduce((rows,id) => [...rows, `repeating_ailments_${id}_ailTrigger`, `repeating_ailments_${id}_ailDecayRoundEnd`, `repeating_ailments_${id}_ailNextTurn`, `repeating_ailments_${id}_ailNum`, `repeating_ailments_${id}_ailNumNextTurn`], ''); @@ -11935,14 +11940,9 @@ getSectionIDs(`repeating_global`, idarray => { setAttrs(output); - }); - }); }); - - /* AutoScripts */ - resetConditionals(); - AutoScriptMain("", "Round start"); - + }); + }); }); function updateAdvantages(changeval){ @@ -12402,7 +12402,14 @@ getSectionIDs(`repeating_global`, idarray => { AutoScript = AutoScript.replace("undefined", ""); resetConditionals(); - AutoScriptMain(AutoScript, triggerType); + AutoScriptMain(AutoScript, triggerType, function(returnValues) { + + let autoeffectdice1 = 0; + let autoeffectdice2 = 0; + let autoeffectdice3 = 0; + if (returnValues.diceCount != undefined) { autoeffectdice1 = returnValues.diceCount} + if (returnValues.dicePower != undefined) { autoeffectdice2 = returnValues.dicePower} + if (returnValues.diceMax != undefined) { autoeffectdice3 = returnValues.diceMax} /* Power */ let activepower = "0"; @@ -12445,9 +12452,9 @@ getSectionIDs(`repeating_global`, idarray => { } /* Dice formatting */ - combinedice1 = parseInt(basedice1) + parseInt(distortdice1) + parseInt(skilldice1); - combinedice2 = parseInt(basedice2) + parseInt(distortdice2) + parseInt(skilldice2); - combinedice3 = parseInt(basedice3) + parseInt(distortdice3) + parseInt(skilldice3) + parseInt(activepower); + combinedice1 = Math.max(parseInt(basedice1) + parseInt(distortdice1) + parseInt(skilldice1) + parseInt(autoeffectdice1), 0); + combinedice2 = Math.max(parseInt(basedice2) + parseInt(distortdice2) + parseInt(skilldice2) + parseInt(autoeffectdice2), 0); + combinedice3 = parseInt(basedice3) + parseInt(distortdice3) + parseInt(skilldice3) + parseInt(activepower) + parseInt(autoeffectdice3); if(values.settingMultihitUses == "true" && limitbehavior != "Limitless" && limitbehavior != null){ if(combinedice1 > currentuses){ @@ -12624,6 +12631,7 @@ getSectionIDs(`repeating_global`, idarray => { setAttrs({"dummy":" ", "skillSelect":"0", [`${uses}`]:newuses}); + }); }); }); }); @@ -12631,10 +12639,13 @@ getSectionIDs(`repeating_global`, idarray => { /* Action: Challenge Roll */ on('clicked:rollChallenge', (info) => { - /* Preparing values */ /* Get IDs/names */ - let buttonid = info.htmlAttributes.id.split('_')[1]; - + let buttonid = info.htmlAttributes.id.split('_')[1]; + rollChallenge(buttonid); +}); +function rollChallenge(buttonid, rollDifficulty=0) { + + /* Preparing values */ let headercolor = "#888"; let newicon = "/"; let headertext = "#fff"; @@ -12656,16 +12667,24 @@ on('clicked:rollChallenge', (info) => { let whispertarget = values.settingWhisperTarget; let tracker = ""; - let difficulty = values.difficulty; + let difficulty = parseInt(values.difficulty) + parseInt(rollDifficulty); let spdjustice = values.justice; let newicon = "/"; let lucknum = "0"; - let rollformat = "2d6" + "+" + parseInt(stat) + "+(" + parseInt(difficulty) + ")"; - /* AutoScripts */ resetConditionals(); - AutoScriptMain("", "Challenge"); + AutoScriptMain("", ["Challenge", "Combat start"], function(returnValues) { + + let autoEffectDiceCount = 0; + let autoEffectDiceMax = 0; + let autoEffectSpeedCombat = 0; + if (returnValues.dicePower != undefined) { stat = returnValues.dicePower } + if (returnValues.diceCount != undefined) { autoEffectDiceCount = returnValues.diceCount } + if (returnValues.diceMax != undefined) { autoEffectDiceMax = returnValues.diceMax } + if (returnValues.speedCombat != undefined) { autoEffectSpeedCombat = returnValues.speedCombat } + + let rollformat = Math.max(autoEffectDiceCount + 2, 0) + "d" + Math.max(autoEffectDiceMax + 6, 0) + "+" + parseInt(stat) + "+(" + parseInt(difficulty) + ")"; /* Type Formatting */ if(buttonid == "instinct"){ @@ -12705,7 +12724,7 @@ on('clicked:rollChallenge', (info) => { statn = "Speed"; headercolor = "#cf8c44"; tracker = "&{tracker}" - rollformat = "1d6+" + parseInt(spdjustice) + "+(" + parseInt(difficulty) + ")"; + rollformat = "1d6+" + (parseInt(spdjustice) + parseInt(autoEffectSpeedCombat)) + "+(" + parseInt(difficulty) + ")"; challenge = " "; } @@ -12780,10 +12799,6 @@ on('clicked:rollChallenge', (info) => { } else if(statn == "Speed"){ setAttrs({"baseSpeed": total }); - - /* AutoScripts */ - resetConditionals(); - AutoScriptMain("", "Combat start"); } finishRoll( @@ -12802,8 +12817,8 @@ on('clicked:rollChallenge', (info) => { }); - -}); + }); +} /* Action: Damage helper apply damage */ @@ -14694,7 +14709,8 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, /* Appends one or more AutoScripts based on the trigger type */ let autoScriptTypes = []; if (collect == "true") { - autoScriptTypes.push(triggerType) + if (typeof triggerType == "string") { autoScriptTypes.push(triggerType) } + else {autoScriptTypes.push(...triggerType) } if (triggerType != "None") { if (autoScriptTypes.includes("Block") || autoScriptTypes.includes("Evade")) { autoScriptTypes.push("Defensive"); @@ -14710,6 +14726,8 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, autoScriptTypes.push("Permanent") } } + + console.log(autoScriptTypes) getAttrs(["augmentAutoScript", "outfitAutoScript", "egoAutoScript", "distortState", "egoActiveState"], function(values) { @@ -14732,7 +14750,8 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, TypedAutoScript.forEach((autoScriptType) => { if (autoScriptTypes.includes(autoScriptType[0])) { - AutoScript += "(Reset)" + autoScriptType[1]; + if (AutoScript != "") { AutoScript += "(Reset)"; } + AutoScript += autoScriptType[1]; } }); @@ -14741,7 +14760,7 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, /* Get relevant attributes */ getAttrs(["settingMuteMessage", "settingWhisperRolls", "settingWhisperTarget", "settingLimbusStyle", "settingHideNextTurn", - "HP", "HP_max", "StagRes", "StagRes_max", "SP", "SP_max", + "HP", "HP_max", "StagRes", "StagRes_max", "SP", "SP_max", "thisRoundSpeed", "nextRoundSpeed", "StaggerState", "distortState", "egoActiveState", "egoType"], function(values) { let settingMuteMessage = values.settingMuteMessage; @@ -14759,6 +14778,9 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, let STdamage = values.StagRes_max - ST; let SPdamage = values.SP_max - SP; let barDamageList = { "-HP": HPdamage, "-ST":STdamage, "-SP":SPdamage } + + let thisRoundSpeed = values.thisRoundSpeed; + let nextRoundSpeed = values.nextRoundSpeed; let StaggerState = values.StaggerState; let distortState = values.distortState; @@ -14771,7 +14793,8 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, let output = {}; let tempOutput = {}; let returnValues = { checkResult:"success", error:false, }; - let conditionalList = {} + let conditionalList = {}; + let challengeRollList = {}; let ailmentList = {}; @@ -14854,6 +14877,14 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, switch (AutoEffect[0][0]) { case "Require": case "Consume": case "Reset": break; /* Already executed above */ case "Gain": tempOutput = autoEffectGainAilment(AutoEffect[0], ailmentList, scaling); break; + case "DicePower": tempOutput = autoEffectDicePower(AutoEffect[0], scaling); break; + case "Set": tempOutput = autoEffectSetBar(AutoEffect[0], barList, scaling); break; + case "Add": tempOutput = autoEffectAddBar(AutoEffect[0], barList, scaling); break; + case "Multi": tempOutput = autoEffectMultiBar(AutoEffect[0], barList, scaling); break; + case "DiceMax": tempOutput = autoEffectDiceMax(AutoEffect[0], scaling); break; + case "DiceCount": tempOutput = autoEffectDiceCount(AutoEffect[0], scaling); break; + case "ChallengeRoll": tempOutput = autoEffectChallengeRoll(AutoEffect[0], scaling); break; + case "Speed": tempOutput = autoEffectSpeed(AutoEffect[0], scaling, thisRoundSpeed, nextRoundSpeed); break; default: tempOutput = {error:true}; autoEffectErrorMessage(`${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); break; } } @@ -14885,16 +14916,27 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, } delete tempOutput.checkResult; } - + + /* Handle DicePower, DiceMax, DiceCount and Speed with Combat duration */ + if (tempOutput.dicePower != undefined) { returnValues.dicePower = tempOutput.dicePower } + if (tempOutput.diceMax != undefined) { returnValues.diceMax = tempOutput.diceMax } + if (tempOutput.diceCount != undefined) { returnValues.diceCount = tempOutput.diceCount } + if (tempOutput.speedCombat != undefined) { returnValues.speedCombat = tempOutput.speedCombat } + + /* Handle challenge rolls */ + if (tempOutput.challengeRollStat != undefined) { + challengeRollList[tempOutput.challengeRollStat] = tempOutput.challengeRollDifficulty; + } + /* Add attribute changes from AutoEffect to output */ /* The first time a attribute is modified, add its count */ /* For example, if Gain 3 Burn is used and current Burn is 2, output Burn is set to 5 */ /* If Consume 4 Burn is used later, this amount will be removed without adding count */ for (const property in tempOutput) { if (output.hasOwnProperty(property)) { - output[property] += tempOutput[property]; + output[property] += Math.floor(tempOutput[property]); } else { - output[property] = tempOutput[property] + tempOutput.count; + output[property] = Math.floor(tempOutput[property] + tempOutput.count); } } } @@ -14909,15 +14951,22 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, if (buttonAutoScript.indexOf("#Do not display#") != -1) { continue; } createConditionalButton(buttonName, buttonAutoScript); } - + + /* Execute challange rolls */ + for (const [statName, rollDifficulty] of Object.entries(challengeRollList)) { + /* Checks if any checks failed and the button should not be displayed */ + rollChallenge(statName, rollDifficulty); + } /* Message handling */ - /* Error handling */ + /* Error handling and returnValues callback */ if (returnValues.error == true) { - /* Run function that clears all condition buttons */ + resetConditionals(); + callback({error: true}); } + console.log(returnValues); callback(returnValues); }); }); @@ -15019,10 +15068,6 @@ function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { /* Check format */ if (AutoEffect.length < 3 || AutoEffect.length > 4) { autoEffectErrorMessage(`Expected format: (Require N #Ailment/#Bar/#BarDamage #Scaling(optional))`, AutoEffect); return {error: true}; } - /* Get required value */ - let effectVal = parseInt(Math.abs(AutoEffect[1])); - if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } - /* Get target count */ let effectName = AutoEffect[2]; @@ -15033,6 +15078,25 @@ function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { /* Handle bar damage count */ else if (barDamageList.hasOwnProperty(effectName)) { count = barDamageList[effectName]; } else { autoEffectErrorMessage(`Ailment, Bar or BarDamage "${effectName}" does not exist`, AutoEffect); return {error: true}; } + + /* Get required value. Recalculate count if percentage */ + let effectVal = AutoEffect[1]; + if (isNaN(parseInt(Math.abs(effectVal))) == false) { + effectVal = parseInt(Math.abs(effectVal)); + } + else if ((/[0-9]+[%]/g).test(String(effectVal))) { + let percentage = parseFloat(effectVal.replace("%","")) / 100; + let barVal = parseInt(barList[effectName.replace("-","")]); + let barMax = parseInt(barVal) + parseInt(barDamageList[`-${effectName.replace("-","")}`]); + if (barList.hasOwnProperty(effectName)) { + count = barVal; + } + else if (barDamageList.hasOwnProperty(effectName)) { + count = barMax - barVal; + } + effectVal = barMax*percentage; + } + else { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number or percentage`, AutoEffect); return {error: true}; } /* Handle the optional scaling property */ let scaling = 1; @@ -15107,7 +15171,7 @@ function autoEffectConsume(AutoEffect, ailmentList, barList) { function autoEffectGainAilment(AutoEffect, ailmentList, scaling) { /* Check format */ - if (AutoEffect.length < 3 || AutoEffect.length > 6) { autoEffectErrorMessage(`Expected format: (Gain N #Ailment #Round(optional))`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 3 || AutoEffect.length > 5) { autoEffectErrorMessage(`Expected format: (Gain N #Ailment #Round(optional))`, AutoEffect); return {error: true}; } /* Handle scaling */ AutoEffect[1] *= scaling; @@ -15126,7 +15190,7 @@ function autoEffectGainAilment(AutoEffect, ailmentList, scaling) { /* This is between you and me, but "Next turn" doesn't actually do anything ;) */ let forceTarget = ""; if (AutoEffect[3] != undefined) { - if (["this", "thisturn", "this turn"].includes(AutoEffect[3].toLowerCase())) { forceTarget = "This turn"; } + if (["this", "thisround", "this round, thisturn, this turn"].includes(AutoEffect[3].toLowerCase())) { forceTarget = "This turn"; } } /* Get target attribute */ @@ -15144,7 +15208,174 @@ function autoEffectGainAilment(AutoEffect, ailmentList, scaling) { } /* Execute AutoEffect */ - return { [effectTarget]: parseInt(effectVal), count:parseInt(count) } + return { [effectTarget]: parseInt(effectVal), count: parseInt(count) } +} + +function autoEffectSetBar(AutoEffect, barList, scaling) { + /* Check format */ + if (AutoEffect.length != 3) { autoEffectErrorMessage(`Expected format: (Set N #Bar)`, AutoEffect); return {error: true}; } + + /* Handle scaling */ + AutoEffect[1] *= scaling; + if (scaling == 0) { return {}; } + + /* Get value */ + let effectVal = parseInt(Math.abs(AutoEffect[1])); + if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + + /* Get target */ + let effectBar = AutoEffect[2]; + let effectTarget = ""; + if (barList.hasOwnProperty(effectBar)) { effectTarget = effectBar.replace("ST", "StagRes"); } + else { autoEffectErrorMessage(`Bar "${effectBar}" does not exist`, AutoEffect); return {error: true}; } + + /* Execute AutoEffect */ + return {[effectTarget]: parseInt(effectVal), count: 0}; +} +function autoEffectAddBar(AutoEffect, barList, scaling) { + /* Check format */ + if (AutoEffect.length != 3) { autoEffectErrorMessage(`Expected format: (Add N #Bar)`, AutoEffect); return {error: true}; } + + /* Handle scaling */ + AutoEffect[1] *= scaling; + if (scaling == 0) { return {}; } + + /* Get value */ + let effectVal = parseInt(Math.abs(AutoEffect[1])); + if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + let count = 0; + + /* Get target */ + let effectBar = AutoEffect[2]; + let effectTarget = ""; + if (barList.hasOwnProperty(effectBar)) { + effectTarget = effectBar.replace("ST", "StagRes"); + count = barList[effectBar]; + } + else { autoEffectErrorMessage(`Bar "${effectBar}" does not exist`, AutoEffect); return {error: true}; } + + /* Execute AutoEffect */ + return {[effectTarget]: parseInt(effectVal), count: parseInt(count)}; +} +function autoEffectMultiBar(AutoEffect, barList, scaling) { + /* Check format */ + if (AutoEffect.length != 3) { autoEffectErrorMessage(`Expected format: (Multi N #Bar)`, AutoEffect); return {error: true}; } + + /* Handle scaling */ + AutoEffect[1] *= scaling; + if (scaling == 0) { return {}; } + + /* Get value */ + let effectVal = parseFloat(Math.abs(AutoEffect[1])); + if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + + /* Get target */ + let effectBar = AutoEffect[2]; + let effectTarget = ""; + if (barList.hasOwnProperty(effectBar)) { + effectTarget = effectBar.replace("ST", "StagRes"); + count = barList[effectBar]; + } + else { autoEffectErrorMessage(`Bar "${effectBar}" does not exist`, AutoEffect); return {error: true}; } + + /* Execute AutoEffect */ + return {[effectTarget]: parseFloat(effectVal) * parseInt(count), count: 0 }; +} + +function autoEffectDicePower(AutoEffect, scaling) { + /* Check format */ + if (AutoEffect.length != 2) { autoEffectErrorMessage(`Expected format: (DicePower N)`, AutoEffect); return {error: true}; } + + /* Handle scaling */ + AutoEffect[1] *= scaling; + if (scaling == 0) { return {}; } + + /* Get values */ + let effectVal = parseInt(AutoEffect[1]); + if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + + /* Execute AutoEffect */ + return { dicePower: parseInt(effectVal) } +} +function autoEffectDiceMax(AutoEffect, scaling) { + /* Check format */ + if (AutoEffect.length != 2) { autoEffectErrorMessage(`Expected format: (DiceMax N)`, AutoEffect); return {error: true}; } + + /* Handle scaling */ + AutoEffect[1] *= scaling; + if (scaling == 0) { return {}; } + + /* Get values */ + let effectVal = parseInt(AutoEffect[1]); + if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + + /* Execute AutoEffect */ + return { diceMax: parseInt(effectVal) } +} +function autoEffectDiceCount(AutoEffect, scaling) { + /* Check format */ + if (AutoEffect.length != 2) { autoEffectErrorMessage(`Expected format: (DiceCount N)`, AutoEffect); return {error: true}; } + + /* Handle scaling */ + AutoEffect[1] *= scaling; + if (scaling == 0) { return {}; } + + /* Get values */ + let effectVal = parseInt(AutoEffect[1]); + if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + + /* Execute AutoEffect */ + return { diceCount: parseInt(effectVal) } +} + +function autoEffectChallengeRoll(AutoEffect, scaling) { + /* Check format */ + if (AutoEffect.length != 3) { autoEffectErrorMessage(`Expected format: (ChallengeRoll #Stat N)`, AutoEffect); return {error: true}; } + + /* Handle scaling */ + AutoEffect[2] *= scaling; + if (scaling == 0) { return {}; } + + /* Get values */ + let effectVal = parseInt(AutoEffect[2]); + if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + + /* Get target stat */ + let statTarget = ""; + if (["fortitude", "instinct", "prudence", "wisdom", "justice", "charm", "insight", "temperance"].includes(AutoEffect[1].toLowerCase())) { + statTarget = AutoEffect[1].toLowerCase().replace("fortitude","instinct").replace("prudence","wisdom"); + } + else { autoEffectErrorMessage(`Stat "${AutoEffect[1]}" does not exist.`, AutoEffect); return {error: true}; } + + /* Execute AutoEffect */ + return { challengeRollStat: statTarget, challengeRollDifficulty: effectVal } +} + +function autoEffectSpeed(AutoEffect, scaling, prevThisRoundSpeed, prevNextRoundSpeed) { + /* Check format */ + if (AutoEffect.length < 3 || AutoEffect.length > 4) { autoEffectErrorMessage(`Expected format: (Speed N #Duration)`, AutoEffect); return {error: true}; } + + /* Handle scaling */ + AutoEffect[1] *= scaling; + if (scaling == 0) { return {}; } + + /* Get values */ + let effectVal = parseInt(AutoEffect[1]); + if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + + /* Get duration */ + let effectDuration = ""; + if (AutoEffect[2].toLowerCase() == "combat") { effectDuration = "Combat"; } + else if (["this", "thisround", "this round, thisturn, this turn"].includes(AutoEffect[2].toLowerCase())) { effectDuration = "ThisRound"; } + else if (["next", "nextround", "next round, nextturn, next turn"].includes(AutoEffect[2].toLowerCase())) { effectDuration = "NextRound"; } + else { autoEffectErrorMessage(`Duration "${AutoEffect[2]}" does not exist. Expected "Combat", "This round" or "Next round"`, AutoEffect); return {error: true}; } + + /* Execute AutoEffect */ + switch (effectDuration) { + case "Combat": return { speedCombat: parseInt(effectVal) }; break; + case "ThisRound": return { thisRoundSpeed: parseInt(effectVal), count: parseInt(prevThisRoundSpeed)}; break; + case "NextRound": return { nextRoundSpeed: parseInt(effectVal), count: parseInt(prevNextRoundSpeed)}; break; + } } /*--- AutoEffect functions end ---*/ diff --git a/ProjectMoonTRPG/translation.json b/ProjectMoonTRPG/translation.json index f0a819e1ab..8a5896118f 100644 --- a/ProjectMoonTRPG/translation.json +++ b/ProjectMoonTRPG/translation.json @@ -11,6 +11,7 @@ "settings-simpledisplay":"Simple roll display", "settings-extraequip":"Extra weapons/tools/skills", "settings-hidespecial":"Hide: Special items", + "settings-hidenextturn":"Hide: Next turn input", "settings-hidehelpertext":"Hide: Helper text", "settings-hideshare":"Hide: Share buttons", "settings-burnimmune":"No burn damage", From 7610a769864335ae9f9f3668c4f8431127dc9b4c Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Wed, 31 Jul 2024 03:55:26 +0200 Subject: [PATCH 16/55] AutoEffects: part 10 Added AutoScripts to the import/export functionality --- ProjectMoonTRPG/ProjectMoonTRPG.html | 50 ++++++++++++++-------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index d5ca8b8b72..b0a8ca2efc 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -15388,39 +15388,39 @@ let attrkeyCharacter = ["character_nameBase", "instinct", "wisdom", "justice", " let attrkeySettings = ["settingWhisperRolls", "settingMuteMessage", "settingAutoDetect", "settingTurnUpdate", "settingSimpleDisplay", "settingExtraEquip", "settingHideSpecial", "settingHelperText", "settingHideShare", "settingBurnImmune", "settingBleedImmune", "settingMultihitFull", "settingMultihitUses", "settingHideUses"]; -let attrkeyEquip = ["outfitName", "outfitRank", "outfitDescription", "outfitEffect", "defDice1", "defDice2", "defDice3", "evdDice1", "evdDice2", "evdDice3", "outfitImmune1", "outfitImmune2", "outfitImmune3", "outfitImmune4", "outfitImmune5", "outfitImmune6", "bleedResist", "burnResist", "damageResist", +let attrkeyEquip = ["outfitName", "outfitRank", "outfitDescription", "outfitEffect", "defDice1", "defDice2", "defDice3", "evdDice1", "evdDice2", "evdDice3", "outfitImmune1", "outfitImmune2", "outfitImmune3", "outfitImmune4", "outfitImmune5", "outfitImmune6", "bleedResist", "burnResist", "damageResist", "outfitAutoScript", -"weapon1Name", "weapon1Rank", "weapon1Description", "weapon1Effect", "weapon1Dice1", "weapon1Dice2", "weapon1Dice3", "weapon1Type", "weapon1Range", "weapon1Uses", "weapon1Uses_max", "weapon1UseType", -"weapon2Name", "weapon2Rank", "weapon2Description", "weapon2Effect", "weapon2Dice1", "weapon2Dice2", "weapon2Dice3", "weapon2Type", "weapon2Range", "weapon2Uses", "weapon2Uses_max", "weapon2UseType", -"weapon3Name", "weapon3Rank", "weapon3Description", "weapon3Effect", "weapon3Dice1", "weapon3Dice2", "weapon3Dice3", "weapon3Type", "weapon3Range", "weapon3Uses", "weapon3Uses_max", "weapon3UseType", -"weapon4Name", "weapon4Rank", "weapon4Description", "weapon4Effect", "weapon4Dice1", "weapon4Dice2", "weapon4Dice3", "weapon4Type", "weapon4Range", "weapon4Uses", "weapon4Uses_max", "weapon4UseType", +"weapon1Name", "weapon1Rank", "weapon1Description", "weapon1Effect", "weapon1Dice1", "weapon1Dice2", "weapon1Dice3", "weapon1Type", "weapon1Range", "weapon1Uses", "weapon1Uses_max", "weapon1UseType", "weapon1AutoScript", +"weapon2Name", "weapon2Rank", "weapon2Description", "weapon2Effect", "weapon2Dice1", "weapon2Dice2", "weapon2Dice3", "weapon2Type", "weapon2Range", "weapon2Uses", "weapon2Uses_max", "weapon2UseType", "weapon2AutoScript", +"weapon3Name", "weapon3Rank", "weapon3Description", "weapon3Effect", "weapon3Dice1", "weapon3Dice2", "weapon3Dice3", "weapon3Type", "weapon3Range", "weapon3Uses", "weapon3Uses_max", "weapon3UseType", "weapon3AutoScript", +"weapon4Name", "weapon4Rank", "weapon4Description", "weapon4Effect", "weapon4Dice1", "weapon4Dice2", "weapon4Dice3", "weapon4Type", "weapon4Range", "weapon4Uses", "weapon4Uses_max", "weapon4UseType", "weapon4AutoScript", -"augmentName", "augmentRank", "augmentType", "augmentDescription", "augmentEffect", +"augmentName", "augmentRank", "augmentType", "augmentDescription", "augmentEffect", "augmentAutoScript", -"tool1Name", "tool1Rank", "tool1Description", "tool1Effect", "tool1Portable", "tool1Reusable", "tool1Uses", "tool1Uses_max", "tool1Icon", -"tool2Name", "tool2Rank", "tool2Description", "tool2Effect", "tool2Portable", "tool2Reusable", "tool2Uses", "tool2Uses", "tool2Uses_max", "tool2Icon", -"tool3Name", "tool3Rank", "tool3Description", "tool3Effect", "tool3Portable", "tool3Reusable", "tool3Uses", "tool3Uses", "tool3Uses_max", "tool3Icon", -"tool4Name", "tool4Rank", "tool4Description", "tool4Effect", "tool4Portable", "tool4Reusable", "tool4Uses", "tool4Uses", "tool4Uses_max", "tool4Icon", +"tool1Name", "tool1Rank", "tool1Description", "tool1Effect", "tool1Portable", "tool1Reusable", "tool1Uses", "tool1Uses_max", "tool1Icon", "tool1AutoScript", +"tool2Name", "tool2Rank", "tool2Description", "tool2Effect", "tool2Portable", "tool2Reusable", "tool2Uses", "tool2Uses", "tool2Uses_max", "tool2Icon", "tool2AutoScript", +"tool3Name", "tool3Rank", "tool3Description", "tool3Effect", "tool3Portable", "tool3Reusable", "tool3Uses", "tool3Uses", "tool3Uses_max", "tool3Icon", "tool3AutoScript", +"tool4Name", "tool4Rank", "tool4Description", "tool4Effect", "tool4Portable", "tool4Reusable", "tool4Uses", "tool4Uses", "tool4Uses_max", "tool4Icon", "tool4AutoScript", -"special1Name", "special1Rank", "special1Risk", "special1Range", "special1Duration", "special1Description", -"special2Name", "special2Rank", "special2Risk", "special2Range", "special2Duration", "special2Description"]; +"special1Name", "special1Rank", "special1Risk", "special1Range", "special1Duration", "special1Description", "special1AutoScript", +"special2Name", "special2Rank", "special2Risk", "special2Range", "special2Duration", "special2Description", "special2AutoScript"]; let attrkeyDistort = ["distort_name", "distortWork", "distortCounter", "distortWorkInstinct", "distortWorkWisdom", "distortWorkJustice", "distortWorkCharm", "distortWorkInsight", "distortWorkTemperance", "distortResultGood", "distortResultNormal", "distortResultBad", "distortWeaponDice1", "distortWeaponDice2", "distortWeaponDice3", "distortDefDice1", "distortDefDice2", "distortDefDice3", "distortEvdDice1", "distortEvdDice2", "distortEvdDice3", "distortDescription", "distortEffect", "distortDescription2", "distortEffect2", "distort_url", "distort_summary", "distort_behavior", "distort_combatnote", "distort_origin", "distort_notes", "distort_taboo", "distort_appearance", "distort_atmosphere", "distort_story"]; -let attrkeyEgo = ["egoName", "egoCondition", "egoType", "egoRank", "egoIdeology", "egoDescription", "egoEffect", "egoWeaponDice1", "egoWeaponDice2", "egoWeaponDice3", "egoWeaponType", "egoWeaponRange", "egoDefDice1", "egoDefDice2", "egoDefDice3", "egoEvdDice1", "egoEvdDice2", "egoEvdDice3", "egoImmune1", "egoImmune2", "egoImmune3", "egoImmune4", "egoImmune5", "egoImmune6", "egoUses", "egoUses_max", "egoUseType", "egoRisk", "egoRange", "egoDuration", "bleedResist_ego", "burnResist_ego", "damageResist_ego"]; +let attrkeyEgo = ["egoName", "egoCondition", "egoType", "egoRank", "egoIdeology", "egoDescription", "egoEffect", "egoWeaponDice1", "egoWeaponDice2", "egoWeaponDice3", "egoWeaponType", "egoWeaponRange", "egoDefDice1", "egoDefDice2", "egoDefDice3", "egoEvdDice1", "egoEvdDice2", "egoEvdDice3", "egoImmune1", "egoImmune2", "egoImmune3", "egoImmune4", "egoImmune5", "egoImmune6", "egoUses", "egoUses_max", "egoUseType", "egoRisk", "egoRange", "egoDuration", "bleedResist_ego", "burnResist_ego", "damageResist_ego", "egoAutoScript"]; -let attrkeySkills = ["skill1Name", "skill1Rank", "skill1Type", "skill1Light", "skill1Dice1", "skill1Dice2", "skill1Dice3", "skill1Description", "skill1Effect", -"skill2Name", "skill2Rank", "skill2Type", "skill2Light", "skill2Dice1", "skill2Dice2", "skill2Dice3", "skill2Description", "skill2Effect", -"skill3Name", "skill3Rank", "skill3Type", "skill3Light", "skill3Dice1", "skill3Dice2", "skill3Dice3", "skill3Description", "skill3Effect", -"skill4Name", "skill4Rank", "skill4Type", "skill4Light", "skill4Dice1", "skill4Dice2", "skill4Dice3", "skill4Description", "skill4Effect", -"skill5Name", "skill5Rank", "skill5Type", "skill5Light", "skill5Dice1", "skill5Dice2", "skill5Dice3", "skill5Description", "skill5Effect", -"skill6Name", "skill6Rank", "skill6Type", "skill6Light", "skill6Dice1", "skill6Dice2", "skill6Dice3", "skill6Description", "skill6Effect", -"egoSkill1Name", "egoSkill1Rank", "egoSkill1Type", "egoSkill1Light", "egoSkill1Dice1", "egoSkill1Dice2", "egoSkill1Dice3", "egoSkill1Description", "egoSkill1Effect", -"egoSkill2Name", "egoSkill2Rank", "egoSkill2Type", "egoSkill2Light", "egoSkill2Dice1", "egoSkill2Dice2", "egoSkill2Dice3", "egoSkill2Description", "egoSkill2Effect", -"egoSkill3Name", "egoSkill3Rank", "egoSkill3Type", "egoSkill3Light", "egoSkill3Dice1", "egoSkill3Dice2", "egoSkill3Dice3", "egoSkill3Description", "egoSkill3Effect", -"egoSkill4Name", "egoSkill4Rank", "egoSkill4Type", "egoSkill4Light", "egoSkill4Dice1", "egoSkill4Dice2", "egoSkill4Dice3", "egoSkill4Description", "egoSkill4Effect", -"egoSkill5Name", "egoSkill5Rank", "egoSkill5Type", "egoSkill5Light", "egoSkill5Dice1", "egoSkill5Dice2", "egoSkill5Dice3", "egoSkill5Description", "egoSkill5Effect", -"egoSkill6Name", "egoSkill6Rank", "egoSkill6Type", "egoSkill6Light", "egoSkill6Dice1", "egoSkill6Dice2", "egoSkill6Dice3", "egoSkill6Description", "egoSkill6Effect"]; +let attrkeySkills = ["skill1Name", "skill1Rank", "skill1Type", "skill1Light", "skill1Dice1", "skill1Dice2", "skill1Dice3", "skill1Description", "skill1Effect", "skill1AutoScript", +"skill2Name", "skill2Rank", "skill2Type", "skill2Light", "skill2Dice1", "skill2Dice2", "skill2Dice3", "skill2Description", "skill2Effect", "skill2AutoScript", +"skill3Name", "skill3Rank", "skill3Type", "skill3Light", "skill3Dice1", "skill3Dice2", "skill3Dice3", "skill3Description", "skill3Effect", "skill3AutoScript", +"skill4Name", "skill4Rank", "skill4Type", "skill4Light", "skill4Dice1", "skill4Dice2", "skill4Dice3", "skill4Description", "skill4Effect", "skill4AutoScript", +"skill5Name", "skill5Rank", "skill5Type", "skill5Light", "skill5Dice1", "skill5Dice2", "skill5Dice3", "skill5Description", "skill5Effect", "skill5AutoScript", +"skill6Name", "skill6Rank", "skill6Type", "skill6Light", "skill6Dice1", "skill6Dice2", "skill6Dice3", "skill6Description", "skill6Effect", "skill6AutoScript", +"egoSkill1Name", "egoSkill1Rank", "egoSkill1Type", "egoSkill1Light", "egoSkill1Dice1", "egoSkill1Dice2", "egoSkill1Dice3", "egoSkill1Description", "egoSkill1Effect", "egoSkill1AutoScript", +"egoSkill2Name", "egoSkill2Rank", "egoSkill2Type", "egoSkill2Light", "egoSkill2Dice1", "egoSkill2Dice2", "egoSkill2Dice3", "egoSkill2Description", "egoSkill2Effect", "egoSkill2AutoScript", +"egoSkill3Name", "egoSkill3Rank", "egoSkill3Type", "egoSkill3Light", "egoSkill3Dice1", "egoSkill3Dice2", "egoSkill3Dice3", "egoSkill3Description", "egoSkill3Effect", "egoSkill3AutoScript", +"egoSkill4Name", "egoSkill4Rank", "egoSkill4Type", "egoSkill4Light", "egoSkill4Dice1", "egoSkill4Dice2", "egoSkill4Dice3", "egoSkill4Description", "egoSkill4Effect", "egoSkill4AutoScript", +"egoSkill5Name", "egoSkill5Rank", "egoSkill5Type", "egoSkill5Light", "egoSkill5Dice1", "egoSkill5Dice2", "egoSkill5Dice3", "egoSkill5Description", "egoSkill5Effect", "egoSkill5AutoScript", +"egoSkill6Name", "egoSkill6Rank", "egoSkill6Type", "egoSkill6Light", "egoSkill6Dice1", "egoSkill6Dice2", "egoSkill6Dice3", "egoSkill6Description", "egoSkill6Effect", "egoSkill6AutoScript"]; let attrkeyGlobal = ["global_ruleName", "global_healthBase", "global_healthStat", "global_healthStatMod", "global_healthRankMod", "global_staggerBase", "global_staggerStat", "global_staggerStatMod", "global_staggerRankMod", "global_sanityBase", "global_sanityStat", "global_sanityStatMod", "global_sanityRankMod", "global_lightBase", "global_lightRankMod", "global_distortLightBase", "global_distortLightRankMod", "global_attStat", "global_defStat", "global_evdStat", "global_evdAilment", "global_multiPenalty", "global_multiStyle", "global_staggerRecoverPercent", "global_staggerRecoverBase", "global_staggerSanity", "global_burnDecayMode", "global_burnDecayVal", "global_burnNextTurnSetting", "global_bleedDecayMode", "global_bleedDecayVal", "global_bleedNextTurnSetting", "global_smokeDecayMode", "global_smokeDecayVal", "global_smokeNextTurnSetting", "global_smokeCalculationMode", "global_smokeCalculationVal", "global_chargeDecayMode", "global_chargeDecayVal", "global_chargeNextTurnSetting", "settingLimbusStyle"]; From fa44f8144b1d15323f9962f4ef29637e5ca43b5b Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Wed, 31 Jul 2024 04:28:17 +0200 Subject: [PATCH 17/55] AutoEffect: part 11 AutoScript editor can now be resized --- ProjectMoonTRPG/ProjectMoonTRPGStyle.css | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css index 11148a5ebc..aa832459e3 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css +++ b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css @@ -2507,6 +2507,13 @@ justify-content: center; color: #999; pointer-events: none } +#autoScriptInput { + resize: vertical; + overflow: auto; + min-height:60px; + height: 120px; + max-height: 500px; +} /* AutoEffect conditional buttons */ From a8570632d18cad7c0b58329b74393b4f0e278fb2 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Thu, 1 Aug 2024 09:31:59 +0200 Subject: [PATCH 18/55] AutoEffects: part 12 - Added chat messages for all AutoEffects. The messages are either appended to another chat message or sent as its own message - Added CustomMessage AutoEffect which allows the user to configure their own AutoEffect messages with custom formats. Takes in values from the last executed AutoEffect. These values can be displayed using [NUM], [SCALING], [TARGET], etc. - Added Silent option to all AutoEffects which suppress the default chat message for the AutoEffect - Slimmed down weapon, outfit, tool and skill descriptions in chat messages. Empty descriptions are not displayed, and small descriptions occupy just the height needed to display its contents - Changed Consume to now update the effect value in ailmentList and barList, informing future Consume AutoEffects that less of their target is available - Tons of smaller AutoEffect bugfixes and improvements --- ProjectMoonTRPG/ProjectMoonTRPG.html | 519 +++++++++++++++++++---- ProjectMoonTRPG/ProjectMoonTRPGStyle.css | 38 ++ ProjectMoonTRPG/translation.json | 3 +- 3 files changed, 466 insertions(+), 94 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index b0a8ca2efc..380c2f6c97 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -108,7 +108,7 @@
- + @@ -10238,6 +10238,20 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects."> + +
+
+
+ {{icon}} +
+
{{#title}}{{title}}{{/title}}
+
+
For: {{#name}}{{name}}{{/name}}
+
{{#message}} {{message}} {{/message}}
+
+
+ +
@@ -10689,11 +10703,6 @@ on("change:StagRes", function() { setAttrs({"StaggerState":"Staggered"}); - /* AutoScripts */ - resetConditionals(); - AutoScriptMain("", "Staggered"); - - } /* Value check end */ }); @@ -10791,11 +10800,6 @@ on("change:SP", function() { if(currentsan <= 0 && panicstate == "0"){ setAttrs({"PanicState":"Panic"}); - - /* AutoScripts */ - resetConditionals(); - AutoScriptMain("", "Panic"); - } else if(currentsan > 0 && panicstate != "0"){ setAttrs({"PanicState":"0"}); @@ -10831,10 +10835,6 @@ on("change:HP", function() { setAttrs({"DefeatState":"Defeated"}); - /* AutoScripts */ - resetConditionals(); - AutoScriptMain("", "Defeated"); - } /* Defeat check end */ }); @@ -10960,6 +10960,14 @@ on("change:PanicState", function() { setAttrs({"dummyIcon":iconnew}); + /* AutoScripts */ + resetConditionals(); + let autoScriptTrigger = currentstate == "Panic" ? "Panic" : "None"; + AutoScriptMain("", autoScriptTrigger, "true", function(returnValues) { + + let autoScriptMessage = ""; + if (returnValues.message != undefined) { autoScriptMessage = returnValues.message } + /* Translation prep */ let langStateTrue = " went into Panic!"; let langStateFalse = " is no longer Panicked"; @@ -10971,19 +10979,20 @@ on("change:PanicState", function() { } if(messagestate != "true" && currentstate != "Panic"){ - startRoll((whisper + "&{template:message} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{message=" + langStateFalse + "}}"), (results) => { + startRoll((whisper + "&{template:message} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{message=" + langStateFalse + autoScriptMessage + "}}"), (results) => { finishRoll(results.rollId, {} ); }); } else if(messagestate != "true" && currentstate == "Panic"){ - startRoll((whisper + "&{template:message} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{message=" + langStateTrue + "}}"), (results) => { + startRoll((whisper + "&{template:message} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{message=" + langStateTrue + autoScriptMessage + "}}"), (results) => { finishRoll(results.rollId, {} ); }); } }); + }); }); /* Auto: Defeat State updates */ @@ -11008,6 +11017,13 @@ on("change:DefeatState", function() { setAttrs({"dummyIcon":iconnew}); + /* AutoScripts */ + resetConditionals(); + AutoScriptMain("", "Defeated", "true", function(returnValues) { + + let autoScriptMessage = ""; + if (returnValues.message != undefined) { autoScriptMessage = returnValues.message } + /* Whisper roll */ let whisperrolls = values.settingWhisperRolls; let whispertarget = values.settingWhisperTarget; @@ -11026,13 +11042,14 @@ on("change:DefeatState", function() { } if(messagestate != "true" && currentstate == "Defeated"){ - startRoll((whisper + "&{template:message} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{message=" + langDefeat + "}}"), (results) => { + startRoll((whisper + "&{template:message} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{message=" + langDefeat + autoScriptMessage + "}}"), (results) => { finishRoll(results.rollId, {} ); }); } }); + }); }); /* Auto: Stagger State updates */ @@ -11071,6 +11088,14 @@ getSectionIDs(`repeating_global`, idarray => { setAttrs({"dummyIcon":iconnew}); + /* AutoScripts */ + resetConditionals(); + let autoScriptTrigger = currentstate == "Staggered" ? "Staggered" : "None"; + AutoScriptMain("", autoScriptTrigger, "true", function(returnValues) { + + let autoScriptMessage = ""; + if (returnValues.message != undefined) { autoScriptMessage = returnValues.message } + /* Whisper roll */ let whisperrolls = values.settingWhisperRolls; let whispertarget = values.settingWhisperTarget; @@ -11090,19 +11115,20 @@ getSectionIDs(`repeating_global`, idarray => { } if(messagestate != "true" && currentstate != "Staggered"){ - startRoll((whisper + "&{template:message} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{message=" + langStateFalse + "}}"), (results) => { + startRoll((whisper + "&{template:message} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{message=" + langStateFalse + autoScriptMessage + "}}"), (results) => { finishRoll(results.rollId, {} ); }); } else if(messagestate != "true" && currentstate == "Staggered"){ - startRoll((whisper + "&{template:message} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{message=" + langStateTrue + "}}"), (results) => { + startRoll((whisper + "&{template:message} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{message=" + langStateTrue + autoScriptMessage + "}}"), (results) => { finishRoll(results.rollId, {} ); }); } - }); + }); + }); }); }); @@ -12402,14 +12428,17 @@ getSectionIDs(`repeating_global`, idarray => { AutoScript = AutoScript.replace("undefined", ""); resetConditionals(); - AutoScriptMain(AutoScript, triggerType, function(returnValues) { + AutoScriptMain(AutoScript, triggerType, "true", function(returnValues) { let autoeffectdice1 = 0; let autoeffectdice2 = 0; let autoeffectdice3 = 0; if (returnValues.diceCount != undefined) { autoeffectdice1 = returnValues.diceCount} - if (returnValues.dicePower != undefined) { autoeffectdice2 = returnValues.dicePower} - if (returnValues.diceMax != undefined) { autoeffectdice3 = returnValues.diceMax} + if (returnValues.diceMax != undefined) { autoeffectdice2 = returnValues.diceMax} + if (returnValues.dicePower != undefined) { autoeffectdice3 = returnValues.dicePower} + + let autoScriptMessage = ""; + if (returnValues.message != undefined) { autoScriptMessage = returnValues.message } /* Power */ let activepower = "0"; @@ -12575,11 +12604,16 @@ getSectionIDs(`repeating_global`, idarray => { distortformat = "
" + langDistortEffect + "
" + distorteffect + "
"; } + let baseEffectDescription = "
" + langEffectBase + ":
" + baseeffect + "
"; + let skillEffectDescription = "
" + langEffectSkill + ":
" + skilleffect + "
" + if (baseeffect == "") { baseEffectDescription = ""; skillEffectDescription = "
" + skillEffectDescription.replaceAll("style='width: 50%;", "style='width: 100%;") } + if (skilleffect == "(No Skill)") { skillEffectDescription = ""; baseEffectDescription = baseEffectDescription.replaceAll("style='width: 50%;", "style='width: 100%;") } + let header = "
" + basename + "
"; - let body = "" + langFrom + ": "+ charname + "
" + langRoll + ": " + rollformatmessage + skillinfo + "
" + attackmessage + "

" + langEffectBase + ":
" + baseeffect + "
" + langEffectSkill + ":
" + skilleffect + "
" + distortformat; + let body = "" + langFrom + ": "+ charname + "
" + langRoll + ": " + rollformatmessage + skillinfo + "
" + attackmessage + "
" + baseEffectDescription + skillEffectDescription + distortformat; - let info = header + body; + let info = header + body + autoScriptMessage; if(simpledisplay == "true"){ info = header; @@ -12674,7 +12708,7 @@ function rollChallenge(buttonid, rollDifficulty=0) { /* AutoScripts */ resetConditionals(); - AutoScriptMain("", ["Challenge", "Combat start"], function(returnValues) { + AutoScriptMain("", ["Challenge", "Combat start"], "true", function(returnValues) { let autoEffectDiceCount = 0; let autoEffectDiceMax = 0; @@ -12683,7 +12717,10 @@ function rollChallenge(buttonid, rollDifficulty=0) { if (returnValues.diceCount != undefined) { autoEffectDiceCount = returnValues.diceCount } if (returnValues.diceMax != undefined) { autoEffectDiceMax = returnValues.diceMax } if (returnValues.speedCombat != undefined) { autoEffectSpeedCombat = returnValues.speedCombat } - + + let autoScriptMessage = ""; + if (returnValues.message != undefined) { autoScriptMessage = returnValues.message } + let rollformat = Math.max(autoEffectDiceCount + 2, 0) + "d" + Math.max(autoEffectDiceMax + 6, 0) + "+" + parseInt(stat) + "+(" + parseInt(difficulty) + ")"; /* Type Formatting */ @@ -12775,7 +12812,7 @@ function rollChallenge(buttonid, rollDifficulty=0) { let body = "" + langFrom + ": " + charname + "
" + langRoll + ": " + rollformatmessage; - let info = header + body; + let info = header + body + autoScriptMessage; if(simpledisplay == "true"){ info = header; @@ -13130,9 +13167,17 @@ on('clicked:applyDamage', (info) => { setAttrs(output); /* AutoScripts */ - if (newHP < oldHP) { resetConditionals(); AutoScriptMain("", "DamagedHP"); } - if (newST < oldST) { resetConditionals(); AutoScriptMain("", "DamagedST"); } - if (newSP < oldSP) { resetConditionals(); AutoScriptMain("", "DamagedSP"); } + let autoScriptTriggers = ["None"]; + if (newHP < oldHP) { autoScriptTriggers.push("DamagedHP"); } + if (newST < oldST) { autoScriptTriggers.push("DamagedST"); } + if (newSP < oldSP) { autoScriptTriggers.push("DamagedSP"); } + + resetConditionals(); + AutoScriptMain("", autoScriptTriggers, "true", function(returnValues) { + + let autoScriptMessage = ""; + if (returnValues.message != undefined) { autoScriptMessage = returnValues.message } + /* console.log("HP base: " + sumBothBefore + ". HP after resistance: " + Math.ceil(Math.min((hpResistance * (sumBothBefore + sumHpBefore)) + hpProtection + damageResistance, 0))) console.log("ST base: " + sumBothBefore + ". ST after resistance: " + Math.ceil(Math.min((stResistance * (sumBothBefore + sumStBefore)) + stProtection + damageResistance, 0))) @@ -13237,6 +13282,7 @@ on('clicked:applyDamage', (info) => { damageCalculation += `
${hpDamageHead}${hpDamageBody}
`; damageCalculation += `
${stDamageHead}${stDamageBody}
`; damageCalculation += `
${spDamageHead}${spDamageBody}
`; + damageCalculation += autoScriptMessage; /* Damage type icon */ let damageIcon = ""; @@ -13270,6 +13316,7 @@ on('clicked:applyDamage', (info) => { }); }); }); +}); /* Damage helper functions beginning */ @@ -13556,14 +13603,20 @@ on('clicked:declareAction', (info) => { let lightmessage = ""; /* AutoScripts */ - let AutoScript = values[`${toolselect}AutoScript`]; + let AutoScript = ""; + if (toolselect != "0") { + AutoScript = values[`${toolselect}AutoScript`]; + + /* Clean AutoScript. Remove nested and undefined */ + AutoScript = AutoScript.replace(/\[([#][^]+[#])\]/g, ""); + AutoScript = AutoScript.replace("undefined", ""); + } - /* Clean AutoScript. Remove nested and undefined */ - AutoScript = AutoScript.replace(/\[([#][^]+[#])\]/g, ""); - AutoScript = AutoScript.replace("undefined", ""); - resetConditionals(); - AutoScriptMain(AutoScript, "None"); + AutoScriptMain(AutoScript, "None", "true", function(returnValues) { + + let autoScriptMessage = ""; + if (returnValues.message != undefined) { autoScriptMessage = returnValues.message } /* Translation prep */ let langFrom = "From"; @@ -13606,8 +13659,13 @@ on('clicked:declareAction', (info) => { } + let toolDescription = "
" + tooldesc + "
"; + let toolEffect = "
" + tooleffect + "
"; + if (tooldesc == "") { toolDescription = ""; } + if (tooleffect == "") { toolEffect = ""; toolDescription = toolDescription.replaceAll(" padding-bottom: 3px;","").replaceAll(" padding: 5px;"," padding-top: 5px;"); } + if(toolselect != "" && toolselect != null && toolselect != "0"){ - toolinfo = "" + langUse + ": " + toolname + toolusestext + "
" + tooldesc + "
" + tooleffect + "
"; + toolinfo = "" + langUse + ": " + toolname + toolusestext + "
" + toolDescription + toolEffect; } if(currentlight >= skillcost){ @@ -13629,7 +13687,7 @@ on('clicked:declareAction', (info) => { - let info = "
" + actiontext + lightmessage + "
" + langFrom + ": " + charname + "
" + toolinfo + skillinfo; + let info = "
" + actiontext + lightmessage + "
" + langFrom + ": " + charname + "
" + toolinfo + skillinfo + autoScriptMessage; setAttrs({"dummy":info}); @@ -13678,7 +13736,7 @@ on('clicked:declareAction', (info) => { }); }); - + }); }); /* Share: Outfit */ @@ -14679,14 +14737,17 @@ on("clicked:closeAutoScriptEdit", function(info) { on("clicked:repeating_conditionalButtons:activate", function(info) { let buttonid = info.sourceAttribute.split("_")[2]; let buttonAutoScript = ""; - let returnValues = {}; - getAttrs([`repeating_conditionalButtons_${buttonid}_buttonAutoScript`], function(values) { - buttonAutoScript = values[`repeating_conditionalButtons_${buttonid}_buttonAutoScript`] - AutoScriptMain(buttonAutoScript, "None", function(returnValues) { - if (returnValues.checkResult != "success") { - setAttrs({[`repeating_conditionalButtons_${buttonid}_hideButton`]: "true"}) - } - }, "false"); + let buttonName = ""; + + getAttrs([`repeating_conditionalButtons_${buttonid}_buttonAutoScript`, `repeating_conditionalButtons_${buttonid}_buttonName`], function(values) { + buttonAutoScript = values[`repeating_conditionalButtons_${buttonid}_buttonAutoScript`]; + buttonName = values[`repeating_conditionalButtons_${buttonid}_buttonName`]; + + AutoScriptMain(buttonAutoScript, "None", "false", function(returnValues) { + if (returnValues.checkResult != "success") { + setAttrs({[`repeating_conditionalButtons_${buttonid}_hideButton`]: "true"}) + } + }, "false", buttonName); }); }); @@ -14698,7 +14759,7 @@ Selects which type of AutoEffects to collect and append to an AutoScript. Block and Evade also include Defensive */ /* callback: Function to be run on returnValues. Defaults to an empty function */ /* collect: If the function should collect augment/outfit/etc. AutoEffects or not*/ -function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, collect="true") { +function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="false", callback=() => {}, collect="true", messageHeaderTitle="AutoEffects") { /* Adds the input AutoScript */ let AutoScript = ""; @@ -14707,27 +14768,27 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, } /* Appends one or more AutoScripts based on the trigger type */ - let autoScriptTypes = []; + let autoScriptTriggers = []; if (collect == "true") { - if (typeof triggerType == "string") { autoScriptTypes.push(triggerType) } - else {autoScriptTypes.push(...triggerType) } + if (typeof triggerType == "string") { autoScriptTriggers.push(triggerType) } + else {autoScriptTriggers.push(...triggerType) } if (triggerType != "None") { - if (autoScriptTypes.includes("Block") || autoScriptTypes.includes("Evade")) { - autoScriptTypes.push("Defensive"); + if (autoScriptTriggers.includes("Block") || autoScriptTriggers.includes("Evade")) { + autoScriptTriggers.push("Defensive"); } - else if (autoScriptTypes.includes("Combat start")) { - autoScriptTypes.push("Round start"); + else if (autoScriptTriggers.includes("Combat start")) { + autoScriptTriggers.push("Round start"); } - else if (autoScriptTypes.some(item => ["DamagedHP", "DamagedST", "DamagedSP"].includes(item))) { - autoScriptTypes.push("Damaged"); + else if (autoScriptTriggers.some(item => ["DamagedHP", "DamagedST", "DamagedSP"].includes(item))) { + autoScriptTriggers.push("Damaged"); } } - if (!autoScriptTypes.includes("Permanent")) { - autoScriptTypes.push("Permanent") + if (!autoScriptTriggers.includes("Permanent")) { + autoScriptTriggers.push("Permanent") } } - console.log(autoScriptTypes) + console.log(autoScriptTriggers) getAttrs(["augmentAutoScript", "outfitAutoScript", "egoAutoScript", "distortState", "egoActiveState"], function(values) { @@ -14746,12 +14807,12 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, if (egoAutoScript == null) { egoAutoScript = ""; } } - let TypedAutoScript = AutoScriptToArray(augmentAutoScript + outfitAutoScript + egoAutoScript, "nested"); + let collectedAutoScripts = AutoScriptToArray(augmentAutoScript + outfitAutoScript + egoAutoScript, "nested"); - TypedAutoScript.forEach((autoScriptType) => { - if (autoScriptTypes.includes(autoScriptType[0])) { + collectedAutoScripts.forEach((trigger) => { + if (autoScriptTriggers.includes(trigger[0])) { if (AutoScript != "") { AutoScript += "(Reset)"; } - AutoScript += autoScriptType[1]; + AutoScript += trigger[1]; } }); @@ -14795,6 +14856,8 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, let returnValues = { checkResult:"success", error:false, }; let conditionalList = {}; let challengeRollList = {}; + let message = ""; + let messageValues = {}; let ailmentList = {}; @@ -14809,17 +14872,17 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, let ailmentNames = ["Burn", "Bleed", "Paralysis", "Protection", "StaggerProtection", "Fragile", "Strength", "Feeble", "Endurance", "Disarm", "Haste", "Bind", "Smoke", "Charge", "Fortune"] ailmentNames.forEach(ailment => { if (["Burn", "Bleed", "Smoke", "Charge"].includes(ailment)) { - ailmentList[ailment] = [values[ailment.toLowerCase()+"NextTurnSetting"], values[ailment], values[`${ailment}NextTurn`]]; + ailmentList[ailment] = [values[ailment.toLowerCase()+"NextTurnSetting"], values[ailment], values[`${ailment}NextTurn`], 0, ailment]; } else { - ailmentList[ailment] = [HasNextTurn, values[ailment], values[`${ailment}NextTurn`]]; + ailmentList[ailment] = [HasNextTurn, values[ailment], values[`${ailment}NextTurn`], 0, ailment]; } }); /* Get all custom ailments */ getSectionIDs(`repeating_ailments`, idarray => { const fieldnames = idarray.reduce((rows,id) => - [...rows, `repeating_ailments_${id}_ailName`, `repeating_ailments_${id}_ailNextTurn`, - `repeating_ailments_${id}_ailNum`, `repeating_ailments_${id}_ailNumNextTurn`, ], ''); + [...rows, `repeating_ailments_${id}_ailName`, `repeating_ailments_${id}_ailNextTurn`,`repeating_ailments_${id}_ailNum`, + `repeating_ailments_${id}_ailNumNextTurn`, `repeating_ailments_${id}_ailIcon`], ''); let ailName = ""; let ailHasNextTurn = ""; @@ -14832,8 +14895,9 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, ailHasNextTurn = v[`repeating_ailments_${id}_ailNextTurn`]; ailNum = v[`repeating_ailments_${id}_ailNum`]; ailNumNextTurn = v[`repeating_ailments_${id}_ailNumNextTurn`] + ailIcon = v[`repeating_ailments_${id}_ailIcon`] - ailmentList[ailName] = [ailHasNextTurn, ailNum, ailNumNextTurn, id]; + ailmentList[ailName] = [ailHasNextTurn, ailNum, ailNumNextTurn, id, ailIcon]; }); @@ -14871,12 +14935,13 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, case "Require": tempOutput = autoEffectRequire(AutoEffect[0], ailmentList, barList, barDamageList); break; case "Consume": tempOutput = autoEffectConsume(AutoEffect[0], ailmentList, barList); break; case "Reset": tempOutput = {checkResult: "success", scaling: 1}; break; + case "CustomMessage": tempOutput = autoEffectCustomMessage(AutoEffect[0], messageValues); break; default: tempOutput = {}; break; } if (checkResult != "failure") { switch (AutoEffect[0][0]) { - case "Require": case "Consume": case "Reset": break; /* Already executed above */ - case "Gain": tempOutput = autoEffectGainAilment(AutoEffect[0], ailmentList, scaling); break; + case "Require": case "Consume": case "Reset": case "CustomMessage": break; /* Already executed above */ + case "Gain": tempOutput = autoEffectGainAilment(AutoEffect[0], ailmentList, scaling, settingLimbusStyle); break; case "DicePower": tempOutput = autoEffectDicePower(AutoEffect[0], scaling); break; case "Set": tempOutput = autoEffectSetBar(AutoEffect[0], barList, scaling); break; case "Add": tempOutput = autoEffectAddBar(AutoEffect[0], barList, scaling); break; @@ -14917,6 +14982,19 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, delete tempOutput.checkResult; } + /* Handle updating ailmentList and barList after a successful Consume AutoEffect */ + if (tempOutput.consumeList != undefined) { + if (tempOutput.consumeList == "barList") { + barList[tempOutput.consumeTarget] = parseInt(barList[tempOutput.consumeTarget]) + parseInt(tempOutput.consumeVal); + } else { + console.log(ailmentList[tempOutput.consumeTarget][1]) + ailmentList[tempOutput.consumeTarget][1] = parseInt(ailmentList[tempOutput.consumeTarget][1]) + parseInt(tempOutput.consumeVal); + } + delete tempOutput.consumeList; + delete tempOutput.consumeVal; + delete tempOutput.consumeVal; + } + /* Handle DicePower, DiceMax, DiceCount and Speed with Combat duration */ if (tempOutput.dicePower != undefined) { returnValues.dicePower = tempOutput.dicePower } if (tempOutput.diceMax != undefined) { returnValues.diceMax = tempOutput.diceMax } @@ -14927,6 +15005,16 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, if (tempOutput.challengeRollStat != undefined) { challengeRollList[tempOutput.challengeRollStat] = tempOutput.challengeRollDifficulty; } + + /* Handle message */ + if (tempOutput.message != undefined) { + message += tempOutput.message; + } + + /* Handle messageValues. Used by the CustomMessage AutoEffect. Outputted by all AutoEffects that generate messages */ + if (tempOutput.messageValues != undefined) { + messageValues = tempOutput.messageValues; + } /* Add attribute changes from AutoEffect to output */ /* The first time a attribute is modified, add its count */ @@ -14959,6 +15047,35 @@ function AutoScriptMain(inputAutoScript, triggerType="None", callback=() => {}, } /* Message handling */ + if (settingMuteMessage != "true" && message != "") { + let newmessage = "
" + + if (returnMessage == "false") { + let messageHeaderIcon = getIcon("icons", "gear"); + newmessage += message + "
"; + + setAttrs({dummyIcon: messageHeaderIcon, dummy: newmessage}); + + let whisper = ""; + if(settingWhisperRolls == "true"){ + whisper = "/w " + settingWhisperTarget; + } + + startRoll((whisper + "&{template:autoeffect} {{icon=@{dummyIcon}}} {{title=" + messageHeaderTitle + "}} {{name=@{character_name}}} {{message=@{dummy} }}"), (results) => { + finishRoll(results.rollId, {} ); + }); + } + else { + newmessage += `
` + newmessage += `
` + newmessage += `${getIcon("icons", "gear")}` + newmessage += `
` + newmessage += `
AutoEffects
` + newmessage += `
` + message + "
"; + + returnValues.message = newmessage; + } + } /* Error handling and returnValues callback */ if (returnValues.error == true) { @@ -15041,6 +15158,69 @@ function AutoScriptToArray(inputAutoScript, mode="normal") { /*--- AutoEffect functions ---*/ + +function autoEffectMessage(messageFormat, effectTarget="No target", effectVal=0, effectCount=0, scaling=1, checkResult="success", settingLimbusStyle="false") { + if(messageFormat != ""){ + let message = messageFormat; + + let langCheck = "[CHECK]"; + let langSuccess = "Success"; + let langFailure = "Failure"; + let langNum = "[NUM]"; + let langScaling = "[SCALING]"; + let langScalingNum = "[SCALING NUM]"; + let langInitial = "[INITIAL]"; + let langResult = "[RESULT]"; + let langTarget = "[TARGET]"; + let langTargetIcon = "[/TARGET]"; + + /*if(getTranslationByKey("message-match-check") != false){ + langCheck = getTranslationByKey("message-match-check"); + langSuccess = getTranslationByKey("distortion-result-good"); + langFailure = getTranslationByKey("distortion-result-bad"); + langNum = getTranslationByKey("message-match-num"); + langScaling = getTranslationByKey("message-match-scaling"); + langScalingNum = getTranslationByKey("message-match-scalingnum"); + langTarget = getTranslationByKey("message-match-target"); + langTargetIcon = getTranslationByKey("message-match-targeticon"); + }*/ + + if (checkResult == "failure") { message = message.replaceAll(langCheck, "" + langFailure + ""); } + else { message = message.replaceAll(langCheck, "" + langSuccess + ""); } + message = message.replaceAll(langNum, "" + effectVal + ""); + message = message.replaceAll(langScaling, "" + scaling + ""); + message = message.replaceAll(langScalingNum, "" + (parseFloat(scaling) * parseFloat(effectVal)) + ""); + message = message.replaceAll(langInitial, "" + parseFloat(effectCount) + ""); + message = message.replaceAll(langResult, "" + (parseFloat(effectCount) + parseFloat(effectVal)) + ""); + message = message.replaceAll(langTarget, "" + effectTarget.replace("limbus/","").replace("community/","") + ""); + + /* Icon handling */ + /* Get target icon. Is in this format: [/TARGET] */ + message = message.replaceAll(langTargetIcon, getIcon("ailments", effectTarget, settingLimbusStyle)); + + /* Question mark icon */ + message = message.replaceAll("[/Question]", getIcon("icons", "Question")); + + if ((/\[\/([^0-9]+)\]/g).test(message)) { + /* Get custom icon. Is in one of these formats: [/iconName], [/limbus/iconName], [/community/iconName]*/ + message = message.replaceAll("[/community/", "[community, "); + message = message.replaceAll("[/limbus/", "[ailments, limbus/"); + message = message.replaceAll("[/", "[ailments, "); + + message.match((/\[([^0-9]+)\]/g)).forEach(icon => { + let iconSelector = icon.replaceAll("[","").replaceAll("]",""); + let iconFolder = iconSelector.split(", ")[0]; + let iconName = iconSelector.split(", ")[1] + message = message.replace(icon, getIcon(iconFolder, iconName)); + }); + } + + newmessage = "
" + message + "
"; + + return newmessage; + } +} + /* Whispers an error message to the user detailing an AutoEffect error */ function autoEffectErrorMessage(errorString, autoEffect) { console.log(errorString + autoEffect) @@ -15066,7 +15246,7 @@ function resetConditionals() { function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { /* Check format */ - if (AutoEffect.length < 3 || AutoEffect.length > 4) { autoEffectErrorMessage(`Expected format: (Require N #Ailment/#Bar/#BarDamage #Scaling(optional))`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 3 || AutoEffect.length > 5) { autoEffectErrorMessage(`Expected format: (Require N #Ailment/#Bar/#BarDamage #Scaling(optional) #Silent(optional))`, AutoEffect); return {error: true}; } /* Get target count */ let effectName = AutoEffect[2]; @@ -15114,6 +15294,17 @@ function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { } else { returnValues.checkResult = "failure"; } + + /* Handle message */ + let messageFormat = "Require [SCALING NUM] [TARGET]: [CHECK]"; + if (ailmentList.hasOwnProperty(effectName)) { messageFormat = "[/TARGET] " + messageFormat; } + + if (!AutoEffect.includes("Silent")) { + returnValues.message = autoEffectMessage(messageFormat, effectName, effectVal/scaling, count, scaling, returnValues.checkResult); + } + returnValues.messageValues = { effectTarget: effectName, effectVal: effectVal/scaling, effectCount: count, scaling: scaling, checkResult: returnValues.checkResult } + + /* Return check result */ return returnValues; } @@ -15129,11 +15320,10 @@ function autoEffectConsume(AutoEffect, ailmentList, barList) { /* Get target */ let effectName = AutoEffect[2]; let effectTarget = ""; - let effectRepeatingId = ailmentList[effectName][3]; - + /* Handle ailment target */ if (ailmentList.hasOwnProperty(effectName)) { - if (effectRepeatingId == undefined) { effectTarget = effectName; } /* If standard ailment */ + if (ailmentList[effectName][3] == "0") { effectTarget = effectName; } /* If standard ailment */ else { effectTarget = `repeating_ailments_${ailmentList[effectName][3]}_ailNum`; } /* If custom ailment */ count = ailmentList[effectName][1]; } @@ -15163,15 +15353,30 @@ function autoEffectConsume(AutoEffect, ailmentList, barList) { } else { returnValues.checkResult = "success"; } + if (ailmentList.hasOwnProperty(effectName)) { returnValues.consumeList = "ailmentList"; } + else { returnValues.consumeList = "barList"; } + returnValues.consumeTarget = effectName; + returnValues.consumeVal = -effectVal*scaling; } else { returnValues.checkResult = "failure"; } + + /* Handle message */ + let messageFormat = "Consume [SCALING NUM] [TARGET]: [CHECK]"; + if (ailmentList.hasOwnProperty(effectName)) { messageFormat = "[/TARGET] " + messageFormat; } + + if (!(AutoEffect.includes("Silent"))) { + returnValues.message = autoEffectMessage(messageFormat, effectName, effectVal/scaling, count, scaling, returnValues.checkResult); + } + returnValues.messageValues = { effectTarget: effectName, effectVal: effectVal/scaling, effectCount: count, scaling: scaling, checkResult: returnValues.checkResult } + + /* Return check result */ return returnValues; } -function autoEffectGainAilment(AutoEffect, ailmentList, scaling) { +function autoEffectGainAilment(AutoEffect, ailmentList, scaling, settingLimbusStyle) { /* Check format */ - if (AutoEffect.length < 3 || AutoEffect.length > 5) { autoEffectErrorMessage(`Expected format: (Gain N #Ailment #Round(optional))`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 3 || AutoEffect.length > 6) { autoEffectErrorMessage(`Expected format: (Gain N #Ailment #Round(optional) #Silent(optional))`, AutoEffect); return {error: true}; } /* Handle scaling */ AutoEffect[1] *= scaling; @@ -15197,7 +15402,7 @@ function autoEffectGainAilment(AutoEffect, ailmentList, scaling) { let effectTarget = ""; let effectRepeatingId = ailmentList[effectAilment][3]; let effectHasNextTurn = ailmentList[effectAilment][0]; - if (effectRepeatingId == undefined) { effectTarget = effectAilment; } /* If standard ailment */ + if (effectRepeatingId == 0) { effectTarget = effectAilment; } /* If standard ailment */ else { effectTarget = `repeating_ailments_${ailmentList[effectAilment][3]}_ailNum`; } /* If custom ailment */ /* Effect changes target to the next turn field if it's enabled */ @@ -15206,9 +15411,21 @@ function autoEffectGainAilment(AutoEffect, ailmentList, scaling) { effectTarget += "NextTurn"; count = ailmentList[effectAilment][2]; } + + /* Handle message */ + let message = ""; + let messageValues = {}; + let messageFormat = "[/TARGET] Gained [SCALING NUM] [TARGET]"; + let effectIcon = ailmentList[effectAilment][4]; + if (effectHasNextTurn == 'true' && forceTarget != "This turn") { messageFormat += " next turn"; } + + if (!AutoEffect.includes("Silent")) { + message = autoEffectMessage(messageFormat, effectIcon, effectVal/scaling, count, scaling, "success", settingLimbusStyle); + } + messageValues = { effectTarget: effectIcon, effectVal: effectVal/scaling, effectCount: count, scaling: scaling, checkResult: "success", settingLimbusStyle: settingLimbusStyle } /* Execute AutoEffect */ - return { [effectTarget]: parseInt(effectVal), count: parseInt(count) } + return { [effectTarget]: parseInt(effectVal), count: parseInt(count), message: message, messageValues: messageValues } } function autoEffectSetBar(AutoEffect, barList, scaling) { @@ -15222,15 +15439,29 @@ function autoEffectSetBar(AutoEffect, barList, scaling) { /* Get value */ let effectVal = parseInt(Math.abs(AutoEffect[1])); if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + let count = 0; /* Get target */ let effectBar = AutoEffect[2]; let effectTarget = ""; - if (barList.hasOwnProperty(effectBar)) { effectTarget = effectBar.replace("ST", "StagRes"); } + if (barList.hasOwnProperty(effectBar)) { + effectTarget = effectBar.replace("ST", "StagRes"); + count = barList[effectBar]; + } else { autoEffectErrorMessage(`Bar "${effectBar}" does not exist`, AutoEffect); return {error: true}; } + + /* Handle message */ + let message = ""; + let messageValues = {}; + let messageFormat = "Set [TARGET] to [RESULT]"; + + if (!AutoEffect.includes("Silent")) { + message = autoEffectMessage(messageFormat, effectTarget, (parseInt(effectVal) - parseInt(count))/scaling, count, scaling, "success"); + } + messageValues = { effectTarget: effectTarget, effectVal: (parseInt(effectVal) - parseInt(count))/scaling, effectCount: count, scaling: scaling, checkResult: "success" } /* Execute AutoEffect */ - return {[effectTarget]: parseInt(effectVal), count: 0}; + return {[effectTarget]: parseInt(effectVal) - parseInt(count), count: count, message: message, messageValues: messageValues}; } function autoEffectAddBar(AutoEffect, barList, scaling) { /* Check format */ @@ -15253,9 +15484,20 @@ function autoEffectAddBar(AutoEffect, barList, scaling) { count = barList[effectBar]; } else { autoEffectErrorMessage(`Bar "${effectBar}" does not exist`, AutoEffect); return {error: true}; } + + /* Handle message */ + let message = ""; + let messageValues = {}; + let messageFormat = "Regened [SCALING NUM] [TARGET]"; + if (effectVal < 0) { messageFormat = "Recieved [SCALING NUM] [TARGET] damage"; } + + if (!AutoEffect.includes("Silent")) { + message = autoEffectMessage(messageFormat, effectTarget, effectVal/scaling, count, scaling, "success"); + } + messageValues = { effectTarget: effectTarget, effectVal: effectVal/scaling, effectCount: count, scaling: scaling, checkResult: "success" } /* Execute AutoEffect */ - return {[effectTarget]: parseInt(effectVal), count: parseInt(count)}; + return {[effectTarget]: parseInt(effectVal), count: parseInt(count), message: message, messageValues: messageValues}; } function autoEffectMultiBar(AutoEffect, barList, scaling) { /* Check format */ @@ -15277,9 +15519,19 @@ function autoEffectMultiBar(AutoEffect, barList, scaling) { count = barList[effectBar]; } else { autoEffectErrorMessage(`Bar "${effectBar}" does not exist`, AutoEffect); return {error: true}; } + + /* Handle message */ + let message = ""; + let messageValues = {}; + let messageFormat = `Multiplied [TARGET] by ${effectVal} [[SCALING NUM]]`; + + if (!AutoEffect.includes("Silent")) { + message = autoEffectMessage(messageFormat, effectTarget, Math.floor(parseFloat(effectVal) * parseInt(count) - parseInt(count))/scaling, count, scaling, "success"); + } + messageValues = { effectTarget: effectTarget, effectVal: Math.floor(parseFloat(effectVal) * parseInt(count) - parseInt(count))/scaling, effectCount: count, scaling: scaling, checkResult: "success" } /* Execute AutoEffect */ - return {[effectTarget]: parseFloat(effectVal) * parseInt(count), count: 0 }; + return {[effectTarget]: Math.floor(parseFloat(effectVal) * parseInt(count) - parseInt(count)), count: count, message: message, messageValues: messageValues }; } function autoEffectDicePower(AutoEffect, scaling) { @@ -15293,9 +15545,20 @@ function autoEffectDicePower(AutoEffect, scaling) { /* Get values */ let effectVal = parseInt(AutoEffect[1]); if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + + /* Handle message */ + let message = ""; + let messageValues = {}; + let messageFormat = "Increased [TARGET] by [SCALING NUM]"; + if (effectVal < 0) { messageFormat = "Reduced [TARGET] by [SCALING NUM]"; } + + if (!AutoEffect.includes("Silent")) { + message = autoEffectMessage(messageFormat, "Dice Power", effectVal/scaling, 0, scaling, "success"); + } + messageValues = { effectTarget: "Dice Power", effectVal: effectVal/scaling, effectCount: 0, scaling: scaling, checkResult: "success" } /* Execute AutoEffect */ - return { dicePower: parseInt(effectVal) } + return { dicePower: parseInt(effectVal), message: message, messageValues: messageValues } } function autoEffectDiceMax(AutoEffect, scaling) { /* Check format */ @@ -15308,9 +15571,20 @@ function autoEffectDiceMax(AutoEffect, scaling) { /* Get values */ let effectVal = parseInt(AutoEffect[1]); if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + + /* Handle message */ + let message = ""; + let messageValues = {}; + let messageFormat = "Increased [TARGET] by [SCALING NUM]"; + if (effectVal < 0) { messageFormat = "Reduced [TARGET] by [SCALING NUM]"; } + + if (!AutoEffect.includes("Silent")) { + message = autoEffectMessage(messageFormat, "Dice Max", effectVal/scaling, 0, scaling, "success"); + } + messageValues = { effectTarget: "Dice Max", effectVal: effectVal/scaling, effectCount: 0, scaling: scaling, checkResult: "success" } /* Execute AutoEffect */ - return { diceMax: parseInt(effectVal) } + return { diceMax: parseInt(effectVal), message: message, messageValues: messageValues } } function autoEffectDiceCount(AutoEffect, scaling) { /* Check format */ @@ -15323,9 +15597,20 @@ function autoEffectDiceCount(AutoEffect, scaling) { /* Get values */ let effectVal = parseInt(AutoEffect[1]); if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + + /* Handle message */ + let message = ""; + let messageValues = {}; + let messageFormat = "Increased [TARGET] by [SCALING NUM]"; + if (effectVal < 0) { messageFormat = "Reduced [TARGET] by [SCALING NUM]"; } + + if (!AutoEffect.includes("Silent")) { + message = autoEffectMessage(messageFormat, "Dice Count", effectVal/scaling, 0, scaling, "success"); + } + messageValues = { effectTarget: "Dice Count", effectVal: effectVal/scaling, effectCount: 0, scaling: scaling, checkResult: "success" } /* Execute AutoEffect */ - return { diceCount: parseInt(effectVal) } + return { diceCount: parseInt(effectVal), message: message, messageValues: messageValues } } function autoEffectChallengeRoll(AutoEffect, scaling) { @@ -15348,7 +15633,7 @@ function autoEffectChallengeRoll(AutoEffect, scaling) { else { autoEffectErrorMessage(`Stat "${AutoEffect[1]}" does not exist.`, AutoEffect); return {error: true}; } /* Execute AutoEffect */ - return { challengeRollStat: statTarget, challengeRollDifficulty: effectVal } + return { challengeRollStat: statTarget, challengeRollDifficulty: effectVal, message: message, messageValues: messageValues } } function autoEffectSpeed(AutoEffect, scaling, prevThisRoundSpeed, prevNextRoundSpeed) { @@ -15370,13 +15655,63 @@ function autoEffectSpeed(AutoEffect, scaling, prevThisRoundSpeed, prevNextRoundS else if (["next", "nextround", "next round, nextturn, next turn"].includes(AutoEffect[2].toLowerCase())) { effectDuration = "NextRound"; } else { autoEffectErrorMessage(`Duration "${AutoEffect[2]}" does not exist. Expected "Combat", "This round" or "Next round"`, AutoEffect); return {error: true}; } + /* Handle message */ + let message = ""; + let messageValues = {}; + let messageFormat = "Increased [TARGET] by [SCALING NUM]"; + if (effectVal < 0) { messageFormat = "Reduced [TARGET] by [SCALING NUM]"; } + switch (effectDuration) { + case "Combat": messageFormat += " this combat"; break; + case "ThisRound": messageFormat += " this round"; break; + case "NextRound": messageFormat += " next round"; break; + } + + if (!AutoEffect.includes("Silent")) { + message = autoEffectMessage(messageFormat, "Speed", effectVal/scaling, 0, scaling, "success"); + } + messageValues = { effectTarget: "Speed", effectVal: effectVal/scaling, effectCount: 0, scaling: scaling, checkResult: "success" } + /* Execute AutoEffect */ switch (effectDuration) { - case "Combat": return { speedCombat: parseInt(effectVal) }; break; - case "ThisRound": return { thisRoundSpeed: parseInt(effectVal), count: parseInt(prevThisRoundSpeed)}; break; - case "NextRound": return { nextRoundSpeed: parseInt(effectVal), count: parseInt(prevNextRoundSpeed)}; break; + case "Combat": return { speedCombat: parseInt(effectVal), message: message, messageValues: messageValues }; break; + case "ThisRound": return { thisRoundSpeed: parseInt(effectVal), count: parseInt(prevThisRoundSpeed), message: message, messageValues: messageValues }; break; + case "NextRound": return { nextRoundSpeed: parseInt(effectVal), count: parseInt(prevNextRoundSpeed), message: message, messageValues: messageValues }; break; } } + +function autoEffectCustomMessage(AutoEffect, messageValues = {}) { + console.log(messageValues) + + let messageFormat = ""; + let checkResultOption = "success"; + let effectTarget = "No target"; + let effectVal = 0; + let effectCount = 0; + let scaling = 1; + let checkResult = "success"; + let settingLimbusStyle = "false"; + + if (AutoEffect[1] != undefined) { messageFormat = AutoEffect.slice(1).join(" "); } + if ((/\"[ \t]*(checksuccess)/ig).test(messageFormat)) { messageFormat = messageFormat.replaceAll(/\"[ \t]*(checksuccess)/ig, "") } + else if ((/\"[ \t]*(checkfailure)/ig).test(messageFormat)) { checkResultOption = "failure"; messageFormat = messageFormat.replaceAll(/\"[ \t]*(checkfailure)/ig, "") } + else if ((/\"[ \t]*(checkignore)/ig).test(messageFormat)) { checkResultOption = "ignore"; messageFormat = messageFormat.replaceAll(/\"[ \t]*(checkignore)/ig, "")} + messageFormat = messageFormat.replaceAll('"',''); + + if (messageValues.effectTarget != undefined) { effectTarget = messageValues.effectTarget; } + if (messageValues.effectVal != undefined) { effectVal = messageValues.effectVal; } + if (messageValues.effectCount != undefined) { effectCount = messageValues.effectCount; } + if (messageValues.scaling != undefined) { scaling = messageValues.scaling; } + if (messageValues.checkResult != undefined) { checkResult = messageValues.checkResult; } + if (messageValues.settingLimbusStyle != undefined) { settingLimbusStyle = messageValues.settingLimbusStyle; } + + if (checkResult == checkResultOption || checkResultOption == "ignore") { + return { message: autoEffectMessage(messageFormat, effectTarget, effectVal, effectCount, scaling, checkResult, settingLimbusStyle) } + } else { + return {} + } +} + + /*--- AutoEffect functions end ---*/ diff --git a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css index aa832459e3..b9c7deaa4a 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css +++ b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css @@ -2386,6 +2386,8 @@ height: 35px;} color: #fff !important; background-color: rgba(0,0,0,0.5) !important; } + +/* Damage helper message styling*/ .sheet-rolltemplate-damagecalculation img { height: 25px; width: 25px; @@ -2437,6 +2439,42 @@ height: 35px;} .sheet-rolltemplate-damagecalculation .userscript-stCalculationContainer div:first-child { color: #f1c232; background-color: #111; } .sheet-rolltemplate-damagecalculation .userscript-spCalculationContainer div:first-child { color: #6d9eeb; background-color: #111; } +/* AutoEffect message styling */ +/* Yes, you have to write them all out like this... */ +.sheet-rolltemplate-damagecalculation .userscript-autoeffectContainer img, +.sheet-rolltemplate-autoeffect .userscript-autoeffectContainer img, +.sheet-rolltemplate-message .userscript-autoeffectContainer img, +.sheet-rolltemplate-baseRoll .userscript-autoeffectContainer img { + height: 25px; + width: 25px; +} +.sheet-rolltemplate-damagecalculation .userscript-autoeffectContainer, +.sheet-rolltemplate-autoeffect .userscript-autoeffectContainer, +.sheet-rolltemplate-message .userscript-autoeffectContainer, +.sheet-rolltemplate-baseRoll .userscript-autoeffectContainer { + margin-top: 10px; + border-radius: 5px; + border: 1px solid #555; + position: relative; +} +.sheet-rolltemplate-baseRoll .userscript-autoeffectContainer { + float: left; + width: 99.3%; + margin-top: 10px; +} +.sheet-rolltemplate-damagecalculation .userscript-autoeffectContainer > .userscript-autoeffectEntry, +.sheet-rolltemplate-autoeffect .userscript-autoeffectContainer > .userscript-autoeffectEntry, +.sheet-rolltemplate-message .userscript-autoeffectContainer > .userscript-autoeffectEntry, +.sheet-rolltemplate-baseRoll .userscript-autoeffectContainer > .userscript-autoeffectEntry { + line-height: 25px; + border-bottom: 1px solid #555; +} +.sheet-rolltemplate-damagecalculation .userscript-autoeffectEntry:not(:has(img:first-child)), +.sheet-rolltemplate-autoeffect .userscript-autoeffectEntry:not(:has(img:first-child)), +.sheet-rolltemplate-message .userscript-autoeffectEntryn:not(:has(img:first-child)), +.sheet-rolltemplate-baseRoll .userscript-autoeffectEntry:not(:has(img:first-child)){ + padding-left: 8px; +} /* Alright here's the actual sheet tab switching functionality */ diff --git a/ProjectMoonTRPG/translation.json b/ProjectMoonTRPG/translation.json index 8a5896118f..fdf6a81500 100644 --- a/ProjectMoonTRPG/translation.json +++ b/ProjectMoonTRPG/translation.json @@ -245,7 +245,7 @@ "import-type-add":"Add", "autoscript-edit":"Edit AutoScript", "autoscript-editor":"AutoScript Editor", - "autoscript-close-editor":"Close AutoScript Editor", + "autoscript-close-editor":"Save and close AutoScript Editor", "autoscript-save-changes":"Save AutoScript changes", "equip-weapon1-name":"Weapon Name (1)", "equip-weapon2-name":"Weapon Name (2)", @@ -378,7 +378,6 @@ "message-type":"Type", "message-mod":"Mod", "message-cost":"Cost", - "message-noskill":"(No Skill)", "message-failure":"Failure...", "message-normal":"Partial Success", "message-success":"Success!", From 15e6d22289f5ebbcad7120609cd5dd290f8c8e13 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Thu, 1 Aug 2024 10:11:07 +0200 Subject: [PATCH 19/55] Bugfix: Attack/Defend skill description not displaying correctly --- ProjectMoonTRPG/ProjectMoonTRPG.html | 11 ++++------- ProjectMoonTRPG/translation.json | 1 + 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 380c2f6c97..7352c70ed4 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -13660,7 +13660,7 @@ on('clicked:declareAction', (info) => { } let toolDescription = "
" + tooldesc + "
"; - let toolEffect = "
" + tooleffect + "
"; + let toolEffect = "
" + tooleffect + "
"; if (tooldesc == "") { toolDescription = ""; } if (tooleffect == "") { toolEffect = ""; toolDescription = toolDescription.replaceAll(" padding-bottom: 3px;","").replaceAll(" padding: 5px;"," padding-top: 5px;"); } @@ -14787,8 +14787,6 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals autoScriptTriggers.push("Permanent") } } - - console.log(autoScriptTriggers) getAttrs(["augmentAutoScript", "outfitAutoScript", "egoAutoScript", "distortState", "egoActiveState"], function(values) { @@ -14987,7 +14985,6 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals if (tempOutput.consumeList == "barList") { barList[tempOutput.consumeTarget] = parseInt(barList[tempOutput.consumeTarget]) + parseInt(tempOutput.consumeVal); } else { - console.log(ailmentList[tempOutput.consumeTarget][1]) ailmentList[tempOutput.consumeTarget][1] = parseInt(ailmentList[tempOutput.consumeTarget][1]) + parseInt(tempOutput.consumeVal); } delete tempOutput.consumeList; @@ -15083,7 +15080,6 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals callback({error: true}); } - console.log(returnValues); callback(returnValues); }); }); @@ -15680,8 +15676,9 @@ function autoEffectSpeed(AutoEffect, scaling, prevThisRoundSpeed, prevNextRoundS } function autoEffectCustomMessage(AutoEffect, messageValues = {}) { + console.log(messageValues) - + let messageFormat = ""; let checkResultOption = "success"; let effectTarget = "No target"; @@ -15701,7 +15698,7 @@ function autoEffectCustomMessage(AutoEffect, messageValues = {}) { if (messageValues.effectVal != undefined) { effectVal = messageValues.effectVal; } if (messageValues.effectCount != undefined) { effectCount = messageValues.effectCount; } if (messageValues.scaling != undefined) { scaling = messageValues.scaling; } - if (messageValues.checkResult != undefined) { checkResult = messageValues.checkResult; } + if (messageValues.checkResult != undefined) { checkResult = messageValues.checkResult.replace("last ","");} if (messageValues.settingLimbusStyle != undefined) { settingLimbusStyle = messageValues.settingLimbusStyle; } if (checkResult == checkResultOption || checkResultOption == "ignore") { diff --git a/ProjectMoonTRPG/translation.json b/ProjectMoonTRPG/translation.json index fdf6a81500..613737df54 100644 --- a/ProjectMoonTRPG/translation.json +++ b/ProjectMoonTRPG/translation.json @@ -378,6 +378,7 @@ "message-type":"Type", "message-mod":"Mod", "message-cost":"Cost", + "message-noskill":"(No Skill)", "message-failure":"Failure...", "message-normal":"Partial Success", "message-success":"Success!", From 2b42ded882df24218058a4619beb823c05de0907 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Thu, 1 Aug 2024 10:29:19 +0200 Subject: [PATCH 20/55] Bugfix: Conditional buttons were displaying improperly when failing a check --- ProjectMoonTRPG/ProjectMoonTRPG.html | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 7352c70ed4..a44c72a02a 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -2733,8 +2733,7 @@
- -
+
@@ -14745,7 +14744,7 @@ on("clicked:repeating_conditionalButtons:activate", function(info) { AutoScriptMain(buttonAutoScript, "None", "false", function(returnValues) { if (returnValues.checkResult != "success") { - setAttrs({[`repeating_conditionalButtons_${buttonid}_hideButton`]: "true"}) + removeRepeatingRow("repeating_conditionalButtons_" + buttonid) } }, "false", buttonName); }); @@ -15189,7 +15188,7 @@ function autoEffectMessage(messageFormat, effectTarget="No target", effectVal=0, message = message.replaceAll(langInitial, "" + parseFloat(effectCount) + ""); message = message.replaceAll(langResult, "" + (parseFloat(effectCount) + parseFloat(effectVal)) + ""); message = message.replaceAll(langTarget, "" + effectTarget.replace("limbus/","").replace("community/","") + ""); - + /* Icon handling */ /* Get target icon. Is in this format: [/TARGET] */ message = message.replaceAll(langTargetIcon, getIcon("ailments", effectTarget, settingLimbusStyle)); @@ -15293,12 +15292,13 @@ function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { /* Handle message */ let messageFormat = "Require [SCALING NUM] [TARGET]: [CHECK]"; + let effectIcon = ailmentList[effectName][4]; if (ailmentList.hasOwnProperty(effectName)) { messageFormat = "[/TARGET] " + messageFormat; } if (!AutoEffect.includes("Silent")) { returnValues.message = autoEffectMessage(messageFormat, effectName, effectVal/scaling, count, scaling, returnValues.checkResult); } - returnValues.messageValues = { effectTarget: effectName, effectVal: effectVal/scaling, effectCount: count, scaling: scaling, checkResult: returnValues.checkResult } + returnValues.messageValues = { effectTarget: effectIcon, effectVal: effectVal/scaling, effectCount: count, scaling: scaling, checkResult: returnValues.checkResult } /* Return check result */ return returnValues; @@ -15359,12 +15359,13 @@ function autoEffectConsume(AutoEffect, ailmentList, barList) { /* Handle message */ let messageFormat = "Consume [SCALING NUM] [TARGET]: [CHECK]"; + let effectIcon = ailmentList[effectName][4]; if (ailmentList.hasOwnProperty(effectName)) { messageFormat = "[/TARGET] " + messageFormat; } if (!(AutoEffect.includes("Silent"))) { returnValues.message = autoEffectMessage(messageFormat, effectName, effectVal/scaling, count, scaling, returnValues.checkResult); } - returnValues.messageValues = { effectTarget: effectName, effectVal: effectVal/scaling, effectCount: count, scaling: scaling, checkResult: returnValues.checkResult } + returnValues.messageValues = { effectTarget: effectIcon, effectVal: effectVal/scaling, effectCount: count, scaling: scaling, checkResult: returnValues.checkResult } /* Return check result */ return returnValues; From 0b01455a251bc8c70841a963dfa910a034ec3952 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Thu, 1 Aug 2024 10:34:45 +0200 Subject: [PATCH 21/55] AutoEffects: part 12.5 - Added new AutoEffect message options [-NUM], [-SCALING] and [-SCALING NUM], which resolve to the negative of the values --- ProjectMoonTRPG/ProjectMoonTRPG.html | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index a44c72a02a..da0699b8ff 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -15164,6 +15164,9 @@ function autoEffectMessage(messageFormat, effectTarget="No target", effectVal=0, let langNum = "[NUM]"; let langScaling = "[SCALING]"; let langScalingNum = "[SCALING NUM]"; + let langNegNum = "[-NUM]"; + let langNegScaling = "[-SCALING]"; + let langNegScalingNum = "[-SCALING NUM]"; let langInitial = "[INITIAL]"; let langResult = "[RESULT]"; let langTarget = "[TARGET]"; @@ -15185,6 +15188,9 @@ function autoEffectMessage(messageFormat, effectTarget="No target", effectVal=0, message = message.replaceAll(langNum, "" + effectVal + ""); message = message.replaceAll(langScaling, "" + scaling + ""); message = message.replaceAll(langScalingNum, "" + (parseFloat(scaling) * parseFloat(effectVal)) + ""); + message = message.replaceAll(langNegNum, "" + (-effectVal) + ""); + message = message.replaceAll(langNegScaling, "" + (-scaling) + ""); + message = message.replaceAll(langNegScalingNum, "" + (-parseFloat(scaling) * parseFloat(effectVal)) + ""); message = message.replaceAll(langInitial, "" + parseFloat(effectCount) + ""); message = message.replaceAll(langResult, "" + (parseFloat(effectCount) + parseFloat(effectVal)) + ""); message = message.replaceAll(langTarget, "" + effectTarget.replace("limbus/","").replace("community/","") + ""); @@ -15469,7 +15475,7 @@ function autoEffectAddBar(AutoEffect, barList, scaling) { if (scaling == 0) { return {}; } /* Get value */ - let effectVal = parseInt(Math.abs(AutoEffect[1])); + let effectVal = parseInt(AutoEffect[1]); if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } let count = 0; @@ -15486,7 +15492,7 @@ function autoEffectAddBar(AutoEffect, barList, scaling) { let message = ""; let messageValues = {}; let messageFormat = "Regened [SCALING NUM] [TARGET]"; - if (effectVal < 0) { messageFormat = "Recieved [SCALING NUM] [TARGET] damage"; } + if (effectVal < 0) { messageFormat = "Recieved [-SCALING NUM] [TARGET] damage"; } if (!AutoEffect.includes("Silent")) { message = autoEffectMessage(messageFormat, effectTarget, effectVal/scaling, count, scaling, "success"); From 05e52e702762d497442dbdcd0c1eb3e96c81fc62 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Thu, 1 Aug 2024 10:42:17 +0200 Subject: [PATCH 22/55] Bugfix: Require using ailment icons for bars --- ProjectMoonTRPG/ProjectMoonTRPG.html | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index da0699b8ff..612bce4b7b 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -15298,8 +15298,11 @@ function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { /* Handle message */ let messageFormat = "Require [SCALING NUM] [TARGET]: [CHECK]"; - let effectIcon = ailmentList[effectName][4]; - if (ailmentList.hasOwnProperty(effectName)) { messageFormat = "[/TARGET] " + messageFormat; } + let effectIcon = effectName; + if (ailmentList.hasOwnProperty(effectName)) { + messageFormat = "[/TARGET] " + messageFormat; + effectIcon = ailmentList[effectName][4]; + } if (!AutoEffect.includes("Silent")) { returnValues.message = autoEffectMessage(messageFormat, effectName, effectVal/scaling, count, scaling, returnValues.checkResult); From 3a0bb1b7249757a10423972fba284e0d0a5fcc27 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Thu, 1 Aug 2024 11:12:49 +0200 Subject: [PATCH 23/55] Bugfix: Checks message displaying NaN when scaling is 0 --- ProjectMoonTRPG/ProjectMoonTRPG.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 612bce4b7b..e5a3c07c03 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -15305,9 +15305,9 @@ function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { } if (!AutoEffect.includes("Silent")) { - returnValues.message = autoEffectMessage(messageFormat, effectName, effectVal/scaling, count, scaling, returnValues.checkResult); + returnValues.message = autoEffectMessage(messageFormat, effectName, effectVal, count, Math.max(scaling,1), returnValues.checkResult); } - returnValues.messageValues = { effectTarget: effectIcon, effectVal: effectVal/scaling, effectCount: count, scaling: scaling, checkResult: returnValues.checkResult } + returnValues.messageValues = { effectTarget: effectIcon, effectVal: effectVal, effectCount: count, scaling: Math.max(scaling,1), checkResult: returnValues.checkResult } /* Return check result */ return returnValues; @@ -15372,9 +15372,9 @@ function autoEffectConsume(AutoEffect, ailmentList, barList) { if (ailmentList.hasOwnProperty(effectName)) { messageFormat = "[/TARGET] " + messageFormat; } if (!(AutoEffect.includes("Silent"))) { - returnValues.message = autoEffectMessage(messageFormat, effectName, effectVal/scaling, count, scaling, returnValues.checkResult); + returnValues.message = autoEffectMessage(messageFormat, effectName, effectVal, count, Math.max(scaling,1), returnValues.checkResult); } - returnValues.messageValues = { effectTarget: effectIcon, effectVal: effectVal/scaling, effectCount: count, scaling: scaling, checkResult: returnValues.checkResult } + returnValues.messageValues = { effectTarget: effectIcon, effectVal: effectVal, effectCount: count, scaling: Math.max(scaling,1), checkResult: returnValues.checkResult } /* Return check result */ return returnValues; From 291885fe6b43d92bf42ea225c80c29567cebecde Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Thu, 1 Aug 2024 12:21:52 +0200 Subject: [PATCH 24/55] AutoEffects: part 13 - Added support for applied tools. Tools can now be applied to attack and defence, adding their AutoEffects in the same way as a skill - Fixed skill AutoEffects being able to be applied to actions not matching the skill --- ProjectMoonTRPG/ProjectMoonTRPG.html | 71 +++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 6 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index e5a3c07c03..42650c21a2 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -12236,17 +12236,21 @@ on('clicked:rollCombat', (info) => { getSectionIDs(`repeating_global`, idarray => { let id = `repeating_global_${idarray[0]}`; - /* Get skillSelect first as it's used to gather further values */ - getAttrs(["skillSelect"], function(values) { + /* Get skillSelect and toolSelect first as they're used to gather further values */ + getAttrs(["skillSelect", "toolselect"], function(values) { let skillselect = values.skillSelect; + let toolselect = values.toolselect; getAttrs(["egoActiveState", "settingSimpleDisplay", "settingWhisperRolls", "settingWhisperTarget", "settingMultihitFull", `${id}_multiPenalty`, `${id}_multiStyle`, "character_name", "advState", "difficulty", "baseActNum", "Light", "difficulty", "Endurance", "Disarm", "Strength", "Feeble", "evdPositive", "evdNegative", "advNum", "disadvNum", "attPower", "defPower", "evdPower", "selectName", "selectLight", "selectType", "selectDice1", "selectDice2", "selectDice3", "selectEffect", "distortWeaponDice1", "distortWeaponDice2", "distortWeaponDice3", "distortDefDice1", "distortDefDice2", "distortDefDice3", "distortEvdDice1", "distortEvdDice2", "distortEvdDice3", "distortEffect", "distortEffect2", "settingMultihitUses", "settingHideUses", `${name}`, `${type}`, `${range}`, `${effect}`, `${diceA}`, `${diceB}`, `${diceC}`, `${uses}`, `${usesmax}`, `${usetype}`, - `${buttonid}AutoScript`, "outfitAutoScript", "egoAutoScript", `${skillselect}AutoScript`], function(values) { + `${buttonid}AutoScript`, "outfitAutoScript", "egoAutoScript", + `${skillselect}AutoScript`, `${toolselect}Name`, `${toolselect}Description`, `${toolselect}Effect`, `${toolselect}Uses`, `${toolselect}Uses_max`, `${toolselect}Reusable`, `${toolselect}AutoScript`], function(values) { + let output = {} + let currentlight = parseInt(values.Light); let newlight = parseInt(values.Light); let charname = values.character_name; @@ -12354,6 +12358,42 @@ getSectionIDs(`repeating_global`, idarray => { } + /* Tool */ + let toolDescription = ""; + let toolEffect = ""; + let toolinfo = ""; + let toolname = ""; + let tooldesc = ""; + let tooleffect = ""; + + let langUse = "Use Tool"; + let langEffectTool = "Tool Effects"; + + if (toolselect != "" && toolselect != null && toolselect != "0") { + toolname = values[`${toolselect}Name`]; + tooldesc = values[`${toolselect}Description`]; + tooleffect = values[`${toolselect}Effect`]; + let tooluses = values[`${toolselect}Uses`]; + let toolusesmax = values[`${toolselect}Uses_max`]; + let toolreuse = values[`${toolselect}Reusable`]; + let toolnewuses = tooluses; + + if (getTranslationByKey("palette-action-tool") != false) { + langUse = getTranslationByKey("palette-action-tool"); + langEffectTool = getTranslationByKey("tool-effect").replace(".",""); + } + + if(toolreuse == "Reusable"){ + toolnewuses = parseInt(tooluses) - 1; + if(parseInt(newuses) < 0){ + toolnewuses = "0"; + } + output[`${toolselect}Uses`] = toolnewuses; + } + else { + output[`${toolselect}Uses`] = "0"; + } + } /* Skill */ let skillname = values.selectName; @@ -12392,7 +12432,7 @@ getSectionIDs(`repeating_global`, idarray => { newlight = currentlight - skillcost; lightmessage = " (" + langSkill + ")"; - skillinfo= "
" + langSkill + ": " + skillname + "
"; + skillinfo= "
" + langSkill + ": " + skillname; skilleffect = values.selectEffect; @@ -12417,9 +12457,14 @@ getSectionIDs(`repeating_global`, idarray => { case "Evade": triggerType = "Evade"; break; } + /* Get tool AutoAcript if any */ + if (toolselect != "0") { + AutoScript += "(Reset)" + values[`${toolselect}AutoScript`]; + } + /* Get skill AutoAcript if any */ - if (skillselect != undefined || skillselect != "0") { - AutoScript += values[`${skillselect}AutoScript`]; + if ((skillselect != undefined || skillselect != "0") && basetype == skilltype) { + AutoScript += "(Reset)" + values[`${skillselect}AutoScript`]; } /* Clean AutoScript. Remove nested and undefined */ @@ -12608,6 +12653,19 @@ getSectionIDs(`repeating_global`, idarray => { if (baseeffect == "") { baseEffectDescription = ""; skillEffectDescription = "
" + skillEffectDescription.replaceAll("style='width: 50%;", "style='width: 100%;") } if (skilleffect == "(No Skill)") { skillEffectDescription = ""; baseEffectDescription = baseEffectDescription.replaceAll("style='width: 50%;", "style='width: 100%;") } + if(toolselect != "" && toolselect != null && toolselect != "0"){ + toolDescription = "
" + tooldesc + "
"; + toolEffect = "
" + langEffectTool + ":
" + tooleffect + "
"; + if (tooldesc == "") { toolDescription = ""; } + if (tooleffect == "") { toolEffect = ""; toolDescription = toolDescription.replaceAll(" padding-bottom: 3px;","").replaceAll(" padding: 5px;"," padding-top: 5px;"); } + + toolinfo = "
" + langUse + ": " + toolname + "
"; + + baseEffectDescription += toolDescription; + skillEffectDescription += toolEffect; + skillinfo += toolinfo; + } + let header = "
" + basename + "
"; let body = "" + langFrom + ": "+ charname + "
" + langRoll + ": " + rollformatmessage + skillinfo + "
" + attackmessage + "
" + baseEffectDescription + skillEffectDescription + distortformat; @@ -12621,6 +12679,7 @@ getSectionIDs(`repeating_global`, idarray => { setAttrs({"baseActNum":actcounter, "dummy":info, "Light":newlight, "dummy2":rollformat, "advState":advstate}); + setAttrs(output); let whisper = ""; if(whisperrolls == "true"){ From 8a219303311b050b6d1e169318d84a678d21069a Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Thu, 1 Aug 2024 13:20:37 +0200 Subject: [PATCH 25/55] AutoEffects: part 14 - Added Inflict and Give AutoEffects. These function as Gain, but sends a message detailing ailments to be applied to allies or enemies instead of the user - Added BaseDamage and FlatDamage AutoEffect, which details additional damage that's dealt to enemies --- ProjectMoonTRPG/ProjectMoonTRPG.html | 163 +++++++++++++++++++-------- 1 file changed, 115 insertions(+), 48 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 42650c21a2..982ed5ecb5 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -14997,13 +14997,17 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals if (checkResult != "failure") { switch (AutoEffect[0][0]) { case "Require": case "Consume": case "Reset": case "CustomMessage": break; /* Already executed above */ - case "Gain": tempOutput = autoEffectGainAilment(AutoEffect[0], ailmentList, scaling, settingLimbusStyle); break; + case "Gain": tempOutput = autoEffectAilment(AutoEffect[0], ailmentList, scaling, settingLimbusStyle); break; + case "Inflict": tempOutput = autoEffectAilment(AutoEffect[0], ailmentList, scaling, settingLimbusStyle); break; + case "Give": tempOutput = autoEffectAilment(AutoEffect[0], ailmentList, scaling, settingLimbusStyle); break; case "DicePower": tempOutput = autoEffectDicePower(AutoEffect[0], scaling); break; case "Set": tempOutput = autoEffectSetBar(AutoEffect[0], barList, scaling); break; case "Add": tempOutput = autoEffectAddBar(AutoEffect[0], barList, scaling); break; case "Multi": tempOutput = autoEffectMultiBar(AutoEffect[0], barList, scaling); break; case "DiceMax": tempOutput = autoEffectDiceMax(AutoEffect[0], scaling); break; case "DiceCount": tempOutput = autoEffectDiceCount(AutoEffect[0], scaling); break; + case "BaseDamage": tempOutput = autoEffectDamage(AutoEffect[0], barList, scaling); break; + case "FlatDamage": tempOutput = autoEffectDamage(AutoEffect[0], barList, scaling); break; case "ChallengeRoll": tempOutput = autoEffectChallengeRoll(AutoEffect[0], scaling); break; case "Speed": tempOutput = autoEffectSpeed(AutoEffect[0], scaling, thisRoundSpeed, nextRoundSpeed); break; default: tempOutput = {error:true}; autoEffectErrorMessage(`${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); break; @@ -15304,6 +15308,39 @@ function resetConditionals() { }); } +function autoEffectCustomMessage(AutoEffect, messageValues = {}) { + + console.log(messageValues) + + let messageFormat = ""; + let checkResultOption = "success"; + let effectTarget = "No target"; + let effectVal = 0; + let effectCount = 0; + let scaling = 1; + let checkResult = "success"; + let settingLimbusStyle = "false"; + + if (AutoEffect[1] != undefined) { messageFormat = AutoEffect.slice(1).join(" "); } + if ((/\"[ \t]*(checksuccess)/ig).test(messageFormat)) { messageFormat = messageFormat.replaceAll(/\"[ \t]*(checksuccess)/ig, "") } + else if ((/\"[ \t]*(checkfailure)/ig).test(messageFormat)) { checkResultOption = "failure"; messageFormat = messageFormat.replaceAll(/\"[ \t]*(checkfailure)/ig, "") } + else if ((/\"[ \t]*(checkignore)/ig).test(messageFormat)) { checkResultOption = "ignore"; messageFormat = messageFormat.replaceAll(/\"[ \t]*(checkignore)/ig, "")} + messageFormat = messageFormat.replaceAll('"',''); + + if (messageValues.effectTarget != undefined) { effectTarget = messageValues.effectTarget; } + if (messageValues.effectVal != undefined) { effectVal = messageValues.effectVal; } + if (messageValues.effectCount != undefined) { effectCount = messageValues.effectCount; } + if (messageValues.scaling != undefined) { scaling = messageValues.scaling; } + if (messageValues.checkResult != undefined) { checkResult = messageValues.checkResult.replace("last ","");} + if (messageValues.settingLimbusStyle != undefined) { settingLimbusStyle = messageValues.settingLimbusStyle; } + + if (checkResult == checkResultOption || checkResultOption == "ignore") { + return { message: autoEffectMessage(messageFormat, effectTarget, effectVal, effectCount, scaling, checkResult, settingLimbusStyle) } + } else { + return {} + } +} + function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { /* Check format */ if (AutoEffect.length < 3 || AutoEffect.length > 5) { autoEffectErrorMessage(`Expected format: (Require N #Ailment/#Bar/#BarDamage #Scaling(optional) #Silent(optional))`, AutoEffect); return {error: true}; } @@ -15374,7 +15411,7 @@ function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { function autoEffectConsume(AutoEffect, ailmentList, barList) { /* Check format */ - if (AutoEffect.length < 3 || AutoEffect.length > 4) { autoEffectErrorMessage(`Expected format: (Consume N #Ailment/#Bar #Scaling(optional))`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 3 || AutoEffect.length > 5) { autoEffectErrorMessage(`Expected format: (Consume N #Ailment/#Bar #Scaling(optional) #Silent(optional))`, AutoEffect); return {error: true}; } /* Get consumed value */ let effectVal = parseInt(Math.abs(AutoEffect[1])); @@ -15439,9 +15476,18 @@ function autoEffectConsume(AutoEffect, ailmentList, barList) { return returnValues; } -function autoEffectGainAilment(AutoEffect, ailmentList, scaling, settingLimbusStyle) { +function autoEffectAilment(AutoEffect, ailmentList, scaling, settingLimbusStyle) { + /* Check if Gain, Inflict or Give */ + let autoEffectVariant = ""; + switch (AutoEffect[0]) { + case "Gain": autoEffectVariant = "Gain"; break; + case "Inflict": autoEffectVariant = "Inflict"; break; + case "Give": autoEffectVariant = "Give"; break; + default: autoEffectErrorMessage(`${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); return {error: true} + } + /* Check format */ - if (AutoEffect.length < 3 || AutoEffect.length > 6) { autoEffectErrorMessage(`Expected format: (Gain N #Ailment #Round(optional) #Silent(optional))`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 3 || AutoEffect.length > 6) { autoEffectErrorMessage(`Expected format: (${autoEffectVariant} N #Ailment #Round(optional) #Silent(optional))`, AutoEffect); return {error: true}; } /* Handle scaling */ AutoEffect[1] *= scaling; @@ -15460,7 +15506,7 @@ function autoEffectGainAilment(AutoEffect, ailmentList, scaling, settingLimbusSt /* This is between you and me, but "Next turn" doesn't actually do anything ;) */ let forceTarget = ""; if (AutoEffect[3] != undefined) { - if (["this", "thisround", "this round, thisturn, this turn"].includes(AutoEffect[3].toLowerCase())) { forceTarget = "This turn"; } + if (["this", "thisround", "this round, thisturn, this turn"].includes(AutoEffect[3].toLowerCase())) { forceTarget = "This round"; } } /* Get target attribute */ @@ -15472,7 +15518,7 @@ function autoEffectGainAilment(AutoEffect, ailmentList, scaling, settingLimbusSt /* Effect changes target to the next turn field if it's enabled */ /* Is ignored if "This turn" override is included */ - if (effectHasNextTurn == 'true' && forceTarget != "This turn") { + if (effectHasNextTurn == 'true' && forceTarget != "This round") { effectTarget += "NextTurn"; count = ailmentList[effectAilment][2]; } @@ -15480,9 +15526,15 @@ function autoEffectGainAilment(AutoEffect, ailmentList, scaling, settingLimbusSt /* Handle message */ let message = ""; let messageValues = {}; - let messageFormat = "[/TARGET] Gained [SCALING NUM] [TARGET]"; + let messageFormat = ""; + switch (autoEffectVariant) { + case "Gain": messageFormat = "[/TARGET] Gained [SCALING NUM] [TARGET]"; break; + case "Inflict": messageFormat = "[/TARGET] Inflict [SCALING NUM] [TARGET] to target"; break; + case "Give": messageFormat = "[/TARGET] Give [SCALING NUM] [TARGET] to ally"; break; + } + let effectIcon = ailmentList[effectAilment][4]; - if (effectHasNextTurn == 'true' && forceTarget != "This turn") { messageFormat += " next turn"; } + if (effectHasNextTurn == 'true' && forceTarget != "This round") { messageFormat += " next round"; } if (!AutoEffect.includes("Silent")) { message = autoEffectMessage(messageFormat, effectIcon, effectVal/scaling, count, scaling, "success", settingLimbusStyle); @@ -15490,12 +15542,14 @@ function autoEffectGainAilment(AutoEffect, ailmentList, scaling, settingLimbusSt messageValues = { effectTarget: effectIcon, effectVal: effectVal/scaling, effectCount: count, scaling: scaling, checkResult: "success", settingLimbusStyle: settingLimbusStyle } /* Execute AutoEffect */ - return { [effectTarget]: parseInt(effectVal), count: parseInt(count), message: message, messageValues: messageValues } + let returnValues = { message: message, messageValues: messageValues }; + if (autoEffectVariant == "Gain") { returnValues = { ...returnValues, [effectTarget]: parseInt(effectVal), count: parseInt(count) } } + return returnValues; } function autoEffectSetBar(AutoEffect, barList, scaling) { /* Check format */ - if (AutoEffect.length != 3) { autoEffectErrorMessage(`Expected format: (Set N #Bar)`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 3 || AutoEffect.length > 4) { autoEffectErrorMessage(`Expected format: (Set N #Bar #Silent(optional))`, AutoEffect); return {error: true}; } /* Handle scaling */ AutoEffect[1] *= scaling; @@ -15530,7 +15584,7 @@ function autoEffectSetBar(AutoEffect, barList, scaling) { } function autoEffectAddBar(AutoEffect, barList, scaling) { /* Check format */ - if (AutoEffect.length != 3) { autoEffectErrorMessage(`Expected format: (Add N #Bar)`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 3 || AutoEffect.length > 4) { autoEffectErrorMessage(`Expected format: (Add N #Bar #Silent(optional))`, AutoEffect); return {error: true}; } /* Handle scaling */ AutoEffect[1] *= scaling; @@ -15566,7 +15620,7 @@ function autoEffectAddBar(AutoEffect, barList, scaling) { } function autoEffectMultiBar(AutoEffect, barList, scaling) { /* Check format */ - if (AutoEffect.length != 3) { autoEffectErrorMessage(`Expected format: (Multi N #Bar)`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 3 || AutoEffect.length > 4) { autoEffectErrorMessage(`Expected format: (Multi N #Bar #Silent(optional))`, AutoEffect); return {error: true}; } /* Handle scaling */ AutoEffect[1] *= scaling; @@ -15601,7 +15655,7 @@ function autoEffectMultiBar(AutoEffect, barList, scaling) { function autoEffectDicePower(AutoEffect, scaling) { /* Check format */ - if (AutoEffect.length != 2) { autoEffectErrorMessage(`Expected format: (DicePower N)`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 2 || AutoEffect.length > 3) { autoEffectErrorMessage(`Expected format: (DicePower N #Silent(optional))`, AutoEffect); return {error: true}; } /* Handle scaling */ AutoEffect[1] *= scaling; @@ -15627,7 +15681,7 @@ function autoEffectDicePower(AutoEffect, scaling) { } function autoEffectDiceMax(AutoEffect, scaling) { /* Check format */ - if (AutoEffect.length != 2) { autoEffectErrorMessage(`Expected format: (DiceMax N)`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 2 || AutoEffect.length > 3) { autoEffectErrorMessage(`Expected format: (DiceMax N #Silent(optional))`, AutoEffect); return {error: true}; } /* Handle scaling */ AutoEffect[1] *= scaling; @@ -15653,7 +15707,7 @@ function autoEffectDiceMax(AutoEffect, scaling) { } function autoEffectDiceCount(AutoEffect, scaling) { /* Check format */ - if (AutoEffect.length != 2) { autoEffectErrorMessage(`Expected format: (DiceCount N)`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 2 || AutoEffect.length > 3) { autoEffectErrorMessage(`Expected format: (DiceCount N #Silent(optional))`, AutoEffect); return {error: true}; } /* Handle scaling */ AutoEffect[1] *= scaling; @@ -15703,7 +15757,7 @@ function autoEffectChallengeRoll(AutoEffect, scaling) { function autoEffectSpeed(AutoEffect, scaling, prevThisRoundSpeed, prevNextRoundSpeed) { /* Check format */ - if (AutoEffect.length < 3 || AutoEffect.length > 4) { autoEffectErrorMessage(`Expected format: (Speed N #Duration)`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 3 || AutoEffect.length > 5) { autoEffectErrorMessage(`Expected format: (Speed N #Duration #Silent(optional))`, AutoEffect); return {error: true}; } /* Handle scaling */ AutoEffect[1] *= scaling; @@ -15744,40 +15798,53 @@ function autoEffectSpeed(AutoEffect, scaling, prevThisRoundSpeed, prevNextRoundS } } -function autoEffectCustomMessage(AutoEffect, messageValues = {}) { - - console.log(messageValues) - - let messageFormat = ""; - let checkResultOption = "success"; - let effectTarget = "No target"; - let effectVal = 0; - let effectCount = 0; - let scaling = 1; - let checkResult = "success"; - let settingLimbusStyle = "false"; - - if (AutoEffect[1] != undefined) { messageFormat = AutoEffect.slice(1).join(" "); } - if ((/\"[ \t]*(checksuccess)/ig).test(messageFormat)) { messageFormat = messageFormat.replaceAll(/\"[ \t]*(checksuccess)/ig, "") } - else if ((/\"[ \t]*(checkfailure)/ig).test(messageFormat)) { checkResultOption = "failure"; messageFormat = messageFormat.replaceAll(/\"[ \t]*(checkfailure)/ig, "") } - else if ((/\"[ \t]*(checkignore)/ig).test(messageFormat)) { checkResultOption = "ignore"; messageFormat = messageFormat.replaceAll(/\"[ \t]*(checkignore)/ig, "")} - messageFormat = messageFormat.replaceAll('"',''); - - if (messageValues.effectTarget != undefined) { effectTarget = messageValues.effectTarget; } - if (messageValues.effectVal != undefined) { effectVal = messageValues.effectVal; } - if (messageValues.effectCount != undefined) { effectCount = messageValues.effectCount; } - if (messageValues.scaling != undefined) { scaling = messageValues.scaling; } - if (messageValues.checkResult != undefined) { checkResult = messageValues.checkResult.replace("last ","");} - if (messageValues.settingLimbusStyle != undefined) { settingLimbusStyle = messageValues.settingLimbusStyle; } - - if (checkResult == checkResultOption || checkResultOption == "ignore") { - return { message: autoEffectMessage(messageFormat, effectTarget, effectVal, effectCount, scaling, checkResult, settingLimbusStyle) } - } else { - return {} +function autoEffectDamage(AutoEffect, barList, scaling) { + /* Check if BaseDamage or FlatDamage */ + let autoEffectVariant = ""; + switch (AutoEffect[0]) { + case "BaseDamage": autoEffectVariant = "BaseDamage"; break; + case "FlatDamage": autoEffectVariant = "FlatDamage"; break; + default: autoEffectErrorMessage(`${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); return {error: true} } + + /* Check format */ + if (AutoEffect.length < 3 || AutoEffect.length > 4) { autoEffectErrorMessage(`Expected format: (${autoEffectVariant} N #Bar #Silent(optional))`, AutoEffect); return {error: true}; } + + /* Handle scaling */ + AutoEffect[1] *= scaling; + if (scaling == 0) { return {}; } + + /* Get value */ + let effectVal = parseInt(Math.abs(AutoEffect[1])); + if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + let count = 0; + + /* Get target */ + let effectBar = AutoEffect[2]; + let effectTarget = ""; + if (barList.hasOwnProperty(effectBar)) { + effectTarget = effectBar.replace("ST", "StagRes"); + count = barList[effectBar]; + } + else { autoEffectErrorMessage(`Bar "${effectBar}" does not exist`, AutoEffect); return {error: true}; } + + /* Handle message */ + let message = ""; + let messageValues = {}; + let messageFormat = ""; + switch (autoEffectVariant) { + case "BaseDamage": messageFormat = "Increased Base Damage by [SCALING NUM]"; break; + case "FlatDamage": messageFormat = "Dealt [SCALING NUM] [TARGET] Damage"; break; + } + + if (!AutoEffect.includes("Silent")) { + message = autoEffectMessage(messageFormat, effectTarget, effectVal/scaling, count, scaling, "success"); + } + messageValues = { effectTarget: effectTarget, effectVal: effectVal/scaling, effectCount: count, scaling: scaling, checkResult: "success" } + + /* Execute AutoEffect */ + return { message: message, messageValues: messageValues }; } - - /*--- AutoEffect functions end ---*/ From 8c047b65ed71492b938470b4c4403ffbfdc6de3d Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Thu, 1 Aug 2024 13:32:29 +0200 Subject: [PATCH 26/55] Bugfix: Speed roll was affected by Challenge AutoEffects and vice verse. Luck rolls was affected by both Speed and Challenge AutoEffects --- ProjectMoonTRPG/ProjectMoonTRPG.html | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 982ed5ecb5..1505967528 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -12765,8 +12765,12 @@ function rollChallenge(buttonid, rollDifficulty=0) { let lucknum = "0"; /* AutoScripts */ + let autoScriptTriggers = ["None"]; + if (buttonid == "speed") { autoScriptTriggers.push("Combat start"); } + else if (buttonid != "luck") { autoScriptTriggers.push("Challenge"); } + resetConditionals(); - AutoScriptMain("", ["Challenge", "Combat start"], "true", function(returnValues) { + AutoScriptMain("", autoScriptTriggers, "true", function(returnValues) { let autoEffectDiceCount = 0; let autoEffectDiceMax = 0; @@ -15752,7 +15756,7 @@ function autoEffectChallengeRoll(AutoEffect, scaling) { else { autoEffectErrorMessage(`Stat "${AutoEffect[1]}" does not exist.`, AutoEffect); return {error: true}; } /* Execute AutoEffect */ - return { challengeRollStat: statTarget, challengeRollDifficulty: effectVal, message: message, messageValues: messageValues } + return { challengeRollStat: statTarget, challengeRollDifficulty: effectVal } } function autoEffectSpeed(AutoEffect, scaling, prevThisRoundSpeed, prevNextRoundSpeed) { From 2cd4613f22dba7a99739438260c724c591d65136 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Thu, 1 Aug 2024 13:56:41 +0200 Subject: [PATCH 27/55] Bugfix: ChallengeRoll AutoEffect was clearing conditional buttons --- ProjectMoonTRPG/ProjectMoonTRPG.html | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 1505967528..f5b5ac6902 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -12735,7 +12735,7 @@ on('clicked:rollChallenge', (info) => { let buttonid = info.htmlAttributes.id.split('_')[1]; rollChallenge(buttonid); }); -function rollChallenge(buttonid, rollDifficulty=0) { +function rollChallenge(buttonid, rollDifficulty=0, handleAutoScriptConditionals="true") { /* Preparing values */ let headercolor = "#888"; @@ -12769,7 +12769,7 @@ function rollChallenge(buttonid, rollDifficulty=0) { if (buttonid == "speed") { autoScriptTriggers.push("Combat start"); } else if (buttonid != "luck") { autoScriptTriggers.push("Challenge"); } - resetConditionals(); + if (handleAutoScriptConditionals == true) { resetConditionals(); } AutoScriptMain("", autoScriptTriggers, "true", function(returnValues) { let autoEffectDiceCount = 0; @@ -12915,7 +12915,7 @@ function rollChallenge(buttonid, rollDifficulty=0) { setAttrs({"dummy":" ", "skillSelect":"0"}); - }); + }, handleAutoScriptConditionals); }); } @@ -14960,6 +14960,7 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals ailmentList[ailName] = [ailHasNextTurn, ailNum, ailNumNextTurn, id, ailIcon]; }); + console.log(AutoScript) /* Execute each AutoEffect in the AutoScript */ AutoScript.forEach(AutoEffect => { @@ -15067,16 +15068,20 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals /* Handle challenge rolls */ if (tempOutput.challengeRollStat != undefined) { challengeRollList[tempOutput.challengeRollStat] = tempOutput.challengeRollDifficulty; + delete tempOutput.challengeRollStat; + delete tempOutput.challengeRollDifficulty; } /* Handle message */ if (tempOutput.message != undefined) { message += tempOutput.message; + delete tempOutput.message; } /* Handle messageValues. Used by the CustomMessage AutoEffect. Outputted by all AutoEffects that generate messages */ if (tempOutput.messageValues != undefined) { messageValues = tempOutput.messageValues; + delete tempOutput.messageValues; } /* Add attribute changes from AutoEffect to output */ @@ -15106,7 +15111,7 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals /* Execute challange rolls */ for (const [statName, rollDifficulty] of Object.entries(challengeRollList)) { /* Checks if any checks failed and the button should not be displayed */ - rollChallenge(statName, rollDifficulty); + rollChallenge(statName, rollDifficulty, "false"); } /* Message handling */ @@ -15738,7 +15743,7 @@ function autoEffectDiceCount(AutoEffect, scaling) { function autoEffectChallengeRoll(AutoEffect, scaling) { /* Check format */ - if (AutoEffect.length != 3) { autoEffectErrorMessage(`Expected format: (ChallengeRoll #Stat N)`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 3 || AutoEffect.length > 3 ) { autoEffectErrorMessage(`Expected format: (ChallengeRoll #Stat N #Silent(optional))`, AutoEffect); return {error: true}; } /* Handle scaling */ AutoEffect[2] *= scaling; @@ -15754,9 +15759,20 @@ function autoEffectChallengeRoll(AutoEffect, scaling) { statTarget = AutoEffect[1].toLowerCase().replace("fortitude","instinct").replace("prudence","wisdom"); } else { autoEffectErrorMessage(`Stat "${AutoEffect[1]}" does not exist.`, AutoEffect); return {error: true}; } + + /* Handle message */ + let message = ""; + let messageValues = {}; + let messageFormat = "Rolling [TARGET] +[SCALING NUM]"; + if (effectVal < 0) { messageFormat = "Rolling [TARGET] [SCALING NUM]"; } + + if (!AutoEffect.includes("Silent")) { + message = autoEffectMessage(messageFormat, (statTarget.charAt(0).toUpperCase() + statTarget.slice(1)), effectVal/scaling, 0, scaling, "success"); + } + messageValues = { effectTarget: (statTarget.charAt(0).toUpperCase() + statTarget.slice(1)), effectVal: effectVal/scaling, effectCount: 0, scaling: scaling, checkResult: "success" } /* Execute AutoEffect */ - return { challengeRollStat: statTarget, challengeRollDifficulty: effectVal } + return { challengeRollStat: statTarget, challengeRollDifficulty: effectVal, message: message, messageValues: messageValues } } function autoEffectSpeed(AutoEffect, scaling, prevThisRoundSpeed, prevNextRoundSpeed) { From 09c5f298fb56209060f8b374e4108c3a8cc1e447 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Thu, 1 Aug 2024 19:41:45 +0200 Subject: [PATCH 28/55] AutoEffects: part 14.5 - Combined DicePower, DiceCount and DiceMax into one function with three variants --- ProjectMoonTRPG/ProjectMoonTRPG.html | 78 +++++++--------------------- 1 file changed, 18 insertions(+), 60 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index f5b5ac6902..022c206ca1 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -12775,7 +12775,7 @@ function rollChallenge(buttonid, rollDifficulty=0, handleAutoScriptConditionals= let autoEffectDiceCount = 0; let autoEffectDiceMax = 0; let autoEffectSpeedCombat = 0; - if (returnValues.dicePower != undefined) { stat = returnValues.dicePower } + if (returnValues.dicePower != undefined) { stat += returnValues.dicePower } if (returnValues.diceCount != undefined) { autoEffectDiceCount = returnValues.diceCount } if (returnValues.diceMax != undefined) { autoEffectDiceMax = returnValues.diceMax } if (returnValues.speedCombat != undefined) { autoEffectSpeedCombat = returnValues.speedCombat } @@ -15005,12 +15005,12 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals case "Gain": tempOutput = autoEffectAilment(AutoEffect[0], ailmentList, scaling, settingLimbusStyle); break; case "Inflict": tempOutput = autoEffectAilment(AutoEffect[0], ailmentList, scaling, settingLimbusStyle); break; case "Give": tempOutput = autoEffectAilment(AutoEffect[0], ailmentList, scaling, settingLimbusStyle); break; - case "DicePower": tempOutput = autoEffectDicePower(AutoEffect[0], scaling); break; case "Set": tempOutput = autoEffectSetBar(AutoEffect[0], barList, scaling); break; case "Add": tempOutput = autoEffectAddBar(AutoEffect[0], barList, scaling); break; case "Multi": tempOutput = autoEffectMultiBar(AutoEffect[0], barList, scaling); break; - case "DiceMax": tempOutput = autoEffectDiceMax(AutoEffect[0], scaling); break; - case "DiceCount": tempOutput = autoEffectDiceCount(AutoEffect[0], scaling); break; + case "DicePower": tempOutput = autoEffectDice(AutoEffect[0], scaling); break; + case "DiceMax": tempOutput = autoEffectDice(AutoEffect[0], scaling); break; + case "DiceCount": tempOutput = autoEffectDice(AutoEffect[0], scaling); break; case "BaseDamage": tempOutput = autoEffectDamage(AutoEffect[0], barList, scaling); break; case "FlatDamage": tempOutput = autoEffectDamage(AutoEffect[0], barList, scaling); break; case "ChallengeRoll": tempOutput = autoEffectChallengeRoll(AutoEffect[0], scaling); break; @@ -15662,9 +15662,18 @@ function autoEffectMultiBar(AutoEffect, barList, scaling) { return {[effectTarget]: Math.floor(parseFloat(effectVal) * parseInt(count) - parseInt(count)), count: count, message: message, messageValues: messageValues }; } -function autoEffectDicePower(AutoEffect, scaling) { +function autoEffectDice(AutoEffect, scaling) { + /* Check if DicePower, DiceMax or DiceCount */ + let autoEffectVariant = ""; + switch (AutoEffect[0]) { + case "DicePower": autoEffectVariant = "DicePower"; break; + case "DiceMax": autoEffectVariant = "DiceMax"; break; + case "DiceCount": autoEffectVariant = "DiceCount"; break; + default: autoEffectErrorMessage(`${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); return {error: true} + } + /* Check format */ - if (AutoEffect.length < 2 || AutoEffect.length > 3) { autoEffectErrorMessage(`Expected format: (DicePower N #Silent(optional))`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 2 || AutoEffect.length > 3) { autoEffectErrorMessage(`Expected format: (${autoEffectVariant} N #Silent(optional))`, AutoEffect); return {error: true}; } /* Handle scaling */ AutoEffect[1] *= scaling; @@ -15675,31 +15684,6 @@ function autoEffectDicePower(AutoEffect, scaling) { if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } /* Handle message */ - let message = ""; - let messageValues = {}; - let messageFormat = "Increased [TARGET] by [SCALING NUM]"; - if (effectVal < 0) { messageFormat = "Reduced [TARGET] by [SCALING NUM]"; } - - if (!AutoEffect.includes("Silent")) { - message = autoEffectMessage(messageFormat, "Dice Power", effectVal/scaling, 0, scaling, "success"); - } - messageValues = { effectTarget: "Dice Power", effectVal: effectVal/scaling, effectCount: 0, scaling: scaling, checkResult: "success" } - - /* Execute AutoEffect */ - return { dicePower: parseInt(effectVal), message: message, messageValues: messageValues } -} -function autoEffectDiceMax(AutoEffect, scaling) { - /* Check format */ - if (AutoEffect.length < 2 || AutoEffect.length > 3) { autoEffectErrorMessage(`Expected format: (DiceMax N #Silent(optional))`, AutoEffect); return {error: true}; } - - /* Handle scaling */ - AutoEffect[1] *= scaling; - if (scaling == 0) { return {}; } - - /* Get values */ - let effectVal = parseInt(AutoEffect[1]); - if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } - /* Handle message */ let message = ""; let messageValues = {}; @@ -15707,38 +15691,12 @@ function autoEffectDiceMax(AutoEffect, scaling) { if (effectVal < 0) { messageFormat = "Reduced [TARGET] by [SCALING NUM]"; } if (!AutoEffect.includes("Silent")) { - message = autoEffectMessage(messageFormat, "Dice Max", effectVal/scaling, 0, scaling, "success"); + message = autoEffectMessage(messageFormat, AutoEffect[0].replace("Dice", "Dice "), effectVal/scaling, 0, scaling, "success"); } - messageValues = { effectTarget: "Dice Max", effectVal: effectVal/scaling, effectCount: 0, scaling: scaling, checkResult: "success" } + messageValues = { effectTarget: AutoEffect[0].replace("Dice", "Dice "), effectVal: effectVal/scaling, effectCount: 0, scaling: scaling, checkResult: "success" } /* Execute AutoEffect */ - return { diceMax: parseInt(effectVal), message: message, messageValues: messageValues } -} -function autoEffectDiceCount(AutoEffect, scaling) { - /* Check format */ - if (AutoEffect.length < 2 || AutoEffect.length > 3) { autoEffectErrorMessage(`Expected format: (DiceCount N #Silent(optional))`, AutoEffect); return {error: true}; } - - /* Handle scaling */ - AutoEffect[1] *= scaling; - if (scaling == 0) { return {}; } - - /* Get values */ - let effectVal = parseInt(AutoEffect[1]); - if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } - - /* Handle message */ - let message = ""; - let messageValues = {}; - let messageFormat = "Increased [TARGET] by [SCALING NUM]"; - if (effectVal < 0) { messageFormat = "Reduced [TARGET] by [SCALING NUM]"; } - - if (!AutoEffect.includes("Silent")) { - message = autoEffectMessage(messageFormat, "Dice Count", effectVal/scaling, 0, scaling, "success"); - } - messageValues = { effectTarget: "Dice Count", effectVal: effectVal/scaling, effectCount: 0, scaling: scaling, checkResult: "success" } - - /* Execute AutoEffect */ - return { diceCount: parseInt(effectVal), message: message, messageValues: messageValues } + return { [AutoEffect[0].replace("D","d")]: parseInt(effectVal), message: message, messageValues: messageValues } } function autoEffectChallengeRoll(AutoEffect, scaling) { From 611082f080a25babff14cff6795fd8708ab15972 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Sat, 3 Aug 2024 14:39:23 +0200 Subject: [PATCH 29/55] Small updates: Damage Helper - Changed wording of damage taken from "Suffered x damage" to "x damage received". This better matches the sentence structure of Japanese and Korean (verb after subject) - When staggered, the ST status bar update changes from "xx -> xx" to "Staggered!". This adds context to why damage resistances are treated as 2x --- ProjectMoonTRPG/ProjectMoonTRPG.html | 136 +++++++++++++++++---------- ProjectMoonTRPG/translation.json | 4 +- 2 files changed, 87 insertions(+), 53 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 022c206ca1..636afa1178 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -13287,7 +13287,7 @@ on('clicked:applyDamage', (info) => { /* Calculation summaries (Message head) */ hpDamageHead = generateDamageHelperHeader("HP", newHP, oldHP); - stDamageHead = generateDamageHelperHeader("ST", newST, oldST); + stDamageHead = generateDamageHelperHeader("ST", newST, oldST, staggerState); spDamageHead = generateDamageHelperHeader("SP", newSP, oldSP); /* Simple display settings (Envelops entire body block)*/ @@ -13390,18 +13390,20 @@ function getIcon(iconFolder, iconName, settingLimbusStyle = "false") { } } -function generateDamageHelperHeader(statName, newStat, oldStat) { +function generateDamageHelperHeader(statName, newStat, oldStat, staggerState="0") { let langBar = "HP"; let langDamage = "damage"; - let langSuffered = "Suffered"; - let langSufferedNo = "Suffered no"; + let langSuffered = "received"; + let langSufferedNo = "Received no"; let langRegened = "Regened"; + let langStaggered = "Regened"; let updateDisplay = ""; let displayContent = ""; if(getTranslationByKey("message-damage") != false) { langDamage = getTranslationByKey("message-damage"); + langStaggered = getTranslationByKey("ailments-stagger-text"); switch (statName) { case "HP": langBar = getTranslationByKey("bar-health-shortened"); break; case "ST": langBar = getTranslationByKey("bar-stagres-shortened"); break; @@ -13410,14 +13412,14 @@ function generateDamageHelperHeader(statName, newStat, oldStat) { } else { langBar = statName; } + if (staggerState == "Staggered") { updateDisplay = `
${langStaggered}!
`; } + else { updateDisplay = `
${oldStat} -> ${newStat}
`; } - updateDisplay = `
${oldStat} -> ${newStat}
`; - - if (newStat < oldStat) { langSuffered = getTranslationByKey("message-suffered"); - return `
${langSuffered} ${oldStat-newStat} ${langBar} ${langDamage}
${updateDisplay}
`; } + if (newStat < oldStat) { langSuffered = getTranslationByKey("message-received"); + return `
${oldStat-newStat} ${langBar} ${langDamage} ${langSuffered}
${updateDisplay}
`; } else if (newStat > oldStat) { langRegened = getTranslationByKey("message-regened-capitalized"); return `
${langRegened} ${newStat-oldStat} ${langBar}
${updateDisplay}
`; } - else { langSufferedNo = getTranslationByKey("message-suffered-no"); + else { langSufferedNo = getTranslationByKey("message-received-no"); return `
${langSufferedNo} ${langBar} ${langDamage}
${updateDisplay}
` } } @@ -14915,6 +14917,7 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals let tempOutput = {}; let returnValues = { checkResult:"success", error:false, }; let conditionalList = {}; + let conditionalMessageList = {}; let challengeRollList = {}; let message = ""; let messageValues = {}; @@ -14967,57 +14970,42 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals if (AutoEffect == undefined) { return; } - /* If conditional, add AutoEffect to either a new conditional button or a existing one */ + /* Handle conditional */ if (AutoEffect.length > 1) { AutoEffect.slice(1).forEach(conditional => { - if (conditionalList.hasOwnProperty(conditional)) { - conditionalList[conditional] += " (" + AutoEffect[0].toString().replaceAll(","," ") + ")"; - } else { - conditionalList[conditional] = "(" + AutoEffect[0].toString().replaceAll(","," ") + ")"; + /* If conditional button, add AutoEffect to either a new conditional button or a existing one */ + if (!conditional.includes("#Message")) { + if (conditionalList.hasOwnProperty(conditional)) { + conditionalList[conditional] += " (" + AutoEffect[0].toString().replaceAll(","," ") + ")"; + } else { + conditionalList[conditional] = "(" + AutoEffect[0].toString().replaceAll(","," ") + ")"; + } + + /* If AutoEffect is Require or Consume, do not display the button if the check will fail */ + if (AutoEffect[0][0] == "Require" || AutoEffect[0][0] == "Consume") { + switch (AutoEffect[0][0]) { + case "Require": tempOutput = autoEffectRequire(AutoEffect[0], ailmentList, barList, barDamageList); break; + case "Consume": tempOutput = autoEffectConsume(AutoEffect[0], ailmentList, barList); break; + default: tempOutput = {}; break; + } + if (tempOutput.checkResult == "failure") { + conditionalList[conditional] = "#Do not display#"; + } + } } - - /* If AutoEffect is Require or Consume, do not display the button if the check will fail */ - if (AutoEffect[0][0] == "Require" || AutoEffect[0][0] == "Consume") { - switch (AutoEffect[0][0]) { - case "Require": tempOutput = autoEffectRequire(AutoEffect[0], ailmentList, barList, barDamageList); break; - case "Consume": tempOutput = autoEffectConsume(AutoEffect[0], ailmentList, barList); break; - default: tempOutput = {}; break; - } - if (tempOutput.checkResult == "failure") { - conditionalList[conditional] = "#Do not display#"; - } + /* If conditional message, add AutoEffect return message to a new section for the current roll */ + else { + conditional = conditional.replace("#Message","").trim(); + tempOutput = autoEffectExecute(AutoEffect[0], ailmentList, barList, barDamageList, scaling, settingLimbusStyle, checkResult, messageValues, thisRoundSpeed, nextRoundSpeed); + conditionalMessageList[conditional] = tempOutput.message; + console.log(conditionalMessageList) } }); } /* If not conditional, process AutoEffect as normal */ else { /* Checks and Reset are always processed. Other AutoEffects are not processed if the last check failed */ - switch (AutoEffect[0][0]) { - case "Require": tempOutput = autoEffectRequire(AutoEffect[0], ailmentList, barList, barDamageList); break; - case "Consume": tempOutput = autoEffectConsume(AutoEffect[0], ailmentList, barList); break; - case "Reset": tempOutput = {checkResult: "success", scaling: 1}; break; - case "CustomMessage": tempOutput = autoEffectCustomMessage(AutoEffect[0], messageValues); break; - default: tempOutput = {}; break; - } - if (checkResult != "failure") { - switch (AutoEffect[0][0]) { - case "Require": case "Consume": case "Reset": case "CustomMessage": break; /* Already executed above */ - case "Gain": tempOutput = autoEffectAilment(AutoEffect[0], ailmentList, scaling, settingLimbusStyle); break; - case "Inflict": tempOutput = autoEffectAilment(AutoEffect[0], ailmentList, scaling, settingLimbusStyle); break; - case "Give": tempOutput = autoEffectAilment(AutoEffect[0], ailmentList, scaling, settingLimbusStyle); break; - case "Set": tempOutput = autoEffectSetBar(AutoEffect[0], barList, scaling); break; - case "Add": tempOutput = autoEffectAddBar(AutoEffect[0], barList, scaling); break; - case "Multi": tempOutput = autoEffectMultiBar(AutoEffect[0], barList, scaling); break; - case "DicePower": tempOutput = autoEffectDice(AutoEffect[0], scaling); break; - case "DiceMax": tempOutput = autoEffectDice(AutoEffect[0], scaling); break; - case "DiceCount": tempOutput = autoEffectDice(AutoEffect[0], scaling); break; - case "BaseDamage": tempOutput = autoEffectDamage(AutoEffect[0], barList, scaling); break; - case "FlatDamage": tempOutput = autoEffectDamage(AutoEffect[0], barList, scaling); break; - case "ChallengeRoll": tempOutput = autoEffectChallengeRoll(AutoEffect[0], scaling); break; - case "Speed": tempOutput = autoEffectSpeed(AutoEffect[0], scaling, thisRoundSpeed, nextRoundSpeed); break; - default: tempOutput = {error:true}; autoEffectErrorMessage(`${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); break; - } - } + tempOutput = autoEffectExecute(AutoEffect[0], ailmentList, barList, barDamageList, scaling, settingLimbusStyle, checkResult, messageValues, thisRoundSpeed, nextRoundSpeed); console.log(tempOutput) /* Handle errors. Continues executing AutoEffects for the sake of finding additional errors, */ @@ -15144,6 +15132,19 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals returnValues.message = newmessage; } } + + /* Conditional message handling */ + for (const [conditionName, conditionMessage] of Object.entries(conditionalMessageList)) { + let newmessage = "
"; + newmessage += `
` + newmessage += `
` + newmessage += `${getIcon("icons", "gear")}` + newmessage += `
` + newmessage += `
${conditionName}
` + newmessage += `
` + conditionMessage + "
"; + + returnValues.message += newmessage; + } /* Error handling and returnValues callback */ if (returnValues.error == true) { @@ -15224,7 +15225,40 @@ function AutoScriptToArray(inputAutoScript, mode="normal") { /*--- AutoEffect functions ---*/ +function autoEffectExecute(AutoEffect, ailmentList, barList, barDamageList, scaling=1, settingLimbusStyle="false", checkResult="success", messageValues={}, thisRoundSpeed="0", nextRoundSpeed="0") { + + let tempOutput = {}; + + /* Checks and Reset are always processed. Other AutoEffects are not processed if the last check failed */ + switch (AutoEffect[0]) { + case "Require": tempOutput = autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList); break; + case "Consume": tempOutput = autoEffectConsume(AutoEffect, ailmentList, barList); break; + case "Reset": tempOutput = {checkResult: "success", scaling: 1}; break; + case "CustomMessage": tempOutput = autoEffectCustomMessage(AutoEffect, messageValues); break; + default: tempOutput = {}; break; + } + if (checkResult != "failure") { + switch (AutoEffect[0]) { + case "Require": case "Consume": case "Reset": case "CustomMessage": break; /* Already executed above */ + case "Gain": tempOutput = autoEffectAilment(AutoEffect, ailmentList, scaling, settingLimbusStyle); break; + case "Inflict": tempOutput = autoEffectAilment(AutoEffect, ailmentList, scaling, settingLimbusStyle); break; + case "Give": tempOutput = autoEffectAilment(AutoEffect, ailmentList, scaling, settingLimbusStyle); break; + case "Set": tempOutput = autoEffectSetBar(AutoEffect, barList, scaling); break; + case "Add": tempOutput = autoEffectAddBar(AutoEffect, barList, scaling); break; + case "Multi": tempOutput = autoEffectMultiBar(AutoEffect, barList, scaling); break; + case "DicePower": tempOutput = autoEffectDice(AutoEffect, scaling); break; + case "DiceMax": tempOutput = autoEffectDice(AutoEffect, scaling); break; + case "DiceCount": tempOutput = autoEffectDice(AutoEffect, scaling); break; + case "BaseDamage": tempOutput = autoEffectDamage(AutoEffect, barList, scaling); break; + case "FlatDamage": tempOutput = autoEffectDamage(AutoEffect, barList, scaling); break; + case "ChallengeRoll": tempOutput = autoEffectChallengeRoll(AutoEffect, scaling); break; + case "Speed": tempOutput = autoEffectSpeed(AutoEffect, scaling, thisRoundSpeed, nextRoundSpeed); break; + default: tempOutput = {error:true}; autoEffectErrorMessage(`${AutoEffect} is not a valid AutoEffect`, AutoEffect); break; + } + } + return tempOutput; +} function autoEffectMessage(messageFormat, effectTarget="No target", effectVal=0, effectCount=0, scaling=1, checkResult="success", settingLimbusStyle="false") { if(messageFormat != ""){ diff --git a/ProjectMoonTRPG/translation.json b/ProjectMoonTRPG/translation.json index 613737df54..440b3fd25d 100644 --- a/ProjectMoonTRPG/translation.json +++ b/ProjectMoonTRPG/translation.json @@ -402,8 +402,8 @@ "message-regened":"regened", "message-reduced-damage-by":"reduced damage by", "message-increased-HP-damage-by":"increased HP damage by", - "message-suffered":"Suffered", - "message-suffered-no":"Suffered no", + "message-received":"received", + "message-received-no":"Received no", "message-regened-capitalized":"Regened", "message-resist":"Resistance: ", "message-distorted":"Distorted", From d5055ba424932cff4879c28030d5ba01cf99cee6 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Sat, 3 Aug 2024 15:58:25 +0200 Subject: [PATCH 30/55] AutoEffects: part 15 - Added option #MessageButton to have a conditional both display a new section in the roll message and display a conditional button. The button will not display a message if this option is used - Fixed conditional messages not using scaling --- ProjectMoonTRPG/ProjectMoonTRPG.html | 145 ++++++++++++++++----------- 1 file changed, 85 insertions(+), 60 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 636afa1178..843ab437d2 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -14912,12 +14912,16 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals let scaling = 1; let checkResult = "success"; - + let autoEffectType = "standard"; + + let autoEffectConditional = ""; + let conditionalMessageList = {}; + let conditionalButtonList = {}; + let conditionalButtonSilent = ""; + let output = {}; let tempOutput = {}; let returnValues = { checkResult:"success", error:false, }; - let conditionalList = {}; - let conditionalMessageList = {}; let challengeRollList = {}; let message = ""; let messageValues = {}; @@ -14967,19 +14971,36 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals /* Execute each AutoEffect in the AutoScript */ AutoScript.forEach(AutoEffect => { - if (AutoEffect == undefined) { + if (AutoEffect == undefined) { return; } /* Handle conditional */ if (AutoEffect.length > 1) { AutoEffect.slice(1).forEach(conditional => { + /* If conditional message, execute the script as normal but do not apply any effects and add the message to a seperate section */ + if (conditional.includes("#Message") && !conditional.includes("#MessageButton")) { + autoEffectConditional = conditional.replace("#Message","").trim(); + autoEffectType = "conditional message"; + } /* If conditional button, add AutoEffect to either a new conditional button or a existing one */ - if (!conditional.includes("#Message")) { - if (conditionalList.hasOwnProperty(conditional)) { - conditionalList[conditional] += " (" + AutoEffect[0].toString().replaceAll(","," ") + ")"; + /* If conditional message + button, add Silent to AutoEffect after execution */ + else { + if (conditional.includes("#MessageButton") || conditional.includes("#ButtonMessage")) { + autoEffectConditional = conditional.replace("#MessageButton","").replace("#ButtonMessage","").trim(); + conditionalButtonSilent = AutoEffect[0].includes("Silent") ? "" : " Silent"; + autoEffectType = "conditional message + button"; } else { - conditionalList[conditional] = "(" + AutoEffect[0].toString().replaceAll(","," ") + ")"; + autoEffectConditional = conditional.replace("#Button","").trim(); + conditionalButtonSilent = ""; + autoEffectType = "conditional button"; } + + if (conditionalButtonList.hasOwnProperty(autoEffectConditional)) { + conditionalButtonList[autoEffectConditional] += " (" + AutoEffect[0].toString().replaceAll(","," ") + conditionalButtonSilent + ")"; + } else { + conditionalButtonList[autoEffectConditional] = "(" + AutoEffect[0].toString().replaceAll(","," ") + conditionalButtonSilent + ")"; + } + console.log(conditionalButtonList[autoEffectConditional]) /* If AutoEffect is Require or Consume, do not display the button if the check will fail */ if (AutoEffect[0][0] == "Require" || AutoEffect[0][0] == "Consume") { @@ -14989,23 +15010,44 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals default: tempOutput = {}; break; } if (tempOutput.checkResult == "failure") { - conditionalList[conditional] = "#Do not display#"; + conditionalButtonList[autoEffectConditional] = "#Do not display#"; } } } - /* If conditional message, add AutoEffect return message to a new section for the current roll */ - else { - conditional = conditional.replace("#Message","").trim(); - tempOutput = autoEffectExecute(AutoEffect[0], ailmentList, barList, barDamageList, scaling, settingLimbusStyle, checkResult, messageValues, thisRoundSpeed, nextRoundSpeed); - conditionalMessageList[conditional] = tempOutput.message; - console.log(conditionalMessageList) - } }); + } else { + autoEffectType = "standard"; } /* If not conditional, process AutoEffect as normal */ - else { + if (autoEffectType != "conditional button") { /* Checks and Reset are always processed. Other AutoEffects are not processed if the last check failed */ - tempOutput = autoEffectExecute(AutoEffect[0], ailmentList, barList, barDamageList, scaling, settingLimbusStyle, checkResult, messageValues, thisRoundSpeed, nextRoundSpeed); + /* Checks and Reset are always processed. Other AutoEffects are not processed if the last check failed */ + switch (AutoEffect[0][0]) { + case "Require": tempOutput = autoEffectRequire(AutoEffect[0], ailmentList, barList, barDamageList); break; + case "Consume": tempOutput = autoEffectConsume(AutoEffect[0], ailmentList, barList); break; + case "Reset": tempOutput = {checkResult: "success", scaling: 1}; break; + case "CustomMessage": tempOutput = autoEffectCustomMessage(AutoEffect[0], messageValues); break; + default: tempOutput = {}; break; + } + if (checkResult != "failure") { + switch (AutoEffect[0][0]) { + case "Require": case "Consume": case "Reset": case "CustomMessage": break; /* Already executed above */ + case "Gain": tempOutput = autoEffectAilment(AutoEffect[0], ailmentList, scaling, settingLimbusStyle); break; + case "Inflict": tempOutput = autoEffectAilment(AutoEffect[0], ailmentList, scaling, settingLimbusStyle); break; + case "Give": tempOutput = autoEffectAilment(AutoEffect[0], ailmentList, scaling, settingLimbusStyle); break; + case "Set": tempOutput = autoEffectSetBar(AutoEffect[0], barList, scaling); break; + case "Add": tempOutput = autoEffectAddBar(AutoEffect[0], barList, scaling); break; + case "Multi": tempOutput = autoEffectMultiBar(AutoEffect[0], barList, scaling); break; + case "DicePower": tempOutput = autoEffectDice(AutoEffect[0], scaling); break; + case "DiceMax": tempOutput = autoEffectDice(AutoEffect[0], scaling); break; + case "DiceCount": tempOutput = autoEffectDice(AutoEffect[0], scaling); break; + case "BaseDamage": tempOutput = autoEffectDamage(AutoEffect[0], barList, scaling); break; + case "FlatDamage": tempOutput = autoEffectDamage(AutoEffect[0], barList, scaling); break; + case "ChallengeRoll": tempOutput = autoEffectChallengeRoll(AutoEffect[0], scaling); break; + case "Speed": tempOutput = autoEffectSpeed(AutoEffect[0], scaling, thisRoundSpeed, nextRoundSpeed); break; + default: tempOutput = {error:true}; autoEffectErrorMessage(`${AutoEffect} is not a valid AutoEffect`, AutoEffect); break; + } + } console.log(tempOutput) /* Handle errors. Continues executing AutoEffects for the sake of finding additional errors, */ @@ -15062,7 +15104,11 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals /* Handle message */ if (tempOutput.message != undefined) { - message += tempOutput.message; + if (autoEffectType == "conditional message" || autoEffectType == "conditional message + button") { + conditionalMessageList[autoEffectConditional] += tempOutput.message; + } else { + message += tempOutput.message; + } delete tempOutput.message; } @@ -15071,16 +15117,24 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals messageValues = tempOutput.messageValues; delete tempOutput.messageValues; } + + /* Handle conditional message + button having silent AutoEffects */ + if (autoEffectType == "conditional message + button") { + AutoEffect[0].push("Silent"); + } + console.log(AutoEffect) /* Add attribute changes from AutoEffect to output */ /* The first time a attribute is modified, add its count */ /* For example, if Gain 3 Burn is used and current Burn is 2, output Burn is set to 5 */ /* If Consume 4 Burn is used later, this amount will be removed without adding count */ for (const property in tempOutput) { - if (output.hasOwnProperty(property)) { - output[property] += Math.floor(tempOutput[property]); - } else { - output[property] = Math.floor(tempOutput[property] + tempOutput.count); + if (autoEffectType == "standard") { + if (output.hasOwnProperty(property)) { + output[property] += Math.floor(tempOutput[property]); + } else { + output[property] = Math.floor(tempOutput[property] + tempOutput.count); + } } } } @@ -15090,7 +15144,7 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals setAttrs(output); /* Create conditional buttons */ - for (const [buttonName, buttonAutoScript] of Object.entries(conditionalList)) { + for (const [buttonName, buttonAutoScript] of Object.entries(conditionalButtonList)) { /* Checks if any checks failed and the button should not be displayed */ if (buttonAutoScript.indexOf("#Do not display#") != -1) { continue; } createConditionalButton(buttonName, buttonAutoScript); @@ -15225,41 +15279,6 @@ function AutoScriptToArray(inputAutoScript, mode="normal") { /*--- AutoEffect functions ---*/ -function autoEffectExecute(AutoEffect, ailmentList, barList, barDamageList, scaling=1, settingLimbusStyle="false", checkResult="success", messageValues={}, thisRoundSpeed="0", nextRoundSpeed="0") { - - let tempOutput = {}; - - /* Checks and Reset are always processed. Other AutoEffects are not processed if the last check failed */ - switch (AutoEffect[0]) { - case "Require": tempOutput = autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList); break; - case "Consume": tempOutput = autoEffectConsume(AutoEffect, ailmentList, barList); break; - case "Reset": tempOutput = {checkResult: "success", scaling: 1}; break; - case "CustomMessage": tempOutput = autoEffectCustomMessage(AutoEffect, messageValues); break; - default: tempOutput = {}; break; - } - if (checkResult != "failure") { - switch (AutoEffect[0]) { - case "Require": case "Consume": case "Reset": case "CustomMessage": break; /* Already executed above */ - case "Gain": tempOutput = autoEffectAilment(AutoEffect, ailmentList, scaling, settingLimbusStyle); break; - case "Inflict": tempOutput = autoEffectAilment(AutoEffect, ailmentList, scaling, settingLimbusStyle); break; - case "Give": tempOutput = autoEffectAilment(AutoEffect, ailmentList, scaling, settingLimbusStyle); break; - case "Set": tempOutput = autoEffectSetBar(AutoEffect, barList, scaling); break; - case "Add": tempOutput = autoEffectAddBar(AutoEffect, barList, scaling); break; - case "Multi": tempOutput = autoEffectMultiBar(AutoEffect, barList, scaling); break; - case "DicePower": tempOutput = autoEffectDice(AutoEffect, scaling); break; - case "DiceMax": tempOutput = autoEffectDice(AutoEffect, scaling); break; - case "DiceCount": tempOutput = autoEffectDice(AutoEffect, scaling); break; - case "BaseDamage": tempOutput = autoEffectDamage(AutoEffect, barList, scaling); break; - case "FlatDamage": tempOutput = autoEffectDamage(AutoEffect, barList, scaling); break; - case "ChallengeRoll": tempOutput = autoEffectChallengeRoll(AutoEffect, scaling); break; - case "Speed": tempOutput = autoEffectSpeed(AutoEffect, scaling, thisRoundSpeed, nextRoundSpeed); break; - default: tempOutput = {error:true}; autoEffectErrorMessage(`${AutoEffect} is not a valid AutoEffect`, AutoEffect); break; - } - } - - return tempOutput; -} - function autoEffectMessage(messageFormat, effectTarget="No target", effectVal=0, effectCount=0, scaling=1, checkResult="success", settingLimbusStyle="false") { if(messageFormat != ""){ let message = messageFormat; @@ -15364,6 +15383,12 @@ function autoEffectCustomMessage(AutoEffect, messageValues = {}) { let checkResult = "success"; let settingLimbusStyle = "false"; + /* Check if CustomMessage is silent. No reason to do any formatting being that the message will not be displayed anyways */ + let silent = "false"; + if (AutoEffect.indexOf("Silent") > AutoEffect.lastIndexOf('"')) { + silent = "true"; + } + if (AutoEffect[1] != undefined) { messageFormat = AutoEffect.slice(1).join(" "); } if ((/\"[ \t]*(checksuccess)/ig).test(messageFormat)) { messageFormat = messageFormat.replaceAll(/\"[ \t]*(checksuccess)/ig, "") } else if ((/\"[ \t]*(checkfailure)/ig).test(messageFormat)) { checkResultOption = "failure"; messageFormat = messageFormat.replaceAll(/\"[ \t]*(checkfailure)/ig, "") } @@ -15377,7 +15402,7 @@ function autoEffectCustomMessage(AutoEffect, messageValues = {}) { if (messageValues.checkResult != undefined) { checkResult = messageValues.checkResult.replace("last ","");} if (messageValues.settingLimbusStyle != undefined) { settingLimbusStyle = messageValues.settingLimbusStyle; } - if (checkResult == checkResultOption || checkResultOption == "ignore") { + if (silent == "false" && (checkResult == checkResultOption || checkResultOption == "ignore")) { return { message: autoEffectMessage(messageFormat, effectTarget, effectVal, effectCount, scaling, checkResult, settingLimbusStyle) } } else { return {} From 6daa6b630eef4282d1c5be82bff7d66fc3c269fa Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Sat, 3 Aug 2024 16:47:25 +0200 Subject: [PATCH 31/55] Bugfix: AutoEffect message with no non-conditionals displays "undefined" in roll messages --- ProjectMoonTRPG/ProjectMoonTRPG.html | 53 ++++++++++++++-------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 843ab437d2..90f530bc17 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -14869,7 +14869,7 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals if (egoAutoScript == null) { egoAutoScript = ""; } } - let collectedAutoScripts = AutoScriptToArray(augmentAutoScript + outfitAutoScript + egoAutoScript, "nested"); + let collectedAutoScripts = autoScriptToArray(augmentAutoScript + outfitAutoScript + egoAutoScript, "nested"); collectedAutoScripts.forEach((trigger) => { if (autoScriptTriggers.includes(trigger[0])) { @@ -14879,7 +14879,7 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals }); /* Convert AutoScript to an array */ - AutoScript = AutoScriptToArray(AutoScript); + AutoScript = autoScriptToArray(AutoScript); /* Get relevant attributes */ getAttrs(["settingMuteMessage", "settingWhisperRolls", "settingWhisperTarget", "settingLimbusStyle", "settingHideNextTurn", @@ -15000,7 +15000,6 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals } else { conditionalButtonList[autoEffectConditional] = "(" + AutoEffect[0].toString().replaceAll(","," ") + conditionalButtonSilent + ")"; } - console.log(conditionalButtonList[autoEffectConditional]) /* If AutoEffect is Require or Consume, do not display the button if the check will fail */ if (AutoEffect[0][0] == "Require" || AutoEffect[0][0] == "Consume") { @@ -15105,7 +15104,11 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals /* Handle message */ if (tempOutput.message != undefined) { if (autoEffectType == "conditional message" || autoEffectType == "conditional message + button") { - conditionalMessageList[autoEffectConditional] += tempOutput.message; + if (conditionalMessageList[autoEffectConditional] != undefined) { + conditionalMessageList[autoEffectConditional] += tempOutput.message; + } else { + conditionalMessageList[autoEffectConditional] = tempOutput.message; + } } else { message += tempOutput.message; } @@ -15158,13 +15161,10 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals /* Message handling */ if (settingMuteMessage != "true" && message != "") { - let newmessage = "
" - if (returnMessage == "false") { let messageHeaderIcon = getIcon("icons", "gear"); - newmessage += message + "
"; - setAttrs({dummyIcon: messageHeaderIcon, dummy: newmessage}); + setAttrs({dummyIcon: messageHeaderIcon, dummy: "
" + message + "
"}); let whisper = ""; if(settingWhisperRolls == "true"){ @@ -15176,28 +15176,17 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals }); } else { - newmessage += `
` - newmessage += `
` - newmessage += `${getIcon("icons", "gear")}` - newmessage += `
` - newmessage += `
AutoEffects
` - newmessage += `
` + message + "
"; - - returnValues.message = newmessage; + returnValues.message = autoEffectEntry("AutoEffects", message, "gear"); } } /* Conditional message handling */ for (const [conditionName, conditionMessage] of Object.entries(conditionalMessageList)) { - let newmessage = "
"; - newmessage += `
` - newmessage += `
` - newmessage += `${getIcon("icons", "gear")}` - newmessage += `
` - newmessage += `
${conditionName}
` - newmessage += `
` + conditionMessage + "
"; - - returnValues.message += newmessage; + if (returnValues.message == undefined) { + returnValues.message = autoEffectEntry(conditionName, conditionMessage, "gear"); + } else { + returnValues.message += autoEffectEntry(conditionName, conditionMessage, "gear"); + } } /* Error handling and returnValues callback */ @@ -15224,7 +15213,7 @@ function cleanAutoScript(AutoScript) { /* Converts an AutoScript from a string to an array */ /* mode: normal is for strings of type (AutoEffect...) (AutoEffect...) ... */ /* mode: nested is for strings of type [#Offensive, (AutoEffect...) ... #] [#Round start, (AutoEffect...) ... ]*/ -function AutoScriptToArray(inputAutoScript, mode="normal") { +function autoScriptToArray(inputAutoScript, mode="normal") { let AutoScript = inputAutoScript; let AutoEffect = ""; let AutoEffectArray = []; @@ -15279,6 +15268,18 @@ function AutoScriptToArray(inputAutoScript, mode="normal") { /*--- AutoEffect functions ---*/ +function autoEffectEntry(header, message, iconName) { + let newEntry = "
" + newEntry += `
` + newEntry += `
` + newEntry += `${getIcon("icons", iconName)}` + newEntry += `
`; + newEntry += `
${header}
` + newEntry += `
` + message + "
"; + + return newEntry; +} + function autoEffectMessage(messageFormat, effectTarget="No target", effectVal=0, effectCount=0, scaling=1, checkResult="success", settingLimbusStyle="false") { if(messageFormat != ""){ let message = messageFormat; From 09bc84bd04308abafcc4f08f95ac82ec085867f8 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Sat, 3 Aug 2024 21:40:05 +0200 Subject: [PATCH 32/55] AutoEffects: part 16 - Full translation support has been added. AutoEffects can be configured to have custom formatting and names. Uses translated autoeffect names, options, bars, ailments, triggers and custom message matches - Cannot test this, but one should be able to write AutoEffects in a translated language and still have them execute correctly. If not they can still be written in English, or a mix of English and one's native language --- ProjectMoonTRPG/ProjectMoonTRPG.html | 590 +++++++++++++++++---------- ProjectMoonTRPG/translation.json | 76 +++- 2 files changed, 452 insertions(+), 214 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 90f530bc17..5ab6c60f51 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -14872,7 +14872,7 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals let collectedAutoScripts = autoScriptToArray(augmentAutoScript + outfitAutoScript + egoAutoScript, "nested"); collectedAutoScripts.forEach((trigger) => { - if (autoScriptTriggers.includes(trigger[0])) { + if (autoScriptTriggers.includes(getTriggerFromTranslation(trigger[0]))) { if (AutoScript != "") { AutoScript += "(Reset)"; } AutoScript += trigger[1]; } @@ -14881,6 +14881,9 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals /* Convert AutoScript to an array */ AutoScript = autoScriptToArray(AutoScript); + /* Translates AutoEffect names, bars and ailments to English */ + AutoScript = translateAutoScriptArrayToEnglish(AutoScript); + /* Get relevant attributes */ getAttrs(["settingMuteMessage", "settingWhisperRolls", "settingWhisperTarget", "settingLimbusStyle", "settingHideNextTurn", "HP", "HP_max", "StagRes", "StagRes_max", "SP", "SP_max", "thisRoundSpeed", "nextRoundSpeed", @@ -14967,180 +14970,180 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals ailmentList[ailName] = [ailHasNextTurn, ailNum, ailNumNextTurn, id, ailIcon]; }); - console.log(AutoScript) - /* Execute each AutoEffect in the AutoScript */ - AutoScript.forEach(AutoEffect => { - if (AutoEffect == undefined) { + /* Execute each AutoEffect in the AutoScript */ + AutoScript.forEach(AutoEffect => { + if (AutoEffect == undefined) { + return; + } + /* Handle conditional */ + if (AutoEffect.length > 1) { + AutoEffect.slice(1).forEach(conditional => { + /* If conditional message, execute the script as normal but do not apply any effects and add the message to a seperate section */ + if (conditional.includes("#Message") && !conditional.includes("#MessageButton")) { + autoEffectConditional = conditional.replace("#Message","").trim(); + autoEffectType = "conditional message"; + } + /* If conditional button, add AutoEffect to either a new conditional button or a existing one */ + /* If conditional message + button, add Silent to AutoEffect after execution */ + else { + if (conditional.includes("#MessageButton")) { + autoEffectConditional = conditional.replace("#MessageButton","").trim(); + conditionalButtonSilent = AutoEffect[0].includes("Silent") ? "" : " " + "Silent"; + autoEffectType = "conditional message + button"; + } else { + autoEffectConditional = conditional.replace("Button","").trim(); + conditionalButtonSilent = ""; + autoEffectType = "conditional button"; + } + + if (conditionalButtonList.hasOwnProperty(autoEffectConditional)) { + conditionalButtonList[autoEffectConditional] += " (" + AutoEffect[0].toString().replaceAll(","," ") + conditionalButtonSilent + ")"; + } else { + conditionalButtonList[autoEffectConditional] = "(" + AutoEffect[0].toString().replaceAll(","," ") + conditionalButtonSilent + ")"; + } + + /* If AutoEffect is Require or Consume, do not display the button if the check will fail */ + if (AutoEffect[0][0] == "Require" || AutoEffect[0][0] == "Consume") { + switch (AutoEffect[0][0]) { + case "Require": tempOutput = autoEffectRequire(AutoEffect[0], ailmentList, barList, barDamageList); break; + case "Consume": tempOutput = autoEffectConsume(AutoEffect[0], ailmentList, barList); break; + default: tempOutput = {}; break; + } + if (tempOutput.checkResult == "failure") { + conditionalButtonList[autoEffectConditional] = "#Do not display#"; + } + } + } + }); + } else { + autoEffectType = "standard"; + } + /* If not conditional, process AutoEffect as normal */ + if (autoEffectType != "conditional button") { + /* Checks and Reset are always processed. Other AutoEffects are not processed if the last check failed */ + switch (AutoEffect[0][0]) { + case "Require": tempOutput = autoEffectRequire(AutoEffect[0], ailmentList, barList, barDamageList); break; + case "Consume": tempOutput = autoEffectConsume(AutoEffect[0], ailmentList, barList); break; + case "Reset": tempOutput = {checkResult: "success", scaling: 1}; break; + case "CustomMessage": tempOutput = autoEffectCustomMessage(AutoEffect[0], messageValues); break; + default: tempOutput = {}; break; + } + if (checkResult != "failure") { + switch (AutoEffect[0][0]) { + case "Require": case "Consume": case "Reset": case "CustomMessage": break; /* Already executed above */ + case "Gain": tempOutput = autoEffectAilment(AutoEffect[0], ailmentList, scaling, settingLimbusStyle); break; + case "Inflict": tempOutput = autoEffectAilment(AutoEffect[0], ailmentList, scaling, settingLimbusStyle); break; + case "Give": tempOutput = autoEffectAilment(AutoEffect[0], ailmentList, scaling, settingLimbusStyle); break; + case "Set": tempOutput = autoEffectSetBar(AutoEffect[0], barList, scaling); break; + case "Add": tempOutput = autoEffectAddBar(AutoEffect[0], barList, scaling); break; + case "Multi": tempOutput = autoEffectMultiBar(AutoEffect[0], barList, scaling); break; + case "DicePower": tempOutput = autoEffectDice(AutoEffect[0], scaling); break; + case "DiceMax": tempOutput = autoEffectDice(AutoEffect[0], scaling); break; + case "DiceCount": tempOutput = autoEffectDice(AutoEffect[0], scaling); break; + case "BaseDamage": tempOutput = autoEffectDamage(AutoEffect[0], barList, scaling); break; + case "FlatDamage": tempOutput = autoEffectDamage(AutoEffect[0], barList, scaling); break; + case "ChallengeRoll": tempOutput = autoEffectChallengeRoll(AutoEffect[0], scaling); break; + case "Speed": tempOutput = autoEffectSpeed(AutoEffect[0], scaling, thisRoundSpeed, nextRoundSpeed); break; + default: tempOutput = {error:true}; autoEffectErrorMessage(`${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); break; + } + } + console.log(tempOutput) + + /* Handle errors. Continues executing AutoEffects for the sake of finding additional errors, */ + /* but does not apply any changes to attributes */ + if (tempOutput.hasOwnProperty("error") || returnValues.error == true) { + returnValues.error == true; + output = {}; return; } - /* Handle conditional */ - if (AutoEffect.length > 1) { - AutoEffect.slice(1).forEach(conditional => { - /* If conditional message, execute the script as normal but do not apply any effects and add the message to a seperate section */ - if (conditional.includes("#Message") && !conditional.includes("#MessageButton")) { - autoEffectConditional = conditional.replace("#Message","").trim(); - autoEffectType = "conditional message"; - } - /* If conditional button, add AutoEffect to either a new conditional button or a existing one */ - /* If conditional message + button, add Silent to AutoEffect after execution */ - else { - if (conditional.includes("#MessageButton") || conditional.includes("#ButtonMessage")) { - autoEffectConditional = conditional.replace("#MessageButton","").replace("#ButtonMessage","").trim(); - conditionalButtonSilent = AutoEffect[0].includes("Silent") ? "" : " Silent"; - autoEffectType = "conditional message + button"; - } else { - autoEffectConditional = conditional.replace("#Button","").trim(); - conditionalButtonSilent = ""; - autoEffectType = "conditional button"; - } - if (conditionalButtonList.hasOwnProperty(autoEffectConditional)) { - conditionalButtonList[autoEffectConditional] += " (" + AutoEffect[0].toString().replaceAll(","," ") + conditionalButtonSilent + ")"; - } else { - conditionalButtonList[autoEffectConditional] = "(" + AutoEffect[0].toString().replaceAll(","," ") + conditionalButtonSilent + ")"; - } - - /* If AutoEffect is Require or Consume, do not display the button if the check will fail */ - if (AutoEffect[0][0] == "Require" || AutoEffect[0][0] == "Consume") { - switch (AutoEffect[0][0]) { - case "Require": tempOutput = autoEffectRequire(AutoEffect[0], ailmentList, barList, barDamageList); break; - case "Consume": tempOutput = autoEffectConsume(AutoEffect[0], ailmentList, barList); break; - default: tempOutput = {}; break; - } - if (tempOutput.checkResult == "failure") { - conditionalButtonList[autoEffectConditional] = "#Do not display#"; - } - } - } - }); - } else { - autoEffectType = "standard"; + /* Handle changes to scaling */ + if (tempOutput.hasOwnProperty("scaling")) { + scaling = parseInt(tempOutput.scaling); + delete tempOutput.scaling; } - /* If not conditional, process AutoEffect as normal */ - if (autoEffectType != "conditional button") { - /* Checks and Reset are always processed. Other AutoEffects are not processed if the last check failed */ - /* Checks and Reset are always processed. Other AutoEffects are not processed if the last check failed */ - switch (AutoEffect[0][0]) { - case "Require": tempOutput = autoEffectRequire(AutoEffect[0], ailmentList, barList, barDamageList); break; - case "Consume": tempOutput = autoEffectConsume(AutoEffect[0], ailmentList, barList); break; - case "Reset": tempOutput = {checkResult: "success", scaling: 1}; break; - case "CustomMessage": tempOutput = autoEffectCustomMessage(AutoEffect[0], messageValues); break; - default: tempOutput = {}; break; + + /* Handle check results from Require and Consume */ + /* For the returnValues, the worst result is returned */ + if (tempOutput.checkResult != undefined) { + checkResult = tempOutput.checkResult; + if (returnValues.checkResult == "success") { + returnValues.checkResult = tempOutput.checkResult; } - if (checkResult != "failure") { - switch (AutoEffect[0][0]) { - case "Require": case "Consume": case "Reset": case "CustomMessage": break; /* Already executed above */ - case "Gain": tempOutput = autoEffectAilment(AutoEffect[0], ailmentList, scaling, settingLimbusStyle); break; - case "Inflict": tempOutput = autoEffectAilment(AutoEffect[0], ailmentList, scaling, settingLimbusStyle); break; - case "Give": tempOutput = autoEffectAilment(AutoEffect[0], ailmentList, scaling, settingLimbusStyle); break; - case "Set": tempOutput = autoEffectSetBar(AutoEffect[0], barList, scaling); break; - case "Add": tempOutput = autoEffectAddBar(AutoEffect[0], barList, scaling); break; - case "Multi": tempOutput = autoEffectMultiBar(AutoEffect[0], barList, scaling); break; - case "DicePower": tempOutput = autoEffectDice(AutoEffect[0], scaling); break; - case "DiceMax": tempOutput = autoEffectDice(AutoEffect[0], scaling); break; - case "DiceCount": tempOutput = autoEffectDice(AutoEffect[0], scaling); break; - case "BaseDamage": tempOutput = autoEffectDamage(AutoEffect[0], barList, scaling); break; - case "FlatDamage": tempOutput = autoEffectDamage(AutoEffect[0], barList, scaling); break; - case "ChallengeRoll": tempOutput = autoEffectChallengeRoll(AutoEffect[0], scaling); break; - case "Speed": tempOutput = autoEffectSpeed(AutoEffect[0], scaling, thisRoundSpeed, nextRoundSpeed); break; - default: tempOutput = {error:true}; autoEffectErrorMessage(`${AutoEffect} is not a valid AutoEffect`, AutoEffect); break; - } + else if (returnValues.checkResult == "last success" && tempOutput.checkResult == "failure") { + returnValues.checkResult = tempOutput.checkResult; } - console.log(tempOutput) + delete tempOutput.checkResult; + } + + /* Handle updating ailmentList and barList after a successful Consume AutoEffect */ + if (tempOutput.consumeList != undefined) { + if (tempOutput.consumeList == "barList") { + barList[tempOutput.consumeTarget] = parseInt(barList[tempOutput.consumeTarget]) + parseInt(tempOutput.consumeVal); + } else { + ailmentList[tempOutput.consumeTarget][1] = parseInt(ailmentList[tempOutput.consumeTarget][1]) + parseInt(tempOutput.consumeVal); + } + delete tempOutput.consumeList; + delete tempOutput.consumeVal; + delete tempOutput.consumeVal; + } + + /* Handle DicePower, DiceMax, DiceCount and Speed with Combat duration */ + if (tempOutput.dicePower != undefined) { returnValues.dicePower = tempOutput.dicePower } + if (tempOutput.diceMax != undefined) { returnValues.diceMax = tempOutput.diceMax } + if (tempOutput.diceCount != undefined) { returnValues.diceCount = tempOutput.diceCount } + if (tempOutput.speedCombat != undefined) { returnValues.speedCombat = tempOutput.speedCombat } + + /* Handle challenge rolls */ + if (tempOutput.challengeRollStat != undefined) { + challengeRollList[tempOutput.challengeRollStat] = tempOutput.challengeRollDifficulty; + delete tempOutput.challengeRollStat; + delete tempOutput.challengeRollDifficulty; + } + + /* Handle message */ + if (tempOutput.message != undefined) { + /* Translate output message. Targets are still written in English */ + tempOutput.message = autoEffectTranslateMessage(tempOutput.message); - /* Handle errors. Continues executing AutoEffects for the sake of finding additional errors, */ - /* but does not apply any changes to attributes */ - if (tempOutput.hasOwnProperty("error") || returnValues.error == true) { - returnValues.error == true; - output = {}; - return; - } - - /* Handle changes to scaling */ - if (tempOutput.hasOwnProperty("scaling")) { - scaling = parseInt(tempOutput.scaling); - delete tempOutput.scaling; - } - - /* Handle check results from Require and Consume */ - /* For the returnValues, the worst result is returned */ - if (tempOutput.checkResult != undefined) { - checkResult = tempOutput.checkResult; - if (returnValues.checkResult == "success") { - returnValues.checkResult = tempOutput.checkResult; - } - else if (returnValues.checkResult == "last success" && tempOutput.checkResult == "failure") { - returnValues.checkResult = tempOutput.checkResult; - } - delete tempOutput.checkResult; - } - - /* Handle updating ailmentList and barList after a successful Consume AutoEffect */ - if (tempOutput.consumeList != undefined) { - if (tempOutput.consumeList == "barList") { - barList[tempOutput.consumeTarget] = parseInt(barList[tempOutput.consumeTarget]) + parseInt(tempOutput.consumeVal); + if (autoEffectType == "conditional message" || autoEffectType == "conditional message + button") { + if (conditionalMessageList[autoEffectConditional] != undefined) { + conditionalMessageList[autoEffectConditional] += tempOutput.message; } else { - ailmentList[tempOutput.consumeTarget][1] = parseInt(ailmentList[tempOutput.consumeTarget][1]) + parseInt(tempOutput.consumeVal); + conditionalMessageList[autoEffectConditional] = tempOutput.message; } - delete tempOutput.consumeList; - delete tempOutput.consumeVal; - delete tempOutput.consumeVal; + } else { + message += tempOutput.message; } + delete tempOutput.message; + } - /* Handle DicePower, DiceMax, DiceCount and Speed with Combat duration */ - if (tempOutput.dicePower != undefined) { returnValues.dicePower = tempOutput.dicePower } - if (tempOutput.diceMax != undefined) { returnValues.diceMax = tempOutput.diceMax } - if (tempOutput.diceCount != undefined) { returnValues.diceCount = tempOutput.diceCount } - if (tempOutput.speedCombat != undefined) { returnValues.speedCombat = tempOutput.speedCombat } + /* Handle messageValues. Used by the CustomMessage AutoEffect. Outputted by all AutoEffects that generate messages */ + if (tempOutput.messageValues != undefined) { + messageValues = tempOutput.messageValues; + delete tempOutput.messageValues; + } - /* Handle challenge rolls */ - if (tempOutput.challengeRollStat != undefined) { - challengeRollList[tempOutput.challengeRollStat] = tempOutput.challengeRollDifficulty; - delete tempOutput.challengeRollStat; - delete tempOutput.challengeRollDifficulty; - } - - /* Handle message */ - if (tempOutput.message != undefined) { - if (autoEffectType == "conditional message" || autoEffectType == "conditional message + button") { - if (conditionalMessageList[autoEffectConditional] != undefined) { - conditionalMessageList[autoEffectConditional] += tempOutput.message; - } else { - conditionalMessageList[autoEffectConditional] = tempOutput.message; - } + /* Handle conditional message + button having silent AutoEffects */ + if (autoEffectType == "conditional message + button") { + AutoEffect[0].push("Silent"); + } + + /* Add attribute changes from AutoEffect to output */ + /* The first time a attribute is modified, add its count */ + /* For example, if Gain 3 Burn is used and current Burn is 2, output Burn is set to 5 */ + /* If Consume 4 Burn is used later, this amount will be removed without adding count */ + for (const property in tempOutput) { + if (autoEffectType == "standard") { + if (output.hasOwnProperty(property)) { + output[property] += Math.floor(tempOutput[property]); } else { - message += tempOutput.message; - } - delete tempOutput.message; - } - - /* Handle messageValues. Used by the CustomMessage AutoEffect. Outputted by all AutoEffects that generate messages */ - if (tempOutput.messageValues != undefined) { - messageValues = tempOutput.messageValues; - delete tempOutput.messageValues; - } - - /* Handle conditional message + button having silent AutoEffects */ - if (autoEffectType == "conditional message + button") { - AutoEffect[0].push("Silent"); - } - console.log(AutoEffect) - - /* Add attribute changes from AutoEffect to output */ - /* The first time a attribute is modified, add its count */ - /* For example, if Gain 3 Burn is used and current Burn is 2, output Burn is set to 5 */ - /* If Consume 4 Burn is used later, this amount will be removed without adding count */ - for (const property in tempOutput) { - if (autoEffectType == "standard") { - if (output.hasOwnProperty(property)) { - output[property] += Math.floor(tempOutput[property]); - } else { - output[property] = Math.floor(tempOutput[property] + tempOutput.count); - } + output[property] = Math.floor(tempOutput[property] + tempOutput.count); } } } + } }); // console.log(output) @@ -15262,6 +15265,42 @@ function autoScriptToArray(inputAutoScript, mode="normal") { /* Return the converted AutoScript */ return AutoScriptArray; } + +function translateAutoScriptArrayToEnglish(AutoScript) { + for (let i = 0; i < AutoScript.length; i++) { + /* Translate AutoEffect names */ + AutoScript[i][0][0] = getAutoEffectFromTranslation(AutoScript[i][0][0]); + + /* Translate Ailments and Bars */ + switch (AutoScript[i][0][0]) { + case "Reset": case "CustomMessage": case "DicePower": case "DiceMax": case "DiceCount": case "BaseDamage": break; + case "Require": case "Consume": AutoScript[i][0][2] = getAilmentOrBarFromTranslation(AutoScript[i][0][2]); break; + case "Gain": case "Inflict": case "Give": AutoScript[i][0][2] = getAilmentFromTranslation(AutoScript[i][0][2]); break; + case "Set": case "Add": case "Multi": case "FlatDamage": AutoScript[i][0][2] = getBarFromTranslation(AutoScript[i][0][2]); break; + case "ChallengeRoll": AutoScript[i][0][1] = getStatFromTranslation(AutoScript[i][0][1]); break; + default: console.log("Translation error with AutoEffect name " + AutoScript[i][0][0]) + } + + /* Translate Options */ + for (let j = 0; j < AutoScript[i][0].length; j++) { + if(getOptionFromTranslation(AutoScript[i][0][j]) != "Unknown Option") { + AutoScript[i][0][j] = getOptionFromTranslation(AutoScript[i][0][j]); + } + } + + /* Translate conditional options */ + let langButtonOption = getTranslationByKey("autoeffect-option-button"); + let langMessageOption = getTranslationByKey("autoeffect-option-message"); + let langMessageButtonOption = getTranslationByKey("autoeffect-option-messagebutton"); + + /*for (let k = 0; k < AutoScript[i].length; k++) { + AutoScript[i][k] = AutoScript[i][k].replace(langButtonOption,"#Button"); + AutoScript[i][k] = AutoScript[i][k].replace(langMessageOption,"#Message"); + AutoScript[i][k] = AutoScript[i][k].replace(langMessageButtonOption,"#MessageButton"); + }*/ + } + return AutoScript; +} /*--- AutoScript functions end ---*/ @@ -15284,30 +15323,19 @@ function autoEffectMessage(messageFormat, effectTarget="No target", effectVal=0, if(messageFormat != ""){ let message = messageFormat; - let langCheck = "[CHECK]"; - let langSuccess = "Success"; - let langFailure = "Failure"; - let langNum = "[NUM]"; - let langScaling = "[SCALING]"; - let langScalingNum = "[SCALING NUM]"; - let langNegNum = "[-NUM]"; - let langNegScaling = "[-SCALING]"; - let langNegScalingNum = "[-SCALING NUM]"; - let langInitial = "[INITIAL]"; - let langResult = "[RESULT]"; - let langTarget = "[TARGET]"; - let langTargetIcon = "[/TARGET]"; - - /*if(getTranslationByKey("message-match-check") != false){ - langCheck = getTranslationByKey("message-match-check"); - langSuccess = getTranslationByKey("distortion-result-good"); - langFailure = getTranslationByKey("distortion-result-bad"); - langNum = getTranslationByKey("message-match-num"); - langScaling = getTranslationByKey("message-match-scaling"); - langScalingNum = getTranslationByKey("message-match-scalingnum"); - langTarget = getTranslationByKey("message-match-target"); - langTargetIcon = getTranslationByKey("message-match-targeticon"); - }*/ + let langCheck = getTranslationByKeyCustom("[CHECK]", "autoeffect-match-check"); + let langSuccess = getTranslationByKeyCustom("Success", "distort-results-good"); + let langFailure = getTranslationByKeyCustom("Failure", "distort-results-bad"); + let langNum = getTranslationByKeyCustom("[NUM]", "autoeffect-match-num"); + let langScaling = getTranslationByKeyCustom("[SCALING]", "autoeffect-match-scaling"); + let langScalingNum = getTranslationByKeyCustom("[SCALING NUM]", "autoeffect-match-scalingnum"); + let langNegNum = getTranslationByKeyCustom("[-NUM]", "autoeffect-match-neg-num"); + let langNegScaling = getTranslationByKeyCustom("[-SCALING]", "autoeffect-match-neg-scaling"); + let langNegScalingNum = getTranslationByKeyCustom("[-SCALING NUM]", "autoeffect-match-neg-scalingnum"); + let langInitial = getTranslationByKeyCustom("[INITIAL]", "autoeffect-match-initial"); + let langResult = getTranslationByKeyCustom("[RESULT]", "autoeffect-match-result"); + let langTarget = getTranslationByKeyCustom("[TARGET]", "autoeffect-match-target"); + let langTargetIcon = getTranslationByKeyCustom("[/TARGET]", "autoeffect-match-targeticon"); if (checkResult == "failure") { message = message.replaceAll(langCheck, "" + langFailure + ""); } else { message = message.replaceAll(langCheck, "" + langSuccess + ""); } @@ -15348,6 +15376,32 @@ function autoEffectMessage(messageFormat, effectTarget="No target", effectVal=0, } } +function autoEffectTranslateMessage(message) { + let returnMessage = message + .replaceAll("Burn", getTranslationByKeyCustom("Burn","ailments-burn")) + .replaceAll("Bleed", getTranslationByKeyCustom("Bleed","ailments-bleed")) + .replaceAll("Paralysis", getTranslationByKeyCustom("Paralysis","ailments-paralysis")) + .replaceAll("Fragile", getTranslationByKeyCustom("Fragile","ailments-fragile")) + .replaceAll("Protection", getTranslationByKeyCustom("Protection","ailments-protection")) + .replaceAll("Stagger Protection", getTranslationByKeyCustom("Stagger Protection","ailments-stgprotection")) + .replaceAll("Strength", getTranslationByKeyCustom("Strength","ailments-strength")) + .replaceAll("Endurance", getTranslationByKeyCustom("Endurance","ailments-endurance")) + .replaceAll("Haste", getTranslationByKeyCustom("Haste","ailments-haste")) + .replaceAll("Feeble", getTranslationByKeyCustom("Feeble","ailments-feeble")) + .replaceAll("Disarm", getTranslationByKeyCustom("Disarm","ailments-disarm")) + .replaceAll("Bind", getTranslationByKeyCustom("Bind","ailments-bind")) + .replaceAll("Smoke", getTranslationByKeyCustom("Smoke","ailments-smoke")) + .replaceAll("Charge", getTranslationByKeyCustom("Charge","ailments-charge")) + .replaceAll("Fortune", getTranslationByKeyCustom("Fortune","ailments-fortune")) + .replaceAll("HP", getTranslationByKeyCustom("HP","bar-health-shortened")) + .replaceAll("ST", getTranslationByKeyCustom("ST","bar-stagres-shortened")) + .replaceAll("SP", getTranslationByKeyCustom("SP","bar-sanity-shortened")) + .replaceAll("THP", getTranslationByKeyCustom("THP","bar-health-temp-shortened")) + .replaceAll("TST", getTranslationByKeyCustom("TST","bar-stagres-temp-shortened")); + + return returnMessage; +} + /* Whispers an error message to the user detailing an AutoEffect error */ function autoEffectErrorMessage(errorString, autoEffect) { console.log(errorString + autoEffect) @@ -15373,8 +15427,6 @@ function resetConditionals() { function autoEffectCustomMessage(AutoEffect, messageValues = {}) { - console.log(messageValues) - let messageFormat = ""; let checkResultOption = "success"; let effectTarget = "No target"; @@ -15386,12 +15438,12 @@ function autoEffectCustomMessage(AutoEffect, messageValues = {}) { /* Check if CustomMessage is silent. No reason to do any formatting being that the message will not be displayed anyways */ let silent = "false"; - if (AutoEffect.indexOf("Silent") > AutoEffect.lastIndexOf('"')) { + if (AutoEffect.indexOf("#Silent") > AutoEffect.lastIndexOf('"')) { silent = "true"; } if (AutoEffect[1] != undefined) { messageFormat = AutoEffect.slice(1).join(" "); } - if ((/\"[ \t]*(checksuccess)/ig).test(messageFormat)) { messageFormat = messageFormat.replaceAll(/\"[ \t]*(checksuccess)/ig, "") } + if ((/\"[ \t]*(checksuccess)/ig).test(messageFormat)) { messageFormat = messageFormat.replaceAll((/\"[ \t]*(checksuccess)/ig), "") } else if ((/\"[ \t]*(checkfailure)/ig).test(messageFormat)) { checkResultOption = "failure"; messageFormat = messageFormat.replaceAll(/\"[ \t]*(checkfailure)/ig, "") } else if ((/\"[ \t]*(checkignore)/ig).test(messageFormat)) { checkResultOption = "ignore"; messageFormat = messageFormat.replaceAll(/\"[ \t]*(checkignore)/ig, "")} messageFormat = messageFormat.replaceAll('"',''); @@ -15422,7 +15474,7 @@ function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { /* Handle bar count */ else if (barList.hasOwnProperty(effectName)) { count = barList[effectName]; } /* Handle bar damage count */ - else if (barDamageList.hasOwnProperty(effectName)) { count = barDamageList[effectName]; } + else if (barDamageList.hasOwnProperty("-" + effectName)) { count = barDamageList[effectName]; } else { autoEffectErrorMessage(`Ailment, Bar or BarDamage "${effectName}" does not exist`, AutoEffect); return {error: true}; } /* Get required value. Recalculate count if percentage */ @@ -15462,7 +15514,8 @@ function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { } /* Handle message */ - let messageFormat = "Require [SCALING NUM] [TARGET]: [CHECK]"; + let messageFormat = getTranslationByKeyCustom("Require [SCALING NUM] [TARGET]: [CHECK]", "autoeffect-require"); + let effectIcon = effectName; if (ailmentList.hasOwnProperty(effectName)) { messageFormat = "[/TARGET] " + messageFormat; @@ -15532,11 +15585,12 @@ function autoEffectConsume(AutoEffect, ailmentList, barList) { } /* Handle message */ - let messageFormat = "Consume [SCALING NUM] [TARGET]: [CHECK]"; + let messageFormat = getTranslationByKeyCustom("Consume [SCALING NUM] [TARGET]: [CHECK]", "autoeffect-format-consume"); + let effectIcon = ailmentList[effectName][4]; if (ailmentList.hasOwnProperty(effectName)) { messageFormat = "[/TARGET] " + messageFormat; } - if (!(AutoEffect.includes("Silent"))) { + if (!AutoEffect.includes("Silent")) { returnValues.message = autoEffectMessage(messageFormat, effectName, effectVal, count, Math.max(scaling,1), returnValues.checkResult); } returnValues.messageValues = { effectTarget: effectIcon, effectVal: effectVal, effectCount: count, scaling: Math.max(scaling,1), checkResult: returnValues.checkResult } @@ -15597,9 +15651,9 @@ function autoEffectAilment(AutoEffect, ailmentList, scaling, settingLimbusStyle) let messageValues = {}; let messageFormat = ""; switch (autoEffectVariant) { - case "Gain": messageFormat = "[/TARGET] Gained [SCALING NUM] [TARGET]"; break; - case "Inflict": messageFormat = "[/TARGET] Inflict [SCALING NUM] [TARGET] to target"; break; - case "Give": messageFormat = "[/TARGET] Give [SCALING NUM] [TARGET] to ally"; break; + case "Gain": messageFormat = getTranslationByKeyCustom("[/TARGET] Gain [SCALING NUM] [TARGET]", "autoeffect-format-gain"); break; + case "Inflict": messageFormat = getTranslationByKeyCustom("[/TARGET] Inflict [SCALING NUM] [TARGET] to target", "autoeffect-format-inflict"); break; + case "Give": messageFormat = getTranslationByKeyCustom("[/TARGET] Give [SCALING NUM] [TARGET] to ally", "autoeffect-format-give"); break; } let effectIcon = ailmentList[effectAilment][4]; @@ -15641,7 +15695,7 @@ function autoEffectSetBar(AutoEffect, barList, scaling) { /* Handle message */ let message = ""; let messageValues = {}; - let messageFormat = "Set [TARGET] to [RESULT]"; + let messageFormat = getTranslationByKeyCustom("Set [TARGET] to [RESULT]", "autoeffect-format-set"); if (!AutoEffect.includes("Silent")) { message = autoEffectMessage(messageFormat, effectTarget, (parseInt(effectVal) - parseInt(count))/scaling, count, scaling, "success"); @@ -15676,8 +15730,8 @@ function autoEffectAddBar(AutoEffect, barList, scaling) { /* Handle message */ let message = ""; let messageValues = {}; - let messageFormat = "Regened [SCALING NUM] [TARGET]"; - if (effectVal < 0) { messageFormat = "Recieved [-SCALING NUM] [TARGET] damage"; } + let messageFormat = getTranslationByKeyCustom("Regen [SCALING NUM] [TARGET]", "autoeffect-format-add") + if (effectVal < 0) { messageFormat = getTranslationByKeyCustom("Receive [-SCALING NUM] [TARGET] damage", "autoeffect-format-add-neg"); } if (!AutoEffect.includes("Silent")) { message = autoEffectMessage(messageFormat, effectTarget, effectVal/scaling, count, scaling, "success"); @@ -15711,7 +15765,7 @@ function autoEffectMultiBar(AutoEffect, barList, scaling) { /* Handle message */ let message = ""; let messageValues = {}; - let messageFormat = `Multiplied [TARGET] by ${effectVal} [[SCALING NUM]]`; + let messageFormat = getTranslationByKeyCustom("Multiply [TARGET] by ", "autoeffect-format-multi1") + effectVal + getTranslationByKeyCustom(" [[SCALING NUM]]", "autoeffect-format-multi2"); if (!AutoEffect.includes("Silent")) { message = autoEffectMessage(messageFormat, effectTarget, Math.floor(parseFloat(effectVal) * parseInt(count) - parseInt(count))/scaling, count, scaling, "success"); @@ -15743,12 +15797,11 @@ function autoEffectDice(AutoEffect, scaling) { let effectVal = parseInt(AutoEffect[1]); if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } - /* Handle message */ /* Handle message */ let message = ""; let messageValues = {}; - let messageFormat = "Increased [TARGET] by [SCALING NUM]"; - if (effectVal < 0) { messageFormat = "Reduced [TARGET] by [SCALING NUM]"; } + let messageFormat = getTranslationByKeyCustom("Increase [TARGET] by [SCALING NUM]", "autoeffect-format-dice"); + if (effectVal < 0) { messageFormat = getTranslationByKeyCustom("Reduce [TARGET] by [SCALING NUM]", "autoeffect-format-dice-neg"); } if (!AutoEffect.includes("Silent")) { message = autoEffectMessage(messageFormat, AutoEffect[0].replace("Dice", "Dice "), effectVal/scaling, 0, scaling, "success"); @@ -15774,15 +15827,15 @@ function autoEffectChallengeRoll(AutoEffect, scaling) { /* Get target stat */ let statTarget = ""; if (["fortitude", "instinct", "prudence", "wisdom", "justice", "charm", "insight", "temperance"].includes(AutoEffect[1].toLowerCase())) { - statTarget = AutoEffect[1].toLowerCase().replace("fortitude","instinct").replace("prudence","wisdom"); + statTarget = AutoEffect[1].toLowerCase(); } else { autoEffectErrorMessage(`Stat "${AutoEffect[1]}" does not exist.`, AutoEffect); return {error: true}; } /* Handle message */ let message = ""; let messageValues = {}; - let messageFormat = "Rolling [TARGET] +[SCALING NUM]"; - if (effectVal < 0) { messageFormat = "Rolling [TARGET] [SCALING NUM]"; } + let messageFormat = getTranslationByKeyCustom("Rolling [TARGET] +[SCALING NUM]", "autoeffect-format-challengeroll"); + if (effectVal < 0) { messageFormat = getTranslationByKeyCustom("Rolling [TARGET] [SCALING NUM]", "autoeffect-format-challengeroll-neg"); } if (!AutoEffect.includes("Silent")) { message = autoEffectMessage(messageFormat, (statTarget.charAt(0).toUpperCase() + statTarget.slice(1)), effectVal/scaling, 0, scaling, "success"); @@ -15790,7 +15843,7 @@ function autoEffectChallengeRoll(AutoEffect, scaling) { messageValues = { effectTarget: (statTarget.charAt(0).toUpperCase() + statTarget.slice(1)), effectVal: effectVal/scaling, effectCount: 0, scaling: scaling, checkResult: "success" } /* Execute AutoEffect */ - return { challengeRollStat: statTarget, challengeRollDifficulty: effectVal, message: message, messageValues: messageValues } + return { challengeRollStat: statTarget.replace("fortitude","instinct").replace("prudence","wisdom"), challengeRollDifficulty: effectVal, message: message, messageValues: messageValues } } function autoEffectSpeed(AutoEffect, scaling, prevThisRoundSpeed, prevNextRoundSpeed) { @@ -15807,7 +15860,7 @@ function autoEffectSpeed(AutoEffect, scaling, prevThisRoundSpeed, prevNextRoundS /* Get duration */ let effectDuration = ""; - if (AutoEffect[2].toLowerCase() == "combat") { effectDuration = "Combat"; } + if (AutoEffect[2].toLowerCase() == "this combat") { effectDuration = "Combat"; } else if (["this", "thisround", "this round, thisturn, this turn"].includes(AutoEffect[2].toLowerCase())) { effectDuration = "ThisRound"; } else if (["next", "nextround", "next round, nextturn, next turn"].includes(AutoEffect[2].toLowerCase())) { effectDuration = "NextRound"; } else { autoEffectErrorMessage(`Duration "${AutoEffect[2]}" does not exist. Expected "Combat", "This round" or "Next round"`, AutoEffect); return {error: true}; } @@ -15815,12 +15868,12 @@ function autoEffectSpeed(AutoEffect, scaling, prevThisRoundSpeed, prevNextRoundS /* Handle message */ let message = ""; let messageValues = {}; - let messageFormat = "Increased [TARGET] by [SCALING NUM]"; - if (effectVal < 0) { messageFormat = "Reduced [TARGET] by [SCALING NUM]"; } + getTranslationByKeyCustom("Increase [TARGET] by [SCALING NUM]", "autoeffect-format-speed"); + if (effectVal < 0) { messageFormat = getTranslationByKeyCustom("Reduce [TARGET] by [SCALING NUM]", "autoeffect-format-speed-neg"); } switch (effectDuration) { - case "Combat": messageFormat += " this combat"; break; - case "ThisRound": messageFormat += " this round"; break; - case "NextRound": messageFormat += " next round"; break; + case "Combat": messageFormat += " " + getTranslationByKeyCustom("this combat", "autoeffect-option-thiscombat"); break; + case "ThisRound": messageFormat += " " + getTranslationByKeyCustom("this round", "autoeffect-option-thisround"); break; + case "NextRound": messageFormat += " " + getTranslationByKeyCustom("next round", "autoeffect-option-nextround"); break; } if (!AutoEffect.includes("Silent")) { @@ -15871,8 +15924,8 @@ function autoEffectDamage(AutoEffect, barList, scaling) { let messageValues = {}; let messageFormat = ""; switch (autoEffectVariant) { - case "BaseDamage": messageFormat = "Increased Base Damage by [SCALING NUM]"; break; - case "FlatDamage": messageFormat = "Dealt [SCALING NUM] [TARGET] Damage"; break; + case "BaseDamage": messageFormat = getTranslationByKeyCustom("Increase Base Damage by [SCALING NUM]", "autoeffect-format-basedamage"); break; + case "FlatDamage": messageFormat = getTranslationByKeyCustom("Deal [SCALING NUM] [TARGET] Damage", "autoeffect-format-flatdamage"); break; } if (!AutoEffect.includes("Silent")) { @@ -16992,6 +17045,119 @@ getSectionIDs("repeating_global", function(idarray) { }); +/* --- Generic helper functions --- */ + +/* Returns a translation, or a base string if no translation is available */ +function getTranslationByKeyCustom(base, key) { + if (getTranslationByKey(key) != false) { + return getTranslationByKey(key); + } else { + return base; + } +} + +/* Inputs an AutoEffect name written in the current language and returns it back to English */ +function getAutoEffectFromTranslation(autoEffect) { + if (getTranslationByKey("autoeffect-require") == autoEffect) { return "Require"; } + if (getTranslationByKey("autoeffect-consume") == autoEffect) { return "Consume"; } + if (getTranslationByKey("autoeffect-custommessage") == autoEffect) { return "CustomMessage"; } + if (getTranslationByKey("autoeffect-reset") == autoEffect) { return "Reset"; } + if (getTranslationByKey("autoeffect-gain") == autoEffect) { return "Gain"; } + if (getTranslationByKey("autoeffect-inflict") == autoEffect) { return "Inflict"; } + if (getTranslationByKey("autoeffect-give") == autoEffect) { return "Give"; } + if (getTranslationByKey("autoeffect-set") == autoEffect) { return "Set"; } + if (getTranslationByKey("autoeffect-add") == autoEffect) { return "Add"; } + if (getTranslationByKey("autoeffect-multi") == autoEffect) { return "Multi"; } + if (getTranslationByKey("autoeffect-basedamage") == autoEffect) { return "BaseDamage"; } + if (getTranslationByKey("autoeffect-flatdamage") == autoEffect) { return "FlatDamage"; } + if (getTranslationByKey("autoeffect-dicepower") == autoEffect) { return "DicePower"; } + if (getTranslationByKey("autoeffect-dicemax") == autoEffect) { return "DiceMax"; } + if (getTranslationByKey("autoeffect-dicecount") == autoEffect) { return "DiceCount"; } + if (getTranslationByKey("autoeffect-challengeroll") == autoEffect) { return "ChallengeRoll"; } + if (getTranslationByKey("autoeffect-speed") == autoEffect) { return "Speed"; } + return "Unknown AutoEffect: " + autoEffect; +} + +/* Inputs a trigger written in the current language and returns it back to English */ +function getTriggerFromTranslation(trigger) { + if (getTranslationByKey("autoeffect-trigger-combatstart") == trigger) { return "Combat start"; } + if (getTranslationByKey("autoeffect-trigger-roundstart") == trigger) { return "Round start"; } + if (getTranslationByKey("autoeffect-trigger-permanent") == trigger) { return "Permanent"; } + if (getTranslationByKey("autoeffect-trigger-damaged") == trigger) { return "Damaged"; } + if (getTranslationByKey("autoeffect-trigger-damagedhp") == trigger) { return "DamagedHP"; } + if (getTranslationByKey("autoeffect-trigger-damagedst") == trigger) { return "DamagedST"; } + if (getTranslationByKey("autoeffect-trigger-damagedsp") == trigger) { return "DamagedSP"; } + if (getTranslationByKey("autoeffect-trigger-staggered") == trigger) { return "Staggered"; } + if (getTranslationByKey("autoeffect-trigger-defeated") == trigger) { return "Defeated"; } + if (getTranslationByKey("autoeffect-trigger-panic") == trigger) { return "Panic"; } + if (getTranslationByKey("autoeffect-trigger-challenge") == trigger) { return "Challenge"; } + if (getTranslationByKey("autoeffect-trigger-offensive") == trigger) { return "Offensive"; } + if (getTranslationByKey("autoeffect-trigger-defensive") == trigger) { return "Defensive"; } + if (getTranslationByKey("autoeffect-trigger-block") == trigger) { return "Block"; } + if (getTranslationByKey("autoeffect-trigger-evade") == trigger) { return "Evade"; } + return "Unknown Trigger" +} + +/* Inputs an ailment written in the current language and returns it back to English */ +function getAilmentFromTranslation(ailment) { + if (getTranslationByKey("ailments-burn") == ailment) { return "Burn"; } + if (getTranslationByKey("ailments-bleed") == ailment) { return "Bleed"; } + if (getTranslationByKey("ailments-paralysis") == ailment) { return "Paralysis"; } + if (getTranslationByKey("ailments-fragile") == ailment) { return "Fragile"; } + if (getTranslationByKey("ailments-protection") == ailment) { return "Protection"; } + if (getTranslationByKey("ailments-stgprotection") == ailment) { return "Stagger Protection"; } + if (getTranslationByKey("ailments-strength") == ailment) { return "Strength"; } + if (getTranslationByKey("ailments-endurance") == ailment) { return "Endurance"; } + if (getTranslationByKey("ailments-haste") == ailment) { return "Haste"; } + if (getTranslationByKey("ailments-feeble") == ailment) { return "Feeble"; } + if (getTranslationByKey("ailments-disarm") == ailment) { return "Disarm"; } + if (getTranslationByKey("ailments-bind") == ailment) { return "Bind"; } + if (getTranslationByKey("ailments-smoke") == ailment) { return "Smoke"; } + if (getTranslationByKey("ailments-charge") == ailment) { return "Charge"; } + if (getTranslationByKey("ailments-fortune") == ailment) { return "Fortune"; } + return ailment; /* Is presumably a custom ailment */ +} + +/* Inputs an status bar shorthand written in the current language and returns it back to English */ +function getBarFromTranslation(bar) { + if (getTranslationByKey("bar-health-shortened") == bar) { return "HP"; } + if (getTranslationByKey("bar-stagres-shortened") == bar) { return "ST"; } + if (getTranslationByKey("bar-sanity-shortened") == bar) { return "SP"; } + if ("-" + getTranslationByKey("bar-health-shortened") == bar) { return "-HP"; } + if ("-" + getTranslationByKey("bar-stagres-shortened") == bar) { return "-ST"; } + if ("-" + getTranslationByKey("bar-sanity-shortened") == bar) { return "-SP"; } + if (getTranslationByKey("bar-health-temp-shortened") == bar) { return "THP"; } + if (getTranslationByKey("bar-stagres-temp-shortened") == bar) { return "TST"; } + return "Unknown Bar"; +} + +function getAilmentOrBarFromTranslation(input) { + if (getBarFromTranslation(input) != "Unknown Bar") { return getBarFromTranslation(input); } + return getAilmentFromTranslation(input); +} + +function getStatFromTranslation(stat) { + if (getTranslationByKey("stats-instinct") == stat) { return "Fortitude"; } + if (getTranslationByKey("stats-wisdom") == stat) { return "Prudence"; } + if (getTranslationByKey("stats-justice") == stat) { return "Justice"; } + if (getTranslationByKey("stats-charm") == stat) { return "Charm"; } + if (getTranslationByKey("stats-insight") == stat) { return "Insight"; } + if (getTranslationByKey("stats-temperance") == stat) { return "Temperance"; } + return "Unknown Stat"; +} + +function getOptionFromTranslation(option) { + if (getTranslationByKey("autoeffect-option-scaling") == option) { return "Scaling"; } + if (getTranslationByKey("autoeffect-option-silent") == option) { return "Silent"; } + if (getTranslationByKey("autoeffect-option-thisround") == option) { return "this round"; } + if (getTranslationByKey("autoeffect-option-nextround") == option) { return "next round"; } + if (getTranslationByKey("autoeffect-option-thiscombat") == option) { return "this combat"; } + if (getTranslationByKey("autoeffect-option-checksuccess") == option) { return "CheckSuccess"; } + if (getTranslationByKey("autoeffect-option-checkfailure") == option) { return "CheckFailure"; } + if (getTranslationByKey("autoeffect-option-checkignore") == option) { return "CheckIgnore"; } + return "Unknown Option"; +} + diff --git a/ProjectMoonTRPG/translation.json b/ProjectMoonTRPG/translation.json index 440b3fd25d..ebd37cf113 100644 --- a/ProjectMoonTRPG/translation.json +++ b/ProjectMoonTRPG/translation.json @@ -112,9 +112,9 @@ "bar-stagres-shortened":"ST", "bar-health-and-stagres": "Health and Stagger", "bar-health-temp": "Temporary Health", - "bar-health-temp-shortened": "Temp HP", + "bar-health-temp-shortened": "THP", "bar-stagres-temp": "Temporary Stagger Res", - "bar-stagres-temp-shortened": "Temp HP", + "bar-stagres-temp-shortened": "TST", "bar-sanity":"Sanity", "bar-sanity-shortened":"SP", "bar-light":"Light", @@ -247,6 +247,78 @@ "autoscript-editor":"AutoScript Editor", "autoscript-close-editor":"Save and close AutoScript Editor", "autoscript-save-changes":"Save AutoScript changes", + "autoeffect-option-scaling": "Scaling", + "autoeffect-option-silent": "Silent", + "autoeffect-option-button": "#Button", + "autoeffect-option-message": "#Message", + "autoeffect-option-messagebutton": "#MessageButton", + "autoeffect-option-thisround": "this round", + "autoeffect-option-nextround": "next round", + "autoeffect-option-thiscombat": "this combat", + "autoeffect-option-checksuccess":"CheckSuccess", + "autoeffect-option-checkfailure":"CheckFailure", + "autoeffect-option-checkignore":"CheckIgnore", + "autoeffect-require": "Require", + "autoeffect-consume": "Consume", + "autoeffect-custommessage": "CustomMessage", + "autoeffect-reset": "Reset", + "autoeffect-gain": "Gain", + "autoeffect-inflict": "Inflict", + "autoeffect-give": "Give", + "autoeffect-set": "Set", + "autoeffect-add": "Add", + "autoeffect-multi": "Multi", + "autoeffect-basedamage": "BaseDamage", + "autoeffect-flatdamage": "FlatDamage", + "autoeffect-dicepower": "DicePower", + "autoeffect-dicemax": "DiceMax", + "autoeffect-dicecount": "DiceCount", + "autoeffect-challengeroll": "ChallengeRoll", + "autoeffect-speed": "Speed", + "autoeffect-format-require": "Require [SCALING NUM] [TARGET]: [CHECK]", + "autoeffect-format-consume": "Consume [SCALING NUM] [TARGET]: [CHECK]", + "autoeffect-format-gain": "[/TARGET] Gain [SCALING NUM] [TARGET]", + "autoeffect-format-inflict": "[/TARGET] Inflict [SCALING NUM] [TARGET]", + "autoeffect-format-give": "[/TARGET] Give [SCALING NUM] [TARGET]", + "autoeffect-format-set": "Set [TARGET] to [RESULT]", + "autoeffect-format-add": "Regen [SCALING NUM] [TARGET]", + "autoeffect-format-add-neg": "Receive [-SCALING NUM] [TARGET] damage", + "autoeffect-format-multi1": "Multiply [TARGET] by ", + "autoeffect-format-multi2": " [[SCALING NUM]]", + "autoeffect-format-basedamage": "Increase Base Damage by [SCALING NUM]", + "autoeffect-format-flatdamage": "Deal [SCALING NUM] [TARGET] Damage", + "autoeffect-format-dice": "Increase [TARGET] by [SCALING NUM]", + "autoeffect-format-dice-neg": "Reduce [TARGET] by [SCALING NUM]", + "autoeffect-format-challengeroll": "Rolling [TARGET] +[SCALING NUM]", + "autoeffect-format-challengeroll-neg": "Rolling [TARGET] [SCALING NUM]", + "autoeffect-format-speed": "Increase [TARGET] by [SCALING NUM]", + "autoeffect-format-speed-neg": "Reduce [TARGET] by [SCALING NUM]", + "autoeffect-match-check": "[CHECK]", + "autoeffect-match-num": "[NUM]", + "autoeffect-match-scaling": "[SCALING]", + "autoeffect-match-scalingnum": "[SCALING NUM]", + "autoeffect-match-neg-num": "[-NUM]", + "autoeffect-match-neg-scaling": "[-SCALING]", + "autoeffect-match-neg-scalingnum": "[-SCALING NUM]", + "autoeffect-match-initial": "[INITIAL]", + "autoeffect-match-result": "[RESULT]", + "autoeffect-match-target": "[TARGET]", + "autoeffect-match-targeticon": "[/TARGET]", + "autoeffect-trigger-combatstart": "Combat start", + "autoeffect-trigger-roundstart": "Round start", + "autoeffect-trigger-permanent": "Permanent", + "autoeffect-trigger-damaged": "Damaged", + "autoeffect-trigger-damagedhp": "DamagedHP", + "autoeffect-trigger-damagedst": "DamagedST", + "autoeffect-trigger-damagedsp": "DamagedSP", + "autoeffect-trigger-staggered": "Staggered", + "autoeffect-trigger-defeated": "Defeated", + "autoeffect-trigger-panic": "Panic", + "autoeffect-trigger-challenge": "Challenge", + "autoeffect-trigger-offensive": "Offensive", + "autoeffect-trigger-defensive": "Defensive", + "autoeffect-trigger-block": "Block", + "autoeffect-trigger-evade": "Evade", "equip-weapon1-name":"Weapon Name (1)", "equip-weapon2-name":"Weapon Name (2)", "equip-weapon3-name":"Weapon Name (3)", From 978f872d11bd9ff5535eec0ad3837e3dea149fda Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Sat, 3 Aug 2024 21:42:51 +0200 Subject: [PATCH 33/55] Bugfix: AutoEffect title missing translation support --- ProjectMoonTRPG/ProjectMoonTRPG.html | 2 +- ProjectMoonTRPG/translation.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 5ab6c60f51..a998aa5726 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -14823,7 +14823,7 @@ Selects which type of AutoEffects to collect and append to an AutoScript. Block and Evade also include Defensive */ /* callback: Function to be run on returnValues. Defaults to an empty function */ /* collect: If the function should collect augment/outfit/etc. AutoEffects or not*/ -function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="false", callback=() => {}, collect="true", messageHeaderTitle="AutoEffects") { +function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="false", callback=() => {}, collect="true", messageHeaderTitle=getTranslationByKeyCustom("AutoEffects", "autoeffect-title")) { /* Adds the input AutoScript */ let AutoScript = ""; diff --git a/ProjectMoonTRPG/translation.json b/ProjectMoonTRPG/translation.json index ebd37cf113..4582101806 100644 --- a/ProjectMoonTRPG/translation.json +++ b/ProjectMoonTRPG/translation.json @@ -247,6 +247,7 @@ "autoscript-editor":"AutoScript Editor", "autoscript-close-editor":"Save and close AutoScript Editor", "autoscript-save-changes":"Save AutoScript changes", + "autoeffect-title": "AutoEffects", "autoeffect-option-scaling": "Scaling", "autoeffect-option-silent": "Silent", "autoeffect-option-button": "#Button", From e3cd92d77c8fb8a2c3f005d6c2025db072422911 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Sun, 4 Aug 2024 01:05:49 +0200 Subject: [PATCH 34/55] AutoEffects: part 17 - Added styling rules for the icons of conditional buttons and messages - AutoScript editor has a button to view and edit the AutoScript styling rules --- ProjectMoonTRPG/ProjectMoonTRPG.html | 228 +++++++++++++------ ProjectMoonTRPG/ProjectMoonTRPGStyle.css | 13 +- ProjectMoonTRPG/images/icons/lose.png | Bin 0 -> 4458 bytes ProjectMoonTRPG/images/icons/win.png | Bin 0 -> 4655 bytes ProjectMoonTRPG/imagesResized/icons/lose.png | Bin 0 -> 969 bytes ProjectMoonTRPG/imagesResized/icons/win.png | Bin 0 -> 973 bytes ProjectMoonTRPG/translation.json | 4 +- 7 files changed, 174 insertions(+), 71 deletions(-) create mode 100644 ProjectMoonTRPG/images/icons/lose.png create mode 100644 ProjectMoonTRPG/images/icons/win.png create mode 100644 ProjectMoonTRPG/imagesResized/icons/lose.png create mode 100644 ProjectMoonTRPG/imagesResized/icons/win.png diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index a998aa5726..9687fb5929 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -107,11 +107,13 @@
- + + +
@@ -13384,9 +13386,9 @@ on('clicked:applyDamage', (info) => { /* Damage helper functions beginning */ function getIcon(iconFolder, iconName, settingLimbusStyle = "false") { if (settingLimbusStyle == "true") { - return ``; + return ``; } else { - return `` + return `` } } @@ -14887,14 +14889,14 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals /* Get relevant attributes */ getAttrs(["settingMuteMessage", "settingWhisperRolls", "settingWhisperTarget", "settingLimbusStyle", "settingHideNextTurn", "HP", "HP_max", "StagRes", "StagRes_max", "SP", "SP_max", "thisRoundSpeed", "nextRoundSpeed", - "StaggerState", "distortState", "egoActiveState", "egoType"], function(values) { + "StaggerState", "distortState", "egoActiveState", "egoType", "autoScriptStyling"], function(values) { let settingMuteMessage = values.settingMuteMessage; let settingWhisperRolls = values.settingWhisperRolls; let settingWhisperTarget = values.settingWhisperTarget; let settingLimbusStyle = values.settingLimbusStyle; let settingHideNextTurn = values.settingHideNextTurn; - + let HP = values.HP; let ST = values.StagRes; let SP = values.SP; @@ -14921,10 +14923,15 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals let conditionalMessageList = {}; let conditionalButtonList = {}; let conditionalButtonSilent = ""; + let errorMessageList = {}; + + let stylingList = parseAutoScriptStyling(values.autoScriptStyling); + + console.log(stylingList) let output = {}; let tempOutput = {}; - let returnValues = { checkResult:"success", error:false, }; + let returnValues = { checkResult:"success", error:false }; let challengeRollList = {}; let message = ""; let messageValues = {}; @@ -15045,7 +15052,7 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals case "FlatDamage": tempOutput = autoEffectDamage(AutoEffect[0], barList, scaling); break; case "ChallengeRoll": tempOutput = autoEffectChallengeRoll(AutoEffect[0], scaling); break; case "Speed": tempOutput = autoEffectSpeed(AutoEffect[0], scaling, thisRoundSpeed, nextRoundSpeed); break; - default: tempOutput = {error:true}; autoEffectErrorMessage(`${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); break; + default: tempOutput = autoEffectErrorMessage("Invalid AutoEffect", `${AutoEffect[0][0].replace("Unknown: ","")} is not a valid AutoEffect`, AutoEffect[0]); break; } } console.log(tempOutput) @@ -15053,7 +15060,17 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals /* Handle errors. Continues executing AutoEffects for the sake of finding additional errors, */ /* but does not apply any changes to attributes */ if (tempOutput.hasOwnProperty("error") || returnValues.error == true) { - returnValues.error == true; + if (tempOutput.errorType != undefined) { + if (errorMessageList[tempOutput.errorType] != undefined) { + errorMessageList[tempOutput.errorType] += tempOutput.errorMessage; + } else { + errorMessageList[tempOutput.errorType] = tempOutput.errorMessage; + } + } + + if (returnValues.error != true) { + returnValues.error = tempOutput.error; + } output = {}; return; } @@ -15145,9 +15162,6 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals } } }); - - // console.log(output) - setAttrs(output); /* Create conditional buttons */ for (const [buttonName, buttonAutoScript] of Object.entries(conditionalButtonList)) { @@ -15163,7 +15177,7 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals } /* Message handling */ - if (settingMuteMessage != "true" && message != "") { + if (settingMuteMessage != "true" && message != "" && returnValues.error != true) { if (returnMessage == "false") { let messageHeaderIcon = getIcon("icons", "gear"); @@ -15184,20 +15198,42 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals } /* Conditional message handling */ - for (const [conditionName, conditionMessage] of Object.entries(conditionalMessageList)) { - if (returnValues.message == undefined) { - returnValues.message = autoEffectEntry(conditionName, conditionMessage, "gear"); - } else { - returnValues.message += autoEffectEntry(conditionName, conditionMessage, "gear"); + if (returnValues.error != true) { + for (const [conditionName, conditionMessage] of Object.entries(conditionalMessageList)) { + let iconName = "gear"; + let iconColor = "#85a874"; + if (stylingList[conditionName] != undefined) { + iconName = stylingList[conditionName][0]; + iconColor = stylingList[conditionName][1]; + } + + if (returnValues.message == undefined) { + returnValues.message = autoEffectEntry(conditionName, conditionMessage, iconName, iconColor); + } else { + returnValues.message += autoEffectEntry(conditionName, conditionMessage, iconName, iconColor); + } } } - + /* Error handling and returnValues callback */ if (returnValues.error == true) { + returnValues.message = ""; + + /* Error message */ + for (const [errorType, errorMessage] of Object.entries(errorMessageList)) { + if (errorType) + if (returnValues.message == undefined) { + returnValues.message = autoEffectEntry(errorType, errorMessage, "exit", "Red"); + } else { + returnValues.message += autoEffectEntry(errorType, errorMessage, "exit", "Red"); + } + } + resetConditionals(); - callback({error: true}); } + // console.log(output) + setAttrs(output); callback(returnValues); }); }); @@ -15283,7 +15319,7 @@ function translateAutoScriptArrayToEnglish(AutoScript) { /* Translate Options */ for (let j = 0; j < AutoScript[i][0].length; j++) { - if(getOptionFromTranslation(AutoScript[i][0][j]) != "Unknown Option") { + if(getOptionFromTranslation(AutoScript[i][0][j]) != "Unknown: " + AutoScript[i][0][j]) { AutoScript[i][0][j] = getOptionFromTranslation(AutoScript[i][0][j]); } } @@ -15301,16 +15337,56 @@ function translateAutoScriptArrayToEnglish(AutoScript) { } return AutoScript; } + +function parseAutoScriptStyling(AutoScriptStyling) { + let stylingList = {}; + let stylingRule = ""; + + /* Remove all newlines, tab spaces and comments */ + AutoScriptStyling = cleanAutoScript(AutoScriptStyling); + + do { + AutoScriptStyling = AutoScriptStyling.trim(); + + /* Checks if an styling rule still remains in the AutoScript */ + if (AutoScriptStyling.indexOf("(") == 0 && AutoScriptStyling.indexOf(")")) { + + /* Removes the next styling rule from the string. Removes the parentheses */ + stylingRule = AutoScriptStyling.substring(1, AutoScriptStyling.indexOf(")")); + AutoScriptStyling = AutoScriptStyling.substring(AutoScriptStyling.indexOf(")")+1); + + stylingRule = stylingRule.trim().split(","); + stylingRule = stylingRule.map(e => e.trim()); + + stylingList[stylingRule[0]] = [stylingRule[1], stylingRule[2]]; + } else { + break; + } + } while (AutoScriptStyling.length > 1) + + /* Return the styling list */ + return stylingList; +} /*--- AutoScript functions end ---*/ /*--- AutoEffect functions ---*/ -function autoEffectEntry(header, message, iconName) { +function autoEffectEntry(header, message, iconName="gear", iconColor="#85a874") { + if (!(/^#(?:[0-9a-fA-F]{3}){1,2}$/).test(iconColor)) { + switch (iconColor.toLowerCase()) { + case "red": iconColor = "#c25944"; break; + case "blue": iconColor = "#7397d1"; break; + case "yellow": iconColor = "#dbb748"; break; + case "purple": iconColor = "#8e7cc3"; break; + default: iconColor = "#85a874"; + } + } + let newEntry = "
" newEntry += `
` - newEntry += `
` + newEntry += `
` newEntry += `${getIcon("icons", iconName)}` newEntry += `
`; newEntry += `
${header}
` @@ -15403,8 +15479,10 @@ function autoEffectTranslateMessage(message) { } /* Whispers an error message to the user detailing an AutoEffect error */ -function autoEffectErrorMessage(errorString, autoEffect) { - console.log(errorString + autoEffect) +function autoEffectErrorMessage(errorType, errorString, AutoEffect) { + AutoEffect = AutoEffect.join(" ").replace("Unknown: ",""); + errorMessage = `(${AutoEffect}) - ${errorString}` + return { errorType: errorType, errorMessage: errorMessage, error: true}; } /* Creates a new conditional button*/ @@ -15426,6 +15504,7 @@ function resetConditionals() { } function autoEffectCustomMessage(AutoEffect, messageValues = {}) { + if (AutoEffect.length > 2) { AutoEffect.slice(3).forEach(option => { if (!["checksuccess", "checkfailure", "checkignore"].includes(option.toLowerCase())) { return autoEffectErrorMessage("Invalid Option", `Option "${option}" is not a valid option`, AutoEffect); } }); } let messageFormat = ""; let checkResultOption = "success"; @@ -15463,8 +15542,11 @@ function autoEffectCustomMessage(AutoEffect, messageValues = {}) { } function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { + let returnValues = {}; + /* Check format */ - if (AutoEffect.length < 3 || AutoEffect.length > 5) { autoEffectErrorMessage(`Expected format: (Require N #Ailment/#Bar/#BarDamage #Scaling(optional) #Silent(optional))`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 3 || AutoEffect.length > 5) { return autoEffectErrorMessage("Format Error", `Expected format: (Require N #Ailment/#Bar/#BarDamage #Scaling(optional) #Silent(optional))`, AutoEffect); } + if (AutoEffect.length > 3) { AutoEffect.slice(3).forEach(option => { if (!["scaling", "silent"].includes(option.toLowerCase())) { returnValues = autoEffectErrorMessage("Invalid Option", `Option "${option}" is not a valid option`, AutoEffect); } }); } /* Get target count */ let effectName = AutoEffect[2]; @@ -15475,7 +15557,7 @@ function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { else if (barList.hasOwnProperty(effectName)) { count = barList[effectName]; } /* Handle bar damage count */ else if (barDamageList.hasOwnProperty("-" + effectName)) { count = barDamageList[effectName]; } - else { autoEffectErrorMessage(`Ailment, Bar or BarDamage "${effectName}" does not exist`, AutoEffect); return {error: true}; } + else { return autoEffectErrorMessage("Invalid Target", `Ailment, Bar or BarDamage "${effectName}" does not exist`, AutoEffect); } /* Get required value. Recalculate count if percentage */ let effectVal = AutoEffect[1]; @@ -15494,11 +15576,10 @@ function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { } effectVal = barMax*percentage; } - else { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number or percentage`, AutoEffect); return {error: true}; } + else { return autoEffectErrorMessage("Invalid Value", `Value "${AutoEffect[1]}" is not a number or percentage`, AutoEffect); } /* Handle the optional scaling property */ let scaling = 1; - let returnValues = {}; if (AutoEffect[3] != undefined) { if (AutoEffect[3].toLowerCase() == "scaling") { scaling = Math.floor(count/effectVal); @@ -15532,12 +15613,15 @@ function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { } function autoEffectConsume(AutoEffect, ailmentList, barList) { - /* Check format */ - if (AutoEffect.length < 3 || AutoEffect.length > 5) { autoEffectErrorMessage(`Expected format: (Consume N #Ailment/#Bar #Scaling(optional) #Silent(optional))`, AutoEffect); return {error: true}; } + let returnValues = {}; + /* Check format */ + if (AutoEffect.length < 3 || AutoEffect.length > 5) { return autoEffectErrorMessage("Format Error", `Expected format: (Consume N #Ailment/#Bar #Scaling(optional) #Silent(optional))`, AutoEffect); } + if (AutoEffect.length > 3) { AutoEffect.slice(3).forEach(option => { if (!["scaling", "silent"].includes(option.toLowerCase())) { returnValues = autoEffectErrorMessage("Invalid Option", `Option "${option}" is not a valid option`, AutoEffect); } }); } + /* Get consumed value */ let effectVal = parseInt(Math.abs(AutoEffect[1])); - if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + if (isNaN(effectVal) == true) { return autoEffectErrorMessage("Invalid Value", `Value "${AutoEffect[1]}" is not a number`, AutoEffect); } let count = 0; /* Get target */ @@ -15555,11 +15639,10 @@ function autoEffectConsume(AutoEffect, ailmentList, barList) { effectTarget = effectName; count = barList[effectName]; } - else { autoEffectErrorMessage(`Ailment or Bar "${effectName}" does not exist`, AutoEffect); return {error: true}; } + else { return autoEffectErrorMessage("Invalid Target", `Ailment or Bar "${effectName}" does not exist`, AutoEffect); } /* Handle the optional scaling property */ let scaling = 1; - let returnValues = {}; if (AutoEffect[3] != undefined) { if (AutoEffect[3].toLowerCase() == "scaling") { scaling = Math.floor(count/effectVal); @@ -15600,29 +15683,32 @@ function autoEffectConsume(AutoEffect, ailmentList, barList) { } function autoEffectAilment(AutoEffect, ailmentList, scaling, settingLimbusStyle) { + let returnValues = {}; + /* Check if Gain, Inflict or Give */ let autoEffectVariant = ""; switch (AutoEffect[0]) { case "Gain": autoEffectVariant = "Gain"; break; case "Inflict": autoEffectVariant = "Inflict"; break; case "Give": autoEffectVariant = "Give"; break; - default: autoEffectErrorMessage(`${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); return {error: true} + default: return autoEffectErrorMessage("Invalid AutoEffect", `${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); } /* Check format */ - if (AutoEffect.length < 3 || AutoEffect.length > 6) { autoEffectErrorMessage(`Expected format: (${autoEffectVariant} N #Ailment #Round(optional) #Silent(optional))`, AutoEffect); return {error: true}; } - + if (AutoEffect.length < 3 || AutoEffect.length > 6) { return autoEffectErrorMessage("Format Error", `Expected format: (${autoEffectVariant} N #Ailment #Round(optional) #Silent(optional))`, AutoEffect); } + if (AutoEffect.length > 3) { AutoEffect.slice(3).forEach(option => { if (!["this", "next", "thisround", "nextround", "thisturn", "nextturn", "turn", "round", "silent"].includes(option.toLowerCase())) { returnValues = autoEffectErrorMessage("Invalid Option", `Option "${option}" is not a valid option`, AutoEffect); } }); } + /* Handle scaling */ AutoEffect[1] *= scaling; if (scaling == 0) { return {}; } /* Get ailment name */ let effectAilment = AutoEffect[2]; - if (!ailmentList.hasOwnProperty(effectAilment)) { autoEffectErrorMessage(`Ailment "${effectAilment}" does not exist`, AutoEffect); return {error: true}; } + if (!ailmentList.hasOwnProperty(effectAilment)) { return autoEffectErrorMessage("Invalid Target", `Ailment "${effectAilment}" does not exist`, AutoEffect); } /* Get values */ let effectVal = parseInt(Math.abs(AutoEffect[1])); - if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + if (isNaN(effectVal) == true) { return autoEffectErrorMessage("Invalid Value", `Value "${AutoEffect[1]}" is not a number`, AutoEffect); } let count = ailmentList[effectAilment][1]; /* Handle the optional turn override */ @@ -15665,14 +15751,15 @@ function autoEffectAilment(AutoEffect, ailmentList, scaling, settingLimbusStyle) messageValues = { effectTarget: effectIcon, effectVal: effectVal/scaling, effectCount: count, scaling: scaling, checkResult: "success", settingLimbusStyle: settingLimbusStyle } /* Execute AutoEffect */ - let returnValues = { message: message, messageValues: messageValues }; + returnValues = {...returnValues, message: message, messageValues: messageValues }; if (autoEffectVariant == "Gain") { returnValues = { ...returnValues, [effectTarget]: parseInt(effectVal), count: parseInt(count) } } return returnValues; } function autoEffectSetBar(AutoEffect, barList, scaling) { /* Check format */ - if (AutoEffect.length < 3 || AutoEffect.length > 4) { autoEffectErrorMessage(`Expected format: (Set N #Bar #Silent(optional))`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 3 || AutoEffect.length > 4) { return autoEffectErrorMessage("Format Error", `Expected format: (Set N #Bar #Silent(optional))`, AutoEffect); } + if (AutoEffect.length > 3) { if (AutoEffect[3].toLowerCase() != "silent") { return autoEffectErrorMessage("Invalid Option", `Option "${AutoEffect[3]}" is not a valid option`, AutoEffect); } } /* Handle scaling */ AutoEffect[1] *= scaling; @@ -15680,7 +15767,7 @@ function autoEffectSetBar(AutoEffect, barList, scaling) { /* Get value */ let effectVal = parseInt(Math.abs(AutoEffect[1])); - if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + if (isNaN(effectVal) == true) { return autoEffectErrorMessage("Invalid Value", `Value "${AutoEffect[1]}" is not a number`, AutoEffect); } let count = 0; /* Get target */ @@ -15690,7 +15777,7 @@ function autoEffectSetBar(AutoEffect, barList, scaling) { effectTarget = effectBar.replace("ST", "StagRes"); count = barList[effectBar]; } - else { autoEffectErrorMessage(`Bar "${effectBar}" does not exist`, AutoEffect); return {error: true}; } + else { return autoEffectErrorMessage("Invalid Target", `Bar "${effectBar}" does not exist`, AutoEffect); } /* Handle message */ let message = ""; @@ -15707,7 +15794,8 @@ function autoEffectSetBar(AutoEffect, barList, scaling) { } function autoEffectAddBar(AutoEffect, barList, scaling) { /* Check format */ - if (AutoEffect.length < 3 || AutoEffect.length > 4) { autoEffectErrorMessage(`Expected format: (Add N #Bar #Silent(optional))`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 3 || AutoEffect.length > 4) { return autoEffectErrorMessage("Format Error", `Expected format: (Add N #Bar #Silent(optional))`, AutoEffect); } + if (AutoEffect.length > 3) { if (AutoEffect[3].toLowerCase() != "silent") { return autoEffectErrorMessage("Invalid Option", `Option "${AutoEffect[3]}" is not a valid option`, AutoEffect); } } /* Handle scaling */ AutoEffect[1] *= scaling; @@ -15715,7 +15803,7 @@ function autoEffectAddBar(AutoEffect, barList, scaling) { /* Get value */ let effectVal = parseInt(AutoEffect[1]); - if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + if (isNaN(effectVal) == true) { return autoEffectErrorMessage("Invalid Value", `Value "${AutoEffect[1]}" is not a number`, AutoEffect); } let count = 0; /* Get target */ @@ -15725,7 +15813,7 @@ function autoEffectAddBar(AutoEffect, barList, scaling) { effectTarget = effectBar.replace("ST", "StagRes"); count = barList[effectBar]; } - else { autoEffectErrorMessage(`Bar "${effectBar}" does not exist`, AutoEffect); return {error: true}; } + else { return autoEffectErrorMessage("Invalid Target", `Bar "${effectBar}" does not exist`, AutoEffect); } /* Handle message */ let message = ""; @@ -15743,7 +15831,8 @@ function autoEffectAddBar(AutoEffect, barList, scaling) { } function autoEffectMultiBar(AutoEffect, barList, scaling) { /* Check format */ - if (AutoEffect.length < 3 || AutoEffect.length > 4) { autoEffectErrorMessage(`Expected format: (Multi N #Bar #Silent(optional))`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 3 || AutoEffect.length > 4) { return autoEffectErrorMessage("Format Error", `Expected format: (Multi N #Bar #Silent(optional))`, AutoEffect); } + if (AutoEffect.length > 3) { if (AutoEffect[3].toLowerCase() != "silent") { return autoEffectErrorMessage("Invalid Option", `Option "${AutoEffect[3]}" is not a valid option`, AutoEffect); } } /* Handle scaling */ AutoEffect[1] *= scaling; @@ -15751,7 +15840,7 @@ function autoEffectMultiBar(AutoEffect, barList, scaling) { /* Get value */ let effectVal = parseFloat(Math.abs(AutoEffect[1])); - if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + if (isNaN(effectVal) == true) { return autoEffectErrorMessage("Invalid Value", `Value "${AutoEffect[1]}" is not a number`, AutoEffect); } /* Get target */ let effectBar = AutoEffect[2]; @@ -15760,7 +15849,7 @@ function autoEffectMultiBar(AutoEffect, barList, scaling) { effectTarget = effectBar.replace("ST", "StagRes"); count = barList[effectBar]; } - else { autoEffectErrorMessage(`Bar "${effectBar}" does not exist`, AutoEffect); return {error: true}; } + else { return autoEffectErrorMessage("Invalid Target", `Bar "${effectBar}" does not exist`, AutoEffect); } /* Handle message */ let message = ""; @@ -15783,11 +15872,12 @@ function autoEffectDice(AutoEffect, scaling) { case "DicePower": autoEffectVariant = "DicePower"; break; case "DiceMax": autoEffectVariant = "DiceMax"; break; case "DiceCount": autoEffectVariant = "DiceCount"; break; - default: autoEffectErrorMessage(`${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); return {error: true} + default: return autoEffectErrorMessage("Invalid AutoEffect", `${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); } /* Check format */ - if (AutoEffect.length < 2 || AutoEffect.length > 3) { autoEffectErrorMessage(`Expected format: (${autoEffectVariant} N #Silent(optional))`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 2 || AutoEffect.length > 3) { return autoEffectErrorMessage("Format Error", `Expected format: (${autoEffectVariant} N #Silent(optional))`, AutoEffect); } + if (AutoEffect.length > 2) { if (AutoEffect[2].toLowerCase() != "silent") { return autoEffectErrorMessage("Invalid Option", `Option "${AutoEffect[2]}" is not a valid option`, AutoEffect); } } /* Handle scaling */ AutoEffect[1] *= scaling; @@ -15795,7 +15885,7 @@ function autoEffectDice(AutoEffect, scaling) { /* Get values */ let effectVal = parseInt(AutoEffect[1]); - if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + if (isNaN(effectVal) == true) { return autoEffectErrorMessage("Invalid Value", `Value "${AutoEffect[1]}" is not a number`, AutoEffect); } /* Handle message */ let message = ""; @@ -15814,7 +15904,8 @@ function autoEffectDice(AutoEffect, scaling) { function autoEffectChallengeRoll(AutoEffect, scaling) { /* Check format */ - if (AutoEffect.length < 3 || AutoEffect.length > 3 ) { autoEffectErrorMessage(`Expected format: (ChallengeRoll #Stat N #Silent(optional))`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 3 || AutoEffect.length > 3 ) { return autoEffectErrorMessage("Format Error", `Expected format: (ChallengeRoll #Stat N #Silent(optional))`, AutoEffect); } + if (AutoEffect.length > 3) { if (AutoEffect[3].toLowerCase() != "silent") { return autoEffectErrorMessage("Invalid Option", `Option "${AutoEffect[3]}" is not a valid option`, AutoEffect); } } /* Handle scaling */ AutoEffect[2] *= scaling; @@ -15822,14 +15913,14 @@ function autoEffectChallengeRoll(AutoEffect, scaling) { /* Get values */ let effectVal = parseInt(AutoEffect[2]); - if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + if (isNaN(effectVal) == true) { return autoEffectErrorMessage("Invalid Value", `Value "${AutoEffect[1]}" is not a number`, AutoEffect); } /* Get target stat */ let statTarget = ""; if (["fortitude", "instinct", "prudence", "wisdom", "justice", "charm", "insight", "temperance"].includes(AutoEffect[1].toLowerCase())) { statTarget = AutoEffect[1].toLowerCase(); } - else { autoEffectErrorMessage(`Stat "${AutoEffect[1]}" does not exist.`, AutoEffect); return {error: true}; } + else { return autoEffectErrorMessage("Invalid Stat", `Stat "${AutoEffect[1]}" does not exist.`, AutoEffect); } /* Handle message */ let message = ""; @@ -15848,7 +15939,7 @@ function autoEffectChallengeRoll(AutoEffect, scaling) { function autoEffectSpeed(AutoEffect, scaling, prevThisRoundSpeed, prevNextRoundSpeed) { /* Check format */ - if (AutoEffect.length < 3 || AutoEffect.length > 5) { autoEffectErrorMessage(`Expected format: (Speed N #Duration #Silent(optional))`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 3 || AutoEffect.length > 5) { return autoEffectErrorMessage("Format Error", `Expected format: (Speed N #Duration #Silent(optional))`, AutoEffect); } /* Handle scaling */ AutoEffect[1] *= scaling; @@ -15856,14 +15947,14 @@ function autoEffectSpeed(AutoEffect, scaling, prevThisRoundSpeed, prevNextRoundS /* Get values */ let effectVal = parseInt(AutoEffect[1]); - if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + if (isNaN(effectVal) == true) { return autoEffectErrorMessage("Invalid Value", `Value "${AutoEffect[1]}" is not a number`, AutoEffect); } /* Get duration */ let effectDuration = ""; - if (AutoEffect[2].toLowerCase() == "this combat") { effectDuration = "Combat"; } + if (["thiscombat"].includes(AutoEffect[2].toLowerCase()) || AutoEffect[3].toLowerCase() == "combat" ) { effectDuration = "Combat"; } else if (["this", "thisround", "this round, thisturn, this turn"].includes(AutoEffect[2].toLowerCase())) { effectDuration = "ThisRound"; } else if (["next", "nextround", "next round, nextturn, next turn"].includes(AutoEffect[2].toLowerCase())) { effectDuration = "NextRound"; } - else { autoEffectErrorMessage(`Duration "${AutoEffect[2]}" does not exist. Expected "Combat", "This round" or "Next round"`, AutoEffect); return {error: true}; } + else { return autoEffectErrorMessage("Invalid Option", `Duration "${AutoEffect.slice(2).join(" ")}" does not exist. Expected "This Combat", "This round" or "Next round"`, AutoEffect); } /* Handle message */ let message = ""; @@ -15895,11 +15986,12 @@ function autoEffectDamage(AutoEffect, barList, scaling) { switch (AutoEffect[0]) { case "BaseDamage": autoEffectVariant = "BaseDamage"; break; case "FlatDamage": autoEffectVariant = "FlatDamage"; break; - default: autoEffectErrorMessage(`${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); return {error: true} + default: return autoEffectErrorMessage("Invalid AutoEffect", `${AutoEffect[0]} is not a valid AutoEffect`, AutoEffect); } /* Check format */ - if (AutoEffect.length < 3 || AutoEffect.length > 4) { autoEffectErrorMessage(`Expected format: (${autoEffectVariant} N #Bar #Silent(optional))`, AutoEffect); return {error: true}; } + if (AutoEffect.length < 3 || AutoEffect.length > 4) { return autoEffectErrorMessage("Format Error", `Expected format: (${autoEffectVariant} N #Bar #Silent(optional))`, AutoEffect); } + if (AutoEffect.length > 3) { if (AutoEffect[3].toLowerCase() != "silent") { return autoEffectErrorMessage("Invalid Option", `Option "${AutoEffect[3]}" is not a valid option`, AutoEffect); } } /* Handle scaling */ AutoEffect[1] *= scaling; @@ -15907,7 +15999,7 @@ function autoEffectDamage(AutoEffect, barList, scaling) { /* Get value */ let effectVal = parseInt(Math.abs(AutoEffect[1])); - if (isNaN(effectVal) == true) { autoEffectErrorMessage(`Value "${AutoEffect[1]}" is not a number`, AutoEffect); return {error: true}; } + if (isNaN(effectVal) == true) { return autoEffectErrorMessage("Invalid Value", `Value "${AutoEffect[1]}" is not a number`, AutoEffect); } let count = 0; /* Get target */ @@ -15917,7 +16009,7 @@ function autoEffectDamage(AutoEffect, barList, scaling) { effectTarget = effectBar.replace("ST", "StagRes"); count = barList[effectBar]; } - else { autoEffectErrorMessage(`Bar "${effectBar}" does not exist`, AutoEffect); return {error: true}; } + else { return autoEffectErrorMessage("Invalid Target", `Bar "${effectBar}" does not exist`, AutoEffect); } /* Handle message */ let message = ""; @@ -17075,7 +17167,7 @@ function getAutoEffectFromTranslation(autoEffect) { if (getTranslationByKey("autoeffect-dicecount") == autoEffect) { return "DiceCount"; } if (getTranslationByKey("autoeffect-challengeroll") == autoEffect) { return "ChallengeRoll"; } if (getTranslationByKey("autoeffect-speed") == autoEffect) { return "Speed"; } - return "Unknown AutoEffect: " + autoEffect; + return "Unknown: " + autoEffect; } /* Inputs a trigger written in the current language and returns it back to English */ @@ -17095,7 +17187,7 @@ function getTriggerFromTranslation(trigger) { if (getTranslationByKey("autoeffect-trigger-defensive") == trigger) { return "Defensive"; } if (getTranslationByKey("autoeffect-trigger-block") == trigger) { return "Block"; } if (getTranslationByKey("autoeffect-trigger-evade") == trigger) { return "Evade"; } - return "Unknown Trigger" + return "Unknown: " + trigger; } /* Inputs an ailment written in the current language and returns it back to English */ @@ -17128,11 +17220,11 @@ function getBarFromTranslation(bar) { if ("-" + getTranslationByKey("bar-sanity-shortened") == bar) { return "-SP"; } if (getTranslationByKey("bar-health-temp-shortened") == bar) { return "THP"; } if (getTranslationByKey("bar-stagres-temp-shortened") == bar) { return "TST"; } - return "Unknown Bar"; + return "Unknown: " + bar; } function getAilmentOrBarFromTranslation(input) { - if (getBarFromTranslation(input) != "Unknown Bar") { return getBarFromTranslation(input); } + if (getBarFromTranslation(input) != "Unknown: " + input) { return getBarFromTranslation(input); } return getAilmentFromTranslation(input); } @@ -17143,7 +17235,7 @@ function getStatFromTranslation(stat) { if (getTranslationByKey("stats-charm") == stat) { return "Charm"; } if (getTranslationByKey("stats-insight") == stat) { return "Insight"; } if (getTranslationByKey("stats-temperance") == stat) { return "Temperance"; } - return "Unknown Stat"; + return "Unknown: " + stat; } function getOptionFromTranslation(option) { @@ -17155,7 +17247,7 @@ function getOptionFromTranslation(option) { if (getTranslationByKey("autoeffect-option-checksuccess") == option) { return "CheckSuccess"; } if (getTranslationByKey("autoeffect-option-checkfailure") == option) { return "CheckFailure"; } if (getTranslationByKey("autoeffect-option-checkignore") == option) { return "CheckIgnore"; } - return "Unknown Option"; + return "Unknown: " + option; } diff --git a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css index b9c7deaa4a..fc1ebc179c 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css +++ b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css @@ -2598,7 +2598,7 @@ justify-content: center; /* Assorted buttons */ -.shareButton, .editButton, .autoScriptButton, .closeAutoScriptButton, .saveAutoScriptButton, .copyButton, .displayButton, .lockButton { +.shareButton, .editButton, .autoScriptButton, .closeAutoScriptButton, .saveAutoScriptButton, .styleAutoScriptButton, .copyButton, .displayButton, .lockButton { position: absolute; height: 25px; width: 25px; @@ -2613,7 +2613,7 @@ justify-content: center; } -:is(.closeAutoScriptButton, .saveAutoScriptButton):hover { +:is(.closeAutoScriptButton, .saveAutoScriptButton, .styleAutoScriptButton):hover { background-color: #000 !important; } @@ -2655,6 +2655,15 @@ justify-content: center; width: auto; } +.styleAutoScriptButton { + top: 4px; + right: 80px; + z-index: 20; + padding-left: 4px; + padding-right: 4px; + width: auto; +} + :is(.augmentBlock, .specialBlock, .skillBlock) .autoScriptButton { right: 35px; } diff --git a/ProjectMoonTRPG/images/icons/lose.png b/ProjectMoonTRPG/images/icons/lose.png new file mode 100644 index 0000000000000000000000000000000000000000..3c73848acf54a560d44991300fd54dcc30f57bc1 GIT binary patch literal 4458 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 literal 0 HcmV?d00001 diff --git a/ProjectMoonTRPG/images/icons/win.png b/ProjectMoonTRPG/images/icons/win.png new file mode 100644 index 0000000000000000000000000000000000000000..6dfc48cb24f642ddebf2ab483758a126619a2f3c GIT binary patch literal 4655 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 Tw5fCA009VkM!MzNw;%lv!-QA1 literal 0 HcmV?d00001 diff --git a/ProjectMoonTRPG/imagesResized/icons/lose.png b/ProjectMoonTRPG/imagesResized/icons/lose.png new file mode 100644 index 0000000000000000000000000000000000000000..1b993b0abe2abb37045c20abc4744a9a144378bd GIT binary patch literal 969 zcmV;)12+7LP)Px&gGod|RA@u(S&MBOF$@(aX){ThNt#TOWRj+nG?^snB&^?oJkSay@+A9G7(O5f zVDltCzQ>PbDi`w5h2SVxApaYaS4J+15oZ2QL?0PYu!UXLKC`B^nUWSWzn4<(GR`sc zV=3h?5xs16GGjjr=2c0t2H zfIn^lJqrXN07jorV3-+<0f;`3;%h77%&ftABBJLkGqXTyC$aAl7|Ek0(dBU+Wac_3 zA#*27c98))QCpmq1b?c&e{`5>a3EE}+!Vnl!-iEYGne^e*UpV}vN z5;C#?x~%npodSqWaj@VU28olzl z_5oA1JXvW4^KvFFDK*^0h`wZWjuMPyM53zXY^3q|t&A(y;dPv!mDDg08L@S=&`85! zdkRF<1JvpOSq1@`of1WYk*;v8Y z%Ckf`nw6Y@c=>YrF}?%h(^vu9-oeS_nMNMx7iH8Qz`)S&s1c^6l>mXYR*7|Im&TW! zgip(>TeX~1ThGttnZ5N=RXAE^sddBhs|k9Tk1*2PGFxwabn=Us5fG_KA#-670`VLY zaJK@?9*|NA>Lh!FJCyDa5T`NfN1+S`KH&HlhO}#(w=o(kK37Jvk=o1dVi@@c8=US!XvI`c00000NkvXXu0mjfzZPx&heb)Ex@Fdgf$uV*pioGjM{0OKj1I9(~FO|t4r ztFX@6CdKDl(&Br*n>F7s06q7xthzu9=kZ8qvf|7b5}jI^92}Ugfrm9fy9?ovYo(OR zdeM{6ycy+8(q}Ojpq>ng2@pQ{hoomY*A{o%uOk;&@U>=}iUktcsxel8nuXLQEj_aZ z<}95>P;|efn3>q>NUQ|Ztt)Oul)h^PY|%qyIpR=6a*|3)N!l6y7K!N=XSE#<0kM*` zWJEDQQcHedyMRDqlKcPxRO@lM*f0>Ib}Tfk?3;Fj&CY$8?7CyeW?pFI!$7h;Y7uO; z@mMVh&gU#M6%d)LwBw-)KLo@8!M>^sb28)%l5^%B*HVc-oi1yv)Xc-OG&c}OPgOlM z@gAqbym^wJN2>i?_=@@Y|Dj{C3y1>*n=^r^F5#^_B{pmwFc(r>&4_VcXw6wm_=ypf z+~f*{^W^Be+<9U$k{6Oz!gJ>E0AU`$5OJ#u7VPH5#!#=N>IVzoXN@m5(Wvf|Yw1RC zuy>Q->NK Date: Sun, 4 Aug 2024 04:44:59 +0200 Subject: [PATCH 35/55] AutoEffects: part 17.5 - Added default styling rules. Is for now hardcoded, but looking into ways of making this a configurable setting --- ProjectMoonTRPG/ProjectMoonTRPG.html | 62 +++++++++++++++++++----- ProjectMoonTRPG/ProjectMoonTRPGStyle.css | 19 +++++++- 2 files changed, 67 insertions(+), 14 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 9687fb5929..88e7c970b9 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -107,13 +107,16 @@
+ + - + +
@@ -14764,6 +14767,30 @@ getAttrs(["settingEditMode"], function(values) { /*--- AutoScript functions ---*/ +/* Auto: Set default AutoScript styling */ +/* This is intended as a temporary solution while I figure out a better way to add styling as a setting */ +on("sheet:opened", function() { + getAttrs(["autoScriptStylingDefault"], function(values) { + let sheetDefaults = values.autoScriptStylingDefault; + + let stylingDefault = +`/* Clash results */ +(Clash Win, icons, win, red) (CW, icons, win, red) +(Clash Lose, icons, lose, yellow) (CL, icons, lose, yellow) + +/* On Use and On Hit */ +(On Use, icons, Portable, blue) +(On Hit, icons, Attack, purple)`; + + if(sheetDefaults != stylingDefault){ + + setAttrs({"autoScriptStylingDefault":stylingDefault}); + + } + + }); +}); + /* AutoScript editor open button */ on("clicked:autoScriptEdit", function(info) { let newEditorTarget = info.htmlAttributes.id; @@ -14797,6 +14824,15 @@ on("clicked:closeAutoScriptEdit", function(info) { saveAutoScriptEditor(); setAttrs({autoScriptEditor_display: "0"}); }); +/* AutoScript editor reset styling to default button */ +on("clicked:autoScriptStylingDefault", function(info) { + getAttrs(["autoScriptStylingDefault"], function(values) { + setAttrs({ + autoScriptStyling: values.autoScriptStylingDefault, + autoScriptEditorInput: values.autoScriptStylingDefault + }); + }); +}); /* Executes a conditional button. Hides the button if at least one check fails */ /* Also hides the button if a Consume check would fail after using the button again */ @@ -15193,24 +15229,26 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals }); } else { - returnValues.message = autoEffectEntry("AutoEffects", message, "gear"); + returnValues.message = autoEffectEntry("AutoEffects", message); } } /* Conditional message handling */ if (returnValues.error != true) { for (const [conditionName, conditionMessage] of Object.entries(conditionalMessageList)) { + let iconFolder = "icons"; let iconName = "gear"; let iconColor = "#85a874"; if (stylingList[conditionName] != undefined) { - iconName = stylingList[conditionName][0]; - iconColor = stylingList[conditionName][1]; + iconFolder = stylingList[conditionName][0]; + iconName = stylingList[conditionName][1]; + iconColor = stylingList[conditionName][2]; } if (returnValues.message == undefined) { - returnValues.message = autoEffectEntry(conditionName, conditionMessage, iconName, iconColor); + returnValues.message = autoEffectEntry(conditionName, conditionMessage, iconFolder, iconName, iconColor); } else { - returnValues.message += autoEffectEntry(conditionName, conditionMessage, iconName, iconColor); + returnValues.message += autoEffectEntry(conditionName, conditionMessage, iconFolder, iconName, iconColor); } } } @@ -15223,9 +15261,9 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals for (const [errorType, errorMessage] of Object.entries(errorMessageList)) { if (errorType) if (returnValues.message == undefined) { - returnValues.message = autoEffectEntry(errorType, errorMessage, "exit", "Red"); + returnValues.message = autoEffectEntry(errorType, errorMessage, "icons", "exit", "Red"); } else { - returnValues.message += autoEffectEntry(errorType, errorMessage, "exit", "Red"); + returnValues.message += autoEffectEntry(errorType, errorMessage, "icons", "exit", "Red"); } } @@ -15358,7 +15396,7 @@ function parseAutoScriptStyling(AutoScriptStyling) { stylingRule = stylingRule.trim().split(","); stylingRule = stylingRule.map(e => e.trim()); - stylingList[stylingRule[0]] = [stylingRule[1], stylingRule[2]]; + stylingList[stylingRule[0]] = [stylingRule[1], stylingRule[2], stylingRule[3]]; } else { break; } @@ -15373,7 +15411,7 @@ function parseAutoScriptStyling(AutoScriptStyling) { /*--- AutoEffect functions ---*/ -function autoEffectEntry(header, message, iconName="gear", iconColor="#85a874") { +function autoEffectEntry(header, message, iconFolder="icons", iconName="gear", iconColor="#85a874") { if (!(/^#(?:[0-9a-fA-F]{3}){1,2}$/).test(iconColor)) { switch (iconColor.toLowerCase()) { case "red": iconColor = "#c25944"; break; @@ -15387,7 +15425,7 @@ function autoEffectEntry(header, message, iconName="gear", iconColor="#85a874") let newEntry = "
" newEntry += `
` newEntry += `
` - newEntry += `${getIcon("icons", iconName)}` + newEntry += `${getIcon(iconFolder, iconName)}` newEntry += `
`; newEntry += `
${header}
` newEntry += `
` + message + "
"; @@ -16037,7 +16075,7 @@ function autoEffectDamage(AutoEffect, barList, scaling) { let attrkeyCharacter = ["character_nameBase", "instinct", "wisdom", "justice", "charm", "insight", "temperance", "EXP", "character_job", "age", "height", "character_origin", "character_residence", "character_assets", "character_ahn", "character_url", "character_summary", "character_combatnote", "character_history", "character_relations", "character_notes", "character_desc", "character_personality", "character_background"]; -let attrkeySettings = ["settingWhisperRolls", "settingMuteMessage", "settingAutoDetect", "settingTurnUpdate", "settingSimpleDisplay", "settingExtraEquip", "settingHideSpecial", "settingHelperText", "settingHideShare", "settingBurnImmune", "settingBleedImmune", "settingMultihitFull", "settingMultihitUses", "settingHideUses"]; +let attrkeySettings = ["settingWhisperRolls", "settingMuteMessage", "settingAutoDetect", "settingTurnUpdate", "settingSimpleDisplay", "settingExtraEquip", "settingHideSpecial", "settingHelperText", "settingHideShare", "settingBurnImmune", "settingBleedImmune", "settingMultihitFull", "settingMultihitUses", "settingHideUses", "AutoScriptStyling"]; let attrkeyEquip = ["outfitName", "outfitRank", "outfitDescription", "outfitEffect", "defDice1", "defDice2", "defDice3", "evdDice1", "evdDice2", "evdDice3", "outfitImmune1", "outfitImmune2", "outfitImmune3", "outfitImmune4", "outfitImmune5", "outfitImmune6", "bleedResist", "burnResist", "damageResist", "outfitAutoScript", diff --git a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css index fc1ebc179c..c09a719a49 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css +++ b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css @@ -2598,7 +2598,7 @@ justify-content: center; /* Assorted buttons */ -.shareButton, .editButton, .autoScriptButton, .closeAutoScriptButton, .saveAutoScriptButton, .styleAutoScriptButton, .copyButton, .displayButton, .lockButton { +.shareButton, .editButton, .autoScriptButton, .closeAutoScriptButton, .saveAutoScriptButton, .styleAutoScriptButton, .styleAutoScriptDefault, .copyButton, .displayButton, .lockButton { position: absolute; height: 25px; width: 25px; @@ -2613,7 +2613,7 @@ justify-content: center; } -:is(.closeAutoScriptButton, .saveAutoScriptButton, .styleAutoScriptButton):hover { +:is(.closeAutoScriptButton, .saveAutoScriptButton, .styleAutoScriptButton, .styleAutoScriptDefault):hover { background-color: #000 !important; } @@ -2663,6 +2663,21 @@ justify-content: center; padding-right: 4px; width: auto; } +.toggleStylingButton:checked ~ .styleAutoScriptButton { + display: none !important; +} + +.styleAutoScriptDefault { + top: 4px; + right: 80px; + z-index: 20; + padding-left: 4px; + padding-right: 4px; + width: auto; +} +.toggleStylingButton:not(:checked) ~ .styleAutoScriptDefault { + display: none !important; +} :is(.augmentBlock, .specialBlock, .skillBlock) .autoScriptButton { right: 35px; From 7b7d4b79d8c5e35cb332bdf11e3acbb167b5bdec Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Sun, 4 Aug 2024 04:58:54 +0200 Subject: [PATCH 36/55] Translation: Add capitalize(string) function to remove need for duplicate capitalized translations --- ProjectMoonTRPG/ProjectMoonTRPG.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 88e7c970b9..0582ec5e11 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -17288,6 +17288,10 @@ function getOptionFromTranslation(option) { return "Unknown: " + option; } +function capitalize(string) { + return string.charAt(0).toUpperCase() + string.slice(1); +} + From c4f2ed5df9426118be17c1fefceeda93c4f22d1d Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Sun, 4 Aug 2024 05:08:24 +0200 Subject: [PATCH 37/55] Bugfix: Special tool setting drop-down displaying below textfield --- ProjectMoonTRPG/ProjectMoonTRPG.html | 8 ++++---- ProjectMoonTRPG/ProjectMoonTRPGStyle.css | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 0582ec5e11..4bb7ac14b0 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -7670,7 +7670,7 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects.">
Effect Range - @@ -7684,7 +7684,7 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects.">
Duration - @@ -7744,7 +7744,7 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects.">
Effect Range - @@ -7758,7 +7758,7 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects.">
Duration - diff --git a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css index c09a719a49..9ffb29f8d1 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css +++ b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css @@ -1410,6 +1410,9 @@ margin-bottom: 0px !important; margin-top: 7px; width: 140px; } +.specialInput { + width: 140px; +} .toolDescriptionInput { height: 65px !important; From 53c735fb489abeaa76ed8b1ba9fd92c18077efa9 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Sun, 4 Aug 2024 05:26:03 +0200 Subject: [PATCH 38/55] Bugfix: Damage Calculation message missing translation for its header --- ProjectMoonTRPG/ProjectMoonTRPG.html | 4 ++-- ProjectMoonTRPG/translation.json | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 4bb7ac14b0..936798abb1 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -10234,7 +10234,7 @@ data-i18n-placeholder="tool-effect" placeholder="Tool effects.">
{{icon}}
-
Damage Calculation
+
{{#title}}{{title}}{{/title}}
For: {{#name}}{{name}}{{/name}}
{{#damagecalculations}} {{damagecalculations}} {{/damagecalculations}}
@@ -13368,7 +13368,7 @@ on('clicked:applyDamage', (info) => { setAttrs({"dummy":damageCalculation, "dummyIcon":damageIcon, "damageHelperType":"None"}); - startRoll((whisper + "&{template:damagecalculation} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{damagecalculations=@{dummy} }}"), (results) => { + startRoll((whisper + `&{template:damagecalculation} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{title=${getTranslationByKeyCustom("Damage Calculation", "heading-damagecalculation")}}} {{damagecalculations=@{dummy} }}`), (results) => { finishRoll(results.rollId, {} ); }); /* Damage calculation chat message block end */ diff --git a/ProjectMoonTRPG/translation.json b/ProjectMoonTRPG/translation.json index 51627281d4..fb275dd792 100644 --- a/ProjectMoonTRPG/translation.json +++ b/ProjectMoonTRPG/translation.json @@ -100,6 +100,7 @@ "heading-derived":"Derived values", "heading-rollhelper":"Roll helpers", "heading-damagehelper": "Damage helper", + "heading-damagecalculation": "Damage Calculation", "heading-ailments":"Status ailments", "heading-stats":"Stats", "heading-observation":"Observation level", From 43bd1966df75208a6e03f6657e61e0e38e5fd450 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Sun, 4 Aug 2024 05:55:49 +0200 Subject: [PATCH 39/55] AutoEffects: part 18 - Added new settings (Hide: Base Effect) which when enabled disabled the base effect of skills, tools and equipment from showing in chat messages - AutoEffects can in many cases fill the same purpose as these messages. Players may choose which option they prefer by mixing this setting with the #Message option for AutoEffect conditionals --- ProjectMoonTRPG/ProjectMoonTRPG.html | 13 ++++++++++--- ProjectMoonTRPG/translation.json | 1 + 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 936798abb1..726705df32 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -45,6 +45,8 @@ + + @@ -10941,6 +10943,7 @@ on("change:PanicState", function() { let currentstate = values.PanicState; let messagestate = values.settingMuteMessage; let overridecheck = values.messageOverride; + let overrideeffect = values.settingHideBaseEffect; let style = "https://raw.githubusercontent.com/punibird/roll20-character-sheets/master/ProjectMoonTRPG/images/ailments/"; if(values.settingLimbusStyle == "true"){ @@ -12246,7 +12249,7 @@ getSectionIDs(`repeating_global`, idarray => { let skillselect = values.skillSelect; let toolselect = values.toolselect; - getAttrs(["egoActiveState", "settingSimpleDisplay", "settingWhisperRolls", "settingWhisperTarget", "settingMultihitFull", `${id}_multiPenalty`, `${id}_multiStyle`, "character_name", "advState", "difficulty", "baseActNum", "Light", + getAttrs(["egoActiveState", "settingSimpleDisplay", "settingHideBaseEffect", "settingWhisperRolls", "settingWhisperTarget", "settingMultihitFull", `${id}_multiPenalty`, `${id}_multiStyle`, "character_name", "advState", "difficulty", "baseActNum", "Light", "difficulty", "Endurance", "Disarm", "Strength", "Feeble", "evdPositive", "evdNegative", "advNum", "disadvNum", "attPower", "defPower", "evdPower", "selectName", "selectLight", "selectType", "selectDice1", "selectDice2", "selectDice3", "selectEffect", "distortWeaponDice1", "distortWeaponDice2", "distortWeaponDice3", "distortDefDice1", "distortDefDice2", "distortDefDice3", "distortEvdDice1", "distortEvdDice2", "distortEvdDice3", "distortEffect", "distortEffect2", "settingMultihitUses", "settingHideUses", @@ -12260,6 +12263,7 @@ getSectionIDs(`repeating_global`, idarray => { let newlight = parseInt(values.Light); let charname = values.character_name; let simpledisplay = values.settingSimpleDisplay; + let hidebaseffect = values.settingHideBaseEffect; let whisperrolls = values.settingWhisperRolls; let whispertarget = values.settingWhisperTarget; @@ -12671,6 +12675,8 @@ getSectionIDs(`repeating_global`, idarray => { skillinfo += toolinfo; } + if (hidebaseffect == "true") { baseEffectDescription = ""; skillEffectDescription = ""; } + let header = "
" + basename + "
"; let body = "" + langFrom + ": "+ charname + "
" + langRoll + ": " + rollformatmessage + skillinfo + "
" + attackmessage + "
" + baseEffectDescription + skillEffectDescription + distortformat; @@ -13516,10 +13522,11 @@ on('clicked:declareAction', (info) => { let toolselect = values.toolSelect; /* Get attributes */ - getAttrs(["actionType", "settingSimpleDisplay", "settingWhisperRolls", "settingWhisperTarget", "character_name", "Light", "selectName", "selectLight", "selectType", "selectDice1", "selectDice2", "selectDice3", "selectEffect", "selectDescription", "baseActNum", "distortState", "tool1Name", "tool1Reusable", "tool1Uses", "tool1Uses_max", "tool1Effect", "tool1Description", "tool2Name", "tool2Reusable", "tool2Uses", "tool2Uses_max", "tool2Effect", "tool2Description", "tool3Name", "tool3Reusable", "tool3Uses", "tool3Uses_max", "tool3Effect", "tool3Description", "tool4Name", "tool4Reusable", "tool4Uses", "tool4Uses_max", "tool4Effect", "tool4Description", "special1Name","special1Description", "special1Range", "special1Duration", "special1Risk", "special2Name", "special2Description", "special2Range", "special2Duration", "special2Risk", "egoName", "egoType", "egoDescription", "egoUses", "egoUses_max", "egoUseType", "egoEffect", "egoRisk", "egoRange", "egoDuration", "settingHideUses", `${toolselect}AutoScript`], function(values) { + getAttrs(["actionType", "settingSimpleDisplay", "settingHideBaseEffect", "settingWhisperRolls", "settingWhisperTarget", "character_name", "Light", "selectName", "selectLight", "selectType", "selectDice1", "selectDice2", "selectDice3", "selectEffect", "selectDescription", "baseActNum", "distortState", "tool1Name", "tool1Reusable", "tool1Uses", "tool1Uses_max", "tool1Effect", "tool1Description", "tool2Name", "tool2Reusable", "tool2Uses", "tool2Uses_max", "tool2Effect", "tool2Description", "tool3Name", "tool3Reusable", "tool3Uses", "tool3Uses_max", "tool3Effect", "tool3Description", "tool4Name", "tool4Reusable", "tool4Uses", "tool4Uses_max", "tool4Effect", "tool4Description", "special1Name","special1Description", "special1Range", "special1Duration", "special1Risk", "special2Name", "special2Description", "special2Range", "special2Duration", "special2Risk", "egoName", "egoType", "egoDescription", "egoUses", "egoUses_max", "egoUseType", "egoEffect", "egoRisk", "egoRange", "egoDuration", "settingHideUses", `${toolselect}AutoScript`], function(values) { let charname = values.character_name; let simpledisplay = values.settingSimpleDisplay; + let hidebaseffect = values.settingHideBaseEffect; let whisperrolls = values.settingWhisperRolls; let whispertarget = values.settingWhisperTarget; let distortstate = values.distortState; @@ -13754,7 +13761,7 @@ on('clicked:declareAction', (info) => { } } - + if (hidebaseffect == "true") { skillinfo= "" + langSkill + ": " + skillname; toolinfo = "" + langUse + ": " + toolname + toolusestext + "
"; } let info = "
" + actiontext + lightmessage + "
" + langFrom + ": " + charname + "
" + toolinfo + skillinfo + autoScriptMessage; diff --git a/ProjectMoonTRPG/translation.json b/ProjectMoonTRPG/translation.json index fb275dd792..0f1fd5e657 100644 --- a/ProjectMoonTRPG/translation.json +++ b/ProjectMoonTRPG/translation.json @@ -11,6 +11,7 @@ "settings-simpledisplay":"Simple roll display", "settings-extraequip":"Extra weapons/tools/skills", "settings-hidespecial":"Hide: Special items", + "settings-hidebaseeffect":"Hide: Base effects", "settings-hidenextturn":"Hide: Next turn input", "settings-hidehelpertext":"Hide: Helper text", "settings-hideshare":"Hide: Share buttons", From c3ebc23cf7950561cce9f2f431539f6c53379771 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Sun, 4 Aug 2024 06:26:06 +0200 Subject: [PATCH 40/55] Bugfix: Ailment display spinners weren't displaying correctly in Firefox browsers --- ProjectMoonTRPG/ProjectMoonTRPGStyle.css | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css index 9ffb29f8d1..44f27d2295 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css +++ b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css @@ -1772,20 +1772,24 @@ background-image: linear-gradient(to bottom, rgba(0,0,0,0.8), rgba(0,0,0,0)), ur position: absolute; left: 25px; } + +/* This two rules disables the spinner (up and down buttons in number inputs) when not hovering over or selecting an ailment field */ +/* Also work for Firefox! */ +.ailmentNumNextTurn, .ailmentNumThisTurn { + appearance: textfield; +} +.ailmentNumNextTurn:focus, +.ailmentNumNextTurn:hover, +.ailmentNumThisTurn:focus, +.ailmentNumThisTurn:hover { + appearance: auto; +} /* If the next turn field is disabled by a hide toggle (Burn/Bleed/Smoke/Charge individual setting) or by a hide toggle rev (Global setting) the standard field is returned to it's normal styling */ .status_effect_value .hide-toggle:not(:checked) ~ .ailmentNumThisTurn, .status_effect_value .hide-toggle-rev:checked ~ .ailmentNumThisTurn { width: 45.5px !important; padding-right: 4px; } -/* This wide boi disables the spinner (up and down buttons in number inputs) when not hovering over or selecting an ailment field */ -/* The default behavour is to make their opacity 0. This also causes any text beneath the spinner to be hidden with it which looks terrible */ -.ailmentNumNextTurn:not(:hover):not(:focus)::-webkit-inner-spin-button, -.ailmentNumNextTurn:not(:hover):not(:focus)::-webkit-outer-spin-button, -.ailmentNumThisTurn:not(:hover):not(:focus)::-webkit-inner-spin-button, -.ailmentNumThisTurn:not(:hover):not(:focus)::-webkit-outer-spin-button { - display: none !important; -} /* This lengthy boi disables interacting with the next turn field while selecting or hovering over the current turn field (the fields partially overlap) */ :is(.ailmentNumThisTurn:hover, .ailmentNumThisTurn:focus) + :is(.ailmentNumNextTurn) { From dc8c3aff0e6f6b41ff02af1e507433889ce9f615 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Sun, 4 Aug 2024 06:29:30 +0200 Subject: [PATCH 41/55] Cleanup: Modified all image links to reference the master branch --- ProjectMoonTRPG/ProjectMoonTRPG.html | 4 ++-- ProjectMoonTRPG/ProjectMoonTRPGStyle.css | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 726705df32..ecdacb6b44 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -13395,9 +13395,9 @@ on('clicked:applyDamage', (info) => { /* Damage helper functions beginning */ function getIcon(iconFolder, iconName, settingLimbusStyle = "false") { if (settingLimbusStyle == "true") { - return ``; + return ``; } else { - return `` + return `` } } diff --git a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css index 44f27d2295..59b2dcf0d3 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css +++ b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css @@ -1563,7 +1563,7 @@ margin-bottom: 2px !important;} background-position: center; background-repeat: no-repeat; margin-top: 2px; - background-image: url('https://raw.githubusercontent.com/BeautiDemise/roll20-character-sheets/ProjectMoonTRPG-LoR-Rework/ProjectMoonTRPG/imagesResized/icons/damage.png'); + background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/ProjectMoonTRPG-LoR-Rework/ProjectMoonTRPG/imagesResized/icons/damage.png'); border-radius: 5px; background-color: #222 !important; border: 1px #111 solid; @@ -1959,10 +1959,10 @@ background-image: url('https://raw.githubusercontent.com/punibird/roll20-charact .whisper { background-image: url('https://raw.githubusercontent.com/punibird/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/icons/whisper.png');} .damageResist { - background-image: url('https://raw.githubusercontent.com/BeautiDemise/roll20-character-sheets/ProjectMoonTRPG-LoR-Rework/ProjectMoonTRPG/imagesResized/ailments/DamageResist.png'); + background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/ProjectMoonTRPG-LoR-Rework/ProjectMoonTRPG/imagesResized/ailments/DamageResist.png'); } .damageResist-limbus { - background-image: url('https://raw.githubusercontent.com/BeautiDemise/roll20-character-sheets/ProjectMoonTRPG-LoR-Rework/ProjectMoonTRPG/imagesResized/ailments/limbus/DamageResist.png'); + background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/ProjectMoonTRPG-LoR-Rework/ProjectMoonTRPG/imagesResized/ailments/limbus/DamageResist.png'); } /* Ailment Icons */ @@ -2643,14 +2643,14 @@ justify-content: center; bottom: 5px; right: 65px; z-index: 20; - background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/AutoEffects-Functionality/ProjectMoonTRPG/imagesResized/icons/script.png'); + background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/icons/script.png'); } .closeAutoScriptButton { top: 4px; right: 6px; z-index: 20; - background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/AutoEffects-Functionality/ProjectMoonTRPG/imagesResized/icons/exit.png'); + background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/icons/exit.png'); } .saveAutoScriptButton { From 581c4186774e680fb721781c102fee0264d32ef5 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Sun, 4 Aug 2024 06:40:18 +0200 Subject: [PATCH 42/55] Cleanup: Changed contact info from gmail to Discord user link --- ProjectMoonTRPG/sheet.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ProjectMoonTRPG/sheet.json b/ProjectMoonTRPG/sheet.json index 7cfaba3f86..3d4c306527 100644 --- a/ProjectMoonTRPG/sheet.json +++ b/ProjectMoonTRPG/sheet.json @@ -4,7 +4,7 @@ "authors": "punibird, BeautifulDemise", "roll20userid": "11544351, 487875", "preview": "ProjectMoonTRPG-preview.jpg", - "instructions": "**Project Moon TRPG - Roll20 Sheet** - (version 0.5)\n\n**Supported Languages:** English, 日本語, 한국어\nThis is a Roll20 character sheet and playing tool for Project Moon TRPG, a fan-made system based on the games and world setting of Project Moon.\nThe original system was created in Korean by helloing0119.\n\n**Contact:** [Google Form](https://forms.gle/EMnjArzsgdpQJwfZ9) | [@punibird](https://twitter.com/punibird) | beautidemise@gmail.com \n\n**PMTRPG Resources:** [Google Drive](https://drive.google.com/drive/u/2/folders/15nMYLz0sB5xWUiSOG4oN6IsteRJjpdZk)\n[Rule Summary](https://docs.google.com/document/d/1MRk6HRD79pw-3-dcgteGgHIBAzdKVpDHRYIY5EFscE4/) | [Roll20 Sheet Guide](https://docs.google.com/document/d/1ok4-2vBbgH9jyBw05kGwsl0F96qrck4vmU9PO5kvoWU/)", + "instructions": "**Project Moon TRPG - Roll20 Sheet** - (version 0.5)\n\n**Supported Languages:** English, 日本語, 한국어\nThis is a Roll20 character sheet and playing tool for Project Moon TRPG, a fan-made system based on the games and world setting of Project Moon.\nThe original system was created in Korean by helloing0119.\n\n**Contact:** [Google Form](https://forms.gle/EMnjArzsgdpQJwfZ9) | [@punibird](https://twitter.com/punibird) | [beautifuldemise (Discord)](https://discord.com/users/166920510330896384) \n\n**PMTRPG Resources:** [Google Drive](https://drive.google.com/drive/u/2/folders/15nMYLz0sB5xWUiSOG4oN6IsteRJjpdZk)\n[Rule Summary](https://docs.google.com/document/d/1MRk6HRD79pw-3-dcgteGgHIBAzdKVpDHRYIY5EFscE4/) | [Roll20 Sheet Guide](https://docs.google.com/document/d/1ok4-2vBbgH9jyBw05kGwsl0F96qrck4vmU9PO5kvoWU/)", "instructionstranslationkey": "sheetsettings-instructions", "useroptions": [ { From 932de80ef2f6d84b6cb3c4b90cb43517dfe45104 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Mon, 5 Aug 2024 18:04:01 +0200 Subject: [PATCH 43/55] Cleanup: Added two new damage helper settings requested by the community --- ProjectMoonTRPG/ProjectMoonTRPG.html | 64 +++++++++++++----------- ProjectMoonTRPG/ProjectMoonTRPGStyle.css | 4 +- ProjectMoonTRPG/translation.json | 2 + 3 files changed, 38 insertions(+), 32 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index ecdacb6b44..8a2bbb578e 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -34,9 +34,10 @@ + + - @@ -47,7 +48,9 @@ - + + + @@ -12486,9 +12489,9 @@ getSectionIDs(`repeating_global`, idarray => { let autoeffectdice1 = 0; let autoeffectdice2 = 0; let autoeffectdice3 = 0; - if (returnValues.diceCount != undefined) { autoeffectdice1 = returnValues.diceCount} - if (returnValues.diceMax != undefined) { autoeffectdice2 = returnValues.diceMax} - if (returnValues.dicePower != undefined) { autoeffectdice3 = returnValues.dicePower} + if (returnValues.diceCount != undefined) { autoeffectdice1 = returnValues.diceCount; } + if (returnValues.diceMax != undefined) { autoeffectdice2 = returnValues.diceMax; } + if (returnValues.dicePower != undefined) { autoeffectdice3 = returnValues.dicePower; } let autoScriptMessage = ""; if (returnValues.message != undefined) { autoScriptMessage = returnValues.message } @@ -12621,8 +12624,6 @@ getSectionIDs(`repeating_global`, idarray => { rollformatmessage += " x" + acounter + ")"; } - - /* Multi-hit formatting */ if(combinedice1 > 1){ @@ -12786,11 +12787,11 @@ function rollChallenge(buttonid, rollDifficulty=0, handleAutoScriptConditionals= let autoEffectDiceCount = 0; let autoEffectDiceMax = 0; let autoEffectSpeedCombat = 0; - if (returnValues.dicePower != undefined) { stat += returnValues.dicePower } - if (returnValues.diceCount != undefined) { autoEffectDiceCount = returnValues.diceCount } - if (returnValues.diceMax != undefined) { autoEffectDiceMax = returnValues.diceMax } - if (returnValues.speedCombat != undefined) { autoEffectSpeedCombat = returnValues.speedCombat } - + if (returnValues.dicePower != undefined) { stat += returnValues.dicePower; } + if (returnValues.diceCount != undefined) { autoEffectDiceCount = returnValues.diceCount; } + if (returnValues.diceMax != undefined) { autoEffectDiceMax = returnValues.diceMax; } + if (returnValues.speedCombat != undefined) { autoEffectSpeedCombat = returnValues.speedCombat; } + let autoScriptMessage = ""; if (returnValues.message != undefined) { autoScriptMessage = returnValues.message } @@ -12936,7 +12937,7 @@ on('clicked:applyDamage', (info) => { /* Get attribute values */ getAttrs(["character_name", "HP", "StagRes", "SP", "HP_max", "StagRes_max", "SP_max", - "settingLimbusStyle", "settingWhisperRolls", "settingWhisperTarget", "settingSimpleDisplay", + "settingLimbusStyle", "settingWhisperRolls", "settingWhisperTarget", "settingSimpleDisplay", "settingAutoApplyDamage", "settingHideBarUpdate", "baseDamage", "flatDamageHP", "flatDamageST", "damageHelperType", "distortState", "egoActiveState", "egoType", "StaggerState", "damageResist", "damageResist_ego"], function(values) { @@ -12946,6 +12947,8 @@ on('clicked:applyDamage', (info) => { let whisperrolls = values.settingWhisperRolls; let whispertarget = values.settingWhisperTarget; let simpledisplay = values.settingSimpleDisplay; + let autoapplydamage = values.settingAutoApplyDamage; + let hidebarupdate = values.settingHideBarUpdate; let characterName = values.character_name; @@ -13237,7 +13240,9 @@ on('clicked:applyDamage', (info) => { if (newST > maxST) { newST = maxST } if (newSP > maxSP) { newSP = maxSP } output["HP"] = newHP; output["StagRes"] = newST; output["SP"] = newSP; - setAttrs(output); + if (autoapplydamage == "true") { + setAttrs(output); + } /* AutoScripts */ let autoScriptTriggers = ["None"]; @@ -13297,9 +13302,9 @@ on('clicked:applyDamage', (info) => { let resSTIcon = "Res" + damageType + "Stg"; /* Calculation summaries (Message head) */ - hpDamageHead = generateDamageHelperHeader("HP", newHP, oldHP); - stDamageHead = generateDamageHelperHeader("ST", newST, oldST, staggerState); - spDamageHead = generateDamageHelperHeader("SP", newSP, oldSP); + hpDamageHead = generateDamageHelperHeader("HP", newHP, oldHP, "0", autoapplydamage, hidebarupdate); + stDamageHead = generateDamageHelperHeader("ST", newST, oldST, staggerState, autoapplydamage, hidebarupdate); + spDamageHead = generateDamageHelperHeader("SP", newSP, oldSP, "0", autoapplydamage, hidebarupdate); /* Simple display settings (Envelops entire body block)*/ if (simpledisplay == "0") { @@ -13395,13 +13400,13 @@ on('clicked:applyDamage', (info) => { /* Damage helper functions beginning */ function getIcon(iconFolder, iconName, settingLimbusStyle = "false") { if (settingLimbusStyle == "true") { - return ``; + return ``; } else { - return `` + return `` } } -function generateDamageHelperHeader(statName, newStat, oldStat, staggerState="0") { +function generateDamageHelperHeader(statName, newStat, oldStat, staggerState="0", autoapplydamage="true", hidebarupdate="false") { let langBar = "HP"; let langDamage = "damage"; let langSuffered = "received"; @@ -13424,6 +13429,7 @@ function generateDamageHelperHeader(statName, newStat, oldStat, staggerState="0" langBar = statName; } if (staggerState == "Staggered") { updateDisplay = `
${langStaggered}!
`; } + else if (autoapplydamage != "true" || hidebarupdate != "false") { updateDisplay = `
---
`; } else { updateDisplay = `
${oldStat} -> ${newStat}
`; } if (newStat < oldStat) { langSuffered = getTranslationByKey("message-received"); @@ -14970,8 +14976,6 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals let stylingList = parseAutoScriptStyling(values.autoScriptStyling); - console.log(stylingList) - let output = {}; let tempOutput = {}; let returnValues = { checkResult:"success", error:false }; @@ -15042,7 +15046,7 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals conditionalButtonSilent = AutoEffect[0].includes("Silent") ? "" : " " + "Silent"; autoEffectType = "conditional message + button"; } else { - autoEffectConditional = conditional.replace("Button","").trim(); + autoEffectConditional = conditional.replace("#Button","").trim(); conditionalButtonSilent = ""; autoEffectType = "conditional button"; } @@ -15150,9 +15154,9 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals } /* Handle DicePower, DiceMax, DiceCount and Speed with Combat duration */ - if (tempOutput.dicePower != undefined) { returnValues.dicePower = tempOutput.dicePower } - if (tempOutput.diceMax != undefined) { returnValues.diceMax = tempOutput.diceMax } - if (tempOutput.diceCount != undefined) { returnValues.diceCount = tempOutput.diceCount } + if (tempOutput.DicePower != undefined) { returnValues.dicePower = tempOutput.DicePower } + if (tempOutput.DiceMax != undefined) { returnValues.diceMax = tempOutput.DiceMax } + if (tempOutput.DiceCount != undefined) { returnValues.diceCount = tempOutput.DiceCount } if (tempOutput.speedCombat != undefined) { returnValues.speedCombat = tempOutput.speedCombat } /* Handle challenge rolls */ @@ -15601,7 +15605,7 @@ function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { /* Handle bar count */ else if (barList.hasOwnProperty(effectName)) { count = barList[effectName]; } /* Handle bar damage count */ - else if (barDamageList.hasOwnProperty("-" + effectName)) { count = barDamageList[effectName]; } + else if (barDamageList.hasOwnProperty(effectName)) { count = barDamageList[effectName]; } else { return autoEffectErrorMessage("Invalid Target", `Ailment, Bar or BarDamage "${effectName}" does not exist`, AutoEffect); } /* Get required value. Recalculate count if percentage */ @@ -15640,7 +15644,7 @@ function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { } /* Handle message */ - let messageFormat = getTranslationByKeyCustom("Require [SCALING NUM] [TARGET]: [CHECK]", "autoeffect-require"); + let messageFormat = getTranslationByKeyCustom("Require [SCALING NUM] [TARGET]: [CHECK]", "autoeffect-format-require"); let effectIcon = effectName; if (ailmentList.hasOwnProperty(effectName)) { @@ -15944,7 +15948,7 @@ function autoEffectDice(AutoEffect, scaling) { messageValues = { effectTarget: AutoEffect[0].replace("Dice", "Dice "), effectVal: effectVal/scaling, effectCount: 0, scaling: scaling, checkResult: "success" } /* Execute AutoEffect */ - return { [AutoEffect[0].replace("D","d")]: parseInt(effectVal), message: message, messageValues: messageValues } + return { [AutoEffect[0]]: parseInt(effectVal), message: message, messageValues: messageValues } } function autoEffectChallengeRoll(AutoEffect, scaling) { @@ -16004,7 +16008,7 @@ function autoEffectSpeed(AutoEffect, scaling, prevThisRoundSpeed, prevNextRoundS /* Handle message */ let message = ""; let messageValues = {}; - getTranslationByKeyCustom("Increase [TARGET] by [SCALING NUM]", "autoeffect-format-speed"); + let messageFormat = getTranslationByKeyCustom("Increase [TARGET] by [SCALING NUM]", "autoeffect-format-speed"); if (effectVal < 0) { messageFormat = getTranslationByKeyCustom("Reduce [TARGET] by [SCALING NUM]", "autoeffect-format-speed-neg"); } switch (effectDuration) { case "Combat": messageFormat += " " + getTranslationByKeyCustom("this combat", "autoeffect-option-thiscombat"); break; diff --git a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css index 59b2dcf0d3..55a8335881 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css +++ b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css @@ -2643,14 +2643,14 @@ justify-content: center; bottom: 5px; right: 65px; z-index: 20; - background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/icons/script.png'); + background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/Release-v0.6/ProjectMoonTRPG/imagesResized/icons/script.png'); } .closeAutoScriptButton { top: 4px; right: 6px; z-index: 20; - background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/icons/exit.png'); + background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/Release-v0.6/ProjectMoonTRPG/imagesResized/icons/exit.png'); } .saveAutoScriptButton { diff --git a/ProjectMoonTRPG/translation.json b/ProjectMoonTRPG/translation.json index 0f1fd5e657..2afba76ad5 100644 --- a/ProjectMoonTRPG/translation.json +++ b/ProjectMoonTRPG/translation.json @@ -8,11 +8,13 @@ "settings":"Settings", "settings-mute":"Mute ailment messages", "settings-detect":"Auto: Detect combat states", + "settings-disableautoapplydamage":"Auto: Apply damage taken", "settings-simpledisplay":"Simple roll display", "settings-extraequip":"Extra weapons/tools/skills", "settings-hidespecial":"Hide: Special items", "settings-hidebaseeffect":"Hide: Base effects", "settings-hidenextturn":"Hide: Next turn input", + "settings-hidebarupdate":"Hide: Status bar update", "settings-hidehelpertext":"Hide: Helper text", "settings-hideshare":"Hide: Share buttons", "settings-burnimmune":"No burn damage", From 1a00a6f3c75a438599aa687d67e17126a35b249a Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Mon, 5 Aug 2024 18:42:03 +0200 Subject: [PATCH 44/55] Cleanup: Changed name of Endure icon to Endurance to match the name of the status ailment --- ProjectMoonTRPG/ProjectMoonTRPGStyle.css | 6 +++--- .../images/ailments/{Endure.png => Endurance.png} | Bin .../ailments/limbus/{Endure.png => Endurance.png} | Bin .../limbus/{EndureBlue.png => EnduranceBlue.png} | Bin 4 files changed, 3 insertions(+), 3 deletions(-) rename ProjectMoonTRPG/images/ailments/{Endure.png => Endurance.png} (100%) rename ProjectMoonTRPG/images/ailments/limbus/{Endure.png => Endurance.png} (100%) rename ProjectMoonTRPG/images/ailments/limbus/{EndureBlue.png => EnduranceBlue.png} (100%) diff --git a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css index 55a8335881..5c7b8c46fa 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css +++ b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css @@ -2040,13 +2040,13 @@ background-image: url('https://raw.githubusercontent.com/punibird/roll20-charact } .endurance { -background-image: url('https://raw.githubusercontent.com/punibird/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/ailments/Endure.png'); +background-image: url('https://raw.githubusercontent.com/punibird/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/ailments/Endurance.png'); } .endurance-limbus { -background-image: url('https://raw.githubusercontent.com/punibird/roll20-character-sheets/master/ProjectMoonTRPG/images/ailments/limbus/Endure.png'); +background-image: url('https://raw.githubusercontent.com/punibird/roll20-character-sheets/master/ProjectMoonTRPG/images/ailments/limbus/Endurance.png'); } .endurance-limbus-blue { -background-image: url('https://raw.githubusercontent.com/punibird/roll20-character-sheets/master/ProjectMoonTRPG/images/ailments/limbus/EndureBlue.png'); +background-image: url('https://raw.githubusercontent.com/punibird/roll20-character-sheets/master/ProjectMoonTRPG/images/ailments/limbus/EnduranceBlue.png'); } .haste { diff --git a/ProjectMoonTRPG/images/ailments/Endure.png b/ProjectMoonTRPG/images/ailments/Endurance.png similarity index 100% rename from ProjectMoonTRPG/images/ailments/Endure.png rename to ProjectMoonTRPG/images/ailments/Endurance.png diff --git a/ProjectMoonTRPG/images/ailments/limbus/Endure.png b/ProjectMoonTRPG/images/ailments/limbus/Endurance.png similarity index 100% rename from ProjectMoonTRPG/images/ailments/limbus/Endure.png rename to ProjectMoonTRPG/images/ailments/limbus/Endurance.png diff --git a/ProjectMoonTRPG/images/ailments/limbus/EndureBlue.png b/ProjectMoonTRPG/images/ailments/limbus/EnduranceBlue.png similarity index 100% rename from ProjectMoonTRPG/images/ailments/limbus/EndureBlue.png rename to ProjectMoonTRPG/images/ailments/limbus/EnduranceBlue.png From e0678fc4d613a04fd0e0d9d22263426397b99a2f Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Mon, 5 Aug 2024 18:49:36 +0200 Subject: [PATCH 45/55] Cleanup: Changed resized version of Endurance icon --- ProjectMoonTRPG/ProjectMoonTRPGStyle.css | 6 +++--- .../ailments/{Endure.png => Endurance.png} | Bin .../ailments/limbus/{Endure.png => Endurance.png} | Bin .../limbus/{EndureBlue.png => EndureanceBlue.png} | Bin 4 files changed, 3 insertions(+), 3 deletions(-) rename ProjectMoonTRPG/imagesResized/ailments/{Endure.png => Endurance.png} (100%) rename ProjectMoonTRPG/imagesResized/ailments/limbus/{Endure.png => Endurance.png} (100%) rename ProjectMoonTRPG/imagesResized/ailments/limbus/{EndureBlue.png => EndureanceBlue.png} (100%) diff --git a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css index 5c7b8c46fa..503164521e 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css +++ b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css @@ -2040,13 +2040,13 @@ background-image: url('https://raw.githubusercontent.com/punibird/roll20-charact } .endurance { -background-image: url('https://raw.githubusercontent.com/punibird/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/ailments/Endurance.png'); +background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/ailments/Endurance.png'); } .endurance-limbus { -background-image: url('https://raw.githubusercontent.com/punibird/roll20-character-sheets/master/ProjectMoonTRPG/images/ailments/limbus/Endurance.png'); +background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/master/ProjectMoonTRPG/images/ailments/limbus/Endurance.png'); } .endurance-limbus-blue { -background-image: url('https://raw.githubusercontent.com/punibird/roll20-character-sheets/master/ProjectMoonTRPG/images/ailments/limbus/EnduranceBlue.png'); +background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/master/ProjectMoonTRPG/images/ailments/limbus/EnduranceBlue.png'); } .haste { diff --git a/ProjectMoonTRPG/imagesResized/ailments/Endure.png b/ProjectMoonTRPG/imagesResized/ailments/Endurance.png similarity index 100% rename from ProjectMoonTRPG/imagesResized/ailments/Endure.png rename to ProjectMoonTRPG/imagesResized/ailments/Endurance.png diff --git a/ProjectMoonTRPG/imagesResized/ailments/limbus/Endure.png b/ProjectMoonTRPG/imagesResized/ailments/limbus/Endurance.png similarity index 100% rename from ProjectMoonTRPG/imagesResized/ailments/limbus/Endure.png rename to ProjectMoonTRPG/imagesResized/ailments/limbus/Endurance.png diff --git a/ProjectMoonTRPG/imagesResized/ailments/limbus/EndureBlue.png b/ProjectMoonTRPG/imagesResized/ailments/limbus/EndureanceBlue.png similarity index 100% rename from ProjectMoonTRPG/imagesResized/ailments/limbus/EndureBlue.png rename to ProjectMoonTRPG/imagesResized/ailments/limbus/EndureanceBlue.png From ba493b3e191e29406d8a430f1050959980402165 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Mon, 5 Aug 2024 18:52:10 +0200 Subject: [PATCH 46/55] AutoEffects: part 18.5 - Added option to set a max value for Scaling using the format ScalingN --- ProjectMoonTRPG/ProjectMoonTRPG.html | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 8a2bbb578e..b650dced7a 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -15566,7 +15566,7 @@ function autoEffectCustomMessage(AutoEffect, messageValues = {}) { /* Check if CustomMessage is silent. No reason to do any formatting being that the message will not be displayed anyways */ let silent = "false"; - if (AutoEffect.indexOf("#Silent") > AutoEffect.lastIndexOf('"')) { + if (AutoEffect.indexOf("Silent") > AutoEffect.lastIndexOf('"')) { silent = "true"; } @@ -15595,7 +15595,7 @@ function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { /* Check format */ if (AutoEffect.length < 3 || AutoEffect.length > 5) { return autoEffectErrorMessage("Format Error", `Expected format: (Require N #Ailment/#Bar/#BarDamage #Scaling(optional) #Silent(optional))`, AutoEffect); } - if (AutoEffect.length > 3) { AutoEffect.slice(3).forEach(option => { if (!["scaling", "silent"].includes(option.toLowerCase())) { returnValues = autoEffectErrorMessage("Invalid Option", `Option "${option}" is not a valid option`, AutoEffect); } }); } + if (AutoEffect.length > 3) { AutoEffect.slice(3).forEach(option => { if (!(["scaling", "silent"].includes(option.toLowerCase()) || (/(scaling[0-9]+)/ig).test(option))) { returnValues = autoEffectErrorMessage("Invalid Option", `Option "${option}" is not a valid option`, AutoEffect); } }); } /* Get target count */ let effectName = AutoEffect[2]; @@ -15630,8 +15630,12 @@ function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { /* Handle the optional scaling property */ let scaling = 1; if (AutoEffect[3] != undefined) { - if (AutoEffect[3].toLowerCase() == "scaling") { - scaling = Math.floor(count/effectVal); + if (AutoEffect[3].toLowerCase().includes("scaling")) { + if ((/(scaling[0-9]+)/ig).test(AutoEffect[3])) { + scaling = Math.min(Math.floor(count/effectVal), parseInt(AutoEffect[3].toLowerCase().replace("scaling",""))); + } else { + scaling = Math.floor(count/effectVal); + } returnValues.scaling = scaling; } } @@ -15666,7 +15670,7 @@ function autoEffectConsume(AutoEffect, ailmentList, barList) { /* Check format */ if (AutoEffect.length < 3 || AutoEffect.length > 5) { return autoEffectErrorMessage("Format Error", `Expected format: (Consume N #Ailment/#Bar #Scaling(optional) #Silent(optional))`, AutoEffect); } - if (AutoEffect.length > 3) { AutoEffect.slice(3).forEach(option => { if (!["scaling", "silent"].includes(option.toLowerCase())) { returnValues = autoEffectErrorMessage("Invalid Option", `Option "${option}" is not a valid option`, AutoEffect); } }); } + if (AutoEffect.length > 3) { AutoEffect.slice(3).forEach(option => { if (!(["scaling", "silent"].includes(option.toLowerCase()) || (/(scaling[0-9]+)/ig).test(option))) { returnValues = autoEffectErrorMessage("Invalid Option", `Option "${option}" is not a valid option`, AutoEffect); } }); } /* Get consumed value */ let effectVal = parseInt(Math.abs(AutoEffect[1])); @@ -15693,8 +15697,12 @@ function autoEffectConsume(AutoEffect, ailmentList, barList) { /* Handle the optional scaling property */ let scaling = 1; if (AutoEffect[3] != undefined) { - if (AutoEffect[3].toLowerCase() == "scaling") { - scaling = Math.floor(count/effectVal); + if (AutoEffect[3].toLowerCase().includes("scaling")) { + if ((/(scaling[0-9]+)/ig).test(AutoEffect[3])) { + scaling = Math.min(Math.floor(count/effectVal), parseInt(AutoEffect[3].toLowerCase().replace("scaling",""))); + } else { + scaling = Math.floor(count/effectVal); + } returnValues.scaling = scaling; } } From 4a6c2f877537066a74f27929a30952cc9a18997e Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Mon, 5 Aug 2024 19:27:09 +0200 Subject: [PATCH 47/55] AutoEffects: part 19 - Added support for float values for DicePower, DiceMax, DiceCount and speed. Round down before the value is applied to a roll --- ProjectMoonTRPG/ProjectMoonTRPG.html | 44 ++++++++++++++++++---------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index b650dced7a..c38b5f6f78 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -12787,10 +12787,10 @@ function rollChallenge(buttonid, rollDifficulty=0, handleAutoScriptConditionals= let autoEffectDiceCount = 0; let autoEffectDiceMax = 0; let autoEffectSpeedCombat = 0; - if (returnValues.dicePower != undefined) { stat += returnValues.dicePower; } - if (returnValues.diceCount != undefined) { autoEffectDiceCount = returnValues.diceCount; } - if (returnValues.diceMax != undefined) { autoEffectDiceMax = returnValues.diceMax; } - if (returnValues.speedCombat != undefined) { autoEffectSpeedCombat = returnValues.speedCombat; } + if (returnValues.dicePower != undefined) { stat += returnValues.parseInt(dicePower); } + if (returnValues.diceCount != undefined) { autoEffectDiceCount = parseInt(returnValues.diceCount); } + if (returnValues.diceMax != undefined) { autoEffectDiceMax = parseInt(returnValues.diceMax); } + if (returnValues.speedCombat != undefined) { autoEffectSpeedCombat = parseInt(returnValues.speedCombat); } let autoScriptMessage = ""; if (returnValues.message != undefined) { autoScriptMessage = returnValues.message } @@ -14956,8 +14956,8 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals let SPdamage = values.SP_max - SP; let barDamageList = { "-HP": HPdamage, "-ST":STdamage, "-SP":SPdamage } - let thisRoundSpeed = values.thisRoundSpeed; - let nextRoundSpeed = values.nextRoundSpeed; + let thisRoundSpeed = parseInt(values.thisRoundSpeed); + let nextRoundSpeed = parseInt(values.nextRoundSpeed); let StaggerState = values.StaggerState; let distortState = values.distortState; @@ -15154,10 +15154,22 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals } /* Handle DicePower, DiceMax, DiceCount and Speed with Combat duration */ - if (tempOutput.DicePower != undefined) { returnValues.dicePower = tempOutput.DicePower } - if (tempOutput.DiceMax != undefined) { returnValues.diceMax = tempOutput.DiceMax } - if (tempOutput.DiceCount != undefined) { returnValues.diceCount = tempOutput.DiceCount } - if (tempOutput.speedCombat != undefined) { returnValues.speedCombat = tempOutput.speedCombat } + if (tempOutput.DicePower != undefined) { + if (returnValues.dicePower != undefined) { returnValues.dicePower += tempOutput.DicePower } + else { returnValues.dicePower = tempOutput.DicePower } + } + if (tempOutput.DiceMax != undefined) { + if (returnValues.DiceMax != undefined) { returnValues.DiceMax += tempOutput.DiceMax } + else { returnValues.DiceMax = tempOutput.DiceMax } + } + if (tempOutput.DiceCount != undefined) { + if (returnValues.DiceCount != undefined) { returnValues.DiceCount += tempOutput.DiceCount } + else { returnValues.DiceCount = tempOutput.DiceCount } + } + if (tempOutput.speedCombat != undefined) { + if (returnValues.speedCombat != undefined) { returnValues.speedCombat += tempOutput.speedCombat } + else { returnValues.speedCombat = tempOutput.speedCombat } + } /* Handle challenge rolls */ if (tempOutput.challengeRollStat != undefined) { @@ -15941,7 +15953,7 @@ function autoEffectDice(AutoEffect, scaling) { if (scaling == 0) { return {}; } /* Get values */ - let effectVal = parseInt(AutoEffect[1]); + let effectVal = parseFloat(AutoEffect[1]); if (isNaN(effectVal) == true) { return autoEffectErrorMessage("Invalid Value", `Value "${AutoEffect[1]}" is not a number`, AutoEffect); } /* Handle message */ @@ -15956,7 +15968,7 @@ function autoEffectDice(AutoEffect, scaling) { messageValues = { effectTarget: AutoEffect[0].replace("Dice", "Dice "), effectVal: effectVal/scaling, effectCount: 0, scaling: scaling, checkResult: "success" } /* Execute AutoEffect */ - return { [AutoEffect[0]]: parseInt(effectVal), message: message, messageValues: messageValues } + return { [AutoEffect[0]]: parseFloat(effectVal), message: message, messageValues: messageValues } } function autoEffectChallengeRoll(AutoEffect, scaling) { @@ -16003,7 +16015,7 @@ function autoEffectSpeed(AutoEffect, scaling, prevThisRoundSpeed, prevNextRoundS if (scaling == 0) { return {}; } /* Get values */ - let effectVal = parseInt(AutoEffect[1]); + let effectVal = parseFloat(AutoEffect[1]); if (isNaN(effectVal) == true) { return autoEffectErrorMessage("Invalid Value", `Value "${AutoEffect[1]}" is not a number`, AutoEffect); } /* Get duration */ @@ -16031,9 +16043,9 @@ function autoEffectSpeed(AutoEffect, scaling, prevThisRoundSpeed, prevNextRoundS /* Execute AutoEffect */ switch (effectDuration) { - case "Combat": return { speedCombat: parseInt(effectVal), message: message, messageValues: messageValues }; break; - case "ThisRound": return { thisRoundSpeed: parseInt(effectVal), count: parseInt(prevThisRoundSpeed), message: message, messageValues: messageValues }; break; - case "NextRound": return { nextRoundSpeed: parseInt(effectVal), count: parseInt(prevNextRoundSpeed), message: message, messageValues: messageValues }; break; + case "Combat": return { speedCombat: parseFloat(effectVal), message: message, messageValues: messageValues }; break; + case "ThisRound": return { thisRoundSpeed: parseFloat(effectVal), count: parseInt(prevThisRoundSpeed), message: message, messageValues: messageValues }; break; + case "NextRound": return { nextRoundSpeed: parseFloat(effectVal), count: parseInt(prevNextRoundSpeed), message: message, messageValues: messageValues }; break; } } From c6b0a93214f47b7034e2e497f2dde37ce5a8f634 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Mon, 5 Aug 2024 21:45:50 +0200 Subject: [PATCH 48/55] =?UTF-8?q?Cleanup:=20CustomMessage=20AutoEffect=20n?= =?UTF-8?q?ow=20function=20with=20=E2=80=9C=E2=80=9D=20quotes=20(From=20Wo?= =?UTF-8?q?rd=20and=20Google=20Docs)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ProjectMoonTRPG/ProjectMoonTRPG.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index c38b5f6f78..dac97a4060 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -15582,7 +15582,7 @@ function autoEffectCustomMessage(AutoEffect, messageValues = {}) { silent = "true"; } - if (AutoEffect[1] != undefined) { messageFormat = AutoEffect.slice(1).join(" "); } + if (AutoEffect[1] != undefined) { messageFormat = AutoEffect.slice(1).join(" ").replaceAll('“','"').replaceAll('”','"'); } if ((/\"[ \t]*(checksuccess)/ig).test(messageFormat)) { messageFormat = messageFormat.replaceAll((/\"[ \t]*(checksuccess)/ig), "") } else if ((/\"[ \t]*(checkfailure)/ig).test(messageFormat)) { checkResultOption = "failure"; messageFormat = messageFormat.replaceAll(/\"[ \t]*(checkfailure)/ig, "") } else if ((/\"[ \t]*(checkignore)/ig).test(messageFormat)) { checkResultOption = "ignore"; messageFormat = messageFormat.replaceAll(/\"[ \t]*(checkignore)/ig, "")} From 212176a8d33844363d819a518c661c9562139b07 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Tue, 6 Aug 2024 02:24:46 +0200 Subject: [PATCH 49/55] Cleanup: Changed Auto Apply Damage translation name --- ProjectMoonTRPG/ProjectMoonTRPG.html | 2 +- ProjectMoonTRPG/translation.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index dac97a4060..c608d93f3b 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -34,7 +34,7 @@ - + diff --git a/ProjectMoonTRPG/translation.json b/ProjectMoonTRPG/translation.json index 2afba76ad5..464f74372a 100644 --- a/ProjectMoonTRPG/translation.json +++ b/ProjectMoonTRPG/translation.json @@ -8,7 +8,7 @@ "settings":"Settings", "settings-mute":"Mute ailment messages", "settings-detect":"Auto: Detect combat states", - "settings-disableautoapplydamage":"Auto: Apply damage taken", + "settings-autoapplydamage":"Auto: Apply damage taken", "settings-simpledisplay":"Simple roll display", "settings-extraequip":"Extra weapons/tools/skills", "settings-hidespecial":"Hide: Special items", From 78134e374ee2bf8fd6c2835ba8ac5a149b583546 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Tue, 6 Aug 2024 03:00:46 +0200 Subject: [PATCH 50/55] Cleanup: Changed all image link to reference the master branch --- ProjectMoonTRPG/ProjectMoonTRPG.html | 4 ++-- ProjectMoonTRPG/ProjectMoonTRPGStyle.css | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index c608d93f3b..d4d23879e0 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -13400,9 +13400,9 @@ on('clicked:applyDamage', (info) => { /* Damage helper functions beginning */ function getIcon(iconFolder, iconName, settingLimbusStyle = "false") { if (settingLimbusStyle == "true") { - return ``; + return ``; } else { - return `` + return `` } } diff --git a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css index 503164521e..ad79e28d5b 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css +++ b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css @@ -2643,14 +2643,14 @@ justify-content: center; bottom: 5px; right: 65px; z-index: 20; - background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/Release-v0.6/ProjectMoonTRPG/imagesResized/icons/script.png'); + background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/icons/script.png'); } .closeAutoScriptButton { top: 4px; right: 6px; z-index: 20; - background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/Release-v0.6/ProjectMoonTRPG/imagesResized/icons/exit.png'); + background-image: url('https://raw.githubusercontent.com/beautidemise/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/icons/exit.png'); } .saveAutoScriptButton { From f4fb3df570ad30ebb2a94210be787061e4e101d2 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Tue, 6 Aug 2024 03:13:36 +0200 Subject: [PATCH 51/55] Cleanup: Fixed ailment display spinner buttons hiding text behind them --- ProjectMoonTRPG/ProjectMoonTRPGStyle.css | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css index ad79e28d5b..ed03a284f8 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css +++ b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css @@ -1773,8 +1773,14 @@ background-image: linear-gradient(to bottom, rgba(0,0,0,0.8), rgba(0,0,0,0)), ur left: 25px; } -/* This two rules disables the spinner (up and down buttons in number inputs) when not hovering over or selecting an ailment field */ -/* Also work for Firefox! */ +/* This rule disables the spinner (up and down buttons in number inputs) when not hovering over or selecting an ailment field */ +.ailmentNumNextTurn:not(:hover):not(:focus)::-webkit-inner-spin-button, +.ailmentNumNextTurn:not(:hover):not(:focus)::-webkit-outer-spin-button, +.ailmentNumThisTurn:not(:hover):not(:focus)::-webkit-inner-spin-button, +.ailmentNumThisTurn:not(:hover):not(:focus)::-webkit-outer-spin-button { + display: none; +} +/* This disables the spinner in Firefox! */ .ailmentNumNextTurn, .ailmentNumThisTurn { appearance: textfield; } From bf0d9d2c4a91bd5ac2252891290a101f809c6848 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Tue, 6 Aug 2024 06:01:48 +0200 Subject: [PATCH 52/55] Cleanup: Corrected some more styling issues for Firefox browsers --- ProjectMoonTRPG/ProjectMoonTRPG.html | 2 +- ProjectMoonTRPG/ProjectMoonTRPGStyle.css | 29 ++++++++++++++++++------ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index d4d23879e0..57ac83d30f 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -1563,7 +1563,7 @@
-
+
Speed/Luck
diff --git a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css index ed03a284f8..134e4ed344 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPGStyle.css +++ b/ProjectMoonTRPG/ProjectMoonTRPGStyle.css @@ -1379,12 +1379,18 @@ opacity: 50%; .tool input[type=checkbox], .profileHeader input[type=checkbox] { display:none; } -.toolMaxInput:not(:hover):not(:focus)::-webkit-inner-spin-button, -.toolMaxInput:not(:hover):not(:focus)::-webkit-outer-spin-button, +/* Hide spinner on Chromium brosers unless selected/hovered over */ .toolMaxInput:not(:hover):not(:focus)::-webkit-inner-spin-button, .toolMaxInput:not(:hover):not(:focus)::-webkit-outer-spin-button { display: none; } +/* Hide spinner on Firefox */ +.toolMaxInput { + appearance: textfield; +} +.toolMaxInput:focus, .toolMaxInput:hover { + appearance: auto; +} .portableIcon { background-image: url("https://raw.githubusercontent.com/punibird/roll20-character-sheets/master/ProjectMoonTRPG/imagesResized/icons/Portable.png"); } @@ -1526,13 +1532,21 @@ margin-bottom: 2px !important;} .flatSTInput { border: 2px solid #dbb748 !important; } -/* Does not display the input spinner when not in used. If this is not done the spinner hides part of larger numbers behind it */ +/* Hide spinner on Chromium brosers unless selected/hovered over */ .flatHPInput:not(:hover):not(:focus)::-webkit-inner-spin-button, .flatHPInput:not(:hover):not(:focus)::-webkit-outer-spin-button, .flatSTInput:not(:hover):not(:focus)::-webkit-inner-spin-button, .flatSTInput:not(:hover):not(:focus)::-webkit-outer-spin-button { display: none; } +/* Hide spinner on Firefox */ +.flatHPInput, .flatSTInput { + appearance: textfield; +} +.flatHPInput:focus, .flatHPInput:hover, +.flatSTInput:focus, .flatSTInput:hover { + appearance: auto; +} .damageHelperType input[type=radio] { display: none; @@ -1784,10 +1798,8 @@ background-image: linear-gradient(to bottom, rgba(0,0,0,0.8), rgba(0,0,0,0)), ur .ailmentNumNextTurn, .ailmentNumThisTurn { appearance: textfield; } -.ailmentNumNextTurn:focus, -.ailmentNumNextTurn:hover, -.ailmentNumThisTurn:focus, -.ailmentNumThisTurn:hover { +.ailmentNumNextTurn:focus, .ailmentNumNextTurn:hover, +.ailmentNumThisTurn:focus, .ailmentNumThisTurn:hover { appearance: auto; } /* If the next turn field is disabled by a hide toggle (Burn/Bleed/Smoke/Charge individual setting) or by a hide toggle rev (Global setting) the standard field is returned to it's normal styling */ @@ -2558,6 +2570,9 @@ justify-content: center; color: #999; pointer-events: none } +.autoscriptEditorContainer label { + color: #B3B3B3; +} #autoScriptInput { resize: vertical; overflow: auto; From 8e67d65b9c693d135566d7a50b398012c2dd49d0 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Tue, 6 Aug 2024 06:07:57 +0200 Subject: [PATCH 53/55] Cleanup: Hide: Status bar update not detecting when disabled --- ProjectMoonTRPG/ProjectMoonTRPG.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 57ac83d30f..af970c8063 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -12949,6 +12949,8 @@ on('clicked:applyDamage', (info) => { let simpledisplay = values.settingSimpleDisplay; let autoapplydamage = values.settingAutoApplyDamage; let hidebarupdate = values.settingHideBarUpdate; + + console.log(hidebarupdate) let characterName = values.character_name; @@ -13429,7 +13431,7 @@ function generateDamageHelperHeader(statName, newStat, oldStat, staggerState="0" langBar = statName; } if (staggerState == "Staggered") { updateDisplay = `
${langStaggered}!
`; } - else if (autoapplydamage != "true" || hidebarupdate != "false") { updateDisplay = `
---
`; } + else if (autoapplydamage != "true" || hidebarupdate == "true") { updateDisplay = `
---
`; } else { updateDisplay = `
${oldStat} -> ${newStat}
`; } if (newStat < oldStat) { langSuffered = getTranslationByKey("message-received"); From 3f2102412279f7657e380b2335bd2ab329cb9c07 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Tue, 6 Aug 2024 07:55:57 +0200 Subject: [PATCH 54/55] AutoEffects: part 19 - Added First round option for triggers, making the trigger only activate if it is currently the first roun - Fixed a bug with displaying Reset not correctly reseting the checkResult --- ProjectMoonTRPG/ProjectMoonTRPG.html | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index af970c8063..9f1ed15a68 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -1573,6 +1573,7 @@ +
@@ -11942,7 +11943,7 @@ getSectionIDs(`repeating_global`, idarray => { setAttrs({ - "thisRoundSpeed":nextRoundSpeed, "nextRoundSpeed":0, "Bleed":bleednew, "BleedNextTurn":"0", "Burn": burnnew, "BurnNextTurn":"0", "Paralysis": paralysisnew, "ParalysisNextTurn":"0", "Protection": protectionnew, "ProtectionNextTurn":"0", "StaggerProtection": staggerprotectionnew, "StaggerProtectionNextTurn":"0", "Fragile": fragilenew, "FragileNextTurn":"0", "Strength": strengthnew, "StrengthNextTurn":"0", "Feeble": feeblenew, "FeebleNextTurn":"0", "Endurance": endurancenew, "EnduranceNextTurn":"0", "Disarm": disarmnew, "DisarmNextTurn":"0", "Haste": hastenew, "HasteNextTurn":"0", "Bind": bindnew, "BindNextTurn":"0", "Smoke": smokenew, "SmokeNextTurn":"0", "Charge":chargenew, "ChargeNextTurn":"0", "Fortune":fortunenew, "FortuneNextTurn":"0", "baseActNum":"0"}); + "thisRoundSpeed":nextRoundSpeed, "nextRoundSpeed":0, "isFirstRound":"false", "Bleed":bleednew, "BleedNextTurn":"0", "Burn": burnnew, "BurnNextTurn":"0", "Paralysis": paralysisnew, "ParalysisNextTurn":"0", "Protection": protectionnew, "ProtectionNextTurn":"0", "StaggerProtection": staggerprotectionnew, "StaggerProtectionNextTurn":"0", "Fragile": fragilenew, "FragileNextTurn":"0", "Strength": strengthnew, "StrengthNextTurn":"0", "Feeble": feeblenew, "FeebleNextTurn":"0", "Endurance": endurancenew, "EnduranceNextTurn":"0", "Disarm": disarmnew, "DisarmNextTurn":"0", "Haste": hastenew, "HasteNextTurn":"0", "Bind": bindnew, "BindNextTurn":"0", "Smoke": smokenew, "SmokeNextTurn":"0", "Charge":chargenew, "ChargeNextTurn":"0", "Fortune":fortunenew, "FortuneNextTurn":"0", "baseActNum":"0"}); }); @@ -12909,7 +12910,7 @@ function rollChallenge(buttonid, rollDifficulty=0, handleAutoScriptConditionals= setAttrs({"baseLuckNum": total }); } else if(statn == "Speed"){ - setAttrs({"baseSpeed": total }); + setAttrs({"baseSpeed": total, "isFirstRound": "true"}); } finishRoll( @@ -12949,8 +12950,6 @@ on('clicked:applyDamage', (info) => { let simpledisplay = values.settingSimpleDisplay; let autoapplydamage = values.settingAutoApplyDamage; let hidebarupdate = values.settingHideBarUpdate; - - console.log(hidebarupdate) let characterName = values.character_name; @@ -14905,7 +14904,7 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals } } - getAttrs(["augmentAutoScript", "outfitAutoScript", "egoAutoScript", "distortState", "egoActiveState"], function(values) { + getAttrs(["augmentAutoScript", "outfitAutoScript", "egoAutoScript", "distortState", "egoActiveState", "isFirstRound"], function(values) { let augmentAutoScript = ""; let outfitAutoScript = ""; @@ -14924,7 +14923,12 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals let collectedAutoScripts = autoScriptToArray(augmentAutoScript + outfitAutoScript + egoAutoScript, "nested"); + let firstRound = getTranslationByKeyCustom("#First round", "") + collectedAutoScripts.forEach((trigger) => { + /* Accept #First round triggers if it is currently the first round. Otherwise discard them */ + if (trigger[0].includes(firstRound) && values.isFirstRound == "true") { trigger[0] = trigger[0].replace(firstRound,"").trim(); } + if (autoScriptTriggers.includes(getTriggerFromTranslation(trigger[0]))) { if (AutoScript != "") { AutoScript += "(Reset)"; } AutoScript += trigger[1]; @@ -15025,7 +15029,7 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals ailmentList[ailName] = [ailHasNextTurn, ailNum, ailNumNextTurn, id, ailIcon]; }); - + /* Execute each AutoEffect in the AutoScript */ AutoScript.forEach(AutoEffect => { @@ -15081,7 +15085,7 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals switch (AutoEffect[0][0]) { case "Require": tempOutput = autoEffectRequire(AutoEffect[0], ailmentList, barList, barDamageList); break; case "Consume": tempOutput = autoEffectConsume(AutoEffect[0], ailmentList, barList); break; - case "Reset": tempOutput = {checkResult: "success", scaling: 1}; break; + case "Reset": tempOutput = { checkResult: "success", scaling: 1, messageValues: {checkResult:"success"} }; break; case "CustomMessage": tempOutput = autoEffectCustomMessage(AutoEffect[0], messageValues); break; default: tempOutput = {}; break; } @@ -15197,6 +15201,8 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals delete tempOutput.message; } + console.log(conditionalMessageList) + /* Handle messageValues. Used by the CustomMessage AutoEffect. Outputted by all AutoEffects that generate messages */ if (tempOutput.messageValues != undefined) { messageValues = tempOutput.messageValues; @@ -15309,6 +15315,7 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals function cleanAutoScript(AutoScript) { let cleanAutoScript = AutoScript.replace(/(\r\n|\n|\r|\t)/gm, ""); cleanAutoScript = cleanAutoScript.replace(/\/\*[\s\S]*?\*\/|(?<=[^:])\/\/.*|^\/\/.*/g,''); + cleanAutoScript = cleanAutoScript.replaceAll('“','').replaceAll('”',''); return cleanAutoScript; } @@ -15584,7 +15591,7 @@ function autoEffectCustomMessage(AutoEffect, messageValues = {}) { silent = "true"; } - if (AutoEffect[1] != undefined) { messageFormat = AutoEffect.slice(1).join(" ").replaceAll('“','"').replaceAll('”','"'); } + if (AutoEffect[1] != undefined) { messageFormat = AutoEffect.slice(1).join(" "); } if ((/\"[ \t]*(checksuccess)/ig).test(messageFormat)) { messageFormat = messageFormat.replaceAll((/\"[ \t]*(checksuccess)/ig), "") } else if ((/\"[ \t]*(checkfailure)/ig).test(messageFormat)) { checkResultOption = "failure"; messageFormat = messageFormat.replaceAll(/\"[ \t]*(checkfailure)/ig, "") } else if ((/\"[ \t]*(checkignore)/ig).test(messageFormat)) { checkResultOption = "ignore"; messageFormat = messageFormat.replaceAll(/\"[ \t]*(checkignore)/ig, "")} From c57ab2c67ef81ff5fce9c4fe4ddf6a84ecbd2df1 Mon Sep 17 00:00:00 2001 From: BeautiDemise Date: Tue, 6 Aug 2024 14:14:34 +0200 Subject: [PATCH 55/55] AutoEffects: final update - CustomMessages can now contain commas and parentheses - Fixed some conditionals not displaying correctly - Ailment icons are now set correctly when the ailment name doesn't match the icon name --- ProjectMoonTRPG/ProjectMoonTRPG.html | 148 +++++++++++++++------------ ProjectMoonTRPG/translation.json | 1 + 2 files changed, 86 insertions(+), 63 deletions(-) diff --git a/ProjectMoonTRPG/ProjectMoonTRPG.html b/ProjectMoonTRPG/ProjectMoonTRPG.html index 9f1ed15a68..c4b026a360 100644 --- a/ProjectMoonTRPG/ProjectMoonTRPG.html +++ b/ProjectMoonTRPG/ProjectMoonTRPG.html @@ -10974,10 +10974,7 @@ on("change:PanicState", function() { /* AutoScripts */ resetConditionals(); let autoScriptTrigger = currentstate == "Panic" ? "Panic" : "None"; - AutoScriptMain("", autoScriptTrigger, "true", function(returnValues) { - - let autoScriptMessage = ""; - if (returnValues.message != undefined) { autoScriptMessage = returnValues.message } + AutoScriptMain("", autoScriptTrigger, "false") /* Translation prep */ let langStateTrue = " went into Panic!"; @@ -10990,20 +10987,19 @@ on("change:PanicState", function() { } if(messagestate != "true" && currentstate != "Panic"){ - startRoll((whisper + "&{template:message} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{message=" + langStateFalse + autoScriptMessage + "}}"), (results) => { + startRoll((whisper + "&{template:message} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{message=" + langStateFalse + "}}"), (results) => { finishRoll(results.rollId, {} ); }); } else if(messagestate != "true" && currentstate == "Panic"){ - startRoll((whisper + "&{template:message} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{message=" + langStateTrue + autoScriptMessage + "}}"), (results) => { + startRoll((whisper + "&{template:message} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{message=" + langStateTrue + "}}"), (results) => { finishRoll(results.rollId, {} ); }); } }); - }); }); /* Auto: Defeat State updates */ @@ -11030,10 +11026,7 @@ on("change:DefeatState", function() { /* AutoScripts */ resetConditionals(); - AutoScriptMain("", "Defeated", "true", function(returnValues) { - - let autoScriptMessage = ""; - if (returnValues.message != undefined) { autoScriptMessage = returnValues.message } + AutoScriptMain("", "Defeated", "false") /* Whisper roll */ let whisperrolls = values.settingWhisperRolls; @@ -11053,14 +11046,13 @@ on("change:DefeatState", function() { } if(messagestate != "true" && currentstate == "Defeated"){ - startRoll((whisper + "&{template:message} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{message=" + langDefeat + autoScriptMessage + "}}"), (results) => { + startRoll((whisper + "&{template:message} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{message=" + langDefeat + "}}"), (results) => { finishRoll(results.rollId, {} ); }); } }); - }); }); /* Auto: Stagger State updates */ @@ -11102,10 +11094,7 @@ getSectionIDs(`repeating_global`, idarray => { /* AutoScripts */ resetConditionals(); let autoScriptTrigger = currentstate == "Staggered" ? "Staggered" : "None"; - AutoScriptMain("", autoScriptTrigger, "true", function(returnValues) { - - let autoScriptMessage = ""; - if (returnValues.message != undefined) { autoScriptMessage = returnValues.message } + AutoScriptMain("", autoScriptTrigger, "false") /* Whisper roll */ let whisperrolls = values.settingWhisperRolls; @@ -11126,13 +11115,13 @@ getSectionIDs(`repeating_global`, idarray => { } if(messagestate != "true" && currentstate != "Staggered"){ - startRoll((whisper + "&{template:message} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{message=" + langStateFalse + autoScriptMessage + "}}"), (results) => { + startRoll((whisper + "&{template:message} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{message=" + langStateFalse + "}}"), (results) => { finishRoll(results.rollId, {} ); }); } else if(messagestate != "true" && currentstate == "Staggered"){ - startRoll((whisper + "&{template:message} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{message=" + langStateTrue + autoScriptMessage + "}}"), (results) => { + startRoll((whisper + "&{template:message} {{icon=@{dummyIcon}}} {{name=@{character_name}}} {{message=" + langStateTrue + "}}"), (results) => { finishRoll(results.rollId, {} ); }); @@ -11140,7 +11129,6 @@ getSectionIDs(`repeating_global`, idarray => { }); }); - }); }); /* Auto: Immobile State updates */ @@ -15058,9 +15046,9 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals } if (conditionalButtonList.hasOwnProperty(autoEffectConditional)) { - conditionalButtonList[autoEffectConditional] += " (" + AutoEffect[0].toString().replaceAll(","," ") + conditionalButtonSilent + ")"; + conditionalButtonList[autoEffectConditional] += " (" + AutoEffect[0].join(" ") + conditionalButtonSilent + ")"; } else { - conditionalButtonList[autoEffectConditional] = "(" + AutoEffect[0].toString().replaceAll(","," ") + conditionalButtonSilent + ")"; + conditionalButtonList[autoEffectConditional] = "(" + AutoEffect[0].join(" ") + conditionalButtonSilent + ")"; } /* If AutoEffect is Require or Consume, do not display the button if the check will fail */ @@ -15108,7 +15096,7 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals default: tempOutput = autoEffectErrorMessage("Invalid AutoEffect", `${AutoEffect[0][0].replace("Unknown: ","")} is not a valid AutoEffect`, AutoEffect[0]); break; } } - console.log(tempOutput) + // console.log(tempOutput) /* Handle errors. Continues executing AutoEffects for the sake of finding additional errors, */ /* but does not apply any changes to attributes */ @@ -15201,8 +15189,6 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals delete tempOutput.message; } - console.log(conditionalMessageList) - /* Handle messageValues. Used by the CustomMessage AutoEffect. Outputted by all AutoEffects that generate messages */ if (tempOutput.messageValues != undefined) { messageValues = tempOutput.messageValues; @@ -15244,28 +15230,14 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals } /* Message handling */ - if (settingMuteMessage != "true" && message != "" && returnValues.error != true) { - if (returnMessage == "false") { - let messageHeaderIcon = getIcon("icons", "gear"); - - setAttrs({dummyIcon: messageHeaderIcon, dummy: "
" + message + "
"}); - - let whisper = ""; - if(settingWhisperRolls == "true"){ - whisper = "/w " + settingWhisperTarget; - } - - startRoll((whisper + "&{template:autoeffect} {{icon=@{dummyIcon}}} {{title=" + messageHeaderTitle + "}} {{name=@{character_name}}} {{message=@{dummy} }}"), (results) => { - finishRoll(results.rollId, {} ); - }); - } - else { + if (returnValues.error != true && message != "") { + if (returnMessage == "true") { returnValues.message = autoEffectEntry("AutoEffects", message); } } /* Conditional message handling */ - if (returnValues.error != true) { + if (returnValues.message != "") { for (const [conditionName, conditionMessage] of Object.entries(conditionalMessageList)) { let iconFolder = "icons"; let iconName = "gear"; @@ -15284,7 +15256,7 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals } } - /* Error handling and returnValues callback */ + /* Error handling */ if (returnValues.error == true) { returnValues.message = ""; @@ -15297,9 +15269,27 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals returnValues.message += autoEffectEntry(errorType, errorMessage, "icons", "exit", "Red"); } } - resetConditionals(); } + + /* If no message is to be returned, print both message and returnValues.message (if it has any contents) to the chat */ + if (settingMuteMessage != "true" && (message != "" || returnValues.message != undefined)) { + if (returnMessage == "false") { + let messageHeaderIcon = getIcon("icons", "gear"); + if (returnValues.message == undefined) { returnValues.message = ""; } + let messageContents = "
" + message + returnValues.message + "
"; + + let whisper = ""; + if(settingWhisperRolls == "true"){ + whisper = "/w " + settingWhisperTarget; + } + + setAttrs({dummyIcon: messageHeaderIcon, dummy: messageContents}); + startRoll((whisper + "&{template:autoeffect} {{icon=@{dummyIcon}}} {{title=" + messageHeaderTitle + "}} {{name=@{character_name}}} {{message=@{dummy} }}"), (results) => { + finishRoll(results.rollId, {} ); + }); + } + } // console.log(output) setAttrs(output); @@ -15313,9 +15303,17 @@ function AutoScriptMain(inputAutoScript, triggerType="None", returnMessage="fals /* Removes all newline and tab characters as well as JavaScript comments from an AutoScript */ function cleanAutoScript(AutoScript) { + /* Remove all newlines and tab spaces */ let cleanAutoScript = AutoScript.replace(/(\r\n|\n|\r|\t)/gm, ""); + + /* Remove all comments */ cleanAutoScript = cleanAutoScript.replace(/\/\*[\s\S]*?\*\/|(?<=[^:])\/\/.*|^\/\/.*/g,''); - cleanAutoScript = cleanAutoScript.replaceAll('“','').replaceAll('”',''); + + /* Remove all spaces between AutoEffects ex. ) ( -> )( */ + cleanAutoScript = cleanAutoScript.replace(/\)( +)\(/g,')(') + + /* Replace all “” quotes with "" quotes */ + cleanAutoScript = cleanAutoScript.replaceAll('“','"').replaceAll('”','"'); return cleanAutoScript; } @@ -15329,16 +15327,17 @@ function autoScriptToArray(inputAutoScript, mode="normal") { let AutoScriptArray = []; let beginChar = "("; + let middleChar = ")(" let endChar = ")"; let charOffset = 1; if (mode == "nested") { beginChar = "[#"; + middleChar = "#][#"; endChar = "#]"; charOffset = 2; } - /* Remove all newlines, tab spaces and comments */ AutoScript = cleanAutoScript(AutoScript); do { @@ -15348,16 +15347,29 @@ function autoScriptToArray(inputAutoScript, mode="normal") { if (AutoScript.indexOf(beginChar) == 0 && AutoScript.indexOf(endChar)) { /* Removes the next AutoEffect from the AutoScript. Removes the parentheses */ - AutoEffect = AutoScript.substring(charOffset, AutoScript.indexOf(endChar)); - AutoScript = AutoScript.substring(AutoScript.indexOf(endChar)+charOffset); - + if (AutoScript.indexOf(middleChar) != "-1") { + AutoEffect = AutoScript.substring(charOffset, AutoScript.indexOf(middleChar)); + AutoScript = AutoScript.substring(AutoScript.indexOf(middleChar)+charOffset); + } else { + AutoEffect = AutoScript.substring(charOffset, AutoScript.length-1); + AutoScript = ""; + } + /* Structures the AutoEffect into an array and stores it */ if (mode == "nested") { AutoEffect = AutoEffect.trim().replace(",","£"); AutoEffectArray = AutoEffect.split("£"); AutoEffectArray = AutoEffectArray.map(e => e.trim()); } else { - AutoEffectArray = AutoEffect.trim().split(","); + /* For CustomMessage AutoScripts, preserve commas in the messages format by extracting the format before splitting over "," */ + if (AutoEffect.includes("CustomMessage")) { + let messageFormat = AutoEffect.match(/"(.*?)"/g); + AutoEffect = AutoEffect.replace(/"(.*?)"/g,"£").trim().split(","); + AutoEffect[0] = AutoEffect[0].replace("£", messageFormat); + AutoEffectArray = AutoEffect; + } else { + AutoEffectArray = AutoEffect.trim().split(","); + } AutoEffectArray = AutoEffectArray.map(e => e.trim()); AutoEffectArray[0] = AutoEffectArray[0].split(/\s+/); } @@ -15465,7 +15477,7 @@ function autoEffectEntry(header, message, iconFolder="icons", iconName="gear", i return newEntry; } -function autoEffectMessage(messageFormat, effectTarget="No target", effectVal=0, effectCount=0, scaling=1, checkResult="success", settingLimbusStyle="false") { +function autoEffectMessage(messageFormat, effectTarget="No target", effectVal=0, effectCount=0, scaling=1, checkResult="success", settingLimbusStyle="false", effectIcon="No icon") { if(messageFormat != ""){ let message = messageFormat; @@ -15496,8 +15508,12 @@ function autoEffectMessage(messageFormat, effectTarget="No target", effectVal=0, message = message.replaceAll(langTarget, "" + effectTarget.replace("limbus/","").replace("community/","") + ""); /* Icon handling */ - /* Get target icon. Is in this format: [/TARGET] */ - message = message.replaceAll(langTargetIcon, getIcon("ailments", effectTarget, settingLimbusStyle)); + /* Get target icon. Is in this format: [/TARGET]. If a effectIcon is procided, use that instead */ + if (effectIcon != "No icon") { + message = message.replaceAll(langTargetIcon, getIcon("ailments", effectIcon, settingLimbusStyle)); + } else { + message = message.replaceAll(langTargetIcon, getIcon("ailments", effectTarget, settingLimbusStyle)); + } /* Question mark icon */ message = message.replaceAll("[/Question]", getIcon("icons", "Question")); @@ -15579,6 +15595,7 @@ function autoEffectCustomMessage(AutoEffect, messageValues = {}) { let messageFormat = ""; let checkResultOption = "success"; let effectTarget = "No target"; + let effectIcon = "No icon"; let effectVal = 0; let effectCount = 0; let scaling = 1; @@ -15598,6 +15615,7 @@ function autoEffectCustomMessage(AutoEffect, messageValues = {}) { messageFormat = messageFormat.replaceAll('"',''); if (messageValues.effectTarget != undefined) { effectTarget = messageValues.effectTarget; } + if (messageValues.effectIcon != undefined) { effectTarget = messageValues.effectIcon; } if (messageValues.effectVal != undefined) { effectVal = messageValues.effectVal; } if (messageValues.effectCount != undefined) { effectCount = messageValues.effectCount; } if (messageValues.scaling != undefined) { scaling = messageValues.scaling; } @@ -15605,7 +15623,7 @@ function autoEffectCustomMessage(AutoEffect, messageValues = {}) { if (messageValues.settingLimbusStyle != undefined) { settingLimbusStyle = messageValues.settingLimbusStyle; } if (silent == "false" && (checkResult == checkResultOption || checkResultOption == "ignore")) { - return { message: autoEffectMessage(messageFormat, effectTarget, effectVal, effectCount, scaling, checkResult, settingLimbusStyle) } + return { message: autoEffectMessage(messageFormat, effectTarget, effectVal, effectCount, scaling, checkResult, settingLimbusStyle, effectIcon) } } else { return {} } @@ -15631,8 +15649,8 @@ function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { /* Get required value. Recalculate count if percentage */ let effectVal = AutoEffect[1]; - if (isNaN(parseInt(Math.abs(effectVal))) == false) { - effectVal = parseInt(Math.abs(effectVal)); + if (isNaN(parseFloat(Math.abs(effectVal))) == false) { + effectVal = parseFloat(Math.abs(effectVal)); } else if ((/[0-9]+[%]/g).test(String(effectVal))) { let percentage = parseFloat(effectVal.replace("%","")) / 100; @@ -15680,7 +15698,7 @@ function autoEffectRequire(AutoEffect, ailmentList, barList, barDamageList) { if (!AutoEffect.includes("Silent")) { returnValues.message = autoEffectMessage(messageFormat, effectName, effectVal, count, Math.max(scaling,1), returnValues.checkResult); } - returnValues.messageValues = { effectTarget: effectIcon, effectVal: effectVal, effectCount: count, scaling: Math.max(scaling,1), checkResult: returnValues.checkResult } + returnValues.messageValues = { effectTarget: effectName, effectIcon: effectIcon, effectVal: effectVal, effectCount: count, scaling: Math.max(scaling,1), checkResult: returnValues.checkResult } /* Return check result */ return returnValues; @@ -15747,14 +15765,17 @@ function autoEffectConsume(AutoEffect, ailmentList, barList) { /* Handle message */ let messageFormat = getTranslationByKeyCustom("Consume [SCALING NUM] [TARGET]: [CHECK]", "autoeffect-format-consume"); - - let effectIcon = ailmentList[effectName][4]; - if (ailmentList.hasOwnProperty(effectName)) { messageFormat = "[/TARGET] " + messageFormat; } + + let effectIcon = effectName; + if (ailmentList.hasOwnProperty(effectName)) { + messageFormat = "[/TARGET] " + messageFormat; + effectIcon = ailmentList[effectName][4]; + } if (!AutoEffect.includes("Silent")) { returnValues.message = autoEffectMessage(messageFormat, effectName, effectVal, count, Math.max(scaling,1), returnValues.checkResult); } - returnValues.messageValues = { effectTarget: effectIcon, effectVal: effectVal, effectCount: count, scaling: Math.max(scaling,1), checkResult: returnValues.checkResult } + returnValues.messageValues = { effectTarget: effectName, effectIcon: effectIcon, effectVal: effectVal, effectCount: count, scaling: Math.max(scaling,1), checkResult: returnValues.checkResult } /* Return check result */ return returnValues; @@ -15792,6 +15813,7 @@ function autoEffectAilment(AutoEffect, ailmentList, scaling, settingLimbusStyle) /* Handle the optional turn override */ /* This is between you and me, but "Next turn" doesn't actually do anything ;) */ let forceTarget = ""; + if (AutoEffect[3] != undefined) { if (["this", "thisround", "this round, thisturn, this turn"].includes(AutoEffect[3].toLowerCase())) { forceTarget = "This round"; } } @@ -15824,9 +15846,9 @@ function autoEffectAilment(AutoEffect, ailmentList, scaling, settingLimbusStyle) if (effectHasNextTurn == 'true' && forceTarget != "This round") { messageFormat += " next round"; } if (!AutoEffect.includes("Silent")) { - message = autoEffectMessage(messageFormat, effectIcon, effectVal/scaling, count, scaling, "success", settingLimbusStyle); + message = autoEffectMessage(messageFormat, effectAilment, effectVal/scaling, count, scaling, "success", settingLimbusStyle, effectIcon); } - messageValues = { effectTarget: effectIcon, effectVal: effectVal/scaling, effectCount: count, scaling: scaling, checkResult: "success", settingLimbusStyle: settingLimbusStyle } + messageValues = { effectTarget: effectAilment, effectVal: effectVal/scaling, effectCount: count, scaling: scaling, checkResult: "success", settingLimbusStyle: settingLimbusStyle } /* Execute AutoEffect */ returnValues = {...returnValues, message: message, messageValues: messageValues }; diff --git a/ProjectMoonTRPG/translation.json b/ProjectMoonTRPG/translation.json index 464f74372a..4e328393cc 100644 --- a/ProjectMoonTRPG/translation.json +++ b/ProjectMoonTRPG/translation.json @@ -265,6 +265,7 @@ "autoeffect-option-checksuccess":"CheckSuccess", "autoeffect-option-checkfailure":"CheckFailure", "autoeffect-option-checkignore":"CheckIgnore", + "autoeffect-option-firstround":"#First round", "autoeffect-require": "Require", "autoeffect-consume": "Consume", "autoeffect-custommessage": "CustomMessage",