Skip to content

Commit

Permalink
fix(dungeons): Prevent unwinnable Dungeons when no bosses are unlocked (
Browse files Browse the repository at this point in the history
pokeclicker#5600)

* Prevent Dungeon no-unlocked-boss traps

* Display dungeon enemy list if bosses are locked

* Ensure Dungeon Guides can't enter locked dungeons

* Linting

* Clean up approach, same general concept

* Small fix

* Adjust Golbat boss in Sealed Chamber

---------

Co-authored-by: CypherX <[email protected]>
  • Loading branch information
umbralOptimatum and CypherX authored Nov 13, 2024
1 parent f340615 commit 2f07f9f
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 23 deletions.
6 changes: 5 additions & 1 deletion src/scripts/dungeons/Dungeon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ class Dungeon {
}
}

public hasUnlockedBoss(): boolean {
return this.bossList.some(boss => boss.options?.requirement?.isCompleted() ?? true);
}

/**
* Retreives the weights for all the possible bosses
*/
Expand Down Expand Up @@ -3847,7 +3851,7 @@ dungeonList['Sealed Chamber'] = new Dungeon('Sealed Chamber',
},
500000,
[
new DungeonBossPokemon('Golbat', 4500000, 20, {hide: true, requirement: new QuestLineStepCompletedRequirement('The Three Golems', 8, GameConstants.AchievementOption.less)}),
new DungeonBossPokemon('Golbat', 4500000, 20, {weight: 0.25}),
new DungeonBossPokemon('Regirock', 4500000, 20, {requirement: new QuestLineStepCompletedRequirement('The Three Golems', 8)}),
new DungeonBossPokemon('Regice', 4500000, 20, {requirement: new QuestLineStepCompletedRequirement('The Three Golems', 8)}),
new DungeonBossPokemon('Registeel', 4500000, 20, {requirement: new QuestLineStepCompletedRequirement('The Three Golems', 8)}),
Expand Down
13 changes: 12 additions & 1 deletion src/scripts/dungeons/DungeonGuides.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ class DungeonGuides {
return;
}
const guide = this.list[this.selected()];
const dungeon = player.town.dungeon;
// Check player has enough currency
if (!this.canAfford()) {
Notifier.notify({
Expand All @@ -162,14 +163,24 @@ class DungeonGuides {
});
return;
}
// Just in case the dungeon is locked or something
if (!DungeonRunner.canStartDungeon(dungeon)) {
Notifier.notify({
title: `[DUNGEON GUIDE] <img src="assets/images/profile/trainer-${guide.trainerSprite}.png" height="24px" class="pixelated"/> ${guide.name}`,
message: 'You can\'t access that dungeon right now!',
type: NotificationConstants.NotificationOption.warning,
timeout: 30 * GameConstants.SECOND,
});
return;
}
// Charge the player and hire the guide
guide.hire();
this.calcCost().forEach((cost) => App.game.wallet.loseAmount(cost));
App.game.wallet.loseAmount(this.calcDungeonCost());
// Hide modals
$('.modal.show').modal('hide');
// Start the dungeon
DungeonRunner.initializeDungeon(player.town.dungeon);
DungeonRunner.initializeDungeon(dungeon);
}

public static getRandomWeightedNearbyTile(nearbyTiles: DungeonTile[]): DungeonTile {
Expand Down
57 changes: 36 additions & 21 deletions src/scripts/dungeons/DungeonRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,37 @@ class DungeonRunner {
public static continuousInteractionInput = false;

public static initializeDungeon(dungeon: Dungeon) {
if (!dungeon.isUnlocked()) {
if (dungeon.name === 'Viridian Forest') {
Notifier.notify({
message: 'You need the Dungeon Ticket to access dungeons.\n<i>Check out the shop at Viridian City.</i>',
type: NotificationConstants.NotificationOption.danger,
});
return false;
if (!DungeonRunner.canStartDungeon(dungeon)) {
let message;
let notifType;
if (!dungeon.isUnlocked()) {
if (dungeon.name === 'Viridian Forest') {
message = 'You need the Dungeon Ticket to access dungeons.\n<i>Check out the shop at Viridian City.</i>';
notifType = NotificationConstants.NotificationOption.danger;
} else {
message = `You don't have access to this dungeon yet.\n<i>${dungeon.getRequirementHints()}</i>`;
notifType = NotificationConstants.NotificationOption.warning;
}
} else if (!dungeon.hasUnlockedBoss()) {
message = 'You can\'t access this dungeon right now because all of its bosses are locked.';
notifType = NotificationConstants.NotificationOption.warning;
} else if (!DungeonGuides.hired() && !DungeonRunner.hasEnoughTokens(dungeon)) {
message = 'You don\'t have enough Dungeon Tokens.';
notifType = NotificationConstants.NotificationOption.danger;
} else {
Notifier.notify({
message: `You don't have access to this dungeon yet.\n<i>${dungeon.getRequirementHints()}</i>`,
type: NotificationConstants.NotificationOption.warning,
});
return false;
message = 'You can\'t enter this dungeon right now.';
notifType = NotificationConstants.NotificationOption.danger;
}
Notifier.notify({
message: message,
type: notifType,
});
return false;
}
DungeonRunner.dungeon = dungeon;

// Only charge the player if they aren't using a dungeon guide as they are charged when they start the dungeon
if (!DungeonGuides.hired()) {
if (!DungeonRunner.hasEnoughTokens()) {
Notifier.notify({
message: 'You don\'t have enough Dungeon Tokens.',
type: NotificationConstants.NotificationOption.danger,
});
return false;
}
App.game.wallet.loseAmount(new Amount(DungeonRunner.dungeon.tokenCost, GameConstants.Currency.dungeonToken));
}
// Reset any trainers/pokemon if there was one previously
Expand Down Expand Up @@ -254,6 +259,12 @@ class DungeonRunner {
return;
}

if (!DungeonRunner.dungeon.hasUnlockedBoss()) {
// Prevent the player from being unable to finish the dungeon if somehow all the bosses became locked after entering
DungeonRunner.dungeonWon();
return;
}

DungeonRunner.fightingBoss(true);
DungeonBattle.generateNewBoss();
}
Expand Down Expand Up @@ -342,8 +353,12 @@ class DungeonRunner {
});
}

public static hasEnoughTokens() {
return App.game.wallet.hasAmount(new Amount(DungeonRunner.dungeon.tokenCost, GameConstants.Currency.dungeonToken));
public static canStartDungeon(dungeon: Dungeon = DungeonRunner.dungeon) {
return (DungeonGuides.hired() || DungeonRunner.hasEnoughTokens(dungeon)) && dungeon.isUnlocked() && dungeon.hasUnlockedBoss();
}

public static hasEnoughTokens(dungeon: Dungeon = DungeonRunner.dungeon) {
return App.game.wallet.hasAmount(new Amount(dungeon.tokenCost, GameConstants.Currency.dungeonToken));
}

public static dungeonLevel(): number {
Expand Down

0 comments on commit 2f07f9f

Please sign in to comment.