Started removing old action engine methods

This commit is contained in:
ThaumRystra
2024-05-04 19:25:38 +02:00
parent c11013eddb
commit 9a6cb4b23f
10 changed files with 51 additions and 465 deletions

View File

@@ -4,7 +4,6 @@ import InputProvider from '/imports/api/engine/action/functions/userInput/InputP
import { applyDefaultAfterPropTasks } from '/imports/api/engine/action/functions/applyTaskGroups';
import { getEffectiveActionScope } from '/imports/api/engine/action/functions/getEffectiveActionScope';
import recalculateCalculation from '/imports/api/engine/action/functions/recalculateCalculation';
import { applyUnresolvedEffects } from '/imports/api/engine/action/methods/doCheck';
import { PropTask } from '/imports/api/engine/action/tasks/Task';
import TaskResult from '/imports/api/engine/action/tasks/TaskResult';
import { getVariables } from '/imports/api/engine/loadCreatures';
@@ -64,11 +63,8 @@ export default async function applySavingThrowProperty(
applyDefaultAfterPropTasks(action, prop, [targetId], inputProvider);
}
let rollModifierText = numberToSignedString(save.value, true);
let rollModifier = save.value
const { effectBonus, effectString } = applyUnresolvedEffects(save, scope)
rollModifierText += effectString;
rollModifier += effectBonus;
const rollModifierText = numberToSignedString(save.value, true);
const rollModifier = save.value;
let value, resultPrefix;
if (save.advantage === 1) {

View File

@@ -37,8 +37,8 @@ export type Advantage = 0 | 1 | -1;
export type CheckParams = {
advantage: Advantage;
skillVariableName: string;
abilityVariableName: string;
skillVariableName?: string;
abilityVariableName?: string;
dc: number | null;
contest?: true;
targetSkillVariableName?: string;

View File

@@ -1,139 +0,0 @@
import SimpleSchema from 'simpl-schema';
import { ValidatedMethod } from 'meteor/mdg:validated-method';
import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions';
import rollDice from '/imports/parser/rollDice';
import numberToSignedString from '/imports/api/utility/numberToSignedString';
import { getSingleProperty } from '/imports/api/engine/loadCreatures';
// TODO Migrate this to the new action engine
const doCheck = new ValidatedMethod({
name: 'creatureProperties.doCheck',
validate: new SimpleSchema({
propId: SimpleSchema.RegEx.Id,
scope: {
type: Object,
blackbox: true,
},
}).validator(),
mixins: [RateLimiterMixin],
rateLimit: {
numRequests: 10,
timeInterval: 5000,
},
run({ propId, scope }) {
console.warn('do check not implemented');
return;
const prop = CreatureProperties.findOne(propId);
if (!prop) throw new Meteor.Error('not-found', 'The property was not found');
const creatureId = prop.root.id;
const actionContext = new ActionContext(creatureId, [creatureId], this);
Object.assign(actionContext.scope, scope);
actionContext.scope[`#${prop.type}`] = prop;
// Check permissions
assertEditPermission(actionContext.creature, this.userId);
// Do the check
doCheckWork({ prop, actionContext });
},
});
export default doCheck;
export function doCheckWork({ prop, actionContext }) {
applyTriggers(actionContext.triggers.check?.before, prop, actionContext);
rollCheck(prop, actionContext);
applyTriggers(actionContext.triggers.check?.after, prop, actionContext);
// Insert the log
actionContext.writeLog();
}
function rollCheck(prop, actionContext) {
const scope = actionContext.scope;
// get the modifier for the roll
let rollModifier;
let logName = `${prop.name} check`;
if (prop.type === 'skill') {
rollModifier = prop.value;
if (prop.skillType === 'save') {
if (prop.name.match(/save/i)) {
logName = prop.name;
} else {
logName = prop.name ? `${prop.name} save` : 'Saving Throw';
}
}
} else if (prop.type === 'attribute') {
if (prop.attributeType === 'ability') {
rollModifier = prop.modifier;
} else {
rollModifier = prop.value;
}
} else {
throw (`${prop.type} not supported for checks`);
}
let rollModifierText = numberToSignedString(rollModifier, true);
const { effectBonus, effectString } = applyUnresolvedEffects(prop, actionContext)
rollModifierText += effectString;
rollModifier += effectBonus;
let value, values, resultPrefix;
if (scope['~checkAdvantage']?.value === 1) {
logName += ' (Advantage)';
const [a, b] = rollDice(2, 20);
if (a >= b) {
value = a;
resultPrefix = `1d20 [ ${a}, ~~${b}~~ ] ${rollModifierText} = `;
} else {
value = b;
resultPrefix = `1d20 [ ~~${a}~~, ${b} ] ${rollModifierText} = `;
}
} else if (scope['~checkAdvantage']?.value === -1) {
logName += ' (Disadvantage)';
const [a, b] = rollDice(2, 20);
if (a <= b) {
value = a;
resultPrefix = `1d20 [ ${a}, ~~${b}~~ ] ${rollModifierText} = `;
} else {
value = b;
resultPrefix = `1d20 [ ~~${a}~~, ${b} ] ${rollModifierText} = `;
}
} else {
values = rollDice(1, 20);
value = values[0];
resultPrefix = `1d20 [ ${value} ] ${rollModifierText} = `
}
const result = (value + rollModifier) || 0;
scope['~checkDiceRoll'] = { value };
scope['~checkRoll'] = { value: result };
scope['~checkModifier'] = { value: rollModifier };
actionContext.addLog({
name: logName,
value: `${resultPrefix} **${result}**`,
});
}
// TODO replace this with recalculating and then rolling/reducing the value node
export function applyUnresolvedEffects(prop, actionContext) {
let effectBonus = 0;
let effectString = '';
if (!prop.effectIds) {
return { effectBonus, effectString };
}
prop.effectIds.forEach(id => {
const effect = getSingleProperty(actionContext.creature._id, id);
if (!effect.amount?.parseNode) return;
if (effect.operation !== 'add') return;
recalculateCalculation(effect.amount, actionContext, undefined, 'reduce');
if (typeof effect.amount?.value !== 'number') return;
effectBonus += effect.amount.value;
effectString += ` ${effect.amount.value < 0 ? '-' : '+'} [${effect.amount.calculation}] ${Math.abs(effect.amount.value)}`
});
return { effectBonus, effectString };
}

View File

@@ -1,122 +0,0 @@
<template lang="html">
<div>
<v-menu
v-model="open"
origin="center center"
transition="scale-transition"
nudge-left="100px"
nudge-top="100px"
:close-on-content-click="false"
>
<template #activator="{ on }">
<v-btn
v-bind="$attrs"
:class="buttonClass"
v-on="noClick ? {} : on"
@click="e => { if (!noClick) e.stopPropagation(); }"
>
<slot />
</v-btn>
</template>
<v-sheet class="d-flex flex-column align-center justify-center">
<v-btn-toggle
v-model="dataAdvantage"
color="accent"
>
<v-btn :value="-1">
Disadvantage
</v-btn>
<v-btn :value="1">
Advantage
</v-btn>
</v-btn-toggle>
<div class="ma-1 text-subtitle-2">
{{ name }}
</div>
<div>
<v-scale-transition
origin="center center"
>
<vertical-hex
v-if="dataAdvantage"
style="position:absolute; transition: margin-left 0.3s ease;"
:style="{marginLeft: dataAdvantage == 1 ? '24px' : '-24px'}"
disable-hover
/>
</v-scale-transition>
<vertical-hex @click="roll">
<div>
Roll
</div>
<div v-if="rollText">
{{ rollText }}
</div>
</vertical-hex>
</div>
<v-btn
text
color="primary"
style="align-self: end"
@click="close"
>
Cancel
</v-btn>
</v-sheet>
</v-menu>
</div>
</template>
<script lang="js">
import VerticalHex from '/imports/client/ui/components/VerticalHex.vue';
export default {
components: {
VerticalHex
},
props: {
name: {
type: String,
default: undefined,
},
rollText: {
type: String,
default: undefined,
},
buttonClass: {
type: String,
default: undefined,
},
advantage: {
type: Number,
default: undefined,
},
noClick: Boolean,
},
data(){return {
open: false,
dataAdvantage: this.advantage,
}},
watch: {
advantage(val){
this.dataAdvantage = val;
},
open(val){
if(!val){
this.dataAdvantage = this.advantage;
}
},
},
methods: {
roll(){
this.$emit('roll', {advantage: this.dataAdvantage});
this.open = false;
},
close(){
this.open = false;
}
},
}
</script>
<style lang="css" scoped>
</style>

View File

@@ -1,99 +0,0 @@
<template lang="html">
<v-card>
<template v-if="!result">
<v-btn-toggle v-model="advantage">
<v-btn text>
Advantage
</v-btn>
<v-btn text>
Disadvantage
</v-btn>
</v-btn-toggle>
<v-card-text>
<div class="layout justify-center align-center">
<v-btn
large
fab
outlined
@click="makeRoll"
>
<div class="text-h4">
{{ numberToSignedString(bonus) }}
</div>
</v-btn>
</div>
</v-card-text>
</template>
<template v-else>
<div>
<div class="text-h6">
<span
v-for="(roll, index) of rolls"
:key="index"
class="roll"
:class="{strikethrough: index !== chosenRollIndex}"
>
{{ roll }}
</span>
<span class="ml-1">
{{ numberToSignedString(bonus) }}
</span>
</div>
<div class="text-h4">
{{ result }}
</div>
</div>
</template>
</v-card>
</template>
<script lang="js">
import numberToSignedString from '../../../../api/utility/numberToSignedString';
export default {
props: {
attributeVarName: {
type: String,
default: '',
},
attributeName: {
type: String,
default: '',
},
creatureId: {
type: String,
default: '',
},
bonus: {
type: Number,
required: true,
},
},
data(){return {
advantage: undefined,
result: undefined,
rolls: undefined,
chosenRoll: undefined,
chosenRollIndex: undefined,
}},
methods: {
makeRoll(){
//let {rolls, bonus, chosenRoll, result} = doCheckWork.call();
this.rolls = [12, 8];
if (this.advantage === 1){
this.chosenRoll = 8;
} else {
this.chosenRoll = 12;
}
this.result = this.chosenRoll + this.bonus;
this.chosenRollIndex = this.rolls.indexOf(this.chosenRoll);
},
numberToSignedString,
}
}
</script>
<style lang="css" scoped>
.strikethrough {
text-decoration: line-through;
}
</style>

View File

@@ -7,16 +7,14 @@
class="ma-0"
style="min-width: 40px;"
>
<roll-popup
button-class="mr-4 py-2"
<v-btn
class="mr-4 py-2"
text
height="82"
:roll-text="numberToSignedString(model.modifier)"
:name="model.name"
:advantage="model.advantage"
:data-id="`check-btn-${model._id}`"
:loading="checkLoading"
:disabled="!context.editPermission"
@roll="check"
@click.stop="check"
>
<div>
<div class="text-h4 mod">
@@ -40,7 +38,7 @@
</template>
</div>
</div>
</roll-popup>
</v-btn>
</v-list-item-action>
<v-list-item-content>
@@ -64,15 +62,11 @@
</template>
<script lang="js">
import doCheck from '/imports/api/engine/action/methods/doCheck';
import numberToSignedString from '/imports/api/utility/numberToSignedString';
import RollPopup from '/imports/client/ui/components/RollPopup.vue';
import { snackbar } from '/imports/client/ui/components/snackbars/SnackbarQueue';
import doAction from '/imports/client/ui/creature/actions/doAction';
export default {
components: {
RollPopup,
},
inject: {
context: {
default: {},
@@ -96,19 +90,21 @@ export default {
click(e) {
this.$emit('click', e);
},
check({ advantage }) {
check() {
this.checkLoading = true;
doCheck.call({
propId: this.model._id,
scope: {
'~checkAdvantage': { value: advantage },
},
}, error => {
doAction(this.model, this.$store, `check-btn-${this.model._id}`, {
subtaskFn: 'check',
prop: this.model,
targetIds: [this.model.root.id],
advantage: this.model.advantage,
skillVariableName: undefined,
abilityVariableName: this.model.variableName,
dc: null,
}).catch(error => {
snackbar({ text: error.reason || error.message || error.toString() });
console.error(error);
}).finally(() => {
this.checkLoading = false;
if (error) {
console.error(error);
snackbar({ text: error.reason });
}
});
},
},
@@ -153,4 +149,3 @@ export default {
min-width: 42px;
}
</style>
../../../../../api/engine/action/methods/doCheck

View File

@@ -5,23 +5,20 @@
@mouseover="$emit('mouseover')"
@mouseleave="$emit('mouseleave')"
>
<roll-popup
<v-btn
v-if="model.attributeType === 'modifier' || model.type === 'skill'"
button-class="px-0"
class="px-0"
text
height="70"
min-width="72"
:roll-text="computedValue && computedValue.toString()"
:name="model.name"
:advantage="model.advantage"
:loading="checkLoading"
:disabled="!context.editPermission"
@roll="check"
@click.stop="check"
>
<v-card-title class="value text-h4 flex-shrink-0">
{{ computedValue }}
</v-card-title>
</roll-popup>
</v-btn>
<v-card-title
v-else
class="value text-h4 flex-shrink-0"
@@ -47,15 +44,11 @@
</template>
<script lang="js">
import RollPopup from '/imports/client/ui/components/RollPopup.vue';
import doCheck from '/imports/api/engine/action/methods/doCheck.js';
import {snackbar} from '/imports/client/ui/components/snackbars/SnackbarQueue';
import numberToSignedString from '/imports/api/utility/numberToSignedString';
import doAction from '/imports/client/ui/creature/actions/doAction';
export default {
components: {
RollPopup,
},
inject: {
context: {
default: {},
@@ -82,19 +75,21 @@ export default {
},
methods: {
signed: numberToSignedString,
check({advantage}){
check(){
this.checkLoading = true;
doCheck.call({
propId: this.model._id,
scope: {
'~checkAdvantage': { value: advantage },
},
}, error => {
doAction(this.model, this.$store, `check-btn-${this.model._id}`, {
subtaskFn: 'check',
prop: this.model,
targetIds: [this.model.root.id],
advantage: this.model.advantage,
skillVariableName: this.model.variableName,
abilityVariableName: this.model.ability,
dc: null,
}).catch(error => {
snackbar({ text: error.reason || error.message || error.toString() });
console.error(error);
}).finally(() => {
this.checkLoading = false;
if (error){
console.error(error);
snackbar({text: error.reason});
}
});
},
},
@@ -106,4 +101,4 @@ export default {
min-width: 72px;
justify-content: center;
}
</style>../../../../../api/engine/action/methods/doCheck
</style>

View File

@@ -10,6 +10,7 @@
v-if="!hideModifier"
text
tile
:loading="checkLoading"
:disabled="!context.editPermission"
:data-id="`check-btn-${model._id}`"
class="pl-3 pr-2 prof-mod mr-1 flex-shrink-0"
@@ -58,6 +59,7 @@
import ProficiencyIcon from '/imports/client/ui/properties/shared/ProficiencyIcon.vue';
import numberToSignedString from '/imports/api/utility/numberToSignedString';
import doAction from '/imports/client/ui/creature/actions/doAction';
import { snackbar } from '/imports/client/ui/components/snackbars/SnackbarQueue';
export default {
components: {
@@ -101,6 +103,7 @@ export default {
this.$emit('click', e);
},
check() {
this.checkLoading = true;
doAction(this.model, this.$store, `check-btn-${this.model._id}`, {
subtaskFn: 'check',
prop: this.model,
@@ -109,9 +112,12 @@ export default {
skillVariableName: this.model.variableName,
abilityVariableName: this.model.ability,
dc: null,
}).catch(e => {
console.error(e);
})
}).catch(error => {
snackbar({ text: error.reason || error.message || error.toString() });
console.error(error);
}).finally(() => {
this.checkLoading = false;
});
},
}
}

View File

@@ -159,20 +159,7 @@
>
Cancel
</v-btn>
<roll-popup
v-if="selectedSpell && selectedSpell.attackRoll"
text
color="primary"
class="mx-2"
:disabled="!canCast"
:name="selectedSpell.name"
:advantage="selectedSpell.attackRoll && selectedSpell.attackRoll.advantage"
@roll="cast"
>
Cast
</roll-popup>
<v-btn
v-else
text
:disabled="!canCast"
class="mx-2 px-4"
@@ -192,7 +179,6 @@ import CreatureProperties from '/imports/api/creature/creatureProperties/Creatur
import spellsWithSubheaders from '/imports/client/ui/properties/components/spells/spellsWithSubheaders';
import SpellSlotListTile from '/imports/client/ui/properties/components/attributes/SpellSlotListTile.vue';
import SpellListTile from '/imports/client/ui/properties/components/spells/SpellListTile.vue';
import RollPopup from '/imports/client/ui/components/RollPopup.vue';
import { find } from 'lodash';
const slotFilter = {
@@ -207,7 +193,6 @@ const slotFilter = {
export default {
components: {
DialogBase,
RollPopup,
SplitListLayout,
SpellSlotListTile,
SpellListTile,

View File

@@ -10,36 +10,7 @@
class="avatar"
:style="{ opacity: active ? '' : '0.5'}"
>
<roll-popup
v-if="rollBonus"
:icon="!active"
:outlined="!active"
:fab="active"
style="letter-spacing: normal;"
class="mr-2"
:no-click="!active"
:style="{
fontSize: active ? '24px' : '16px'
}"
:large="active"
:color="model.color || 'primary'"
:loading="doActionLoading"
:disabled="model.insufficientResources || !context.editPermission || !!targetingError"
:roll-text="rollBonus"
:name="model.name"
:advantage="model.attackRoll && model.attackRoll.advantage"
@roll="doAction"
>
<template v-if="rollBonus && !rollBonusTooLong">
{{ rollBonus }}
</template>
<property-icon
v-else
:model="model"
/>
</roll-popup>
<v-btn
v-else
:icon="!active"
:outlined="!active"
:fab="active"
@@ -157,7 +128,6 @@ import numberToSignedString from '/imports/api/utility/numberToSignedString.js';
import AttributeConsumedView from '/imports/client/ui/properties/components/actions/AttributeConsumedView.vue';
import ItemConsumedView from '/imports/client/ui/properties/components/actions/ItemConsumedView.vue';
import PropertyIcon from '/imports/client/ui/properties/shared/PropertyIcon.vue';
import RollPopup from '/imports/client/ui/components/RollPopup.vue';
import MarkdownText from '/imports/client/ui/components/MarkdownText.vue';
import { snackbar } from '/imports/client/ui/components/snackbars/SnackbarQueue.js';
import CardHighlight from '/imports/client/ui/components/CardHighlight.vue';
@@ -172,7 +142,6 @@ export default {
ItemConsumedView,
MarkdownText,
PropertyIcon,
RollPopup,
CardHighlight,
TreeNodeList,
},