Merge branch 'develop' into lasten

This commit is contained in:
2024-01-21 12:24:35 +01:00
34 changed files with 1244 additions and 670 deletions
+2 -1
View File
@@ -6,13 +6,14 @@ const preloadTemplates = async (): Promise<Handlebars.TemplateDelegate<any>[]> =
// const templates = [ rootPath + "actor/actor-sheet.hbs" ]
// This would map to our local folder of /Assets/Templates/Actor/actor-sheet.hbs
const templates: Array<string> = [
"sheets/character/description.hbs",
"sheets/character/attribute.hbs",
"sheets/character/base_values.hbs",
"sheets/character/main.hbs",
"sheets/character/skills.hbs",
"sheets/character/gear.hbs",
"sheets/character/spells.hbs",
"sheets/character/kampfkuenste.hbs",
"sheets/character/combat.hbs",
"sheets/character/effects.hbs",
"sheets/partial/mod.hbs",
"sheets/item/rolls.hbs",
+12
View File
@@ -49,6 +49,18 @@ export interface M5RollResult extends M5RollTemplate {
css: string;
}
export enum M5ItemType {
SKILL = "skill",
ITEM = "item",
WEAPON = "weapon",
DEFENSIVE_WEAPON = "defensiveWeapon",
ARMOR = "armor",
CONTAINER = "container",
SPELL = "spell",
KAMPFKUNST = "kampfkunst",
EFFECT = "effect",
}
export enum M5EwResult {
TBD = "",
FUMBLE = "roll-ew-result-fumble",
+73 -39
View File
@@ -1,5 +1,5 @@
import { M5Item } from "../items/M5Item";
import { M5Attribute, M5Attributes, M5CharacterCalculatedData, M5ItemMod, M5ModOperation, M5ModResult, M5RollData, M5Skill, M5SkillCalculated, M5SkillLearned, M5Stats } from "../M5Base";
import { M5Attribute, M5CharacterCalculatedData, M5ItemMod, M5ItemType, M5ModOperation, M5ModResult, M5RollData, M5Skill, M5SkillCalculated, M5SkillLearned } from "../M5Base";
import M5ModAggregate from "./M5ModAggregate";
export class M5Character extends Actor {
// constructor(
@@ -198,9 +198,9 @@ export class M5Character extends Actor {
ret.stats.perceptionFW = 6;
ret.stats.drinking = this.modResult(0);
ret.stats.drinkingFW = Math.floor(ret.attributes.ko.value / 10);
ret.stats.hoardMin = M5Character.levelThreshold.at (ret.level - 1)/2;
ret.stats.hoardNext = M5Character.levelThreshold.at (ret.level)/2;
ret.stats.wealth = data.info.gold + data.info.silver/10 + data.info.copper/100;
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);
@@ -212,19 +212,19 @@ export class M5Character extends Actor {
// if (data.info.encumbrance > data.info.loadMax && !loadMessage) {
// let messageContent = `Höchstlast von ${data.info.name} überschritten: [[1d1]] AP Schaden durch Belastung alle 10 Minuten abziehen!`;
// let chatData = {
// speaker: ChatMessage.getSpeaker({actor: Actor.name}),
// content: messageContent,
// };
// ChatMessage.create(chatData, {});
// let chatData = {
// speaker: ChatMessage.getSpeaker({actor: Actor.name}),
// content: messageContent,
// };
// ChatMessage.create(chatData, {});
// loadMessage = true;
// // ui.notifications.warn(messageContent);
// // ui.notifications.warn(messageContent);
// }
// if (data.info.encumbrance < data.info.loadMax && loadMessage) {
// loadMessage = false;
// }
if (!skip?.mods) {
const aggregate = new M5ModAggregate(data, ret);
@@ -251,17 +251,17 @@ export class M5Character extends Actor {
let label = item.name;
if (item.system.magic) {
label += "*";
};
if (item.system.valuable) {
ret.stats.wealth += item.system.value || 0;
};
}
if (item.system.valuable) {
ret.stats.wealth += this.calculateValue(item.system.value, item.system.currency);
}
if (item.system.hoarded) {
ret.stats.hoard += item.system.value || 0;
};
}
if (item.system.equipped) {
ret.stats.encumbrance += item.system.weight || 0;
}
let icon = item.img;
let rollable = false;
@@ -272,7 +272,7 @@ export class M5Character extends Actor {
break;
}
}
ret.gear.items[item.id] = {
label: label,
icon: icon,
@@ -320,13 +320,11 @@ export class M5Character extends Actor {
calc: item.system.calc,
equipped: item.system?.equipped,
weight: item.system.weight || 0,
containerId: item.system.containerId || "",
value: item.system.value || 0,
currency: item.system.currency || "",
quantity: item.system.quantity || 0,
rollExist: rollable,
};
});
}
@@ -339,8 +337,8 @@ export class M5Character extends Actor {
let label = item.name;
if (item.system.magic) {
label += "*";
};
}
ret.gear.effects[item.id] = {
label: label,
magic: item.system.magic,
@@ -383,25 +381,29 @@ export class M5Character extends Actor {
(item.system.stats.damageBonus < 0 ? "" : "+") +
item.system.stats.damageBonus +
")";
};
}
if (item.system.valuable) {
ret.stats.wealth += item.system.value || 0;
};
ret.stats.wealth += this.calculateValue(item.system.value, item.system.currency);
}
if (item.system.hoarded) {
ret.stats.hoard += item.system.value || 0;
};
}
if (item.system.equipped) {
ret.stats.encumbrance += item.system.weight || 0;
}
ret.gear.weapons[item.id] = {
label: label,
skillId: item.system.skillId,
magic: item.system.magic,
valuable: item.system?.valuable,
hoarded: item.system?.hoarded,
value: item.system.value || 0,
value: item.system.value || 0,
calc: item.system.calc,
special: item.system.special,
damageBase: item.system.damageBase,
equipped: item.system?.equipped,
containerId: item.system.containerId || "",
};
});
}
@@ -415,17 +417,17 @@ export class M5Character extends Actor {
let label = item.name;
if (item.system.magic) {
label += "*(" + (item.system.stats.defenseBonus < 0 ? "" : "+") + item.system.stats.defenseBonus + ")";
};
}
if (item.system.valuable) {
ret.stats.wealth += item.system.value || 0;
};
ret.stats.wealth += this.calculateValue(item.system.value, item.system.currency);
}
if (item.system.hoarded) {
ret.stats.hoard += item.system.value || 0;
};
}
if (item.system.equipped) {
ret.stats.encumbrance += item.system.weight || 0;
}
ret.gear.defensiveWeapons[item.id] = {
label: label,
skillId: item.system.skillId,
@@ -433,7 +435,10 @@ export class M5Character extends Actor {
valuable: item.system?.valuable,
hoarded: item.system?.hoarded,
value: item.system.value || 0,
defenseBonus: item.system.stats.defenseBonus,
calc: item.system.calc,
equipped: item.system?.equipped,
containerId: item.system.containerId || "",
};
});
}
@@ -447,25 +452,29 @@ export class M5Character extends Actor {
let label = item.name;
if (item.system.magic) {
label += "*";
};
}
if (item.system.valuable) {
ret.stats.wealth += item.system.value || 0;
};
ret.stats.wealth += this.calculateValue(item.system.value, item.system.currency);
}
if (item.system.hoarded) {
ret.stats.hoard += item.system.value || 0;
};
}
if (item.system.equipped) {
ret.stats.encumbrance += 0;
} else {ret.stats.encumbrance += item.system.weight || 0}
} else {
ret.stats.encumbrance += item.system.weight || 0;
}
ret.gear.armor[item.id] = {
label: label,
magic: item.system.magic,
valuable: item.system?.valuable,
hoarded: item.system?.hoarded,
value: item.system.value || 0,
lpProtection: item.system.lpProtection,
calc: item.system.calc,
equipped: item.system?.equipped,
containerId: item.system.containerId || "",
};
});
}
@@ -602,11 +611,36 @@ export class M5Character extends Actor {
});
}
createItem(itemName: string, itemType: M5ItemType): Promise<M5Item> {
const itemData = {
name: itemName,
type: itemType,
};
return (this as any).createEmbeddedDocuments("Item", [itemData]).then((docs) => {
const item = docs[0];
return item;
});
}
getItem(itemId: string): any {
if (!(this as any).items) return null;
return (this as any).getEmbeddedDocument("Item", itemId);
}
private calculateValue(value: number, currency: string): number {
switch (currency) {
case "gold":
return value;
case "silver":
return parseFloat((value / 10).toPrecision(3));
case "copper":
return parseFloat((value / 100).toPrecision(3));
default:
return 0;
}
}
private modResult(value: number): M5ModResult {
return {
value: value,
+32 -1
View File
@@ -79,14 +79,23 @@ export class M5Item extends Item {
calc.special = itemData.special ? 2 : 0;
calc.ew = calc.special + itemData.stats.attackBonus;
calc.combatSkills = null;
calc.containers = null;
if (actor) {
const actorCalc = character.derivedData({ weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true, effects: true, kampfkuenste: true });
if (actorCalc) {
calc.ew += actorCalc.stats.attackBonus.value;
calc.combatSkills = actorCalc.skills.combat;
calc.containers = actorCalc.gear.containers;
}
const container = character.getItem(itemData.containerId);
//console.log("M5Item.prepareDerivedData:containers", itemData, container?.system)
if (container) {
container.prepareDerivedData();
const containerData = container.system;
}
const skill = character.getItem(itemData.skillId);
//console.log("M5Item.prepareDerivedData:weapon", itemData, skill?.system)
if (skill) {
@@ -103,14 +112,23 @@ export class M5Item extends Item {
calc.special = itemData.special ? 2 : 0;
calc.ew = calc.special + itemData.stats.defenseBonus;
calc.combatSkills = null;
calc.containers = null;
if (actor) {
const actorCalc = character.derivedData({ weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true, effects: true, kampfkuenste: true });
if (actorCalc) {
calc.ew += actorCalc.stats.defense.value + actorCalc.stats.defenseBonus.value;
calc.combatSkills = actorCalc.skills.combat;
calc.containers = actorCalc.gear.containers;
}
const container = character.getItem(itemData.containerId);
//console.log("M5Item.prepareDerivedData:containers", itemData, container?.system)
if (container) {
container.prepareDerivedData();
const containerData = container.system;
}
const skill = character.getItem(itemData.skillId);
//console.log("M5Item.prepareDerivedData:weapon", itemData, skill?.system)
if (skill) {
@@ -128,6 +146,19 @@ export class M5Item extends Item {
itemData.mods[3] = { type: "attribute", id: "gw", operation: "add100", value: itemData.attributeMod.gw };
itemData.mods[4] = { type: "stat", id: "lpProtection", operation: "set", value: itemData.lpProtection };
itemData.mods[5] = { type: "stat", id: "apProtection", operation: "set", value: itemData.apProtection };
calc.containers = null;
if (actor) {
const actorCalc = actor.derivedData({ weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true, effects: true, kampfkuenste: true });
if (actorCalc) {
calc.containers = actorCalc.gear.containers;
}
const container = character.getItem(itemData.containerId);
//console.log("M5Item.prepareDerivedData:containers", itemData, container?.system)
if (container) {
container.prepareDerivedData();
const containerData = container.system;
}
}
} else if (itemType === "spell") {
calc.fw = 0;
if (actor) {
+122 -5
View File
@@ -1,14 +1,14 @@
import Logger from "../../utils/Logger";
import { M5Character } from "../actors/M5Character";
import { M5Item } from "../items/M5Item";
import { M5SkillLearned, M5SkillUnlearned } from "../M5Base";
import { M5ItemType, M5SkillLearned, M5SkillUnlearned } from "../M5Base";
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: 1200,
width: 1000,
height: 800,
classes: ["midgard5", "sheet", "character"],
tabs: [{ navSelector: ".sheet-navigation", contentSelector: ".sheet-content", initial: "base_values" }],
@@ -111,7 +111,11 @@ export default class M5CharacterSheet extends ActorSheet {
if (!item.system.quantity) {
item.system.quantity = 0;
}
item.system.quantity += 1;
item.update({
data: {
quantity: item.system.quantity + 1,
},
});
this.render();
});
@@ -127,7 +131,11 @@ export default class M5CharacterSheet extends ActorSheet {
const context = this.actor as any;
const item = context.items.get(itemId);
if (item.system.quantity > 0) {
item.system.quantity -= 1;
item.update({
data: {
quantity: item.system.quantity - 1,
},
});
}
this.render();
});
@@ -144,7 +152,11 @@ export default class M5CharacterSheet extends ActorSheet {
const context = this.actor as any;
const item = context.items.get(itemId);
if (item.system.quantity > 0) {
item.system.quantity -= 1;
item.update({
data: {
quantity: item.system.quantity - 1,
},
});
}
await item.roll();
@@ -246,6 +258,111 @@ export default class M5CharacterSheet extends ActorSheet {
const roll = M5Roll.resistanceBody(this.actor);
await roll.toMessage();
});
html.find(".change-equipped").on("click", async (event) => {
let row = event.target.parentElement;
let itemId = row.dataset["item"];
while (!itemId) {
row = row.parentElement;
if (!row) return;
itemId = row.dataset["item"];
}
const context = this.actor as any;
const item = context.items.get(itemId);
if (item.system.equipped === true) {
item.system.equipped = false;
} else {
item.system.equipped = true;
}
this.render();
});
html.find(".add-item").on("click", async (event) => {
const data = this.actor.system;
const character = this.actor as M5Character;
character.createItem((game as Game).i18n.localize("TYPES.Item.item"), M5ItemType.ITEM).then((i) => {
const item = i as any;
item.update({
data: {
quantity: 1,
},
});
});
});
html.find(".add-weapon").on("click", async (event) => {
const data = this.actor.system;
const character = this.actor as M5Character;
character.createItem((game as Game).i18n.localize("TYPES.Item.weapon"), M5ItemType.WEAPON);
});
html.find(".add-defensiveWeapon").on("click", async (event) => {
const data = this.actor.system;
const character = this.actor as M5Character;
character.createItem((game as Game).i18n.localize("TYPES.Item.defensiveWeapon"), M5ItemType.DEFENSIVE_WEAPON);
});
html.find(".add-armor").on("click", async (event) => {
const data = this.actor.system;
const character = this.actor as M5Character;
character.createItem((game as Game).i18n.localize("TYPES.Item.armor"), M5ItemType.ARMOR);
});
html.find(".add-container").on("click", async (event) => {
const data = this.actor.system;
const character = this.actor as M5Character;
character.createItem((game as Game).i18n.localize("TYPES.Item.container"), M5ItemType.CONTAINER).then((i) => {
const item = i as any;
item.update({
data: {
quantity: 1,
},
});
});
});
html.find(".add-spell").on("click", async (event) => {
const data = this.actor.system;
const character = this.actor as M5Character;
character.createItem((game as Game).i18n.localize("TYPES.Item.spell"), M5ItemType.SPELL).then((i) => {
const item = i as any;
item.update({
data: {
process: "none",
},
});
});
});
html.find(".add-kampfkunst").on("click", async (event) => {
const data = this.actor.system;
const character = this.actor as M5Character;
character.createItem((game as Game).i18n.localize("TYPES.Item.kampfkunst"), M5ItemType.KAMPFKUNST).then((i) => {
const item = i as any;
item.update({
data: {
type: "angriff",
variante: "anstuermen",
},
});
});
});
html.find(".add-effect").on("click", async (event) => {
const data = this.actor.system;
const character = this.actor as M5Character;
character.createItem((game as Game).i18n.localize("TYPES.Item.effect"), M5ItemType.EFFECT);
});
// Drag & Drop
const dragDrop = new DragDrop({
dragSelector: ".items-list .item",
+85 -17
View File
@@ -6,17 +6,42 @@
.flexbox {
display: flex;
flex-direction: row;
flex-wrap: wrap
flex-wrap: wrap;
}
.flexcolumn {
flex-wrap: wrap;
}
.flexcolumn-1 {
flex: 100%;
flex-wrap: wrap;
}
.flexcolumn-2 {
flex: 50%;
flex-wrap: wrap;
}
.flexcolumn-3 {
flex: 33%;
flex-wrap: wrap;
}
.flexcolumn-4 {
flex: 25%;
flex-wrap: wrap;
}
.flexcolumn-5 {
flex: 20%;
flex-wrap: wrap;
}
.flexpart {
gap: 0;
padding: 0;
margin: 10px;
margin: 5px;
background-color: beige;
border: 2px solid black;
}
@@ -46,6 +71,15 @@
color: white;
}
.profile-img {
display: block;
margin-left: auto;
margin-right: auto;
height: 100%;
width: auto;
border: 0px solid black;
}
.sheet.character {
form {
display: flex;
@@ -62,12 +96,6 @@
}
}
.profile-img {
max-width: 128px;
height: 128px;
border: 0px solid black;
}
.description {
flex: 0 0 100%;
margin: 0;
@@ -100,6 +128,13 @@
table {
background-color: beige;
border: 0px solid transparent;
&.bordered {
border-collapse: separate;
border: 2px solid black;
border-radius: 10px;
font-size: larger;
font-weight: bolder;
}
}
td,
@@ -137,6 +172,11 @@
text-align: left;
font-weight: bold;
}
&.highlight {
font-weight: bold;
font-style: italic;
}
}
.table-icon {
@@ -146,6 +186,10 @@
border: 0px solid transparent;
}
input {
border: 0px solid black;
}
input.skill {
width: 5rem;
}
@@ -154,22 +198,34 @@
width: 5rem;
}
input.checkbox {
width: 1rem;
height: 1rem;
}
.new-skill {
font-style: italic;
background: rgba(0, 0, 0, 0.3);
color: rgba(255, 255, 255);
button {
background: rgba(255, 255, 255, 0.5);
}
}
button.roll-button {
.roll-button {
background: url(/icons/svg/d20-black.svg) no-repeat;
background-size: 24px 24px;
background-size: 1rem 1rem;
border: #000000 solid 0px;
width: 26px;
height: 26px;
width: 1rem;
height: 1rem;
}
.learn-button {
padding: 0;
margin: 0;
height: 1rem;
width: 4rem;
background: rgba(255, 255, 255, 0.5);
font-size: smaller;
text-align: center;
line-height: 0.8rem;
}
span.spell-process {
@@ -222,15 +278,27 @@
}
}
.biography {
margin: 0.5rem 0.5rem 0.5rem 0.5rem;
height: 180px;
background-color: #eaead7;
.editor {
height: 100%;
width: 100%;
}
}
.attributes {
padding: 0.5rem 0.5rem 0.5rem 0.5rem;
display: flex;
flex-direction: row;
margin-bottom: 0.5rem;
background-color: beige;
flex-wrap: wrap;
justify-content: center;
.attribute {
flex: 0 0 7rem;
flex: 0 0 6rem;
margin: 0;
border: 1px solid @attributeBorderColor;
//border-bottom: none;
+9 -5
View File
@@ -3,13 +3,17 @@
"name": "midgard5",
"title": "Midgard 5. Edition",
"description": "The German RPG Midgard 5. Edition",
"version": "2.3.1",
"version": "2.4.0",
"compatibility": {
"minimum": "10",
"verified": "11",
"maximum": "11"
},
"authors": [{"name": "Byroks"}],
"authors": [
{"name": "Byroks"},
{"name": "Le-Frique"},
{"name": "Oskaloq"}
],
"scripts": ["bundle.js"],
"styles": ["bundle.css"],
"packs": [
@@ -153,9 +157,9 @@
"gridUnits": "m",
"primaryTokenAttribute": "lp",
"secondaryTokenAttribute": "ap",
"url": "https://github.com/Byroks/foundry-vtt-system-midgard5",
"manifest": "https://github.com/Byroks/foundry-vtt-system-midgard5/releases/download/v2.3.1/system.json",
"download": "https://github.com/Byroks/foundry-vtt-system-midgard5/releases/download/v2.3.1/midgard5-v2.3.1.zip",
"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.4.0/system.json",
"download": "https://git.byroks.de/MidgardVTT-Entwicklung/foundry-vtt-system-midgard5/releases/download/v2.4.0/midgard5-v2.4.0.zip",
"initiative": "@c.calc.attributes.gw.value",
"license": "LICENSE.txt"
}
+3 -1
View File
@@ -5,9 +5,11 @@
"characterDescription": {
"info": {
"description": "",
"background": "",
"class": "",
"race": "",
"magicUsing": false,
"showAllItems": false,
"gender": "",
"weight": "",
"height": "",
@@ -202,7 +204,7 @@
},
"equippable": {
"equippable": false,
"equipped": true
"equipped": false
},
"valuable": {
"valuable": false,