import { Conversation } from "../Conversation" ; import { DialoguePrompt } from "../DialoguePrompt" ; import { Face , FaceModes } from "../Face" ; import { Greeting } from "../Greeting" ; import { PhysicsEntity } from "./PhysicsEntity" ; import { sleep } from "../util" ; import { SpeechBubble } from "../SpeechBubble" ; const PAUSE_AFTER_CONVERSATION = 1.5 ; export abstract class NPC extends PhysicsEntity { public direction = 1 ; public face : Face | null = null ; public defaultFaceMode = FaceModes . NEUTRAL ; public greeting : Greeting | null = null ; public conversation : Conversation | null = null ; public thinkBubble : SpeechBubble | null = null ; public speechBubble = new SpeechBubble ( this . scene , this . x , this . y ) ; public lookAtPlayer = true ; public dialoguePrompt = new DialoguePrompt ( this . scene , this . x , this . y ) ; private lastEndedConversation = - Infinity ; protected met = false ; protected drawFace ( ctx , lookAtPlayer = true ) { if ( this . face ) { if ( lookAtPlayer ) { const dx = this . scene . player . x - this . x ; this . face . toggleDirection ( ( dx > 0 ) ? 1 : - 1 ) ; this . face . draw ( ctx ) ; } else { this . face . setDirection ( this . direction ) ; this . face . draw ( ctx ) ; } } } public async think ( message , time ) { if ( this . thinkBubble ) { this . thinkBubble . hide ( ) ; this . thinkBubble = null ; } const thinkBubble = this . thinkBubble = new SpeechBubble ( this . scene , this . x , this . y ) ; thinkBubble . setMessage ( message ) ; thinkBubble . show ( ) ; await sleep ( time ) ; if ( this . thinkBubble === thinkBubble ) { thinkBubble . hide ( ) ; this . thinkBubble = null ; } } public hasMet ( ) { return false ; } public meet ( ) { this . met = true ; } public getInteractionText ( ) { return "Talk" ; } protected showDialoguePrompt ( ) { if ( this . hasActiveConversation ( ) || ! this . scene . player . isControllable ) { return false ; } return true ; } protected drawDialoguePrompt ( ) { this . dialoguePrompt . draw ( ) ; } protected drawGreeting ( ctx ) { this . greeting ?. draw ( ctx ) ; } protected updateGreeting ( ) { this . greeting ?. update ( ) ; } public registerEndedConversation ( ) { this . lastEndedConversation = this . scene . gameTime ; } public isReadyForConversation ( ) { return ( this . conversation && ! this . scene . player . isCarrying ( this ) && this . scene . gameTime - this . lastEndedConversation > PAUSE_AFTER_CONVERSATION ) ; } public hasActiveConversation ( ) { return ( this . scene . player . playerConversation !== null && this . scene . player . playerConversation . npc === this ) ; } public toggleDirection ( direction = this . direction > 0 ? - 1 : 1 ) { if ( direction !== this . direction ) { this . direction = direction ; } } public update ( dt ) { if ( this . lookAtPlayer ) { const dx = this . scene . player . x - this . x ; this . toggleDirection ( ( dx > 0 ) ? 1 : - 1 ) ; } super . update ( dt ) ; } }