diff --git a/README.md b/README.md index d291168c..7056f17e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# src # +# Toontown Stride - src # The source code for Toontown Stride. diff --git a/toontown/parties/Decoration.py b/toontown/parties/Decoration.py index 60dc60f1..43543df9 100755 --- a/toontown/parties/Decoration.py +++ b/toontown/parties/Decoration.py @@ -123,6 +123,26 @@ class Decoration(NodePath): balloonRight.reparentTo(balloonRightLocator) self.heartBanner.loop('idle') self.heartBanner.reparentTo(self) + elif self.name == 'Hydra' or self.name == 'StageWinter': + if self.name == 'StageWinter': + self.hydra = Actor.Actor('phase_13/models/parties/tt_r_ara_pty_winterProps', {'dance': 'phase_13/models/parties/tt_a_ara_pty_hydra_dance'}) + else: + self.hydra = Actor.Actor('phase_13/models/parties/tt_a_ara_pty_hydra_default', {'dance': 'phase_13/models/parties/tt_a_ara_pty_hydra_dance'}) + st = random.randint(0, 10) + animIval = ActorInterval(self.hydra, 'dance') + animIvalDur = animIval.getDuration() + self.decSfx = loader.loadSfx('phase_13/audio/sfx/tt_s_ara_pty_propsShow_dance.ogg') + soundIval = SoundInterval(self.decSfx, node=self.hydra, listenerNode=base.localAvatar, volume=PartyGlobals.DECORATION_VOLUME, cutOff=PartyGlobals.DECORATION_CUTOFF, duration=animIvalDur) + self.animSeq = Parallel(animIval, soundIval) + self.animSeq.loop(st) + collisions = self.hydra.find('**/*collision*') + collisions.setPos(0, 0, -5) + self.hydra.flattenStrong() + self.hydra.reparentTo(self) + if self.name == 'StageWinter': + stageBounds = self.hydra.find('**/stage').node().getBounds() + self.hydra.node().setBounds(stageBounds) + self.hydra.node().setFinal(1) elif self.name == 'TubeCogVictory': self.tubeCog = Actor.Actor('phase_5.5/models/estate/tt_a_ara_pty_tubeCogVictory_default', {'wave': 'phase_5.5/models/estate/tt_a_ara_pty_tubeCogVictory_wave'}) st = random.randint(0, 10) @@ -159,6 +179,10 @@ class Decoration(NodePath): self.decorationModel = loader.loadModel('phase_13/models/parties/tt_m_ara_pty_cogDoodleVictory') self.decorationModel.reparentTo(self) self.decorationShadow = self.setupAnimSeq() + elif self.name == 'CogIceCreamVictory': + self.decorationModel = loader.loadModel('phase_13/models/parties/tt_m_ara_pty_cogIceCreamVictory') + self.decorationModel.reparentTo(self) + self.decorationShadow = self.setupAnimSeq() elif self.name == 'cogIceCreamWinter': self.decorationModel = loader.loadModel('phase_13/models/parties/tt_m_ara_pty_cogIceCreamWinter') self.decorationModel.reparentTo(self) @@ -223,6 +247,12 @@ class Decoration(NodePath): del self.globeSphere self.partyGlobe.removeNode() del self.partyGlobe + elif self.name == 'Hydra' or self.name == 'StageWinter': + self.cleanUpAnimSequences() + self.hydra.removeNode() + del self.hydra + if hasattr(self, 'decSfx'): + del self.decSfx elif self.name == 'TubeCogVictory': self.cleanUpAnimSequences() self.tubeCog.removeNode() @@ -244,7 +274,7 @@ class Decoration(NodePath): elif self.name == 'CannonVictory': self.cannonVictory.removeNode() del self.cannonVictory - elif self.name == 'CogStatueVictory' or self.name == 'cogIceCreamWinter' or self.name == 'CogStatueWinter': + elif self.name == 'CogIceCreamVictory' or self.name == 'CogStatueVictory' or self.name == 'cogIceCreamWinter' or self.name == 'CogStatueWinter': self.cleanUpAnimSequences() self.decorationModel.removeNode() self.decorationShadow.removeNode() diff --git a/toontown/parties/DistributedPartyActivity.py b/toontown/parties/DistributedPartyActivity.py index 025039a5..05c9ed22 100755 --- a/toontown/parties/DistributedPartyActivity.py +++ b/toontown/parties/DistributedPartyActivity.py @@ -258,10 +258,6 @@ class DistributedPartyActivity(DistributedObject.DistributedObject): self.signFlatWithNote.stash() self.signTextLocator.stash() - def unloadSign(self): - self.sign.removeNode() - del self.sign - def loadLever(self): self.lever = self.root.attachNewNode('%sLever' % self.activityName) self.leverModel = self.party.defaultLeverModel.copyTo(self.lever) @@ -413,9 +409,8 @@ class DistributedPartyActivity(DistributedObject.DistributedObject): self._disableCollisions() self.signModel.removeNode() del self.signModel - if hasattr(self, 'sign'): - self.sign.removeNode() - del self.sign + self.sign.removeNode() + del self.sign self.ignoreAll() if self.wantLever: self.unloadLever() diff --git a/toontown/parties/PartyEditor.py b/toontown/parties/PartyEditor.py index 55d5fb2a..bac13a04 100755 --- a/toontown/parties/PartyEditor.py +++ b/toontown/parties/PartyEditor.py @@ -47,15 +47,30 @@ class PartyEditor(DirectObject, FSM): self.partyPlanner.gui.find('**/activitiesButtonDown_rollover'), self.partyPlanner.gui.find('**/activitiesButtonDown_inactive')), incButton_relief=None, incButton_pos=(-0.05, 0.0, -0.94), itemFrame_pos=(pos[0], pos[1], pos[2] + 0.04), itemFrame_relief=None, numItemsVisible=1, items=[]) holidayIds = base.cr.newsManager.getHolidayIdList() + isWinter = ToontownGlobals.WINTER_DECORATIONS in holidayIds or ToontownGlobals.WACKY_WINTER_DECORATIONS in holidayIds + isVictory = ToontownGlobals.VICTORY_PARTY_HOLIDAY in holidayIds + isValentine = ToontownGlobals.VALENTINES_DAY in holidayIds for activityId in PartyGlobals.PartyEditorActivityOrder: - pele = PartyEditorListElement(self, activityId) - self.elementList.addItem(pele) - if activityId == PartyGlobals.ActivityIds.PartyClock: - self.partyClockElement = pele + if not isVictory and activityId in PartyGlobals.VictoryPartyActivityIds or not isWinter and activityId in PartyGlobals.WinterPartyActivityIds or not isValentine and activityId in PartyGlobals.ValentinePartyActivityIds: + pass + elif isVictory and activityId in PartyGlobals.VictoryPartyReplacementActivityIds or isWinter and activityId in PartyGlobals.WinterPartyReplacementActivityIds or isValentine and activityId in PartyGlobals.ValentinePartyReplacementActivityIds: + pass + else: + pele = PartyEditorListElement(self, activityId) + self.elementList.addItem(pele) + if activityId == PartyGlobals.ActivityIds.PartyClock: + self.partyClockElement = pele for decorationId in PartyGlobals.DecorationIds: - pele = PartyEditorListElement(self, decorationId, isDecoration=True) - self.elementList.addItem(pele) + if not isVictory and decorationId in PartyGlobals.VictoryPartyDecorationIds or not isWinter and decorationId in PartyGlobals.WinterPartyDecorationIds or not isValentine and decorationId in PartyGlobals.ValentinePartyDecorationIds: + pass + elif isVictory and decorationId in PartyGlobals.VictoryPartyReplacementDecorationIds or isValentine and decorationId in PartyGlobals.ValentinePartyReplacementDecorationIds: + pass + elif decorationId in PartyGlobals.TTSUnreleasedDecor: + pass + else: + pele = PartyEditorListElement(self, decorationId, isDecoration=True) + self.elementList.addItem(pele) self.elementList.refresh() self.elementList['command'] = self.scrollItemChanged @@ -105,7 +120,7 @@ class PartyEditor(DirectObject, FSM): self.initPartyClock() if self.currentElement: - self.currentElement.checkSoldOutAndAffordability() + self.currentElement.checkSoldOutAndPaidStatusAndAffordability() def buyCurrentElement(self): if self.currentElement: @@ -136,7 +151,7 @@ class PartyEditor(DirectObject, FSM): self.elementList.scrollTo(0) self.elementList['items'][0].elementSelectedFromList() self.currentElement = self.elementList['items'][self.elementList.getSelectedIndex()] - self.currentElement.checkSoldOutAndAffordability() + self.currentElement.checkSoldOutAndPaidStatusAndAffordability() self.partyPlanner.instructionLabel['text'] = TTLocalizer.PartyPlannerEditorInstructionsIdle self.updateCostsAndBank() self.handleMutuallyExclusiveActivities() diff --git a/toontown/parties/PartyEditorGridElement.py b/toontown/parties/PartyEditorGridElement.py index 3023bdb0..1f2c9ea4 100755 --- a/toontown/parties/PartyEditorGridElement.py +++ b/toontown/parties/PartyEditorGridElement.py @@ -13,11 +13,11 @@ from toontown.parties import PartyUtils class PartyEditorGridElement(DirectButton): notify = directNotify.newCategory('PartyEditorGridElement') - def __init__(self, partyEditor, id, isDecoration, checkSoldOutAndAffordability, **kw): + def __init__(self, partyEditor, id, isDecoration, checkSoldOutAndPaidStatusAndAffordability, **kw): self.partyEditor = partyEditor self.id = id self.isDecoration = isDecoration - self.checkSoldOutAndAffordability = checkSoldOutAndAffordability + self.checkSoldOutAndPaidStatusAndAffordability = checkSoldOutAndPaidStatusAndAffordability if self.isDecoration: self.name = TTLocalizer.PartyDecorationNameDict[self.id]['editor'] colorList = ((1.0, 1.0, 1.0, 1.0), @@ -218,7 +218,7 @@ class PartyEditorGridElement(DirectButton): self.partyEditor.handleMutuallyExclusiveActivities() else: self.stash() - self.checkSoldOutAndAffordability() + self.checkSoldOutAndPaidStatusAndAffordability() return def placeInPartyGrounds(self, desiredXY = None): @@ -230,7 +230,7 @@ class PartyEditorGridElement(DirectButton): self.partyEditor.partyEditorGrid.registerNewElement(self, self.centerGridSquare, self.getGridSize()) self.partyEditor.updateCostsAndBank() self.partyEditor.partyPlanner.instructionLabel['text'] = TTLocalizer.PartyPlannerEditorInstructionsPartyGrounds - self.checkSoldOutAndAffordability() + self.checkSoldOutAndPaidStatusAndAffordability() return True else: return False diff --git a/toontown/parties/PartyEditorListElement.py b/toontown/parties/PartyEditorListElement.py index 85c4087a..5e117bc2 100755 --- a/toontown/parties/PartyEditorListElement.py +++ b/toontown/parties/PartyEditorListElement.py @@ -13,6 +13,8 @@ class PartyEditorListElement(DirectButton): self.partyEditor = partyEditor self.id = id self.isDecoration = isDecoration + self.unreleased = self.calcUnreleased(id) + self.comingSoonTextScale = 1.0 if self.isDecoration: self.name = TTLocalizer.PartyDecorationNameDict[self.id]['editor'] colorList = ((1.0, 0.0, 1.0, 1.0), @@ -20,8 +22,10 @@ class PartyEditorListElement(DirectButton): (0.0, 1.0, 1.0, 1.0), (0.5, 0.5, 0.5, 1.0)) assetName = PartyGlobals.DecorationIds.getString(self.id) + if assetName == 'Hydra': + assetName = 'StageSummer' geom = self.partyEditor.decorationModels.find('**/partyDecoration_%s' % assetName) - if geom.isEmpty(): + if geom.isEmpty() or self.unreleased: helpGui = loader.loadModel('phase_3.5/models/gui/tt_m_gui_brd_help') helpImageList = (helpGui.find('**/tt_t_gui_brd_helpUp'), helpGui.find('**/tt_t_gui_brd_helpDown'), @@ -31,11 +35,12 @@ class PartyEditorListElement(DirectButton): geom3_color = (0.5, 0.5, 0.5, 1.0) scale = Vec3(2.5, 2.5, 2.5) geom_pos = (0.0, 0.0, 0.0) + self.comingSoonTextScale = 0.035 else: geom_pos = (0.0, 0.0, -3.0) geom3_color = (0.5, 0.5, 0.5, 1.0) scale = Vec3(0.06, 0.0001, 0.06) - if self.id in [PartyGlobals.DecorationIds.CogStatueVictory, PartyGlobals.DecorationIds.TubeCogVictory]: + if self.id in [PartyGlobals.DecorationIds.CogStatueVictory, PartyGlobals.DecorationIds.TubeCogVictory, PartyGlobals.DecorationIds.CogIceCreamVictory]: geom_pos = (0.0, 0.0, -3.9) scale = Vec3(0.05, 0.0001, 0.05) else: @@ -53,6 +58,7 @@ class PartyEditorListElement(DirectButton): scale = 0.35 geom3_color = (0.5, 0.5, 0.5, 1.0) geom_pos = (0.0, 0.0, 0.0) + self.comingSoonTextScale = 0.25 optiondefs = (('geom', geom, None), ('geom3_color', geom3_color, None), ('geom_pos', geom_pos, None), @@ -67,13 +73,30 @@ class PartyEditorListElement(DirectButton): self.partyEditorGridElements = [] if self.isDecoration: for i in xrange(PartyGlobals.DecorationInformationDict[self.id]['limitPerParty']): - self.partyEditorGridElements.append(PartyEditorGridElement(self.partyEditor, self.id, self.isDecoration, self.checkSoldOutAndAffordability)) + self.partyEditorGridElements.append(PartyEditorGridElement(self.partyEditor, self.id, self.isDecoration, self.checkSoldOutAndPaidStatusAndAffordability)) else: for i in xrange(PartyGlobals.ActivityInformationDict[self.id]['limitPerParty']): - self.partyEditorGridElements.append(PartyEditorGridElement(self.partyEditor, self.id, self.isDecoration, self.checkSoldOutAndAffordability)) + self.partyEditorGridElements.append(PartyEditorGridElement(self.partyEditor, self.id, self.isDecoration, self.checkSoldOutAndPaidStatusAndAffordability)) self.activeGridElementIndex = -1 + self.adjustForUnreleased() + return + + def calcUnreleased(self, id): + if base.cr.partyManager.allowUnreleasedClient(): + self.unreleased = False + elif self.isDecoration: + self.unreleased = id in PartyGlobals.UnreleasedDecorationIds + else: + self.unreleased = id in PartyGlobals.UnreleasedActivityIds + return self.unreleased + + def adjustForUnreleased(self): + if self.unreleased: + textScale = self.comingSoonTextScale + comingSoon = DirectLabel(parent=self, text=TTLocalizer.PartyPlannerComingSoon, text_scale=textScale, text_fg=(1.0, 0, 0, 1.0), text_shadow=(0, 0, 0, 1), relief=None) + self['state'] = DirectGuiGlobals.DISABLED return def clearPartyGrounds(self): @@ -90,12 +113,12 @@ class PartyEditorListElement(DirectButton): self.partyEditor.partyPlanner.elementDescriptionNode.setText(TTLocalizer.PartyActivityNameDict[self.id]['description']) self.partyEditor.partyPlanner.elementPriceNode.setText('%d %s' % (PartyGlobals.ActivityInformationDict[self.id]['cost'], TTLocalizer.PartyPlannerBeans)) self.partyEditor.partyPlanner.elementTitleLabel['text'] = self.name - self.checkSoldOutAndAffordability() + self.checkSoldOutAndPaidStatusAndAffordability() - def checkSoldOutAndAffordability(self): + def checkSoldOutAndPaidStatusAndAffordability(self): if self.partyEditor.currentElement != self: if self.partyEditor.currentElement is not None: - self.partyEditor.currentElement.checkSoldOutAndAffordability() + self.partyEditor.currentElement.checkSoldOutAndPaidStatusAndAffordability() return if self.isDecoration: infoDict = PartyGlobals.DecorationInformationDict @@ -134,6 +157,10 @@ class PartyEditorListElement(DirectButton): self['state'] = DirectGuiGlobals.NORMAL self.partyEditor.partyPlanner.elementBuyButton['text'] = TTLocalizer.PartyPlannerBuy self.partyEditor.partyPlanner.elementBuyButton['state'] = DirectGuiGlobals.NORMAL + if self.unreleased: + self['state'] = DirectGuiGlobals.DISABLED + self.partyEditor.partyPlanner.elementBuyButton['text'] = TTLocalizer.PartyPlannerCantBuy + self.partyEditor.partyPlanner.elementBuyButton['state'] = DirectGuiGlobals.DISABLED def clicked(self, mouseEvent): PartyEditorListElement.notify.debug("Element %s's icon was clicked" % self.name) @@ -151,7 +178,7 @@ class PartyEditorListElement(DirectButton): self.activeGridElementIndex = i return True else: - self.checkSoldOutAndAffordability() + self.checkSoldOutAndPaidStatusAndAffordability() return False def released(self, mouseEvent): diff --git a/toontown/parties/PartyGlobals.py b/toontown/parties/PartyGlobals.py index f4ecd96d..2876ccb3 100755 --- a/toontown/parties/PartyGlobals.py +++ b/toontown/parties/PartyGlobals.py @@ -70,10 +70,10 @@ ChangePartyFieldErrorCode = PythonUtil.Enum(('AllOk', 'AlreadyRefunded')) ActivityTypes = PythonUtil.Enum(('HostInitiated', 'GuestInitiated', 'Continuous')) PartyGateDenialReasons = PythonUtil.Enum(('Unavailable', 'Full')) -ActivityIds = PythonUtil.Enum(('PartyCatch', - 'PartyJukebox', +ActivityIds = PythonUtil.Enum(('PartyJukebox', 'PartyCannon', 'PartyTrampoline', + 'PartyCatch', 'PartyDance', 'PartyTugOfWar', 'PartyFireworks', @@ -110,6 +110,14 @@ PartyEditorActivityOrder = [ ActivityIds.PartyClock, ActivityIds.PartyCog, ActivityIds.PartyWinterCog, ActivityIds.PartyFireworks] +UnreleasedActivityIds = (ActivityIds.PartyWinterCog, + ActivityIds.PartyValentineJukebox, + ActivityIds.PartyValentineJukebox40, + ActivityIds.PartyValentineTrampoline, + ActivityIds.PartyWinterTrampoline, + ActivityIds.PartyWinterCatch, + ActivityIds.PartyValentineDance, + ActivityIds.PartyValentineDance20) MutuallyExclusiveActivities = ((ActivityIds.PartyJukebox, ActivityIds.PartyJukebox40), (ActivityIds.PartyValentineJukebox, ActivityIds.PartyValentineJukebox40), (ActivityIds.PartyDance, ActivityIds.PartyDance20), @@ -144,22 +152,41 @@ DecorationIds = PythonUtil.Enum(('BalloonAnvil', 'HeartTarget', 'HeartBanner', 'FlyingHeart', + 'Hydra', 'BannerVictory', 'CannonVictory', 'CogStatueVictory', 'TubeCogVictory', + 'CogIceCreamVictory', 'cogIceCreamWinter', 'StageWinter', 'CogStatueWinter', 'snowman', 'snowDoodle', 'BalloonAnvilValentine')) -DECORATION_VOLUME = 1.0 -DECORATION_CUTOFF = 45 -VictoryPartyDecorationIds = frozenset([DecorationIds.BannerVictory, +TTSUnreleasedDecor = [DecorationIds.HeartTarget, + DecorationIds.HeartBanner, + DecorationIds.FlyingHeart, + DecorationIds.Hydra, + DecorationIds.BannerVictory, DecorationIds.CannonVictory, DecorationIds.CogStatueVictory, - DecorationIds.TubeCogVictory]) + DecorationIds.TubeCogVictory, + DecorationIds.CogIceCreamVictory, + DecorationIds.cogIceCreamWinter, + DecorationIds.StageWinter, + DecorationIds.CogStatueWinter, + DecorationIds.snowman, + DecorationIds.snowDoodle, + DecorationIds.BalloonAnvilValentine] +DECORATION_VOLUME = 1.0 +DECORATION_CUTOFF = 45 +VictoryPartyDecorationIds = frozenset([DecorationIds.Hydra, + DecorationIds.BannerVictory, + DecorationIds.CannonVictory, + DecorationIds.CogStatueVictory, + DecorationIds.TubeCogVictory, + DecorationIds.CogIceCreamVictory]) WinterPartyDecorationIds = frozenset([DecorationIds.cogIceCreamWinter, DecorationIds.StageWinter, DecorationIds.CogStatueWinter, @@ -171,6 +198,7 @@ ValentinePartyDecorationIds = frozenset([DecorationIds.BalloonAnvilValentine, DecorationIds.HeartTarget, DecorationIds.FlyingHeart]) ValentinePartyReplacementDecorationIds = frozenset([DecorationIds.BalloonAnvil, DecorationIds.BannerJellyBean]) +UnreleasedDecorationIds = () GoToPartyStatus = PythonUtil.Enum(('AllowedToGo', 'PartyFull', 'PrivateParty', @@ -390,6 +418,11 @@ DecorationInformationDict = {DecorationIds.BalloonAnvil: {'cost': int(10 * Party 'numberPerPurchase': 1, 'limitPerParty': 5, 'gridAsset': 'decoration_1x1'}, + DecorationIds.Hydra: {'cost': int(25 * PartyCostMultiplier), + 'gridsize': (2, 2), + 'numberPerPurchase': 1, + 'limitPerParty': 5, + 'gridAsset': 'decoration_propStage_2x2'}, DecorationIds.BannerVictory: {'cost': int(25 * PartyCostMultiplier), 'gridsize': (1, 1), 'numberPerPurchase': 1, @@ -410,6 +443,11 @@ DecorationInformationDict = {DecorationIds.BalloonAnvil: {'cost': int(10 * Party 'numberPerPurchase': 1, 'limitPerParty': 5, 'gridAsset': 'decoration_1x1'}, + DecorationIds.CogIceCreamVictory: {'cost': int(25 * PartyCostMultiplier), + 'gridsize': (1, 1), + 'numberPerPurchase': 1, + 'limitPerParty': 5, + 'gridAsset': 'decoration_1x1'}, DecorationIds.cogIceCreamWinter: {'cost': int(25 * PartyCostMultiplier), 'gridsize': (1, 1), 'numberPerPurchase': 1,