import { Actor } from "./Actors" ; import { BattleOutcome , Animations } from "./Animations" ; import { Main as MainAnimator } from "./animators/Main" ; import { BattleInfo , BattleOptions , BattleTeam } from "./Battles" ; import { BattleMovrSettings } from "./types" ; import { SelectorFactories } from "./Selectors" ; import { ActionsOrderer , TeamBase , TeamDescriptor , TeamId } from "./Teams" ; param actors returns const findFirstAliveIndex = ( actors ) : number => { for ( let i = 0 ; i < actors . length ; i += 1 ) { if ( actors [ i ] . statistics . health . current !== 0 ) { return i ; } } throw new Error ( "Cannot create team since no actors exist." ) ; } ; /**
 * Drives RPG-like battles between two teams of actors.
 */ export class BattleMovr { /**
     * Selector factories keyed by type name.
     */ private readonly actionsOrderer : ActionsOrderer ; /**
     * Animations for various battle activities.
     */ private readonly animations : Animations ; /**
     * Selector factories keyed by type name.
     */ private readonly selectorFactories : SelectorFactories ; /**
     * Animator for the current battle, if one is happening.
     */ private animator ? : MainAnimator ; /**
     * Battle info for the current battle, if one is happening.
     */ private battleInfo ? : BattleInfo ; param settings public constructor ( settings ) { this . actionsOrderer = settings . actionsOrderer ; this . animations = settings . animations ; this . selectorFactories = settings . selectorFactories ; } returns public inBattle ( ) { return this . battleInfo !== undefined ; } returns public getBattleInfo ( ) { if ( this . battleInfo === undefined ) { throw new Error ( "There is no current battle." ) ; } return this . battleInfo ; } param options returns public startBattle ( options ) { if ( this . battleInfo !== undefined ) { throw new Error ( "A battle is already happening." ) ; } this . battleInfo = { ... options , choices : { } , teams : { opponent : this . createTeamFromInfo ( options . teams . opponent ) , player : this . createTeamFromInfo ( options . teams . player ) , } , } ; this . animator = new MainAnimator ( { animations : this . animations , battleInfo : this . battleInfo , } , this . actionsOrderer ) ; this . animator . run ( ) ; return this . battleInfo ; } param team param newActor public switchSelectedActor ( team , newActor ) { if ( this . battleInfo === undefined ) { throw new Error ( "No battle is happening." ) ; } const battleTeam = this . battleInfo . teams [ TeamId [ team ] ] ; const oldActor = battleTeam . selectedActor ; if ( oldActor === newActor ) { throw new Error ( "Cannot switch to the currently selected actor." ) ; } battleTeam . actors [ battleTeam . actors . indexOf ( newActor ) ] = oldActor ; battleTeam . actors [ battleTeam . selectedIndex ] = newActor ; battleTeam . selectedActor = newActor ; } param outcome param onComplete public stopBattle ( outcome , onComplete ? ) { if ( this . battleInfo === undefined ) { throw new Error ( "No battle is happening." ) ; } this . animations . complete ( outcome , ( ) : void => { this . animator = undefined ; this . battleInfo = undefined ; if ( onComplete !== undefined ) { onComplete ( ) ; } } ) ; } param team returns private createTeamFromInfo ( team ) { const selectorFactory = this . selectorFactories [ team . selector ] ; if ( selectorFactory === undefined ) { throw new Error ( `Unknown selector type: '${ team . selector }.` ) ; } const firstAliveIndex = findFirstAliveIndex ( team . actors ) ; return { ... team , orderedActors : team . actors . slice ( ) , selectedActor : team . actors [ firstAliveIndex ] , selectedIndex : firstAliveIndex , selector : selectorFactory ( ) , } ; } }