From 65526aa1cd780686a34029599797d1c3044bfb32 Mon Sep 17 00:00:00 2001 From: "Erica M. (\"Loonatic\")" Date: Fri, 11 Feb 2022 13:26:25 -0600 Subject: [PATCH 01/48] convert: Convert all instances of jpg&rgb texture calls in codebase to png --- toontown/battle/BattleProps.py | 4 +- toontown/catalog/CatalogFlooringItem.py | 48 +- toontown/catalog/CatalogMouldingItem.py | 28 +- toontown/catalog/CatalogWainscotingItem.py | 10 +- toontown/catalog/CatalogWallpaperItem.py | 268 ++--- toontown/char/Char.py | 12 +- .../cogdominium/DistributedCogdoBarrel.py | 4 +- toontown/estate/DistributedToonStatuary.py | 10 +- toontown/hood/StreetSign.py | 2 +- toontown/minigame/DistributedTargetGame.py | 8 +- toontown/minigame/Purchase.py | 6 +- toontown/minigame/SwingVine.py | 2 +- .../DistributedPartyJukebox40Activity.py | 2 +- ...tributedPartyValentineJukebox40Activity.py | 2 +- ...istributedPartyValentineJukeboxActivity.py | 2 +- ...ributedPartyValentineTrampolineActivity.py | 2 +- ...stributedPartyVictoryTrampolineActivity.py | 2 +- ...istributedPartyWinterTrampolineActivity.py | 2 +- toontown/parties/PartyCogActivity.py | 3 +- toontown/pets/Pet.py | 8 +- toontown/pets/PetDNA.py | 38 +- toontown/racing/DistributedRace.py | 2 +- toontown/racing/Kart.py | 6 +- toontown/racing/KartShopGui.py | 20 +- toontown/shtiker/InGameNewsFrame.py | 2 +- toontown/shtiker/IssueFrame.py | 2 +- toontown/shtiker/KartPage.py | 14 +- toontown/shtiker/PhotoAlbumPage.py | 2 +- toontown/suit/Suit.py | 48 +- toontown/toon/Toon.py | 2 +- toontown/toon/ToonDNA.py | 976 +++++++++--------- toontown/toon/ToonHead.py | 18 +- toontown/town/Street.py | 4 +- 33 files changed, 778 insertions(+), 781 deletions(-) diff --git a/toontown/battle/BattleProps.py b/toontown/battle/BattleProps.py index d717b37..2e2b866 100644 --- a/toontown/battle/BattleProps.py +++ b/toontown/battle/BattleProps.py @@ -324,12 +324,12 @@ class PropPool: lips.setPos(0, 0, -3.04) lips.flattenMedium() elif name == '5dollar': - tex = loader.loadTexture('phase_5/maps/dollar_5.jpg') + tex = loader.loadTexture('phase_5/maps/dollar_5.png') tex.setMinfilter(Texture.FTLinearMipmapLinear) tex.setMagfilter(Texture.FTLinear) self.props[name].setTexture(tex, 1) elif name == '10dollar': - tex = loader.loadTexture('phase_5/maps/dollar_10.jpg') + tex = loader.loadTexture('phase_5/maps/dollar_10.png') tex.setMinfilter(Texture.FTLinearMipmapLinear) tex.setMagfilter(Texture.FTLinear) self.props[name].setTexture(tex, 1) diff --git a/toontown/catalog/CatalogFlooringItem.py b/toontown/catalog/CatalogFlooringItem.py index 984b135..d39c611 100644 --- a/toontown/catalog/CatalogFlooringItem.py +++ b/toontown/catalog/CatalogFlooringItem.py @@ -2,30 +2,30 @@ from .CatalogSurfaceItem import * FTTextureName = 0 FTColor = 1 FTBasePrice = 2 -FlooringTypes = {1000: ('phase_5.5/maps/floor_wood_neutral.jpg', CTBasicWoodColorOnWhite, 150), - 1010: ('phase_5.5/maps/flooring_carpetA_neutral.jpg', CTFlatColorDark, 150), - 1020: ('phase_4/maps/flooring_tile_neutral.jpg', CTFlatColorDark, 150), - 1030: ('phase_5.5/maps/flooring_tileB2.jpg', None, 150), - 1040: ('phase_4/maps/grass.jpg', None, 150), - 1050: ('phase_4/maps/floor_tile_brick_diagonal2.jpg', None, 150), - 1060: ('phase_4/maps/floor_tile_brick_diagonal.jpg', None, 150), - 1070: ('phase_4/maps/plazz_tile.jpg', None, 150), - 1080: ('phase_4/maps/sidewalk.jpg', CTFlatColorDark, 150), - 1090: ('phase_3.5/maps/boardwalk_floor.jpg', None, 150), - 1100: ('phase_3.5/maps/dustroad.jpg', None, 150), - 1110: ('phase_5.5/maps/floor_woodtile_neutral.jpg', CTBasicWoodColorOnWhite, 150), - 1120: ('phase_5.5/maps/floor_tile_neutral.jpg', CTBasicWoodColorOnWhite + CTFlatColorDark, 150), - 1130: ('phase_5.5/maps/floor_tile_honeycomb_neutral.jpg', CTBasicWoodColorOnWhite, 150), - 1140: ('phase_5.5/maps/UWwaterFloor1.jpg', None, 150), - 1150: ('phase_5.5/maps/UWtileFloor4.jpg', None, 150), - 1160: ('phase_5.5/maps/UWtileFloor3.jpg', None, 150), - 1170: ('phase_5.5/maps/UWtileFloor2.jpg', None, 150), - 1180: ('phase_5.5/maps/UWtileFloor1.jpg', None, 150), - 1190: ('phase_5.5/maps/UWsandyFloor1.jpg', None, 150), - 10000: ('phase_5.5/maps/floor_icecube.jpg', CTWhite, 225), - 10010: ('phase_5.5/maps/floor_snow.jpg', CTWhite, 225), - 11000: ('phase_5.5/maps/StPatsFloor1.jpg', CTWhite, 225), - 11010: ('phase_5.5/maps/StPatsFloor2.jpg', CTWhite, 225)} +FlooringTypes = {1000: ('phase_5.5/maps/floor_wood_neutral.png', CTBasicWoodColorOnWhite, 150), + 1010: ('phase_5.5/maps/flooring_carpetA_neutral.png', CTFlatColorDark, 150), + 1020: ('phase_4/maps/flooring_tile_neutral.png', CTFlatColorDark, 150), + 1030: ('phase_5.5/maps/flooring_tileB2.png', None, 150), + 1040: ('phase_4/maps/grass.png', None, 150), + 1050: ('phase_4/maps/floor_tile_brick_diagonal2.png', None, 150), + 1060: ('phase_4/maps/floor_tile_brick_diagonal.png', None, 150), + 1070: ('phase_4/maps/plazz_tile.png', None, 150), + 1080: ('phase_4/maps/sidewalk.png', CTFlatColorDark, 150), + 1090: ('phase_3.5/maps/boardwalk_floor.png', None, 150), + 1100: ('phase_3.5/maps/dustroad.png', None, 150), + 1110: ('phase_5.5/maps/floor_woodtile_neutral.png', CTBasicWoodColorOnWhite, 150), + 1120: ('phase_5.5/maps/floor_tile_neutral.png', CTBasicWoodColorOnWhite + CTFlatColorDark, 150), + 1130: ('phase_5.5/maps/floor_tile_honeycomb_neutral.png', CTBasicWoodColorOnWhite, 150), + 1140: ('phase_5.5/maps/UWwaterFloor1.png', None, 150), + 1150: ('phase_5.5/maps/UWtileFloor4.png', None, 150), + 1160: ('phase_5.5/maps/UWtileFloor3.png', None, 150), + 1170: ('phase_5.5/maps/UWtileFloor2.png', None, 150), + 1180: ('phase_5.5/maps/UWtileFloor1.png', None, 150), + 1190: ('phase_5.5/maps/UWsandyFloor1.png', None, 150), + 10000: ('phase_5.5/maps/floor_icecube.png', CTWhite, 225), + 10010: ('phase_5.5/maps/floor_snow.png', CTWhite, 225), + 11000: ('phase_5.5/maps/StPatsFloor1.png', CTWhite, 225), + 11010: ('phase_5.5/maps/StPatsFloor2.png', CTWhite, 225)} class CatalogFlooringItem(CatalogSurfaceItem): diff --git a/toontown/catalog/CatalogMouldingItem.py b/toontown/catalog/CatalogMouldingItem.py index ca976d0..e3e3349 100644 --- a/toontown/catalog/CatalogMouldingItem.py +++ b/toontown/catalog/CatalogMouldingItem.py @@ -2,20 +2,20 @@ from .CatalogSurfaceItem import * MTTextureName = 0 MTColor = 1 MTBasePrice = 2 -MouldingTypes = {1000: ('phase_3.5/maps/molding_wood1.jpg', CTBasicWoodColorOnWhite, 150), - 1010: ('phase_5.5/maps/bd_grey_border1.jpg', CTFlatColorDark, 150), - 1020: ('phase_5.5/maps/dental_Border_wood_neutral.jpg', CTFlatColorDark, 150), - 1030: ('phase_5.5/maps/littleFlowers_border.jpg', CTWhite, 150), - 1040: ('phase_5.5/maps/littleFlowers_border_neutral.jpg', CTFlatColorDark, 150), - 1050: ('phase_5.5/maps/ladybugs2_Border.jpg', CTFlatColorDark, 150), - 1060: ('phase_5.5/maps/bd_grey_border1.jpg', CTValentinesColors, 150), - 1070: ('phase_5.5/maps/bd_grey_border1.jpg', CTUnderwaterColors, 150), - 1080: ('phase_5.5/maps/tt_t_ara_int_border_winterLights1.jpg', CTWhite, 150), - 1085: ('phase_5.5/maps/tt_t_ara_int_border_winterLights2.jpg', CTWhite, 150), - 1090: ('phase_5.5/maps/tt_t_ara_int_border_winterLights3.jpg', CTWhite, 150), - 1100: ('phase_5.5/maps/tt_t_ara_int_border_valentine_cupid.jpg', CTWhite, 150), - 1110: ('phase_5.5/maps/tt_t_ara_int_border_valentine_heart1.jpg', CTWhite, 150), - 1120: ('phase_5.5/maps/tt_t_ara_int_border_valentine_heart2.jpg', CTWhite, 150)} +MouldingTypes = {1000: ('phase_3.5/maps/molding_wood1.png', CTBasicWoodColorOnWhite, 150), + 1010: ('phase_5.5/maps/bd_grey_border1.png', CTFlatColorDark, 150), + 1020: ('phase_5.5/maps/dental_Border_wood_neutral.png', CTFlatColorDark, 150), + 1030: ('phase_5.5/maps/littleFlowers_border.png', CTWhite, 150), + 1040: ('phase_5.5/maps/littleFlowers_border_neutral.png', CTFlatColorDark, 150), + 1050: ('phase_5.5/maps/ladybugs2_Border.png', CTFlatColorDark, 150), + 1060: ('phase_5.5/maps/bd_grey_border1.png', CTValentinesColors, 150), + 1070: ('phase_5.5/maps/bd_grey_border1.png', CTUnderwaterColors, 150), + 1080: ('phase_5.5/maps/tt_t_ara_int_border_winterLights1.png', CTWhite, 150), + 1085: ('phase_5.5/maps/tt_t_ara_int_border_winterLights2.png', CTWhite, 150), + 1090: ('phase_5.5/maps/tt_t_ara_int_border_winterLights3.png', CTWhite, 150), + 1100: ('phase_5.5/maps/tt_t_ara_int_border_valentine_cupid.png', CTWhite, 150), + 1110: ('phase_5.5/maps/tt_t_ara_int_border_valentine_heart1.png', CTWhite, 150), + 1120: ('phase_5.5/maps/tt_t_ara_int_border_valentine_heart2.png', CTWhite, 150)} class CatalogMouldingItem(CatalogSurfaceItem): diff --git a/toontown/catalog/CatalogWainscotingItem.py b/toontown/catalog/CatalogWainscotingItem.py index b6b9cad..e86b801 100644 --- a/toontown/catalog/CatalogWainscotingItem.py +++ b/toontown/catalog/CatalogWainscotingItem.py @@ -2,11 +2,11 @@ from .CatalogSurfaceItem import * WSTTextureName = 0 WSTColor = 1 WSTBasePrice = 2 -WainscotingTypes = {1000: ('phase_3.5/maps/wall_paper_b3.jpg', CTFlatColorDark, 200), - 1010: ('phase_5.5/maps/wall_paper_b4_greyscale.jpg', CTBasicWoodColorOnWhite, 200), - 1020: ('phase_5.5/maps/wainscotings_neutral.jpg', CTBasicWoodColorOnWhite, 200), - 1030: ('phase_3.5/maps/wall_paper_b3.jpg', CTValentinesColors, 200), - 1040: ('phase_3.5/maps/wall_paper_b3.jpg', CTUnderwaterColors, 200)} +WainscotingTypes = {1000: ('phase_3.5/maps/wall_paper_b3.png', CTFlatColorDark, 200), + 1010: ('phase_5.5/maps/wall_paper_b4_greyscale.png', CTBasicWoodColorOnWhite, 200), + 1020: ('phase_5.5/maps/wainscotings_neutral.png', CTBasicWoodColorOnWhite, 200), + 1030: ('phase_3.5/maps/wall_paper_b3.png', CTValentinesColors, 200), + 1040: ('phase_3.5/maps/wall_paper_b3.png', CTUnderwaterColors, 200)} class CatalogWainscotingItem(CatalogSurfaceItem): diff --git a/toontown/catalog/CatalogWallpaperItem.py b/toontown/catalog/CatalogWallpaperItem.py index fd0f107..1659e6e 100644 --- a/toontown/catalog/CatalogWallpaperItem.py +++ b/toontown/catalog/CatalogWallpaperItem.py @@ -13,242 +13,242 @@ All = (1000, 1050, 1060, 1070) -WallpaperTypes = {1000: ('phase_5.5/maps/flat_wallpaper1.jpg', +WallpaperTypes = {1000: ('phase_5.5/maps/flat_wallpaper1.png', CTFlatColor, (0, 1000), 180), - 1100: ('phase_5.5/maps/big_stripes1.jpg', + 1100: ('phase_5.5/maps/big_stripes1.png', CTWhite, (0, 1010), 180), - 1110: ('phase_5.5/maps/big_stripes2.jpg', + 1110: ('phase_5.5/maps/big_stripes2.png', CTWhite, (0, 1040), 180), - 1120: ('phase_5.5/maps/big_stripes3.jpg', + 1120: ('phase_5.5/maps/big_stripes3.png', CTWhite, (0, 1030), 180), - 1130: ('phase_5.5/maps/big_stripes4.jpg', + 1130: ('phase_5.5/maps/big_stripes4.png', CTWhite, (0, 1010), 180), - 1140: ('phase_5.5/maps/big_stripes5.jpg', + 1140: ('phase_5.5/maps/big_stripes5.png', CTWhite, (0, 1020), 180), - 1150: ('phase_5.5/maps/big_stripes6.jpg', + 1150: ('phase_5.5/maps/big_stripes6.png', CTWhite, (0, 1020), 180), - 1200: ('phase_5.5/maps/stripeB1.jpg', + 1200: ('phase_5.5/maps/stripeB1.png', CTWhite, (0, 1000), 180), - 1210: ('phase_5.5/maps/stripeB2.jpg', + 1210: ('phase_5.5/maps/stripeB2.png', CTWhite, (0, 1000), 180), - 1220: ('phase_5.5/maps/stripeB3.jpg', + 1220: ('phase_5.5/maps/stripeB3.png', CTWhite, (0, 1000), 180), - 1230: ('phase_5.5/maps/stripeB4.jpg', + 1230: ('phase_5.5/maps/stripeB4.png', CTWhite, (0, 1000), 180), - 1240: ('phase_3.5/maps/stripeB5.jpg', + 1240: ('phase_3.5/maps/stripeB5.png', CTWhite, (0, 1000), 180), - 1250: ('phase_5.5/maps/stripeB6.jpg', + 1250: ('phase_5.5/maps/stripeB6.png', CTWhite, (0, 1000), 180), - 1260: ('phase_5.5/maps/stripeB7.jpg', + 1260: ('phase_5.5/maps/stripeB7.png', CTWhite, (0, 1000), 180), - 1300: ('phase_5.5/maps/squiggle1.jpg', + 1300: ('phase_5.5/maps/squiggle1.png', CTWhite, (0,), 180), - 1310: ('phase_5.5/maps/squiggle2.jpg', + 1310: ('phase_5.5/maps/squiggle2.png', CTWhite, (0,), 180), - 1320: ('phase_5.5/maps/squiggle3.jpg', + 1320: ('phase_5.5/maps/squiggle3.png', CTWhite, (0,), 180), - 1330: ('phase_5.5/maps/squiggle4.jpg', + 1330: ('phase_5.5/maps/squiggle4.png', CTWhite, (0,), 180), - 1340: ('phase_5.5/maps/squiggle5.jpg', + 1340: ('phase_5.5/maps/squiggle5.png', CTWhite, (0,), 180), - 1350: ('phase_5.5/maps/squiggle6.jpg', + 1350: ('phase_5.5/maps/squiggle6.png', CTWhite, (0,), 180), - 1400: ('phase_5.5/maps/stripes_cyan.jpg', + 1400: ('phase_5.5/maps/stripes_cyan.png', CTWhite, (0, 1000), 180), - 1410: ('phase_5.5/maps/stripes_green.jpg', + 1410: ('phase_5.5/maps/stripes_green.png', CTWhite, (0, 1000), 180), - 1420: ('phase_5.5/maps/stripes_magenta.jpg', + 1420: ('phase_5.5/maps/stripes_magenta.png', CTWhite, (0, 1000), 180), - 1430: ('phase_5.5/maps/two_stripes1.jpg', + 1430: ('phase_5.5/maps/two_stripes1.png', CTWhite, (0, 1000), 180), - 1440: ('phase_5.5/maps/two_stripes2.jpg', + 1440: ('phase_5.5/maps/two_stripes2.png', CTWhite, (0, 1000), 180), - 1450: ('phase_5.5/maps/two_stripes3.jpg', + 1450: ('phase_5.5/maps/two_stripes3.png', CTWhite, (0, 1000), 180), - 1500: ('phase_5.5/maps/leaves1.jpg', + 1500: ('phase_5.5/maps/leaves1.png', CTWhite, (0,), 180), - 1510: ('phase_5.5/maps/leaves2.jpg', + 1510: ('phase_5.5/maps/leaves2.png', CTWhite, (0,), 180), - 1520: ('phase_5.5/maps/leaves3.jpg', + 1520: ('phase_5.5/maps/leaves3.png', CTWhite, (0,), 180), - 1600: ('phase_5.5/maps/diamonds2_cherries.jpg', + 1600: ('phase_5.5/maps/diamonds2_cherries.png', CTWhite, (0, 1000), 180), - 1610: ('phase_5.5/maps/diamonds3_cherries.jpg', + 1610: ('phase_5.5/maps/diamonds3_cherries.png', CTWhite, (0, 1000), 180), - 1620: ('phase_5.5/maps/diamonds3_cherry.jpg', + 1620: ('phase_5.5/maps/diamonds3_cherry.png', CTWhite, (0, 1000), 180), - 1630: ('phase_5.5/maps/diamonds4_cherries.jpg', + 1630: ('phase_5.5/maps/diamonds4_cherries.png', CTWhite, (0, 1000), 180), - 1640: ('phase_5.5/maps/diamonds4_cherry.jpg', + 1640: ('phase_5.5/maps/diamonds4_cherry.png', CTWhite, (0, 1000), 180), - 1650: ('phase_5.5/maps/diamonds5_cherries.jpg', + 1650: ('phase_5.5/maps/diamonds5_cherries.png', CTWhite, (0, 1000), 180), - 1660: ('phase_5.5/maps/diamonds6_cherry.jpg', + 1660: ('phase_5.5/maps/diamonds6_cherry.png', CTWhite, (0, 1000), 180), - 1700: ('phase_5.5/maps/moon1.jpg', + 1700: ('phase_5.5/maps/moon1.png', CTWhite, (0,), 180), - 1710: ('phase_5.5/maps/moon2.jpg', + 1710: ('phase_5.5/maps/moon2.png', CTWhite, (0,), 180), - 1720: ('phase_5.5/maps/moon3.jpg', + 1720: ('phase_5.5/maps/moon3.png', CTWhite, (0,), 180), - 1730: ('phase_5.5/maps/moon4.jpg', + 1730: ('phase_5.5/maps/moon4.png', CTWhite, (0,), 180), - 1740: ('phase_5.5/maps/moon5.jpg', + 1740: ('phase_5.5/maps/moon5.png', CTWhite, (0,), 180), - 1750: ('phase_5.5/maps/moon6.jpg', + 1750: ('phase_5.5/maps/moon6.png', CTWhite, (0,), 180), - 1760: ('phase_5.5/maps/moon7.jpg', + 1760: ('phase_5.5/maps/moon7.png', CTWhite, (0,), 180), - 1800: ('phase_5.5/maps/stars1.jpg', + 1800: ('phase_5.5/maps/stars1.png', CTWhite, (0,), 180), - 1810: ('phase_5.5/maps/stars2.jpg', + 1810: ('phase_5.5/maps/stars2.png', (CT_BLUE2, CT_PINK2, CT_RED), (0,), 180), - 1820: ('phase_5.5/maps/stars3.jpg', + 1820: ('phase_5.5/maps/stars3.png', (CT_BLUE2, CT_PINK2, CT_RED, CT_WHITE), (0,), 180), - 1830: ('phase_5.5/maps/stars4.jpg', + 1830: ('phase_5.5/maps/stars4.png', CTWhite, (0,), 180), - 1840: ('phase_5.5/maps/stars5.jpg', + 1840: ('phase_5.5/maps/stars5.png', CTWhite, (0,), 180), - 1850: ('phase_5.5/maps/stars6.jpg', + 1850: ('phase_5.5/maps/stars6.png', CTWhite, (0,), 180), - 1860: ('phase_5.5/maps/stars7.jpg', + 1860: ('phase_5.5/maps/stars7.png', (CT_BEIGE2, CT_WHITE), (0,), 180), - 1900: ('phase_5.5/maps/wall_paper_flower1.jpg', + 1900: ('phase_5.5/maps/wall_paper_flower1.png', CTWhite, (0, 1000), 180), - 1910: ('phase_5.5/maps/wall_paper_flower2.jpg', + 1910: ('phase_5.5/maps/wall_paper_flower2.png', CTWhite, (0, 1000), 180), - 1920: ('phase_5.5/maps/wall_paper_flower3.jpg', + 1920: ('phase_5.5/maps/wall_paper_flower3.png', CTWhite, (0, 1000), 180), - 1930: ('phase_5.5/maps/wall_paper_flower4.jpg', + 1930: ('phase_5.5/maps/wall_paper_flower4.png', CTWhite, (0, 1000), 180), - 1940: ('phase_5.5/maps/wall_paper_flower5.jpg', + 1940: ('phase_5.5/maps/wall_paper_flower5.png', CTWhite, (0, 1000), 180), - 1950: ('phase_5.5/maps/wall_paper_flower6.jpg', + 1950: ('phase_5.5/maps/wall_paper_flower6.png', CTWhite, (0, 1000), 180), - 2000: ('phase_5.5/maps/flat_wallpaper1.jpg', + 2000: ('phase_5.5/maps/flat_wallpaper1.png', (CT_BEIGE, CT_BEIGE2, CT_RED), (1050,), 180), - 2010: ('phase_5.5/maps/flat_wallpaper1.jpg', + 2010: ('phase_5.5/maps/flat_wallpaper1.png', (CT_BLUE2, CT_PINK2), (1060,), 180), - 2020: ('phase_5.5/maps/flat_wallpaper1.jpg', + 2020: ('phase_5.5/maps/flat_wallpaper1.png', (CT_BEIGE2, CT_BLUE2, CT_PINK2, @@ -256,207 +256,207 @@ WallpaperTypes = {1000: ('phase_5.5/maps/flat_wallpaper1.jpg', CT_RED), (1070,), 180), - 2100: ('phase_5.5/maps/big_stripes1.jpg', + 2100: ('phase_5.5/maps/big_stripes1.png', CTWhite, (1050,), 180), - 2110: ('phase_5.5/maps/big_stripes2.jpg', + 2110: ('phase_5.5/maps/big_stripes2.png', CTWhite, (1050,), 180), - 2120: ('phase_5.5/maps/big_stripes3.jpg', + 2120: ('phase_5.5/maps/big_stripes3.png', CTWhite, (1060,), 180), - 2130: ('phase_5.5/maps/big_stripes3.jpg', + 2130: ('phase_5.5/maps/big_stripes3.png', CTWhite, (1070,), 180), - 2140: ('phase_5.5/maps/big_stripes6.jpg', + 2140: ('phase_5.5/maps/big_stripes6.png', CTWhite, (1070,), 180), - 2200: ('phase_5.5/maps/wall_paper_car.jpg', + 2200: ('phase_5.5/maps/wall_paper_car.png', CTWhite, (0, 1000), 180), - 2210: ('phase_5.5/maps/wall_paper_car_neutral.jpg', + 2210: ('phase_5.5/maps/wall_paper_car_neutral.png', CTFlatColor, (0, 1000), 180), - 2300: ('phase_5.5/maps/wall_paper_football_neutral.jpg', + 2300: ('phase_5.5/maps/wall_paper_football_neutral.png', CTFlatColor, (0, 1080), 180), - 2400: ('phase_5.5/maps/wall_paper_clouds.jpg', + 2400: ('phase_5.5/maps/wall_paper_clouds.png', CTWhite, (0, 1000), 180), - 2500: ('phase_5.5/maps/wall_paper_vine_neutral.jpg', + 2500: ('phase_5.5/maps/wall_paper_vine_neutral.png', CTFlatColorAll, (0, 1090), 180), - 2600: ('phase_5.5/maps/basket.jpg', + 2600: ('phase_5.5/maps/basket.png', CTWhite, (0, 1000), 180), - 2610: ('phase_5.5/maps/basket_neutral.jpg', + 2610: ('phase_5.5/maps/basket_neutral.png', CTFlatColor, (0, 1000), 180), - 2700: ('phase_5.5/maps/doll.jpg', + 2700: ('phase_5.5/maps/doll.png', CTWhite, (0, 1000, 1110), 180), - 2710: ('phase_5.5/maps/doll_neutral.jpg', + 2710: ('phase_5.5/maps/doll_neutral.png', CTFlatColor, (0, 1100, 1110), 180), - 2800: ('phase_5.5/maps/littleFlowers.jpg', + 2800: ('phase_5.5/maps/littleFlowers.png', CTWhite, (0, 1000), 180), - 2810: ('phase_5.5/maps/littleFlowers_neutral.jpg', + 2810: ('phase_5.5/maps/littleFlowers_neutral.png', CTFlatColor, (0, 1000), 180), - 2900: ('phase_5.5/maps/UWwallPaperAngelFish.jpg', + 2900: ('phase_5.5/maps/UWwallPaperAngelFish.png', CTWhite, (0, 1120, 1160), 180), - 2910: ('phase_5.5/maps/UWwallPaperAngelFishColor.jpg', + 2910: ('phase_5.5/maps/UWwallPaperAngelFishColor.png', CTWhite, (0, 1120, 1160), 180), - 2920: ('phase_5.5/maps/UWwallPaperBubbles.jpg', + 2920: ('phase_5.5/maps/UWwallPaperBubbles.png', CTWhite, (0, 1120, 1160), 180), - 2930: ('phase_5.5/maps/UWwallPaperBubbles2.jpg', + 2930: ('phase_5.5/maps/UWwallPaperBubbles2.png', CTWhite, (0, 1120, 1160), 180), - 2940: ('phase_5.5/maps/UWwallPaperGreenFish.jpg', + 2940: ('phase_5.5/maps/UWwallPaperGreenFish.png', CTWhite, (0, 1120, 1160), 180), - 2950: ('phase_5.5/maps/UWwallPaperRedFish.jpg', + 2950: ('phase_5.5/maps/UWwallPaperRedFish.png', CTWhite, (0, 1120, 1160), 180), - 2960: ('phase_5.5/maps/UWwallPaperSea_horse.jpg', + 2960: ('phase_5.5/maps/UWwallPaperSea_horse.png', CTWhite, (0, 1120, 1160), 180), - 2970: ('phase_5.5/maps/UWwallPaperShells.jpg', + 2970: ('phase_5.5/maps/UWwallPaperShells.png', CTWhite, (0, 1140, 1150), 180), - 2980: ('phase_5.5/maps/UWwaterFloor1.jpg', + 2980: ('phase_5.5/maps/UWwaterFloor1.png', (CT_WHITE, CT_PALE_GREEN, CT_LIGHT_BLUE), (0,), 180), - 3000: ('phase_5.5/maps/UWwallPaperBubbles.jpg', + 3000: ('phase_5.5/maps/UWwallPaperBubbles.png', CTWhite, (0, 1120, 1160), 180), - 3100: ('phase_5.5/maps/UWwallPaperBubbles2.jpg', + 3100: ('phase_5.5/maps/UWwallPaperBubbles2.png', CTWhite, (0, 1120, 1160), 180), - 3200: ('phase_5.5/maps/UWwallPaperGreenFish.jpg', + 3200: ('phase_5.5/maps/UWwallPaperGreenFish.png', CTWhite, (0, 1120, 1160), 180), - 3300: ('phase_5.5/maps/UWwallPaperRedFish.jpg', + 3300: ('phase_5.5/maps/UWwallPaperRedFish.png', CTWhite, (0, 1120, 1160), 180), - 3400: ('phase_5.5/maps/UWwallPaperSea_horse.jpg', + 3400: ('phase_5.5/maps/UWwallPaperSea_horse.png', CTWhite, (0, 1120, 1160), 180), - 3500: ('phase_5.5/maps/UWwallPaperShells.jpg', + 3500: ('phase_5.5/maps/UWwallPaperShells.png', (CT_WHITE, CT_SEA_GREEN, CT_LIGHT_BLUE), (0, 1140, 1150), 180), - 3600: ('phase_5.5/maps/UWwaterFloor1.jpg', + 3600: ('phase_5.5/maps/UWwaterFloor1.png', (CT_WHITE, CT_PALE_GREEN, CT_LIGHT_BLUE), (0,), 180), - 3700: ('phase_5.5/maps/WesternBootWallpaper1.jpg', + 3700: ('phase_5.5/maps/WesternBootWallpaper1.png', CTWhite, (0, 1170, 1180), 180), - 3800: ('phase_5.5/maps/WesternCactusWallpaper1.jpg', + 3800: ('phase_5.5/maps/WesternCactusWallpaper1.png', CTWhite, (0, 1170, 1180), 180), - 3900: ('phase_5.5/maps/WesternHatWallpaper1.jpg', + 3900: ('phase_5.5/maps/WesternHatWallpaper1.png', CTWhite, (0, 1170, 1180), 180), - 10100: ('phase_5.5/maps/cats1.jpg', + 10100: ('phase_5.5/maps/cats1.png', CTWhite, (0, 10010, 10020), 400), - 10200: ('phase_5.5/maps/bats2.jpg', + 10200: ('phase_5.5/maps/bats2.png', CTWhite, (0, 10010, 10020), 400), - 11000: ('phase_5.5/maps/wall_paper_snowflakes.jpg', + 11000: ('phase_5.5/maps/wall_paper_snowflakes.png', CTWhite, (0, 11000, 11010), 400), - 11100: ('phase_5.5/maps/wall_paper_hollyleaf.jpg', + 11100: ('phase_5.5/maps/wall_paper_hollyleaf.png', CTWhite, (0, 11000, 11010), 400), - 11200: ('phase_5.5/maps/wall_paper_snowman.jpg', + 11200: ('phase_5.5/maps/wall_paper_snowman.png', CTWhite, (0, 11000, 11010), 400), - 12000: ('phase_5.5/maps/VdayWall1.jpg', + 12000: ('phase_5.5/maps/VdayWall1.png', CTWhite, (0, 12000, 12010, 12020), 400), - 12100: ('phase_5.5/maps/VdayWall2.jpg', + 12100: ('phase_5.5/maps/VdayWall2.png', CTWhite, (0, 12000, 12010, 12020), 400), - 12200: ('phase_5.5/maps/VdayWall3.jpg', + 12200: ('phase_5.5/maps/VdayWall3.png', CTWhite, (0, 12000, 12010, 12020), 400), - 12300: ('phase_5.5/maps/VdayWall4.jpg', + 12300: ('phase_5.5/maps/VdayWall4.png', CTWhite, (0, 12000, 12010, 12020), 400), - 13000: ('phase_5.5/maps/StPatWallpaper1.jpg', + 13000: ('phase_5.5/maps/StPatWallpaper1.png', CTWhite, (0, 13000), 400), - 13100: ('phase_5.5/maps/StPatWallpaper2.jpg', + 13100: ('phase_5.5/maps/StPatWallpaper2.png', CTWhite, (0, 13000), 400), - 13200: ('phase_5.5/maps/StPatWallpaper3.jpg', + 13200: ('phase_5.5/maps/StPatWallpaper3.png', CTWhite, (0, 13000), 400), - 13300: ('phase_5.5/maps/StPatWallpaper4.jpg', + 13300: ('phase_5.5/maps/StPatWallpaper4.png', CTWhite, (0, 13000), 400)} @@ -524,33 +524,33 @@ WallpaperGroups = {1100: (1100, 2700: (2700, 2710), 2800: (2800, 2810), 2900: (2900, 2910)} -BorderTypes = {1000: ('phase_5.5/maps/bd_grey_border1.jpg', CTFlatColorDark), - 1010: ('phase_5.5/maps/diamonds_border2.jpg', CTWhite), - 1020: ('phase_5.5/maps/diamonds_border2ch.jpg', CTWhite), - 1030: ('phase_5.5/maps/diamonds_border3ch.jpg', CTWhite), - 1040: ('phase_5.5/maps/diamonds_border4ch.jpg', CTWhite), - 1050: ('phase_5.5/maps/flower_border2.jpg', CTWhite), - 1060: ('phase_5.5/maps/flower_border5.jpg', CTWhite), - 1070: ('phase_5.5/maps/flower_border6.jpg', CTWhite), - 1080: ('phase_5.5/maps/football_border_neutral.jpg', CTFlatColorDark), - 1090: ('phase_5.5/maps/vine_border1.jpg', CTFlatColorDark), - 1100: ('phase_5.5/maps/doll_board.jpg', CTWhite), - 1110: ('phase_5.5/maps/doll_board_neutral.jpg', CTFlatColorDark), - 1120: ('phase_5.5/maps/UWwallPaperPlantBorder.jpg', CTWhite), - 1130: ('phase_5.5/maps/UWwallPaperSea_horseBorder.jpg', CTWhite), - 1140: ('phase_5.5/maps/UWwallPaperShellBorder1.jpg', CTWhite), - 1150: ('phase_5.5/maps/UWwallPaperShellBorder2.jpg', CTWhite), - 1160: ('phase_5.5/maps/UWwallPaperWaveBorder.jpg', CTWhite), - 1170: ('phase_5.5/maps/WesternSkullBorder.jpg', CTWhite), - 1180: ('phase_5.5/maps/WesternStarBorder.jpg', CTWhite), - 10010: ('phase_5.5/maps/border_ScarryMoon1.jpg', CTWhite), - 10020: ('phase_5.5/maps/border_candy1.jpg', CTWhite), - 11000: ('phase_5.5/maps/flakes_border.jpg', CTWhite), - 11010: ('phase_5.5/maps/hollyleaf_border.jpg', CTWhite), - 12000: ('phase_5.5/maps/Vborder1a.jpg', CTWhite), - 12010: ('phase_5.5/maps/Vborder1b.jpg', CTWhite), - 12020: ('phase_5.5/maps/Vborder2b.jpg', CTWhite), - 13000: ('phase_5.5/maps/StPatBorder1.jpg', CTWhite)} +BorderTypes = {1000: ('phase_5.5/maps/bd_grey_border1.png', CTFlatColorDark), + 1010: ('phase_5.5/maps/diamonds_border2.png', CTWhite), + 1020: ('phase_5.5/maps/diamonds_border2ch.png', CTWhite), + 1030: ('phase_5.5/maps/diamonds_border3ch.png', CTWhite), + 1040: ('phase_5.5/maps/diamonds_border4ch.png', CTWhite), + 1050: ('phase_5.5/maps/flower_border2.png', CTWhite), + 1060: ('phase_5.5/maps/flower_border5.png', CTWhite), + 1070: ('phase_5.5/maps/flower_border6.png', CTWhite), + 1080: ('phase_5.5/maps/football_border_neutral.png', CTFlatColorDark), + 1090: ('phase_5.5/maps/vine_border1.png', CTFlatColorDark), + 1100: ('phase_5.5/maps/doll_board.png', CTWhite), + 1110: ('phase_5.5/maps/doll_board_neutral.png', CTFlatColorDark), + 1120: ('phase_5.5/maps/UWwallPaperPlantBorder.png', CTWhite), + 1130: ('phase_5.5/maps/UWwallPaperSea_horseBorder.png', CTWhite), + 1140: ('phase_5.5/maps/UWwallPaperShellBorder1.png', CTWhite), + 1150: ('phase_5.5/maps/UWwallPaperShellBorder2.png', CTWhite), + 1160: ('phase_5.5/maps/UWwallPaperWaveBorder.png', CTWhite), + 1170: ('phase_5.5/maps/WesternSkullBorder.png', CTWhite), + 1180: ('phase_5.5/maps/WesternStarBorder.png', CTWhite), + 10010: ('phase_5.5/maps/border_ScarryMoon1.png', CTWhite), + 10020: ('phase_5.5/maps/border_candy1.png', CTWhite), + 11000: ('phase_5.5/maps/flakes_border.png', CTWhite), + 11010: ('phase_5.5/maps/hollyleaf_border.png', CTWhite), + 12000: ('phase_5.5/maps/Vborder1a.png', CTWhite), + 12010: ('phase_5.5/maps/Vborder1b.png', CTWhite), + 12020: ('phase_5.5/maps/Vborder2b.png', CTWhite), + 13000: ('phase_5.5/maps/StPatBorder1.png', CTWhite)} class CatalogWallpaperItem(CatalogSurfaceItem): diff --git a/toontown/char/Char.py b/toontown/char/Char.py index 1af94f2..7403948 100644 --- a/toontown/char/Char.py +++ b/toontown/char/Char.py @@ -252,8 +252,8 @@ class Char(Avatar.Avatar): self.eyesOpen = None self.eyesClosed = None if self._name == 'mickey' or self._name == 'minnie': - self.eyesOpen = loader.loadTexture('phase_3/maps/eyes1.jpg', 'phase_3/maps/eyes1_a.rgb') - self.eyesClosed = loader.loadTexture('phase_3/maps/mickey_eyes_closed.jpg', 'phase_3/maps/mickey_eyes_closed_a.rgb') + self.eyesOpen = loader.loadTexture('phase_3/maps/eyes1.png') + self.eyesClosed = loader.loadTexture('phase_3/maps/mickey_eyes_closed.png') self.eyes = self.find('**/1200/**/eyes') self.eyes.setBin('transparent', 0) self.lpupil = self.find('**/1200/**/joint_pupilL') @@ -285,8 +285,8 @@ class Char(Avatar.Avatar): part.hide() elif self._name == 'pluto': - self.eyesOpen = loader.loadTexture('phase_6/maps/plutoEyesOpen.jpg', 'phase_6/maps/plutoEyesOpen_a.rgb') - self.eyesClosed = loader.loadTexture('phase_6/maps/plutoEyesClosed.jpg', 'phase_6/maps/plutoEyesClosed_a.rgb') + self.eyesOpen = loader.loadTexture('phase_6/maps/plutoEyesOpen.png') + self.eyesClosed = loader.loadTexture('phase_6/maps/plutoEyesClosed.png') self.eyes = self.find('**/1000/**/eyes') self.lpupil = self.find('**/1000/**/joint_pupilL') self.rpupil = self.find('**/1000/**/joint_pupilR') @@ -317,8 +317,8 @@ class Char(Avatar.Avatar): self.rpupil = self.find('**/joint_pupilR') self.drawInFront('joint_pupil?', 'eyes*', -3) elif self._name == 'chip' or self._name == 'dale': - self.eyesOpen = loader.loadTexture('phase_6/maps/dale_eye1.jpg', 'phase_6/maps/dale_eye1_a.rgb') - self.eyesClosed = loader.loadTexture('phase_6/maps/chip_dale_eye1_blink.jpg', 'phase_6/maps/chip_dale_eye1_blink_a.rgb') + self.eyesOpen = loader.loadTexture('phase_6/maps/dale_eye1.png') + self.eyesClosed = loader.loadTexture('phase_6/maps/chip_dale_eye1_blink.png') self.eyes = self.find('**/eyes') self.lpupil = self.find('**/pupil_left') self.rpupil = self.find('**/pupil_right') diff --git a/toontown/cogdominium/DistributedCogdoBarrel.py b/toontown/cogdominium/DistributedCogdoBarrel.py index d6c5c20..f62cc59 100644 --- a/toontown/cogdominium/DistributedCogdoBarrel.py +++ b/toontown/cogdominium/DistributedCogdoBarrel.py @@ -34,8 +34,8 @@ class DistributedCogdoBarrel(DistributedObject.DistributedObject): cogdoBarrelsNode = render.attachNewNode('CogdoBarrels') cogdoBarrelsNode.stash() self.model.reparentTo(cogdoBarrelsNode) - self.availableTex = loader.loadTexture('phase_5/maps/tt_t_ara_cbr_Barrel_notUsed.jpg') - self.usedTex = loader.loadTexture('phase_5/maps/tt_t_ara_cbr_Barrel_Used.jpg') + self.availableTex = loader.loadTexture('phase_5/maps/tt_t_ara_cbr_Barrel_notUsed.png') + self.usedTex = loader.loadTexture('phase_5/maps/tt_t_ara_cbr_Barrel_Used.png') self.model.setTexture(self.availableTex, 100) def __addCollision(self): diff --git a/toontown/estate/DistributedToonStatuary.py b/toontown/estate/DistributedToonStatuary.py index c3e5264..8542b50 100644 --- a/toontown/estate/DistributedToonStatuary.py +++ b/toontown/estate/DistributedToonStatuary.py @@ -98,10 +98,10 @@ class DistributedToonStatuary(DistributedStatuary.DistributedStatuary): for node in self.toon.findAllMatches('**/*'): node.setState(RenderState.makeEmpty()) - desatShirtTex = loader.loadTexture('phase_3/maps/desat_shirt_1.jpg') - desatSleeveTex = loader.loadTexture('phase_3/maps/desat_sleeve_1.jpg') - desatShortsTex = loader.loadTexture('phase_3/maps/desat_shorts_1.jpg') - desatSkirtTex = loader.loadTexture('phase_3/maps/desat_skirt_1.jpg') + desatShirtTex = loader.loadTexture('phase_3/maps/desat_shirt_1.png') + desatSleeveTex = loader.loadTexture('phase_3/maps/desat_sleeve_1.png') + desatShortsTex = loader.loadTexture('phase_3/maps/desat_shorts_1.png') + desatSkirtTex = loader.loadTexture('phase_3/maps/desat_skirt_1.png') if self.toon.hasLOD(): for lodName in self.toon.getLODNames(): torso = self.toon.getPart('torso', lodName) @@ -123,7 +123,7 @@ class DistributedToonStatuary(DistributedStatuary.DistributedStatuary): def setStoneTexture(self): gray = VBase4(1.6, 1.6, 1.6, 1) self.toon.setColor(gray, 10) - stoneTex = loader.loadTexture('phase_5.5/maps/smoothwall_1.jpg') + stoneTex = loader.loadTexture('phase_5.5/maps/smoothwall_1.png') ts = TextureStage('ts') ts.setPriority(1) self.toon.setTexture(ts, stoneTex) diff --git a/toontown/hood/StreetSign.py b/toontown/hood/StreetSign.py index a0fec90..f92e2c8 100644 --- a/toontown/hood/StreetSign.py +++ b/toontown/hood/StreetSign.py @@ -9,7 +9,7 @@ from toontown.toonbase import TTLocalizer class StreetSign(DistributedObject.DistributedObject): RedownloadTaskName = 'RedownloadStreetSign' - StreetSignFileName = config.GetString('street-sign-filename', 'texture.jpg') + StreetSignFileName = config.GetString('street-sign-filename', 'texture.png') StreetSignBaseDir = config.GetString('street-sign-base-dir', 'sign') StreetSignUrl = base.config.GetString('street-sign-url', 'http://cdn.toontown.disney.go.com/toontown/en/street-signs/img/') notify = DirectNotifyGlobal.directNotify.newCategory('StreetSign') diff --git a/toontown/minigame/DistributedTargetGame.py b/toontown/minigame/DistributedTargetGame.py index 47046e2..0a07552 100644 --- a/toontown/minigame/DistributedTargetGame.py +++ b/toontown/minigame/DistributedTargetGame.py @@ -137,10 +137,10 @@ class DistributedTargetGame(DistributedMinigame): UPDATE_RUBBER_BAND_PRIORITY = 2 COLLISION_DETECTION_PRIORITY = 5 UPDATE_SHADOWS_PRIORITY = 47 - UMBRELLA_TEXTURE_LIST = ['phase_4/maps/mg_slingshot_umbrella_blue.jpg', - 'phase_4/maps/mg_slingshot_umbrella_purple.jpg', - 'phase_4/maps/mg_slingshot_umbrella_red.jpg', - 'phase_4/maps/mg_slingshot_umbrella_yellow.jpg'] + UMBRELLA_TEXTURE_LIST = ['phase_4/maps/mg_slingshot_umbrella_blue.png', + 'phase_4/maps/mg_slingshot_umbrella_purple.png', + 'phase_4/maps/mg_slingshot_umbrella_red.png', + 'phase_4/maps/mg_slingshot_umbrella_yellow.png'] RT_UNKNOWN = 0 RT_SUCCESS = 1 RT_GROUPSUCCESS = 2 diff --git a/toontown/minigame/Purchase.py b/toontown/minigame/Purchase.py index 1c7b987..d7147a9 100644 --- a/toontown/minigame/Purchase.py +++ b/toontown/minigame/Purchase.py @@ -51,15 +51,15 @@ class Purchase(PurchaseBase): self.bg = loader.loadModel('phase_%s/models/modules/toon_interior' % interiorPhase) self.bg.setPos(0.0, 5.0, -1.0) self.wt = self.bg.find('**/random_tc1_TI_wallpaper') - wallTex = loader.loadTexture('phase_%s/maps/wall_paper_a5.jpg' % interiorPhase) + wallTex = loader.loadTexture('phase_%s/maps/wall_paper_a5.png' % interiorPhase) self.wt.setTexture(wallTex, 100) self.wt.setColorScale(0.8, 0.67, 0.549, 1.0) self.bt = self.bg.find('**/random_tc1_TI_wallpaper_border') - wallTex = loader.loadTexture('phase_%s/maps/wall_paper_a5.jpg' % interiorPhase) + wallTex = loader.loadTexture('phase_%s/maps/wall_paper_a5.png' % interiorPhase) self.bt.setTexture(wallTex, 100) self.bt.setColorScale(0.8, 0.67, 0.549, 1.0) self.wb = self.bg.find('**/random_tc1_TI_wainscotting') - wainTex = loader.loadTexture('phase_%s/maps/wall_paper_b4.jpg' % interiorPhase) + wainTex = loader.loadTexture('phase_%s/maps/wall_paper_b4.png' % interiorPhase) self.wb.setTexture(wainTex, 100) self.wb.setColorScale(0.473, 0.675, 0.488, 1.0) self.playAgain = DirectButton(parent=self.frame, relief=None, scale=1.04, pos=(0.72, 0, -0.24), image=(purchaseModels.find('**/PurchScrn_BTN_UP'), diff --git a/toontown/minigame/SwingVine.py b/toontown/minigame/SwingVine.py index 5451f41..88448a1 100644 --- a/toontown/minigame/SwingVine.py +++ b/toontown/minigame/SwingVine.py @@ -111,7 +111,7 @@ class SwingVine(NodePath): self.link1 = self.links[-2][0] self.rope = self.makeSpline() self.rope.reparentTo(self.root) - myTexture = loader.loadTexture('phase_4/maps/swinging_vine.jpg') + myTexture = loader.loadTexture('phase_4/maps/swinging_vine.png') gameAssets = loader.loadModel('phase_4/models/minigames/vine_game') vine = gameAssets.find('**/vine1') self.cableTex = vine.findTexture('*') diff --git a/toontown/parties/DistributedPartyJukebox40Activity.py b/toontown/parties/DistributedPartyJukebox40Activity.py index 6358bed..8454aa2 100644 --- a/toontown/parties/DistributedPartyJukebox40Activity.py +++ b/toontown/parties/DistributedPartyJukebox40Activity.py @@ -9,7 +9,7 @@ class DistributedPartyJukebox40Activity(DistributedPartyJukeboxActivityBase): def load(self): DistributedPartyJukeboxActivityBase.load(self) - newTexture = loader.loadTexture('phase_13/maps/tt_t_ara_pty_jukeboxBlue.jpg', 'phase_13/maps/tt_t_ara_pty_jukeboxBlue_a.rgb') + newTexture = loader.loadTexture('phase_13/maps/tt_t_ara_pty_jukeboxBlue.png') case = self.jukebox.find('**/jukeboxGlass') if not case.isEmpty(): case.setTexture(newTexture, 1) diff --git a/toontown/parties/DistributedPartyValentineJukebox40Activity.py b/toontown/parties/DistributedPartyValentineJukebox40Activity.py index 7fc3f28..101db6b 100644 --- a/toontown/parties/DistributedPartyValentineJukebox40Activity.py +++ b/toontown/parties/DistributedPartyValentineJukebox40Activity.py @@ -9,7 +9,7 @@ class DistributedPartyValentineJukebox40Activity(DistributedPartyJukeboxActivity def load(self): DistributedPartyJukeboxActivityBase.load(self) - newTexture = loader.loadTexture('phase_13/maps/tt_t_ara_pty_jukeboxValentineB.jpg', 'phase_13/maps/tt_t_ara_pty_jukeboxValentineB_a.rgb') + newTexture = loader.loadTexture('phase_13/maps/tt_t_ara_pty_jukeboxValentineB.png') case = self.jukebox.find('**/jukeboxGlass') if not case.isEmpty(): case.setTexture(newTexture, 1) diff --git a/toontown/parties/DistributedPartyValentineJukeboxActivity.py b/toontown/parties/DistributedPartyValentineJukeboxActivity.py index f67cb5a..0b8f11d 100644 --- a/toontown/parties/DistributedPartyValentineJukeboxActivity.py +++ b/toontown/parties/DistributedPartyValentineJukeboxActivity.py @@ -9,7 +9,7 @@ class DistributedPartyValentineJukeboxActivity(DistributedPartyJukeboxActivityBa def load(self): DistributedPartyJukeboxActivityBase.load(self) - newTexture = loader.loadTexture('phase_13/maps/tt_t_ara_pty_jukeboxValentineA.jpg', 'phase_13/maps/tt_t_ara_pty_jukeboxValentineA_a.rgb') + newTexture = loader.loadTexture('phase_13/maps/tt_t_ara_pty_jukeboxValentineA.png') case = self.jukebox.find('**/jukeboxGlass') if not case.isEmpty(): case.setTexture(newTexture, 1) diff --git a/toontown/parties/DistributedPartyValentineTrampolineActivity.py b/toontown/parties/DistributedPartyValentineTrampolineActivity.py index a362d3c..bb665c2 100644 --- a/toontown/parties/DistributedPartyValentineTrampolineActivity.py +++ b/toontown/parties/DistributedPartyValentineTrampolineActivity.py @@ -3,4 +3,4 @@ from toontown.parties.DistributedPartyTrampolineActivity import DistributedParty class DistributedPartyValentineTrampolineActivity(DistributedPartyTrampolineActivity): def __init__(self, cr, doJellyBeans = True, doTricks = False, texture = None): - DistributedPartyTrampolineActivity.__init__(self, cr, doJellyBeans, doTricks, 'phase_13/maps/tt_t_ara_pty_trampolineValentine.jpg') + DistributedPartyTrampolineActivity.__init__(self, cr, doJellyBeans, doTricks, 'phase_13/maps/tt_t_ara_pty_trampolineValentine.png') diff --git a/toontown/parties/DistributedPartyVictoryTrampolineActivity.py b/toontown/parties/DistributedPartyVictoryTrampolineActivity.py index 99d156b..3659fc1 100644 --- a/toontown/parties/DistributedPartyVictoryTrampolineActivity.py +++ b/toontown/parties/DistributedPartyVictoryTrampolineActivity.py @@ -3,4 +3,4 @@ from toontown.parties.DistributedPartyTrampolineActivity import DistributedParty class DistributedPartyVictoryTrampolineActivity(DistributedPartyTrampolineActivity): def __init__(self, cr, doJellyBeans = True, doTricks = False, texture = None): - DistributedPartyTrampolineActivity.__init__(self, cr, doJellyBeans, doTricks, 'phase_13/maps/tt_t_ara_pty_trampolineVictory.jpg') + DistributedPartyTrampolineActivity.__init__(self, cr, doJellyBeans, doTricks, 'phase_13/maps/tt_t_ara_pty_trampolineVictory.png') diff --git a/toontown/parties/DistributedPartyWinterTrampolineActivity.py b/toontown/parties/DistributedPartyWinterTrampolineActivity.py index a0dcbfd..3db46be 100644 --- a/toontown/parties/DistributedPartyWinterTrampolineActivity.py +++ b/toontown/parties/DistributedPartyWinterTrampolineActivity.py @@ -3,4 +3,4 @@ from toontown.parties.DistributedPartyTrampolineActivity import DistributedParty class DistributedPartyWinterTrampolineActivity(DistributedPartyTrampolineActivity): def __init__(self, cr, doJellyBeans = True, doTricks = False, texture = None): - DistributedPartyTrampolineActivity.__init__(self, cr, doJellyBeans, doTricks, 'phase_13/maps/tt_t_ara_pty_trampolineWinter.jpg') + DistributedPartyTrampolineActivity.__init__(self, cr, doJellyBeans, doTricks, 'phase_13/maps/tt_t_ara_pty_trampolineWinter.png') diff --git a/toontown/parties/PartyCogActivity.py b/toontown/parties/PartyCogActivity.py index e08dd23..ec97ef6 100644 --- a/toontown/parties/PartyCogActivity.py +++ b/toontown/parties/PartyCogActivity.py @@ -97,8 +97,7 @@ class PartyCogActivity(DirectObject): signLocator = self.arena.find('**/eventSign_locator') self.activity.sign.setPos(signLocator.getPos(self.root)) if self.texture: - textureAlpha = self.texture[:-4] + '_a.rgb' - reskinTexture = loader.loadTexture(self.texture, textureAlpha) + reskinTexture = loader.loadTexture(self.texture) self.arena.find('**/center_grp').setTexture(reskinTexture, 100) self.arena.find('**/leftSide_grp').setTexture(reskinTexture, 100) self.arena.find('**/rightSide_grp').setTexture(reskinTexture, 100) diff --git a/toontown/pets/Pet.py b/toontown/pets/Pet.py index aec1233..e1e957a 100644 --- a/toontown/pets/Pet.py +++ b/toontown/pets/Pet.py @@ -247,11 +247,11 @@ class Pet(Avatar.Avatar): self.rightHighlight.hide() self.leftHighlight.hide() if self.style[8]: - self.eyesOpenTexture = loader.loadTexture('phase_4/maps/BeanEyeBoys2.jpg', 'phase_4/maps/BeanEyeBoys2_a.rgb') - self.eyesClosedTexture = loader.loadTexture('phase_4/maps/BeanEyeBoysBlink.jpg', 'phase_4/maps/BeanEyeBoysBlink_a.rgb') + self.eyesOpenTexture = loader.loadTexture('phase_4/maps/BeanEyeBoys2.png') + self.eyesClosedTexture = loader.loadTexture('phase_4/maps/BeanEyeBoysBlink.png') else: - self.eyesOpenTexture = loader.loadTexture('phase_4/maps/BeanEyeGirlsNew.jpg', 'phase_4/maps/BeanEyeGirlsNew_a.rgb') - self.eyesClosedTexture = loader.loadTexture('phase_4/maps/BeanEyeGirlsBlinkNew.jpg', 'phase_4/maps/BeanEyeGirlsBlinkNew_a.rgb') + self.eyesOpenTexture = loader.loadTexture('phase_4/maps/BeanEyeGirlsNew.png') + self.eyesClosedTexture = loader.loadTexture('phase_4/maps/BeanEyeGirlsBlinkNew.png') self.eyesOpenTexture.setMinfilter(Texture.FTLinear) self.eyesOpenTexture.setMagfilter(Texture.FTLinear) self.eyesClosedTexture.setMinfilter(Texture.FTLinear) diff --git a/toontown/pets/PetDNA.py b/toontown/pets/PetDNA.py index 3de514e..3a4b39c 100644 --- a/toontown/pets/PetDNA.py +++ b/toontown/pets/PetDNA.py @@ -21,13 +21,13 @@ EarParts = ['horns', EarTextures = {'horns': None, 'antennae': None, 'dogEars': None, - 'catEars': 'phase_4/maps/BeanCatEar6.jpg', - 'rabbitEars': 'phase_4/maps/BeanBunnyEar6.jpg'} + 'catEars': 'phase_4/maps/BeanCatEar6.png', + 'rabbitEars': 'phase_4/maps/BeanBunnyEar6.png'} ExoticEarTextures = {'horns': None, 'antennae': None, 'dogEars': None, - 'catEars': 'phase_4/maps/BeanCatEar3Yellow.jpg', - 'rabbitEars': 'phase_4/maps/BeanBunnyEar6.jpg'} + 'catEars': 'phase_4/maps/BeanCatEar3Yellow.png', + 'rabbitEars': 'phase_4/maps/BeanBunnyEar6.png'} NoseParts = ['clownNose', 'dogNose', 'ovalNose', @@ -36,12 +36,12 @@ TailParts = ['catTail', 'longTail', 'birdTail', 'bunnyTail'] -TailTextures = {'catTail': 'phase_4/maps/beanCatTail6.jpg', - 'longTail': 'phase_4/maps/BeanLongTail6.jpg', +TailTextures = {'catTail': 'phase_4/maps/beanCatTail6.png', + 'longTail': 'phase_4/maps/BeanLongTail6.png', 'birdTail': None, 'bunnyTail': None} -GiraffeTail = 'phase_4/maps/BeanLongTailGiraffe.jpg' -LeopardTail = 'phase_4/maps/BeanLongTailLepord.jpg' +GiraffeTail = 'phase_4/maps/BeanLongTailGiraffe.png' +LeopardTail = 'phase_4/maps/BeanLongTailLepord.png' GenericBodies = ['dots', 'threeStripe', 'tigerStripe', @@ -85,17 +85,17 @@ PetRarities = {'body': {ToontownGlobals.ToontownCentral: {'threeStripe': 50, 'turtle': 25, 'giraffe': 20, 'leopard': 10}}} -BodyTextures = {'dots': 'phase_4/maps/BeanbodyDots6.jpg', - 'threeStripe': 'phase_4/maps/Beanbody3stripes6.jpg', - 'tigerStripe': 'phase_4/maps/BeanbodyZebraStripes6.jpg', - 'turtle': 'phase_4/maps/BeanbodyTurtle.jpg', - 'giraffe': 'phase_4/maps/BeanbodyGiraffe1.jpg', - 'leopard': 'phase_4/maps/BeanbodyLepord2.jpg', - 'tummy': 'phase_4/maps/BeanbodyTummy6.jpg'} -FeetTextures = {'normal': 'phase_4/maps/BeanFoot6.jpg', - 'turtle': 'phase_4/maps/BeanFootTurttle.jpg', - 'giraffe': 'phase_4/maps/BeanFootYellow3.jpg', - 'leopard': 'phase_4/maps/BeanFootYellow3.jpg'} +BodyTextures = {'dots': 'phase_4/maps/BeanbodyDots6.png', + 'threeStripe': 'phase_4/maps/Beanbody3stripes6.png', + 'tigerStripe': 'phase_4/maps/BeanbodyZebraStripes6.png', + 'turtle': 'phase_4/maps/BeanbodyTurtle.png', + 'giraffe': 'phase_4/maps/BeanbodyGiraffe1.png', + 'leopard': 'phase_4/maps/BeanbodyLepord2.png', + 'tummy': 'phase_4/maps/BeanbodyTummy6.png'} +FeetTextures = {'normal': 'phase_4/maps/BeanFoot6.png', + 'turtle': 'phase_4/maps/BeanFootTurttle.png', + 'giraffe': 'phase_4/maps/BeanFootYellow3.png', + 'leopard': 'phase_4/maps/BeanFootYellow3.png'} AllPetColors = (VBase4(1.0, 1.0, 1.0, 1.0), VBase4(0.96875, 0.691406, 0.699219, 1.0), VBase4(0.933594, 0.265625, 0.28125, 1.0), diff --git a/toontown/racing/DistributedRace.py b/toontown/racing/DistributedRace.py index e62586d..0f0df9f 100644 --- a/toontown/racing/DistributedRace.py +++ b/toontown/racing/DistributedRace.py @@ -41,7 +41,7 @@ class DistributedRace(DistributedObject.DistributedObject): def __init__(self, cr): self.qbox = loader.loadModel('phase_6/models/karting/qbox') - self.boostArrowTexture = loader.loadTexture('phase_6/maps/boost_arrow.jpg', 'phase_6/maps/boost_arrow_a.rgb') + self.boostArrowTexture = loader.loadTexture('phase_6/maps/boost_arrow.png') self.boostArrowTexture.setMinfilter(Texture.FTLinear) DistributedObject.DistributedObject.__init__(self, cr) self.kartMap = {} diff --git a/toontown/racing/Kart.py b/toontown/racing/Kart.py index a4d551d..5481d26 100644 --- a/toontown/racing/Kart.py +++ b/toontown/racing/Kart.py @@ -315,7 +315,7 @@ class Kart(NodePath, ShadowCaster.ShadowCaster): rimTexPath = getAccessory(getDefaultRim()) else: rimTexPath = getAccessory(self.kartDNA[KartDNA.rimsType]) - rimTex = loader.loadTexture('%s.jpg' % rimTexPath, '%s_a.rgb' % rimTexPath) + rimTex = loader.loadTexture('%s.png' % rimTexPath) for kart in self.geom: leftFrontWheelRim = self.geom[kart].find('**/leftFrontWheelRim') rightFrontWheelRim = self.geom[kart].find('**/rightFrontWheelRim') @@ -397,8 +397,8 @@ class Kart(NodePath, ShadowCaster.ShadowCaster): if self.kartDNA[KartDNA.decalType] != InvalidEntry: decalId = getAccessory(self.kartDNA[KartDNA.decalType]) kartDecal = getDecalId(self.kartDNA[KartDNA.bodyType]) - hoodDecalTex = loader.loadTexture('phase_6/maps/%s_HoodDecal_%s.jpg' % (kartDecal, decalId), 'phase_6/maps/%s_HoodDecal_%s_a.rgb' % (kartDecal, decalId)) - sideDecalTex = loader.loadTexture('phase_6/maps/%s_SideDecal_%s.jpg' % (kartDecal, decalId), 'phase_6/maps/%s_SideDecal_%s_a.rgb' % (kartDecal, decalId)) + hoodDecalTex = loader.loadTexture('phase_6/maps/%s_HoodDecal_%s.png' % (kartDecal, decalId)) + sideDecalTex = loader.loadTexture('phase_6/maps/%s_SideDecal_%s.png' % (kartDecal, decalId)) hoodDecalTex.setMinfilter(Texture.FTLinearMipmapLinear) sideDecalTex.setMinfilter(Texture.FTLinearMipmapLinear) for kart in self.geom: diff --git a/toontown/racing/KartShopGui.py b/toontown/racing/KartShopGui.py index 42642a6..f0ab23c 100644 --- a/toontown/racing/KartShopGui.py +++ b/toontown/racing/KartShopGui.py @@ -687,15 +687,15 @@ class KartShopGuiMgr(DirectObject.DirectObject, object): KartDNA.fwwType, KartDNA.bwwType]: texNodePath = getTexCardNode(accID) - tex = loader.loadTexture('phase_6/maps/%s.jpg' % texNodePath, 'phase_6/maps/%s_a.rgb' % texNodePath) + tex = loader.loadTexture('phase_6/maps/%s.png' % texNodePath) elif accType == KartDNA.rimsType: if accID == InvalidEntry: texNodePath = getTexCardNode(getDefaultRim()) else: texNodePath = getTexCardNode(accID) - tex = loader.loadTexture('phase_6/maps/%s.jpg' % texNodePath, 'phase_6/maps/%s_a.rgb' % texNodePath) + tex = loader.loadTexture('phase_6/maps/%s.png' % texNodePath) elif accType in [KartDNA.bodyColor, KartDNA.accColor]: - tex = loader.loadTexture('phase_6/maps/Kartmenu_paintbucket.jpg', 'phase_6/maps/Kartmenu_paintbucket_a.rgb') + tex = loader.loadTexture('phase_6/maps/Kartmenu_paintbucket.png') if accID == InvalidEntry: self.kartView.component('geom0').setColorScale(getDefaultColor()) else: @@ -703,9 +703,9 @@ class KartShopGuiMgr(DirectObject.DirectObject, object): elif accType == KartDNA.decalType: kartDecal = getDecalId(base.localAvatar.getKartBodyType()) texNodePath = getTexCardNode(accID) - tex = loader.loadTexture('phase_6/maps/%s.jpg' % texNodePath % kartDecal, 'phase_6/maps/%s_a.rgb' % texNodePath % kartDecal) + tex = loader.loadTexture('phase_6/maps/%s.png' % texNodePath % kartDecal) else: - tex = loader.loadTexture('phase_6/maps/NoAccessoryIcon3.jpg', 'phase_6/maps/NoAccessoryIcon3_a.rgb') + tex = loader.loadTexture('phase_6/maps/NoAccessoryIcon3.png') tex.setMinfilter(Texture.FTLinearMipmapLinear) self.kartView.component('geom0').setTexture(tex, 1) self.initialize = True @@ -747,15 +747,15 @@ class KartShopGuiMgr(DirectObject.DirectObject, object): KartDNA.fwwType, KartDNA.bwwType]: texNodePath = getTexCardNode(accID) - tex = loader.loadTexture('phase_6/maps/%s.jpg' % texNodePath, 'phase_6/maps/%s_a.rgb' % texNodePath) + tex = loader.loadTexture('phase_6/maps/%s.png' % texNodePath) elif accType == KartDNA.rimsType: if accID == InvalidEntry: texNodePath = getTexCardNode(getDefaultRim()) else: texNodePath = getTexCardNode(accID) - tex = loader.loadTexture('phase_6/maps/%s.jpg' % texNodePath, 'phase_6/maps/%s_a.rgb' % texNodePath) + tex = loader.loadTexture('phase_6/maps/%s.png' % texNodePath) elif accType in [KartDNA.bodyColor, KartDNA.accColor]: - tex = loader.loadTexture('phase_6/maps/Kartmenu_paintbucket.jpg', 'phase_6/maps/Kartmenu_paintbucket_a.rgb') + tex = loader.loadTexture('phase_6/maps/Kartmenu_paintbucket.png') if accID == InvalidEntry: self.kartView.component('geom0').setColorScale(getDefaultColor()) else: @@ -763,9 +763,9 @@ class KartShopGuiMgr(DirectObject.DirectObject, object): elif accType == KartDNA.decalType: kartDecal = getDecalId(base.localAvatar.getKartBodyType()) texNodePath = getTexCardNode(accID) - tex = loader.loadTexture('phase_6/maps/%s.jpg' % texNodePath % kartDecal, 'phase_6/maps/%s_a.rgb' % texNodePath % kartDecal) + tex = loader.loadTexture('phase_6/maps/%s.png' % texNodePath % kartDecal) else: - tex = loader.loadTexture('phase_6/maps/NoAccessoryIcon3.jpg', 'phase_6/maps/NoAccessoryIcon3_a.rgb') + tex = loader.loadTexture('phase_6/maps/NoAccessoryIcon3.png') tex.setMinfilter(Texture.FTLinearMipmapLinear) self.kartView.component('geom0').setTexture(tex, 1) self.initialize = True diff --git a/toontown/shtiker/InGameNewsFrame.py b/toontown/shtiker/InGameNewsFrame.py index 44166d9..154d1af 100644 --- a/toontown/shtiker/InGameNewsFrame.py +++ b/toontown/shtiker/InGameNewsFrame.py @@ -34,6 +34,6 @@ class InGameNewsFrame(HtmlView.HtmlView): filename = filename.replace('.', '-') pngfilename = filename + '.png' self.writeTex(pngfilename) - jpgfilename = filename + '.jpg' + jpgfilename = filename + '.png' self.writeTex(jpgfilename) return jpgfilename diff --git a/toontown/shtiker/IssueFrame.py b/toontown/shtiker/IssueFrame.py index 11eee88..a4aa403 100644 --- a/toontown/shtiker/IssueFrame.py +++ b/toontown/shtiker/IssueFrame.py @@ -23,7 +23,7 @@ class IssueFrame(DirectFrame): -0.751666665077, 0.751666665077) notify = DirectNotifyGlobal.directNotify.newCategory('IssueFrame') - ContentPattern = 'tt_i_art_%s_%s%d.jpg' + ContentPattern = 'tt_i_art_%s_%s%d.png' SectionIdents = ['hom', 'new', 'evt', diff --git a/toontown/shtiker/KartPage.py b/toontown/shtiker/KartPage.py index 15b473d..49221d4 100644 --- a/toontown/shtiker/KartPage.py +++ b/toontown/shtiker/KartPage.py @@ -366,7 +366,7 @@ class ItemSelector(DirectFrame): self.locator2 = self.attachNewNode('locator2') self.locator1.setPos(0, 0, 0.035) self.locator2.setPos(0.0, 0.0, 0.0) - tex = loader.loadTexture('phase_6/maps/NoAccessoryIcon3.jpg', 'phase_6/maps/NoAccessoryIcon3_a.rgb') + tex = loader.loadTexture('phase_6/maps/NoAccessoryIcon3.png') self.uiImagePlane.component('geom0').setTexture(tex, self.texCount) self.texCount += 1 self.uiTextBox = DirectFrame(parent=self, relief=None, scale=1.0, text='', text_font=ToontownGlobals.getInterfaceFont(), text_fg=(0.5, 0, 0, 1), text_shadow=(0, 0, 0, 1), text_scale=0.0715, text_pos=(0.0, -0.23, 0.0)) @@ -526,15 +526,15 @@ class ItemSelector(DirectFrame): KartDNA.fwwType, KartDNA.bwwType]: texNodePath = getTexCardNode(self.currItem) - tex = loader.loadTexture('phase_6/maps/%s.jpg' % texNodePath, 'phase_6/maps/%s_a.rgb' % texNodePath) + tex = loader.loadTexture('phase_6/maps/%s.png' % texNodePath) elif self.currAccessoryType == KartDNA.rimsType: if self.currItem == InvalidEntry: texNodePath = getTexCardNode(getDefaultRim()) else: texNodePath = getTexCardNode(self.currItem) - tex = loader.loadTexture('phase_6/maps/%s.jpg' % texNodePath, 'phase_6/maps/%s_a.rgb' % texNodePath) + tex = loader.loadTexture('phase_6/maps/%s.png' % texNodePath) elif self.currAccessoryType in [KartDNA.bodyColor, KartDNA.accColor]: - tex = loader.loadTexture('phase_6/maps/Kartmenu_paintbucket.jpg', 'phase_6/maps/Kartmenu_paintbucket_a.rgb') + tex = loader.loadTexture('phase_6/maps/Kartmenu_paintbucket.png') if self.currItem == InvalidEntry: self.uiImagePlane.component('geom0').setColorScale(getDefaultColor()) else: @@ -543,9 +543,9 @@ class ItemSelector(DirectFrame): kart = self._parent._parent.getKartViewer().getKart() kartDecal = getDecalId(kart.kartDNA[KartDNA.bodyType]) texNodePath = getTexCardNode(self.currItem) - tex = loader.loadTexture('phase_6/maps/%s.jpg' % texNodePath % kartDecal, 'phase_6/maps/%s_a.rgb' % texNodePath % kartDecal) + tex = loader.loadTexture('phase_6/maps/%s.png' % texNodePath % kartDecal) else: - tex = loader.loadTexture('phase_6/maps/NoAccessoryIcon3.jpg', 'phase_6/maps/NoAccessoryIcon3_a.rgb') + tex = loader.loadTexture('phase_6/maps/NoAccessoryIcon3.png') colorTypeList = [KartDNA.bodyColor, KartDNA.accColor] if self.currItem == InvalidEntry: if self.currAccessoryType == KartDNA.rimsType: @@ -561,7 +561,7 @@ class ItemSelector(DirectFrame): def __handleHideItem(self): self.uiImagePlane.component('geom0').setColorScale(1.0, 1.0, 1.0, 1.0) - self.uiImagePlane.component('geom0').setTexture(loader.loadTexture('phase_6/maps/NoAccessoryIcon3.jpg', 'phase_6/maps/NoAccessoryIcon3_a.rgb'), self.texCount) + self.uiImagePlane.component('geom0').setTexture(loader.loadTexture('phase_6/maps/NoAccessoryIcon3.png'), self.texCount) self.texCount += 1 def __handleItemDeleteConfirm(self): diff --git a/toontown/shtiker/PhotoAlbumPage.py b/toontown/shtiker/PhotoAlbumPage.py index 24cf619..16b1ae9 100644 --- a/toontown/shtiker/PhotoAlbumPage.py +++ b/toontown/shtiker/PhotoAlbumPage.py @@ -182,7 +182,7 @@ class PhotoAlbumPage(ShtikerPage.ShtikerPage): files = os.listdir('.') photos = [] for fileName in files: - if fileName[0:10] == 'screenshot' and fileName[-4:] == '.jpg': + if fileName[0:10] == 'screenshot' and fileName[-4:] == '.png': photos.append(fileName) return photos diff --git a/toontown/suit/Suit.py b/toontown/suit/Suit.py index 644b2b3..8cac5af 100644 --- a/toontown/suit/Suit.py +++ b/toontown/suit/Suit.py @@ -448,7 +448,7 @@ class Suit(Avatar.Avatar): self.scale = 6.75 / cSize self.handColor = VBase4(0.85, 0.55, 0.55, 1.0) self.generateBody() - self.headTexture = 'corporate-raider.jpg' + self.headTexture = 'corporate-raider.png' self.generateHead('flunky') self.setHeight(8.23) elif dna.name == 'tbc': @@ -461,21 +461,21 @@ class Suit(Avatar.Avatar): self.scale = 4.0 / cSize self.handColor = SuitDNA.legalPolyColor self.generateBody() - self.headTexture = 'bottom-feeder.jpg' + self.headTexture = 'bottom-feeder.png' self.generateHead('tightwad') self.setHeight(4.81) elif dna.name == 'b': self.scale = 4.375 / bSize self.handColor = VBase4(0.95, 0.95, 1.0, 1.0) self.generateBody() - self.headTexture = 'blood-sucker.jpg' + self.headTexture = 'blood-sucker.png' self.generateHead('movershaker') self.setHeight(6.17) elif dna.name == 'dt': self.scale = 4.25 / aSize self.handColor = SuitDNA.legalPolyColor self.generateBody() - self.headTexture = 'double-talker.jpg' + self.headTexture = 'double-talker.png' self.generateHead('twoface') self.setHeight(5.63) elif dna.name == 'ac': @@ -494,7 +494,7 @@ class Suit(Avatar.Avatar): self.scale = 5.65 / bSize self.handColor = VBase4(0.5, 0.8, 0.75, 1.0) self.generateBody() - self.headTexture = 'spin-doctor.jpg' + self.headTexture = 'spin-doctor.png' self.generateHead('telemarketer') self.setHeight(7.9) elif dna.name == 'le': @@ -555,7 +555,7 @@ class Suit(Avatar.Avatar): self.scale = 7.0 / aSize self.handColor = SuitDNA.moneyPolyColor self.generateBody() - self.headTexture = 'robber-baron.jpg' + self.headTexture = 'robber-baron.png' self.generateHead('yesman') self.setHeight(8.95) elif dna.name == 'cc': @@ -575,7 +575,7 @@ class Suit(Avatar.Avatar): self.scale = 4.35 / aSize self.handColor = SuitDNA.salesPolyColor self.generateBody() - self.headTexture = 'name-dropper.jpg' + self.headTexture = 'name-dropper.png' self.generateHead('numbercruncher') self.setHeight(5.98) elif dna.name == 'gh': @@ -600,7 +600,7 @@ class Suit(Avatar.Avatar): self.scale = 5.75 / aSize self.handColor = SuitDNA.salesPolyColor self.generateBody() - self.headTexture = 'mingler.jpg' + self.headTexture = 'mingler.png' self.generateHead('twoface') self.setHeight(7.61) elif dna.name == 'mh': @@ -683,13 +683,13 @@ class Suit(Avatar.Avatar): phase = 3.5 def __doItTheOldWay__(): - torsoTex = loader.loadTexture('phase_%s/maps/%s_blazer.jpg' % (phase, dept)) + torsoTex = loader.loadTexture('phase_%s/maps/%s_blazer.png' % (phase, dept)) torsoTex.setMinfilter(Texture.FTLinearMipmapLinear) torsoTex.setMagfilter(Texture.FTLinear) - legTex = loader.loadTexture('phase_%s/maps/%s_leg.jpg' % (phase, dept)) + legTex = loader.loadTexture('phase_%s/maps/%s_leg.png' % (phase, dept)) legTex.setMinfilter(Texture.FTLinearMipmapLinear) legTex.setMagfilter(Texture.FTLinear) - armTex = loader.loadTexture('phase_%s/maps/%s_sleeve.jpg' % (phase, dept)) + armTex = loader.loadTexture('phase_%s/maps/%s_sleeve.png' % (phase, dept)) armTex.setMinfilter(Texture.FTLinearMipmapLinear) armTex.setMagfilter(Texture.FTLinear) modelRoot.find('**/torso').setTexture(torsoTex, 1) @@ -713,8 +713,8 @@ class Suit(Avatar.Avatar): if self.find('**/body').isEmpty(): __doItTheOldWay__() else: - filepath = 'phase_3.5/maps/tt_t_ene_' + texType + '.jpg' - if cogExists('/maps/tt_t_ene_' + texType + '.jpg'): + filepath = 'phase_3.5/maps/tt_t_ene_' + texType + '.png' + if cogExists('/maps/tt_t_ene_' + texType + '.png'): bodyTex = loader.loadTexture(filepath) self.find('**/body').setTexture(bodyTex, 1) self.leftHand = self.find('**/def_joint_left_hold') @@ -728,13 +728,13 @@ class Suit(Avatar.Avatar): if not modelRoot: modelRoot = self self.isWaiter = 1 - torsoTex = loader.loadTexture('phase_3.5/maps/waiter_m_blazer.jpg') + torsoTex = loader.loadTexture('phase_3.5/maps/waiter_m_blazer.png') torsoTex.setMinfilter(Texture.FTLinearMipmapLinear) torsoTex.setMagfilter(Texture.FTLinear) - legTex = loader.loadTexture('phase_3.5/maps/waiter_m_leg.jpg') + legTex = loader.loadTexture('phase_3.5/maps/waiter_m_leg.png') legTex.setMinfilter(Texture.FTLinearMipmapLinear) legTex.setMagfilter(Texture.FTLinear) - armTex = loader.loadTexture('phase_3.5/maps/waiter_m_sleeve.jpg') + armTex = loader.loadTexture('phase_3.5/maps/waiter_m_sleeve.png') armTex.setMinfilter(Texture.FTLinearMipmapLinear) armTex.setMagfilter(Texture.FTLinear) modelRoot.find('**/torso').setTexture(torsoTex, 1) @@ -745,10 +745,10 @@ class Suit(Avatar.Avatar): if not modelRoot: modelRoot = self.getGeomNode() if suitType == 's': - torsoTex = loader.loadTexture('phase_3.5/maps/tt_t_ene_sellbotRental_blazer.jpg') - legTex = loader.loadTexture('phase_3.5/maps/tt_t_ene_sellbotRental_leg.jpg') - armTex = loader.loadTexture('phase_3.5/maps/tt_t_ene_sellbotRental_sleeve.jpg') - handTex = loader.loadTexture('phase_3.5/maps/tt_t_ene_sellbotRental_hand.jpg') + torsoTex = loader.loadTexture('phase_3.5/maps/tt_t_ene_sellbotRental_blazer.png') + legTex = loader.loadTexture('phase_3.5/maps/tt_t_ene_sellbotRental_leg.png') + armTex = loader.loadTexture('phase_3.5/maps/tt_t_ene_sellbotRental_sleeve.png') + handTex = loader.loadTexture('phase_3.5/maps/tt_t_ene_sellbotRental_hand.png') else: self.notify.warning('No rental suit for cog type %s' % suitType) return @@ -792,13 +792,13 @@ class Suit(Avatar.Avatar): self.notify.warning('skelecog has no tie model!!!') return if dept == 'c': - tieTex = loader.loadTexture('phase_5/maps/cog_robot_tie_boss.jpg') + tieTex = loader.loadTexture('phase_5/maps/cog_robot_tie_boss.png') elif dept == 's': - tieTex = loader.loadTexture('phase_5/maps/cog_robot_tie_sales.jpg') + tieTex = loader.loadTexture('phase_5/maps/cog_robot_tie_sales.png') elif dept == 'l': - tieTex = loader.loadTexture('phase_5/maps/cog_robot_tie_legal.jpg') + tieTex = loader.loadTexture('phase_5/maps/cog_robot_tie_legal.png') elif dept == 'm': - tieTex = loader.loadTexture('phase_5/maps/cog_robot_tie_money.jpg') + tieTex = loader.loadTexture('phase_5/maps/cog_robot_tie_money.png') tieTex.setMinfilter(Texture.FTLinearMipmapLinear) tieTex.setMagfilter(Texture.FTLinear) tie.setTexture(tieTex, 1) diff --git a/toontown/toon/Toon.py b/toontown/toon/Toon.py index ea017e2..8dc436c 100644 --- a/toontown/toon/Toon.py +++ b/toontown/toon/Toon.py @@ -1168,7 +1168,7 @@ class Toon(Avatar.Avatar, ToonHead): for geom in geoms: texName = ToonDNA.ShoesTextures[shoes[1]] if self.style.legs == 'l' and shoes[0] == 3: - texName = texName[:-4] + 'LL.jpg' + texName = texName[:-4] + 'LL.png' tex = loader.loadTexture(texName, okMissing=True) if tex is None: self.sendLogSuspiciousEvent('failed to load texture %s' % texName) diff --git a/toontown/toon/ToonDNA.py b/toontown/toon/ToonDNA.py index 4507efc..f75a9cd 100644 --- a/toontown/toon/ToonDNA.py +++ b/toontown/toon/ToonDNA.py @@ -175,157 +175,157 @@ toonTorsoTypes = ['ss', 'm', 'l'] toonLegTypes = ['s', 'm', 'l'] -Shirts = ['phase_3/maps/desat_shirt_1.jpg', - 'phase_3/maps/desat_shirt_2.jpg', - 'phase_3/maps/desat_shirt_3.jpg', - 'phase_3/maps/desat_shirt_4.jpg', - 'phase_3/maps/desat_shirt_5.jpg', - 'phase_3/maps/desat_shirt_6.jpg', - 'phase_3/maps/desat_shirt_7.jpg', - 'phase_3/maps/desat_shirt_8.jpg', - 'phase_3/maps/desat_shirt_9.jpg', - 'phase_3/maps/desat_shirt_10.jpg', - 'phase_3/maps/desat_shirt_11.jpg', - 'phase_3/maps/desat_shirt_12.jpg', - 'phase_3/maps/desat_shirt_13.jpg', - 'phase_3/maps/desat_shirt_14.jpg', - 'phase_3/maps/desat_shirt_15.jpg', - 'phase_3/maps/desat_shirt_16.jpg', - 'phase_3/maps/desat_shirt_17.jpg', - 'phase_3/maps/desat_shirt_18.jpg', - 'phase_3/maps/desat_shirt_19.jpg', - 'phase_3/maps/desat_shirt_20.jpg', - 'phase_3/maps/desat_shirt_21.jpg', - 'phase_3/maps/desat_shirt_22.jpg', - 'phase_3/maps/desat_shirt_23.jpg', - 'phase_4/maps/female_shirt1b.jpg', - 'phase_4/maps/female_shirt2.jpg', - 'phase_4/maps/female_shirt3.jpg', - 'phase_4/maps/male_shirt1.jpg', - 'phase_4/maps/male_shirt2_palm.jpg', - 'phase_4/maps/male_shirt3c.jpg', - 'phase_4/maps/shirt_ghost.jpg', - 'phase_4/maps/shirt_pumkin.jpg', - 'phase_4/maps/holiday_shirt1.jpg', - 'phase_4/maps/holiday_shirt2b.jpg', - 'phase_4/maps/holidayShirt3b.jpg', - 'phase_4/maps/holidayShirt4.jpg', - 'phase_4/maps/female_shirt1b.jpg', - 'phase_4/maps/female_shirt5New.jpg', - 'phase_4/maps/shirtMale4B.jpg', - 'phase_4/maps/shirt6New.jpg', - 'phase_4/maps/shirtMaleNew7.jpg', - 'phase_4/maps/femaleShirtNew6.jpg', - 'phase_4/maps/Vday1Shirt5.jpg', - 'phase_4/maps/Vday1Shirt6SHD.jpg', - 'phase_4/maps/Vday1Shirt4.jpg', - 'phase_4/maps/Vday_shirt2c.jpg', - 'phase_4/maps/shirtTieDyeNew.jpg', - 'phase_4/maps/male_shirt1.jpg', - 'phase_4/maps/StPats_shirt1.jpg', - 'phase_4/maps/StPats_shirt2.jpg', - 'phase_4/maps/ContestfishingVestShirt2.jpg', - 'phase_4/maps/ContestFishtankShirt1.jpg', - 'phase_4/maps/ContestPawShirt1.jpg', - 'phase_4/maps/CowboyShirt1.jpg', - 'phase_4/maps/CowboyShirt2.jpg', - 'phase_4/maps/CowboyShirt3.jpg', - 'phase_4/maps/CowboyShirt4.jpg', - 'phase_4/maps/CowboyShirt5.jpg', - 'phase_4/maps/CowboyShirt6.jpg', - 'phase_4/maps/4thJulyShirt1.jpg', - 'phase_4/maps/4thJulyShirt2.jpg', - 'phase_4/maps/shirt_Cat7_01.jpg', - 'phase_4/maps/shirt_Cat7_02.jpg', - 'phase_4/maps/contest_backpack3.jpg', - 'phase_4/maps/contest_leder.jpg', - 'phase_4/maps/contest_mellon2.jpg', - 'phase_4/maps/contest_race2.jpg', - 'phase_4/maps/PJBlueBanana2.jpg', - 'phase_4/maps/PJRedHorn2.jpg', - 'phase_4/maps/PJGlasses2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_valentine1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_valentine2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_desat4.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_fishing1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_fishing2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_gardening1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_gardening2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_party1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_party2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_racing1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_racing2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_summer1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_summer2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_golf1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_golf2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_halloween1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_halloween2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_marathon1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_saveBuilding1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_saveBuilding2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_toonTask1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_toonTask2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_trolley1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_trolley2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_winter1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_halloween3.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_halloween4.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_valentine3.jpg', - 'phase_4/maps/tt_t_chr_shirt_scientistC.jpg', - 'phase_4/maps/tt_t_chr_shirt_scientistA.jpg', - 'phase_4/maps/tt_t_chr_shirt_scientistB.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_mailbox.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_trashcan.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_loonyLabs.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_hydrant.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_whistle.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_cogbuster.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_mostCogsDefeated01.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_victoryParty01.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_victoryParty02.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_sellbotIcon.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_sellbotVPIcon.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_sellbotCrusher.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_jellyBeans.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_doodle.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_halloween5.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_halloweenTurtle.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_greentoon1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_getConnectedMoverShaker.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_racingGrandPrix.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_lawbotIcon.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_lawbotVPIcon.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_lawbotCrusher.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_bee.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_pirate.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_supertoon.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_vampire.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_dinosaur.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_fishing04.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_golf03.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_mostCogsDefeated02.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_racing03.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_saveBuilding3.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_trolley03.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_fishing05.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_golf04.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_halloween06.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_winter03.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_halloween07.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_winter02.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_fishing06.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_fishing07.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_golf05.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_racing04.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_racing05.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_mostCogsDefeated03.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_mostCogsDefeated04.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_trolley04.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_trolley05.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_saveBuilding4.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_saveBuilding05.jpg', - 'phase_4/maps/tt_t_chr_avt_shirt_anniversary.jpg'] +Shirts = ['phase_3/maps/desat_shirt_1.png', + 'phase_3/maps/desat_shirt_2.png', + 'phase_3/maps/desat_shirt_3.png', + 'phase_3/maps/desat_shirt_4.png', + 'phase_3/maps/desat_shirt_5.png', + 'phase_3/maps/desat_shirt_6.png', + 'phase_3/maps/desat_shirt_7.png', + 'phase_3/maps/desat_shirt_8.png', + 'phase_3/maps/desat_shirt_9.png', + 'phase_3/maps/desat_shirt_10.png', + 'phase_3/maps/desat_shirt_11.png', + 'phase_3/maps/desat_shirt_12.png', + 'phase_3/maps/desat_shirt_13.png', + 'phase_3/maps/desat_shirt_14.png', + 'phase_3/maps/desat_shirt_15.png', + 'phase_3/maps/desat_shirt_16.png', + 'phase_3/maps/desat_shirt_17.png', + 'phase_3/maps/desat_shirt_18.png', + 'phase_3/maps/desat_shirt_19.png', + 'phase_3/maps/desat_shirt_20.png', + 'phase_3/maps/desat_shirt_21.png', + 'phase_3/maps/desat_shirt_22.png', + 'phase_3/maps/desat_shirt_23.png', + 'phase_4/maps/female_shirt1b.png', + 'phase_4/maps/female_shirt2.png', + 'phase_4/maps/female_shirt3.png', + 'phase_4/maps/male_shirt1.png', + 'phase_4/maps/male_shirt2_palm.png', + 'phase_4/maps/male_shirt3c.png', + 'phase_4/maps/shirt_ghost.png', + 'phase_4/maps/shirt_pumkin.png', + 'phase_4/maps/holiday_shirt1.png', + 'phase_4/maps/holiday_shirt2b.png', + 'phase_4/maps/holidayShirt3b.png', + 'phase_4/maps/holidayShirt4.png', + 'phase_4/maps/female_shirt1b.png', + 'phase_4/maps/female_shirt5New.png', + 'phase_4/maps/shirtMale4B.png', + 'phase_4/maps/shirt6New.png', + 'phase_4/maps/shirtMaleNew7.png', + 'phase_4/maps/femaleShirtNew6.png', + 'phase_4/maps/Vday1Shirt5.png', + 'phase_4/maps/Vday1Shirt6SHD.png', + 'phase_4/maps/Vday1Shirt4.png', + 'phase_4/maps/Vday_shirt2c.png', + 'phase_4/maps/shirtTieDyeNew.png', + 'phase_4/maps/male_shirt1.png', + 'phase_4/maps/StPats_shirt1.png', + 'phase_4/maps/StPats_shirt2.png', + 'phase_4/maps/ContestfishingVestShirt2.png', + 'phase_4/maps/ContestFishtankShirt1.png', + 'phase_4/maps/ContestPawShirt1.png', + 'phase_4/maps/CowboyShirt1.png', + 'phase_4/maps/CowboyShirt2.png', + 'phase_4/maps/CowboyShirt3.png', + 'phase_4/maps/CowboyShirt4.png', + 'phase_4/maps/CowboyShirt5.png', + 'phase_4/maps/CowboyShirt6.png', + 'phase_4/maps/4thJulyShirt1.png', + 'phase_4/maps/4thJulyShirt2.png', + 'phase_4/maps/shirt_Cat7_01.png', + 'phase_4/maps/shirt_Cat7_02.png', + 'phase_4/maps/contest_backpack3.png', + 'phase_4/maps/contest_leder.png', + 'phase_4/maps/contest_mellon2.png', + 'phase_4/maps/contest_race2.png', + 'phase_4/maps/PJBlueBanana2.png', + 'phase_4/maps/PJRedHorn2.png', + 'phase_4/maps/PJGlasses2.png', + 'phase_4/maps/tt_t_chr_avt_shirt_valentine1.png', + 'phase_4/maps/tt_t_chr_avt_shirt_valentine2.png', + 'phase_4/maps/tt_t_chr_avt_shirt_desat4.png', + 'phase_4/maps/tt_t_chr_avt_shirt_fishing1.png', + 'phase_4/maps/tt_t_chr_avt_shirt_fishing2.png', + 'phase_4/maps/tt_t_chr_avt_shirt_gardening1.png', + 'phase_4/maps/tt_t_chr_avt_shirt_gardening2.png', + 'phase_4/maps/tt_t_chr_avt_shirt_party1.png', + 'phase_4/maps/tt_t_chr_avt_shirt_party2.png', + 'phase_4/maps/tt_t_chr_avt_shirt_racing1.png', + 'phase_4/maps/tt_t_chr_avt_shirt_racing2.png', + 'phase_4/maps/tt_t_chr_avt_shirt_summer1.png', + 'phase_4/maps/tt_t_chr_avt_shirt_summer2.png', + 'phase_4/maps/tt_t_chr_avt_shirt_golf1.png', + 'phase_4/maps/tt_t_chr_avt_shirt_golf2.png', + 'phase_4/maps/tt_t_chr_avt_shirt_halloween1.png', + 'phase_4/maps/tt_t_chr_avt_shirt_halloween2.png', + 'phase_4/maps/tt_t_chr_avt_shirt_marathon1.png', + 'phase_4/maps/tt_t_chr_avt_shirt_saveBuilding1.png', + 'phase_4/maps/tt_t_chr_avt_shirt_saveBuilding2.png', + 'phase_4/maps/tt_t_chr_avt_shirt_toonTask1.png', + 'phase_4/maps/tt_t_chr_avt_shirt_toonTask2.png', + 'phase_4/maps/tt_t_chr_avt_shirt_trolley1.png', + 'phase_4/maps/tt_t_chr_avt_shirt_trolley2.png', + 'phase_4/maps/tt_t_chr_avt_shirt_winter1.png', + 'phase_4/maps/tt_t_chr_avt_shirt_halloween3.png', + 'phase_4/maps/tt_t_chr_avt_shirt_halloween4.png', + 'phase_4/maps/tt_t_chr_avt_shirt_valentine3.png', + 'phase_4/maps/tt_t_chr_shirt_scientistC.png', + 'phase_4/maps/tt_t_chr_shirt_scientistA.png', + 'phase_4/maps/tt_t_chr_shirt_scientistB.png', + 'phase_4/maps/tt_t_chr_avt_shirt_mailbox.png', + 'phase_4/maps/tt_t_chr_avt_shirt_trashcan.png', + 'phase_4/maps/tt_t_chr_avt_shirt_loonyLabs.png', + 'phase_4/maps/tt_t_chr_avt_shirt_hydrant.png', + 'phase_4/maps/tt_t_chr_avt_shirt_whistle.png', + 'phase_4/maps/tt_t_chr_avt_shirt_cogbuster.png', + 'phase_4/maps/tt_t_chr_avt_shirt_mostCogsDefeated01.png', + 'phase_4/maps/tt_t_chr_avt_shirt_victoryParty01.png', + 'phase_4/maps/tt_t_chr_avt_shirt_victoryParty02.png', + 'phase_4/maps/tt_t_chr_avt_shirt_sellbotIcon.png', + 'phase_4/maps/tt_t_chr_avt_shirt_sellbotVPIcon.png', + 'phase_4/maps/tt_t_chr_avt_shirt_sellbotCrusher.png', + 'phase_4/maps/tt_t_chr_avt_shirt_jellyBeans.png', + 'phase_4/maps/tt_t_chr_avt_shirt_doodle.png', + 'phase_4/maps/tt_t_chr_avt_shirt_halloween5.png', + 'phase_4/maps/tt_t_chr_avt_shirt_halloweenTurtle.png', + 'phase_4/maps/tt_t_chr_avt_shirt_greentoon1.png', + 'phase_4/maps/tt_t_chr_avt_shirt_getConnectedMoverShaker.png', + 'phase_4/maps/tt_t_chr_avt_shirt_racingGrandPrix.png', + 'phase_4/maps/tt_t_chr_avt_shirt_lawbotIcon.png', + 'phase_4/maps/tt_t_chr_avt_shirt_lawbotVPIcon.png', + 'phase_4/maps/tt_t_chr_avt_shirt_lawbotCrusher.png', + 'phase_4/maps/tt_t_chr_avt_shirt_bee.png', + 'phase_4/maps/tt_t_chr_avt_shirt_pirate.png', + 'phase_4/maps/tt_t_chr_avt_shirt_supertoon.png', + 'phase_4/maps/tt_t_chr_avt_shirt_vampire.png', + 'phase_4/maps/tt_t_chr_avt_shirt_dinosaur.png', + 'phase_4/maps/tt_t_chr_avt_shirt_fishing04.png', + 'phase_4/maps/tt_t_chr_avt_shirt_golf03.png', + 'phase_4/maps/tt_t_chr_avt_shirt_mostCogsDefeated02.png', + 'phase_4/maps/tt_t_chr_avt_shirt_racing03.png', + 'phase_4/maps/tt_t_chr_avt_shirt_saveBuilding3.png', + 'phase_4/maps/tt_t_chr_avt_shirt_trolley03.png', + 'phase_4/maps/tt_t_chr_avt_shirt_fishing05.png', + 'phase_4/maps/tt_t_chr_avt_shirt_golf04.png', + 'phase_4/maps/tt_t_chr_avt_shirt_halloween06.png', + 'phase_4/maps/tt_t_chr_avt_shirt_winter03.png', + 'phase_4/maps/tt_t_chr_avt_shirt_halloween07.png', + 'phase_4/maps/tt_t_chr_avt_shirt_winter02.png', + 'phase_4/maps/tt_t_chr_avt_shirt_fishing06.png', + 'phase_4/maps/tt_t_chr_avt_shirt_fishing07.png', + 'phase_4/maps/tt_t_chr_avt_shirt_golf05.png', + 'phase_4/maps/tt_t_chr_avt_shirt_racing04.png', + 'phase_4/maps/tt_t_chr_avt_shirt_racing05.png', + 'phase_4/maps/tt_t_chr_avt_shirt_mostCogsDefeated03.png', + 'phase_4/maps/tt_t_chr_avt_shirt_mostCogsDefeated04.png', + 'phase_4/maps/tt_t_chr_avt_shirt_trolley04.png', + 'phase_4/maps/tt_t_chr_avt_shirt_trolley05.png', + 'phase_4/maps/tt_t_chr_avt_shirt_saveBuilding4.png', + 'phase_4/maps/tt_t_chr_avt_shirt_saveBuilding05.png', + 'phase_4/maps/tt_t_chr_avt_shirt_anniversary.png'] BoyShirts = [(0, 0), (1, 1), (2, 2), @@ -373,267 +373,267 @@ def isValidGirlShirt(index): return 0 -Sleeves = ['phase_3/maps/desat_sleeve_1.jpg', - 'phase_3/maps/desat_sleeve_2.jpg', - 'phase_3/maps/desat_sleeve_3.jpg', - 'phase_3/maps/desat_sleeve_4.jpg', - 'phase_3/maps/desat_sleeve_5.jpg', - 'phase_3/maps/desat_sleeve_6.jpg', - 'phase_3/maps/desat_sleeve_7.jpg', - 'phase_3/maps/desat_sleeve_8.jpg', - 'phase_3/maps/desat_sleeve_9.jpg', - 'phase_3/maps/desat_sleeve_10.jpg', - 'phase_3/maps/desat_sleeve_15.jpg', - 'phase_3/maps/desat_sleeve_16.jpg', - 'phase_3/maps/desat_sleeve_19.jpg', - 'phase_3/maps/desat_sleeve_20.jpg', - 'phase_4/maps/female_sleeve1b.jpg', - 'phase_4/maps/female_sleeve2.jpg', - 'phase_4/maps/female_sleeve3.jpg', - 'phase_4/maps/male_sleeve1.jpg', - 'phase_4/maps/male_sleeve2_palm.jpg', - 'phase_4/maps/male_sleeve3c.jpg', - 'phase_4/maps/shirt_Sleeve_ghost.jpg', - 'phase_4/maps/shirt_Sleeve_pumkin.jpg', - 'phase_4/maps/holidaySleeve1.jpg', - 'phase_4/maps/holidaySleeve3.jpg', - 'phase_4/maps/female_sleeve1b.jpg', - 'phase_4/maps/female_sleeve5New.jpg', - 'phase_4/maps/male_sleeve4New.jpg', - 'phase_4/maps/sleeve6New.jpg', - 'phase_4/maps/SleeveMaleNew7.jpg', - 'phase_4/maps/female_sleeveNew6.jpg', - 'phase_4/maps/Vday5Sleeve.jpg', - 'phase_4/maps/Vda6Sleeve.jpg', - 'phase_4/maps/Vday_shirt4sleeve.jpg', - 'phase_4/maps/Vday2cSleeve.jpg', - 'phase_4/maps/sleeveTieDye.jpg', - 'phase_4/maps/male_sleeve1.jpg', - 'phase_4/maps/StPats_sleeve.jpg', - 'phase_4/maps/StPats_sleeve2.jpg', - 'phase_4/maps/ContestfishingVestSleeve1.jpg', - 'phase_4/maps/ContestFishtankSleeve1.jpg', - 'phase_4/maps/ContestPawSleeve1.jpg', - 'phase_4/maps/CowboySleeve1.jpg', - 'phase_4/maps/CowboySleeve2.jpg', - 'phase_4/maps/CowboySleeve3.jpg', - 'phase_4/maps/CowboySleeve4.jpg', - 'phase_4/maps/CowboySleeve5.jpg', - 'phase_4/maps/CowboySleeve6.jpg', - 'phase_4/maps/4thJulySleeve1.jpg', - 'phase_4/maps/4thJulySleeve2.jpg', - 'phase_4/maps/shirt_sleeveCat7_01.jpg', - 'phase_4/maps/shirt_sleeveCat7_02.jpg', - 'phase_4/maps/contest_backpack_sleeve.jpg', - 'phase_4/maps/Contest_leder_sleeve.jpg', - 'phase_4/maps/contest_mellon_sleeve2.jpg', - 'phase_4/maps/contest_race_sleeve.jpg', - 'phase_4/maps/PJSleeveBlue.jpg', - 'phase_4/maps/PJSleeveRed.jpg', - 'phase_4/maps/PJSleevePurple.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_valentine1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_valentine2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_desat4.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_fishing1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_fishing2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_gardening1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_gardening2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_party1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_party2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_racing1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_racing2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_summer1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_summer2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_golf1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_golf2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_halloween1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_halloween2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_marathon1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_saveBuilding1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_saveBuilding2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_toonTask1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_toonTask2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_trolley1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_trolley2.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_winter1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_halloween3.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_halloween4.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_valentine3.jpg', - 'phase_4/maps/tt_t_chr_shirtSleeve_scientist.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_mailbox.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_trashcan.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_loonyLabs.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_hydrant.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_whistle.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_cogbuster.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_mostCogsDefeated01.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_victoryParty01.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_victoryParty02.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_sellbotIcon.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_sellbotVPIcon.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_sellbotCrusher.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_jellyBeans.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_doodle.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_halloween5.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_halloweenTurtle.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_greentoon1.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_getConnectedMoverShaker.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_racingGrandPrix.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_lawbotIcon.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_lawbotVPIcon.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_lawbotCrusher.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_bee.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_pirate.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_supertoon.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_vampire.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_dinosaur.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_fishing04.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_golf03.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_mostCogsDefeated02.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_racing03.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_saveBuilding3.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_trolley03.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_fishing05.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_golf04.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_halloween06.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_winter03.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_halloween07.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_winter02.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_fishing06.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_fishing07.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_golf05.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_racing04.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_racing05.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_mostCogsDefeated03.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_mostCogsDefeated04.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_trolley04.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_trolley05.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_saveBuilding4.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_saveBuilding05.jpg', - 'phase_4/maps/tt_t_chr_avt_shirtSleeve_anniversary.jpg'] -BoyShorts = ['phase_3/maps/desat_shorts_1.jpg', - 'phase_3/maps/desat_shorts_2.jpg', - 'phase_3/maps/desat_shorts_4.jpg', - 'phase_3/maps/desat_shorts_6.jpg', - 'phase_3/maps/desat_shorts_7.jpg', - 'phase_3/maps/desat_shorts_8.jpg', - 'phase_3/maps/desat_shorts_9.jpg', - 'phase_3/maps/desat_shorts_10.jpg', - 'phase_4/maps/VdayShorts2.jpg', - 'phase_4/maps/shorts4.jpg', - 'phase_4/maps/shorts1.jpg', - 'phase_4/maps/shorts5.jpg', - 'phase_4/maps/CowboyShorts1.jpg', - 'phase_4/maps/CowboyShorts2.jpg', - 'phase_4/maps/4thJulyShorts1.jpg', - 'phase_4/maps/shortsCat7_01.jpg', - 'phase_4/maps/Blue_shorts_1.jpg', - 'phase_4/maps/Red_shorts_1.jpg', - 'phase_4/maps/Purple_shorts_1.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_winter1.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_winter2.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_winter3.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_winter4.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_valentine1.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_valentine2.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_fishing1.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_gardening1.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_party1.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_racing1.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_summer1.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_golf1.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_halloween1.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_halloween2.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_saveBuilding1.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_trolley1.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_halloween4.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_halloween3.jpg', - 'phase_4/maps/tt_t_chr_shorts_scientistA.jpg', - 'phase_4/maps/tt_t_chr_shorts_scientistB.jpg', - 'phase_4/maps/tt_t_chr_shorts_scientistC.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_cogbuster.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_sellbotCrusher.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_halloween5.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_halloweenTurtle.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_greentoon1.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_racingGrandPrix.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_lawbotCrusher.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_bee.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_pirate.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_supertoon.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_vampire.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_dinosaur.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_golf03.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_racing03.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_golf04.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_golf05.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_racing04.jpg', - 'phase_4/maps/tt_t_chr_avt_shorts_racing05.jpg'] +Sleeves = ['phase_3/maps/desat_sleeve_1.png', + 'phase_3/maps/desat_sleeve_2.png', + 'phase_3/maps/desat_sleeve_3.png', + 'phase_3/maps/desat_sleeve_4.png', + 'phase_3/maps/desat_sleeve_5.png', + 'phase_3/maps/desat_sleeve_6.png', + 'phase_3/maps/desat_sleeve_7.png', + 'phase_3/maps/desat_sleeve_8.png', + 'phase_3/maps/desat_sleeve_9.png', + 'phase_3/maps/desat_sleeve_10.png', + 'phase_3/maps/desat_sleeve_15.png', + 'phase_3/maps/desat_sleeve_16.png', + 'phase_3/maps/desat_sleeve_19.png', + 'phase_3/maps/desat_sleeve_20.png', + 'phase_4/maps/female_sleeve1b.png', + 'phase_4/maps/female_sleeve2.png', + 'phase_4/maps/female_sleeve3.png', + 'phase_4/maps/male_sleeve1.png', + 'phase_4/maps/male_sleeve2_palm.png', + 'phase_4/maps/male_sleeve3c.png', + 'phase_4/maps/shirt_Sleeve_ghost.png', + 'phase_4/maps/shirt_Sleeve_pumkin.png', + 'phase_4/maps/holidaySleeve1.png', + 'phase_4/maps/holidaySleeve3.png', + 'phase_4/maps/female_sleeve1b.png', + 'phase_4/maps/female_sleeve5New.png', + 'phase_4/maps/male_sleeve4New.png', + 'phase_4/maps/sleeve6New.png', + 'phase_4/maps/SleeveMaleNew7.png', + 'phase_4/maps/female_sleeveNew6.png', + 'phase_4/maps/Vday5Sleeve.png', + 'phase_4/maps/Vda6Sleeve.png', + 'phase_4/maps/Vday_shirt4sleeve.png', + 'phase_4/maps/Vday2cSleeve.png', + 'phase_4/maps/sleeveTieDye.png', + 'phase_4/maps/male_sleeve1.png', + 'phase_4/maps/StPats_sleeve.png', + 'phase_4/maps/StPats_sleeve2.png', + 'phase_4/maps/ContestfishingVestSleeve1.png', + 'phase_4/maps/ContestFishtankSleeve1.png', + 'phase_4/maps/ContestPawSleeve1.png', + 'phase_4/maps/CowboySleeve1.png', + 'phase_4/maps/CowboySleeve2.png', + 'phase_4/maps/CowboySleeve3.png', + 'phase_4/maps/CowboySleeve4.png', + 'phase_4/maps/CowboySleeve5.png', + 'phase_4/maps/CowboySleeve6.png', + 'phase_4/maps/4thJulySleeve1.png', + 'phase_4/maps/4thJulySleeve2.png', + 'phase_4/maps/shirt_sleeveCat7_01.png', + 'phase_4/maps/shirt_sleeveCat7_02.png', + 'phase_4/maps/contest_backpack_sleeve.png', + 'phase_4/maps/Contest_leder_sleeve.png', + 'phase_4/maps/contest_mellon_sleeve2.png', + 'phase_4/maps/contest_race_sleeve.png', + 'phase_4/maps/PJSleeveBlue.png', + 'phase_4/maps/PJSleeveRed.png', + 'phase_4/maps/PJSleevePurple.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_valentine1.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_valentine2.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_desat4.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_fishing1.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_fishing2.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_gardening1.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_gardening2.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_party1.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_party2.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_racing1.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_racing2.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_summer1.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_summer2.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_golf1.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_golf2.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_halloween1.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_halloween2.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_marathon1.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_saveBuilding1.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_saveBuilding2.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_toonTask1.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_toonTask2.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_trolley1.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_trolley2.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_winter1.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_halloween3.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_halloween4.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_valentine3.png', + 'phase_4/maps/tt_t_chr_shirtSleeve_scientist.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_mailbox.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_trashcan.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_loonyLabs.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_hydrant.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_whistle.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_cogbuster.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_mostCogsDefeated01.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_victoryParty01.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_victoryParty02.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_sellbotIcon.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_sellbotVPIcon.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_sellbotCrusher.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_jellyBeans.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_doodle.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_halloween5.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_halloweenTurtle.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_greentoon1.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_getConnectedMoverShaker.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_racingGrandPrix.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_lawbotIcon.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_lawbotVPIcon.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_lawbotCrusher.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_bee.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_pirate.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_supertoon.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_vampire.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_dinosaur.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_fishing04.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_golf03.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_mostCogsDefeated02.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_racing03.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_saveBuilding3.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_trolley03.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_fishing05.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_golf04.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_halloween06.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_winter03.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_halloween07.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_winter02.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_fishing06.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_fishing07.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_golf05.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_racing04.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_racing05.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_mostCogsDefeated03.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_mostCogsDefeated04.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_trolley04.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_trolley05.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_saveBuilding4.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_saveBuilding05.png', + 'phase_4/maps/tt_t_chr_avt_shirtSleeve_anniversary.png'] +BoyShorts = ['phase_3/maps/desat_shorts_1.png', + 'phase_3/maps/desat_shorts_2.png', + 'phase_3/maps/desat_shorts_4.png', + 'phase_3/maps/desat_shorts_6.png', + 'phase_3/maps/desat_shorts_7.png', + 'phase_3/maps/desat_shorts_8.png', + 'phase_3/maps/desat_shorts_9.png', + 'phase_3/maps/desat_shorts_10.png', + 'phase_4/maps/VdayShorts2.png', + 'phase_4/maps/shorts4.png', + 'phase_4/maps/shorts1.png', + 'phase_4/maps/shorts5.png', + 'phase_4/maps/CowboyShorts1.png', + 'phase_4/maps/CowboyShorts2.png', + 'phase_4/maps/4thJulyShorts1.png', + 'phase_4/maps/shortsCat7_01.png', + 'phase_4/maps/Blue_shorts_1.png', + 'phase_4/maps/Red_shorts_1.png', + 'phase_4/maps/Purple_shorts_1.png', + 'phase_4/maps/tt_t_chr_avt_shorts_winter1.png', + 'phase_4/maps/tt_t_chr_avt_shorts_winter2.png', + 'phase_4/maps/tt_t_chr_avt_shorts_winter3.png', + 'phase_4/maps/tt_t_chr_avt_shorts_winter4.png', + 'phase_4/maps/tt_t_chr_avt_shorts_valentine1.png', + 'phase_4/maps/tt_t_chr_avt_shorts_valentine2.png', + 'phase_4/maps/tt_t_chr_avt_shorts_fishing1.png', + 'phase_4/maps/tt_t_chr_avt_shorts_gardening1.png', + 'phase_4/maps/tt_t_chr_avt_shorts_party1.png', + 'phase_4/maps/tt_t_chr_avt_shorts_racing1.png', + 'phase_4/maps/tt_t_chr_avt_shorts_summer1.png', + 'phase_4/maps/tt_t_chr_avt_shorts_golf1.png', + 'phase_4/maps/tt_t_chr_avt_shorts_halloween1.png', + 'phase_4/maps/tt_t_chr_avt_shorts_halloween2.png', + 'phase_4/maps/tt_t_chr_avt_shorts_saveBuilding1.png', + 'phase_4/maps/tt_t_chr_avt_shorts_trolley1.png', + 'phase_4/maps/tt_t_chr_avt_shorts_halloween4.png', + 'phase_4/maps/tt_t_chr_avt_shorts_halloween3.png', + 'phase_4/maps/tt_t_chr_shorts_scientistA.png', + 'phase_4/maps/tt_t_chr_shorts_scientistB.png', + 'phase_4/maps/tt_t_chr_shorts_scientistC.png', + 'phase_4/maps/tt_t_chr_avt_shorts_cogbuster.png', + 'phase_4/maps/tt_t_chr_avt_shorts_sellbotCrusher.png', + 'phase_4/maps/tt_t_chr_avt_shorts_halloween5.png', + 'phase_4/maps/tt_t_chr_avt_shorts_halloweenTurtle.png', + 'phase_4/maps/tt_t_chr_avt_shorts_greentoon1.png', + 'phase_4/maps/tt_t_chr_avt_shorts_racingGrandPrix.png', + 'phase_4/maps/tt_t_chr_avt_shorts_lawbotCrusher.png', + 'phase_4/maps/tt_t_chr_avt_shorts_bee.png', + 'phase_4/maps/tt_t_chr_avt_shorts_pirate.png', + 'phase_4/maps/tt_t_chr_avt_shorts_supertoon.png', + 'phase_4/maps/tt_t_chr_avt_shorts_vampire.png', + 'phase_4/maps/tt_t_chr_avt_shorts_dinosaur.png', + 'phase_4/maps/tt_t_chr_avt_shorts_golf03.png', + 'phase_4/maps/tt_t_chr_avt_shorts_racing03.png', + 'phase_4/maps/tt_t_chr_avt_shorts_golf04.png', + 'phase_4/maps/tt_t_chr_avt_shorts_golf05.png', + 'phase_4/maps/tt_t_chr_avt_shorts_racing04.png', + 'phase_4/maps/tt_t_chr_avt_shorts_racing05.png'] SHORTS = 0 SKIRT = 1 -GirlBottoms = [('phase_3/maps/desat_skirt_1.jpg', SKIRT), - ('phase_3/maps/desat_skirt_2.jpg', SKIRT), - ('phase_3/maps/desat_skirt_3.jpg', SKIRT), - ('phase_3/maps/desat_skirt_4.jpg', SKIRT), - ('phase_3/maps/desat_skirt_5.jpg', SKIRT), - ('phase_3/maps/desat_shorts_1.jpg', SHORTS), - ('phase_3/maps/desat_shorts_5.jpg', SHORTS), - ('phase_3/maps/desat_skirt_6.jpg', SKIRT), - ('phase_3/maps/desat_skirt_7.jpg', SKIRT), - ('phase_3/maps/desat_shorts_10.jpg', SHORTS), - ('phase_4/maps/female_skirt1.jpg', SKIRT), - ('phase_4/maps/female_skirt2.jpg', SKIRT), - ('phase_4/maps/female_skirt3.jpg', SKIRT), - ('phase_4/maps/VdaySkirt1.jpg', SKIRT), - ('phase_4/maps/skirtNew5.jpg', SKIRT), - ('phase_4/maps/shorts5.jpg', SHORTS), - ('phase_4/maps/CowboySkirt1.jpg', SKIRT), - ('phase_4/maps/CowboySkirt2.jpg', SKIRT), - ('phase_4/maps/4thJulySkirt1.jpg', SKIRT), - ('phase_4/maps/skirtCat7_01.jpg', SKIRT), - ('phase_4/maps/Blue_shorts_1.jpg', SHORTS), - ('phase_4/maps/Red_shorts_1.jpg', SHORTS), - ('phase_4/maps/Purple_shorts_1.jpg', SHORTS), - ('phase_4/maps/tt_t_chr_avt_skirt_winter1.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_winter2.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_winter3.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_winter4.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_valentine1.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_valentine2.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_fishing1.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_gardening1.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_party1.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_racing1.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_summer1.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_golf1.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_halloween1.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_halloween2.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_saveBuilding1.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_trolley1.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_halloween3.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_halloween4.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_shorts_scientistA.jpg', SHORTS), - ('phase_4/maps/tt_t_chr_shorts_scientistB.jpg', SHORTS), - ('phase_4/maps/tt_t_chr_shorts_scientistC.jpg', SHORTS), - ('phase_4/maps/tt_t_chr_avt_shorts_cogbuster.jpg', SHORTS), - ('phase_4/maps/tt_t_chr_avt_shorts_sellbotCrusher.jpg', SHORTS), - ('phase_4/maps/tt_t_chr_avt_shorts_halloween5.jpg', SHORTS), - ('phase_4/maps/tt_t_chr_avt_shorts_halloweenTurtle.jpg', SHORTS), - ('phase_4/maps/tt_t_chr_avt_skirt_greentoon1.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_racingGrandPrix.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_shorts_lawbotCrusher.jpg', SHORTS), - ('phase_4/maps/tt_t_chr_avt_shorts_bee.jpg', SHORTS), - ('phase_4/maps/tt_t_chr_avt_shorts_pirate.jpg', SHORTS), - ('phase_4/maps/tt_t_chr_avt_skirt_pirate.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_shorts_supertoon.jpg', SHORTS), - ('phase_4/maps/tt_t_chr_avt_shorts_vampire.jpg', SHORTS), - ('phase_4/maps/tt_t_chr_avt_shorts_dinosaur.jpg', SHORTS), - ('phase_4/maps/tt_t_chr_avt_skirt_golf02.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_racing03.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_golf03.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_golf04.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_racing04.jpg', SKIRT), - ('phase_4/maps/tt_t_chr_avt_skirt_racing05.jpg', SKIRT)] +GirlBottoms = [('phase_3/maps/desat_skirt_1.png', SKIRT), + ('phase_3/maps/desat_skirt_2.png', SKIRT), + ('phase_3/maps/desat_skirt_3.png', SKIRT), + ('phase_3/maps/desat_skirt_4.png', SKIRT), + ('phase_3/maps/desat_skirt_5.png', SKIRT), + ('phase_3/maps/desat_shorts_1.png', SHORTS), + ('phase_3/maps/desat_shorts_5.png', SHORTS), + ('phase_3/maps/desat_skirt_6.png', SKIRT), + ('phase_3/maps/desat_skirt_7.png', SKIRT), + ('phase_3/maps/desat_shorts_10.png', SHORTS), + ('phase_4/maps/female_skirt1.png', SKIRT), + ('phase_4/maps/female_skirt2.png', SKIRT), + ('phase_4/maps/female_skirt3.png', SKIRT), + ('phase_4/maps/VdaySkirt1.png', SKIRT), + ('phase_4/maps/skirtNew5.png', SKIRT), + ('phase_4/maps/shorts5.png', SHORTS), + ('phase_4/maps/CowboySkirt1.png', SKIRT), + ('phase_4/maps/CowboySkirt2.png', SKIRT), + ('phase_4/maps/4thJulySkirt1.png', SKIRT), + ('phase_4/maps/skirtCat7_01.png', SKIRT), + ('phase_4/maps/Blue_shorts_1.png', SHORTS), + ('phase_4/maps/Red_shorts_1.png', SHORTS), + ('phase_4/maps/Purple_shorts_1.png', SHORTS), + ('phase_4/maps/tt_t_chr_avt_skirt_winter1.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_winter2.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_winter3.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_winter4.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_valentine1.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_valentine2.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_fishing1.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_gardening1.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_party1.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_racing1.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_summer1.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_golf1.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_halloween1.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_halloween2.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_saveBuilding1.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_trolley1.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_halloween3.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_halloween4.png', SKIRT), + ('phase_4/maps/tt_t_chr_shorts_scientistA.png', SHORTS), + ('phase_4/maps/tt_t_chr_shorts_scientistB.png', SHORTS), + ('phase_4/maps/tt_t_chr_shorts_scientistC.png', SHORTS), + ('phase_4/maps/tt_t_chr_avt_shorts_cogbuster.png', SHORTS), + ('phase_4/maps/tt_t_chr_avt_shorts_sellbotCrusher.png', SHORTS), + ('phase_4/maps/tt_t_chr_avt_shorts_halloween5.png', SHORTS), + ('phase_4/maps/tt_t_chr_avt_shorts_halloweenTurtle.png', SHORTS), + ('phase_4/maps/tt_t_chr_avt_skirt_greentoon1.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_racingGrandPrix.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_shorts_lawbotCrusher.png', SHORTS), + ('phase_4/maps/tt_t_chr_avt_shorts_bee.png', SHORTS), + ('phase_4/maps/tt_t_chr_avt_shorts_pirate.png', SHORTS), + ('phase_4/maps/tt_t_chr_avt_skirt_pirate.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_shorts_supertoon.png', SHORTS), + ('phase_4/maps/tt_t_chr_avt_shorts_vampire.png', SHORTS), + ('phase_4/maps/tt_t_chr_avt_shorts_dinosaur.png', SHORTS), + ('phase_4/maps/tt_t_chr_avt_skirt_golf02.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_racing03.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_golf03.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_golf04.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_racing04.png', SKIRT), + ('phase_4/maps/tt_t_chr_avt_skirt_racing05.png', SKIRT)] ClothesColors = [VBase4(0.933594, 0.265625, 0.28125, 1.0), VBase4(0.863281, 0.40625, 0.417969, 1.0), VBase4(0.710938, 0.234375, 0.4375, 1.0), @@ -2037,25 +2037,25 @@ HatModels = [None, 'phase_4/models/accessories/tt_m_chr_avt_acc_hat_band', 'phase_4/models/accessories/tt_m_chr_avt_acc_hat_birdNest'] HatTextures = [None, - 'phase_4/maps/tt_t_chr_avt_acc_hat_ribbonRed.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_hat_ribbonPurple.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_hat_heartYellow.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_hat_topHatBlue.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_hat_safariBrown.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_hat_safariGreen.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_hat_baseballBlue.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_hat_baseballOrange.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_hat_ribbonYellow.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_hat_ribbonChecker.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_hat_ribbonLtRed.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_hat_ribbonRainbow.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_hat_baseballYellow.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_hat_baseballRed.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_hat_baseballTeal.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_hat_ribbonPinkDots.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_hat_baseballPurple.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_hat_ribbonCheckerGreen.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_hat_partyToon.jpg'] + 'phase_4/maps/tt_t_chr_avt_acc_hat_ribbonRed.png', + 'phase_4/maps/tt_t_chr_avt_acc_hat_ribbonPurple.png', + 'phase_4/maps/tt_t_chr_avt_acc_hat_heartYellow.png', + 'phase_4/maps/tt_t_chr_avt_acc_hat_topHatBlue.png', + 'phase_4/maps/tt_t_chr_avt_acc_hat_safariBrown.png', + 'phase_4/maps/tt_t_chr_avt_acc_hat_safariGreen.png', + 'phase_4/maps/tt_t_chr_avt_acc_hat_baseballBlue.png', + 'phase_4/maps/tt_t_chr_avt_acc_hat_baseballOrange.png', + 'phase_4/maps/tt_t_chr_avt_acc_hat_ribbonYellow.png', + 'phase_4/maps/tt_t_chr_avt_acc_hat_ribbonChecker.png', + 'phase_4/maps/tt_t_chr_avt_acc_hat_ribbonLtRed.png', + 'phase_4/maps/tt_t_chr_avt_acc_hat_ribbonRainbow.png', + 'phase_4/maps/tt_t_chr_avt_acc_hat_baseballYellow.png', + 'phase_4/maps/tt_t_chr_avt_acc_hat_baseballRed.png', + 'phase_4/maps/tt_t_chr_avt_acc_hat_baseballTeal.png', + 'phase_4/maps/tt_t_chr_avt_acc_hat_ribbonPinkDots.png', + 'phase_4/maps/tt_t_chr_avt_acc_hat_baseballPurple.png', + 'phase_4/maps/tt_t_chr_avt_acc_hat_ribbonCheckerGreen.png', + 'phase_4/maps/tt_t_chr_avt_acc_hat_partyToon.png'] GlassesModels = [None, 'phase_4/models/accessories/tt_m_chr_avt_acc_msk_roundGlasses', 'phase_4/models/accessories/tt_m_chr_avt_acc_msk_miniblinds', @@ -2079,10 +2079,10 @@ GlassesModels = [None, 'phase_4/models/accessories/tt_m_chr_avt_acc_msk_eyepatch', 'phase_4/models/accessories/tt_m_chr_avt_acc_msk_alienGlasses'] GlassesTextures = [None, - 'phase_4/maps/tt_t_chr_avt_acc_msk_masqueradeTypeMask2.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_msk_masqueradeTypeMask4.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_msk_masqueradeTypeMask5.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_msk_eyepatchGems.jpg'] + 'phase_4/maps/tt_t_chr_avt_acc_msk_masqueradeTypeMask2.png', + 'phase_4/maps/tt_t_chr_avt_acc_msk_masqueradeTypeMask4.png', + 'phase_4/maps/tt_t_chr_avt_acc_msk_masqueradeTypeMask5.png', + 'phase_4/maps/tt_t_chr_avt_acc_msk_eyepatchGems.png'] BackpackModels = [None, 'phase_4/models/accessories/tt_m_chr_avt_acc_pac_backpack', 'phase_4/models/accessories/tt_m_chr_avt_acc_pac_batWings', @@ -2109,65 +2109,65 @@ BackpackModels = [None, 'phase_4/models/accessories/tt_m_chr_avt_acc_pac_gags', 'phase_4/models/accessories/tt_m_chr_avt_acc_pac_flunky'] BackpackTextures = [None, - 'phase_4/maps/tt_t_chr_avt_acc_pac_backpackOrange.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_pac_backpackPurple.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_pac_backpackPolkaDotRed.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_pac_backpackPolkaDotYellow.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_pac_angelWingsMultiColor.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_pac_butterflyWingsStyle2.jpg'] + 'phase_4/maps/tt_t_chr_avt_acc_pac_backpackOrange.png', + 'phase_4/maps/tt_t_chr_avt_acc_pac_backpackPurple.png', + 'phase_4/maps/tt_t_chr_avt_acc_pac_backpackPolkaDotRed.png', + 'phase_4/maps/tt_t_chr_avt_acc_pac_backpackPolkaDotYellow.png', + 'phase_4/maps/tt_t_chr_avt_acc_pac_angelWingsMultiColor.png', + 'phase_4/maps/tt_t_chr_avt_acc_pac_butterflyWingsStyle2.png'] ShoesModels = ['feet', 'shoes', 'boots_short', 'boots_long'] -ShoesTextures = ['phase_3/maps/tt_t_chr_avt_acc_sho_athleticGreen.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_athleticRed.jpg', - 'phase_3/maps/tt_t_chr_avt_acc_sho_docMartinBootsGreen.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_converseStyleGreen.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_wingtips.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_maryJaneShoes.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_deckShoes.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_athleticYellow.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_converseStyleBlack.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_converseStyleWhite.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_converseStylePink.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_cowboyBoots.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_fashionBootsPurple.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_hiTopSneakers.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_maryJaneShoesBrown.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_maryJaneShoesRed.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_superToonRedBoots.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_tennisShoesGreen.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_tennisShoesPink.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_converseStyleRed.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_docMartinBootsAqua.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_docMartinBootsBrown.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_docMartinBootsYellow.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_fashionBootsBlueSquares.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_fashionBootsGreenHearts.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_fashionBootsGreyDots.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_fashionBootsOrangeStars.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_fashionBootsPinkStars.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_loafers.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_maryJaneShoesPurple.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_motorcycleBoots.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_oxfords.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_rainBootsPink.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_santaBoots.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_winterBootsBeige.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_winterBootsPink.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_workBoots.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_converseStyleYellow.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_docMartinBootsPink.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_hiTopSneakersPink.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_rainBootsRedDots.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_tennisShoesPurple.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_tennisShoesViolet.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_tennisShoesYellow.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_rainBootsBlue.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_rainBootsYellow.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_athleticBlack.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_pirate.jpg', - 'phase_4/maps/tt_t_chr_avt_acc_sho_dinosaur.jpg'] +ShoesTextures = ['phase_3/maps/tt_t_chr_avt_acc_sho_athleticGreen.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_athleticRed.png', + 'phase_3/maps/tt_t_chr_avt_acc_sho_docMartinBootsGreen.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_converseStyleGreen.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_wingtips.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_maryJaneShoes.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_deckShoes.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_athleticYellow.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_converseStyleBlack.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_converseStyleWhite.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_converseStylePink.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_cowboyBoots.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_fashionBootsPurple.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_hiTopSneakers.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_maryJaneShoesBrown.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_maryJaneShoesRed.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_superToonRedBoots.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_tennisShoesGreen.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_tennisShoesPink.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_converseStyleRed.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_docMartinBootsAqua.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_docMartinBootsBrown.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_docMartinBootsYellow.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_fashionBootsBlueSquares.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_fashionBootsGreenHearts.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_fashionBootsGreyDots.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_fashionBootsOrangeStars.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_fashionBootsPinkStars.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_loafers.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_maryJaneShoesPurple.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_motorcycleBoots.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_oxfords.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_rainBootsPink.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_santaBoots.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_winterBootsBeige.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_winterBootsPink.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_workBoots.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_converseStyleYellow.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_docMartinBootsPink.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_hiTopSneakersPink.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_rainBootsRedDots.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_tennisShoesPurple.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_tennisShoesViolet.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_tennisShoesYellow.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_rainBootsBlue.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_rainBootsYellow.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_athleticBlack.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_pirate.png', + 'phase_4/maps/tt_t_chr_avt_acc_sho_dinosaur.png'] HatStyles = {'none': [0, 0, 0], 'hbb1': [1, 0, 0], 'hsf1': [2, 0, 0], diff --git a/toontown/toon/ToonHead.py b/toontown/toon/ToonHead.py index 7a0769b..84b82ae 100644 --- a/toontown/toon/ToonHead.py +++ b/toontown/toon/ToonHead.py @@ -50,31 +50,31 @@ DogMuzzleDict = {'dls': '/models/char/dogMM_Shorts-headMuzzles-', class ToonHead(Actor.Actor): notify = DirectNotifyGlobal.directNotify.newCategory('ToonHead') - EyesOpen = loader.loadTexture('phase_3/maps/eyes.jpg', 'phase_3/maps/eyes_a.rgb') + EyesOpen = loader.loadTexture('phase_3/maps/eyes.png') EyesOpen.setMinfilter(Texture.FTLinear) EyesOpen.setMagfilter(Texture.FTLinear) - EyesClosed = loader.loadTexture('phase_3/maps/eyesClosed.jpg', 'phase_3/maps/eyesClosed_a.rgb') + EyesClosed = loader.loadTexture('phase_3/maps/eyesClosed.png') EyesClosed.setMinfilter(Texture.FTLinear) EyesClosed.setMagfilter(Texture.FTLinear) - EyesSadOpen = loader.loadTexture('phase_3/maps/eyesSad.jpg', 'phase_3/maps/eyesSad_a.rgb') + EyesSadOpen = loader.loadTexture('phase_3/maps/eyesSad.png') EyesSadOpen.setMinfilter(Texture.FTLinear) EyesSadOpen.setMagfilter(Texture.FTLinear) - EyesSadClosed = loader.loadTexture('phase_3/maps/eyesSadClosed.jpg', 'phase_3/maps/eyesSadClosed_a.rgb') + EyesSadClosed = loader.loadTexture('phase_3/maps/eyesSadClosed.png') EyesSadClosed.setMinfilter(Texture.FTLinear) EyesSadClosed.setMagfilter(Texture.FTLinear) - EyesAngryOpen = loader.loadTexture('phase_3/maps/eyesAngry.jpg', 'phase_3/maps/eyesAngry_a.rgb') + EyesAngryOpen = loader.loadTexture('phase_3/maps/eyesAngry.png') EyesAngryOpen.setMinfilter(Texture.FTLinear) EyesAngryOpen.setMagfilter(Texture.FTLinear) - EyesAngryClosed = loader.loadTexture('phase_3/maps/eyesAngryClosed.jpg', 'phase_3/maps/eyesAngryClosed_a.rgb') + EyesAngryClosed = loader.loadTexture('phase_3/maps/eyesAngryClosed.png') EyesAngryClosed.setMinfilter(Texture.FTLinear) EyesAngryClosed.setMagfilter(Texture.FTLinear) - EyesSurprised = loader.loadTexture('phase_3/maps/eyesSurprised.jpg', 'phase_3/maps/eyesSurprised_a.rgb') + EyesSurprised = loader.loadTexture('phase_3/maps/eyesSurprised.png') EyesSurprised.setMinfilter(Texture.FTLinear) EyesSurprised.setMagfilter(Texture.FTLinear) - Muzzle = loader.loadTexture('phase_3/maps/muzzleShrtGeneric.jpg') + Muzzle = loader.loadTexture('phase_3/maps/muzzleShrtGeneric.png') Muzzle.setMinfilter(Texture.FTLinear) Muzzle.setMagfilter(Texture.FTLinear) - MuzzleSurprised = loader.loadTexture('phase_3/maps/muzzleShortSurprised.jpg') + MuzzleSurprised = loader.loadTexture('phase_3/maps/muzzleShortSurprised.png') MuzzleSurprised.setMinfilter(Texture.FTLinear) MuzzleSurprised.setMagfilter(Texture.FTLinear) LeftA = Point3(0.06, 0.0, 0.14) diff --git a/toontown/town/Street.py b/toontown/town/Street.py index 975b65f..ead20cd 100644 --- a/toontown/town/Street.py +++ b/toontown/town/Street.py @@ -386,13 +386,11 @@ class Street(BattlePlace.BattlePlace): streetSign = base.cr.streetSign signTexturePath = streetSign.StreetSignBaseDir + '/' + streetSign.StreetSignFileName loaderTexturePath = Filename(str(signTexturePath)) - alphaPath = 'phase_4/maps/tt_t_ara_gen_tunnelAheadSign_a.rgb' inDreamland = False if place.zoneId and ZoneUtil.getCanonicalHoodId(place.zoneId) == ToontownGlobals.DonaldsDreamland: inDreamland = True - alphaPath = 'phase_4/maps/tt_t_ara_gen_tunnelAheadSign_a.rgb' if Filename(signTexturePath).exists(): - signTexture = loader.loadTexture(loaderTexturePath, alphaPath) + signTexture = loader.loadTexture(loaderTexturePath) for sign in signs: if Filename(signTexturePath).exists(): sign.setTexture(signTexture, 1) From 6deb7056e24ee6e6846e715fbb0ccb6ef316c8d9 Mon Sep 17 00:00:00 2001 From: "Erica M. (\"Loonatic\")" Date: Thu, 12 Jan 2023 19:48:12 -0600 Subject: [PATCH 02/48] Fonts: Add TTF variants for most fonts --- toontown/toonbase/TTLocalizerEnglish.py | 34 +++++++++++++------------ 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/toontown/toonbase/TTLocalizerEnglish.py b/toontown/toonbase/TTLocalizerEnglish.py index 925284f..2416935 100644 --- a/toontown/toonbase/TTLocalizerEnglish.py +++ b/toontown/toonbase/TTLocalizerEnglish.py @@ -10,22 +10,24 @@ InterfaceFont = 'phase_3/models/fonts/ImpressBT.ttf' ToonFont = 'phase_3/models/fonts/ImpressBT.ttf' SuitFont = 'phase_3/models/fonts/vtRemingtonPortable.ttf' SignFont = 'phase_3/models/fonts/MickeyFont' -MinnieFont = 'phase_3/models/fonts/MinnieFont' -FancyFont = 'phase_3/models/fonts/Comedy' -NametagFonts = ('phase_3/models/fonts/AnimGothic', - 'phase_3/models/fonts/Aftershock', - 'phase_3/models/fonts/JiggeryPokery', - 'phase_3/models/fonts/Ironwork', - 'phase_3/models/fonts/HastyPudding', - 'phase_3/models/fonts/Comedy', - 'phase_3/models/fonts/Humanist', - 'phase_3/models/fonts/Portago', - 'phase_3/models/fonts/Musicals', - 'phase_3/models/fonts/Scurlock', - 'phase_3/models/fonts/Danger', - 'phase_3/models/fonts/Alie', - 'phase_3/models/fonts/OysterBar', - 'phase_3/models/fonts/RedDogSaloon') +MinnieFont = 'phase_3/models/fonts/MinnieFont.ttf' +FancyFont = 'phase_3/models/fonts/Comedy.ttf' +NametagFonts = ( + 'phase_3/models/fonts/AnimGothic.ttf', + 'phase_3/models/fonts/Aftershock.ttf', + 'phase_3/models/fonts/JiggeryPokery.ttf', + 'phase_3/models/fonts/Ironwork.ttf', + 'phase_3/models/fonts/HastyPudding.ttf', + 'phase_3/models/fonts/Comedy.ttf', + 'phase_3/models/fonts/Humanist.ttf', + 'phase_3/models/fonts/Portago.ttf', + 'phase_3/models/fonts/Musicals.ttf', + 'phase_3/models/fonts/Scurlock.ttf', + 'phase_3/models/fonts/Danger.ttf', + 'phase_3/models/fonts/Alie.ttf', + 'phase_3/models/fonts/OysterBar.ttf', + 'phase_3/models/fonts/RedDogSaloon.ttf' +) NametagFontNames = ('Member', 'Shivering', 'Wonky', From 325fdddf93e7b26e89903bbc238e1a63ea8771bf Mon Sep 17 00:00:00 2001 From: Little Cat Date: Fri, 13 Jan 2023 05:36:38 -0400 Subject: [PATCH 03/48] suit: Add missing CFO import. --- toontown/suit/DistributedCashbotBoss.py | 1 + 1 file changed, 1 insertion(+) diff --git a/toontown/suit/DistributedCashbotBoss.py b/toontown/suit/DistributedCashbotBoss.py index b8186b6..b4cdfce 100644 --- a/toontown/suit/DistributedCashbotBoss.py +++ b/toontown/suit/DistributedCashbotBoss.py @@ -19,6 +19,7 @@ from toontown.distributed import DelayDelete from toontown.chat import ResistanceChat from toontown.coghq import CogDisguiseGlobals from panda3d.core import * +from panda3d.direct import ShowInterval from panda3d.physics import * from panda3d.otp import * import random From 5151d94ac438520ab4fa589832270395126d906e Mon Sep 17 00:00:00 2001 From: Little Cat Date: Fri, 13 Jan 2023 05:37:32 -0400 Subject: [PATCH 04/48] spellbook: Fix crash when using minigame word in welcome valley. --- 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 d01e34e..aaf47da 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -352,7 +352,7 @@ class Minigame(MagicWord): if any((isTeleport, isRequest)): if isTeleport and (ZoneUtil.isDynamicZone(toon.zoneId) or not toon.zoneId == mgSzId): return "Target needs to be in a playground to teleport to a minigame." - MinigameCreatorAI.RequestMinigame[avId] = (mgId, mgKeep, mgDiff, mgSzId) + MinigameCreatorAI.RequestMinigame[avId] = (mgId, mgKeep, mgDiff, ToontownGlobals.ToontownCentral if ZoneUtil.isWelcomeValley(mgSzId) else mgSzId) if isTeleport: try: result = MinigameCreatorAI.createMinigame(self.air, [avId], mgSzId) From 717ef9f1bbf1223fff53ce09c893cae0ace9fb41 Mon Sep 17 00:00:00 2001 From: DarthNihilus1 Date: Fri, 20 Jan 2023 00:30:39 -0500 Subject: [PATCH 05/48] Kart: Fix crash when buying kart --- toontown/racing/Kart.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toontown/racing/Kart.py b/toontown/racing/Kart.py index fd19504..b772461 100644 --- a/toontown/racing/Kart.py +++ b/toontown/racing/Kart.py @@ -1,7 +1,7 @@ from direct.directnotify import DirectNotifyGlobal from panda3d.core import * +from panda3d.physics import * from direct.gui.DirectGui import * -from panda3d.core import * from direct.interval.IntervalGlobal import * from otp.avatar import ShadowCaster from toontown.racing.KartDNA import * From 3b98453725e4bafb02ea014d8d3a918eb4bd3a40 Mon Sep 17 00:00:00 2001 From: Open Toontown <57279094+opentoontown@users.noreply.github.com> Date: Sun, 26 Mar 2023 20:27:23 -0400 Subject: [PATCH 06/48] fix ImportError on newer panda3d --- toontown/cogdominium/CogdoExecutiveSuiteMovies.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/toontown/cogdominium/CogdoExecutiveSuiteMovies.py b/toontown/cogdominium/CogdoExecutiveSuiteMovies.py index 0558ba0..9868269 100644 --- a/toontown/cogdominium/CogdoExecutiveSuiteMovies.py +++ b/toontown/cogdominium/CogdoExecutiveSuiteMovies.py @@ -1,6 +1,5 @@ -from panda3d.core import NodePath, Point3, PlaneNode, TextNode +from panda3d.core import NodePath, Point3, Plane, PlaneNode, TextNode from direct.interval.IntervalGlobal import * -from direct.showbase.ShowBase import Plane from direct.directnotify import DirectNotifyGlobal from direct.showbase.RandomNumGen import RandomNumGen from direct.interval.MetaInterval import Sequence, Parallel From f6d57ced5c536b1deb0c38ac6cf132870b7a9177 Mon Sep 17 00:00:00 2001 From: Open Toontown <57279094+opentoontown@users.noreply.github.com> Date: Sun, 26 Mar 2023 20:39:59 -0400 Subject: [PATCH 07/48] fix more ImportErrors --- toontown/cogdominium/CogdoElevatorMovie.py | 3 +-- toontown/cogdominium/CogdoFlyingGameMovies.py | 3 +-- toontown/cogdominium/CogdoMazeGameMovies.py | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/toontown/cogdominium/CogdoElevatorMovie.py b/toontown/cogdominium/CogdoElevatorMovie.py index c76972f..269b3d8 100644 --- a/toontown/cogdominium/CogdoElevatorMovie.py +++ b/toontown/cogdominium/CogdoElevatorMovie.py @@ -1,6 +1,5 @@ -from panda3d.core import NodePath, Point3, PlaneNode, TextNode +from panda3d.core import NodePath, Point3, Plane, PlaneNode, TextNode from direct.interval.IntervalGlobal import * -from direct.showbase.ShowBase import Plane from direct.directnotify import DirectNotifyGlobal from direct.showbase.RandomNumGen import RandomNumGen from direct.interval.MetaInterval import Sequence, Parallel diff --git a/toontown/cogdominium/CogdoFlyingGameMovies.py b/toontown/cogdominium/CogdoFlyingGameMovies.py index 64378a5..3ce87ca 100644 --- a/toontown/cogdominium/CogdoFlyingGameMovies.py +++ b/toontown/cogdominium/CogdoFlyingGameMovies.py @@ -1,5 +1,4 @@ -from panda3d.core import Point3, PlaneNode -from direct.showbase.ShowBase import Plane +from panda3d.core import Point3, Plane, PlaneNode from direct.showbase.RandomNumGen import RandomNumGen from direct.interval.MetaInterval import Sequence, Parallel from direct.interval.FunctionInterval import Func, Wait diff --git a/toontown/cogdominium/CogdoMazeGameMovies.py b/toontown/cogdominium/CogdoMazeGameMovies.py index e3b45e5..20e6874 100644 --- a/toontown/cogdominium/CogdoMazeGameMovies.py +++ b/toontown/cogdominium/CogdoMazeGameMovies.py @@ -1,5 +1,4 @@ -from panda3d.core import NodePath, Point3, PlaneNode -from direct.showbase.ShowBase import Plane +from panda3d.core import NodePath, Point3, Plane, PlaneNode from direct.showbase.RandomNumGen import RandomNumGen from direct.interval.MetaInterval import Sequence, Parallel from direct.interval.FunctionInterval import Func, Wait From 22f87eb182dd5c8ad0d95dbd23f6286abb6b3c1f Mon Sep 17 00:00:00 2001 From: Open Toontown <57279094+opentoontown@users.noreply.github.com> Date: Sun, 23 Apr 2023 02:21:37 -0400 Subject: [PATCH 08/48] fix missing msgtypes --- otp/login/AstronLoginManagerUD.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/otp/login/AstronLoginManagerUD.py b/otp/login/AstronLoginManagerUD.py index af41023..3f905c9 100644 --- a/otp/login/AstronLoginManagerUD.py +++ b/otp/login/AstronLoginManagerUD.py @@ -5,7 +5,17 @@ from datetime import datetime from direct.directnotify import DirectNotifyGlobal from direct.distributed.DistributedObjectGlobalUD import DistributedObjectGlobalUD -from direct.distributed.PyDatagram import * +from direct.distributed.PyDatagram import PyDatagram +from direct.distributed.MsgTypes import ( + CLIENTAGENT_ADD_POST_REMOVE, + CLIENTAGENT_CLEAR_POST_REMOVES, + CLIENTAGENT_CLOSE_CHANNEL, + CLIENTAGENT_EJECT, + CLIENTAGENT_OPEN_CHANNEL, + CLIENTAGENT_REMOVE_SESSION_OBJECT, + CLIENTAGENT_SET_CLIENT_ID, + STATESERVER_OBJECT_DELETE_RAM +) from otp.otpbase import OTPGlobals From 327fb57e614fa70da64f19baa36cf9f0b7be8e83 Mon Sep 17 00:00:00 2001 From: Open Toontown <57279094+opentoontown@users.noreply.github.com> Date: Sun, 23 Apr 2023 23:18:37 -0400 Subject: [PATCH 09/48] misc cleanup --- toontown/minigame/OrthoDrive.py | 25 +++++++++++++++--------- toontown/minigame/TwoDDrive.py | 30 ++++++++++++++++++----------- toontown/toonbase/ToonBaseGlobal.py | 6 +++++- toontown/toonbase/ToontownStart.py | 29 ++++++++++++++++++---------- 4 files changed, 59 insertions(+), 31 deletions(-) diff --git a/toontown/minigame/OrthoDrive.py b/toontown/minigame/OrthoDrive.py index 0b3a904..742906f 100644 --- a/toontown/minigame/OrthoDrive.py +++ b/toontown/minigame/OrthoDrive.py @@ -1,11 +1,18 @@ -from direct.interval.IntervalGlobal import * -from direct.task.Task import Task +from panda3d.core import Point3, Vec3 + +from direct.directnotify.DirectNotifyGlobal import directNotify +from direct.interval.IntervalGlobal import LerpHprInterval +from direct.showbase.PythonUtil import fitSrcAngle2Dest +from direct.task.TaskManagerGlobal import taskMgr + from otp.otpbase import OTPGlobals -from toontown.toonbase.ToonBaseGlobal import * -from . import ArrowKeys + +from toontown.minigame.ArrowKeys import ArrowKeys +from toontown.toonbase.ToonBaseGlobal import base + class OrthoDrive: - notify = DirectNotifyGlobal.directNotify.newCategory('OrthoDrive') + notify = directNotify.newCategory('OrthoDrive') TASK_NAME = 'OrthoDriveTask' SET_ATREST_HEADING_TASK = 'setAtRestHeadingTask' @@ -17,7 +24,7 @@ class OrthoDrive: self.priority = priority self.setHeading = setHeading self.upHeading = upHeading - self.arrowKeys = ArrowKeys.ArrowKeys() + self.arrowKeys = ArrowKeys() self.lt = base.localAvatar self.instantTurn = instantTurn @@ -85,7 +92,7 @@ class OrthoDrive: if self.setHeading: self.__handleHeading(xVel, yVel) toonPos = self.lt.getPos() - dt = globalClock.getDt() + dt = base.clock.getDt() posOffset = vel * dt posOffset += toonPos - self.lastPos toonPos = self.lastPos @@ -100,7 +107,7 @@ class OrthoDrive: toonPos = toonPos + posOffset self.lt.setPos(toonPos) self.lastPos = toonPos - return Task.cont + return task.cont def __handleHeading(self, xVel, yVel): def getHeading(xVel, yVel): @@ -126,7 +133,7 @@ class OrthoDrive: if ((self.lastXVel and self.lastYVel) and not (xVel and yVel)): def setAtRestHeading(task, self = self, angle = curHeading): self.atRestHeading = angle - return Task.done + return task.done taskMgr.doMethodLater(0.05, setAtRestHeading, OrthoDrive.SET_ATREST_HEADING_TASK) else: diff --git a/toontown/minigame/TwoDDrive.py b/toontown/minigame/TwoDDrive.py index 0fc34f1..16284a3 100644 --- a/toontown/minigame/TwoDDrive.py +++ b/toontown/minigame/TwoDDrive.py @@ -1,11 +1,19 @@ -from toontown.toonbase.ToonBaseGlobal import * +from panda3d.core import Point3, Vec3 + +from direct.directnotify.DirectNotifyGlobal import directNotify +from direct.interval.IntervalGlobal import LerpHprInterval +from direct.showbase.MessengerGlobal import messenger +from direct.showbase.PythonUtil import fitSrcAngle2Dest +from direct.task.TaskManagerGlobal import taskMgr + from otp.otpbase import OTPGlobals -from direct.interval.IntervalGlobal import * -from . import ArrowKeys -from direct.task.Task import Task + +from toontown.minigame.ArrowKeys import ArrowKeys +from toontown.toonbase.ToonBaseGlobal import base + class TwoDDrive: - notify = DirectNotifyGlobal.directNotify.newCategory('TwoDDrive') + notify = directNotify.newCategory('TwoDDrive') TASK_NAME = 'TwoDDriveTask' SET_ATREST_HEADING_TASK = 'setAtRestHeadingTask' @@ -17,7 +25,7 @@ class TwoDDrive: self.priority = priority self.setHeading = setHeading self.upHeading = upHeading - self.arrowKeys = ArrowKeys.ArrowKeys() + self.arrowKeys = ArrowKeys() self.wasUpReleased = True self.lt = base.localAvatar base.localAvatar.useTwoDControls() @@ -78,11 +86,11 @@ class TwoDDrive: elif self.arrowKeys.upPressed() and self.wasUpReleased: self.wasUpReleased = False if not self.game.isHeadInFloor: - if localAvatar.controlManager.currentControls == localAvatar.controlManager.get('twoD'): + if base.localAvatar.controlManager.currentControls == base.localAvatar.controlManager.get('twoD'): base.localAvatar.controlManager.currentControls.jumpPressed() elif self.arrowKeys.upPressed(): if not self.game.isHeadInFloor: - if localAvatar.controlManager.currentControls == localAvatar.controlManager.get('twoD'): + if base.localAvatar.controlManager.currentControls == base.localAvatar.controlManager.get('twoD'): base.localAvatar.controlManager.currentControls.jumpPressed() if self.arrowKeys.leftPressed(): xVel -= 1 @@ -110,7 +118,7 @@ class TwoDDrive: if self.setHeading: self.__handleHeading(xVel, yVel) toonPos = self.lt.getPos() - dt = globalClock.getDt() + dt = base.clock.getDt() posOffset = vel * dt if self.customCollisionCallback: toonPos = self.customCollisionCallback(toonPos, toonPos + posOffset) @@ -118,7 +126,7 @@ class TwoDDrive: toonPos += posOffset self.lt.setPos(toonPos) self.lastPos = toonPos - return Task.cont + return task.cont def __handleHeading(self, xVel, yVel): def getHeading(xVel, yVel): @@ -144,7 +152,7 @@ class TwoDDrive: if ((self.lastXVel and self.lastYVel) and not (xVel and yVel)): def setAtRestHeading(task, self = self, angle = curHeading): self.atRestHeading = angle - return Task.done + return task.done taskMgr.doMethodLater(0.05, setAtRestHeading, TwoDDrive.SET_ATREST_HEADING_TASK) else: diff --git a/toontown/toonbase/ToonBaseGlobal.py b/toontown/toonbase/ToonBaseGlobal.py index d10c337..7ddaba1 100644 --- a/toontown/toonbase/ToonBaseGlobal.py +++ b/toontown/toonbase/ToonBaseGlobal.py @@ -1 +1,5 @@ -from .ToonBase import * +__all__ = ['base'] + +from .ToonBase import ToonBase + +base = ToonBase() diff --git a/toontown/toonbase/ToontownStart.py b/toontown/toonbase/ToontownStart.py index 6ecda03..f331542 100644 --- a/toontown/toonbase/ToontownStart.py +++ b/toontown/toonbase/ToontownStart.py @@ -6,7 +6,20 @@ class game: builtins.game = game() -from panda3d.core import * +from panda3d.core import ( + ConfigVariableBool, + ConfigVariableDouble, + ConfigVariableString, + Filename, + HTTPClient, + Loader, + loadPrcFile, + TextNode, + Thread, + VBase3, + Vec4 +) + import time import sys try: @@ -38,8 +51,7 @@ print('ToontownStart: setting default font') from . import ToontownGlobals DirectGuiGlobals.setDefaultFontFunc(ToontownGlobals.getInterfaceFont) launcher.setPandaErrorCode(7) -from . import ToonBase -ToonBase.ToonBase() +from .ToonBaseGlobal import base if base.win == None: print('Unable to open window; aborting.') sys.exit() @@ -70,21 +82,19 @@ if base.musicManagerIsValid: DirectGuiGlobals.setDefaultClickSound(base.loader.loadSfx('phase_3/audio/sfx/GUI_create_toon_fwd.ogg')) else: music = None -from direct.gui.DirectGui import * +from direct.gui.DirectGui import OnscreenText serverVersion = ConfigVariableString('server-version', 'no_version_set').value print('ToontownStart: serverVersion: ', serverVersion) version = OnscreenText(serverVersion, pos=(-1.3, -0.975), scale=0.06, fg=Vec4(0, 0, 1, 0.6), align=TextNode.ALeft) loader.beginBulkLoad('init', TTLocalizer.LoaderLabel, 138, 0, TTLocalizer.TIP_NONE) -from .ToonBaseGlobal import * -from direct.showbase.MessengerGlobal import * -from toontown.distributed import ToontownClientRepository -cr = ToontownClientRepository.ToontownClientRepository(serverVersion, launcher) +from toontown.distributed.ToontownClientRepository import ToontownClientRepository +cr = ToontownClientRepository(serverVersion, launcher) cr.music = music del music base.initNametagGlobals() base.cr = cr loader.endBulkLoad('init') -from otp.distributed.OtpDoGlobals import * +from otp.distributed.OtpDoGlobals import OTP_DO_ID_FRIEND_MANAGER cr.generateGlobalObject(OTP_DO_ID_FRIEND_MANAGER, 'FriendManager') if not launcher.isDummy(): base.startShow(cr, launcher.getGameServer()) @@ -97,7 +107,6 @@ del backgroundNode del tempLoader version.cleanup() del version -base.loader = base.loader builtins.loader = base.loader autoRun = ConfigVariableBool('toontown-auto-run', 1) if autoRun and launcher.isDummy() and (not Thread.isTrueThreads() or __name__ == '__main__'): From 1e4a7495d256e611411ec691f47041d1e1e75e4d Mon Sep 17 00:00:00 2001 From: Open Toontown <57279094+opentoontown@users.noreply.github.com> Date: Mon, 24 Apr 2023 00:12:43 -0400 Subject: [PATCH 10/48] more cleanup, game will crash --- toontown/building/ToonInterior.py | 104 ++++++++++++++------------- toontown/hood/Hood.py | 110 +++++++++++++++++------------ toontown/minigame/OrthoDrive.py | 15 +++- toontown/minigame/TwoDDrive.py | 15 +++- toontown/toonbase/ToontownStart.py | 5 ++ 5 files changed, 147 insertions(+), 102 deletions(-) diff --git a/toontown/building/ToonInterior.py b/toontown/building/ToonInterior.py index c39acd4..69229ae 100644 --- a/toontown/building/ToonInterior.py +++ b/toontown/building/ToonInterior.py @@ -1,31 +1,33 @@ -from panda3d.core import * -from toontown.toonbase.ToonBaseGlobal import * -from direct.directnotify import DirectNotifyGlobal -from toontown.hood import Place -from toontown.hood import ZoneUtil -from direct.showbase import DirectObject -from direct.fsm import StateData -from direct.fsm import ClassicFSM, State -from direct.fsm import State -from direct.task import Task -from otp.distributed.TelemetryLimiter import RotationLimitToH, TLGatherAllAvs -from toontown.toonbase import ToontownGlobals -from toontown.toonbase import TTLocalizer -from toontown.toon import NPCForceAcknowledge -from toontown.toon import HealthForceAcknowledge +from panda3d.core import ModelPool, TexturePool +from panda3d.otp import NametagGlobals -class ToonInterior(Place.Place): - notify = DirectNotifyGlobal.directNotify.newCategory('ToonInterior') +from direct.directnotify.DirectNotifyGlobal import directNotify +from direct.fsm.ClassicFSM import ClassicFSM +from direct.fsm.State import State +from direct.showbase.MessengerGlobal import messenger + +from otp.distributed.TelemetryLimiter import RotationLimitToH, TLGatherAllAvs + +from toontown.hood import ZoneUtil +from toontown.hood.Place import Place +from toontown.toon.HealthForceAcknowledge import HealthForceAcknowledge +from toontown.toon.NPCForceAcknowledge import NPCForceAcknowledge +from toontown.toonbase import ToontownGlobals +from toontown.toonbase.ToonBaseGlobal import base + + +class ToonInterior(Place): + notify = directNotify.newCategory('ToonInterior') def __init__(self, loader, parentFSMState, doneEvent): - Place.Place.__init__(self, loader, doneEvent) + Place.__init__(self, loader, doneEvent) self.dnaFile = 'phase_7/models/modules/toon_interior' self.isInterior = 1 self.tfaDoneEvent = 'tfaDoneEvent' self.hfaDoneEvent = 'hfaDoneEvent' self.npcfaDoneEvent = 'npcfaDoneEvent' - self.fsm = ClassicFSM.ClassicFSM('ToonInterior', [State.State('start', self.enterStart, self.exitStart, ['doorIn', 'teleportIn', 'tutorial']), - State.State('walk', self.enterWalk, self.exitWalk, ['sit', + self.fsm = ClassicFSM('ToonInterior', [State('start', self.enterStart, self.exitStart, ['doorIn', 'teleportIn', 'tutorial']), + State('walk', self.enterWalk, self.exitWalk, ['sit', 'stickerBook', 'doorOut', 'DFA', @@ -36,8 +38,8 @@ class ToonInterior(Place.Place): 'phone', 'stopped', 'pet']), - State.State('sit', self.enterSit, self.exitSit, ['walk']), - State.State('stickerBook', self.enterStickerBook, self.exitStickerBook, ['walk', + State('sit', self.enterSit, self.exitSit, ['walk']), + State('stickerBook', self.enterStickerBook, self.exitStickerBook, ['walk', 'DFA', 'trialerFA', 'sit', @@ -48,37 +50,37 @@ class ToonInterior(Place.Place): 'phone', 'stopped', 'pet']), - State.State('trialerFA', self.enterTrialerFA, self.exitTrialerFA, ['trialerFAReject', 'DFA']), - State.State('trialerFAReject', self.enterTrialerFAReject, self.exitTrialerFAReject, ['walk']), - State.State('DFA', self.enterDFA, self.exitDFA, ['DFAReject', + State('trialerFA', self.enterTrialerFA, self.exitTrialerFA, ['trialerFAReject', 'DFA']), + State('trialerFAReject', self.enterTrialerFAReject, self.exitTrialerFAReject, ['walk']), + State('DFA', self.enterDFA, self.exitDFA, ['DFAReject', 'HFA', 'NPCFA', 'teleportOut', 'doorOut']), - State.State('DFAReject', self.enterDFAReject, self.exitDFAReject, ['walk']), - State.State('NPCFA', self.enterNPCFA, self.exitNPCFA, ['NPCFAReject', 'HFA', 'teleportOut']), - State.State('NPCFAReject', self.enterNPCFAReject, self.exitNPCFAReject, ['walk']), - State.State('HFA', self.enterHFA, self.exitHFA, ['HFAReject', 'teleportOut', 'tunnelOut']), - State.State('HFAReject', self.enterHFAReject, self.exitHFAReject, ['walk']), - State.State('doorIn', self.enterDoorIn, self.exitDoorIn, ['walk']), - State.State('doorOut', self.enterDoorOut, self.exitDoorOut, ['walk', 'stopped']), - State.State('teleportIn', self.enterTeleportIn, self.exitTeleportIn, ['walk']), - State.State('teleportOut', self.enterTeleportOut, self.exitTeleportOut, ['teleportIn']), - State.State('quest', self.enterQuest, self.exitQuest, ['walk', 'doorOut']), - State.State('tutorial', self.enterTutorial, self.exitTutorial, ['walk', 'quest']), - State.State('purchase', self.enterPurchase, self.exitPurchase, ['walk', 'doorOut']), - State.State('pet', self.enterPet, self.exitPet, ['walk']), - State.State('phone', self.enterPhone, self.exitPhone, ['walk', 'doorOut']), - State.State('stopped', self.enterStopped, self.exitStopped, ['walk', 'doorOut']), - State.State('final', self.enterFinal, self.exitFinal, ['start'])], 'start', 'final') + State('DFAReject', self.enterDFAReject, self.exitDFAReject, ['walk']), + State('NPCFA', self.enterNPCFA, self.exitNPCFA, ['NPCFAReject', 'HFA', 'teleportOut']), + State('NPCFAReject', self.enterNPCFAReject, self.exitNPCFAReject, ['walk']), + State('HFA', self.enterHFA, self.exitHFA, ['HFAReject', 'teleportOut', 'tunnelOut']), + State('HFAReject', self.enterHFAReject, self.exitHFAReject, ['walk']), + State('doorIn', self.enterDoorIn, self.exitDoorIn, ['walk']), + State('doorOut', self.enterDoorOut, self.exitDoorOut, ['walk', 'stopped']), + State('teleportIn', self.enterTeleportIn, self.exitTeleportIn, ['walk']), + State('teleportOut', self.enterTeleportOut, self.exitTeleportOut, ['teleportIn']), + State('quest', self.enterQuest, self.exitQuest, ['walk', 'doorOut']), + State('tutorial', self.enterTutorial, self.exitTutorial, ['walk', 'quest']), + State('purchase', self.enterPurchase, self.exitPurchase, ['walk', 'doorOut']), + State('pet', self.enterPet, self.exitPet, ['walk']), + State('phone', self.enterPhone, self.exitPhone, ['walk', 'doorOut']), + State('stopped', self.enterStopped, self.exitStopped, ['walk', 'doorOut']), + State('final', self.enterFinal, self.exitFinal, ['start'])], 'start', 'final') self.parentFSMState = parentFSMState def load(self): - Place.Place.load(self) + Place.load(self) self.parentFSMState.addChild(self.fsm) def unload(self): - Place.Place.unload(self) + Place.unload(self) self.parentFSMState.removeChild(self.fsm) del self.parentFSMState del self.fsm @@ -111,7 +113,7 @@ class ToonInterior(Place.Place): def enterTutorial(self, requestStatus): self.fsm.request('walk') base.localAvatar.b_setParent(ToontownGlobals.SPRender) - globalClock.tick() + base.clock.tick() base.transitions.irisIn() messenger.send('enterTutorialInterior') @@ -134,7 +136,7 @@ class ToonInterior(Place.Place): def enterNPCFA(self, requestStatus): self.acceptOnce(self.npcfaDoneEvent, self.enterNPCFACallback, [requestStatus]) - self.npcfa = NPCForceAcknowledge.NPCForceAcknowledge(self.npcfaDoneEvent) + self.npcfa = NPCForceAcknowledge(self.npcfaDoneEvent) self.npcfa.enter() def exitNPCFA(self): @@ -161,7 +163,7 @@ class ToonInterior(Place.Place): def enterHFA(self, requestStatus): self.acceptOnce(self.hfaDoneEvent, self.enterHFACallback, [requestStatus]) - self.hfa = HealthForceAcknowledge.HealthForceAcknowledge(self.hfaDoneEvent) + self.hfa = HealthForceAcknowledge(self.hfaDoneEvent) self.hfa.enter(1) def exitHFA(self): @@ -191,10 +193,11 @@ class ToonInterior(Place.Place): base.localAvatar.setPosHpr(0, 0, ToontownGlobals.FloorOffset, 45.0, 0.0, 0.0) else: base.localAvatar.setPosHpr(2.5, 11.5, ToontownGlobals.FloorOffset, 45.0, 0.0, 0.0) - Place.Place.enterTeleportIn(self, requestStatus) + + Place.enterTeleportIn(self, requestStatus) def enterTeleportOut(self, requestStatus): - Place.Place.enterTeleportOut(self, requestStatus, self.__teleportOutDone) + Place.enterTeleportOut(self, requestStatus, self.__teleportOutDone) def __teleportOutDone(self, requestStatus): hoodId = requestStatus['hoodId'] @@ -207,7 +210,6 @@ class ToonInterior(Place.Place): else: self.doneStatus = requestStatus messenger.send(self.doneEvent) - return def goHomeFailed(self, task): self.notifyUserGoHomeFailed() @@ -215,7 +217,7 @@ class ToonInterior(Place.Place): self.doneStatus['avId'] = -1 self.doneStatus['zoneId'] = self.getZoneId() self.fsm.request('teleportIn', [self.doneStatus]) - return Task.done + return task.done def exitTeleportOut(self): - Place.Place.exitTeleportOut(self) + Place.exitTeleportOut(self) diff --git a/toontown/hood/Hood.py b/toontown/hood/Hood.py index 6872c50..3bd164c 100644 --- a/toontown/hood/Hood.py +++ b/toontown/hood/Hood.py @@ -1,24 +1,33 @@ -from panda3d.core import * -from toontown.toonbase.ToonBaseGlobal import * -from toontown.toonbase.ToontownGlobals import * -from toontown.distributed.ToontownMsgTypes import * -from direct.directnotify import DirectNotifyGlobal -from direct.fsm import StateData -from direct.task.Task import Task -from toontown.minigame import Purchase -from direct.gui import OnscreenText -from toontown.building import SuitInterior -from . import QuietZoneState -from . import ZoneUtil -from toontown.toonbase import TTLocalizer -from toontown.toon.Toon import teleportDebug -from direct.interval.IntervalGlobal import * +from panda3d.core import ( + CompassEffect, + ModelPool, + NodePath, + TexturePool, + TransparencyAttrib, + Vec4 +) -class Hood(StateData.StateData): - notify = DirectNotifyGlobal.directNotify.newCategory('Hood') +from direct.directnotify.DirectNotifyGlobal import directNotify +from direct.fsm.StateData import StateData +from direct.gui.OnscreenText import OnscreenText +from direct.interval.IntervalGlobal import Sequence, Wait, Func +from direct.showbase.MessengerGlobal import messenger +from direct.showbase.PythonUtil import uniqueName +from direct.task.TaskManagerGlobal import taskMgr + +from toontown.hood import ZoneUtil +from toontown.hood.QuietZoneState import QuietZoneState +from toontown.toon.Toon import teleportDebug +from toontown.toonbase import ToontownGlobals +from toontown.toonbase import TTLocalizer +from toontown.toonbase.ToonBaseGlobal import base + + +class Hood(StateData): + notify = directNotify.newCategory('Hood') def __init__(self, parentFSM, doneEvent, dnaStore, hoodId): - StateData.StateData.__init__(self, doneEvent) + StateData.__init__(self, doneEvent) self.loader = 'not initialized' self.parentFSM = parentFSM self.dnaStore = dnaStore @@ -31,21 +40,20 @@ class Hood(StateData.StateData): self.holidayStorageDNADict = {} self.spookySkyFile = None self.halloweenLights = [] - return def enter(self, requestStatus): - hoodId = requestStatus['hoodId'] zoneId = requestStatus['zoneId'] hoodText = self.getHoodText(zoneId) - self.titleText = OnscreenText.OnscreenText(hoodText, fg=self.titleColor, font=getSignFont(), pos=(0, -0.5), scale=TTLocalizer.HtitleText, drawOrder=0, mayChange=1) + self.titleText = OnscreenText(hoodText, fg=self.titleColor, font=ToontownGlobals.getSignFont(), pos=(0, -0.5), scale=TTLocalizer.HtitleText, drawOrder=0, mayChange=1) self.fsm.request(requestStatus['loader'], [requestStatus]) def getHoodText(self, zoneId): hoodText = base.cr.hoodMgr.getFullnameFromId(self.id) - if self.id != Tutorial: - streetName = StreetNames.get(ZoneUtil.getCanonicalBranchZone(zoneId)) + if self.id != ToontownGlobals.Tutorial: + streetName = ToontownGlobals.StreetNames.get(ZoneUtil.getCanonicalBranchZone(zoneId)) if streetName: hoodText = hoodText + '\n' + streetName[-1] + return hoodText def spawnTitleText(self, zoneId): @@ -69,32 +77,35 @@ class Hood(StateData.StateData): if self.titleTextSeq: self.titleTextSeq.finish() self.titleTextSeq = None + if self.titleText: self.titleText.cleanup() self.titleText = None + base.localAvatar.stopChat() - return def load(self): if self.storageDNAFile: - loader.loadDNAFile(self.dnaStore, self.storageDNAFile) + base.loader.loadDNAFile(self.dnaStore, self.storageDNAFile) + newsManager = base.cr.newsManager if newsManager: holidayIds = base.cr.newsManager.getDecorationHolidayId() for holiday in holidayIds: for storageFile in self.holidayStorageDNADict.get(holiday, []): - loader.loadDNAFile(self.dnaStore, storageFile) + base.loader.loadDNAFile(self.dnaStore, storageFile) if ToontownGlobals.HALLOWEEN_COSTUMES not in holidayIds and ToontownGlobals.SPOOKY_COSTUMES not in holidayIds or not self.spookySkyFile: - self.sky = loader.loadModel(self.skyFile) + self.sky = base.loader.loadModel(self.skyFile) self.sky.setTag('sky', 'Regular') self.sky.setScale(1.0) self.sky.setFogOff() else: - self.sky = loader.loadModel(self.spookySkyFile) + self.sky = base.loader.loadModel(self.spookySkyFile) self.sky.setTag('sky', 'Halloween') + if not newsManager: - self.sky = loader.loadModel(self.skyFile) + self.sky = base.loader.loadModel(self.skyFile) self.sky.setTag('sky', 'Regular') self.sky.setScale(1.0) self.sky.setFogOff() @@ -105,6 +116,7 @@ class Hood(StateData.StateData): self.loader.exit() self.loader.unload() del self.loader + del self.fsm del self.parentFSM self.dnaStore.resetHood() @@ -134,12 +146,13 @@ class Hood(StateData.StateData): teleportDebug(requestStatus, 'Hood.enterQuietZone: status=%s' % requestStatus) self._quietZoneDoneEvent = uniqueName('quietZoneDone') self.acceptOnce(self._quietZoneDoneEvent, self.handleQuietZoneDone) - self.quietZoneStateData = QuietZoneState.QuietZoneState(self._quietZoneDoneEvent) + self.quietZoneStateData = QuietZoneState(self._quietZoneDoneEvent) self._enterWaitForSetZoneResponseMsg = self.quietZoneStateData.getEnterWaitForSetZoneResponseMsg() self.acceptOnce(self._enterWaitForSetZoneResponseMsg, self.handleWaitForSetZoneResponse) self._quietZoneLeftEvent = self.quietZoneStateData.getQuietZoneLeftEvent() if base.placeBeforeObjects: self.acceptOnce(self._quietZoneLeftEvent, self.handleLeftQuietZone) + self.quietZoneStateData.load() self.quietZoneStateData.enter(requestStatus) @@ -151,7 +164,6 @@ class Hood(StateData.StateData): self.quietZoneStateData.exit() self.quietZoneStateData.unload() self.quietZoneStateData = None - return def loadLoader(self, requestStatus): pass @@ -159,19 +171,21 @@ class Hood(StateData.StateData): def handleWaitForSetZoneResponse(self, requestStatus): loaderName = requestStatus['loader'] if loaderName == 'safeZoneLoader': - if not loader.inBulkBlock: - loader.beginBulkLoad('hood', TTLocalizer.HeadingToPlayground, safeZoneCountMap[self.id], 1, TTLocalizer.TIP_GENERAL) + if not base.loader.inBulkBlock: + base.loader.beginBulkLoad('hood', TTLocalizer.HeadingToPlayground, ToontownGlobals.safeZoneCountMap[self.id], 1, TTLocalizer.TIP_GENERAL) + self.loadLoader(requestStatus) - loader.endBulkLoad('hood') + base.loader.endBulkLoad('hood') elif loaderName == 'townLoader': - if not loader.inBulkBlock: + if not base.loader.inBulkBlock: zoneId = requestStatus['zoneId'] - toPhrase = StreetNames[ZoneUtil.getCanonicalBranchZone(zoneId)][0] - streetName = StreetNames[ZoneUtil.getCanonicalBranchZone(zoneId)][-1] - loader.beginBulkLoad('hood', TTLocalizer.HeadingToStreet % {'to': toPhrase, - 'street': streetName}, townCountMap[self.id], 1, TTLocalizer.TIP_STREET) + toPhrase = ToontownGlobals.StreetNames[ZoneUtil.getCanonicalBranchZone(zoneId)][0] + streetName = ToontownGlobals.StreetNames[ZoneUtil.getCanonicalBranchZone(zoneId)][-1] + base.loader.beginBulkLoad('hood', TTLocalizer.HeadingToStreet % {'to': toPhrase, + 'street': streetName}, ToontownGlobals.townCountMap[self.id], 1, TTLocalizer.TIP_STREET) + self.loadLoader(requestStatus) - loader.endBulkLoad('hood') + base.loader.endBulkLoad('hood') elif loaderName == 'minigame': pass elif loaderName == 'cogHQLoader': @@ -197,6 +211,7 @@ class Hood(StateData.StateData): if self.titleTextSeq: self.titleTextSeq.finish() self.titleTextSeq = None + self.hideTitleText() self.ignore(self.loaderDoneEvent) self.loader.exit() @@ -215,7 +230,7 @@ class Hood(StateData.StateData): messenger.send(self.doneEvent) def startSky(self): - self.sky.reparentTo(camera) + self.sky.reparentTo(base.camera) self.sky.setZ(0.0) self.sky.setHpr(0.0, 0.0, 0.0) ce = CompassEffect.make(NodePath(), CompassEffect.PRot | CompassEffect.PZ) @@ -223,17 +238,19 @@ class Hood(StateData.StateData): def stopSky(self): taskMgr.remove('skyTrack') - self.sky.reparentTo(hidden) + self.sky.reparentTo(base.hidden) def startSpookySky(self): if not self.spookySkyFile: return + if hasattr(self, 'sky') and self.sky: self.stopSky() - self.sky = loader.loadModel(self.spookySkyFile) + + self.sky = base.loader.loadModel(self.spookySkyFile) self.sky.setTag('sky', 'Halloween') self.sky.setColor(0.5, 0.5, 0.5, 1) - self.sky.reparentTo(camera) + self.sky.reparentTo(base.camera) self.sky.setTransparency(TransparencyAttrib.MDual, 1) fadeIn = self.sky.colorScaleInterval(1.5, Vec4(1, 1, 1, 1), startColorScale=Vec4(1, 1, 1, 0.25), blendType='easeInOut') fadeIn.start() @@ -244,9 +261,10 @@ class Hood(StateData.StateData): def endSpookySky(self): if hasattr(self, 'sky') and self.sky: - self.sky.reparentTo(hidden) + self.sky.reparentTo(base.hidden) + if hasattr(self, 'sky'): - self.sky = loader.loadModel(self.skyFile) + self.sky = base.loader.loadModel(self.skyFile) self.sky.setTag('sky', 'Regular') self.sky.setScale(1.0) self.startSky() diff --git a/toontown/minigame/OrthoDrive.py b/toontown/minigame/OrthoDrive.py index 742906f..e341905 100644 --- a/toontown/minigame/OrthoDrive.py +++ b/toontown/minigame/OrthoDrive.py @@ -38,18 +38,17 @@ class OrthoDrive: self.__placeToonHOG(self.lt.getPos()) taskMgr.add(self.__update, OrthoDrive.TASK_NAME, priority=self.priority) self.lastAction = None - return def __placeToonHOG(self, pos, h = None): if h == None: h = self.lt.getH() + self.lt.setPos(pos) self.lt.setH(h) self.lastPos = pos self.atRestHeading = h self.lastXVel = 0 self.lastYVel = 0 - return def stop(self): self.notify.debug('stop') @@ -59,7 +58,9 @@ class OrthoDrive: if hasattr(self, 'turnLocalToonIval'): if self.turnLocalToonIval.isPlaying(): self.turnLocalToonIval.pause() + del self.turnLocalToonIval + base.localAvatar.setSpeed(0, 0) def __update(self, task): @@ -68,12 +69,16 @@ class OrthoDrive: yVel = 0 if self.arrowKeys.upPressed(): yVel += 1 + if self.arrowKeys.downPressed(): yVel -= 1 + if self.arrowKeys.leftPressed(): xVel -= 1 + if self.arrowKeys.rightPressed(): xVel += 1 + vel.setX(xVel) vel.setY(yVel) vel.normalize() @@ -89,8 +94,10 @@ class OrthoDrive: self.lt.runSound() else: self.lt.stopSound() + if self.setHeading: self.__handleHeading(xVel, yVel) + toonPos = self.lt.getPos() dt = base.clock.getDt() posOffset = vel * dt @@ -101,10 +108,12 @@ class OrthoDrive: if posOffsetLen > self.maxFrameMove: posOffset *= self.maxFrameMove posOffset /= posOffsetLen + if self.customCollisionCallback: toonPos = self.customCollisionCallback(toonPos, toonPos + posOffset) else: toonPos = toonPos + posOffset + self.lt.setPos(toonPos) self.lastPos = toonPos return task.cont @@ -138,6 +147,8 @@ class OrthoDrive: taskMgr.doMethodLater(0.05, setAtRestHeading, OrthoDrive.SET_ATREST_HEADING_TASK) else: self.atRestHeading = curHeading + orientToon(curHeading) + self.lastXVel = xVel self.lastYVel = yVel diff --git a/toontown/minigame/TwoDDrive.py b/toontown/minigame/TwoDDrive.py index 16284a3..1111f66 100644 --- a/toontown/minigame/TwoDDrive.py +++ b/toontown/minigame/TwoDDrive.py @@ -33,7 +33,6 @@ class TwoDDrive: self.ONE_JUMP_PER_UP_PRESSED = True self.lastAction = None self.isMovingX = False - return def destroy(self): self.game = None @@ -43,7 +42,6 @@ class TwoDDrive: del self.arrowKeys del self.customCollisionCallback self.lastAction = None - return def start(self): self.notify.debug('start') @@ -55,6 +53,7 @@ class TwoDDrive: def __placeToonHOG(self, pos, h = None): if h == None: h = self.lt.getH() + self.lt.setPos(pos) self.lt.setH(h) self.lastPos = pos @@ -62,7 +61,6 @@ class TwoDDrive: self.oldAtRestHeading = h self.lastXVel = 0 self.lastYVel = 0 - return def stop(self): self.notify.debug('stop') @@ -72,7 +70,9 @@ class TwoDDrive: if hasattr(self, 'turnLocalToonIval'): if self.turnLocalToonIval.isPlaying(): self.turnLocalToonIval.pause() + del self.turnLocalToonIval + base.localAvatar.setSpeed(0, 0) base.localAvatar.stopSound() @@ -92,10 +92,13 @@ class TwoDDrive: if not self.game.isHeadInFloor: if base.localAvatar.controlManager.currentControls == base.localAvatar.controlManager.get('twoD'): base.localAvatar.controlManager.currentControls.jumpPressed() + if self.arrowKeys.leftPressed(): xVel -= 1 + if self.arrowKeys.rightPressed(): xVel += 1 + vel.setX(xVel) vel.setY(yVel) vel.normalize() @@ -107,6 +110,7 @@ class TwoDDrive: elif self.isMovingX: self.isMovingX = False messenger.send('avatarStoppedX') + speed = vel.length() action = self.lt.setSpeed(speed, 0) if action != self.lastAction: @@ -115,8 +119,10 @@ class TwoDDrive: base.localAvatar.runSound() else: base.localAvatar.stopSound() + if self.setHeading: self.__handleHeading(xVel, yVel) + toonPos = self.lt.getPos() dt = base.clock.getDt() posOffset = vel * dt @@ -124,6 +130,7 @@ class TwoDDrive: toonPos = self.customCollisionCallback(toonPos, toonPos + posOffset) else: toonPos += posOffset + self.lt.setPos(toonPos) self.lastPos = toonPos return task.cont @@ -157,6 +164,8 @@ class TwoDDrive: taskMgr.doMethodLater(0.05, setAtRestHeading, TwoDDrive.SET_ATREST_HEADING_TASK) else: self.atRestHeading = curHeading + orientToon(curHeading) + self.lastXVel = xVel self.lastYVel = yVel diff --git a/toontown/toonbase/ToontownStart.py b/toontown/toonbase/ToontownStart.py index f331542..de6d608 100644 --- a/toontown/toonbase/ToontownStart.py +++ b/toontown/toonbase/ToontownStart.py @@ -44,6 +44,7 @@ if launcher.isDummy(): http = HTTPClient() else: http = launcher.http + tempLoader = Loader() backgroundNode = tempLoader.loadSync(Filename('phase_3/models/gui/loading-background')) from direct.gui import DirectGuiGlobals @@ -55,6 +56,7 @@ from .ToonBaseGlobal import base if base.win == None: print('Unable to open window; aborting.') sys.exit() + launcher.setPandaErrorCode(0) launcher.setPandaWindowOpen() ConfigVariableDouble('decompressor-step-time').setValue(0.01) @@ -77,11 +79,13 @@ if base.musicManagerIsValid: music.setLoop(1) music.setVolume(0.9) music.play() + print('ToontownStart: Loading default gui sounds') DirectGuiGlobals.setDefaultRolloverSound(base.loader.loadSfx('phase_3/audio/sfx/GUI_rollover.ogg')) DirectGuiGlobals.setDefaultClickSound(base.loader.loadSfx('phase_3/audio/sfx/GUI_create_toon_fwd.ogg')) else: music = None + from direct.gui.DirectGui import OnscreenText serverVersion = ConfigVariableString('server-version', 'no_version_set').value print('ToontownStart: serverVersion: ', serverVersion) @@ -100,6 +104,7 @@ if not launcher.isDummy(): base.startShow(cr, launcher.getGameServer()) else: base.startShow(cr) + backgroundNodePath.reparentTo(hidden) backgroundNodePath.removeNode() del backgroundNodePath From 25e353e2909227d3f199ae58e924fba461ae582a Mon Sep 17 00:00:00 2001 From: Open Toontown <57279094+opentoontown@users.noreply.github.com> Date: Fri, 28 Apr 2023 21:51:00 -0400 Subject: [PATCH 11/48] more cleanup --- toontown/battle/DistributedBattleBase.py | 315 +++++++++++++++-------- toontown/building/DistributedDoor.py | 186 ++++++++----- toontown/hood/Place.py | 179 +++++++------ toontown/safezone/Playground.py | 193 +++++++------- 4 files changed, 523 insertions(+), 350 deletions(-) diff --git a/toontown/battle/DistributedBattleBase.py b/toontown/battle/DistributedBattleBase.py index 9716ede..5e886b1 100644 --- a/toontown/battle/DistributedBattleBase.py +++ b/toontown/battle/DistributedBattleBase.py @@ -1,28 +1,55 @@ -from panda3d.core import * -from toontown.toonbase.ToonBaseGlobal import * -from direct.interval.IntervalGlobal import * -from .BattleBase import * -from direct.distributed.ClockDelta import * -from toontown.toonbase import ToontownBattleGlobals -from direct.distributed import DistributedNode -from direct.fsm import ClassicFSM, State -from direct.fsm import State -from direct.task.Task import Task -from direct.directnotify import DirectNotifyGlobal -from . import Movie -from . import MovieUtil -from toontown.suit import Suit -from direct.actor import Actor -from . import BattleProps -from direct.particles import ParticleEffect -from . import BattleParticles -from toontown.hood import ZoneUtil -from toontown.distributed import DelayDelete -from toontown.toon import TTEmote -from otp.avatar import Emote +from panda3d.core import CollisionNode, CollisionTube, LineSegs, NodePath, Point3, VBase3 +from panda3d.otp import NametagGlobals -class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): - notify = DirectNotifyGlobal.directNotify.newCategory('DistributedBattleBase') +from direct.actor.Actor import Actor +from direct.directnotify.DirectNotifyGlobal import directNotify +from direct.distributed.ClockDelta import globalClockDelta +from direct.distributed.DistributedNode import DistributedNode +from direct.fsm.ClassicFSM import ClassicFSM +from direct.fsm.State import State +from direct.interval.IntervalGlobal import Func, LerpPosInterval, Parallel, Sequence +from direct.showbase.MessengerGlobal import messenger +from direct.task.Task import Task +from direct.task.TaskManagerGlobal import taskMgr +from direct.task.Timer import Timer + +from otp.avatar.Emote import globalEmote + +from toontown.battle import BattleParticles +from toontown.battle import MovieUtil +from toontown.battle.BattleBase import ( + attackAffectsGroup, + BattleBase, + BATTLE_SMALL_VALUE, + CLIENT_INPUT_TIMEOUT, + FIRE, + HEAL, + levelAffectsGroup, + LURE, + MAX_JOIN_T, + NO_ATTACK, + NO_TRAP, + NPCSOS, + PASS, + PASS_ATTACK, + PETSOS, + SOS, + TRAP, + UN_ATTACK +) + +from toontown.battle.BattleProps import globalPropPool +from toontown.battle.Movie import Movie +from toontown.distributed.DelayDelete import DelayDelete, cleanupDelayDeletes +from toontown.hood import ZoneUtil +from toontown.suit.Suit import Suit +from toontown.toonbase import ToontownBattleGlobals +from toontown.toonbase import ToontownGlobals +from toontown.toonbase.ToonBaseGlobal import base + + +class DistributedBattleBase(DistributedNode, BattleBase): + notify = directNotify.newCategory('DistributedBattleBase') id = 0 camPos = ToontownBattleGlobals.BattleCamDefaultPos camHpr = ToontownBattleGlobals.BattleCamDefaultHpr @@ -32,9 +59,9 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): camJoinHpr = ToontownBattleGlobals.BattleCamJoinHpr def __init__(self, cr, townBattle): - DistributedNode.DistributedNode.__init__(self, cr) + DistributedNode.__init__(self, cr) NodePath.__init__(self) - self.assign(render.attachNewNode(self.uniqueBattleName('distributed-battle'))) + self.assign(base.render.attachNewNode(self.uniqueBattleName('distributed-battle'))) BattleBase.__init__(self) self.bossBattle = 0 self.townBattle = townBattle @@ -50,35 +77,34 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): self.localToonBattleEvent = self.uniqueBattleName('localtoon-battle-event') self.adjustName = self.uniqueBattleName('adjust') self.timerCountdownTaskName = self.uniqueBattleName('timer-countdown') - self.movie = Movie.Movie(self) + self.movie = Movie(self) self.timer = Timer() self.needAdjustTownBattle = 0 self.streetBattle = 1 self.levelBattle = 0 - self.localToonFsm = ClassicFSM.ClassicFSM('LocalToon', [State.State('HasLocalToon', self.enterHasLocalToon, self.exitHasLocalToon, ['NoLocalToon', 'WaitForServer']), State.State('NoLocalToon', self.enterNoLocalToon, self.exitNoLocalToon, ['HasLocalToon', 'WaitForServer']), State.State('WaitForServer', self.enterWaitForServer, self.exitWaitForServer, ['HasLocalToon', 'NoLocalToon'])], 'WaitForServer', 'WaitForServer') + self.localToonFsm = ClassicFSM('LocalToon', [State('HasLocalToon', self.enterHasLocalToon, self.exitHasLocalToon, ['NoLocalToon', 'WaitForServer']), State('NoLocalToon', self.enterNoLocalToon, self.exitNoLocalToon, ['HasLocalToon', 'WaitForServer']), State('WaitForServer', self.enterWaitForServer, self.exitWaitForServer, ['HasLocalToon', 'NoLocalToon'])], 'WaitForServer', 'WaitForServer') self.localToonFsm.enterInitialState() - self.fsm = ClassicFSM.ClassicFSM('DistributedBattle', [State.State('Off', self.enterOff, self.exitOff, ['FaceOff', + self.fsm = ClassicFSM('DistributedBattle', [State('Off', self.enterOff, self.exitOff, ['FaceOff', 'WaitForInput', 'WaitForJoin', 'MakeMovie', 'PlayMovie', 'Reward', 'Resume']), - State.State('FaceOff', self.enterFaceOff, self.exitFaceOff, ['WaitForInput']), - State.State('WaitForJoin', self.enterWaitForJoin, self.exitWaitForJoin, ['WaitForInput', 'Resume']), - State.State('WaitForInput', self.enterWaitForInput, self.exitWaitForInput, ['WaitForInput', 'PlayMovie', 'Resume']), - State.State('MakeMovie', self.enterMakeMovie, self.exitMakeMovie, ['PlayMovie', 'Resume']), - State.State('PlayMovie', self.enterPlayMovie, self.exitPlayMovie, ['WaitForInput', + State('FaceOff', self.enterFaceOff, self.exitFaceOff, ['WaitForInput']), + State('WaitForJoin', self.enterWaitForJoin, self.exitWaitForJoin, ['WaitForInput', 'Resume']), + State('WaitForInput', self.enterWaitForInput, self.exitWaitForInput, ['WaitForInput', 'PlayMovie', 'Resume']), + State('MakeMovie', self.enterMakeMovie, self.exitMakeMovie, ['PlayMovie', 'Resume']), + State('PlayMovie', self.enterPlayMovie, self.exitPlayMovie, ['WaitForInput', 'WaitForJoin', 'Reward', 'Resume']), - State.State('Reward', self.enterReward, self.exitReward, ['Resume']), - State.State('Resume', self.enterResume, self.exitResume, [])], 'Off', 'Off') + State('Reward', self.enterReward, self.exitReward, ['Resume']), + State('Resume', self.enterResume, self.exitResume, [])], 'Off', 'Off') self.fsm.enterInitialState() - self.adjustFsm = ClassicFSM.ClassicFSM('Adjust', [State.State('Adjusting', self.enterAdjusting, self.exitAdjusting, ['NotAdjusting']), State.State('NotAdjusting', self.enterNotAdjusting, self.exitNotAdjusting, ['Adjusting'])], 'NotAdjusting', 'NotAdjusting') + self.adjustFsm = ClassicFSM('Adjust', [State('Adjusting', self.enterAdjusting, self.exitAdjusting, ['NotAdjusting']), State('NotAdjusting', self.enterNotAdjusting, self.exitNotAdjusting, ['Adjusting'])], 'NotAdjusting', 'NotAdjusting') self.adjustFsm.enterInitialState() self.interactiveProp = None - return def uniqueBattleName(self, name): DistributedBattleBase.id += 1 @@ -86,9 +112,9 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): def generate(self): self.notify.debug('generate(%s)' % self.doId) - DistributedNode.DistributedNode.generate(self) + DistributedNode.generate(self) self.__battleCleanedUp = 0 - self.reparentTo(render) + self.reparentTo(base.render) self._skippingRewardMovie = False def storeInterval(self, interval, name): @@ -96,12 +122,13 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): ival = self.activeIntervals[name] if hasattr(ival, 'delayDelete') or hasattr(ival, 'delayDeletes'): self.clearInterval(name, finish=1) + self.activeIntervals[name] = interval def __cleanupIntervals(self): for interval in list(self.activeIntervals.values()): interval.finish() - DelayDelete.cleanupDelayDeletes(interval) + cleanupDelayDeletes(interval) self.activeIntervals = {} @@ -112,8 +139,9 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): ival.finish() else: ival.pause() + if name in self.activeIntervals: - DelayDelete.cleanupDelayDeletes(ival) + cleanupDelayDeletes(ival) if name in self.activeIntervals: del self.activeIntervals[name] else: @@ -127,7 +155,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): def disable(self): self.notify.debug('disable(%s)' % self.doId) self.cleanupBattle() - DistributedNode.DistributedNode.disable(self) + DistributedNode.disable(self) def battleCleanedUp(self): return self.__battleCleanedUp @@ -135,6 +163,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): def cleanupBattle(self): if self.__battleCleanedUp: return + self.notify.debug('cleanupBattle(%s)' % self.doId) self.__battleCleanedUp = 1 self.__cleanupIntervals() @@ -142,12 +171,14 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): if self.hasLocalToon(): self.removeLocalToon() base.camLens.setFov(ToontownGlobals.DefaultCameraFov) + self.localToonFsm.request('WaitForServer') self.ignoreAll() for suit in self.suits: if suit.battleTrap != NO_TRAP: self.notify.debug('250 calling self.removeTrap, suit=%d' % suit.doId) self.removeTrap(suit) + suit.battleTrap = NO_TRAP suit.battleTrapProp = None self.notify.debug('253 suit.battleTrapProp = None') @@ -166,7 +197,6 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): self.__stopTimer() self.__cleanupIntervals() self._removeMembersKeep() - return def delete(self): self.notify.debug('delete(%s)' % self.doId) @@ -180,13 +210,12 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): self.adjustFsm = None self.__stopTimer() self.timer = None - DistributedNode.DistributedNode.delete(self) - return + DistributedNode.delete(self) def loadTrap(self, suit, trapid): self.notify.debug('loadTrap() trap: %d suit: %d' % (trapid, suit.doId)) - trapName = AvProps[TRAP][trapid] - trap = BattleProps.globalPropPool.getProp(trapName) + trapName = ToontownBattleGlobals.AvProps[TRAP][trapid] + trap = globalPropPool.getProp(trapName) suit.battleTrap = trapid suit.battleTrapIsFresh = 0 suit.battleTrapProp = trap @@ -195,6 +224,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): pass else: trap.wrtReparentTo(suit) + distance = MovieUtil.SUIT_TRAP_DISTANCE if trapName == 'rake': distance = MovieUtil.SUIT_TRAP_RAKE_DISTANCE @@ -212,8 +242,9 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): sparks = BattleParticles.createParticleEffect(file='tnt') trap.sparksEffect = sparks sparks.start(tip) + trap.setPos(0, distance, 0) - if isinstance(trap, Actor.Actor): + if isinstance(trap, Actor): frame = trap.getNumFrames(trapName) - 1 trap.pose(trapName, frame) @@ -223,7 +254,8 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): self.notify.debug('suit.battleTrapProp == None, suit.battleTrap=%s setting to NO_TRAP, returning' % suit.battleTrap) suit.battleTrap = NO_TRAP return - if suit.battleTrap == UBER_GAG_LEVEL_INDEX: + + if suit.battleTrap == ToontownBattleGlobals.UBER_GAG_LEVEL_INDEX: if removeTrainTrack: self.notify.debug('doing removeProp on traintrack') MovieUtil.removeProp(suit.battleTrapProp) @@ -233,17 +265,16 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): self.notify.debug('351 otherSuit=%d otherSuit.battleTrapProp = None' % otherSuit.doId) otherSuit.battleTrap = NO_TRAP otherSuit.battleTrapIsFresh = 0 - else: self.notify.debug('deliberately not doing removeProp on traintrack') else: self.notify.debug('suit.battleTrap != UBER_GAG_LEVEL_INDEX') MovieUtil.removeProp(suit.battleTrapProp) + suit.battleTrapProp = None self.notify.debug('360 suit.battleTrapProp = None') suit.battleTrap = NO_TRAP suit.battleTrapIsFresh = 0 - return def pause(self): self.timer.stop() @@ -256,21 +287,19 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): if s.doId == id: return s - return None - def findToon(self, id): toon = self.getToon(id) if toon == None: return + for t in self.toons: if t == toon: return t - return - def isSuitLured(self, suit): if self.luredSuits.count(suit) != 0: return 1 + return 0 def unlureSuit(self, suit): @@ -278,19 +307,18 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): if self.luredSuits.count(suit) != 0: self.luredSuits.remove(suit) self.needAdjustTownBattle = 1 - return None def lureSuit(self, suit): self.notify.debug('movie luring suit %s' % suit.doId) if self.luredSuits.count(suit) == 0: self.luredSuits.append(suit) self.needAdjustTownBattle = 1 - return None def getActorPosHpr(self, actor, actorList = []): - if isinstance(actor, Suit.Suit): + if isinstance(actor, Suit): if actorList == []: actorList = self.activeSuits + if actorList.count(actor) != 0: numSuits = len(actorList) - 1 index = actorList.index(actor) @@ -301,6 +329,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): else: if actorList == []: actorList = self.activeToons + if actorList.count(actor) != 0: numToons = len(actorList) - 1 index = actorList.index(actor) @@ -339,12 +368,14 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): def setState(self, state, timestamp): if self.__battleCleanedUp: return + self.notify.debug('setState(%s)' % state) self.fsm.request(state, [globalClockDelta.localElapsedTime(timestamp)]) def setMembers(self, suits, suitsJoining, suitsPending, suitsActive, suitsLured, suitTraps, toons, toonsJoining, toonsPending, toonsActive, toonsRunning, timestamp): if self.__battleCleanedUp: return + self.notify.debug('setMembers() - suits: %s suitsJoining: %s suitsPending: %s suitsActive: %s suitsLured: %s suitTraps: %s toons: %s toonsJoining: %s toonsPending: %s toonsActive: %s toonsRunning: %s' % (suits, suitsJoining, suitsPending, @@ -373,7 +404,6 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): suit.battleTrapProp = None self.notify.debug('496 suit.battleTrapProp = None') suit.battleTrapIsFresh = 0 - else: self.notify.warning('setMembers() - no suit in repository: %d' % s) self.suits.append(None) @@ -391,6 +421,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): if not trainTrap.isEmpty(): self.notify.debug('removing old train trap when 4 suits died') trainTrap.removeNode() + for s in suitsJoining: suit = self.suits[int(s)] if suit != None and self.joiningSuits.count(suit) == 0: @@ -428,12 +459,14 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): trapid = int(s) if trapid == 9: trapid = -1 + suit = self.suits[index] index += 1 if suit != None: if (trapid == NO_TRAP or trapid != suit.battleTrap) and suit.battleTrapProp != None: self.notify.debug('569 calling self.removeTrap, suit=%d' % suit.doId) self.removeTrap(suit) + if trapid != NO_TRAP and suit.battleTrapProp == None: if self.fsm.getCurrentState().getName() != 'PlayMovie': self.loadTrap(suit, trapid) @@ -454,6 +487,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): self.suits = validSuits self.needAdjustTownBattle = 1 + oldtoons = self.toons self.toons = [] toonGone = 0 @@ -464,6 +498,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): self.toons.append(None) toonGone = 1 continue + self.toons.append(toon) if oldtoons.count(toon) == 0: self.notify.debug('setMembers() - add toon: %d' % toon.doId) @@ -506,6 +541,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): if len(activeSuits) > 0 or len(activeToons) > 0: self.__makeAvsActive(activeSuits, activeToons) + if toonGone == 1: validToons = [] for toon in self.toons: @@ -513,15 +549,19 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): validToons.append(toon) self.toons = validToons + if len(self.activeToons) > 0: self.__requestAdjustTownBattle() + currStateName = self.localToonFsm.getCurrentState().getName() if self.toons.count(base.localAvatar): if oldtoons.count(base.localAvatar) == 0: self.notify.debug('setMembers() - local toon just joined') if self.streetBattle == 1: base.cr.playGame.getPlace().enterZone(self.zoneId) + self.localToonJustJoined = 1 + if currStateName != 'HasLocalToon': self.localToonFsm.request('HasLocalToon') else: @@ -529,19 +569,23 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): self.notify.debug('setMembers() - local toon just ran') if self.levelBattle: self.unlockLevelViz() + if currStateName != 'NoLocalToon': self.localToonFsm.request('NoLocalToon') + return oldtoons def adjust(self, timestamp): if self.__battleCleanedUp: return + self.notify.debug('adjust(%f) from server' % globalClockDelta.localElapsedTime(timestamp)) self.adjustFsm.request('Adjusting', [globalClockDelta.localElapsedTime(timestamp)]) def setMovie(self, active, toons, suits, id0, tr0, le0, tg0, hp0, ac0, hpb0, kbb0, died0, revive0, id1, tr1, le1, tg1, hp1, ac1, hpb1, kbb1, died1, revive1, id2, tr2, le2, tg2, hp2, ac2, hpb2, kbb2, died2, revive2, id3, tr3, le3, tg3, hp3, ac3, hpb3, kbb3, died3, revive3, sid0, at0, stg0, dm0, sd0, sb0, st0, sid1, at1, stg1, dm1, sd1, sb1, st1, sid2, at2, stg2, dm2, sd2, sb2, st2, sid3, at3, stg3, dm3, sd3, sb3, st3): if self.__battleCleanedUp: return + self.notify.debug('setMovie()') if int(active) == 1: self.notify.debug('setMovie() - movie is active') @@ -550,6 +594,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): def setChosenToonAttacks(self, ids, tracks, levels, targets): if self.__battleCleanedUp: return + self.notify.debug('setChosenToonAttacks() - (%s), (%s), (%s), (%s)' % (ids, tracks, levels, @@ -569,8 +614,10 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): levels.append(-1) targetIndices.append(-1) continue + if toon == base.localAvatar: localToonInList = 1 + toonIndices.append(self.activeToons.index(toon)) if track == SOS: targetIndex = -1 @@ -603,6 +650,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): targetIndex = self.activeSuits.index(target) else: targetIndex = -1 + targetIndices.append(targetIndex) for i in range(4 - len(ids)): @@ -619,12 +667,13 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): if unAttack == 1 and self.fsm.getCurrentState().getName() == 'WaitForInput': if self.townBattle.fsm.getCurrentState().getName() != 'Attack': self.townBattle.setState('Attack') + self.townBattle.updateChosenAttacks(self.townBattleAttacks[0], self.townBattleAttacks[1], self.townBattleAttacks[2], self.townBattleAttacks[3]) - return def setBattleExperience(self, id0, origExp0, earnedExp0, origQuests0, items0, missedItems0, origMerits0, merits0, parts0, id1, origExp1, earnedExp1, origQuests1, items1, missedItems1, origMerits1, merits1, parts1, id2, origExp2, earnedExp2, origQuests2, items2, missedItems2, origMerits2, merits2, parts2, id3, origExp3, earnedExp3, origQuests3, items3, missedItems3, origMerits3, merits3, parts3, deathList, uberList, helpfulToonsList): if self.__battleCleanedUp: return + self.movie.genRewardDicts(id0, origExp0, earnedExp0, origQuests0, items0, missedItems0, origMerits0, merits0, parts0, id1, origExp1, earnedExp1, origQuests1, items1, missedItems1, origMerits1, merits1, parts1, id2, origExp2, earnedExp2, origQuests2, items2, missedItems2, origMerits2, merits2, parts2, id3, origExp3, earnedExp3, origQuests3, items3, missedItems3, origMerits3, merits3, parts3, deathList, uberList, helpfulToonsList) def __listenForUnexpectedExit(self, toon): @@ -644,10 +693,10 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): def delayDeleteMembers(self): membersKeep = [] for t in self.toons: - membersKeep.append(DelayDelete.DelayDelete(t, 'delayDeleteMembers')) + membersKeep.append(DelayDelete(t, 'delayDeleteMembers')) for s in self.suits: - membersKeep.append(DelayDelete.DelayDelete(s, 'delayDeleteMembers')) + membersKeep.append(DelayDelete(s, 'delayDeleteMembers')) self._removeMembersKeep() self.membersKeep = membersKeep @@ -658,45 +707,53 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): delayDelete.destroy() self.membersKeep = None - return def __removeSuit(self, suit): self.notify.debug('__removeSuit(%d)' % suit.doId) if self.suits.count(suit) != 0: self.suits.remove(suit) + if self.joiningSuits.count(suit) != 0: self.joiningSuits.remove(suit) + if self.pendingSuits.count(suit) != 0: self.pendingSuits.remove(suit) + if self.activeSuits.count(suit) != 0: self.activeSuits.remove(suit) + self.suitGone = 1 if suit.battleTrap != NO_TRAP: self.notify.debug('882 calling self.removeTrap, suit=%d' % suit.doId) self.removeTrap(suit) + suit.battleTrap = NO_TRAP suit.battleTrapProp = None self.notify.debug('883 suit.battleTrapProp = None') suit.battleTrapIsFresh = 0 - return def __removeToon(self, toon, unexpected = 0): self.notify.debug('__removeToon(%d)' % toon.doId) self.exitedToons.append(toon) if self.toons.count(toon) != 0: self.toons.remove(toon) + if self.joiningToons.count(toon) != 0: self.clearInterval(self.taskName('to-pending-toon-%d' % toon.doId)) if toon in self.joiningToons: self.joiningToons.remove(toon) + if self.pendingToons.count(toon) != 0: self.pendingToons.remove(toon) + if self.activeToons.count(toon) != 0: self.activeToons.remove(toon) + if self.runningToons.count(toon) != 0: self.clearInterval(self.taskName('running-%d' % toon.doId), finish=1) if toon in self.runningToons: self.runningToons.remove(toon) + self.ignore(toon.uniqueName('disable')) self.ignore(toon.uniqueName('died')) self.toonGone = 1 @@ -704,28 +761,33 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): self.removeLocalToon() self.__teleportToSafeZone(toon) return 1 + return 0 def removeLocalToon(self): if self._skippingRewardMovie: return + if base.cr.playGame.getPlace() != None: base.cr.playGame.getPlace().setState('walk') + base.localAvatar.earnedExperience = None self.localToonFsm.request('NoLocalToon') - return def removeInactiveLocalToon(self, toon): self.notify.debug('removeInactiveLocalToon(%d)' % toon.doId) self.exitedToons.append(toon) if self.toons.count(toon) != 0: self.toons.remove(toon) + if self.joiningToons.count(toon) != 0: self.clearInterval(self.taskName('to-pending-toon-%d' % toon.doId), finish=1) if toon in self.joiningToons: self.joiningToons.remove(toon) + if self.pendingToons.count(toon) != 0: self.pendingToons.remove(toon) + self.ignore(toon.uniqueName('disable')) self.ignore(toon.uniqueName('died')) base.cr.playGame.getPlace().setState('walk') @@ -733,7 +795,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): def __createJoinInterval(self, av, destPos, destHpr, name, ts, callback, toon = 0): joinTrack = Sequence() - joinTrack.append(Func(Emote.globalEmote.disableAll, av, 'dbattlebase, createJoinInterval')) + joinTrack.append(Func(globalEmote.disableAll, av, 'dbattlebase, createJoinInterval')) avPos = av.getPos(self) avPos = Point3(avPos[0], avPos[1], 0.0) av.setShadowHeight(0) @@ -746,6 +808,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): else: timeToDest = self.calcToonMoveTime(avPos, destPos) joinTrack.append(Func(av.loop, 'run')) + if timeToDest > BATTLE_SMALL_VALUE: joinTrack.append(LerpPosInterval(av, timeToDest, destPos, other=self)) totalTime = timeToDest @@ -761,14 +824,17 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): timeToPerimeter = self.calcToonMoveTime(plist[0], avPos) timePerSegment = 10.0 / BattleBase.toonSpeed timeToDest = self.calcToonMoveTime(BattleBase.posE, destPos) + totalTime = timeToPerimeter + (len(plist) - 1) * timePerSegment + timeToDest if totalTime > MAX_JOIN_T: self.notify.warning('__createJoinInterval() - time: %f' % totalTime) + joinTrack.append(Func(av.headsUp, self, plist[0])) if toon == 0: joinTrack.append(Func(av.loop, 'walk')) else: joinTrack.append(Func(av.loop, 'run')) + joinTrack.append(LerpPosInterval(av, timeToPerimeter, plist[0], other=self)) for p in plist[1:]: joinTrack.append(Func(av.headsUp, self, p)) @@ -776,12 +842,14 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): joinTrack.append(Func(av.headsUp, self, destPos)) joinTrack.append(LerpPosInterval(av, timeToDest, destPos, other=self)) + joinTrack.append(Func(av.loop, 'neutral')) joinTrack.append(Func(av.headsUp, self, Point3(0, 0, 0))) tval = totalTime - ts if tval < 0: tval = totalTime - joinTrack.append(Func(Emote.globalEmote.releaseAll, av, 'dbattlebase, createJoinInterval')) + + joinTrack.append(Func(globalEmote.releaseAll, av, 'dbattlebase, createJoinInterval')) joinTrack.append(Func(callback, av, tval)) if av == base.localAvatar: camTrack = Sequence() @@ -790,9 +858,9 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): base.camLens.setFov(fov) camTrack.append(Func(setCamFov, self.camFov)) - camTrack.append(Func(camera.wrtReparentTo, self)) - camTrack.append(Func(camera.setPos, self.camJoinPos)) - camTrack.append(Func(camera.setHpr, self.camJoinHpr)) + camTrack.append(Func(base.camera.wrtReparentTo, self)) + camTrack.append(Func(base.camera.setPos, self.camJoinPos)) + camTrack.append(Func(base.camera.setHpr, self.camJoinHpr)) return Parallel(joinTrack, camTrack, name=name) else: return Sequence(joinTrack, name=name) @@ -808,7 +876,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): trackName = self.taskName('to-pending-suit-%d' % suit.doId) track = self.__createJoinInterval(suit, pos, hpr, trackName, ts, self.__handleSuitJoinDone) track.start(ts) - track.delayDelete = DelayDelete.DelayDelete(suit, 'makeSuitJoin') + track.delayDelete = DelayDelete(suit, 'makeSuitJoin') self.storeInterval(track, trackName) if ToontownBattleGlobals.SkipMovie: track.finish() @@ -823,6 +891,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): self.clearInterval(self.taskName('to-pending-suit-%d' % suit.doId), finish=1) if self.joiningSuits.count(suit): self.joiningSuits.remove(suit) + self.pendingSuits.append(suit) def __teleportToSafeZone(self, toon): @@ -832,6 +901,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): target_sz = ZoneUtil.getSafeZoneId(self.zoneId) else: target_sz = ZoneUtil.getSafeZoneId(base.localAvatar.defaultZone) + base.cr.playGame.getPlace().fsm.request('teleportOut', [{'loader': ZoneUtil.getLoaderName(target_sz), 'where': ZoneUtil.getWhereName(target_sz, 1), 'how': 'teleportIn', @@ -840,7 +910,6 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): 'shardId': None, 'avId': -1, 'battle': 1}]) - return def __makeToonJoin(self, toon, pendingToons, ts): self.notify.debug('__makeToonJoin(%d)' % toon.doId) @@ -853,8 +922,9 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): track = self.__createJoinInterval(toon, pos, hpr, trackName, ts, self.__handleToonJoinDone, toon=1) if toon != base.localAvatar: toon.animFSM.request('off') + track.start(ts) - track.delayDelete = DelayDelete.DelayDelete(toon, '__makeToonJoin') + track.delayDelete = DelayDelete(toon, '__makeToonJoin') self.storeInterval(track, trackName) def __handleToonJoinDone(self, toon, ts): @@ -867,6 +937,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): self.clearInterval(self.taskName('to-pending-toon-%d' % toon.doId), finish=1) if self.joiningToons.count(toon): self.joiningToons.remove(toon) + spotIndex = len(self.pendingToons) self.pendingToons.append(toon) openSpot = self.toonPendingPoints[spotIndex] @@ -874,8 +945,6 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): hpr = VBase3(openSpot[1], 0.0, 0.0) toon.loop('neutral') toon.setPosHpr(self, pos, hpr) - if base.localAvatar == toon: - currStateName = self.fsm.getCurrentState().getName() def __makeAvsActive(self, suits, toons): self.notify.debug('__makeAvsActive()') @@ -884,8 +953,10 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): if self.joiningSuits.count(s): self.notify.warning('suit: %d was in joining list!' % s.doId) self.joiningSuits.remove(s) + if self.pendingSuits.count(s): self.pendingSuits.remove(s) + self.notify.debug('__makeAvsActive() - suit: %d' % s.doId) self.activeSuits.append(s) @@ -897,14 +968,17 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): else: spos = Point3(suitPos[0], suitPos[1] - MovieUtil.SUIT_LURE_DISTANCE, suitPos[2]) suit.setPosHpr(self, spos, suitHpr) + suit.loop('neutral') for toon in toons: if self.joiningToons.count(toon): self.notify.warning('toon: %d was in joining list!' % toon.doId) self.joiningToons.remove(toon) + if self.pendingToons.count(toon): self.pendingToons.remove(toon) + self.notify.debug('__makeAvsActive() - toon: %d' % toon.doId) if self.activeToons.count(toon) == 0: self.activeToons.append(toon) @@ -927,16 +1001,18 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): self.notify.debug('__makeToonRun(%d)' % toon.doId) if self.activeToons.count(toon): self.activeToons.remove(toon) + self.runningToons.append(toon) self.toonGone = 1 self.__stopTimer() if self.localToonRunning(): self.townBattle.setState('Off') + runMTrack = MovieUtil.getToonTeleportOutInterval(toon) runName = self.taskName('running-%d' % toon.doId) self.notify.debug('duration: %f' % runMTrack.getDuration()) runMTrack.start(ts) - runMTrack.delayDelete = DelayDelete.DelayDelete(toon, '__makeToonRun') + runMTrack.delayDelete = DelayDelete(toon, '__makeToonRun') self.storeInterval(runMTrack, runName) def getToon(self, toonId): @@ -944,8 +1020,6 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): return self.cr.doId2do[toonId] else: self.notify.warning('getToon() - toon: %d not in repository!' % toonId) - return None - return None def d_toonRequestJoin(self, toonId, pos): self.notify.debug('network:toonRequestJoin()') @@ -993,27 +1067,25 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): def enterOff(self, ts = 0): self.localToonFsm.requestFinalState() - return None def exitOff(self): - return None + pass def enterFaceOff(self, ts = 0): - return None + pass def exitFaceOff(self): - return None + pass def enterWaitForJoin(self, ts = 0): self.notify.debug('enterWaitForJoin()') - return None def exitWaitForJoin(self): - return None + pass def __enterLocalToonWaitForInput(self): self.notify.debug('enterLocalToonWaitForInput()') - camera.setPosHpr(self.camPos, self.camHpr) + base.camera.setPosHpr(self.camPos, self.camHpr) base.camLens.setFov(self.camMenuFov) NametagGlobals.setMasterArrowsOn(0) self.townBattle.setState('Attack') @@ -1025,6 +1097,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): self.notify.warning('startTimer() - ts: %f timeout: %f' % (ts, CLIENT_INPUT_TIMEOUT)) self.__timedOut() return + self.timer.startCallback(CLIENT_INPUT_TIMEOUT - ts, self.__timedOut) timeTask = Task.loop(Task(self.__countdown), Task.pause(0.2)) taskMgr.add(timeTask, self.timerCountdownTaskName) @@ -1040,19 +1113,21 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): else: self.notify.warning('__countdown has tried to update a timer that has been deleted. Stopping timer') self.__stopTimer() - return Task.done + + return task.done def enterWaitForInput(self, ts = 0): self.notify.debug('enterWaitForInput()') if self.interactiveProp: self.interactiveProp.gotoBattleCheer() + self.choseAttackAlready = 0 if self.localToonActive(): self.__enterLocalToonWaitForInput() self.startTimer(ts) + if self.needAdjustTownBattle == 1: self.__adjustTownBattle() - return None def exitWaitForInput(self): self.notify.debug('exitWaitForInput()') @@ -1061,7 +1136,6 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): base.camLens.setFov(self.camFov) self.ignore(self.localToonBattleEvent) self.__stopTimer() - return None def __handleLocalToonBattleEvent(self, response): mode = response['mode'] @@ -1089,6 +1163,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): targetId = self.activeSuits[target].doId else: target = -1 + if len(self.luredSuits) > 0: if track == TRAP or track == LURE and not levelAffectsGroup(LURE, level): if target != -1: @@ -1104,6 +1179,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): track = -1 level = -1 targetId = -1 + if track == TRAP: if target != -1: if attackAffectsGroup(track, level): @@ -1115,6 +1191,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): track = -1 level = -1 targetId = -1 + self.d_requestAttack(base.localAvatar.doId, track, level, targetId) elif mode == 'Run': self.notify.debug('got a run') @@ -1141,6 +1218,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): messenger.send(proxyGenerateMessage) else: self.d_requestPetProxy(base.localAvatar.doId, petProxyId) + noAttack = 1 elif mode == 'Pass': targetId = response['id'] @@ -1156,6 +1234,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): else: self.notify.warning('unknown battle response') return + if noAttack == 1: self.choseAttackAlready = 0 else: @@ -1164,6 +1243,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): def __timedOut(self): if self.choseAttackAlready == 1: return + self.notify.debug('WaitForInput timed out') if self.localToonActive(): self.notify.debug('battle timed out') @@ -1171,27 +1251,27 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): def enterMakeMovie(self, ts = 0): self.notify.debug('enterMakeMovie()') - return None def exitMakeMovie(self): - return None + pass def enterPlayMovie(self, ts): self.notify.debug('enterPlayMovie()') self.delayDeleteMembers() if self.hasLocalToon(): NametagGlobals.setMasterArrowsOn(0) + if ToontownBattleGlobals.SkipMovie: self.movie.play(ts, self.__handleMovieDone) self.movie.finish() else: self.movie.play(ts, self.__handleMovieDone) - return None def __handleMovieDone(self): self.notify.debug('__handleMovieDone()') if self.hasLocalToon(): self.d_movieDone(base.localAvatar.doId) + self.movie.reset() def exitPlayMovie(self): @@ -1214,7 +1294,6 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): 0, 0, 0]) - return None def hasLocalToon(self): return self.toons.count(base.localAvatar) > 0 @@ -1235,59 +1314,61 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): self.notify.debug('enterHasLocalToon()') if base.cr.playGame.getPlace() != None: base.cr.playGame.getPlace().setState('battle', self.localToonBattleEvent) - if localAvatar and hasattr(localAvatar, 'inventory') and localAvatar.inventory: - localAvatar.inventory.setInteractivePropTrackBonus(self.interactivePropTrackBonus) - camera.wrtReparentTo(self) + if base.localAvatar and hasattr(base.localAvatar, 'inventory') and base.localAvatar.inventory: + base.localAvatar.inventory.setInteractivePropTrackBonus(self.interactivePropTrackBonus) + + base.camera.wrtReparentTo(self) base.camLens.setFov(self.camFov) - return def exitHasLocalToon(self): self.ignore(self.localToonBattleEvent) self.__stopTimer() - if localAvatar and hasattr(localAvatar, 'inventory') and localAvatar.inventory: - localAvatar.inventory.setInteractivePropTrackBonus(-1) + if base.localAvatar and hasattr(base.localAvatar, 'inventory') and base.localAvatar.inventory: + base.localAvatar.inventory.setInteractivePropTrackBonus(-1) + stateName = None place = base.cr.playGame.getPlace() if place: stateName = place.fsm.getCurrentState().getName() + if stateName == 'died': self.movie.reset() - camera.reparentTo(render) - camera.setPosHpr(localAvatar, 5.2, 5.45, localAvatar.getHeight() * 0.66, 131.5, 3.6, 0) + base.camera.reparentTo(base.render) + base.camera.setPosHpr(base.localAvatar, 5.2, 5.45, base.localAvatar.getHeight() * 0.66, 131.5, 3.6, 0) else: - camera.wrtReparentTo(base.localAvatar) + base.camera.wrtReparentTo(base.localAvatar) messenger.send('localToonLeftBattle') + base.camLens.setFov(ToontownGlobals.DefaultCameraFov) - return def enterNoLocalToon(self): self.notify.debug('enterNoLocalToon()') - return None def exitNoLocalToon(self): - return None + pass def setSkippingRewardMovie(self): self._skippingRewardMovie = True def enterWaitForServer(self): self.notify.debug('enterWaitForServer()') - return None def exitWaitForServer(self): - return None + pass def createAdjustInterval(self, av, destPos, destHpr, toon = 0, run = 0): if run == 1: adjustTime = self.calcToonMoveTime(destPos, av.getPos(self)) else: adjustTime = self.calcSuitMoveTime(destPos, av.getPos(self)) + self.notify.debug('creating adjust interval for: %d' % av.doId) adjustTrack = Sequence() if run == 1: adjustTrack.append(Func(av.loop, 'run')) else: adjustTrack.append(Func(av.loop, 'walk')) + adjustTrack.append(Func(av.headsUp, self, destPos)) adjustTrack.append(LerpPosInterval(av, adjustTime, destPos, other=self)) adjustTrack.append(Func(av.setHpr, self, destHpr)) @@ -1307,9 +1388,11 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): destPos = point[0] if self.isSuitLured(suit) == 1: destPos = Point3(destPos[0], destPos[1] - MovieUtil.SUIT_LURE_DISTANCE, destPos[2]) + if pos != destPos: destHpr = VBase3(point[1], 0.0, 0.0) adjustTrack.append(self.createAdjustInterval(suit, destPos, destHpr)) + index += 1 for suit in self.pendingSuits: @@ -1330,6 +1413,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): if pos != destPos: destHpr = VBase3(point[1], 0.0, 0.0) adjustTrack.append(self.createAdjustInterval(toon, destPos, destHpr)) + index += 1 for toon in self.pendingToons: @@ -1377,6 +1461,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): for suit in self.luredSuits: if suit not in self.activeSuits: self.notify.error('lured suit not in self.activeSuits') + luredSuits.append(self.activeSuits.index(suit)) trappedSuits = [] @@ -1387,21 +1472,23 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): self.townBattle.adjustCogsAndToons(self.activeSuits, luredSuits, trappedSuits, self.activeToons) if hasattr(self, 'townBattleAttacks'): self.townBattle.updateChosenAttacks(self.townBattleAttacks[0], self.townBattleAttacks[1], self.townBattleAttacks[2], self.townBattleAttacks[3]) + self.needAdjustTownBattle = 0 def __adjustDone(self): self.notify.debug('__adjustDone()') if self.hasLocalToon(): self.d_adjustDone(base.localAvatar.doId) + self.adjustFsm.request('NotAdjusting') def enterAdjusting(self, ts): self.notify.debug('enterAdjusting()') if self.localToonActive(): self.__stopTimer() + self.delayDeleteMembers() self.__adjust(ts, self.__handleAdjustDone) - return None def exitAdjusting(self): self.notify.debug('exitAdjusting()') @@ -1410,14 +1497,12 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): currStateName = self.fsm.getCurrentState().getName() if currStateName == 'WaitForInput' and self.localToonActive(): self.startTimer() - return None def enterNotAdjusting(self): self.notify.debug('enterNotAdjusting()') - return None def exitNotAdjusting(self): - return None + pass def visualize(self): try: @@ -1440,7 +1525,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): p = BattleBase.allPoints[0] lsegs.drawTo(p[0], p[1], p[2]) self.vis = self.attachNewNode(lsegs.create()) - self.reparentTo(render) + self.reparentTo(base.render) self.isVisualized = 1 def setupCollisions(self, name): @@ -1466,14 +1551,17 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): if self.fsm.getCurrentState().getName() == 'Off': self.notify.debug('ignoring collision in Off state') return + if not base.localAvatar.wantBattles: return + if self._skippingRewardMovie: return + base.cr.playGame.getPlace().setState('WaitForBattle') toon = base.localAvatar self.d_toonRequestJoin(toon.doId, toon.getPos(self)) - base.localAvatar.preBattleHpr = base.localAvatar.getHpr(render) + base.localAvatar.preBattleHpr = base.localAvatar.getHpr(base.render) self.localToonFsm.request('WaitForServer') self.onWaitingForJoin() @@ -1485,6 +1573,7 @@ class DistributedBattleBase(DistributedNode.DistributedNode, BattleBase): place = self.cr.playGame.getPlace() if place.fsm.getCurrentState().getName() == 'WaitForBattle': place.setState('walk') + self.localToonFsm.request('NoLocalToon') def disableCollision(self): diff --git a/toontown/building/DistributedDoor.py b/toontown/building/DistributedDoor.py index 42c27e1..fa6af36 100644 --- a/toontown/building/DistributedDoor.py +++ b/toontown/building/DistributedDoor.py @@ -1,48 +1,66 @@ -from toontown.toonbase.ToonBaseGlobal import * -from panda3d.core import * -from direct.interval.IntervalGlobal import * -from direct.distributed.ClockDelta import * -from toontown.toonbase import ToontownGlobals -from direct.directnotify import DirectNotifyGlobal -from direct.fsm import ClassicFSM, State -from direct.distributed import DistributedObject -from toontown.hood import ZoneUtil -from toontown.suit import Suit -from toontown.distributed import DelayDelete -from . import FADoorCodes -from direct.task.Task import Task -from . import DoorTypes -from toontown.toontowngui import TTDialog -from toontown.toonbase import TTLocalizer -from toontown.toontowngui import TeaserPanel -from toontown.distributed.DelayDeletable import DelayDeletable -if (__debug__): - import pdb +from panda3d.core import NodePath, Point3, VBase3, Vec3 +from panda3d.otp import Nametag, NametagGroup -class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): +from direct.directnotify.DirectNotifyGlobal import directNotify +from direct.distributed.ClockDelta import globalClockDelta +from direct.distributed.DistributedObject import DistributedObject +from direct.fsm.ClassicFSM import ClassicFSM +from direct.fsm.State import State +from direct.interval.IntervalGlobal import ( + ActorInterval, + Func, + HprInterval, + LerpHprInterval, + LerpPosHprInterval, + LerpPosInterval, + Parallel, + PosHprInterval, + Sequence, + SoundInterval, + Wait +) + +from direct.showbase.MessengerGlobal import messenger +from direct.task.TaskManagerGlobal import taskMgr + +from toontown.building import DoorTypes +from toontown.building import FADoorCodes +from toontown.distributed.DelayDeletable import DelayDeletable +from toontown.distributed.DelayDelete import DelayDelete, cleanupDelayDeletes +from toontown.hood import ZoneUtil +from toontown.suit.Suit import Suit +from toontown.toonbase import ToontownGlobals +from toontown.toonbase import TTLocalizer +from toontown.toonbase.ToonBaseGlobal import base +from toontown.toontowngui import TTDialog +from toontown.toontowngui.TeaserPanel import TeaserPanel + + +class DistributedDoor(DistributedObject, DelayDeletable): + notify = directNotify.newCategory('DistributedDoor') def __init__(self, cr): - DistributedObject.DistributedObject.__init__(self, cr) + DistributedObject.__init__(self, cr) self.openSfx = base.loader.loadSfx('phase_3.5/audio/sfx/Door_Open_1.ogg') self.closeSfx = base.loader.loadSfx('phase_3.5/audio/sfx/Door_Close_1.ogg') self.nametag = None - self.fsm = ClassicFSM.ClassicFSM('DistributedDoor_right', [State.State('off', self.enterOff, self.exitOff, ['closing', + self.fsm = ClassicFSM('DistributedDoor_right', [State('off', self.enterOff, self.exitOff, ['closing', 'closed', 'opening', 'open']), - State.State('closing', self.enterClosing, self.exitClosing, ['closed', 'opening']), - State.State('closed', self.enterClosed, self.exitClosed, ['opening']), - State.State('opening', self.enterOpening, self.exitOpening, ['open']), - State.State('open', self.enterOpen, self.exitOpen, ['closing', 'open'])], 'off', 'off') + State('closing', self.enterClosing, self.exitClosing, ['closed', 'opening']), + State('closed', self.enterClosed, self.exitClosed, ['opening']), + State('opening', self.enterOpening, self.exitOpening, ['open']), + State('open', self.enterOpen, self.exitOpen, ['closing', 'open'])], 'off', 'off') self.fsm.enterInitialState() - self.exitDoorFSM = ClassicFSM.ClassicFSM('DistributedDoor_left', [State.State('off', self.exitDoorEnterOff, self.exitDoorExitOff, ['closing', + self.exitDoorFSM = ClassicFSM('DistributedDoor_left', [State('off', self.exitDoorEnterOff, self.exitDoorExitOff, ['closing', 'closed', 'opening', 'open']), - State.State('closing', self.exitDoorEnterClosing, self.exitDoorExitClosing, ['closed', 'opening']), - State.State('closed', self.exitDoorEnterClosed, self.exitDoorExitClosed, ['opening']), - State.State('opening', self.exitDoorEnterOpening, self.exitDoorExitOpening, ['open']), - State.State('open', self.exitDoorEnterOpen, self.exitDoorExitOpen, ['closing', 'open'])], 'off', 'off') + State('closing', self.exitDoorEnterClosing, self.exitDoorExitClosing, ['closed', 'opening']), + State('closed', self.exitDoorEnterClosed, self.exitDoorExitClosed, ['opening']), + State('opening', self.exitDoorEnterOpening, self.exitDoorExitOpening, ['open']), + State('open', self.exitDoorEnterOpen, self.exitDoorExitOpen, ['closing', 'open'])], 'off', 'off') self.exitDoorFSM.enterInitialState() self.specialDoorTypes = {DoorTypes.EXT_HQ: 0, DoorTypes.EXT_COGHQ: 0, @@ -50,17 +68,15 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): DoorTypes.EXT_KS: 0, DoorTypes.INT_KS: 0} self.doorX = 1.5 - return def generate(self): - DistributedObject.DistributedObject.generate(self) + DistributedObject.generate(self) self.avatarTracks = [] self.avatarExitTracks = [] self.avatarIDList = [] self.avatarExitIDList = [] self.doorTrack = None self.doorExitTrack = None - return def disable(self): self.clearNametag() @@ -72,20 +88,22 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): self.exitDoorFSM.request('off') if 'building' in self.__dict__: del self.building + self.finishAllTracks() self.avatarIDList = [] self.avatarExitIDList = [] if hasattr(self, 'tempDoorNodePath'): self.tempDoorNodePath.removeNode() del self.tempDoorNodePath - DistributedObject.DistributedObject.disable(self) + + DistributedObject.disable(self) def delete(self): del self.fsm del self.exitDoorFSM del self.openSfx del self.closeSfx - DistributedObject.DistributedObject.delete(self) + DistributedObject.delete(self) def wantsNametag(self): return not ZoneUtil.isInterior(self.zoneId) @@ -93,11 +111,13 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): def setupNametag(self): if not self.wantsNametag(): return + if self.nametag == None: self.nametag = NametagGroup() self.nametag.setFont(ToontownGlobals.getBuildingNametagFont()) if TTLocalizer.BuildingNametagShadow: self.nametag.setShadow(*TTLocalizer.BuildingNametagShadow) + self.nametag.setContents(Nametag.CName) self.nametag.setColorCode(NametagGroup.CCToonBuilding) self.nametag.setActive(0) @@ -106,14 +126,12 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): name = self.cr.playGame.dnaStore.getTitleFromBlockNumber(self.block) self.nametag.setName(name) self.nametag.manage(base.marginManager) - return def clearNametag(self): if self.nametag != None: self.nametag.unmanage(base.marginManager) self.nametag.setAvatar(NodePath()) self.nametag = None - return def getTriggerName(self): if self.doorType == DoorTypes.INT_HQ or self.doorType in self.specialDoorTypes: @@ -137,26 +155,25 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): self.hideIfHasFlat(self.findDoorNode('leftDoor')) self.findDoorNode('doorFrameHoleRight').hide() self.findDoorNode('doorFrameHoleLeft').hide() - else: - return def setTriggerName(self): if self.doorType in self.specialDoorTypes: building = self.getBuilding() doorTrigger = building.find('**/door_' + str(self.doorIndex) + '/**/door_trigger*') doorTrigger.node().setName(self.getTriggerName()) - else: - return def setTriggerName_wip(self): building = self.getBuilding() doorTrigger = building.find('**/door_%d/**/door_trigger_%d' % (self.doorIndex, self.block)) if doorTrigger.isEmpty(): doorTrigger = building.find('**/door_trigger_%d' % (self.block,)) + if doorTrigger.isEmpty(): doorTrigger = building.find('**/door_%d/**/door_trigger_*' % (self.doorIndex,)) + if doorTrigger.isEmpty(): doorTrigger = building.find('**/door_trigger_*') + doorTrigger.node().setName(self.getTriggerName()) def setZoneIdAndBlock(self, zoneId, block): @@ -185,7 +202,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): self.exitDoorFSM.request(state, [globalClockDelta.localElapsedTime(timestamp)]) def announceGenerate(self): - DistributedObject.DistributedObject.announceGenerate(self) + DistributedObject.announceGenerate(self) self.doPostAnnounceGenerate() def doPostAnnounceGenerate(self): @@ -193,6 +210,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): self.bHasFlat = True else: self.bHasFlat = not self.findDoorNode('door*flat', True).isEmpty() + self.hideDoorParts() self.setTriggerName() self.accept(self.getEnterTriggerEvent(), self.doorTrigger) @@ -202,13 +220,13 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): def getBuilding(self): if 'building' not in self.__dict__: if self.doorType == DoorTypes.INT_STANDARD: - door = render.find('**/leftDoor;+s') + door = base.render.find('**/leftDoor;+s') self.building = door.getParent() elif self.doorType == DoorTypes.INT_HQ: - door = render.find('**/door_0') + door = base.render.find('**/door_0') self.building = door.getParent() elif self.doorType == DoorTypes.INT_KS: - self.building = render.find('**/KartShop_Interior*') + self.building = base.render.find('**/KartShop_Interior*') elif self.doorType == DoorTypes.EXT_STANDARD or self.doorType == DoorTypes.EXT_HQ or self.doorType == DoorTypes.EXT_KS: self.building = self.cr.playGame.hood.loader.geom.find('**/??' + str(self.block) + ':*_landmark_*_DNARoot;+s') if self.building.isEmpty(): @@ -217,6 +235,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): self.building = self.cr.playGame.hood.loader.geom else: self.notify.error('No such door type as ' + str(self.doorType)) + return self.building def getBuilding_wip(self): @@ -226,6 +245,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): else: self.building = self.cr.playGame.hood.loader.geom print('---------------- door is interior -------') + return self.building def readyToExit(self): @@ -238,33 +258,38 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): otherNP = self.getDoorNodePath() if hasattr(avatar, 'stopSmooth'): avatar.stopSmooth() + if avatar.doId == base.localAvatar.doId: - track.append(LerpPosHprInterval(nodePath=camera, other=avatar, duration=duration, pos=Point3(0, -8, avatar.getHeight()), hpr=VBase3(0, 0, 0), blendType='easeInOut')) + track.append(LerpPosHprInterval(nodePath=base.camera, other=avatar, duration=duration, pos=Point3(0, -8, avatar.getHeight()), hpr=VBase3(0, 0, 0), blendType='easeInOut')) + finalPos = avatar.getParent().getRelativePoint(otherNP, Point3(self.doorX, 2, ToontownGlobals.FloorOffset)) moveHere = Sequence(self.getAnimStateInterval(avatar, 'walk'), LerpPosInterval(nodePath=avatar, duration=duration, pos=finalPos, blendType='easeIn')) track.append(moveHere) if avatar.doId == base.localAvatar.doId: track.append(Sequence(Wait(duration * 0.5), Func(base.transitions.irisOut, duration * 0.5), Wait(duration * 0.5), Func(avatar.b_setParent, ToontownGlobals.SPHidden))) - track.delayDelete = DelayDelete.DelayDelete(avatar, 'avatarEnterDoorTrack') + + track.delayDelete = DelayDelete(avatar, 'avatarEnterDoorTrack') return track def avatarEnqueueTrack(self, avatar, duration): if hasattr(avatar, 'stopSmooth'): avatar.stopSmooth() + back = -5.0 - 2.0 * len(self.avatarIDList) if back < -9.0: back = -9.0 + offset = Point3(self.doorX, back, ToontownGlobals.FloorOffset) otherNP = self.getDoorNodePath() walkLike = ActorInterval(avatar, 'walk', startTime=1, duration=duration, endTime=0.0001) standHere = Sequence(LerpPosHprInterval(nodePath=avatar, other=otherNP, duration=duration, pos=offset, hpr=VBase3(0, 0, 0), blendType='easeInOut'), self.getAnimStateInterval(avatar, 'neutral')) trackName = 'avatarEnqueueDoor-%d-%d' % (self.doId, avatar.doId) track = Parallel(walkLike, standHere, name=trackName) - track.delayDelete = DelayDelete.DelayDelete(avatar, 'avatarEnqueueTrack') + track.delayDelete = DelayDelete(avatar, 'avatarEnqueueTrack') return track def getAnimStateInterval(self, avatar, animName): - isSuit = isinstance(avatar, Suit.Suit) + isSuit = isinstance(avatar, Suit) if isSuit: return Func(avatar.loop, animName, 0) else: @@ -284,7 +309,8 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): place = base.cr.playGame.getPlace() if place: place.fsm.request('stopped') - self.dialog = TeaserPanel.TeaserPanel(pageName='otherHoods', doneFunc=self.handleOkTeaser) + + self.dialog = TeaserPanel(pageName='otherHoods', doneFunc=self.handleOkTeaser) def handleOkTeaser(self): self.accept(self.getEnterTriggerEvent(), self.doorTrigger) @@ -301,6 +327,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): allowed = base.ttAccess.canAccess(zoneId) else: allowed = base.ttAccess.canAccess() + return allowed def checkIsDoorHitTaskName(self): @@ -311,8 +338,9 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): self.ignore(self.checkIsDoorHitTaskName()) self.ignore(self.getExitTriggerEvent()) self.enterDoor() - return Task.done - return Task.cont + return task.done + + return task.cont def cancelCheckIsDoorHitTask(self, args): taskMgr.remove(self.checkIsDoorHitTaskName()) @@ -333,7 +361,6 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): else: self.accept(self.getExitTriggerEvent(), self.cancelCheckIsDoorHitTask) taskMgr.add(self.checkIsDoorHitTask, self.checkIsDoorHitTaskName()) - return def avatarEnter(self, avatarID): avatar = self.cr.doId2do.get(avatarID, None) @@ -343,7 +370,6 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): track.start() self.avatarTracks.append(track) self.avatarIDList.append(avatarID) - return def rejectEnter(self, reason): message = FADoorCodes.reasonDict[reason] @@ -360,7 +386,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): def __faRejectEnter(self, message): self.rejectDialog = TTDialog.TTGlobalDialog(message=message, doneEvent='doorRejectAck', style=TTDialog.Acknowledge) self.rejectDialog.show() - self.rejectDialog.delayDelete = DelayDelete.DelayDelete(self, '__faRejectEnter') + self.rejectDialog.delayDelete = DelayDelete(self, '__faRejectEnter') event = 'clientCleanup' self.acceptOnce(event, self.__handleClientCleanup) base.cr.playGame.getPlace().setState('stopped') @@ -370,6 +396,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): def __handleClientCleanup(self): if hasattr(self, 'rejectDialog') and self.rejectDialog: self.rejectDialog.doneStatus = 'ok' + self.__handleRejectAck() def __handleFallAsleepDoor(self): @@ -383,6 +410,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): doneStatus = self.rejectDialog.doneStatus if doneStatus != 'ok': self.notify.error('Unrecognized doneStatus: ' + str(doneStatus)) + self.__basicRejectEnter() self.rejectDialog.delayDelete.destroy() self.rejectDialog.cleanup() @@ -390,7 +418,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): def getDoorNodePath(self): if self.doorType == DoorTypes.INT_STANDARD: - otherNP = render.find('**/door_origin') + otherNP = base.render.find('**/door_origin') elif self.doorType == DoorTypes.EXT_STANDARD: if hasattr(self, 'tempDoorNodePath'): return self.tempDoorNodePath @@ -404,14 +432,16 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): building = self.getBuilding() otherNP = building.find('**/door_origin_' + str(self.doorIndex)) elif self.doorType == DoorTypes.INT_HQ: - otherNP = render.find('**/door_origin_' + str(self.doorIndex)) + otherNP = base.render.find('**/door_origin_' + str(self.doorIndex)) else: self.notify.error('No such door type as ' + str(self.doorType)) + return otherNP def avatarExitTrack(self, avatar, duration): if hasattr(avatar, 'stopSmooth'): avatar.stopSmooth() + otherNP = self.getDoorNodePath() trackName = 'avatarExitDoor-%d-%d' % (self.doId, avatar.doId) track = Sequence(name=trackName) @@ -419,18 +449,22 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): track.append(PosHprInterval(avatar, Point3(-self.doorX, 0, ToontownGlobals.FloorOffset), VBase3(179, 0, 0), other=otherNP)) track.append(Func(avatar.setParent, ToontownGlobals.SPRender)) if avatar.doId == base.localAvatar.doId: - track.append(PosHprInterval(camera, VBase3(-self.doorX, 5, avatar.getHeight()), VBase3(180, 0, 0), other=otherNP)) + track.append(PosHprInterval(base.camera, VBase3(-self.doorX, 5, avatar.getHeight()), VBase3(180, 0, 0), other=otherNP)) + if avatar.doId == base.localAvatar.doId: - finalPos = render.getRelativePoint(otherNP, Point3(-self.doorX, -6, ToontownGlobals.FloorOffset)) + finalPos = base.render.getRelativePoint(otherNP, Point3(-self.doorX, -6, ToontownGlobals.FloorOffset)) else: - finalPos = render.getRelativePoint(otherNP, Point3(-self.doorX, -3, ToontownGlobals.FloorOffset)) + finalPos = base.render.getRelativePoint(otherNP, Point3(-self.doorX, -3, ToontownGlobals.FloorOffset)) + track.append(LerpPosInterval(nodePath=avatar, duration=duration, pos=finalPos, blendType='easeInOut')) if avatar.doId == base.localAvatar.doId: track.append(Func(self.exitCompleted)) track.append(Func(base.transitions.irisIn)) + if hasattr(avatar, 'startSmooth'): track.append(Func(avatar.startSmooth)) - track.delayDelete = DelayDelete.DelayDelete(avatar, 'DistributedDoor.avatarExitTrack') + + track.delayDelete = DelayDelete(avatar, 'DistributedDoor.avatarExitTrack') return track def exitCompleted(self): @@ -438,6 +472,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): place = self.cr.playGame.getPlace() if place: place.setState('walk') + base.localAvatar.d_setParent(ToontownGlobals.SPRender) def avatarExit(self, avatarID): @@ -451,26 +486,26 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): def finishDoorTrack(self): if self.doorTrack: self.doorTrack.finish() + self.doorTrack = None - return def finishDoorExitTrack(self): if self.doorExitTrack: self.doorExitTrack.finish() + self.doorExitTrack = None - return def finishAllTracks(self): self.finishDoorTrack() self.finishDoorExitTrack() for t in self.avatarTracks: t.finish() - DelayDelete.cleanupDelayDeletes(t) + cleanupDelayDeletes(t) self.avatarTracks = [] for t in self.avatarExitTracks: t.finish() - DelayDelete.cleanupDelayDeletes(t) + cleanupDelayDeletes(t) self.avatarExitTracks = [] @@ -498,16 +533,19 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): if doorFrameHoleRight.isEmpty(): self.notify.warning('enterClosing(): did not find doorFrameHoleRight') return + rightDoor = self.findDoorNode('rightDoor') if rightDoor.isEmpty(): self.notify.warning('enterClosing(): did not find rightDoor') return + otherNP = self.getDoorNodePath() trackName = 'doorClose-%d' % self.doId if self.rightSwing: h = 100 else: h = -100 + self.finishDoorTrack() self.doorTrack = Sequence(LerpHprInterval(nodePath=rightDoor, duration=1.0, hpr=VBase3(0, 0, 0), startHpr=VBase3(h, 0, 0), other=otherNP, blendType='easeInOut'), Func(doorFrameHoleRight.hide), Func(self.hideIfHasFlat, rightDoor), SoundInterval(self.closeSfx, node=rightDoor), name=trackName) self.doorTrack.start(ts) @@ -529,16 +567,19 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): if doorFrameHoleRight.isEmpty(): self.notify.warning('enterOpening(): did not find doorFrameHoleRight') return + rightDoor = self.findDoorNode('rightDoor') if rightDoor.isEmpty(): self.notify.warning('enterOpening(): did not find rightDoor') return + otherNP = self.getDoorNodePath() trackName = 'doorOpen-%d' % self.doId if self.rightSwing: h = 100 else: h = -100 + self.finishDoorTrack() self.doorTrack = Parallel(SoundInterval(self.openSfx, node=rightDoor), Sequence(HprInterval(rightDoor, VBase3(0, 0, 0), other=otherNP), Wait(0.4), Func(rightDoor.show), Func(doorFrameHoleRight.show), LerpHprInterval(nodePath=rightDoor, duration=0.6, hpr=VBase3(h, 0, 0), startHpr=VBase3(0, 0, 0), other=otherNP, blendType='easeInOut')), name=trackName) self.doorTrack.start(ts) @@ -553,6 +594,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): track = self.avatarEnterDoorTrack(avatar, 1.0) track.start(ts) self.avatarTracks.append(track) + if avatarID == base.localAvatar.doId: self.done = 1 @@ -561,7 +603,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): def exitOpen(self): for track in self.avatarTracks: track.finish() - DelayDelete.cleanupDelayDeletes(track) + cleanupDelayDeletes(track) self.avatarTracks = [] @@ -576,10 +618,12 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): if doorFrameHoleLeft.isEmpty(): self.notify.warning('enterOpening(): did not find flatDoors') return + if self.leftSwing: h = -100 else: h = 100 + leftDoor = self.findDoorNode('leftDoor') if not leftDoor.isEmpty(): otherNP = self.getDoorNodePath() @@ -602,11 +646,13 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): if doorFrameHoleLeft.isEmpty(): self.notify.warning('enterOpening(): did not find flatDoors') return + leftDoor = self.findDoorNode('leftDoor') if self.leftSwing: h = -100 else: h = 100 + if not leftDoor.isEmpty(): otherNP = self.getDoorNodePath() trackName = 'doorDoorExitTrack-%d' % self.doId @@ -632,7 +678,7 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): def exitDoorExitOpen(self): for track in self.avatarExitTracks: track.finish() - DelayDelete.cleanupDelayDeletes(track) + cleanupDelayDeletes(track) self.avatarExitTracks = [] @@ -645,8 +691,10 @@ class DistributedDoor(DistributedObject.DistributedObject, DelayDeletable): foundNode = building.find('**/door_' + str(self.doorIndex) + '/**/' + string + '*;+s+i') if foundNode.isEmpty(): foundNode = building.find('**/' + string + '*;+s+i') + if allowEmpty: return foundNode + return foundNode def hideIfHasFlat(self, node): diff --git a/toontown/hood/Place.py b/toontown/hood/Place.py index 486bb56..fa346a2 100644 --- a/toontown/hood/Place.py +++ b/toontown/hood/Place.py @@ -1,30 +1,36 @@ -from panda3d.core import * -from toontown.toonbase.ToonBaseGlobal import * -from direct.directnotify import DirectNotifyGlobal -from direct.fsm import StateData -from direct.showbase.PythonUtil import PriorityCallbacks -from toontown.safezone import PublicWalk -from toontown.launcher import DownloadForceAcknowledge -from . import TrialerForceAcknowledge -from . import ZoneUtil -from toontown.friends import FriendsListManager -from toontown.toonbase import ToontownGlobals -from toontown.toon.Toon import teleportDebug -from toontown.estate import HouseGlobals -from toontown.toonbase import TTLocalizer -from otp.otpbase import OTPLocalizer -from otp.avatar import Emote -from otp.avatar.Avatar import teleportNotify -from direct.task import Task -from . import QuietZoneState -from toontown.distributed import ToontownDistrictStats +from panda3d.core import NodePath +from panda3d.otp import NametagGlobals -class Place(StateData.StateData, FriendsListManager.FriendsListManager): - notify = DirectNotifyGlobal.directNotify.newCategory('Place') +from direct.directnotify.DirectNotifyGlobal import directNotify +from direct.fsm.StateData import StateData +from direct.showbase.MessengerGlobal import messenger +from direct.showbase.PythonUtil import Functor, PriorityCallbacks, SubframeCall, uniqueName +from direct.task.TaskManagerGlobal import taskMgr + +from otp.avatar.Avatar import teleportNotify +from otp.avatar.Emote import globalEmote +from otp.otpbase import OTPLocalizer + +from toontown.distributed import ToontownDistrictStats +from toontown.estate import HouseGlobals +from toontown.friends.FriendsListManager import FriendsListManager +from toontown.hood import ZoneUtil +from toontown.hood.QuietZoneState import QuietZoneState +from toontown.hood.TrialerForceAcknowledge import TrialerForceAcknowledge +from toontown.launcher.DownloadForceAcknowledge import DownloadForceAcknowledge +from toontown.safezone.PublicWalk import PublicWalk +from toontown.toon.Toon import teleportDebug +from toontown.toonbase import ToontownGlobals +from toontown.toonbase import TTLocalizer +from toontown.toonbase.ToonBaseGlobal import base + + +class Place(StateData, FriendsListManager): + notify = directNotify.newCategory('Place') def __init__(self, loader, doneEvent): - StateData.StateData.__init__(self, doneEvent) - FriendsListManager.FriendsListManager.__init__(self) + StateData.__init__(self, doneEvent) + FriendsListManager.__init__(self) self.loader = loader self.dfaDoneEvent = 'dfaDoneEvent' self.trialerFADoneEvent = 'trialerFADoneEvent' @@ -35,26 +41,27 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): self._leftQuietZoneSubframeCall = None self._setZoneCompleteLocalCallbacks = PriorityCallbacks() self._setZoneCompleteSubframeCall = None - return def load(self): - StateData.StateData.load(self) - FriendsListManager.FriendsListManager.load(self) + StateData.load(self) + FriendsListManager.load(self) self.walkDoneEvent = 'walkDone' - self.walkStateData = PublicWalk.PublicWalk(self.fsm, self.walkDoneEvent) + self.walkStateData = PublicWalk(self.fsm, self.walkDoneEvent) self.walkStateData.load() self._tempFSM = self.fsm def unload(self): - StateData.StateData.unload(self) - FriendsListManager.FriendsListManager.unload(self) + StateData.unload(self) + FriendsListManager.unload(self) self.notify.info('Unloading Place (%s). Fsm in %s' % (self.zoneId, self._tempFSM.getCurrentState().getName())) if self._leftQuietZoneSubframeCall: self._leftQuietZoneSubframeCall.cleanup() self._leftQuietZoneSubframeCall = None + if self._setZoneCompleteSubframeCall: self._setZoneCompleteSubframeCall.cleanup() self._setZoneCompleteSubframeCall = None + self._leftQuietZoneLocalCallbacks = None self._setZoneCompleteLocalCallbacks = None del self._tempFSM @@ -66,12 +73,12 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): if self.trialerFA: self.trialerFA.exit() del self.trialerFA - return def _getQZState(self): if hasattr(base, 'cr') and hasattr(base.cr, 'playGame'): if hasattr(base.cr.playGame, 'quietZoneStateData') and base.cr.playGame.quietZoneStateData: return base.cr.playGame.quietZoneStateData + return None def addLeftQuietZoneCallback(self, callback, priority = None): @@ -82,22 +89,22 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): token = self._leftQuietZoneLocalCallbacks.add(callback, priority=priority) if not self._leftQuietZoneSubframeCall: self._leftQuietZoneSubframeCall = SubframeCall(self._doLeftQuietZoneCallbacks, taskMgr.getCurrentTask().getPriority() - 1) + return token def removeLeftQuietZoneCallback(self, token): if token is not None: if token in self._leftQuietZoneLocalCallbacks: self._leftQuietZoneLocalCallbacks.remove(token) + qzsd = self._getQZState() if qzsd: qzsd.removeLeftQuietZoneCallback(token) - return def _doLeftQuietZoneCallbacks(self): self._leftQuietZoneLocalCallbacks() self._leftQuietZoneLocalCallbacks.clear() self._leftQuietZoneSubframeCall = None - return def addSetZoneCompleteCallback(self, callback, priority = None): qzsd = self._getQZState() @@ -107,29 +114,30 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): token = self._setZoneCompleteLocalCallbacks.add(callback, priority=priority) if not self._setZoneCompleteSubframeCall: self._setZoneCompleteSubframeCall = SubframeCall(self._doSetZoneCompleteLocalCallbacks, taskMgr.getCurrentTask().getPriority() - 1) + return token def removeSetZoneCompleteCallback(self, token): if token is not None: if any(token == x[1] for x in self._setZoneCompleteLocalCallbacks._callbacks): self._setZoneCompleteLocalCallbacks.remove(token) + qzsd = self._getQZState() if qzsd: qzsd.removeSetZoneCompleteCallback(token) - return def _doSetZoneCompleteLocalCallbacks(self): self._setZoneCompleteSubframeCall = None localCallbacks = self._setZoneCompleteLocalCallbacks self._setZoneCompleteLocalCallbacks() localCallbacks.clear() - return def setState(self, state): if hasattr(self, 'fsm'): curState = self.fsm.getName() if state == 'pet' or curState == 'pet': self.preserveFriendsList() + self.fsm.request(state) def getState(self): @@ -148,10 +156,10 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): def handleTeleportQuery(self, fromAvatar, toAvatar): if base.config.GetBool('want-tptrack', False): - if toAvatar == localAvatar: + if toAvatar == base.localAvatar: toAvatar.doTeleportResponse(fromAvatar, toAvatar, toAvatar.doId, 1, toAvatar.defaultShard, base.cr.playGame.getPlaceId(), self.getZoneId(), fromAvatar.doId) else: - self.notify.warning('handleTeleportQuery toAvatar.doId != localAvatar.doId' % (toAvatar.doId, localAvatar.doId)) + self.notify.warning('handleTeleportQuery toAvatar.doId != localAvatar.doId' % (toAvatar.doId, base.localAvatar.doId)) else: fromAvatar.d_teleportResponse(toAvatar.doId, 1, toAvatar.defaultShard, base.cr.playGame.getPlaceId(), self.getZoneId()) @@ -159,6 +167,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): if self.isPeriodTimerEffective(): if base.cr.periodTimerExpired: taskMgr.doMethodLater(5, self.redoPeriodTimer, 'redoPeriodTimer') + self.accept('periodTimerExpired', self.periodTimerExpired) def disablePeriodTimer(self): @@ -167,7 +176,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): def redoPeriodTimer(self, task): messenger.send('periodTimerExpired') - return Task.done + return task.done def periodTimerExpired(self): self.fsm.request('final') @@ -209,10 +218,12 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): self.walkStateData.enter() if teleportIn == 0: self.walkStateData.fsm.request('walking') + self.acceptOnce(self.walkDoneEvent, self.handleWalkDone) if base.cr.productName in ['DisneyOnline-US', 'ES'] and not base.cr.isPaid() and base.localAvatar.tutorialAck: base.localAvatar.chatMgr.obscure(0, 0) base.localAvatar.chatMgr.normalButton.show() + self.accept('teleportQuery', self.handleTeleportQuery) base.localAvatar.setTeleportAvailable(1) base.localAvatar.questPage.acceptOnscreenHooks() @@ -225,6 +236,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): self.exitFLM() if base.cr.productName in ['DisneyOnline-US', 'ES'] and not base.cr.isPaid() and base.localAvatar.tutorialAck and not base.cr.whiteListChatEnabled: base.localAvatar.chatMgr.obscure(1, 0) + self.disablePeriodTimer() messenger.send('wakeup') self.walkStateData.exit() @@ -233,13 +245,13 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): self.ignore('teleportQuery') if base.cr.playGame.hood != None: base.cr.playGame.hood.hideTitleText() + base.localAvatar.questPage.hideQuestsOnscreen() base.localAvatar.questPage.ignoreOnscreenHooks() base.localAvatar.invPage.ignoreOnscreenHooks() base.localAvatar.invPage.hideInventoryOnscreen() base.localAvatar.questMap.hide() base.localAvatar.questMap.ignoreOnscreenHooks() - return def handleWalkDone(self, doneStatus): mode = doneStatus['mode'] @@ -308,10 +320,12 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): target = base.cr.doFind('DistributedTarget') if target: target.hideGui() + self.accept('teleportQuery', self.handleTeleportQuery) base.localAvatar.setTeleportAvailable(1) if page: base.localAvatar.book.setPage(page) + base.localAvatar.b_setAnimState('OpenBook', 1, self.enterStickerBookGUI) base.localAvatar.obscureMoveFurnitureButton(1) @@ -328,11 +342,12 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): def __handleFallingAsleep(self, task): base.localAvatar.book.exit() base.localAvatar.b_setAnimState('CloseBook', 1, callback=self.__handleFallingAsleepBookClose) - return Task.done + return task.done def __handleFallingAsleepBookClose(self): if hasattr(self, 'fsm'): self.fsm.request('walk') + base.localAvatar.forceGotoSleep() def exitStickerBook(self): @@ -377,10 +392,11 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): base.localAvatar.b_setAnimState('CloseBook', 1, callback=self.startPartyNow, extraArgs=[firstStart, hostId]) def handleBookCloseTeleport(self, hoodId, zoneId): - if localAvatar.hasActiveBoardingGroup(): + if base.localAvatar.hasActiveBoardingGroup(): rejectText = TTLocalizer.BoardingCannotLeaveZone - localAvatar.elevatorNotifier.showMe(rejectText) + base.localAvatar.elevatorNotifier.showMe(rejectText) return + self.requestLeave({'loader': ZoneUtil.getBranchLoaderName(zoneId), 'where': ZoneUtil.getToonWhereName(zoneId), 'how': 'teleportIn', @@ -388,7 +404,6 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): 'zoneId': zoneId, 'shardId': None, 'avId': -1}) - return def __handleBookCloseExit(self): base.localAvatar.b_setAnimState('TeleportOut', 1, self.__handleBookExitTeleport, [0]) @@ -396,14 +411,16 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): def __handleBookExitTeleport(self, requestStatus): if base.cr.timeManager: base.cr.timeManager.setDisconnectReason(ToontownGlobals.DisconnectBookExit) + base.transitions.fadeScreen(1.0) base.cr.gameFSM.request(self.exitTo) def goHomeNow(self, curZoneId): - if localAvatar.hasActiveBoardingGroup(): + if base.localAvatar.hasActiveBoardingGroup(): rejectText = TTLocalizer.BoardingCannotLeaveZone - localAvatar.elevatorNotifier.showMe(rejectText) + base.localAvatar.elevatorNotifier.showMe(rejectText) return + hoodId = ToontownGlobals.MyEstate self.requestLeave({'loader': 'safeZoneLoader', 'where': 'estate', @@ -412,13 +429,13 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): 'zoneId': -1, 'shardId': None, 'avId': -1}) - return def startPartyNow(self, firstStart, hostId): - if localAvatar.hasActiveBoardingGroup(): + if base.localAvatar.hasActiveBoardingGroup(): rejectText = TTLocalizer.BoardingCannotLeaveZone - localAvatar.elevatorNotifier.showMe(rejectText) + base.localAvatar.elevatorNotifier.showMe(rejectText) return + base.localAvatar.creatingNewPartyWithMagicWord = False base.localAvatar.aboutToPlanParty = False hoodId = ToontownGlobals.PartyHood @@ -436,6 +453,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): if shardId == base.localAvatar.defaultShard: shardId = None + base.cr.playGame.getPlace().requestLeave({'loader': 'safeZoneLoader', 'where': 'party', 'how': 'teleportIn', @@ -446,13 +464,13 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): else: if hostId is None: hostId = base.localAvatar.doId + base.cr.partyManager.sendAvatarToParty(hostId) - return - return def handleBookClose(self): if hasattr(self, 'fsm'): self.fsm.request('walk') + if hasattr(self, 'toonSubmerged') and self.toonSubmerged == 1: if hasattr(self, 'walkStateData'): self.walkStateData.fsm.request('swimming', [self.loader.swimSound]) @@ -469,26 +487,27 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): def enterDFA(self, requestStatus): teleportDebug(requestStatus, 'enterDFA(%s)' % (requestStatus,)) self.acceptOnce(self.dfaDoneEvent, self.enterDFACallback, [requestStatus]) - self.dfa = DownloadForceAcknowledge.DownloadForceAcknowledge(self.dfaDoneEvent) + self.dfa = DownloadForceAcknowledge(self.dfaDoneEvent) self.dfa.enter(base.cr.hoodMgr.getPhaseFromHood(requestStatus['hoodId'])) def exitDFA(self): self.ignore(self.dfaDoneEvent) def handleEnterTunnel(self, requestStatus, collEntry): - if localAvatar.hasActiveBoardingGroup(): + if base.localAvatar.hasActiveBoardingGroup(): rejectText = TTLocalizer.BoardingCannotLeaveZone - localAvatar.elevatorNotifier.showMe(rejectText) + base.localAvatar.elevatorNotifier.showMe(rejectText) dummyNP = NodePath('dummyNP') - dummyNP.reparentTo(render) + dummyNP.reparentTo(base.render) tunnelOrigin = requestStatus['tunnelOrigin'] - dummyNP.setPos(localAvatar.getPos()) + dummyNP.setPos(base.localAvatar.getPos()) dummyNP.setH(tunnelOrigin.getH()) dummyNP.setPos(dummyNP, 0, 4, 0) - localAvatar.setPos(dummyNP.getPos()) + base.localAvatar.setPos(dummyNP.getPos()) dummyNP.removeNode() del dummyNP return + self.requestLeave(requestStatus) def enterDFACallback(self, requestStatus, doneStatus): @@ -504,6 +523,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): out = {'teleportIn': 'teleportOut', 'tunnelIn': 'tunnelOut', 'doorIn': 'doorOut'} + teleportDebug(requestStatus, 'requesting %s, requestStatus=%s' % (out[requestStatus['how']], requestStatus)) self.fsm.request(out[requestStatus['how']], [requestStatus]) elif doneStatus['mode'] == 'incomplete': @@ -520,7 +540,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): def enterTrialerFA(self, requestStatus): teleportDebug(requestStatus, 'enterTrialerFA(%s)' % requestStatus) self.acceptOnce(self.trialerFADoneEvent, self.trialerFACallback, [requestStatus]) - self.trialerFA = TrialerForceAcknowledge.TrialerForceAcknowledge(self.trialerFADoneEvent) + self.trialerFA = TrialerForceAcknowledge(self.trialerFADoneEvent) self.trialerFA.enter(requestStatus['hoodId']) def exitTrialerFA(self): @@ -589,6 +609,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): tunnelName = requestStatus.get('tunnelName') if tunnelName == None: tunnelName = base.cr.hoodMgr.makeLinkTunnelName(self.loader.hood.id, fromZoneId) + self.doneStatus = {'loader': ZoneUtil.getLoaderName(zoneId), 'where': ZoneUtil.getToonWhereName(zoneId), 'how': how, @@ -599,7 +620,6 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): self.accept('tunnelOutMovieDone', self.__tunnelOutMovieDone) base.localAvatar.tunnelOut(tunnelOrigin) base.localAvatar.stopQuestMap() - return def __tunnelOutMovieDone(self): self.ignore('tunnelOutMovieDone') @@ -621,11 +641,11 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): def enterDied(self, requestStatus, callback = None): if callback == None: callback = self.__diedDone + base.localAvatar.laffMeter.start() - camera.wrtReparentTo(render) + base.camera.wrtReparentTo(base.render) base.localAvatar.b_setAnimState('Died', 1, callback, [requestStatus]) base.localAvatar.obscureMoveFurnitureButton(1) - return def __diedDone(self, requestStatus): self.doneStatus = requestStatus @@ -643,6 +663,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): base.cr.estateMgr.getLocalEstateZone(avId) else: base.cr.estateMgr.getLocalEstateZone(base.localAvatar.getDoId()) + if HouseGlobals.WANT_TELEPORT_TIMEOUT: taskMgr.doMethodLater(HouseGlobals.TELEPORT_TIMEOUT, self.goHomeFailed, 'goHomeFailed') @@ -653,6 +674,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): self.doneStatus['failed'] = 1 self.goHomeFailed(None) return + if ownerId == 0 and zoneId == 0: if self.doneStatus['shardId'] is None or self.doneStatus['shardId'] is base.localAvatar.defaultShard: self.doneStatus['failed'] = 1 @@ -666,14 +688,15 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): self.doneStatus['how'] = 'teleportIn' messenger.send(self.doneEvent) return + if self.doneStatus['zoneId'] == -1: self.doneStatus['zoneId'] = zoneId elif self.doneStatus['zoneId'] != zoneId: self.doneStatus['where'] = 'house' + self.doneStatus['ownerId'] = ownerId messenger.send(self.doneEvent) messenger.send('localToonLeft') - return def goHomeFailed(self, task): self.notify.debug('goHomeFailed') @@ -682,7 +705,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): self.doneStatus['hood'] = base.localAvatar.lastHood self.doneStatus['zone'] = base.localAvatar.lastHood self.fsm.request('teleportIn', [self.doneStatus]) - return Task.done + return task.done def notifyUserGoHomeFailed(self): self.notify.debug('notifyUserGoHomeFailed') @@ -692,12 +715,13 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): avatar = base.cr.identifyAvatar(failedToVisitAvId) if avatar: avName = avatar.getName() + if avName: message = TTLocalizer.EstateTeleportFailedNotFriends % avName else: message = TTLocalizer.EstateTeleportFailed + base.localAvatar.setSystemMessage(0, message) - return def enterTeleportIn(self, requestStatus): self._tiToken = self.addSetZoneCompleteCallback(Functor(self._placeTeleportInPostZoneComplete, requestStatus), 100) @@ -723,16 +747,16 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): teleportDebug(requestStatus, 'friend not here, giving up') base.localAvatar.setSystemMessage(avId, OTPLocalizer.WhisperTargetLeftVisit % (friend.getName(),)) friend.d_teleportGiveup(base.localAvatar.doId) + base.transitions.irisIn() self.nextState = requestStatus.get('nextState', 'walk') base.localAvatar.attachCamera() base.localAvatar.startUpdateSmartCamera() base.localAvatar.startPosHprBroadcast() - globalClock.tick() + base.clock.tick() base.localAvatar.b_setAnimState('TeleportIn', 1, callback=self.teleportInDone) base.localAvatar.d_broadcastPositionNow() base.localAvatar.b_setParent(ToontownGlobals.SPRender) - return def teleportInDone(self): if hasattr(self, 'fsm'): @@ -748,7 +772,6 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): base.localAvatar.stopUpdateSmartCamera() base.localAvatar.detachCamera() base.localAvatar.stopPosHprBroadcast() - return def requestTeleport(self, hoodId, zoneId, shardId, avId): if avId > 0: @@ -756,20 +779,25 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): zoneId, shardId, avId),)) - if localAvatar.hasActiveBoardingGroup(): + + if base.localAvatar.hasActiveBoardingGroup(): if avId > 0: teleportNotify.debug('requestTeleport: has active boarding group') + rejectText = TTLocalizer.BoardingCannotLeaveZone - localAvatar.elevatorNotifier.showMe(rejectText) + base.localAvatar.elevatorNotifier.showMe(rejectText) return + loaderId = ZoneUtil.getBranchLoaderName(zoneId) whereId = ZoneUtil.getToonWhereName(zoneId) if hoodId == ToontownGlobals.MyEstate: loaderId = 'safeZoneLoader' whereId = 'estate' + if hoodId == ToontownGlobals.PartyHood: loaderId = 'safeZoneLoader' whereId = 'party' + self.requestLeave({'loader': loaderId, 'where': whereId, 'how': 'teleportIn', @@ -828,6 +856,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): if hasattr(self, 'fsm'): messenger.send('bankAsleep') self.fsm.request('walk') + base.localAvatar.forceGotoSleep() def exitBanking(self): @@ -850,6 +879,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): def __handleFallingAsleepPhone(self, arg): if hasattr(self, 'fsm'): self.fsm.request('walk') + messenger.send('phoneAsleep') base.localAvatar.forceGotoSleep() @@ -863,12 +893,13 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): def enterStopped(self): base.localAvatar.b_setAnimState('neutral', 1) - Emote.globalEmote.disableBody(base.localAvatar, 'enterStopped') + globalEmote.disableBody(base.localAvatar, 'enterStopped') self.accept('teleportQuery', self.handleTeleportQuery) if base.localAvatar.isDisguised: base.localAvatar.setTeleportAvailable(0) else: base.localAvatar.setTeleportAvailable(1) + base.localAvatar.laffMeter.start() base.localAvatar.obscureMoveFurnitureButton(1) base.localAvatar.startSleepWatch(self.__handleFallingAsleepStopped) @@ -877,11 +908,12 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): def __handleFallingAsleepStopped(self, arg): if hasattr(self, 'fsm'): self.fsm.request('walk') + base.localAvatar.forceGotoSleep() messenger.send('stoppedAsleep') def exitStopped(self): - Emote.globalEmote.releaseBody(base.localAvatar, 'exitStopped') + globalEmote.releaseBody(base.localAvatar, 'exitStopped') base.localAvatar.setTeleportAvailable(0) self.ignore('teleportQuery') base.localAvatar.laffMeter.stop() @@ -892,7 +924,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): def enterPet(self): base.localAvatar.b_setAnimState('neutral', 1) - Emote.globalEmote.disableBody(base.localAvatar, 'enterPet') + globalEmote.disableBody(base.localAvatar, 'enterPet') self.accept('teleportQuery', self.handleTeleportQuery) base.localAvatar.setTeleportAvailable(1) base.localAvatar.setTeleportAllowed(0) @@ -902,7 +934,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): def exitPet(self): base.localAvatar.setTeleportAvailable(0) base.localAvatar.setTeleportAllowed(1) - Emote.globalEmote.releaseBody(base.localAvatar, 'exitPet') + globalEmote.releaseBody(base.localAvatar, 'exitPet') self.ignore('teleportQuery') base.localAvatar.laffMeter.stop() self.exitFLM() @@ -910,7 +942,7 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): def enterQuietZone(self, requestStatus): self.quietZoneDoneEvent = uniqueName('quietZoneDone') self.acceptOnce(self.quietZoneDoneEvent, self.handleQuietZoneDone) - self.quietZoneStateData = QuietZoneState.QuietZoneState(self.quietZoneDoneEvent) + self.quietZoneStateData = QuietZoneState(self.quietZoneDoneEvent) self.quietZoneStateData.load() self.quietZoneStateData.enter(requestStatus) @@ -920,7 +952,6 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): self.quietZoneStateData.exit() self.quietZoneStateData.unload() self.quietZoneStateData = None - return def handleQuietZoneDone(self): how = base.cr.handlerArgs['how'] diff --git a/toontown/safezone/Playground.py b/toontown/safezone/Playground.py index 2a7a18e..5484176 100644 --- a/toontown/safezone/Playground.py +++ b/toontown/safezone/Playground.py @@ -1,41 +1,45 @@ -from direct.interval.IntervalGlobal import * -from panda3d.core import * -from toontown.toonbase.ToonBaseGlobal import * -from direct.directnotify import DirectNotifyGlobal -from toontown.hood import Place -from direct.showbase import DirectObject -from direct.fsm import StateData -from direct.fsm import ClassicFSM, State -from direct.fsm import State -from direct.task import Task -from toontown.toon import DeathForceAcknowledge -from toontown.toon import HealthForceAcknowledge -from toontown.tutorial import TutorialForceAcknowledge -from toontown.toon import NPCForceAcknowledge -from toontown.trolley import Trolley -from toontown.toontowngui import TTDialog -from toontown.toonbase import ToontownGlobals -from toontown.toon.Toon import teleportDebug -from toontown.toonbase import TTLocalizer -from direct.gui import DirectLabel -from otp.distributed.TelemetryLimiter import RotationLimitToH, TLGatherAllAvs -from toontown.quest import Quests +from panda3d.core import LineSegs, NodePath, TextNode, Vec4 +from panda3d.otp import NametagGlobals -class Playground(Place.Place): - notify = DirectNotifyGlobal.directNotify.newCategory('Playground') +from direct.directnotify.DirectNotifyGlobal import directNotify +from direct.fsm.ClassicFSM import ClassicFSM +from direct.fsm.State import State +from direct.gui.DirectLabel import DirectLabel +from direct.interval.IntervalGlobal import Func, LerpColorScaleInterval, Sequence +from direct.showbase.MessengerGlobal import messenger + +from otp.distributed.TelemetryLimiter import RotationLimitToH, TLGatherAllAvs + +from toontown.classicchars import CCharPaths +from toontown.hood.Place import Place +from toontown.quest import Quests +from toontown.toon.DeathForceAcknowledge import DeathForceAcknowledge +from toontown.toon.HealthForceAcknowledge import HealthForceAcknowledge +from toontown.toon.NPCForceAcknowledge import NPCForceAcknowledge +from toontown.toon.Toon import teleportDebug +from toontown.toonbase import ToontownGlobals +from toontown.toonbase import TTLocalizer +from toontown.toonbase.ToonBaseGlobal import base +from toontown.toontowngui import TTDialog +from toontown.trolley.Trolley import Trolley +from toontown.tutorial.TutorialForceAcknowledge import TutorialForceAcknowledge + + +class Playground(Place): + notify = directNotify.newCategory('Playground') def __init__(self, loader, parentFSM, doneEvent): - Place.Place.__init__(self, loader, doneEvent) + Place.__init__(self, loader, doneEvent) self.tfaDoneEvent = 'tfaDoneEvent' - self.fsm = ClassicFSM.ClassicFSM('Playground', [ - State.State('start', + self.fsm = ClassicFSM('Playground', [ + State('start', self.enterStart, self.exitStart, [ 'walk', 'deathAck', 'doorIn', 'tunnelIn']), - State.State('walk', + State('walk', self.enterWalk, self.exitWalk, [ 'drive', @@ -52,7 +56,7 @@ class Playground(Place.Place): 'purchase', 'stopped', 'fishing']), - State.State('stickerBook', + State('stickerBook', self.enterStickerBook, self.exitStickerBook, [ 'walk', @@ -66,124 +70,124 @@ class Playground(Place.Place): 'stopped', 'fishing', 'trialerFA']), - State.State('sit', + State('sit', self.enterSit, self.exitSit, [ 'walk', 'DFA', 'trialerFA']), - State.State('drive', + State('drive', self.enterDrive, self.exitDrive, [ 'walk', 'DFA', 'trialerFA']), - State.State('trolley', + State('trolley', self.enterTrolley, self.exitTrolley, [ 'walk']), - State.State('doorIn', + State('doorIn', self.enterDoorIn, self.exitDoorIn, [ 'walk']), - State.State('doorOut', + State('doorOut', self.enterDoorOut, self.exitDoorOut, [ 'walk']), - State.State('TFA', + State('TFA', self.enterTFA, self.exitTFA, [ 'TFAReject', 'DFA']), - State.State('TFAReject', + State('TFAReject', self.enterTFAReject, self.exitTFAReject, [ 'walk']), - State.State('trialerFA', + State('trialerFA', self.enterTrialerFA, self.exitTrialerFA, [ 'trialerFAReject', 'DFA']), - State.State('trialerFAReject', + State('trialerFAReject', self.enterTrialerFAReject, self.exitTrialerFAReject, [ 'walk']), - State.State('DFA', + State('DFA', self.enterDFA, self.exitDFA, [ 'DFAReject', 'NPCFA', 'HFA']), - State.State('DFAReject', + State('DFAReject', self.enterDFAReject, self.exitDFAReject, [ 'walk']), - State.State('NPCFA', + State('NPCFA', self.enterNPCFA, self.exitNPCFA, [ 'NPCFAReject', 'HFA']), - State.State('NPCFAReject', + State('NPCFAReject', self.enterNPCFAReject, self.exitNPCFAReject, [ 'walk']), - State.State('HFA', + State('HFA', self.enterHFA, self.exitHFA, [ 'HFAReject', 'teleportOut', 'tunnelOut']), - State.State('HFAReject', + State('HFAReject', self.enterHFAReject, self.exitHFAReject, [ 'walk']), - State.State('deathAck', + State('deathAck', self.enterDeathAck, self.exitDeathAck, [ 'teleportIn']), - State.State('teleportIn', + State('teleportIn', self.enterTeleportIn, self.exitTeleportIn, [ 'walk', 'popup']), - State.State('popup', + State('popup', self.enterPopup, self.exitPopup, [ 'walk']), - State.State('teleportOut', + State('teleportOut', self.enterTeleportOut, self.exitTeleportOut, [ 'deathAck', 'teleportIn']), - State.State('died', + State('died', self.enterDied, self.exitDied, [ 'final']), - State.State('tunnelIn', + State('tunnelIn', self.enterTunnelIn, self.exitTunnelIn, [ 'walk']), - State.State('tunnelOut', + State('tunnelOut', self.enterTunnelOut, self.exitTunnelOut, [ 'final']), - State.State('quest', + State('quest', self.enterQuest, self.exitQuest, [ 'walk']), - State.State('purchase', + State('purchase', self.enterPurchase, self.exitPurchase, [ 'walk']), - State.State('stopped', + State('stopped', self.enterStopped, self.exitStopped, [ 'walk']), - State.State('fishing', + State('fishing', self.enterFishing, self.exitFishing, [ 'walk']), - State.State('final', + State('final', self.enterFinal, self.exitFinal, [ 'start'])], @@ -195,7 +199,6 @@ class Playground(Place.Place): self.npcfaDoneEvent = 'npcfaDoneEvent' self.dialog = None self.deathAckBox = None - return def enter(self, requestStatus): self.fsm.enterInitialState() @@ -203,7 +206,7 @@ class Playground(Place.Place): self.accept('doorDoneEvent', self.handleDoorDoneEvent) self.accept('DistributedDoor_doorTrigger', self.handleDoorTrigger) base.playMusic(self.loader.music, looping=1, volume=0.8) - self.loader.geom.reparentTo(render) + self.loader.geom.reparentTo(base.render) for i in self.loader.nodeList: self.loader.enterAnimatedProps(i) @@ -231,12 +234,14 @@ class Playground(Place.Place): self.loader.hood.startSky() lightsOn = LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, 0.1, Vec4(1, 1, 1, 1)) lightsOn.start() + NametagGlobals.setMasterArrowsOn(1) self.zoneId = requestStatus['zoneId'] self.tunnelOriginList = base.cr.hoodMgr.addLinkTunnelHooks(self, self.loader.nodeList, self.zoneId) how = requestStatus['how'] if how == 'teleportIn': how = 'deathAck' + self.fsm.request(how, [requestStatus]) def exit(self): @@ -248,13 +253,12 @@ class Playground(Place.Place): node.removeNode() del self.tunnelOriginList - self.loader.geom.reparentTo(hidden) + self.loader.geom.reparentTo(base.hidden) def __lightDecorationOff__(): for light in self.loader.hood.halloweenLights: - light.reparentTo(hidden) + light.reparentTo(base.hidden) - newsManager = base.cr.newsManager NametagGlobals.setMasterArrowsOn(0) for i in self.loader.nodeList: self.loader.exitAnimatedProps(i) @@ -263,7 +267,7 @@ class Playground(Place.Place): self.loader.music.stop() def load(self): - Place.Place.load(self) + Place.load(self) self.parentFSM.getStateNamed('playground').addChild(self.fsm) def unload(self): @@ -273,13 +277,14 @@ class Playground(Place.Place): if self.dialog: self.dialog.cleanup() self.dialog = None + if self.deathAckBox: self.deathAckBox.cleanup() self.deathAckBox = None + TTDialog.cleanupDialog('globalDialog') self.ignoreAll() - Place.Place.unload(self) - return + Place.unload(self) def showTreasurePoints(self, points): self.hideDebugPointText() @@ -303,7 +308,6 @@ class Playground(Place.Place): self.hideDebugPointText() lines = LineSegs() lines.setColor(1, 0, 0, 1) - from toontown.classicchars import CCharPaths for name, pointDef in list(paths.items()): self.showDebugPointText(name, pointDef[0]) for connectTo in pointDef[1]: @@ -333,6 +337,7 @@ class Playground(Place.Place): self.debugTextNode.setTextColor(1, 0, 0, 1) self.debugTextNode.setAlign(TextNode.ACenter) self.debugTextNode.setFont(ToontownGlobals.getSignFont()) + self.debugTextNode.setText(text) np = self.debugText.attachNewNode(self.debugTextNode.generate()) np.setPos(point[0], point[1], point[2]) @@ -344,7 +349,7 @@ class Playground(Place.Place): base.localAvatar.b_setAnimState('off', 1) base.localAvatar.cantLeaveGame = 1 self.accept(self.trolleyDoneEvent, self.handleTrolleyDone) - self.trolley = Trolley.Trolley(self, self.fsm, self.trolleyDoneEvent) + self.trolley = Trolley(self, self.fsm, self.trolleyDoneEvent) self.trolley.load() self.trolley.enter() @@ -376,7 +381,6 @@ class Playground(Place.Place): messenger.send(self.doneEvent) else: self.notify.error('Unknown mode: ' + mode + ' in handleTrolleyDone') - return def debugStartMinigame(self, zoneId, minigameId): self.doneStatus = {'loader': 'minigame', @@ -386,7 +390,6 @@ class Playground(Place.Place): 'shardId': None, 'minigameId': minigameId} messenger.send(self.doneEvent) - return def enterTFACallback(self, requestStatus, doneStatus): self.tfa.exit() @@ -412,7 +415,7 @@ class Playground(Place.Place): def enterHFA(self, requestStatus): self.acceptOnce(self.hfaDoneEvent, self.enterHFACallback, [requestStatus]) - self.hfa = HealthForceAcknowledge.HealthForceAcknowledge(self.hfaDoneEvent) + self.hfa = HealthForceAcknowledge(self.hfaDoneEvent) self.hfa.enter(1) def exitHFA(self): @@ -428,6 +431,7 @@ class Playground(Place.Place): outHow = {'teleportIn': 'teleportOut', 'tunnelIn': 'tunnelOut', 'doorIn': 'doorOut'} + self.fsm.request(outHow[requestStatus['how']], [requestStatus]) elif doneStatus['mode'] == 'incomplete': self.fsm.request('HFAReject') @@ -442,7 +446,7 @@ class Playground(Place.Place): def enterNPCFA(self, requestStatus): self.acceptOnce(self.npcfaDoneEvent, self.enterNPCFACallback, [requestStatus]) - self.npcfa = NPCForceAcknowledge.NPCForceAcknowledge(self.npcfaDoneEvent) + self.npcfa = NPCForceAcknowledge(self.npcfaDoneEvent) self.npcfa.enter() def exitNPCFA(self): @@ -469,20 +473,18 @@ class Playground(Place.Place): self.ignore('deathAck') self.deathAckBox.cleanup() self.deathAckBox = None - Place.Place.enterWalk(self, teleportIn) - return + + Place.enterWalk(self, teleportIn) def enterDeathAck(self, requestStatus): self.deathAckBox = None self.fsm.request('teleportIn', [requestStatus]) - return def exitDeathAck(self): if self.deathAckBox: self.ignore('deathAck') self.deathAckBox.cleanup() self.deathAckBox = None - return def enterTeleportIn(self, requestStatus): imgScale = 0.25 @@ -492,10 +494,10 @@ class Playground(Place.Place): requestStatus['nextState'] = 'popup' x, y, z, h, p, r = base.cr.hoodMgr.getPlaygroundCenterFromId(self.loader.hood.id) self.accept('deathAck', self.__handleDeathAck, extraArgs=[requestStatus]) - self.deathAckBox = DeathForceAcknowledge.DeathForceAcknowledge(doneEvent='deathAck') + self.deathAckBox = DeathForceAcknowledge(doneEvent='deathAck') elif base.localAvatar.hp > 0 and (Quests.avatarHasTrolleyQuest(base.localAvatar) or Quests.avatarHasFirstCogQuest(base.localAvatar) or Quests.avatarHasFriendQuest(base.localAvatar) or Quests.avatarHasPhoneQuest(base.localAvatar) and Quests.avatarHasCompletedPhoneQuest(base.localAvatar)) and self.loader.hood.id == ToontownGlobals.ToontownCentral: requestStatus['nextState'] = 'popup' - imageModel = loader.loadModel('phase_4/models/gui/tfa_images') + imageModel = base.loader.loadModel('phase_4/models/gui/tfa_images') if base.localAvatar.quests[0][0] == Quests.TROLLEY_QUEST_ID: if not Quests.avatarHasCompletedTrolleyQuest(base.localAvatar): x, y, z, h, p, r = base.cr.hoodMgr.getDropPoint(base.cr.hoodMgr.ToontownCentralInitialDropPoints) @@ -526,7 +528,7 @@ class Playground(Place.Place): if not Quests.avatarHasCompletedFriendQuest(base.localAvatar): x, y, z, h, p, r = base.cr.hoodMgr.getDropPoint(base.cr.hoodMgr.ToontownCentralInitialDropPoints) msg = TTLocalizer.NPCForceAcknowledgeMessage7 - gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui') + gui = base.loader.loadModel('phase_3.5/models/gui/friendslist_gui') imgNodePath = gui.find('**/FriendsBox_Closed') imgPos = (0, 0, 0.04) imgScale = 1.0 @@ -544,38 +546,40 @@ class Playground(Place.Place): imgNodePath = imageModel.find('**/hq-dialog-image') imgPos = (0, 0, 0.05) imgScale = 0.5 + self.dialog = TTDialog.TTDialog(text=msg, command=self.__cleanupDialog, style=TTDialog.Acknowledge) - imgLabel = DirectLabel.DirectLabel(parent=self.dialog, relief=None, pos=imgPos, scale=TTLocalizer.PimgLabel, image=imgNodePath, image_scale=imgScale) + imgLabel = DirectLabel(parent=self.dialog, relief=None, pos=imgPos, scale=TTLocalizer.PimgLabel, image=imgNodePath, image_scale=imgScale) imageModel.removeNode() else: requestStatus['nextState'] = 'walk' x, y, z, h, p, r = base.cr.hoodMgr.getPlaygroundCenterFromId(self.loader.hood.id) + base.localAvatar.detachNode() - base.localAvatar.setPosHpr(render, x, y, z, h, p, r) - Place.Place.enterTeleportIn(self, requestStatus) - return + base.localAvatar.setPosHpr(base.render, x, y, z, h, p, r) + Place.enterTeleportIn(self, requestStatus) def __cleanupDialog(self, value): if self.dialog: self.dialog.cleanup() self.dialog = None + if hasattr(self, 'fsm'): self.fsm.request('walk', [1]) - return def __handleDeathAck(self, requestStatus): if self.deathAckBox: self.ignore('deathAck') self.deathAckBox.cleanup() self.deathAckBox = None + self.fsm.request('walk', [1]) - return def enterPopup(self, teleportIn = 0): if base.localAvatar.hp < 1: base.localAvatar.b_setAnimState('Sad', 1) else: base.localAvatar.b_setAnimState('neutral', 1.0) + self.accept('teleportQuery', self.handleTeleportQuery) base.localAvatar.setTeleportAvailable(1) base.localAvatar.startSleepWatch(self.__handleFallingAsleepPopup) @@ -589,18 +593,19 @@ class Playground(Place.Place): if hasattr(self, 'fsm'): self.fsm.request('walk') base.localAvatar.forceGotoSleep() - return Task.done + + return task.done def enterTeleportOut(self, requestStatus): - Place.Place.enterTeleportOut(self, requestStatus, self.__teleportOutDone) + Place.enterTeleportOut(self, requestStatus, self.__teleportOutDone) def __teleportOutDone(self, requestStatus): teleportDebug(requestStatus, 'Playground.__teleportOutDone(%s)' % (requestStatus,)) if hasattr(self, 'activityFsm'): self.activityFsm.requestFinalState() + hoodId = requestStatus['hoodId'] zoneId = requestStatus['zoneId'] - avId = requestStatus['avId'] shardId = requestStatus['shardId'] if hoodId == self.loader.hood.hoodId and zoneId == self.loader.hood.hoodId and shardId == None: teleportDebug(requestStatus, 'same playground') @@ -612,19 +617,19 @@ class Playground(Place.Place): teleportDebug(requestStatus, 'different hood/zone') self.doneStatus = requestStatus messenger.send(self.doneEvent) - return def exitTeleportOut(self): - Place.Place.exitTeleportOut(self) + Place.exitTeleportOut(self) def createPlayground(self, dnaFile): - loader.loadDNAFile(self.loader.dnaStore, self.safeZoneStorageDNAFile) - node = loader.loadDNAFile(self.loader.dnaStore, dnaFile) + base.loader.loadDNAFile(self.loader.dnaStore, self.safeZoneStorageDNAFile) + node = base.loader.loadDNAFile(self.loader.dnaStore, dnaFile) if node.getNumParents() == 1: self.geom = NodePath(node.getParent(0)) - self.geom.reparentTo(hidden) + self.geom.reparentTo(base.hidden) else: - self.geom = hidden.attachNewNode(node) + self.geom = base.hidden.attachNewNode(node) + self.makeDictionaries(self.loader.dnaStore) self.tunnelOriginList = base.cr.hoodMgr.addLinkTunnelHooks(self, self.nodeList, self.zoneId) self.geom.flattenMedium() @@ -636,10 +641,10 @@ class Playground(Place.Place): self.nodeList = [] for i in range(dnaStore.getNumDNAVisGroups()): groupFullName = dnaStore.getDNAVisGroupName(i) - groupName = base.cr.hoodMgr.extractGroupName(groupFullName) groupNode = self.geom.find('**/' + groupFullName) if groupNode.isEmpty(): self.notify.error('Could not find visgroup') + self.nodeList.append(groupNode) self.removeLandmarkBlockNodes() @@ -655,7 +660,7 @@ class Playground(Place.Place): def enterTFA(self, requestStatus): self.acceptOnce(self.tfaDoneEvent, self.enterTFACallback, [requestStatus]) - self.tfa = TutorialForceAcknowledge.TutorialForceAcknowledge(self.tfaDoneEvent) + self.tfa = TutorialForceAcknowledge(self.tfaDoneEvent) self.tfa.enter() def exitTFA(self): From 72c6316f6ef14c3b2450feb21b961a757543135c Mon Sep 17 00:00:00 2001 From: Open Toontown <57279094+opentoontown@users.noreply.github.com> Date: Sat, 29 Apr 2023 00:23:47 -0400 Subject: [PATCH 12/48] fix more crashes --- toontown/building/DistributedHQInterior.py | 63 ++++++++++++---------- toontown/minigame/ToonBlitzAssetMgr.py | 54 ++++++++++--------- toontown/minigame/TwoDBattleMgr.py | 55 +++++++++++++------ toontown/racing/DistributedLeaderBoard.py | 43 +++++++-------- 4 files changed, 123 insertions(+), 92 deletions(-) diff --git a/toontown/building/DistributedHQInterior.py b/toontown/building/DistributedHQInterior.py index 7cf0e7f..466e797 100644 --- a/toontown/building/DistributedHQInterior.py +++ b/toontown/building/DistributedHQInterior.py @@ -1,19 +1,24 @@ -from toontown.toonbase.ToonBaseGlobal import * -from panda3d.core import * -from panda3d.toontown import * -from toontown.toonbase.ToontownGlobals import * -import random -from direct.task.Task import Task -from direct.distributed import DistributedObject -from direct.directnotify import DirectNotifyGlobal -from . import ToonInteriorColors -import pickle -from toontown.toonbase import TTLocalizer +from panda3d.core import ModelNode, NodePath, TextNode +from panda3d.toontown import DNADoor -class DistributedHQInterior(DistributedObject.DistributedObject): +from direct.directnotify.DirectNotifyGlobal import directNotify +from direct.distributed.DistributedObject import DistributedObject +from direct.task.TaskManagerGlobal import taskMgr + +from toontown.building import ToonInteriorColors +from toontown.toonbase import ToontownGlobals +from toontown.toonbase import TTLocalizer +from toontown.toonbase.ToonBaseGlobal import base + +import pickle +from random import Random + + +class DistributedHQInterior(DistributedObject): + notify = directNotify.newCategory('DistributedHQInterior') def __init__(self, cr): - DistributedObject.DistributedObject.__init__(self, cr) + DistributedObject.__init__(self, cr) self.dnaStore = cr.playGame.dnaStore self.leaderAvIds = [] self.leaderNames = [] @@ -22,15 +27,15 @@ class DistributedHQInterior(DistributedObject.DistributedObject): self.tutorial = 0 def generate(self): - DistributedObject.DistributedObject.generate(self) - self.interior = loader.loadModel('phase_3.5/models/modules/HQ_interior') - self.interior.reparentTo(render) + DistributedObject.generate(self) + self.interior = base.loader.loadModel('phase_3.5/models/modules/HQ_interior') + self.interior.reparentTo(base.render) self.interior.find('**/cream').hide() self.interior.find('**/crashed_piano').hide() self.buildLeaderBoard() def announceGenerate(self): - DistributedObject.DistributedObject.announceGenerate(self) + DistributedObject.announceGenerate(self) self.setupDoors() self.interior.flattenMedium() emptyBoard = self.interior.find('**/empty_board') @@ -41,6 +46,7 @@ class DistributedHQInterior(DistributedObject.DistributedObject): return else: self.tutorial = flag + if self.tutorial: self.interior.find('**/periscope').hide() self.interior.find('**/speakers').hide() @@ -53,7 +59,7 @@ class DistributedHQInterior(DistributedObject.DistributedObject): self.block = block def buildLeaderBoard(self): - self.leaderBoard = hidden.attachNewNode('leaderBoard') + self.leaderBoard = base.hidden.attachNewNode('leaderBoard') self.leaderBoard.setPosHprScale(0.1, 0, 4.5, 90, 0, 0, 0.9, 0.9, 0.9) z = 0 row = self.buildTitleRow() @@ -63,7 +69,7 @@ class DistributedHQInterior(DistributedObject.DistributedObject): self.nameTextNodes = [] self.scoreTextNodes = [] self.trophyStars = [] - for i in range(self.numLeaders): + for _ in range(self.numLeaders): row, nameText, scoreText, trophyStar = self.buildLeaderRow() self.nameTextNodes.append(nameText) self.scoreTextNodes.append(scoreText) @@ -87,7 +93,7 @@ class DistributedHQInterior(DistributedObject.DistributedObject): self.trophyStars[i].hide() def buildTitleRow(self): - row = hidden.attachNewNode('leaderRow') + row = base.hidden.attachNewNode('leaderRow') nameText = TextNode('titleRow') nameText.setFont(ToontownGlobals.getSignFont()) nameText.setAlign(TextNode.ACenter) @@ -98,7 +104,7 @@ class DistributedHQInterior(DistributedObject.DistributedObject): return row def buildLeaderRow(self): - row = hidden.attachNewNode('leaderRow') + row = base.hidden.attachNewNode('leaderRow') nameText = TextNode('nameText') nameText.setFont(ToontownGlobals.getToonFont()) nameText.setAlign(TextNode.ALeft) @@ -135,15 +141,16 @@ class DistributedHQInterior(DistributedObject.DistributedObject): doorModelName = doorModelName[:-1] + 'l' else: doorModelName = doorModelName[:-1] + 'r' + door = self.dnaStore.findNode(doorModelName) return door def setupDoors(self): - self.randomGenerator = random.Random() + self.randomGenerator = Random() self.randomGenerator.seed(self.zoneId) - self.colors = ToonInteriorColors.colors[ToontownCentral] + self.colors = ToonInteriorColors.colors[ToontownGlobals.ToontownCentral] door = self.chooseDoor() - doorOrigins = render.findAllMatches('**/door_origin*') + doorOrigins = base.render.findAllMatches('**/door_origin*') numDoorOrigins = doorOrigins.getNumPaths() for npIndex in range(numDoorOrigins): doorOrigin = doorOrigins[npIndex] @@ -173,10 +180,10 @@ class DistributedHQInterior(DistributedObject.DistributedObject): del self.scoreTextNodes del self.trophyStars taskMgr.remove(self.uniqueName('starSpinHQ')) - DistributedObject.DistributedObject.disable(self) + DistributedObject.disable(self) def buildTrophyStar(self): - trophyStar = loader.loadModel('phase_3.5/models/gui/name_star') + trophyStar = base.loader.loadModel('phase_3.5/models/gui/name_star') trophyStar.hide() trophyStar.setPos(*TTLocalizer.DHQItrophyStarPos) return trophyStar @@ -211,7 +218,7 @@ class DistributedHQInterior(DistributedObject.DistributedObject): trophyStar.hide() def __starSpin(self, task): - now = globalClock.getFrameTime() + now = base.clock.getFrameTime() r = now * task.trophyStarSpeed % 360.0 task.trophyStar.setR(r) - return Task.cont + return task.cont diff --git a/toontown/minigame/ToonBlitzAssetMgr.py b/toontown/minigame/ToonBlitzAssetMgr.py index ea4cfd0..aecf8c0 100644 --- a/toontown/minigame/ToonBlitzAssetMgr.py +++ b/toontown/minigame/ToonBlitzAssetMgr.py @@ -1,12 +1,15 @@ -from panda3d.core import * +from panda3d.core import CardMaker, CollisionNode, CollisionPlane, NodePath, Plane, Point3, Vec3 + +from direct.directnotify.DirectNotifyGlobal import directNotify from direct.showbase.DirectObject import DirectObject -from toontown.toonbase.ToonBaseGlobal import * -from direct.directnotify import DirectNotifyGlobal -from toontown.minigame import ToonBlitzGlobals, TwoDBlock -from panda3d.core import CardMaker + +from toontown.minigame import ToonBlitzGlobals +from toontown.toonbase import ToontownGlobals +from toontown.toonbase.ToonBaseGlobal import base + class ToonBlitzAssetMgr(DirectObject): - notify = DirectNotifyGlobal.directNotify.newCategory('DistributedToonBlitzAssets') + notify = directNotify.newCategory('DistributedToonBlitzAssets') def __init__(self, game): self.__defineConstants() @@ -18,47 +21,47 @@ class ToonBlitzAssetMgr(DirectObject): def load(self): self.world = NodePath('ToonBlitzWorld') - self.background = loader.loadModel('phase_4/models/minigames/toonblitz_game') + self.background = base.loader.loadModel('phase_4/models/minigames/toonblitz_game') self.background.reparentTo(self.world) - self.startingWall = loader.loadModel('phase_4/models/minigames/toonblitz_game_wall') - self.startingPipe = loader.loadModel('phase_4/models/minigames/toonblitz_game_start') - self.exitElevator = loader.loadModel('phase_4/models/minigames/toonblitz_game_elevator') - self.arrow = loader.loadModel('phase_4/models/minigames/toonblitz_game_arrow') - self.sprayProp = loader.loadModel('phase_4/models/minigames/prop_waterspray') + self.startingWall = base.loader.loadModel('phase_4/models/minigames/toonblitz_game_wall') + self.startingPipe = base.loader.loadModel('phase_4/models/minigames/toonblitz_game_start') + self.exitElevator = base.loader.loadModel('phase_4/models/minigames/toonblitz_game_elevator') + self.arrow = base.loader.loadModel('phase_4/models/minigames/toonblitz_game_arrow') + self.sprayProp = base.loader.loadModel('phase_4/models/minigames/prop_waterspray') self.treasureModelList = [] - salesIcon = loader.loadModel('phase_4/models/minigames/salesIcon') + salesIcon = base.loader.loadModel('phase_4/models/minigames/salesIcon') self.treasureModelList.append(salesIcon) - moneyIcon = loader.loadModel('phase_4/models/minigames/moneyIcon') + moneyIcon = base.loader.loadModel('phase_4/models/minigames/moneyIcon') self.treasureModelList.append(moneyIcon) - legalIcon = loader.loadModel('phase_4/models/minigames/legalIcon') + legalIcon = base.loader.loadModel('phase_4/models/minigames/legalIcon') self.treasureModelList.append(legalIcon) - corpIcon = loader.loadModel('phase_4/models/minigames/corpIcon') + corpIcon = base.loader.loadModel('phase_4/models/minigames/corpIcon') self.treasureModelList.append(corpIcon) - self.particleGlow = loader.loadModel('phase_4/models/minigames/particleGlow') + self.particleGlow = base.loader.loadModel('phase_4/models/minigames/particleGlow') self.blockTypes = [] for i in range(4): - blockType = loader.loadModel('phase_4/models/minigames/toonblitz_game_block0' + str(i)) + blockType = base.loader.loadModel('phase_4/models/minigames/toonblitz_game_block0' + str(i)) self.blockTypes.append(blockType) - self.stomper = loader.loadModel('phase_4/models/minigames/toonblitz_game_stomper') + self.stomper = base.loader.loadModel('phase_4/models/minigames/toonblitz_game_stomper') plane = CollisionPlane(Plane(Vec3(0, 0, 1), Point3(0, 0, -50))) dropPlane = CollisionNode('dropPlane') dropPlane.addSolid(plane) dropPlane.setCollideMask(ToontownGlobals.FloorBitmask) self.world.attachNewNode(dropPlane) self.gameMusic = base.loader.loadMusic('phase_4/audio/bgm/MG_TwoDGame.ogg') - self.treasureGrabSound = loader.loadSfx('phase_4/audio/sfx/SZ_DD_treasure.ogg') + self.treasureGrabSound = base.loader.loadSfx('phase_4/audio/sfx/SZ_DD_treasure.ogg') self.sndOof = base.loader.loadSfx('phase_4/audio/sfx/MG_cannon_hit_dirt.ogg') self.soundJump = base.loader.loadSfx('phase_4/audio/sfx/MG_sfx_vine_game_jump.ogg') self.fallSound = base.loader.loadSfx('phase_4/audio/sfx/MG_sfx_vine_game_fall.ogg') self.watergunSound = base.loader.loadSfx('phase_4/audio/sfx/AA_squirt_seltzer_miss.ogg') self.splashSound = base.loader.loadSfx('phase_4/audio/sfx/Seltzer_squirt_2dgame_hit.ogg') - self.threeSparkles = loader.loadSfx('phase_4/audio/sfx/threeSparkles.ogg') - self.sparkleSound = loader.loadSfx('phase_4/audio/sfx/sparkly.ogg') - self.headCollideSound = loader.loadSfx('phase_3.5/audio/sfx/AV_collision.ogg') + self.threeSparkles = base.loader.loadSfx('phase_4/audio/sfx/threeSparkles.ogg') + self.sparkleSound = base.loader.loadSfx('phase_4/audio/sfx/sparkly.ogg') + self.headCollideSound = base.loader.loadSfx('phase_3.5/audio/sfx/AV_collision.ogg') self.faceStartPos = Vec3(-0.8, 0, -0.87) self.faceEndPos = Vec3(0.8, 0, -0.87) - self.aspect2dRoot = aspect2d.attachNewNode('TwoDGuiAspect2dRoot') + self.aspect2dRoot = base.aspect2d.attachNewNode('TwoDGuiAspect2dRoot') self.aspect2dRoot.setDepthWrite(1) self.cardMaker = CardMaker('card') self.cardMaker.reset() @@ -114,10 +117,9 @@ class ToonBlitzAssetMgr(DirectObject): del self.sparkleSound del self.headCollideSound self.game = None - return def onstage(self): - self.world.reparentTo(render) + self.world.reparentTo(base.render) base.playMusic(self.gameMusic, looping=1, volume=0.9) def offstage(self): diff --git a/toontown/minigame/TwoDBattleMgr.py b/toontown/minigame/TwoDBattleMgr.py index 7937237..db135a3 100644 --- a/toontown/minigame/TwoDBattleMgr.py +++ b/toontown/minigame/TwoDBattleMgr.py @@ -1,14 +1,29 @@ -from panda3d.core import * +from panda3d.core import CollisionHandlerEvent, CollisionNode, CollisionSphere, Point3, Point4, VBase3, Vec3 + +from direct.directnotify.DirectNotifyGlobal import directNotify +from direct.interval.IntervalGlobal import ( + ActorInterval, + Func, + LerpPosInterval, + LerpScaleInterval, + Parallel, + Sequence, + Wait +) + from direct.showbase.DirectObject import DirectObject -from toontown.toonbase.ToonBaseGlobal import * -from direct.directnotify import DirectNotifyGlobal -from direct.interval.IntervalGlobal import * -from toontown.battle.BattleProps import * +from direct.showbase.MessengerGlobal import messenger + from toontown.battle import MovieUtil -import math +from toontown.battle.BattleProps import globalPropPool +from toontown.toonbase import ToontownGlobals +from toontown.toonbase.ToonBaseGlobal import base + +from math import sin + class TwoDBattleMgr(DirectObject): - notify = DirectNotifyGlobal.directNotify.newCategory('TwoDBattleMgr') + notify = directNotify.newCategory('TwoDBattleMgr') def __init__(self, game, toon): self.game = game @@ -26,7 +41,6 @@ class TwoDBattleMgr(DirectObject): self.setupPistol() if self.toon == base.localAvatar: self.createShootCollision() - return def destroy(self): if self.toon == base.localAvatar: @@ -34,18 +48,20 @@ class TwoDBattleMgr(DirectObject): self.waterBulletIval.finish() del self.waterBulletIval self.waterBulletIval = None + self.ignore('enter' + self.collSphereName) base.localAvatar.controlManager.currentControls.cTrav.removeCollider(self.waterBullet) self.waterBullet.removeNode() del self.waterBullet + self.hand_jointpath0.removeNode() MovieUtil.removeProp(self.pistol) if self.shootTrack != None: self.shootTrack.finish() self.shootTrack = None + self.game = None self.toon = None - return def start(self): pass @@ -67,6 +83,7 @@ class TwoDBattleMgr(DirectObject): if self.toon == base.localAvatar: self.shootTrack.append(Func(self.game.assetMgr.playWatergunSound)) self.shootTrack.append(self.getWaterBulletIval()) + self.shootTrack.start() return elif self.shootTrack.isStopped(): @@ -74,6 +91,7 @@ class TwoDBattleMgr(DirectObject): if self.toon == base.localAvatar: self.shootTrack.append(Func(self.game.assetMgr.playWatergunSound)) self.shootTrack.append(self.getWaterBulletIval()) + self.shootTrack.start() def createShootCollision(self): @@ -90,6 +108,7 @@ class TwoDBattleMgr(DirectObject): self.waterBullet.hide() if self.showCollSpheres: self.waterBullet.show() + bulletEvent = CollisionHandlerEvent() bulletEvent.addInPattern('enter%fn') bulletEvent.addOutPattern('exit%fn') @@ -108,22 +127,23 @@ class TwoDBattleMgr(DirectObject): else: toon.loop('neutral') - torso = self.toon.getPart('torso', '1000') toonTrack = Sequence(ActorInterval(self.toon, 'water-gun', startFrame=48, endFrame=58, partName='torso'), ActorInterval(self.toon, 'water-gun', startFrame=107, endFrame=126, playRate=2, partName='torso'), Func(returnToLastAnim, self.toon)) return toonTrack def calcSprayStartPos(self): if self.toon: self.toon.update(0) + joint = self.pistol.find('**/joint_nozzle') - p = joint.getPos(render) + p = joint.getPos(base.render) self.origin = p def calcSprayEndPos(self): if self.toon: - xDirection = -math.sin(self.toon.getH()) + xDirection = -sin(self.toon.getH()) else: - xDirection = -math.sin(-90) + xDirection = -sin(-90) + endPos = Point3(self.origin.getX() + self.SHOOT_DISTANCE * xDirection, self.origin.getY(), self.origin.getZ()) self.target = endPos @@ -131,7 +151,7 @@ class TwoDBattleMgr(DirectObject): dSprayScale = 0.15 dSprayHold = 0.035 color = self.WATER_SPRAY_COLOR - parent = render + parent = base.render horizScale = 1.0 vertScale = 1.0 @@ -161,12 +181,13 @@ class TwoDBattleMgr(DirectObject): sprayScale.removeNode() sprayProp = self.sprayProp - sprayScale = hidden.attachNewNode('spray-parent') - sprayRot = hidden.attachNewNode('spray-rotate') + sprayScale = base.hidden.attachNewNode('spray-parent') + sprayRot = base.hidden.attachNewNode('spray-rotate') spray = sprayRot spray.setColor(color) if color[3] < 1.0: spray.setTransparency(1) + track = Sequence(Wait(0.1), Func(self.calcSprayStartPos), Func(self.calcSprayEndPos), Func(showSpray, sprayScale, sprayRot, sprayProp, parent), LerpScaleInterval(sprayScale, dSprayScale, calcTargetScale, startScale=MovieUtil.PNT3_NEARZERO), Wait(dSprayHold), Func(prepareToShrinkSpray, spray, sprayProp), LerpScaleInterval(sprayScale, dSprayScale, MovieUtil.PNT3_NEARZERO), Func(hideSpray, spray, sprayScale, sprayRot, sprayProp, globalPropPool)) return track @@ -180,8 +201,8 @@ class TwoDBattleMgr(DirectObject): if self.waterBulletIval: self.waterBulletIval.finish() del self.waterBulletIval + self.waterBulletIval = None - return def getWaterBulletIval(self): if not self.waterBulletIval.isPlaying(): diff --git a/toontown/racing/DistributedLeaderBoard.py b/toontown/racing/DistributedLeaderBoard.py index ee8b1af..ccf3fe3 100644 --- a/toontown/racing/DistributedLeaderBoard.py +++ b/toontown/racing/DistributedLeaderBoard.py @@ -1,39 +1,39 @@ -from direct.distributed import DistributedObject -from direct.directnotify import DirectNotifyGlobal -from otp.otpbase import OTPTimer +from panda3d.core import NodePath, TextNode + +from direct.directnotify.DirectNotifyGlobal import directNotify +from direct.distributed.DistributedObject import DistributedObject + +from toontown.toonbase import ToontownGlobals from toontown.toonbase import TTLocalizer -from toontown.racing import KartShopGlobals -from toontown.toonbase.ToonBaseGlobal import * -from panda3d.core import * -from toontown.toonbase.ToontownGlobals import * -import random +from toontown.toonbase.ToonBaseGlobal import base + import pickle -class DistributedLeaderBoard(DistributedObject.DistributedObject): - notify = DirectNotifyGlobal.directNotify.newCategory('DisributedLeaderBoard') + +class DistributedLeaderBoard(DistributedObject): + notify = directNotify.newCategory('DisributedLeaderBoard') def __init__(self, cr): self.notify.debug('__init__: initialization of local leaderboard') - DistributedObject.DistributedObject.__init__(self, cr) + DistributedObject.__init__(self, cr) self.corner = 0 self.length = 0 self.width = 0 self.updateCount = 0 self.board = None self.surface = None - return def generateInit(self): - DistributedObject.DistributedObject.generateInit(self) + DistributedObject.generateInit(self) self.board = NodePath(self.uniqueName('LeaderBoard')) def generate(self): - DistributedObject.DistributedObject.generate(self) + DistributedObject.generate(self) self.buildListParts() def announceGenerate(self): - DistributedObject.DistributedObject.announceGenerate(self) - self.board.reparentTo(render) + DistributedObject.announceGenerate(self) + self.board.reparentTo(base.render) self.accept('decorator-holiday-%d-ending' % ToontownGlobals.CRASHED_LEADERBOARD, self.showLists) self.accept('decorator-holiday-%d-starting' % ToontownGlobals.CRASHED_LEADERBOARD, self.hideLists) newsManager = base.cr.newsManager @@ -72,7 +72,7 @@ class DistributedLeaderBoard(DistributedObject.DistributedObject): z = zListTop self.nameTextNodes = [] self.timeTextNodes = [] - for i in range(10): + for _ in range(10): row, nameText, timeText, placeText = self.buildLeaderRow() self.nameTextNodes.append(nameText) placeText.setText(str(len(self.nameTextNodes)) + '.') @@ -81,6 +81,7 @@ class DistributedLeaderBoard(DistributedObject.DistributedObject): if len(self.nameTextNodes) == 6: z = zListTop x = 0.35 + row.setX(x) row.setZ(z) row.setY(1.6) @@ -105,7 +106,7 @@ class DistributedLeaderBoard(DistributedObject.DistributedObject): self.timeTextNodes[i].setText('%02d:%02d:%02d' % (min, sec, hundredths * 100)) def buildTitleRow(self): - row = hidden.attachNewNode('TitleRow') + row = base.hidden.attachNewNode('TitleRow') nameText = TextNode('titleRow') nameText.setFont(ToontownGlobals.getSignFont()) nameText.setAlign(TextNode.ACenter) @@ -117,7 +118,7 @@ class DistributedLeaderBoard(DistributedObject.DistributedObject): return (row, nameText) def buildTrackRow(self): - row = hidden.attachNewNode('trackRow') + row = base.hidden.attachNewNode('trackRow') nameText = TextNode('trackRow') nameText.setFont(ToontownGlobals.getSignFont()) nameText.setAlign(TextNode.ACenter) @@ -129,7 +130,7 @@ class DistributedLeaderBoard(DistributedObject.DistributedObject): return (row, nameText) def buildLeaderRow(self): - row = hidden.attachNewNode('leaderRow') + row = base.hidden.attachNewNode('leaderRow') nameText = TextNode('nameText') nameText.setFont(ToontownGlobals.getToonFont()) nameText.setAlign(TextNode.ALeft) @@ -166,4 +167,4 @@ class DistributedLeaderBoard(DistributedObject.DistributedObject): self.notify.debug('delete: deleting local leaderboard') self.ignoreAll() self.board.removeNode() - DistributedObject.DistributedObject.delete(self) + DistributedObject.delete(self) From 03c45eedb0af7ed2caca00320f19f76e78b5657e Mon Sep 17 00:00:00 2001 From: Open Toontown <57279094+opentoontown@users.noreply.github.com> Date: Sat, 29 Apr 2023 22:20:11 -0400 Subject: [PATCH 13/48] fix some broken minigames --- toontown/minigame/DistributedCannonGame.py | 287 +++++++++-------- toontown/minigame/DistributedPatternGame.py | 150 +++++---- toontown/minigame/DistributedTugOfWarGame.py | 307 +++++++++++-------- 3 files changed, 437 insertions(+), 307 deletions(-) diff --git a/toontown/minigame/DistributedCannonGame.py b/toontown/minigame/DistributedCannonGame.py index 8b75fac..8c46021 100644 --- a/toontown/minigame/DistributedCannonGame.py +++ b/toontown/minigame/DistributedCannonGame.py @@ -1,23 +1,28 @@ -from direct.directnotify import DirectNotifyGlobal -from panda3d.core import * -from toontown.toonbase.ToonBaseGlobal import * -from .DistributedMinigame import * -from direct.distributed.ClockDelta import * -from direct.interval.IntervalGlobal import * -from direct.fsm import ClassicFSM, State -from direct.fsm import State -from toontown.toonbase import ToontownGlobals -from toontown.toonbase import ToontownTimer +from panda3d.core import Point3, Quat, rad2Deg, Vec3 +from panda3d.otp import Nametag, NametagFloat3d + +from direct.directnotify.DirectNotifyGlobal import directNotify +from direct.fsm.ClassicFSM import ClassicFSM +from direct.fsm.State import State +from direct.gui.DirectGui import DGG, DirectButton, DirectFrame, DirectLabel +from direct.interval.IntervalGlobal import Parallel, Sequence, SoundInterval, Wait from direct.task.Task import Task -from . import Trajectory -import math -from toontown.toon import ToonHead -from toontown.effects import Splash -from toontown.effects import DustCloud -from . import CannonGameGlobals -from direct.gui.DirectGui import * -from panda3d.core import * +from direct.task.TaskManagerGlobal import taskMgr + +from toontown.effects.DustCloud import DustCloud +from toontown.effects.Splash import Splash +from toontown.minigame import CannonGameGlobals +from toontown.minigame import MinigameGlobals +from toontown.minigame.DistributedMinigame import DistributedMinigame +from toontown.minigame.Trajectory import Trajectory +from toontown.toon.ToonHead import ToonHead +from toontown.toonbase import ToontownGlobals from toontown.toonbase import TTLocalizer +from toontown.toonbase.ToonBaseGlobal import base +from toontown.toonbase.ToontownTimer import ToontownTimer + +import math + LAND_TIME = 2 WORLD_SCALE = 2.0 GROUND_SCALE = 1.4 * WORLD_SCALE @@ -40,8 +45,9 @@ TOWER_X_RANGE = int(TOWER_Y_RANGE / 2.0) INITIAL_VELOCITY = 94.0 WHISTLE_SPEED = INITIAL_VELOCITY * 0.55 + class DistributedCannonGame(DistributedMinigame): - notify = DirectNotifyGlobal.directNotify.newCategory('DistributedMinigame') + notify = directNotify.newCategory('DistributedCannonGame') font = ToontownGlobals.getToonFont() LOCAL_CANNON_MOVE_TASK = 'localCannonMoveTask' REWARD_COUNTDOWN_TASK = 'cannonGameRewardCountdown' @@ -58,11 +64,11 @@ class DistributedCannonGame(DistributedMinigame): def __init__(self, cr): DistributedMinigame.__init__(self, cr) - self.gameFSM = ClassicFSM.ClassicFSM('DistributedCannonGame', [State.State('off', self.enterOff, self.exitOff, ['aim']), - State.State('aim', self.enterAim, self.exitAim, ['shoot', 'waitForToonsToLand', 'cleanup']), - State.State('shoot', self.enterShoot, self.exitShoot, ['aim', 'waitForToonsToLand', 'cleanup']), - State.State('waitForToonsToLand', self.enterWaitForToonsToLand, self.exitWaitForToonsToLand, ['cleanup']), - State.State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup') + self.gameFSM = ClassicFSM('DistributedCannonGame', [State('off', self.enterOff, self.exitOff, ['aim']), + State('aim', self.enterAim, self.exitAim, ['shoot', 'waitForToonsToLand', 'cleanup']), + State('shoot', self.enterShoot, self.exitShoot, ['aim', 'waitForToonsToLand', 'cleanup']), + State('waitForToonsToLand', self.enterWaitForToonsToLand, self.exitWaitForToonsToLand, ['cleanup']), + State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup') self.addChildGameFSM(self.gameFSM) self.cannonLocationDict = {} self.cannonPositionDict = {} @@ -92,12 +98,12 @@ class DistributedCannonGame(DistributedMinigame): def load(self): self.notify.debug('load') DistributedMinigame.load(self) - self.sky = loader.loadModel('phase_3.5/models/props/TT_sky') - self.ground = loader.loadModel('phase_4/models/minigames/toon_cannon_gameground') - self.tower = loader.loadModel('phase_4/models/minigames/toon_cannon_water_tower') - self.cannon = loader.loadModel('phase_4/models/minigames/toon_cannon') - self.dropShadow = loader.loadModel('phase_3/models/props/drop_shadow') - self.hill = loader.loadModel('phase_4/models/minigames/cannon_hill') + self.sky = base.loader.loadModel('phase_3.5/models/props/TT_sky') + self.ground = base.loader.loadModel('phase_4/models/minigames/toon_cannon_gameground') + self.tower = base.loader.loadModel('phase_4/models/minigames/toon_cannon_water_tower') + self.cannon = base.loader.loadModel('phase_4/models/minigames/toon_cannon') + self.dropShadow = base.loader.loadModel('phase_3/models/props/drop_shadow') + self.hill = base.loader.loadModel('phase_4/models/minigames/cannon_hill') self.sky.setScale(WORLD_SCALE) self.ground.setScale(GROUND_SCALE) self.cannon.setScale(CANNON_SCALE) @@ -105,12 +111,12 @@ class DistributedCannonGame(DistributedMinigame): self.ground.setColor(0.85, 0.85, 0.85, 1.0) self.hill.setScale(1, 1, CANNON_Z / 20.0) self.dropShadow.setBin('fixed', 0, 1) - self.splash = Splash.Splash(render) - self.dustCloud = DustCloud.DustCloud(render) - purchaseModels = loader.loadModel('phase_4/models/gui/purchase_gui') + self.splash = Splash(base.render) + self.dustCloud = DustCloud(base.render) + purchaseModels = base.loader.loadModel('phase_4/models/gui/purchase_gui') self.jarImage = purchaseModels.find('**/Jar') - self.jarImage.reparentTo(hidden) - self.rewardPanel = DirectLabel(parent=hidden, relief=None, pos=(1.16, 0.0, 0.45), scale=0.65, text='', text_scale=0.2, text_fg=(0.95, 0.95, 0, 1), text_pos=(0, -.13), text_font=ToontownGlobals.getSignFont(), image=self.jarImage) + self.jarImage.reparentTo(base.hidden) + self.rewardPanel = DirectLabel(parent=base.hidden, relief=None, pos=(1.16, 0.0, 0.45), scale=0.65, text='', text_scale=0.2, text_fg=(0.95, 0.95, 0, 1), text_pos=(0, -.13), text_font=ToontownGlobals.getSignFont(), image=self.jarImage) self.rewardPanelTitle = DirectLabel(parent=self.rewardPanel, relief=None, pos=(0, 0, 0.06), scale=0.08, text=TTLocalizer.CannonGameReward, text_fg=(0.95, 0.95, 0, 1), text_shadow=(0, 0, 0, 1)) self.music = base.loader.loadMusic('phase_4/audio/bgm/MG_cannon_game.ogg') self.sndCannonMove = base.loader.loadSfx('phase_4/audio/sfx/MG_cannon_adjust.ogg') @@ -122,7 +128,7 @@ class DistributedCannonGame(DistributedMinigame): self.sndWin = base.loader.loadSfx('phase_4/audio/sfx/MG_win.ogg') self.sndRewardTick = base.loader.loadSfx('phase_3.5/audio/sfx/tick_counter.ogg') guiModel = 'phase_4/models/gui/cannon_game_gui' - cannonGui = loader.loadModel(guiModel) + cannonGui = base.loader.loadModel(guiModel) self.aimPad = DirectFrame(image=cannonGui.find('**/CannonFire_PAD'), relief=None, pos=(0.7, 0, -0.553333), scale=0.8) cannonGui.removeNode() self.aimPad.hide() @@ -141,14 +147,13 @@ class DistributedCannonGame(DistributedMinigame): bindButton(self.downButton, self.__downPressed, self.__downReleased) bindButton(self.leftButton, self.__leftPressed, self.__leftReleased) bindButton(self.rightButton, self.__rightPressed, self.__rightReleased) - self.timer = ToontownTimer.ToontownTimer() + self.timer = ToontownTimer() self.timer.posInTopRightCorner() self.timer.hide() self.DEBUG_TOWER_RANGE = 0 self.DEBUG_CANNON_FAR_LEFT = 0 self.DEBUG_TOWER_NEAR = 1 self.DEBUG_TOWER_FAR_LEFT = 1 - return def unload(self): self.notify.debug('unload') @@ -199,6 +204,7 @@ class DistributedCannonGame(DistributedMinigame): av.loop('neutral') av.setPlayRate(1.0, 'run') av.nametag.removeNametag(head.tag) + head.delete() del self.toonHeadDict @@ -227,19 +233,19 @@ class DistributedCannonGame(DistributedMinigame): DistributedMinigame.onstage(self) self.__createCannons() for avId in self.avIdList: - self.cannonDict[avId][0].reparentTo(render) + self.cannonDict[avId][0].reparentTo(base.render) self.towerPos = self.getTowerPosition() self.tower.setPos(self.towerPos) - self.tower.reparentTo(render) - self.sky.reparentTo(render) - self.ground.reparentTo(render) + self.tower.reparentTo(base.render) + self.sky.reparentTo(base.render) + self.ground.reparentTo(base.render) self.hill.setPosHpr(0, CANNON_Y + 2.33, 0, 0, 0, 0) - self.hill.reparentTo(render) - self.splash.reparentTo(render) - self.dustCloud.reparentTo(render) + self.hill.reparentTo(base.render) + self.splash.reparentTo(base.render) + self.dustCloud.reparentTo(base.render) self.__createToonModels(self.localAvId) - camera.reparentTo(render) + base.camera.reparentTo(base.render) self.__oldCamFar = base.camLens.getFar() base.camLens.setFar(FAR_PLANE_DIST) self.__startIntro() @@ -248,27 +254,28 @@ class DistributedCannonGame(DistributedMinigame): def offstage(self): self.notify.debug('offstage') - self.sky.reparentTo(hidden) - self.ground.reparentTo(hidden) - self.hill.reparentTo(hidden) - self.tower.reparentTo(hidden) + self.sky.reparentTo(base.hidden) + self.ground.reparentTo(base.hidden) + self.hill.reparentTo(base.hidden) + self.tower.reparentTo(base.hidden) for avId in self.avIdList: - self.cannonDict[avId][0].reparentTo(hidden) + self.cannonDict[avId][0].reparentTo(base.hidden) if avId in self.dropShadowDict: - self.dropShadowDict[avId].reparentTo(hidden) + self.dropShadowDict[avId].reparentTo(base.hidden) + av = self.getAvatar(avId) if av: av.dropShadow.show() av.resetLOD() - self.splash.reparentTo(hidden) + self.splash.reparentTo(base.hidden) self.splash.stop() - self.dustCloud.reparentTo(hidden) + self.dustCloud.reparentTo(base.hidden) self.dustCloud.stop() self.__stopIntro() base.camLens.setFar(self.__oldCamFar) - self.timer.reparentTo(hidden) - self.rewardPanel.reparentTo(hidden) + self.timer.reparentTo(base.hidden) + self.rewardPanel.reparentTo(base.hidden) DistributedMinigame.offstage(self) def getTowerPosition(self): @@ -282,6 +289,7 @@ class DistributedCannonGame(DistributedMinigame): y = yMax else: y = self.randomNumGen.randint(yMin, yMax) + xRange = TOWER_X_RANGE if self.DEBUG_TOWER_RANGE: if self.DEBUG_TOWER_FAR_LEFT: @@ -290,6 +298,7 @@ class DistributedCannonGame(DistributedMinigame): x = xRange else: x = self.randomNumGen.randint(0, xRange) + x = x - int(xRange / 2.0) if base.wantMinigameDifficulty: diff = self.getDifficulty() @@ -297,6 +306,7 @@ class DistributedCannonGame(DistributedMinigame): x *= scale yCenter = (yMin + yMax) / 2.0 y = (y - yCenter) * scale + yCenter + x = float(x) * (float(y) / float(yRange)) y = y - int(yRange / 2.0) self.notify.debug('getTowerPosition: ' + str(x) + ', ' + str(y)) @@ -304,7 +314,7 @@ class DistributedCannonGame(DistributedMinigame): def __createCannons(self): for avId in self.avIdList: - cannon = self.cannon.copyTo(hidden) + cannon = self.cannon.copyTo(base.hidden) barrel = cannon.find('**/cannon') self.cannonDict[avId] = [cannon, barrel] @@ -317,6 +327,7 @@ class DistributedCannonGame(DistributedMinigame): self.cannonLocationDict[avId] = Point3(0 * CANNON_X_SPACING - (4 - 1) * CANNON_X_SPACING / 2, CANNON_Y, CANNON_Z) else: self.cannonLocationDict[avId] = Point3(3 * CANNON_X_SPACING - (4 - 1) * CANNON_X_SPACING / 2, CANNON_Y, CANNON_Z) + self.cannonPositionDict[avId] = [0, CannonGameGlobals.CANNON_ANGLE_MIN] self.cannonDict[avId][0].setPos(self.cannonLocationDict[avId]) self.__updateCannonPosition(avId) @@ -324,9 +335,11 @@ class DistributedCannonGame(DistributedMinigame): def setGameReady(self): if not self.hasLocalToon: return + self.notify.debug('setGameReady') if DistributedMinigame.setGameReady(self): return + for avId in self.avIdList: if avId != self.localAvId: self.__createToonModels(avId) @@ -335,13 +348,13 @@ class DistributedCannonGame(DistributedMinigame): toon = self.getAvatar(avId) self.toonScaleDict[avId] = toon.getScale() toon.useLOD(1000) - toonParent = render.attachNewNode('toonOriginChange') + toonParent = base.render.attachNewNode('toonOriginChange') toon.reparentTo(toonParent) toon.setPosHpr(0, 0, -(toon.getHeight() / 2.0), 0, 0, 0) self.toonModelDict[avId] = toonParent - head = ToonHead.ToonHead() + head = ToonHead() head.setupHead(self.getAvatar(avId).style) - head.reparentTo(hidden) + head.reparentTo(base.hidden) self.toonHeadDict[avId] = head toon = self.getAvatar(avId) tag = NametagFloat3d() @@ -354,11 +367,12 @@ class DistributedCannonGame(DistributedMinigame): head.tag = tag self.__loadToonInCannon(avId) self.getAvatar(avId).dropShadow.hide() - self.dropShadowDict[avId] = self.dropShadow.copyTo(hidden) + self.dropShadowDict[avId] = self.dropShadow.copyTo(base.hidden) def setGameStart(self, timestamp): if not self.hasLocalToon: return + self.notify.debug('setGameStart') DistributedMinigame.setGameStart(self, timestamp) self.__stopIntro() @@ -366,13 +380,13 @@ class DistributedCannonGame(DistributedMinigame): if not base.config.GetBool('endless-cannon-game', 0): self.timer.show() self.timer.countdown(CannonGameGlobals.GameTime, self.__gameTimerExpired) - self.rewardPanel.reparentTo(aspect2d) + + self.rewardPanel.reparentTo(base.aspect2d) self.scoreMult = MinigameGlobals.getScoreMult(self.cr.playGame.hood.id) self.__startRewardCountdown() self.airborneToons = 0 self.clockStopTime = None self.gameFSM.request('aim') - return def __gameTimerExpired(self): self.notify.debug('game timer expired') @@ -384,8 +398,10 @@ class DistributedCannonGame(DistributedMinigame): def updateCannonPosition(self, avId, zRot, angle): if not self.hasLocalToon: return + if not self.__playing(): return + if avId != self.localAvId: self.cannonPositionDict[avId] = [zRot, angle] self.__updateCannonPosition(avId) @@ -393,8 +409,10 @@ class DistributedCannonGame(DistributedMinigame): def setCannonWillFire(self, avId, fireTime, zRot, angle): if not self.hasLocalToon: return + if not self.__playing(): return + self.notify.debug('setCannonWillFire: ' + str(avId) + ': zRot=' + str(zRot) + ', angle=' + str(angle) + ', time=' + str(fireTime)) self.cannonPositionDict[avId][0] = zRot self.cannonPositionDict[avId][1] = angle @@ -407,6 +425,7 @@ class DistributedCannonGame(DistributedMinigame): fireTask = Task.sequence(Task.pause(timeToWait), task) else: fireTask = task + fireTask = task taskMgr.add(fireTask, 'fireCannon' + str(avId)) self.airborneToons += 1 @@ -414,10 +433,10 @@ class DistributedCannonGame(DistributedMinigame): def announceToonWillLandInWater(self, avId, landTime): if not self.hasLocalToon: return + self.notify.debug('announceToonWillLandInWater: ' + str(avId) + ': time=' + str(landTime)) if self.clockStopTime == None: self.clockStopTime = landTime - return def enterOff(self): self.notify.debug('enterOff') @@ -444,6 +463,7 @@ class DistributedCannonGame(DistributedMinigame): def __somebodyWon(self, avId): if avId == self.localAvId: base.playSfx(self.sndWin) + self.__killRewardCountdown() self.timer.stop() self.gameFSM.request('waitForToonsToLand') @@ -463,6 +483,7 @@ class DistributedCannonGame(DistributedMinigame): if hasattr(self, 'jarIval'): self.jarIval.finish() del self.jarIval + for avId in self.avIdList: taskMgr.remove('fireCannon' + str(avId)) taskMgr.remove('flyingToon' + str(avId)) @@ -607,27 +628,34 @@ class DistributedCannonGame(DistributedMinigame): rotVel = 0 if self.leftPressed: rotVel += CannonGameGlobals.CANNON_ROTATION_VEL + if self.rightPressed: rotVel -= CannonGameGlobals.CANNON_ROTATION_VEL - pos[0] += rotVel * globalClock.getDt() + + pos[0] += rotVel * base.clock.getDt() if pos[0] < CannonGameGlobals.CANNON_ROTATION_MIN: pos[0] = CannonGameGlobals.CANNON_ROTATION_MIN elif pos[0] > CannonGameGlobals.CANNON_ROTATION_MAX: pos[0] = CannonGameGlobals.CANNON_ROTATION_MAX + angVel = 0 if self.upPressed: angVel += CannonGameGlobals.CANNON_ANGLE_VEL + if self.downPressed: angVel -= CannonGameGlobals.CANNON_ANGLE_VEL - pos[1] += angVel * globalClock.getDt() + + pos[1] += angVel * base.clock.getDt() if pos[1] < CannonGameGlobals.CANNON_ANGLE_MIN: pos[1] = CannonGameGlobals.CANNON_ANGLE_MIN elif pos[1] > CannonGameGlobals.CANNON_ANGLE_MAX: pos[1] = CannonGameGlobals.CANNON_ANGLE_MAX + if oldRot != pos[0] or oldAng != pos[1]: if self.cannonMoving == 0: self.cannonMoving = 1 base.playSfx(self.sndCannonMove, looping=1) + self.__updateCannonPosition(self.localAvId) if task.time - task.lastPositionBroadcastTime > CANNON_MOVE_UPDATE_FREQ: task.lastPositionBroadcastTime = task.time @@ -636,7 +664,8 @@ class DistributedCannonGame(DistributedMinigame): self.cannonMoving = 0 self.sndCannonMove.stop() self.__broadcastLocalCannonPosition() - return Task.cont + + return task.cont def __broadcastLocalCannonPosition(self): self.sendUpdate('setCannonPosition', [self.cannonPositionDict[self.localAvId][0], self.cannonPositionDict[self.localAvId][1]]) @@ -649,8 +678,8 @@ class DistributedCannonGame(DistributedMinigame): return Point3(self.cannonLocationDict[self.localAvId][0], CANNON_Y - 25.0, CANNON_Z + 7) def __putCameraBehindCannon(self): - camera.setPos(self.__getCameraPositionBehindCannon()) - camera.setHpr(0, 0, 0) + base.camera.setPos(self.__getCameraPositionBehindCannon()) + base.camera.setHpr(0, 0, 0) def __loadToonInCannon(self, avId): self.toonModelDict[avId].detachNode() @@ -660,7 +689,7 @@ class DistributedCannonGame(DistributedMinigame): head.reparentTo(self.cannonDict[avId][1]) head.setPosHpr(0, 6, 0, 0, -45, 0) sc = self.toonScaleDict[avId] - head.setScale(render, sc[0], sc[1], sc[2]) + head.setScale(base.render, sc[0], sc[1], sc[2]) def __toRadians(self, angle): return angle * 2.0 * math.pi / 360.0 @@ -670,10 +699,10 @@ class DistributedCannonGame(DistributedMinigame): def __calcFlightResults(self, avId, launchTime): head = self.toonHeadDict[avId] - startPos = head.getPos(render) - startHpr = head.getHpr(render) - hpr = self.cannonDict[avId][1].getHpr(render) - towerPos = self.tower.getPos(render) + startPos = head.getPos(base.render) + startHpr = head.getHpr(base.render) + hpr = self.cannonDict[avId][1].getHpr(base.render) + towerPos = self.tower.getPos(base.render) rotation = self.__toRadians(hpr[0]) angle = self.__toRadians(hpr[1]) horizVel = INITIAL_VELOCITY * math.cos(angle) @@ -681,7 +710,7 @@ class DistributedCannonGame(DistributedMinigame): yVel = horizVel * math.cos(rotation) zVel = INITIAL_VELOCITY * math.sin(angle) startVel = Vec3(xVel, yVel, zVel) - trajectory = Trajectory.Trajectory(launchTime, startPos, startVel) + trajectory = Trajectory(launchTime, startPos, startVel) towerList = [towerPos + Point3(0, 0, BUCKET_HEIGHT), TOWER_RADIUS, TOWER_HEIGHT - BUCKET_HEIGHT] self.notify.debug('calcFlightResults(%s): rotation(%s), angle(%s), horizVel(%s), xVel(%s), yVel(%s), zVel(%s), startVel(%s), trajectory(%s), towerList(%s)' % (avId, rotation, @@ -701,7 +730,6 @@ class DistributedCannonGame(DistributedMinigame): avId = task.avId self.notify.debug('FIRING CANNON FOR AVATAR ' + str(avId)) startPos, startHpr, startVel, trajectory, timeOfImpact, hitWhat = self.__calcFlightResults(avId, launchTime) - self.notify.debug('start position: ' + str(startPos)) self.notify.debug('start velocity: ' + str(startVel)) self.notify.debug('time of launch: ' + str(launchTime)) @@ -713,12 +741,13 @@ class DistributedCannonGame(DistributedMinigame): self.notify.debug('toon will hit the tower') else: self.notify.debug('toon will hit the ground') + head = self.toonHeadDict[avId] head.stopBlink() head.stopLookAroundNow() - head.reparentTo(hidden) + head.reparentTo(base.hidden) av = self.toonModelDict[avId] - av.reparentTo(render) + av.reparentTo(base.render) av.setPos(startPos) av.setHpr(startHpr) avatar = self.getAvatar(avId) @@ -737,7 +766,7 @@ class DistributedCannonGame(DistributedMinigame): info['hRot'] = self.cannonPositionDict[avId][0] info['haveWhistled'] = 0 info['maxCamPullback'] = CAMERA_PULLBACK_MIN - info['timeEnterTowerXY'], info['timeExitTowerXY'] = trajectory.calcEnterAndLeaveCylinderXY(self.tower.getPos(render), TOWER_RADIUS) + info['timeEnterTowerXY'], info['timeExitTowerXY'] = trajectory.calcEnterAndLeaveCylinderXY(self.tower.getPos(base.render), TOWER_RADIUS) shootTask.info = info flyTask.info = info seqDoneTask.info = info @@ -746,7 +775,8 @@ class DistributedCannonGame(DistributedMinigame): if avId == self.localAvId: if info['hitWhat'] == self.HIT_WATER: self.sendUpdate('setToonWillLandInWater', [info['timeOfImpact']]) - return Task.done + + return task.done def __calcToonImpact(self, trajectory, waterTower): self.notify.debug('trajectory: %s' % trajectory) @@ -757,10 +787,12 @@ class DistributedCannonGame(DistributedMinigame): self.notify.debug('t_waterImpact: %s' % t_waterImpact) if t_waterImpact > 0: return (t_waterImpact, self.HIT_WATER) + t_towerImpact = trajectory.checkCollisionWithCylinderSides(waterTower[0], waterTower[1], waterTower[2]) self.notify.debug('t_towerImpact: %s' % t_towerImpact) if t_towerImpact > 0: return (t_towerImpact, self.HIT_TOWER) + t_groundImpact = trajectory.checkCollisionWithGround() self.notify.debug('t_groundImpact: %s' % t_groundImpact) if t_groundImpact >= trajectory.getStartTime(): @@ -771,8 +803,8 @@ class DistributedCannonGame(DistributedMinigame): def __shootTask(self, task): base.playSfx(self.sndCannonFire) - self.dropShadowDict[task.info['avId']].reparentTo(render) - return Task.done + self.dropShadowDict[task.info['avId']].reparentTo(base.render) + return task.done def __flyTask(self, task): curTime = task.time + task.info['launchTime'] @@ -780,10 +812,11 @@ class DistributedCannonGame(DistributedMinigame): pos = task.info['trajectory'].getPos(t) task.info['toon'].setPos(pos) shadowPos = Point3(pos) - if t >= task.info['timeEnterTowerXY'] and t <= task.info['timeExitTowerXY'] and pos[2] >= self.tower.getPos(render)[2] + TOWER_HEIGHT: - shadowPos.setZ(self.tower.getPos(render)[2] + TOWER_HEIGHT + SHADOW_Z_OFFSET) + if t >= task.info['timeEnterTowerXY'] and t <= task.info['timeExitTowerXY'] and pos[2] >= self.tower.getPos(base.render)[2] + TOWER_HEIGHT: + shadowPos.setZ(self.tower.getPos(base.render)[2] + TOWER_HEIGHT + SHADOW_Z_OFFSET) else: shadowPos.setZ(SHADOW_Z_OFFSET) + self.dropShadowDict[task.info['avId']].setPos(shadowPos) vel = task.info['trajectory'].getVel(t) run = math.sqrt(vel[0] * vel[0] + vel[1] * vel[1]) @@ -791,7 +824,7 @@ class DistributedCannonGame(DistributedMinigame): theta = self.__toDegrees(math.atan(rise / run)) task.info['toon'].setHpr(task.info['hRot'], -90 + theta, 0) if task.info['avId'] == self.localAvId: - lookAt = self.tower.getPos(render) + lookAt = self.tower.getPos(base.render) lookAt.setZ(lookAt.getZ() - TOWER_HEIGHT / 2.0) towerPos = Point3(self.towerPos) towerPos.setZ(TOWER_HEIGHT) @@ -804,26 +837,31 @@ class DistributedCannonGame(DistributedMinigame): perp.normalize() if ttVec.dot(perp) > 0.0: perp = Vec3(-perp[0], -perp[1], -perp[2]) + a = 1.0 - toonTowerDist / TOON_TOWER_THRESHOLD a_2 = a * a multiplier = -2.0 * a_2 * a + 3 * a_2 lookAt = lookAt + perp * (multiplier * MAX_LOOKAT_OFFSET) + foo = Vec3(pos - lookAt) foo.normalize() task.info['maxCamPullback'] = max(task.info['maxCamPullback'], CAMERA_PULLBACK_MIN + multiplier * (CAMERA_PULLBACK_MAX - CAMERA_PULLBACK_MIN)) foo = foo * task.info['maxCamPullback'] camPos = pos + Point3(foo) - camera.setPos(camPos) - camera.lookAt(pos) + base.camera.setPos(camPos) + base.camera.lookAt(pos) + if task.info['haveWhistled'] == 0: if -vel[2] > WHISTLE_SPEED: if t < task.info['timeOfImpact'] - 0.5: task.info['haveWhistled'] = 1 base.playSfx(self.sndWhizz) + if t == task.info['timeOfImpact']: if task.info['haveWhistled']: self.sndWhizz.stop() - self.dropShadowDict[task.info['avId']].reparentTo(hidden) + + self.dropShadowDict[task.info['avId']].reparentTo(base.hidden) avatar = self.getAvatar(task.info['avId']) if task.info['hitWhat'] == self.HIT_WATER: avatar.loop('neutral') @@ -853,15 +891,17 @@ class DistributedCannonGame(DistributedMinigame): avatar.pose('slip-forward', 25) base.playSfx(self.sndHitTower) elif task.info['hitWhat'] == self.HIT_GROUND: - task.info['toon'].setP(render, -150.0) + task.info['toon'].setP(base.render, -150.0) self.dustCloud.setPos(task.info['toon'], 0, 0, -2.5) self.dustCloud.setScale(0.35) self.dustCloud.play() base.playSfx(self.sndHitGround) avatar.setPlayRate(2.0, 'run') avatar.loop('run') - return Task.done - return Task.cont + + return task.done + + return task.cont def __flySequenceDoneTask(self, task): self.airborneToons -= 1 @@ -872,7 +912,8 @@ class DistributedCannonGame(DistributedMinigame): self.__loadToonInCannon(task.info['avId']) if task.info['avId'] == self.localAvId: self.gameFSM.request('aim') - return Task.done + + return task.done def __startRewardCountdown(self): taskMgr.remove(self.REWARD_COUNTDOWN_TASK) @@ -883,24 +924,29 @@ class DistributedCannonGame(DistributedMinigame): def __updateRewardCountdown(self, task): if not hasattr(self, 'rewardPanel'): - return Task.cont + return task.cont + curTime = self.getCurrentGameTime() if self.clockStopTime is not None: if self.clockStopTime < curTime: self.__killRewardCountdown() curTime = self.clockStopTime + score = int(self.scoreMult * CannonGameGlobals.calcScore(curTime) + 0.5) if not hasattr(task, 'curScore'): task.curScore = score + self.rewardPanel['text'] = str(score) if task.curScore != score: if hasattr(self, 'jarIval'): self.jarIval.finish() + s = self.rewardPanel.getScale() self.jarIval = Parallel(Sequence(self.rewardPanel.scaleInterval(0.15, s * 3.0 / 4.0, blendType='easeOut'), self.rewardPanel.scaleInterval(0.15, s, blendType='easeIn')), SoundInterval(self.sndRewardTick), name='cannonGameRewardJarThrob') self.jarIval.start() + task.curScore = score - return Task.cont + return task.cont def __startIntro(self): self.T_WATER = 1 @@ -926,18 +972,19 @@ class DistributedCannonGame(DistributedMinigame): if self.introCameraSeq: self.introCameraSeq.finish() self.introCameraSeq = None - camera.wrtReparentTo(render) + + base.camera.wrtReparentTo(base.render) def __spawnCameraLookAtLerp(self, targetPos, targetLookAt, duration): - oldPos = camera.getPos() - oldHpr = camera.getHpr() - camera.setPos(targetPos) - camera.lookAt(targetLookAt) + oldPos = base.camera.getPos() + oldHpr = base.camera.getHpr() + base.camera.setPos(targetPos) + base.camera.lookAt(targetLookAt) targetQuat = Quat() - targetQuat.setHpr(camera.getHpr()) - camera.setPos(oldPos) - camera.setHpr(oldHpr) - self.introCameraSeq = camera.posQuatInterval(duration, Point3(targetPos), targetQuat, blendType='easeInOut', name=self.INTRO_TASK_NAME_CAMERA_LERP) + targetQuat.setHpr(base.camera.getHpr()) + base.camera.setPos(oldPos) + base.camera.setHpr(oldHpr) + self.introCameraSeq = base.camera.posQuatInterval(duration, Point3(targetPos), targetQuat, blendType='easeInOut', name=self.INTRO_TASK_NAME_CAMERA_LERP) self.introCameraSeq.start() def __taskLookInWater(self, task): @@ -949,40 +996,40 @@ class DistributedCannonGame(DistributedMinigame): vecAwayFromCannons.normalize() camLoc = Point3(vecAwayFromCannons * 20) + Point3(0, 0, 20) camLoc = camLoc + task.data['towerWaterCenter'] - camera.setPos(camLoc) - camera.lookAt(task.data['towerWaterCenter']) + base.camera.setPos(camLoc) + base.camera.lookAt(task.data['towerWaterCenter']) task.data['vecAwayFromCannons'] = vecAwayFromCannons - return Task.done + return task.done def __taskPullBackFromWater(self, task): camLoc = Point3(task.data['vecAwayFromCannons'] * 40) + Point3(0, 0, 20) camLoc = camLoc + task.data['towerWaterCenter'] lookAt = task.data['cannonCenter'] self.__spawnCameraLookAtLerp(camLoc, lookAt, self.T_WATER2LONGVIEW) - return Task.done + return task.done def __flyUpToToon(self, task): - headPos = self.toonHeadDict[self.localAvId].getPos(render) + headPos = self.toonHeadDict[self.localAvId].getPos(base.render) camLoc = headPos + Point3(0, 5, 0) lookAt = Point3(headPos) self.__spawnCameraLookAtLerp(camLoc, lookAt, self.T_LONGVIEW2TOONHEAD) - return Task.done + return task.done def __flyToBackOfCannon(self, task): - lerpNode = hidden.attachNewNode('CannonGameCameraLerpNode') - lerpNode.reparentTo(render) + lerpNode = base.hidden.attachNewNode('CannonGameCameraLerpNode') + lerpNode.reparentTo(base.render) lerpNode.setPos(self.cannonLocationDict[self.localAvId] + Point3(0, 1, 0)) - relCamPos = camera.getPos(lerpNode) - relCamHpr = camera.getHpr(lerpNode) + relCamPos = base.camera.getPos(lerpNode) + relCamHpr = base.camera.getHpr(lerpNode) startRotation = lerpNode.getHpr() endRotation = Point3(-180, 0, 0) lerpNode.setHpr(endRotation) - camera.setPos(self.__getCameraPositionBehindCannon()) - endPos = camera.getPos(lerpNode) + base.camera.setPos(self.__getCameraPositionBehindCannon()) + endPos = base.camera.getPos(lerpNode) lerpNode.setHpr(startRotation) - camera.reparentTo(lerpNode) - camera.setPos(relCamPos) - camera.setHpr(relCamHpr) - self.introCameraSeq = Parallel(lerpNode.hprInterval(self.T_TOONHEAD2CANNONBACK, endRotation, blendType='easeInOut', name=self.INTRO_TASK_NAME_CAMERA_LERP), camera.posInterval(self.T_TOONHEAD2CANNONBACK, endPos, blendType='easeInOut', name=self.INTRO_TASK_NAME_CAMERA_LERP)) + base.camera.reparentTo(lerpNode) + base.camera.setPos(relCamPos) + base.camera.setHpr(relCamHpr) + self.introCameraSeq = Parallel(lerpNode.hprInterval(self.T_TOONHEAD2CANNONBACK, endRotation, blendType='easeInOut', name=self.INTRO_TASK_NAME_CAMERA_LERP), base.camera.posInterval(self.T_TOONHEAD2CANNONBACK, endPos, blendType='easeInOut', name=self.INTRO_TASK_NAME_CAMERA_LERP)) self.introCameraSeq.start() - return Task.done + return task.done diff --git a/toontown/minigame/DistributedPatternGame.py b/toontown/minigame/DistributedPatternGame.py index 286ea7e..7e7420c 100644 --- a/toontown/minigame/DistributedPatternGame.py +++ b/toontown/minigame/DistributedPatternGame.py @@ -1,22 +1,36 @@ -from panda3d.core import * -from toontown.toonbase.ToonBaseGlobal import * -from direct.interval.IntervalGlobal import * -from .DistributedMinigame import * -from direct.gui.DirectGui import * -from panda3d.core import * -from direct.fsm import ClassicFSM, State -from direct.fsm import State -from toontown.toonbase import ToontownTimer -from . import PatternGameGlobals -from toontown.toon import ToonHead -from toontown.char import CharDNA -from toontown.char import Char -from . import ArrowKeys -import random +from panda3d.core import Point3, VBase4, Vec3 +from panda3d.otp import CFSpeech, NametagGlobals + +from direct.directnotify.DirectNotifyGlobal import directNotify +from direct.fsm.ClassicFSM import ClassicFSM +from direct.fsm.State import State +from direct.gui.DirectGui import DirectLabel +from direct.interval.IntervalGlobal import ( + ActorInterval, + Func, + LerpColorInterval, + LerpHprInterval, + LerpPosInterval, + Parallel, + Sequence, + Wait +) + +from toontown.char.Char import Char +from toontown.char.CharDNA import CharDNA +from toontown.minigame import PatternGameGlobals +from toontown.minigame.ArrowKeys import ArrowKeys +from toontown.minigame.DistributedMinigame import DistributedMinigame from toontown.toonbase import ToontownGlobals from toontown.toonbase import TTLocalizer +from toontown.toonbase.ToonBaseGlobal import base +from toontown.toonbase.ToontownTimer import ToontownTimer + +from random import choice + class DistributedPatternGame(DistributedMinigame): + notify = directNotify.newCategory('DistributedPatternGame') phase4snd = 'phase_4/audio/sfx/' ButtonSoundNames = (phase4snd + 'm_match_trumpet.ogg', phase4snd + 'm_match_guitar.ogg', @@ -46,14 +60,14 @@ class DistributedPatternGame(DistributedMinigame): def __init__(self, cr): DistributedMinigame.__init__(self, cr) - self.gameFSM = ClassicFSM.ClassicFSM('DistributedPatternGame', [State.State('off', self.enterOff, self.exitOff, ['waitForServerPattern']), - State.State('waitForServerPattern', self.enterWaitForServerPattern, self.exitWaitForServerPattern, ['showServerPattern', 'cleanup']), - State.State('showServerPattern', self.enterShowServerPattern, self.exitShowServerPattern, ['getUserInput', 'playBackPatterns', 'cleanup']), - State.State('getUserInput', self.enterGetUserInput, self.exitGetUserInput, ['waitForPlayerPatterns', 'playBackPatterns', 'cleanup']), - State.State('waitForPlayerPatterns', self.enterWaitForPlayerPatterns, self.exitWaitForPlayerPatterns, ['playBackPatterns', 'cleanup', 'checkGameOver']), - State.State('playBackPatterns', self.enterPlayBackPatterns, self.exitPlayBackPatterns, ['checkGameOver', 'cleanup']), - State.State('checkGameOver', self.enterCheckGameOver, self.exitCheckGameOver, ['waitForServerPattern', 'cleanup']), - State.State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup') + self.gameFSM = ClassicFSM('DistributedPatternGame', [State('off', self.enterOff, self.exitOff, ['waitForServerPattern']), + State('waitForServerPattern', self.enterWaitForServerPattern, self.exitWaitForServerPattern, ['showServerPattern', 'cleanup']), + State('showServerPattern', self.enterShowServerPattern, self.exitShowServerPattern, ['getUserInput', 'playBackPatterns', 'cleanup']), + State('getUserInput', self.enterGetUserInput, self.exitGetUserInput, ['waitForPlayerPatterns', 'playBackPatterns', 'cleanup']), + State('waitForPlayerPatterns', self.enterWaitForPlayerPatterns, self.exitWaitForPlayerPatterns, ['playBackPatterns', 'cleanup', 'checkGameOver']), + State('playBackPatterns', self.enterPlayBackPatterns, self.exitPlayBackPatterns, ['checkGameOver', 'cleanup']), + State('checkGameOver', self.enterCheckGameOver, self.exitCheckGameOver, ['waitForServerPattern', 'cleanup']), + State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup') self.addChildGameFSM(self.gameFSM) self.arrowColor = VBase4(1, 0, 0, 1) self.xColor = VBase4(1, 0, 0, 1) @@ -63,7 +77,6 @@ class DistributedPatternGame(DistributedMinigame): self.opaq = VBase4(1, 0, 0, 1) self.normalTextColor = VBase4(0.537, 0.84, 0.33, 1.0) self.__otherToonIndex = {} - return def getTitle(self): return TTLocalizer.PatternGameTitle @@ -78,10 +91,10 @@ class DistributedPatternGame(DistributedMinigame): def load(self): self.notify.debug('load') DistributedMinigame.load(self) - self.timer = ToontownTimer.ToontownTimer() + self.timer = ToontownTimer() self.timer.posInTopRightCorner() self.timer.hide() - self.room = loader.loadModel('phase_4/models/minigames/matching_room') + self.room = base.loader.loadModel('phase_4/models/minigames/matching_room') self.buttonSounds = [] for soundName in self.ButtonSoundNames: self.buttonSounds.append(base.loader.loadSfx(soundName)) @@ -95,18 +108,18 @@ class DistributedPatternGame(DistributedMinigame): self.roundText = DirectLabel(text=self.strRound % 1, text_fg=self.normalTextColor, frameColor=(1, 1, 1, 0), text_font=ToontownGlobals.getSignFont(), pos=(0.014, 0, -.84), scale=0.12) self.roundText.hide() self.waitingText.hide() - matchingGameGui = loader.loadModel('phase_3.5/models/gui/matching_game_gui') + matchingGameGui = base.loader.loadModel('phase_3.5/models/gui/matching_game_gui') minnieArrow = matchingGameGui.find('**/minnieArrow') minnieX = matchingGameGui.find('**/minnieX') minnieCircle = matchingGameGui.find('**/minnieCircle') self.arrows = [None] * 5 for x in range(0, 5): - self.arrows[x] = minnieArrow.copyTo(hidden) + self.arrows[x] = minnieArrow.copyTo(base.hidden) self.arrows[x].hide() self.xs = [None] * 5 for x in range(0, 5): - self.xs[x] = minnieX.copyTo(hidden) + self.xs[x] = minnieX.copyTo(base.hidden) self.xs[x].hide() self.statusBalls = [] @@ -116,20 +129,20 @@ class DistributedPatternGame(DistributedMinigame): for x in range(0, 4): for y in range(0, self.totalMoves): - self.statusBalls[x][y] = minnieCircle.copyTo(hidden) + self.statusBalls[x][y] = minnieCircle.copyTo(base.hidden) self.statusBalls[x][y].hide() minnieArrow.removeNode() minnieX.removeNode() minnieCircle.removeNode() matchingGameGui.removeNode() - self.minnie = Char.Char() + self.minnie = Char() m = self.minnie - dna = CharDNA.CharDNA() + dna = CharDNA() dna.newChar('mn') m.setDNA(dna) m.setName(TTLocalizer.Minnie) - m.reparentTo(hidden) + m.reparentTo(base.hidden) self.backRowHome = Point3(3, 11, 0) self.backRowXSpacing = 1.8 self.frontRowHome = Point3(0, 18, 0) @@ -140,12 +153,10 @@ class DistributedPatternGame(DistributedMinigame): self.animPlayRates = [] animPlayRate = 1.4 animPlayRateMult = 1.06 - for i in range(PatternGameGlobals.NUM_ROUNDS): + for _ in range(PatternGameGlobals.NUM_ROUNDS): self.animPlayRates.append(animPlayRate) animPlayRate *= animPlayRateMult - return - def unload(self): self.notify.debug('unload') DistributedMinigame.unload(self) @@ -201,12 +212,12 @@ class DistributedPatternGame(DistributedMinigame): DistributedMinigame.onstage(self) self.arrowDict = {} self.lt = base.localAvatar - camera.reparentTo(render) - camera.setPosHpr(0.0, -14.59, 10.56, 0.0, -16.39, 0.0) + base.camera.reparentTo(base.render) + base.camera.setPosHpr(0.0, -14.59, 10.56, 0.0, -16.39, 0.0) base.camLens.setFov(24.66) NametagGlobals.setGlobalNametagScale(0.6) - self.arrowKeys = ArrowKeys.ArrowKeys() - self.room.reparentTo(render) + self.arrowKeys = ArrowKeys() + self.room.reparentTo(base.render) self.room.setPosHpr(0.0, 18.39, -ToontownGlobals.FloorOffset, 0.0, 0.0, 0.0) self.room.setScale(1) for anim in self.minnieAnimNames: @@ -226,7 +237,7 @@ class DistributedPatternGame(DistributedMinigame): self.toonAnimSpeedMult[anim] = float(self.__numPingPongFrames(numFrames)) / float(self.stdNumDanceStepPingPongFrames) lt = self.lt - lt.reparentTo(render) + lt.reparentTo(base.render) lt.useLOD(1000) lt.setPos(-3.5, 11, 0.0) lt.setScale(1) @@ -246,11 +257,12 @@ class DistributedPatternGame(DistributedMinigame): else: self.arrowDict['lt'][k].setScale(4, 4, 4) self.arrowDict['lt'][k].setColor(self.xColor) + self.arrowDict['lt'][k].setPos(0, 0, 1) self.formatStatusBalls(self.arrowDict['lt'][2], jj) m = self.minnie - m.reparentTo(render) + m.reparentTo(base.render) m.setPos(-1.6, 20, 0) m.setScale(1) self.makeToonLookatCamera(m) @@ -280,13 +292,13 @@ class DistributedPatternGame(DistributedMinigame): NametagGlobals.setGlobalNametagScale(1.0) self.arrowKeys.destroy() del self.arrowKeys - self.room.reparentTo(hidden) + self.room.reparentTo(base.hidden) self.roundText.hide() self.minnie.nametag.unmanage(base.marginManager) self.minnie.stopEarTask() self.minnie.stop() self.minnie.stopBlink() - self.minnie.reparentTo(hidden) + self.minnie.reparentTo(base.hidden) self.lt.setScale(1) for avId in self.remoteAvIdList: toon = self.getAvatar(avId) @@ -303,9 +315,11 @@ class DistributedPatternGame(DistributedMinigame): def setGameReady(self): if not self.hasLocalToon: return + self.notify.debug('setGameReady') if DistributedMinigame.setGameReady(self): return + for avId in self.remoteAvIdList: toon = self.getAvatar(avId) if toon: @@ -321,10 +335,11 @@ class DistributedPatternGame(DistributedMinigame): else: self.arrowDict[avId][k].setScale(4, 4, 4) self.arrowDict[avId][k].setColor(self.xColor) + self.arrowDict[avId][k].setPos(0, 0, 1) self.formatStatusBalls(self.arrowDict[avId][2], jj) - toon.reparentTo(render) + toon.reparentTo(base.render) toon.useLOD(1000) toon.setPos(self.getBackRowPos(avId)) toon.setScale(0.9) @@ -338,16 +353,17 @@ class DistributedPatternGame(DistributedMinigame): self.waitingText['text'] = self.strPleaseWait else: self.waitingText['text'] = self.strWaitingOtherPlayers + self.animTracks = {} for avId in self.avIdList: self.animTracks[avId] = None self.__initGameVars() - return def setGameStart(self, timestamp): if not self.hasLocalToon: return + self.notify.debug('setGameStart') DistributedMinigame.setGameStart(self, timestamp) self.gameFSM.request('waitForServerPattern') @@ -360,7 +376,7 @@ class DistributedPatternGame(DistributedMinigame): return numFrames * 2 - 1 def makeToonLookatCamera(self, toon): - toon.headsUp(camera) + toon.headsUp(base.camera) def setText(self, t, newtext): t['text'] = newtext @@ -376,6 +392,7 @@ class DistributedPatternGame(DistributedMinigame): if startPos: toon.setPos(startPos) track.append(Func(toon.setPos, startPos)) + for endPos in posList: toon.headsUp(Point3(endPos)) track.append(Func(toon.setHpr, Point3(toon.getH(), 0, 0))) @@ -387,14 +404,16 @@ class DistributedPatternGame(DistributedMinigame): if lookAtCam: saveHpr = toon.getHpr() - toon.headsUp(camera) + toon.headsUp(base.camera) endHeading = toon.getHpr()[0] toon.setHpr(saveHpr) + curHeading = toon.getH() if endHeading - curHeading > 180.0: endHeading -= 360 elif endHeading - curHeading < -180.0: endHeading += 360 + endHpr = Point3(endHeading, 0, 0) duration = abs(endHeading - curHeading) / 180.0 * 0.3 track.extend([Func(toon.loop, 'walk'), LerpHprInterval(toon, duration, endHpr), Func(toon.loop, 'neutral')]) @@ -456,6 +475,7 @@ class DistributedPatternGame(DistributedMinigame): ri.append(ActorInterval(actor=self.lt, animName='victory', duration=5.5)) else: ri.append(Func(self.lt.loop, 'neutral')) + for avId in self.remoteAvIdList: toon = self.getAvatar(avId) if toon: @@ -503,18 +523,21 @@ class DistributedPatternGame(DistributedMinigame): track = Sequence(Func(self.changeArrow, toonID, index), Wait(wait)) else: track = Sequence(Func(self.changeArrow, toonID, index), Wait(wait), LerpColorInterval(self.arrowDict[toonID][0], d, self.trans, self.opaq)) + return track def getDanceSequenceAnimTrack(self, toon, pattern): getDanceStepTrack = self.__getToonDanceStepAnimTrack if toon == self.minnie: getDanceStepTrack = self.__getMinnieDanceStepAnimTrack + tracks = Sequence() for direction in pattern: tracks.append(getDanceStepTrack(toon, direction)) if len(pattern): tracks.append(Func(toon.loop, 'neutral')) + return tracks def getDanceSequenceButtonSoundTrack(self, pattern): @@ -558,6 +581,7 @@ class DistributedPatternGame(DistributedMinigame): def setPattern(self, pattern): if not self.hasLocalToon: return + self.notify.debug('setPattern: ' + str(pattern)) self.__serverPattern = pattern self.gameFSM.request('showServerPattern') @@ -591,6 +615,7 @@ class DistributedPatternGame(DistributedMinigame): def exitShowServerPattern(self): if self.showTrack.isPlaying(): self.showTrack.pause() + del self.showTrack def enterGetUserInput(self): @@ -599,7 +624,7 @@ class DistributedPatternGame(DistributedMinigame): self.proceedTrack = None def startTimer(self = self): - self.currentStartTime = globalClock.getFrameTime() + self.currentStartTime = base.clock.getFrameTime() self.timer.show() self.timer.countdown(PatternGameGlobals.InputTime, self.__handleInputTimeout) @@ -629,7 +654,6 @@ class DistributedPatternGame(DistributedMinigame): self.setupTrack = Sequence(Func(self.__setMinnieChat, self.strGo, 0), Func(self.setText, self.roundText, TTLocalizer.PatternGameGo), Func(self.roundText.setScale, 0.3), Func(enableKeys), Func(startTimer), Wait(0.8), Func(self.__clearMinnieChat), Func(self.setText, self.roundText, ' '), Func(self.roundText.setScale, 0.12), Func(self.setTextFG, self.roundText, self.normalTextColor)) self.setupTrack.start() - return def __handleInputTimeout(self): self.__doneGettingInput(self.__localPattern) @@ -643,15 +667,18 @@ class DistributedPatternGame(DistributedMinigame): def remoteButtonPressed(self, avId, index, wrong): if not self.hasLocalToon: return + if self.gameFSM.getCurrentState().getName() not in ['getUserInput', 'waitForPlayerPatterns']: return + if avId != self.localAvId: if self.animTracks[avId]: self.animTracks[avId].finish() + av = self.getAvatar(avId) if wrong: acts = ['slip-forward', 'slip-backward'] - ag = random.choice(acts) + ag = choice(acts) self.arrowDict[avId][0].hide() self.animTracks[avId] = Sequence(Func(self.showX, avId), Func(self.colorStatusBall, avId, self.__otherToonIndex[avId], 0), ActorInterval(actor=av, animName=ag, duration=2.35), Func(av.loop, 'neutral'), Func(self.hideX, avId)) else: @@ -659,6 +686,7 @@ class DistributedPatternGame(DistributedMinigame): arrowTrack = self.getDanceArrowAnimTrack(avId, [index], 1) potTrack = self.getDanceSequenceAnimTrack(av, [index]) self.animTracks[avId] = Parallel(potTrack, arrowTrack) + self.__otherToonIndex[avId] += 1 self.animTracks[avId].start() @@ -668,13 +696,15 @@ class DistributedPatternGame(DistributedMinigame): def __buttonPressed(self, index): if len(self.__localPattern) >= len(self.__serverPattern): return + if self.animTracks[self.localAvId]: self.animTracks[self.localAvId].finish() + badd = 0 if index != self.__serverPattern[len(self.__localPattern)]: badd = 1 acts = ['slip-forward', 'slip-backward'] - ag = random.choice(acts) + ag = choice(acts) self.animTracks[self.localAvId] = Sequence(Func(self.showX, 'lt'), Func(self.colorStatusBall, 'lt', len(self.__localPattern), 0), ActorInterval(actor=self.lt, animName=ag, duration=2.35), Func(self.lt.loop, 'neutral'), Func(self.hideX, 'lt')) self.arrowDict['lt'][0].hide() base.playSfx(self.fallSound) @@ -684,6 +714,7 @@ class DistributedPatternGame(DistributedMinigame): arrowTrack = self.getDanceArrowAnimTrack('lt', [index], 1) potTrack = self.getDanceSequenceAnimTrack(self.lt, [index]) self.animTracks[self.localAvId] = Parallel(potTrack, arrowTrack) + self.sendUpdate('reportButtonPress', [index, badd]) self.animTracks[self.localAvId].start() self.__localPattern.append(index) @@ -692,7 +723,7 @@ class DistributedPatternGame(DistributedMinigame): def __doneGettingInput(self, pattern): self.arrowKeys.setPressHandlers(self.arrowKeys.NULL_HANDLERS) - self.currentTotalTime = globalClock.getFrameTime() - self.currentStartTime + self.currentTotalTime = base.clock.getFrameTime() - self.currentStartTime self.proceedTrack = Sequence(Wait(self.getDanceStepDuration()), Func(self.sendUpdate, 'reportPlayerPattern', [pattern, self.currentTotalTime]), Func(self.gameFSM.request, 'waitForPlayerPatterns')) self.proceedTrack.start() @@ -703,8 +734,10 @@ class DistributedPatternGame(DistributedMinigame): self.arrowKeys.setReleaseHandlers(self.arrowKeys.NULL_HANDLERS) if self.setupTrack and self.setupTrack.isPlaying(): self.setupTrack.pause() + if self.proceedTrack and self.proceedTrack.isPlaying(): self.proceedTrack.pause() + del self.setupTrack del self.proceedTrack self.__clearMinnieChat() @@ -715,6 +748,7 @@ class DistributedPatternGame(DistributedMinigame): def setPlayerPatterns(self, pattern1, pattern2, pattern3, pattern4, fastestAvId): if not self.hasLocalToon: return + self.fastestAvId = fastestAvId self.notify.debug('setPlayerPatterns:' + ' pattern1:' + str(pattern1) + ' pattern2:' + str(pattern2) + ' pattern3:' + str(pattern3) + ' pattern4:' + str(pattern4)) self.playerPatterns = {} @@ -738,6 +772,7 @@ class DistributedPatternGame(DistributedMinigame): self.roundText['text'] = TTLocalizer.PatternGameFastest else: self.roundText['text'] = TTLocalizer.PatternGameFaster + jumpTrack = Sequence(ActorInterval(actor=self.lt, animName='jump', duration=1.7), Func(self.lt.loop, 'neutral')) elif self.fastestAvId == 0: if self.round == PatternGameGlobals.NUM_ROUNDS: @@ -745,6 +780,7 @@ class DistributedPatternGame(DistributedMinigame): else: self.roundText.setScale(0.1) self.roundText['text'] = TTLocalizer.PatternGameYouCanDoIt + jumpTrack = Sequence(Wait(0.5), Wait(0.5)) elif self.fastestAvId == 1: self.roundText.setScale(0.1) @@ -758,7 +794,9 @@ class DistributedPatternGame(DistributedMinigame): rewardStr = TTLocalizer.PatternGameOtherFastest else: rewardStr = TTLocalizer.PatternGameOtherFaster + self.roundText['text'] = av.getName() + rewardStr + success = self.playerPatterns[self.localAvId] == self.__serverPattern self.hideStatusBalls('lt') for avId in self.remoteAvIdList: @@ -771,6 +809,7 @@ class DistributedPatternGame(DistributedMinigame): self.perfectGame = 0 sound = self.incorrectSound text = self.strWrong + soundTrack = Sequence(Func(base.playSfx, sound), Wait(1.6)) textTrack = Sequence(Wait(0.2), Func(self.__setMinnieChat, text, 0), Wait(1.3), Func(self.__clearMinnieChat)) self.playBackPatternsTrack = Sequence(Parallel(soundTrack, textTrack, jumpTrack), Func(self.gameFSM.request, 'checkGameOver')) @@ -779,6 +818,7 @@ class DistributedPatternGame(DistributedMinigame): def exitPlayBackPatterns(self): if self.playBackPatternsTrack.isPlaying(): self.playBackPatternsTrack.pause() + del self.playBackPatternsTrack def enterCheckGameOver(self): @@ -794,17 +834,19 @@ class DistributedPatternGame(DistributedMinigame): text = self.strPerfect sound = self.perfectSound delay = 2.2 + if self.celebrate: text = TTLocalizer.PatternGameImprov self.__winTrack = Sequence(Func(self.__setMinnieChat, text, 1), Func(base.playSfx, self.perfectSound), Sequence(self.returnCelebrationIntervals(1)), Sequence(self.returnCelebrationIntervals(0)), Func(self.__clearMinnieChat), Func(self.gameOver)) else: self.__winTrack = Sequence(Func(self.__setMinnieChat, text, 1), Func(base.playSfx, sound), Wait(delay), Func(self.__clearMinnieChat), Func(self.gameOver)) + self.__winTrack.start() - return def exitCheckGameOver(self): if self.__winTrack and self.__winTrack.isPlaying(): self.__winTrack.pause() + del self.__winTrack def enterCleanup(self): diff --git a/toontown/minigame/DistributedTugOfWarGame.py b/toontown/minigame/DistributedTugOfWarGame.py index 7530efe..2dcae83 100644 --- a/toontown/minigame/DistributedTugOfWarGame.py +++ b/toontown/minigame/DistributedTugOfWarGame.py @@ -1,30 +1,42 @@ -from panda3d.core import * -from toontown.toonbase.ToonBaseGlobal import * -from direct.interval.IntervalGlobal import * -from .DistributedMinigame import * -from direct.gui.DirectGui import * -from panda3d.core import * -from direct.fsm import ClassicFSM, State -from direct.fsm import State -from toontown.toonbase import ToontownTimer -from toontown.toon import ToonHead -from toontown.suit import SuitDNA -from toontown.suit import Suit -from toontown.char import Char -from . import ArrowKeys -import random +from panda3d.core import RopeNode, VBase3 +from panda3d.otp import NametagGlobals + +from direct.directnotify.DirectNotifyGlobal import directNotify +from direct.fsm.ClassicFSM import ClassicFSM +from direct.fsm.State import State +from direct.gui.DirectGui import DGG, DirectLabel +from direct.interval.IntervalGlobal import ( + ActorInterval, + Func, + LerpHprInterval, + LerpPosInterval, + LerpPosHprInterval, + Parallel, + Sequence, + Wait +) + +from direct.showutil.Rope import Rope +from direct.task.TaskManagerGlobal import taskMgr + +from toontown.effects.Ripples import Ripples +from toontown.effects.Splash import Splash +from toontown.minigame import TugOfWarGameGlobals +from toontown.minigame.ArrowKeys import ArrowKeys +from toontown.minigame.DistributedMinigame import DistributedMinigame +from toontown.minigame.MinigamePowerMeter import MinigamePowerMeter +from toontown.suit.Suit import Suit +from toontown.suit.SuitDNA import SuitDNA from toontown.toonbase import ToontownGlobals -import string from toontown.toonbase import TTLocalizer -from . import TugOfWarGameGlobals -from direct.showutil import Rope -from toontown.effects import Splash -from toontown.effects import Ripples -from toontown.toonbase import TTLocalizer -from . import MinigamePowerMeter -from direct.task.Task import Task +from toontown.toonbase.ToonBaseGlobal import base +from toontown.toonbase.ToontownTimer import ToontownTimer + +import math + class DistributedTugOfWarGame(DistributedMinigame): + notify = directNotify.newCategory('DistributedTugOfWarGame') bgm = 'phase_4/audio/bgm/MG_tug_o_war.ogg' toonAnimNames = ['neutral', 'tug-o-war', @@ -46,11 +58,11 @@ class DistributedTugOfWarGame(DistributedMinigame): def __init__(self, cr): DistributedMinigame.__init__(self, cr) - self.gameFSM = ClassicFSM.ClassicFSM('DistributedTugOfWarGame', [State.State('off', self.enterOff, self.exitOff, ['waitForGoSignal']), - State.State('waitForGoSignal', self.enterWaitForGoSignal, self.exitWaitForGoSignal, ['tug', 'cleanup']), - State.State('tug', self.enterTug, self.exitTug, ['gameDone', 'cleanup']), - State.State('gameDone', self.enterGameDone, self.exitGameDone, ['cleanup']), - State.State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup') + self.gameFSM = ClassicFSM('DistributedTugOfWarGame', [State('off', self.enterOff, self.exitOff, ['waitForGoSignal']), + State('waitForGoSignal', self.enterWaitForGoSignal, self.exitWaitForGoSignal, ['tug', 'cleanup']), + State('tug', self.enterTug, self.exitTug, ['gameDone', 'cleanup']), + State('gameDone', self.enterGameDone, self.exitGameDone, ['cleanup']), + State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup') self.addChildGameFSM(self.gameFSM) self.gameType = TugOfWarGameGlobals.TOON_VS_TOON self.suit = None @@ -92,13 +104,11 @@ class DistributedTugOfWarGame(DistributedMinigame): for k in range(4): self.drinkPositions.append(VBase3(-.2 + 0.2 * k, 16 + 2 * k, 0.0)) - self.rng = RandomNumGen.RandomNumGen(1000) self.introTrack = None self.showTrack = None self.setupTrack = None self.animTracks = {} self.randomNumGen = None - return def getTitle(self): return TTLocalizer.TugOfWarGameTitle @@ -112,40 +122,39 @@ class DistributedTugOfWarGame(DistributedMinigame): def load(self): self.notify.debug('load') DistributedMinigame.load(self) - self.timer = ToontownTimer.ToontownTimer() + self.timer = ToontownTimer() self.timer.posInTopRightCorner() self.timer.hide() - self.room = loader.loadModel('phase_4/models/minigames/tug_of_war_dock') - self.room.reparentTo(hidden) - ropeModel = loader.loadModel('phase_4/models/minigames/tug_of_war_rope') + self.room = base.loader.loadModel('phase_4/models/minigames/tug_of_war_dock') + self.room.reparentTo(base.hidden) + ropeModel = base.loader.loadModel('phase_4/models/minigames/tug_of_war_rope') self.ropeTexture = ropeModel.findTexture('*') ropeModel.removeNode() - self.sky = loader.loadModel('phase_3.5/models/props/TT_sky') - self.dropShadow = loader.loadModel('phase_3/models/props/drop_shadow') + self.sky = base.loader.loadModel('phase_3.5/models/props/TT_sky') + self.dropShadow = base.loader.loadModel('phase_3/models/props/drop_shadow') self.correctSound = base.loader.loadSfx('phase_4/audio/sfx/MG_pos_buzzer.ogg') self.sndHitWater = base.loader.loadSfx('phase_4/audio/sfx/MG_cannon_splash.ogg') self.whistleSound = base.loader.loadSfx('phase_4/audio/sfx/AA_sound_whistle.ogg') self.music = base.loader.loadMusic(self.bgm) self.roundText = DirectLabel(text=' ', text_fg=(0, 1, 0, 1), frameColor=(1, 1, 1, 0), text_font=ToontownGlobals.getSignFont(), pos=(0.014, 0, -.84), scale=0.2) - self.powerMeter = MinigamePowerMeter.MinigamePowerMeter(17) - self.powerMeter.reparentTo(aspect2d) + self.powerMeter = MinigamePowerMeter(17) + self.powerMeter.reparentTo(base.aspect2d) self.powerMeter.setPos(0, 0, 0.4) self.powerMeter.setPower(8) self.powerMeter.setTarget(8) self.arrows = [None] * 2 for x in range(len(self.arrows)): - self.arrows[x] = loader.loadModel('phase_3/models/props/arrow') + self.arrows[x] = base.loader.loadModel('phase_3/models/props/arrow') self.arrows[x].reparentTo(self.powerMeter) self.arrows[x].hide() self.arrows[x].setScale(0.2 - 0.4 * x, 0.2, 0.2) self.arrows[x].setPos(0.12 - 0.24 * x, 0, -.26) self.disableArrow(self.arrows[x]) - self.splash = Splash.Splash(render) - self.suitSplash = Splash.Splash(render) - self.ripples = Ripples.Ripples(render) - self.suitRipples = Ripples.Ripples(render) - return + self.splash = Splash(base.render) + self.suitSplash = Splash(base.render) + self.ripples = Ripples(base.render) + self.suitRipples = Ripples(base.render) def toggleMouseMode(self, param): self.mouseMode = not self.mouseMode @@ -155,6 +164,7 @@ class DistributedTugOfWarGame(DistributedMinigame): self.hilightArrow(self.arrows[1]) else: self.hilightArrow(self.arrows[0]) + self.__spawnMouseSpeedTask() else: self.__releaseHandler(0) @@ -183,6 +193,7 @@ class DistributedTugOfWarGame(DistributedMinigame): if self.powerMeter: self.powerMeter.destroy() del self.powerMeter + for x in self.arrows: if x: x.removeNode() @@ -197,10 +208,12 @@ class DistributedTugOfWarGame(DistributedMinigame): self.ripples.stop() self.ripples.detachNode() del self.ripples + if self.suitRipples != None: self.suitRipples.stop() self.suitRipples.detachNode() del self.suitRipples + for x in self.avList: del x @@ -208,6 +221,7 @@ class DistributedTugOfWarGame(DistributedMinigame): for x in self.tugRopes: if x != None: x.detachNode() + del x del self.tugRopes @@ -235,6 +249,7 @@ class DistributedTugOfWarGame(DistributedMinigame): if self.suit: self.suit.delete() del self.suit + del self.sides del self.buttons del self.pullingDict @@ -245,26 +260,24 @@ class DistributedTugOfWarGame(DistributedMinigame): del self.drinkPositions del self.offsetDict del self.keyTTL - del self.rng - return def onstage(self): self.notify.debug('onstage') DistributedMinigame.onstage(self) self.lt = base.localAvatar NametagGlobals.setGlobalNametagScale(1) - self.arrowKeys = ArrowKeys.ArrowKeys() - self.room.reparentTo(render) + self.arrowKeys = ArrowKeys() + self.room.reparentTo(base.render) self.room.setPosHpr(0.0, 18.39, -ToontownGlobals.FloorOffset, 0.0, 0.0, 0.0) self.room.setScale(0.4) self.sky.setZ(-5) - self.sky.reparentTo(render) + self.sky.reparentTo(base.render) self.dropShadow.setColor(0, 0, 0, 0.5) - camera.reparentTo(render) - camera.setPosHpr(-11.4427, 9.03559, 2.80094, -49.104, -0.89, 0) + base.camera.reparentTo(base.render) + base.camera.setPosHpr(-11.4427, 9.03559, 2.80094, -49.104, -0.89, 0) self.dropShadow.setBin('fixed', 0, 1) - self.splash.reparentTo(render) - self.suitSplash.reparentTo(render) + self.splash.reparentTo(base.render) + self.suitSplash.reparentTo(base.render) base.playMusic(self.music, looping=1, volume=1) for x in range(len(self.arrows)): self.arrows[x].show() @@ -280,20 +293,24 @@ class DistributedTugOfWarGame(DistributedMinigame): self.introTrack.finish() del self.introTrack self.introTrack = None + for track in list(self.animTracks.values()): if track: track.finish() del track + self.animTracks = {} if self.showTrack: self.showTrack.finish() del self.showTrack self.showTrack = None + if self.setupTrack: self.setupTrack.finish() del self.setupTrack self.setupTrack = None + base.camLens.setFov(ToontownGlobals.DefaultCameraFov) base.camLens.setNearFar(ToontownGlobals.DefaultCameraNear, ToontownGlobals.DefaultCameraFar) NametagGlobals.setGlobalNametagScale(1.0) @@ -303,13 +320,14 @@ class DistributedTugOfWarGame(DistributedMinigame): self.arrowKeys.destroy() del self.arrowKeys self.arrowKeys = None - self.room.reparentTo(hidden) - self.sky.reparentTo(hidden) - self.splash.reparentTo(hidden) + + self.room.reparentTo(base.hidden) + self.sky.reparentTo(base.hidden) + self.splash.reparentTo(base.hidden) self.splash.stop() - self.suitSplash.reparentTo(hidden) + self.suitSplash.reparentTo(base.hidden) self.suitSplash.stop() - self.ripples.reparentTo(hidden) + self.ripples.reparentTo(base.hidden) self.ripples.stop() self.hideControls() self.roundText.hide() @@ -322,42 +340,36 @@ class DistributedTugOfWarGame(DistributedMinigame): for x in self.tugRopes: if x != None: - x.reparentTo(hidden) + x.reparentTo(base.hidden) if self.suit: - self.suit.reparentTo(hidden) + self.suit.reparentTo(base.hidden) + for avId in self.avIdList: if avId in self.dropShadowDict: - self.dropShadowDict[avId].reparentTo(hidden) + self.dropShadowDict[avId].reparentTo(base.hidden) if self.suitId in self.dropShadowDict: - self.dropShadowDict[self.suitId].reparentTo(hidden) - return + self.dropShadowDict[self.suitId].reparentTo(base.hidden) def initCamera(self): - birdseyePosHpr = [1.95461, - 18.4891, - 38.4646, - 1.18185, - -87.5308, - 0] introPosHpr = [None] * 2 introPosHpr[0] = [VBase3(-11.4427, 9.03559, 2.80094), VBase3(-49.104, -0.732374, 0)] introPosHpr[1] = [VBase3(16.9291, 13.9302, 2.64282), VBase3(66.9685, -6.195, 0)] gameCamHpr = VBase3(-1.13, 1.042, 0) gameCamPos = VBase3(0, 1.0838, 2.745) - camera.reparentTo(render) - camera.setPosHpr(introPosHpr[self.sides[self.localAvId]][0], introPosHpr[self.sides[self.localAvId]][1]) + base.camera.reparentTo(base.render) + base.camera.setPosHpr(introPosHpr[self.sides[self.localAvId]][0], introPosHpr[self.sides[self.localAvId]][1]) lerpDur = 8 - self.introTrack = LerpPosHprInterval(camera, lerpDur, pos=gameCamPos, hpr=gameCamHpr, blendType='easeInOut', name=self.uniqueName('introLerpCameraPos')) + self.introTrack = LerpPosHprInterval(base.camera, lerpDur, pos=gameCamPos, hpr=gameCamHpr, blendType='easeInOut', name=self.uniqueName('introLerpCameraPos')) self.introTrack.start() base.camLens.setFov(60 + 2 * self.numPlayers) base.camLens.setFar(450.0) - return def sendGameType(self, index, suit): if not self.hasLocalToon: return + self.gameType = index self.suitLevel = suit if suit == 1: @@ -372,9 +384,11 @@ class DistributedTugOfWarGame(DistributedMinigame): def setGameReady(self): if not self.hasLocalToon: return + self.notify.debug('setGameReady') if DistributedMinigame.setGameReady(self): return + self.initToons() self.createSuits() self.calculatePositions() @@ -389,7 +403,6 @@ class DistributedTugOfWarGame(DistributedMinigame): self.showTrack = None self.setupTrack = None self.__initGameVars() - return def hideControls(self): for x in range(len(self.arrows)): @@ -397,40 +410,39 @@ class DistributedTugOfWarGame(DistributedMinigame): for rope in self.tugRopes: if rope != None: - rope.reparentTo(hidden) + rope.reparentTo(base.hidden) for tex in self.ropeTex: if tex != None: for texi in tex: if texi: - texi.reparentTo(hidden) + texi.reparentTo(base.hidden) if self.powerMeter != None: self.powerMeter.unbind(DGG.B1PRESS) self.powerMeter.unbind(DGG.B1RELEASE) self.powerMeter.hide() - return def setUpRopes(self, notTaut): if self.numPlayers == 1: suitRightHand = self.suit.getRightHand() toonRightHand = self.rightHandDict[self.avIdList[0]] if notTaut: - self.tugRopes[0].setup(3, ((toonRightHand, (0, 0, 0)), (render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0, + self.tugRopes[0].setup(3, ((toonRightHand, (0, 0, 0)), (base.render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0, 0, 0, 1, 1, 1]) else: - midPt = (suitRightHand.getPos() - toonRightHand.getPos()) / 2.0 self.tugRopes[0].setup(3, ((toonRightHand, (0, 0, 0)), (toonRightHand, (0, 0, 0)), (suitRightHand, (0, 0, 0))), [0, 0, 0, 1, 1, 1]) - self.tugRopes[0].reparentTo(render) + + self.tugRopes[0].reparentTo(base.render) elif self.numPlayers == 2: if self.gameType == TugOfWarGameGlobals.TOON_VS_COG: self.tugRopes[0].setup(3, ((self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0))), [0, @@ -442,25 +454,25 @@ class DistributedTugOfWarGame(DistributedMinigame): suitRightHand = self.suit.getRightHand() toonRightHand = self.rightHandDict[self.avIdList[1]] if notTaut: - self.tugRopes[1].setup(3, ((toonRightHand, (0, 0, 0)), (render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0, + self.tugRopes[1].setup(3, ((toonRightHand, (0, 0, 0)), (base.render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0, 0, 0, 1, 1, 1]) else: - midPt = (suitRightHand.getPos() - toonRightHand.getPos()) / 2.0 self.tugRopes[1].setup(3, ((toonRightHand, (0, 0, 0)), (toonRightHand, (0, 0, 0)), (suitRightHand, (0, 0, 0))), [0, 0, 0, 1, 1, 1]) - self.tugRopes[0].reparentTo(render) - self.tugRopes[1].reparentTo(render) + + self.tugRopes[0].reparentTo(base.render) + self.tugRopes[1].reparentTo(base.render) else: if notTaut: - self.tugRopes[0].setup(3, ((self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (render, (0, 18, -1)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0))), [0, + self.tugRopes[0].setup(3, ((self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (base.render, (0, 18, -1)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0))), [0, 0, 0, 1, @@ -473,7 +485,8 @@ class DistributedTugOfWarGame(DistributedMinigame): 1, 1, 1]) - self.tugRopes[0].reparentTo(render) + + self.tugRopes[0].reparentTo(base.render) elif self.numPlayers == 3: if self.gameType == TugOfWarGameGlobals.TOON_VS_COG: self.tugRopes[1].setup(3, ((self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0))), [0, @@ -491,26 +504,26 @@ class DistributedTugOfWarGame(DistributedMinigame): suitRightHand = self.suit.getRightHand() toonRightHand = self.rightHandDict[self.avIdList[2]] if notTaut: - self.tugRopes[2].setup(3, ((toonRightHand, (0, 0, 0)), (render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0, + self.tugRopes[2].setup(3, ((toonRightHand, (0, 0, 0)), (base.render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0, 0, 0, 1, 1, 1]) else: - midPt = (suitRightHand.getPos() - toonRightHand.getPos()) / 2.0 self.tugRopes[2].setup(3, ((toonRightHand, (0, 0, 0)), (toonRightHand, (0, 0, 0)), (suitRightHand, (0, 0, 0))), [0, 0, 0, 1, 1, 1]) - self.tugRopes[0].reparentTo(render) - self.tugRopes[1].reparentTo(render) - self.tugRopes[2].reparentTo(render) + + self.tugRopes[0].reparentTo(base.render) + self.tugRopes[1].reparentTo(base.render) + self.tugRopes[2].reparentTo(base.render) else: if notTaut: - self.tugRopes[1].setup(3, ((self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (render, (0, 18, -1)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0))), [0, + self.tugRopes[1].setup(3, ((self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (base.render, (0, 18, -1)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0))), [0, 0, 0, 1, @@ -523,14 +536,15 @@ class DistributedTugOfWarGame(DistributedMinigame): 1, 1, 1]) + self.tugRopes[0].setup(3, ((self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0))), [0, 0, 0, 1, 1, 1]) - self.tugRopes[0].reparentTo(render) - self.tugRopes[1].reparentTo(render) + self.tugRopes[0].reparentTo(base.render) + self.tugRopes[1].reparentTo(base.render) elif self.numPlayers == 4: if self.gameType == TugOfWarGameGlobals.TOON_VS_COG: self.tugRopes[2].setup(3, ((self.rightHandDict[self.avIdList[2]], (0, 0, 0)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0)), (self.rightHandDict[self.avIdList[3]], (0, 0, 0))), [0, @@ -554,24 +568,24 @@ class DistributedTugOfWarGame(DistributedMinigame): suitRightHand = self.suit.getRightHand() toonRightHand = self.rightHandDict[self.avIdList[3]] if notTaut: - self.tugRopes[3].setup(3, ((toonRightHand, (0, 0, 0)), (render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0, + self.tugRopes[3].setup(3, ((toonRightHand, (0, 0, 0)), (base.render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0, 0, 0, 1, 1, 1]) else: - midPt = (suitRightHand.getPos() - toonRightHand.getPos()) / 2.0 self.tugRopes[3].setup(3, ((toonRightHand, (0, 0, 0)), (toonRightHand, (0, 0, 0)), (suitRightHand, (0, 0, 0))), [0, 0, 0, 1, 1, 1]) - self.tugRopes[0].reparentTo(render) - self.tugRopes[1].reparentTo(render) - self.tugRopes[2].reparentTo(render) - self.tugRopes[3].reparentTo(render) + + self.tugRopes[0].reparentTo(base.render) + self.tugRopes[1].reparentTo(base.render) + self.tugRopes[2].reparentTo(base.render) + self.tugRopes[3].reparentTo(base.render) else: self.tugRopes[2].setup(3, ((self.rightHandDict[self.avIdList[2]], (0, 0, 0)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0)), (self.rightHandDict[self.avIdList[3]], (0, 0, 0))), [0, 0, @@ -586,7 +600,7 @@ class DistributedTugOfWarGame(DistributedMinigame): 1, 1]) if notTaut: - self.tugRopes[1].setup(3, ((self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (render, (0, 18, -1)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0))), [0, + self.tugRopes[1].setup(3, ((self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (base.render, (0, 18, -1)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0))), [0, 0, 0, 1, @@ -599,15 +613,16 @@ class DistributedTugOfWarGame(DistributedMinigame): 1, 1, 1]) - self.tugRopes[0].reparentTo(render) - self.tugRopes[1].reparentTo(render) - self.tugRopes[2].reparentTo(render) + + self.tugRopes[0].reparentTo(base.render) + self.tugRopes[1].reparentTo(base.render) + self.tugRopes[2].reparentTo(base.render) def initToons(self): for avId in self.avIdList: toon = self.getAvatar(avId) if toon: - toon.reparentTo(render) + toon.reparentTo(base.render) toon.useLOD(1000) toon.startBlink() toon.startLookAround() @@ -618,7 +633,7 @@ class DistributedTugOfWarGame(DistributedMinigame): self.rightHandDict[avId] = toon.getRightHands()[0] toon.loop('neutral') toon.dropShadow.hide() - self.dropShadowDict[avId] = self.dropShadow.copyTo(hidden) + self.dropShadowDict[avId] = self.dropShadow.copyTo(base.hidden) self.dropShadowDict[avId].reparentTo(toon) self.dropShadowDict[avId].setScale(0.35) @@ -696,6 +711,7 @@ class DistributedTugOfWarGame(DistributedMinigame): self.hprDict[self.avIdList[1]] = hprPositions[0] self.hprDict[self.avIdList[2]] = hprPositions[1] self.hprDict[self.avIdList[3]] = hprPositions[1] + for x in self.avIdList: self.offsetDict[x] = 0 if self.posDict[x][0] < 0: @@ -741,9 +757,11 @@ class DistributedTugOfWarGame(DistributedMinigame): def setGameStart(self, timestamp): if not self.hasLocalToon: return + self.notify.debug('setGameStart') if not self.__playing(): return + DistributedMinigame.setGameStart(self, timestamp) self.gameFSM.request('waitForGoSignal') @@ -751,7 +769,7 @@ class DistributedTugOfWarGame(DistributedMinigame): pass def makeToonLookatCamera(self, toon): - toon.headsUp(camera) + toon.headsUp(base.camera) def setText(self, t, newtext): t['text'] = newtext @@ -788,6 +806,7 @@ class DistributedTugOfWarGame(DistributedMinigame): self.notify.debug('exitTug') if self.suit: self.suit.loop('neutral') + self.timer.stop() self.timer.hide() taskMgr.remove(self.taskName('tug-timeout')) @@ -828,7 +847,8 @@ class DistributedTugOfWarGame(DistributedMinigame): def __updateKeyPressRateTask(self, task): if self.gameFSM.getCurrentState().getName() != 'tug': - return Task.done + return task.done + for i in range(len(self.keyTTL)): self.keyTTL[i] -= 0.1 @@ -844,18 +864,20 @@ class DistributedTugOfWarGame(DistributedMinigame): self.rateMatchAward += 0.3 else: self.rateMatchAward = 0 + self.__spawnUpdateKeyPressRateTask() - return Task.done + return task.done def __updateTimerTask(self, task): if self.gameFSM.getCurrentState().getName() != 'tug': - return Task.done + return task.done + self.currentForce = self.computeForce(self.keyRate) self.sendUpdate('reportCurrentKeyRate', [self.keyRate, self.currentForce]) self.setSpeedGauge() self.setAnimState(self.localAvId, self.keyRate) self.__spawnUpdateTimerTask() - return Task.done + return task.done def __spawnUpdateTimerTask(self): taskMgr.remove(self.taskName(self.UPDATE_TIMER_TASK)) @@ -881,10 +903,12 @@ class DistributedTugOfWarGame(DistributedMinigame): if self.nextRateIndex < len(self.targetRateList): if self.nextRateIndex == len(self.targetRateList) - 1: self.allOutMode = 1 + self.idealRate = self.targetRateList[self.nextRateIndex][1] self.idealForce = self.advantage * (4 + 0.4 * self.idealRate) taskMgr.doMethodLater(self.targetRateList[self.nextRateIndex][0], self.__updateIdealRateTask, self.taskName('targetRateTimer')) - return Task.done + + return task.done def __killUpdateIdealRateTask(self): taskMgr.remove(self.taskName('targetRateTimer')) @@ -892,14 +916,14 @@ class DistributedTugOfWarGame(DistributedMinigame): def sendGoSignal(self, index): if not self.hasLocalToon: return + self.notify.debug('sendGoSignal') self.buttons = index self.setupTrack = None self.showTrack = None def startTimer(self = self): - self.currentStartTime = int(globalClock.getFrameTime() * 1000) - time = 10 + self.currentStartTime = int(base.clock.getFrameTime() * 1000) self.timer.show() self.timer.setTime(TugOfWarGameGlobals.GAME_DURATION) self.timer.countdown(TugOfWarGameGlobals.GAME_DURATION, self.__gameTimerExpired) @@ -926,13 +950,14 @@ class DistributedTugOfWarGame(DistributedMinigame): if self.introTrack != None: self.introTrack.finish() self.introTrack = None + self.setupTrack = Sequence(Func(self.setText, self.roundText, TTLocalizer.TugOfWarGameReady), Wait(1.5), Func(base.playSfx, self.whistleSound), Func(self.setText, self.roundText, TTLocalizer.TugOfWarGameGo), Func(self.roundText.setScale, 0.3), Wait(1.5), Func(startTimer), Func(enableKeys), Func(self.gameFSM.request, 'tug'), Func(self.setText, self.roundText, ' '), Func(self.roundText.setScale, 0.2)) self.setupTrack.start() - return def sendStopSignal(self, winners, losers, tieers): if not self.hasLocalToon: return + self.notify.debug('sendStopSignal') self.gameFSM.request('gameDone') self.hideControls() @@ -941,6 +966,7 @@ class DistributedTugOfWarGame(DistributedMinigame): suitSlipTime = 0 if self.gameFSM.getCurrentState().getName() == 'cleanup' or not self.randomNumGen: return + if self.suit: if self.suitId in winners: newPos = VBase3(2.65, 18, 0.1) @@ -959,6 +985,7 @@ class DistributedTugOfWarGame(DistributedMinigame): destHpr = startHpr + VBase3(0, 0, -30) oopsTrack = Sequence(Parallel(Func(self.suit.play, 'flail', None, 26, 38), LerpHprInterval(self.suit, 0.5, destHpr, startHpr=startHpr)), Parallel(Func(self.suit.play, 'slip-forward'), LerpPosInterval(self.suit, duration=1, pos=waterPos), Sequence(Wait(0.55), Func(base.playSfx, self.sndHitWater), Func(self.suitSplash.play), Func(self.ripples.play)))) reactSeq.append(Sequence(Func(self.suit.loop, 'victory'), Wait(2.6), LerpPosInterval(self.suit, duration=2, pos=newPos), oopsTrack, Func(self.suit.loop, 'neutral'))) + for avId in self.avIdList: toon = self.getAvatar(avId) toon.loop('neutral') @@ -978,6 +1005,7 @@ class DistributedTugOfWarGame(DistributedMinigame): else: exitSeq.append(Func(self.setText, self.roundText, TTLocalizer.TugOfWarGameTie)) exitSeq.append(Wait(2.5)) + exitSeq.append(Func(self.gameOver)) self.showTrack = Parallel(reactSeq, exitSeq) for x in list(self.animTracks.values()): @@ -988,27 +1016,31 @@ class DistributedTugOfWarGame(DistributedMinigame): if self.arrowKeys: self.arrowKeys.setPressHandlers(self.arrowKeys.NULL_HANDLERS) self.arrowKeys.setReleaseHandlers(self.arrowKeys.NULL_HANDLERS) - return def remoteKeyRateUpdate(self, avId, keyRate): if not self.hasLocalToon: return + if avId != self.localAvId: self.setAnimState(avId, keyRate) def sendSuitPosition(self, suitOffset): if not self.hasLocalToon: return + if self.gameFSM.getCurrentState().getName() != 'tug': return + self.suitOffset = suitOffset self.moveSuits() def sendCurrentPosition(self, avIdList, offsetList): if not self.hasLocalToon: return + if self.gameFSM.getCurrentState().getName() != 'tug': return + for i in range(len(avIdList)): self.offsetDict[avIdList[i]] = offsetList[i] @@ -1017,20 +1049,20 @@ class DistributedTugOfWarGame(DistributedMinigame): def createSuits(self): if self.gameType == TugOfWarGameGlobals.TOON_VS_COG: - self.suit = Suit.Suit() + self.suit = Suit() self.origSuitPosHpr = [VBase3(6.0, 18, 0.1), VBase3(120, 0, 0)] self.suitOffset = 0 - d = SuitDNA.SuitDNA() + d = SuitDNA() d.newSuit(self.suitType) self.suit.setDNA(d) - self.suit.reparentTo(render) + self.suit.reparentTo(base.render) self.suit.setPos(self.origSuitPosHpr[0]) self.suit.setHpr(self.origSuitPosHpr[1]) for anim in self.suitAnimNames: self.suit.pose(anim, 0) self.suit.pose('tug-o-war', 0) - self.dropShadowDict[self.suitId] = self.dropShadow.copyTo(hidden) + self.dropShadowDict[self.suitId] = self.dropShadow.copyTo(base.hidden) self.dropShadowDict[self.suitId].reparentTo(self.suit) self.dropShadowDict[self.suitId].setScale(0.45) @@ -1040,11 +1072,13 @@ class DistributedTugOfWarGame(DistributedMinigame): toon = self.getAvatar(self.avList[0][0]) if self.avList[0][0] == self.localAvId: self.advantage = 2.0 + toon.applyCheesyEffect(ToontownGlobals.CEBigHead) elif len(self.avList[1]) == 1: toon = self.getAvatar(self.avList[1][0]) if self.avList[1][0] == self.localAvId: self.advantage = 2.0 + toon.applyCheesyEffect(ToontownGlobals.CEBigHead) def setSpeedGauge(self): @@ -1052,12 +1086,14 @@ class DistributedTugOfWarGame(DistributedMinigame): self.powerMeter.setTarget(self.idealRate) if not self.allOutMode: self.powerMeter.updateTooSlowTooFast() + if not self.allOutMode: index = float(self.currentForce) / self.idealForce bonus = 0.0 if index > 1: bonus = max(1, index - 1) index = 1 + color = (0, 0.75 * index + 0.25 * bonus, 0.75 * (1 - index), @@ -1069,10 +1105,12 @@ class DistributedTugOfWarGame(DistributedMinigame): def setAnimState(self, avId, keyRate): if self.gameFSM.getCurrentState().getName() != 'tug': return + toon = self.getAvatar(avId) if keyRate > 0 and self.pullingDict[avId] == 0: toon.loop('tug-o-war') self.pullingDict[avId] = 1 + if keyRate <= 0 and self.pullingDict[avId] == 1: toon.pose('tug-o-war', 3) toon.startLookAround() @@ -1081,6 +1119,7 @@ class DistributedTugOfWarGame(DistributedMinigame): def moveSuits(self): if self.gameType != TugOfWarGameGlobals.TOON_VS_COG: return + origPos = self.origSuitPosHpr[0] curPos = self.suit.getPos() newPos = VBase3(origPos[0] + self.suitOffset, curPos[1], curPos[2]) @@ -1088,10 +1127,10 @@ class DistributedTugOfWarGame(DistributedMinigame): if self.animTracks[self.suitId].isPlaying(): self.animTracks[self.suitId].finish() self.checkIfFallen() + if self.suitId not in self.fallenList: self.animTracks[self.suitId] = Sequence(LerpPosInterval(self.suit, duration=TugOfWarGameGlobals.SEND_UPDATE, pos=newPos), Func(self.checkIfFallen)) self.animTracks[self.suitId].start() - return def moveToons(self): for avId in self.avIdList: @@ -1105,12 +1144,11 @@ class DistributedTugOfWarGame(DistributedMinigame): if self.animTracks[avId].isPlaying(): self.animTracks[avId].finish() self.checkIfFallen(avId) + if avId not in self.fallenList: self.animTracks[avId] = Sequence(LerpPosInterval(toon, duration=TugOfWarGameGlobals.SEND_UPDATE, pos=newPos), Func(self.checkIfFallen, avId)) self.animTracks[avId].start() - return - def checkIfFallen(self, avId = None): if avId == None: if self.suitId not in self.fallenList: @@ -1132,7 +1170,6 @@ class DistributedTugOfWarGame(DistributedMinigame): self.throwInWater(avId) self.sendUpdate('reportEndOfContest', [losingSide]) - return def throwInWater(self, avId = None): if avId == None: @@ -1140,7 +1177,7 @@ class DistributedTugOfWarGame(DistributedMinigame): waterPos = self.drinkPositions.pop() newPos = VBase3(waterPos[0], waterPos[1], waterPos[2] - self.suit.getHeight() / 1.5) self.suit.loop('neutral') - self.dropShadowDict[self.suitId].reparentTo(hidden) + self.dropShadowDict[self.suitId].reparentTo(base.hidden) loser = self.suit animId = self.suitId else: @@ -1149,19 +1186,20 @@ class DistributedTugOfWarGame(DistributedMinigame): waterPos = self.drinkPositions.pop() newPos = VBase3(waterPos[0], waterPos[1], waterPos[2] - toon.getHeight()) toon.loop('neutral') - self.dropShadowDict[avId].reparentTo(hidden) + self.dropShadowDict[avId].reparentTo(base.hidden) loser = toon animId = avId + if self.animTracks[animId] != None: if self.animTracks[animId].isPlaying(): self.animTracks[animId].finish() + self.splash.setPos(newPos[0], newPos[1], -1.8) self.splash.setScale(2.5, 2.5, 1) self.ripples.setPos(newPos[0], newPos[1], -1.7) self.ripples.setScale(1, 1, 1) self.animTracks[animId] = Sequence(Parallel(ActorInterval(actor=loser, animName='slip-forward', duration=2.0), LerpPosInterval(loser, duration=2.0, pos=newPos), Sequence(Wait(1.0), Parallel(Func(base.playSfx, self.sndHitWater), Func(self.splash.play), Func(self.ripples.play)))), Func(loser.loop, 'neutral')) self.animTracks[animId].start() - return def computeForce(self, keyRate): F = 0 @@ -1170,6 +1208,7 @@ class DistributedTugOfWarGame(DistributedMinigame): else: stdDev = 0.25 * self.idealRate F = self.advantage * (self.rateMatchAward + 4 + 0.4 * self.idealRate) * math.pow(math.e, -math.pow(keyRate - self.idealRate, 2) / (2.0 * math.pow(stdDev, 2))) + return F def initRopes(self): @@ -1177,8 +1216,9 @@ class DistributedTugOfWarGame(DistributedMinigame): numRopes = self.numPlayers else: numRopes = self.numPlayers - 1 + for x in range(0, numRopes): - rope = Rope.Rope(self.uniqueName('TugRope' + str(x))) + rope = Rope(self.uniqueName('TugRope' + str(x))) if rope.showRope: rope.ropeNode.setRenderMode(RopeNode.RMBillboard) rope.ropeNode.setThickness(0.2) @@ -1187,6 +1227,7 @@ class DistributedTugOfWarGame(DistributedMinigame): rope.ropeNode.setUvDirection(1) rope.setTransparency(1) rope.setColor(0.89, 0.89, 0.6, 1) + self.tugRopes.append(rope) self.setUpRopes(1) @@ -1203,18 +1244,18 @@ class DistributedTugOfWarGame(DistributedMinigame): for j in range(len(self.ropePts[i])): self.ropeTex[i][j].setPos(self.ropePts[i][j]) - return Task.cont + return task.cont def __killUpdateRopeTask(self): taskMgr.remove(self.taskName(self.UPDATE_ROPE_TASK)) def tugTimeoutTask(self, task): self.gameOver() - return Task.done + return task.done def waitForGoTimeoutTask(self, task): self.gameOver() - return Task.done + return task.done def __spawnMouseSpeedTask(self): taskMgr.remove(self.taskName('mouseSpeed')) @@ -1227,7 +1268,6 @@ class DistributedTugOfWarGame(DistributedMinigame): dx = 0.1 if self.mouseMode: mx = base.mouseWatcherNode.getMouseX() - my = base.mouseWatcherNode.getMouseY() if self.mouseSide == 0: if mx > dx: self.mouseSide = 1 @@ -1242,4 +1282,5 @@ class DistributedTugOfWarGame(DistributedMinigame): self.__pressHandler(1) elif mx < dx: self.__releaseHandler(0) - return Task.cont + + return task.cont From e573dc879d2a93249bcf716765ce5a52145813e6 Mon Sep 17 00:00:00 2001 From: demiurgeQuantified <8355611+demiurgeQuantified@users.noreply.github.com> Date: Fri, 19 May 2023 14:56:07 +0100 Subject: [PATCH 14/48] trolley: fix client crash when matching game ends --- toontown/minigame/DistributedPairingGame.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toontown/minigame/DistributedPairingGame.py b/toontown/minigame/DistributedPairingGame.py index 0c70f9c..9fa4964 100644 --- a/toontown/minigame/DistributedPairingGame.py +++ b/toontown/minigame/DistributedPairingGame.py @@ -11,7 +11,7 @@ from toontown.minigame import PlayingCardDeck from toontown.minigame import PairingGameGlobals from .OrthoWalk import OrthoWalk from .OrthoDrive import OrthoDrive -from direct.interval.IntervalGlobal import Sequence, Parallel, Func, LerpColorScaleInterval, LerpScaleInterval, LerpFunctionInterval, Wait, SoundInterval +from direct.interval.IntervalGlobal import Sequence, Parallel, Func, LerpColorScaleInterval, LerpScaleInterval, LerpFunctionInterval, Wait, SoundInterval, WaitInterval from toontown.toonbase.ToontownGlobals import GlobalDialogColor class DistributedPairingGame(DistributedMinigame): From 63051a26cfcd84658b7d39f7b6b92f3b00fe1dd9 Mon Sep 17 00:00:00 2001 From: demiurgeQuantified <8355611+demiurgeQuantified@users.noreply.github.com> Date: Fri, 19 May 2023 14:58:02 +0100 Subject: [PATCH 15/48] trolley: fix client crash when launching early in slingshot game --- toontown/toon/Toon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toontown/toon/Toon.py b/toontown/toon/Toon.py index ecfb114..8cc88c1 100644 --- a/toontown/toon/Toon.py +++ b/toontown/toon/Toon.py @@ -1995,7 +1995,7 @@ class Toon(Avatar.Avatar, ToonHead): def exitSitStart(self): self.playingAnim = 'neutral' if self.track != None: - self.track.finish() + self.track.pause() DelayDelete.cleanupDelayDeletes(self.track) self.track = None Emote.globalEmote.releaseBody(self) From 5be4056d2f57b7810e726f0bf5400ed9c63cbbd7 Mon Sep 17 00:00:00 2001 From: demiurgeQuantified <8355611+demiurgeQuantified@users.noreply.github.com> Date: Fri, 19 May 2023 18:44:37 +0100 Subject: [PATCH 16/48] trolley: fix district crash when requesting a minigame --- 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 aaf47da..efe856f 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -335,7 +335,7 @@ class Minigame(MagicWord): mgId = None mgDiff = None if difficulty == 0 else difficulty mgKeep = None - mgSzId = ZoneUtil.getSafeZoneId(toon.zoneId) if isTeleport else None + mgSzId = ZoneUtil.getSafeZoneId(toon.zoneId) if not any ((isTeleport, isRequest)): return f"Unknown command or minigame \"{command}\". Valid commands: \"teleport\", \"request\", or a minigame to automatically teleport or request" From 5814facc54bba9d334a7daf0b5ea315b08cd83b2 Mon Sep 17 00:00:00 2001 From: demiurgeQuantified <8355611+demiurgeQuantified@users.noreply.github.com> Date: Fri, 19 May 2023 23:43:37 +0100 Subject: [PATCH 17/48] trolley: fix new district crash when requesting a minigame --- toontown/spellbook/MagicWordIndex.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/toontown/spellbook/MagicWordIndex.py b/toontown/spellbook/MagicWordIndex.py index efe856f..39eddcb 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -335,7 +335,7 @@ class Minigame(MagicWord): mgId = None mgDiff = None if difficulty == 0 else difficulty mgKeep = None - mgSzId = ZoneUtil.getSafeZoneId(toon.zoneId) + mgSzId = ZoneUtil.getSafeZoneId(toon.zoneId) if isTeleport else None if not any ((isTeleport, isRequest)): return f"Unknown command or minigame \"{command}\". Valid commands: \"teleport\", \"request\", or a minigame to automatically teleport or request" @@ -350,9 +350,11 @@ class Minigame(MagicWord): mgId = ToontownGlobals.MinigameNames.get(minigame) if any((isTeleport, isRequest)): - if isTeleport and (ZoneUtil.isDynamicZone(toon.zoneId) or not toon.zoneId == mgSzId): - return "Target needs to be in a playground to teleport to a minigame." - MinigameCreatorAI.RequestMinigame[avId] = (mgId, mgKeep, mgDiff, ToontownGlobals.ToontownCentral if ZoneUtil.isWelcomeValley(mgSzId) else mgSzId) + if isTeleport: + if ZoneUtil.isDynamicZone(toon.zoneId) or not toon.zoneId == mgSzId: + return "Target needs to be in a playground to teleport to a minigame." + mgSzId = ToontownGlobals.ToontownCentral if ZoneUtil.isWelcomeValley(mgSzId) else mgSzId + MinigameCreatorAI.RequestMinigame[avId] = (mgId, mgKeep, mgDiff, mgSzId) if isTeleport: try: result = MinigameCreatorAI.createMinigame(self.air, [avId], mgSzId) From d466c74147cf7373160e7a8b1f96a984e6339857 Mon Sep 17 00:00:00 2001 From: demiurgeQuantified <8355611+demiurgeQuantified@users.noreply.github.com> Date: Tue, 23 May 2023 16:10:42 +0100 Subject: [PATCH 18/48] hood: add fisherman + party toons to playgrounds --- toontown/ai/ToontownAIRepository.py | 31 ++++++++++++++++++- toontown/fishing/DistributedFishingPondAI.py | 10 ++++++ toontown/uberdog/DistributedPartyManagerAI.py | 3 ++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/toontown/ai/ToontownAIRepository.py b/toontown/ai/ToontownAIRepository.py index 340edea..19e549c 100644 --- a/toontown/ai/ToontownAIRepository.py +++ b/toontown/ai/ToontownAIRepository.py @@ -36,12 +36,14 @@ from toontown.hood.TTHoodDataAI import TTHoodDataAI from toontown.pets.PetManagerAI import PetManagerAI from toontown.quest.QuestManagerAI import QuestManagerAI from toontown.racing import RaceGlobals +from toontown.fishing.DistributedFishingPondAI import DistributedFishingPondAI from toontown.racing.DistributedLeaderBoardAI import DistributedLeaderBoardAI from toontown.racing.DistributedRacePadAI import DistributedRacePadAI from toontown.racing.DistributedStartingBlockAI import DistributedStartingBlockAI from toontown.racing.DistributedStartingBlockAI import DistributedViewingBlockAI from toontown.racing.DistributedViewPadAI import DistributedViewPadAI from toontown.racing.RaceManagerAI import RaceManagerAI +from toontown.uberdog.DistributedPartyManagerAI import DistributedPartyManagerAI from toontown.safezone.SafeZoneManagerAI import SafeZoneManagerAI from toontown.shtiker.CogPageManagerAI import CogPageManagerAI from toontown.spellbook.ToontownMagicWordManagerAI import ToontownMagicWordManagerAI @@ -91,6 +93,7 @@ class ToontownAIRepository(ToontownInternalRepository): self.trophyMgr = None self.safeZoneManager = None self.magicWordManager = None + self.partyManager = None self.zoneTable = {} self.dnaStoreMap = {} self.dnaDataMap = {} @@ -225,6 +228,10 @@ class ToontownAIRepository(ToontownInternalRepository): self.tutorialManager = TutorialManagerAI(self) self.tutorialManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT) + # Generate our party manager... + self.partyManager = DistributedPartyManagerAI(self) + self.partyManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT) + def generateHood(self, hoodConstructor, zoneId): # Bossbot HQ doesn't use DNA, so we skip over that. if zoneId != ToontownGlobals.BossbotHQ: @@ -374,7 +381,29 @@ class ToontownAIRepository(ToontownInternalRepository): return loadDNAFileAI(dnaStore, dnaFileName) def findFishingPonds(self, dnaData, zoneId, area): - return [], [] # TODO + fishingPonds, fishingPondGroups = [], [] + + if "fishing_pond" in dnaData.getName(): + fishingPondGroups.append(dnaData) + pond = DistributedFishingPondAI(self) + pond.setArea(area) + pond.generateWithRequired(zoneId) + fishingPonds.append(pond) + else: + if isinstance(dnaData, DNAVisGroup): + name = dnaData.getName() + visId = int(name.split(":", 1)[0]) % 1000 + zoneId = ZoneUtil.getHoodId(zoneId) + visId + + for i in range(dnaData.getNumChildren()): + foundFishingPonds, foundFishingPondGroups = self.findFishingPonds(dnaData.at(i), zoneId, area) + fishingPonds.extend(foundFishingPonds) + fishingPondGroups.extend(foundFishingPondGroups) + + return fishingPonds, fishingPondGroups + + def findFishingSpots(self, dnaData, pond): + return [] # TODO def findPartyHats(self, dnaData, zoneId): return [] # TODO diff --git a/toontown/fishing/DistributedFishingPondAI.py b/toontown/fishing/DistributedFishingPondAI.py index 68754c4..d2e86ab 100644 --- a/toontown/fishing/DistributedFishingPondAI.py +++ b/toontown/fishing/DistributedFishingPondAI.py @@ -3,3 +3,13 @@ from direct.distributed.DistributedObjectAI import DistributedObjectAI class DistributedFishingPondAI(DistributedObjectAI): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedFishingPondAI') + + def __init__(self, air): + DistributedObjectAI.__init__(self, air) + self.area = None + + def setArea(self, area): + self.area = area + + def getArea(self): + return self.area diff --git a/toontown/uberdog/DistributedPartyManagerAI.py b/toontown/uberdog/DistributedPartyManagerAI.py index 2de29d9..75866e7 100644 --- a/toontown/uberdog/DistributedPartyManagerAI.py +++ b/toontown/uberdog/DistributedPartyManagerAI.py @@ -3,3 +3,6 @@ from direct.distributed.DistributedObjectAI import DistributedObjectAI class DistributedPartyManagerAI(DistributedObjectAI): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedPartyManagerAI') + + def canBuyParties(self): + return False # TODO From 440fe2c51bb15cafeb772e2bc182fcf3a03e594e Mon Sep 17 00:00:00 2001 From: Michael G <10155689+DarthMDev@users.noreply.github.com> Date: Tue, 30 May 2023 17:50:06 -0400 Subject: [PATCH 19/48] MagicWordIndex: Add some more magic words Restockinventory to fill up gags emtpyinventory to emptygags and setpinkslips to give pinkslips --- toontown/spellbook/MagicWordIndex.py | 32 ++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/toontown/spellbook/MagicWordIndex.py b/toontown/spellbook/MagicWordIndex.py index 39eddcb..c109628 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -286,7 +286,39 @@ class MaxToon(MagicWord): toon.b_setCogLevels([ToontownGlobals.MaxCogSuitLevel] * 4) return f"Successfully maxed {toon.getName()}!" + +class RestockInventory(MagicWord): + aliases = ['allstuff', 'restockinv', 'maxinv', 'maxinventory', 'restock'] + desc = 'Gives target all the inventory they can carry.' + execLocation = MagicWordConfig.EXEC_LOC_SERVER + def handleWord(self, invoker, avId, toon, *args): + toon.inventory.maxOutInv() + toon.d_setInventory(toon.inventory.makeNetString()) + return ("Maxing out inventory for " + toon.getName() + ".") + +class EmptyInventory(MagicWord): + aliases = ['nostuff', 'emptyinv', 'zeroinv', 'zeroinventory'] + desc = 'Gives target all the inventory they can carry.' + execLocation = MagicWordConfig.EXEC_LOC_SERVER + + def handleWord(self, invoker, avId, toon, *args): + toon.inventory.zeroInv() + 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 + aliases = ["pinkslips"] + desc = "Gives the target toon the specified amount of pink slips." + execLocation = MagicWordConfig.EXEC_LOC_SERVER + arguments = [("amount", int, False, 255)] + + def handleWord(self, invoker, avId, toon, *args): + toon.b_setPinkSlips(args[0]) + return f"Gave {toon.getName()} {args[0]} pink slips!" + class AbortMinigame(MagicWord): aliases = ["exitgame", "exitminigame", "quitgame", "quitminigame", "skipgame", "skipminigame"] desc = "Aborts an ongoing minigame." From fd0e7d86a2363843055ca134601d093f433d25e4 Mon Sep 17 00:00:00 2001 From: DarthNihilus1 Date: Tue, 30 May 2023 18:20:54 -0400 Subject: [PATCH 20/48] MagicWordIndex: update - Combine inventory commands - Add aliases for setting pink slips --- toontown/spellbook/MagicWordIndex.py | 37 +++++++++++++++------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/toontown/spellbook/MagicWordIndex.py b/toontown/spellbook/MagicWordIndex.py index c109628..a2b7a5f 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -287,30 +287,33 @@ class MaxToon(MagicWord): return f"Successfully maxed {toon.getName()}!" -class RestockInventory(MagicWord): - aliases = ['allstuff', 'restockinv', 'maxinv', 'maxinventory', 'restock'] - desc = 'Gives target all the inventory they can carry.' +class Inventory(MagicWord): + # by default restock the inventory + aliases = ['gags', 'inv'] + desc = 'This allows you to modify your inventory in various ways.' execLocation = MagicWordConfig.EXEC_LOC_SERVER - + arguments = [("command", str, False, ''), ("track", str, False, ""), ("level", int, False, 0), ("amount", int, False, 0)] def handleWord(self, invoker, avId, toon, *args): - toon.inventory.maxOutInv() - toon.d_setInventory(toon.inventory.makeNetString()) - return ("Maxing out inventory for " + toon.getName() + ".") + command = args[0] + # the list of words that can be used to restock the inventory + restockInvWords = ['restock', 'max', 'all', '', 'fill'] + # the list of words that can be used to empty the inventory + emptyInvWords = ['empty', 'zero', 'null', 'clear', 'none', 'reset'] + if command in restockInvWords: + toon.inventory.maxOutInv() + toon.d_setInventory(toon.inventory.makeNetString()) + return ("Maxing out inventory for " + toon.getName() + ".") + if command in emptyInvWords: + toon.inventory.zeroInv() + toon.d_setInventory(toon.inventory.makeNetString()) + return ("Zeroing inventory for " + toon.getName() + ".") -class EmptyInventory(MagicWord): - aliases = ['nostuff', 'emptyinv', 'zeroinv', 'zeroinventory'] - desc = 'Gives target all the inventory they can carry.' - execLocation = MagicWordConfig.EXEC_LOC_SERVER - - def handleWord(self, invoker, avId, toon, *args): - toon.inventory.zeroInv() - 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 - aliases = ["pinkslips"] + aliases = ["pinkslips", "fires", 'setfires'] desc = "Gives the target toon the specified amount of pink slips." execLocation = MagicWordConfig.EXEC_LOC_SERVER arguments = [("amount", int, False, 255)] From e77d954d5befd793beca2355168fc88bd39dd091 Mon Sep 17 00:00:00 2001 From: Crimson Fox <43253740+CrimsonFox762@users.noreply.github.com> Date: Mon, 31 Jul 2023 13:23:19 -0400 Subject: [PATCH 21/48] Fixed Knockback for Lure --- toontown/battle/BattleCalculatorAI.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toontown/battle/BattleCalculatorAI.py b/toontown/battle/BattleCalculatorAI.py index d76ea92..982b4b8 100644 --- a/toontown/battle/BattleCalculatorAI.py +++ b/toontown/battle/BattleCalculatorAI.py @@ -751,7 +751,7 @@ class BattleCalculatorAI: return tgts = self.__createToonTargetList(toonId) for currTgt in tgts: - tgtPos = self.battle.suits.index(currTgt) + tgtPos = self.battle.activeSuits.index(currTgt) attackerId = self.toonAtkOrder[attackIndex] attack = self.battle.toonAttacks[attackerId] track = self.__getActualTrack(attack) From 393df6ec998ff796fa192bff4293a06f4ed11c70 Mon Sep 17 00:00:00 2001 From: Crimson Fox <43253740+CrimsonFox762@users.noreply.github.com> Date: Tue, 1 Aug 2023 09:24:55 -0400 Subject: [PATCH 22/48] Tweaked Code for Knockback --- toontown/battle/BattleCalculatorAI.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/toontown/battle/BattleCalculatorAI.py b/toontown/battle/BattleCalculatorAI.py index 982b4b8..9dd3f5a 100644 --- a/toontown/battle/BattleCalculatorAI.py +++ b/toontown/battle/BattleCalculatorAI.py @@ -747,11 +747,15 @@ class BattleCalculatorAI: toonId = self.toonAtkOrder[attackIndex] attack = self.battle.toonAttacks[toonId] atkTrack = self.__getActualTrack(attack) + TTOStyle = simbase.config.GetBool('want-tto-style-knockback', False) if atkTrack == HEAL or atkTrack == PETSOS: return tgts = self.__createToonTargetList(toonId) for currTgt in tgts: - tgtPos = self.battle.activeSuits.index(currTgt) + if not TTOStyle: + tgtPos = self.battle.activeSuits.index(currTgt) + else: + tgtPos = self.battle.suits.index(currTgt) attackerId = self.toonAtkOrder[attackIndex] attack = self.battle.toonAttacks[attackerId] track = self.__getActualTrack(attack) From 872a0659cd0094099fe0f77dd3018cf2fe2d3792 Mon Sep 17 00:00:00 2001 From: Comrade <54220881+ComradeNapCali@users.noreply.github.com> Date: Mon, 21 Aug 2023 16:51:15 -0700 Subject: [PATCH 23/48] battle: Rename unfortunately named variables to be more inclusive. (#97) --- toontown/battle/MovieLure.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/toontown/battle/MovieLure.py b/toontown/battle/MovieLure.py index 378b0aa..d7dafef 100644 --- a/toontown/battle/MovieLure.py +++ b/toontown/battle/MovieLure.py @@ -98,10 +98,10 @@ def __createFishingPoleMultiTrack(lure, dollar, dollarName): suitTrack.append(Func(suit.loop, 'neutral')) suitTrack.append(Wait(3.5)) suitName = suit.getStyleName() - retardPos, retardHpr = battle.getActorPosHpr(suit) - retardPos.setY(retardPos.getY() + MovieUtil.SUIT_EXTRA_REACH_DISTANCE) + luredPos, luredHpr = battle.getActorPosHpr(suit) + luredPos.setY(luredPos.getY() + MovieUtil.SUIT_EXTRA_REACH_DISTANCE) if suitName in MovieUtil.largeSuits: - moveTrack = lerpSuit(suit, 0.0, reachAnimDuration / 2.5, retardPos, battle, trapProp) + moveTrack = lerpSuit(suit, 0.0, reachAnimDuration / 2.5, luredPos, battle, trapProp) reachTrack = ActorInterval(suit, 'reach', duration=reachAnimDuration) suitTrack.append(Parallel(moveTrack, reachTrack)) else: From ef72eabdf8431e1ff83d0ccff54480edde68e71d Mon Sep 17 00:00:00 2001 From: Michael G <10155689+DarthMDev@users.noreply.github.com> Date: Mon, 11 Sep 2023 05:50:34 -0400 Subject: [PATCH 24/48] DistributedToonHallInterior: Fix missing import issue Should fix #103 --- toontown/building/DistributedToonHallInterior.py | 1 + 1 file changed, 1 insertion(+) diff --git a/toontown/building/DistributedToonHallInterior.py b/toontown/building/DistributedToonHallInterior.py index cfbee85..1fb9d16 100644 --- a/toontown/building/DistributedToonHallInterior.py +++ b/toontown/building/DistributedToonHallInterior.py @@ -1,3 +1,4 @@ +from panda3d.core import * from panda3d.toontown import * from toontown.toonbase.ToonBaseGlobal import * from direct.interval.IntervalGlobal import * From 47471f927290dcdec3b2038c1cee612bc000d44d Mon Sep 17 00:00:00 2001 From: Crimson Fox <43253740+CrimsonFox762@users.noreply.github.com> Date: Wed, 18 Oct 2023 11:01:22 -0400 Subject: [PATCH 25/48] Bug Fix for Photo Fun --- toontown/minigame/DistributedPhotoGame.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/toontown/minigame/DistributedPhotoGame.py b/toontown/minigame/DistributedPhotoGame.py index 5321eec..35e1cc2 100644 --- a/toontown/minigame/DistributedPhotoGame.py +++ b/toontown/minigame/DistributedPhotoGame.py @@ -28,6 +28,8 @@ from toontown.makeatoon import NameGenerator from otp.otpbase import OTPGlobals from toontown.battle import BattleParticles from toontown.minigame import PhotoGameBase +from panda3d.otp import * + WORLD_SCALE = 2.0 FAR_PLANE_DIST = 600 * WORLD_SCALE STAGE_Z_OFFSET = 7.0 From f02cf5d80992373df930892d2ef93c6057916c46 Mon Sep 17 00:00:00 2001 From: demiurgeQuantified <8355611+demiurgeQuantified@users.noreply.github.com> Date: Tue, 31 Oct 2023 18:58:44 +0000 Subject: [PATCH 26/48] fix photo fun memory leak identified in #109 --- toontown/minigame/DistributedPhotoGame.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/toontown/minigame/DistributedPhotoGame.py b/toontown/minigame/DistributedPhotoGame.py index 35e1cc2..bcf6096 100644 --- a/toontown/minigame/DistributedPhotoGame.py +++ b/toontown/minigame/DistributedPhotoGame.py @@ -245,6 +245,11 @@ class DistributedPhotoGame(DistributedMinigame, PhotoGameBase.PhotoGameBase): self.removeChildGameFSM(self.gameFSM) del self.gameFSM self.ignoreAll() + + for rayEntry in self.rayArray: + rayEntry[3].remove_node() + del self.rayArray + return def onstage(self): From 347829eb57c94f397e23660174c9c3b625cd624d Mon Sep 17 00:00:00 2001 From: demiurgeQuantified <8355611+demiurgeQuantified@users.noreply.github.com> Date: Tue, 31 Oct 2023 20:25:36 +0000 Subject: [PATCH 27/48] reparent shtickerbook actors when swapping toon torso, fixes #108 --- toontown/toon/Toon.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/toontown/toon/Toon.py b/toontown/toon/Toon.py index 8cc88c1..75b616b 100644 --- a/toontown/toon/Toon.py +++ b/toontown/toon/Toon.py @@ -860,6 +860,9 @@ class Toon(Avatar.Avatar, ToonHead): self.resetHeight() self.setupToonNodes() self.generateBackpack() + hands = self.getRightHands() + for bookActor, hand in zip(self.__bookActors, hands): + bookActor.reparentTo(hand) def generateToonHead(self, copy = 1): headHeight = ToonHead.generateToonHead(self, copy, self.style, ('1000', '500', '250')) From a72808ddd95899025f4554de55672949401693a8 Mon Sep 17 00:00:00 2001 From: Samuel T Date: Tue, 7 Nov 2023 17:41:13 +0000 Subject: [PATCH 28/48] 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 29/48] 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 30/48] 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 e4e94207d54d7a3d7319cb618c371181128b9f13 Mon Sep 17 00:00:00 2001 From: Samuel T Date: Tue, 7 Nov 2023 22:59:21 +0000 Subject: [PATCH 31/48] golf: Address missing imports (#112) * golf: Address missing imports * spellbook: Golf related magic words for easier debugging * Revert "spellbook: Golf related magic words for easier debugging" This reverts commit c0de7f671335dbf5660bb4ed4c613edc18720293. --- 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 83c8ee19b792a252a2ef3e63ae8e5d8b970f180f Mon Sep 17 00:00:00 2001 From: Samuel T Date: Tue, 7 Nov 2023 23:31:00 +0000 Subject: [PATCH 32/48] 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 33/48] 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 34/48] 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 35/48] 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 36/48] 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 37/48] 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 38/48] 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 39/48] 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 40/48] 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 41/48] 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 42/48] 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 43/48] 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 44/48] 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 45/48] 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' From 05d73cb4fb9cd653e09592f2558604feba3145c3 Mon Sep 17 00:00:00 2001 From: DarthM Date: Tue, 28 Jan 2025 01:47:30 -0500 Subject: [PATCH 46/48] Friends: True friend codes can now be generated --- etc/toon.dc | 1 + otp/friends/FriendManagerAI.py | 17 + otp/friends/FriendSecret.py | 471 +++++++++++++------ toontown/friends/ToontownFriendSecret.py | 75 ++- toontown/friends/ToontownFriendsManagerAI.py | 3 + toontown/friends/ToontownFriendsManagerUD.py | 470 +++++++++++++++++- 6 files changed, 863 insertions(+), 174 deletions(-) diff --git a/etc/toon.dc b/etc/toon.dc index 184ca91..ccaebef 100755 --- a/etc/toon.dc +++ b/etc/toon.dc @@ -2874,6 +2874,7 @@ dclass ToontownFriendsManager : DistributedObject { makeFriendsResponse(uint32, uint32, uint8, uint32) airecv; removeFriend(uint32) clsend; requestSecret(uint32); + requestSecretResponse(uint8, string, uint32) airecv; }; dclass TTSpeedchatRelay : SpeedchatRelay { diff --git a/otp/friends/FriendManagerAI.py b/otp/friends/FriendManagerAI.py index ab4a1e0..3321330 100644 --- a/otp/friends/FriendManagerAI.py +++ b/otp/friends/FriendManagerAI.py @@ -50,9 +50,11 @@ class FriendManagerAI(DistributedObjectGlobalAI): # will be sent in response to secret requests to the database, # via the AIR. self.accept("makeFriendsReply", self.makeFriendsReply) + self.accept("requestSecretReply", self.requestSecretReply) def delete(self): self.ignore("makeFriendsReply") + self.ignore("requestSecretReply") DistributedObjectGlobalAI.delete(self) ### Messages sent from inviter client to AI @@ -409,3 +411,18 @@ class FriendManagerAI(DistributedObjectGlobalAI): avatar.d_friendsNotify(invite.inviterId, 2) self.clearInvite(invite) + + def requestSecretReply(self, result, secret, requesterId): + self.down_requestSecretResponse(requesterId, result, secret) + + def down_requestSecretResponse(self, recipient, result, secret): + """requestSecret(self, int8 result, string secret) + + Sent by the AI to the client in response to requestSecret(). + result is one of: + + 0 - Too many secrets outstanding. Try again later. + 1 - Success. The new secret is supplied. + + """ + self.sendUpdateToAvatarId(recipient, 'requestSecretResponse', [result, secret]) \ No newline at end of file diff --git a/otp/friends/FriendSecret.py b/otp/friends/FriendSecret.py index 0b01bd2..3eaefc8 100644 --- a/otp/friends/FriendSecret.py +++ b/otp/friends/FriendSecret.py @@ -1,59 +1,67 @@ -from panda3d.core import * -from panda3d.otp import * -from direct.gui.DirectGui import * from direct.directnotify import DirectNotifyGlobal from direct.fsm import StateData -from otp.otpbase import OTPLocalizer +from direct.gui.DirectGui import * +from panda3d.core import * +from panda3d.otp import NametagGlobals + from otp.otpbase import OTPGlobals +from otp.otpbase import OTPLocalizer from otp.uberdog import RejectCode + globalFriendSecret = None AccountSecret = 0 AvatarSecret = 1 BothSecrets = 2 -def showFriendSecret(secretType = AvatarSecret): + +def showFriendSecret(secretType=AvatarSecret): + """ + Added optional parameter to offer the choice between account and avatar friend tokens. + """ + # A module function to open the global secret panel. global globalFriendSecret if not base.cr.isPaid(): + # bring up teaser panel chatMgr = base.localAvatar.chatMgr - chatMgr.fsm.request('trueFriendTeaserPanel') + chatMgr.fsm.request("trueFriendTeaserPanel") elif not base.cr.isParentPasswordSet(): + # non-COPPA gamecard user: prompt to leave game and set parent password chatMgr = base.localAvatar.chatMgr - if base.cr.productName in ['DisneyOnline-AP', - 'DisneyOnline-UK', - 'JP', - 'DE', - 'BR', - 'FR']: + if base.cr.productName in ['DisneyOnline-AP', 'DisneyOnline-UK', 'JP', 'DE', 'BR', 'FR']: chatMgr = base.localAvatar.chatMgr if not base.cr.isPaid(): - chatMgr.fsm.request('unpaidChatWarning') + chatMgr.fsm.request("unpaidChatWarning") else: chatMgr.paidNoParentPassword = 1 - chatMgr.fsm.request('unpaidChatWarning') + chatMgr.fsm.request("unpaidChatWarning") else: chatMgr.paidNoParentPassword = 1 - chatMgr.fsm.request('noSecretChatAtAll') + chatMgr.fsm.request("noSecretChatAtAll") # bring up dialog for true friends # open chat with true friends + elif not base.cr.allowSecretChat(): + # If we're paid but have not yet activated secrets, pop up the + # dialog to do this. chatMgr = base.localAvatar.chatMgr - if base.cr.productName in ['DisneyOnline-AP', - 'DisneyOnline-UK', - 'JP', - 'DE', - 'BR', - 'FR']: + if base.cr.productName in ['DisneyOnline-AP', 'DisneyOnline-UK', 'JP', 'DE', 'BR', 'FR']: chatMgr = base.localAvatar.chatMgr if not base.cr.isPaid(): - chatMgr.fsm.request('unpaidChatWarning') + chatMgr.fsm.request("unpaidChatWarning") else: chatMgr.paidNoParentPassword = 1 - chatMgr.fsm.request('unpaidChatWarning') + chatMgr.fsm.request("unpaidChatWarning") else: - chatMgr.fsm.request('noSecretChatAtAll') + # we no longer offer the ability to enable chat in game + # chatMgr.fsm.request("noSecretChatWarning") + chatMgr.fsm.request("noSecretChatAtAll") elif base.cr.needParentPasswordForSecretChat(): + # If we're paid but have the flag set to require the Parent Password to be + # entered to get or use a Secret Friends password, pop up the + # dialog to get the Parent Password. unloadFriendSecret() globalFriendSecret = FriendSecretNeedsParentLogin(secretType) globalFriendSecret.enter() else: + # Otherwise, actually open the secrets panel. openFriendSecret(secretType) @@ -63,53 +71,60 @@ def openFriendSecret(secretType): globalFriendSecret.unload() globalFriendSecret = FriendSecret(secretType) globalFriendSecret.enter() - return def hideFriendSecret(): + # A module function to close the global secret panel if it is open. if globalFriendSecret != None: globalFriendSecret.exit() - return def unloadFriendSecret(): + # A module function to completely unload the global secret panel. global globalFriendSecret if globalFriendSecret != None: globalFriendSecret.unload() globalFriendSecret = None - return class FriendSecretNeedsParentLogin(StateData.StateData): - notify = DirectNotifyGlobal.directNotify.newCategory('FriendSecretNeedsParentLogin') + notify = DirectNotifyGlobal.directNotify.newCategory("FriendSecretNeedsParentLogin") def __init__(self, secretType): - StateData.StateData.__init__(self, 'friend-secret-needs-parent-login-done') + StateData.StateData.__init__(self, "friend-secret-needs-parent-login-done") self.dialog = None self.secretType = secretType - return def enter(self): StateData.StateData.enter(self) - base.localAvatar.chatMgr.fsm.request('otherDialog') + base.localAvatar.chatMgr.fsm.request("otherDialog") + # Pop up a dialog indicating the parent account needs to login + # in order to get to the Secret Friends chat: if self.dialog == None: - guiButton = loader.loadModel('phase_3/models/gui/quit_button') + guiButton = loader.loadModel("phase_3/models/gui/quit_button") buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui') - nameBalloon = loader.loadModel('phase_3/models/props/chatbox_input') - optionsButtonImage = (guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')) - okButtonImage = (buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')) - cancelButtonImage = (buttons.find('**/CloseBtn_UP'), buttons.find('**/CloseBtn_DN'), buttons.find('**/CloseBtn_Rllvr')) + nameBalloon = loader.loadModel("phase_3/models/props/chatbox_input") + optionsButtonImage = ( + guiButton.find("**/QuitBtn_UP"), guiButton.find("**/QuitBtn_DN"), guiButton.find("**/QuitBtn_RLVR")) + okButtonImage = ( + buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')) + cancelButtonImage = ( + buttons.find('**/CloseBtn_UP'), buttons.find('**/CloseBtn_DN'), buttons.find('**/CloseBtn_Rllvr')) + + # The Castillian (and all foreign) version relies on a seperate parent + # password system. Omit the the password entry field and cancel button. withParentAccount = False try: withParentAccount = base.cr.withParentAccount except: - self.notify.warning('withParentAccount not found in base.cr') + self.notify.warning("withParentAccount not found in base.cr") + pass if withParentAccount: okPos = (-0.22, 0.0, -0.5) textPos = (0, 0.25) okCommand = self.__handleOKWithParentAccount - elif base.cr.productName != 'Terra-DMC': + elif base.cr.productName != "Terra-DMC": okPos = (-0.22, 0.0, -0.5) textPos = (0, 0.25) okCommand = self.__oldHandleOK @@ -118,24 +133,48 @@ class FriendSecretNeedsParentLogin(StateData.StateData): okPos = (0, 0, -0.35) textPos = (0, 0.125) okCommand = self.__handleCancel - self.dialog = DirectFrame(parent=aspect2dp, pos=(0.0, 0.1, 0.2), relief=None, image=DGG.getDefaultDialogGeom(), image_color=OTPGlobals.GlobalDialogColor, image_scale=(1.4, 1.0, 1.25), image_pos=(0, 0, -0.1), text=OTPLocalizer.FriendSecretNeedsParentLoginWarning, text_wordwrap=21.5, text_scale=0.055, text_pos=textPos, textMayChange=1) - DirectButton(self.dialog, image=okButtonImage, relief=None, text=OTPLocalizer.FriendSecretNeedsPasswordWarningOK, text_scale=0.05, text_pos=(0.0, -0.1), textMayChange=0, pos=okPos, command=okCommand) - DirectLabel(parent=self.dialog, relief=None, pos=(0, 0, 0.35), text=OTPLocalizer.FriendSecretNeedsPasswordWarningTitle, textMayChange=0, text_scale=0.08) - if base.cr.productName != 'Terra-DMC': - self.usernameLabel = DirectLabel(parent=self.dialog, relief=None, pos=(-0.07, 0.0, -0.1), text=OTPLocalizer.ParentLogin, text_scale=0.06, text_align=TextNode.ARight, textMayChange=0) - self.usernameEntry = DirectEntry(parent=self.dialog, relief=None, image=nameBalloon, image1_color=(0.8, 0.8, 0.8, 1.0), scale=0.064, pos=(0.0, 0.0, -0.1), width=OTPGlobals.maxLoginWidth, numLines=1, focus=1, cursorKeys=1, obscured=1, command=self.__handleUsername) - self.passwordLabel = DirectLabel(parent=self.dialog, relief=None, pos=(-0.02, 0.0, -0.3), text=OTPLocalizer.ParentPassword, text_scale=0.06, text_align=TextNode.ARight, textMayChange=0) - self.passwordEntry = DirectEntry(parent=self.dialog, relief=None, image=nameBalloon, image1_color=(0.8, 0.8, 0.8, 1.0), scale=0.064, pos=(0.04, 0.0, -0.3), width=OTPGlobals.maxLoginWidth, numLines=1, focus=1, cursorKeys=1, obscured=1, command=okCommand) - DirectButton(self.dialog, image=cancelButtonImage, relief=None, text=OTPLocalizer.FriendSecretNeedsPasswordWarningCancel, text_scale=0.05, text_pos=(0.0, -0.1), textMayChange=1, pos=(0.2, 0.0, -0.5), command=self.__handleCancel) + + # make the common gui elements + self.dialog = DirectFrame(parent=aspect2dp, pos=(0.0, 0.1, 0.2), relief=None, + image=DGG.getDefaultDialogGeom(), image_color=OTPGlobals.GlobalDialogColor, + image_scale=(1.4, 1.0, 1.25), image_pos=(0, 0, -0.1), + text=OTPLocalizer.FriendSecretNeedsParentLoginWarning, text_wordwrap=21.5, text_scale=0.055, + text_pos=textPos, textMayChange=1) + DirectButton(self.dialog, image=okButtonImage, relief=None, + text=OTPLocalizer.FriendSecretNeedsPasswordWarningOK, text_scale=0.05, text_pos=(0.0, -0.1), + textMayChange=0, pos=okPos, command=okCommand) + DirectLabel(parent=self.dialog, relief=None, pos=(0, 0, 0.35), + text=OTPLocalizer.FriendSecretNeedsPasswordWarningTitle, textMayChange=0, text_scale=0.08) + + # if not foreign, make the domestic only password entry elements + if base.cr.productName != "Terra-DMC": + self.usernameLabel = DirectLabel(parent=self.dialog, relief=None, pos=(-0.07, 0.0, -0.1), + text=OTPLocalizer.ParentLogin, text_scale=0.06, text_align=TextNode.ARight, textMayChange=0) + self.usernameEntry = DirectEntry(parent=self.dialog, relief=None, image=nameBalloon, + image1_color=(0.8, 0.8, 0.8, 1.0), scale=0.064, pos=(0.0, 0.0, -0.1), + width=OTPGlobals.maxLoginWidth, numLines=1, focus=1, cursorKeys=1, obscured=1, + command=self.__handleUsername) + self.passwordLabel = DirectLabel(parent=self.dialog, relief=None, pos=(-0.02, 0.0, -0.3), + text=OTPLocalizer.ParentPassword, text_scale=0.06, text_align=TextNode.ARight, textMayChange=0) + self.passwordEntry = DirectEntry(parent=self.dialog, relief=None, image=nameBalloon, + image1_color=(0.8, 0.8, 0.8, 1.0), scale=0.064, pos=(0.04, 0.0, -0.3), + width=OTPGlobals.maxLoginWidth, numLines=1, focus=1, cursorKeys=1, obscured=1, command=okCommand) + DirectButton(self.dialog, image=cancelButtonImage, relief=None, + text=OTPLocalizer.FriendSecretNeedsPasswordWarningCancel, text_scale=0.05, text_pos=(0.0, -0.1), + textMayChange=1, pos=(0.2, 0.0, -0.5), command=self.__handleCancel) + + # hide the parent login as it's not valid yet if withParentAccount: self.usernameEntry.enterText('') self.usernameEntry['focus'] = 1 self.passwordEntry.enterText('') + else: self.usernameEntry.hide() self.usernameLabel.hide() self.passwordEntry['focus'] = 1 self.passwordEntry.enterText('') + guiButton.removeNode() buttons.removeNode() nameBalloon.removeNode() @@ -147,8 +186,8 @@ class FriendSecretNeedsParentLogin(StateData.StateData): elif self.passwordEntry: self.passwordEntry['focus'] = 1 self.passwordEntry.enterText('') + self.dialog.show() - return def exit(self): self.ignoreAll() @@ -156,11 +195,11 @@ class FriendSecretNeedsParentLogin(StateData.StateData): self.dialog.destroy() self.dialog = None if self.isEntered: - base.localAvatar.chatMgr.fsm.request('mainMenu') + base.localAvatar.chatMgr.fsm.request("mainMenu") StateData.StateData.exit(self) - return def __handleUsername(self, *args): + # activate password entry if self.passwordEntry: self.passwordEntry['focus'] = 1 self.passwordEntry.enterText('') @@ -168,17 +207,29 @@ class FriendSecretNeedsParentLogin(StateData.StateData): def __handleOKWithParentAccount(self, *args): username = self.usernameEntry.get() password = self.passwordEntry.get() + # we need to store these in base.cr for __enterSecret base.cr.parentUsername = username base.cr.parentPassword = password tt = base.cr.loginInterface - okflag, message = tt.authenticateParentUsernameAndPassword(localAvatar.DISLid, base.cr.password, username, password) + try: + DISLIdFromLogin = base.cr.DISLIdFromLogin + except: + DISLIdFromLogin = 0 + if DISLIdFromLogin and (DISLIdFromLogin != localAvatar.DISLid): + # we only expect to have 1 DISLId per player, we're screwed if this happens + self.notify.error( + "Mismatched DISLIds, fromLogin=%s, localAvatar.dislId=%s" % (DISLIdFromLogin, localAvatar.DISLid)) + okflag, message = tt.authenticateParentUsernameAndPassword(localAvatar.DISLid, base.cr.password, username, + password) if okflag: self.exit() openFriendSecret(self.secretType) elif message: - base.localAvatar.chatMgr.fsm.request('problemActivatingChat') - base.localAvatar.chatMgr.problemActivatingChat['text'] = OTPLocalizer.ProblemActivatingChat % message + # Error connecting. + base.localAvatar.chatMgr.fsm.request("problemActivatingChat") + base.localAvatar.chatMgr.problemActivatingChat['text'] = OTPLocalizer.ProblemActivatingChat % (message) else: + # Wrong password. self.dialog['text'] = OTPLocalizer.FriendSecretNeedsPasswordWarningWrongPassword self.passwordEntry['focus'] = 1 self.passwordEntry.enterText('') @@ -186,6 +237,7 @@ class FriendSecretNeedsParentLogin(StateData.StateData): def __oldHandleOK(self, *args): username = self.usernameEntry.get() password = self.passwordEntry.get() + # we need to store these in base.cr for __enterSecret base.cr.parentUsername = username base.cr.parentPassword = password tt = base.cr.loginInterface @@ -194,59 +246,83 @@ class FriendSecretNeedsParentLogin(StateData.StateData): self.exit() openFriendSecret(self.secretType) elif message: - base.localAvatar.chatMgr.fsm.request('problemActivatingChat') - base.localAvatar.chatMgr.problemActivatingChat['text'] = OTPLocalizer.ProblemActivatingChat % message + # Error connecting. + base.localAvatar.chatMgr.fsm.request("problemActivatingChat") + base.localAvatar.chatMgr.problemActivatingChat['text'] = OTPLocalizer.ProblemActivatingChat % (message) else: + # Wrong password. self.dialog['text'] = OTPLocalizer.FriendSecretNeedsPasswordWarningWrongPassword self.passwordEntry['focus'] = 1 self.passwordEntry.enterText('') def __handleOK(self, *args): + base.cr.parentUsername = self.usernameEntry.get() base.cr.parentPassword = self.passwordEntry.get() + # we don't have a request for this yet, so pretend we are submitting a limited secret base.cr.playerFriendsManager.sendRequestUseLimitedSecret('', base.cr.parentUsername, base.cr.parentPassword) self.accept(OTPGlobals.PlayerFriendRejectUseSecretEvent, self.__handleParentLogin) + # we won't get an answer yet, so spoof a return code + # self.__handleParentLogin(0) + # that doesn't work, just immediately close the panel self.exit() def __handleParentLogin(self, reason): + # don't know reason codes yet, spoof something if reason == 0: self.exit() openFriendSecret(self.secretType) elif reason == 1: + # Wrong username self.dialog['text'] = OTPLocalizer.FriendSecretNeedsPasswordWarningWrongUsername self.usernameEntry['focus'] = 1 self.usernameEntry.enterText('') elif reason == 2: + # Wrong password self.dialog['text'] = OTPLocalizer.FriendSecretNeedsPasswordWarningWrongPassword self.passwordEntry['focus'] = 1 self.passwordEntry.enterText('') else: - base.localAvatar.chatMgr.fsm.request('problemActivatingChat') - base.localAvatar.chatMgr.problemActivatingChat['text'] = OTPLocalizer.ProblemActivatingChat % message + # Error connecting (fall through case) + base.localAvatar.chatMgr.fsm.request("problemActivatingChat") + base.localAvatar.chatMgr.problemActivatingChat['text'] = OTPLocalizer.ProblemActivatingChat % (message) def __handleCancel(self): self.exit() class FriendSecret(DirectFrame, StateData.StateData): - notify = DirectNotifyGlobal.directNotify.newCategory('FriendSecret') + """ + This is a panel that allows the user to manage 'secrets' that is, + code words that identify people who are actually friends in real + life (and thus are entitled to use full chat with each other). + + This panel is the place the user will come to either get a new + 'secret' to give to someone else, or to enter the 'secret' they + got from someone. + """ + notify = DirectNotifyGlobal.directNotify.newCategory("FriendSecret") def __init__(self, secretType): - DirectFrame.__init__(self, parent=aspect2dp, pos=(0, 0, 0.3), relief=None, image=DGG.getDefaultDialogGeom(), image_scale=(1.6, 1, 1.4), image_pos=(0, 0, -0.05), image_color=OTPGlobals.GlobalDialogColor, borderWidth=(0.01, 0.01)) - StateData.StateData.__init__(self, 'friend-secret-done') + DirectFrame.__init__(self, parent=aspect2dp, pos=(0, 0, 0.30), relief=None, image=DGG.getDefaultDialogGeom(), + image_scale=(1.6, 1, 1.4), image_pos=(0, 0, -0.05), + image_color=OTPGlobals.GlobalDialogColor, borderWidth=(0.01, 0.01), ) + StateData.StateData.__init__(self, "friend-secret-done") self.initialiseoptions(FriendSecret) self.prefix = OTPGlobals.getDefaultProductPrefix() + # what types of secret friends will we offer self.secretType = secretType - self.notify.debug('### secretType = %s' % self.secretType) + self.notify.debug("### secretType = %s" % self.secretType) + # what type of secret friend has the user chosen self.requestedSecretType = secretType - self.notify.debug('### requestedSecretType = %s' % self.requestedSecretType) - return + self.notify.debug("### requestedSecretType = %s" % self.requestedSecretType) def unload(self): if self.isLoaded == 0: return None self.isLoaded = 0 self.exit() + del self.introText del self.getSecret del self.enterSecretText @@ -259,34 +335,48 @@ class FriendSecret(DirectFrame, StateData.StateData): del self.accountButton DirectFrame.destroy(self) self.ignore('clientCleanup') - return None def load(self): if self.isLoaded == 1: return None self.isLoaded = 1 - self.introText = DirectLabel(parent=self, relief=None, pos=(0, 0, 0.4), scale=0.05, text=OTPLocalizer.FriendSecretIntro, text_fg=(0, 0, 0, 1), text_wordwrap=30) + + self.introText = DirectLabel(parent=self, relief=None, pos=(0, 0, 0.4), scale=0.05, + text=OTPLocalizer.FriendSecretIntro, text_fg=(0, 0, 0, 1), text_wordwrap=30, ) self.introText.hide() - guiButton = loader.loadModel('phase_3/models/gui/quit_button') - self.getSecret = DirectButton(parent=self, relief=None, pos=(0, 0, -0.11), image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=OTPLocalizer.FSgetSecret, text=OTPLocalizer.FriendSecretGetSecret, text_scale=OTPLocalizer.FSgetSecretButton, text_pos=(0, -0.02), command=self.__determineSecret) + + guiButton = loader.loadModel("phase_3/models/gui/quit_button") + + self.getSecret = DirectButton(parent=self, relief=None, pos=(0, 0, -0.11), image=( + guiButton.find("**/QuitBtn_UP"), guiButton.find("**/QuitBtn_DN"), guiButton.find("**/QuitBtn_RLVR"),), + image_scale=OTPLocalizer.FSgetSecret, text=OTPLocalizer.FriendSecretGetSecret, + text_scale=OTPLocalizer.FSgetSecretButton, text_pos=(0, -0.02), command=self.__determineSecret, ) self.getSecret.hide() - self.enterSecretText = DirectLabel(parent=self, relief=None, pos=OTPLocalizer.FSenterSecretTextPos, scale=0.05, text=OTPLocalizer.FriendSecretEnterSecret, text_fg=(0, 0, 0, 1), text_wordwrap=30) + + self.enterSecretText = DirectLabel(parent=self, relief=None, pos=OTPLocalizer.FSenterSecretTextPos, scale=0.05, + text=OTPLocalizer.FriendSecretEnterSecret, text_fg=(0, 0, 0, 1), text_wordwrap=30, ) self.enterSecretText.hide() - self.enterSecret = DirectEntry(parent=self, relief=DGG.SUNKEN, scale=0.06, pos=(-0.6, 0, -0.38), frameColor=(0.8, 0.8, 0.5, 1), borderWidth=(0.1, 0.1), numLines=1, width=20, frameSize=(-0.4, - 20.4, - -0.4, - 1.1), command=self.__enterSecret) + + self.enterSecret = DirectEntry(parent=self, relief=DGG.SUNKEN, scale=0.06, pos=(-0.60, 0, -0.38), + frameColor=(0.8, 0.8, 0.5, 1), borderWidth=(0.1, 0.1), numLines=1, width=20, + frameSize=(-0.4, 20.4, -0.4, 1.1), command=self.__enterSecret) + + # This fixes a little problem with the initial frame size. self.enterSecret.resetFrameSize() self.enterSecret.hide() - self.ok1 = DirectButton(parent=self, relief=None, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=OTPLocalizer.FSok1, text=OTPLocalizer.FriendSecretEnter, text_scale=0.06, text_pos=(0, -0.02), pos=(0, 0, -0.5), command=self.__ok1) + + self.ok1 = DirectButton(parent=self, relief=None, image=( + guiButton.find("**/QuitBtn_UP"), guiButton.find("**/QuitBtn_DN"), guiButton.find("**/QuitBtn_RLVR"),), + image_scale=OTPLocalizer.FSok1, text=OTPLocalizer.FriendSecretEnter, text_scale=0.06, text_pos=(0, -0.02), + pos=(0, 0, -0.5), command=self.__ok1, ) self.ok1.hide() - if base.cr.productName in ['JP', - 'DE', - 'BR', - 'FR']: + if base.cr.productName in ['JP', 'DE', 'BR', 'FR']: + # There should be no 'change secret friends options' button in + # the UK version. + # the only thing we do to self.changeOptions is show and hide it; + # avoid adding a bunch of 'if' statements class ShowHide: - def show(self): pass @@ -294,16 +384,32 @@ class FriendSecret(DirectFrame, StateData.StateData): pass self.changeOptions = ShowHide() - self.ok2 = DirectButton(parent=self, relief=None, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=OTPLocalizer.FSok2, text=OTPLocalizer.FriendSecretOK, text_scale=0.06, text_pos=(0, -0.02), pos=(0, 0, -0.57), command=self.__ok2) + + self.ok2 = DirectButton(parent=self, relief=None, image=( + guiButton.find("**/QuitBtn_UP"), guiButton.find("**/QuitBtn_DN"), guiButton.find("**/QuitBtn_RLVR"),), + image_scale=OTPLocalizer.FSok2, text=OTPLocalizer.FriendSecretOK, text_scale=0.06, text_pos=(0, -0.02), + pos=(0, 0, -0.57), command=self.__ok2, ) self.ok2.hide() - self.cancel = DirectButton(parent=self, relief=None, text=OTPLocalizer.FriendSecretCancel, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=OTPLocalizer.FScancel, text_scale=0.06, text_pos=(0, -0.02), pos=(0, 0, -0.57), command=self.__cancel) + + self.cancel = DirectButton(parent=self, relief=None, text=OTPLocalizer.FriendSecretCancel, image=( + guiButton.find("**/QuitBtn_UP"), guiButton.find("**/QuitBtn_DN"), guiButton.find("**/QuitBtn_RLVR"),), + image_scale=OTPLocalizer.FScancel, text_scale=0.06, text_pos=(0, -0.02), pos=(0, 0, -0.57), + command=self.__cancel, ) self.cancel.hide() - self.nextText = DirectLabel(parent=self, relief=None, pos=(0, 0, 0.3), scale=0.06, text='', text_scale=OTPLocalizer.FSnextText, text_fg=(0, 0, 0, 1), text_wordwrap=25.5) + + self.nextText = DirectLabel(parent=self, relief=None, pos=(0, 0, 0.30), scale=0.06, text="", + text_scale=OTPLocalizer.FSnextText, text_fg=(0, 0, 0, 1), text_wordwrap=25.5, ) self.nextText.hide() - self.secretText = DirectLabel(parent=self, relief=None, pos=(0, 0, -0.42), scale=0.1, text='', text_fg=(0, 0, 0, 1), text_wordwrap=30) + + self.secretText = DirectLabel(parent=self, relief=None, pos=(0, 0, -0.42), scale=0.1, text="", + text_fg=(0, 0, 0, 1), text_wordwrap=30, ) self.secretText.hide() + guiButton.removeNode() + + # moved into it's own method to make overloading easier self.makeFriendTypeButtons() + self.accept('clientCleanup', self.__handleCleanup) self.accept('walkDone', self.__handleStop) @@ -314,59 +420,100 @@ class FriendSecret(DirectFrame, StateData.StateData): self.unload() def makeFriendTypeButtons(self): + # NOTE: this uses generic text, if you want game-specific text, please inherit and override + # (see $TOONTOWN/src/friends/ToontownFriendSecret.py for an example) buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui') - self.avatarButton = DirectButton(self, image=(buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')), relief=None, text=OTPLocalizer.FriendSecretDetermineSecretAvatar, text_scale=0.07, text_pos=(0.0, -0.1), pos=(-0.35, 0.0, -0.05), command=self.__handleAvatar) - avatarText = DirectLabel(parent=self, relief=None, pos=Vec3(0.35, 0, -0.3), text=OTPLocalizer.FriendSecretDetermineSecretAvatarRollover, text_fg=(0, 0, 0, 1), text_pos=(0, 0), text_scale=0.055, text_align=TextNode.ACenter) + + # make an avatar friend + self.avatarButton = DirectButton(self, image=( + buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')), + relief=None, text=OTPLocalizer.FriendSecretDetermineSecretAvatar, text_scale=0.07, text_pos=(0.0, -0.1), + pos=(-0.35, 0.0, -0.05), command=self.__handleAvatar) + # make a label to show avatar friend desc on rollover + avatarText = DirectLabel(parent=self, relief=None, pos=Vec3(0.35, 0, -0.3), + text=OTPLocalizer.FriendSecretDetermineSecretAvatarRollover, text_fg=(0, 0, 0, 1), text_pos=(0, 0), + text_scale=0.055, text_align=TextNode.ACenter, ) avatarText.reparentTo(self.avatarButton.stateNodePath[2]) self.avatarButton.hide() - self.accountButton = DirectButton(self, image=(buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')), relief=None, text=OTPLocalizer.FriendSecretDetermineSecretAccount, text_scale=0.07, text_pos=(0.0, -0.1), pos=(0.35, 0.0, -0.05), command=self.__handleAccount) - accountText = DirectLabel(parent=self, relief=None, pos=Vec3(-0.35, 0, -0.3), text=OTPLocalizer.FriendSecretDetermineSecretAccountRollover, text_fg=(0, 0, 0, 1), text_pos=(0, 0), text_scale=0.055, text_align=TextNode.ACenter) + + # make an account friend + self.accountButton = DirectButton(self, image=( + buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')), + relief=None, text=OTPLocalizer.FriendSecretDetermineSecretAccount, text_scale=0.07, text_pos=(0.0, -0.1), + pos=(0.35, 0.0, -0.05), command=self.__handleAccount) + # make a label to show feature desc on rollover + accountText = DirectLabel(parent=self, relief=None, pos=Vec3(-0.35, 0, -0.3), + text=OTPLocalizer.FriendSecretDetermineSecretAccountRollover, text_fg=(0, 0, 0, 1), text_pos=(0, 0), + text_scale=0.055, text_align=TextNode.ACenter, ) accountText.reparentTo(self.accountButton.stateNodePath[2]) self.accountButton.hide() + buttons.removeNode() - return def enter(self): if self.isEntered == 1: return self.isEntered = 1 + # Use isLoaded to avoid redundant loading if self.isLoaded == 0: self.load() + self.show() + + # Set us up on the first page. self.introText.show() self.getSecret.show() self.enterSecretText.show() self.enterSecret.show() self.ok1.show() + self.ok2.hide() self.cancel.hide() self.nextText.hide() self.secretText.hide() - base.localAvatar.chatMgr.fsm.request('otherDialog') + + # While the entry's on the screen, we have to turn off the + # background focus on the normal chat entry. Otherwise, + # keypresses would start chatting! + base.localAvatar.chatMgr.fsm.request("otherDialog") + + # And now we can set the focus on our entry. self.enterSecret['focus'] = 1 + + # The secret panel uses up a lot of space onscreen; in + # particular, it will hide most of the chat balloons. Force + # these to go to the margins. NametagGlobals.setOnscreenChatForced(1) def exit(self): if self.isEntered == 0: return self.isEntered = 0 + + # Restore the normal chat behavior. NametagGlobals.setOnscreenChatForced(0) + self.__cleanupFirstPage() self.ignoreAll() self.accept('clientCleanup', self.unload) self.hide() def __determineSecret(self): + # If we support both types of secrets... if self.secretType == BothSecrets: + # ask the player what type they want self.__cleanupFirstPage() self.ok1.hide() + # NOTE: this uses generic text, if you want game-specific text, please inherit and override + # (see $TOONTOWN/src/friends/ToontownFriendSecret.py for an example) self.nextText['text'] = OTPLocalizer.FriendSecretDetermineSecret - self.nextText.setPos(0, 0, 0.3) + self.nextText.setPos(0, 0, 0.30) self.nextText.show() self.avatarButton.show() self.accountButton.show() self.cancel.show() else: + # or just get the secret self.__getSecret() def __handleAvatar(self): @@ -383,39 +530,36 @@ class FriendSecret(DirectFrame, StateData.StateData): def __getSecret(self): self.__cleanupFirstPage() self.nextText['text'] = OTPLocalizer.FriendSecretGettingSecret - self.nextText.setPos(0, 0, 0.3) + self.nextText.setPos(0, 0, 0.30) self.nextText.show() self.avatarButton.hide() self.accountButton.hide() self.ok1.hide() self.cancel.show() - if self.requestedSecretType == AvatarSecret: - if not base.cr.friendManager: - self.notify.warning('No FriendManager available.') - self.exit() - return - base.cr.friendManager.up_requestSecret() - self.accept('requestSecretResponse', self.__gotAvatarSecret) - else: - if base.cr.needParentPasswordForSecretChat(): - self.notify.info('### requestLimitedSecret') - base.cr.playerFriendsManager.sendRequestLimitedSecret(base.cr.parentUsername, base.cr.parentPassword) - else: - base.cr.playerFriendsManager.sendRequestUnlimitedSecret() - self.notify.info('### requestUnlimitedSecret') - self.accept(OTPGlobals.PlayerFriendNewSecretEvent, self.__gotAccountSecret) - self.accept(OTPGlobals.PlayerFriendRejectNewSecretEvent, self.__rejectAccountSecret) + # If we don't have a FriendManager, something's badly wrong. + # Most likely we're running in a development environment + # without an AI client. + if not base.cr.friendManager: + self.notify.warning("No FriendManager available.") + self.exit() + return + base.cr.friendManager.up_requestSecret() + self.accept('requestSecretResponse', + self.__gotAvatarSecret) # else: # if base.cr.needParentPasswordForSecretChat(): # self.notify.info("### requestLimitedSecret") # base.cr.playerFriendsManager.sendRequestLimitedSecret(base.cr.parentUsername, base.cr.parentPassword) # else: # base.cr.playerFriendsManager.sendRequestUnlimitedSecret() # self.notify.info("### requestUnlimitedSecret") # self.accept(OTPGlobals.PlayerFriendNewSecretEvent, self.__gotAccountSecret) # self.accept(OTPGlobals.PlayerFriendRejectNewSecretEvent, self.__rejectAccountSecret) def __gotAvatarSecret(self, result, secret): self.ignore('requestSecretResponse') + if result == 1: self.nextText['text'] = OTPLocalizer.FriendSecretGotSecret self.nextText.setPos(*OTPLocalizer.FSgotSecretPos) - if self.prefix: - self.secretText['text'] = self.prefix + ' ' + secret - else: - self.secretText['text'] = secret + # always append the prefix + self.secretText['text'] = self.prefix + ' ' + secret + elif result == 2: + self.nextText['text'] = OTPLocalizer.FriendSecretTooManyFriends + else: + # Oops, too many secrets. self.nextText['text'] = OTPLocalizer.FriendSecretTooMany self.nextText.show() self.secretText.show() @@ -423,133 +567,148 @@ class FriendSecret(DirectFrame, StateData.StateData): self.ok1.hide() self.ok2.show() - def __gotAccountSecret(self, secret): - self.ignore(OTPGlobals.PlayerFriendNewSecretEvent) - self.ignore(OTPGlobals.PlayerFriendRejectNewSecretEvent) - self.nextText['text'] = OTPLocalizer.FriendSecretGotSecret - self.nextText.setPos(0, 0, 0.47) - self.secretText['text'] = secret - self.nextText.show() - self.secretText.show() - self.cancel.hide() - self.ok1.hide() - self.ok2.show() - - def __rejectAccountSecret(self, reason): - print('## rejectAccountSecret: reason = ', reason) - self.ignore(OTPGlobals.PlayerFriendNewSecretEvent) - self.ignore(OTPGlobals.PlayerFriendRejectNewSecretEvent) - self.nextText['text'] = OTPLocalizer.FriendSecretTooMany - self.nextText.show() - self.secretText.show() - self.cancel.hide() - self.ok1.hide() - self.ok2.show() - def __enterSecret(self, secret): - self.enterSecret.set('') + # Empty the entry for next time. + self.enterSecret.set("") + secret = secret.strip() if not secret: + # If the secret is empty, it just means to close down + # the dialog. self.exit() return + + # If we don't have a FriendManager, something's badly wrong. + # Most likely we're running in a development environment + # without an AI client. if not base.cr.friendManager: - self.notify.warning('No FriendManager available.') + self.notify.warning("No FriendManager available.") self.exit() return + self.__cleanupFirstPage() + + # The client can now prepend a product prefix to all secrets - strip this off if present if self.prefix: if secret[0:2] == self.prefix: secret = secret[3:] - self.notify.info('### use TT secret') + self.notify.info("### use TT secret") self.accept('submitSecretResponse', self.__enteredSecret) base.cr.friendManager.up_submitSecret(secret) - else: - self.accept(OTPGlobals.PlayerFriendUpdateEvent, self.__useAccountSecret) - self.accept(OTPGlobals.PlayerFriendRejectUseSecretEvent, self.__rejectUseAccountSecret) - if base.cr.needParentPasswordForSecretChat(): - self.notify.info('### useLimitedSecret') - base.cr.playerFriendsManager.sendRequestUseLimitedSecret(secret, base.cr.parentUsername, base.cr.parentPassword) - else: - self.notify.info('### useUnlimitedSecret') - base.cr.playerFriendsManager.sendRequestUseUnlimitedSecret(secret) + self.nextText['text'] = OTPLocalizer.FriendSecretTryingSecret - self.nextText.setPos(0, 0, 0.3) + self.nextText.setPos(0, 0, 0.30) self.nextText.show() self.ok1.hide() self.cancel.show() def __enteredSecret(self, result, avId): self.ignore('submitSecretResponse') + if result == 1: + # We made it! handle = base.cr.identifyAvatar(avId) if handle != None: - self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretSuccess % handle.getName() + self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretSuccess % (handle.getName()) else: + # Shoot. We just made friends with someone, but we + # don't know who it is yet. We'll have to ask the + # server who this is, and wait for the response before + # we can continue. self.accept('friendsMapComplete', self.__nowFriends, [avId]) ready = base.cr.fillUpFriendsMap() if ready: self.__nowFriends(avId) return + elif result == 0: + # Unknown secret. self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretUnknown + elif result == 2: + # Friends list full. handle = base.cr.identifyAvatar(avId) if handle != None: - self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretFull % handle.getName() + self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretFull % (handle.getName()) else: self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretFullNoName + elif result == 3: + # Self match. self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretSelf + elif result == 4: - self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretWrongProduct % self.prefix + # This doesn't look like our secret friend code - wrong prefix + self.nextText['text'] = OTPLocalizer.FriendSecretEnteredSecretWrongProduct % (self.prefix) + self.nextText.show() self.cancel.hide() self.ok1.hide() self.ok2.show() - return def __useAccountSecret(self, avId, friendInfo): self.ignore(OTPGlobals.PlayerFriendUpdateEvent) self.ignore(OTPGlobals.PlayerFriendRejectUseSecretEvent) + + # todo - pass an avId? self.__enteredSecret(1, 0) def __rejectUseAccountSecret(self, reason): - print('## rejectUseAccountSecret: reason = ', reason) + print("## rejectUseAccountSecret: reason = ", reason) self.ignore(OTPGlobals.PlayerFriendUpdateEvent) self.ignore(OTPGlobals.PlayerFriendRejectUseSecretEvent) - if reason == RejectCode.RejectCode.FRIENDS_LIST_FULL: + + if (reason == RejectCode.RejectCode.FRIENDS_LIST_FULL): self.__enteredSecret(2, 0) - elif reason == RejectCode.RejectCode.ALREADY_FRIENDS_WITH_SELF: + elif (reason == RejectCode.RejectCode.ALREADY_FRIENDS_WITH_SELF): self.__enteredSecret(3, 0) else: + # todo: this shouldn't be the fall thru self.__enteredSecret(0, 0) def __nowFriends(self, avId): + # This is called only from enteredSecret(), after the friend + # transaction has completed. This will be called only if the + # client didn't know the identity of the friend at the time, + # but it should know now. + self.ignore('friendsMapComplete') + handle = base.cr.identifyAvatar(avId) if handle != None: - self.nextText['text'] = OTPLocalizer.FriendSecretNowFriends % handle.getName() + self.nextText['text'] = OTPLocalizer.FriendSecretNowFriends % (handle.getName()) else: + # This really shouldn't be possible. self.nextText['text'] = OTPLocalizer.FriendSecretNowFriendsNoName + self.nextText.show() self.cancel.hide() self.ok1.hide() self.ok2.show() - return def __ok1(self): + # Clicking "ok" from the front screen is the same thing as + # pressing Enter in the entry. secret = self.enterSecret.get() self.__enterSecret(secret) def __ok2(self): + # Clicking "ok" from a finished screen just makes the thing go + # away. self.exit() def __cancel(self): + # Clicking "cancel" makes the panel close too. self.exit() def __cleanupFirstPage(self): + # Removes all the widgets etc. that were created for the + # welcome page, except the introText. + self.introText.hide() self.getSecret.hide() self.enterSecretText.hide() self.enterSecret.hide() - base.localAvatar.chatMgr.fsm.request('mainMenu') + + # Restore the background focus on the chat entry. + base.localAvatar.chatMgr.fsm.request("mainMenu") diff --git a/toontown/friends/ToontownFriendSecret.py b/toontown/friends/ToontownFriendSecret.py index 491a7ce..f7dc1a8 100644 --- a/toontown/friends/ToontownFriendSecret.py +++ b/toontown/friends/ToontownFriendSecret.py @@ -3,9 +3,13 @@ from direct.gui.DirectGui import * from direct.directnotify import DirectNotifyGlobal from otp.otpbase import OTPLocalizer from toontown.toonbase import TTLocalizer + +# This file overrides key methods in FriendSecret to add Toontown specific text to the OTP buttons + from otp.friends.FriendSecret import AccountSecret from otp.friends.FriendSecret import AvatarSecret from otp.friends.FriendSecret import BothSecrets + from otp.friends import FriendSecret from otp.friends.FriendSecret import globalFriendSecret from otp.friends.FriendSecret import showFriendSecret @@ -18,41 +22,94 @@ def openFriendSecret(secretType): globalFriendSecret.unload() globalFriendSecret = ToontownFriendSecret(secretType) globalFriendSecret.enter() - return - +# there is no way to overload module level methods, so hammer it in FriendSecret.openFriendSecret = openFriendSecret class ToontownFriendSecret(FriendSecret.FriendSecret): - notify = DirectNotifyGlobal.directNotify.newCategory('ToontownFriendSecret') + + notify = DirectNotifyGlobal.directNotify.newCategory("ToontownFriendSecret") def __init__(self, secretType): + #secretType is specefied in toon/ToonAvatarPanel.py-> __handleSecrets(self): FriendSecret.FriendSecret.__init__(self, secretType) self.initialiseoptions(ToontownFriendSecret) def makeFriendTypeButtons(self): + assert self.notify.debugCall() + buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui') - self.avatarButton = DirectButton(parent=self, image=(buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')), relief=None, text=TTLocalizer.FriendInviterToon, text_scale=0.07, text_pos=(0.0, -0.1), pos=(-0.35, 0.0, -0.05), command=self._FriendSecret__handleAvatar) - avatarText = DirectLabel(parent=self, relief=None, pos=Vec3(0.35, 0, -0.3), text=TTLocalizer.FriendInviterToonFriendInfo, text_fg=(0, 0, 0, 1), text_pos=(0, 0), text_scale=0.055, text_align=TextNode.ACenter) + + # make an avatar friend + self.avatarButton = DirectButton( + parent = self, + image = (buttons.find('**/ChtBx_OKBtn_UP'), + buttons.find('**/ChtBx_OKBtn_DN'), + buttons.find('**/ChtBx_OKBtn_Rllvr')), + relief = None, + text = TTLocalizer.FriendInviterToon, + text_scale = 0.07, + text_pos = (0.0, -0.1), + pos = (-0.35, 0.0, -0.05), + command = self._FriendSecret__handleAvatar + ) + # make a label to show avatar friend desc on rollover + avatarText = DirectLabel( + parent = self, + relief = None, + pos = Vec3(0.35, 0, -0.3), + text = TTLocalizer.FriendInviterToonFriendInfo, + text_fg = (0, 0, 0, 1), + text_pos = (0, 0), + text_scale = 0.055, + text_align = TextNode.ACenter, + ) avatarText.reparentTo(self.avatarButton.stateNodePath[2]) self.avatarButton.hide() - self.accountButton = DirectButton(parent=self, image=(buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')), relief=None, text=TTLocalizer.FriendInviterPlayer, text_scale=0.07, text_pos=(0.0, -0.1), pos=(0.35, 0.0, -0.05), command=self._FriendSecret__handleAccount) - accountText = DirectLabel(parent=self, relief=None, pos=Vec3(-0.35, 0, -0.3), text=TTLocalizer.FriendInviterPlayerFriendInfo, text_fg=(0, 0, 0, 1), text_pos=(0, 0), text_scale=0.055, text_align=TextNode.ACenter) + + # make an account friend + self.accountButton = DirectButton( + parent = self, + image = (buttons.find('**/ChtBx_OKBtn_UP'), + buttons.find('**/ChtBx_OKBtn_DN'), + buttons.find('**/ChtBx_OKBtn_Rllvr')), + relief = None, + text = TTLocalizer.FriendInviterPlayer, + text_scale = 0.07, + text_pos = (0.0, -0.1), + pos = (0.35, 0.0, -0.05), + command = self._FriendSecret__handleAccount + ) + # make a label to show feature desc on rollover + accountText = DirectLabel( + parent = self, + relief = None, + pos = Vec3(-0.35, 0, -0.3), + text = TTLocalizer.FriendInviterPlayerFriendInfo, + text_fg = (0, 0, 0, 1), + text_pos = (0, 0), + text_scale = 0.055, + text_align = TextNode.ACenter, + ) accountText.reparentTo(self.accountButton.stateNodePath[2]) self.accountButton.hide() + buttons.removeNode() - return def __determineSecret(self): + assert self.notify.debugCall() + # If we support both types of secrets... if self.secretType == BothSecrets: + # ask the player what type they want self._FriendSecret__cleanupFirstPage() self.ok1.hide() self.changeOptions.hide() self.nextText['text'] = TTLocalizer.FriendInviterBegin - self.nextText.setPos(0, 0, 0.3) + self.nextText.setPos(0, 0, 0.30) self.nextText.show() self.avatarButton.show() self.accountButton.show() self.cancel.show() else: + # or just get the secret self._FriendSecret__getSecret() diff --git a/toontown/friends/ToontownFriendsManagerAI.py b/toontown/friends/ToontownFriendsManagerAI.py index a068cc7..7a73003 100644 --- a/toontown/friends/ToontownFriendsManagerAI.py +++ b/toontown/friends/ToontownFriendsManagerAI.py @@ -22,5 +22,8 @@ class ToontownFriendsManagerAI(DistributedObjectGlobalAI): messenger.send("makeFriendsReply", [result, context]) + def requestSecretResponse(self, result, secret, avId): + messenger.send("requestSecretReply", [result, secret, avId]) + def sendRequestSecret(self, requesterId): self.sendUpdate('requestSecret', [requesterId]) diff --git a/toontown/friends/ToontownFriendsManagerUD.py b/toontown/friends/ToontownFriendsManagerUD.py index 91830eb..42f6402 100644 --- a/toontown/friends/ToontownFriendsManagerUD.py +++ b/toontown/friends/ToontownFriendsManagerUD.py @@ -3,26 +3,52 @@ from direct.distributed.DistributedObjectGlobalUD import DistributedObjectGlobal from direct.distributed.PyDatagram import * from otp.otpbase import OTPGlobals - - +import random +import string +import json class FriendsOperation: + """ + Base class for all friend-related operations. + """ def __init__(self, friendsManager, sender): + """ + Initialize the FriendsOperation. + + :param friendsManager: The friends manager instance. + :param sender: The sender's ID. + """ self.friendsManager = friendsManager self.sender = sender def _handleDone(self): - # TODO - pass + """ + Handle the completion of the operation. + """ + self.friendsManager.operations.remove(self) def _handleError(self, error): - # TODO - pass + """ + Handle an error during the operation. + + :param error: The error message. + """ + self.friendsManager.notify.warning(error) + self.friendsManager.operations.remove(self) class GetFriendsListOperation(FriendsOperation): + """ + Operation to retrieve the friends list of a sender. + """ def __init__(self, friendsManager, sender): + """ + Initialize the GetFriendsListOperation. + + :param friendsManager: The friends manager instance. + :param sender: The sender's ID. + """ FriendsOperation.__init__(self, friendsManager, sender) self.friendsList = None self.tempFriendsList = None @@ -30,6 +56,9 @@ class GetFriendsListOperation(FriendsOperation): self.currentFriendIdx = None def start(self): + """ + Start the operation to retrieve the friends list. + """ self.friendsList = [] self.tempFriendsList = [] self.onlineFriends = [] @@ -38,6 +67,12 @@ class GetFriendsListOperation(FriendsOperation): self.__handleSenderRetrieved) def __handleSenderRetrieved(self, dclass, fields): + """ + Handle the retrieval of the sender's data. + + :param dclass: The data class of the sender. + :param fields: The fields of the sender. + """ if dclass != self.friendsManager.air.dclassesByName['DistributedToonUD']: self._handleError('Retrieved sender is not a DistributedToonUD!') return @@ -51,6 +86,12 @@ class GetFriendsListOperation(FriendsOperation): self.__handleFriendRetrieved) def __handleFriendRetrieved(self, dclass, fields): + """ + Handle the retrieval of a friend's data. + + :param dclass: The data class of the friend. + :param fields: The fields of the friend. + """ if dclass != self.friendsManager.air.dclassesByName['DistributedToonUD']: self._handleError('Retrieved friend is not a DistributedToonUD!') return @@ -67,11 +108,20 @@ class GetFriendsListOperation(FriendsOperation): self.__handleFriendRetrieved) def __checkFriendsOnline(self): + """ + Check which friends are currently online. + """ self.currentFriendIdx = 0 for friendDetails in self.friendsList: self.friendsManager.air.getActivated(friendDetails[0], self.__gotActivatedResp) def __gotActivatedResp(self, avId, activated): + """ + Handle the response of checking if a friend is activated. + + :param avId: The avatar ID. + :param activated: Whether the friend is activated. + """ self.currentFriendIdx += 1 if activated: self.onlineFriends.append(avId) @@ -80,34 +130,67 @@ class GetFriendsListOperation(FriendsOperation): self._handleDone() def __sendFriendsList(self, success): + """ + Send the friends list to the sender. + + :param success: Whether the operation was successful. + """ self.friendsManager.sendUpdateToAvatarId(self.sender, 'getFriendsListResponse', [success, self.friendsList if success else []]) for friendId in self.onlineFriends: self.friendsManager.sendFriendOnline(self.sender, friendId, 0, 1) def _handleDone(self): + """ + Handle the completion of the operation. + """ self.__sendFriendsList(True) FriendsOperation._handleDone(self) def _handleError(self, error): + """ + Handle an error during the operation. + + :param error: The error message. + """ self.__sendFriendsList(False) FriendsOperation._handleError(self, error) class GetAvatarDetailsOperation(FriendsOperation): + """ + Operation to retrieve the details of an avatar. + """ def __init__(self, friendsManager, sender): + """ + Initialize the GetAvatarDetailsOperation. + + :param friendsManager: The friends manager instance. + :param sender: The sender's ID. + """ FriendsOperation.__init__(self, friendsManager, sender) self.avId = None self.dclass = None self.fields = None def start(self, avId): + """ + Start the operation to retrieve the avatar details. + + :param avId: The avatar ID. + """ self.avId = avId self.fields = {} self.friendsManager.air.dbInterface.queryObject(self.friendsManager.air.dbId, avId, self.__handleAvatarRetrieved) def __handleAvatarRetrieved(self, dclass, fields): + """ + Handle the retrieval of the avatar's data. + + :param dclass: The data class of the avatar. + :param fields: The fields of the avatar. + """ if dclass not in (self.friendsManager.air.dclassesByName['DistributedToonUD'], self.friendsManager.air.dclassesByName['DistributedPetAI']): self._handleError('Retrieved avatar is not a DistributedToonUD or DistributedPetAI!') @@ -119,6 +202,13 @@ class GetAvatarDetailsOperation(FriendsOperation): self._handleDone() def __packAvatarDetails(self, dclass, fields): + """ + Pack the avatar details into a byte array. + + :param dclass: The data class of the avatar. + :param fields: The fields of the avatar. + :return: The packed avatar details. + """ # Pack required fields. fieldPacker = DCPacker() for i in range(dclass.getNumInheritedFields()): @@ -140,6 +230,11 @@ class GetAvatarDetailsOperation(FriendsOperation): return fieldPacker.getBytes() def __sendAvatarDetails(self, success): + """ + Send the avatar details to the sender. + + :param success: Whether the operation was successful. + """ datagram = PyDatagram() datagram.addUint32(self.fields['avId']) # avId datagram.addUint8(0 if success else 1) # returnCode @@ -150,17 +245,33 @@ class GetAvatarDetailsOperation(FriendsOperation): self.friendsManager.sendUpdateToAvatarId(self.sender, 'getAvatarDetailsResponse', [datagram.getMessage()]) def _handleDone(self): + """ + Handle the completion of the operation. + """ self.__sendAvatarDetails(True) FriendsOperation._handleDone(self) def _handleError(self, error): + """ + Handle an error during the operation. + + :param error: The error message. + """ self.__sendAvatarDetails(False) FriendsOperation._handleError(self, error) class MakeFriendsOperation(FriendsOperation): + """ + Operation to make two avatars friends. + """ def __init__(self, friendsManager): + """ + Initialize the MakeFriendsOperation. + + :param friendsManager: The friends manager instance. + """ FriendsOperation.__init__(self, friendsManager, None) self.avatarAId = None self.avatarBId = None @@ -172,6 +283,14 @@ class MakeFriendsOperation(FriendsOperation): self.avatarBFriendsList = None def start(self, avatarAId, avatarBId, flags, context): + """ + Start the operation to make two avatars friends. + + :param avatarAId: The first avatar's ID. + :param avatarBId: The second avatar's ID. + :param flags: The friendship flags. + :param context: The context of the operation. + """ self.avatarAId = avatarAId self.avatarBId = avatarBId self.flags = flags @@ -181,14 +300,34 @@ class MakeFriendsOperation(FriendsOperation): self.friendsManager.air.getActivated(self.avatarAId, self.__gotActivatedAvatarA) def __handleActivatedResp(self, avId, activated): + """ + Handle the response of checking if an avatar is activated. + + :param avId: The avatar ID. + :param activated: Whether the avatar is activated. + """ if activated: self.onlineToons.append(avId) def __gotActivatedAvatarA(self, avId, activated): + """ + Handle the response of checking if the first avatar is activated. + + :param avId: The avatar ID. + :param activated: Whether the avatar is activated. + """ self.__handleActivatedResp(avId, activated) self.friendsManager.air.getActivated(self.avatarBId, self.__gotActivatedAvatarB) def __handleMakeFriends(self, dclass, fields, friendId): + """ + Handle the process of making friends. + + :param dclass: The data class of the avatar. + :param fields: The fields of the avatar. + :param friendId: The friend's ID. + :return: A tuple indicating success and the updated friends list. + """ if dclass != self.friendsManager.air.dclassesByName['DistributedToonUD']: self._handleError('Retrieved avatar is not a DistributedToonUD!') return False, [] @@ -207,6 +346,12 @@ class MakeFriendsOperation(FriendsOperation): return True, friendsList def __handleAvatarARetrieved(self, dclass, fields): + """ + Handle the retrieval of the first avatar's data. + + :param dclass: The data class of the avatar. + :param fields: The fields of the avatar. + """ success, avatarAFriendsList = self.__handleMakeFriends(dclass, fields, self.avatarBId) if success: self.avatarAFriendsList = avatarAFriendsList @@ -214,17 +359,35 @@ class MakeFriendsOperation(FriendsOperation): self.__handleAvatarBRetrieved) def __gotActivatedAvatarB(self, avId, activated): + """ + Handle the response of checking if the second avatar is activated. + + :param avId: The avatar ID. + :param activated: Whether the avatar is activated. + """ self.__handleActivatedResp(avId, activated) self.friendsManager.air.dbInterface.queryObject(self.friendsManager.air.dbId, self.avatarAId, self.__handleAvatarARetrieved) def __handleAvatarBRetrieved(self, dclass, fields): + """ + Handle the retrieval of the second avatar's data. + + :param dclass: The data class of the avatar. + :param fields: The fields of the avatar. + """ success, avatarBFriendsList = self.__handleMakeFriends(dclass, fields, self.avatarAId) if success: self.avatarBFriendsList = avatarBFriendsList self._handleDone() def __handleSetFriendsList(self, avId, friendsList): + """ + Handle setting the friends list for an avatar. + + :param avId: The avatar ID. + :param friendsList: The updated friends list. + """ if avId in self.onlineToons: self.friendsManager.sendUpdateToAvatar(avId, 'setFriendsList', [friendsList]) else: @@ -234,6 +397,9 @@ class MakeFriendsOperation(FriendsOperation): {'setFriendsList': [friendsList]}) def _handleDone(self): + """ + Handle the completion of the operation. + """ self.resultCode = 1 if self.avatarAFriendsList is not None and self.avatarBFriendsList is not None: self.__handleSetFriendsList(self.avatarAId, self.avatarAFriendsList) @@ -247,14 +413,28 @@ class MakeFriendsOperation(FriendsOperation): FriendsOperation._handleDone(self) def _handleError(self, error): + """ + Handle an error during the operation. + + :param error: The error message. + """ self.resultCode = 0 self.friendsManager.sendMakeFriendsResponse(self.avatarAId, self.avatarBId, self.resultCode, self.context) FriendsOperation._handleError(self, error) class RemoveFriendOperation(FriendsOperation): + """ + Operation to remove a friend from the sender's friends list. + """ def __init__(self, friendsManager, sender): + """ + Initialize the RemoveFriendOperation. + + :param friendsManager: The friends manager instance. + :param sender: The sender's ID. + """ FriendsOperation.__init__(self, friendsManager, sender) self.friendId = None self.onlineToons = None @@ -262,24 +442,55 @@ class RemoveFriendOperation(FriendsOperation): self.friendFriendsList = None def start(self, friendId): + """ + Start the operation to remove a friend. + + :param friendId: The friend's ID. + """ self.friendId = friendId self.onlineToons = [] self.friendsManager.air.getActivated(self.sender, self.__gotSenderActivated) def __handleActivatedResp(self, avId, activated): + """ + Handle the response of checking if an avatar is activated. + + :param avId: The avatar ID. + :param activated: Whether the avatar is activated. + """ if activated: self.onlineToons.append(avId) def __gotSenderActivated(self, avId, activated): + """ + Handle the response of checking if the sender is activated. + + :param avId: The avatar ID. + :param activated: Whether the avatar is activated. + """ self.__handleActivatedResp(avId, activated) self.friendsManager.air.getActivated(self.friendId, self.__gotFriendActivated) def __gotFriendActivated(self, avId, activated): + """ + Handle the response of checking if the friend is activated. + + :param avId: The avatar ID. + :param activated: Whether the avatar is activated. + """ self.__handleActivatedResp(avId, activated) self.friendsManager.air.dbInterface.queryObject(self.friendsManager.air.dbId, self.sender, self.__handleSenderRetrieved) def __handleRemoveFriend(self, dclass, fields, friendId): + """ + Handle the process of removing a friend. + + :param dclass: The data class of the avatar. + :param fields: The fields of the avatar. + :param friendId: The friend's ID. + :return: A tuple indicating success and the updated friends list. + """ if dclass != self.friendsManager.air.dclassesByName['DistributedToonUD']: self._handleError('Retrieved sender is not a DistributedToonUD!') return False, [] @@ -299,6 +510,12 @@ class RemoveFriendOperation(FriendsOperation): return False, [] def __handleSenderRetrieved(self, dclass, fields): + """ + Handle the retrieval of the sender's data. + + :param dclass: The data class of the sender. + :param fields: The fields of the sender. + """ success, senderFriendsList = self.__handleRemoveFriend(dclass, fields, self.friendId) if success: self.senderFriendsList = senderFriendsList @@ -306,12 +523,24 @@ class RemoveFriendOperation(FriendsOperation): self.__handleFriendRetrieved) def __handleFriendRetrieved(self, dclass, fields): + """ + Handle the retrieval of the friend's data. + + :param dclass: The data class of the friend. + :param fields: The fields of the friend. + """ success, friendFriendsList = self.__handleRemoveFriend(dclass, fields, self.sender) if success: self.friendFriendsList = friendFriendsList self._handleDone() def __handleSetFriendsList(self, avId, friendsList): + """ + Handle setting the friends list for an avatar. + + :param avId: The avatar ID. + :param friendsList: The updated friends list. + """ if avId in self.onlineToons: self.friendsManager.sendUpdateToAvatar(avId, 'setFriendsList', [friendsList]) else: @@ -321,6 +550,9 @@ class RemoveFriendOperation(FriendsOperation): {'setFriendsList': [friendsList]}) def _handleDone(self): + """ + Handle the completion of the operation. + """ if self.senderFriendsList is not None and self.friendFriendsList is not None: self.__handleSetFriendsList(self.sender, self.senderFriendsList) self.__handleSetFriendsList(self.friendId, self.friendFriendsList) @@ -336,24 +568,47 @@ class RemoveFriendOperation(FriendsOperation): class ComingOnlineOperation(FriendsOperation): + """ + Operation to handle an avatar coming online. + """ def __init__(self, friendsManager): + """ + Initialize the ComingOnlineOperation. + + :param friendsManager: The friends manager instance. + """ FriendsOperation.__init__(self, friendsManager, None) self.avId = None self.friendsList = None self.currentFriendIdx = None def start(self, avId, friendsList): + """ + Start the operation to handle an avatar coming online. + + :param avId: The avatar ID. + :param friendsList: The friends list of the avatar. + """ self.avId = avId self.friendsList = friendsList self.__checkFriendsOnline() def __checkFriendsOnline(self): + """ + Check which friends are currently online. + """ self.currentFriendIdx = 0 for friendId in self.friendsList: self.friendsManager.air.getActivated(friendId, self.__gotFriendActivated) def __gotFriendActivated(self, avId, activated): + """ + Handle the response of checking if a friend is activated. + + :param avId: The avatar ID. + :param activated: Whether the friend is activated. + """ self.currentFriendIdx += 1 if activated: self.friendsManager.declareObject(avId, self.avId) @@ -365,8 +620,16 @@ class ComingOnlineOperation(FriendsOperation): class GoingOfflineOperation(FriendsOperation): + """ + Operation to handle an avatar going offline. + """ def __init__(self, friendsManager): + """ + Initialize the GoingOfflineOperation. + + :param friendsManager: The friends manager instance. + """ FriendsOperation.__init__(self, friendsManager, None) self.avId = None self.friendsList = None @@ -374,12 +637,23 @@ class GoingOfflineOperation(FriendsOperation): self.currentFriendIdx = None def start(self, avId): + """ + Start the operation to handle an avatar going offline. + + :param avId: The avatar ID. + """ self.avId = avId self.friendsList = [] self.accId = 0 self.friendsManager.air.dbInterface.queryObject(self.friendsManager.air.dbId, self.avId, self.__handleAvatarRetrieved) def __handleAvatarRetrieved(self, dclass, fields): + """ + Handle the retrieval of the avatar's data. + + :param dclass: The data class of the avatar. + :param fields: The fields of the avatar. + """ if dclass != self.friendsManager.air.dclassesByName['DistributedToonUD']: self._handleError('Retrieved avatar is not a DistributedToonUD!') return @@ -389,11 +663,20 @@ class GoingOfflineOperation(FriendsOperation): self.__checkFriendsOnline() def __checkFriendsOnline(self): + """ + Check which friends are currently online. + """ self.currentFriendIdx = 0 for friendId, _ in self.friendsList: self.friendsManager.air.getActivated(friendId, self.__gotFriendActivated) def __gotFriendActivated(self, avId, activated): + """ + Handle the response of checking if a friend is activated. + + :param avId: The avatar ID. + :param activated: Whether the friend is activated. + """ self.currentFriendIdx += 1 if activated: self.friendsManager.undeclareObject(avId, self.avId) @@ -403,19 +686,97 @@ class GoingOfflineOperation(FriendsOperation): if self.currentFriendIdx >= len(self.friendsList): self._handleDone() +class GenerateSecretOperation(FriendsOperation): + """ + Operation to generate a secret. + """ + def __init__(self, friendsManager): + """ + Initialize the GenerateSecretOperation. + + :param friendsManager: The friends manager instance. + :param requesterId: The requester's ID. + """ + FriendsOperation.__init__(self, friendsManager, None) + self.secret = None + self.requesterId = None + + def start(self, requesterId): + """ + Start the operation to generate a secret. + Format of secret: + TT 3 random letters/numbers 3 random letters/numbers + """ + self.requesterId = requesterId + # first check if friends list is full + + # check if too many secrets + # TODO + self.secret = '' + for i in range(3): + self.secret += random.choice(string.ascii_letters + string.digits) + self.secret += ' ' + for i in range(3): + self.secret += random.choice(string.ascii_letters + string.digits) + + self.friendsManager.secrets[self.secret] = requesterId + self._handleDone() + + def _handleDone(self): + """ + Handle the completion of the operation. + """ + FriendsOperation._handleDone(self) + # send the response to the requester that it was a success, the result and the secret + self.friendsManager.sendRequestSecretResponse(self.requesterId, 1, self.secret) + + + def _handleError(self, error): + """ + Handle an error during the operation. + + :param error: The error message. + """ + FriendsOperation._handleError(self, error) + # send the response to the requester that it was a failure, the result and the secret + self.friendsManager.sendRequestSecretResponse(self.requesterId, 0, '') + class ToontownFriendsManagerUD(DistributedObjectGlobalUD): + """ + The main friends manager class for Toontown. + """ notify = DirectNotifyGlobal.directNotify.newCategory('ToontownFriendsManagerUD') def __init__(self, air): + """ + Initialize the ToontownFriendsManagerUD. + + :param air: The AI repository instance. + """ DistributedObjectGlobalUD.__init__(self, air) + self.secret = None self.operations = [] - self.secrets = [] + self.secrets = {} def sendMakeFriendsResponse(self, avatarAId, avatarBId, result, context): + """ + Send the response for making friends. + + :param avatarAId: The first avatar's ID. + :param avatarBId: The second avatar's ID. + :param result: The result of the operation. + :param context: The context of the operation. + """ self.sendUpdate('makeFriendsResponse', [avatarAId, avatarBId, result, context]) def declareObject(self, doId, objId): + """ + Declare an object to the client. + + :param doId: The distributed object ID. + :param objId: The object ID. + """ datagram = PyDatagram() datagram.addServerHeader(self.GetPuppetConnectionChannel(doId), self.air.ourChannel, CLIENTAGENT_DECLARE_OBJECT) datagram.addUint32(objId) @@ -423,6 +784,13 @@ class ToontownFriendsManagerUD(DistributedObjectGlobalUD): self.air.send(datagram) def undeclareObject(self, doId, objId, isAccount=False): + """ + Undeclare an object to the client. + + :param doId: The distributed object ID. + :param objId: The object ID. + :param isAccount: Whether the object is an account. + """ datagram = PyDatagram() if isAccount: datagram.addServerHeader(self.GetAccountConnectionChannel(doId), self.air.ourChannel, @@ -435,12 +803,33 @@ class ToontownFriendsManagerUD(DistributedObjectGlobalUD): self.air.send(datagram) def sendFriendOnline(self, avId, friendId, commonChatFlags, whitelistChatFlags): + """ + Notify that a friend has come online. + + :param avId: The avatar ID. + :param friendId: The friend's ID. + :param commonChatFlags: The common chat flags. + :param whitelistChatFlags: The whitelist chat flags. + """ self.sendUpdateToAvatarId(avId, 'friendOnline', [friendId, commonChatFlags, whitelistChatFlags]) def sendFriendOffline(self, avId, friendId): + """ + Notify that a friend has gone offline. + + :param avId: The avatar ID. + :param friendId: The friend's ID. + """ self.sendUpdateToAvatarId(avId, 'friendOffline', [friendId]) def sendUpdateToAvatar(self, avId, fieldName, args=[]): + """ + Send an update to an avatar. + + :param avId: The avatar ID. + :param fieldName: The field name to update. + :param args: The arguments for the update. + """ dclass = self.air.dclassesByName['DistributedToonUD'] if not dclass: return @@ -453,6 +842,12 @@ class ToontownFriendsManagerUD(DistributedObjectGlobalUD): self.air.send(datagram) def runSenderOperation(self, operationType, *args): + """ + Run an operation initiated by the sender. + + :param operationType: The type of operation. + :param args: The arguments for the operation. + """ sender = self.air.getAvatarIdFromSender() if not sender: return @@ -462,27 +857,84 @@ class ToontownFriendsManagerUD(DistributedObjectGlobalUD): newOperation.start(*args) def runServerOperation(self, operationType, *args): + """ + Run an operation initiated by the server. + + :param operationType: The type of operation. + :param args: The arguments for the operation. + """ newOperation = operationType(self) self.operations.append(newOperation) newOperation.start(*args) def getFriendsListRequest(self): + """ + Handle a request to get the friends list. + """ self.runSenderOperation(GetFriendsListOperation) def getAvatarDetailsRequest(self, avId): + """ + Handle a request to get avatar details. + + :param avId: The avatar ID. + """ self.runSenderOperation(GetAvatarDetailsOperation, avId) def makeFriends(self, avatarAId, avatarBId, flags, context): + """ + Handle a request to make two avatars friends. + + :param avatarAId: The first avatar's ID. + :param avatarBId: The second avatar's ID. + :param flags: The friendship flags. + :param context: The context of the operation. + """ self.runServerOperation(MakeFriendsOperation, avatarAId, avatarBId, flags, context) def removeFriend(self, friendId): + """ + Handle a request to remove a friend. + + :param friendId: The friend's ID. + """ self.runSenderOperation(RemoveFriendOperation, friendId) + def requestSecret(self, requesterId): + """ + Handle a request to generate a secret. + + """ + self.runServerOperation(GenerateSecretOperation, requesterId) + def comingOnline(self, avId, friendsList): + """ + Handle a request for an avatar coming online. + + :param avId: The avatar ID. + :param friendsList: The friends list of the avatar. + """ self.runServerOperation(ComingOnlineOperation, avId, friendsList) def goingOffline(self, avId): + """ + Handle a request for an avatar going offline. + + :param avId: The avatar ID. + """ self.runServerOperation(GoingOfflineOperation, avId) - def requestSecret(self, requesterId): - print('requestSecret') + def sendRequestSecretResponse(self, requesterId, success, secret): + """ + Send a response to a secret request. + + :param requesterId: The requester's ID. + :param success: Whether the operation was successful. + :param secret: The generated secret. + """ + self.sendUpdate('requestSecretResponse', [success, secret, requesterId]) + + + + + \ No newline at end of file From 653122c76ebb7e2e98a8fd52e437c679a7b1f92c Mon Sep 17 00:00:00 2001 From: DarthM Date: Tue, 28 Jan 2025 03:16:56 -0500 Subject: [PATCH 47/48] Friends: True friends work for the most part now --- etc/toon.dc | 2 + otp/friends/FriendManagerAI.py | 54 +++++++++++++++++++- toontown/ai/ToontownAIRepository.py | 13 +++++ toontown/friends/ToontownFriendsManagerAI.py | 6 +++ toontown/friends/ToontownFriendsManagerUD.py | 44 ++++++++++++++-- 5 files changed, 114 insertions(+), 5 deletions(-) diff --git a/etc/toon.dc b/etc/toon.dc index ccaebef..b4b29ed 100755 --- a/etc/toon.dc +++ b/etc/toon.dc @@ -2874,7 +2874,9 @@ dclass ToontownFriendsManager : DistributedObject { makeFriendsResponse(uint32, uint32, uint8, uint32) airecv; removeFriend(uint32) clsend; requestSecret(uint32); + submitSecret(uint32, string); requestSecretResponse(uint8, string, uint32) airecv; + submitSecretResponse(uint8, uint32, uint32) airecv; }; dclass TTSpeedchatRelay : SpeedchatRelay { diff --git a/otp/friends/FriendManagerAI.py b/otp/friends/FriendManagerAI.py index 3321330..b3c3bcd 100644 --- a/otp/friends/FriendManagerAI.py +++ b/otp/friends/FriendManagerAI.py @@ -18,6 +18,11 @@ class FriendManagerAI(DistributedObjectGlobalAI): # forget who has declined friendships from whom. DeclineFriendshipTimeout = 600.0 + # This is the length of time, in seconds, to sit on a secret guess + # # before processing it. This serves to make it difficult to guess + # # passwords at random. + SecretDelay = 1.0 + # This subclass is used to record currently outstanding # in-the-game invitation requests. class Invite: @@ -51,10 +56,12 @@ class FriendManagerAI(DistributedObjectGlobalAI): # via the AIR. self.accept("makeFriendsReply", self.makeFriendsReply) self.accept("requestSecretReply", self.requestSecretReply) + self.accept('submitSecretReply', self.submitSecretReply) def delete(self): self.ignore("makeFriendsReply") self.ignore("requestSecretReply") + self.ignore('submitSecretReply') DistributedObjectGlobalAI.delete(self) ### Messages sent from inviter client to AI @@ -223,6 +230,51 @@ class FriendManagerAI(DistributedObjectGlobalAI): self.sendUpdateToAvatarId(recipient, "friendResponse", [yesNoMaybe, context]) self.notify.debug("AI: friendResponse(%d, %d)" % (yesNoMaybe, context)) + def submitSecret(self, secret): + """submitSecret(self, string secret) + + Sent by the client to the AI to submit a "secret" typed in by + the user. + """ + avId = self.air.getAvatarIdFromSender() + + # We have to sit on this request for a few seconds before + # processing it. This delay is solely to discourage password + # guessing. + taskName = "secret-" + str(avId) + taskMgr.remove(taskName) + if FriendManagerAI.SecretDelay: + taskMgr.doMethodLater(FriendManagerAI.SecretDelay, + self.continueSubmission, + taskName, + extraArgs = (avId, secret)) + else: + # No delay + self.continueSubmission(avId, secret) + + def continueSubmission(self, avId, secret): + """continueSubmission(self, avId, secret) + Finishes the work of submitSecret, a short time later. + """ + self.air.submitSecret(avId, secret) + + def submitSecretReply(self, result, recipient, avId): + self.down_submitSecretResponse(recipient, result, avId) + + def down_submitSecretResponse(self, recipient, result, avId): + """submitSecret(self, int8 result, int32 avId) + + Sent by the AI to the client in response to submitSecret(). + result is one of: + + 0 - Failure. The secret is unknown or has timed out. + 1 - Success. You are now friends with the indicated avId. + 2 - Failure. One of the avatars has too many friends already. + 3 - Failure. You just used up your own secret. + + """ + self.sendUpdateToAvatarId(recipient, 'submitSecretResponse', [result, avId]) + ### Support methods def newInvite(self, inviterId, inviteeId): @@ -414,7 +466,7 @@ class FriendManagerAI(DistributedObjectGlobalAI): def requestSecretReply(self, result, secret, requesterId): self.down_requestSecretResponse(requesterId, result, secret) - + def down_requestSecretResponse(self, recipient, result, secret): """requestSecret(self, int8 result, string secret) diff --git a/toontown/ai/ToontownAIRepository.py b/toontown/ai/ToontownAIRepository.py index 2d8bb31..4349269 100644 --- a/toontown/ai/ToontownAIRepository.py +++ b/toontown/ai/ToontownAIRepository.py @@ -547,6 +547,19 @@ class ToontownAIRepository(ToontownInternalRepository): if __astron__: self.toontownFriendsManager.sendRequestSecret(requesterId) + def submitSecret(self, avId, secret): + """ + avId: the avatar id of the friend who requested the secret + secret: the secret that was requested + Submits a secret that was previously requested. + Will submit through the friends manager. + When the secret is submitted, a "submitSecretReply" message will + be thrown with two parameters: the result code (0 or 1, + indicating failure or success), and the requesterId again. + """ + if __astron__: + self.toontownFriendsManager.sendSubmitSecret(avId, secret) + def setupFiles(self): if not os.path.exists(self.dataFolder): os.mkdir(self.dataFolder) diff --git a/toontown/friends/ToontownFriendsManagerAI.py b/toontown/friends/ToontownFriendsManagerAI.py index 7a73003..cca30e2 100644 --- a/toontown/friends/ToontownFriendsManagerAI.py +++ b/toontown/friends/ToontownFriendsManagerAI.py @@ -27,3 +27,9 @@ class ToontownFriendsManagerAI(DistributedObjectGlobalAI): def sendRequestSecret(self, requesterId): self.sendUpdate('requestSecret', [requesterId]) + + def sendSubmitSecret(self, avId, secret): + self.sendUpdate('submitSecret', [avId, secret]) + + def submitSecretResponse(self, result, recipient, requesterId): + messenger.send("submitSecretReply", [result, recipient, requesterId]) \ No newline at end of file diff --git a/toontown/friends/ToontownFriendsManagerUD.py b/toontown/friends/ToontownFriendsManagerUD.py index 42f6402..f572f6e 100644 --- a/toontown/friends/ToontownFriendsManagerUD.py +++ b/toontown/friends/ToontownFriendsManagerUD.py @@ -1,7 +1,7 @@ from direct.directnotify import DirectNotifyGlobal from direct.distributed.DistributedObjectGlobalUD import DistributedObjectGlobalUD from direct.distributed.PyDatagram import * - +from direct.distributed.MsgTypes import * from otp.otpbase import OTPGlobals import random import string @@ -709,8 +709,7 @@ class GenerateSecretOperation(FriendsOperation): TT 3 random letters/numbers 3 random letters/numbers """ self.requesterId = requesterId - # first check if friends list is full - + self.friendsManager.loadSecretsDB() # check if too many secrets # TODO self.secret = '' @@ -728,6 +727,7 @@ class GenerateSecretOperation(FriendsOperation): Handle the completion of the operation. """ FriendsOperation._handleDone(self) + self.friendsManager.updateSecretsDB() # send the response to the requester that it was a success, the result and the secret self.friendsManager.sendRequestSecretResponse(self.requesterId, 1, self.secret) @@ -907,6 +907,32 @@ class ToontownFriendsManagerUD(DistributedObjectGlobalUD): """ self.runServerOperation(GenerateSecretOperation, requesterId) + def submitSecret(self, avId, secret): + """ + Handle a request to submit a secret. + + :param avId: The avatar ID. + :param secret: The secret. + """ + self.loadSecretsDB() + recipient = self.secrets.get(secret, None) + if recipient: + self.runServerOperation(MakeFriendsOperation, avId, recipient, 0, 0) + self.sendSubmitSecretResponse(avId, 1, recipient) + else: + self.sendSubmitSecretResponse(avId, 0, recipient) + + def sendSubmitSecretResponse(self, requesterId, success, recipient): + """ + Send a response to a secret submission. + + :param requesterId: The requester's ID. + :param success: Whether the operation was successful. + :param secret: The secret. + :param recipient: The recipient's ID. + """ + self.sendUpdate('submitSecretResponse', [success, recipient, requesterId]) + def comingOnline(self, avId, friendsList): """ Handle a request for an avatar coming online. @@ -935,6 +961,16 @@ class ToontownFriendsManagerUD(DistributedObjectGlobalUD): self.sendUpdate('requestSecretResponse', [success, secret, requesterId]) + def updateSecretsDB(self): + with open('astron/databases/secrets.json', 'w') as f: + json.dump(self.secrets, f) + self.notify.debug('Updated secrets database') - + def loadSecretsDB(self): + try: + with open('astron/databases/secrets.json', 'r') as f: + self.secrets = json.load(f) + self.notify.debug('Loaded secrets database') + except: + self.notify.warning('Failed to load secrets database') \ No newline at end of file From 326d85bceac7235773b62a72c9af7614f3d0c5a9 Mon Sep 17 00:00:00 2001 From: DarthM Date: Tue, 28 Jan 2025 04:49:20 -0500 Subject: [PATCH 48/48] ToontownFriendsManagerUD: Fix missing import issue --- toontown/friends/ToontownFriendsManagerUD.py | 1 + 1 file changed, 1 insertion(+) diff --git a/toontown/friends/ToontownFriendsManagerUD.py b/toontown/friends/ToontownFriendsManagerUD.py index f572f6e..33a4d33 100644 --- a/toontown/friends/ToontownFriendsManagerUD.py +++ b/toontown/friends/ToontownFriendsManagerUD.py @@ -6,6 +6,7 @@ from otp.otpbase import OTPGlobals import random import string import json +from panda3d.direct import DCPacker class FriendsOperation: """ Base class for all friend-related operations.