import {PlayerCharacterDataModel} from "./module/data/character.mjs"; import {SkillSheet} from "./module/sheets/skillSheet.mjs"; import {SpellSheet} from "./module/sheets/spellSheet.mjs"; import {SkillDataModel} from "./module/data/skill.mjs"; import {SpellDataModel} from "./module/data/spell.mjs"; import {VornachteileDataModel} from "./module/data/vornachteile.mjs"; import {Character} from "./module/documents/character.mjs"; import CharacterSheet from "./module/sheets/characterSheet.mjs"; import {AdvantageSheet} from "./module/sheets/advantageSheet.mjs"; import {GroupDataModel} from "./module/data/group.mjs"; import {GroupSheet} from "./module/sheets/groupSheet.mjs"; import {EquipmentDataModel} from "./module/data/equipment.mjs"; import {EquipmentSheet} from "./module/sheets/equipmentSheet.mjs"; import {CreatureDataModel} from "./module/data/creature.mjs"; import {CreatureSheet} from "./module/sheets/creatureSheet.mjs"; import {LiturgySheet} from "./module/sheets/liturgySheet.mjs"; import {LiturgyDataModel} from "./module/data/liturgy.mjs"; import {BlessingDataModel} from "./module/data/blessing.mjs"; import {SpecialAbilityDataModel} from "./module/data/specialAbility.mjs"; import {SpecialAbilitySheet} from "./module/sheets/specialAbilitySheet.mjs"; import {ActiveEffectSheet} from "./module/sheets/ActiveEffectSheet.mjs"; import {ActiveEffectDataModel} from "./module/data/activeeffect.mjs"; import {Trefferzone, Wunde, Zonenruestung, Zonenwunde} from "./module/data/Trefferzone.js"; import {ProfessionDataModel} from "./module/data/profession.mjs"; import {SpeciesDataModel} from "./module/data/species.mjs"; import {CultureDataModel} from "./module/data/culture.mjs"; import {CultureSheet} from "./module/sheets/CultureSheet.mjs"; import {SpeciesSheet} from "./module/sheets/SpeciesSheet.mjs"; import {ProfessionSheet} from "./module/sheets/ProfessionSheet.mjs"; import {XmlImportDialog} from "./module/dialog/xmlImportDialog.mjs"; import {MerchantDataModel} from "./module/data/merchant.mjs"; import {MerchantSheet} from "./module/sheets/merchantSheet.mjs"; import {RestingDialog} from "./module/dialog/restingDialog.mjs"; import {BattleDialog} from "./module/dialog/battleDialog.mjs"; async function preloadHandlebarsTemplates() { return foundry.applications.handlebars.loadTemplates([ // ui partials. 'systems/DSA_4-1/templates/ui/partial-rollable-button.hbs', 'systems/DSA_4-1/templates/ui/partial-rollable-weaponskill-button.hbs', 'systems/DSA_4-1/templates/ui/partial-rollable-language-button.hbs', 'systems/DSA_4-1/templates/ui/partial-attribute-button.hbs', 'systems/DSA_4-1/templates/ui/partial-talent-editable.hbs', 'systems/DSA_4-1/templates/ui/partial-die.hbs', 'systems/DSA_4-1/templates/ui/partial-advantage-button.hbs', 'systems/DSA_4-1/templates/ui/partial-sf-button.hbs', 'systems/DSA_4-1/templates/ui/partial-action-button.hbs', 'systems/DSA_4-1/templates/ui/partial-equipment-button.hbs', 'systems/DSA_4-1/templates/ui/partial-array-editor.hbs', 'systems/DSA_4-1/templates/dialog/liturgy-dialog.hbs' ]); } Hooks.once("init", () => { game.DSA41 = { rollItemMacro, Zonenruestung, Zonenwunde, Trefferzone, Wunde, RestingDialog, BattleDialog } // Configure custom Document implementations. CONFIG.Actor.documentClass = Character; // Configure System Data Models. CONFIG.Actor.dataModels = { character: PlayerCharacterDataModel, group: GroupDataModel, creature: CreatureDataModel, Merchant: MerchantDataModel, }; CONFIG.Item.dataModels = { Skill: SkillDataModel, Spell: SpellDataModel, Advantage: VornachteileDataModel, Equipment: EquipmentDataModel, Liturgy: LiturgyDataModel, Blessing: BlessingDataModel, SpecialAbility: SpecialAbilityDataModel, ActiveEffect: ActiveEffectDataModel, Profession: ProfessionDataModel, Spezies: SpeciesDataModel, Kultur: CultureDataModel, } CONFIG.Combat.initiative = { formula: `(@ini.wuerfel)d6 + @ini.aktuell`, decimals: 0 } const setMovementSpeeds = () => { const movementActions = CONFIG.Token.movement.actions for (const key of ["swim", "climb", "crawl", "walk", "drive", "ride", "fly"]) { delete movementActions[key]?.getCostFunction } movementActions.climb.canSelect = (token) => { const actor = token.actor | null; return (actor.type === "Character" && actor.system.itemTypes["Skill"].find(p => p.name === "Klettern")?.system.taw > 0) || actor.type === "Creature" } movementActions.crawl.canSelect = (token) => { const actor = token.actor | null; return actor.type === "Character" || actor.type === "Creature" } movementActions.walk.canSelect = (token) => { const actor = token.actor | null; return actor.type === "Character" || actor.type === "Creature" } movementActions.swim = { label: "TOKEN.MOVEMENT.ACTIONS.swim.label", icon: "fa-solid fa-swim", order: 0, canSelect: (token) => { const actor = token.actor | null; return actor.type === "Character" || actor.type === "Creature" }, deriveTerrainDifficulty: () => 1, } movementActions.drive = { label: "TOKEN.MOVEMENT.ACTIONS.drive.label", icon: "fa-solid fa-car-side", order: 0, canSelect: (token) => { const actor = token.actor | null; return (actor.type === "Character" && actor.system.itemTypes["Skill"].find(p => p.name === "Fahrzeuge lenken")?.system.taw > 0) || actor.type === "Creature" }, deriveTerrainDifficulty: () => 1, } movementActions.ride = { label: "TOKEN.MOVEMENT.ACTIONS.ride.label", icon: "fa-solid fa-horse", order: 0, canSelect: (token) => { const actor = token.actor | null; return (actor.type === "Character" && actor.system.itemTypes["Skill"].find(p => p.name === "Reiten")?.system.taw > 0) || actor.type === "Creature" }, deriveTerrainDifficulty: () => 1, } movementActions.fly = { label: "TOKEN.MOVEMENT.ACTIONS.fly.label", icon: "fa-solid fa-wings", order: 0, canSelect: (token) => { const actor = token.actor | null; return (actor.type === "Character" && actor.system.itemTypes["Skill"].find(p => p.name === "Fliegen")?.system.taw > 0) || actor.type === "Creature" }, deriveTerrainDifficulty: () => 1, } } setMovementSpeeds() console.log("DSA 4.1 is ready for development!") foundry.documents.collections.Actors.registerSheet('dsa41.character', CharacterSheet, { types: ["character"], makeDefault: true, label: 'DSA41.CharacterLabels.Item' }) foundry.documents.collections.Actors.registerSheet('dsa41.creature', CreatureSheet, { types: ["creature"], makeDefault: true, label: 'DSA41.CreatureLabel.Item' }) foundry.documents.collections.Actors.registerSheet('dsa41.group', GroupSheet, { types: ["group"], makeDefault: true, label: 'DSA41.GroupLabel.Item' }) foundry.documents.collections.Items.registerSheet('dsa41.skill', SkillSheet, { types: ["Skill"], makeDefault: true, label: 'DSA41.SkillLabels.Item', }); foundry.documents.collections.Items.registerSheet('dsa41.spell', SpellSheet, { types: ["Spell"], makeDefault: true, label: 'DSA41.SpellLabels.Item', }); foundry.documents.collections.Items.registerSheet('dsa41.advantage', AdvantageSheet, { types: ["Advantage"], makeDefault: true, label: 'DSA41.VornachteilLabels.Item' }) foundry.documents.collections.Items.registerSheet('dsa41.equipment', EquipmentSheet, { types: ["Equipment"], makeDefault: false, label: 'DSA41.AusruestungLabels.Item' }) foundry.documents.collections.Items.registerSheet('dsa41.liturgy', LiturgySheet, { types: ["Liturgy"], makeDefault: true, label: 'DSA41.LiturgyLabels.Item' }) foundry.documents.collections.Items.registerSheet('dsa41.specialAbility', SpecialAbilitySheet, { types: ["SpecialAbility"], makeDefault: true, label: 'DSA41.SpecialAbilityLabels.Item' }) foundry.documents.collections.Items.registerSheet('dsa41.activeEffect', ActiveEffectSheet, { types: ['ActiveEffect'], makeDefault: true, label: 'DSA41.ActiveEffectLabels.ActiveEffect' }) foundry.documents.collections.Items.registerSheet('dsa41.culture', CultureSheet, { types: ['Culture'], makeDefault: true, label: 'DSA41.CultureLabels.Culture' }) foundry.documents.collections.Items.registerSheet('dsa41.spezien', SpeciesSheet, { types: ['Species'], makeDefault: true, label: 'DSA41.SpeciesLabels.Species' }) foundry.documents.collections.Items.registerSheet('dsa41.profession', ProfessionSheet, { types: ['Profession'], makeDefault: true, label: 'DSA41.ProfessionLabels.Profession' }) foundry.documents.collections.Actors.registerSheet('dsa41.merchant', MerchantSheet, { types: ['Merchant'], makeDefault: true, label: 'DSA41.MerchantLabels.MerchantLabel' }) game.settings.register('DSA_4-1', 'optional_colorfuldice', { name: "Optional: Farbige Würfel nach Paramanthus", hint: "Färbt die Würfel je nach Attribut ein", scope: "client", config: true, type: Boolean, default: false, onChange: value => { }, requiresReload: false }) game.settings.register('DSA_4-1', 'optional_trefferzonen', { name: "Optional: Trefferzonen", hint: "Ersetzt das Wundensystem aus dem BRW durch das Trefferzonensystem aus WdH", scope: "world", config: true, type: Boolean, default: false, onChange: value => { }, requiresReload: true }) game.settings.register('DSA_4-1', 'optional_ruestungzonen', { name: "Optional: Zonenrüstung", hint: "Ersetzt das Rüstungssystem aus dem BRW durch das Zonenrüstungssystem aus WdH", scope: "world", config: true, type: Boolean, default: false, onChange: value => { }, requiresReload: true }) game.settings.register('DSA_4-1', 'optional_ausdauer', { name: "Optional: Ausdauerregeln", hint: "Aktiviert Regeln für das Spiel mit Ausdauer", scope: "world", config: true, type: Boolean, default: false, onChange: value => { }, requiresReload: true }) game.settings.register('DSA_4-1', 'optional_distanzklassen', { name: "Optional: Distanzklassen", hint: "Aktiviert Regeln für das Spiel mit Distanzklassen", scope: "world", config: true, type: Boolean, default: false, onChange: value => { }, requiresReload: true }) game.settings.register('DSA_4-1', 'optional_aufstufen_von_liturgien', { name: "Optional: Aufstufen von Liturgien", hint: "Aktiviert die Regeln zum Aufstufen von Liturgien", scope: "world", config: true, type: Boolean, default: false, disabled: true, requiresReload: true }) Handlebars.registerHelper("weight", (data) => { const baseValue = data * 1000 // to get to gramms (1/1000 Stone) const stone = Math.floor(baseValue / 1000) const remainder = baseValue - (stone * 1000) const ounces = remainder / 25 let stoneRepresentation = '' let ouncesRepresentation = '' if (stone > 0) { stoneRepresentation = `${stone}` } if (ounces > 0) { ouncesRepresentation = `${ounces}` } return new Handlebars.SafeString(`${stoneRepresentation}${ouncesRepresentation}`) }) Handlebars.registerHelper("fieldTooltip", (...args) => { const [fieldName, actorId] = args const actor = game.actors.find(p => p._id === actorId) let tooltip = "" if (actor) { Object.entries(actor.getModificationsOn(fieldName)).forEach(([key, value]) => { tooltip += `${key}: ${value}
` }) } else { tooltip = `${fieldName} not found` } return new Handlebars.SafeString(tooltip) }) Handlebars.registerHelper("currency", (data) => { // schema for Mittelreich: 1 Ducat = 10 Silver = 100 Kreutzer = 1000 Heller // internally the price is always given in Silver // so we need to inflate the value of price by 100 to be able to divide beginning from Heller const baseValue = data * 100 // then we can regex over it const currencyRegexp = /(.*)(.)(.)(.)/g const withDucats = currencyRegexp.exec(baseValue) let _ = undefined let ducats = 0 let silver = 0 let kreutzer = 0 let heller = 0 if (withDucats) { [_, ducats, silver, kreutzer, heller] = withDucats } else { const currencyRegexp = /(.)(.)(.)/g const withSilver = currencyRegexp.exec(baseValue) if (withSilver) { [_, silver, kreutzer, heller] = withSilver } else { const currencyRegexp = /(.)(.)/g const withKreutzer = currencyRegexp.exec(baseValue) if (withKreutzer) { [_, kreutzer, heller] = withKreutzer } else { heller = baseValue } } } let str = `` if (ducats > 0) { str += ducats + "" } if (silver > 0) { str += silver + "" } if (kreutzer > 0) { str += kreutzer + "" } if (heller > 0) { str += heller + "" } str = str + "" return new Handlebars.SafeString(str) }) return preloadHandlebarsTemplates(); }) Hooks.once("ready", async function () { // Wait to register hotbar drop hook on ready so that modules could register earlier if they want to Hooks.on("hotbarDrop", (bar, data, slot) => { return createTalentMacro(data, slot) }); }); Hooks.on("getActorContextOptions", (application, menuItems) => { menuItems.push({ name: "Import from XML", icon: '', callback: (li) => { const actorId = li.getAttribute("data-entry-id") const actor = game.actors.get(actorId) //actor.import() new XmlImportDialog(actor).render(true) } }) }) async function createTalentMacro(data, slot) { if (data.type !== "Item") return; const uuid = foundry.utils.parseUuid(data.uuid) const itemId = uuid.id; const actorId = uuid.primaryId; const item = await game.actors.get(actorId).items.get(itemId); // Create the macro command const command = `game.DSA41.rollItemMacro("${data.uuid}");`; const macro = await Macro.create({ name: item.name, type: "script", img: item.img, command: command, flags: {"dsa41.skillMacro": true} }); game.user.assignHotbarMacro(macro, slot); return false; } function rollItemMacro(_uuid) { const speaker = ChatMessage.getSpeaker(); const uuid = foundry.utils.parseUuid(_uuid) const itemId = uuid.id; const actorId = uuid.primaryId; let actor = game.actors.get(actorId); const item = actor ? actor.items.get(itemId) : null; if (!item) return ui.notifications.warn(`Your controlled Actor does not have an item with id ${itemId}`); return item.system.roll(); }