#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:
+159
-157
@@ -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[];
|
||||
}
|
||||
|
||||
+622
-511
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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
@@ -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
@@ -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) {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user