UNPKG

roleplayer

Version:

A library for building table top role playing game worlds, and managing campaigns in those worlds

121 lines (106 loc) 4.2 kB
import { DnDRuleset, HealthResourceTypeName, SystemEventType, generateId } from "../.."; import { addCharacterItem, characterEquipItem, createCharacterWithDefaults, nextRound, performCharacterAttack, startCampaign, } from "../actions"; import { ItemEquipmentType, ItemSlot, ItemType, type ItemDefinition } from "../inventory/item"; import { Roleplayer } from "../roleplayer"; import { Rarity } from "../world/rarity"; import { TargetType } from "./action"; import { StatusDurationType, StatusType, type StatusDefinition } from "./status"; describe("actions", () => { const ruleset = new DnDRuleset((str) => { const [, staticValue = "0"] = str.split("+"); return 2 + +staticValue; }); const coldElement = ruleset.getElementDefinitions().find((ed) => ed.name === "Cold")!; const mainHandEquipmentSlot = ruleset.getCharacterEquipmentSlots().find((eq) => eq.name === "Main hand")!; const healthResource = ruleset.getCharacterResourceTypes().find((r) => r.name === HealthResourceTypeName)!; const frozenStatus: StatusDefinition = { id: "status-chill", name: "Chill", duration: 2, durationType: StatusDurationType.NumberOfRounds, type: StatusType.Magic, appliesEffects: [ { effect: { eventType: "CharacterResourceLoss", elementTypeId: coldElement.id, resourceTypeId: healthResource.id, roll: "D10+2", }, appliesAt: SystemEventType.RoundStarted, }, ], }; const frostSword: ItemDefinition = { id: "item-frost-sword", description: "", equipmentType: ItemEquipmentType.OneHandWeapon, weightUnits: 1, rarity: Rarity.Rare, actions: [ { id: "action-frost-sword-slash", description: "", appliesEffects: [ { eventType: "CharacterResourceLoss", roll: "D10+2", resourceTypeId: healthResource.id, elementTypeId: coldElement.id, }, { eventType: "CharacterStatusGain", statusId: frozenStatus.id, }, ], eligibleTargets: [TargetType.Hostile], name: "Slash", rangeDistanceUnits: 5, requiresResources: [], }, ], name: "Sword of Frost", occupiesSlots: [ItemSlot.MainHand], type: ItemType.Equipment, stats: [], }; const roleplayer = new Roleplayer( { ruleset }, { id: generateId(), itemTemplates: [frostSword], statuses: [frozenStatus] } ); it("should apply effects from being hit", () => { roleplayer.dispatchAction(startCampaign()); const attackerId = "attacker-id"; const defenderId = "defender-id"; // Setup attacker roleplayer.dispatchAction(createCharacterWithDefaults(attackerId, "Attacker")); roleplayer.dispatchAction(addCharacterItem(attackerId, frostSword.id)); const afterAddSword = roleplayer.campaign; const characterWithSword = afterAddSword.characters.find((c) => c.id === attackerId); roleplayer.dispatchAction( characterEquipItem(attackerId, mainHandEquipmentSlot.id, characterWithSword!.inventory[0]!.id) ); // Setup defender roleplayer.dispatchAction(createCharacterWithDefaults(defenderId, "Defender")); roleplayer.dispatchAction(nextRound()); const beforeAttack = roleplayer.campaign; const attacker = beforeAttack.characters.find((c) => c.id === attackerId); const actions = attacker!.getAvailableActions(); const characterAction = actions.find((a) => a.id === "action-frost-sword-slash"); const defenderBeforeAttack = beforeAttack.characters.filter((c) => c.id === defenderId); roleplayer.dispatchAction(performCharacterAttack(attacker!, characterAction!, defenderBeforeAttack)); const afterAttack = roleplayer.campaign; const defenderAfterAttack = afterAttack.characters.find((c) => c.id === defenderId); const defenderHealth = defenderAfterAttack!.resources.find((r) => r.resourceTypeId === healthResource.id)?.amount; const defenderChillStatus = defenderAfterAttack!.statuses.find((s) => s.name === "Chill"); expect(defenderHealth).toBe(6); expect(defenderChillStatus).toBeDefined(); }); });