From f7e3f522adb209f4ac426225aca73674f09bb9f5 Mon Sep 17 00:00:00 2001 From: Austin Decker Date: Mon, 9 Oct 2023 03:07:39 +0000 Subject: [PATCH] 23-10-08 session --- Config/options.json | 2 +- Data/assets/akihiro_token.png | 3 + Data/assets/aysun_adara.jpg | 3 + Data/assets/aysun_adara_token.png | 3 + Data/modules/pf2e-staves/LICENSE | 21 + Data/modules/pf2e-staves/README.md | 30 ++ Data/modules/pf2e-staves/module.json | 48 +++ Data/modules/pf2e-staves/scripts/main.js | 359 ++++++++++++++++++ Data/modules/pf2e-staves/styles/style.css | 19 + .../the-fall-of-plaguestone/data/actors.db | 4 +- .../the-fall-of-plaguestone/data/combats.db | 4 +- .../the-fall-of-plaguestone/data/fog.db | 4 +- .../the-fall-of-plaguestone/data/folders.db | 4 +- .../the-fall-of-plaguestone/data/items.db | 4 +- .../the-fall-of-plaguestone/data/macros.db | 4 +- .../the-fall-of-plaguestone/data/messages.db | 4 +- .../the-fall-of-plaguestone/data/scenes.db | 4 +- .../the-fall-of-plaguestone/data/settings.db | 4 +- .../the-fall-of-plaguestone/data/tables.db | 3 - .../the-fall-of-plaguestone/data/users.db | 4 +- 20 files changed, 507 insertions(+), 24 deletions(-) create mode 100644 Data/assets/akihiro_token.png create mode 100644 Data/assets/aysun_adara.jpg create mode 100644 Data/assets/aysun_adara_token.png create mode 100644 Data/modules/pf2e-staves/LICENSE create mode 100644 Data/modules/pf2e-staves/README.md create mode 100644 Data/modules/pf2e-staves/module.json create mode 100644 Data/modules/pf2e-staves/scripts/main.js create mode 100644 Data/modules/pf2e-staves/styles/style.css diff --git a/Config/options.json b/Config/options.json index a9c4f13a..c25b18e5 100644 --- a/Config/options.json +++ b/Config/options.json @@ -10,7 +10,7 @@ "proxyPort": 443, "proxySSL": true, "routePrefix": null, - "updateChannel": "testing", + "updateChannel": "stable", "upnp": true, "upnpLeaseDuration": null, "awsConfig": null, diff --git a/Data/assets/akihiro_token.png b/Data/assets/akihiro_token.png new file mode 100644 index 00000000..b11fb1d5 --- /dev/null +++ b/Data/assets/akihiro_token.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b252216940acda244284faefb28311745fbee19d9025351d30b0c2eab5df7dd1 +size 94168 diff --git a/Data/assets/aysun_adara.jpg b/Data/assets/aysun_adara.jpg new file mode 100644 index 00000000..adbe54e6 --- /dev/null +++ b/Data/assets/aysun_adara.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f915c018dd9ef37fcd8853b5a3342520422786ce23666c5dc45bf5095a79f25 +size 5083 diff --git a/Data/assets/aysun_adara_token.png b/Data/assets/aysun_adara_token.png new file mode 100644 index 00000000..9d74436e --- /dev/null +++ b/Data/assets/aysun_adara_token.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1052672d87e1fff7889b52abe5b95b99134c5cbe709e6113cbd5915510173a37 +size 78210 diff --git a/Data/modules/pf2e-staves/LICENSE b/Data/modules/pf2e-staves/LICENSE new file mode 100644 index 00000000..c8341585 --- /dev/null +++ b/Data/modules/pf2e-staves/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 jessev14 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Data/modules/pf2e-staves/README.md b/Data/modules/pf2e-staves/README.md new file mode 100644 index 00000000..9c1d86f9 --- /dev/null +++ b/Data/modules/pf2e-staves/README.md @@ -0,0 +1,30 @@ +![All Downloads](https://img.shields.io/github/downloads/jessev14/pf2e-staves/total?style=for-the-badge) + +![Latest Release Download Count](https://img.shields.io/github/downloads/jessev14/pf2e-staves/latest/module.zip) +[![Forge Installs](https://img.shields.io/badge/dynamic/json?label=Forge%20Installs&query=package.installs&suffix=%25&url=https%3A%2F%2Fforge-vtt.com%2Fapi%2Fbazaar%2Fpackage%2Fpf2e-staves&colorB=4aa94a)](https://forge-vtt.com/bazaar#package=pf2e-staves) + +This module was funded by a commission. Donations help fund updates and new modules! + +[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/jessev14) + +# PF2e Staves + +This FoundryVTT module implements automations for Staves in the PF2e game system. + +## Usage + +When an item with the "magical" and "staff" traits are added to a character sheet, a corresponding spellcasting entry will be created. + +![](/images/pf2e-staves-1.png) + +Any spells linked in the text description will be automatically added to the spellcasting entry. This works for custom spells, as long as the spell exists in the item directory. + +![](/images/pf2e-staves-2.png) + +This spellcasting entry uses charges. The number of charges defaults to the highest level spell slot the character has. Casting spells in this spellcasting entry requires charges equal the level of the spell. If the character has Spontaneous spellcasting, the charge cost can be reduced by right clicking the Cast button. A spell slot of equal or higher level than the spell can be expended to reduce the charge cost to one charge. + +![](/images/pf2e-staves-3.png) + +When the character is ready to regain charges, the reset button next to the charge value will open a prompt to charge the stave. This will replenish the number of charges back to the default (equal to highest spell slot available). If the character has Prepared spellcasting, the player may choose a spell slot to expend to gain extra charges equal to the level of the spell slot. + +![](/images/pf2e-staves-4.png) diff --git a/Data/modules/pf2e-staves/module.json b/Data/modules/pf2e-staves/module.json new file mode 100644 index 00000000..5cd8877c --- /dev/null +++ b/Data/modules/pf2e-staves/module.json @@ -0,0 +1,48 @@ +{ + "id": "pf2e-staves", + "title": "PF2e Staves", + "description": "", + "authors": [ + { + "name": "enso", + "discord": "enso#0361" + } + ], + "version": "1.3.1", + "compatibility": { + "minimum": "10", + "verified": "10" + }, + "relationships": { + "systems": [ + { + "id": "pf2e", + "type": "system", + "compatibility": { + "minimum": "4.3.0" + } + } + ], + "requires": [ + { + "id": "lib-wrapper", + "type": "module", + "compatibility": { + "minimum": "1", + "verified": "1.12.7.1" + } + } + ] + }, + "esmodules": [ + "./scripts/main.js" + ], + "styles": [ + "./styles/style.css" + ], + "languages": [], + "flags": {}, + "url": "https://github.com/jessev14/pf2e-staves", + "manifest": "https://github.com/jessev14/pf2e-staves/releases/latest/download/module.json", + "download": "https://github.com/jessev14/pf2e-staves/releases/download/1.3.1/module.zip" +} \ No newline at end of file diff --git a/Data/modules/pf2e-staves/scripts/main.js b/Data/modules/pf2e-staves/scripts/main.js new file mode 100644 index 00000000..dec0c993 --- /dev/null +++ b/Data/modules/pf2e-staves/scripts/main.js @@ -0,0 +1,359 @@ +export const moduleID = 'pf2e-staves'; + + +export const lg = x => console.log(x); + +const mostCommonInList = (arr) => { + return arr.sort((a,b) => + arr.filter(v => v===a).length + - arr.filter(v => v===b).length + ).pop(); +} + + +Hooks.once('init', () => { + // Add Charge spell type. + CONFIG.PF2E.spellCategories.charge = 'Charge'; + CONFIG.PF2E.preparationType.charge = 'Charge'; + + // Patch spellcastingEntry#cast to use charges instead of spell slots for staves. + libWrapper.register(moduleID, 'CONFIG.PF2E.Item.documentClasses.spellcastingEntry.prototype.cast', spellcastingEntry_cast, 'MIXED'); +}); + + +// When stave added to a character, also create corresponding spellcasting entry. +Hooks.on('createItem', async (weapon, options, userID) => { + if (!weapon.actor) return; + if (userID !== game.user.id) return; + + const traits = weapon.system.traits?.value; + const isStave = traits?.includes('magical') && traits?.includes('staff'); + const isCoda = traits?.includes('coda') && traits?.includes('staff'); + if (!isStave && !isCoda) return; + + return createStaveSpellcastingEntry(weapon, weapon.actor); +}); + +// When stave updated on a character, create spellcasting entry if none found. Update existing entry if found. +Hooks.on('updateItem', async (weapon, update, options, userID) => { + if (!weapon.actor) return; + if (userID !== game.user.id) return; + + const traits = weapon.system.traits?.value; + const isStave = traits?.includes('magical') && traits?.includes('staff'); + const isCoda = traits?.includes('coda') && traits?.includes('staff'); + if (!isStave && !isCoda) return; + + const { actor } = weapon; + const existingStaveEntry = actor.spellcasting.find(s => s.flags && s.flags[moduleID]?.staveID === weapon?.id); + return createStaveSpellcastingEntry(weapon, actor, existingStaveEntry); +}); + +// Delete spellcastingEntry associated with stave. +Hooks.on('preDeleteItem', (weapon, options, userID) => { + const traits = weapon.system.traits?.value; + const isStave = traits?.includes('magical') && traits?.includes('staff'); + const isCoda = traits?.includes('coda') && traits?.includes('staff'); + if (!isStave && !isCoda) return; + + const { actor } = weapon; + const spellcastingEntries = actor.items.filter(i => i.type === 'spellcastingEntry'); + const spellcastingEntry = spellcastingEntries.find(i => i.getFlag(moduleID, 'staveID') === weapon.id); + if (spellcastingEntry) spellcastingEntry.delete(); +}); + +// Implement charge spellcasting rules on character sheet. +// Hooks.on('renderCharacterSheetPF2e', (sheet, [html], sheetData) => { +Hooks.on('renderCreatureSheetPF2e', (sheet, [html], sheetData) => { + const actor = sheet.object; + const isPC = actor.type === 'character'; + + const spellcastingLis = html.querySelectorAll('li.spellcasting-entry'); + for (const li of spellcastingLis) { + const spellcastingEntry = actor.spellcasting.get(li.dataset.containerId); + if (spellcastingEntry?.system?.prepared?.value !== 'charge') continue; + + let chargeEl; + if (isPC) { + chargeEl = document.createElement('section'); + chargeEl.innerHTML = ` +

Charges

+ + + `; + } else { + chargeEl = document.createElement('div'); + chargeEl.classList.add('inline-field'); + chargeEl.innerHTML = ` + + + + `; + } + + // Charge input. + chargeEl.querySelector('input').addEventListener('focus', ev => { + ev.currentTarget.select(); + }); + chargeEl.querySelector('input').addEventListener('change', async ev => { + const { target } = ev; + const charges = target.value; + const clampedCharges = Math.max(0, charges); + target.value = clampedCharges; + + await spellcastingEntry.setFlag(moduleID, 'charges', clampedCharges); + }); + + // Charge stave prompt. + chargeEl.querySelector('a').addEventListener('click', async ev => { + let options = ``; + for (const li of spellcastingLis) { + const spellcastingEntry = actor.spellcasting.get(li.dataset.containerId); + if (spellcastingEntry?.system?.prepared?.value !== 'prepared') continue; + + const preppedSpells = []; + for (const spellLi of li.querySelectorAll('li.item.spell')) { + if (spellLi.dataset.expendedState === 'true' || !parseInt(spellLi.dataset.slotLevel)) continue; + + const spell = actor.items.get(spellLi.dataset.itemId); + const { entryId, slotLevel, slotId } = spellLi.dataset; + preppedSpells.push({ + name: spell.name, + entryId, + slotLevel, + slotId + }); + } + if (preppedSpells.length) { + options += `` + for (const spell of preppedSpells) { + options += `` + } + options += ``; + } + } + + if (options) options = `` + options; + const content = options + ? ` +
Expend spell slot for extra charges?
+ + ` + : null; + await Dialog.prompt({ + title: 'Charge Stave?', + content, + label: 'Charge', + callback: async ([dialogHtml]) => { + const charges = getHighestSpellslot(actor); + const select = dialogHtml.querySelector('select'); + if (!select || !select?.selectedIndex) return spellcastingEntry.setFlag(moduleID, 'charges', charges); + + const selectedSpellOption = select.options[select.selectedIndex]; + const { entryId, slotLevel, slotId } = selectedSpellOption.dataset; + const entry = actor.items.get(entryId); + entry.setSlotExpendedState(slotLevel, slotId, true); + + return spellcastingEntry.setFlag(moduleID, 'charges', charges + parseInt(slotLevel)); + }, + rejectClose: false, + options: { width: 250 } + }); + }); + + const characterHeader = li.querySelector('div.statistic-values'); + const npcHeader = li.querySelector('h4.name'); + if (isPC) characterHeader.appendChild(chargeEl); + else npcHeader.after(chargeEl); + + // Add spontaneous spellcasting rules to Cast button right click. + const castButtons = li.querySelectorAll('button.cast-spell'); + castButtons.forEach(button => { + button.addEventListener('contextmenu', () => { + const spellLi = button.closest('li.item.spell'); + const { itemId, slotLevel, slotId, entryId } = spellLi.dataset; + const collection = actor.spellcasting.collections.get(entryId, { strict: true }); + const spell = collection.get(itemId, { strict: true }); + collection.entry.cast(spell, { level: slotLevel, [`${moduleID}Spontaneous`]: true }); + }); + }); + + // Add .slotless-level-toggle button. + const slotToggleButton = document.createElement('a'); + slotToggleButton.title = 'Toggle visibility of spell levels without slots'; + slotToggleButton.classList.add('skill-name', 'slotless-level-toggle'); + slotToggleButton.innerHTML = ``; + slotToggleButton.addEventListener('click', async ev => { + ev.preventDefault(); + + const spellcastingID = $(ev.currentTarget).parents(".item-container").attr("data-container-id") ?? ""; + if (!spellcastingID) return; + + const spellcastingEntry = actor.items.get(spellcastingID); + const bool = !(spellcastingEntry?.system?.showSlotlessLevels || {}).value; + await spellcastingEntry.update({ + "system.showSlotlessLevels.value": bool, + }); + }); + + const itemControls = li.querySelector('div.item-controls'); + itemControls.prepend(slotToggleButton); + } +}); + + +async function createStaveSpellcastingEntry(stave, actor, existingEntry = null) { + const spells = []; + const description = stave.system.description.value; + const slotLevels = ['Cantrips?', '1st', '2nd', '3rd', '4th', '5th', '6th', '7th', '8th', '9th', '10th', '11th']; + for (let i = 0; i < slotLevels.length; i++) { + const regex = new RegExp(`${slotLevels[i]}.*@(UUID|Compendium).*\n`); + const match = description.match(regex); + if (!match) continue; + + const strs = match[0].match(/(@UUID\[Compendium\.|@Compendium\[)(.*?)]({.*?})?/g); + for (const str of strs) { + const UUID = str.split('[')[1].split(']')[0].replace('Compendium.', ''); + const spell = await fromUuid("Compendium." + UUID); + if (!spell || spell?.type !== 'spell') continue; + + let spellClone; + if (spell.id) spellClone = spell.clone({ 'system.location.heightenedLevel': i }); + else { + const { pack, _id } = spell; + const spellFromPack = await game.packs.get(pack)?.getDocuments().find(s => s.id === _id); + spellClone = spellFromPack.clone({ 'system.location.heightenedLevel': i }); + } + + spells.push(spellClone); + } + } + + if (!spells.length) { // fallback + const UUIDs = description.match(/(@UUID\[Compendium\.|@Compendium\[)(.*?)].*?}/g); + if (!UUIDs) return; + + for (const str of UUIDs) { + const UUID = str.split('[')[1].split(']')[0].replace('Compendium.', ''); + const spell = await fromUuid("Compendium." + UUID); + if (!spell || spell?.type !== 'spell') continue; + + if (spell.id) spells.push(spell); + else { + const { pack, _id } = spell; + const spellFromPack = await game.packs.get(pack)?.getDocuments().find(s => s.id === _id); + if (spellFromPack) spells.push(spellFromPack); + } + } + } + + if (!spells.length) return; + + if (!existingEntry) { + const highestMentalAbilityValue = Math.max(...Object.keys(actor.abilities).filter(abi => ['cha', 'int', 'wis'].includes(abi)).map(abi => actor.abilities[abi].value)); + // picking best mental ability; not always correct, but it's a good rule of thumb + const bestMentalAbility = Object.keys(actor.abilities).find(abi => actor.abilities[abi].value === highestMentalAbilityValue); + // rule of thumb for tradition is to pick whatever exists in other spellcasting entries + const mostCommonTradition = mostCommonInList(actor.spellcasting.map(se => se?.system?.tradition.value).filter(se => !!se)); + const createData = { + type: 'spellcastingEntry', + name: stave.name, + system: { + prepared: { + value: 'charge' + }, + ability: { + value: bestMentalAbility + }, + tradition: { + value: mostCommonTradition + }, + showSlotlessLevels: { + value: false + } + }, + flags: { + [moduleID]: { + staveID: stave.id, + charges: getHighestSpellslot(actor) + } + } + } + const [spellcastingEntry] = await actor.createEmbeddedDocuments('Item', [createData]); + for (const spell of spells) await spellcastingEntry.addSpell(spell); + } else { + for (const spell of existingEntry.spells) await spell.delete(); + for (const spell of spells) await existingEntry.addSpell(spell); + } +} + +function getHighestSpellslot(actor) { + let charges = 0; + actor.spellcasting.forEach(entry => { + if (!entry?.flags || entry.flags[moduleID]) return; + + let i = 0; + Object.values(entry.system.slots).forEach(slot => { + if (slot.max && charges < i) charges = i; + i++; + }); + }); + + return charges; +} + +async function spellcastingEntry_cast(wrapped, spell, options) { + if (!spell.spellcasting.flags[moduleID] || spell.isCantrip) return wrapped(spell, options); + + options.consume = false; + if (options[`${moduleID}Override`]) return wrapped(spell, options); + + const { actor } = spell; + const charges = spell.spellcasting.getFlag(moduleID, 'charges'); + if (options[`${moduleID}Spontaneous`]) { + if (!charges) return ui.notifications.warn('You do not have enough stave charges to cast this spell.'); + + const select = document.createElement('select'); + select.style.width = '100%'; + select.style['margin-bottom'] = '5px'; + for (const entry of actor.spellcasting.filter(e => e.system)) { + if (entry.system.prepared.value !== 'spontaneous') continue; + select.innerHTML += ``; + for (let i = parseInt(options.level); i < 12; i++) { + const currentSlotLevel = Object.values(entry.system.slots)[i]; + const { value, max } = currentSlotLevel; + if (value) select.innerHTML += ``; + } + + select.innerHTML += ``; + } + if (!select.length) return ui.notifications.warn('You do not have any Spontaneous spell slots available to cast this spell.'); + + await Dialog.prompt({ + title: 'Use Spell Slot?', + content: select.outerHTML, + label: 'Consume Spell Slot', + callback: async ([html]) => { + const select = html.querySelector('select'); + const [entryID, selectedLevel] = select.value.split('-'); + const entry = actor.spellcasting.get(entryID); + const currentSlots = entry.system.slots[`slot${selectedLevel}`].value; + + await actor.spellcasting.get(entryID).update({ [`system.slots.slot${selectedLevel}.value`]: currentSlots - 1 }); + await spell.spellcasting.setFlag(moduleID, 'charges', charges - 1); + options[`${moduleID}Override`] = true; + return spell.spellcasting.cast(spell, options); + }, + rejectClose: false, + options: { width: 250 } + }); + + } else { + if (spell.level > charges) return ui.notifications.warn('You do not have enough stave charges to cast this spell.'); + + await spell.spellcasting.setFlag(moduleID, 'charges', charges - spell.level); + return wrapped(spell, options); + } +} diff --git a/Data/modules/pf2e-staves/styles/style.css b/Data/modules/pf2e-staves/styles/style.css new file mode 100644 index 00000000..8fad70e5 --- /dev/null +++ b/Data/modules/pf2e-staves/styles/style.css @@ -0,0 +1,19 @@ +input.pf2e-staves-charges { + background: var(--alt); + border: 1px solid var(--sub); + border-radius: 3px; + color: #fff; + font-size: var(--font-size-11); + height: 14px; + text-align: center; + width: 22px; + + padding: 0; + margin-left: 5px; +} + +a.pf2e-staves-charge { + font-size: var(--font-size-10); + padding-left: 5px; + line-height: 1px; +} \ No newline at end of file diff --git a/Data/worlds/the-fall-of-plaguestone/data/actors.db b/Data/worlds/the-fall-of-plaguestone/data/actors.db index 03f1972c..8ffef1b7 100644 --- a/Data/worlds/the-fall-of-plaguestone/data/actors.db +++ b/Data/worlds/the-fall-of-plaguestone/data/actors.db @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fb61d474514d7d3cfc9fd82fa234a326fb838f90bb5c1c723c591c55caec2904 -size 2195062 +oid sha256:c27cfe917fde03434820a9a3c11bd5cee8377b346cc917940a7c3cee48f4ca4d +size 1338587 diff --git a/Data/worlds/the-fall-of-plaguestone/data/combats.db b/Data/worlds/the-fall-of-plaguestone/data/combats.db index 310323a5..8027ca85 100644 --- a/Data/worlds/the-fall-of-plaguestone/data/combats.db +++ b/Data/worlds/the-fall-of-plaguestone/data/combats.db @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd91f1db3f720041c47a10620987ae11788ee9a7fc0cd89c089c4d476e865aab -size 20188 +oid sha256:97a3b441f46c583c8835e4f96fc6811ab65a0706ff78de122dcebebcecde0e25 +size 295 diff --git a/Data/worlds/the-fall-of-plaguestone/data/fog.db b/Data/worlds/the-fall-of-plaguestone/data/fog.db index 0a1c95fb..9668542c 100644 --- a/Data/worlds/the-fall-of-plaguestone/data/fog.db +++ b/Data/worlds/the-fall-of-plaguestone/data/fog.db @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a550cfb472ec445e0ea749e0f3187c014533666bab594acb4471caaaa6ef802a -size 16964152 +oid sha256:285b21aa93783f8bbe42a9b418d4179625cd735da2943e261d8b702590dab201 +size 5862251 diff --git a/Data/worlds/the-fall-of-plaguestone/data/folders.db b/Data/worlds/the-fall-of-plaguestone/data/folders.db index e28f5caa..90b3f48f 100644 --- a/Data/worlds/the-fall-of-plaguestone/data/folders.db +++ b/Data/worlds/the-fall-of-plaguestone/data/folders.db @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0e07598b99d3d7cac68a57900b57d468b42307e6828f4149701f44644274debf -size 5032 +oid sha256:9c6c7120695c53fc5d35febb4a2b804aa1a4f83c14f274a29fadb6376c973aa0 +size 5023 diff --git a/Data/worlds/the-fall-of-plaguestone/data/items.db b/Data/worlds/the-fall-of-plaguestone/data/items.db index ad3e8d27..4050f582 100644 --- a/Data/worlds/the-fall-of-plaguestone/data/items.db +++ b/Data/worlds/the-fall-of-plaguestone/data/items.db @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b4f688082276f4ec01db96318b65991dbc461df44535887f6eef9091c4ba6be -size 135701 +oid sha256:04fff74e0ebe5b75914591576d2aa37378170c2ebda062ccae2fed02c9c6b0e6 +size 44516 diff --git a/Data/worlds/the-fall-of-plaguestone/data/macros.db b/Data/worlds/the-fall-of-plaguestone/data/macros.db index 2156181e..3ed3e3e0 100644 --- a/Data/worlds/the-fall-of-plaguestone/data/macros.db +++ b/Data/worlds/the-fall-of-plaguestone/data/macros.db @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1ad45225ebb4616906bb8db1cc84792ef5e7134e3861eb8af413b3514308c27a -size 24361 +oid sha256:f19d4bc75ea6267c0ae938a760720bb323237dff5875fb704ca3d04f7721da4b +size 26260 diff --git a/Data/worlds/the-fall-of-plaguestone/data/messages.db b/Data/worlds/the-fall-of-plaguestone/data/messages.db index f1b1593e..2ccabb3e 100644 --- a/Data/worlds/the-fall-of-plaguestone/data/messages.db +++ b/Data/worlds/the-fall-of-plaguestone/data/messages.db @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c334a4ede2207f281c65da13d1352ed21983313269b618d9ca4136e8ec224daf -size 7824433 +oid sha256:a118a31c450138e68ecb31e72ae8ab5ca204607220b086ef5082846b53bcb4a9 +size 9564078 diff --git a/Data/worlds/the-fall-of-plaguestone/data/scenes.db b/Data/worlds/the-fall-of-plaguestone/data/scenes.db index 6ca25eb5..93fd72bd 100644 --- a/Data/worlds/the-fall-of-plaguestone/data/scenes.db +++ b/Data/worlds/the-fall-of-plaguestone/data/scenes.db @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f2dd2b732004c2273cd5340121c639f46c857ceca5e9348ebb46c8c96194f287 -size 6213321 +oid sha256:c9133cbfaf1f5b086dfc2e766a2256043dc1c67949ba9456169254837989e420 +size 472802 diff --git a/Data/worlds/the-fall-of-plaguestone/data/settings.db b/Data/worlds/the-fall-of-plaguestone/data/settings.db index 5b3b6540..822841c8 100644 --- a/Data/worlds/the-fall-of-plaguestone/data/settings.db +++ b/Data/worlds/the-fall-of-plaguestone/data/settings.db @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:018ab9efc05a0416551a6467b318dca6fc50c9b06735df59c4ead5de85ca86fb -size 54612 +oid sha256:2385f4be56d1f7c11bd7dd2aa079772a391a3adbdcdf74e67914874e13c87e03 +size 36739 diff --git a/Data/worlds/the-fall-of-plaguestone/data/tables.db b/Data/worlds/the-fall-of-plaguestone/data/tables.db index 43ab5a1c..e69de29b 100644 --- a/Data/worlds/the-fall-of-plaguestone/data/tables.db +++ b/Data/worlds/the-fall-of-plaguestone/data/tables.db @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3c3927f02a01a2f98d98274634daf3f523ac630c9fc5a7e4cd916869c8d8b221 -size 23654 diff --git a/Data/worlds/the-fall-of-plaguestone/data/users.db b/Data/worlds/the-fall-of-plaguestone/data/users.db index 1302bf12..f966b2fa 100644 --- a/Data/worlds/the-fall-of-plaguestone/data/users.db +++ b/Data/worlds/the-fall-of-plaguestone/data/users.db @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1de1a9a23961dab787df486230515a4d49150e91b607766023eae555554161eb -size 9934 +oid sha256:41876a730621cae7f89c7e9d43ce265f734d1140f58973780137d0d4450ccf76 +size 9357