foundry-vtt-system-midgard5/source/module/items/M5Item.ts

275 lines
8.4 KiB
TypeScript

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";
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 === "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,
},
},
];
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,
},
});
}
}
const res = M5ModAggregate.processPairs(pairs);
res.mods.forEach((mod) => {
if ([M5ModOperation.SET, M5ModOperation.FIXED].includes(mod.operation)) calc.fw = mod.value;
else 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;
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;
}
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;
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;
}
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 === "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;
}
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;
}
}
} else if (itemType === "item" || itemType === "effect") {
calc.mods = {};
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.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;
}
}
calc.mods[key] = modCalc;
});
}
}
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: {},
};
ret.i = item.system;
ret.iType = item.type;
return ret;
}
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}`;
// 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;
}
}
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);
}
// 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 : ""
// }
// }
// return super.migrateSystemData()
// }
}