From 0c12e38c83c5e9c3070e2c3432780fb8b1651986 Mon Sep 17 00:00:00 2001 From: Little Cat Date: Thu, 29 Dec 2022 21:32:43 -0400 Subject: [PATCH 1/5] pets: Fix crash for newer panda. --- toontown/pets/PetObserve.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/toontown/pets/PetObserve.py b/toontown/pets/PetObserve.py index 9373082..0b5d096 100644 --- a/toontown/pets/PetObserve.py +++ b/toontown/pets/PetObserve.py @@ -1,5 +1,5 @@ from direct.directnotify import DirectNotifyGlobal -from direct.showbase.PythonUtil import list2dict, Enum +from enum import IntEnum from toontown.pets import PetTricks import types notify = DirectNotifyGlobal.directNotify.newCategory('PetObserve') @@ -16,8 +16,8 @@ def send(zoneIds, petObserve): messenger.send(getEventName(zoneId), [petObserve]) -Phrases = Enum('HI, BYE, YES, NO, SOOTHE, PRAISE, CRITICISM, HAPPY,SAD, ANGRY, HURRY, QUESTION, FRIENDLY, LETS_PLAY,COME, FOLLOW_ME, STAY, NEED_LAFF, NEED_GAGS, NEED_JB,GO_AWAY, DO_TRICK,') -Actions = Enum('FEED, SCRATCH,ATTENDED_START, ATTENDED_STOP,ATTENDING_START, ATTENDING_STOP,CHANGE_ZONE, LOGOUT,GARDEN') +Phrases = IntEnum('Phrases', ('HI', 'BYE', 'YES', 'NO', 'SOOTHE', 'PRAISE', 'CRITICISM', 'HAPPY', 'SAD', 'ANGRY', 'HURRY', 'QUESTION', 'FRIENDLY', 'LETS_PLAY', 'COME', 'FOLLOW_ME', 'STAY', 'NEED_LAFF', 'NEED_GAGS', 'NEED_JB','GO_AWAY', 'DO_TRICK'), start=0) +Actions = IntEnum('Actions', ('FEED', 'SCRATCH', 'ATTENDED_START', 'ATTENDED_STOP', 'ATTENDING_START', 'ATTENDING_STOP', 'CHANGE_ZONE', 'LOGOUT', 'GARDEN'), start=0) class PetObserve: @@ -76,7 +76,7 @@ class PetPhraseObserve(PetObserve): petBrain._handlePhraseObserve(self) def __repr__(self): - return '%s(%s,%s)' % (self.__class__.__name__, Phrases.getString(self.petPhrase), self.avId) + return '%s(%s,%s)' % (self.__class__.__name__, Phrases(self.petPhrase).name, self.avId) class SCObserve(PetPhraseObserve): From bd2077814362df67e9a4daf94e0046dc1312cdb4 Mon Sep 17 00:00:00 2001 From: Little Cat Date: Thu, 29 Dec 2022 22:13:42 -0400 Subject: [PATCH 2/5] spellbook: List and join ongoing boss battles. --- toontown/spellbook/MagicWordIndex.py | 65 +++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/toontown/spellbook/MagicWordIndex.py b/toontown/spellbook/MagicWordIndex.py index d88731b..94e77ef 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -13,11 +13,14 @@ import collections, types from direct.distributed.ClockDelta import * from direct.interval.IntervalGlobal import * +from direct.showbase.DirectObject import DirectObject +from direct.showbase.PythonUtil import * from panda3d.otp import NametagGroup, WhisperPopup from otp.otpbase import OTPLocalizer from otp.otpbase import OTPGlobals +from otp.otpbase.PythonUtil import * from . import MagicWordConfig import time, random, re, json @@ -25,7 +28,7 @@ import time, random, re, json magicWordIndex = collections.OrderedDict() -class MagicWord: +class MagicWord(DirectObject): notify = DirectNotifyGlobal.directNotify.newCategory('MagicWord') # Whether this Magic word should be considered "hidden" @@ -424,13 +427,12 @@ class BossBattle(MagicWord): except ValueError: start = 1 - from toontown.suit.DistributedBossCogAI import DistributedBossCogAI + from toontown.suit.DistributedBossCogAI import AllBossCogs boss = None - for do in self.air.doId2do.values(): - if isinstance(do, DistributedBossCogAI): - if do.isToonKnown(invoker.doId): - boss = do - break + for bc in AllBossCogs: + if bc.isToonKnown(invoker.doId): + boss = bc + break if command == "create": if boss: @@ -457,6 +459,8 @@ class BossBattle(MagicWord): boss.b_setState('WaitForToons') else: boss.b_setState('Frolic') + + self.acceptOnce(boss.uniqueName('BossDone'), self.__destroyBoss, extraArgs=[boss]) respText = f"Created {type.upper()} boss battle" if not start: @@ -464,6 +468,49 @@ class BossBattle(MagicWord): return respText + ", teleporting...", ["cogHQLoader", "cogHQBossBattle", "movie" if start else "teleportIn", boss.getHoodId(), boss.zoneId, 0] + elif command == "list": + # List all the ongoing boss battles. + dept2name = {'c': 'ceo', + 'l': 'cj', + 'm': 'cfo', + 's': 'vp'} + name2dept = invertDict(dept2name) + + if not AllBossCogs: + return "No ongoing boss battles." + + respText = "\nBoss Battles:" + + if type: + # Filter by boss type + dept = name2dept.get(type) + if not dept: + return f"Can't filter by unknown type \"{type.upper()}\"" + bossBattles = (boss for boss in AllBossCogs if boss.dept == dept) + else: + bossBattles = AllBossCogs + + for boss in bossBattles: + index = AllBossCogs.index(boss) + respText += f"\n - #{index}: {dept2name.get(boss.dept, '???').upper()}, {boss.zoneId}, {boss.state}, {len(boss.involvedToons)}" + return respText + + elif command == "join": + # Join an ongoing boss battle. + if boss: + return "You're already in a boss battle. Please finish this one." + try: + index = int(type) + except ValueError: + return "Boss index not an integer!" + + if index not in range(len(AllBossCogs)): + return "Index out of range!" + + boss = AllBossCogs[index] + return "Teleporting to boss battle...", ["cogHQLoader", "cogHQBossBattle", "", boss.getHoodId(), boss.zoneId, 0] + + # The following commands needs the invoker to be in a boss battle. if not boss: return "You ain't in a boss battle! Use the \"create\" command to create a boss battle." @@ -502,6 +549,10 @@ class BossBattle(MagicWord): # they can use INSIDE the battle. return respText + f"Unknown command: \"{command}\". Valid commands: \"start\", \"stop\", \"skip\", \"final\", \"kill\"." + def __destroyBoss(self, boss): + bossZone = boss.zoneId + boss.requestDelete() + self.air.deallocateZone(bossZone) # Instantiate all classes defined here to register them. # A bit hacky, but better than the old system From f1051658f27a83fed02d3e9676de6f3beeace2b8 Mon Sep 17 00:00:00 2001 From: Little Cat Date: Sat, 31 Dec 2022 03:26:27 -0400 Subject: [PATCH 3/5] otp: no delay district checking after none found. --- otp/distributed/OTPClientRepository.py | 2 +- toontown/classicchars/CharStateDatasAI.py | 1 - toontown/minigame/VineBat.py | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/otp/distributed/OTPClientRepository.py b/otp/distributed/OTPClientRepository.py index f52d47e..f169ed1 100644 --- a/otp/distributed/OTPClientRepository.py +++ b/otp/distributed/OTPClientRepository.py @@ -791,7 +791,7 @@ class OTPClientRepository(ClientRepositoryBase): def doneWait(task, self = self): self.loginFSM.request('waitForShardList') - if __dev__: + if __debug__: delay = 0.0 else: delay = 6.5 + random.random() * 2.0 diff --git a/toontown/classicchars/CharStateDatasAI.py b/toontown/classicchars/CharStateDatasAI.py index 81864bc..6e2f68b 100644 --- a/toontown/classicchars/CharStateDatasAI.py +++ b/toontown/classicchars/CharStateDatasAI.py @@ -41,7 +41,6 @@ class CharLonelyStateAI(StateData.StateData): class CharChattyStateAI(StateData.StateData): notify = DirectNotifyGlobal.directNotify.newCategory('CharChattyStateAI') - notify.setDebug(True) def __init__(self, doneEvent, character): StateData.StateData.__init__(self, doneEvent) diff --git a/toontown/minigame/VineBat.py b/toontown/minigame/VineBat.py index 23d3f1c..2f79485 100644 --- a/toontown/minigame/VineBat.py +++ b/toontown/minigame/VineBat.py @@ -7,7 +7,6 @@ from direct.interval.SoundInterval import SoundInterval class VineBat(NodePath, DirectObject): notify = DirectNotifyGlobal.directNotify.newCategory('VineBat') - notify.setDebug(True) RADIUS = 1.7 def __init__(self, batIndex, timeToTraverseField): From f7c90dde046a2a257129b70b8471fcb74f63cea0 Mon Sep 17 00:00:00 2001 From: Little Cat Date: Sat, 31 Dec 2022 03:32:03 -0400 Subject: [PATCH 4/5] battle: Dymanic boss cog round reward duration. --- toontown/battle/DistributedBattleFinalAI.py | 3 ++- toontown/suit/DistributedBossCogAI.py | 4 ++++ toontown/suit/DistributedLawbotBossAI.py | 4 ++++ toontown/suit/DistributedSellbotBossAI.py | 4 ++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/toontown/battle/DistributedBattleFinalAI.py b/toontown/battle/DistributedBattleFinalAI.py index c4579a8..bb4ef70 100644 --- a/toontown/battle/DistributedBattleFinalAI.py +++ b/toontown/battle/DistributedBattleFinalAI.py @@ -17,6 +17,7 @@ class DistributedBattleFinalAI(DistributedBattleBaseAI.DistributedBattleBaseAI): DistributedBattleBaseAI.DistributedBattleBaseAI.__init__(self, air, bossCog.zoneId, finishCallback) self.bossCogId = bossCog.doId self.battleNumber = bossCog.battleNumber + self.rewardDuration = bossCog.getEndOfBattleMovieDuration() self.battleSide = battleSide self.streetBattle = 0 self.roundCallback = roundCallback @@ -112,7 +113,7 @@ class DistributedBattleFinalAI(DistributedBattleBaseAI.DistributedBattleBaseAI): return None def enterReward(self): - self.timer.startCallback(FLOOR_REWARD_TIMEOUT + 5, self.serverRewardDone) + self.timer.startCallback(FLOOR_REWARD_TIMEOUT + self.rewardDuration, self.serverRewardDone) return None def exitReward(self): diff --git a/toontown/suit/DistributedBossCogAI.py b/toontown/suit/DistributedBossCogAI.py index 7dc5461..7f67fa4 100644 --- a/toontown/suit/DistributedBossCogAI.py +++ b/toontown/suit/DistributedBossCogAI.py @@ -524,6 +524,10 @@ class DistributedBossCogAI(DistributedAvatarAI.DistributedAvatarAI): if self.battleB: self.handleRoundDone(self.battleB, self.suitsB, self.activeSuitsB, toonIds, totalHp, deadSuits) + @staticmethod + def getEndOfBattleMovieDuration(): + return 0 + def handleBattleADone(self, zoneId, toonIds): if self.battleA: self.battleA.requestDelete() diff --git a/toontown/suit/DistributedLawbotBossAI.py b/toontown/suit/DistributedLawbotBossAI.py index ede2291..8ee332e 100644 --- a/toontown/suit/DistributedLawbotBossAI.py +++ b/toontown/suit/DistributedLawbotBossAI.py @@ -264,6 +264,10 @@ class DistributedLawbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FSM def makeBattleOneBattles(self): self.postBattleState = 'RollToBattleTwo' self.initializeBattles(1, ToontownGlobals.LawbotBossBattleOnePosHpr) + + @staticmethod + def getEndOfBattleMovieDuration(): + return 5 def generateSuits(self, battleNumber): if battleNumber == 1: diff --git a/toontown/suit/DistributedSellbotBossAI.py b/toontown/suit/DistributedSellbotBossAI.py index 9675b7e..87c6898 100644 --- a/toontown/suit/DistributedSellbotBossAI.py +++ b/toontown/suit/DistributedSellbotBossAI.py @@ -217,6 +217,10 @@ class DistributedSellbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FS def makeBattleOneBattles(self): self.postBattleState = 'RollToBattleTwo' self.initializeBattles(1, ToontownGlobals.SellbotBossBattleOnePosHpr) + + @staticmethod + def getEndOfBattleMovieDuration(): + return 5 def generateSuits(self, battleNumber): if self.nerfed: From bc5bafbacfce394417b9217b1ca8f9960bb521f6 Mon Sep 17 00:00:00 2001 From: Little Cat Date: Sat, 31 Dec 2022 05:20:47 -0400 Subject: [PATCH 5/5] spellbook: Fireworks magic word --- toontown/cogdominium/CogdoFlyingObjects.py | 1 + toontown/cogdominium/CogdoFlyingObstacles.py | 1 + toontown/effects/DistributedFireworkShowAI.py | 40 ++++++----- toontown/effects/FireworkSparkles.py | 1 + toontown/effects/Fireworks.py | 1 + toontown/effects/GlowTrail.py | 1 + toontown/effects/IceCream.py | 1 + toontown/effects/NoiseSparkles.py | 1 + toontown/effects/RingEffect.py | 1 + toontown/effects/SimpleSparkles.py | 1 + toontown/effects/SparksTrail.py | 1 + toontown/effects/SparksTrailLong.py | 1 + toontown/effects/StarBurst.py | 1 + toontown/racing/DistributedVehicle.py | 1 + toontown/racing/Piejectile.py | 1 + toontown/spellbook/MagicWordIndex.py | 67 +++++++++++++++++++ 16 files changed, 103 insertions(+), 18 deletions(-) diff --git a/toontown/cogdominium/CogdoFlyingObjects.py b/toontown/cogdominium/CogdoFlyingObjects.py index 73ac609..98fae9f 100644 --- a/toontown/cogdominium/CogdoFlyingObjects.py +++ b/toontown/cogdominium/CogdoFlyingObjects.py @@ -1,5 +1,6 @@ import random from panda3d.core import * +from panda3d.physics import * from direct.interval.IntervalGlobal import Sequence, Func, Parallel, Wait, LerpHprInterval, LerpScaleInterval, LerpFunctionInterval from otp.otpbase import OTPGlobals from toontown.toonbase import ToontownGlobals diff --git a/toontown/cogdominium/CogdoFlyingObstacles.py b/toontown/cogdominium/CogdoFlyingObstacles.py index c189998..7072ad0 100644 --- a/toontown/cogdominium/CogdoFlyingObstacles.py +++ b/toontown/cogdominium/CogdoFlyingObstacles.py @@ -4,6 +4,7 @@ from direct.interval.IntervalGlobal import LerpFunc, ActorInterval, LerpPosInter from direct.interval.MetaInterval import Sequence from direct.directutil import Mopath from panda3d.core import * +from panda3d.physics import * from toontown.toonbase import ToontownGlobals from toontown.suit import Suit from toontown.suit import SuitDNA diff --git a/toontown/effects/DistributedFireworkShowAI.py b/toontown/effects/DistributedFireworkShowAI.py index c305233..a1a6701 100644 --- a/toontown/effects/DistributedFireworkShowAI.py +++ b/toontown/effects/DistributedFireworkShowAI.py @@ -4,24 +4,23 @@ from direct.directnotify import DirectNotifyGlobal from direct.distributed import ClockDelta from .FireworkShow import FireworkShow from .FireworkShows import getShowDuration -import random from direct.task import Task class DistributedFireworkShowAI(DistributedObjectAI.DistributedObjectAI): - notify = DirectNotifyGlobal.directNotify.newCategory('DistributedFireworkShowAI') - def __init__(self, air, fireworkMgr = None): + notify = DirectNotifyGlobal.directNotify.newCategory("DistributedFireworkShowAI") + def __init__(self, air, fireworkMgr=None): DistributedObjectAI.DistributedObjectAI.__init__(self, air) self.fireworkMgr = fireworkMgr - self.eventId = None + self.eventId = None # either a holiday name constant from ToontownGlobals + # or a FireworkShows from PartyGlobals self.style = None self.timestamp = None self.throwAwayShow = FireworkShow() - return def delete(self): del self.throwAwayShow - taskMgr.remove(self.taskName('waitForShowDone')) + taskMgr.remove(self.taskName("waitForShowDone")) DistributedObjectAI.DistributedObjectAI.delete(self) def d_startShow(self, eventId, style): @@ -29,34 +28,39 @@ class DistributedFireworkShowAI(DistributedObjectAI.DistributedObjectAI): self.eventId = eventId self.style = style self.timestamp = timestamp - self.sendUpdate('startShow', (self.eventId, self.style, self.timestamp)) + self.sendUpdate("startShow", + (self.eventId, self.style, self.timestamp)) if simbase.air.config.GetBool('want-old-fireworks', 0): duration = getShowDuration(self.eventId, self.style) - taskMgr.doMethodLater(duration, self.fireworkShowDone, self.taskName('waitForShowDone')) + taskMgr.doMethodLater(duration, self.fireworkShowDone, self.taskName("waitForShowDone")) else: + duration = self.throwAwayShow.getShowDuration(self.eventId) + + assert( DistributedFireworkShowAI.notify.debug("startShow: event: %s, networkTime: %s, showDuration: %s" \ + % (self.eventId, self.timestamp, duration) ) ) + + # Add the start and postShow delays and give ample time for postshow to complete duration += 20.0 - taskMgr.doMethodLater(duration, self.fireworkShowDone, self.taskName('waitForShowDone')) + taskMgr.doMethodLater(duration, self.fireworkShowDone, self.taskName("waitForShowDone")) def fireworkShowDone(self, task): - self.notify.debug('fireworkShowDone') + self.notify.debug("fireworkShowDone") + # Tell the firework manager to stop us, we are done if self.fireworkMgr: self.fireworkMgr.stopShow(self.zoneId) return Task.done def requestFirework(self, x, y, z, style, color1, color2): avId = self.air.getAvatarIdFromSender() - self.notify.debug('requestFirework: avId: %s, style: %s' % (avId, style)) + self.notify.debug("requestFirework: avId: %s, style: %s" % (avId, style)) + # TODO: check permissions, check cost, etc if self.fireworkMgr: if self.fireworkMgr.isShowRunning(self.zoneId): self.d_shootFirework(x, y, z, style, color1, color2) + # Charge the avId some jellybeans else: - self.d_shootFirework(x, y, z, style, color1, color2) + self.d_shootFirework(x, y, z, style, color1,color2) def d_shootFirework(self, x, y, z, style, color1, color2): - self.sendUpdate('shootFirework', (x, - y, - z, - style, - color1, - color2)) + self.sendUpdate("shootFirework", (x, y, z, style, color1, color2)) diff --git a/toontown/effects/FireworkSparkles.py b/toontown/effects/FireworkSparkles.py index a35325d..41b26a1 100644 --- a/toontown/effects/FireworkSparkles.py +++ b/toontown/effects/FireworkSparkles.py @@ -1,4 +1,5 @@ from panda3d.core import * +from panda3d.physics import * from direct.interval.IntervalGlobal import * from direct.particles import ParticleEffect, Particles, ForceGroup from .EffectController import EffectController diff --git a/toontown/effects/Fireworks.py b/toontown/effects/Fireworks.py index ee0f7ae..f628c64 100644 --- a/toontown/effects/Fireworks.py +++ b/toontown/effects/Fireworks.py @@ -3,6 +3,7 @@ from direct.particles import ParticleEffect from direct.particles import Particles from direct.particles import ForceGroup from panda3d.core import * +from panda3d.physics import * import random from .FireworkGlobals import * colors = {WHITE: Vec4(1, 1, 1, 1), diff --git a/toontown/effects/GlowTrail.py b/toontown/effects/GlowTrail.py index a049897..c0e9eb4 100644 --- a/toontown/effects/GlowTrail.py +++ b/toontown/effects/GlowTrail.py @@ -1,4 +1,5 @@ from panda3d.core import * +from panda3d.physics import * from direct.interval.IntervalGlobal import * from direct.particles import ParticleEffect, Particles, ForceGroup from .PooledEffect import PooledEffect diff --git a/toontown/effects/IceCream.py b/toontown/effects/IceCream.py index 0f67fd6..d0afda9 100644 --- a/toontown/effects/IceCream.py +++ b/toontown/effects/IceCream.py @@ -1,4 +1,5 @@ from panda3d.core import * +from panda3d.physics import * from direct.interval.IntervalGlobal import * from direct.particles import ParticleEffect, Particles, ForceGroup from .EffectController import EffectController diff --git a/toontown/effects/NoiseSparkles.py b/toontown/effects/NoiseSparkles.py index 5a6b262..e9822c1 100644 --- a/toontown/effects/NoiseSparkles.py +++ b/toontown/effects/NoiseSparkles.py @@ -1,4 +1,5 @@ from panda3d.core import * +from panda3d.physics import * from direct.interval.IntervalGlobal import * from direct.particles import ParticleEffect, Particles, ForceGroup from .EffectController import EffectController diff --git a/toontown/effects/RingEffect.py b/toontown/effects/RingEffect.py index 1c844d2..27f7ed1 100644 --- a/toontown/effects/RingEffect.py +++ b/toontown/effects/RingEffect.py @@ -1,4 +1,5 @@ from panda3d.core import * +from panda3d.physics import * from direct.interval.IntervalGlobal import * from direct.particles import ParticleEffect, Particles, ForceGroup from .EffectController import EffectController diff --git a/toontown/effects/SimpleSparkles.py b/toontown/effects/SimpleSparkles.py index 8e40a22..38e3a42 100644 --- a/toontown/effects/SimpleSparkles.py +++ b/toontown/effects/SimpleSparkles.py @@ -1,4 +1,5 @@ from panda3d.core import * +from panda3d.physics import * from direct.interval.IntervalGlobal import * from direct.particles import ParticleEffect, Particles, ForceGroup from .EffectController import EffectController diff --git a/toontown/effects/SparksTrail.py b/toontown/effects/SparksTrail.py index 35323fb..dfa8420 100644 --- a/toontown/effects/SparksTrail.py +++ b/toontown/effects/SparksTrail.py @@ -1,4 +1,5 @@ from panda3d.core import * +from panda3d.physics import * from direct.interval.IntervalGlobal import * from direct.particles import ParticleEffect, Particles, ForceGroup from .PooledEffect import PooledEffect diff --git a/toontown/effects/SparksTrailLong.py b/toontown/effects/SparksTrailLong.py index b16fa58..aaf9f45 100644 --- a/toontown/effects/SparksTrailLong.py +++ b/toontown/effects/SparksTrailLong.py @@ -1,4 +1,5 @@ from panda3d.core import * +from panda3d.physics import * from direct.interval.IntervalGlobal import * from direct.particles import ParticleEffect, Particles, ForceGroup from .PooledEffect import PooledEffect diff --git a/toontown/effects/StarBurst.py b/toontown/effects/StarBurst.py index e37ac57..a68520e 100644 --- a/toontown/effects/StarBurst.py +++ b/toontown/effects/StarBurst.py @@ -1,4 +1,5 @@ from panda3d.core import * +from panda3d.physics import * from direct.interval.IntervalGlobal import * from direct.particles import ParticleEffect, Particles, ForceGroup from .EffectController import EffectController diff --git a/toontown/racing/DistributedVehicle.py b/toontown/racing/DistributedVehicle.py index e3a303e..26c6c4d 100644 --- a/toontown/racing/DistributedVehicle.py +++ b/toontown/racing/DistributedVehicle.py @@ -4,6 +4,7 @@ from direct.distributed.ClockDelta import * from direct.interval.IntervalGlobal import * from direct.gui.DirectGui import * from panda3d.core import * +from panda3d.physics import * from direct.fsm import FSM from direct.distributed import DistributedSmoothNode from direct.interval.IntervalGlobal import * diff --git a/toontown/racing/Piejectile.py b/toontown/racing/Piejectile.py index d991f96..daf603b 100644 --- a/toontown/racing/Piejectile.py +++ b/toontown/racing/Piejectile.py @@ -4,6 +4,7 @@ from direct.showbase.PythonUtil import * from direct.showbase.DirectObject import DirectObject from direct.task import Task from panda3d.core import * +from panda3d.physics import * from direct.fsm import FSM from direct.distributed import DistributedSmoothNode from otp.avatar import ShadowCaster diff --git a/toontown/spellbook/MagicWordIndex.py b/toontown/spellbook/MagicWordIndex.py index 94e77ef..8ee1667 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -554,6 +554,73 @@ class BossBattle(MagicWord): boss.requestDelete() self.air.deallocateZone(bossZone) +class Fireworks(MagicWord): + aliases = ["firework"] + desc = "Starts a firework show." + execLocation = MagicWordConfig.EXEC_LOC_SERVER + arguments = [("name", str, False, "newyear"), ("hood", str, False, "")] + + # List of firework shows currently in progress + fireworkShows = {} + + def handleWord(self, invoker, avId, toon, *args): + name = args[0] + hood = args[1] + + from toontown.toonbase import ToontownGlobals + from toontown.parties import PartyGlobals + name2showId = { + 'newyear': ToontownGlobals.NEWYEARS_FIREWORKS, + 'newyears': ToontownGlobals.NEWYEARS_FIREWORKS, + 'summer': ToontownGlobals.JULY4_FIREWORKS, + 'combo': ToontownGlobals.COMBO_FIREWORKS, + 'party': PartyGlobals.FireworkShows.Summer + } + + if name not in name2showId: + return f"Unknown firework name \"{name}\". Valid names: {list(name2showId.keys())}" + showId = name2showId[name] + + zoneToStyleDict = { + ToontownGlobals.DonaldsDock : 5, + ToontownGlobals.ToontownCentral : 0, + ToontownGlobals.TheBrrrgh : 4, + ToontownGlobals.MinniesMelodyland : 3, + ToontownGlobals.DaisyGardens : 1, + ToontownGlobals.OutdoorZone : 0, + ToontownGlobals.GoofySpeedway : 0, + ToontownGlobals.DonaldsDreamland : 2 + } + + from toontown.hood import ZoneUtil + zones = [] + if not hood: + zones = (toon.zoneId,) + elif hood == "all": + zones = zoneToStyleDict.keys() + else: + return "Missing hood argument." + + # Generate our firework shows + from toontown.effects.DistributedFireworkShowAI import DistributedFireworkShowAI + count = 0 + for zone in zones: + if zone not in self.fireworkShows: + show = DistributedFireworkShowAI(self.air, self) + show.generateWithRequired(zone) + self.fireworkShows[zone] = show + show.d_startShow(showId, zoneToStyleDict.get(zone, 0)) + count += 1 + + return f"Started firework {'show' if count == 1 else 'shows'} in {count} {'zone' if count == 1 else 'zones'}!" + + def stopShow(self, zoneId): + if zoneId in self.fireworkShows: + show = self.fireworkShows[zoneId] + show.requestDelete() + del self.fireworkShows[zoneId] + + # Instantiate all classes defined here to register them. # A bit hacky, but better than the old system for item in list(globals().values()):