oldschool-toontown/toontown/cogdominium/DistCogdoGameAI.py
2019-12-30 13:03:23 -05:00

269 lines
8.4 KiB
Python

from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.distributed.ClockDelta import globalClockDelta
from direct.distributed.DistributedObjectAI import DistributedObjectAI
from direct.fsm import ClassicFSM, State
from toontown.cogdominium import CogdoGameConsts
from toontown.cogdominium.DistCogdoGameBase import DistCogdoGameBase
from otp.ai.Barrier import Barrier
class SadCallbackToken:
pass
class DistCogdoGameAI(DistCogdoGameBase, DistributedObjectAI):
notify = directNotify.newCategory('DistCogdoGameAI')
EndlessCogdoGames = simbase.config.GetBool('endless-cogdo-games', 0)
def __init__(self, air, interior):
DistributedObjectAI.__init__(self, air)
self._interior = interior
self.loadFSM = ClassicFSM.ClassicFSM('DistCogdoGameAI.loaded', [
State.State('NotLoaded', self.enterNotLoaded, self.exitNotLoaded, [
'Loaded']),
State.State('Loaded', self.enterLoaded, self.exitLoaded, [
'NotLoaded'])], 'NotLoaded', 'NotLoaded')
self.loadFSM.enterInitialState()
self.fsm = ClassicFSM.ClassicFSM('DistCogdoGameAI', [
State.State('Visible', self.enterVisible, self.exitVisible, [
'Intro']),
State.State('Intro', self.enterIntro, self.exitIntro, [
'Game']),
State.State('Game', self.enterGame, self.exitGame, [
'Finish']),
State.State('Finish', self.enterFinish, self.exitFinish, [
'Off']),
State.State('Off', self.enterOff, self.exitOff, [
'Visible'])], 'Off', 'Off')
self.fsm.enterInitialState()
self.difficultyOverride = None
self.exteriorZoneOverride = None
def setExteriorZone(self, exteriorZone):
self.exteriorZone = exteriorZone
def logSuspiciousEvent(self, avId, msg):
self.air.writeServerEvent('suspicious', avId, msg)
def generate(self):
DistributedObjectAI.generate(self)
self._sadToken2callback = {}
self.notify.debug('difficulty: %s, safezoneId: %s' % (self.getDifficulty(), self.getSafezoneId()))
def getInteriorId(self):
return self._interior.doId
def getExteriorZone(self):
return self.exteriorZone
def getDroneCogDNA(self):
return self._interior.getDroneCogDNA()
def getToonIds(self):
toonIds = []
for toonId in self._interior.getToons()[0]:
if toonId:
toonIds.append(toonId)
return toonIds
def getNumPlayers(self):
return len(self.getToonIds())
def requestDelete(self):
self.fsm.requestFinalState()
self.loadFSM.requestFinalState()
self._sadToken2callback = None
DistributedObjectAI.requestDelete(self)
def delete(self):
self._interior = None
self.fsm = None
self.loadFSM = None
DistributedObjectAI.delete(self)
def makeVisible(self):
self.loadFSM.request('Loaded')
self.fsm.request('Visible')
def start(self):
self.fsm.request('Intro')
def markStartTime(self):
self._startTime = globalClock.getRealTime()
def getStartTime(self):
return self._startTime
def markFinishTime(self):
self._finishTime = globalClock.getRealTime()
def getFinishTime(self):
return self._finishTime
def setDifficultyOverrides(self, difficultyOverride, exteriorZoneOverride):
self.difficultyOverride = difficultyOverride
if self.difficultyOverride is not None:
self.difficultyOverride = CogdoGameConsts.QuantizeDifficultyOverride(difficultyOverride)
self.exteriorZoneOverride = exteriorZoneOverride
def getDifficultyOverrides(self):
response = [
self.difficultyOverride,
self.exteriorZoneOverride]
if response[0] is None:
response[0] = CogdoGameConsts.NoDifficultyOverride
else:
response[0] *= CogdoGameConsts.DifficultyOverrideMult
response[0] = int(response[0])
if response[1] is None:
response[1] = CogdoGameConsts.NoExteriorZoneOverride
return response
def getDifficulty(self):
if self.difficultyOverride is not None:
return self.difficultyOverride
if hasattr(self.air, 'cogdoGameDifficulty'):
return float(self.air.cogdoGameDifficulty)
return CogdoGameConsts.getDifficulty(self.getSafezoneId())
def getSafezoneId(self):
if self.exteriorZoneOverride is not None:
return self.exteriorZoneOverride
if hasattr(self.air, 'cogdoGameSafezoneId'):
return CogdoGameConsts.getSafezoneId(self.air.cogdoGameSafezoneId)
return CogdoGameConsts.getSafezoneId(self.exteriorZone)
def _validateSenderId(self, senderId):
if senderId in self.getToonIds():
return True
self._reportSuspiciousEvent(senderId, 'Not currently playing CogDo Game.')
return False
def _reportSuspiciousEvent(self, senderId, message):
self.logSuspiciousEvent(senderId, message)
def handleToonDisconnected(self, toonId):
self.notify.debug('handleToonDisconnected: %s' % toonId)
self.sendUpdate('setToonDisconnect', [
toonId])
def handleToonWentSad(self, toonId):
self.notify.debug('handleToonWentSad: %s' % toonId)
self.sendUpdate('setToonSad', [
toonId])
if self._sadToken2callback is not None:
callbacks = list(self._sadToken2callback.values())
for callback in callbacks:
callback(toonId)
def _registerSadCallback(self, callback):
token = SadCallbackToken()
self._sadToken2callback[token] = callback
return token
def _unregisterSadCallback(self, token):
self._sadToken2callback.pop(token)
def enterNotLoaded(self):
pass
def exitNotLoaded(self):
pass
def enterLoaded(self):
pass
def exitLoaded(self):
pass
def enterOff(self):
self.ignore('cogdoGameEnd')
def exitOff(self):
self._wasEnded = False
self.accept('cogdoGameEnd', self._handleGameEnd)
def enterVisible(self):
self.sendUpdate('setVisible', [])
def exitVisible(self):
pass
def enterIntro(self):
self.sendUpdate('setIntroStart', [])
self._introBarrier = Barrier('intro', self.uniqueName('intro'), self.getToonIds(), 1 << 20, doneFunc = self._handleIntroBarrierDone)
self._sadToken = self._registerSadCallback(self._handleSadToonDuringIntro)
def exitIntro(self):
self._unregisterSadCallback(self._sadToken)
self._sadToken = None
self._introBarrier.cleanup()
self._introBarrier = None
def _handleSadToonDuringIntro(self, toonId):
self._introBarrier.clear(toonId)
def setAvatarReady(self):
senderId = self.air.getAvatarIdFromSender()
if senderId not in self.getToonIds():
self.logSuspiciousEvent(senderId, 'CogdoGameAI.setAvatarReady: unknown avatar')
return
if hasattr(self, '_introBarrier') and self._introBarrier:
self._introBarrier.clear(senderId)
def _handleIntroBarrierDone(self, avIds):
self.fsm.request('Game')
def enterGame(self):
self.markStartTime()
self.sendUpdate('setGameStart', [
globalClockDelta.localToNetworkTime(self.getStartTime())])
def exitGame(self):
pass
def _handleGameFinished(self, overrideEndless = False):
if overrideEndless or not (self.EndlessCogdoGames):
self.fsm.request('Finish')
def _handleGameEnd(self):
self._wasEnded = True
if self.fsm.getCurrentState().getName() == 'Off':
self.fsm.request('Intro')
if self.fsm.getCurrentState().getName() == 'Intro':
self.fsm.request('Game')
self._handleGameFinished(overrideEndless = True)
self.announceGameDone()
def wasEnded(self):
return self._wasEnded
def enterFinish(self):
self.markFinishTime()
self.sendUpdate('setGameFinish', [
globalClockDelta.localToNetworkTime(self.getFinishTime())])
def exitFinish(self):
pass
def setScore(self, score):
self._interior._setGameScore(score)
def isDoorOpen(self):
return True
def isToonInDoor(self, toonId):
return True
def announceGameDone(self):
self._interior._gameDone()