Return defeated parties to dormant state
This commit is contained in:
@@ -61,7 +61,7 @@ export class Game {
|
||||
return true
|
||||
}
|
||||
forceEndPlayerPhase():boolean {if(this.state.phase.kind!=='player')return false;this.endPlayerPhase();return true}
|
||||
resetRunByAdmin():void {this.resetRun('admin-reset','An administrator reset the run.')}
|
||||
resetRunByAdmin():void {this.resetRun()}
|
||||
|
||||
spawn(message: SpawnMessage): SpawnResult {
|
||||
if(this.externalEvents.has(message.externalEventId)) return {accepted:false,reason:'DUPLICATE',message:'That spawn request was already handled.'}
|
||||
@@ -85,6 +85,7 @@ export class Game {
|
||||
if(p.lifeState!=='dead') return {accepted:false,reason:'PLAYER_ALIVE',message:'That character is already alive.'}
|
||||
p.lifeState='alive'; p.hp=3; p.ap=0; p.guard=0; p.eligibleThisPhase=false; p.diedOnFloor=null; p.position=copy(this.state.floor.spawnTiles[0]!)
|
||||
this.log('player-resurrected',p.twitchUserId,null,`${p.displayName} rose again at the spawn!`)
|
||||
if(this.state.phase.kind==='dormant')this.startPlayerPhase()
|
||||
return {accepted:true,reason:null,message:`${p.displayName} resurrected.`}
|
||||
}
|
||||
|
||||
@@ -180,7 +181,7 @@ export class Game {
|
||||
if(adjacent(g.position,target.position)){
|
||||
const hit=this.deps.random.next()<0.5
|
||||
if(hit && target.guard>0){target.guard--;this.log('guard-blocked','goblin',target.twitchUserId,`${target.displayName}'s Guard blocks the hit.`)}
|
||||
else if(hit){target.hp--;this.log('goblin-hit','goblin',target.twitchUserId,`The Goblin hits ${target.displayName} for 1 damage.`);if(target.hp<=0)this.killPlayer(target)}
|
||||
else if(hit){target.hp--;this.log('goblin-hit','goblin',target.twitchUserId,`The Goblin hits ${target.displayName} for 1 damage.`);if(target.hp<=0){this.killPlayer(target);if(this.state.phase.kind==='dormant')return}}
|
||||
else this.log('goblin-missed','goblin',target.twitchUserId,`The Goblin misses ${target.displayName}.`)
|
||||
} else { const step=this.nextPathStep(g.position,target.position);if(!step)break;g.position=step;this.log('goblin-moved','goblin',target.twitchUserId,'The Goblin closes in.') }
|
||||
} else if(g.mode==='returning'){
|
||||
@@ -195,17 +196,17 @@ export class Game {
|
||||
player.hp=0;player.lifeState='dead';player.ap=0;player.guard=0;player.eligibleThisPhase=false;player.diedOnFloor=this.state.floorNumber
|
||||
this.log('player-died','goblin',player.twitchUserId,`${player.displayName} has fallen.`)
|
||||
if(this.state.goblin.targetPlayerId===player.twitchUserId){this.state.goblin.mode='returning';this.state.goblin.targetPlayerId=null}
|
||||
const all=Object.values(this.state.players);if(all.length>0 && all.every(p=>p.lifeState==='dead'))this.resetRun()
|
||||
const all=Object.values(this.state.players);if(all.length>0 && all.every(p=>p.lifeState==='dead')){this.state.phase={kind:'dormant'};this.log('party-defeated',null,null,'The party has fallen. The dungeon is dormant until an adventurer returns.')}
|
||||
}
|
||||
private advanceFloor(): void {
|
||||
this.state.phase={kind:'transition',reason:'floor-advance'};this.state.floorNumber++
|
||||
const floor=this.deps.generateFloor(`${this.state.runId}-floor-${this.state.floorNumber}`);this.state.floor=floor;this.state.goblin=this.newGoblin(floor)
|
||||
this.restorePlayers();this.log('floor-advanced',null,null,`The party reaches Floor ${this.state.floorNumber}!`);this.startPlayerPhase()
|
||||
}
|
||||
private resetRun(logType='party-wipe',message='The party has fallen. A new run begins on Floor 1.'): void {
|
||||
this.state.phase={kind:'transition',reason:'party-wipe'};this.state.runId=this.deps.ids.next('run');this.state.floorNumber=1
|
||||
private resetRun(): void {
|
||||
this.state.phase={kind:'transition',reason:'admin-reset'};this.state.runId=this.deps.ids.next('run');this.state.floorNumber=1
|
||||
const floor=this.deps.generateFloor(`${this.state.runId}-floor-1`);this.state.floor=floor;this.state.goblin=this.newGoblin(floor)
|
||||
this.restorePlayers();this.log(logType,null,null,message);this.startPlayerPhase()
|
||||
this.restorePlayers();this.log('admin-reset',null,null,'An administrator reset the run.');this.startPlayerPhase()
|
||||
}
|
||||
private restorePlayers(): void { for(const p of Object.values(this.state.players)){p.hp=3;p.lifeState='alive';p.ap=0;p.guard=0;p.healAvailable=true;p.diedOnFloor=null;p.eligibleThisPhase=false;p.participatingFloor=this.state.floorNumber;p.position=copy(this.state.floor.spawnTiles[0]!)} }
|
||||
private nextPathStep(start:TilePosition,goal:TilePosition):TilePosition|null {
|
||||
|
||||
@@ -21,7 +21,7 @@ export type PhaseState = { kind: 'dormant' } | {
|
||||
kind: 'player'; phaseId: string; startedAt: number; deadlineAt: number
|
||||
initialEligiblePlayerIds: string[]
|
||||
} | { kind: 'enemy'; phaseId: string } | {
|
||||
kind: 'transition'; reason: 'floor-advance' | 'party-wipe'
|
||||
kind: 'transition'; reason: 'floor-advance' | 'admin-reset'
|
||||
}
|
||||
export interface ActionLogEntry {
|
||||
sequence: number; runId: string; floorNumber: number; phaseId: string | null
|
||||
|
||||
Reference in New Issue
Block a user