toontown-just-works/toontown/parties/DistributedPartyTeamActivity.py

379 lines
14 KiB
Python
Raw Normal View History

2024-07-07 18:08:39 -05:00
from direct.distributed.ClockDelta import globalClockDelta
from toontown.toonbase import TTLocalizer
from toontown.parties import PartyGlobals
from toontown.parties.DistributedPartyActivity import DistributedPartyActivity
from toontown.parties.activityFSMs import TeamActivityFSM
from toontown.parties.TeamActivityGui import TeamActivityGui
class DistributedPartyTeamActivity(DistributedPartyActivity):
notify = directNotify.newCategory('DistributedPartyTeamActivity')
def __init__(self, cr, activityId, startDelay = PartyGlobals.TeamActivityStartDelay, balanceTeams = False):
DistributedPartyActivity.__init__(self, cr, activityId, PartyGlobals.ActivityTypes.GuestInitiated, wantRewardGui=True)
self.notify.debug('__init__')
self.toonIds = ([], [])
self.isLocalToonPlaying = False
self.localToonTeam = None
self.advantage = 1.0
self.waitToStartTimestamp = None
self._maxPlayersPerTeam = 0
self._minPlayersPerTeam = 0
self._duration = 0
self._startDelay = base.config.GetFloat('party-team-activity-start-delay', startDelay)
self._willBalanceTeams = False # balanceTeams
self._currentStatus = ''
return
def load(self):
DistributedPartyActivity.load(self)
self.teamActivityGui = TeamActivityGui(self)
self.activityFSM = TeamActivityFSM(self)
def unload(self):
DistributedPartyActivity.unload(self)
del self.activityFSM
self.teamActivityGui.unload()
del self.teamActivityGui
if hasattr(self, 'toonIds'):
del self.toonIds
del self.isLocalToonPlaying
del self.localToonTeam
del self.advantage
del self.waitToStartTimestamp
def handleToonShifted(self, toonId):
self.notify.error('handleToonShifted( toonId=%d ) must be overriden by child class.' % toonId)
def handleToonSwitchedTeams(self, toonId):
if toonId == base.localAvatar.doId and self._canSwitchTeams:
if self.isState('WaitForEnough') or self.isState('WaitToStart'):
self.teamActivityGui.enableExitButton()
self.teamActivityGui.enableSwitchButton()
def handleToonDisabled(self, toonId):
self.notify.error('handleToonDisabled( toonId=%d ) must be overriden by child class.' % toonId)
def setPlayersPerTeam(self, min, max):
self._minPlayersPerTeam = min
self._maxPlayersPerTeam = max
def setDuration(self, duration):
self._duration = duration
def setCanSwitchTeams(self, canSwitchTeams):
self._canSwitchTeams = canSwitchTeams
def d_toonJoinRequest(self, team):
if self.isLocalToonInActivity():
return
if self.activityFSM.state in ['WaitForEnough', 'WaitToStart'] and self._localToonRequestStatus is None:
base.cr.playGame.getPlace().fsm.request('activity')
self.localToonJoining()
self.sendUpdate('toonJoinRequest', [team])
return
def d_toonExitRequest(self):
toonId = base.localAvatar.doId
team = self.getTeam(toonId)
if team is not None:
if self._localToonRequestStatus is None:
self.localToonExiting()
self.sendUpdate('toonExitRequest', [team])
else:
self.notify.warning('Not sending exitRequest as localToon has no team.')
return
def joinRequestDenied(self, reason):
DistributedPartyActivity.joinRequestDenied(self, reason)
self.notify.debug('joinRequestDenied')
if reason == PartyGlobals.DenialReasons.Full:
self.showMessage(TTLocalizer.PartyTeamActivityTeamFull)
elif reason == PartyGlobals.DenialReasons.Default:
self.showMessage(TTLocalizer.PartyTeamActivityJoinDenied % self.getTitle())
def exitRequestDenied(self, reason):
DistributedPartyActivity.exitRequestDenied(self, reason)
if reason == PartyGlobals.DenialReasons.Default:
self.showMessage(TTLocalizer.PartyTeamActivityExitDenied % self.getTitle())
if self.isLocalToonPlaying and (self.isState('WaitToStart') or self.isState('WaitForEnough')):
self.teamActivityGui.enableExitButton()
if self._canSwitchTeams:
self.teamActivityGui.enableSwitchButton()
def d_toonSwitchTeamRequest(self):
if not self._canSwitchTeams:
return
self.sendUpdate('toonSwitchTeamRequest')
def switchTeamRequestDenied(self, reason):
self.notify.debug('switchTeamRequestDenied')
if reason == PartyGlobals.DenialReasons.Full:
self.showMessage(TTLocalizer.PartyTeamActivityTeamFull, endState='activity')
elif reason == PartyGlobals.DenialReasons.Default:
self.showMessage(TTLocalizer.PartyTeamActivitySwitchDenied, endState='activity')
if self.isLocalToonPlaying and (self.isState('WaitToStart') or self.isState('WaitForEnough')) and self._canSwitchTeams:
self.teamActivityGui.enableSwitchButton()
def setToonsPlaying(self, leftTeamToonIds, rightTeamToonIds):
newToonIds = [leftTeamToonIds, rightTeamToonIds]
exitedToons, joinedToons, shifters, switchers = self.getToonsPlayingChanges(self.toonIds, newToonIds)
if base.localAvatar.doId in exitedToons:
self.localToonExiting()
self._processExitedToons(exitedToons)
self.setToonIds([leftTeamToonIds, rightTeamToonIds])
self._processJoinedToons(joinedToons)
for toonId in shifters:
self.handleToonShifted(toonId)
if self._canSwitchTeams:
for toonId in switchers:
self.handleToonSwitchedTeams(toonId)
if self.isState('WaitForEnough'):
self._updateWaitForEnoughStatus()
def _updateWaitForEnoughStatus(self):
amount = self.getNumToonsNeededToStart()
if self._willBalanceTeams:
text = TTLocalizer.PartyTeamActivityForMoreWithBalance
else:
text = TTLocalizer.PartyTeamActivityForMore
if amount > 1:
plural = TTLocalizer.PartyTeamActivityForMorePlural
else:
plural = ''
self.setStatus(text % (amount, plural))
def setState(self, newState, timestamp, data):
DistributedPartyActivity.setState(self, newState, timestamp)
if newState == 'WaitToStart':
self.activityFSM.request(newState, timestamp)
elif newState == 'Conclusion':
self.activityFSM.request(newState, data)
else:
self.activityFSM.request(newState)
def d_toonReady(self):
self.sendUpdate('toonReady')
def setAdvantage(self, advantage):
self.advantage = advantage
def handleToonJoined(self, toonId):
if toonId == base.localAvatar.doId:
self.isLocalToonPlaying = True
self.localToonTeam = self.getTeam(base.localAvatar.doId)
self.teamActivityGui.load()
self.teamActivityGui.enableExitButton()
if self._canSwitchTeams:
self.teamActivityGui.enableSwitchButton()
if self.activityFSM.state == 'WaitToStart':
self.showWaitToStartCountdown()
else:
self.showStatus()
def handleToonExited(self, toonId):
if toonId == base.localAvatar.doId:
self.hideStatus()
self.teamActivityGui.disableExitButton()
if self._canSwitchTeams:
self.teamActivityGui.disableSwitchButton()
if self.activityFSM.state == 'WaitToStart':
self.hideWaitToStartCountdown()
self.teamActivityGui.unload()
self.isLocalToonPlaying = False
self.localToonTeam = None
return
def handleRulesDone(self):
self.notify.debug('handleRulesDone')
self.d_toonReady()
self.activityFSM.request('WaitForServer')
def handleGameTimerExpired(self):
pass
def getToonsPlayingChanges(self, oldToonIds, newToonIds):
oldLeftTeam = oldToonIds[0]
oldRightTeam = oldToonIds[1]
newLeftTeam = newToonIds[0]
newRightTeam = newToonIds[1]
oldToons = set(oldLeftTeam + oldRightTeam)
newToons = set(newLeftTeam + newRightTeam)
exitedToons = oldToons.difference(newToons)
joinedToons = newToons.difference(oldToons)
shifters = []
if self._canSwitchTeams:
switchers = list(set(oldLeftTeam) & set(newRightTeam)) + list(set(oldRightTeam) & set(newLeftTeam))
else:
switchers = []
for i in range(len(PartyGlobals.TeamActivityTeams)):
persistentToons = set(oldToonIds[i]) & set(newToonIds[i])
for toonId in persistentToons:
if oldToonIds[i].index(toonId) != newToonIds[i].index(toonId):
shifters.append(toonId)
return (list(exitedToons),
list(joinedToons),
shifters,
switchers)
def getMaxPlayersPerTeam(self):
return self._maxPlayersPerTeam
def getMinPlayersPerTeam(self):
return self._minPlayersPerTeam
def getNumToonsNeededToStart(self):
if self._willBalanceTeams:
return abs(self._minPlayersPerTeam * 2 - self.getNumToonsPlaying())
else:
return self._minPlayersPerTeam
def getToonIdsAsList(self):
return self.toonIds[0] + self.toonIds[1]
def getNumToonsPlaying(self):
return len(self.toonIds[0]) + len(self.toonIds[1])
def getNumToonsInTeam(self, team):
return len(self.toonIds[team])
def getTeam(self, toonId):
for i in range(len(PartyGlobals.TeamActivityTeams)):
if self.toonIds[i].count(toonId) > 0:
return i
else:
return None
return None
def getIndex(self, toonId, team):
if self.toonIds[team].count(toonId) > 0:
return self.toonIds[team].index(toonId)
else:
return None
return None
def _joinLeftTeam(self, collEntry):
if self.isLocalToonInActivity():
return
self.d_toonJoinRequest(PartyGlobals.TeamActivityTeams.LeftTeam)
def _joinRightTeam(self, collEntry):
if self.isLocalToonInActivity():
return
self.d_toonJoinRequest(PartyGlobals.TeamActivityTeams.RightTeam)
def showWaitToStartCountdown(self):
if self.waitToStartTimestamp is None:
self.notify.warning('showWaitToStartCountdown was called when self.waitToStartTimestamp was None')
return
self.teamActivityGui.showWaitToStartCountdown(self._startDelay, self.waitToStartTimestamp, almostDoneCallback=self._onCountdownAlmostDone)
self.showStatus()
self.teamActivityGui.enableExitButton()
return
def _onCountdownAlmostDone(self):
if self._canSwitchTeams:
self.teamActivityGui.disableSwitchButton()
def hideWaitToStartCountdown(self):
self.teamActivityGui.hideWaitToStartCountdown()
self.teamActivityGui.disableExitButton()
self.hideStatus()
def setStatus(self, text):
self._currentStatus = text
if self.isLocalToonPlaying:
self.showStatus()
def showStatus(self):
if self.teamActivityGui is not None:
self.teamActivityGui.showStatus(self._currentStatus)
return
def hideStatus(self):
if self.teamActivityGui is not None:
self.teamActivityGui.hideStatus()
return
def toonsCanSwitchTeams(self):
return self._canSwitchTeams
def isState(self, state):
return hasattr(self, 'activityFSM') and self.activityFSM.getCurrentOrNextState() == state
def startWaitForEnough(self):
self.notify.debug('startWaitForEnough')
self.advantage = 1.0
self._updateWaitForEnoughStatus()
if self.isLocalToonPlaying:
self.teamActivityGui.enableExitButton()
if self._canSwitchTeams:
self.teamActivityGui.enableSwitchButton()
def finishWaitForEnough(self):
self.notify.debug('finishWaitForEnough')
def startWaitToStart(self, waitStartTimestamp):
self.notify.debug('startWaitToStart')
self.waitToStartTimestamp = globalClockDelta.networkToLocalTime(waitStartTimestamp)
self._updateWaitForEnoughStatus()
self.setStatus(TTLocalizer.PartyTeamActivityWaitingToStart)
if self.isLocalToonPlaying:
self.showWaitToStartCountdown()
def finishWaitToStart(self):
self.notify.debug('finishWaitToStart')
if self.isLocalToonPlaying:
self.hideWaitToStartCountdown()
if self._canSwitchTeams:
self.teamActivityGui.disableSwitchButton()
self.waitToStartTimestamp = None
return
def startRules(self):
self.notify.debug('startRules')
if self.isLocalToonPlaying:
DistributedPartyActivity.startRules(self)
def finishRules(self):
self.notify.debug('finishRules')
if self.isLocalToonPlaying:
DistributedPartyActivity.finishRules(self)
if self.activityFSM.getCurrentOrNextState() == 'WaitForEnough':
DistributedPartyActivity.finishRules(self)
def startWaitForServer(self):
self.notify.debug('startWaitForServer')
self.setStatus(TTLocalizer.PartyTeamActivityWaitingForOtherPlayers)
def finishWaitForServer(self):
self.notify.debug('finishWaitForServer')
if self.isLocalToonPlaying:
self.hideStatus()
def startActive(self):
self.notify.debug('startActive')
if self.isLocalToonPlaying:
self.hideStatus()
self.teamActivityGui.showTimer(self._duration)
def finishActive(self):
self.notify.debug('finishActive')
if self.isLocalToonPlaying:
self.teamActivityGui.hideTimer()
self.hideStatus()
def startConclusion(self, data):
self.notify.debug('startConclusion')
self.setStatus('')
if self.isLocalToonPlaying:
self.localToonExiting()
def finishConclusion(self):
self.notify.debug('finishConclusion')
if self.isLocalToonPlaying:
self.hideStatus()