import { M5Attribute, M5AttributeCalculated, M5Attributes, M5CharacterCalculatedData, M5ItemMod, M5ModOperation, M5ModResult, M5ModSource, M5ModType, M5Stats, M5ModPair } from "../M5Base" export default class M5ModAggregate { private attributes = new Map>() private stats = new Map>() private skills = new Map>() constructor(public data: any, public calc: M5CharacterCalculatedData) { const characterString = (game as Game).i18n.localize("ACTOR.TypeCharacter") 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.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.movementBonus.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) } push(mod: M5ItemMod, source: string) { if (!mod?.id || mod.id === "") return let map: Map> = 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.has(mod.id)) map.get(mod.id).push(pair) else map.set(mod.id, [pair]) } } 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.stats.forEach((pairs, id) => { const res = M5ModAggregate.processPairs(pairs) calc.stats[id] = res }) const ret = {} this.skills.forEach((pairs, id) => { ret[id] = pairs }) return ret } static pairAsSource(pair: M5ModPair): M5ModSource { return { operation: pair.mod.operation, value: pair.mod.value, item: pair.source } } static processPairs(arr: Array): 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] 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) 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) } } return ret } 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 modToString(mod: M5ItemMod): string { } }