-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #576 from m-h-c-t/draconic-depths
Add support for Draconic Depths
- Loading branch information
Showing
8 changed files
with
220 additions
and
0 deletions.
There are no files selected for viewing
31 changes: 31 additions & 0 deletions
31
src/scripts/hunt-filter/exemptions/environments/draconicDepth.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(), | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
}[] | ||
}; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
93 changes: 93 additions & 0 deletions
93
tests/scripts/modules/stages/environments/draconicDepths.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}, | ||
], | ||
}, | ||
}, | ||
}; | ||
} |