generated from nhcarrigan/template
feat: another balance and bug fix pass (#238)
Working through open issues — fixes, balance changes, and features. ## Closed - Closes #161 - Closes #181 - Closes #191 - Closes #199 - Closes #201 - Closes #202 - Closes #203 - Closes #204 - Closes #205 - Closes #206 - Closes #208 - Closes #211 - Closes #212 - Closes #213 - Closes #214 - Closes #216 - Closes #219 - Closes #220 - Closes #221 - Closes #222 - Closes #224 - Closes #225 - Closes #226 - Closes #228 - Closes #229 - Closes #230 - Closes #231 - Closes #232 - Closes #233 - Closes #234 - Closes #235 - Closes #236 ✨ This PR was created with help from Hikari~ 🌸 Reviewed-on: #238 Co-authored-by: Hikari <hikari@nhcarrigan.com> Co-committed-by: Hikari <hikari@nhcarrigan.com>
This commit was merged in pull request #238.
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
/* eslint-disable react/no-multi-comp -- Sub-component is tightly coupled to the panel */
|
||||
/* eslint-disable max-lines-per-function -- Complex companion card with conditional renders */
|
||||
/* eslint-disable complexity -- Companion card has many conditional render paths */
|
||||
import { COMPANIONS, type Companion } from "@elysium/types";
|
||||
import { useGame } from "../../context/gameContext.js";
|
||||
import { cdnImage } from "../../utils/cdn.js";
|
||||
@@ -28,41 +29,13 @@ const unlockLabels: Record<string, string> = {
|
||||
transcendence: "transcendence(s)",
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats a companion unlock threshold for display.
|
||||
* @param type - The unlock condition type.
|
||||
* @param threshold - The threshold value.
|
||||
* @returns The formatted threshold string.
|
||||
*/
|
||||
const formatThreshold = (type: string, threshold: number): string => {
|
||||
if (type === "lifetimeGold") {
|
||||
if (threshold >= 1e18) {
|
||||
return `${(threshold / 1e18).toFixed(0)}Qt`;
|
||||
}
|
||||
if (threshold >= 1e15) {
|
||||
return `${(threshold / 1e15).toFixed(0)}Q`;
|
||||
}
|
||||
if (threshold >= 1e12) {
|
||||
return `${(threshold / 1e12).toFixed(0)}T`;
|
||||
}
|
||||
if (threshold >= 1e9) {
|
||||
return `${(threshold / 1e9).toFixed(0)}B`;
|
||||
}
|
||||
if (threshold >= 1e6) {
|
||||
return `${(threshold / 1e6).toFixed(0)}M`;
|
||||
}
|
||||
if (threshold >= 1e3) {
|
||||
return `${(threshold / 1e3).toFixed(0)}K`;
|
||||
}
|
||||
}
|
||||
return threshold.toString();
|
||||
};
|
||||
|
||||
interface CompanionCardProperties {
|
||||
readonly companion: Companion;
|
||||
readonly isUnlocked: boolean;
|
||||
readonly isActive: boolean;
|
||||
readonly onSelect: ()=> void;
|
||||
readonly companion: Companion;
|
||||
readonly isUnlocked: boolean;
|
||||
readonly isActive: boolean;
|
||||
readonly onSelect: ()=> void;
|
||||
readonly formatNumber: (n: number)=> string;
|
||||
readonly currentProgress: number;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,6 +45,8 @@ interface CompanionCardProperties {
|
||||
* @param props.isUnlocked - Whether this companion is unlocked.
|
||||
* @param props.isActive - Whether this companion is currently active.
|
||||
* @param props.onSelect - Callback when the companion is selected/deselected.
|
||||
* @param props.formatNumber - The number formatting utility function.
|
||||
* @param props.currentProgress - The player's current progress toward the unlock threshold.
|
||||
* @returns The JSX element.
|
||||
*/
|
||||
const CompanionCard = ({
|
||||
@@ -79,6 +54,8 @@ const CompanionCard = ({
|
||||
isUnlocked,
|
||||
isActive,
|
||||
onSelect,
|
||||
formatNumber,
|
||||
currentProgress,
|
||||
}: CompanionCardProperties): JSX.Element => {
|
||||
const bonusSign = companion.bonus.type === "questTime"
|
||||
? "-"
|
||||
@@ -137,12 +114,28 @@ const CompanionCard = ({
|
||||
: "Activate"}
|
||||
</button>
|
||||
: <div className="companion-unlock-requirement">
|
||||
{"🔒 Unlock: "}
|
||||
{formatThreshold(
|
||||
companion.unlock.type,
|
||||
companion.unlock.threshold,
|
||||
)}{" "}
|
||||
{unlockLabels[companion.unlock.type] ?? companion.unlock.type}
|
||||
<p>
|
||||
{"🔒 Unlock: "}
|
||||
{companion.unlock.type === "lifetimeGold"
|
||||
? formatNumber(companion.unlock.threshold)
|
||||
: String(companion.unlock.threshold)}{" "}
|
||||
{unlockLabels[companion.unlock.type] ?? companion.unlock.type}
|
||||
</p>
|
||||
<div className="companion-progress">
|
||||
<progress
|
||||
max={companion.unlock.threshold}
|
||||
value={Math.min(currentProgress, companion.unlock.threshold)}
|
||||
/>
|
||||
<span className="companion-progress-label">
|
||||
{companion.unlock.type === "lifetimeGold"
|
||||
? formatNumber(currentProgress)
|
||||
: String(currentProgress)}
|
||||
{" / "}
|
||||
{companion.unlock.type === "lifetimeGold"
|
||||
? formatNumber(companion.unlock.threshold)
|
||||
: String(companion.unlock.threshold)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@@ -154,7 +147,7 @@ const CompanionCard = ({
|
||||
* @returns The JSX element.
|
||||
*/
|
||||
const CompanionPanel = (): JSX.Element => {
|
||||
const { state, setActiveCompanion } = useGame();
|
||||
const { formatNumber, setActiveCompanion, state } = useGame();
|
||||
|
||||
if (state === null) {
|
||||
return (
|
||||
@@ -167,6 +160,15 @@ const CompanionPanel = (): JSX.Element => {
|
||||
const unlockedIds = state.companions?.unlockedCompanionIds ?? [];
|
||||
const activeId = state.companions?.activeCompanionId ?? null;
|
||||
|
||||
const progressByUnlockType: Record<string, number> = {
|
||||
apotheosis: state.apotheosis?.count ?? 0,
|
||||
lifetimeBosses: state.player.lifetimeBossesDefeated,
|
||||
lifetimeGold: state.player.lifetimeGoldEarned,
|
||||
lifetimeQuests: state.player.lifetimeQuestsCompleted,
|
||||
prestige: state.prestige.count,
|
||||
transcendence: state.transcendence?.count ?? 0,
|
||||
};
|
||||
|
||||
function handleSelect(companionId: string): void {
|
||||
setActiveCompanion(activeId === companionId
|
||||
? null
|
||||
@@ -204,6 +206,10 @@ const CompanionPanel = (): JSX.Element => {
|
||||
return (
|
||||
<CompanionCard
|
||||
companion={companion}
|
||||
currentProgress={
|
||||
progressByUnlockType[companion.unlock.type] ?? 0
|
||||
}
|
||||
formatNumber={formatNumber}
|
||||
isActive={activeId === companion.id}
|
||||
isUnlocked={unlockedIds.includes(companion.id)}
|
||||
key={companion.id}
|
||||
|
||||
Reference in New Issue
Block a user