Fixed spell casting
This commit is contained in:
@@ -2,32 +2,14 @@ import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
||||
import { CastSpellTask } from '/imports/api/engine/action/tasks/Task';
|
||||
import TaskResult from './TaskResult';
|
||||
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||
import { getPropertiesOfType, getSingleProperty } from '/imports/api/engine/loadCreatures';
|
||||
import { getSingleProperty } from '/imports/api/engine/loadCreatures';
|
||||
import applyTask from '/imports/api/engine/action/tasks/applyTask';
|
||||
import applyActionProperty from '../applyProperties/applyActionProperty';
|
||||
|
||||
export default async function applySpellProperty(
|
||||
task: CastSpellTask, action: EngineAction, result: TaskResult, userInput: InputProvider
|
||||
): Promise<void> {
|
||||
let prop = task.prop;
|
||||
// Ask the user how this spell is being cast
|
||||
const castOptions = await userInput.castSpell({
|
||||
spellId: task.params.spellId,
|
||||
slotId: prop?.castWithoutSpellSlots
|
||||
? undefined
|
||||
: getSuggestedSpellSlotId(action.creatureId, prop),
|
||||
ritual: false,
|
||||
});
|
||||
if (!castOptions.spellId) {
|
||||
result.appendLog({
|
||||
name: 'Error casting spell',
|
||||
value: 'No spell was selected',
|
||||
silenced: false,
|
||||
}, [action.creatureId]);
|
||||
return;
|
||||
}
|
||||
// If the user changed the spell they are casting, use that as the prop
|
||||
prop = getSingleProperty(action.creatureId, castOptions.spellId);
|
||||
const prop = task.prop;
|
||||
|
||||
if (!prop) {
|
||||
result.appendLog({
|
||||
@@ -38,65 +20,62 @@ export default async function applySpellProperty(
|
||||
return;
|
||||
}
|
||||
let slotLevel = prop.level || 0;
|
||||
// Get the slot being cast with
|
||||
const slot = castOptions.slotId && getSingleProperty(action.creatureId, castOptions.slotId);
|
||||
// Log casting method
|
||||
logCastingMessage(slot?.spellSlotLevel?.value, castOptions, result, prop, task.targetIds);
|
||||
// Spend the spell slot and change the spell's casting level if a slot is used
|
||||
if (slot) {
|
||||
await spendSpellSlot(action, castOptions, userInput);
|
||||
slotLevel = slot.spellSlotLevel?.value || 0;
|
||||
let message = '';
|
||||
|
||||
if (task.params.withoutSpellSlot) {
|
||||
message = `Casting at level ${slotLevel}`
|
||||
} else if (task.params.ritual) {
|
||||
message = `Ritual casting at level ${slotLevel}`
|
||||
} else {
|
||||
// Get the slot being cast with
|
||||
const spellSlot = task.params.slotId && getSingleProperty(action.creatureId, task.params.slotId) || undefined;
|
||||
// Ensure the slot exists
|
||||
if (!spellSlot) {
|
||||
result.appendLog({
|
||||
name: 'Error casting spell',
|
||||
value: 'The chosen spell requires a spell slot to cast',
|
||||
silenced: false,
|
||||
}, [action.creatureId]);
|
||||
return;
|
||||
}
|
||||
// And is the right type
|
||||
if (spellSlot.type !== 'attribute' || spellSlot.attributeType !== 'spellSlot') {
|
||||
result.appendLog({
|
||||
name: 'Error casting spell',
|
||||
value: 'The chosen slot was not actually a spell slot',
|
||||
silenced: false,
|
||||
}, [action.creatureId]);
|
||||
return;
|
||||
}
|
||||
// Spend the slot
|
||||
await applyTask(action, {
|
||||
targetIds: [action.creatureId],
|
||||
subtaskFn: 'damageProp',
|
||||
params: {
|
||||
operation: 'increment',
|
||||
value: 1,
|
||||
targetProp: spellSlot,
|
||||
},
|
||||
}, userInput);
|
||||
slotLevel = spellSlot ? Number(spellSlot.spellSlotLevel?.value) || 0 : slotLevel;
|
||||
message = `Casting using a level ${slotLevel} spell slot`;
|
||||
}
|
||||
|
||||
// Log casting method
|
||||
result.appendLog({
|
||||
name: message,
|
||||
silenced: prop.silent,
|
||||
}, task.targetIds);
|
||||
|
||||
// Add the slot level to the scope
|
||||
result.pushScope = {
|
||||
'~slotLevel': { value: slotLevel },
|
||||
'slotLevel': { value: slotLevel },
|
||||
};
|
||||
|
||||
// Run the rest of the spell as if it were an action
|
||||
return applyActionProperty({
|
||||
prop,
|
||||
targetIds: task.targetIds,
|
||||
}, action, result, userInput);
|
||||
}
|
||||
|
||||
function getSuggestedSpellSlotId(creatureId, prop) {
|
||||
if (!prop) return;
|
||||
const slots = getPropertiesOfType(creatureId, 'spellSlot')
|
||||
.sort((a, b) => a.spellSlotLevel?.value - b.spellSlotLevel?.value)
|
||||
.filter(slot => slot.spellSlotLevel.value > prop.level);
|
||||
return slots[0]?._id;
|
||||
}
|
||||
|
||||
function logCastingMessage(slotLevel: number, castOptions, result: TaskResult, prop, targetIds: string[]) {
|
||||
let message = '';
|
||||
// Determine which message to post
|
||||
if (slotLevel) {
|
||||
message = `Casting using a level ${slotLevel} spell slot`
|
||||
} else if (prop.level) {
|
||||
if (castOptions.ritual) {
|
||||
message = `Ritual casting at level ${slotLevel}`
|
||||
} else {
|
||||
message = `Casting at level ${slotLevel}`
|
||||
}
|
||||
}
|
||||
// Post the message
|
||||
if (message) {
|
||||
result.appendLog({
|
||||
name: `Casting at level ${slotLevel}`,
|
||||
silenced: prop.silent,
|
||||
}, targetIds);
|
||||
}
|
||||
}
|
||||
|
||||
function spendSpellSlot(action, castOptions, userInput) {
|
||||
const slot = getSingleProperty(action.creatureId, castOptions.slotId);
|
||||
return applyTask(action, {
|
||||
targetIds: [action.creatureId],
|
||||
subtaskFn: 'damageProp',
|
||||
params: {
|
||||
operation: 'increment',
|
||||
value: 1,
|
||||
targetProp: slot,
|
||||
},
|
||||
}, userInput);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user