from direct.directnotify import DirectNotifyGlobal from DistributedPartyTeamActivityAI import DistributedPartyTeamActivityAI from toontown.toonbase import TTLocalizer import PartyGlobals ''' dclass DistributedPartyTugOfWarActivity : DistributedPartyTeamActivity { reportKeyRateForce(uint32, int16/100) airecv clsend; reportFallIn(uint8) airecv clsend; setToonsPlaying(uint32 [0-4], uint32 [0-4]) required broadcast ram; updateToonKeyRate(uint32, uint32) broadcast; updateToonPositions(int16/1000) broadcast; }; ''' scoreRef = {'tie': (PartyGlobals.TugOfWarTieReward, PartyGlobals.TugOfWarTieReward), 0: (PartyGlobals.TugOfWarWinReward, PartyGlobals.TugOfWarLossReward), 1: (PartyGlobals.TugOfWarLossReward, PartyGlobals.TugOfWarWinReward), 10:(PartyGlobals.TugOfWarFallInWinReward, PartyGlobals.TugOfWarFallInLossReward), 11: (PartyGlobals.TugOfWarFallInLossReward, PartyGlobals.TugOfWarFallInWinReward), } class DistributedPartyTugOfWarActivityAI(DistributedPartyTeamActivityAI): notify = DirectNotifyGlobal.directNotify.newCategory("DistributedPartyTugOfWarActivityAI") forbidTeamChanges = True startDelay = PartyGlobals.TugOfWarStartDelay def getDuration(self): return PartyGlobals.TugOfWarDuration def reportKeyRateForce(self, keyRate, force): # Basic sanity check av = self._getCaller() if not av: return avId = av.doId if not (avId in self.toonIds[0] or avId in self.toonIds[1]): self.air.writeServerEvent('suspicious', avId, 'sent DistributedPartyTugOfWarActivityAI.reportKeyRateForce, but not playing') return self.forces[avId] = force self.sendUpdate('updateToonKeyRate', [avId, keyRate]) self.d_updateToonPositions() def d_updateToonPositions(self): _getTeamForce = lambda team: sum(self.forces.get(avId, 0) for avId in self.toonIds[team]) f0 = _getTeamForce(0) f1 = _getTeamForce(1) fr = f0 + f1 if fr != 0: delta = (f0 - f1) / fr self.pos += -delta * PartyGlobals.TugOfWarMovementFactor * 2 self.sendUpdate('updateToonPositions', [self.pos]) def reportFallIn(self, losingTeam): if self.fsm.state != 'Active' or self._hasFall: return # Basic sanity check av = self._getCaller() if not av: return avId = av.doId if not (avId in self.toonIds[0] or avId in self.toonIds[1]): self.air.writeServerEvent('suspicious', avId, 'sent DistributedPartyTugOfWarActivityAI.reportFallIn, but not playing') return losers = int(self.pos < 0) if losers != losingTeam: self.air.writeServerEvent('suspicious', avId, 'called DistributedPartyTugOfWarActivityAI.reportFallIn with incorrect losingTeam') self._hasFall = 1 def _advance(task): self.calcReward() return task.done taskMgr.doMethodLater(1, _advance, self.taskName('fallIn-advance')) taskMgr.remove(self.taskName('finish')) # Mitigate races def calcReward(self): nobodyWins = abs(self.pos) <= 2 if nobodyWins: self._winnerTeam = 3 self._teamScores = scoreRef['tie'] else: self._winnerTeam = int(self.pos < 0) self._teamScores = scoreRef[self._winnerTeam + self._hasFall * 10] self.b_setState('Conclusion', self._winnerTeam) def startActive(self, data): self.forces = {} self.pos = 0 self._hasFall = 0 DistributedPartyTeamActivityAI.startActive(self, data) def startConclusion(self, data): taskMgr.doMethodLater(1, self.__exitConclusion, self.taskName('exitconc')) def finishConclusion(self): taskMgr.remove(self.taskName('exitconc')) def __exitConclusion(self, task): def _sendReward(team): jb = self._teamScores[team] msg = TTLocalizer.PartyTeamActivityRewardMessage % jb for avId in self.toonIds[team]: av = self.air.doId2do.get(avId) if av: self.sendUpdateToAvatarId(avId, 'showJellybeanReward', [jb, av.getMoney(), msg]) av.addMoney(jb) _sendReward(0) _sendReward(1) self.toonsPlaying = [] self.toonIds = ([], []) self.updateToonsPlaying() self.b_setState('WaitForEnough') return task.done