Skip to content

Commit

Permalink
Merge pull request #576 from m-h-c-t/draconic-depths
Browse files Browse the repository at this point in the history
Add support for Draconic Depths
  • Loading branch information
AardWolf authored Aug 16, 2024
2 parents 6d26342 + 090f2ab commit 3803985
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 0 deletions.
31 changes: 31 additions & 0 deletions src/scripts/hunt-filter/exemptions/environments/draconicDepth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type {IMessageExemption} from '@scripts/hunt-filter/interfaces';
import type {IntakeMessage} from '@scripts/types/mhct';

class DraconicDepthsCavernExemptions implements IMessageExemption {
readonly description = 'Allow transitions between cavern stages';
readonly property = 'stage';

getExemptions(pre: IntakeMessage, post: IntakeMessage): (keyof IntakeMessage)[] | null {
if (pre.location?.name !== 'Draconic Depths' || post.location?.name !== 'Draconic Depths') {
return null;
}

if (typeof pre.stage !== 'string' || typeof post.stage !== 'string') {
return null;
}

if (pre.stage.startsWith('Cavern') && post.stage === 'Crucible Forge') {
return ['stage', 'cheese'];
}

if (pre.stage.startsWith('Cavern') && post.stage.startsWith('Cavern')) {
return ['stage'];
}

return null;
}
}

