From a72808ddd95899025f4554de55672949401693a8 Mon Sep 17 00:00:00 2001 From: Samuel T Date: Tue, 7 Nov 2023 17:41:13 +0000 Subject: [PATCH 01/17] golf: Address missing imports --- toontown/golf/GolfHoleBase.py | 1 + toontown/golf/GolfRewardDialog.py | 3 ++- toontown/golf/GolfScoreBoard.py | 3 ++- toontown/golf/PhysicsWorldBase.py | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/toontown/golf/GolfHoleBase.py b/toontown/golf/GolfHoleBase.py index 3de8ed8..c2a2106 100644 --- a/toontown/golf/GolfHoleBase.py +++ b/toontown/golf/GolfHoleBase.py @@ -2,6 +2,7 @@ from direct.distributed import DistributedObjectAI from direct.directnotify import DirectNotifyGlobal from toontown.toonbase import ToontownGlobals from panda3d.core import * +from panda3d.ode import OdeTriMeshData, OdeTriMeshGeom, OdeBody, OdeRayGeom from . import DistributedPhysicsWorldAI from direct.fsm.FSM import FSM from toontown.ai.ToonBarrier import * diff --git a/toontown/golf/GolfRewardDialog.py b/toontown/golf/GolfRewardDialog.py index bd90ba8..e02ed2b 100644 --- a/toontown/golf/GolfRewardDialog.py +++ b/toontown/golf/GolfRewardDialog.py @@ -1,5 +1,6 @@ from panda3d.core import * -from toontown.toonbase.ToonBaseGlobal import * +from direct.gui.DirectGui import * +from toontown.toonbase import TTLocalizer, ToontownGlobals from direct.interval.IntervalGlobal import * from direct.task import Task from direct.directnotify import DirectNotifyGlobal diff --git a/toontown/golf/GolfScoreBoard.py b/toontown/golf/GolfScoreBoard.py index 2664b22..684cb94 100644 --- a/toontown/golf/GolfScoreBoard.py +++ b/toontown/golf/GolfScoreBoard.py @@ -1,6 +1,7 @@ from panda3d.core import * -from toontown.toonbase.ToonBaseGlobal import * +from toontown.toonbase import TTLocalizer, ToontownGlobals from direct.directnotify import DirectNotifyGlobal +from direct.gui.DirectGui import * from direct.interval.IntervalGlobal import * from direct.task import Task from math import * diff --git a/toontown/golf/PhysicsWorldBase.py b/toontown/golf/PhysicsWorldBase.py index aa45cfa..d83d36c 100644 --- a/toontown/golf/PhysicsWorldBase.py +++ b/toontown/golf/PhysicsWorldBase.py @@ -2,6 +2,7 @@ from direct.distributed import DistributedObject from direct.directnotify import DirectNotifyGlobal from toontown.toonbase import ToontownGlobals from panda3d.core import * +from panda3d.ode import OdeWorld, OdeSimpleSpace, OdeJointGroup, OdePlaneGeom, OdeBody, OdeMass, OdeSphereGeom, OdeBoxGeom, OdeSliderJoint, OdeTriMeshData, OdeTriMeshGeom, OdeHingeJoint from math import * import math from direct.fsm.FSM import FSM From c0de7f671335dbf5660bb4ed4c613edc18720293 Mon Sep 17 00:00:00 2001 From: Samuel T Date: Tue, 7 Nov 2023 18:54:54 +0000 Subject: [PATCH 02/17] spellbook: Golf related magic words for easier debugging --- toontown/spellbook/MagicWordIndex.py | 47 +++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/toontown/spellbook/MagicWordIndex.py b/toontown/spellbook/MagicWordIndex.py index a2b7a5f..a905558 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -330,7 +330,52 @@ class AbortMinigame(MagicWord): def handleWord(self, invoker, avId, toon, *args): messenger.send("minigameAbort") - return "Requested minigame abort." + return "Requested minigame abort." + +class SkipMiniGolfHole(MagicWord): + aliases = ["skipgolfhole", "skiphole"] + desc = "Skips the current golf hole." + execLocation = MagicWordConfig.EXEC_LOC_SERVER + arguments = [] + + def handleWord(self, invoker, avId, toon, *args): + from toontown.golf.DistributedGolfCourseAI import DistributedGolfCourseAI + course = None + for do in simbase.air.doId2do.values(): + if isinstance(do, DistributedGolfCourseAI): + if invoker.doId in do.avIdList: + course = do + break + if not course: + return "You aren't in a golf course!" + + if course.isPlayingLastHole(): + course.demand('WaitReward') + else: + course.holeOver() + + return "Skipped the current hole." + +class AbortGolfCourse(MagicWord): + aliases = ["abortminigolf", "abortgolf", "abortcourse", "leavegolf", "leavecourse"] + desc = "Aborts the current golf course." + execLocation = MagicWordConfig.EXEC_LOC_SERVER + arguments = [] + + def handleWord(self, invoker, avId, toon, *args): + from toontown.golf.DistributedGolfCourseAI import DistributedGolfCourseAI + course = None + for do in simbase.air.doId2do.values(): + if isinstance(do, DistributedGolfCourseAI): + if invoker.doId in do.avIdList: + course = do + break + if not course: + return "You aren't in a golf course!" + + course.setCourseAbort() + + return "Aborted golf course." class Minigame(MagicWord): aliases = ["mg"] From 0ceb3383e51ca604af31930d7f99436ea4540256 Mon Sep 17 00:00:00 2001 From: Samuel T Date: Tue, 7 Nov 2023 18:56:24 +0000 Subject: [PATCH 03/17] Revert "spellbook: Golf related magic words for easier debugging" This reverts commit c0de7f671335dbf5660bb4ed4c613edc18720293. --- toontown/spellbook/MagicWordIndex.py | 47 +--------------------------- 1 file changed, 1 insertion(+), 46 deletions(-) diff --git a/toontown/spellbook/MagicWordIndex.py b/toontown/spellbook/MagicWordIndex.py index a905558..a2b7a5f 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -330,52 +330,7 @@ class AbortMinigame(MagicWord): def handleWord(self, invoker, avId, toon, *args): messenger.send("minigameAbort") - return "Requested minigame abort." - -class SkipMiniGolfHole(MagicWord): - aliases = ["skipgolfhole", "skiphole"] - desc = "Skips the current golf hole." - execLocation = MagicWordConfig.EXEC_LOC_SERVER - arguments = [] - - def handleWord(self, invoker, avId, toon, *args): - from toontown.golf.DistributedGolfCourseAI import DistributedGolfCourseAI - course = None - for do in simbase.air.doId2do.values(): - if isinstance(do, DistributedGolfCourseAI): - if invoker.doId in do.avIdList: - course = do - break - if not course: - return "You aren't in a golf course!" - - if course.isPlayingLastHole(): - course.demand('WaitReward') - else: - course.holeOver() - - return "Skipped the current hole." - -class AbortGolfCourse(MagicWord): - aliases = ["abortminigolf", "abortgolf", "abortcourse", "leavegolf", "leavecourse"] - desc = "Aborts the current golf course." - execLocation = MagicWordConfig.EXEC_LOC_SERVER - arguments = [] - - def handleWord(self, invoker, avId, toon, *args): - from toontown.golf.DistributedGolfCourseAI import DistributedGolfCourseAI - course = None - for do in simbase.air.doId2do.values(): - if isinstance(do, DistributedGolfCourseAI): - if invoker.doId in do.avIdList: - course = do - break - if not course: - return "You aren't in a golf course!" - - course.setCourseAbort() - - return "Aborted golf course." + return "Requested minigame abort." class Minigame(MagicWord): aliases = ["mg"] From 83c8ee19b792a252a2ef3e63ae8e5d8b970f180f Mon Sep 17 00:00:00 2001 From: Samuel T Date: Tue, 7 Nov 2023 23:31:00 +0000 Subject: [PATCH 04/17] Revert "Revert "spellbook: Golf related magic words for easier debugging"" This reverts commit 0ceb3383e51ca604af31930d7f99436ea4540256. --- toontown/spellbook/MagicWordIndex.py | 47 +++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/toontown/spellbook/MagicWordIndex.py b/toontown/spellbook/MagicWordIndex.py index a2b7a5f..a905558 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -330,7 +330,52 @@ class AbortMinigame(MagicWord): def handleWord(self, invoker, avId, toon, *args): messenger.send("minigameAbort") - return "Requested minigame abort." + return "Requested minigame abort." + +class SkipMiniGolfHole(MagicWord): + aliases = ["skipgolfhole", "skiphole"] + desc = "Skips the current golf hole." + execLocation = MagicWordConfig.EXEC_LOC_SERVER + arguments = [] + + def handleWord(self, invoker, avId, toon, *args): + from toontown.golf.DistributedGolfCourseAI import DistributedGolfCourseAI + course = None + for do in simbase.air.doId2do.values(): + if isinstance(do, DistributedGolfCourseAI): + if invoker.doId in do.avIdList: + course = do + break + if not course: + return "You aren't in a golf course!" + + if course.isPlayingLastHole(): + course.demand('WaitReward') + else: + course.holeOver() + + return "Skipped the current hole." + +class AbortGolfCourse(MagicWord): + aliases = ["abortminigolf", "abortgolf", "abortcourse", "leavegolf", "leavecourse"] + desc = "Aborts the current golf course." + execLocation = MagicWordConfig.EXEC_LOC_SERVER + arguments = [] + + def handleWord(self, invoker, avId, toon, *args): + from toontown.golf.DistributedGolfCourseAI import DistributedGolfCourseAI + course = None + for do in simbase.air.doId2do.values(): + if isinstance(do, DistributedGolfCourseAI): + if invoker.doId in do.avIdList: + course = do + break + if not course: + return "You aren't in a golf course!" + + course.setCourseAbort() + + return "Aborted golf course." class Minigame(MagicWord): aliases = ["mg"] From a36f07d1110f0f332b66cd800ac66715f27cdef7 Mon Sep 17 00:00:00 2001 From: Samuel T Date: Wed, 8 Nov 2023 13:53:50 +0000 Subject: [PATCH 05/17] spellbook: Add another alias to SkipMiniGolfHole --- toontown/spellbook/MagicWordIndex.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/toontown/spellbook/MagicWordIndex.py b/toontown/spellbook/MagicWordIndex.py index a905558..0553ffb 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -176,7 +176,6 @@ class MagicWord(DirectObject): def handleWord(self, invoker, avId, toon, *args): raise NotImplementedError - class SetHP(MagicWord): aliases = ["hp", "setlaff", "laff"] desc = "Sets the target's current laff." @@ -200,7 +199,6 @@ class SetHP(MagicWord): toon.b_setHp(hp) return "{}'s laff has been set to {}.".format(toon.getName(), hp) - class SetMaxHP(MagicWord): aliases = ["maxhp", "setmaxlaff", "maxlaff"] desc = "Sets the target's max laff." @@ -219,7 +217,6 @@ class SetMaxHP(MagicWord): toon.toonUp(maxhp) return "{}'s max laff has been set to {}.".format(toon.getName(), maxhp) - class ToggleOobe(MagicWord): aliases = ["oobe"] desc = "Toggles the out of body experience mode, which lets you move the camera freely." @@ -232,7 +229,6 @@ class ToggleOobe(MagicWord): base.oobe() return "Oobe mode has been toggled." - class ToggleRun(MagicWord): aliases = ["run"] desc = "Toggles run mode, which gives you a faster running speed." @@ -308,8 +304,6 @@ class Inventory(MagicWord): toon.d_setInventory(toon.inventory.makeNetString()) return ("Zeroing inventory for " + toon.getName() + ".") - - class SetPinkSlips(MagicWord): # this command gives the target toon the specified amount of pink slips # default is 255 @@ -333,7 +327,7 @@ class AbortMinigame(MagicWord): return "Requested minigame abort." class SkipMiniGolfHole(MagicWord): - aliases = ["skipgolfhole", "skiphole"] + aliases = ["skipgolfhole", "skipgolf", "skiphole"] desc = "Skips the current golf hole." execLocation = MagicWordConfig.EXEC_LOC_SERVER arguments = [] From 01751ad10ec097203beeb220d68176b83df07d41 Mon Sep 17 00:00:00 2001 From: Samuel T Date: Wed, 8 Nov 2023 17:43:41 +0000 Subject: [PATCH 06/17] spellbook: Teleport and GlobalTP magic words --- toontown/spellbook/MagicWordIndex.py | 68 ++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 3 deletions(-) diff --git a/toontown/spellbook/MagicWordIndex.py b/toontown/spellbook/MagicWordIndex.py index 0553ffb..3f5b62d 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -335,7 +335,7 @@ class SkipMiniGolfHole(MagicWord): def handleWord(self, invoker, avId, toon, *args): from toontown.golf.DistributedGolfCourseAI import DistributedGolfCourseAI course = None - for do in simbase.air.doId2do.values(): + for do in simbase.air.doId2do.values(): # For all doids, check whether it's a golf course, then check if our target is part of it. if isinstance(do, DistributedGolfCourseAI): if invoker.doId in do.avIdList: course = do @@ -343,7 +343,7 @@ class SkipMiniGolfHole(MagicWord): if not course: return "You aren't in a golf course!" - if course.isPlayingLastHole(): + if course.isPlayingLastHole(): # If the Toon is on the final hole, calling holeOver() will softlock, so instead we move onto the reward screen. course.demand('WaitReward') else: course.holeOver() @@ -359,7 +359,7 @@ class AbortGolfCourse(MagicWord): def handleWord(self, invoker, avId, toon, *args): from toontown.golf.DistributedGolfCourseAI import DistributedGolfCourseAI course = None - for do in simbase.air.doId2do.values(): + for do in simbase.air.doId2do.values(): # For all doids, check whether it's a golf course, then check if our target is part of it. if isinstance(do, DistributedGolfCourseAI): if invoker.doId in do.avIdList: course = do @@ -643,6 +643,68 @@ class BossBattle(MagicWord): boss.requestDelete() self.air.deallocateZone(bossZone) +class GlobalTeleport(MagicWord): + aliases = ["globaltp", "tpaccess"] + desc = "Enables teleport access to all zones." + execLocation = MagicWordConfig.EXEC_LOC_SERVER + + def handleWord(self, invoker, avId, toon, *args): + from toontown.toonbase import ToontownGlobals + toon.b_setHoodsVisited(ToontownGlobals.HoodsForTeleportAll) + toon.b_setTeleportAccess(ToontownGlobals.HoodsForTeleportAll) + return f"Enabled teleport access to all zones for {toon.getName()}." + +class Teleport(MagicWord): + aliases = ["tp", "goto"] + desc = "Teleport to a specified zone." + execLocation = MagicWordConfig.EXEC_LOC_CLIENT + arguments = [("zoneName", str, False, '')] + + def handleWord(self, invoker, avId, toon, *args): + from toontown.hood import ZoneUtil + from toontown.toonbase import ToontownGlobals + zoneName = args[0] + place = base.cr.playGame.getPlace() + + # Can add stuff like streets to this too if you wanted, but if you do you'll want it to be a valid zone on that street. eg: 2100 is invalid, but any value 2101 to 2156 is fine. + # so if you wanted to add a silly street key, theroetically you could do something like this: 'sillystreet': ToontownGlobals.SillyStreet +1, + zoneName2Id = {'ttc': ToontownGlobals.ToontownCentral, + 'dd': ToontownGlobals.DonaldsDock, + 'dg': ToontownGlobals.DaisyGardens, + 'mml': ToontownGlobals.MinniesMelodyland, + 'tb': ToontownGlobals.TheBrrrgh, + 'ddl': ToontownGlobals.DonaldsDreamland, + 'gs': ToontownGlobals.GoofySpeedway, + 'oz': ToontownGlobals.OutdoorZone, + 'aa': ToontownGlobals.OutdoorZone, + 'gz': ToontownGlobals.GolfZone, + 'sbhq': ToontownGlobals.SellbotHQ, + 'factory': ToontownGlobals.SellbotFactoryExt, + 'cbhq': ToontownGlobals.CashbotHQ, + 'lbhq': ToontownGlobals.LawbotHQ, + 'bbhq': ToontownGlobals.BossbotHQ} + + try: + zone = zoneName2Id[zoneName] + except KeyError: + return "Unknown zone name!" + + hood = ZoneUtil.getHoodId(zone) + + try: + place.requestLeave({'loader': ZoneUtil.getBranchLoaderName(zone), + 'where': ZoneUtil.getToonWhereName(zone), + 'how': 'teleportIn', + 'hoodId': hood, + 'zoneId': zone, + 'shardId': None, + 'avId': -1}) + except Exception: # Most likely cause is the place the person is in has no teleportOut state, for example, boss lobbies. + place.fsm.request('DFAReject') # We have to do this, or the Toon will be stuck. + return f"Unable to teleport {toon.getName()} to zone {zone}." + + return f"Successfully teleporting {toon.getName()} to zone {zone}." + class Fireworks(MagicWord): aliases = ["firework"] desc = "Starts a firework show." From 48d88e1afe9367f4feceaeaa7d293a86de4e6a4c Mon Sep 17 00:00:00 2001 From: Samuel T Date: Wed, 8 Nov 2023 18:54:04 +0000 Subject: [PATCH 07/17] spellbook: ToggleSleep magic word --- etc/toon.dc | 1 + otp/avatar/LocalAvatar.py | 3 +++ toontown/spellbook/MagicWordIndex.py | 9 +++++++++ toontown/toon/DistributedToon.py | 6 ++++++ toontown/toon/DistributedToonAI.py | 3 +++ 5 files changed, 22 insertions(+) diff --git a/etc/toon.dc b/etc/toon.dc index 9e0fef8..5c4ed03 100755 --- a/etc/toon.dc +++ b/etc/toon.dc @@ -618,6 +618,7 @@ dclass DistributedToon : DistributedPlayer { setNeverStartedPartyRefunded(uint64, int8, uint16) ownrecv; setDISLname(string) ram; setDISLid(uint32) ram db airecv; + toggleSleep() ownrecv; }; dclass DistributedCCharBase : DistributedObject { diff --git a/otp/avatar/LocalAvatar.py b/otp/avatar/LocalAvatar.py index 2b689cc..b8e04ec 100644 --- a/otp/avatar/LocalAvatar.py +++ b/otp/avatar/LocalAvatar.py @@ -61,6 +61,7 @@ class LocalAvatar(DistributedAvatar.DistributedAvatar, DistributedSmoothNode.Dis self.soundRun = None self.soundWalk = None self.sleepFlag = 0 + self.noSleep = 0 self.isDisguised = 0 self.movingFlag = 0 self.swimmingFlag = 0 @@ -984,6 +985,8 @@ class LocalAvatar(DistributedAvatar.DistributedAvatar, DistributedSmoothNode.Dis return def gotoSleep(self): + if self.noSleep: + return if not self.sleepFlag: self.b_setAnimState('Sleep', self.animMultiplier) self.sleepFlag = 1 diff --git a/toontown/spellbook/MagicWordIndex.py b/toontown/spellbook/MagicWordIndex.py index 3f5b62d..1e22159 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -705,6 +705,15 @@ class Teleport(MagicWord): return f"Successfully teleporting {toon.getName()} to zone {zone}." +class ToggleSleep(MagicWord): + aliases = ["sleep", "nosleep", "neversleep", "togglesleeping", "insomnia"] + desc = "Toggles sleeping for the target." + execLocation = MagicWordConfig.EXEC_LOC_SERVER + + def handleWord(self, invoker, avId, toon, *args): + toon.d_toggleSleep() + return f"Toggled sleeping for {toon.getName()}." + class Fireworks(MagicWord): aliases = ["firework"] desc = "Starts a firework show." diff --git a/toontown/toon/DistributedToon.py b/toontown/toon/DistributedToon.py index 0602211..35f1b60 100644 --- a/toontown/toon/DistributedToon.py +++ b/toontown/toon/DistributedToon.py @@ -2589,3 +2589,9 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute def getTransitioning(self): return self.transitioning + + def toggleSleep(self): + if base.localAvatar.noSleep: + base.localAvatar.noSleep = 0 + else: + base.localAvatar.noSleep = 1 \ No newline at end of file diff --git a/toontown/toon/DistributedToonAI.py b/toontown/toon/DistributedToonAI.py index cf78958..79b9990 100644 --- a/toontown/toon/DistributedToonAI.py +++ b/toontown/toon/DistributedToonAI.py @@ -4129,6 +4129,9 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo zoneId]) self.air.send(dg) + def d_toggleSleep(self): + self.sendUpdate('toggleSleep', []) + @staticmethod def staticGetLogicalZoneChangeAllEvent(): return 'DOLogicalChangeZone-all' From e16f614b398154c57a9a306c35a2f1e93d14cedb Mon Sep 17 00:00:00 2001 From: Samuel T Date: Wed, 8 Nov 2023 23:56:52 +0000 Subject: [PATCH 08/17] spellbook: Update Teleport magic word to be server-sided --- etc/toon.dc | 1 + toontown/spellbook/MagicWordIndex.py | 20 +++----------------- toontown/toon/DistributedToon.py | 16 +++++++++++++++- toontown/toon/DistributedToonAI.py | 3 +++ 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/etc/toon.dc b/etc/toon.dc index 5c4ed03..ade48bb 100755 --- a/etc/toon.dc +++ b/etc/toon.dc @@ -619,6 +619,7 @@ dclass DistributedToon : DistributedPlayer { setDISLname(string) ram; setDISLid(uint32) ram db airecv; toggleSleep() ownrecv; + magicWordTeleport(uint32) ownrecv; }; dclass DistributedCCharBase : DistributedObject { diff --git a/toontown/spellbook/MagicWordIndex.py b/toontown/spellbook/MagicWordIndex.py index 1e22159..3ac5a78 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -657,14 +657,12 @@ class GlobalTeleport(MagicWord): class Teleport(MagicWord): aliases = ["tp", "goto"] desc = "Teleport to a specified zone." - execLocation = MagicWordConfig.EXEC_LOC_CLIENT + execLocation = MagicWordConfig.EXEC_LOC_SERVER arguments = [("zoneName", str, False, '')] def handleWord(self, invoker, avId, toon, *args): - from toontown.hood import ZoneUtil from toontown.toonbase import ToontownGlobals zoneName = args[0] - place = base.cr.playGame.getPlace() # Can add stuff like streets to this too if you wanted, but if you do you'll want it to be a valid zone on that street. eg: 2100 is invalid, but any value 2101 to 2156 is fine. # so if you wanted to add a silly street key, theroetically you could do something like this: 'sillystreet': ToontownGlobals.SillyStreet +1, @@ -688,22 +686,10 @@ class Teleport(MagicWord): zone = zoneName2Id[zoneName] except KeyError: return "Unknown zone name!" - - hood = ZoneUtil.getHoodId(zone) - try: - place.requestLeave({'loader': ZoneUtil.getBranchLoaderName(zone), - 'where': ZoneUtil.getToonWhereName(zone), - 'how': 'teleportIn', - 'hoodId': hood, - 'zoneId': zone, - 'shardId': None, - 'avId': -1}) - except Exception: # Most likely cause is the place the person is in has no teleportOut state, for example, boss lobbies. - place.fsm.request('DFAReject') # We have to do this, or the Toon will be stuck. - return f"Unable to teleport {toon.getName()} to zone {zone}." + toon.d_magicWordTeleport(zone) - return f"Successfully teleporting {toon.getName()} to zone {zone}." + return f"Requested to teleport {toon.getName()} to zone {zone}." class ToggleSleep(MagicWord): aliases = ["sleep", "nosleep", "neversleep", "togglesleeping", "insomnia"] diff --git a/toontown/toon/DistributedToon.py b/toontown/toon/DistributedToon.py index 35f1b60..56410d4 100644 --- a/toontown/toon/DistributedToon.py +++ b/toontown/toon/DistributedToon.py @@ -2594,4 +2594,18 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute if base.localAvatar.noSleep: base.localAvatar.noSleep = 0 else: - base.localAvatar.noSleep = 1 \ No newline at end of file + base.localAvatar.noSleep = 1 + + def magicWordTeleport(self, zone): + hood = ZoneUtil.getHoodId(zone) + place = base.cr.playGame.getPlace() + try: + place.requestLeave({'loader': ZoneUtil.getBranchLoaderName(zone), + 'where': ZoneUtil.getToonWhereName(zone), + 'how': 'teleportIn', + 'hoodId': hood, + 'zoneId': zone, + 'shardId': None, + 'avId': -1}) + except Exception: # Most likely cause is the place the person is in has no teleportOut state, for example, boss lobbies. + place.fsm.request('DFAReject') # We have to do this, or the Toon will be stuck. \ No newline at end of file diff --git a/toontown/toon/DistributedToonAI.py b/toontown/toon/DistributedToonAI.py index 79b9990..a1cb233 100644 --- a/toontown/toon/DistributedToonAI.py +++ b/toontown/toon/DistributedToonAI.py @@ -4132,6 +4132,9 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo def d_toggleSleep(self): self.sendUpdate('toggleSleep', []) + def d_magicWordTeleport(self, zone): + self.sendUpdate('magicWordTeleport', [zone]) + @staticmethod def staticGetLogicalZoneChangeAllEvent(): return 'DOLogicalChangeZone-all' From df3a690e51d3467358a5ac7f70e9de1f7141050c Mon Sep 17 00:00:00 2001 From: Samuel T Date: Thu, 9 Nov 2023 00:08:47 +0000 Subject: [PATCH 09/17] toon: Sleep deprivation (seriously, why did I do it like that) --- toontown/toon/DistributedToon.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/toontown/toon/DistributedToon.py b/toontown/toon/DistributedToon.py index 56410d4..8e85357 100644 --- a/toontown/toon/DistributedToon.py +++ b/toontown/toon/DistributedToon.py @@ -2591,10 +2591,7 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute return self.transitioning def toggleSleep(self): - if base.localAvatar.noSleep: - base.localAvatar.noSleep = 0 - else: - base.localAvatar.noSleep = 1 + base.localAvatar.noSleep = not base.localAvatar.noSleep def magicWordTeleport(self, zone): hood = ZoneUtil.getHoodId(zone) From 3be7219d68f7466737e688228ae3980716605936 Mon Sep 17 00:00:00 2001 From: Samuel T Date: Thu, 9 Nov 2023 00:51:31 +0000 Subject: [PATCH 10/17] spellbook: Immortal and Ghost magic words --- toontown/spellbook/MagicWordIndex.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/toontown/spellbook/MagicWordIndex.py b/toontown/spellbook/MagicWordIndex.py index 3ac5a78..a9cbd26 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -699,6 +699,25 @@ class ToggleSleep(MagicWord): def handleWord(self, invoker, avId, toon, *args): toon.d_toggleSleep() return f"Toggled sleeping for {toon.getName()}." + +class ToggleImmortal(MagicWord): + aliases = ["immortal", "invincible", "invulnerable"] + desc = "Toggle immortal mode. This makes the Toon immune to damage." + execLocation = MagicWordConfig.EXEC_LOC_SERVER + + def handleWord(self, invoker, avId, toon, *args): + toon.setImmortalMode(not toon.immortalMode) + return f"Toggled immortal mode for {toon.getName()}" + +class ToggleGhost(MagicWord): + aliases = ["ghost", "invisible", "spy"] + desc = "Toggle ghost mode." + execLocation = MagicWordConfig.EXEC_LOC_SERVER + + def handleWord(self, invoker, avId, toon, *args): + # 1 is for the attic, 2 enables you to see yourself other ghost toons. 0 is off. + toon.b_setGhostMode(2 if not toon.ghostMode else 0) # As it's primarily for moderation purposes, we set it to 2 here, or 0 if it's already on. + return f"Toggled ghost mode for {toon.getName()}" class Fireworks(MagicWord): aliases = ["firework"] From 50601fc92dc0c2224247aca76a29dd8f4a8f94ae Mon Sep 17 00:00:00 2001 From: Samuel T Date: Thu, 9 Nov 2023 01:15:48 +0000 Subject: [PATCH 11/17] spellbook: SetGM magic word --- toontown/spellbook/MagicWordIndex.py | 16 ++++++++++++++++ toontown/toon/DistributedToon.py | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/toontown/spellbook/MagicWordIndex.py b/toontown/spellbook/MagicWordIndex.py index a9cbd26..4cf08d8 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -718,6 +718,22 @@ class ToggleGhost(MagicWord): # 1 is for the attic, 2 enables you to see yourself other ghost toons. 0 is off. toon.b_setGhostMode(2 if not toon.ghostMode else 0) # As it's primarily for moderation purposes, we set it to 2 here, or 0 if it's already on. return f"Toggled ghost mode for {toon.getName()}" + +class SetGM(MagicWord): + aliases = ["icon", "seticon", "gm", "gmicon", "setgmicon"] + desc = "Sets the GM icon on the target." + execLocation = MagicWordConfig.EXEC_LOC_SERVER + arguments = [("iconRequest", int, False, 0),] + + def handleWord(self, invoker, avId, toon, *args): + from toontown.toonbase import TTLocalizer + + iconRequest = args[0] + if iconRequest > len(TTLocalizer.GM_NAMES) or iconRequest < 0: + return "Invalid GM icon ID!" + + toon.b_setGM(iconRequest) + return f"GM icon set to {iconRequest} for {toon.getName()}" class Fireworks(MagicWord): aliases = ["firework"] diff --git a/toontown/toon/DistributedToon.py b/toontown/toon/DistributedToon.py index 8e85357..ed7282a 100644 --- a/toontown/toon/DistributedToon.py +++ b/toontown/toon/DistributedToon.py @@ -2528,7 +2528,7 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute self._handleGMName() def _handleGMName(self): - name = self.name + name = self._name self.setDisplayName(name) if self._isGM: self.setNametagStyle(5) From eb2f347f09e758369359b31ae20eeae8a74917e6 Mon Sep 17 00:00:00 2001 From: Samuel T Date: Thu, 9 Nov 2023 01:18:57 +0000 Subject: [PATCH 12/17] spellbook: Fix Toon keeping old GM icon on switch --- toontown/spellbook/MagicWordIndex.py | 1 + 1 file changed, 1 insertion(+) diff --git a/toontown/spellbook/MagicWordIndex.py b/toontown/spellbook/MagicWordIndex.py index 4cf08d8..fe26ce2 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -732,6 +732,7 @@ class SetGM(MagicWord): if iconRequest > len(TTLocalizer.GM_NAMES) or iconRequest < 0: return "Invalid GM icon ID!" + toon.b_setGM(0) # Reset it first, otherwise the Toon keeps the old icon, but the name still changes. toon.b_setGM(iconRequest) return f"GM icon set to {iconRequest} for {toon.getName()}" From 00573d0975eeaf0680ec2f104a0f9e393cc0aa63 Mon Sep 17 00:00:00 2001 From: Samuel T Date: Thu, 9 Nov 2023 01:55:00 +0000 Subject: [PATCH 13/17] spellbook: SetMaxCarry magic word --- toontown/spellbook/MagicWordIndex.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/toontown/spellbook/MagicWordIndex.py b/toontown/spellbook/MagicWordIndex.py index fe26ce2..dacdf5e 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -735,6 +735,21 @@ class SetGM(MagicWord): toon.b_setGM(0) # Reset it first, otherwise the Toon keeps the old icon, but the name still changes. toon.b_setGM(iconRequest) return f"GM icon set to {iconRequest} for {toon.getName()}" + +class SetMaxCarry(MagicWord): + aliases = ["gagpouch", "pouch", "gagcapacity"] + desc = "Set a Toon's gag pouch size." + execLocation = MagicWordConfig.EXEC_LOC_SERVER + arguments = [("pouchSize", int, True)] + + def handleWord(self, invoker, avId, toon, *args): + pouchSize = args[0] + + if pouchSize > 255 or pouchSize < 0: + return "Specified pouch size must be between 1 and 255." + + toon.b_setMaxCarry(pouchSize) + return f"Set gag pouch size to {pouchSize} for {toon.getName()}" class Fireworks(MagicWord): aliases = ["firework"] From 3880f2049f48980f3e904fbd7db86500a6d9f2dd Mon Sep 17 00:00:00 2001 From: Samuel T Date: Thu, 9 Nov 2023 02:07:17 +0000 Subject: [PATCH 14/17] spellbook: Fix AI crash caused by using invalid BossBattle command --- toontown/spellbook/MagicWordIndex.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toontown/spellbook/MagicWordIndex.py b/toontown/spellbook/MagicWordIndex.py index dacdf5e..bfcea3a 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -636,7 +636,7 @@ class BossBattle(MagicWord): # The create command is already described when the invoker is not in a battle. These are the commands # they can use INSIDE the battle. - return respText + f"Unknown command: \"{command}\". Valid commands: \"start\", \"stop\", \"skip\", \"final\", \"kill\"." + return f"Unknown command: \"{command}\". Valid commands: \"start\", \"stop\", \"skip\", \"final\", \"kill\"." def __destroyBoss(self, boss): bossZone = boss.zoneId From 736ced4aecf1b937429982ed7fd250fc6a20fe1d Mon Sep 17 00:00:00 2001 From: Samuel T Date: Thu, 9 Nov 2023 02:38:31 +0000 Subject: [PATCH 15/17] avatar: Merged gotoSleep if statement --- otp/avatar/LocalAvatar.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/otp/avatar/LocalAvatar.py b/otp/avatar/LocalAvatar.py index b8e04ec..8af6d4b 100644 --- a/otp/avatar/LocalAvatar.py +++ b/otp/avatar/LocalAvatar.py @@ -985,9 +985,7 @@ class LocalAvatar(DistributedAvatar.DistributedAvatar, DistributedSmoothNode.Dis return def gotoSleep(self): - if self.noSleep: - return - if not self.sleepFlag: + if not self.sleepFlag and not self.noSleep: self.b_setAnimState('Sleep', self.animMultiplier) self.sleepFlag = 1 From ff220f7f5fe77a2cc94f5128584655d17162fa6b Mon Sep 17 00:00:00 2001 From: Samuel T Date: Thu, 9 Nov 2023 02:55:44 +0000 Subject: [PATCH 16/17] spellbook: ToggleInstantKill magic word --- toontown/battle/BattleCalculatorAI.py | 6 +++++- toontown/spellbook/MagicWordIndex.py | 9 +++++++++ toontown/toon/DistributedToonAI.py | 4 ++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/toontown/battle/BattleCalculatorAI.py b/toontown/battle/BattleCalculatorAI.py index 9dd3f5a..0ed39aa 100644 --- a/toontown/battle/BattleCalculatorAI.py +++ b/toontown/battle/BattleCalculatorAI.py @@ -74,7 +74,8 @@ class BattleCalculatorAI: return (1, 95) else: return (0, 0) - if self.toonsAlwaysHit: + toon = self.battle.getToon(attackIndex) + if self.toonsAlwaysHit or toon.instantKillMode: return (1, 95) elif self.toonsAlwaysMiss: return (0, 0) @@ -529,6 +530,9 @@ class BattleCalculatorAI: if attackLevel == -1 and not atkTrack == FIRE: result = LURE_SUCCEEDED elif atkTrack != TRAP: + toon = self.battle.getToon(toonId) + if atkTrack != HEAL and toon.instantKillMode: + attackDamage = 32767 result = attackDamage if atkTrack == HEAL: if not self.__attackHasHit(attack, suit=0): diff --git a/toontown/spellbook/MagicWordIndex.py b/toontown/spellbook/MagicWordIndex.py index bfcea3a..4009900 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -750,6 +750,15 @@ class SetMaxCarry(MagicWord): toon.b_setMaxCarry(pouchSize) return f"Set gag pouch size to {pouchSize} for {toon.getName()}" + +class ToggleInstantKill(MagicWord): + aliases = ["instantkill", "instakill"] + desc = "Toggle the ability to instantly kill a Cog with any gag." + execLocation = MagicWordConfig.EXEC_LOC_SERVER + + def handleWord(self, invoker, avId, toon, *args): + toon.setInstantKillMode(not toon.instantKillMode) + return f"Toggled instant-kill mode for {toon.getName()}" class Fireworks(MagicWord): aliases = ["firework"] diff --git a/toontown/toon/DistributedToonAI.py b/toontown/toon/DistributedToonAI.py index a1cb233..af8f667 100644 --- a/toontown/toon/DistributedToonAI.py +++ b/toontown/toon/DistributedToonAI.py @@ -155,6 +155,7 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo self.savedCheesyExpireTime = 0 self.ghostMode = 0 self.immortalMode = 0 + self.instantKillMode = 0 self.numPies = 0 self.pieType = 0 self._isGM = False @@ -2375,6 +2376,9 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo def setImmortalMode(self, flag): self.immortalMode = flag + def setInstantKillMode(self, flag): + self.instantKillMode = flag + def b_setSpeedChatStyleIndex(self, index): self.setSpeedChatStyleIndex(index) self.d_setSpeedChatStyleIndex(index) From ecf87d34b3e0e4057245374671694fc169c651bd Mon Sep 17 00:00:00 2001 From: Samuel T Date: Thu, 9 Nov 2023 03:46:35 +0000 Subject: [PATCH 17/17] spellbook: Fix Teleport command redundancies, add support for BossBattle targeting --- etc/toon.dc | 1 - toontown/spellbook/MagicWordIndex.py | 9 ++++----- .../spellbook/ToontownMagicWordManager.py | 19 +++++++++++-------- toontown/toon/DistributedToon.py | 16 +--------------- toontown/toon/DistributedToonAI.py | 3 --- 5 files changed, 16 insertions(+), 32 deletions(-) diff --git a/etc/toon.dc b/etc/toon.dc index ade48bb..5c4ed03 100755 --- a/etc/toon.dc +++ b/etc/toon.dc @@ -619,7 +619,6 @@ dclass DistributedToon : DistributedPlayer { setDISLname(string) ram; setDISLid(uint32) ram db airecv; toggleSleep() ownrecv; - magicWordTeleport(uint32) ownrecv; }; dclass DistributedCCharBase : DistributedObject { diff --git a/toontown/spellbook/MagicWordIndex.py b/toontown/spellbook/MagicWordIndex.py index 4009900..543e02b 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -555,7 +555,7 @@ class BossBattle(MagicWord): if not start: respText += " in Frolic state" - return respText + ", teleporting...", ["cogHQLoader", "cogHQBossBattle", "movie" if start else "teleportIn", boss.getHoodId(), boss.zoneId, 0] + return respText + ", teleporting...", toon.doId, ["cogHQLoader", "cogHQBossBattle", "movie" if start else "teleportIn", boss.getHoodId(), boss.zoneId, 0] elif command == "list": # List all the ongoing boss battles. @@ -597,7 +597,7 @@ class BossBattle(MagicWord): return "Index out of range!" boss = AllBossCogs[index] - return "Teleporting to boss battle...", ["cogHQLoader", "cogHQBossBattle", "", boss.getHoodId(), boss.zoneId, 0] + return "Teleporting to boss battle...", toon.doId, ["cogHQLoader", "cogHQBossBattle", "", boss.getHoodId(), boss.zoneId, 0] # The following commands needs the invoker to be in a boss battle. @@ -661,6 +661,7 @@ class Teleport(MagicWord): arguments = [("zoneName", str, False, '')] def handleWord(self, invoker, avId, toon, *args): + from toontown.hood import ZoneUtil from toontown.toonbase import ToontownGlobals zoneName = args[0] @@ -686,10 +687,8 @@ class Teleport(MagicWord): zone = zoneName2Id[zoneName] except KeyError: return "Unknown zone name!" - - toon.d_magicWordTeleport(zone) - return f"Requested to teleport {toon.getName()} to zone {zone}." + return f"Requested to teleport {toon.getName()} to zone {zone}.", toon.doId, [ZoneUtil.getBranchLoaderName(zone), ZoneUtil.getToonWhereName(zone), "", ZoneUtil.getHoodId(zone), zone, 0] class ToggleSleep(MagicWord): aliases = ["sleep", "nosleep", "neversleep", "togglesleeping", "insomnia"] diff --git a/toontown/spellbook/ToontownMagicWordManager.py b/toontown/spellbook/ToontownMagicWordManager.py index 9a53d36..d8a6c2f 100644 --- a/toontown/spellbook/ToontownMagicWordManager.py +++ b/toontown/spellbook/ToontownMagicWordManager.py @@ -275,11 +275,14 @@ class ToontownMagicWordManager(DistributedObject.DistributedObject): hoodId = place.loader.hood.id if avId == 0: avId = -1 - place.fsm.forceTransition('teleportOut', - [{"loader": loaderId, - "where": whereId, - "how": how, - "hoodId": hoodId, - "zoneId": zoneId, - "shardId": None, - "avId": avId}]) + try: + place.fsm.forceTransition('teleportOut', + [{"loader": loaderId, + "where": whereId, + "how": how, + "hoodId": hoodId, + "zoneId": zoneId, + "shardId": None, + "avId": avId}]) + except Exception: # Most likely cause is the place the avatar is in has no teleportOut state, for example, boss lobbies. + place.fsm.request('DFAReject') # We have to do this, or the avatar will be stuck. diff --git a/toontown/toon/DistributedToon.py b/toontown/toon/DistributedToon.py index ed7282a..3a52f75 100644 --- a/toontown/toon/DistributedToon.py +++ b/toontown/toon/DistributedToon.py @@ -2591,18 +2591,4 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute return self.transitioning def toggleSleep(self): - base.localAvatar.noSleep = not base.localAvatar.noSleep - - def magicWordTeleport(self, zone): - hood = ZoneUtil.getHoodId(zone) - place = base.cr.playGame.getPlace() - try: - place.requestLeave({'loader': ZoneUtil.getBranchLoaderName(zone), - 'where': ZoneUtil.getToonWhereName(zone), - 'how': 'teleportIn', - 'hoodId': hood, - 'zoneId': zone, - 'shardId': None, - 'avId': -1}) - except Exception: # Most likely cause is the place the person is in has no teleportOut state, for example, boss lobbies. - place.fsm.request('DFAReject') # We have to do this, or the Toon will be stuck. \ No newline at end of file + base.localAvatar.noSleep = not base.localAvatar.noSleep \ No newline at end of file diff --git a/toontown/toon/DistributedToonAI.py b/toontown/toon/DistributedToonAI.py index af8f667..b5489fe 100644 --- a/toontown/toon/DistributedToonAI.py +++ b/toontown/toon/DistributedToonAI.py @@ -4136,9 +4136,6 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo def d_toggleSleep(self): self.sendUpdate('toggleSleep', []) - def d_magicWordTeleport(self, zone): - self.sendUpdate('magicWordTeleport', [zone]) - @staticmethod def staticGetLogicalZoneChangeAllEvent(): return 'DOLogicalChangeZone-all'