generated from nhcarrigan/template
fix: adventurer unlocks not applied by force-unlock tool #93
@@ -257,6 +257,37 @@ const applyBossUnlocks = (state: GameState): number => {
|
|||||||
return count;
|
return count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlocks any adventurer tiers that were granted as rewards for completed quests
|
||||||
|
* but are still locked in the player's state.
|
||||||
|
* @param state - The player's current game state (mutated directly).
|
||||||
|
* @returns The number of adventurer tiers that were unlocked.
|
||||||
|
*/
|
||||||
|
const applyAdventurerUnlocks = (state: GameState): number => {
|
||||||
|
let count = 0;
|
||||||
|
const earnedAdventurerIds = new Set<string>();
|
||||||
|
|
||||||
|
for (const quest of state.quests) {
|
||||||
|
if (quest.status !== "completed") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (const reward of quest.rewards) {
|
||||||
|
if (reward.type === "adventurer" && reward.targetId !== undefined) {
|
||||||
|
earnedAdventurerIds.add(reward.targetId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const adventurer of state.adventurers) {
|
||||||
|
if (!adventurer.unlocked && earnedAdventurerIds.has(adventurer.id)) {
|
||||||
|
adventurer.unlocked = true;
|
||||||
|
count = count + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes available any exploration areas whose parent zone is now unlocked.
|
* Makes available any exploration areas whose parent zone is now unlocked.
|
||||||
* @param state - The player's current game state (mutated directly).
|
* @param state - The player's current game state (mutated directly).
|
||||||
@@ -301,6 +332,7 @@ const applyExplorationUnlocks = (state: GameState): number => {
|
|||||||
const applyForceUnlocks = (
|
const applyForceUnlocks = (
|
||||||
state: GameState,
|
state: GameState,
|
||||||
): {
|
): {
|
||||||
|
adventurersUnlocked: number;
|
||||||
bossesUnlocked: number;
|
bossesUnlocked: number;
|
||||||
explorationUnlocked: number;
|
explorationUnlocked: number;
|
||||||
questsUnlocked: number;
|
questsUnlocked: number;
|
||||||
@@ -310,7 +342,14 @@ const applyForceUnlocks = (
|
|||||||
const questsUnlocked = applyQuestUnlocks(state);
|
const questsUnlocked = applyQuestUnlocks(state);
|
||||||
const bossesUnlocked = applyBossUnlocks(state);
|
const bossesUnlocked = applyBossUnlocks(state);
|
||||||
const explorationUnlocked = applyExplorationUnlocks(state);
|
const explorationUnlocked = applyExplorationUnlocks(state);
|
||||||
return { bossesUnlocked, explorationUnlocked, questsUnlocked, zonesUnlocked };
|
const adventurersUnlocked = applyAdventurerUnlocks(state);
|
||||||
|
return {
|
||||||
|
adventurersUnlocked,
|
||||||
|
bossesUnlocked,
|
||||||
|
explorationUnlocked,
|
||||||
|
questsUnlocked,
|
||||||
|
zonesUnlocked,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const debugRouter = new Hono<HonoEnvironment>();
|
const debugRouter = new Hono<HonoEnvironment>();
|
||||||
@@ -330,8 +369,13 @@ debugRouter.post("/force-unlocks", async(context) => {
|
|||||||
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Prisma stores state as JSON object */
|
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Prisma stores state as JSON object */
|
||||||
const state = gameStateRecord.state as unknown as GameState;
|
const state = gameStateRecord.state as unknown as GameState;
|
||||||
|
|
||||||
const { bossesUnlocked, explorationUnlocked, questsUnlocked, zonesUnlocked }
|
const {
|
||||||
= applyForceUnlocks(state);
|
adventurersUnlocked,
|
||||||
|
bossesUnlocked,
|
||||||
|
explorationUnlocked,
|
||||||
|
questsUnlocked,
|
||||||
|
zonesUnlocked,
|
||||||
|
} = applyForceUnlocks(state);
|
||||||
|
|
||||||
const updatedAt = Date.now();
|
const updatedAt = Date.now();
|
||||||
await prisma.gameState.update({
|
await prisma.gameState.update({
|
||||||
@@ -347,6 +391,7 @@ debugRouter.post("/force-unlocks", async(context) => {
|
|||||||
: computeHmac(JSON.stringify(state), secret);
|
: computeHmac(JSON.stringify(state), secret);
|
||||||
|
|
||||||
return context.json({
|
return context.json({
|
||||||
|
adventurersUnlocked,
|
||||||
bossesUnlocked,
|
bossesUnlocked,
|
||||||
explorationUnlocked,
|
explorationUnlocked,
|
||||||
questsUnlocked,
|
questsUnlocked,
|
||||||
|
|||||||
@@ -51,11 +51,15 @@ const DebugPanel = (): JSX.Element => {
|
|||||||
if (result.explorationUnlocked > 0) {
|
if (result.explorationUnlocked > 0) {
|
||||||
parts.push(`${String(result.explorationUnlocked)} exploration area(s)`);
|
parts.push(`${String(result.explorationUnlocked)} exploration area(s)`);
|
||||||
}
|
}
|
||||||
|
if (result.adventurersUnlocked > 0) {
|
||||||
|
parts.push(`${String(result.adventurersUnlocked)} adventurer tier(s)`);
|
||||||
|
}
|
||||||
const total
|
const total
|
||||||
= result.zonesUnlocked
|
= result.zonesUnlocked
|
||||||
+ result.questsUnlocked
|
+ result.questsUnlocked
|
||||||
+ result.bossesUnlocked
|
+ result.bossesUnlocked
|
||||||
+ result.explorationUnlocked;
|
+ result.explorationUnlocked
|
||||||
|
+ result.adventurersUnlocked;
|
||||||
const message
|
const message
|
||||||
= parts.length === 0
|
= parts.length === 0
|
||||||
? "Everything looks correct — no missing unlocks were found."
|
? "Everything looks correct — no missing unlocks were found."
|
||||||
|
|||||||
@@ -558,6 +558,7 @@ interface GameContextValue {
|
|||||||
* @returns Counts of what was corrected.
|
* @returns Counts of what was corrected.
|
||||||
*/
|
*/
|
||||||
forceUnlocks: ()=> Promise<{
|
forceUnlocks: ()=> Promise<{
|
||||||
|
adventurersUnlocked: number;
|
||||||
bossesUnlocked: number;
|
bossesUnlocked: number;
|
||||||
explorationUnlocked: number;
|
explorationUnlocked: number;
|
||||||
questsUnlocked: number;
|
questsUnlocked: number;
|
||||||
@@ -2104,6 +2105,7 @@ export const GameProvider = ({
|
|||||||
localStorage.setItem("elysium_save_signature", data.signature);
|
localStorage.setItem("elysium_save_signature", data.signature);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
adventurersUnlocked: data.adventurersUnlocked,
|
||||||
bossesUnlocked: data.bossesUnlocked,
|
bossesUnlocked: data.bossesUnlocked,
|
||||||
explorationUnlocked: data.explorationUnlocked,
|
explorationUnlocked: data.explorationUnlocked,
|
||||||
questsUnlocked: data.questsUnlocked,
|
questsUnlocked: data.questsUnlocked,
|
||||||
@@ -2116,6 +2118,7 @@ export const GameProvider = ({
|
|||||||
: "Failed to force unlocks",
|
: "Failed to force unlocks",
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
|
adventurersUnlocked: 0,
|
||||||
bossesUnlocked: 0,
|
bossesUnlocked: 0,
|
||||||
explorationUnlocked: 0,
|
explorationUnlocked: 0,
|
||||||
questsUnlocked: 0,
|
questsUnlocked: 0,
|
||||||
|
|||||||
@@ -425,6 +425,11 @@ interface ForceUnlocksResponse {
|
|||||||
*/
|
*/
|
||||||
explorationUnlocked: number;
|
explorationUnlocked: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of adventurer tiers that were unlocked by this operation.
|
||||||
|
*/
|
||||||
|
adventurersUnlocked: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HMAC-SHA256 signature of the corrected state for anti-cheat chain continuity.
|
* HMAC-SHA256 signature of the corrected state for anti-cheat chain continuity.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user