Compare commits

...
7 Commits
Author SHA1 Message Date
Byroks e85fd1c41f fix Zaubern EW display in spell
Changes:
 + fix Zaubern EW display in spell list
2023-11-19 21:13:29 +01:00
Byroks d9e7152b4d verson change v1.2.2 2023-11-19 20:58:03 +01:00
Byroks 9e7d81f413 version change to v1.2.2 2023-11-19 20:57:16 +01:00
Byroks 8dd29e8da5 hide skill when learned
Changes:
 + Hide learned skills from unlearned skill list
2023-11-19 20:52:29 +01:00
Byroks 0d259f40a7 adjust version to 1.2.1 2023-11-17 16:10:31 +01:00
Byroks 4ec3cc9570 add race boni and default resistance rolls
Changes:
 + add Race Selection Dropdown
 + change resistance/defense value calculation, based on race, stats and class
 + add default rolls for defense and resistances
2023-11-17 16:09:24 +01:00
Byroks 2b02f787f2 fix spelling mistake in macros 2023-11-17 09:27:33 +01:00
14 changed files with 314 additions and 186 deletions
+5 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "foundry-system-midgard5", "name": "foundry-system-midgard5",
"version": "1.2.0", "version": "1.2.2",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
@@ -13,7 +13,7 @@
"build:watch:target": "gulp watchTarget", "build:watch:target": "gulp watchTarget",
"clean": "gulp clean && gulp link --clean" "clean": "gulp clean && gulp link --clean"
}, },
"author": "Simon Gustavs", "author": "Byroks",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@babel/core": "^7.15.0", "@babel/core": "^7.15.0",
@@ -54,5 +54,8 @@
"vinyl-buffer": "^1.0.1", "vinyl-buffer": "^1.0.1",
"vinyl-source-stream": "^2.0.0", "vinyl-source-stream": "^2.0.0",
"yargs": "^17.1.1" "yargs": "^17.1.1"
},
"dependencies": {
"handlebars-helpers": "^0.10.0"
} }
} }
@@ -11,7 +11,7 @@
} }
}, },
"scope": "global", "scope": "global",
"command": "await game.tables.getName(\"Kritische Fehler beim Zaubern\").draw()", "command": "await game.tables.getName(\"Kritischer Fehler beim Zaubern\").draw()",
"author": "CBq5YXAqbO7HoJ03", "author": "CBq5YXAqbO7HoJ03",
"img": "systems/midgard5/assets/icons/macro/kritfehlerzauber.svg", "img": "systems/midgard5/assets/icons/macro/kritfehlerzauber.svg",
"actorIds": [], "actorIds": [],
@@ -11,7 +11,7 @@
} }
}, },
"scope": "global", "scope": "global",
"command": "await game.tables.getName(\"Kritische Erfolg bei der Abwehr\").draw()", "command": "await game.tables.getName(\"Kritischer Erfolg bei der Abwehr\").draw()",
"author": "CBq5YXAqbO7HoJ03", "author": "CBq5YXAqbO7HoJ03",
"img": "systems/midgard5/assets/icons/macro/kriterfolgabwehr.svg", "img": "systems/midgard5/assets/icons/macro/kriterfolgabwehr.svg",
"actorIds": [], "actorIds": [],
@@ -11,7 +11,7 @@
} }
}, },
"scope": "global", "scope": "global",
"command": "await game.tables.getName(\"Kritische Fehler bei Angriffen\").draw()", "command": "await game.tables.getName(\"Kritischer Fehler bei Angriffen\").draw()",
"author": "CBq5YXAqbO7HoJ03", "author": "CBq5YXAqbO7HoJ03",
"img": "systems/midgard5/assets/icons/macro/kritfehlerangriff.svg", "img": "systems/midgard5/assets/icons/macro/kritfehlerangriff.svg",
"actorIds": [], "actorIds": [],
@@ -11,7 +11,7 @@
} }
}, },
"scope": "global", "scope": "global",
"command": "await game.tables.getName(\"Kritische Fehler bei der Abwehr\").draw()", "command": "await game.tables.getName(\"Kritischer Fehler bei der Abwehr\").draw()",
"author": "CBq5YXAqbO7HoJ03", "author": "CBq5YXAqbO7HoJ03",
"img": "systems/midgard5/assets/icons/macro/kritfehlerabwehr.svg", "img": "systems/midgard5/assets/icons/macro/kritfehlerabwehr.svg",
"actorIds": [], "actorIds": [],
+64 -57
View File
@@ -1,98 +1,105 @@
import Logger from "./utils/Logger" import Logger from "./utils/Logger";
import M5CharacterSheet from "./module/sheets/M5CharacterSheet" import M5CharacterSheet from "./module/sheets/M5CharacterSheet";
import preloadTemplates from "./PreloadTemplates" import preloadTemplates from "./PreloadTemplates";
import { M5Character } from "./module/actors/M5Character" import { M5Character } from "./module/actors/M5Character";
import { M5Skill } from "./module/M5Base" import { M5Skill } from "./module/M5Base";
import { M5ItemSheet } from "./module/sheets/M5ItemSheet" import { M5ItemSheet } from "./module/sheets/M5ItemSheet";
import { M5Item } from "./module/items/M5Item" import { M5Item } from "./module/items/M5Item";
Hooks.once("init", async () => { Hooks.once("init", async () => {
Logger.log("M5 | Initialisierung Midgard 5") Logger.log("M5 | Initialisierung Midgard 5");
Handlebars.registerHelper("times", (n: number, block) => { Handlebars.registerHelper("times", (n: number, block) => {
var accum = "" var accum = "";
for(let i = 0; i < n; ++i) for (let i = 0; i < n; ++i) accum += block.fn(i);
accum += block.fn(i) return accum;
return accum });
})
Handlebars.registerHelper("array", (arr: any[], index: number) => { Handlebars.registerHelper("array", (arr: any[], index: number) => {
return arr[index] return arr[index];
}) });
Handlebars.registerHelper("m5concat", (...values) => { Handlebars.registerHelper("m5concat", (...values) => {
const options = values.pop(); const options = values.pop();
const join = options.hash?.join || ""; const join = options.hash?.join || "";
//return new Handlebars.SafeString(values.join(join)); //return new Handlebars.SafeString(values.join(join));
return values.map(val => val.toString()).join(join) return values.map((val) => val.toString()).join(join);
}) });
Handlebars.registerHelper("add", (...values) => { Handlebars.registerHelper("add", (...values) => {
const options = values.pop(); const options = values.pop();
return values.reduce((prev, cur) => prev + cur) return values.reduce((prev, cur) => prev + cur);
}) });
Handlebars.registerHelper("localizeMidgard", (str: string) => { Handlebars.registerHelper("localizeMidgard", (str: string) => {
const template = Handlebars.compile("{{localize value}}") const template = Handlebars.compile("{{localize value}}");
return template({ return template({
value: "midgard5." + str value: "midgard5." + str,
}) });
}) });
Handlebars.registerHelper("skillBonus", (actorId: string, skill: M5Skill) => { Handlebars.registerHelper("skillBonus", (actorId: string, skill: M5Skill) => {
const actor = (game as Game).actors.get(actorId) as M5Character const actor = (game as Game).actors.get(actorId) as M5Character;
return actor.skillBonus(skill).toString() return actor.skillBonus(skill).toString();
}) });
Handlebars.registerHelper("skillEw", (actorId: string, skill: M5Skill) => { Handlebars.registerHelper("skillEw", (actorId: string, skill: M5Skill) => {
const actor = (game as Game).actors.get(actorId) as M5Character const actor = (game as Game).actors.get(actorId) as M5Character;
return actor.skillEw(skill).toString() return actor.skillEw(skill).toString();
}) });
Handlebars.registerHelper("skill", (skillId: string) => { Handlebars.registerHelper("skill", (skillId: string) => {
return (game as Game).items.get(skillId) return (game as Game).items.get(skillId);
}) });
Handlebars.registerHelper("itemValue", (id: string, path: string) => { Handlebars.registerHelper("itemValue", (id: string, path: string) => {
let obj = (game as Game).items.get(id) let obj = (game as Game).items.get(id);
path.split(".").forEach(p => obj = obj[p]) path.split(".").forEach((p) => (obj = obj[p]));
return `${obj}` return `${obj}`;
}) });
Handlebars.registerHelper("actorItemValue", (actorId: any, itemId: string, path: string) => { Handlebars.registerHelper("actorItemValue", (actorId: any, itemId: string, path: string) => {
//console.log("actorItemValue", actorId, itemId, path) //console.log("actorItemValue", actorId, itemId, path)
const actor = (game as Game).actors.get(actorId) const actor = (game as Game).actors.get(actorId);
let obj = actor.items.get(itemId).system let obj = actor.items.get(itemId).system;
path.split(".").forEach(p => { path.split(".").forEach((p) => {
if (obj) if (obj) obj = obj[p];
obj = obj[p] });
}) return `${obj}`;
return `${obj}` });
})
Handlebars.registerHelper("icon", (relpath: string) => { Handlebars.registerHelper("icon", (relpath: string) => {
return `systems/midgard5/assets/icons/${relpath}` 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;
});
// Default Sheet für Items definieren und das Standardsheet deaktivieren // Default Sheet für Items definieren und das Standardsheet deaktivieren
Items.unregisterSheet("core", ItemSheet) Items.unregisterSheet("core", ItemSheet);
Items.registerSheet("midgard5", M5ItemSheet, { makeDefault: true }) Items.registerSheet("midgard5", M5ItemSheet, { makeDefault: true });
// Default Sheet für Actors definieren und das Standardsheet deaktivieren // Default Sheet für Actors definieren und das Standardsheet deaktivieren
Actors.unregisterSheet("core", ActorSheet) Actors.unregisterSheet("core", ActorSheet);
Actors.registerSheet("midgard5", M5CharacterSheet, { makeDefault: true }) Actors.registerSheet("midgard5", M5CharacterSheet, { makeDefault: true });
CONFIG.Actor.documentClass = M5Character CONFIG.Actor.documentClass = M5Character;
CONFIG.Item.documentClass = M5Item CONFIG.Item.documentClass = M5Item;
//RegisterSettings(); //RegisterSettings();
await preloadTemplates() await preloadTemplates();
}) });
Hooks.once("setup", () => { Hooks.once("setup", () => {
Logger.log("Template module is being setup.") Logger.log("Template module is being setup.");
}) });
Hooks.once("ready", () => { Hooks.once("ready", () => {
Logger.ok("Template module is now ready.") Logger.ok("Template module is now ready.");
}) });
+21 -2
View File
@@ -108,8 +108,12 @@ export class M5Character extends Actor {
ret.stats.attackBonus = this.modResult(ret.attributes.gs.bonus); ret.stats.attackBonus = this.modResult(ret.attributes.gs.bonus);
ret.stats.defenseBonus = this.modResult(ret.attributes.gw.bonus); ret.stats.defenseBonus = this.modResult(ret.attributes.gw.bonus);
ret.stats.movementBonus = this.modResult(0); ret.stats.movementBonus = this.modResult(0);
ret.stats.resistanceMind = this.modResult(ret.stats.defense.value); ret.stats.resistanceMind = this.modResult(
ret.stats.resistanceBody = this.modResult(ret.stats.defense.value + 1); (data.info.magicUsing ? 2 : 0) + ret.stats.defense.value + (data.info.race === "Mensch" ? ret.attributes.in.bonus : this.raceBonus(data.info.race))
);
ret.stats.resistanceBody = this.modResult(
(data.info.magicUsing ? 2 : 1) + ret.stats.defense.value + (data.info.race === "Mensch" ? ret.attributes.ko.bonus : this.raceBonus(data.info.race))
);
ret.stats.spellCasting = this.modResult((data.info.magicUsing ? M5Character.spellCastingFromLevel(ret.level) : 3) + ret.attributes.zt.bonus); ret.stats.spellCasting = this.modResult((data.info.magicUsing ? M5Character.spellCastingFromLevel(ret.level) : 3) + ret.attributes.zt.bonus);
ret.stats.brawl = this.modResult(Math.floor((ret.attributes.st.value + ret.attributes.gw.value) / 20)); ret.stats.brawl = this.modResult(Math.floor((ret.attributes.st.value + ret.attributes.gw.value) / 20));
ret.stats.brawlEw = ret.stats.brawl.value + ret.stats.attackBonus.value; ret.stats.brawlEw = ret.stats.brawl.value + ret.stats.attackBonus.value;
@@ -251,6 +255,21 @@ export class M5Character extends Actor {
return ret; return ret;
} }
raceBonus(race: string) {
switch (race) {
case "Elf":
return 2;
case "Gnom":
return 4;
case "Halbling":
return 4;
case "Zwerg":
return 3;
default:
return 0;
}
}
prepareDerivedData() { prepareDerivedData() {
console.log("M5Character", "prepareDerivedData"); console.log("M5Character", "prepareDerivedData");
const data = (this as any).system; const data = (this as any).system;
+1 -1
View File
@@ -110,7 +110,7 @@ export class M5Item extends Item {
if (actor) { if (actor) {
const actorCalc = character.derivedData({ weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true }); const actorCalc = character.derivedData({ weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true });
if (actorCalc) { if (actorCalc) {
calc.ew += actorCalc.stats.spellCasting.value; calc.ew = actorCalc.stats.spellCasting.value;
} }
} }
} else if (itemType === "item") { } else if (itemType === "item") {
+156 -103
View File
@@ -2,12 +2,13 @@ import { Evaluated } from "@league-of-foundry-developers/foundry-vtt-types/src/f
import { M5Character } from "../actors/M5Character"; import { M5Character } from "../actors/M5Character";
import { M5EwResult, M5RollData, M5RollResult, M5SkillUnlearned } from "../M5Base"; import { M5EwResult, M5RollData, M5RollResult, M5SkillUnlearned } from "../M5Base";
export class M5Roll { // extends Roll<M5RollData> export class M5Roll {
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 _evaluated: boolean = false;
public _total: number = 0 public _total: number = 0;
public pool: PoolTerm = null public pool: PoolTerm = null;
constructor(public data: M5RollData, public actor: any, public label: string) { constructor(public data: M5RollData, public actor: any, public label: string) {
//super(null) //super(null)
@@ -17,116 +18,108 @@ export class M5Roll { // extends Roll<M5RollData>
// @ts-ignore // @ts-ignore
//override evaluate(options?: InexactPartial<RollTerm.EvaluationOptions>): Evaluated<Roll<M5RollData>> | Promise<Evaluated<Roll<M5RollData>>> { //override evaluate(options?: InexactPartial<RollTerm.EvaluationOptions>): Evaluated<Roll<M5RollData>> | Promise<Evaluated<Roll<M5RollData>>> {
evaluate() { evaluate() {
const indexMap = new Map<number, string>() const indexMap = new Map<number, string>();
const rollNames = Object.keys(this.data.rolls) const rollNames = Object.keys(this.data.rolls);
const rolls = rollNames.filter(rollName => this.data.rolls[rollName].enabled).map((rollName, index) => { const rolls = rollNames
indexMap.set(index, rollName) .filter((rollName) => this.data.rolls[rollName].enabled)
const formula = this.data.rolls[rollName] .map((rollName, index) => {
const roll = new Roll(formula.formula, this.data) indexMap.set(index, rollName);
return roll const formula = this.data.rolls[rollName];
}) const roll = new Roll(formula.formula, this.data);
return roll;
});
this.pool = PoolTerm.fromRolls(rolls) this.pool = PoolTerm.fromRolls(rolls);
console.log("evaluate", this._evaluated, this.pool) console.log("evaluate", this._evaluated, this.pool);
return this.pool.evaluate({ async: true }).then(results => { return this.pool.evaluate({ async: true }).then((results) => {
this._total = 0 this._total = 0;
results.rolls.forEach((roll, index) => { results.rolls.forEach((roll, index) => {
const rollIndex = indexMap.get(index) const rollIndex = indexMap.get(index);
const rollResult = this.data.rolls[rollIndex] as M5RollResult const rollResult = this.data.rolls[rollIndex] as M5RollResult;
rollResult.result = roll.result rollResult.result = roll.result;
rollResult.total = roll.total rollResult.total = roll.total;
rollResult.totalStr = roll.total.toString() rollResult.totalStr = roll.total.toString();
this._total += roll.total this._total += roll.total;
let rowRes = M5EwResult.TBD let rowRes = M5EwResult.TBD;
let face100 = -1 let face100 = -1;
roll.dice.forEach((d, dIndex) => { roll.dice.forEach((d, dIndex) => {
rollResult.dice[dIndex.toString()] = d.total rollResult.dice[dIndex.toString()] = d.total;
if (rowRes === M5EwResult.TBD && dIndex === 0) { if (rowRes === M5EwResult.TBD && dIndex === 0) {
if (d.faces === 20) { if (d.faces === 20) {
//if (rollResult.type === "ew") { //if (rollResult.type === "ew") {
if (d.total === 1) if (d.total === 1) rowRes = M5EwResult.FUMBLE;
rowRes = M5EwResult.FUMBLE else if (d.total === 20) rowRes = M5EwResult.CRITICAL;
else if (d.total === 20) else if (d.total >= 16) rowRes = M5EwResult.HIGH;
rowRes = M5EwResult.CRITICAL
else if (d.total >= 16)
rowRes = M5EwResult.HIGH
} else if (d.faces === 100) { } else if (d.faces === 100) {
face100 = d.total as number face100 = d.total as number;
} }
} }
}) });
const parseResult = M5Roll.parseDiceSides(rollResult.formula) const parseResult = M5Roll.parseDiceSides(rollResult.formula);
//console.log("evaluate roll", parseResult) //console.log("evaluate roll", parseResult)
if (parseResult?.sides === 20) { if (parseResult?.sides === 20) {
if (roll.total < 20) { if (roll.total < 20) {
if (rowRes === M5EwResult.TBD || rowRes === M5EwResult.HIGH) if (rowRes === M5EwResult.TBD || rowRes === M5EwResult.HIGH) rowRes = M5EwResult.FAIL;
rowRes = M5EwResult.FAIL
} else { } else {
if (rowRes === M5EwResult.TBD) if (rowRes === M5EwResult.TBD) rowRes = M5EwResult.PASS;
rowRes = M5EwResult.PASS
} }
} else if (face100 >= 0) { } else if (face100 >= 0) {
const threshold100 = roll.total + face100 const threshold100 = roll.total + face100;
const threshold = Math.floor(threshold100 / 10) const threshold = Math.floor(threshold100 / 10);
if (face100 === 100) { if (face100 === 100) {
if (rowRes === M5EwResult.TBD) if (rowRes === M5EwResult.TBD) rowRes = M5EwResult.FUMBLE;
rowRes = M5EwResult.FUMBLE
} else if (roll.total < 0) { } else if (roll.total < 0) {
if (rowRes === M5EwResult.TBD) if (rowRes === M5EwResult.TBD) rowRes = M5EwResult.FAIL;
rowRes = M5EwResult.FAIL
} else if (face100 <= threshold) { } else if (face100 <= threshold) {
if (rowRes === M5EwResult.TBD) if (rowRes === M5EwResult.TBD) rowRes = M5EwResult.CRITICAL;
rowRes = M5EwResult.CRITICAL
} else { } else {
if (rowRes === M5EwResult.TBD) if (rowRes === M5EwResult.TBD) rowRes = M5EwResult.PASS;
rowRes = M5EwResult.PASS
} }
} }
rollResult.css = rowRes rollResult.css = rowRes;
}) });
this.data.res.label = this.label this.data.res.label = this.label;
this._evaluated = true this._evaluated = true;
return this return this;
}) });
} }
async render(): Promise<string> { async render(): Promise<string> {
return renderTemplate(M5Roll.TEMPLATE_PATH, this.data) return renderTemplate(M5Roll.TEMPLATE_PATH, this.data);
} }
async toMessage() { async toMessage() {
if (!this._evaluated) if (!this._evaluated) await this.evaluate();
await this.evaluate()
const rMode = (game as Game).settings.get("core", "rollMode") const rMode = (game as Game).settings.get("core", "rollMode");
const chatData = { const chatData = {
type: CONST.CHAT_MESSAGE_TYPES.ROLL, type: CONST.CHAT_MESSAGE_TYPES.ROLL,
content: await this.render(), content: await this.render(),
speaker: ChatMessage.getSpeaker({actor: this.actor}), speaker: ChatMessage.getSpeaker({ actor: this.actor }),
sound: CONFIG.sounds.dice, sound: CONFIG.sounds.dice,
roll: Roll.fromTerms([this.pool]) roll: Roll.fromTerms([this.pool]),
} };
ChatMessage.applyRollMode(chatData, rMode) ChatMessage.applyRollMode(chatData, rMode);
return ChatMessage.create(chatData) return ChatMessage.create(chatData);
} }
static fromAttribute(actor: any, attributeKey: string) { static fromAttribute(actor: any, attributeKey: string) {
const character = actor as M5Character const character = actor as M5Character;
const attribute = character.attribute(attributeKey) const attribute = character.attribute(attributeKey);
const rollData = actor.getRollData() as M5RollData const rollData = actor.getRollData() as M5RollData;
rollData.i = attribute.value + attribute.bonus rollData.i = attribute.value + attribute.bonus;
rollData.rolls["0"] = { rollData.rolls["0"] = {
formula: "@i - 1d100", formula: "@i - 1d100",
enabled: true, enabled: true,
@@ -135,15 +128,15 @@ export class M5Roll { // extends Roll<M5RollData>
total: 0, total: 0,
totalStr: "", totalStr: "",
dice: {}, dice: {},
css: "" css: "",
} as M5RollResult } 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 fromAttributeValue(actor: any, attributeKey: string, attributeValue: number) { static fromAttributeValue(actor: any, attributeKey: string, attributeValue: number) {
const rollData = actor.getRollData() as M5RollData const rollData = actor.getRollData() as M5RollData;
rollData.i = attributeValue rollData.i = attributeValue;
rollData.rolls["0"] = { rollData.rolls["0"] = {
formula: "@i - 1d100", formula: "@i - 1d100",
enabled: true, enabled: true,
@@ -152,19 +145,19 @@ export class M5Roll { // extends Roll<M5RollData>
total: 0, total: 0,
totalStr: "", totalStr: "",
dice: {}, dice: {},
css: "" css: "",
} as M5RollResult } 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) { static fromUnlearnedSkill(actor: any, skill: M5SkillUnlearned, skillName: string) {
const rollData = actor.getRollData() as M5RollData const rollData = actor.getRollData() as M5RollData;
rollData.i = { rollData.i = {
fw: skill.fw, fw: skill.fw,
bonus: actor.system.calc?.attributes[skill.attribute]?.bonus ?? 0 bonus: actor.system.calc?.attributes[skill.attribute]?.bonus ?? 0,
} };
rollData.iType = "skill" rollData.iType = "skill";
rollData.rolls["0"] = { rollData.rolls["0"] = {
formula: "1d20 + @i.fw + @i.bonus", formula: "1d20 + @i.fw + @i.bonus",
@@ -174,18 +167,18 @@ export class M5Roll { // extends Roll<M5RollData>
total: 0, total: 0,
totalStr: "", totalStr: "",
dice: {}, dice: {},
css: "" css: "",
} as M5RollResult } 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) { static brawl(actor: any) {
const rollData = actor.getRollData() as M5RollData const rollData = actor.getRollData() as M5RollData;
rollData.i = { rollData.i = {
attackBonus: 0, attackBonus: 0,
damageBonus: 0 damageBonus: 0,
} };
rollData.rolls["0"] = { rollData.rolls["0"] = {
formula: "1d20 + @c.calc.stats.brawl + @c.calc.stats.attackBonus + @i.attackBonus", formula: "1d20 + @c.calc.stats.brawl + @c.calc.stats.attackBonus + @i.attackBonus",
@@ -195,8 +188,8 @@ export class M5Roll { // extends Roll<M5RollData>
total: 0, total: 0,
totalStr: "", totalStr: "",
dice: {}, dice: {},
css: "" css: "",
} as M5RollResult } as M5RollResult;
rollData.rolls["1"] = { rollData.rolls["1"] = {
formula: "1d6 - 4 + @c.calc.stats.damageBonus + @i.damageBonus", formula: "1d6 - 4 + @c.calc.stats.damageBonus + @i.damageBonus",
@@ -206,40 +199,100 @@ export class M5Roll { // extends Roll<M5RollData>
total: 0, total: 0,
totalStr: "", totalStr: "",
dice: {}, dice: {},
css: "" css: "",
} as M5RollResult } 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 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;
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,
};
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"));
}
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;
return new M5Roll(rollData, actor, (game as Game).i18n.localize("midgard5.resistanceBody"));
} }
static parseDiceSides(formula: string): FormulaParseResult { static parseDiceSides(formula: string): FormulaParseResult {
const ewMatcher: RegExp = /\d*[dD]20/g const ewMatcher: RegExp = /\d*[dD]20/g;
const pwMatcher: RegExp = /(\d+)\s*\-\s*\d*[dD]100/g const pwMatcher: RegExp = /(\d+)\s*\-\s*\d*[dD]100/g;
let res = formula.match(ewMatcher) let res = formula.match(ewMatcher);
if (res && !!res[0]) { if (res && !!res[0]) {
return { return {
sides: 20, sides: 20,
type: "ew", type: "ew",
threshold: null threshold: null,
} };
} }
res = formula.match(pwMatcher) res = formula.match(pwMatcher);
if (res && !!res[1]) { if (res && !!res[1]) {
return { return {
sides: 100, sides: 100,
type: "pw", type: "pw",
threshold: parseInt(res[1]) threshold: parseInt(res[1]),
} };
} }
return null return null;
} }
} }
interface FormulaParseResult { interface FormulaParseResult {
sides: number, sides: number;
type: string, type: string;
threshold: number threshold: number;
} }
+14
View File
@@ -167,6 +167,20 @@ export default class M5CharacterSheet extends ActorSheet {
await roll.toMessage(); await roll.toMessage();
}); });
html.find(".roll-defense-button").on("click", async (event) => {
const roll = M5Roll.defense(this.actor);
await roll.toMessage();
});
html.find(".roll-resistanceMind-button").on("click", async (event) => {
const roll = M5Roll.resistanceMind(this.actor);
await roll.toMessage();
});
html.find(".roll-resistanceBody-button").on("click", async (event) => {
const roll = M5Roll.resistanceBody(this.actor);
await roll.toMessage();
});
// Drag & Drop // Drag & Drop
const dragDrop = new DragDrop({ const dragDrop = new DragDrop({
dragSelector: ".items-list .item", dragSelector: ".items-list .item",
+3 -3
View File
@@ -2,7 +2,7 @@
"id": "midgard5", "id": "midgard5",
"title": "Midgard 5. Edition", "title": "Midgard 5. Edition",
"description": "The German RPG Midgard 5. Edition", "description": "The German RPG Midgard 5. Edition",
"version": "1.2.0", "version": "1.2.2",
"compatibility": { "compatibility": {
"minimum": "10", "minimum": "10",
"verified": "10" "verified": "10"
@@ -66,8 +66,8 @@
"primaryTokenAttribute": "lp", "primaryTokenAttribute": "lp",
"secondaryTokenAttribute": "ap", "secondaryTokenAttribute": "ap",
"url": "https://github.com/Byroks/foundry-vtt-system-midgard5", "url": "https://github.com/Byroks/foundry-vtt-system-midgard5",
"manifest": "https://github.com/Byroks/foundry-vtt-system-midgard5/releases/download/v1.2.0/system.json", "manifest": "https://github.com/Byroks/foundry-vtt-system-midgard5/releases/download/v1.2.2/system.json",
"download": "https://github.com/Byroks/foundry-vtt-system-midgard5/releases/download/v1.2.0/midgard5-v1.2.0.zip", "download": "https://github.com/Byroks/foundry-vtt-system-midgard5/releases/download/v1.2.2/midgard5-v1.2.2.zip",
"initiative": "@calc.attributes.gw.value", "initiative": "@calc.attributes.gw.value",
"license": "LICENSE.txt" "license": "LICENSE.txt"
} }
+10 -1
View File
@@ -126,7 +126,16 @@
<tbody> <tbody>
<tr> <tr>
<td>{{localize "midgard5.race"}}</td> <td>{{localize "midgard5.race"}}</td>
<td><input name="data.info.race" type="text" value="{{data.info.race}}" data-dtype="String" /></td> <td>
<input list="races" type="search" name="data.info.race" value="{{data.info.race}}" />
<datalist id="races">
<option value="Mensch">
<option value="Elf">
<option value="Gnom">
<option value="Halbling">
<option value="Zwerg">
</datalist>
</td>
<td>{{localize "midgard5.gender"}}</td> <td>{{localize "midgard5.gender"}}</td>
<td><input name="data.info.gender" type="text" value="{{data.info.gender}}" data-dtype="String" /></td> <td><input name="data.info.gender" type="text" value="{{data.info.gender}}" data-dtype="String" /></td>
</tr> </tr>
+21
View File
@@ -44,6 +44,27 @@
<td class="fixed-value"><a class="item-delete" title="Delete Item"><i class="fas fa-trash"></i></a></td> <td class="fixed-value"><a class="item-delete" title="Delete Item"><i class="fas fa-trash"></i></a></td>
</tr> </tr>
{{/each}} {{/each}}
<tr data-item="{{itemId}}">
<td class="padding edit-item">{{localize "midgard5.defense"}}</td>
<td class="center">{{add data.calc.stats.defense.value data.calc.stats.defenseBonus.value}}</td>
<td class="fixed-value"><button class="roll-button roll-defense-button"></button></td>
<td class="fixed-value"></td>
</tr>
<tr data-item="{{itemId}}">
<td class="padding edit-item">{{localize "midgard5.resistanceMind"}}</td>
<td class="center">{{data.calc.stats.resistanceMind.value}}</td>
<td class="fixed-value"><button class="roll-button roll-resistanceMind-button"></button></td>
<td class="fixed-value"></td>
</tr>
<tr data-item="{{itemId}}">
<td class="padding edit-item">{{localize "midgard5.resistanceBody"}}</td>
<td class="center">{{data.calc.stats.resistanceBody.value}}</td>
<td class="fixed-value"><button class="roll-button roll-resistanceBody-button"></button></td>
<td class="fixed-value"></td>
</tr>
</tbody> </tbody>
</table> </table>
+2
View File
@@ -119,6 +119,7 @@
</thead> </thead>
<tbody> <tbody>
{{#each data.skills.general as |skill key|}} {{#each data.skills.general as |skill key|}}
{{#unless (isSkillInList (localizeMidgard key) ../actor.system.calc.skills.general) }}
<tr data-skill="{{key}}"> <tr data-skill="{{key}}">
<td><button class="learn-button">{{localize "midgard5.learn"}}</button></td> <td><button class="learn-button">{{localize "midgard5.learn"}}</button></td>
<td class="padding">{{localizeMidgard key}}</td> <td class="padding">{{localizeMidgard key}}</td>
@@ -129,6 +130,7 @@
<td class="fixed-value"><button class="roll-button roll-general-button"></button></td> <td class="fixed-value"><button class="roll-button roll-general-button"></button></td>
<td class="fixed-value"></td> <td class="fixed-value"></td>
</tr> </tr>
{{/unless}}
{{/each}} {{/each}}
</tbody> </tbody>
</table> </table>