toontown-just-works/toontown/parties/DistributedPartyTeamActivityAI.py
2024-07-07 18:08:39 -05:00

216 lines
No EOL
8 KiB
Python

from direct.directnotify import DirectNotifyGlobal
from direct.distributed.ClockDelta import globalClockDelta
from DistributedPartyActivityAI import DistributedPartyActivityAI
from activityFSMs import TeamActivityAIFSM
import PartyGlobals
'''
dclass DistributedPartyTeamActivity : DistributedPartyActivity {
toonJoinRequest(uint8(0-1)) airecv clsend;
toonExitRequest(uint8(0-1)) airecv clsend;
toonSwitchTeamRequest() airecv clsend;
setPlayersPerTeam(uint8, uint8) broadcast required;
setDuration(uint8) broadcast required;
setCanSwitchTeams(bool) broadcast required;
setState(string, int16, uint32) broadcast ram;
setToonsPlaying(uint32 [0-8], uint32 [0-8]) required broadcast ram;
setAdvantage(uint16/100);
switchTeamRequestDenied(uint8);
};
'''
'''self.defaultTransitions = {'WaitForEnough': ['WaitToStart'],
'WaitToStart': ['WaitForEnough', 'WaitClientsReady'],
'WaitClientsReady': ['WaitForEnough', 'Active'],
'Active': ['WaitForEnough', 'Conclusion'],
'Conclusion': ['WaitForEnough']}'''
class DistributedPartyTeamActivityAI(DistributedPartyActivityAI):
notify = DirectNotifyGlobal.directNotify.newCategory("DistributedPartyTeamActivityAI")
forbidTeamChanges = False
startDelay = PartyGlobals.TeamActivityStartDelay
def __init__(self, air, parent, activityTuple):
self.toonIds = ([], [])
self.responses = set()
self.fsm = TeamActivityAIFSM(self)
DistributedPartyActivityAI.__init__(self, air, parent, activityTuple)
def announceGenerate(self):
self.b_setState('WaitForEnough')
DistributedPartyActivityAI.announceGenerate(self)
def toonJoinRequest(self, team):
av = self._getCaller()
if not av:
return
if not self.fsm.state in ('WaitForEnough', 'WaitToStart'):
self.sendUpdateToAvatarId(av.doId, 'joinTeamRequestDenied', [PartyGlobals.DenialReasons.Default])
return
if len(self.toonIds[team]) >= self.getPlayersPerTeam()[1]:
self.sendUpdateToAvatarId(av.doId, 'joinTeamRequestDenied', [PartyGlobals.DenialReasons.Full])
return
if av.doId in self.toonsPlaying:
self.air.writeServerEvent('suspicious', av.doId, 'tried to join party team activity again!')
self.sendUpdateToAvatarId(av.doId, 'joinTeamRequestDenied', [PartyGlobals.DenialReasons.Default])
return
# idgaf if they exit unexpectedly in this case
self.toonIds[team].append(av.doId)
DistributedPartyActivityAI.toonJoinRequest(self)
self.__update()
def toonExitRequest(self, team):
av = self._getCaller()
if not av:
return
if not self.fsm.state in ('WaitForEnough', 'WaitToStart'):
self.sendUpdateToAvatarId(av.doId, 'exitRequestDenied', [PartyGlobals.DenialReasons.Default])
return
if not (av.doId in self.toonIds[0] or av.doId in self.toonIds[1]):
self.air.writeServerEvent('suspicious', avId, 'tried to switch DistributedPartyActivityAI team, but not in one')
self.sendUpdateToAvatarId(av.doId, 'exitRequestDenied', [PartyGlobals.DenialReasons.Default])
return
currentTeam = (1, 0)[av.doId in self.toonIds[0]]
self.toonIds[currentTeam].remove(av.doId)
DistributedPartyActivityAI.toonExitRequest(self)
self.__update()
def toonSwitchTeamRequest(self):
av = self._getCaller()
if not av:
return
if not self.getCanSwitchTeams():
self.air.writeServerEvent('suspicious', avId, 'tried to switch DistributedPartyActivityAI team in bad time')
self.sendUpdateToAvatarId(av.doId, 'switchTeamRequestDenied', [PartyGlobals.DenialReasons.Default])
return
if not (av.doId in self.toonIds[0] or av.doId in self.toonIds[1]):
self.air.writeServerEvent('suspicious', avId, 'tried to switch DistributedPartyActivityAI team, but not in one')
self.sendUpdateToAvatarId(av.doId, 'switchTeamRequestDenied', [PartyGlobals.DenialReasons.Default])
return
currentTeam = (1, 0)[av.doId in self.toonIds[0]]
otherTeam = (1, 0)[currentTeam]
if len(self.toonIds[otherTeam]) >= self.getPlayersPerTeam()[1]:
self.sendUpdateToAvatarId(av.doId, 'switchTeamRequestDenied', [PartyGlobals.DenialReasons.Full])
return
self.toonIds[currentTeam].remove(av.doId)
self.toonIds[otherTeam].append(av.doId)
self.__update()
def getPlayersPerTeam(self):
return (PartyGlobals.CogActivityMinPlayersPerTeam,
PartyGlobals.CogActivityMaxPlayersPerTeam)
def __areTeamsCorrect(self):
minPlayers = self.getPlayersPerTeam()[0]
return all(len(self.toonIds[i]) >= minPlayers for i in xrange(2))
def getDuration(self):
raise NotImplementedError('getDuration() -- pure virtual')
def getCanSwitchTeams(self):
return self.fsm.state in ('Off', 'WaitForEnough', 'WaitToStart') and not self.forbidTeamChanges
def updateToonsPlaying(self):
self.sendUpdate('setToonsPlaying', self.getToonsPlaying())
def getToonsPlaying(self):
return self.toonIds
def setAdvantage(self, todo0):
pass
def b_setState(self, state, data=0):
self.fsm.request(state, data)
self.d_setState(state, data)
def d_setState(self, state, data=0):
self.sendUpdate('setState', [state, globalClockDelta.getRealNetworkTime(), data])
def _getCaller(self):
avId = self.air.getAvatarIdFromSender()
if avId not in self.air.doId2do:
self.air.writeServerEvent('suspicious', avId, 'called some DistributedPartyActivityAI method outside shard')
return None
return self.air.doId2do[avId]
def __update(self):
self.updateToonsPlaying()
if self.fsm.state == 'WaitForEnough':
if self.__areTeamsCorrect():
self.b_setState('WaitToStart')
elif self.fsm.state == 'WaitToStart':
if not self.__areTeamsCorrect():
self.b_setState('WaitForEnough')
def startWaitForEnough(self, data):
pass
def finishWaitForEnough(self):
pass
def startWaitToStart(self, data):
def advance(task):
self.fsm.request('WaitClientsReady')
self.d_setState('Rules')
return task.done
taskMgr.doMethodLater(self.startDelay, advance, self.taskName('dostart'))
def finishWaitToStart(self):
taskMgr.remove(self.taskName('dostart'))
def __doStart(self, task = None):
self.b_setState('Active')
if task: return task.done
def startWaitClientsReady(self):
self.responses = set()
taskMgr.doMethodLater(15, self.__doStart, self.taskName('clientready'))
def finishWaitClientsReady(self):
taskMgr.remove(self.taskName('clientready'))
def toonReady(self):
self.responses.add(self.air.getAvatarIdFromSender())
if self.responses == set(self.toonsPlaying):
self.__doStart()
def startActive(self, data):
taskMgr.doMethodLater(self.getDuration(), self.__finish, self.taskName('finish'))
def finishActive(self):
taskMgr.remove(self.taskName('finish'))
def __finish(self, task):
self.calcReward()
self.b_setState('Conclusion')
return task.done
def calcReward(self):
raise NotImplementedError('calcReward() -- pure virtual')
def startConclusion(self, data):
raise NotImplementedError('startConclusion() -- pure virtual')
def finishConclusion(self):
raise NotImplementedError('finishConclusion() -- pure virtual')