generated from nhcarrigan/template
fix: resolve sync inflation, signature mismatch, CP accuracy, auto-buy cap, unlock hints
- #147: Guard all patch functions with hasChanged before incrementing sync counter to prevent inflation on no-op patches - #148: Clear stale HMAC signature after each boss fight so subsequent auto-saves do not send a mismatched signature - #146: Auto-unlock adventurer-specific upgrades in applyTick when their adventurer count > 0; show recruit hint in upgrade panel - #149: Add Essence/s row to resource bar dropdown - #150: Fix broken auto-quest CP reduce formula; centralise via computePartyCombatPower which applies all multipliers correctly - #151: Cap auto-buy at 100 for non-max-tier adventurers; max tier (highest level unlocked) remains uncapped - #152: Export computePartyCombatPower from tick, applying global upgrades, prestige, equipment, set bonuses, echo, crafted, and companion multipliers; use it in resource bar and boss panel
This commit is contained in:
@@ -11,10 +11,11 @@
|
||||
/* eslint-disable max-lines -- Boss panel with sub-component and helper function */
|
||||
import { type JSX, useState } from "react";
|
||||
import { useGame } from "../../context/gameContext.js";
|
||||
import { computePartyCombatPower } from "../../engine/tick.js";
|
||||
import { cdnImage } from "../../utils/cdn.js";
|
||||
import { LockToggle } from "../ui/lockToggle.js";
|
||||
import { ZoneSelector } from "./zoneSelector.js";
|
||||
import type { Boss, GameState } from "@elysium/types";
|
||||
import type { Boss } from "@elysium/types";
|
||||
|
||||
interface BossCardProperties {
|
||||
readonly boss: Boss;
|
||||
@@ -157,72 +158,6 @@ const BossCard = ({
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Computes party DPS and HP from the current game state.
|
||||
* @param state - The full game state.
|
||||
* @returns The computed party DPS and HP values.
|
||||
*/
|
||||
const computePartyStats = (
|
||||
state: GameState,
|
||||
): {
|
||||
partyDps: number;
|
||||
partyHp: number;
|
||||
} => {
|
||||
const { upgrades, adventurers, equipment, prestige } = state;
|
||||
let globalMultiplier = 1;
|
||||
for (const upgrade of upgrades) {
|
||||
const { purchased, target, multiplier } = upgrade;
|
||||
if (purchased && target === "global") {
|
||||
globalMultiplier = globalMultiplier * multiplier;
|
||||
}
|
||||
}
|
||||
const prestigeBonus = prestige.count * 0.1;
|
||||
const prestigeMultiplier = 1 + prestigeBonus;
|
||||
const equipmentCombatMultiplier = equipment.
|
||||
filter((item) => {
|
||||
return item.equipped && item.bonus.combatMultiplier !== undefined;
|
||||
}).
|
||||
reduce((multiplier, item) => {
|
||||
return multiplier * (item.bonus.combatMultiplier ?? 1);
|
||||
}, 1);
|
||||
|
||||
let partyDps = 0;
|
||||
let partyHp = 0;
|
||||
for (const adventurer of adventurers) {
|
||||
const { count, id: adventurerId, combatPower, level } = adventurer;
|
||||
if (count === 0) {
|
||||
continue;
|
||||
}
|
||||
let adventurerMultiplier = 1;
|
||||
for (const upgrade of upgrades) {
|
||||
const {
|
||||
purchased,
|
||||
target,
|
||||
multiplier,
|
||||
adventurerId: upgradeAdventurerId,
|
||||
} = upgrade;
|
||||
if (
|
||||
purchased
|
||||
&& target === "adventurer"
|
||||
&& upgradeAdventurerId === adventurerId
|
||||
) {
|
||||
adventurerMultiplier = adventurerMultiplier * multiplier;
|
||||
}
|
||||
}
|
||||
const dps
|
||||
= combatPower
|
||||
* count
|
||||
* adventurerMultiplier
|
||||
* globalMultiplier
|
||||
* prestigeMultiplier;
|
||||
partyDps = partyDps + dps;
|
||||
const hp = level * 50 * count;
|
||||
partyHp = partyHp + hp;
|
||||
}
|
||||
partyDps = partyDps * equipmentCombatMultiplier;
|
||||
return { partyDps, partyHp };
|
||||
};
|
||||
|
||||
/**
|
||||
* Renders the boss panel with zone selection and boss list.
|
||||
* @returns The JSX element.
|
||||
@@ -266,7 +201,14 @@ const BossPanel = (): JSX.Element => {
|
||||
void handleChallenge(bossId);
|
||||
}
|
||||
|
||||
const { zones, bosses, quests, autoBoss, prestige: playerPrestige } = state;
|
||||
const {
|
||||
adventurers,
|
||||
autoBoss,
|
||||
bosses,
|
||||
prestige: playerPrestige,
|
||||
quests,
|
||||
zones,
|
||||
} = state;
|
||||
|
||||
const activeZone = zones.find((zone) => {
|
||||
return zone.id === activeZoneId;
|
||||
@@ -349,7 +291,12 @@ const BossPanel = (): JSX.Element => {
|
||||
}
|
||||
|
||||
const autoBossOn = autoBoss === true;
|
||||
const { partyDps, partyHp } = computePartyStats(state);
|
||||
const partyDps = computePartyCombatPower(state);
|
||||
let partyHp = 0;
|
||||
for (const { level, count } of adventurers) {
|
||||
// eslint-disable-next-line stylistic/no-mixed-operators -- level * 50 * count is clear
|
||||
partyHp = partyHp + level * 50 * count;
|
||||
}
|
||||
const { count: prestigeCount } = playerPrestige;
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user