141 lines
3.8 KiB
TypeScript
141 lines
3.8 KiB
TypeScript
import type { PartyMember } from '../game'
|
|
import type { PvpMatchSnapshot, PvpMatchSide } from '../pvpRoguelike'
|
|
|
|
export type PvpRoguelikeSetupSide<TBuff extends string, TDebuff extends string> = {
|
|
party: PartyMember[]
|
|
resource: number
|
|
cooldowns: Record<string, number>
|
|
enemyHealth: number
|
|
buffs: TBuff[]
|
|
debuffs: TDebuff[]
|
|
castsTowardFree: number
|
|
freeCastReady: boolean
|
|
}
|
|
|
|
export type PvpRoguelikeLiveMatchSetup = {
|
|
id: string
|
|
side: PvpMatchSide
|
|
opponentSide: PvpMatchSide
|
|
opponentName: string
|
|
opponentClassName: string
|
|
}
|
|
|
|
export function createPvpRoguelikeStarterSide<TBuff extends string, TDebuff extends string>(
|
|
partyTemplate: readonly PartyMember[],
|
|
maxResource: number,
|
|
): PvpRoguelikeSetupSide<TBuff, TDebuff> {
|
|
return {
|
|
party: partyTemplate.map((member) => ({ ...member })),
|
|
resource: maxResource,
|
|
cooldowns: {},
|
|
enemyHealth: 0,
|
|
buffs: [],
|
|
debuffs: [],
|
|
castsTowardFree: 0,
|
|
freeCastReady: false,
|
|
}
|
|
}
|
|
|
|
export function createPvpRoguelikeMatchStart<
|
|
TBuff extends string,
|
|
TDebuff extends string,
|
|
TEncounter extends { maxHealth: number },
|
|
>({
|
|
startStage,
|
|
encounterPool,
|
|
buildSegment,
|
|
partyTemplate,
|
|
opponentPartyTemplate,
|
|
maxResource,
|
|
upgradeChoiceSeconds,
|
|
}: {
|
|
startStage: number
|
|
encounterPool: readonly TEncounter[]
|
|
buildSegment: (pool: readonly TEncounter[], stage: number) => TEncounter[]
|
|
partyTemplate: readonly PartyMember[]
|
|
opponentPartyTemplate: readonly PartyMember[]
|
|
maxResource: number
|
|
upgradeChoiceSeconds: number
|
|
}) {
|
|
const firstSegment = buildSegment(encounterPool, startStage)
|
|
const firstEncounter = firstSegment[0]
|
|
const playerSide = createPvpRoguelikeStarterSide<TBuff, TDebuff>(partyTemplate, maxResource)
|
|
const opponentSide = createPvpRoguelikeStarterSide<TBuff, TDebuff>(opponentPartyTemplate, maxResource)
|
|
playerSide.enemyHealth = firstEncounter.maxHealth
|
|
opponentSide.enemyHealth = firstEncounter.maxHealth
|
|
|
|
return {
|
|
startStage,
|
|
firstSegment,
|
|
firstEncounter,
|
|
playerSide,
|
|
opponentSide,
|
|
defaults: {
|
|
encounterIndex: 0,
|
|
elapsedTicks: 0,
|
|
encountersCleared: 0,
|
|
paused: false,
|
|
targetGroup: 0 as const,
|
|
upgradeTimeLeft: upgradeChoiceSeconds,
|
|
liveUpgradePending: false,
|
|
rewardError: '',
|
|
showEndLog: false,
|
|
},
|
|
}
|
|
}
|
|
|
|
export function createPvpRoguelikeLiveMatchStart<
|
|
TBuff extends string,
|
|
TDebuff extends string,
|
|
TEncounter extends { maxHealth: number },
|
|
>({
|
|
match,
|
|
side,
|
|
encounterPool,
|
|
buildSegment,
|
|
partyTemplate,
|
|
opponentPartyTemplate,
|
|
maxResource,
|
|
upgradeChoiceSeconds,
|
|
message,
|
|
}: {
|
|
match: PvpMatchSnapshot<PvpRoguelikeSetupSide<TBuff, TDebuff>>
|
|
side: PvpMatchSide
|
|
encounterPool: readonly TEncounter[]
|
|
buildSegment: (pool: readonly TEncounter[], stage: number) => TEncounter[]
|
|
partyTemplate: readonly PartyMember[]
|
|
opponentPartyTemplate: readonly PartyMember[]
|
|
maxResource: number
|
|
upgradeChoiceSeconds: number
|
|
message?: string
|
|
}) {
|
|
const opponentSideId: PvpMatchSide = side === 'a' ? 'b' : 'a'
|
|
const opponent = match.players[opponentSideId]
|
|
const opponentTemplate = opponentPartyTemplate.map((member) => ({
|
|
...member,
|
|
name: member.id === 'mira' ? opponent.characterName : member.name,
|
|
}))
|
|
const setup = createPvpRoguelikeMatchStart<TBuff, TDebuff, TEncounter>({
|
|
startStage: match.startStage,
|
|
encounterPool,
|
|
buildSegment,
|
|
partyTemplate,
|
|
opponentPartyTemplate: opponentTemplate,
|
|
maxResource,
|
|
upgradeChoiceSeconds,
|
|
})
|
|
const liveMatch: PvpRoguelikeLiveMatchSetup = {
|
|
id: match.id,
|
|
side,
|
|
opponentSide: opponentSideId,
|
|
opponentName: opponent.characterName,
|
|
opponentClassName: opponent.className,
|
|
}
|
|
|
|
return {
|
|
...setup,
|
|
liveMatch,
|
|
logText: message ?? `${opponent.characterName} found. Stage ${match.startStage} begins.`,
|
|
}
|
|
}
|