2015-03-03 16:10:12 -06: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)
|
2015-07-27 02:55:40 -05:00
|
|
|
self._willBalanceTeams = False # balanceTeams
|
2015-03-03 16:10:12 -06:00
|
|
|
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 = []
|
2015-07-27 02:55:40 -05:00
|
|
|
for i in range(len(PartyGlobals.TeamActivityTeams)):
|
2015-03-03 16:10:12 -06:00
|
|
|
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):
|
2015-07-27 02:55:40 -05:00
|
|
|
for i in range(len(PartyGlobals.TeamActivityTeams)):
|
2015-03-03 16:10:12 -06:00
|
|
|
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()
|