@plokkke/sw-rune
Version:
Library defining all utils for summoners war rune handling
113 lines (112 loc) • 5.04 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.statFromSW = exports.runeFromSW = exports.upgrade = exports.generate = void 0;
const constants_1 = require("./constants");
const random_1 = require("./random");
const constraints_1 = require("./constraints");
const lodash_1 = __importDefault(require("lodash"));
const random_2 = require("@plokkke/toolbox/random");
function initMainEffect(slot, grade, initialEffect) {
if (initialEffect && !constraints_1.MAIN_EFFECT_BY_SLOT[slot].includes(initialEffect)) {
throw new Error(`Main stat ${initialEffect} is not available for slot ${slot}`);
}
const type = initialEffect ?? (0, random_1.randomMainEffect)(slot);
const value = mainEffectValue(grade, type, 0);
return { effect: type, value };
}
function initInnateStat(isAncient, slot, grade, mainEffect, param) {
const excluded = [mainEffect, ...constraints_1.EXCLUDED_EFFECTS_BY_SLOT[slot]];
if (typeof param === 'string' && excluded.includes(param)) {
throw new Error(`Innate stat ${param} is not available for slot ${slot}`);
}
const hasInnateStat = !lodash_1.default.isUndefined(param) ? Boolean(param) : (0, random_1.randomHasInnateStat)();
if (!hasInnateStat) {
return null;
}
const type = typeof param === 'string' ? param : (0, random_1.randomSubEffect)(excluded);
const value = (0, random_1.randomEffectValue)(grade, type, isAncient);
return { effect: type, value };
}
function initSubStats(isAncient, slot, grade, quality, mainEffect, innateEffect) {
const subStatCount = constants_1.RUNE_QUALITIES.indexOf(quality);
const excluded = [...constraints_1.EXCLUDED_EFFECTS_BY_SLOT[slot], mainEffect, ...(innateEffect ? [innateEffect] : [])];
return lodash_1.default.times(subStatCount, () => {
const type = (0, random_1.randomSubEffect)(excluded);
excluded.push(type);
return { effect: type, value: (0, random_1.randomEffectValue)(grade, type, isAncient) };
});
}
function generate(options) {
const isAncient = options?.isAncient || (0, random_1.randomIsAncient)();
const set = options?.set || (0, random_1.randomSet)();
const slot = options?.slot || (0, random_1.randomSlot)();
const grade = options?.grade || (0, random_1.randomGrade)();
const quality = options?.quality || (0, random_1.randomQuality)();
const mainStat = initMainEffect(slot, grade, options?.mainEffect);
const innateStat = initInnateStat(isAncient, slot, grade, mainStat.effect, options?.innateEffect);
const subStats = initSubStats(isAncient, slot, grade, quality, mainStat.effect, innateStat?.effect ?? null);
return {
isAncient,
slot,
grade,
quality,
set,
level: 0,
mainStat,
innateStat,
subStats,
};
}
exports.generate = generate;
function excludeSubEffect(rune) {
return [...constraints_1.EXCLUDED_EFFECTS_BY_SLOT[rune.slot], rune.mainStat.effect, ...(rune.innateStat ? [rune.innateStat.effect] : []), ...rune.subStats.map((stat) => stat.effect)];
}
function mainEffectValue(grade, type, level) {
const rule = constraints_1.VALUE_BY_GRADE_AND_STAT_TYPE[grade][type];
return level >= 15 ? rule.final : Math.floor(rule.base + rule.inc * level);
}
function upgrade(rune) {
const currentUpgrade = Math.floor(rune.level / 3);
if (currentUpgrade >= 5) {
return rune;
}
rune.level = (currentUpgrade + 1) * 3;
rune.mainStat.value = mainEffectValue(rune.grade, rune.mainStat.effect, rune.level);
const subStats = rune.subStats;
if (currentUpgrade < 4) {
const qualityIdx = constants_1.RUNE_QUALITIES.indexOf(rune.quality);
if (currentUpgrade >= qualityIdx) {
const type = (0, random_1.randomSubEffect)(excludeSubEffect(rune));
const value = (0, random_1.randomEffectValue)(rune.grade, type);
subStats.push({ effect: type, value });
}
else {
const subStat = (0, random_2.randomItem)(subStats);
subStat.value += (0, random_1.randomEffectValue)(rune.grade, subStat.effect);
}
}
return rune;
}
exports.upgrade = upgrade;
function runeFromSW(rune) {
return {
isAncient: rune.extra >= 10,
isEquipped: !!rune.occupied_id,
slot: rune.slot_no,
grade: rune.class,
quality: constants_1.RUNE_QUALITIES[(rune.extra % 10) - 1],
set: constants_1.RUNE_SET_BY_ID[rune.set_id],
level: rune.upgrade_curr,
mainStat: statFromSW(rune.pri_eff),
innateStat: rune.prefix_eff[0] !== 0 ? statFromSW(rune.prefix_eff) : null,
subStats: rune.sec_eff.map(statFromSW),
};
}
exports.runeFromSW = runeFromSW;
function statFromSW([effectId, value]) {
return { effect: constants_1.RUNE_EFFECT_BY_ID[effectId], value };
}
exports.statFromSW = statFromSW;