diff --git a/dependencies/astron/dclass/stride.dc b/dependencies/astron/dclass/stride.dc index bc053e3c..881681f1 100644 --- a/dependencies/astron/dclass/stride.dc +++ b/dependencies/astron/dclass/stride.dc @@ -3202,7 +3202,7 @@ dclass TTSFriendsManager : DistributedObjectGlobal { goingOffline(uint32 avId); getAvatarDetails(uint32) clsend; - friendDetails(uint32, blob, uint16[], int16, int16, uint32, uint32, blob, blob, int8[]); + friendDetails(uint32, blob, uint16[], int16, int16, uint32, uint32, blob, blob, int8[], FriendEntry[]); getPetDetails(uint32) clsend; petDetails(uint32, uint32, string, uint32, uint32, uint16/1000[], PetTrait[], int8[], uint32); diff --git a/toontown/battle/SuitBattleGlobals.py b/toontown/battle/SuitBattleGlobals.py index 36c9cdb3..df0c9b73 100755 --- a/toontown/battle/SuitBattleGlobals.py +++ b/toontown/battle/SuitBattleGlobals.py @@ -3170,3 +3170,18 @@ def getAttackTaunt(attackName, index = None): SuitAttackTaunts = TTLocalizer.SuitAttackTaunts +DisabledAttacks = ('Gavel', 'SongAndDance', 'SandTrap', 'FloodTheMarket', 'FiveOClockShadow') + +def getAttacksByType(attributes): + groupAttacks = [] + singleAttacks = [] + + for attack in sorted(attributes['attacks'], key=lambda x: x[0]): + if attack[0] in DisabledAttacks: + continue + if SuitAttacks[attack[0]][1] == ATK_TGT_GROUP: + groupAttacks.append(attack) + else: + singleAttacks.append(attack) + + return groupAttacks, singleAttacks \ No newline at end of file diff --git a/toontown/friends/TTSFriendsManager.py b/toontown/friends/TTSFriendsManager.py index 0366fec4..5349865f 100755 --- a/toontown/friends/TTSFriendsManager.py +++ b/toontown/friends/TTSFriendsManager.py @@ -27,7 +27,7 @@ class TTSFriendsManager(DistributedObjectGlobal): def d_getAvatarDetails(self, avId): self.sendUpdate('getAvatarDetails', [avId]) - def friendDetails(self, avId, inventory, trackAccess, hp, maxHp, defaultShard, lastHood, dnaString, experience, trackBonusLevel): + def friendDetails(self, avId, inventory, trackAccess, hp, maxHp, defaultShard, lastHood, dnaString, experience, trackBonusLevel, npcFriends): fields = [ ['setExperience' , experience], ['setTrackAccess' , trackAccess], @@ -38,6 +38,7 @@ class TTSFriendsManager(DistributedObjectGlobal): ['setDefaultShard' , defaultShard], ['setLastHood' , lastHood], ['setDNAString' , dnaString], + ['setNPCFriendsDict', npcFriends] ] base.cr.n_handleGetAvatarDetailsResp(avId, fields=fields) @@ -71,6 +72,12 @@ class TTSFriendsManager(DistributedObjectGlobal): if not hasattr(base.localAvatar, 'getTeleportAvailable') or not hasattr(base.localAvatar, 'ghostMode'): self.sendUpdate('teleportResponse', [ fromId, 0, 0, 0, 0 ]) return + if not base.localAvatar.acceptingTeleport: + self.sendUpdate('teleportResponse', [ fromId, 3, 0, 0, 0 ]) + return + if base.localAvatar.isIgnored(fromId): + self.sendUpdate('teleportResponse', [ fromId, 2, 0, 0, 0 ]) + return friend = base.cr.identifyFriend(fromId) diff --git a/toontown/friends/TTSFriendsManagerUD.py b/toontown/friends/TTSFriendsManagerUD.py index d8a9d76e..8237cf43 100755 --- a/toontown/friends/TTSFriendsManagerUD.py +++ b/toontown/friends/TTSFriendsManagerUD.py @@ -198,8 +198,9 @@ class TTSFriendsManagerUD(DistributedObjectGlobalUD): dnaString = fields['setDNAString'][0] experience = fields['setExperience'][0] trackBonusLevel = fields['setTrackBonusLevel'][0] + npcFriends = fields['setNPCFriendsDict'][0] - self.sendUpdateToAvatarId(senderId, 'friendDetails', [avId, inventory, trackAccess, hp, maxHp, defaultShard, lastHood, dnaString, experience, trackBonusLevel]) + self.sendUpdateToAvatarId(senderId, 'friendDetails', [avId, inventory, trackAccess, hp, maxHp, defaultShard, lastHood, dnaString, experience, trackBonusLevel, npcFriends]) self.air.dbInterface.queryObject(self.air.dbId, avId, handleToon) def getPetDetails(self, avId): diff --git a/toontown/safezone/TTSafeZoneLoader.py b/toontown/safezone/TTSafeZoneLoader.py index b6e5b245..ae73f407 100755 --- a/toontown/safezone/TTSafeZoneLoader.py +++ b/toontown/safezone/TTSafeZoneLoader.py @@ -16,8 +16,11 @@ class TTSafeZoneLoader(SafeZoneLoader.SafeZoneLoader): 'phase_4/audio/sfx/SZ_TC_bird2.ogg', 'phase_4/audio/sfx/SZ_TC_bird3.ogg']) bank = self.geom.find('**/*toon_landmark_TT_bank_DNARoot') + library = self.geom.find('**/library/square_drop_shadow') doorTrigger = bank.find('**/door_trigger*') doorTrigger.setY(doorTrigger.getY() - 1.5) + library.find('**/building_front').setY(0.3) + library.find('**/front_entrance_flag').setY(0.1) def unload(self): SafeZoneLoader.SafeZoneLoader.unload(self) diff --git a/toontown/shtiker/OptionsPage.py b/toontown/shtiker/OptionsPage.py index c7f92c29..afa5cdeb 100755 --- a/toontown/shtiker/OptionsPage.py +++ b/toontown/shtiker/OptionsPage.py @@ -731,25 +731,28 @@ class ExtraOptionsTabPage(DirectFrame): self.fov_label = DirectLabel(parent=self, relief=None, text=TTLocalizer.FieldOfViewLabel, text_align=TextNode.ALeft, text_scale=options_text_scale, text_wordwrap=16, pos=(leftMargin, 0, textStartHeight)) self.cogInterface_label = DirectLabel(parent=self, relief=None, text='', text_align=TextNode.ALeft, text_scale=options_text_scale, text_wordwrap=16, pos=(leftMargin, 0, textStartHeight - textRowHeight)) self.tpTransition_label = DirectLabel(parent=self, relief=None, text='', text_align=TextNode.ALeft, text_scale=options_text_scale, text_wordwrap=16, pos=(leftMargin, 0, textStartHeight - 2 * textRowHeight)) + self.teleport_label = DirectLabel(parent=self, relief=None, text='', text_align=TextNode.ALeft, text_scale=options_text_scale, text_wordwrap=16, pos=(leftMargin, 0, textStartHeight - 3 * textRowHeight)) self.fov_slider = DirectSlider(parent=self, pos=(buttonbase_xcoord, 0.0, buttonbase_ycoord), value=settings['fov'], pageSize=5, range=(ToontownGlobals.DefaultCameraFov, ToontownGlobals.MaxCameraFov), command=self.__doFov, thumb_geom=(circleModel.find('**/tt_t_gui_mat_namePanelCircle')), thumb_relief=None, thumb_geom_scale=2) self.fov_slider.setScale(0.25) self.cogInterface_toggleButton = DirectButton(parent=self, relief=None, image=button_image, image_scale=button_image_scale, text='', text_scale=options_text_scale, text_pos=button_textpos, pos=(buttonbase_xcoord, 0.0, buttonbase_ycoord - textRowHeight), command=self.__doToggleCogInterface) self.tpTransition_toggleButton = DirectButton(parent=self, relief=None, image=button_image, image_scale=button_image_scale, text='', text_scale=options_text_scale, text_pos=button_textpos, pos=(buttonbase_xcoord, 0.0, buttonbase_ycoord - 2 * textRowHeight), command=self.__doToggleTpTransition) + self.teleport_toggleButton = DirectButton(parent=self, relief=None, image=button_image, image_scale=button_image_scale, text='', text_scale=options_text_scale, text_pos=button_textpos, pos=(buttonbase_xcoord, 0.0, buttonbase_ycoord - 3 * textRowHeight), command=self.__doToggleTeleport) self.bugReportButton = DirectButton(parent=self, relief=None, text=TTLocalizer.BugReportButton, image=button_image, image_scale=button_image_scale, text_pos=(0, -0.01), text_fg=(0, 0, 0, 1), command=self.showReportNotice, pos=(0.0, 0.0, -0.6), text_scale=(0.045)) guiButton.removeNode() circleModel.removeNode() - self.optionChoosers['pole'] = OptionChooser.OptionChooser(self, TTLocalizer.FishingPoleLabel, 3, self.__updateFishingPole, [False], self.__applyFishingPole) - self.optionChoosers['nametag_style'] = OptionChooser.OptionChooser(self, TTLocalizer.NametagStyleLabel, 4, self.__updateNametagStyle, [False], self.__applyNametagStyle) + self.optionChoosers['pole'] = OptionChooser.OptionChooser(self, TTLocalizer.FishingPoleLabel, 4, self.__updateFishingPole, [False], self.__applyFishingPole) + self.optionChoosers['nametag_style'] = OptionChooser.OptionChooser(self, TTLocalizer.NametagStyleLabel, 5, self.__updateNametagStyle, [False], self.__applyNametagStyle) def enter(self): self.show() self.settingsChanged = 0 self.__setCogInterfaceButton() self.__setTpTransitionButton() + self.__setTeleportButton() self.__updateNametagStyle() self.__updateFishingPole() self.accept('refreshNametagStyle', self.__updateNametagStyle) @@ -776,6 +779,10 @@ class ExtraOptionsTabPage(DirectFrame): del self.tpTransition_label self.tpTransition_toggleButton.destroy() del self.tpTransition_toggleButton + self.teleport_label.destroy() + del self.teleport_label + self.teleport_toggleButton.destroy() + del self.teleport_toggleButton self.bugReportButton.destroy() del self.bugReportButton self.destroyReportNotice() @@ -807,6 +814,23 @@ class ExtraOptionsTabPage(DirectFrame): def __setTpTransitionButton(self): self.tpTransition_label['text'] = TTLocalizer.TpTransitionLabelOn if settings['tpTransition'] else TTLocalizer.TpTransitionLabelOff self.tpTransition_toggleButton['text'] = TTLocalizer.OptionsPageToggleOff if settings['tpTransition'] else TTLocalizer.OptionsPageToggleOn + + def __doToggleTeleport(self): + messenger.send('wakeup') + acceptingTeleport = settings.get('acceptingTeleport', {}) + if base.localAvatar.acceptingTeleport: + base.localAvatar.acceptingTeleport = 0 + acceptingTeleport[str(base.localAvatar.doId)] = False + else: + base.localAvatar.acceptingTeleport = 1 + acceptingTeleport[str(base.localAvatar.doId)] = True + settings['acceptingTeleport'] = acceptingTeleport + self.settingsChanged = 1 + self.__setTeleportButton() + + def __setTeleportButton(self): + self.teleport_label['text'] = TTLocalizer.TeleportLabelOn if base.localAvatar.acceptingTeleport else TTLocalizer.TeleportLabelOff + self.teleport_toggleButton['text'] = TTLocalizer.OptionsPageToggleOff if base.localAvatar.acceptingTeleport else TTLocalizer.OptionsPageToggleOn def __updateNametagStyle(self, resetIndex=True): chooser = self.optionChoosers['nametag_style'] diff --git a/toontown/shtiker/SuitPage.py b/toontown/shtiker/SuitPage.py index ef2c27c5..8490ba9a 100755 --- a/toontown/shtiker/SuitPage.py +++ b/toontown/shtiker/SuitPage.py @@ -230,6 +230,7 @@ class SuitPage(ShtikerPage.ShtikerPage): self.legalRadarButton.destroy() self.moneyRadarButton.destroy() self.salesRadarButton.destroy() + self.rolloverFrame.destroy() for panel in self.panels: panel.destroy() del self.panels @@ -335,6 +336,9 @@ class SuitPage(ShtikerPage.ShtikerPage): yStart = -0.18 xOffset = 0.199 yOffset = 0.284 + self.rolloverFrame = DirectFrame(parent=self.panelNode, relief=None, geom=DGG.getDefaultDialogGeom(), geom_color=(0.5, 0.5, 0.5, 1), geom_scale=(0.8, 0, 0.77), text_scale=0.06, text_pos=(0, 0.32), text='', text_fg=(1, 1, 1, 1), pos=(0.44, 0, 0)) + self.rolloverFrame.setBin('gui-popup', 0) + self.rolloverFrame.hide() for dept in xrange(0, len(SuitDNA.suitDepts)): row = [] color = PANEL_COLORS[dept] @@ -347,10 +351,20 @@ class SuitPage(ShtikerPage.ShtikerPage): panel.shadow = None panel.count = 0 panel.summonButton = None + panel.hoverButton = DirectButton(parent=panel, relief=None, image_scale=(0.15, 0, 0.225), image='phase_3/maps/invisible.png', pressEffect=0) + panel.hoverButton.setTransparency(True) + panel.hoverButton.panel = panel self.addCogRadarLabel(panel) self.panels.append(panel) base.panels.append(panel) - return + + def showInfo(self, panel, text, extra): + self.rolloverFrame.reparentTo(panel) + self.rolloverFrame.show() + self.rolloverFrame['text'] = text + + def hideInfo(self, extra): + self.rolloverFrame.hide() def addQuotaLabel(self, panel): index = self.panels.index(panel) @@ -428,6 +442,9 @@ class SuitPage(ShtikerPage.ShtikerPage): panel.shadow.hide() if panel.summonButton: panel.summonButton.hide() + self.rolloverFrame.hide() + panel.hoverButton.unbind(DGG.ENTER) + panel.hoverButton.unbind(DGG.EXIT) color = PANEL_COLORS[dept] panel['image_color'] = color for button in self.radarButtons: @@ -467,6 +484,19 @@ class SuitPage(ShtikerPage.ShtikerPage): panel['image_color'] = PANEL_COLORS_COMPLETE1[index / SuitDNA.suitsPerDept] elif status == COG_COMPLETE2: panel['image_color'] = PANEL_COLORS_COMPLETE2[index / SuitDNA.suitsPerDept] + if status in (COG_DEFEATED, COG_COMPLETE1, COG_COMPLETE2): + name = SuitDNA.suitHeadTypes[index] + attributes = SuitBattleGlobals.SuitAttributes[name] + level = attributes['level'] + groupAttacks, singleAttacks = SuitBattleGlobals.getAttacksByType(attributes) + info = TTLocalizer.SuitPageAttackFormat % (level + 1, level + 5, self.getAttackStrings(groupAttacks), self.getAttackStrings(singleAttacks)) + + panel.hoverButton.bind(DGG.ENTER, self.showInfo, extraArgs=[panel, info]) + panel.hoverButton.bind(DGG.EXIT, self.hideInfo) + + def getAttackStrings(self, attacks): + string = '\n'.join(['%s %s' % (TTLocalizer.SuitAttackNames[attack[0]], '-'.join(str(x) for x in attack[1])) for attack in attacks]) + return string if string else TTLocalizer.SuitPageNoAttacks def updateAllCogs(self, status): for index in xrange(0, len(base.localAvatar.cogs)): diff --git a/toontown/toon/DistributedToon.py b/toontown/toon/DistributedToon.py index 3401332d..f1264188 100755 --- a/toontown/toon/DistributedToon.py +++ b/toontown/toon/DistributedToon.py @@ -490,6 +490,9 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute def getNPCFriendsDict(self): return self.NPCFriendsDict + + def getNPCFriendCount(self, npcId): + return self.NPCFriendsDict.get(npcId, 0) def setNPCFriendsDict(self, NPCFriendsList): NPCFriendsDict = {} diff --git a/toontown/toon/LocalToon.py b/toontown/toon/LocalToon.py index 6a54f2fe..5d8e211d 100755 --- a/toontown/toon/LocalToon.py +++ b/toontown/toon/LocalToon.py @@ -150,6 +150,7 @@ class LocalToon(DistributedToon.DistributedToon, LocalAvatar.LocalAvatar): self.createSystemMsgAckGui() self.acceptingNewFriends = True self.acceptingNonFriendWhispers = True + self.acceptingTeleport = True self.physControls.event.addAgainPattern('again%in') self.oldPos = None self.questMap = None @@ -214,14 +215,19 @@ class LocalToon(DistributedToon.DistributedToon, LocalAvatar.LocalAvatar): acceptingNewFriends = settings.get('acceptingNewFriends', {}) acceptingNonFriendWhispers = settings.get('acceptingNonFriendWhispers', {}) + acceptingTeleport = settings.get('acceptingTeleport', {}) if str(self.doId) not in acceptingNewFriends: acceptingNewFriends[str(self.doId)] = True settings['acceptingNewFriends'] = acceptingNewFriends if str(self.doId) not in acceptingNonFriendWhispers: acceptingNonFriendWhispers[str(self.doId)] = True settings['acceptingNonFriendWhispers'] = acceptingNonFriendWhispers + if str(self.doId) not in acceptingTeleport: + acceptingTeleport[str(self.doId)] = True + settings['acceptingTeleport'] = acceptingTeleport self.acceptingNewFriends = acceptingNewFriends[str(self.doId)] self.acceptingNonFriendWhispers = acceptingNonFriendWhispers[str(self.doId)] + self.acceptingTeleport = acceptingTeleport[str(self.doId)] def disable(self): self.laffMeter.destroy() diff --git a/toontown/toon/ToonAvatarDetailPanel.py b/toontown/toon/ToonAvatarDetailPanel.py index 5e28dff0..e60517d1 100755 --- a/toontown/toon/ToonAvatarDetailPanel.py +++ b/toontown/toon/ToonAvatarDetailPanel.py @@ -1,6 +1,7 @@ from panda3d.core import * from toontown.toonbase.ToontownGlobals import * from direct.gui.DirectGui import * +from direct.interval.IntervalGlobal import * from direct.showbase import DirectObject from direct.fsm import ClassicFSM, State from direct.fsm import State @@ -8,10 +9,10 @@ from direct.directnotify import DirectNotifyGlobal import DistributedToon from toontown.friends import FriendInviter import ToonTeleportPanel -from toontown.toonbase import TTLocalizer +from toontown.toonbase import TTLocalizer, ToontownGlobals from toontown.hood import ZoneUtil from toontown.toonbase.ToontownBattleGlobals import Tracks, Levels, getAvPropDamage -from toontown.toon import Toon +import Toon, NPCFriendPanel globalAvatarDetail = None def showAvatarDetail(avId, avName): @@ -44,6 +45,7 @@ class ToonAvatarDetailPanel(DirectFrame): def __init__(self, avId, avName, parent = base.a2dTopRight, **kw): buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui') gui = loader.loadModel('phase_3.5/models/gui/avatar_panel_gui') + sosGui = loader.loadModel('phase_3.5/models/gui/playingCard') detailPanel = gui.find('**/avatarInfoPanel') textScale = 0.095 textWrap = 16.4 @@ -72,11 +74,20 @@ class ToonAvatarDetailPanel(DirectFrame): FriendInviter.hideFriendInviter() self.bCancel = DirectButton(self, image=(buttons.find('**/CloseBtn_UP'), buttons.find('**/CloseBtn_DN'), buttons.find('**/CloseBtn_Rllvr')), image_scale=1.1, relief=None, text=TTLocalizer.AvatarDetailPanelCancel, text_scale=TTLocalizer.TADPbCancel, text_pos=(0.12, -0.01), pos=TTLocalizer.TADPbCancelPos, scale=2.0, command=self.__handleCancel) self.bCancel.hide() + self.sosButton = DirectButton(self, relief=None, image=sosGui.find('**/card_back'), scale=0.05, pos=(0.3, 0, -0.76), text=('', TTLocalizer.DetailPanelSOS, TTLocalizer.DetailPanelSOS, ''), text_fg=(1, 1, 0.5, 1), text_shadow=(0, 0, 0, 1), text_scale=2, text_pos=(0, -3.4), text_align=TextNode.ACenter, state=DGG.NORMAL, command=self.__toggleSOSGui) + self.sosButton.hide() + self.sosFrame = DirectFrame(self, relief=None, image=DGG.getDefaultDialogGeom(), image_scale=(2.6, 1, 1.87), image_color=ToontownGlobals.GlobalDialogColor, pos=(0.2, 0, 0.8)) + self.sosFrame.setBin('background', 10) + self.sosFrame.setScale(0.5) + self.sosPage = NPCFriendPanel.NPCFriendPanel(parent=self.sosFrame, callable=False) + self.sosPage.setScale(0.18) + self.sosPage.setPos(0, 0, 0.05) self.initialiseoptions(ToonAvatarDetailPanel) self.fsm.enterInitialState() self.fsm.request('begin') buttons.removeNode() gui.removeNode() + sosGui.removeNode() def cleanup(self): if self.fsm: @@ -87,7 +98,6 @@ class ToonAvatarDetailPanel(DirectFrame): self.avatar.delete() self.createdAvatar = None self.destroy() - return def enterOff(self): pass @@ -110,6 +120,7 @@ class ToonAvatarDetailPanel(DirectFrame): def enterQuery(self): self.dataText['text'] = TTLocalizer.AvatarDetailPanelLookup % self.avName + self.sosButton.hide() self.bCancel.show() self.avatar = base.cr.doId2do.get(self.avId) if self.avatar != None and not self.avatar.ghostMode: @@ -165,10 +176,12 @@ class ToonAvatarDetailPanel(DirectFrame): else: text = TTLocalizer.AvatarDetailPanelOffline % {'identifier': identifier} self.dataText['text'] = text + self.sosButton.show() self.__addToonModel() self.__updateTrackInfo() self.__updateTrophyInfo() self.__updateLaffInfo() + self.__updateSOSPage() def __addToonModel(self): toon = Toon.Toon() @@ -191,13 +204,14 @@ class ToonAvatarDetailPanel(DirectFrame): yOffset = 0.1 ySpacing = -0.115 inventory = self.avatar.inventory + self.inventoryFrame = DirectFrame(parent=self, relief=None) inventoryModels = loader.loadModel('phase_3.5/models/gui/inventory_gui') - rolloverFrame = DirectFrame(parent=self, relief=None, geom=DGG.getDefaultDialogGeom(), geom_color=(0, 0.5, 1, 1), geom_scale=(0.5, 0.3, 0.2), text_scale=0.05, text_pos=(0, 0.0125), text='', text_fg=(1, 1, 1, 1)) + rolloverFrame = DirectFrame(parent=self.inventoryFrame, relief=None, geom=DGG.getDefaultDialogGeom(), geom_color=(0, 0.5, 1, 1), geom_scale=(0.5, 0.3, 0.2), text_scale=0.05, text_pos=(0, 0.0125), text='', text_fg=(1, 1, 1, 1)) rolloverFrame.setBin('gui-popup', 0) rolloverFrame.hide() buttonModel = inventoryModels.find('**/InventoryButtonUp') for track in xrange(0, len(Tracks)): - DirectLabel(parent=self, relief=None, text=TextEncoder.upper(TTLocalizer.BattleGlobalTracks[track]), text_scale=TTLocalizer.TADPtrackLabel, text_align=TextNode.ALeft, pos=(-0.9, 0, TTLocalizer.TADtrackLabelPosZ + track * ySpacing)) + DirectLabel(parent=self.inventoryFrame, relief=None, text=TextEncoder.upper(TTLocalizer.BattleGlobalTracks[track]), text_scale=TTLocalizer.TADPtrackLabel, text_align=TextNode.ALeft, pos=(-0.9, 0, TTLocalizer.TADtrackLabelPosZ + track * ySpacing)) if self.avatar.hasTrackAccess(track): curExp, nextExp = inventory.getCurAndNextExpValues(track) for item in xrange(0, len(Levels[track])): @@ -215,7 +229,7 @@ class ToonAvatarDetailPanel(DirectFrame): image_color = Vec4(0, 0.6, 1, 1) geom_color = None pos = (xOffset + item * xSpacing, 0, yOffset + track * ySpacing) - label = DirectLabel(parent=self, image=buttonModel, image_scale=(0.92, 1, 1), image_color=image_color, geom=inventory.invModels[track][item], geom_color=geom_color, geom_scale=0.6, relief=None, pos=pos, state=DGG.NORMAL) + label = DirectLabel(parent=self.inventoryFrame, image=buttonModel, image_scale=(0.92, 1, 1), image_color=image_color, geom=inventory.invModels[track][item], geom_color=geom_color, geom_scale=0.6, relief=None, pos=pos, state=DGG.NORMAL) label.bind(DGG.ENTER, self.showInfo, extraArgs=[rolloverFrame, track, int(getAvPropDamage(track, item, curExp, organic)), numItems, (pos[0] + 0.37, pos[1], pos[2])]) label.bind(DGG.EXIT, self.hideInfo, extraArgs=[rolloverFrame]) else: @@ -245,4 +259,35 @@ class ToonAvatarDetailPanel(DirectFrame): star = gui.find('**/avatarStar') self.star = DirectLabel(parent=self, image=star, image_color=color, pos=(0.610165, 0, -0.760678), scale=0.9, relief=None) gui.removeNode() - return + + def __updateSOSPage(self): + self.sosPage.setFriends(self.avatar.NPCFriendsDict) + self.sosPage.update() + + def __toggleSOSGui(self): + self.sosButton['state'] = DGG.DISABLED + + if self.sosFrame.getScale() == 0.5: + pos = (-0.4, 0, -1.88) + scale = 1.0 + else: + pos = (0, 0, 0.05) + scale = 0.5 + self.sosFrame.setBin('background', 10) + + Sequence( + Parallel( + self.sosFrame.posInterval(1.0, pos, blendType='easeOut'), + self.sosFrame.scaleInterval(1.0, scale, blendType='easeOut') + ), + Func(self.__enableSOSButton) + ).start() + + def __enableSOSButton(self): + try: + self.sosButton['state'] = DGG.NORMAL + + if self.sosFrame.getScale() == 1.0: + self.sosFrame.clearBin() + except: + pass \ No newline at end of file diff --git a/toontown/toon/ToonTeleportPanel.py b/toontown/toon/ToonTeleportPanel.py index b26a676d..43005fc4 100755 --- a/toontown/toon/ToonTeleportPanel.py +++ b/toontown/toon/ToonTeleportPanel.py @@ -62,6 +62,9 @@ class ToonTeleportPanel(DirectFrame): State.State('ignored', self.enterIgnored, self.exitIgnored), + State.State('noTeleport', + self.enterNoTeleport, + self.exitNoTeleport), State.State('notOnline', self.enterNotOnline, self.exitNotOnline), @@ -148,11 +151,18 @@ class ToonTeleportPanel(DirectFrame): self.bOk.hide() def enterIgnored(self): - self['text'] = TTLocalizer.TeleportPanelNotAvailable % self.avName + self['text'] = TTLocalizer.TeleportPanelIgnored % self.avName self.bOk.show() def exitIgnored(self): self.bOk.hide() + + def enterNoTeleport(self): + self['text'] = TTLocalizer.TeleportPanelNoTeleport % self.avName + self.bOk.show() + + def exitNoTeleport(self): + self.bOk.hide() def enterNotOnline(self): self['text'] = TTLocalizer.TeleportPanelNotOnline % self.avName @@ -270,6 +280,8 @@ class ToonTeleportPanel(DirectFrame): elif available == 2: teleportNotify.debug('__teleportResponse: ignored') self.fsm.request('ignored') + elif available == 3: + self.fsm.request('noTeleport') elif shardId != base.localAvatar.defaultShard: teleportNotify.debug('__teleportResponse: otherShard') self.fsm.request('otherShard', [shardId, hoodId, zoneId]) diff --git a/toontown/toonbase/TTLocalizerEnglish.py b/toontown/toonbase/TTLocalizerEnglish.py index 5e4ad456..303ca50b 100755 --- a/toontown/toonbase/TTLocalizerEnglish.py +++ b/toontown/toonbase/TTLocalizerEnglish.py @@ -8726,6 +8726,27 @@ ShardPageTeleport = 'Teleport to\n%s' TeleportButton = 'Teleport' +BattleCogPopup = '\x01androidGreen\x01Group attacks:\x02\n%s\n\n\x01androidGreen\x01Regular attacks:\x02\n%s' +BattleCogPopupAttack = '%s %s HP' +BattleCogPopupAttackDanger = '\x01red\x01' + BattleCogPopupAttack + '\x02' +BattleCogPopupDanger = '\x01red\x01Dangerous!\x02\n\n' +BattleCogPopupDangerColor = '\x01red' + +SuitPageAttackFormat = 'Levels: %s-%s\n\n' + BattleCogPopup +SuitPageNoAttacks = 'None' + +BattleGagPopup = '%s: %s\nGags left: %s' +BattleSOSPopup = '\x01azure\x01%s\x02\n%s\n%s%s stars\nSOS left: %s' +BattleSOSPopupHeal = 'Heals' +BattleSOSPopupHarm = 'Deals' +BattleSOSPopupHP = '%s %s HP\n' + +DetailPanelSOS = 'SOS Cards' + +TeleportLabelOn = 'Accepting teleports.' +TeleportLabelOff = 'Not accepting teleports.' +TeleportPanelNoTeleport = '%s needs some time alone right now.' + Blacklist = [ "$1ut", "$h1t", diff --git a/toontown/town/TownBattle.py b/toontown/town/TownBattle.py index b44cdc32..4bcd0870 100755 --- a/toontown/town/TownBattle.py +++ b/toontown/town/TownBattle.py @@ -18,7 +18,7 @@ from toontown.toonbase import ToontownTimer from direct.showbase import PythonUtil from toontown.toonbase import TTLocalizer from toontown.pets import PetConstants -from direct.gui.DirectGui import DGG +from direct.gui.DirectGui import * from toontown.battle import FireCogPanel class TownBattle(StateData.StateData): @@ -122,8 +122,11 @@ class TownBattle(StateData.StateData): self.SOSPetInfoPanel = TownBattleSOSPetInfoPanel.TownBattleSOSPetInfoPanel(self.SOSPetInfoPanelDoneEvent) self.fireCogPanelDoneEvent = 'fire-cog-panel-done' self.FireCogPanel = FireCogPanel.FireCogPanel(self.fireCogPanelDoneEvent) - self.toonPanels = [TownBattleToonPanel.TownBattleToonPanel(i) for i in xrange(4)] - self.cogPanels = [TownBattleCogPanel.TownBattleCogPanel(i) for i in xrange(4)] + self.rolloverFrame = DirectFrame(aspect2d, relief=None, geom=DGG.getDefaultDialogGeom(), geom_color=(0.6, 1.0, 0.4, 1), geom_scale=(0.5, 0.3, 0.2), text_scale=0.05, text_pos=(0, 0.0125), text='', text_fg=(0, 0, 0, 1), pos=(0.4, 0, 0)) + self.rolloverFrame.setBin('gui-popup', 0) + self.rolloverFrame.hide() + self.toonPanels = [TownBattleToonPanel.TownBattleToonPanel(self) for i in xrange(4)] + self.cogPanels = [TownBattleCogPanel.TownBattleCogPanel(self) for i in xrange(4)] self.timer = ToontownTimer.ToontownTimer() self.timer.posInTopRightCorner() self.timer.setScale(0.4) @@ -143,6 +146,7 @@ class TownBattle(StateData.StateData): del self.FireCogPanel del self.SOSPetSearchPanel del self.SOSPetInfoPanel + del self.rolloverFrame for panel in self.toonPanels + self.cogPanels: panel.cleanup() @@ -214,6 +218,23 @@ class TownBattle(StateData.StateData): self.time = time self.timer.setTime(time) return None + + def showRolloverFrame(self, parent, scale, textPos, color, pos, text, extra=None): + self.rolloverFrame['geom_scale'] = scale + self.rolloverFrame['text_pos'] = textPos + self.rolloverFrame['geom_color'] = color + self.rolloverFrame.setPos(pos) + self.rolloverFrame.reparentTo(parent) + self.rolloverFrame.show() + self.rolloverFrame['text'] = text + + def hideRolloverFrame(self, extra=None): + self.rolloverFrame.hide() + + def isAttackDangerous(self, hp): + for panel in self.toonPanels: + if panel.hasAvatar() and panel.avatar.getHp() <= hp: + return True def __enterPanels(self, num, localNum): self.notify.debug('enterPanels() num: %d localNum: %d' % (num, localNum)) @@ -227,6 +248,7 @@ class TownBattle(StateData.StateData): for cogPanel in self.cogPanels: cogPanel.hide() cogPanel.updateHealthBar() + cogPanel.updateRolloverBind() cogPanel.setPos(0, 0, 0.62) self.positionPanels(num, self.cogPanels) @@ -436,6 +458,7 @@ class TownBattle(StateData.StateData): self.numToons = len(toons) self.localNum = toons.index(base.localAvatar) currStateName = self.fsm.getCurrentState().getName() + if resetActivateMode: self.__enterPanels(self.numToons, self.localNum) for i in xrange(len(toons)): diff --git a/toontown/town/TownBattleCogPanel.py b/toontown/town/TownBattleCogPanel.py index f68b00c7..48c4bffe 100755 --- a/toontown/town/TownBattleCogPanel.py +++ b/toontown/town/TownBattleCogPanel.py @@ -1,17 +1,22 @@ from direct.gui.DirectGui import * +from toontown.battle import SuitBattleGlobals from toontown.suit import Suit, SuitHealthBar from toontown.toonbase import TTLocalizer class TownBattleCogPanel(DirectFrame): - def __init__(self, id): + def __init__(self, battle): gui = loader.loadModel('phase_3.5/models/gui/battle_gui') DirectFrame.__init__(self, relief=None, image=gui.find('**/ToonBtl_Status_BG'), image_color=(0.86, 0.86, 0.86, 0.7), scale=0.8) self.initialiseoptions(TownBattleCogPanel) + self.battle = battle self.levelText = DirectLabel(parent=self, text='', pos=(-0.06, 0, -0.075), text_scale=0.055) self.typeText = DirectLabel(parent=self, text='', pos=(0.12, 0, -0.075), text_scale=0.045) self.healthBar = SuitHealthBar.SuitHealthBar() self.generateHealthBar() + self.hoverButton = DirectButton(parent=self, relief=None, image_scale=(0.07, 0, 0.06), pos=(0.105, 0, 0.05), image='phase_3/maps/invisible.png', pressEffect=0) + self.hoverButton.setTransparency(True) + self.hoverButton.bind(DGG.EXIT, self.battle.hideRolloverFrame) self.suit = None self.suitHead = None self.hide() @@ -23,9 +28,11 @@ class TownBattleCogPanel(DirectFrame): self.levelText.removeNode() self.typeText.removeNode() self.healthBar.delete() + self.hoverButton.removeNode() del self.levelText del self.typeText del self.healthBar + del self.hoverButton DirectFrame.destroy(self) def cleanupHead(self): @@ -46,6 +53,31 @@ class TownBattleCogPanel(DirectFrame): self.levelText['text'] = TTLocalizer.CogPanelLevel % suit.getActualLevel() self.typeText['text'] = suit.getTypeText() self.accept(suit.uniqueName('hpChange'), self.updateHealthBar) + self.updateRolloverBind() + + def updateRolloverBind(self): + if not self.suit: + return + + attributes = SuitBattleGlobals.SuitAttributes[self.suit.getStyleName()] + groupAttacks, singleAttacks = SuitBattleGlobals.getAttacksByType(attributes) + level = self.suit.getLevel() + info = TTLocalizer.BattleCogPopup % (self.getAttackStrings(groupAttacks, level), self.getAttackStrings(singleAttacks, level)) + + if TTLocalizer.BattleCogPopupDangerColor in info: + info = TTLocalizer.BattleCogPopupDanger + info + + self.hoverButton.bind(DGG.ENTER, self.battle.showRolloverFrame, extraArgs=[self, (0.73, 0, 0.65), (0, 0.26), (0.5, 0.5, 0.5, 1), (0.6, 0, 0.1), info]) + + def getAttackStrings(self, attacks, level): + attackStrings = [] + + for attack in attacks: + hp = attack[1][level] + attackString = TTLocalizer.BattleCogPopupAttackDanger if self.battle.isAttackDangerous(hp) else TTLocalizer.BattleCogPopupAttack + attackStrings.append(attackString % (TTLocalizer.SuitAttackNames[attack[0]], hp)) + + return '\n'.join(attackStrings) if attackStrings else TTLocalizer.SuitPageNoAttacks def generateSuitHead(self, name): self.suitHead = Suit.attachSuitHead(self, name) diff --git a/toontown/town/TownBattleToonPanel.py b/toontown/town/TownBattleToonPanel.py index 388ec7c6..de6426f4 100755 --- a/toontown/town/TownBattleToonPanel.py +++ b/toontown/town/TownBattleToonPanel.py @@ -3,7 +3,7 @@ from toontown.toonbase import ToontownGlobals from toontown.toonbase.ToontownBattleGlobals import * from direct.directnotify import DirectNotifyGlobal import string -from toontown.toon import LaffMeter +from toontown.toon import LaffMeter, NPCToons from toontown.battle import BattleBase from direct.gui.DirectGui import * from toontown.toonbase import TTLocalizer @@ -11,12 +11,14 @@ from toontown.toon.NPCFriendPanel import createNPCToonHead class TownBattleToonPanel(DirectFrame): notify = DirectNotifyGlobal.directNotify.newCategory('TownBattleToonPanel') + sosTracks = Tracks + NPCTracks - def __init__(self, id): + def __init__(self, battle): gui = loader.loadModel('phase_3.5/models/gui/battle_gui') DirectFrame.__init__(self, relief=None, image=gui.find('**/ToonBtl_Status_BG'), image_color=Vec4(0.5, 0.9, 0.5, 0.7)) self.setScale(0.8) self.initialiseoptions(TownBattleToonPanel) + self.battle = battle self.avatar = None self.sosText = DirectLabel(parent=self, relief=None, pos=(0.1, 0, 0.015), text=TTLocalizer.TownBattleToonSOS, text_scale=0.06) self.sosText.hide() @@ -40,28 +42,36 @@ class TownBattleToonPanel(DirectFrame): self.passNode.hide() self.laffMeter = None self.whichText = DirectLabel(parent=self, text='', pos=(0.1, 0, -0.08), text_scale=0.05) + self.hoverButton = DirectButton(parent=self, relief=None, image_scale=(0.07, 0, 0.06), pos=(0.105, 0, 0.05), image='phase_3/maps/invisible.png', pressEffect=0) + self.hoverButton.setTransparency(True) + self.hoverButton.bind(DGG.EXIT, self.battle.hideRolloverFrame) self.hide() gui.removeNode() + + def hasAvatar(self): + return self.avatar is not None def setLaffMeter(self, avatar): self.notify.debug('setLaffMeter: new avatar %s' % avatar.doId) + if self.avatar == avatar: messenger.send(self.avatar.uniqueName('hpChange'), [avatar.hp, avatar.maxHp, 1]) - return None - else: - if self.avatar or self.laffMeter: - self.cleanupLaffMeter() - self.avatar = avatar - self.laffMeter = LaffMeter.LaffMeter(avatar.style, avatar.hp, avatar.maxHp) - self.laffMeter.setAvatar(self.avatar) - self.laffMeter.reparentTo(self) - self.laffMeter.setPos(-0.06, 0, 0.05) - self.laffMeter.setScale(0.045) - self.laffMeter.start() - self.setHealthText(avatar.hp, avatar.maxHp) - self.hpChangeEvent = self.avatar.uniqueName('hpChange') - self.accept(self.hpChangeEvent, self.setHealthText) - return None + return + + if self.avatar or self.laffMeter: + self.cleanupLaffMeter() + self.cleanupSosHead() + + self.avatar = avatar + self.laffMeter = LaffMeter.LaffMeter(avatar.style, avatar.hp, avatar.maxHp) + self.laffMeter.setAvatar(self.avatar) + self.laffMeter.reparentTo(self) + self.laffMeter.setPos(-0.06, 0, 0.05) + self.laffMeter.setScale(0.045) + self.laffMeter.start() + self.setHealthText(avatar.hp, avatar.maxHp) + self.hpChangeEvent = self.avatar.uniqueName('hpChange') + self.accept(self.hpChangeEvent, self.setHealthText) def setHealthText(self, hp, maxHp, quietly = 0): self.healthText['text'] = TTLocalizer.TownBattleHealthText % {'hitPoints': hp, @@ -97,6 +107,7 @@ class TownBattleToonPanel(DirectFrame): self.whichText.hide() self.passNode.hide() self.cleanupSosHead() + self.hoverButton.unbind(DGG.ENTER) self.whichText.setPos(0.1, 0, -0.08) self.whichText['text_scale'] = 0.05 if self.hasGag: @@ -115,6 +126,22 @@ class TownBattleToonPanel(DirectFrame): self.sosHead.reparentTo(self) self.sosHead.setPos(0.1, 0, 0.045) self.sosHead.setScale(0.24) + track, level, hp, rarity = NPCToons.getNPCTrackLevelHpRarity(targetIndex) + sosType = self.sosTracks[track] + + if track == NPC_RESTOCK_GAGS: + if level == -1: + sosType += ' All' + else: + sosType += ' ' + self.sosTracks[level] + + if hp: + hpString = TTLocalizer.BattleSOSPopupHP % (TTLocalizer.BattleSOSPopupHeal if track == HEAL_TRACK else TTLocalizer.BattleSOSPopupHarm, hp) + + sosType = TextEncoder.upper(sosType) + count = max(0, self.avatar.getNPCFriendCount(targetIndex) - 1) + info = TTLocalizer.BattleSOSPopup % (sosType, NPCToons.getNPCName(targetIndex), hpString if hp else '', rarity, count) + self.hoverButton.bind(DGG.ENTER, self.battle.showRolloverFrame, extraArgs=[self, (0.5, 0.3, 0.3), (0, 0.08), (0.6, 1.0, 0.4, 1), (0.4, 0, 0.1), info]) elif track == BattleBase.SOS or track == BattleBase.PETSOS: self.sosText.show() elif track >= MIN_TRACK_INDEX and track <= MAX_TRACK_INDEX: @@ -126,8 +153,16 @@ class TownBattleToonPanel(DirectFrame): self.gag.setScale(0.8) self.gag.setPos(0, 0, 0.02) self.hasGag = 1 - if self.avatar is not None and self.avatar.checkGagBonus(track, level): - self.gag.setColor((1, 0, 0, 1) if track == 1 and level == 5 else (0, 1, 0, 1)) + if self.avatar: + curExp, nextExp = self.avatar.inventory.getCurAndNextExpValues(track) + organic = self.avatar.checkGagBonus(track, level) + damage = int(getAvPropDamage(track, level, curExp, organic)) + numItems = max(0, self.avatar.inventory.numItem(track, level) - 1) + info = TTLocalizer.BattleGagPopup % (self.avatar.inventory.getToonupDmgStr(track, 0), damage, numItems) + self.hoverButton.bind(DGG.ENTER, self.battle.showRolloverFrame, extraArgs=[self, (0.5, 0.3, 0.2), (0, 0.0125), (0.6, 1.0, 0.4, 1), (0.4, 0, 0), info]) + + if self.avatar.checkGagBonus(track, level): + self.gag.setColor((1, 0, 0, 1) if track == 1 and level == 5 else (0, 1, 0, 1)) if numTargets is not None and targetIndex is not None and localNum is not None: self.whichText.show() self.whichText['text'] = self.determineWhichText(numTargets, targetIndex, localNum, index) @@ -175,6 +210,8 @@ class TownBattleToonPanel(DirectFrame): del self.gag self.gagNode.removeNode() del self.gagNode + self.hoverButton.removeNode() + del self.hoverButton self.cleanupSosHead() DirectFrame.destroy(self)