oldschool-toontown/toontown/classicchars/CharStateDatasAI.py

327 lines
13 KiB
Python

from otp.ai.AIBaseGlobal import *
from direct.distributed.ClockDelta import *
from direct.fsm import StateData
from direct.directnotify import DirectNotifyGlobal
import random
from direct.task import Task
from toontown.toonbase import ToontownGlobals
from . import CCharChatter, CCharPaths
CHATTY_DURATION = 120.0
class CharLonelyStateAI(StateData.StateData):
notify = DirectNotifyGlobal.directNotify.newCategory('CharLonelyStateAI')
def __init__(self, doneEvent, character):
StateData.StateData.__init__(self, doneEvent)
self.__doneEvent = doneEvent
self.character = character
StateData.StateData.load(self)
def enter(self):
if hasattr(self.character, 'name'):
name = self.character.getName()
else:
name = 'character'
self.notify.debug('Lonely ' + self.character.getName() + '...')
StateData.StateData.enter(self)
duration = random.randint(3, 15)
taskMgr.doMethodLater(duration, self.__doneHandler, self.character.taskName('startWalking'))
def exit(self):
StateData.StateData.exit(self)
taskMgr.remove(self.character.taskName('startWalking'))
def __doneHandler(self, task):
doneStatus = {}
doneStatus['state'] = 'lonely'
doneStatus['status'] = 'done'
messenger.send(self.__doneEvent, [doneStatus])
return Task.done
class CharChattyStateAI(StateData.StateData):
notify = DirectNotifyGlobal.directNotify.newCategory('CharChattyStateAI')
def __init__(self, doneEvent, character):
StateData.StateData.__init__(self, doneEvent)
self.__doneEvent = doneEvent
self.character = character
self.__chatTaskName = 'characterChat-' + str(character)
self.lastChatTarget = 0
self.nextChatTime = 0
self.lastMessage = [
-1, -1]
StateData.StateData.load(self)
def enter(self):
if hasattr(self.character, 'name'):
name = self.character.getName()
else:
name = 'character'
self.notify.debug('Chatty ' + self.character.getName() + '...')
self.chatter = CCharChatter.getChatter(self.character.getName(), self.character.getCCChatter())
if self.chatter != None:
taskMgr.remove(self.__chatTaskName)
taskMgr.add(self.blather, self.__chatTaskName)
else:
self.notify.debug('Chatter is none.. sending done message')
self.leave(timeout=1)
StateData.StateData.enter(self)
return
def pickMsg(self, category):
self.getLatestChatter()
if self.chatter:
return random.randint(0, len(self.chatter[category]) - 1)
else:
return None
return None
def getLatestChatter(self):
self.chatter = CCharChatter.getChatter(self.character.getName(), self.character.getCCChatter())
def setCorrectChatter(self):
self.chatter = CCharChatter.getChatter(self.character.getName(), self.character.getCCChatter())
def blather(self, task):
now = globalClock.getFrameTime()
if now < self.nextChatTime:
return Task.cont
self.getLatestChatter()
if self.character.lostInterest():
self.leave()
return Task.done
if task.time > CHATTY_DURATION:
self.leave(timeout=1)
return Task.done
if not self.chatter:
self.notify.debug('Chatter doesnt exist')
self.leave(timeout=1)
return Task.done
if not self.character.getNearbyAvatars():
return Task.cont
target = self.character.getNearbyAvatars()[0]
if self.lastChatTarget != target:
self.lastChatTarget = target
category = CCharChatter.GREETING
else:
category = CCharChatter.COMMENT
self.setCorrectChatter()
if category == self.lastMessage[0] and len(self.chatter[category]) > 1:
msg = self.lastMessage[1]
lastMsgIndex = self.lastMessage[1]
if lastMsgIndex < len(self.chatter[category]) and lastMsgIndex >= 0:
while self.chatter[category][msg] == self.chatter[category][lastMsgIndex]:
msg = self.pickMsg(category)
if not msg:
break
else:
msg = self.pickMsg(category)
else:
msg = self.pickMsg(category)
if msg == None:
self.notify.debug('Cannot pick a message')
self.leave(timeout=1)
return Task.done
self.character.sendUpdate('setChat', [category, msg, target])
self.lastMessage = [
category, msg]
self.nextChatTime = now + 8.0 + random.random() * 4.0
return Task.cont
def leave(self, timeout=0):
if self.chatter != None and not timeout:
category = CCharChatter.GOODBYE
msg = random.randint(0, len(self.chatter[CCharChatter.GOODBYE]) - 1)
if len(self.character.getNearbyAvatars()) > 0:
target = self.character.getNearbyAvatars()[0]
self.character.sendUpdate('setChat', [category, msg, target])
else:
self.notify.warning('Nearby avatars left')
if timeout == 1:
self.notify.debug('We were stuck in the chatty state')
taskMgr.doMethodLater(1, self.doneHandler, self.character.taskName('waitToFinish'))
return
def exit(self):
StateData.StateData.exit(self)
taskMgr.remove(self.__chatTaskName)
def doneHandler(self, task):
doneStatus = {}
doneStatus['state'] = 'chatty'
doneStatus['status'] = 'done'
messenger.send(self.__doneEvent, [doneStatus])
return Task.done
class CharWalkStateAI(StateData.StateData):
notify = DirectNotifyGlobal.directNotify.newCategory('CharWalkStateAI')
def __init__(self, doneEvent, character, diffPath=None):
StateData.StateData.__init__(self, doneEvent)
self.__doneEvent = doneEvent
self.character = character
if diffPath == None:
self.paths = CCharPaths.getPaths(character.getName(), character.getCCLocation())
else:
self.paths = CCharPaths.getPaths(diffPath, character.getCCLocation())
self.speed = character.walkSpeed()
self.__lastWalkNode = CCharPaths.startNode
self.__curWalkNode = CCharPaths.startNode
return
def enter(self):
destNode = self.__lastWalkNode
choices = CCharPaths.getAdjacentNodes(self.__curWalkNode, self.paths)
if len(choices) == 1:
destNode = choices[0]
else:
while destNode == self.__lastWalkNode:
destNode = random.choice(CCharPaths.getAdjacentNodes(self.__curWalkNode, self.paths))
self.notify.debug('Walking ' + self.character.getName() + '... from ' + str(self.__curWalkNode) + '(' + str(CCharPaths.getNodePos(self.__curWalkNode, self.paths)) + ') to ' + str(destNode) + '(' + str(CCharPaths.getNodePos(destNode, self.paths)) + ')')
self.character.sendUpdate('setWalk', [self.__curWalkNode, destNode, globalClockDelta.getRealNetworkTime()])
duration = CCharPaths.getWalkDuration(self.__curWalkNode, destNode, self.speed, self.paths)
t = taskMgr.doMethodLater(duration, self.doneHandler, self.character.taskName(self.character.getName() + 'DoneWalking'))
t.newWalkNode = destNode
self.destNode = destNode
def exit(self):
StateData.StateData.exit(self)
taskMgr.remove(self.character.taskName(self.character.getName() + 'DoneWalking'))
def getDestNode(self):
if hasattr(self, 'destNode') and self.destNode:
return self.destNode
else:
return self.__curWalkNode
def setCurNode(self, curWalkNode):
self.__curWalkNode = curWalkNode
def doneHandler(self, task):
self.__lastWalkNode = self.__curWalkNode
self.__curWalkNode = task.newWalkNode
self.character.sendUpdate('setWalk', [self.__curWalkNode, self.__curWalkNode, globalClockDelta.getRealNetworkTime()])
doneStatus = {}
doneStatus['state'] = 'walk'
doneStatus['status'] = 'done'
messenger.send(self.__doneEvent, [doneStatus])
return Task.done
class CharFollowChipStateAI(StateData.StateData):
notify = DirectNotifyGlobal.directNotify.newCategory('CharFollowChipStateAI')
def __init__(self, doneEvent, character, followedChar):
StateData.StateData.__init__(self, doneEvent)
self.__doneEvent = doneEvent
self.character = character
self.followedChar = followedChar
self.paths = CCharPaths.getPaths(character.getName(), character.getCCLocation())
self.speed = character.walkSpeed()
self.__lastWalkNode = CCharPaths.startNode
self.__curWalkNode = CCharPaths.startNode
def enter(self, chipDestNode):
destNode = self.__lastWalkNode
choices = CCharPaths.getAdjacentNodes(self.__curWalkNode, self.paths)
if len(choices) == 1:
destNode = choices[0]
else:
while destNode == self.__lastWalkNode:
destNode = random.choice(CCharPaths.getAdjacentNodes(self.__curWalkNode, self.paths))
destNode = chipDestNode
self.notify.debug('Walking ' + self.character.getName() + '... from ' + str(self.__curWalkNode) + '(' + str(CCharPaths.getNodePos(self.__curWalkNode, self.paths)) + ') to ' + str(destNode) + '(' + str(CCharPaths.getNodePos(destNode, self.paths)) + ')')
self.offsetDistance = ToontownGlobals.DaleOrbitDistance
angle = random.randint(0, 359)
self.offsetX = math.cos(deg2Rad(angle)) * self.offsetDistance
self.offsetY = math.sin(deg2Rad(angle)) * self.offsetDistance
self.character.sendUpdate('setFollowChip', [self.__curWalkNode, destNode, globalClockDelta.getRealNetworkTime(), self.offsetX, self.offsetY])
duration = CCharPaths.getWalkDuration(self.__curWalkNode, destNode, self.speed, self.paths)
t = taskMgr.doMethodLater(duration, self.__doneHandler, self.character.taskName(self.character.getName() + 'DoneWalking'))
t.newWalkNode = destNode
def exit(self):
StateData.StateData.exit(self)
taskMgr.remove(self.character.taskName(self.character.getName() + 'DoneWalking'))
def __doneHandler(self, task):
self.__lastWalkNode = self.__curWalkNode
self.__curWalkNode = task.newWalkNode
self.character.sendUpdate('setFollowChip', [self.__curWalkNode, self.__curWalkNode, globalClockDelta.getRealNetworkTime(), self.offsetX, self.offsetY])
doneStatus = {}
doneStatus['state'] = 'walk'
doneStatus['status'] = 'done'
messenger.send(self.__doneEvent, [doneStatus])
return Task.done
class ChipChattyStateAI(CharChattyStateAI):
notify = DirectNotifyGlobal.directNotify.newCategory('ChipChattyStateAI')
def setDaleId(self, daleId):
self.daleId = daleId
self.dale = simbase.air.doId2do.get(self.daleId)
def blather(self, task):
now = globalClock.getFrameTime()
if now < self.nextChatTime:
return Task.cont
self.getLatestChatter()
if self.character.lostInterest():
self.leave()
return Task.done
if task.time > CHATTY_DURATION:
self.leave(timeout=1)
return Task.done
if not self.chatter:
self.notify.debug('I do not want to talk')
return Task.done
if not self.character.getNearbyAvatars():
return Task.cont
target = self.character.getNearbyAvatars()[0]
if self.lastChatTarget != target:
self.lastChatTarget = target
category = CCharChatter.GREETING
else:
category = CCharChatter.COMMENT
if category == self.lastMessage[0] and len(self.chatter[category]) > 1:
msg = self.lastMessage[1]
lastMsgIndex = self.lastMessage[1]
if lastMsgIndex < len(self.chatter[category]) and lastMsgIndex >= 0:
while self.chatter[category][msg] == self.chatter[category][lastMsgIndex]:
msg = self.pickMsg(category)
if not msg:
break
else:
msg = self.pickMsg(category)
else:
msg = self.pickMsg(category)
if msg == None:
self.notify.debug('I do not want to talk')
return Task.done
self.character.sendUpdate('setChat', [category, msg, target])
if hasattr(self, 'dale') and self.dale:
self.dale.sendUpdate('setChat', [category, msg, target])
self.lastMessage = [category, msg]
self.nextChatTime = now + 8.0 + random.random() * 4.0
return Task.cont
def leave(self, timeout=0):
if self.chatter != None and not timeout:
category = CCharChatter.GOODBYE
msg = random.randint(0, len(self.chatter[CCharChatter.GOODBYE]) - 1)
if len(self.character.getNearbyAvatars()) > 0:
target = self.character.getNearbyAvatars()[0]
self.character.sendUpdate('setChat', [category, msg, target])
if hasattr(self, 'dale') and self.dale:
self.dale.sendUpdate('setChat', [category, msg, target])
else:
self.notify.warning('Nearby avatars left')
taskMgr.doMethodLater(1, self.doneHandler, self.character.taskName('waitToFinish'))
return