Began adding creature templates to libraries

This commit is contained in:
ThaumRystra
2024-06-05 15:10:22 +02:00
parent 6070c499cc
commit 99c14099dc
18 changed files with 774 additions and 26 deletions

View File

@@ -117,7 +117,7 @@ function insertPropertyFromNode(nodeId, root, parentId) {
return node;
}
function storeLibraryNodeReferences(nodes) {
export function storeLibraryNodeReferences(nodes) {
nodes.forEach(node => {
if (node.libraryNodeId) return;
node.libraryNodeId = node._id;
@@ -126,7 +126,7 @@ function storeLibraryNodeReferences(nodes) {
// Covert node references into actual nodes
// TODO: check permissions for each library a reference node references
function reifyNodeReferences(nodes, visitedRefs = new Set(), depth = 0) {
export function reifyNodeReferences(nodes, visitedRefs = new Set(), depth = 0) {
depth += 1;
// New nodes added this function
let newNodes = [];

View File

@@ -0,0 +1,29 @@
import { EngineAction } from '/imports/api/engine/action/EngineActions';
import { PropTask } from '/imports/api/engine/action/tasks/Task';
import recalculateInlineCalculations from '/imports/api/engine/action/functions/recalculateInlineCalculations';
import getPropertyTitle from '/imports/api/utility/getPropertyTitle';
export default async function applyCreatureTemplateProperty(
task: PropTask, action: EngineAction, result, userInput
): Promise<void> {
const prop = task.prop;
//Log the Creature that is about to be summoned
let logValue = prop.description?.value
if (prop.description?.text) {
recalculateInlineCalculations(prop.description, action, 'reduce', userInput);
logValue = prop.description?.value;
}
// There are no targets for creature templates
// Creatures are always summoned as children of the action's creature
result.appendLog({
name: getPropertyTitle(prop),
value: logValue
}, []);
result.appendLog({
name: 'Warning',
value: 'Creature summoning is not yet implemented...'
}, []);
return;
}

View File

@@ -8,6 +8,7 @@ import adjustment from './applyAdjustmentProperty';
import branch from './applyBranchProperty';
import buff from './applyBuffProperty';
import buffRemover from './applyBuffRemoverProperty';
import creature from './applyCreatureTemplateProperty';
import damage from './applyDamageProperty';
import folder from './applyFolderProperty';
import note from './applyNoteProperty';
@@ -24,6 +25,7 @@ const applyPropertyByType: {
branch,
buff,
buffRemover,
creature,
damage,
folder,
note,

View File

@@ -0,0 +1,40 @@
import SimpleSchema from 'simpl-schema';
import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS';
import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema';
// Creature templates represent creatures that don't yet exist
// Used to store creatures in the library, or as templates for another creature to summon
const CreatureTemplateSchema = createPropertySchema({
name: {
type: String,
max: STORAGE_LIMITS.name,
optional: true,
},
description: {
type: 'inlineCalculationFieldToCompute',
optional: true,
},
picture: {
type: String,
optional: true,
max: STORAGE_LIMITS.url,
},
avatarPicture: {
type: String,
optional: true,
max: STORAGE_LIMITS.url,
},
});
const ComputedOnlyCreatureTemplateSchema = createPropertySchema({
description: {
type: 'computedOnlyInlineCalculationField',
optional: true,
},
});
const ComputedCreatureTemplateSchema = new SimpleSchema({})
.extend(CreatureTemplateSchema)
.extend(ComputedOnlyCreatureTemplateSchema);
export { CreatureTemplateSchema, ComputedCreatureTemplateSchema, ComputedOnlyCreatureTemplateSchema };

View File

@@ -2,15 +2,16 @@ import SimpleSchema from 'simpl-schema';
import { ComputedOnlyActionSchema } from '/imports/api/properties/Actions';
import { ComputedOnlyAdjustmentSchema } from '/imports/api/properties/Adjustments';
import { ComputedOnlyAttributeSchema } from '/imports/api/properties/Attributes';
import { ComputedOnlyBuffSchema } from '/imports/api/properties/Buffs';
import { ComputedOnlyBuffRemoverSchema } from '/imports/api/properties/BuffRemovers';
import { ComputedOnlyBranchSchema } from '/imports/api/properties/Branches';
import { ComputedOnlyClassSchema } from '/imports/api/properties/Classes';
import { ComputedOnlyBuffRemoverSchema } from '/imports/api/properties/BuffRemovers';
import { ComputedOnlyBuffSchema } from '/imports/api/properties/Buffs';
import { ComputedOnlyClassLevelSchema } from '/imports/api/properties/ClassLevels';
import { ComputedOnlyClassSchema } from '/imports/api/properties/Classes';
import { ComputedOnlyConstantSchema } from '/imports/api/properties/Constants';
import { ComputedOnlyContainerSchema } from '/imports/api/properties/Containers';
import { ComputedOnlyDamageSchema } from '/imports/api/properties/Damages';
import { ComputedOnlyCreatureTemplateSchema } from '/imports/api/properties/CreatureTemplates';
import { ComputedOnlyDamageMultiplierSchema } from '/imports/api/properties/DamageMultipliers';
import { ComputedOnlyDamageSchema } from '/imports/api/properties/Damages';
import { ComputedOnlyEffectSchema } from '/imports/api/properties/Effects';
import { ComputedOnlyFeatureSchema } from '/imports/api/properties/Features';
import { ComputedOnlyFolderSchema } from '/imports/api/properties/Folders';
@@ -23,8 +24,8 @@ import { ComputedOnlyRollSchema } from '/imports/api/properties/Rolls';
import { ComputedOnlySavingThrowSchema } from '/imports/api/properties/SavingThrows';
import { ComputedOnlySkillSchema } from '/imports/api/properties/Skills';
import { ComputedOnlySlotSchema } from '/imports/api/properties/Slots';
import { ComputedOnlySpellSchema } from '/imports/api/properties/Spells';
import { ComputedOnlySpellListSchema } from '/imports/api/properties/SpellLists';
import { ComputedOnlySpellSchema } from '/imports/api/properties/Spells';
import { ComputedOnlyToggleSchema } from '/imports/api/properties/Toggles';
import { ComputedOnlyTriggerSchema } from '/imports/api/properties/Triggers';
@@ -32,13 +33,14 @@ const propertySchemasIndex = {
action: ComputedOnlyActionSchema,
adjustment: ComputedOnlyAdjustmentSchema,
attribute: ComputedOnlyAttributeSchema,
branch: ComputedOnlyBranchSchema,
buff: ComputedOnlyBuffSchema,
buffRemover: ComputedOnlyBuffRemoverSchema,
branch: ComputedOnlyBranchSchema,
class: ComputedOnlyClassSchema,
classLevel: ComputedOnlyClassLevelSchema,
constant: ComputedOnlyConstantSchema,
container: ComputedOnlyContainerSchema,
creature: ComputedOnlyCreatureTemplateSchema,
damage: ComputedOnlyDamageSchema,
damageMultiplier: ComputedOnlyDamageMultiplierSchema,
effect: ComputedOnlyEffectSchema,
@@ -53,8 +55,8 @@ const propertySchemasIndex = {
roll: ComputedOnlyRollSchema,
savingThrow: ComputedOnlySavingThrowSchema,
skill: ComputedOnlySkillSchema,
spellList: ComputedOnlySpellListSchema,
spell: ComputedOnlySpellSchema,
spellList: ComputedOnlySpellListSchema,
toggle: ComputedOnlyToggleSchema,
trigger: ComputedOnlyTriggerSchema,
any: new SimpleSchema({}),

View File

@@ -10,6 +10,7 @@ import { ComputedClassSchema } from '/imports/api/properties/Classes';
import { ComputedClassLevelSchema } from '/imports/api/properties/ClassLevels';
import { ConstantSchema } from '/imports/api/properties/Constants';
import { ComputedContainerSchema } from '/imports/api/properties/Containers';
import { ComputedCreatureTemplateSchema } from '/imports/api/properties/CreatureTemplates';
import { ComputedDamageSchema } from '/imports/api/properties/Damages';
import { DamageMultiplierSchema } from '/imports/api/properties/DamageMultipliers';
import { ComputedEffectSchema } from '/imports/api/properties/Effects';
@@ -33,17 +34,20 @@ const propertySchemasIndex = {
action: ComputedActionSchema,
adjustment: ComputedAdjustmentSchema,
attribute: ComputedAttributeSchema,
branch: ComputedBranchSchema,
buff: ComputedBuffSchema,
buffRemover: ComputedBuffRemoverSchema,
branch: ComputedBranchSchema,
class: ComputedClassSchema,
classLevel: ComputedClassLevelSchema,
constant: ConstantSchema,
container: ComputedContainerSchema,
creature: ComputedCreatureTemplateSchema,
damage: ComputedDamageSchema,
damageMultiplier: DamageMultiplierSchema,
effect: ComputedEffectSchema,
feature: ComputedFeatureSchema,
folder: ComputedFolderSchema,
item: ComputedItemSchema,
note: ComputedNoteSchema,
pointBuy: ComputedPointBuySchema,
proficiency: ProficiencySchema,
@@ -52,12 +56,10 @@ const propertySchemasIndex = {
roll: ComputedRollSchema,
savingThrow: ComputedSavingThrowSchema,
skill: ComputedSkillSchema,
spellList: ComputedSpellListSchema,
spell: ComputedSpellSchema,
spellList: ComputedSpellListSchema,
toggle: ComputedToggleSchema,
trigger: ComputedTriggerSchema,
container: ComputedContainerSchema,
item: ComputedItemSchema,
any: new SimpleSchema({}),
};

View File

@@ -2,17 +2,20 @@ import SimpleSchema from 'simpl-schema';
import { ActionSchema } from '/imports/api/properties/Actions';
import { AdjustmentSchema } from '/imports/api/properties/Adjustments';
import { AttributeSchema } from '/imports/api/properties/Attributes';
import { BuffSchema } from '/imports/api/properties/Buffs';
import { BuffRemoverSchema } from '/imports/api/properties/BuffRemovers';
import { BranchSchema } from '/imports/api/properties/Branches';
import { ClassSchema } from '/imports/api/properties/Classes';
import { BuffRemoverSchema } from '/imports/api/properties/BuffRemovers';
import { BuffSchema } from '/imports/api/properties/Buffs';
import { ClassLevelSchema } from '/imports/api/properties/ClassLevels';
import { ClassSchema } from '/imports/api/properties/Classes';
import { ConstantSchema } from '/imports/api/properties/Constants';
import { DamageSchema } from '/imports/api/properties/Damages';
import { ContainerSchema } from '/imports/api/properties/Containers';
import { CreatureTemplateSchema } from '/imports/api/properties/CreatureTemplates';
import { DamageMultiplierSchema } from '/imports/api/properties/DamageMultipliers';
import { DamageSchema } from '/imports/api/properties/Damages';
import { EffectSchema } from '/imports/api/properties/Effects';
import { FeatureSchema } from '/imports/api/properties/Features';
import { FolderSchema } from '/imports/api/properties/Folders';
import { ItemSchema } from '/imports/api/properties/Items';
import { NoteSchema } from '/imports/api/properties/Notes';
import { PointBuySchema } from '/imports/api/properties/PointBuys';
import { ProficiencySchema } from '/imports/api/properties/Proficiencies';
@@ -25,24 +28,25 @@ import { SpellListSchema } from '/imports/api/properties/SpellLists';
import { SpellSchema } from '/imports/api/properties/Spells';
import { ToggleSchema } from '/imports/api/properties/Toggles';
import { TriggerSchema } from '/imports/api/properties/Triggers';
import { ContainerSchema } from '/imports/api/properties/Containers';
import { ItemSchema } from '/imports/api/properties/Items';
const propertySchemasIndex = {
action: ActionSchema,
adjustment: AdjustmentSchema,
attribute: AttributeSchema,
branch: BranchSchema,
buff: BuffSchema,
buffRemover: BuffRemoverSchema,
branch: BranchSchema,
class: ClassSchema,
classLevel: ClassLevelSchema,
constant: ConstantSchema,
container: ContainerSchema,
creature: CreatureTemplateSchema,
damage: DamageSchema,
damageMultiplier: DamageMultiplierSchema,
effect: EffectSchema,
feature: FeatureSchema,
folder: FolderSchema,
item: ItemSchema,
note: NoteSchema,
pointBuy: PointBuySchema,
proficiency: ProficiencySchema,
@@ -51,12 +55,10 @@ const propertySchemasIndex = {
roll: RollSchema,
savingThrow: SavingThrowSchema,
skill: SkillSchema,
spellList: SpellListSchema,
spell: SpellSchema,
spellList: SpellListSchema,
toggle: ToggleSchema,
trigger: TriggerSchema,
container: ContainerSchema,
item: ItemSchema,
any: new SimpleSchema({}),
};

View File

@@ -111,5 +111,6 @@ import '/imports/api/tabletop/methods/insertTabletop';
import '/imports/api/tabletop/methods/updateTabletop';
import '/imports/api/tabletop/methods/addCreaturesToTabletop';
import '/imports/api/tabletop/methods/updateTabletopSharing';
import '/imports/api/tabletop/methods/addCreaturesFromLibraryToTabletop';
export default Tabletops;

View File

@@ -0,0 +1,105 @@
import SimpleSchema from 'simpl-schema';
import { ValidatedMethod } from 'meteor/mdg:validated-method';
import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
import { assertUserInTabletop } from './shared/tabletopPermissions';
import { assertUserHasPaidBenefits } from '/imports/api/users/patreon/tiers';
import Creatures from '/imports/api/creature/creatures/Creatures';
import LibraryNodes from '/imports/api/library/LibraryNodes';
import { getFilter, renewDocIds } from '/imports/api/parenting/parentingFunctions';
import { reifyNodeReferences, storeLibraryNodeReferences } from '/imports/api/creature/creatureProperties/methods/insertPropertyFromLibraryNode';
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
const addCreaturesFromLibraryToTabletop = new ValidatedMethod({
name: 'tabletops.addCreaturesFromLibraryToTabletop',
validate: new SimpleSchema({
'libraryNodeIds': {
type: Array,
},
'libraryNodeIds.$': {
type: String,
regEx: SimpleSchema.RegEx.Id,
},
tabletopId: {
type: String,
regEx: SimpleSchema.RegEx.Id,
},
}).validator(),
mixins: [RateLimiterMixin],
rateLimit: {
numRequests: 1,
timeInterval: 5_000,
},
run({ libraryNodeIds, tabletopId }) {
if (!this.userId) {
throw new Meteor.Error('tabletops.addCreatures.denied',
'You need to be logged in to remove a tabletop');
}
assertUserHasPaidBenefits(this.userId);
assertUserInTabletop(tabletopId, this.userId);
for (const nodeId of libraryNodeIds) {
const creatureNode = LibraryNodes.findOne({
_id: nodeId,
type: 'creature',
removed: { $ne: true },
});
if (!creatureNode) {
if (Meteor.isClient) return {};
else {
throw new Meteor.Error(
'Insert property from library failed',
`No library creature with id '${nodeId}' was found`
);
}
}
const creatureId = Creatures.insert({
...creatureNode,
type: 'monster',
tabletopId,
owner: this.userId,
writers: [this.userId],
dirty: true,
});
insertSubProperties(creatureNode, creatureId);
}
},
});
function insertSubProperties(node, creatureId: string) {
let nodes = LibraryNodes.find({
...getFilter.descendants(node),
removed: { $ne: true },
}).fetch();
for (const node of nodes) {
node.root = {
'_id': creatureId,
collection: 'creatures',
};
}
// Convert all references into actual nodes
nodes = reifyNodeReferences(nodes);
// set libraryNodeIds
storeLibraryNodeReferences(nodes);
// Give the docs new IDs without breaking internal references
renewDocIds({
docArray: nodes,
collectionMap: { 'libraryNodes': 'creatureProperties' }
});
// Insert the creature properties
// @ts-expect-error Batch insert not defined
CreatureProperties.batchInsert(nodes);
return node;
}
export default addCreaturesFromLibraryToTabletop;