78 lines
1.9 KiB
TypeScript
78 lines
1.9 KiB
TypeScript
import type { PartyMember } from '../game'
|
|
|
|
export type PvpRoguelikeUpgradeSide<TBuff extends string, TDebuff extends string> = {
|
|
party: PartyMember[]
|
|
resource: number
|
|
cooldowns: Record<string, number>
|
|
enemyHealth: number
|
|
buffs: TBuff[]
|
|
debuffs: TDebuff[]
|
|
}
|
|
|
|
function removeRandomItem<T>(items: readonly T[], random = Math.random) {
|
|
if (items.length === 0) return [...items]
|
|
const removedIndex = Math.floor(random() * items.length)
|
|
return items.filter((_, index) => index !== removedIndex)
|
|
}
|
|
|
|
export function recoverPartyForNextPvpRoguelikeEncounter(party: readonly PartyMember[]) {
|
|
return party.map((member) => ({
|
|
...member,
|
|
health: member.maxHealth,
|
|
debuff: undefined,
|
|
debuffTicks: undefined,
|
|
poisonStacks: undefined,
|
|
maxHealthPenaltyTicks: undefined,
|
|
healingReductionTicks: undefined,
|
|
}))
|
|
}
|
|
|
|
export function applyPvpRoguelikeUpgradeChoice<
|
|
TBuff extends string,
|
|
TDebuff extends string,
|
|
TSide extends PvpRoguelikeUpgradeSide<TBuff, TDebuff>,
|
|
>({
|
|
side,
|
|
buffId,
|
|
incomingDebuffId,
|
|
reviveBuffId,
|
|
random,
|
|
}: {
|
|
side: TSide
|
|
buffId: TBuff
|
|
incomingDebuffId?: TDebuff
|
|
reviveBuffId: TBuff
|
|
random?: () => number
|
|
}) {
|
|
const reviveSelected = buffId === reviveBuffId
|
|
const nextBuffs = reviveSelected ? side.buffs : [...side.buffs, buffId]
|
|
const nextDebuffs = incomingDebuffId ? [...side.debuffs, incomingDebuffId] : side.debuffs
|
|
return {
|
|
...side,
|
|
buffs: nextBuffs,
|
|
debuffs: reviveSelected ? removeRandomItem(nextDebuffs, random) : nextDebuffs,
|
|
}
|
|
}
|
|
|
|
export function preparePvpRoguelikeNextEncounter<
|
|
TBuff extends string,
|
|
TDebuff extends string,
|
|
TSide extends PvpRoguelikeUpgradeSide<TBuff, TDebuff>,
|
|
>({
|
|
side,
|
|
maxResource,
|
|
enemyMaxHealth,
|
|
}: {
|
|
side: TSide
|
|
maxResource: number
|
|
enemyMaxHealth: number
|
|
}) {
|
|
return {
|
|
...side,
|
|
party: recoverPartyForNextPvpRoguelikeEncounter(side.party),
|
|
resource: maxResource,
|
|
cooldowns: {},
|
|
enemyHealth: enemyMaxHealth,
|
|
}
|
|
}
|