Migrated internal variables to ~ prefix

This commit is contained in:
Stefan Zermatten
2023-01-31 20:36:26 +02:00
parent 16f5fe91ea
commit 67da641244
13 changed files with 82 additions and 65 deletions

View File

@@ -64,12 +64,12 @@ export function damagePropertyWork({ prop, operation, value, actionContext, logF
// Save the value to the scope before applying the before triggers
if (operation === 'increment') {
if (value >= 0) {
actionContext.scope['$damage'] = value;
actionContext.scope['~damage'] = { value };
} else {
actionContext.scope['$healing'] = -value;
actionContext.scope['~healing'] = { value: -value };
}
} else {
actionContext.scope['$set'] = value;
actionContext.scope['~set'] = { value };
}
applyTriggers(actionContext.triggers?.damageProperty?.before, prop, actionContext);
@@ -77,12 +77,12 @@ export function damagePropertyWork({ prop, operation, value, actionContext, logF
// fetch the value from the scope after the before triggers, in case they changed them
if (operation === 'increment') {
if (value >= 0) {
value = actionContext.scope['$damage'];
value = actionContext.scope['~damage']?.value;
} else {
value = -actionContext.scope['$healing'];
value = -actionContext.scope['~healing']?.value;
}
} else {
value = actionContext.scope['$set'];
value = actionContext.scope['~set']?.value;
}
let damage, newValue, increment;

View File

@@ -51,11 +51,11 @@ export default function applyAction(node, actionContext) {
}
function applyAttackWithoutTarget({ attack, actionContext }) {
delete actionContext.scope['$attackHit'];
delete actionContext.scope['$attackMiss'];
delete actionContext.scope['$criticalHit'];
delete actionContext.scope['$criticalMiss'];
delete actionContext.scope['$attackRoll'];
delete actionContext.scope['~attackHit'];
delete actionContext.scope['~attackMiss'];
delete actionContext.scope['~criticalHit'];
delete actionContext.scope['~criticalMiss'];
delete actionContext.scope['~attackRoll'];
recalculateCalculation(attack, actionContext);
const scope = actionContext.scope;
@@ -66,16 +66,16 @@ function applyAttackWithoutTarget({ attack, actionContext }) {
criticalMiss,
} = rollAttack(attack, scope);
let name = criticalHit ? 'Critical Hit!' : criticalMiss ? 'Critical Miss!' : 'To Hit';
if (scope['$attackAdvantage'] === 1) {
if (scope['~attackAdvantage']?.value === 1) {
name += ' (Advantage)';
} else if (scope['$attackAdvantage'] === -1) {
} else if (scope['~attackAdvantage']?.value === -1) {
name += ' (Disadvantage)';
}
if (!criticalMiss) {
scope['$attackHit'] = true
scope['~attackHit'] = { value: true }
}
if (!criticalHit) {
scope['$attackMiss'] = true;
scope['~attackMiss'] = { value: true };
}
actionContext.addLog({
@@ -87,12 +87,12 @@ function applyAttackWithoutTarget({ attack, actionContext }) {
function applyAttackToTarget({ attack, target, actionContext }) {
const scope = actionContext.scope;
delete scope['$attackHit'];
delete scope['$attackMiss'];
delete scope['$criticalHit'];
delete scope['$criticalMiss'];
delete scope['$attackDiceRoll'];
delete scope['$attackRoll'];
delete scope['~attackHit'];
delete scope['~attackMiss'];
delete scope['~criticalHit'];
delete scope['~criticalMiss'];
delete scope['~attackDiceRoll'];
delete scope['~attackRoll'];
recalculateCalculation(attack, actionContext);
@@ -109,9 +109,9 @@ function applyAttackToTarget({ attack, target, actionContext }) {
let name = criticalHit ? 'Critical Hit!' :
criticalMiss ? 'Critical Miss!' :
result > armor ? 'Hit!' : 'Miss!';
if (scope['$attackAdvantage'] === 1) {
if (scope['~attackAdvantage']?.value === 1) {
name += ' (Advantage)';
} else if (scope['$attackAdvantage'] === -1) {
} else if (scope['~attackAdvantage']?.value === -1) {
name += ' (Disadvantage)';
}
@@ -121,9 +121,9 @@ function applyAttackToTarget({ attack, target, actionContext }) {
inline: true,
});
if (criticalMiss || result < armor) {
scope['$attackMiss'] = true;
scope['~attackMiss'] = { value: true };
} else {
scope['$attackHit'] = true;
scope['~attackHit'] = { value: true };
}
} else {
actionContext.addLog({
@@ -141,7 +141,7 @@ function applyAttackToTarget({ attack, target, actionContext }) {
function rollAttack(attack, scope) {
const rollModifierText = numberToSignedString(attack.value, true);
let value, resultPrefix;
if (scope['$attackAdvantage'] === 1) {
if (scope['~attackAdvantage']?.value === 1) {
const [a, b] = rollDice(2, 20);
if (a >= b) {
value = a;
@@ -150,7 +150,7 @@ function rollAttack(attack, scope) {
value = b;
resultPrefix = `1d20 [ ~~${a}~~, ${b} ] ${rollModifierText}`;
}
} else if (scope['$attackAdvantage'] === -1) {
} else if (scope['~attackAdvantage']?.value === -1) {
const [a, b] = rollDice(2, 20);
if (a <= b) {
value = a;
@@ -163,23 +163,23 @@ function rollAttack(attack, scope) {
value = rollDice(1, 20)[0];
resultPrefix = `1d20 [${value}] ${rollModifierText}`
}
scope['$attackDiceRoll'] = value;
scope['~attackDiceRoll'] = { value };
const result = value + attack.value;
scope['$attackRoll'] = result;
scope['~attackRoll'] = { value: result };
const { criticalHit, criticalMiss } = applyCrits(value, scope);
return { resultPrefix, result, value, criticalHit, criticalMiss };
}
function applyCrits(value, scope) {
let criticalHitTarget = scope.criticalHitTarget?.value || 20;
const criticalHitTarget = 20; // scope['~criticalHitTarget']?.value || 20;
let criticalHit = value >= criticalHitTarget;
let criticalMiss;
if (criticalHit) {
scope['$criticalHit'] = true;
scope['~criticalHit'] = { value: true };
} else {
criticalMiss = value === 1;
if (criticalMiss) {
scope['$criticalMiss'] = true;
scope['~criticalMiss'] = { value: true };
}
}
return { criticalHit, criticalMiss };

View File

@@ -35,25 +35,25 @@ export default function applyBranch(node, actionContext) {
}
break;
case 'hit':
if (scope['$attackHit']) {
if (scope['~attackHit']?.value) {
if (!targets.length && !prop.silent) actionContext.addLog({ value: '**On hit**' });
applyChildren();
}
break;
case 'miss':
if (scope['$attackMiss']) {
if (scope['~attackMiss']?.value) {
if (!targets.length && !prop.silent) actionContext.addLog({ value: '**On miss**' });
applyChildren();
}
break;
case 'failedSave':
if (scope['$saveFailed']) {
if (scope['~saveFailed']?.value) {
if (!targets.length && !prop.silent) actionContext.addLog({ value: '**On failed save**' });
applyChildren();
}
break;
case 'successfulSave':
if (scope['$saveSucceeded']) {
if (scope['~saveSucceeded']?.value) {
if (!targets.length && !prop.silent) actionContext.addLog({ value: '**On save**', });
applyChildren();
}

View File

@@ -27,7 +27,7 @@ export default function applyDamage(node, actionContext) {
// Choose target
let damageTargets = prop.target === 'self' ? [actionContext.creature] : actionContext.targets;
// Determine if the hit is critical
let criticalHit = scope['$criticalHit'] &&
let criticalHit = scope['~criticalHit']?.value &&
prop.damageType !== 'healing' // Can't critically heal
;
// Double the damage rolls if the hit is critical
@@ -73,12 +73,12 @@ export default function applyDamage(node, actionContext) {
damage = Math.floor(damage);
// Convert extra damage into the stored type
if (prop.damageType === 'extra' && scope['$lastDamageType']) {
prop.damageType = scope['$lastDamageType'];
if (prop.damageType === 'extra' && scope['~lastDamageType']?.value) {
prop.damageType = scope['~lastDamageType']?.value;
}
// Store current damage type
if (prop.damageType !== 'healing') {
scope['$lastDamageType'] = prop.damageType;
scope['~lastDamageType'] = { value: prop.damageType };
}
// Memoise the damage suffix for the log

View File

@@ -46,7 +46,7 @@ export default function applyRoll(node, actionContext) {
}
const value = reduced.value;
actionContext.scope[prop.variableName] = value;
actionContext.scope[prop.variableName] = { value };
logValue.push(`**${value}**`);
if (!prop.silent) {

View File

@@ -31,18 +31,18 @@ export default function applySavingThrow(node, actionContext) {
// If there are no save targets, apply all children as if the save both
// succeeeded and failed
if (!saveTargets?.length) {
scope['$saveFailed'] = true;
scope['$saveSucceeded'] = true;
scope['~saveFailed'] = { value: true };
scope['~saveSucceeded'] = { value: true };
applyNodeTriggers(node, 'after', actionContext);
return node.children.forEach(child => applyProperty(child, actionContext));
}
// Each target makes the saving throw
saveTargets.forEach(target => {
delete scope['$saveFailed'];
delete scope['$saveSucceeded'];
delete scope['$saveDiceRoll'];
delete scope['$saveRoll'];
delete scope['~saveFailed'];
delete scope['~saveSucceeded'];
delete scope['~saveDiceRoll'];
delete scope['~saveRoll'];
const applyChildren = function () {
applyNodeTriggers(node, 'after', actionContext);
@@ -90,14 +90,14 @@ export default function applySavingThrow(node, actionContext) {
value = values[0];
resultPrefix = `1d20 [ ${value} ] ${rollModifierText}`
}
scope['$saveDiceRoll'] = value;
scope['~saveDiceRoll'] = { value };
const result = value + rollModifier || 0;
scope['$saveRoll'] = result;
scope['~saveRoll'] = { value: result };
const saveSuccess = result >= dc;
if (saveSuccess) {
scope['$saveSucceeded'] = true;
scope['~saveSucceeded'] = { value: true };
} else {
scope['$saveFailed'] = true;
scope['~saveFailed'] = { value: true };
}
if (!prop.silent) actionContext.addLog({
name: saveSuccess ? 'Successful save' : 'Failed save',

View File

@@ -117,7 +117,8 @@ const doAction = new ValidatedMethod({
}
}
actionContext.scope['slotLevel'] = slotLevel;
actionContext.scope['slotLevel'] = { value: slotLevel };
actionContext.scope['~slotLevel'] = { value: slotLevel };
// Do the action
doActionWork({

View File

@@ -81,7 +81,7 @@ function rollCheck(prop, actionContext) {
rollModifier += effectBonus;
let value, values, resultPrefix;
if (scope['$checkAdvantage'] === 1) {
if (scope['~checkAdvantage']?.value === 1) {
logName += ' (Advantage)';
const [a, b] = rollDice(2, 20);
if (a >= b) {
@@ -91,7 +91,7 @@ function rollCheck(prop, actionContext) {
value = b;
resultPrefix = `1d20 [ ~~${a}~~, ${b} ] ${rollModifierText} = `;
}
} else if (scope['$checkAdvantage'] === -1) {
} else if (scope['~checkAdvantage']?.value === -1) {
logName += ' (Disadvantage)';
const [a, b] = rollDice(2, 20);
if (a <= b) {
@@ -107,9 +107,9 @@ function rollCheck(prop, actionContext) {
resultPrefix = `1d20 [ ${value} ] ${rollModifierText} = `
}
const result = (value + rollModifier) || 0;
scope['$checkDiceRoll'] = value;
scope['$checkRoll'] = result;
scope['$checkModifier'] = rollModifier;
scope['~checkDiceRoll'] = { value };
scope['~checkRoll'] = { value: result };
scope['~checkModifier'] = { value: rollModifier };
actionContext.addLog({
name: logName,
value: `${resultPrefix} **${result}**`,

View File

@@ -15,18 +15,21 @@ export default function writeScope(creatureId, computation) {
let $set, $unset;
for (const key in scope){
for (const key in scope) {
// Mongo can't handle keys that start with a dollar sign
if (key[0] === '$' || key[0] === '_') continue;
// Remove large properties that aren't likely to be accessed
delete scope[key].parent;
delete scope[key].ancestors;
// Remove empty keys
for (const subKey in scope[key]) {
if (scope[key][subKey] === undefined) {
delete scope[key][subKey]
}
}
// Only update changed fields
if (!EJSON.equals(variables[key], scope[key])) {
if (!$set) $set = {};
@@ -53,9 +56,9 @@ export default function writeScope(creatureId, computation) {
const update = {};
if ($set) update.$set = $set;
if ($unset) update.$unset = $unset;
CreatureVariables.update({_creatureId: creatureId}, update);
CreatureVariables.update({ _creatureId: creatureId }, update);
}
if (computation.creature?.dirty) {
Creatures.update({_id: creatureId}, {$unset: { dirty: 1 }});
Creatures.update({ _id: creatureId }, { $unset: { dirty: 1 } });
}
}

View File

@@ -1,4 +1,4 @@
// Must contain a letter, and be made of word characters only
const VARIABLE_NAME_REGEX = /^[a-z$][\w_]*$/i;
const VARIABLE_NAME_REGEX = /^[a-zA-Z~][a-zA-Z_0-9]+$/i;
export default VARIABLE_NAME_REGEX;

View File

@@ -13,7 +13,7 @@ function id(x) { return x[0]; }
value: s => s.slice(1, -1).replace('\\n', '\n'),
},
name: {
match: /[a-zA-Z_#$]*[a-ce-zA-Z_#$][a-zA-Z0-9_#$]*/,
match: /[a-zA-Z~#][a-zA-Z0-9_]+/,
type: moo.keywords({
'keywords': ['true', 'false'],
}),

View File

@@ -11,7 +11,7 @@
value: s => s.slice(1, -1).replace('\\n', '\n'),
},
name: {
match: /[a-zA-Z_#$]*[a-ce-zA-Z_#$][a-zA-Z0-9_#$]*/,
match: /[a-zA-Z~#][a-zA-Z0-9_]+/,
type: moo.keywords({
'keywords': ['true', 'false'],
}),

13
app/vue.d.ts vendored Normal file
View File

@@ -0,0 +1,13 @@
declare module 'vue/types/options' {
interface ComponentOptions<V extends Vue> {
meteor?: any;
}
}
declare module 'vue/types/vue' {
interface Vue {
$subscribe: (name: string, params: any[]) => void;
$autorun: (fn: () => void) => number;
$subReady: Record<string, boolean>;
}
}