diff --git a/gulpfile.ts b/gulpfile.ts index 73b2ee5..682b2c9 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -473,8 +473,8 @@ const updateManifest = (cb: any) => { const result = `${repoURL}/releases/download`; manifest.file.url = repoURL; - manifest.file.manifest = `${result}/v${manifest.file.version}/${manifest.name}`; - manifest.file.download = `${result}/v${manifest.file.version}/${manifest.file.name}-v${manifest.file.version}.zip`; + manifest.file.manifest = `${result}/latest/${manifest.name}?token=2455375115b92bc8d87c93df7159eec232456f2d`; + manifest.file.download = `${result}/v${manifest.file.version}/${manifest.file.name}-v${manifest.file.version}.zip?token=2455375115b92bc8d87c93df7159eec232456f2d`; const prettyProjectJson = stringify(manifest.file, { maxLength: 35, @@ -504,7 +504,7 @@ const gitTaskBuild = (cb: gulp.TaskFunctionCallback) => { if (!manifest) return cb(Error("could not load manifest.")); return gulp - .src(`${manifest.file.name}-v${manifest.file.version}.zip`) + .src(`${manifest.file.name}.zip`) .pipe(git.checkout(`v${manifest.file.version}`, { args: "-b" })) .pipe(git.add({ args: "--no-all -f" })) .pipe(git.commit(`v${manifest.file.version}`, { args: "-a", disableAppendPaths: true })); diff --git a/lang/de.json b/lang/de.json index c6cc2eb..4a7f4af 100644 --- a/lang/de.json +++ b/lang/de.json @@ -1,6 +1,6 @@ { "TYPES.Actor.character": "Charakter", - "ACTOR.TypeNpc": "Kreatur / Nichtspielerfigur", + "TYPES.Actor.npc": "Kreatur / Nichtspielerfigur", "ACTOR.TypeVehicle": "Transportmittel / Pferd etc.", "TYPES.Item.item": "Gegenstand", @@ -61,6 +61,8 @@ "item-ismagic": "Ist Magisch", "item-wealth": "Vermögenswert", "item-weight": "Gewicht", + "item-abw": "ABW", + "item-abw-long": "Ausbrennwahrscheinlichkeit", "actor-lp": "Lebenspunkte", "actor-lp-short": "LP", @@ -133,7 +135,7 @@ "heavy-load": "Schwere Last", "thrust-load": "Schublast", "load-max": "Höchstlast", - "load-capacity": "Tragkraft", + "capacity": "Tragkraft", "exp-overall": "Erfahrungsschatz", "exp-available": "Erfahrungspunkte", @@ -281,6 +283,7 @@ "rangedWeapon": "Schusswaffe", "assignItemToCharacter": "Füge Gegenstand einem Charakter hinzu, um hier etwas auswählen zu können", "showAll": "Alle anzeigen", + "showUnlearned": "Ungelernte Fertigkeiten", "wealthAndWeight": "Vermögen und Lasten", "itemsInContainers": "Gegenstände in Aufbewahrung", "allItems": "Alle Gegenstände", @@ -356,12 +359,13 @@ "spell-agens": "Agens", "spell-reagens": "Reagens", "spell-material": "Zaubermaterial", + "spell-rank": "Stufe", "kampfkunst-type": "Form", "kampfkunst-variante": "Variante", "kampfkunst-variante-short": "Var", "kampfkunst-ep": "Erfahrungspunkte", - "kampfkunst-rank": "Stufe", + "kampfkunst-rank": "Stufe der Technik", "kampfkunst-weapon": "Waffengruppe", "kampfkunst-enemy": "Einschränkungen durch Art der Gegner", @@ -385,6 +389,10 @@ "kido-variante": "KiDo Variante", "kido-color": "Kampfstilfarbe", "kido-style": "Art der Technik", + "kido-rank": "Stufe der Technik", + "kido-grade": "Ausbildungsgrad", + "kido-enemy": "Einschränkungen durch Art der Gegner", + "kido-weapon": "Waffengruppe", "kido-type-angriff": "Kido Angriff", "kido-type-verteidigung": "Kido Verteidigung", @@ -399,6 +407,7 @@ "kido-variante-blockieren": "Blockieren", "kido-variante-bewegen": "Bewegen", "kido-variante-kontrollieren": "Kontrollieren", + "kido-variante-finte": "Finte", "mod-operation-add100": "Addieren (max 100)", "mod-operation-roll": "Wurf Modifikation", @@ -444,9 +453,9 @@ "reroll": "Neuwürfeln", "options": { - "modifier": "Modifikator", - "difficulty": "Schwellenwert", - "rollMode": "Würfel Modus" + "modifier": "Wurfmodifikator", + "difficulty": "Erfolg", + "rollMode": "Würfelmodus" } } } diff --git a/package.json b/package.json index b3dc8bc..3b9273f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "foundry-system-midgard5", - "version": "2.6.0", + "version": "2.7.0", "description": "", "main": "index.js", "scripts": { @@ -58,4 +58,4 @@ "dependencies": { "handlebars-helpers": "^0.10.0" } -} \ No newline at end of file +} diff --git a/source/PreloadTemplates.ts b/source/PreloadTemplates.ts index b2f2d19..a126db5 100644 --- a/source/PreloadTemplates.ts +++ b/source/PreloadTemplates.ts @@ -15,6 +15,11 @@ const preloadTemplates = async (): Promise[]> = "sheets/character/spells.hbs", "sheets/character/combat.hbs", "sheets/character/effects.hbs", + "sheets/npc/main.hbs", + "sheets/npc/combat.hbs", + "sheets/npc/properties.hbs", + "sheets/npc/description.hbs", + "sheets/npc/attribute.hbs", "sheets/partial/mod.hbs", "sheets/item/rolls.hbs", "chat/roll-m5.hbs", diff --git a/source/module/M5Base.ts b/source/module/M5Base.ts index e890123..fdc1b26 100644 --- a/source/module/M5Base.ts +++ b/source/module/M5Base.ts @@ -162,6 +162,7 @@ export interface M5AttributeCalculated extends M5ModResult { export interface M5CharacterCalculatedData { level: number; + movement: number; attributes: { st: M5AttributeCalculated; gs: M5AttributeCalculated; diff --git a/source/module/actors/M5Character.ts b/source/module/actors/M5Character.ts index 3f83d15..9f1f863 100644 --- a/source/module/actors/M5Character.ts +++ b/source/module/actors/M5Character.ts @@ -152,6 +152,7 @@ export class M5Character extends Actor { ret.level = M5Character.levelFromExp(data.info.race === "Zwerg" ? Math.min(data.calc.stats?.hoard * 2 || 0, data.es) : data.es); + //Set all values that are not dependent on another Value ret.attributes.st.value = M5Character.attributeMinMax(data.attributes.st); // TODO item effects ret.attributes.gs.value = M5Character.attributeMinMax(data.attributes.gs); ret.attributes.gw.value = M5Character.attributeMinMax(data.attributes.gw); @@ -176,29 +177,11 @@ export class M5Character extends Actor { ret.stats.ap = this.modResult(data.ap); ret.stats.lpProtection = this.modResult(0); ret.stats.apProtection = this.modResult(0); - ret.stats.defense = this.modResult(M5Character.defenseFromLevel(ret.level)); - ret.stats.damageBonus = this.modResult(Math.floor(ret.attributes.st.value / 20) + Math.floor(ret.attributes.gs.value / 30) - 3); - ret.stats.attackBonus = this.modResult(ret.attributes.gs.bonus); - ret.stats.defenseBonus = this.modResult(ret.attributes.gw.bonus); ret.stats.movement = this.modResult(data.movement); - ret.stats.resistanceMind = this.modResult(ret.stats.defense.value + (data.info.race === "Mensch" ? ret.attributes.in.bonus : this.raceBonus(data.info.race))); - ret.stats.resistanceBody = this.modResult(ret.stats.defense.value + (data.info.race === "Mensch" ? ret.attributes.ko.bonus : this.raceBonus(data.info.race))); - ret.stats.spellCasting = this.modResult((data.info.magicUsing ? M5Character.spellCastingFromLevel(ret.level) : 3) + ret.attributes.zt.bonus); - ret.stats.brawl = this.modResult(Math.floor((ret.attributes.st.value + ret.attributes.gw.value) / 20)); - ret.stats.brawlFw = ret.stats.brawl.value + ret.stats.attackBonus.value + (data.info.race === "Zwerg" ? 1 : 0); - ret.stats.poisonResistance = this.modResult(30 + Math.floor(ret.attributes.ko.value / 2)); - ret.stats.enduranceBonus = Math.floor(ret.attributes.ko.value / 10) + Math.floor(ret.attributes.st.value / 20); - ret.stats.deprivationCold = this.modResult(Math.floor(ret.attributes.ko.value / 2)); - ret.stats.deprivationHeat = this.modResult(Math.floor(ret.attributes.ko.value / 2)); - ret.stats.deprivationFood = this.modResult(Math.floor(40 + ret.attributes.ko.value / 2)); ret.stats.hoardMin = M5Character.levelThreshold.at(ret.level - 1) / 2; ret.stats.hoardNext = M5Character.levelThreshold.at(ret.level) / 2; ret.stats.wealth = parseFloat((data.info.gold + data.info.silver / 10 + data.info.copper / 100).toPrecision(3)); ret.stats.hoard = 0; - ret.stats.load = M5Character.loadValue(data.attributes.st); - ret.stats.heavyLoad = M5Character.heavyLoadValue(data.attributes.st); - ret.stats.loadMax = M5Character.maxLoadValue(data.attributes.st); - ret.stats.thrustLoad = M5Character.thrustLoadValue(data.attributes.st); ret.stats.encumbrance = 0; if (!skip?.mods) { @@ -221,6 +204,25 @@ export class M5Character extends Actor { ret.skillMods = aggregate.calculate(); } + ret.stats.defense = this.modResult(M5Character.defenseFromLevel(ret.level)); + ret.stats.damageBonus = this.modResult(Math.floor(ret.attributes.st.value / 20) + Math.floor(ret.attributes.gs.value / 30) - 3); + ret.stats.attackBonus = this.modResult(ret.attributes.gs.bonus); + ret.stats.defenseBonus = this.modResult(ret.attributes.gw.bonus); + ret.stats.resistanceMind = this.modResult(ret.stats.defense.value + (data.info.race === "Mensch" ? ret.attributes.in.bonus : this.raceBonus(data.info.race))); + ret.stats.resistanceBody = this.modResult(ret.stats.defense.value + (data.info.race === "Mensch" ? ret.attributes.ko.bonus : this.raceBonus(data.info.race))); + ret.stats.spellCasting = this.modResult((data.info.magicUsing ? M5Character.spellCastingFromLevel(ret.level) : 3) + ret.attributes.zt.bonus); + ret.stats.brawl = this.modResult(Math.floor((ret.attributes.st.value + ret.attributes.gw.value) / 20)); + ret.stats.brawlFw = ret.stats.brawl.value + ret.stats.attackBonus.value + (data.info.race === "Zwerg" ? 1 : 0); + ret.stats.poisonResistance = this.modResult(30 + Math.floor(ret.attributes.ko.value / 2)); + ret.stats.enduranceBonus = Math.floor(ret.attributes.ko.value / 10) + Math.floor(ret.attributes.st.value / 20); + ret.stats.deprivationCold = this.modResult(Math.floor(ret.attributes.ko.value / 2)); + ret.stats.deprivationHeat = this.modResult(Math.floor(ret.attributes.ko.value / 2)); + ret.stats.deprivationFood = this.modResult(Math.floor(40 + ret.attributes.ko.value / 2)); + ret.stats.load = M5Character.loadValue(data.attributes.st); + ret.stats.heavyLoad = M5Character.heavyLoadValue(data.attributes.st); + ret.stats.loadMax = M5Character.maxLoadValue(data.attributes.st); + ret.stats.thrustLoad = M5Character.thrustLoadValue(data.attributes.st); + if (!skip?.containers) { context.items ?.filter((item) => item.type === "container") @@ -280,6 +282,7 @@ export class M5Character extends Actor { if (!!item.system.containerId) { ret.gear.containers[item.system.containerId].weight += parseFloat((item.system.weight * item.system.quantity).toPrecision(4)); + ret.gear.containers[item.system.containerId].value += parseFloat(this.calculateValue(item.system.value * item.system.quantity, item.system.currency).toPrecision(3)); if (ret.gear.containers[item.system.containerId].equipped) { ret.stats.encumbrance += item.system.weight * item.system.quantity; } @@ -302,6 +305,7 @@ export class M5Character extends Actor { label: label, icon: icon, magic: item.system.magic, + abw: item.system.abw || 0, calc: item.system.calc, equipped: item.system?.equipped, valuable: item.system?.valuable, @@ -352,6 +356,7 @@ export class M5Character extends Actor { icon: item.img, skillId: item.system.skillId, magic: item.system.magic, + abw: item.system.abw || 0, valuable: item.system?.valuable, hoarded: item.system?.hoarded, value: item.system.value || 0, @@ -395,6 +400,7 @@ export class M5Character extends Actor { icon: item.img, skillId: item.system.skillId, magic: item.system.magic, + abw: item.system.abw || 0, valuable: item.system?.valuable, hoarded: item.system?.hoarded, value: item.system.value || 0, @@ -438,6 +444,7 @@ export class M5Character extends Actor { label: label, icon: item.img, magic: item.system.magic, + abw: item.system.abw || 0, valuable: item.system?.valuable, hoarded: item.system?.hoarded, value: item.system.value || 0, diff --git a/source/module/items/M5Item.ts b/source/module/items/M5Item.ts index 24b7c3f..183e70d 100644 --- a/source/module/items/M5Item.ts +++ b/source/module/items/M5Item.ts @@ -314,7 +314,7 @@ export class M5Item extends Item { return ret; } - async roll() { + async roll(toggleAutomatedRoll = false) { const item = this as any; // Initialize chat data. @@ -341,14 +341,20 @@ export class M5Item extends Item { } }); - if (item.type === "spell" || item.type === "kampfkunst") { - if (this.actor["system"].ap.value >= item.system.ap) { - this.actor["system"].ap.value -= item.system.ap; + const roll = new M5Roll(rollData, this.actor, item.name, item.id); + if (await roll.toMessage(toggleAutomatedRoll)) { + if (item.type === "spell" || item.type === "kampfkunst") { + if (this.actor["system"].ap.value >= item.system.ap) { + this.actor["update"]({ + data: { + ap: { + value: this.actor["system"].ap.value - item.system.ap, + }, + }, + }); + } } } - - const roll = new M5Roll(rollData, this.actor, item.name, item.id); - return roll.toMessage(); } else { ChatMessage.create({ speaker: speaker, diff --git a/source/module/rolls/M5Roll.ts b/source/module/rolls/M5Roll.ts index 81f49fb..5e296a9 100644 --- a/source/module/rolls/M5Roll.ts +++ b/source/module/rolls/M5Roll.ts @@ -11,7 +11,12 @@ export class M5Roll { public _total: number = 0; public pool: PoolTerm = null; - constructor(public data: M5RollData, public actor: any, public label: string, public id?: string) { + constructor( + public data: M5RollData, + public actor: any, + public label: string, + public id?: string + ) { //super(null) //this.data = rollData } @@ -26,7 +31,7 @@ export class M5Roll { .map((rollName, index) => { indexMap.set(index, rollName); const formula = this.data.rolls[rollName]; - formula.formula = index === 0 && this.id !== "-1" ? formula.formula.replace(/(\d*d\d*)/, `{$1 + ${this.data.b.modifier}}`) : formula.formula; + formula.formula = index === 0 && this.id !== "-1" ? formula.formula + `+ ${this.data.b.modifier}` : formula.formula; const roll = new Roll(formula.formula, this.data); return roll; }); @@ -90,6 +95,7 @@ export class M5Roll { this.data.res.label = this.label; if ((game as Game).settings.get("midgard5", "automatedPP") && this.data.iType !== null) { if ((this.data.i.type === "language" || this.data.i.type === "general") && this.data.rolls[0].dice[0] >= 16) { + ui.notifications.notify(`Praxispunkt eingetragen für ${this.actor.items.get(this.id).name}`); this.actor.items.get(this.id).update({ system: { pp: this.data.i.pp + 1, @@ -97,6 +103,7 @@ export class M5Roll { }); } else if (this.data.rolls[0].dice[0] === 20) { if (this.data.i.type === "combat") { + ui.notifications.notify(`Praxispunkt eingetragen für ${this.actor.items.get(this.id).name}`); // Rolling through skill this.actor.items.get(this.id).update({ system: { @@ -104,6 +111,7 @@ export class M5Roll { }, }); } else if (this.data.iType === "weapon") { + ui.notifications.notify(`Praxispunkt eingetragen für ${this.actor.items.get(this.id).name}`); // Rolling through Weapon Item const skill = this.actor.items.get(this.data.i.skillId); skill.update({ @@ -112,6 +120,7 @@ export class M5Roll { }, }); } else if (this.data.iType === "defensiveWeapon") { + ui.notifications.notify(`Praxispunkt eingetragen für ${this.actor.items.get(this.id).name}`); // Rolling through defensiveWeapon Item const skill = this.actor.items.get(this.data.i.skillId); skill.update({ @@ -120,6 +129,7 @@ export class M5Roll { }, }); } else if (this.data.iType === "spell") { + ui.notifications.notify(`Praxispunkt eingetragen für ${this.data.i.process}`); // Rolling through Spell Item const klasse = this.actor.items.find((x) => x.type === "class" && x.system.equipped); klasse.update({ @@ -142,18 +152,26 @@ export class M5Roll { return renderTemplate(M5Roll.TEMPLATE_PATH, this.data); } - async toMessage() { - let checkOptions = await this.popUp({ isPW: this.data.rolls[0].label === (game as Game).i18n.localize("midgard5.pw") }); - if (checkOptions["cancelled"]) { - return; + async toMessage(toggleAutomatedRoll = false) { + let automatedRoll = (game as Game).settings.get("midgard5", "automatedRoll"); + automatedRoll = toggleAutomatedRoll ? !automatedRoll : automatedRoll; + const rMode = (game as Game).settings.get("core", "rollMode"); + + if (!automatedRoll) { + let checkOptions = await this.popUp({ isPW: this.data.rolls[0].label === (game as Game).i18n.localize("midgard5.pw") }); + if (checkOptions["cancelled"]) { + return; + } else { + const rMode = checkOptions["rollMode"]; + this.data.b = checkOptions; + } } else { - this.data.b = checkOptions; + this.data.b = { difficulty: 20, modifier: 0 }; } if (!this._evaluated) await this.evaluate(); const faces = this.pool.dice.map((x) => x.faces); - const rMode = checkOptions["rollMode"] || (game as Game).settings.get("core", "rollMode"); const chatData = { type: CONST.CHAT_MESSAGE_TYPES.ROLL, content: await this.render(), diff --git a/source/module/sheets/M5CharacterSheet.ts b/source/module/sheets/M5CharacterSheet.ts index 01b8b5b..6160ad0 100644 --- a/source/module/sheets/M5CharacterSheet.ts +++ b/source/module/sheets/M5CharacterSheet.ts @@ -7,7 +7,6 @@ import { M5Roll } from "../rolls/M5Roll"; export default class M5CharacterSheet extends ActorSheet { static get defaultOptions() { return mergeObject(super.defaultOptions, { - template: "systems/midgard5/templates/sheets/character/main.hbs", width: 1000, height: 800, classes: ["midgard5", "sheet", "character"], @@ -21,7 +20,15 @@ export default class M5CharacterSheet extends ActorSheet { }); } - // get template() { + get template() { + //console.log("M5CharacterSheet", this.actor.data.type) + if (this.actor.type === "npc") { + return "systems/midgard5/templates/sheets/npc/main.hbs"; + } + else { + return "systems/midgard5/templates/sheets/character/main.hbs"; + } + } // return "systems/midgard5/templates/character_sheet/main.hbs" // }Options extends ActorSheet.Options = ActorSheet.Options, Data extends object = ActorSheet.Data @@ -78,7 +85,8 @@ export default class M5CharacterSheet extends ActorSheet { let attributeValue = target ? parseInt(target.dataset.value) : null; let attributeStr = target ? target.dataset.attribute : null; const roll = M5Roll.fromAttributeValue(this.actor, attributeStr, attributeValue); - await roll.toMessage(); + let toggleAutomatedRoll = (event.shiftKey) + await roll.toMessage(toggleAutomatedRoll); }); html.find(".edit-item").on("click", async (event) => { @@ -138,7 +146,8 @@ export default class M5CharacterSheet extends ActorSheet { }); } - await item.roll(); + let toggleAutomatedRoll = (event.shiftKey) + await item.roll(toggleAutomatedRoll); this.render(); }); @@ -158,7 +167,8 @@ export default class M5CharacterSheet extends ActorSheet { const actor = this.actor as any; const item = actor.items.get(skillId) as M5Item; - await item.roll(); + let toggleAutomatedRoll = (event.shiftKey) + await item.roll(toggleAutomatedRoll); }); html.find(".roll-general-button").on("click", async (event) => { @@ -169,7 +179,8 @@ export default class M5CharacterSheet extends ActorSheet { const unlearnedSkill = data.skills.general[skillName] as M5SkillUnlearned; const roll = M5Roll.fromUnlearnedSkill(this.actor, unlearnedSkill, skillName); - await roll.toMessage(); + let toggleAutomatedRoll = (event.shiftKey) + await roll.toMessage(toggleAutomatedRoll); }); html.find(".learn-button").on("click", async (event) => { @@ -267,48 +278,57 @@ export default class M5CharacterSheet extends ActorSheet { const context = this.actor as any; const item = context.items.get(itemId) as M5Item; - await item.roll(); + let toggleAutomatedRoll = (event.shiftKey) + await item.roll(toggleAutomatedRoll); this.render(); }); html.find(".roll-brawl-button").on("click", async (event) => { const roll = M5Roll.brawl(this.actor); - await roll.toMessage(); + let toggleAutomatedRoll = (event.shiftKey) + await roll.toMessage(toggleAutomatedRoll); }); html.find(".roll-cleanSpell-button").on("click", async (event) => { const roll = M5Roll.cleanSpell(this.actor); - await roll.toMessage(); + let toggleAutomatedRoll = (event.shiftKey) + await roll.toMessage(toggleAutomatedRoll); }); html.find(".roll-deprivationCold-button").on("click", async (event) => { const roll = M5Roll.deprivationCold(this.actor); - await roll.toMessage(); + let toggleAutomatedRoll = (event.shiftKey) + await roll.toMessage(toggleAutomatedRoll); }); html.find(".roll-deprivationHeat-button").on("click", async (event) => { const roll = M5Roll.deprivationHeat(this.actor); - await roll.toMessage(); + let toggleAutomatedRoll = (event.shiftKey) + await roll.toMessage(toggleAutomatedRoll); }); html.find(".roll-deprivationFood-button").on("click", async (event) => { const roll = M5Roll.deprivationFood(this.actor); - await roll.toMessage(); + let toggleAutomatedRoll = (event.shiftKey) + await roll.toMessage(toggleAutomatedRoll); }); html.find(".roll-defense-button").on("click", async (event) => { const roll = M5Roll.defense(this.actor); - await roll.toMessage(); + let toggleAutomatedRoll = (event.shiftKey) + await roll.toMessage(toggleAutomatedRoll); }); html.find(".roll-resistanceMind-button").on("click", async (event) => { const roll = M5Roll.resistanceMind(this.actor); - await roll.toMessage(); + let toggleAutomatedRoll = (event.shiftKey) + await roll.toMessage(toggleAutomatedRoll); }); html.find(".roll-resistanceBody-button").on("click", async (event) => { const roll = M5Roll.resistanceBody(this.actor); - await roll.toMessage(); + let toggleAutomatedRoll = (event.shiftKey) + await roll.toMessage(toggleAutomatedRoll); }); html.find(".change-equipped").on("click", async (event) => { @@ -526,7 +546,11 @@ export default class M5CharacterSheet extends ActorSheet { let data = null; try { data = JSON.parse(event.dataTransfer.getData("text/plain")); - data.data.system.containerId = ""; //Clean containerId + console.log("Data", data.data); + let target = event.target.closest("[data-container-id]") as HTMLElement; + let containerId = target ? target.dataset.containerId : ""; + console.log("Container ID", containerId); + data.data.system.containerId = containerId; //Update containerId if (data.type !== "Transfer") return false; } catch (err) { return false; @@ -535,6 +559,14 @@ export default class M5CharacterSheet extends ActorSheet { if (!data.data) return false; if (data.actorId === this.actor.id) { + let itemId=data.data._id; + const context = this.actor as any; + const item = context.items.get(itemId); + item.update({ + data: { + containerId: data.data.system.containerId, + }, + }); return this._onSortItem(event, data.data); } diff --git a/source/settings.ts b/source/settings.ts index d9ba705..8705f00 100644 --- a/source/settings.ts +++ b/source/settings.ts @@ -13,4 +13,13 @@ export const loadSettings = async function () { default: true, type: Boolean, }); + (game as Game).settings.register("midgard5", "automatedRoll", { + name: "Automatische Würfelwürfe", + hint: "Falls aktiv, wird bei Würfelwürfen kein Dialog gezeigt. Das Verhalten kann mit gleichzeitig gedrückter Shift Taste umgekehrt werden.", + scope: "world", + config: true, + default: false, + type: Boolean, + }); + }; diff --git a/source/style/npc-sheet.less b/source/style/npc-sheet.less new file mode 100644 index 0000000..408202f --- /dev/null +++ b/source/style/npc-sheet.less @@ -0,0 +1,23 @@ +// main: midgard5.less +@borderGroove: 2px groove #eeede0; +@attributeBorderColor: rgba(0, 0, 0, 0.5); + +.midgard5 { + .sheet-npc { + .attribute-header { + align-items: center; + text-align: center; + font-weight: bold; + border: 0px solid transparent; + } + .attribute-value { + align-items: center; + text-align: center; + border: 0px solid transparent; + } + .fixed-value { + width: 3rem; + text-align: center; + } + } +} \ No newline at end of file diff --git a/source/system.json b/source/system.json index dc58156..38e8a11 100644 --- a/source/system.json +++ b/source/system.json @@ -3,7 +3,7 @@ "name": "midgard5", "title": "Midgard 5. Edition", "description": "The German RPG Midgard 5. Edition", - "version": "2.6.0", + "version": "2.7.0", "compatibility": { "minimum": "10", "verified": "11", @@ -24,8 +24,8 @@ "primaryTokenAttribute": "lp", "secondaryTokenAttribute": "ap", "url": "https://git.byroks.de/MidgardVTT-Entwicklung/foundry-vtt-system-midgard5", - "manifest": "https://git.byroks.de/MidgardVTT-Entwicklung/foundry-vtt-system-midgard5/releases/download/v2.6.0/system.json", - "download": "https://git.byroks.de/MidgardVTT-Entwicklung/foundry-vtt-system-midgard5/releases/download/v2.6.0/midgard5-v2.6.0.zip", + "manifest": "https://git.byroks.de/MidgardVTT-Entwicklung/foundry-vtt-system-midgard5/releases/download/latest/system.json?token=2455375115b92bc8d87c93df7159eec232456f2d", + "download": "https://git.byroks.de/MidgardVTT-Entwicklung/foundry-vtt-system-midgard5/releases/download/latest/midgard5.zip?token=2455375115b92bc8d87c93df7159eec232456f2d", "initiative": "@c.calc.attributes.gw.value", "license": "LICENSE.txt" } diff --git a/source/template.json b/source/template.json index ba41359..b337148 100644 --- a/source/template.json +++ b/source/template.json @@ -1,15 +1,18 @@ { "Actor": { - "types": ["character"], + "types": [ + "character", + "npc" + ], "templates": { "characterDescription": { "info": { "description": "", "background": "", "class": {}, + "npc-class": "", "race": "", "magicUsing": false, - "showAllItems": false, "gender": "", "weight": "", "height": "", @@ -19,9 +22,12 @@ "occupation": "", "origin": "", "faith": "", + "level": 1, "gold": 0, "silver": 0, - "copper": 0 + "copper": 0, + "showAllItems": false, + "showUnlearned": false } }, "characterBars": { @@ -44,6 +50,8 @@ "gp": 0 }, "attributes": { + "level": 1, + "movement": 24, "attributes": { "st": { "value": 50, "bonus": 0 }, "gs": { "value": 50, "bonus": 0 }, @@ -53,7 +61,8 @@ "zt": { "value": 50, "bonus": 0 }, "au": { "value": 50, "bonus": 0 }, "pa": { "value": 50, "bonus": 0 }, - "wk": { "value": 50, "bonus": 0 } + "wk": { "value": 50, "bonus": 0 }, + "git": { "value": 50, "bonus": 0 } } }, "skills": { @@ -156,6 +165,10 @@ "character": { "templates": ["characterBars", "attributes", "characterDescription", "characterHeader", "skills", "gear"], "calc": {} + }, + "npc": { + "templates": ["characterBars", "attributes", "characterDescription", "skills", "gear"], + "calc": {} } }, "Item": { @@ -224,7 +237,8 @@ "weight": 0, "capacity": 0, "containerId": "", - "magic": false + "magic": false, + "abw": 0 }, "durationSelection": { "durationSelection": { @@ -314,7 +328,8 @@ "ausweichen": "midgard5.kido-variante-ausweichen", "blockieren": "midgard5.kido-variante-blockieren", "bewegen": "midgard5.kido-variante-bewegen", - "kontrollieren": "midgard5.kido-variante-kontrollieren" + "kontrollieren": "midgard5.kido-variante-kontrollieren", + "finte": "midgard5.kido-variante-finte" } } }, @@ -374,6 +389,7 @@ "hoarded": false, "skillId": "", "damageBase": "1d6", + "ew": 5, "rolls": { "formulas": { "0": { @@ -438,6 +454,7 @@ "agens": "", "reagens": "", "material": "", + "rank": 0, "rolls": { "formulas": { "0": { @@ -459,10 +476,11 @@ "ap": "", "weapon": "", "ep": "", - "rank": "", + "rank": 0, "enemy": "", "color": "", "style": "", + "grade": "", "rolls": { "formulas": { "0": { diff --git a/templates/chat/roll-m5.hbs b/templates/chat/roll-m5.hbs index 9e516fd..ccbbb64 100644 --- a/templates/chat/roll-m5.hbs +++ b/templates/chat/roll-m5.hbs @@ -94,31 +94,29 @@ {{i.ep}} - {{localize "midgard5.kampfkunst-color"}} + {{localize "midgard5.kido-color"}} {{i.color}} - {{localize "midgard5.kampfkunst-style"}} + {{localize "midgard5.kido-style"}} {{i.style}} {{localize "midgard5.kido-type"}} {{localize (m5concat "midgard5.kido-type-" i.type)}} - {{#if (eq i.type "angriff")}} {{localize "midgard5.kido-variante"}} {{localize (m5concat "midgard5.kido-variante-" i.variante)}} - {{localize "midgard5.kampfkunst-enemy"}} + {{localize "midgard5.kido-enemy"}} {{i.enemy}} - {{localize "midgard5.kampfkunst-weapon"}} + {{localize "midgard5.kido-weapon"}} {{i.weapon}} - {{/if}} {{/unless}} {{/if}} diff --git a/templates/sheets/character/base_values.hbs b/templates/sheets/character/base_values.hbs index 20b25b7..e4ecbc7 100644 --- a/templates/sheets/character/base_values.hbs +++ b/templates/sheets/character/base_values.hbs @@ -35,7 +35,7 @@ {{localize "midgard5.grace"}} {{localize "midgard5.exp-overall"}} - + {{localize "midgard5.destiny"}} diff --git a/templates/sheets/character/gear.hbs b/templates/sheets/character/gear.hbs index 79efc09..ec53822 100644 --- a/templates/sheets/character/gear.hbs +++ b/templates/sheets/character/gear.hbs @@ -63,7 +63,7 @@

{{localize "midgard5.itemsInContainers"}}

{{#each data.calc.gear.containers as |container containerId|}} -
+
{{container.label}}
@@ -234,7 +234,7 @@ - @@ -251,13 +251,13 @@ {{/unless}} - @@ -345,7 +345,7 @@ - @@ -392,7 +392,7 @@ - @@ -438,7 +438,7 @@ - diff --git a/templates/sheets/character/main.hbs b/templates/sheets/character/main.hbs index d5cef81..27af546 100644 --- a/templates/sheets/character/main.hbs +++ b/templates/sheets/character/main.hbs @@ -49,18 +49,6 @@
{{localize "midgard5.capacity"}} +
- {{#unless (or (eq item.weight "") (eq item.equipped?))}} - {{item.weight}} kg + {{#unless (or (eq item.weight 0) (eq item.equipped?))}} + {{item.weight}}kg {{/unless}} - {{#unless (eq item.capacity "")}} - {{item.capacity}} kg + {{#unless (eq item.capacity 0)}} + {{item.capacity}}kg {{/unless}} @@ -289,7 +289,7 @@ {{localize "midgard5.item-weight"}} +
{{localize "midgard5.item-value"}} {{localize "midgard5.item-weight"}} +
{{localize "midgard5.item-value"}} {{localize "midgard5.item-weight"}} +
{{localize "midgard5.item-value"}} {{localize "midgard5.item-weight"}} +
- - - - - - - - - - - - @@ -73,6 +61,18 @@ + + + + + + + + + + + +
{{localize "midgard5.actor-st"}}{{localize "midgard5.actor-gs"}}{{localize "midgard5.actor-gw"}}{{localize "midgard5.actor-ko"}}{{localize "midgard5.actor-in"}}{{localize "midgard5.actor-zt"}}{{localize "midgard5.actor-au"}}{{localize "midgard5.actor-pa"}}{{localize "midgard5.actor-wk"}}{{localize "midgard5.actor-git"}}
{{data.calc.attributes.st.value}} {{data.calc.attributes.gs.value}}{{data.calc.attributes.wk.value}} {{data.calc.stats.poisonResistance.value}}
{{localize "midgard5.actor-st"}}{{localize "midgard5.actor-gs"}}{{localize "midgard5.actor-gw"}}{{localize "midgard5.actor-ko"}}{{localize "midgard5.actor-in"}}{{localize "midgard5.actor-zt"}}{{localize "midgard5.actor-au"}}{{localize "midgard5.actor-pa"}}{{localize "midgard5.actor-wk"}}{{localize "midgard5.actor-git"}}
diff --git a/templates/sheets/character/skills.hbs b/templates/sheets/character/skills.hbs index cbebdde..2fa832d 100644 --- a/templates/sheets/character/skills.hbs +++ b/templates/sheets/character/skills.hbs @@ -142,6 +142,8 @@
{{localize "midgard5.unlearned-skills"}}
+ + @@ -154,6 +156,7 @@ + {{#unless (not data.info.showUnlearned)}} {{#each data.skills.general as |skill key|}} {{#unless (isSkillInList (localizeMidgard key) ../actor.system.calc.skills.general) }} @@ -166,6 +169,7 @@ {{/unless}} {{/each}} + {{/unless}}
diff --git a/templates/sheets/character/spells.hbs b/templates/sheets/character/spells.hbs index 6884d0a..063ee45 100644 --- a/templates/sheets/character/spells.hbs +++ b/templates/sheets/character/spells.hbs @@ -87,6 +87,7 @@
{{#each data.lernKostenZauber as |group name|}} + {{#unless (eq group.kosten 0)}} @@ -95,6 +96,7 @@ + {{/unless}} {{/each}}
diff --git a/templates/sheets/item/armor.hbs b/templates/sheets/item/armor.hbs index 6826f32..40bf142 100644 --- a/templates/sheets/item/armor.hbs +++ b/templates/sheets/item/armor.hbs @@ -51,9 +51,15 @@
{{localize "midgard5.item-weight"}} - +
+ +
+ {{localize "midgard5.item-abw"}} + +
+ diff --git a/templates/sheets/item/container.hbs b/templates/sheets/item/container.hbs index 13c1a87..78c1458 100644 --- a/templates/sheets/item/container.hbs +++ b/templates/sheets/item/container.hbs @@ -18,6 +18,12 @@
+ +
+ {{localize "midgard5.item-abw"}} + +
+ diff --git a/templates/sheets/item/defensiveWeapon.hbs b/templates/sheets/item/defensiveWeapon.hbs index 26ad39d..9de5a35 100644 --- a/templates/sheets/item/defensiveWeapon.hbs +++ b/templates/sheets/item/defensiveWeapon.hbs @@ -55,9 +55,15 @@
{{localize "midgard5.item-weight"}} - +
+ +
+ {{localize "midgard5.item-abw"}} + +
+ diff --git a/templates/sheets/item/item.hbs b/templates/sheets/item/item.hbs index 1509b7d..e64b2db 100644 --- a/templates/sheets/item/item.hbs +++ b/templates/sheets/item/item.hbs @@ -37,8 +37,6 @@
- -
{{localize "midgard5.item-value"}} @@ -53,6 +51,18 @@
+ +
+ {{localize "midgard5.item-weight"}} + +
+ + +
+ {{localize "midgard5.item-abw"}} + +
+ @@ -73,12 +83,6 @@ {{/if}}
- -
- {{localize "midgard5.item-weight"}} - -
- diff --git a/templates/sheets/item/kampfkunst.hbs b/templates/sheets/item/kampfkunst.hbs index 962dd93..d50e049 100644 --- a/templates/sheets/item/kampfkunst.hbs +++ b/templates/sheets/item/kampfkunst.hbs @@ -25,8 +25,10 @@ {{localize "midgard5.kampfkunst-ep"}} + {{#unless item.system.isKido}} {{localize "midgard5.kampfkunst-rank"}} - + + {{/unless}} {{localize "midgard5.kampfkunst-weapon"}} @@ -83,6 +85,20 @@ {{/unless}} {{/unless}} + {{#if item.system.isKido}} + + {{localize "midgard5.kido-color"}} + + {{localize "midgard5.kido-style"}} + + + + {{localize "midgard5.kido-grade"}} + + {{localize "midgard5.kido-rank"}} + + + {{/if}} {{localize "midgard5.skill"}} diff --git a/templates/sheets/item/weapon.hbs b/templates/sheets/item/weapon.hbs index b1c2f79..dcda116 100644 --- a/templates/sheets/item/weapon.hbs +++ b/templates/sheets/item/weapon.hbs @@ -60,9 +60,15 @@
{{localize "midgard5.item-weight"}} - +
+ +
+ {{localize "midgard5.item-abw"}} + +
+ diff --git a/templates/sheets/npc/attribute.hbs b/templates/sheets/npc/attribute.hbs new file mode 100644 index 0000000..6d6f4e6 --- /dev/null +++ b/templates/sheets/npc/attribute.hbs @@ -0,0 +1,4 @@ +
+
{{localize (m5concat "midgard5.actor-" attributeId "-long")}}
+
+
\ No newline at end of file diff --git a/templates/sheets/npc/combat.hbs b/templates/sheets/npc/combat.hbs new file mode 100644 index 0000000..91164f5 --- /dev/null +++ b/templates/sheets/npc/combat.hbs @@ -0,0 +1,233 @@ + +
+ +
+
+
{{localize "midgard5.calculated-values"}}
+ + + + + + + + + + + + + + +
{{localize "midgard5.movementRange"}}{{data.calc.stats.movement.value}}
{{localize "midgard5.initiative"}} + {{#if (isSkillInList (localizeMidgard "anfuehren") data.calc.skills.general)}} + {{skillEwInList (localizeMidgard "anfuehren") data.calc.skills.general}} + {{else}} + {{skillEw actor._id data.skills.general.anfuehren}} + {{/if}} + {{localize "midgard5.actionrank"}}{{data.calc.attributes.gw.value}}
+
+
+ +
+
+
{{localize "midgard5.actionrank"}}
+ + + +
+
+ +
+
+
{{localize "TYPES.Item.effect"}}
+ + + + + + + + + {{#each data.calc.gear.effects as |item itemId|}} + + + + {{!--{{#unless (eq item.label "Belastung")}}--}} + + {{!--{{/unless}}--}} + + {{/each}} + +
{{localize "TYPES.Item.effect"}} + +
+ {{item.label}} + {{#if item.equipped}} + {{localize "midgard5.active"}} + {{#unless (or (eq item.duration.unit "") (eq item.duration.unit "limitless"))}} + {{item.duration.time}} {{localize (concat "midgard5.time-" item.duration.unit)}} + {{/unless}} + {{/if}} +
+
+
+ + +
+
+
{{localize "midgard5.attack"}}
+ + + + + + + + + + + + {{#each data.calc.gear.weapons as |item itemId|}} + + + + + + + + + {{/each}} + +
{{localize "TYPES.Item.weapon"}}{{localize "midgard5.ew"}}{{localize "midgard5.damage"}} +
{{item.label}}{{#if item.special}}(*){{/if}}{{item.calc.ew}}{{item.damageBase}}
+ + + + + + + + + + + + {{#each data.calc.skills.combat as |skill skillId|}} + + + + + + + + {{/each}} + +
{{localize "midgard5.weapon-skill"}}{{localize "midgard5.ew"}}
{{skill.label}}{{skill.calc.ew}}
+
+
+ +
+
+
{{localize "midgard5.defense"}}
+ + + + + + + + + + + + + + + + + + +
{{localize "midgard5.defense"}}{{add data.calc.stats.defense.value data.calc.stats.defenseBonus.value}}
{{localize "midgard5.resistanceMind"}}{{data.calc.stats.resistanceMind.value}}
{{localize "midgard5.resistanceBody"}}{{data.calc.stats.resistanceBody.value}}
+ + + + + + + + + + + + {{#each data.calc.gear.defensiveWeapons as |item itemId|}} + + + + + + + + {{/each}} + +
{{localize "TYPES.Item.defensiveWeapon"}}{{localize "midgard5.ew"}}
{{item.label}}{{item.calc.ew}}
+ + + + + + + + + + + + {{#each data.calc.gear.armor as |item itemId|}} + + + + + + + {{/each}} + +
{{localize "TYPES.Item.armor"}}{{localize "midgard5.actor-lp-short"}}
{{item.label}}{{lpProtection}}
+
+
+ + {{#if actor.system.info.magicUsing }} +
+
+
{{localize "TYPES.Item.spell"}}
+ + + + + + + +
{{localize "midgard5.spellCasting"}}{{data.calc.stats.spellCasting.value}}
+ + + + + + + + + + + + {{#each data.calc.spells as |item itemId|}} + + + + + + + + {{/each}} + +
{{localize "TYPES.Item.spell"}}{{localize "midgard5.ew"}}
{{item.label}}{{#if item.special}}(*){{/if}}{{item.calc.ew}}
+
+
+ {{/if}} +
diff --git a/templates/sheets/npc/description.hbs b/templates/sheets/npc/description.hbs new file mode 100644 index 0000000..d1b9e9f --- /dev/null +++ b/templates/sheets/npc/description.hbs @@ -0,0 +1,18 @@ +
+
+
+
{{localize "midgard5.description"}}
+
+
{{editor data.info.description target="data.info.description" button=true owner=owner editable=editable}}
+
+
+ +
+
+
{{localize "midgard5.background"}}
+
+
{{editor data.info.background target="data.info.background" button=true owner=owner editable=editable}}
+
+
+ +
\ No newline at end of file diff --git a/templates/sheets/npc/main.hbs b/templates/sheets/npc/main.hbs new file mode 100644 index 0000000..610f929 --- /dev/null +++ b/templates/sheets/npc/main.hbs @@ -0,0 +1,127 @@ +
+
+ + +
+ Midgard +
+ + +
+ + + + + + + + + + +
{{localize "midgard5.actor-name"}}
{{localize "midgard5.class"}}{{localize "midgard5.level"}}{{data.calc.level}}
+ + + + + + + + + + + +
{{localize "midgard5.race"}}{{localize "midgard5.occupation"}}
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
{{data.attributes.st.value}}{{data.attributes.gs.value}}{{data.attributes.gw.value}}{{data.attributes.ko.value}}{{data.attributes.in.value}}{{data.attributes.zt.value}}{{data.attributes.au.value}}{{data.attributes.pa.value}}{{data.attributes.wk.value}}{{data.attributes.git.value}}
{{localize "midgard5.actor-st"}}{{localize "midgard5.actor-gs"}}{{localize "midgard5.actor-gw"}}{{localize "midgard5.actor-ko"}}{{localize "midgard5.actor-in"}}{{localize "midgard5.actor-zt"}}{{localize "midgard5.actor-au"}}{{localize "midgard5.actor-pa"}}{{localize "midgard5.actor-wk"}}{{localize "midgard5.actor-git"}}
+
+ + +
+ +
+ + +
+ + + + + + + + + +
{{localize "midgard5.actor-lp-short"}} +
+ + {{#times data.lp.max}} + {{#if (lt this ../data.lp.value)}} +
+ {{else}} +
+ {{/if}} + {{/times}} +
{{data.lp.max}}
+
+
{{localize "midgard5.actor-ap-short"}} +
+ + {{#times data.ap.max}} + {{#if (lt this ../data.ap.value)}} +
+ {{else}} +
+ {{/if}} + {{/times}} +
{{data.ap.max}}
+
+
+
+
+ + {{!-- Character Sheet Navigation --}} + + +
+ +
+ {{> "systems/midgard5/templates/sheets/npc/combat.hbs"}} +
+
+ {{> "systems/midgard5/templates/sheets/npc/properties.hbs"}} +
+
+ {{> "systems/midgard5/templates/sheets/npc/description.hbs"}} +
+ +
+
\ No newline at end of file diff --git a/templates/sheets/npc/properties.hbs b/templates/sheets/npc/properties.hbs new file mode 100644 index 0000000..a7f11e3 --- /dev/null +++ b/templates/sheets/npc/properties.hbs @@ -0,0 +1,117 @@ +
+
+
{{localize "midgard5.attributes"}}
+
+
+ {{> "systems/midgard5/templates/sheets/npc/attribute.hbs" attributeId="st" attribute=data.attributes.st}} + {{> "systems/midgard5/templates/sheets/npc/attribute.hbs" attributeId="gs" attribute=data.attributes.gs}} + {{> "systems/midgard5/templates/sheets/npc/attribute.hbs" attributeId="gw" attribute=data.attributes.gw}} + {{> "systems/midgard5/templates/sheets/npc/attribute.hbs" attributeId="ko" attribute=data.attributes.ko}} + {{> "systems/midgard5/templates/sheets/npc/attribute.hbs" attributeId="in" attribute=data.attributes.in}} + {{> "systems/midgard5/templates/sheets/npc/attribute.hbs" attributeId="zt" attribute=data.attributes.zt}} + {{> "systems/midgard5/templates/sheets/npc/attribute.hbs" attributeId="au" attribute=data.attributes.au}} + {{> "systems/midgard5/templates/sheets/npc/attribute.hbs" attributeId="pa" attribute=data.attributes.pa}} + {{> "systems/midgard5/templates/sheets/npc/attribute.hbs" attributeId="wk" attribute=data.attributes.wk}} + {{> "systems/midgard5/templates/sheets/npc/attribute.hbs" attributeId="git" attribute=data.attributes.git}} +
+
{{localize "midgard5.movementRange"}}
+
+
+
+
{{localize "midgard5.exp-overall"}}
+
+
+
+
{{localize "midgard5.actor-lp-short"}} {{localize "midgard5.maximum"}}
+
+
+
+
{{localize "midgard5.actor-ap-short"}} {{localize "midgard5.maximum"}}
+
+
+
+
{{localize "midgard5.magicUsing"}}
+
+
+
+
+
+
+ +
+
{{localize "midgard5.skills"}}
+ + + + + + + + + + + + + {{#each data.calc.skills.general as |skill skillId|}} + + + + + + + {{/each}} + {{#unless (not data.info.showUnlearned)}} + {{#each data.skills.general as |skill key|}} + {{#unless (isSkillInList (localizeMidgard key) ../actor.system.calc.skills.general) }} + + + + + + + {{/unless}} + {{/each}} + {{/unless}} + +
{{localize "midgard5.skills"}}{{localize "midgard5.ew"}}
{{skill.label}}
{{localizeMidgard key}}
+
+
+
+
+
{{localize "midgard5.gear"}}
+ + + + + + + + + + + + {{#each data.calc.gear.items as |item itemId|}} + + + + + + + + {{/each}} + +
{{localize "TYPES.Item.item"}}{{localize "midgard5.item-quantity"}}{{localize "midgard5.item-value"}} +
+ {{item.label}} + + + {{item.quantity}} + + + {{#unless (or (eq item.value 0) (eq item.currency ""))}} + {{item.value}} {{localize (m5concat "midgard5.currency-" item.currency)}} + {{/unless}} +
+
+
+
\ No newline at end of file