#49 Ziehbare Items

Changes:
 + Items können jetzt zwischen Charakteren ausgetauscht werden (Nur Gegenstände, keine Zauber etc.)
 + Items können Sortiert werden durch verziehen und droppen

Sneak Change:
 + Löschen button für mods hinzugefügt
 + ESLint und Prettier hinzugefügt, sorry für all die changes :D
This commit is contained in:
2024-02-22 15:24:39 +01:00
parent 06ef797ef2
commit 023b924421
397 changed files with 21631 additions and 9145 deletions
+4 -4
View File
@@ -1,9 +1,9 @@
import assert from "assert"
import assert from "assert";
export default {
name: "midgard5",
isModule: false, // If you are developing a system rather than a module, change this to false
}
name: "midgard5",
isModule: false, // If you are developing a system rather than a module, change this to false
};
// Pop some fairly universal types that we might use
+22 -20
View File
@@ -1,25 +1,27 @@
import Globals from "./Globals";
const preloadTemplates = async (): Promise<Handlebars.TemplateDelegate<any>[]> => {
const rootPath = `${Globals.isModule ? "modules" : "systems"}/${Globals.name}/templates/`;
// Place relative paths in array below, e.g.:
// 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/combat.hbs",
"sheets/character/effects.hbs",
"sheets/partial/mod.hbs",
"sheets/item/rolls.hbs",
"chat/roll-m5.hbs",
];
return loadTemplates(templates.map((s) => rootPath + s));
const preloadTemplates = async (): Promise<
Handlebars.TemplateDelegate<any>[]
> => {
const rootPath = `${Globals.isModule ? "modules" : "systems"}/${Globals.name}/templates/`;
// Place relative paths in array below, e.g.:
// 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/combat.hbs",
"sheets/character/effects.hbs",
"sheets/partial/mod.hbs",
"sheets/item/rolls.hbs",
"chat/roll-m5.hbs",
];
return loadTemplates(templates.map((s) => rootPath + s));
};
export default preloadTemplates;
+257 -237
View File
@@ -1,276 +1,296 @@
import Logger from "./utils/Logger";
import M5CharacterSheet from "./module/sheets/M5CharacterSheet";
import preloadTemplates from "./PreloadTemplates";
import { M5Character } from "./module/actors/M5Character";
import { M5ItemMod, M5ModOperation, M5Skill, M5TimeUnit } from "./module/M5Base";
import { M5ItemSheet } from "./module/sheets/M5ItemSheet";
import { M5Item } from "./module/items/M5Item";
import Logger from './utils/Logger';
import M5CharacterSheet from './module/sheets/M5CharacterSheet';
import preloadTemplates from './PreloadTemplates';
import { M5Character } from './module/actors/M5Character';
import { M5ItemMod, M5ModOperation, M5Skill, M5TimeUnit } from './module/M5Base';
import { M5ItemSheet } from './module/sheets/M5ItemSheet';
import { M5Item } from './module/items/M5Item';
Hooks.once("init", async () => {
Logger.log("M5 | Initialisierung Midgard 5");
Hooks.once('init', async () => {
Logger.log('M5 | Initialisierung Midgard 5');
Handlebars.registerHelper("times", (n: number, block) => {
var accum = "";
for (let i = 0; i < n; ++i) accum += block.fn(i);
return accum;
});
Handlebars.registerHelper('times', (n: number, block) => {
var accum = '';
for (let i = 0; i < n; ++i) accum += block.fn(i);
return accum;
});
Handlebars.registerHelper("array", (arr: any[], index: number) => {
return arr[index];
});
Handlebars.registerHelper('array', (arr: any[], index: number) => {
return arr[index];
});
Handlebars.registerHelper("m5concat", (...values) => {
const options = values.pop();
const join = options.hash?.join || "";
//return new Handlebars.SafeString(values.join(join));
return values.map((val) => val.toString()).join(join);
});
Handlebars.registerHelper('m5concat', (...values) => {
const options = values.pop();
const join = options.hash?.join || '';
//return new Handlebars.SafeString(values.join(join));
return values.map(val => val.toString()).join(join);
});
Handlebars.registerHelper("add", (...values) => {
const options = values.pop();
return values.reduce((prev, cur) => prev + cur);
});
Handlebars.registerHelper('add', (...values) => {
const options = values.pop();
return values.reduce((prev, cur) => prev + cur);
});
Handlebars.registerHelper("localizeMidgard", (str: string) => {
const template = Handlebars.compile("{{localize value}}");
return template({
value: "midgard5." + str,
});
});
Handlebars.registerHelper('localizeMidgard', (str: string) => {
const template = Handlebars.compile('{{localize value}}');
return template({
value: 'midgard5.' + str,
});
});
Handlebars.registerHelper("skillBonus", (actorId: string, skill: M5Skill) => {
const actor = (game as Game).actors.get(actorId) as M5Character;
return actor.skillBonus(skill).toString();
});
Handlebars.registerHelper('skillBonus', (actorId: string, skill: M5Skill) => {
const actor = (game as Game).actors.get(actorId) as M5Character;
return actor.skillBonus(skill).toString();
});
Handlebars.registerHelper("skillEw", (actorId: string, skill: M5Skill) => {
const actor = (game as Game).actors.get(actorId) as M5Character;
return actor.skillEw(skill).toString();
});
Handlebars.registerHelper('skillEw', (actorId: string, skill: M5Skill) => {
const actor = (game as Game).actors.get(actorId) as M5Character;
return actor.skillEw(skill).toString();
});
Handlebars.registerHelper("skill", (skillId: string) => {
return (game as Game).items.get(skillId);
});
Handlebars.registerHelper('skill', (skillId: string) => {
return (game as Game).items.get(skillId);
});
Handlebars.registerHelper("itemValue", (id: string, path: string) => {
let obj = (game as Game).items.get(id);
path.split(".").forEach((p) => (obj = obj[p]));
return `${obj}`;
});
Handlebars.registerHelper('itemValue', (id: string, path: string) => {
let obj = (game as Game).items.get(id);
path.split('.').forEach(p => (obj = obj[p]));
return `${obj}`;
});
Handlebars.registerHelper("actorItemValue", (actorId: any, itemId: string, path: string, token?: boolean) => {
//console.log("actorItemValue", actorId, itemId, path)
const actor = (game as Game).actors.get(actorId);
let obj = actor.items.get(itemId)?.system;
path.split(".").forEach((p) => {
if (obj) obj = obj[p];
});
return `${obj}`;
});
Handlebars.registerHelper('actorItemValue', (actorId: any, itemId: string, path: string, token?: boolean) => {
//console.log("actorItemValue", actorId, itemId, path)
const actor = (game as Game).actors.get(actorId);
let obj = actor.items.get(itemId)?.system;
path.split('.').forEach(p => {
if (obj) obj = obj[p];
});
return `${obj}`;
});
Handlebars.registerHelper("icon", (relpath: string) => {
return `systems/midgard5/assets/icons/${relpath}`;
});
Handlebars.registerHelper('icon', (relpath: string) => {
return `systems/midgard5/assets/icons/${relpath}`;
});
Handlebars.registerHelper("isSkillInList", (skillName: string, list: any) => {
for (let key in list) {
if (list[key]?.label?.toLowerCase() === skillName?.toLowerCase()) {
return true;
}
}
return false;
});
Handlebars.registerHelper('isSkillInList', (skillName: string, list: any) => {
for (let key in list) {
if (list[key]?.label?.toLowerCase() === skillName?.toLowerCase()) {
return true;
}
}
return false;
});
Handlebars.registerHelper("stripHtml", function (param) {
var regex = /(<([^>]+)>)/gi;
return param.replace(regex, "");
});
Handlebars.registerHelper('stripHtml', function (param) {
var regex = /(<([^>]+)>)/gi;
return param.replace(regex, '');
});
Handlebars.registerHelper("contains", (label: string, contains: string) => {
return label.toLowerCase().includes(contains.toLowerCase());
});
Handlebars.registerHelper('contains', (label: string, contains: string) => {
return label.toLowerCase().includes(contains.toLowerCase());
});
Handlebars.registerHelper("count", (object: any) => {
var length = 0;
for (var key in object) {
if (object.hasOwnProperty(key)) {
++length;
}
}
return length;
});
Handlebars.registerHelper('count', (object: any) => {
var length = 0;
for (var key in object) {
if (object.hasOwnProperty(key)) {
++length;
}
}
return length;
});
// Default Sheet für Items definieren und das Standardsheet deaktivieren
Items.unregisterSheet("core", ItemSheet);
Items.registerSheet("midgard5", M5ItemSheet, { makeDefault: true });
// Default Sheet für Items definieren und das Standardsheet deaktivieren
Items.unregisterSheet('core', ItemSheet);
Items.registerSheet('midgard5', M5ItemSheet, { makeDefault: true });
// Default Sheet für Actors definieren und das Standardsheet deaktivieren
Actors.unregisterSheet("core", ActorSheet);
Actors.registerSheet("midgard5", M5CharacterSheet, { makeDefault: true });
// Default Sheet für Actors definieren und das Standardsheet deaktivieren
Actors.unregisterSheet('core', ActorSheet);
Actors.registerSheet('midgard5', M5CharacterSheet, { makeDefault: true });
CONFIG.Actor.documentClass = M5Character;
CONFIG.Item.documentClass = M5Item;
//RegisterSettings();
await preloadTemplates();
CONFIG.Actor.documentClass = M5Character;
CONFIG.Item.documentClass = M5Item;
//RegisterSettings();
await preloadTemplates();
});
Hooks.once("setup", () => {
Logger.log("Template module is being setup.");
Hooks.once('setup', () => {
Logger.log('Template module is being setup.');
});
Hooks.on("getChatLogEntryContext", function (html, options) {
options.push(
{
name: "LP & AP Schaden",
icon: '<i class="fas fa-tint"></i>',
condition: (li) => {
const damageRolls = li.find(".damage").length;
Hooks.on('getChatLogEntryContext', function (html, options) {
options.push(
{
name: 'LP & AP Schaden',
icon: '<i class="fas fa-tint"></i>',
// All must be true to show the reroll dialogue
return (game["user"].character || game["canvas"].tokens.controlled) && damageRolls > 0;
},
callback: (li) => applyDamage(li, 2),
},
{
name: "AP Schaden",
icon: '<i class="fas fa-shield-alt"></i>',
condition: (li) => {
const damageRolls = li.find(".damage").length;
condition: li => {
const damageRolls = li.find('.damage').length;
// All must be true to show the reroll dialogue
return (game["user"].character || game["canvas"].tokens.controlled) && damageRolls > 0;
},
callback: (li) => applyDamage(li, 1),
},
{
name: "LP & AP Heilen",
icon: '<i class="fas fa-heart"></i>',
condition: (li) => {
const damageRolls = li.find(".heal").length;
// All must be true to show the reroll dialogue
return (game['user'].character || game['canvas'].tokens.controlled) && damageRolls > 0;
},
callback: li => applyDamage(li, 2),
},
{
name: 'AP Schaden',
icon: '<i class="fas fa-shield-alt"></i>',
condition: li => {
const damageRolls = li.find('.damage').length;
// All must be true to show the reroll dialogue
return (game["user"].character || game["canvas"].tokens.controlled) && damageRolls > 0;
},
callback: (li) => applyDamage(li, -1),
},
{
name: "AP Heilen",
icon: '<i class="far fa-heart"></i>',
condition: (li) => {
const damageRolls = li.find(".heal").length;
// All must be true to show the reroll dialogue
return (game['user'].character || game['canvas'].tokens.controlled) && damageRolls > 0;
},
callback: li => applyDamage(li, 1),
},
{
name: 'LP & AP Heilen',
icon: '<i class="fas fa-heart"></i>',
condition: li => {
const damageRolls = li.find('.heal').length;
// All must be true to show the reroll dialogue
return (game["user"].character || game["canvas"].tokens.controlled) && damageRolls > 0;
},
callback: (li) => applyDamage(li, -2),
}
);
// All must be true to show the reroll dialogue
return (game['user'].character || game['canvas'].tokens.controlled) && damageRolls > 0;
},
callback: li => applyDamage(li, -1),
},
{
name: 'AP Heilen',
icon: '<i class="far fa-heart"></i>',
condition: li => {
const damageRolls = li.find('.heal').length;
// All must be true to show the reroll dialogue
return (game['user'].character || game['canvas'].tokens.controlled) && damageRolls > 0;
},
callback: li => applyDamage(li, -2),
}
);
});
Hooks.on("updateCombat", function (combat: Combat, updateData: { round: number; turn: number }, updateOptions: { advanceTime: number; direction: number }) {
if (combat.round % 2 === 0 && combat.turn !== null) {
const tokenId = combat.current.tokenId;
const actorId = combat.combatant["actorId"];
let currentToken = game["actors"].tokens[tokenId];
if (!currentToken) {
currentToken = game["actors"].get(actorId);
}
let activeEffects = currentToken.items.filter((x) => x.type === "effect" && x.system.equipped) || [];
activeEffects.forEach((effect) => {
if (effect.system?.duration?.time > 0) {
if (effect.system.duration.unit === M5TimeUnit.ROUND) {
effect.system.duration.time -= 1;
}
}
if (effect.system?.duration.time === 0 && effect.system.duration.unit !== M5TimeUnit.LIMITLESS) {
effect.system.equipped = false;
}
for (const key in effect.system.mods) {
if (effect.system.mods[key].operation === M5ModOperation.SUBTRACT) {
switch (effect.system.mods[key].id) {
case "lp":
currentToken["system"].lp.value -= effect.system.mods[key].value;
break;
case "ap":
currentToken["system"].ap.value -= effect.system.mods[key].value;
break;
}
} else if (effect.system.mods[key].operation === M5ModOperation.ADD) {
switch (effect.system.mods[key].id) {
case "lp":
currentToken["system"].lp.value += limitHeal(effect.system.mods[key].value, currentToken["system"].lp.value, currentToken["system"].lp.max);
break;
case "ap":
currentToken["system"].ap.value += limitHeal(effect.system.mods[key].value, currentToken["system"].ap.value, currentToken["system"].ap.max);
break;
}
}
}
});
currentToken.render();
}
Hooks.on(
'updateCombat',
function (
combat: Combat,
updateData: { round: number; turn: number },
updateOptions: { advanceTime: number; direction: number }
) {
if (combat.round % 2 === 0 && combat.turn !== null) {
const tokenId = combat.current.tokenId;
const actorId = combat.combatant['actorId'];
let currentToken = game['actors'].tokens[tokenId];
if (!currentToken) {
currentToken = game['actors'].get(actorId);
}
let activeEffects = currentToken.items.filter(x => x.type === 'effect' && x.system.equipped) || [];
activeEffects.forEach(effect => {
if (effect.system?.duration?.time > 0) {
if (effect.system.duration.unit === M5TimeUnit.ROUND) {
effect.system.duration.time -= 1;
}
}
if (effect.system?.duration.time === 0 && effect.system.duration.unit !== M5TimeUnit.LIMITLESS) {
effect.system.equipped = false;
}
for (const key in effect.system.mods) {
if (effect.system.mods[key].operation === M5ModOperation.SUBTRACT) {
switch (effect.system.mods[key].id) {
case 'lp':
currentToken['system'].lp.value -= effect.system.mods[key].value;
break;
case 'ap':
currentToken['system'].ap.value -= effect.system.mods[key].value;
break;
}
} else if (effect.system.mods[key].operation === M5ModOperation.ADD) {
switch (effect.system.mods[key].id) {
case 'lp':
currentToken['system'].lp.value += limitHeal(
effect.system.mods[key].value,
currentToken['system'].lp.value,
currentToken['system'].lp.max
);
break;
case 'ap':
currentToken['system'].ap.value += limitHeal(
effect.system.mods[key].value,
currentToken['system'].ap.value,
currentToken['system'].ap.max
);
break;
}
}
}
});
currentToken.render();
}
}
);
Hooks.on('renderCombatTracker', (combatTracker, html, context) => {
if (context.combat === null) {
html.find('h3.encounter-title')[0].innerHTML = game['i18n'].localize('midgard5.no-encounter');
} else if (Math.ceil(context.round / 2) === 0) {
html.find('h3.encounter-title')[0].innerHTML = game['i18n'].localize('midgard5.encounter-not-started');
} else {
html.find('h3.encounter-title')[0].innerHTML =
(context.round % 2 == 1
? game['i18n'].localize('midgard5.phase-movement')
: game['i18n'].localize('midgard5.phase-action')) +
' ' +
Math.ceil(context.round / 2);
}
});
Hooks.on("renderCombatTracker", (combatTracker, html, context) => {
if (context.combat === null) {
html.find("h3.encounter-title")[0].innerHTML = game["i18n"].localize("midgard5.no-encounter");
} else if (Math.ceil(context.round / 2) === 0) {
html.find("h3.encounter-title")[0].innerHTML = game["i18n"].localize("midgard5.encounter-not-started");
} else {
html.find("h3.encounter-title")[0].innerHTML =
(context.round % 2 == 1 ? game["i18n"].localize("midgard5.phase-movement") : game["i18n"].localize("midgard5.phase-action")) + " " + Math.ceil(context.round / 2);
}
});
Hooks.once("ready", () => {
Logger.ok("Template module is now ready.");
Hooks.once('ready', () => {
Logger.ok('Template module is now ready.');
});
async function applyDamage(roll, direction) {
console.log(roll, direction);
const damageValue = Array.from(roll.find(".apply") as HTMLElement[])
.map((x) => Math.max(0, Number(x.innerText)))
.reduce((prev, curr) => prev + curr, 0);
const controlledTokens = game["canvas"].tokens.controlled;
const actor = game["user"].character;
console.log(roll, direction);
const damageValue = Array.from(roll.find('.apply') as HTMLElement[])
.map(x => Math.max(0, Number(x.innerText)))
.reduce((prev, curr) => prev + curr, 0);
const controlledTokens = game['canvas'].tokens.controlled;
const actor = game['user'].character;
if (controlledTokens) {
controlledTokens.forEach((controlledToken) => {
let token = controlledToken.document.delta.syntheticActor;
switch (direction) {
case 2:
token["system"].lp.value -= Math.max(0, damageValue - token["system"].calc.stats.lpProtection.value);
case 1:
token["system"].ap.value -= Math.max(0, damageValue - token["system"].calc.stats.apProtection.value);
break;
case -1:
token["system"].lp.value += limitHeal(damageValue, token["system"].lp.value, token["system"].lp.max);
case -2:
token["system"].ap.value += limitHeal(damageValue, token["system"].ap.value, token["system"].ap.max);
}
token.render();
});
} else {
switch (direction) {
case 2:
actor["system"].lp.value -= Math.max(0, damageValue - actor["system"].calc.stats.lpProtection.value);
case 1:
actor["system"].ap.value -= Math.max(0, damageValue - actor["system"].calc.stats.apProtection.value);
break;
case -1:
actor["system"].lp.value += limitHeal(damageValue, actor["system"].lp.value, actor["system"].lp.max);
case -2:
actor["system"].ap.value += limitHeal(damageValue, actor["system"].ap.value, actor["system"].ap.max);
}
actor.render();
}
if (controlledTokens) {
controlledTokens.forEach(controlledToken => {
let token = controlledToken.document.delta.syntheticActor;
switch (direction) {
case 2:
token['system'].lp.value -= Math.max(0, damageValue - token['system'].calc.stats.lpProtection.value);
case 1:
token['system'].ap.value -= Math.max(0, damageValue - token['system'].calc.stats.apProtection.value);
break;
case -1:
token['system'].lp.value += limitHeal(damageValue, token['system'].lp.value, token['system'].lp.max);
case -2:
token['system'].ap.value += limitHeal(damageValue, token['system'].ap.value, token['system'].ap.max);
}
token.render();
});
} else {
switch (direction) {
case 2:
actor['system'].lp.value -= Math.max(0, damageValue - actor['system'].calc.stats.lpProtection.value);
case 1:
actor['system'].ap.value -= Math.max(0, damageValue - actor['system'].calc.stats.apProtection.value);
break;
case -1:
actor['system'].lp.value += limitHeal(damageValue, actor['system'].lp.value, actor['system'].lp.max);
case -2:
actor['system'].ap.value += limitHeal(damageValue, actor['system'].ap.value, actor['system'].ap.max);
}
actor.render();
}
}
function limitHeal(heal: number, current: number, max: number): number {
if (current === max) {
return 0;
} else if (heal + current > max) {
return max - current;
}
return heal;
if (current === max) {
return 0;
} else if (heal + current > max) {
return max - current;
}
return heal;
}
+159 -157
View File
@@ -1,226 +1,228 @@
import { BooleanField } from "@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/data/fields.mjs";
export interface M5Skill {
fw: number;
attribute: string;
pp: number;
fw: number;
attribute: string;
pp: number;
}
export interface M5SkillUnlearned extends M5Skill {
initial: number;
initial: number;
}
export interface M5SkillLearned extends M5Skill {
skill: string;
type: string;
skill: string;
type: string;
}
export interface M5SkillCalculated extends M5Skill {
label: string;
calc: any;
label: string;
calc: any;
}
export interface M5Attribute {
value: number;
bonus: number;
value: number;
bonus: number;
}
export interface M5RollData {
c: any;
i: any;
iType: string;
rolls: {};
res: {
label: string;
};
c: any;
i: any;
iType: string;
rolls: {};
res: {
label: string;
};
}
export interface M5RollTemplate {
formula: string;
label: string;
enabled: boolean;
formula: string;
label: string;
enabled: boolean;
}
export interface M5RollResult extends M5RollTemplate {
total: number;
totalStr: string;
result: string;
dice: {};
css: string;
total: number;
totalStr: string;
result: string;
dice: {};
css: string;
}
export enum M5ItemType {
SKILL = "skill",
ITEM = "item",
WEAPON = "weapon",
DEFENSIVE_WEAPON = "defensiveWeapon",
ARMOR = "armor",
CONTAINER = "container",
SPELL = "spell",
KAMPFKUNST = "kampfkunst",
EFFECT = "effect",
SKILL = "skill",
ITEM = "item",
WEAPON = "weapon",
DEFENSIVE_WEAPON = "defensiveWeapon",
ARMOR = "armor",
CONTAINER = "container",
SPELL = "spell",
KAMPFKUNST = "kampfkunst",
EFFECT = "effect",
}
export enum M5SkillType {
INNATE = "innate",
GENERAL = "general",
LANGUAGE = "language",
COMBAT = "combat",
INNATE = "innate",
GENERAL = "general",
LANGUAGE = "language",
COMBAT = "combat",
}
export enum M5EwResult {
TBD = "",
FUMBLE = "roll-ew-result-fumble",
CRITICAL = "roll-ew-result-critical",
HIGH = "roll-ew-result-high",
FAIL = "roll-ew-result-fail",
PASS = "roll-ew-result-pass",
TBD = "",
FUMBLE = "roll-ew-result-fumble",
CRITICAL = "roll-ew-result-critical",
HIGH = "roll-ew-result-high",
FAIL = "roll-ew-result-fail",
PASS = "roll-ew-result-pass",
}
export enum M5Attributes {
ST = "st",
GW = "gw",
GS = "gs",
KO = "ko",
IN = "in",
ZT = "zt",
AU = "au",
PA = "pa",
WK = "wk",
ST = "st",
GW = "gw",
GS = "gs",
KO = "ko",
IN = "in",
ZT = "zt",
AU = "au",
PA = "pa",
WK = "wk",
}
export enum M5Stats {
DEFENSE = "defenseBonus",
ATTACK = "attackBonus",
DAMAGE = "damageBonus",
MOVEMENT = "movement",
RESISTANCE_MIND = "resistanceMind",
RESISTANCE_BODY = "resistanceBody",
SPELL_CASTING = "spellCasting",
BRAWL = "brawl",
POISON_RESISTANCE = "poisonResistance",
LP = "lp",
AP = "ap",
PROTECTION_LP = "lpProtection",
PROTECTION_AP = "apProtection",
PERCEPTION = "perception",
DRINKING = "drinking",
HOARD = "hoard",
HOARD_NEXT = "hoardNext",
HOARD_MIN = "hoardMin",
WEALTH = "wealth",
DEFENSE = "defenseBonus",
ATTACK = "attackBonus",
DAMAGE = "damageBonus",
MOVEMENT = "movement",
RESISTANCE_MIND = "resistanceMind",
RESISTANCE_BODY = "resistanceBody",
SPELL_CASTING = "spellCasting",
BRAWL = "brawl",
POISON_RESISTANCE = "poisonResistance",
LP = "lp",
AP = "ap",
PROTECTION_LP = "lpProtection",
PROTECTION_AP = "apProtection",
PERCEPTION = "perception",
DRINKING = "drinking",
HOARD = "hoard",
HOARD_NEXT = "hoardNext",
HOARD_MIN = "hoardMin",
WEALTH = "wealth",
}
export enum M5ModType {
ATTRIBUTE = "attribute",
STAT = "stat",
SKILL = "skill",
ATTRIBUTE = "attribute",
STAT = "stat",
SKILL = "skill",
}
export enum M5ModOperation {
ADD_100 = "add100",
ROLL = "roll",
ADD = "add",
SET = "set",
FIXED = "fixed",
MULTIPLY = "multiply",
SUBTRACT = "subtract",
DIVISION = "division",
ADD_100 = "add100",
ROLL = "roll",
ADD = "add",
SET = "set",
FIXED = "fixed",
MULTIPLY = "multiply",
SUBTRACT = "subtract",
DIVISION = "division",
}
export enum M5TimeUnit {
ROUND = "round",
MINUTE = "minute",
HOUR = "hour",
LIMITLESS = "limitless",
ROUND = "round",
MINUTE = "minute",
HOUR = "hour",
LIMITLESS = "limitless",
}
export interface M5ItemMod {
type: M5ModType;
id: string;
operation: M5ModOperation;
value: number;
type: M5ModType;
id: string;
operation: M5ModOperation;
value: number;
}
export interface M5ModPair {
mod: M5ItemMod;
source: string;
mod: M5ItemMod;
source: string;
}
export interface M5ModSource {
item: string;
operation: M5ModOperation;
value: number;
item: string;
operation: M5ModOperation;
value: number;
}
export interface M5ModResult {
mods: Array<M5ModSource>;
value: number;
mods: Array<M5ModSource>;
value: number;
}
export interface M5AttributeCalculated extends M5ModResult {
bonus: number;
bonus: number;
}
export interface M5CharacterCalculatedData {
level: number;
attributes: {
st: M5AttributeCalculated;
gs: M5AttributeCalculated;
gw: M5AttributeCalculated;
ko: M5AttributeCalculated;
in: M5AttributeCalculated;
zt: M5AttributeCalculated;
au: M5AttributeCalculated;
pa: M5AttributeCalculated;
wk: M5AttributeCalculated;
};
stats: {
lp: M5ModResult;
ap: M5ModResult;
lpProtection: M5ModResult;
apProtection: M5ModResult;
defense: M5ModResult;
damageBonus: M5ModResult;
attackBonus: M5ModResult;
defenseBonus: M5ModResult;
movement: M5ModResult;
resistanceMind: M5ModResult;
resistanceBody: M5ModResult;
spellCasting: M5ModResult;
brawl: M5ModResult;
brawlFw: number;
poisonResistance: M5ModResult;
enduranceBonus: number;
perception: M5ModResult;
perceptionFW: number;
drinking: M5ModResult;
drinkingFW: number;
hoard: number;
hoardNext: number;
hoardMin: number;
wealth: number;
};
skillMods: {};
skills: {
innate: {};
general: {};
combat: {};
language: {};
custom: {};
};
gear: {
weapons: {};
defensiveWeapons: {};
armor: {};
items: {};
containers: {};
effects: {};
};
spells: {};
kampfkuenste: {};
level: number;
attributes: {
st: M5AttributeCalculated;
gs: M5AttributeCalculated;
gw: M5AttributeCalculated;
ko: M5AttributeCalculated;
in: M5AttributeCalculated;
zt: M5AttributeCalculated;
au: M5AttributeCalculated;
pa: M5AttributeCalculated;
wk: M5AttributeCalculated;
};
stats: {
lp: M5ModResult;
ap: M5ModResult;
lpProtection: M5ModResult;
apProtection: M5ModResult;
defense: M5ModResult;
damageBonus: M5ModResult;
attackBonus: M5ModResult;
defenseBonus: M5ModResult;
movement: M5ModResult;
resistanceMind: M5ModResult;
resistanceBody: M5ModResult;
spellCasting: M5ModResult;
brawl: M5ModResult;
brawlFw: number;
poisonResistance: M5ModResult;
enduranceBonus: number;
perception: M5ModResult;
perceptionFW: number;
drinking: M5ModResult;
drinkingFW: number;
hoard: number;
hoardNext: number;
hoardMin: number;
wealth: number;
};
skillMods: {};
skills: {
innate: {};
general: {};
combat: {};
language: {};
custom: {};
};
gear: {
weapons: {};
defensiveWeapons: {};
armor: {};
items: {};
containers: {};
effects: {};
};
spells: {};
kampfkuenste: {};
}
export function enumKeys<O extends object, K extends keyof O = keyof O>(obj: O): K[] {
return Object.keys(obj).filter((k) => Number.isNaN(+k)) as K[];
export function enumKeys<O extends object, K extends keyof O = keyof O>(
obj: O,
): K[] {
return Object.keys(obj).filter((k) => Number.isNaN(+k)) as K[];
}
File diff suppressed because it is too large Load Diff
+424 -143
View File
@@ -1,172 +1,453 @@
import { M5Attribute, M5AttributeCalculated, M5Attributes, M5CharacterCalculatedData, M5ItemMod, M5ModOperation, M5ModResult, M5ModSource, M5ModType, M5Stats, M5ModPair } from "../M5Base";
import {
M5Attribute,
M5AttributeCalculated,
M5Attributes,
M5CharacterCalculatedData,
M5ItemMod,
M5ModOperation,
M5ModResult,
M5ModSource,
M5ModType,
M5Stats,
M5ModPair,
} from '../M5Base';
export default class M5ModAggregate {
private attributes = new Map<string, Array<M5ModPair>>();
private stats = new Map<string, Array<M5ModPair>>();
private skills = new Map<string, Array<M5ModPair>>();
private attributes = new Map<string, Array<M5ModPair>>();
private stats = new Map<string, Array<M5ModPair>>();
private skills = new Map<string, Array<M5ModPair>>();
constructor(public data: any, public calc: M5CharacterCalculatedData) {
const characterString = (game as Game).i18n.localize("TYPES.Actor.character");
constructor(
public data: any,
public calc: M5CharacterCalculatedData
) {
const characterString = (game as Game).i18n.localize('TYPES.Actor.character');
this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.ST, operation: M5ModOperation.SET, value: data.attributes.st.value }, characterString);
this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.GS, operation: M5ModOperation.SET, value: data.attributes.gs.value }, characterString);
this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.GW, operation: M5ModOperation.SET, value: data.attributes.gw.value }, characterString);
this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.KO, operation: M5ModOperation.SET, value: data.attributes.ko.value }, characterString);
this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.IN, operation: M5ModOperation.SET, value: data.attributes.in.value }, characterString);
this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.ZT, operation: M5ModOperation.SET, value: data.attributes.zt.value }, characterString);
this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.AU, operation: M5ModOperation.SET, value: data.attributes.au.value }, characterString);
this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.PA, operation: M5ModOperation.SET, value: data.attributes.pa.value }, characterString);
this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.WK, operation: M5ModOperation.SET, value: data.attributes.wk.value }, characterString);
this.push(
{
type: M5ModType.ATTRIBUTE,
id: M5Attributes.ST,
operation: M5ModOperation.SET,
value: data.attributes.st.value,
},
characterString
);
this.push(
{
type: M5ModType.ATTRIBUTE,
id: M5Attributes.GS,
operation: M5ModOperation.SET,
value: data.attributes.gs.value,
},
characterString
);
this.push(
{
type: M5ModType.ATTRIBUTE,
id: M5Attributes.GW,
operation: M5ModOperation.SET,
value: data.attributes.gw.value,
},
characterString
);
this.push(
{
type: M5ModType.ATTRIBUTE,
id: M5Attributes.KO,
operation: M5ModOperation.SET,
value: data.attributes.ko.value,
},
characterString
);
this.push(
{
type: M5ModType.ATTRIBUTE,
id: M5Attributes.IN,
operation: M5ModOperation.SET,
value: data.attributes.in.value,
},
characterString
);
this.push(
{
type: M5ModType.ATTRIBUTE,
id: M5Attributes.ZT,
operation: M5ModOperation.SET,
value: data.attributes.zt.value,
},
characterString
);
this.push(
{
type: M5ModType.ATTRIBUTE,
id: M5Attributes.AU,
operation: M5ModOperation.SET,
value: data.attributes.au.value,
},
characterString
);
this.push(
{
type: M5ModType.ATTRIBUTE,
id: M5Attributes.PA,
operation: M5ModOperation.SET,
value: data.attributes.pa.value,
},
characterString
);
this.push(
{
type: M5ModType.ATTRIBUTE,
id: M5Attributes.WK,
operation: M5ModOperation.SET,
value: data.attributes.wk.value,
},
characterString
);
this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.ST, operation: M5ModOperation.ADD_100, value: data.attributes.st.bonus }, characterString);
this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.GS, operation: M5ModOperation.ADD_100, value: data.attributes.gs.bonus }, characterString);
this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.GW, operation: M5ModOperation.ADD_100, value: data.attributes.gw.bonus }, characterString);
this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.KO, operation: M5ModOperation.ADD_100, value: data.attributes.ko.bonus }, characterString);
this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.IN, operation: M5ModOperation.ADD_100, value: data.attributes.in.bonus }, characterString);
this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.ZT, operation: M5ModOperation.ADD_100, value: data.attributes.zt.bonus }, characterString);
this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.AU, operation: M5ModOperation.ADD_100, value: data.attributes.au.bonus }, characterString);
this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.PA, operation: M5ModOperation.ADD_100, value: data.attributes.pa.bonus }, characterString);
this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.WK, operation: M5ModOperation.ADD_100, value: data.attributes.wk.bonus }, characterString);
this.push(
{
type: M5ModType.ATTRIBUTE,
id: M5Attributes.ST,
operation: M5ModOperation.ADD_100,
value: data.attributes.st.bonus,
},
characterString
);
this.push(
{
type: M5ModType.ATTRIBUTE,
id: M5Attributes.GS,
operation: M5ModOperation.ADD_100,
value: data.attributes.gs.bonus,
},
characterString
);
this.push(
{
type: M5ModType.ATTRIBUTE,
id: M5Attributes.GW,
operation: M5ModOperation.ADD_100,
value: data.attributes.gw.bonus,
},
characterString
);
this.push(
{
type: M5ModType.ATTRIBUTE,
id: M5Attributes.KO,
operation: M5ModOperation.ADD_100,
value: data.attributes.ko.bonus,
},
characterString
);
this.push(
{
type: M5ModType.ATTRIBUTE,
id: M5Attributes.IN,
operation: M5ModOperation.ADD_100,
value: data.attributes.in.bonus,
},
characterString
);
this.push(
{
type: M5ModType.ATTRIBUTE,
id: M5Attributes.ZT,
operation: M5ModOperation.ADD_100,
value: data.attributes.zt.bonus,
},
characterString
);
this.push(
{
type: M5ModType.ATTRIBUTE,
id: M5Attributes.AU,
operation: M5ModOperation.ADD_100,
value: data.attributes.au.bonus,
},
characterString
);
this.push(
{
type: M5ModType.ATTRIBUTE,
id: M5Attributes.PA,
operation: M5ModOperation.ADD_100,
value: data.attributes.pa.bonus,
},
characterString
);
this.push(
{
type: M5ModType.ATTRIBUTE,
id: M5Attributes.WK,
operation: M5ModOperation.ADD_100,
value: data.attributes.wk.bonus,
},
characterString
);
this.push({ type: M5ModType.STAT, id: M5Stats.DEFENSE, operation: M5ModOperation.SET, value: calc.stats.defenseBonus.value }, characterString);
this.push({ type: M5ModType.STAT, id: M5Stats.ATTACK, operation: M5ModOperation.SET, value: calc.stats.attackBonus.value }, characterString);
this.push({ type: M5ModType.STAT, id: M5Stats.DAMAGE, operation: M5ModOperation.SET, value: calc.stats.damageBonus.value }, characterString);
this.push({ type: M5ModType.STAT, id: M5Stats.MOVEMENT, operation: M5ModOperation.SET, value: calc.stats.movement.value }, characterString);
this.push({ type: M5ModType.STAT, id: M5Stats.RESISTANCE_MIND, operation: M5ModOperation.SET, value: calc.stats.resistanceMind.value }, characterString);
this.push({ type: M5ModType.STAT, id: M5Stats.RESISTANCE_BODY, operation: M5ModOperation.SET, value: calc.stats.resistanceBody.value }, characterString);
this.push({ type: M5ModType.STAT, id: M5Stats.SPELL_CASTING, operation: M5ModOperation.SET, value: calc.stats.spellCasting.value }, characterString);
this.push({ type: M5ModType.STAT, id: M5Stats.BRAWL, operation: M5ModOperation.SET, value: calc.stats.brawl.value }, characterString);
this.push({ type: M5ModType.STAT, id: M5Stats.POISON_RESISTANCE, operation: M5ModOperation.SET, value: calc.stats.poisonResistance.value }, characterString);
this.push({ type: M5ModType.STAT, id: M5Stats.LP, operation: M5ModOperation.SET, value: calc.stats.lp.value }, characterString);
this.push({ type: M5ModType.STAT, id: M5Stats.AP, operation: M5ModOperation.SET, value: calc.stats.ap.value }, characterString);
this.push({ type: M5ModType.STAT, id: M5Stats.PROTECTION_LP, operation: M5ModOperation.SET, value: calc.stats.lpProtection.value }, characterString);
this.push({ type: M5ModType.STAT, id: M5Stats.PROTECTION_AP, operation: M5ModOperation.SET, value: calc.stats.apProtection.value }, characterString);
this.push({ type: M5ModType.STAT, id: M5Stats.PERCEPTION, operation: M5ModOperation.SET, value: calc.stats.perception.value }, characterString);
this.push({ type: M5ModType.STAT, id: M5Stats.DRINKING, operation: M5ModOperation.SET, value: calc.stats.drinking.value }, characterString);
}
this.push(
{
type: M5ModType.STAT,
id: M5Stats.DEFENSE,
operation: M5ModOperation.SET,
value: calc.stats.defenseBonus.value,
},
characterString
);
this.push(
{
type: M5ModType.STAT,
id: M5Stats.ATTACK,
operation: M5ModOperation.SET,
value: calc.stats.attackBonus.value,
},
characterString
);
this.push(
{
type: M5ModType.STAT,
id: M5Stats.DAMAGE,
operation: M5ModOperation.SET,
value: calc.stats.damageBonus.value,
},
characterString
);
this.push(
{
type: M5ModType.STAT,
id: M5Stats.MOVEMENT,
operation: M5ModOperation.SET,
value: calc.stats.movement.value,
},
characterString
);
this.push(
{
type: M5ModType.STAT,
id: M5Stats.RESISTANCE_MIND,
operation: M5ModOperation.SET,
value: calc.stats.resistanceMind.value,
},
characterString
);
this.push(
{
type: M5ModType.STAT,
id: M5Stats.RESISTANCE_BODY,
operation: M5ModOperation.SET,
value: calc.stats.resistanceBody.value,
},
characterString
);
this.push(
{
type: M5ModType.STAT,
id: M5Stats.SPELL_CASTING,
operation: M5ModOperation.SET,
value: calc.stats.spellCasting.value,
},
characterString
);
this.push(
{
type: M5ModType.STAT,
id: M5Stats.BRAWL,
operation: M5ModOperation.SET,
value: calc.stats.brawl.value,
},
characterString
);
this.push(
{
type: M5ModType.STAT,
id: M5Stats.POISON_RESISTANCE,
operation: M5ModOperation.SET,
value: calc.stats.poisonResistance.value,
},
characterString
);
this.push(
{
type: M5ModType.STAT,
id: M5Stats.LP,
operation: M5ModOperation.SET,
value: calc.stats.lp.value,
},
characterString
);
this.push(
{
type: M5ModType.STAT,
id: M5Stats.AP,
operation: M5ModOperation.SET,
value: calc.stats.ap.value,
},
characterString
);
this.push(
{
type: M5ModType.STAT,
id: M5Stats.PROTECTION_LP,
operation: M5ModOperation.SET,
value: calc.stats.lpProtection.value,
},
characterString
);
this.push(
{
type: M5ModType.STAT,
id: M5Stats.PROTECTION_AP,
operation: M5ModOperation.SET,
value: calc.stats.apProtection.value,
},
characterString
);
this.push(
{
type: M5ModType.STAT,
id: M5Stats.PERCEPTION,
operation: M5ModOperation.SET,
value: calc.stats.perception.value,
},
characterString
);
this.push(
{
type: M5ModType.STAT,
id: M5Stats.DRINKING,
operation: M5ModOperation.SET,
value: calc.stats.drinking.value,
},
characterString
);
}
push(mod: M5ItemMod, source: string) {
if (!mod?.id || mod.id === "") return;
push(mod: M5ItemMod, source: string) {
if (!mod?.id || mod.id === '') return;
let map: Map<string, Array<M5ModPair>> = null;
if (mod.type === M5ModType.ATTRIBUTE) map = this.attributes;
else if (mod.type === M5ModType.STAT) map = this.stats;
else if (mod.type === M5ModType.SKILL) map = this.skills;
let map: Map<string, Array<M5ModPair>> = null;
if (mod.type === M5ModType.ATTRIBUTE) map = this.attributes;
else if (mod.type === M5ModType.STAT) map = this.stats;
else if (mod.type === M5ModType.SKILL) map = this.skills;
if (map) {
const pair: M5ModPair = {
mod: mod,
source: source,
};
if (map) {
const pair: M5ModPair = {
mod: mod,
source: source,
};
if (map.has(mod.id)) map.get(mod.id).push(pair);
else map.set(mod.id, [pair]);
}
}
if (map.has(mod.id)) map.get(mod.id).push(pair);
else map.set(mod.id, [pair]);
}
}
calculate() {
const calc = this.calc;
calculate() {
const calc = this.calc;
this.attributes.forEach((pairs, id) => {
const res = M5ModAggregate.processPairs(pairs);
calc.attributes[id] = {
value: res.value,
bonus: M5ModAggregate.attributeBonus(res.value),
mods: res.mods,
} as M5AttributeCalculated;
//console.log("calc.attributes." + id, calc.attributes[id])
});
this.attributes.forEach((pairs, id) => {
const res = M5ModAggregate.processPairs(pairs);
calc.attributes[id] = {
value: res.value,
bonus: M5ModAggregate.attributeBonus(res.value),
mods: res.mods,
} as M5AttributeCalculated;
//console.log("calc.attributes." + id, calc.attributes[id])
});
this.stats.forEach((pairs, id) => {
const res = M5ModAggregate.processPairs(pairs);
calc.stats[id] = res;
});
this.stats.forEach((pairs, id) => {
const res = M5ModAggregate.processPairs(pairs);
calc.stats[id] = res;
});
const ret = {};
this.skills.forEach((pairs, id) => {
ret[id] = pairs;
});
const ret = {};
this.skills.forEach((pairs, id) => {
ret[id] = pairs;
});
return ret;
}
return ret;
}
static pairAsSource(pair: M5ModPair): M5ModSource {
return {
operation: pair.mod.operation,
value: pair.mod.value,
item: pair.source,
};
}
static pairAsSource(pair: M5ModPair): M5ModSource {
return {
operation: pair.mod.operation,
value: pair.mod.value,
item: pair.source,
};
}
static processPairs(arr: Array<M5ModPair>): M5ModResult {
let ret: M5ModResult = {
mods: [],
value: 0,
};
static processPairs(arr: Array<M5ModPair>): M5ModResult {
let ret: M5ModResult = {
mods: [],
value: 0,
};
let mods = arr.filter((pair) => pair.mod.operation === M5ModOperation.FIXED).sort((a, b) => b.mod.value - a.mod.value);
let pair = mods.length === 0 ? null : mods[0];
let mods = arr
.filter(pair => pair.mod.operation === M5ModOperation.FIXED)
.sort((a, b) => b.mod.value - a.mod.value);
let pair = mods.length === 0 ? null : mods[0];
if (pair) {
ret.mods.push(this.pairAsSource(pair));
ret.value = pair.mod.value;
} else {
mods = arr.filter((pair) => pair.mod.operation === M5ModOperation.SET).sort((a, b) => b.mod.value - a.mod.value);
if (mods.length !== 0) {
ret.mods.push(this.pairAsSource(mods[0]));
ret.value = mods[0].mod.value;
}
if (pair) {
ret.mods.push(this.pairAsSource(pair));
ret.value = pair.mod.value;
} else {
mods = arr.filter(pair => pair.mod.operation === M5ModOperation.SET).sort((a, b) => b.mod.value - a.mod.value);
if (mods.length !== 0) {
ret.mods.push(this.pairAsSource(mods[0]));
ret.value = mods[0].mod.value;
}
mods = arr.filter((pair) => pair.mod.operation === M5ModOperation.ADD_100);
if (mods.length !== 0) {
ret.mods = ret.mods.concat(mods.map(this.pairAsSource));
const bonus = mods.map((p) => p.mod.value).reduce((a, b) => a + b, 0);
ret.value = Math.min(100, Math.max(0, ret.value + bonus));
}
mods = arr.filter(pair => pair.mod.operation === M5ModOperation.ADD_100);
if (mods.length !== 0) {
ret.mods = ret.mods.concat(mods.map(this.pairAsSource));
const bonus = mods.map(p => p.mod.value).reduce((a, b) => a + b, 0);
ret.value = Math.min(100, Math.max(0, ret.value + bonus));
}
mods = arr.filter((pair) => pair.mod.operation === M5ModOperation.ADD);
if (mods.length !== 0) {
ret.mods = ret.mods.concat(mods.map(this.pairAsSource));
const bonus = mods.map((p) => p.mod.value).reduce((a, b) => a + b, 0);
ret.value = Math.max(0, ret.value + bonus);
}
mods = arr.filter(pair => pair.mod.operation === M5ModOperation.ADD);
if (mods.length !== 0) {
ret.mods = ret.mods.concat(mods.map(this.pairAsSource));
const bonus = mods.map(p => p.mod.value).reduce((a, b) => a + b, 0);
ret.value = Math.max(0, ret.value + bonus);
}
mods = arr.filter((pair) => pair.mod.operation === M5ModOperation.SUBTRACT);
if (mods.length !== 0) {
ret.mods = ret.mods.concat(mods.map(this.pairAsSource));
const bonus = mods.map((p) => p.mod.value).reduce((a, b) => a + b, 0);
ret.value = ret.value - bonus;
}
mods = arr.filter(pair => pair.mod.operation === M5ModOperation.SUBTRACT);
if (mods.length !== 0) {
ret.mods = ret.mods.concat(mods.map(this.pairAsSource));
const bonus = mods.map(p => p.mod.value).reduce((a, b) => a + b, 0);
ret.value = ret.value - bonus;
}
mods = arr.filter((pair) => pair.mod.operation === M5ModOperation.MULTIPLY);
if (mods.length !== 0) {
ret.mods = ret.mods.concat(mods.map(this.pairAsSource));
const bonus = mods.map((p) => p.mod.value).reduce((a, b) => a * b, 1);
ret.value = Math.max(0, ret.value * bonus);
}
mods = arr.filter(pair => pair.mod.operation === M5ModOperation.MULTIPLY);
if (mods.length !== 0) {
ret.mods = ret.mods.concat(mods.map(this.pairAsSource));
const bonus = mods.map(p => p.mod.value).reduce((a, b) => a * b, 1);
ret.value = Math.max(0, ret.value * bonus);
}
mods = arr.filter((pair) => pair.mod.operation === M5ModOperation.DIVISION);
if (mods.length !== 0) {
ret.mods = ret.mods.concat(mods.map(this.pairAsSource));
const bonus = mods.map((p) => p.mod.value).reduce((a, b) => a * b, 1);
ret.value = Math.max(0, Math.floor(ret.value / bonus));
}
}
mods = arr.filter(pair => pair.mod.operation === M5ModOperation.DIVISION);
if (mods.length !== 0) {
ret.mods = ret.mods.concat(mods.map(this.pairAsSource));
const bonus = mods.map(p => p.mod.value).reduce((a, b) => a * b, 1);
ret.value = Math.max(0, Math.floor(ret.value / bonus));
}
}
return ret;
}
return ret;
}
static attributeMinMax(attribute: M5Attribute) {
return Math.min(100, Math.max(0, attribute.value + attribute.bonus));
}
static attributeMinMax(attribute: M5Attribute) {
return Math.min(100, Math.max(0, attribute.value + attribute.bonus));
}
static attributeBonus(value: number) {
if (value > 95) return 2;
if (value > 80) return 1;
if (value > 20) return 0;
if (value > 5) return -1;
return -2;
}
static attributeBonus(value: number) {
if (value > 95) return 2;
if (value > 80) return 1;
if (value > 20) return 0;
if (value > 5) return -1;
return -2;
}
//static modToString(mod: M5ItemMod): string { }
//static modToString(mod: M5ItemMod): string { }
}
+405 -300
View File
@@ -1,335 +1,440 @@
import { M5Character } from "../actors/M5Character";
import M5ModAggregate from "../actors/M5ModAggregate";
import { enumKeys, M5Attributes, M5ModOperation, M5ModPair, M5ModType, M5RollData, M5RollResult, M5Stats } from "../M5Base";
import { M5Roll } from "../rolls/M5Roll";
import { M5Character } from '../actors/M5Character';
import M5ModAggregate from '../actors/M5ModAggregate';
import {
enumKeys,
M5Attributes,
M5ModOperation,
M5ModPair,
M5ModType,
M5RollData,
M5RollResult,
M5Stats,
} from '../M5Base';
import { M5Roll } from '../rolls/M5Roll';
export class M5Item extends Item {
static readonly SKILL = "skill";
static readonly SKILL = 'skill';
prepareDerivedData() {
const itemId: string = (this as any).id;
const itemType: string = (this as any).type;
const actor = this.actor as any;
const character = actor as M5Character;
const itemData = (this as any).system;
const calc = itemData.calc;
prepareDerivedData() {
const itemId: string = (this as any).id;
const itemType: string = (this as any).type;
const actor = this.actor as any;
const character = actor as M5Character;
const itemData = (this as any).system;
const calc = itemData.calc;
if (itemType === "item") {
calc.containers = null;
if (itemType === 'item') {
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 === "skill") {
calc.fw = itemData.fw;
calc.bonus = 0;
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 === 'skill') {
calc.fw = itemData.fw;
calc.bonus = 0;
let pairs: Array<M5ModPair> = [
{
source: (this as any).name,
mod: {
type: M5ModType.SKILL,
id: itemId,
operation: M5ModOperation.SET,
value: itemData.fw,
},
},
];
let pairs: Array<M5ModPair> = [
{
source: (this as any).name,
mod: {
type: M5ModType.SKILL,
id: itemId,
operation: M5ModOperation.SET,
value: itemData.fw,
},
},
];
if (character) {
const actorCalc = character.derivedData({ skills: true, weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true, effects: true, kampfkuenste: true });
if (actorCalc?.skillMods && Object.keys(actorCalc.skillMods).indexOf(itemId) !== -1) {
pairs = pairs.concat(actorCalc.skillMods[itemId]);
}
if (character) {
const actorCalc = character.derivedData({
skills: true,
weapons: true,
defensiveWeapons: true,
armor: true,
items: true,
spells: true,
effects: true,
kampfkuenste: true,
});
if (actorCalc?.skillMods && Object.keys(actorCalc.skillMods).indexOf(itemId) !== -1) {
pairs = pairs.concat(actorCalc.skillMods[itemId]);
}
if (itemData?.attribute && itemData.attribute !== "") {
pairs.push({
source: (this as any).name,
mod: {
type: M5ModType.SKILL,
id: itemId,
operation: M5ModOperation.ADD,
value: actorCalc.attributes[itemData.attribute].bonus,
},
});
}
}
if (itemData?.attribute && itemData.attribute !== '') {
pairs.push({
source: (this as any).name,
mod: {
type: M5ModType.SKILL,
id: itemId,
operation: M5ModOperation.ADD,
value: actorCalc.attributes[itemData.attribute].bonus,
},
});
}
}
const res = M5ModAggregate.processPairs(pairs);
res.mods.forEach((mod) => {
if ([M5ModOperation.SET, M5ModOperation.FIXED].includes(mod.operation)) calc.fw = mod.value;
else if ([M5ModOperation.SUBTRACT].includes(mod.operation)) calc.bonus -= mod.value;
else if ([M5ModOperation.ADD].includes(mod.operation)) calc.bonus += mod.value;
});
const res = M5ModAggregate.processPairs(pairs);
res.mods.forEach(mod => {
if ([M5ModOperation.SET, M5ModOperation.FIXED].includes(mod.operation)) calc.fw = mod.value;
else if ([M5ModOperation.SUBTRACT].includes(mod.operation)) calc.bonus -= mod.value;
else if ([M5ModOperation.ADD].includes(mod.operation)) calc.bonus += mod.value;
});
calc.ew = calc.fw + calc.bonus;
calc.sources = res.mods;
} else if (itemType === "weapon") {
calc.fw = 0;
calc.bonus = 0;
calc.special = itemData.special ? 2 : 0;
calc.ew = calc.special + itemData.stats.attackBonus;
calc.combatSkills = null;
calc.containers = null;
calc.ew = calc.fw + calc.bonus;
calc.sources = res.mods;
} else if (itemType === 'weapon') {
calc.fw = 0;
calc.bonus = 0;
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;
}
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) {
skill.prepareDerivedData();
const skillData = skill.system;
calc.ew += skillData.calc.ew;
calc.bonus += skillData.calc.bonus;
calc.fw += skillData.fw;
}
}
} else if (itemType === "defensiveWeapon") {
calc.fw = 0;
calc.bonus = 0;
calc.special = itemData.special ? 2 : 0;
calc.ew = calc.special + itemData.stats.defenseBonus;
calc.combatSkills = null;
calc.containers = null;
const skill = character.getItem(itemData.skillId);
//console.log("M5Item.prepareDerivedData:weapon", itemData, skill?.system)
if (skill) {
skill.prepareDerivedData();
const skillData = skill.system;
calc.ew += skillData.calc.ew;
calc.bonus += skillData.calc.bonus;
calc.fw += skillData.fw;
}
}
} else if (itemType === 'defensiveWeapon') {
calc.fw = 0;
calc.bonus = 0;
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;
}
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 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) {
skill.prepareDerivedData();
const skillData = skill.system;
calc.ew += skillData.calc.ew;
calc.bonus += skillData.calc.bonus;
calc.fw += skillData.fw;
}
}
} else if (itemType === "armor") {
itemData.mods[0] = { type: "stat", id: "defenseBonus", operation: "add", value: itemData.stats.defenseBonus };
itemData.mods[1] = { type: "stat", id: "attackBonus", operation: "add", value: itemData.stats.attackBonus };
itemData.mods[2] = { type: "stat", id: "movement", operation: "add", value: itemData.stats.movementBonus };
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) {
const actorCalc = character.derivedData({ weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true, effects: true, kampfkuenste: true });
if (actorCalc) {
calc.ew = actorCalc.stats.spellCasting.value;
}
}
} else if (itemType === "kampfkunst") {
calc.fw = 0;
calc.bonus = 0;
calc.ew = 0;
calc.generalSkills = null;
const skill = character.getItem(itemData.skillId);
//console.log("M5Item.prepareDerivedData:weapon", itemData, skill?.system)
if (skill) {
skill.prepareDerivedData();
const skillData = skill.system;
calc.ew += skillData.calc.ew;
calc.bonus += skillData.calc.bonus;
calc.fw += skillData.fw;
}
}
} else if (itemType === 'armor') {
itemData.mods[0] = {
type: 'stat',
id: 'defenseBonus',
operation: 'add',
value: itemData.stats.defenseBonus,
};
itemData.mods[1] = {
type: 'stat',
id: 'attackBonus',
operation: 'add',
value: itemData.stats.attackBonus,
};
itemData.mods[2] = {
type: 'stat',
id: 'movement',
operation: 'add',
value: itemData.stats.movementBonus,
};
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) {
const actorCalc = character.derivedData({
weapons: true,
defensiveWeapons: true,
armor: true,
items: true,
spells: true,
effects: true,
kampfkuenste: true,
});
if (actorCalc) {
calc.ew = actorCalc.stats.spellCasting.value;
}
}
} else if (itemType === 'kampfkunst') {
calc.fw = 0;
calc.bonus = 0;
calc.ew = 0;
calc.generalSkills = null;
if (actor) {
const actorCalc = character.derivedData({ weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true, effects: true, kampfkuenste: true });
if (actorCalc) {
calc.generalSkills = actorCalc.skills.general;
}
if (actor) {
const actorCalc = character.derivedData({
weapons: true,
defensiveWeapons: true,
armor: true,
items: true,
spells: true,
effects: true,
kampfkuenste: true,
});
if (actorCalc) {
calc.generalSkills = actorCalc.skills.general;
}
const skill = character.getItem(itemData.skillId);
if (skill) {
skill.prepareDerivedData();
const skillData = skill.system;
calc.ew = skillData.calc.ew;
calc.fw = skillData.fw + calc.bonus;
itemData.rolls.formulas[0].label = skill.name;
}
}
}
if (itemData?.mods) {
calc.mods = {};
for (let modKey in itemData.mods) {
if (itemData.mods[modKey].type === M5ModType.SKILL && itemData.mods[modKey].id?.includes("midgard5")) {
itemData.mods[modKey].id = actor?.items.find((x) => x.name === game["i18n"].localize(itemData.mods[modKey].id))?.id;
}
}
const skill = character.getItem(itemData.skillId);
if (skill) {
skill.prepareDerivedData();
const skillData = skill.system;
calc.ew = skillData.calc.ew;
calc.fw = skillData.fw + calc.bonus;
itemData.rolls.formulas[0].label = skill.name;
}
}
}
if (itemData?.mods) {
calc.mods = {};
for (let modKey in itemData.mods) {
if (itemData.mods[modKey].type === M5ModType.SKILL && itemData.mods[modKey].id?.includes('midgard5')) {
itemData.mods[modKey].id = actor?.items.find(
x => x.name === game['i18n'].localize(itemData.mods[modKey].id)
)?.id;
}
}
Object.keys(itemData?.mods).forEach((key) => {
const mod = itemData.mods[key];
const modCalc = {};
switch (mod.type) {
case M5ModType.ATTRIBUTE: {
for (const key of enumKeys(M5Attributes)) {
const val: string = M5Attributes[key];
modCalc[val] = (game as Game).i18n.localize(`midgard5.actor-${val}-long`);
}
break;
}
case M5ModType.STAT: {
for (const key of enumKeys(M5Stats)) {
const val: string = M5Stats[key];
modCalc[val] = (game as Game).i18n.localize(`midgard5.mod-stat-${val}`);
}
break;
}
case M5ModType.SKILL: {
if (character) {
const actorCalc = character.derivedData({ weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true, effects: true, kampfkuenste: true });
if (actorCalc) {
let category = (game as Game).i18n.localize("midgard5.skill");
Object.keys(actorCalc.skills.general).forEach((skillId) => {
const skill = character.getItem(skillId);
if (skill) modCalc[skillId] = `${category}: ${skill.name}`;
});
Object.keys(itemData?.mods).forEach(key => {
const mod = itemData.mods[key];
const modCalc = {};
switch (mod.type) {
case M5ModType.ATTRIBUTE: {
for (const key of enumKeys(M5Attributes)) {
const val: string = M5Attributes[key];
modCalc[val] = (game as Game).i18n.localize(`midgard5.actor-${val}-long`);
}
break;
}
case M5ModType.STAT: {
for (const key of enumKeys(M5Stats)) {
const val: string = M5Stats[key];
modCalc[val] = (game as Game).i18n.localize(`midgard5.mod-stat-${val}`);
}
break;
}
case M5ModType.SKILL: {
if (character) {
const actorCalc = character.derivedData({
weapons: true,
defensiveWeapons: true,
armor: true,
items: true,
spells: true,
effects: true,
kampfkuenste: true,
});
if (actorCalc) {
let category = (game as Game).i18n.localize('midgard5.skill');
Object.keys(actorCalc.skills.general).forEach(skillId => {
const skill = character.getItem(skillId);
if (skill) modCalc[skillId] = `${category}: ${skill.name}`;
});
category = (game as Game).i18n.localize("midgard5.language");
Object.keys(actorCalc.skills.language).forEach((skillId) => {
const skill = character.getItem(skillId);
if (skill) modCalc[skillId] = `${category}: ${skill.name}`;
});
category = (game as Game).i18n.localize('midgard5.language');
Object.keys(actorCalc.skills.language).forEach(skillId => {
const skill = character.getItem(skillId);
if (skill) modCalc[skillId] = `${category}: ${skill.name}`;
});
category = (game as Game).i18n.localize("midgard5.weapon-skill");
Object.keys(actorCalc.skills.combat).forEach((skillId) => {
const skill = character.getItem(skillId);
if (skill) modCalc[skillId] = `${category}: ${skill.name}`;
});
category = (game as Game).i18n.localize('midgard5.weapon-skill');
Object.keys(actorCalc.skills.combat).forEach(skillId => {
const skill = character.getItem(skillId);
if (skill) modCalc[skillId] = `${category}: ${skill.name}`;
});
category = (game as Game).i18n.localize("midgard5.innate-ability");
Object.keys(actorCalc.skills.innate).forEach((skillId) => {
const skill = character.getItem(skillId);
if (skill) modCalc[skillId] = `${category}: ${skill.name}`;
});
}
}
break;
}
}
category = (game as Game).i18n.localize('midgard5.innate-ability');
Object.keys(actorCalc.skills.innate).forEach(skillId => {
const skill = character.getItem(skillId);
if (skill) modCalc[skillId] = `${category}: ${skill.name}`;
});
}
}
break;
}
}
calc.mods[key] = modCalc;
});
}
}
calc.mods[key] = modCalc;
});
}
}
getRollData() {
const actor = this.actor as any;
const item = this as any;
getRollData() {
const actor = this.actor as any;
const item = this as any;
let ret: M5RollData = actor?.getRollData() ?? {
c: null,
i: null,
iType: null,
rolls: {},
res: {},
};
let ret: M5RollData = actor?.getRollData() ?? {
c: null,
i: null,
iType: null,
rolls: {},
res: {},
};
ret.i = item.system;
ret.iType = item.type;
return ret;
}
ret.i = item.system;
ret.iType = item.type;
return ret;
}
async roll() {
const item = this as any;
async roll() {
const item = this as any;
// Initialize chat data.
const speaker = ChatMessage.getSpeaker({ actor: this.actor });
const rollMode = (game as Game).settings.get("core", "rollMode");
const label = `[${item.type}] ${item.name}`;
// Initialize chat data.
const speaker = ChatMessage.getSpeaker({ actor: this.actor });
const rollMode = (game as Game).settings.get('core', 'rollMode');
const label = `[${item.type}] ${item.name}`;
// If there's no roll data, send a chat message.
const formulaNames = item.system.rolls?.formulas ? Object.keys(item.system.rolls.formulas) : [];
if (formulaNames.length > 0) {
const rollData = this.getRollData();
formulaNames.forEach((formulaName) => {
const formula = item.system.rolls.formulas[formulaName];
if (formula) {
rollData.rolls[formulaName] = {
formula: formula.formula,
label: formula.label,
enabled: formula.enabled,
result: "",
total: 0,
totalStr: "",
dice: {},
} as M5RollResult;
}
});
// If there's no roll data, send a chat message.
const formulaNames = item.system.rolls?.formulas ? Object.keys(item.system.rolls.formulas) : [];
if (formulaNames.length > 0) {
const rollData = this.getRollData();
formulaNames.forEach(formulaName => {
const formula = item.system.rolls.formulas[formulaName];
if (formula) {
rollData.rolls[formulaName] = {
formula: formula.formula,
label: formula.label,
enabled: formula.enabled,
result: '',
total: 0,
totalStr: '',
dice: {},
} as M5RollResult;
}
});
if (item.type === "spell" || item.type === "kampfkunst") {
if (this.actor["system"].ap.value >= item.system.ap) {
this.actor["system"].ap.value -= item.system.ap;
}
}
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);
return roll.toMessage();
} else {
ChatMessage.create({
speaker: speaker,
rollMode: rollMode,
flavor: label,
content: item.system.description ?? "",
});
return null;
}
}
const roll = new M5Roll(rollData, this.actor, item.name);
return roll.toMessage();
} else {
ChatMessage.create({
speaker: speaker,
rollMode: rollMode,
flavor: label,
content: item.system.description ?? '',
});
return null;
}
}
getItem(itemId: string): any {
return (this as any).getEmbeddedDocument("Item", itemId);
}
getItem(itemId: string): any {
return (this as any).getEmbeddedDocument('Item', itemId);
}
// migrateSystemData(): any {
// const item = (this as any)
// const data = item.system
// migrateSystemData(): any {
// const item = (this as any)
// const data = item.system
// if (item.type === "spell") {
// if (typeof data.ap !== "string") {
// data.ap = Number.isFinite(data.ap) ? "" + data.ap : ""
// }
// }
// if (item.type === "spell") {
// if (typeof data.ap !== "string") {
// data.ap = Number.isFinite(data.ap) ? "" + data.ap : ""
// }
// }
// return super.migrateSystemData()
// }
// return super.migrateSystemData()
// }
}
+276 -269
View File
@@ -1,322 +1,329 @@
import { Evaluated } from "@league-of-foundry-developers/foundry-vtt-types/src/foundry/client/dice/roll";
import { M5Character } from "../actors/M5Character";
import { M5EwResult, M5ModOperation, M5ModType, M5RollData, M5RollResult, M5SkillUnlearned, M5Stats } from "../M5Base";
import { stat } from "fs";
import { Evaluated } from '@league-of-foundry-developers/foundry-vtt-types/src/foundry/client/dice/roll';
import { M5Character } from '../actors/M5Character';
import { M5EwResult, M5ModOperation, M5ModType, M5RollData, M5RollResult, M5SkillUnlearned, M5Stats } from '../M5Base';
import { stat } from 'fs';
export class M5Roll {
// extends Roll<M5RollData>
static readonly TEMPLATE_PATH = "systems/midgard5/templates/chat/roll-m5.hbs";
// extends Roll<M5RollData>
static readonly TEMPLATE_PATH = 'systems/midgard5/templates/chat/roll-m5.hbs';
public _evaluated: boolean = false;
public _total: number = 0;
public pool: PoolTerm = null;
public _evaluated: boolean = false;
public _total: number = 0;
public pool: PoolTerm = null;
constructor(public data: M5RollData, public actor: any, public label: string) {
//super(null)
//this.data = rollData
}
constructor(
public data: M5RollData,
public actor: any,
public label: string
) {
//super(null)
//this.data = rollData
}
// @ts-ignore
//override evaluate(options?: InexactPartial<RollTerm.EvaluationOptions>): Evaluated<Roll<M5RollData>> | Promise<Evaluated<Roll<M5RollData>>> {
evaluate() {
const indexMap = new Map<number, string>();
const rollNames = Object.keys(this.data.rolls);
const rolls = rollNames
.filter((rollName) => this.data.rolls[rollName].enabled)
.map((rollName, index) => {
indexMap.set(index, rollName);
const formula = this.data.rolls[rollName];
const roll = new Roll(formula.formula, this.data);
return roll;
});
// @ts-ignore
//override evaluate(options?: InexactPartial<RollTerm.EvaluationOptions>): Evaluated<Roll<M5RollData>> | Promise<Evaluated<Roll<M5RollData>>> {
evaluate() {
const indexMap = new Map<number, string>();
const rollNames = Object.keys(this.data.rolls);
const rolls = rollNames
.filter(rollName => this.data.rolls[rollName].enabled)
.map((rollName, index) => {
indexMap.set(index, rollName);
const formula = this.data.rolls[rollName];
const roll = new Roll(formula.formula, this.data);
return roll;
});
this.pool = PoolTerm.fromRolls(rolls);
console.log("evaluate", this._evaluated, this.pool);
return this.pool.evaluate({ async: true }).then((results) => {
this._total = 0;
this.pool = PoolTerm.fromRolls(rolls);
console.log('evaluate', this._evaluated, this.pool);
return this.pool.evaluate({ async: true }).then(results => {
this._total = 0;
results.rolls.forEach((roll, index) => {
const rollIndex = indexMap.get(index);
const rollResult = this.data.rolls[rollIndex] as M5RollResult;
results.rolls.forEach((roll, index) => {
const rollIndex = indexMap.get(index);
const rollResult = this.data.rolls[rollIndex] as M5RollResult;
rollResult.result = roll.result;
rollResult.total = roll.total;
rollResult.totalStr = roll.total.toString();
rollResult.result = roll.result;
rollResult.total = roll.total;
rollResult.totalStr = roll.total.toString();
this._total += roll.total;
this._total += roll.total;
let rowRes = M5EwResult.TBD;
let face100 = -1;
let rowRes = M5EwResult.TBD;
let face100 = -1;
roll.dice.forEach((d, dIndex) => {
rollResult.dice[dIndex.toString()] = d.total;
roll.dice.forEach((d, dIndex) => {
rollResult.dice[dIndex.toString()] = d.total;
if (rowRes === M5EwResult.TBD && dIndex === 0) {
if (d.faces === 20) {
//if (rollResult.type === "ew") {
if (d.total === 1) rowRes = M5EwResult.FUMBLE;
else if (d.total === 20) rowRes = M5EwResult.CRITICAL;
else if (d.total >= 16) rowRes = M5EwResult.HIGH;
} else if (d.faces === 100) {
face100 = d.total as number;
}
}
});
if (rowRes === M5EwResult.TBD && dIndex === 0) {
if (d.faces === 20) {
//if (rollResult.type === "ew") {
if (d.total === 1) rowRes = M5EwResult.FUMBLE;
else if (d.total === 20) rowRes = M5EwResult.CRITICAL;
else if (d.total >= 16) rowRes = M5EwResult.HIGH;
} else if (d.faces === 100) {
face100 = d.total as number;
}
}
});
const parseResult = M5Roll.parseDiceSides(rollResult.formula);
//console.log("evaluate roll", parseResult)
if (parseResult?.sides === 20) {
if (roll.total < 20) {
if (rowRes === M5EwResult.TBD || rowRes === M5EwResult.HIGH) rowRes = M5EwResult.FAIL;
} else {
if (rowRes === M5EwResult.TBD) rowRes = M5EwResult.PASS;
}
} else if (face100 >= 0) {
const threshold100 = roll.total + face100;
const threshold = Math.floor(threshold100 / 10);
if (face100 === 100) {
if (rowRes === M5EwResult.TBD) rowRes = M5EwResult.FUMBLE;
} else if (roll.total < 0) {
if (rowRes === M5EwResult.TBD) rowRes = M5EwResult.FAIL;
} else if (face100 <= threshold) {
if (rowRes === M5EwResult.TBD) rowRes = M5EwResult.CRITICAL;
} else {
if (rowRes === M5EwResult.TBD) rowRes = M5EwResult.PASS;
}
}
rollResult.css = rowRes;
});
const parseResult = M5Roll.parseDiceSides(rollResult.formula);
//console.log("evaluate roll", parseResult)
if (parseResult?.sides === 20) {
if (roll.total < 20) {
if (rowRes === M5EwResult.TBD || rowRes === M5EwResult.HIGH) rowRes = M5EwResult.FAIL;
} else {
if (rowRes === M5EwResult.TBD) rowRes = M5EwResult.PASS;
}
} else if (face100 >= 0) {
const threshold100 = roll.total + face100;
const threshold = Math.floor(threshold100 / 10);
if (face100 === 100) {
if (rowRes === M5EwResult.TBD) rowRes = M5EwResult.FUMBLE;
} else if (roll.total < 0) {
if (rowRes === M5EwResult.TBD) rowRes = M5EwResult.FAIL;
} else if (face100 <= threshold) {
if (rowRes === M5EwResult.TBD) rowRes = M5EwResult.CRITICAL;
} else {
if (rowRes === M5EwResult.TBD) rowRes = M5EwResult.PASS;
}
}
rollResult.css = rowRes;
});
this.data.res.label = this.label;
this.data.res.label = this.label;
this._evaluated = true;
return this;
});
}
this._evaluated = true;
return this;
});
}
async render(): Promise<string> {
return renderTemplate(M5Roll.TEMPLATE_PATH, this.data);
}
async render(): Promise<string> {
return renderTemplate(M5Roll.TEMPLATE_PATH, this.data);
}
async toMessage() {
if (!this._evaluated) await this.evaluate();
async toMessage() {
if (!this._evaluated) await this.evaluate();
const rMode = (game as Game).settings.get("core", "rollMode");
const rMode = (game as Game).settings.get('core', 'rollMode');
const chatData = {
type: CONST.CHAT_MESSAGE_TYPES.ROLL,
content: await this.render(),
speaker: ChatMessage.getSpeaker({ actor: this.actor }),
sound: CONFIG.sounds.dice,
roll: Roll.fromTerms([this.pool]),
};
const chatData = {
type: CONST.CHAT_MESSAGE_TYPES.ROLL,
content: await this.render(),
speaker: ChatMessage.getSpeaker({ actor: this.actor }),
sound: CONFIG.sounds.dice,
roll: Roll.fromTerms([this.pool]),
};
ChatMessage.applyRollMode(chatData, rMode);
return ChatMessage.create(chatData);
}
ChatMessage.applyRollMode(chatData, rMode);
return ChatMessage.create(chatData);
}
static fromAttributeValue(actor: any, attributeKey: string, attributeValue: number) {
const rollData = actor.getRollData() as M5RollData;
const itemData = actor.items.filter((x) => x.type === "effect").map((y) => y.system.mods);
rollData.c = 0;
for (let effectKey in itemData) {
for (let modkey in itemData[effectKey])
if (itemData[effectKey][modkey].type === M5ModType.ATTRIBUTE && itemData[effectKey][modkey].operation === M5ModOperation.ROLL) {
rollData.c += itemData[effectKey][modkey].value;
}
}
static fromAttributeValue(actor: any, attributeKey: string, attributeValue: number) {
const rollData = actor.getRollData() as M5RollData;
const itemData = actor.items.filter(x => x.type === 'effect').map(y => y.system.mods);
rollData.c = 0;
for (let effectKey in itemData) {
for (let modkey in itemData[effectKey])
if (
itemData[effectKey][modkey].type === M5ModType.ATTRIBUTE &&
itemData[effectKey][modkey].operation === M5ModOperation.ROLL
) {
rollData.c += itemData[effectKey][modkey].value;
}
}
rollData.i = attributeValue;
rollData.rolls["0"] = {
formula: "@i - 1d100 - @c",
enabled: true,
label: (game as Game).i18n.localize("midgard5.pw"),
result: "",
total: 0,
totalStr: "",
dice: {},
css: "",
} as M5RollResult;
rollData.i = attributeValue;
rollData.rolls['0'] = {
formula: '@i - 1d100 - @c',
enabled: true,
label: (game as Game).i18n.localize('midgard5.pw'),
result: '',
total: 0,
totalStr: '',
dice: {},
css: '',
} as M5RollResult;
return new M5Roll(rollData, actor, (game as Game).i18n.localize(`midgard5.actor-${attributeKey}-long`));
}
return new M5Roll(rollData, actor, (game as Game).i18n.localize(`midgard5.actor-${attributeKey}-long`));
}
static fromUnlearnedSkill(actor: any, skill: M5SkillUnlearned, skillName: string) {
const rollData = actor.getRollData() as M5RollData;
rollData.i = {
fw: skill.fw,
bonus: actor.system.calc?.attributes[skill.attribute]?.bonus ?? 0,
};
rollData.iType = "skill";
static fromUnlearnedSkill(actor: any, skill: M5SkillUnlearned, skillName: string) {
const rollData = actor.getRollData() as M5RollData;
rollData.i = {
fw: skill.fw,
bonus: actor.system.calc?.attributes[skill.attribute]?.bonus ?? 0,
};
rollData.iType = 'skill';
rollData.rolls["0"] = {
formula: "1d20 + @i.fw + @i.bonus",
enabled: true,
label: (game as Game).i18n.localize("midgard5.pw"),
result: "",
total: 0,
totalStr: "",
dice: {},
css: "",
} as M5RollResult;
rollData.rolls['0'] = {
formula: '1d20 + @i.fw + @i.bonus',
enabled: true,
label: (game as Game).i18n.localize('midgard5.pw'),
result: '',
total: 0,
totalStr: '',
dice: {},
css: '',
} as M5RollResult;
return new M5Roll(rollData, actor, (game as Game).i18n.localize(`midgard5.${skillName}`));
}
return new M5Roll(rollData, actor, (game as Game).i18n.localize(`midgard5.${skillName}`));
}
static brawl(actor: any) {
const rollData = actor.getRollData() as M5RollData;
rollData.i = {
attackBonus: 0,
damageBonus: 0,
};
static brawl(actor: any) {
const rollData = actor.getRollData() as M5RollData;
rollData.i = {
attackBonus: 0,
damageBonus: 0,
};
rollData.rolls["0"] = {
formula: "1d20 + @c.calc.stats.brawlFw",
enabled: true,
label: (game as Game).i18n.localize("midgard5.attack"),
result: "",
total: 0,
totalStr: "",
dice: {},
css: "",
} as M5RollResult;
rollData.rolls['0'] = {
formula: '1d20 + @c.calc.stats.brawlFw',
enabled: true,
label: (game as Game).i18n.localize('midgard5.attack'),
result: '',
total: 0,
totalStr: '',
dice: {},
css: '',
} as M5RollResult;
rollData.rolls["1"] = {
formula: "1d6 - 4 + @c.calc.stats.damageBonus.value",
enabled: true,
label: (game as Game).i18n.localize("midgard5.damage"),
result: "",
total: 0,
totalStr: "",
dice: {},
css: "",
} as M5RollResult;
rollData.rolls['1'] = {
formula: '1d6 - 4 + @c.calc.stats.damageBonus.value',
enabled: true,
label: (game as Game).i18n.localize('midgard5.damage'),
result: '',
total: 0,
totalStr: '',
dice: {},
css: '',
} as M5RollResult;
return new M5Roll(rollData, actor, (game as Game).i18n.localize("midgard5.brawl"));
}
return new M5Roll(rollData, actor, (game as Game).i18n.localize('midgard5.brawl'));
}
static perception(actor: any) {
const rollData = actor.getRollData() as M5RollData;
static perception(actor: any) {
const rollData = actor.getRollData() as M5RollData;
rollData.rolls["0"] = {
formula: "1d20 + @c.calc.stats.perception.value + @c.calc.stats.perceptionFW",
enabled: true,
label: (game as Game).i18n.localize("midgard5.perception"),
result: "",
total: 0,
totalStr: "",
dice: {},
css: "",
} as M5RollResult;
rollData.rolls['0'] = {
formula: '1d20 + @c.calc.stats.perception.value + @c.calc.stats.perceptionFW',
enabled: true,
label: (game as Game).i18n.localize('midgard5.perception'),
result: '',
total: 0,
totalStr: '',
dice: {},
css: '',
} as M5RollResult;
return new M5Roll(rollData, actor, (game as Game).i18n.localize("midgard5.perception"));
}
return new M5Roll(rollData, actor, (game as Game).i18n.localize('midgard5.perception'));
}
static drinking(actor: any) {
const rollData = actor.getRollData() as M5RollData;
static drinking(actor: any) {
const rollData = actor.getRollData() as M5RollData;
rollData.rolls["0"] = {
formula: "1d20 + @c.calc.stats.drinking.value + @c.calc.stats.drinkingFW",
enabled: true,
label: (game as Game).i18n.localize("midgard5.drinking"),
result: "",
total: 0,
totalStr: "",
dice: {},
css: "",
} as M5RollResult;
rollData.rolls['0'] = {
formula: '1d20 + @c.calc.stats.drinking.value + @c.calc.stats.drinkingFW',
enabled: true,
label: (game as Game).i18n.localize('midgard5.drinking'),
result: '',
total: 0,
totalStr: '',
dice: {},
css: '',
} as M5RollResult;
return new M5Roll(rollData, actor, (game as Game).i18n.localize("midgard5.drinking"));
}
return new M5Roll(rollData, actor, (game as Game).i18n.localize('midgard5.drinking'));
}
static defense(actor: any) {
const rollData = actor.getRollData() as M5RollData;
rollData.i = {
defenseBonus: 0,
};
static defense(actor: any) {
const rollData = actor.getRollData() as M5RollData;
rollData.i = {
defenseBonus: 0,
};
rollData.rolls["0"] = {
formula: "1d20 + @c.calc.stats.defense.value + @c.calc.stats.defenseBonus.value",
enabled: true,
label: (game as Game).i18n.localize("midgard5.defense"),
result: "",
total: 0,
totalStr: "",
dice: {},
css: "",
} as M5RollResult;
rollData.rolls['0'] = {
formula: '1d20 + @c.calc.stats.defense.value + @c.calc.stats.defenseBonus.value',
enabled: true,
label: (game as Game).i18n.localize('midgard5.defense'),
result: '',
total: 0,
totalStr: '',
dice: {},
css: '',
} as M5RollResult;
return new M5Roll(rollData, actor, (game as Game).i18n.localize("midgard5.defense"));
}
return new M5Roll(rollData, actor, (game as Game).i18n.localize('midgard5.defense'));
}
static resistanceMind(actor: any) {
const rollData = actor.getRollData() as M5RollData;
rollData.i = {
defenseBonus: 0,
};
static resistanceMind(actor: any) {
const rollData = actor.getRollData() as M5RollData;
rollData.i = {
defenseBonus: 0,
};
rollData.rolls["0"] = {
formula: "1d20 + @c.calc.stats.resistanceMind.value",
enabled: true,
label: (game as Game).i18n.localize("midgard5.resistanceMind"),
result: "",
total: 0,
totalStr: "",
dice: {},
css: "",
} as M5RollResult;
rollData.rolls['0'] = {
formula: '1d20 + @c.calc.stats.resistanceMind.value',
enabled: true,
label: (game as Game).i18n.localize('midgard5.resistanceMind'),
result: '',
total: 0,
totalStr: '',
dice: {},
css: '',
} as M5RollResult;
return new M5Roll(rollData, actor, (game as Game).i18n.localize("midgard5.resistanceMind"));
}
return new M5Roll(rollData, actor, (game as Game).i18n.localize('midgard5.resistanceMind'));
}
static resistanceBody(actor: any) {
const rollData = actor.getRollData() as M5RollData;
rollData.i = {
defenseBonus: 0,
};
static resistanceBody(actor: any) {
const rollData = actor.getRollData() as M5RollData;
rollData.i = {
defenseBonus: 0,
};
rollData.rolls["0"] = {
formula: "1d20 + @c.calc.stats.resistanceBody.value",
enabled: true,
label: (game as Game).i18n.localize("midgard5.resistanceBody"),
result: "",
total: 0,
totalStr: "",
dice: {},
css: "",
} as M5RollResult;
rollData.rolls['0'] = {
formula: '1d20 + @c.calc.stats.resistanceBody.value',
enabled: true,
label: (game as Game).i18n.localize('midgard5.resistanceBody'),
result: '',
total: 0,
totalStr: '',
dice: {},
css: '',
} as M5RollResult;
return new M5Roll(rollData, actor, (game as Game).i18n.localize("midgard5.resistanceBody"));
}
return new M5Roll(rollData, actor, (game as Game).i18n.localize('midgard5.resistanceBody'));
}
static parseDiceSides(formula: string): FormulaParseResult {
const ewMatcher: RegExp = /\d*[dD]20/g;
const pwMatcher: RegExp = /(\d+)\s*\-\s*\d*[dD]100/g;
static parseDiceSides(formula: string): FormulaParseResult {
const ewMatcher: RegExp = /\d*[dD]20/g;
const pwMatcher: RegExp = /(\d+)\s*\-\s*\d*[dD]100/g;
let res = formula.match(ewMatcher);
if (res && !!res[0]) {
return {
sides: 20,
type: "ew",
threshold: null,
};
}
let res = formula.match(ewMatcher);
if (res && !!res[0]) {
return {
sides: 20,
type: 'ew',
threshold: null,
};
}
res = formula.match(pwMatcher);
if (res && !!res[1]) {
return {
sides: 100,
type: "pw",
threshold: parseInt(res[1]),
};
}
res = formula.match(pwMatcher);
if (res && !!res[1]) {
return {
sides: 100,
type: 'pw',
threshold: parseInt(res[1]),
};
}
return null;
}
return null;
}
}
interface FormulaParseResult {
sides: number;
type: string;
threshold: number;
sides: number;
type: string;
threshold: number;
}
File diff suppressed because it is too large Load Diff
+192 -165
View File
@@ -1,195 +1,222 @@
import { M5Item } from "../items/M5Item"
import { M5Attributes, M5ItemMod, M5ModOperation, M5ModType, M5RollTemplate } from "../M5Base"
import { M5Item } from "../items/M5Item";
import {
M5Attributes,
M5ItemMod,
M5ModOperation,
M5ModType,
M5RollTemplate,
} from "../M5Base";
export class M5ItemSheet extends ItemSheet {
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
width: 640,
height: 480,
classes: ["midgard5", "sheet", "item"]
})
}
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
width: 640,
height: 480,
classes: ["midgard5", "sheet", "item"],
});
}
get template() {
//console.log("M5ItemSheet", this.item.data.type)
const path = "systems/midgard5/templates/sheets/item"
return `${path}/${this.item.type}.hbs`
}
get template() {
//console.log("M5ItemSheet", this.item.data.type)
const path = "systems/midgard5/templates/sheets/item";
return `${path}/${this.item.type}.hbs`;
}
override getData(options?: Partial<ItemSheet.Options>): ItemSheet.Data<ItemSheet.Options> | Promise<ItemSheet.Data<ItemSheet.Options>> {
const item = this.item as M5Item
return Promise.resolve(super.getData()).then(value => {
item.prepareDerivedData()
const context = value as any
override getData(
options?: Partial<ItemSheet.Options>,
):
| ItemSheet.Data<ItemSheet.Options>
| Promise<ItemSheet.Data<ItemSheet.Options>> {
const item = this.item as M5Item;
return Promise.resolve(super.getData()).then((value) => {
item.prepareDerivedData();
const context = value as any;
// Use a safe clone of the item data for further operations.
const itemData = context.item
// Use a safe clone of the item data for further operations.
const itemData = context.item;
// Retrieve the roll data for TinyMCE editors.
context.rollData = {}
let actor = this.object?.parent ?? null
if (actor) {
context.rollData = actor.getRollData()
}
context.data = itemData.system
context.flags = itemData.flags
return context
})
}
// Retrieve the roll data for TinyMCE editors.
context.rollData = {};
let actor = this.object?.parent ?? null;
if (actor) {
context.rollData = actor.getRollData();
}
override activateListeners(html: JQuery) {
super.activateListeners(html)
context.data = itemData.system;
context.flags = itemData.flags;
html.find(".add-mod").on("click", async (event) => {
const context = this.object
const mods = context.system.mods
const modIndex = Object.keys(mods).length
mods[modIndex.toString()] = {
type: M5ModType.ATTRIBUTE,
id: M5Attributes.ST,
operation: M5ModOperation.ADD,
value: 0
} as M5ItemMod
this.object.update({
data: {
mods: mods
}
})
})
return context;
});
}
html.find(".item-delete").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"]
}
override activateListeners(html: JQuery) {
super.activateListeners(html);
const context = this.item
const item = context.items.get(itemId)
item.delete()
this.render(false)
})
html.find(".add-mod").on("click", async (event) => {
const context = this.object;
const mods = context.system.mods;
const modIndex = Object.keys(mods).length;
mods[modIndex.toString()] = {
type: M5ModType.ATTRIBUTE,
id: M5Attributes.ST,
operation: M5ModOperation.ADD,
value: 0,
} as M5ItemMod;
this.object.update({
data: {
mods: mods,
},
});
});
html.find(".roll-delete").on("click", async (event) => {
//console.log("roll-delete", this.item.data.data.rolls.formulas)
html.find(".item-delete").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"];
}
let row = event.target.parentElement
let rollIndex = row.dataset["roll"]
while (!rollIndex) {
row = row.parentElement
if (!row)
return
rollIndex = row.dataset["roll"]
}
const context = this.item;
const item = context.items.get(itemId);
item.delete();
this.render(false);
});
const rolls = this.item.system.rolls.formulas
rolls[rollIndex] = null
html.find(".mod-delete").on("click", async (event) => {
let row = event.target.parentElement;
let itemId = row.dataset["mod"];
while (!itemId) {
row = row.parentElement;
if (!row) return;
itemId = row.dataset["mod"];
}
const context = this.item;
delete context.system.mods[itemId];
this.render(false);
});
this.item.update({
data: {
rolls: {
formulas: rolls
}
}
})
this.render(false)
})
html.find(".roll-delete").on("click", async (event) => {
//console.log("roll-delete", this.item.data.data.rolls.formulas)
html.find(".roll-create").on("click", async (event) => {
const rolls = this.item.system.rolls.formulas
let row = event.target.parentElement;
let rollIndex = row.dataset["roll"];
while (!rollIndex) {
row = row.parentElement;
if (!row) return;
rollIndex = row.dataset["roll"];
}
const indeces = Object.keys(rolls).map(index => parseInt(index)).sort().reverse()
const index = (indeces.find(index => !!rolls[index.toString()]) ?? -1) + 1
console.log("roll-create", rolls, indeces, index)
const rolls = this.item.system.rolls.formulas;
rolls[rollIndex] = null;
rolls[index.toString()] = {
formula: "1d6",
label: (game as Game).i18n.localize("midgard5.roll"),
enabled: true
} as M5RollTemplate
this.item.update({
data: {
rolls: {
formulas: rolls,
},
},
});
this.render(false);
});
this.item.update({
data: {
rolls: {
formulas: rolls
}
}
})
this.render(false)
})
html.find(".roll-create").on("click", async (event) => {
const rolls = this.item.system.rolls.formulas;
// Drag & Drop
if (["item"].includes(this.object.type)) {
const itemToItemAssociation = new DragDrop({
dragSelector: ".item",
dropSelector: null,
permissions: { dragstart: this._canDragStart.bind(this), drop: this._canDragDrop.bind(this) },
callbacks: { drop: this._onDropItem.bind(this) },
})
itemToItemAssociation.bind(html[0])
}
}
const indeces = Object.keys(rolls)
.map((index) => parseInt(index))
.sort()
.reverse();
const index =
(indeces.find((index) => !!rolls[index.toString()]) ?? -1) + 1;
console.log("roll-create", rolls, indeces, index);
_canDragStart(selector) {
console.log("M5ItemSheet._canDragStart", selector)
return this.options.editable && this.object.isOwner
}
rolls[index.toString()] = {
formula: "1d6",
label: (game as Game).i18n.localize("midgard5.roll"),
enabled: true,
} as M5RollTemplate;
_canDragDrop(selector) {
console.log("M5ItemSheet._canDragDrop", selector)
return true
}
this.item.update({
data: {
rolls: {
formulas: rolls,
},
},
});
this.render(false);
});
async _onDropItem(event) {
let data
const obj = this.object
const li = event.currentTarget
// Drag & Drop
if (["item"].includes(this.object.type)) {
const itemToItemAssociation = new DragDrop({
dragSelector: ".item",
dropSelector: ".item-list",
permissions: {
dragstart: this._canDragStart.bind(this),
drop: this._canDragDrop.bind(this),
},
callbacks: { drop: this._onDropItem.bind(this) },
});
itemToItemAssociation.bind(html[0]);
}
}
try {
data = JSON.parse(event.dataTransfer.getData("text/plain"))
if (data.type !== "Item")
return false
} catch (err) {
return false
}
_canDragStart(selector) {
console.log("M5ItemSheet._canDragStart", selector);
return this.options.editable && this.object.isOwner;
}
// Case 1 - Import from a Compendium pack
let itemObject
if (data.pack) {
const compendiumObject = await (this as any).importItemFromCollection(data.pack, data.id)
itemObject = compendiumObject.data
}
_canDragDrop(selector) {
console.log("M5ItemSheet._canDragDrop", selector);
return true;
}
// Case 2 - Import from World entity
else {
const originalItem = await (game as Game).items.get(data.id)
itemObject = duplicate(originalItem)
if (!itemObject)
return
}
async _onDropItem(event) {
let data;
const obj = this.object;
const li = event.currentTarget;
if ((itemObject.type === "mod")) {
let mods = obj?.system?.mods
if (!mods)
mods = []
try {
data = JSON.parse(event.dataTransfer.getData("text/plain"));
if (data.type !== "Item") return false;
} catch (err) {
return false;
}
itemObject.id = randomID()
console.log("M5ItemSheet._onDropItem", itemObject)
mods.push(itemObject)
// Case 1 - Import from a Compendium pack
let itemObject;
if (data.pack) {
const compendiumObject = await (this as any).importItemFromCollection(
data.pack,
data.id,
);
itemObject = compendiumObject.data;
}
obj.update({
data: {
mods: mods
}
})
}
}
// Case 2 - Import from World entity
else {
const originalItem = await (game as Game).items.get(data.id);
itemObject = duplicate(originalItem);
if (!itemObject) return;
}
async _onDragItemStart(event) { }
if (itemObject.type === "mod") {
let mods = obj?.system?.mods;
if (!mods) mods = [];
itemObject.id = randomID();
console.log("M5ItemSheet._onDropItem", itemObject);
mods.push(itemObject);
obj.update({
data: {
mods: mods,
},
});
}
}
async _onDragItemStart(event) {}
}
+305 -305
View File
@@ -3,366 +3,366 @@
@attributeBorderColor: rgba(0, 0, 0, 0.5);
.midgard5 {
.flexbox {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.flexbox {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.flexcolumn {
flex-wrap: wrap;
flex-direction: column;
}
.flexcolumn {
flex-wrap: wrap;
flex-direction: column;
}
.flexcolumn-1 {
flex-basis: 100%;
flex-wrap: wrap;
}
.flexcolumn-1 {
flex-basis: 100%;
flex-wrap: wrap;
}
.flexcolumn-2 {
flex-basis: 50%;
flex-wrap: wrap;
}
.flexcolumn-2 {
flex-basis: 50%;
flex-wrap: wrap;
}
.flexcolumn-3 {
flex-basis: 33%;
flex-wrap: wrap;
}
.flexcolumn-3 {
flex-basis: 33%;
flex-wrap: wrap;
}
.flexcolumn-4 {
flex-basis: 25%;
flex-wrap: wrap;
}
.flexcolumn-4 {
flex-basis: 25%;
flex-wrap: wrap;
}
.flexcolumn-5 {
flex-basis: 20%;
flex-wrap: wrap;
}
.flexcolumn-5 {
flex-basis: 20%;
flex-wrap: wrap;
}
.flexpart {
gap: 0;
padding: 0;
margin: 2px;
background-color: beige;
border-collapse: separate;
border-radius: 10px;
border: 2px solid black;
}
.flexpart {
gap: 0;
padding: 0;
margin: 2px;
background-color: beige;
border-collapse: separate;
border-radius: 10px;
border: 2px solid black;
}
.flexpart-header {
font-weight: bold;
font-size: large;
text-align: center;
color: black;
}
.flexpart-header {
font-weight: bold;
font-size: large;
text-align: center;
color: black;
}
.flexpart-icon {
height: 2rem;
float: left;
border: 0px solid transparent;
}
.flexpart-icon {
height: 2rem;
float: left;
border: 0px solid transparent;
}
.flexrow {
align-items: center;
}
.flexrow {
align-items: center;
}
h3 {
padding: 0.5rem 0.5rem 0.5rem 0.5rem;
margin-top: 0.5rem;
margin-bottom: 0;
text-align: left;
font-weight: bold;
background-color: #eeede0;
color: black;
border-collapse: separate;
border: 2px solid black;
border-radius: 10px;
}
h3 {
padding: 0.5rem 0.5rem 0.5rem 0.5rem;
margin-top: 0.5rem;
margin-bottom: 0;
text-align: left;
font-weight: bold;
background-color: #eeede0;
color: black;
border-collapse: separate;
border: 2px solid black;
border-radius: 10px;
}
.profile-img {
display: block;
margin-left: auto;
margin-right: auto;
height: 100%;
width: auto;
border: 0px solid black;
}
.profile-img {
display: block;
margin-left: auto;
margin-right: auto;
height: 100%;
width: auto;
border: 0px solid black;
}
.sheet.character {
form {
display: flex;
flex-direction: column;
}
.sheet.character {
form {
display: flex;
flex-direction: column;
}
.sheet-content {
height: 100%;
display: flex;
flex-direction: column;
.sheet-content {
height: 100%;
display: flex;
flex-direction: column;
.editor {
height: 100%;
}
}
.editor {
height: 100%;
}
}
.description {
flex: 0 0 100%;
margin: 0;
}
}
.description {
flex: 0 0 100%;
margin: 0;
}
}
.sheet-navigation {
margin: 4px 0;
background-color: lightgrey;
border-top: 2px solid black;
border-bottom: 2px solid black;
}
.sheet-navigation {
margin: 4px 0;
background-color: lightgrey;
border-top: 2px solid black;
border-bottom: 2px solid black;
}
.sheet-navigation .item {
padding: 8px 12px 8px 12px;
color: black;
font-weight: bold;
font-size: large;
}
.sheet-navigation .item {
padding: 8px 12px 8px 12px;
color: black;
font-weight: bold;
font-size: large;
}
.sheet-navigation .active {
background-color: darkgrey;
}
.sheet-navigation .active {
background-color: darkgrey;
}
.level-display {
text-align: right;
font-weight: bold;
}
.level-display {
text-align: right;
font-weight: bold;
}
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;
}
}
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,
th {
padding: 0 0.5rem 0 0.5rem;
text-align: left;
td,
th {
padding: 0 0.5rem 0 0.5rem;
text-align: left;
&.center {
text-align: center;
}
&.center {
text-align: center;
}
&.fixed-value {
width: 3rem;
text-align: center;
}
&.fixed-value {
width: 3rem;
text-align: center;
}
&.attribute {
text-align: center;
font-weight: bold;
}
&.attribute {
text-align: center;
font-weight: bold;
}
&.attribute-value {
background: url(/icons/svg/d20-grey.svg) no-repeat;
background-size: 50px 50px;
background-position: center;
color: black;
text-align: center;
font-weight: bold;
height: 50px;
width: 50px;
}
&.attribute-value {
background: url(/icons/svg/d20-grey.svg) no-repeat;
background-size: 50px 50px;
background-position: center;
color: black;
text-align: center;
font-weight: bold;
height: 50px;
width: 50px;
}
&.title {
padding: 0.5rem 0.5rem 0.5rem 0.5rem;
text-align: left;
font-weight: bold;
}
&.title {
padding: 0.5rem 0.5rem 0.5rem 0.5rem;
text-align: left;
font-weight: bold;
}
&.highlight {
font-weight: bold;
font-style: italic;
}
}
&.highlight {
font-weight: bold;
font-style: italic;
}
}
.table-icon {
height: 1rem;
width: 1rem;
float: left;
border: 0px solid transparent;
}
.table-icon {
height: 1rem;
width: 1rem;
float: left;
border: 0px solid transparent;
}
input {
border: 0px solid black;
}
input {
border: 0px solid black;
}
input.skill {
width: 5rem;
}
input.skill {
width: 5rem;
}
input.fixed {
width: 5rem;
}
input.fixed {
width: 5rem;
}
input.checkbox {
width: 1rem;
height: 1rem;
}
input.checkbox {
width: 1rem;
height: 1rem;
}
.new-skill {
font-style: italic;
background: rgba(0, 0, 0, 0.3);
color: rgba(255, 255, 255);
}
.new-skill {
font-style: italic;
background: rgba(0, 0, 0, 0.3);
color: rgba(255, 255, 255);
}
.roll-button {
background: url(/icons/svg/d20-black.svg) no-repeat;
background-size: 1rem 1rem;
border: #000000 solid 0px;
width: 1rem;
height: 1rem;
}
.roll-button {
background: url(/icons/svg/d20-black.svg) no-repeat;
background-size: 1rem 1rem;
border: #000000 solid 0px;
width: 1rem;
height: 1rem;
}
.wide-button {
margin: 0.25rem 0;
}
.wide-button {
margin: 0.25rem 0;
}
.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;
}
.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 {
color: rgb(93, 93, 93);
font-style: italic;
}
span.spell-process {
color: rgb(93, 93, 93);
font-style: italic;
}
.filler {
flex: 1 1 auto;
}
.filler {
flex: 1 1 auto;
}
.health-bar {
height: 1rem;
background-color: rgba(0, 0, 0, 0.8);
display: flex;
flex-direction: row;
gap: 1px;
padding: 1px;
//align-items: stretch;
.health-bar {
height: 1rem;
background-color: rgba(0, 0, 0, 0.8);
display: flex;
flex-direction: row;
gap: 1px;
padding: 1px;
//align-items: stretch;
input,
.max-value {
flex: 0 0 2rem;
text-align: center;
height: 100%;
background-color: rgba(109, 108, 102, 1);
color: rgba(255, 255, 255, 1);
font-weight: bold;
border-radius: 0;
}
input,
.max-value {
flex: 0 0 2rem;
text-align: center;
height: 100%;
background-color: rgba(109, 108, 102, 1);
color: rgba(255, 255, 255, 1);
font-weight: bold;
border-radius: 0;
}
.lp-bar-item-empty,
.ap-bar-item-empty {
flex-grow: 1;
background-color: white;
}
.lp-bar-item-empty,
.ap-bar-item-empty {
flex-grow: 1;
background-color: white;
}
.lp-bar-item {
flex-grow: 1;
background-color: lightgreen;
}
.lp-bar-item {
flex-grow: 1;
background-color: lightgreen;
}
.ap-bar-item {
flex-grow: 1;
background-color: lightblue;
}
.ap-bar-item {
flex-grow: 1;
background-color: lightblue;
}
.negative-bar-item {
flex-grow: 1;
background-color: red;
}
}
.negative-bar-item {
flex-grow: 1;
background-color: red;
}
}
.biography {
margin: 0.5rem 0.5rem 0.5rem 0.5rem;
height: 180px;
background-color: #eaead7;
.editor {
height: 100%;
width: 100%;
}
}
.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;
.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 6rem;
margin: 0;
border: 1px solid @attributeBorderColor;
//border-bottom: none;
border-radius: 10;
.attribute {
flex: 0 0 6rem;
margin: 0;
border: 1px solid @attributeBorderColor;
//border-bottom: none;
border-radius: 10;
display: flex;
flex-direction: column;
display: flex;
flex-direction: column;
.attribute-header {
display: flex;
align-items: center;
text-align: center;
justify-content: center;
.attribute-header {
display: flex;
align-items: center;
text-align: center;
justify-content: center;
font-weight: bold;
background-color: @attributeBorderColor;
color: rgba(255, 255, 255, 1);
font-weight: bold;
background-color: @attributeBorderColor;
color: rgba(255, 255, 255, 1);
//font-size: 1.0rem;
height: 2.5rem;
}
//font-size: 1.0rem;
height: 2.5rem;
}
.attribute-main {
padding: 0.2rem;
.attribute-main {
padding: 0.2rem;
.attribute-main-value {
text-align: center;
vertical-align: middle;
font-size: 2rem;
}
.attribute-main-value {
text-align: center;
vertical-align: middle;
font-size: 2rem;
}
.attribute-main-bonus {
text-align: center;
vertical-align: middle;
font-size: 1rem;
}
}
.attribute-main-bonus {
text-align: center;
vertical-align: middle;
font-size: 1rem;
}
}
.attribute-footer {
display: flex;
flex-direction: row;
gap: 0.3rem;
padding: 0.3rem;
background-color: @attributeBorderColor;
.attribute-footer {
display: flex;
flex-direction: row;
gap: 0.3rem;
padding: 0.3rem;
background-color: @attributeBorderColor;
input {
flex-grow: 1;
text-align: center;
background-color: rgba(255, 255, 255, 0.8);
}
}
}
}
input {
flex-grow: 1;
text-align: center;
background-color: rgba(255, 255, 255, 0.8);
}
}
}
}
}
+49 -48
View File
@@ -1,58 +1,59 @@
// main: midgard5.less
.midgard5.sheet.item {
form {
display: flex;
flex-direction: column;
}
.sheet-content {
height: 100%;
display: flex;
flex-direction: column;
.editor {
height: 100%;
}
}
.item-img {
height: 64px;
width: 64px;
}
.midgard5.sheet.item {
form {
display: flex;
flex-direction: column;
}
.sheet-content {
height: 100%;
display: flex;
flex-direction: column;
.editor {
height: 100%;
}
}
.item-img {
height: 64px;
width: 64px;
}
td, th {
padding: 0 0.5rem 0 0.5rem;
td,
th {
padding: 0 0.5rem 0 0.5rem;
&.center {
text-align: center;
}
&.center {
text-align: center;
}
&.fixed-value {
width: 3rem;
text-align: center;
}
}
&.fixed-value {
width: 3rem;
text-align: center;
}
}
table.rolls-table {
.col-enabled {
width: 3rem;
text-align: center;
}
table.rolls-table {
.col-enabled {
width: 3rem;
text-align: center;
}
.col-create {
width: 3rem;
text-align: center;
button {
background: rgba(255, 255, 255, 0.5);
}
}
.col-create {
width: 3rem;
text-align: center;
.col-delete {
width: 3rem;
text-align: center;
}
button {
background: rgba(255, 255, 255, 0.5);
}
}
.col-label {
width: 6rem;
}
}
.col-delete {
width: 3rem;
text-align: center;
}
.col-label {
width: 6rem;
}
}
}
+69 -69
View File
@@ -1,84 +1,84 @@
.m5-roll {
.roll-title {
text-align: center;
vertical-align: middle;
padding: 0.3rem 0 0.1rem 0;
font-weight: bold;
font-size: 1.3rem;
}
.roll-title {
text-align: center;
vertical-align: middle;
padding: 0.3rem 0 0.1rem 0;
font-weight: bold;
font-size: 1.3rem;
}
.roll-description-header {
text-align: start;
vertical-align: middle;
padding: 0.3rem 0 0.1rem 0;
font-weight: bold;
font-size: 1.2rem;
}
.roll-description-header {
text-align: start;
vertical-align: middle;
padding: 0.3rem 0 0.1rem 0;
font-weight: bold;
font-size: 1.2rem;
}
.roll-spell-details {
text-align: right;
padding-right: 1rem;
font-weight: bold;
}
.roll-spell-details {
text-align: right;
padding-right: 1rem;
font-weight: bold;
}
.roll-result {
text-align: right;
padding-right: 1rem;
font-weight: bold;
.roll-result {
text-align: right;
padding-right: 1rem;
font-weight: bold;
display: flex;
flex-direction: row;
display: flex;
flex-direction: row;
.roll-total {
width: 100%;
}
.roll-total {
width: 100%;
}
.roll-detail {
width: 100%;
margin-left: -100%;
}
}
.roll-detail {
width: 100%;
margin-left: -100%;
}
}
.roll-row:not(:hover) {
.roll-total {
visibility: visible;
}
.roll-detail {
visibility: hidden;
}
}
.roll-row:not(:hover) {
.roll-total {
visibility: visible;
}
.roll-detail {
visibility: hidden;
}
}
.roll-row:hover {
.roll-total {
visibility: hidden;
}
.roll-detail {
visibility: visible;
}
}
.roll-row:hover {
.roll-total {
visibility: hidden;
}
.roll-detail {
visibility: visible;
}
}
.roll-ew-result-fumble {
background-color: rgb(202, 54, 54, 0.5);
color: rgb(255, 255, 255);
}
.roll-ew-result-fumble {
background-color: rgb(202, 54, 54, 0.5);
color: rgb(255, 255, 255);
}
.roll-ew-result-critical {
background-color: rgb(202, 197, 54, 0.5);
color: rgb(0, 0, 0);
}
.roll-ew-result-critical {
background-color: rgb(202, 197, 54, 0.5);
color: rgb(0, 0, 0);
}
.roll-ew-result-high {
background-color: rgb(54, 138, 202, 0.5);
color: rgb(255, 255, 255);
}
.roll-ew-result-high {
background-color: rgb(54, 138, 202, 0.5);
color: rgb(255, 255, 255);
}
.roll-ew-result-fail {
background-color: rgb(117, 63, 131, 0.5);
color: rgb(255, 255, 255);
}
.roll-ew-result-fail {
background-color: rgb(117, 63, 131, 0.5);
color: rgb(255, 255, 255);
}
.roll-ew-result-pass {
background-color: rgb(54, 202, 88, 0.5);
color: rgb(0, 0, 0);
}
.roll-ew-result-pass {
background-color: rgb(54, 202, 88, 0.5);
color: rgb(0, 0, 0);
}
}
+153 -164
View File
@@ -1,165 +1,154 @@
{
"id": "midgard5",
"name": "midgard5",
"title": "Midgard 5. Edition",
"description": "The German RPG Midgard 5. Edition",
"version": "2.4.2",
"compatibility": {
"minimum": "10",
"verified": "11",
"maximum": "11"
},
"authors": [
{"name": "Byroks"},
{"name": "Le-Frique"},
{"name": "Oskaloq"}
],
"scripts": ["bundle.js"],
"styles": ["bundle.css"],
"packs": [
{
"name": "blaupause-spielfiguren",
"label": "Blaupausen für Spielfiguren",
"system": "midgard5",
"path": "./packs/actors/blaupause-spielfiguren.db",
"type": "Actor"
},
{
"name": "makros-standardwurfel",
"label": "Standardwürfel",
"system": "midgard5",
"path": "./packs/macros/makros-standardwurfel.db",
"type": "Macro"
},
{
"name": "makros-kritische-ereignisse",
"label": "Makros Kritische Ereignisse",
"system": "midgard5",
"path": "./packs/macros/makros-kritische-ereignisse.db",
"type": "Macro"
},
{
"name": "tabellen-kritische-ereignisse",
"label": "Tabellen Kritische Ereignisse",
"system": "midgard5",
"path": "./packs/rolltables/tabellen-kritische-ereignisse.db",
"type": "RollTable"
},
{
"name": "ausruestung",
"label": "Ausrüstung",
"system": "midgard5",
"path": "./packs/items/ausruestung.db",
"type": "Item"
},
{
"name": "fertigkeiten",
"label": "Fertigkeiten",
"system": "midgard5",
"path": "./packs/items/fertigkeiten.db",
"type": "Item"
},
{
"name": "kampf",
"label": "Kampf",
"system": "midgard5",
"path": "./packs/items/kampf.db",
"type": "Item"
},
{
"name": "kampfzustaende",
"label": "Kampfzustände",
"system": "midgard5",
"path": "./packs/items/kampfzustaende.db",
"type": "Item"
},
{
"name": "verletzungen",
"label": "Verletzungen",
"system": "midgard5",
"path": "./packs/items/verletzungen.db",
"type": "Item"
},
{
"name": "ruestkammer",
"label": "Rüstkammer",
"system": "midgard5",
"path": "./packs/items/ruestkammer.db",
"type": "Item"
},
{
"name": "waffenkammer",
"label": "Waffenkammer",
"system": "midgard5",
"path": "./packs/items/waffenkammer.db",
"type": "Item"
},
{
"name": "zauberwirkungen",
"label": "Zauberwirkungen",
"system": "midgard5",
"path": "./packs/items/zauberwirkungen.db",
"type": "Item"
}
],
"packFolders": [
{
"name": "Midgard 5",
"sorting": "a",
"color": "#0000FF",
"packs": [
"blaupause-spielfiguren",
"tabellen-kritische-ereignisse",
"makros-kritische-ereignisse",
"makros-standardwurfel"
],
"folders": [
{
"name": "Ausrüstung",
"sorting": "a",
"color": "#008000",
"packs": [
"ausruestung",
"ruestkammer",
"waffenkammer"
]
},
{
"name": "Effekte",
"sorting": "a",
"color": "#800080",
"packs": [
"kampfzustaende",
"verletzungen",
"zauberwirkungen"
]
},
{
"name": "Fähigkeiten",
"sorting": "a",
"color": "#800000",
"packs": [
"fertigkeiten",
"kampf"
]
}
]
}
],
"languages": [
{
"lang": "de",
"name": "Deutsch",
"path": "lang/de.json"
}
],
"gridDistance": 1,
"gridUnits": "m",
"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.4.2/system.json",
"download": "https://git.byroks.de/MidgardVTT-Entwicklung/foundry-vtt-system-midgard5/releases/download/v2.4.2/midgard5-v2.4.2.zip",
"initiative": "@c.calc.attributes.gw.value",
"license": "LICENSE.txt"
}
"id": "midgard5",
"name": "midgard5",
"title": "Midgard 5. Edition",
"description": "The German RPG Midgard 5. Edition",
"version": "2.4.2",
"compatibility": {
"minimum": "10",
"verified": "11",
"maximum": "11"
},
"authors": [
{ "name": "Byroks" },
{ "name": "Le-Frique" },
{ "name": "Oskaloq" }
],
"scripts": ["bundle.js"],
"styles": ["bundle.css"],
"packs": [
{
"name": "blaupause-spielfiguren",
"label": "Blaupausen für Spielfiguren",
"system": "midgard5",
"path": "./packs/actors/blaupause-spielfiguren.db",
"type": "Actor"
},
{
"name": "makros-standardwurfel",
"label": "Standardwürfel",
"system": "midgard5",
"path": "./packs/macros/makros-standardwurfel.db",
"type": "Macro"
},
{
"name": "makros-kritische-ereignisse",
"label": "Makros Kritische Ereignisse",
"system": "midgard5",
"path": "./packs/macros/makros-kritische-ereignisse.db",
"type": "Macro"
},
{
"name": "tabellen-kritische-ereignisse",
"label": "Tabellen Kritische Ereignisse",
"system": "midgard5",
"path": "./packs/rolltables/tabellen-kritische-ereignisse.db",
"type": "RollTable"
},
{
"name": "ausruestung",
"label": "Ausrüstung",
"system": "midgard5",
"path": "./packs/items/ausruestung.db",
"type": "Item"
},
{
"name": "fertigkeiten",
"label": "Fertigkeiten",
"system": "midgard5",
"path": "./packs/items/fertigkeiten.db",
"type": "Item"
},
{
"name": "kampf",
"label": "Kampf",
"system": "midgard5",
"path": "./packs/items/kampf.db",
"type": "Item"
},
{
"name": "kampfzustaende",
"label": "Kampfzustände",
"system": "midgard5",
"path": "./packs/items/kampfzustaende.db",
"type": "Item"
},
{
"name": "verletzungen",
"label": "Verletzungen",
"system": "midgard5",
"path": "./packs/items/verletzungen.db",
"type": "Item"
},
{
"name": "ruestkammer",
"label": "Rüstkammer",
"system": "midgard5",
"path": "./packs/items/ruestkammer.db",
"type": "Item"
},
{
"name": "waffenkammer",
"label": "Waffenkammer",
"system": "midgard5",
"path": "./packs/items/waffenkammer.db",
"type": "Item"
},
{
"name": "zauberwirkungen",
"label": "Zauberwirkungen",
"system": "midgard5",
"path": "./packs/items/zauberwirkungen.db",
"type": "Item"
}
],
"packFolders": [
{
"name": "Midgard 5",
"sorting": "a",
"color": "#0000FF",
"packs": [
"blaupause-spielfiguren",
"tabellen-kritische-ereignisse",
"makros-kritische-ereignisse",
"makros-standardwurfel"
],
"folders": [
{
"name": "Ausrüstung",
"sorting": "a",
"color": "#008000",
"packs": ["ausruestung", "ruestkammer", "waffenkammer"]
},
{
"name": "Effekte",
"sorting": "a",
"color": "#800080",
"packs": ["kampfzustaende", "verletzungen", "zauberwirkungen"]
},
{
"name": "Fähigkeiten",
"sorting": "a",
"color": "#800000",
"packs": ["fertigkeiten", "kampf"]
}
]
}
],
"languages": [
{
"lang": "de",
"name": "Deutsch",
"path": "lang/de.json"
}
],
"gridDistance": 1,
"gridUnits": "m",
"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.4.2/system.json",
"download": "https://git.byroks.de/MidgardVTT-Entwicklung/foundry-vtt-system-midgard5/releases/download/v2.4.2/midgard5-v2.4.2.zip",
"initiative": "@c.calc.attributes.gw.value",
"license": "LICENSE.txt"
}
+696 -440
View File
File diff suppressed because it is too large Load Diff
+33 -30
View File
@@ -2,46 +2,49 @@ import Globals from "../Globals";
import Color from "color";
class Logger {
// static class
private constructor() {}
// static class
private constructor() {}
private static GetCurrentTime(): string {
return `[${(new Date().toLocaleTimeString())}] `;
}
private static GetCurrentTime(): string {
return `[${new Date().toLocaleTimeString()}] `;
}
static log(str: string, colour: Color = Color("white"), bold = false): void {
const time = ToConsole(Logger.GetCurrentTime(), Color("gray"), false)
const moduleName = ToConsole(Globals.name + " ", Color("cyan"), true);
const text = ToConsole(str, colour, bold);
console.log(time.str + moduleName.str + text.str, ...time.params.concat(moduleName.params, text.params));
}
static log(str: string, colour: Color = Color("white"), bold = false): void {
const time = ToConsole(Logger.GetCurrentTime(), Color("gray"), false);
const moduleName = ToConsole(Globals.name + " ", Color("cyan"), true);
const text = ToConsole(str, colour, bold);
console.log(
time.str + moduleName.str + text.str,
...time.params.concat(moduleName.params, text.params),
);
}
static err(str: string): void {
Logger.log(str, Color("orange"));
}
static err(str: string): void {
Logger.log(str, Color("orange"));
}
static warn(str: string): void {
Logger.log(str, Color("yellow"));
}
static warn(str: string): void {
Logger.log(str, Color("yellow"));
}
static ok(str: string): void {
Logger.log(str, Color("green"));
}
static ok(str: string): void {
Logger.log(str, Color("green"));
}
}
interface ConsoleColour {
str: string,
params: Array<string>;
str: string;
params: Array<string>;
}
const ToConsole = (str: string, col: Color, bold: boolean): ConsoleColour => {
return {
str: `%c` + str + `%c`,
params: [
"color: " + col.hex() + ";" + (bold ? "font-weight: bold;" : ""),
"color: unset; font-weight: unset;"
]
}
return {
str: `%c` + str + `%c`,
params: [
"color: " + col.hex() + ";" + (bold ? "font-weight: bold;" : ""),
"color: unset; font-weight: unset;",
],
};
};
export default Logger;
export default Logger;
+7 -5
View File
@@ -1,8 +1,10 @@
import {ModuleData} from "@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/packages.mjs";
import { ModuleData } from "@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/packages.mjs";
import Globals from "../Globals";
export const getModuleInformation = async (): Promise<ModuleData> => {
const systemOrModule = Globals.isModule ? "module" : "system"
const module = await fetch(systemOrModule + "s/" + Globals.name + "/" + systemOrModule + ".json")
return await module.json();
};
const systemOrModule = Globals.isModule ? "module" : "system";
const module = await fetch(
systemOrModule + "s/" + Globals.name + "/" + systemOrModule + ".json",
);
return await module.json();
};