diff --git a/.gitignore b/.gitignore index a4e646e1..0e48a00d 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,9 @@ # Mac directory info: .DS_Store +# Shortcuts: +*.lnk + # Game-specific files and directories: preferences.json *.json diff --git a/astron/dclass/united.dc b/astron/dclass/united.dc index 26d9e01b..96178566 100644 --- a/astron/dclass/united.dc +++ b/astron/dclass/united.dc @@ -711,6 +711,7 @@ from toontown.uberdog.DistributedMailManager/AI/UD import DistributedMailManager from toontown.uberdog.DistributedPartyManager/AI/UD import DistributedPartyManager/AI/UD from toontown.rpc.AwardManager/UD import AwardManager/UD from toontown.coderedemption.TTCodeRedemptionMgr/AI import TTCodeRedemptionMgr/AI +from toontown.friends.TrueFriendsMgr/AI import TrueFriendsMgr/AI from toontown.ai.DistributedPhaseEventMgr/AI import DistributedPhaseEventMgr/AI from toontown.ai.DistributedHydrantZeroMgr/AI import DistributedHydrantZeroMgr/AI from toontown.ai.DistributedMailboxZeroMgr/AI import DistributedMailboxZeroMgr/AI @@ -3615,10 +3616,14 @@ dclass AwardManager : DistributedObjectGlobal { }; dclass TTCodeRedemptionMgr : DistributedObject { - redeemCode(char [0-256]) airecv clsend; redeemCodeResult(uint32); }; +dclass TrueFriendsMgr : DistributedObject { + requestIdResult(uint32, string, string); + redeemIdResult(uint32, string); +}; + struct Friend { uint32 doId; diff --git a/otp/distributed/DCClassImports.py b/otp/distributed/DCClassImports.py index 3ca46ec2..e417b112 100644 --- a/otp/distributed/DCClassImports.py +++ b/otp/distributed/DCClassImports.py @@ -34,6 +34,7 @@ from toontown.catalog import CatalogManager, AccountDate from toontown.ai.DistributedHydrantZeroMgr import DistributedHydrantZeroMgr from toontown.rpc.AwardManager import AwardManager from toontown.parties import DistributedParty, DistributedPartyActivity, DistributedPartyTeamActivity, DistributedPartyCannon, DistributedPartyCannonActivity, DistributedPartyCatchActivity, DistributedPartyWinterCatchActivity, DistributedPartyCogActivity, DistributedPartyWinterCogActivity, DistributedPartyFireworksActivity, DistributedPartyDanceActivityBase, DistributedPartyDanceActivity, DistributedPartyDance20Activity, DistributedPartyValentineDanceActivity, DistributedPartyValentineDance20Activity, DistributedPartyTrampolineActivity, DistributedPartyValentineTrampolineActivity, DistributedPartyVictoryTrampolineActivity, DistributedPartyWinterTrampolineActivity, DistributedPartyTugOfWarActivity, DistributedPartyJukeboxActivityBase, DistributedPartyJukeboxActivity, DistributedPartyJukebox40Activity, DistributedPartyValentineJukeboxActivity, DistributedPartyValentineJukebox40Activity +from toontown.friends.TrueFriendsMgr import TrueFriendsMgr from toontown.coghq.InGameEditorDCImports import * from toontown.friends import TTPlayerFriendsManager, TTUFriendsManager from toontown.cogdominium import DistributedCogdoInterior, DistributedCogdoBattleBldg, DistributedCogdoElevatorExt, DistributedCogdoElevatorInt, DistributedCogdoBarrel, DistCogdoGame, DistCogdoLevelGame, DistCogdoBoardroomGame, DistCogdoCraneGame, DistCogdoMazeGame, DistCogdoFlyingGame, DistCogdoCrane, DistCogdoCraneMoneyBag, DistCogdoCraneCog diff --git a/otp/friends/AvatarFriendsManager.py b/otp/friends/AvatarFriendsManager.py index d0ddabef..2b4db4dd 100644 --- a/otp/friends/AvatarFriendsManager.py +++ b/otp/friends/AvatarFriendsManager.py @@ -1,6 +1,5 @@ from direct.distributed.DistributedObjectGlobal import DistributedObjectGlobal from direct.directnotify.DirectNotifyGlobal import directNotify -from otp.uberdog.RejectCode import RejectCode from otp.otpbase import OTPGlobals from otp.otpbase import OTPLocalizer diff --git a/otp/friends/FriendSecret.py b/otp/friends/FriendSecret.py deleted file mode 100644 index d52d1b02..00000000 --- a/otp/friends/FriendSecret.py +++ /dev/null @@ -1,348 +0,0 @@ -from pandac.PandaModules import * -from direct.gui.DirectGui import * -from direct.directnotify import DirectNotifyGlobal -from direct.fsm import StateData -import string -from otp.otpbase import OTPLocalizer -from otp.otpbase import OTPGlobals -from otp.uberdog import RejectCode -from toontown.nametag import NametagGlobals -globalFriendSecret = None -AccountSecret = 0 -AvatarSecret = 1 -BothSecrets = 2 - -def showFriendSecret(secretType = AvatarSecret): - global globalFriendSecret - if not settings['trueFriends']: - chatMgr = base.localAvatar.chatMgr - chatMgr.fsm.request('noSecretChatAtAll') - else: - openFriendSecret(secretType) - - -def openFriendSecret(secretType): - global globalFriendSecret - if globalFriendSecret != None: - globalFriendSecret.unload() - globalFriendSecret = FriendSecret(secretType) - globalFriendSecret.enter() - return - - -def hideFriendSecret(): - if globalFriendSecret != None: - globalFriendSecret.exit() - return - - -def unloadFriendSecret(): - global globalFriendSecret - if globalFriendSecret != None: - globalFriendSecret.unload() - globalFriendSecret = None - return - -class FriendSecret(DirectFrame, StateData.StateData): - notify = DirectNotifyGlobal.directNotify.newCategory('FriendSecret') - - def __init__(self, secretType): - DirectFrame.__init__(self, parent=aspect2dp, pos=(0, 0, 0.3), relief=None, image=DGG.getDefaultDialogGeom(), image_scale=(1.6, 1, 1.4), image_pos=(0, 0, -0.05), image_color=OTPGlobals.GlobalDialogColor, borderWidth=(0.01, 0.01)) - StateData.StateData.__init__(self, 'friend-secret-done') - self.initialiseoptions(FriendSecret) - self.prefix = OTPGlobals.getDefaultProductPrefix() - self.secretType = secretType - self.notify.debug('### secretType = %s' % self.secretType) - self.requestedSecretType = secretType - self.notify.debug('### requestedSecretType = %s' % self.requestedSecretType) - return - - def unload(self): - if self.isLoaded == 0: - return None - self.isLoaded = 0 - self.exit() - del self.introText - del self.getSecret - del self.enterSecretText - del self.enterSecret - del self.ok1 - del self.ok2 - del self.cancel - del self.secretText - del self.avatarButton - del self.accountButton - DirectFrame.destroy(self) - self.ignore('clientCleanup') - return None - - def load(self): - if self.isLoaded == 1: - return None - self.isLoaded = 1 - self.introText = DirectLabel(parent=self, relief=None, pos=(0, 0, 0.4), scale=0.05, text=OTPLocalizer.FriendSecretIntro, text_fg=(0, 0, 0, 1), text_wordwrap=30) - self.introText.hide() - guiButton = loader.loadModel('phase_3/models/gui/quit_button') - self.getSecret = DirectButton(parent=self, relief=None, pos=(0, 0, -0.11), image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=OTPLocalizer.FSgetSecret, text=OTPLocalizer.FriendSecretGetSecret, text_scale=OTPLocalizer.FSgetSecretButton, text_pos=(0, -0.02), command=self.__determineSecret) - self.getSecret.hide() - self.enterSecretText = DirectLabel(parent=self, relief=None, pos=OTPLocalizer.FSenterSecretTextPos, scale=0.05, text=OTPLocalizer.FriendSecretEnterSecret, text_fg=(0, 0, 0, 1), text_wordwrap=30) - self.enterSecretText.hide() - self.enterSecret = DirectEntry(parent=self, relief=DGG.SUNKEN, scale=0.06, pos=(-0.6, 0, -0.38), frameColor=(0.8, 0.8, 0.5, 1), borderWidth=(0.1, 0.1), numLines=1, width=20, frameSize=(-0.4, - 20.4, - -0.4, - 1.1), command=self.__enterSecret) - self.enterSecret.resetFrameSize() - self.enterSecret.hide() - self.ok1 = DirectButton(parent=self, relief=None, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=OTPLocalizer.FSok1, text=OTPLocalizer.FriendSecretEnter, text_scale=0.06, text_pos=(0, -0.02), pos=(0, 0, -0.5), command=self.__ok1) - self.ok1.hide() - self.ok2 = DirectButton(parent=self, relief=None, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=OTPLocalizer.FSok2, text=OTPLocalizer.FriendSecretOK, text_scale=0.06, text_pos=(0, -0.02), pos=(0, 0, -0.57), command=self.__ok2) - self.ok2.hide() - self.cancel = DirectButton(parent=self, relief=None, text=OTPLocalizer.FriendSecretCancel, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=OTPLocalizer.FScancel, text_scale=0.06, text_pos=(0, -0.02), pos=(0, 0, -0.57), command=self.__cancel) - self.cancel.hide() - self.nextText = DirectLabel(parent=self, relief=None, pos=(0, 0, 0.3), scale=0.06, text='', text_scale=OTPLocalizer.FSnextText, text_fg=(0, 0, 0, 1), text_wordwrap=25.5) - self.nextText.hide() - self.secretText = DirectLabel(parent=self, relief=None, pos=(0, 0, -0.42), scale=0.1, text='', text_fg=(0, 0, 0, 1), text_wordwrap=30) - self.secretText.hide() - guiButton.removeNode() - self.makeFriendTypeButtons() - self.accept('clientCleanup', self.__handleCleanup) - self.accept('walkDone', self.__handleStop) - - def __handleStop(self, message): - self.exit() - - def __handleCleanup(self): - self.unload() - - def makeFriendTypeButtons(self): - buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui') - self.avatarButton = DirectButton(self, image=(buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')), relief=None, text=OTPLocalizer.FriendSecretDetermineSecretAvatar, text_scale=0.07, text_pos=(0.0, -0.1), pos=(-0.35, 0.0, -0.05), command=self.__handleAvatar) - avatarText = DirectLabel(parent=self, relief=None, pos=Vec3(0.35, 0, -0.3), text=OTPLocalizer.FriendSecretDetermineSecretAvatarRollover, text_fg=(0, 0, 0, 1), text_pos=(0, 0), text_scale=0.055, text_align=TextNode.ACenter) - avatarText.reparentTo(self.avatarButton.stateNodePath[2]) - self.avatarButton.hide() - self.accountButton = DirectButton(self, image=(buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')), relief=None, text=OTPLocalizer.FriendSecretDetermineSecretAccount, text_scale=0.07, text_pos=(0.0, -0.1), pos=(0.35, 0.0, -0.05), command=self.__handleAccount) - accountText = DirectLabel(parent=self, relief=None, pos=Vec3(-0.35, 0, -0.3), text=OTPLocalizer.FriendSecretDetermineSecretAccountRollover, text_fg=(0, 0, 0, 1), text_pos=(0, 0), text_scale=0.055, text_align=TextNode.ACenter) - accountText.reparentTo(self.accountButton.stateNodePath[2]) - self.accountButton.hide() - buttons.removeNode() - return - - def enter(self): - if self.isEntered == 1: - return - self.isEntered = 1 - if self.isLoaded == 0: - self.load() - self.show() - self.introText.show() - self.getSecret.show() - self.enterSecretText.show() - self.enterSecret.show() - self.ok1.show() - self.ok2.hide() - self.cancel.hide() - self.nextText.hide() - self.secretText.hide() - base.localAvatar.chatMgr.fsm.request('otherDialog') - self.enterSecret['focus'] = 1 - NametagGlobals.setForceOnscreenChat(True) - - def exit(self): - if self.isEntered == 0: - return - self.isEntered = 0 - NametagGlobals.setForceOnscreenChat(False) - self.__cleanupFirstPage() - self.ignoreAll() - self.accept('clientCleanup', self.unload) - self.hide() - - def __determineSecret(self): - if self.secretType == BothSecrets: - self.__cleanupFirstPage() - self.ok1.hide() - self.nextText['text'] = OTPLocalizer.FriendSecretDetermineSecret - self.nextText.setPos(0, 0, 0.3) - self.nextText.show() - self.avatarButton.show() - self.accountButton.show() - self.cancel.show() - else: - self.__getSecret() - - def __handleAvatar(self): - self.requestedSecretType = AvatarSecret - self.__getSecret() - - def __handleAccount(self): - self.requestedSecretType = AccountSecret - self.__getSecret() - - def __handleCancel(self): - self.exit() - - def __getSecret(self): - self.__cleanupFirstPage() - self.nextText['text'] = OTPLocalizer.FriendSecretGettingSecret - self.nextText.setPos(0, 0, 0.3) - self.nextText.show() - self.avatarButton.hide() - self.accountButton.hide() - self.ok1.hide() - self.cancel.show() - if self.requestedSecretType == AvatarSecret: - if not base.cr.friendManager: - self.notify.warning('No FriendManager available.') - self.exit() - return - base.cr.ttuFriendsManager.d_requestSecret() - self.accept('requestSecretResponse', self.__gotAvatarSecret) - else: - base.cr.playerFriendsManager.sendRequestUnlimitedSecret() - self.accept(OTPGlobals.PlayerFriendNewSecretEvent, self.__gotAccountSecret) - self.accept(OTPGlobals.PlayerFriendRejectNewSecretEvent, self.__rejectAccountSecret) - - def __gotAvatarSecret(self, result, secret): - self.ignore('requestSecretResponse') - if result == 1: - self.nextText['text'] = OTPLocalizer.FriendSecretGotSecret - self.nextText.setPos(*OTPLocalizer.FSgotSecretPos) - if self.prefix: - self.secretText['text'] = self.prefix + ' ' + secret - else: - self.secretText['text'] = secret - else: - self.nextText['text'] = OTPLocalizer.FriendSecretTooMany - self.nextText.show() - self.secretText.show() - self.cancel.hide() - self.ok1.hide() - self.ok2.show() - - def __gotAccountSecret(self, secret): - self.ignore(OTPGlobals.PlayerFriendNewSecretEvent) - self.ignore(OTPGlobals.PlayerFriendRejectNewSecretEvent) - self.nextText['text'] = OTPLocalizer.FriendSecretGotSecret - self.nextText.setPos(0, 0, 0.47) - self.secretText['text'] = secret - self.nextText.show() - self.secretText.show() - self.cancel.hide() - self.ok1.hide() - self.ok2.show() - - def __rejectAccountSecret(self, reason): - print '## rejectAccountSecret: reason = ', reason - self.ignore(OTPGlobals.PlayerFriendNewSecretEvent) - self.ignore(OTPGlobals.PlayerFriendRejectNewSecretEvent) - self.nextText['text'] = OTPLocalizer.FriendSecretTooMany - self.nextText.show() - self.secretText.show() - self.cancel.hide() - self.ok1.hide() - self.ok2.show() - - def __enterSecret(self, secret): - self.enterSecret.set('') - secret = secret.strip() - if not secret: - self.exit() - return - if not base.cr.friendManager: - self.notify.warning('No FriendManager available.') - self.exit() - return - self.__cleanupFirstPage() - if self.prefix: - if secret[0:2] == self.prefix: - secret = secret[3:] - self.notify.info('### use TT secret') - self.accept('submitSecretResponse', self.__enteredSecret) - base.cr.ttuFriendsManager.d_submitSecret(secret) - else: - self.accept(OTPGlobals.PlayerFriendUpdateEvent, self.__useAccountSecret) - self.accept(OTPGlobals.PlayerFriendRejectUseSecretEvent, self.__rejectUseAccountSecret) - base.cr.playerFriendsManager.sendRequestUseUnlimitedSecret(secret) - self.nextText['text'] = OTPLocalizer.FriendSecretTryingSecret - self.nextText.setPos(0, 0, 0.3) - self.nextText.show() - self.ok1.hide() - self.cancel.show() - - def __enteredSecret(self, result, avId): - self.ignore('submitSecretResponse') - if result == 1: - handle = base.cr.identifyAvatar(avId) - if handle != None: - self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretSuccess % handle.getName() - else: - self.accept('friendsMapComplete', self.__nowFriends, [avId]) - ready = base.cr.fillUpFriendsMap() - if ready: - self.__nowFriends(avId) - return - elif result == 0: - self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretUnknown - elif result == 2: - handle = base.cr.identifyAvatar(avId) - if handle != None: - self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretFull % handle.getName() - else: - self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretFullNoName - elif result == 3: - self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretSelf - elif result == 4: - self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretWrongProduct % self.prefix - elif result == 5: - self.nextText['text'] = OTPLocalizer.FriendSecretNotImplemented - self.nextText.show() - self.cancel.hide() - self.ok1.hide() - self.ok2.show() - return - - def __useAccountSecret(self, avId, friendInfo): - self.ignore(OTPGlobals.PlayerFriendUpdateEvent) - self.ignore(OTPGlobals.PlayerFriendRejectUseSecretEvent) - self.__enteredSecret(1, 0) - - def __rejectUseAccountSecret(self, reason): - print '## rejectUseAccountSecret: reason = ', reason - self.ignore(OTPGlobals.PlayerFriendUpdateEvent) - self.ignore(OTPGlobals.PlayerFriendRejectUseSecretEvent) - if reason == RejectCode.RejectCode.FRIENDS_LIST_FULL: - self.__enteredSecret(2, 0) - elif reason == RejectCode.RejectCode.ALREADY_FRIENDS_WITH_SELF: - self.__enteredSecret(3, 0) - else: - self.__enteredSecret(0, 0) - - def __nowFriends(self, avId): - self.ignore('friendsMapComplete') - handle = base.cr.identifyAvatar(avId) - if handle != None: - self.nextText['text'] = OTPLocalizer.FriendSecretNowFriends % handle.getName() - else: - self.nextText['text'] = OTPLocalizer.FriendSecretNowFriendsNoName - self.nextText.show() - self.cancel.hide() - self.ok1.hide() - self.ok2.show() - return - - def __ok1(self): - secret = self.enterSecret.get() - self.__enterSecret(secret) - - def __ok2(self): - self.exit() - - def __cancel(self): - self.exit() - - def __cleanupFirstPage(self): - self.introText.hide() - self.getSecret.hide() - self.enterSecretText.hide() - self.enterSecret.hide() - base.localAvatar.chatMgr.fsm.request('mainMenu') diff --git a/otp/otpbase/OTPLocalizerEnglish.py b/otp/otpbase/OTPLocalizerEnglish.py index d422bb8d..d7e1c5b7 100644 --- a/otp/otpbase/OTPLocalizerEnglish.py +++ b/otp/otpbase/OTPLocalizerEnglish.py @@ -215,31 +215,6 @@ SCMenuSellbotInvasion = 'SELLBOT INVASION' SCMenuFieldOffice = 'FIELD OFFICES' SCMenuIdesOfMarch = 'GREEN' ScMenuBugs = 'Bugs' -FriendSecretIntro = "If you are playing Toontown United with someone you know in the real world, you can become True Friends. You can chat using the keyboard with your True Friends. Other Toons won't understand what you're saying.\n\nYou do this by getting a True Friend Code. Tell the True Friend Code to your friend, but not to anyone else. When your friend types in your True Friend Code on his or her screen, you'll be True Friends in Toontown!" -FriendSecretGetSecret = 'Get a True Friend Code' -FriendSecretEnterSecret = 'If you have a True Friend Code from someone you know, type it here.' -FriendSecretOK = lOK -FriendSecretEnter = 'Enter True Friend Code' -FriendSecretCancel = lCancel -FriendSecretGettingSecret = 'Getting True Friend Code. . .' -FriendSecretGotSecret = "Here is your new True Friend Code. Be sure to write it down!\n\nYou may give this True Friend Code to one person only. Once someone types in your True Friend Code, it will not work for anyone else. If you want to give a True Friend Code to more than one person, get another True Friend Code.\n\nThe True Friend Code will only work for the next two days. Your friend will have to type it in before it goes away, or it won't work.\n\nYour True Friend Code is:" -FriendSecretTooMany = "Sorry, you can't have any more True Friend Codes today. You've already had more than your fair share!\n\nTry again tomorrow." -FriendSecretTryingSecret = 'Trying True Friend Code. . .' -FriendSecretNotImplemented = 'True Friends has not been implemented yet!' -FriendSecretEnteredSecretSuccess = 'You are now True Friends with %s!' -FriendSecretTimeOut = 'Sorry, secrets are not working right now.' -FriendSecretEnteredSecretUnknown = "That's not anyone's True Friend Code. Are you sure you spelled it correctly?\n\nIf you did type it correctly, it may have expired. Ask your friend to get a new True Friend Code for you (or get a new one yourself and give it to your friend)." -FriendSecretEnteredSecretFull = "You can't be friends with %s because one of you has too many friends on your friends list." -FriendSecretEnteredSecretFullNoName = "You can't be friends because one of you has too many friends on your friends list." -FriendSecretEnteredSecretSelf = 'You just typed in your own True Friend Code! Now no one else can use that True Friend Code.' -FriendSecretEnteredSecretWrongProduct = "You have entered the wrong type of True Friend Code.\nThis game uses codes that begin with '%s'." -FriendSecretNowFriends = 'You are now True Friends with %s!' -FriendSecretNowFriendsNoName = 'You are now True Friends!' -FriendSecretDetermineSecret = 'What type of True Friend would you like to make?' -FriendSecretDetermineSecretAvatar = 'Avatar' -FriendSecretDetermineSecretAvatarRollover = 'A friend only in this game' -FriendSecretDetermineSecretAccount = 'Account' -FriendSecretDetermineSecretAccountRollover = 'A friend across the Toontown United network' GuildMemberTitle = 'Member Options' GuildMemberPromote = 'Make Officer' GuildMemberPromoteInvite = 'Make Veteran' diff --git a/otp/otpbase/OTPLocalizerEnglishProperty.py b/otp/otpbase/OTPLocalizerEnglishProperty.py index 72c7f446..65cdcc67 100644 --- a/otp/otpbase/OTPLocalizerEnglishProperty.py +++ b/otp/otpbase/OTPLocalizerEnglishProperty.py @@ -1,11 +1,3 @@ -FSenterSecretTextPos = (0, 0, -0.25) -FSgotSecretPos = (0, 0, 0.47) -FSgetSecretButton = 0.06 -FSnextText = 1.0 -FSgetSecret = (1.55, 1, 1) -FSok1 = (1.55, 1, 1) -FSok2 = (0.6, 1, 1) -FScancel = (0.6, 1, 1) LTPDdirectButtonYesText = 0.05 LTPDdirectButtonNoText = 0.05 LTPDdirectFrameText = 0.06 diff --git a/toontown/ai/ToontownAIRepository.py b/toontown/ai/ToontownAIRepository.py index e4d77978..72df72da 100644 --- a/toontown/ai/ToontownAIRepository.py +++ b/toontown/ai/ToontownAIRepository.py @@ -30,6 +30,7 @@ from toontown.distributed.ToontownInternalRepository import ToontownInternalRepo from toontown.coderedemption.TTCodeRedemptionMgrAI import TTCodeRedemptionMgrAI from toontown.dna.DNAParser import loadDNAFileAI from toontown.estate.EstateManagerAI import EstateManagerAI +from toontown.friends.TrueFriendsMgrAI import TrueFriendsMgrAI from toontown.hood import BRHoodAI from toontown.hood import BossbotHQAI from toontown.hood import CashbotHQAI @@ -126,6 +127,8 @@ class ToontownAIRepository(ToontownInternalRepository): self.buildingQueryMgr = DistributedBuildingQueryMgrAI(self) self.buildingQueryMgr.generateWithRequired(2) self.groupManager.generateWithRequired(2) + self.trueFriendsMgr = TrueFriendsMgrAI(self) + self.trueFriendsMgr.generateWithRequired(2) if self.wantFishing: self.fishManager = FishManagerAI(self) if self.wantHousing: diff --git a/toontown/friends/FriendsListPanel.py b/toontown/friends/FriendsListPanel.py index 4daecd58..f251befa 100644 --- a/toontown/friends/FriendsListPanel.py +++ b/toontown/friends/FriendsListPanel.py @@ -317,7 +317,7 @@ class FriendsListPanel(DirectFrame, StateData.StateData): def __secrets(self): messenger.send('wakeup') - ToontownFriendSecret.showFriendSecret(ToontownFriendSecret.AvatarSecret) + ToontownFriendSecret.showFriendSecret() def __newFriend(self): messenger.send('wakeup') diff --git a/toontown/friends/ToontownFriendSecret.py b/toontown/friends/ToontownFriendSecret.py index 647ab7f8..de74719d 100644 --- a/toontown/friends/ToontownFriendSecret.py +++ b/toontown/friends/ToontownFriendSecret.py @@ -1,58 +1,193 @@ from pandac.PandaModules import * from direct.gui.DirectGui import * from direct.directnotify import DirectNotifyGlobal -from otp.otpbase import OTPLocalizer from toontown.toonbase import TTLocalizer -from otp.friends.FriendSecret import AccountSecret -from otp.friends.FriendSecret import AvatarSecret -from otp.friends.FriendSecret import BothSecrets -from otp.friends import FriendSecret -from otp.friends.FriendSecret import globalFriendSecret -from otp.friends.FriendSecret import showFriendSecret -from otp.friends.FriendSecret import hideFriendSecret -from otp.friends.FriendSecret import unloadFriendSecret +from otp.otpbase import OTPGlobals +from toontown.nametag import NametagGlobals -def openFriendSecret(secretType): +globalFriendSecret = None + +def showFriendSecret(): + global globalFriendSecret + if not settings['trueFriends']: + chatMgr = base.localAvatar.chatMgr + chatMgr.fsm.request('noSecretChatAtAll') + else: + if globalFriendSecret != None: + globalFriendSecret.unload() + globalFriendSecret = ToontownFriendSecret() + globalFriendSecret.enter() + +def hideFriendSecret(): + if globalFriendSecret != None: + globalFriendSecret.exit() + +def unloadFriendSecret(): global globalFriendSecret if globalFriendSecret != None: globalFriendSecret.unload() - globalFriendSecret = ToontownFriendSecret(secretType) - globalFriendSecret.enter() + globalFriendSecret = None return - -FriendSecret.openFriendSecret = openFriendSecret - -class ToontownFriendSecret(FriendSecret.FriendSecret): +class ToontownFriendSecret(DirectFrame): notify = DirectNotifyGlobal.directNotify.newCategory('ToontownFriendSecret') - def __init__(self, secretType): - FriendSecret.FriendSecret.__init__(self, secretType) + def __init__(self): + DirectFrame.__init__(self, parent=aspect2dp, pos=(0, 0, 0.3), relief=None, image=DGG.getDefaultDialogGeom(), image_scale=(1.6, 1, 1.4), image_pos=(0, 0, -0.05), image_color=OTPGlobals.GlobalDialogColor, borderWidth=(0.01, 0.01)) self.initialiseoptions(ToontownFriendSecret) - def makeFriendTypeButtons(self): - buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui') - self.avatarButton = DirectButton(parent=self, image=(buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')), relief=None, text=TTLocalizer.FriendInviterToon, text_scale=0.07, text_pos=(0.0, -0.1), pos=(-0.35, 0.0, -0.05), command=self._FriendSecret__handleAvatar) - avatarText = DirectLabel(parent=self, relief=None, pos=Vec3(0.35, 0, -0.3), text=TTLocalizer.FriendInviterToonFriendInfo, text_fg=(0, 0, 0, 1), text_pos=(0, 0), text_scale=0.055, text_align=TextNode.ACenter) - avatarText.reparentTo(self.avatarButton.stateNodePath[2]) - self.avatarButton.hide() - self.accountButton = DirectButton(parent=self, image=(buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')), relief=None, text=TTLocalizer.FriendInviterPlayer, text_scale=0.07, text_pos=(0.0, -0.1), pos=(0.35, 0.0, -0.05), command=self._FriendSecret__handleAccount) - accountText = DirectLabel(parent=self, relief=None, pos=Vec3(-0.35, 0, -0.3), text=TTLocalizer.FriendInviterPlayerFriendInfo, text_fg=(0, 0, 0, 1), text_pos=(0, 0), text_scale=0.055, text_align=TextNode.ACenter) - accountText.reparentTo(self.accountButton.stateNodePath[2]) - self.accountButton.hide() - buttons.removeNode() - return + def unload(self): + if self.isLoaded == 0: + return None + self.isLoaded = 0 + self.exit() + del self.introText + del self.getSecret + del self.enterSecretText + del self.enterSecret + del self.ok1 + del self.ok2 + del self.cancel + del self.secretText + DirectFrame.destroy(self) + return None - def __determineSecret(self): - if self.secretType == BothSecrets: - self._FriendSecret__cleanupFirstPage() - self.ok1.hide() - self.changeOptions.hide() - self.nextText['text'] = TTLocalizer.FriendInviterBegin - self.nextText.setPos(0, 0, 0.3) - self.nextText.show() - self.avatarButton.show() - self.accountButton.show() - self.cancel.show() - else: - self._FriendSecret__getSecret() + def load(self): + if self.isLoaded == 1: + return None + self.isLoaded = 1 + self.introText = DirectLabel(parent=self, relief=None, pos=(0, 0, 0.4), scale=0.05, text=TTLocalizer.FriendSecretIntro, text_fg=(0, 0, 0, 1), text_wordwrap=30) + self.introText.hide() + guiButton = loader.loadModel('phase_3/models/gui/quit_button') + self.getSecret = DirectButton(parent=self, relief=None, pos=(0, 0, -0.11), image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=TTLocalizer.FSgetSecret, text=TTLocalizer.FriendSecretGetSecret, text_scale=TTLocalizer.FSgetSecretButton, text_pos=(0, -0.02), command=self.getSecret) + self.getSecret.hide() + self.enterSecretText = DirectLabel(parent=self, relief=None, pos=TTLocalizer.FSenterSecretTextPos, scale=0.05, text=TTLocalizer.FriendSecretEnterSecret, text_fg=(0, 0, 0, 1), text_wordwrap=30) + self.enterSecretText.hide() + self.enterSecret = DirectEntry(parent=self, relief=DGG.SUNKEN, scale=0.06, pos=(-0.6, 0, -0.38), frameColor=(0.8, 0.8, 0.5, 1), borderWidth=(0.1, 0.1), numLines=1, width=20, frameSize=(-0.4, + 20.4, + -0.4, + 1.1), command=self.__enterSecret) + self.enterSecret.resetFrameSize() + self.enterSecret.hide() + self.ok1 = DirectButton(parent=self, relief=None, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=TTLocalizer.FSok1, text=TTLocalizer.FriendSecretEnter, text_scale=0.06, text_pos=(0, -0.02), pos=(0, 0, -0.5), command=self.__ok1) + self.ok1.hide() + self.ok2 = DirectButton(parent=self, relief=None, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=TTLocalizer.FSok2, text=TTLocalizer.FriendSecretOK, text_scale=0.06, text_pos=(0, -0.02), pos=(0, 0, -0.57), command=self.__ok2) + self.ok2.hide() + self.cancel = DirectButton(parent=self, relief=None, text=TTLocalizer.FriendSecretCancel, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=TTLocalizer.FScancel, text_scale=0.06, text_pos=(0, -0.02), pos=(0, 0, -0.57), command=self.__cancel) + self.cancel.hide() + self.nextText = DirectLabel(parent=self, relief=None, pos=(0, 0, 0.3), scale=0.06, text='', text_scale=TTLocalizer.FSnextText, text_fg=(0, 0, 0, 1), text_wordwrap=25.5) + self.nextText.hide() + self.secretText = DirectLabel(parent=self, relief=None, pos=(0, 0, -0.42), scale=0.1, text='', text_fg=(0, 0, 0, 1), text_wordwrap=30) + self.secretText.hide() + guiButton.removeNode() + + def enter(self): + if self.isEntered == 1: + return + self.isEntered = 1 + if self.isLoaded == 0: + self.load() + self.show() + self.introText.show() + self.getSecret.show() + self.enterSecretText.show() + self.enterSecret.show() + self.ok1.show() + self.ok2.hide() + self.cancel.hide() + self.nextText.hide() + self.secretText.hide() + base.localAvatar.chatMgr.fsm.request('otherDialog') + self.enterSecret['focus'] = 1 + NametagGlobals.setForceOnscreenChat(True) + + def exit(self): + if self.isEntered == 0: + return + self.isEntered = 0 + NametagGlobals.setForceOnscreenChat(False) + self.__cleanupFirstPage() + self.hide() + + def __getSecret(self): + self.__cleanupFirstPage() + self.nextText['text'] = TTLocalizer.FriendSecretGettingSecret + self.nextText.setPos(0, 0, 0.3) + self.nextText.show() + self.ok1.hide() + self.cancel.show() + base.cr.trueFriendsMgr.requestId(self.gotSecret) + + def gotSecret(self, id, result1, result2): + if id == 0: + self.rejectGetSecret(TTLocalizer.FriendSecretNoServer) + elif id == 1: + self.rejectGetSecret(TTLocalizer.FriendSecretNoServerResponse if result1 is None else result1) + elif id == 2: + self.successGetSecret(result1, result2) + + def rejectGetSecret(self, reason): + self.nextText['text'] = reason + self.nextText.show() + self.secretText.show() + self.cancel.hide() + self.ok1.hide() + self.ok2.show() + + def successGetSecret(self, secret, expires): + self.nextText['text'] = TTLocalizer.FriendSecretGotSecret % expires + self.nextText.setPos(*TTLocalizer.FSgotSecretPos) + self.secretText['text'] = secret + self.nextText.show() + self.secretText.show() + self.cancel.hide() + self.ok1.hide() + self.ok2.show() + + def __enterSecret(self, secret): + self.enterSecret.set('') + secret = secret.strip() + + if not secret: + self.exit() + return + + base.cr.trueFriendsMgr.redeemId(secret, self.gotResponse) + self.nextText['text'] = TTLocalizer.FriendSecretTryingSecret + self.nextText.setPos(0, 0, 0.3) + self.nextText.show() + self.ok1.hide() + self.cancel.show() + + def gotResponse(self, id, name): + if id == 0: + self.nextText['text'] = TTLocalizer.FriendSecretNoServer + elif id == 1: + self.nextText['text'] = TTLocalizer.FriendSecretNoServerResponse if result1 is None else result1 + elif id == 2: + self.nextText['text'] = TTLocalizer.FriendSecretEnteredCodeSelf + elif id == 3: + self.nextText['text'] = TTLocalizer.FriendSecretAlreadyTrueFriend + elif id == 4: + self.nextText['text'] = TTLocalizer.FriendSecretSuccess % name + self.nextText.show() + self.cancel.hide() + self.ok1.hide() + self.ok2.show() + + def __ok1(self): + secret = self.enterSecret.get() + self.__enterSecret(secret) + + def __ok2(self): + self.exit() + + def __cancel(self): + self.exit() + + def __cleanupFirstPage(self): + self.introText.hide() + self.getSecret.hide() + self.enterSecretText.hide() + self.enterSecret.hide() + base.localAvatar.chatMgr.fsm.request('mainMenu') diff --git a/toontown/friends/TrueFriendsMgr.py b/toontown/friends/TrueFriendsMgr.py new file mode 100644 index 00000000..aeafa92f --- /dev/null +++ b/toontown/friends/TrueFriendsMgr.py @@ -0,0 +1,34 @@ +from direct.distributed.DistributedObject import DistributedObject +from direct.directnotify.DirectNotifyGlobal import directNotify + +class TrueFriendsMgr(DistributedObject): + neverDisable = 1 + notify = directNotify.newCategory('TrueFriendsMgr') + + def __init__(self, cr): + DistributedObject.__init__(self, cr) + self.requestCallback = None + self.redeemCallback = None + + def announceGenerate(self): + DistributedObject.announceGenerate(self) + base.cr.trueFriendsMgr = self + + def delete(self): + if hasattr(base.cr, 'trueFriendsMgr'): + del base.cr.trueFriendsMgr + DistributedObject.delete(self) + + def requestId(self, callback): + self.requestCallback = callback + self.sendUpdate('requestId') + + def redeemId(self, id, callback): + self.redeemCallback = callback + self.sendUpdate('redeemId', [id]) + + def requestIdResult(self, id, result1, result2): + self.requestCallback(id, result1, result2) + + def redeemIdResult(self, id, name): + self.redeemCallback(id, name) \ No newline at end of file diff --git a/toontown/friends/TrueFriendsMgrAI.py b/toontown/friends/TrueFriendsMgrAI.py new file mode 100644 index 00000000..fc6e3eec --- /dev/null +++ b/toontown/friends/TrueFriendsMgrAI.py @@ -0,0 +1,90 @@ +from direct.directnotify import DirectNotifyGlobal +from direct.distributed.DistributedObjectAI import DistributedObjectAI +from toontown.uberdog.ClientServiceManagerUD import executeHttpRequestAndLog + +class TrueFriendsMgrAI(DistributedObjectAI): + notify = DirectNotifyGlobal.directNotify.newCategory("TrueFriendsMgrAI") + + def announceGenerate(self): + DistributedObjectAI.announceGenerate(self) + + def requestId(self): + avId = self.air.getAvatarIdFromSender() + av = self.air.doId2do.get(avId) + + if not av: + return + + if simbase.config.GetString('accountdb-type', 'developer') != 'remote': + self.sendUpdateToAvatarId(avId, 'requestIdResult', [0, None, None]) + return + + result = executeHttpRequestAndLog('truefriend', avid=avId) + + if result is None: + self.sendUpdateToAvatarId(avId, 'requestIdResult', [1, None, None]) + return + elif 'error' in result: + self.sendUpdateToAvatarId(avId, 'requestIdResult', [1, result['error'], None]) + return + + self.sendUpdateToAvatarId(avId, 'requestIdResult', [2, result['id'], result['expires']]) + + def redeemId(self, id): + avId = self.air.getAvatarIdFromSender() + av = self.air.doId2do.get(avId) + + if not av: + return + + if simbase.config.GetString('accountdb-type', 'developer') != 'remote': + self.sendUpdateToAvatarId(avId, 'redeemIdResult', [0, None]) + return + + result = executeHttpRequestAndLog('truefriend', id=id) + + if result is None: + self.sendUpdateToAvatarId(avId, 'redeemIdResult', [1, None]) + return + elif 'error' in result: + self.sendUpdateToAvatarId(avId, 'redeemIdResult', [1, result['error']]) + return + + targetId = int(result['avId']) + + if targetId == avId: + self.sendUpdateToAvatarId(avId, 'redeemIdResult', [2, None]) + return + elif av.isTrueFriend(targetId): + self.sendUpdateToAvatarId(avId, 'redeemIdResult', [3, None]) + return + + av.addTrueFriend(targetId) + target = self.air.doId2do.get(targetId) + + if target: + target.addTrueFriend(avId) + self.sendUpdateToAvatarId(avId, 'redeemIdResult', [4, target.getName()]) + else: + TrueFriendsOperation(targetId, avId) + +class TrueFriendsOperation: + + def __init__(self, targetId, avId): + self.targetId = targetId + self.avId = avId + simbase.air.dbInterface.queryObject(simbase.air.dbId, self.targetId, self.gotResponse) + + def gotResponse(self, dclass, fields): + if dclass != simbase.air.dclassesByName['DistributedToonAI'] or not 'setName' in fields: + return + + trueFriends = fields['setTrueFriends'] + + if self.avId in trueFriends: + self.sendUpdateToAvatarId(self.avId, 'redeemIdResult', [3, None]) + return + + trueFriends.append(self.avId) + simbase.air.dbInterface.updateObject(simbase.air.dbId, self.targetId, simbase.air.dclassesByName['DistributedToonAI'], {'setTrueFriends': [trueFriends]}) + self.sendUpdateToAvatarId(self.avId, 'redeemIdResult', [4, fields['setName']]) \ No newline at end of file diff --git a/toontown/toon/DistributedToonAI.py b/toontown/toon/DistributedToonAI.py index 2b70066a..7bdb2e0d 100644 --- a/toontown/toon/DistributedToonAI.py +++ b/toontown/toon/DistributedToonAI.py @@ -463,6 +463,11 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo def isTrueFriend(self, doId): return doId in self.trueFriends + + def addTrueFriend(self, doId): + if not isTrueFriend(doId): + self.trueFriends.append(doId) + self.d_setTrueFriends(self.trueFriends) def b_setInventory(self, inventory): self.setInventory(inventory) diff --git a/toontown/toon/ToonAvatarPanel.py b/toontown/toon/ToonAvatarPanel.py index a70d43f8..d3be8bed 100644 --- a/toontown/toon/ToonAvatarPanel.py +++ b/toontown/toon/ToonAvatarPanel.py @@ -395,7 +395,7 @@ class ToonAvatarPanel(AvatarPanelBase.AvatarPanelBase): def __handleSecrets(self): base.localAvatar.chatMgr.noWhisper() - ToontownFriendSecret.showFriendSecret(ToontownFriendSecret.AvatarSecret) + ToontownFriendSecret.showFriendSecret() def __handleFriend(self): base.localAvatar.chatMgr.noWhisper() diff --git a/toontown/toonbase/TTLocalizerEnglish.py b/toontown/toonbase/TTLocalizerEnglish.py index 402cb554..8b810113 100644 --- a/toontown/toonbase/TTLocalizerEnglish.py +++ b/toontown/toonbase/TTLocalizerEnglish.py @@ -8979,9 +8979,22 @@ LanguageSelectorConfirm = 'Are you sure you want to change your language to %s? LanguageSelectorSameLanguage = "You're already using that language!" PickTrackTitle = 'Pick your third track!' PickTrackNotice = 'Choose a track!' -UnknownTrack = 'None' CogLevelLabelOn = 'The cog level GUI is on.' CogLevelLabelOff = 'The cog level GUI is off.' +FriendSecretIntro = "If you are playing Toontown United with someone you know in the real world, you can become True Friends. You can chat using the keyboard with your True Friends. Other Toons won't understand what you're saying.\n\nYou do this by getting a True Friend Code. Tell the True Friend Code to your friend, but not to anyone else. When your friend types in your True Friend Code on his or her screen, you'll be True Friends in Toontown!" +FriendSecretGetSecret = 'Get a True Friend Code' +FriendSecretEnterSecret = 'If you have a True Friend Code from someone you know, type it here.' +FriendSecretOK = lOK +FriendSecretEnter = 'Enter True Friend Code' +FriendSecretCancel = lCancel +FriendSecretGettingSecret = 'Getting True Friend Code...' +FriendSecretGotSecret = "Here is your new True Friend Code. Be sure to write it down!\n\nYou may give this True Friend Code to one person only. Once someone types in your True Friend Code, it will not work for anyone else. If you want to give a True Friend Code to more than one person, get another True Friend Code.\n\nThe True Friend Code will only work until %s. Your friend will have to type it in before it goes away, or it won't work.\n\nYour True Friend Code is:" +FriendSecretTryingSecret = 'Trying True Friend Code. . .' +FriendSecretNoServer = 'True Friends is not set up on this server!' +FriendSecretNoServerResponse = "Couldn't contact the True Friends server!" +FriendSecretEnteredCodeSelf = 'You just typed in your own True Friend Code! Now no one else can use that True Friend Code.' +FriendSecretAlreadyTrueFriend = 'You are True Friends with that toon already!' +FriendSecretSuccess = 'Congratulations! You are now True Friends with %s!' HouseNames = ("Bungalow", "Tiki", "Teepee", "Castle", "Cupcake", "Cabin") CatalogPurchaseHouseType = "When you buy a new house type, the current one is replaced by it. To recover the old type, you'll need to buy it back. Continue?" diff --git a/toontown/toonbase/TTLocalizerEnglishProperty.py b/toontown/toonbase/TTLocalizerEnglishProperty.py index 58418be6..266bdf9f 100644 --- a/toontown/toonbase/TTLocalizerEnglishProperty.py +++ b/toontown/toonbase/TTLocalizerEnglishProperty.py @@ -296,6 +296,14 @@ TPhaveFun = 0.1 TPjoinUs = 0.1 TBSOSPSPenter = 0.1 TexitButton = 0.8 +FSenterSecretTextPos = (0, 0, -0.25) +FSgotSecretPos = (0, 0, 0.47) +FSgetSecretButton = 0.06 +FSnextText = 1.0 +FSgetSecret = (1.55, 1, 1) +FSok1 = (1.55, 1, 1) +FSok2 = (0.6, 1, 1) +FScancel = (0.6, 1, 1) #Some languages need to change the word order SellbotFactoryPosPart1 = (0, -0.25) SellbotFactoryScalePart1 = 0.075 diff --git a/toontown/uberdog/ClientServicesManagerUD.py b/toontown/uberdog/ClientServicesManagerUD.py index 3a333d82..62bcf54d 100644 --- a/toontown/uberdog/ClientServicesManagerUD.py +++ b/toontown/uberdog/ClientServicesManagerUD.py @@ -65,7 +65,6 @@ def executeHttpRequestAndLog(url, **extras): if 'error' in data: notify.warning('Error from ' + url + ':' + data['error']) - return None return data @@ -178,7 +177,7 @@ class RemoteAccountDB(AccountDB): cookie = executeHttpRequestAndLog('cookie', cookie=token) - if cookie is None: + if cookie is None or 'error' in cookie: response = { 'success': False, 'reason': "Couldn't contact login server."