open-toontown/toontown/toon/NPCDialogue.py

177 lines
6.0 KiB
Python

from toontown.toonbase import TTLocalizer
from direct.distributed.ClockDelta import *
from direct.directnotify import DirectNotifyGlobal
from . import DistributedNPCToonBaseAI
from direct.task import Task
import random
class NPCDialogue:
"""
The NPC dialogue for a given topic and set of participants
"""
notify = DirectNotifyGlobal.directNotify.newCategory("NPCDialogue")
def __init__(self, participant, dialogueTopic):
self.participants = {}
if dialogueTopic in TTLocalizer.toontownDialogues:
self.topic = dialogueTopic
else:
self.notify.warning("Dialogue does not exist: %s" %dialogueTopic)
self.topic = TTLocalizer.BoringTopic
self.conversation = TTLocalizer.toontownDialogues[self.topic]
if participant and isinstance(participant, DistributedNPCToonBaseAI.DistributedNPCToonBaseAI):
self.addParticipant(participant)
self.participantProgress = 0
self.currentParticipant = participant.npcId
else:
self.notify.warning("Participant does not exist: %s" %participant)
self.participantProgress = 0
self.currrentParticipant = None
def calcMaxNumMsgs(self):
"""
Find the participant that has the most number of things to say
"""
self.maxNumMsgs = 0
for participant, spiel in self.conversation.items():
if len(spiel)>self.maxNumMsgs and participant[1] in self.participants:
self.maxNumMsgs = len(spiel)
def getTopic(self):
"""
Accessor function for topic
"""
return self.topic
def addParticipant(self, participant):
"""
Add a new participant
"""
if self.getNumParticipants() > self.getMaxParticipants():
return False
if participant:
for partPos in self.conversation.keys():
if partPos[1] == participant.npcId:
if not (participant.npcId in self.participants):
self.participants[participant.npcId] = [participant]
else:
if participant not in self.participants[participant.npcId]:
self.participants[participant.npcId].append(participant)
else:
self.notify.warning("Participant: %s already in the conversation" %participant)
self.calcMaxNumMsgs()
return True
self.notify.warning("Participant: %s should not be in conversation" %participant)
return False
def removeParticipant(self, participant):
"""
Remove a participant
"""
if participant.npcId in self.participants:
if participant.npcId == self.currentParticipant:
self.getNextParticipant()
self.participants[participant.npcId].remove(participant)
if self.participants[participant.npcId] == []:
del self.participants[participant.npcId]
self.calcMaxNumMsgs()
return True
return False
def getNextParticipant(self):
while 1:
self.currentParticipant = self.calcNextParticipant()
if self.currentParticipant in self.participants:
break
def calcNextParticipant(self):
"""
Returns the next in line to talk
"""
nextParticipant = None
for partPos in self.conversation.keys():
if partPos[1] == self.currentParticipant:
nextPos = partPos[0]+1
break
if nextPos>len(self.conversation):
nextPos = 1
self.participantProgress = (self.participantProgress+1)%self.maxNumMsgs
for partPos in self.conversation.keys():
if partPos[0] == nextPos:
nextParticipant = partPos[1]
return nextParticipant
return self.currentParticipant
def getMaxParticipants(self):
"""
Number of conversation pieces provided in TTLocalizer
"""
return len(self.conversation)
def getNumParticipants(self):
"""
Returns the number of NPC's currently participating
"""
return len(self.participants)
def isRunning(self):
if taskMgr.hasTaskNamed("Dialogue"+self.topic):
return True
def start(self):
"""
Start up a dialogue amongst the participants
"""
self.nextChatTime = 0
taskMgr.add(self.__blather, "Dialogue"+self.topic)
return True
def stop(self):
"""
This conversation is over!
"""
taskMgr.remove("Dialogue"+self.topic)
def __blather(self, task):
"""
Speak in turn
"""
now = globalClock.getFrameTime()
if now < self.nextChatTime:
return Task.cont
if not self.currentParticipant:
return Task.done
# Increment the participantProgress
for partPos in self.conversation.keys():
if partPos[1] == self.currentParticipant:
convKey = partPos
break
if self.participantProgress >= len(self.conversation[convKey]):
self.getNextParticipant()
return Task.cont
# Select the current spiel
#msg = self.conversation[self.participants[self.currentParticipant]][self.participantProgress]
for participant in self.participants[self.currentParticipant]:
chatFlags = CFSpeech | CFTimeout
participant.sendUpdate("setChat", [self.topic, convKey[0], convKey[1], self.participantProgress, chatFlags])
self.getNextParticipant()
# Delay before next message
self.nextChatTime = now + 5.0
return Task.cont