Add level-aware builder controls
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
export type Roll = { statId: string; value: number };
|
||||
export type GearSelection = { itemId: string; level: number; brandId: string; talentId: string; health: number; armor: number; rolls: Roll[]; augmentSlots: number[] };
|
||||
export type WeaponSelection = { itemId: string; tier: number; damage: number; firepower: number; toughness: number; engineering: number; talent1Id: string; talent2Id: string };
|
||||
export type GearSelection = { itemId: string; level: number; brandId: string; talentId: string; health: number; armor: number; rolls: [Roll, Roll]; augmentSlots: number[] };
|
||||
export type WeaponSelection = { itemId: string; level: number; tier: number; damage: number; firepower: number; toughness: number; engineering: number; talent1Id: string; talent2Id: string; rolls: [Roll, Roll] };
|
||||
export type ChipSelection = { setId: string; quality: 'Superior' | 'High-end'; primary: Roll; secondary: [Roll, Roll] };
|
||||
export type ProtocolSelection = { itemId: string; level: number; talentUpgrades: number };
|
||||
export type LoadoutDraft = {
|
||||
@@ -15,8 +15,8 @@ export type LoadoutDraft = {
|
||||
|
||||
export const gearSlots = ['Holster', 'Gloves', 'Backpack', 'Knee Pads', 'Body Armor', 'Mask'] as const;
|
||||
export const blankRoll = (): Roll => ({ statId: '', value: 0 });
|
||||
export const blankGear = (): GearSelection => ({ itemId: '', level: 50, brandId: '', talentId: '', health: 0, armor: 0, rolls: [blankRoll()], augmentSlots: [] });
|
||||
export const blankWeapon = (): WeaponSelection => ({ itemId: '', tier: 0, damage: 0, firepower: 0, toughness: 0, engineering: 0, talent1Id: '', talent2Id: '' });
|
||||
export const blankGear = (): GearSelection => ({ itemId: '', level: 50, brandId: '', talentId: '', health: 0, armor: 0, rolls: [blankRoll(), blankRoll()], augmentSlots: [] });
|
||||
export const blankWeapon = (): WeaponSelection => ({ itemId: '', level: 50, tier: 0, damage: 0, firepower: 0, toughness: 0, engineering: 0, talent1Id: '', talent2Id: '', rolls: [blankRoll(), blankRoll()] });
|
||||
export const blankChip = (): ChipSelection => ({ setId: '', quality: 'Superior', primary: blankRoll(), secondary: [blankRoll(), blankRoll()] });
|
||||
export const createDraft = (): LoadoutDraft => ({
|
||||
version: 1,
|
||||
@@ -36,3 +36,45 @@ export const clamp = (value: unknown, min: unknown, max: unknown) => {
|
||||
|
||||
export const scaled = (min: unknown, max: unknown, progress: number, steps: number) =>
|
||||
Number(min) + (Number(max) - Number(min)) * Math.min(steps, Math.max(0, progress)) / steps;
|
||||
|
||||
export type LevelScaledRange = {
|
||||
rawMin: number;
|
||||
rawMax: number;
|
||||
min: number;
|
||||
max: number;
|
||||
provisional: boolean;
|
||||
};
|
||||
|
||||
const itemLevel = (value: unknown) => Math.round(clamp(value, 1, 50));
|
||||
export const gearMultiplier = (level: unknown) => 0.91 + 0.05 * itemLevel(level);
|
||||
export const weaponMultiplier = (level: unknown) => 1.14 + 0.05 * itemLevel(level);
|
||||
|
||||
export function levelScaledRange(
|
||||
minimum: unknown,
|
||||
maximum: unknown,
|
||||
targetLevel: unknown,
|
||||
referenceLevel: unknown,
|
||||
source: 'gear' | 'weapon'
|
||||
): LevelScaledRange {
|
||||
const target = itemLevel(targetLevel);
|
||||
const reference = itemLevel(referenceLevel);
|
||||
const multiplier = source === 'gear' ? gearMultiplier : weaponMultiplier;
|
||||
const ratio = multiplier(target) / multiplier(reference);
|
||||
const configuredMin = Number(minimum);
|
||||
const configuredMax = Number(maximum);
|
||||
const rawMin = (Number.isFinite(configuredMin) ? configuredMin : 0) * ratio;
|
||||
const rawMax = (Number.isFinite(configuredMax) ? configuredMax : 0) * ratio;
|
||||
return {
|
||||
rawMin,
|
||||
rawMax,
|
||||
min: Math.floor(rawMin),
|
||||
max: Math.floor(rawMax),
|
||||
provisional: source === 'gear' ? target < 10 || reference < 10 : target < 40 || reference < 40
|
||||
};
|
||||
}
|
||||
|
||||
export function remapRangeValue(value: unknown, from: LevelScaledRange, to: LevelScaledRange) {
|
||||
const span = from.max - from.min;
|
||||
const position = span > 0 ? (clamp(value, from.min, from.max) - from.min) / span : 0;
|
||||
return Math.round(to.min + (to.max - to.min) * position);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user