generated from nhcarrigan/template
feat: display unlock conditions on all locked items
All locked items now show players exactly what they need to do next: - Adventurers: "📜 Complete: [Quest Name]" - Upgrades: "⚔️ Defeat: [Boss]" or "📜 Complete: [Quest]" - Equipment (boss drops): "⚔️ Drop: [Boss Name]" instead of generic label - Bosses: "⚔️ Defeat: [Previous Boss] first" or zone gate boss - Quests: "📜 Complete: [Prerequisite Quest]" Also wires adventurer unlocks through quests (militia through dragon_rider had no unlock path), retroactively applies rewards on existing saves, syncs boss reward arrays from defaults on load, and removes invalid rune_stone reference from Forest Giant.
This commit is contained in:
@@ -49,7 +49,7 @@ export const DEFAULT_BOSSES: Boss[] = [
|
||||
essenceReward: 400,
|
||||
crystalReward: 20,
|
||||
upgradeRewards: ["archmage_1"],
|
||||
equipmentRewards: ["hide_armour", "rune_stone"],
|
||||
equipmentRewards: ["hide_armour"],
|
||||
prestigeRequirement: 0,
|
||||
zoneId: "verdant_vale",
|
||||
},
|
||||
|
||||
@@ -8,7 +8,10 @@ export const DEFAULT_QUESTS: Quest[] = [
|
||||
description: "Every legend begins somewhere. Send your first adventurer into the field.",
|
||||
status: "available",
|
||||
durationSeconds: 60,
|
||||
rewards: [{ type: "gold", amount: 500 }],
|
||||
rewards: [
|
||||
{ type: "gold", amount: 500 },
|
||||
{ type: "adventurer", targetId: "militia" },
|
||||
],
|
||||
prerequisiteIds: [],
|
||||
zoneId: "verdant_vale",
|
||||
},
|
||||
@@ -21,6 +24,7 @@ export const DEFAULT_QUESTS: Quest[] = [
|
||||
rewards: [
|
||||
{ type: "gold", amount: 2_000 },
|
||||
{ type: "essence", amount: 5 },
|
||||
{ type: "adventurer", targetId: "apprentice" },
|
||||
],
|
||||
prerequisiteIds: ["first_steps"],
|
||||
zoneId: "verdant_vale",
|
||||
@@ -34,6 +38,7 @@ export const DEFAULT_QUESTS: Quest[] = [
|
||||
rewards: [
|
||||
{ type: "crystals", amount: 10 },
|
||||
{ type: "upgrade", targetId: "global_1" },
|
||||
{ type: "adventurer", targetId: "scout" },
|
||||
],
|
||||
prerequisiteIds: ["goblin_camp"],
|
||||
zoneId: "verdant_vale",
|
||||
@@ -47,6 +52,7 @@ export const DEFAULT_QUESTS: Quest[] = [
|
||||
rewards: [
|
||||
{ type: "essence", amount: 50 },
|
||||
{ type: "upgrade", targetId: "click_2" },
|
||||
{ type: "adventurer", targetId: "acolyte" },
|
||||
],
|
||||
prerequisiteIds: ["haunted_mine"],
|
||||
zoneId: "verdant_vale",
|
||||
@@ -63,6 +69,7 @@ export const DEFAULT_QUESTS: Quest[] = [
|
||||
{ type: "gold", amount: 15_000 },
|
||||
{ type: "essence", amount: 20 },
|
||||
{ type: "upgrade", targetId: "cleric_1" },
|
||||
{ type: "adventurer", targetId: "ranger" },
|
||||
],
|
||||
prerequisiteIds: [],
|
||||
zoneId: "shattered_ruins",
|
||||
@@ -78,6 +85,7 @@ export const DEFAULT_QUESTS: Quest[] = [
|
||||
{ type: "gold", amount: 80_000 },
|
||||
{ type: "essence", amount: 120 },
|
||||
{ type: "upgrade", targetId: "scout_1" },
|
||||
{ type: "adventurer", targetId: "knight" },
|
||||
],
|
||||
prerequisiteIds: ["necromancer_tower"],
|
||||
zoneId: "shattered_ruins",
|
||||
@@ -93,6 +101,7 @@ export const DEFAULT_QUESTS: Quest[] = [
|
||||
{ type: "essence", amount: 300 },
|
||||
{ type: "crystals", amount: 30 },
|
||||
{ type: "upgrade", targetId: "mage_1" },
|
||||
{ type: "adventurer", targetId: "archmage" },
|
||||
],
|
||||
prerequisiteIds: ["crumbling_fortress"],
|
||||
zoneId: "shattered_ruins",
|
||||
@@ -107,6 +116,7 @@ export const DEFAULT_QUESTS: Quest[] = [
|
||||
rewards: [
|
||||
{ type: "gold", amount: 500_000 },
|
||||
{ type: "crystals", amount: 50 },
|
||||
{ type: "adventurer", targetId: "paladin" },
|
||||
{ type: "adventurer", targetId: "dragon_rider" },
|
||||
],
|
||||
prerequisiteIds: ["cursed_library"],
|
||||
|
||||
@@ -61,7 +61,7 @@ gameRouter.get("/load", async (context) => {
|
||||
}
|
||||
}
|
||||
|
||||
// Backfill equipmentRewards on bosses that predate the field
|
||||
// Backfill equipmentRewards on bosses that predate the field (will be synced below after defaults load)
|
||||
for (const boss of state.bosses) {
|
||||
if (!Array.isArray(boss.equipmentRewards)) {
|
||||
boss.equipmentRewards = [];
|
||||
@@ -82,7 +82,7 @@ gameRouter.get("/load", async (context) => {
|
||||
}
|
||||
}
|
||||
|
||||
// Sync zoneId on quests to match current defaults
|
||||
// Sync zoneId and rewards on quests to match current defaults
|
||||
for (const quest of state.quests) {
|
||||
const defaults = DEFAULT_QUESTS.find((d) => d.id === quest.id);
|
||||
if (defaults && quest.zoneId !== defaults.zoneId) {
|
||||
@@ -93,6 +93,23 @@ gameRouter.get("/load", async (context) => {
|
||||
quest.zoneId = defaults?.zoneId ?? "verdant_vale";
|
||||
needsBackfill = true;
|
||||
}
|
||||
// Sync rewards to match defaults so newly-added rewards take effect
|
||||
if (defaults && JSON.stringify(quest.rewards) !== JSON.stringify(defaults.rewards)) {
|
||||
quest.rewards = structuredClone(defaults.rewards);
|
||||
needsBackfill = true;
|
||||
}
|
||||
// Retroactively apply adventurer unlocks from already-completed quests
|
||||
if (quest.status === "completed") {
|
||||
for (const reward of quest.rewards) {
|
||||
if (reward.type === "adventurer" && reward.targetId) {
|
||||
const adventurer = state.adventurers.find((a) => a.id === reward.targetId);
|
||||
if (adventurer && !adventurer.unlocked) {
|
||||
adventurer.unlocked = true;
|
||||
needsBackfill = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const defaultUpgrade of DEFAULT_UPGRADES) {
|
||||
@@ -149,13 +166,24 @@ gameRouter.get("/load", async (context) => {
|
||||
}
|
||||
}
|
||||
|
||||
// Backfill zoneId on bosses that predate the field
|
||||
// Backfill zoneId and sync rewards on bosses to match current defaults
|
||||
for (const boss of state.bosses) {
|
||||
const defaults = DEFAULT_BOSSES.find((d) => d.id === boss.id);
|
||||
if (!boss.zoneId) {
|
||||
const defaults = DEFAULT_BOSSES.find((d) => d.id === boss.id);
|
||||
boss.zoneId = defaults?.zoneId ?? "verdant_vale";
|
||||
needsBackfill = true;
|
||||
}
|
||||
// Sync equipmentRewards and upgradeRewards to match defaults
|
||||
if (defaults) {
|
||||
if (JSON.stringify(boss.equipmentRewards) !== JSON.stringify(defaults.equipmentRewards)) {
|
||||
boss.equipmentRewards = structuredClone(defaults.equipmentRewards);
|
||||
needsBackfill = true;
|
||||
}
|
||||
if (JSON.stringify(boss.upgradeRewards) !== JSON.stringify(defaults.upgradeRewards)) {
|
||||
boss.upgradeRewards = structuredClone(defaults.upgradeRewards);
|
||||
needsBackfill = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge new bosses from defaults (new zones' bosses)
|
||||
|
||||
Reference in New Issue
Block a user