90 lines
2.3 KiB
TypeScript
90 lines
2.3 KiB
TypeScript
import type {
|
|
Iwt2ArenaEvent,
|
|
Iwt2PartyEntityState,
|
|
Iwt2RoguelikePressureContentType,
|
|
Iwt2RoguelikePressureState,
|
|
} from './types'
|
|
import { applyPartyDamageToMember, createArenaEvent } from './mechanics'
|
|
|
|
const ROGUELIKE_PRESSURE_INTERVAL_SECONDS = 5
|
|
const ROGUELIKE_PRESSURE_BASE_DAMAGE = 9
|
|
const ROGUELIKE_PRESSURE_INITIAL_STAGE_DAMAGE = 2
|
|
const ROGUELIKE_PRESSURE_SOURCE_ID = 'roguelike-pressure'
|
|
|
|
export function roguelikeIncomingDamageScale(
|
|
stage: number,
|
|
contentType: Iwt2RoguelikePressureContentType,
|
|
): number {
|
|
void stage
|
|
void contentType
|
|
return 1
|
|
}
|
|
|
|
export function createRoguelikePressureState(
|
|
stage: number,
|
|
contentType: Iwt2RoguelikePressureContentType,
|
|
): Iwt2RoguelikePressureState {
|
|
const safeStage = safeRoguelikeStage(stage)
|
|
return {
|
|
stage: safeStage,
|
|
contentType,
|
|
damage: Math.round(ROGUELIKE_PRESSURE_BASE_DAMAGE + ROGUELIKE_PRESSURE_INITIAL_STAGE_DAMAGE),
|
|
intervalSeconds: ROGUELIKE_PRESSURE_INTERVAL_SECONDS,
|
|
nextPulseAt: ROGUELIKE_PRESSURE_INTERVAL_SECONDS,
|
|
}
|
|
}
|
|
|
|
export function tickRoguelikePressure({
|
|
party,
|
|
pressure,
|
|
time,
|
|
}: {
|
|
party: Iwt2PartyEntityState[]
|
|
pressure?: Iwt2RoguelikePressureState
|
|
time: number
|
|
}): {
|
|
events: Iwt2ArenaEvent[]
|
|
party: Iwt2PartyEntityState[]
|
|
pressure?: Iwt2RoguelikePressureState
|
|
} {
|
|
if (!pressure || time < pressure.nextPulseAt) {
|
|
return { events: [], party, pressure }
|
|
}
|
|
|
|
const events: Iwt2ArenaEvent[] = []
|
|
const nextParty = party.map((member) => {
|
|
if (member.health <= 0) return member
|
|
|
|
const before = member.health
|
|
const result = applyPartyDamageToMember(member, pressure.damage)
|
|
events.push(createArenaEvent(
|
|
0,
|
|
time,
|
|
'partyDamaged',
|
|
ROGUELIKE_PRESSURE_SOURCE_ID,
|
|
member.id,
|
|
result.damage,
|
|
))
|
|
if (before > 0 && result.member.health <= 0) {
|
|
events.push(createArenaEvent(0, time, 'entityDefeated', ROGUELIKE_PRESSURE_SOURCE_ID, member.id))
|
|
}
|
|
return result.member
|
|
})
|
|
|
|
let nextPulseAt = pressure.nextPulseAt
|
|
while (nextPulseAt <= time) nextPulseAt += pressure.intervalSeconds
|
|
|
|
return {
|
|
events,
|
|
party: nextParty,
|
|
pressure: {
|
|
...pressure,
|
|
nextPulseAt,
|
|
},
|
|
}
|
|
}
|
|
|
|
function safeRoguelikeStage(stage: number): number {
|
|
return Number.isFinite(stage) ? Math.max(1, Math.floor(stage)) : 1
|
|
}
|