export const draconicDepthsExemptions = [
new DraconicDepthsCavernExemptions(),
];
2 changes: 2 additions & 0 deletions src/scripts/hunt-filter/exemptions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {globalExemptions} from './global';
import {acolyteRealmExemptions} from './environments/acolyteRealm';
import {bountifulBeanstalkExemptions} from './environments/bountifulBeanstalk';
import {clawShotCityExemptions} from './environments/clawShotCity';
import {draconicDepthsExemptions} from './environments/draconicDepth';
import {floatingIslandsExemptions} from './environments/floatingIslands';
import {icebergExemptions} from './environments/iceberg';
import {iceFortressExemptions} from './environments/iceFortress';
Expand All @@ -17,6 +18,7 @@ export const MessageExemptions: IMessageExemption[] = [
...acolyteRealmExemptions,
...bountifulBeanstalkExemptions,
...clawShotCityExemptions,
...draconicDepthsExemptions,
...icebergExemptions,
...iceFortressExemptions,
...floatingIslandsExemptions,
Expand Down
57 changes: 57 additions & 0 deletions src/scripts/modules/stages/environments/draconicDepths.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import type {User} from '@scripts/types/hg';
import type {IStager} from '../stages.types';
import type {IntakeMessage} from '@scripts/types/mhct';
import {CavernTypes} from '@scripts/types/quests/draconicDepths';


export class DraconicDepthsStager implements IStager {
readonly environment: string = 'Draconic Depths';

addStage(message: IntakeMessage, userPre: User, userPost: User, journal: unknown): void {
const quest = userPre.quests.QuestDraconicDepths;

if (!quest) {
throw new Error('QuestDraconicDepths is undefined');
}

if (quest.in_cavern) {
// Make a stage names similar to this format:
// Cavern - 2x Fire 0-99
// Cavern - 1x Poison 100-249
// Cavern - 3x Ice 750+
let multiplier: 1 | 2 | 3 | '?' = 1;
if (quest.cavern.type.startsWith('double')) {
multiplier = 2;
} else if (quest.cavern.type.startsWith('triple')) {
multiplier = 3;
} else if (!CavernTypes.includes(quest.cavern.type)) {
multiplier = '?';
}

// capitalize first letter of category: poison -> Poison
const category = quest.cavern.category.charAt(0).toUpperCase() + quest.cavern.category.slice(1);

const currentTier = quest.cavern.loot_tier.current_tier;
const lootTiers = quest.cavern.loot_tier.tier_data;

// if we're not at the last tier (currentTier is one indexed), then we need a range '0-99'
// which consists of the current tier threshold and the next tier threshold - 1
// otherwise, we just need the a number '750+'
let range: string;
if (currentTier < lootTiers.length) {
range = `${lootTiers[currentTier - 1].threshold}-${lootTiers[currentTier].threshold - 1}`;
} else {
range = `${lootTiers[currentTier - 1].threshold}+`;
}

if (quest.cavern.type === 'elemental_dragon_den') {
message.stage = `Cavern - Elemental ${range}`;
} else {
message.stage = `Cavern - ${multiplier}x ${category} ${range}`;
}

} else {
message.stage = 'Crucible Forge';
}
}
}
2 changes: 2 additions & 0 deletions src/scripts/modules/stages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {BristleWoodsRiftStager} from './environments/bristleWoodsRift';
import {BurroughsRiftStager} from './environments/burroughsRift';
import {ClawShotCityStager} from './environments/clawShotCity';
import {CursedCityStager} from './environments/cursedCity';
import {DraconicDepthsStager} from './environments/draconicDepths';
import {FieryWarpathStager} from './environments/fieryWarpath';
import {FloatingIslandsStager} from './environments/floatingIslands';
import {ForbiddenGroveStager} from './environments/forbiddenGrove';
Expand Down Expand Up @@ -43,6 +44,7 @@ const stageModules: IStager[] = [
new BurroughsRiftStager(),
new ClawShotCityStager(),
new CursedCityStager(),
new DraconicDepthsStager(),
new FieryWarpathStager(),
new FloatingIslandsStager(),
new ForbiddenGroveStager(),
Expand Down
1 change: 1 addition & 0 deletions src/scripts/types/hg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export interface Quests {
QuestBalacksCove?: quests.QuestBalacksCove
QuestBountifulBeanstalk?: quests.QuestBountifulBeanstalk
QuestClawShotCity?: quests.QuestClawShotCity
QuestDraconicDepths?: quests.QuestDraconicDepths
QuestFloatingIslands?: quests.QuestFloatingIslands
QuestForbiddenGrove?: quests.QuestForbiddenGrove
QuestForewordFarm?: quests.QuestForewordFarm
Expand Down
33 changes: 33 additions & 0 deletions src/scripts/types/quests/draconicDepths.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
export type QuestDraconicDepths = CrucibleEnvironment | CavernEnvironment;

export const CavernTypes = [
"flame_cavern",
"double_flame_cavern",
"triple_flame_cavern",
"ice_lair",
"double_ice_lair",
"triple_ice_lair",
"toxic_tunnels",
"double_toxic_tunnels",
"triple_toxic_tunnels",
"elemental_dragon_den",
] as const;
export type CavernType = (typeof CavernTypes)[number];

interface CrucibleEnvironment {
in_cavern: false;
}

interface CavernEnvironment {
in_cavern: true;
cavern: {
type: CavernType;
category: "fire" | "ice" | "poison" | "elemental";
loot_tier: {
current_tier: number;
tier_data: {
threshold: number;
}[]
};
};
}
1 change: 1 addition & 0 deletions src/scripts/types/quests/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from '@scripts/types/quests/bountifulBeanstalk';
export * from '@scripts/types/quests/bristleWoodsRift';
export * from '@scripts/types/quests/burroughsRift';
export * from '@scripts/types/quests/clawShotCity';
export * from '@scripts/types/quests/draconicDepths';
export * from '@scripts/types/quests/floatingIslands';
export * from '@scripts/types/quests/forbiddenGrove';
export * from '@scripts/types/quests/forewordFarm';
Expand Down
93 changes: 93 additions & 0 deletions tests/scripts/modules/stages/environments/draconicDepths.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import {DraconicDepthsStager} from "@scripts/modules/stages/environments/draconicDepths";
import {IStager} from "@scripts/modules/stages/stages.types";
import {User} from "@scripts/types/hg";
import {IntakeMessage} from "@scripts/types/mhct";
import type {CavernType, QuestDraconicDepths} from "@scripts/types/quests/draconicDepths";

describe('Draconic Depths stages', () => {
let stager: IStager;
let message: IntakeMessage;
let preUser: User;
let postUser: User;
const journal = {};

beforeEach(() => {
stager = new DraconicDepthsStager();
message = {} as IntakeMessage;
preUser = {quests: {
QuestDraconicDepths: getDefaultQuest(),
}} as User;
postUser = {} as User;
});

it('should be for the Draconic Depths environment', () => {
expect(stager.environment).toBe('Draconic Depths');
});

it('it should throw when quest is undefined', () => {
preUser.quests.QuestDraconicDepths = undefined;

expect(() => stager.addStage(message, preUser, postUser, journal))
.toThrow('QuestDraconicDepths is undefined');
});

it('should set stage to Crucible Forge when not in cavern', () => {
preUser.quests.QuestDraconicDepths!.in_cavern = false;

stager.addStage(message, preUser, postUser, journal);

expect(message.stage).toBe('Crucible Forge');
});

it.each<{type: CavernType | 'invalid_cavern', category: 'fire' | 'ice' | 'poison' | 'elemental', currentTier: number, expected: string}>([
{type: 'flame_cavern', category: 'fire', currentTier: 1, expected: 'Cavern - 1x Fire 0-99'},
{type: 'ice_lair', category: 'ice', currentTier: 2, expected: 'Cavern - 1x Ice 100-249'},
{type: 'toxic_tunnels', category: 'poison', currentTier: 3, expected: 'Cavern - 1x Poison 250-749'},
{type: 'double_ice_lair', category: 'ice', currentTier: 4, expected: 'Cavern - 2x Ice 750+'},
{type: 'triple_flame_cavern', category: 'fire', currentTier: 1, expected: 'Cavern - 3x Fire 0-99'},
{type: 'elemental_dragon_den', category: 'elemental', currentTier: 1, expected: 'Cavern - Elemental 0-99'},
{type: 'elemental_dragon_den', category: 'elemental', currentTier: 4, expected: 'Cavern - Elemental 750+'},
{type: 'invalid_cavern', category: 'poison', currentTier: 4, expected: 'Cavern - ?x Poison 750+'},
])('should set stage to "$expected" when in looting a tier $currentTier $type', ({type, category, currentTier, expected}) => {
preUser.quests.QuestDraconicDepths = {
in_cavern: true,
cavern: {
// @ts-expect-error - testing invalid cavern type
type,
category,
loot_tier: {
current_tier: currentTier,
tier_data: [
{threshold: 0},
{threshold: 100},
{threshold: 250},
{threshold: 750},
],
},
},
};

stager.addStage(message, preUser, postUser, journal);

expect(message.stage).toBe(expected);
});
});

export function getDefaultQuest(): QuestDraconicDepths {
return {
in_cavern: true,
cavern: {
type: 'flame_cavern',
category: 'fire',
loot_tier: {
current_tier: 1,
tier_data: [
{threshold: 0},
{threshold: 100},
{threshold: 250},
{threshold: 750},
],
},
},
};
}

0 comments on commit 3803985

Please sign in to comment.