diff --git a/.gitignore b/.gitignore index 913fa7fd..e7a97233 100755 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,8 @@ # Local config dependencies/config/local.prc + +# PyMongo +bson +gridfs +pymongo \ No newline at end of file diff --git a/dependencies/astron/astrond b/dependencies/astron/astrond old mode 100644 new mode 100755 index 3ea7dc90..a1bf9fab Binary files a/dependencies/astron/astrond and b/dependencies/astron/astrond differ diff --git a/dependencies/astron/astrond.exe b/dependencies/astron/astrond.exe old mode 100644 new mode 100755 diff --git a/dependencies/astron/dclass/stride.dc b/dependencies/astron/dclass/stride.dc index e30e0294..1702b997 100644 --- a/dependencies/astron/dclass/stride.dc +++ b/dependencies/astron/dclass/stride.dc @@ -27,11 +27,11 @@ dclass Account { uint32 ACCOUNT_AV_SET[] required db; uint32 ESTATE_ID db; AvatarPendingDel ACCOUNT_AV_SET_DEL[] db; - uint64 CREATED db; + string CREATED db; string LAST_LOGIN db; string ACCOUNT_ID db; uint16 ACCESS_LEVEL db; - uint64 LAST_LOGIN_TS db; + uint32 LAST_LOGIN_TS db; }; struct BarrierData { @@ -175,12 +175,14 @@ dclass FriendManager : DistributedObject { friendResponse(int8, int32); inviteeFriendQuery(int32, string, blob, int32); inviteeCancelFriendQuery(int32); + requestTFCode() airecv clsend; + redeemTFCode(string) airecv clsend; + tfResponse(uint8, string); }; from toontown.building import DistributedAnimatedProp/AI from toontown.toon import DistributedToon/AI/UD from toontown.safezone import DistributedTrolley/AI -from toontown.safezone import DistributedPillow/AI from toontown.safezone import DistributedPartyGate/AI from toontown.suit import DistributedSuitPlanner/AI from toontown.suit import DistributedSuitBase/AI @@ -228,7 +230,6 @@ from toontown.estate import DistributedHouse/AI from toontown.estate import DistributedHouseInterior/AI from toontown.estate import DistributedGarden/AI from toontown.shtiker import DeleteManager/AI -from toontown.groups import GroupManager/AI/UD from toontown.ai import NewsManager/AI from toontown.shtiker import PurchaseManager/AI from toontown.shtiker import NewbiePurchaseManager/AI @@ -250,11 +251,10 @@ from toontown.building import DistributedKartShopInterior/AI from toontown.building import DistributedDoor/AI from toontown.estate import DistributedHouseDoor/AI from toontown.coghq import DistributedCogHQDoor/AI -from toontown.coghq import DistributedCogHQExteriorDoor/AI +//from toontown.coghq import DistributedCogHQExteriorDoor/AI from toontown.coghq import DistributedSellbotHQDoor/AI from toontown.toon import DistributedNPCToonBase/AI from toontown.toon import DistributedNPCToon/AI -from toontown.toon import DistributedSmartNPC/AI from toontown.toon import DistributedNPCSpecialQuestGiver/AI from toontown.toon import DistributedNPCFlippyInToonHall/AI from toontown.toon import DistributedNPCScientist/AI @@ -291,6 +291,9 @@ from toontown.estate import DistributedBank/AI from toontown.estate import DistributedCloset/AI from toontown.estate import DistributedTrunk/AI from toontown.estate import DistributedPhone/AI +from toontown.estate import DistributedRewardCrate/AI +from toontown.estate import DistributedChair/AI +from toontown.estate import DistributedTV/AI from toontown.effects import DistributedFireworkShow/AI from toontown.estate import DistributedFireworksCannon/AI from toontown.coghq import LobbyManager/AI @@ -425,7 +428,7 @@ from toontown.safezone import DistributedChineseCheckers/AI from toontown.safezone import DistributedCheckers/AI from toontown.safezone import DistributedFindFour/AI from toontown.uberdog.DistributedPartyManager/AI/UD import DistributedPartyManager/AI/UD -from toontown.uberdog.DistributedLobbyManager/AI/UD import DistributedLobbyManager/AI/UD +//from toontown.uberdog.DistributedLobbyManager/AI/UD import DistributedLobbyManager/AI/UD from toontown.coderedemption.TTCodeRedemptionMgr/AI import TTCodeRedemptionMgr/AI from toontown.cogdominium import DistributedCogdoInterior/AI from toontown.cogdominium import DistributedCogdoBattleBldg/AI @@ -442,14 +445,9 @@ from toontown.cogdominium import DistCogdoCrane/AI from toontown.cogdominium import DistCogdoCraneMoneyBag/AI from toontown.cogdominium import DistCogdoCraneCog/AI from toontown.parties.GlobalPartyManager/AI/UD import GlobalPartyManager/AI/UD -from toontown.uberdog.GlobalLobbyManager/AI/UD import GlobalLobbyManager/AI/UD +//from toontown.uberdog.GlobalLobbyManager/AI/UD import GlobalLobbyManager/AI/UD from toontown.uberdog.ARGManager import ARGManager -struct GiftItem { - blob Item; - string giftTag; -}; - struct gardenSpecial { uint8 index; uint8 count; @@ -484,10 +482,10 @@ struct activity { uint8 h; }; -struct lobby { - uint64 lobbyId; - uint32 hostId; -}; +//struct lobby { +// uint64 lobbyId; +// uint32 hostId; +//}; struct party { uint64 partyId; @@ -557,6 +555,7 @@ dclass ToontownDistrictStats : DistributedObject { setDistrictId(uint32) broadcast required ram; setAvatarCount(uint32) broadcast required ram; setInvasionStatus(uint8) broadcast required ram; + setGroupAvCount(uint32[]) broadcast required ram; }; dclass DistributedAnimatedProp : DistributedObject { @@ -599,7 +598,6 @@ dclass DistributedToon : DistributedPlayer { setMaxClothes(uint32 = 10) required ownrecv db; setClothesTopsList(uint8[] = []) required ownrecv db; setClothesBottomsList(uint8[] = []) required ownrecv db; - setMaxAccessories(uint32 = 0) required ownrecv db; setHatList(uint8[] = []) required ownrecv db; setGlassesList(uint8[] = []) required ownrecv db; setBackpackList(uint8[] = []) required ownrecv db; @@ -668,6 +666,7 @@ dclass DistributedToon : DistributedPlayer { setMaxFishTank(uint8 = 20) required ownrecv db; setFishTank(uint8[] = [], uint8[] = [], uint16[] = []) required ownrecv db; setFishingRod(uint8 = 0) required broadcast ownrecv db; + setMaxFishingRod(uint8 = 0) required broadcast ownrecv db; setFishingTrophies(uint8[] = []) required ownrecv db; setFlowerCollection(uint8[] = [], uint8[] = []) required ownrecv db; setFlowerBasket(uint8[] = [], uint8[] = []) required ownrecv db; @@ -726,8 +725,9 @@ dclass DistributedToon : DistributedPlayer { setUnlimitedSwing(uint8) broadcast ownrecv ram; logSuspiciousEvent(char [0-1024]) ownsend airecv; forceLogoutWithNotify() ownrecv; - setPinkSlips(uint8 = 0) required ownrecv db; + setSpecialInventory(uint8[] = [0, 0]) required ownrecv db; setNametagStyle(uint8 = 0) required broadcast ownrecv db; + setNametagStyles(uint8[] = [0]) required broadcast ownrecv db; setMail(simpleMail []) ownrecv; setNumMailItems(uint32) airecv; setSimpleMailNotify(uint8) ownrecv airecv; @@ -745,8 +745,14 @@ dclass DistributedToon : DistributedPlayer { setBuffs(uint32[] = []) required ownrecv db; setRedeemedCodes(string [] = []) required ownrecv db; setEmblems(uint32[] = [0, 0]) required ownrecv db; - setTrueFriends(uint32[] = []) required clsend ownrecv db; + setTrueFriends(uint32[] = []) required ownrecv db; setNextKnockHeal(uint32) ram airecv; + setTFRequest(uint32[] = [0, 0]) ram airecv; + setEPP(uint8[] = []) required ownrecv db; + setStats(uint32[] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) required ownrecv db; + requestNametagStyle(uint8) airecv ownsend; + requestFishingRod(uint8) airecv ownsend; + wipeStats() airecv ownsend; }; dclass DistributedPartyGate : DistributedObject { @@ -773,9 +779,6 @@ dclass DistributedTrolley : DistributedObject { setMinigameZone(uint32, uint16); }; -dclass DistributedPillow : DistributedObject { -}; - dclass DistributedSuitPlanner : DistributedObject { setZoneId(uint32) required broadcast ram; suitListQuery() airecv clsend; @@ -830,6 +833,7 @@ dclass DistributedBossCog : DistributedNode { setToonIds(uint32[], uint32[], uint32[]) broadcast ram; setBattleIds(uint8, uint32, uint32) broadcast ram; setArenaSide(uint8) broadcast ram; + setKeyReward(bool) required broadcast ram; avatarEnter() airecv clsend; avatarExit() airecv clsend; avatarNearEnter() airecv clsend; @@ -979,6 +983,7 @@ dclass DistributedBattleTutorial : DistributedBattle { }; dclass DistributedLevelBattle : DistributedBattle { + announceCrateReward() broadcast; }; dclass DistributedBattleFactory : DistributedLevelBattle { @@ -1216,45 +1221,41 @@ struct decorItem { }; struct lawnItem { - int8 plot; uint8 type; - uint8 species; - uint8 variety; + uint8 hardPoint; int8 waterLevel; int8 growthLevel; uint16 optional; - uint64 plantedAt; - uint64 wateredAt; }; dclass DistributedEstate : DistributedObject { setEstateReady() broadcast; setClientReady() airecv clsend; + setEstateType(uint8 type = 0) required broadcast db; setClosestHouse(uint8) airecv clsend; setTreasureIds(uint32[]) broadcast ram; requestServerTime() airecv clsend; setServerTime(uint32); setDawnTime(uint32) required broadcast ram; placeOnGround(uint32) broadcast ram; - setDecorData(lawnItem items[] = []) required airecv db; setLastEpochTimeStamp(uint32 timestamp = 0) required airecv db; setRentalTimeStamp(uint32 timestamp = 0) required airecv db; setRentalType(uint8 type = 0) required airecv db; setSlot0ToonId(uint32 toonId = 0) required airecv db; - setSlot0Items(lawnItem items[] = []) required broadcast ownrecv db; + setSlot0Garden(blob g) required airecv db; setSlot1ToonId(uint32 toonId = 0) required airecv db; - setSlot1Items(lawnItem items[] = []) required broadcast ownrecv db; + setSlot1Garden(blob g) required airecv db; setSlot2ToonId(uint32 toonId = 0) required airecv db; - setSlot2Items(lawnItem items[] = []) required broadcast ownrecv db; + setSlot2Garden(blob g) required airecv db; setSlot3ToonId(uint32 toonId = 0) required airecv db; - setSlot3Items(lawnItem items[] = []) required broadcast ownrecv db; + setSlot3Garden(blob g) required airecv db; setSlot4ToonId(uint32 toonId = 0) required airecv db; - setSlot4Items(lawnItem items[] = []) required broadcast ownrecv db; + setSlot4Garden(blob g) required airecv db; setSlot5ToonId(uint32 toonId = 0) required airecv db; - setSlot5Items(lawnItem items[] = []) required broadcast ownrecv db; + setSlot5Garden(blob g) required airecv db; setIdList(uint32 []) broadcast ram; completeFlowerSale(uint8) airecv clsend; - completeFishSale(uint8) airecv clsend; + completeFishSale() airecv clsend; thankSeller(int8, int8, int8); awardedTrophy(uint32) broadcast; setClouds(uint8) required broadcast ram; @@ -1269,6 +1270,7 @@ dclass DistributedHouse : DistributedObject { setAvatarId(uint32 toonId = 0) required broadcast db; setName(string toonName = "") required broadcast db; setColor(uint8 colorIndex = 0) required broadcast db; + setGender(uint8 = 0) required broadcast db; setAtticItems(blob = "") required db; setInteriorItems(blob = "") required db; setAtticWallpaper(blob = "") required db; @@ -1289,8 +1291,7 @@ dclass DistributedHouseInterior : DistributedObject { }; dclass DistributedGarden : DistributedObject { - sendNewProp(uint8, int16/10, int16/10, int16/10) broadcast; - setProps(uint8[]) airecv clsend; + sendNewProp(uint8 prop, int16/10 x, int16/10 y, int16/10 z) broadcast; }; dclass DistributedParty : DistributedObject { @@ -1470,23 +1471,6 @@ dclass DeleteManager : DistributedObject { setInventory(blob) airecv clsend; }; -dclass GroupManager : DistributedObject { - setChildId() clsend airecv; - isPlayerGrouped(uint32); - isInGroup(uint32, uint32); - updateInfo() clsend airecv; - requestInfo() broadcast ram; - getTypeFromId(uint32); - setGroups(string) broadcast ram; - getGroups(); - setGroupPlayers(string) broadcast ram; - getGroupPlayers(uint32); - createGroup(uint32, string) clsend airecv; - closeGroup(uint32) clsend airecv; - addPlayerToGroup(uint32, uint32) clsend airecv; - removePlayerFromGroup(uint32, uint32) clsend airecv; -}; - dclass NewsManager : DistributedObject { startHoliday(uint8) broadcast; endHoliday(uint8) broadcast; @@ -1730,10 +1714,10 @@ dclass DistributedHouseDoor : DistributedDoor { dclass DistributedCogHQDoor : DistributedDoor { }; -dclass DistributedCogHQExteriorDoor : DistributedCogHQDoor { - selectLobby(uint32) broadcast; - confirmEntrance(uint32, bool) airecv clsend; -}; +//dclass DistributedCogHQExteriorDoor : DistributedCogHQDoor { +// selectLobby(uint32) broadcast; +// confirmEntrance(uint32, bool) airecv clsend; +//}; dclass DistributedSellbotHQDoor : DistributedCogHQDoor { informPlayer(uint8) broadcast ram; @@ -1760,13 +1744,6 @@ dclass DistributedNPCToon : DistributedNPCToonBase { chooseTrack(int8) airecv clsend; }; -dclass DistributedSmartNPC : DistributedNPCToonBase { - greet(uint32, uint32) broadcast ram; - talkMessage(uint32, string) airecv clsend; - respond(uint32, string, uint32) broadcast ram; - dismiss(uint32, uint16) broadcast ram; -}; - dclass DistributedNPCSpecialQuestGiver : DistributedNPCToonBase { setMovie(uint8, uint32, uint32, uint16[], int16) broadcast ram; setMovieDone() airecv clsend; @@ -1781,8 +1758,8 @@ dclass DistributedNPCScientist : DistributedNPCToonBase { }; dclass DistributedNPCClerk : DistributedNPCToonBase { - setMovie(uint8, uint32, uint32, int16) broadcast ram; - setInventory(blob, int16, uint8) airecv clsend; + setState(uint32, uint8) broadcast airecv clsend; + setInventory(blob, int16) airecv clsend; }; dclass DistributedNPCTailor : DistributedNPCToonBase { @@ -1822,9 +1799,8 @@ dclass DistributedNPCKartClerk : DistributedNPCToonBase { }; dclass DistributedNPCLaffRestock : DistributedNPCToonBase { - setMovie(uint8, uint32, uint32, uint32[], int16) broadcast ram; - restock(uint32, uint16, uint16) airecv clsend; - transactionDone() airecv clsend; + restock(uint8) airecv clsend; + restockResult(uint8) broadcast; }; dclass DistributedNPCGlove : DistributedNPCToonBase { @@ -1860,7 +1836,6 @@ dclass DistributedElevator : DistributedObject { requestExit() airecv clsend; setElevatorTripId(uint32) required broadcast ram; setAntiShuffle(uint8) required broadcast ram; - setMinLaff(uint8) required broadcast ram; }; dclass DistributedElevatorFSM : DistributedObject { @@ -1887,7 +1862,6 @@ dclass DistributedElevatorFSM : DistributedObject { requestExit() airecv clsend; setElevatorTripId(uint32) required broadcast ram; setAntiShuffle(uint8) required broadcast ram; - setMinLaff(uint8) required broadcast ram; }; dclass DistributedElevatorFloor : DistributedElevatorFSM { @@ -1963,7 +1937,7 @@ dclass DistributedBoardingParty : DistributedObject { postSizeReject(uint32, uint32, uint32) broadcast; postInviteAccepted(uint32) broadcast; postInviteDelcined(uint32) broadcast; - postInviteNotQualify(uint32, int8, uint32) broadcast; + postInviteNotQualify(uint32, int8) broadcast; postAlreadyInGroup() broadcast; postGroupDissolve(uint32, uint32, uint32 [], uint8) broadcast; postMessageAcceptanceFailed(uint32, int8) broadcast; @@ -2093,6 +2067,25 @@ dclass DistributedPhone : DistributedFurnitureItem { requestGiftPurchaseMessage(uint16, uint32, blob, int32) airecv clsend; requestGiftPurchaseResponse(uint16, int8); purchaseItemComplete(); + requestGiftAvatar(uint32) airecv clsend; + setGiftAvatar(blob); +}; + +dclass DistributedRewardCrate : DistributedFurnitureItem { + requestKeyUsage() airecv clsend; + useKeyResponse(uint8, uint32); +}; + +dclass DistributedChair : DistributedFurnitureItem { + setAvId(uint32) broadcast ram; + requestSit(uint8) airecv clsend; + setStatus(uint8) broadcast ram; +}; + +dclass DistributedTV : DistributedFurnitureItem { + setVideo(string(0-255), uint32) required broadcast ram; + requestVideo(string(0-255)) airecv clsend; + requestVideoResponse(uint8); }; dclass DistributedFireworkShow : DistributedObject { @@ -2560,27 +2553,24 @@ dclass DistributedLawbotChair : DistributedObject { }; dclass DistributedLawnDecor : DistributedNode { - setEstate(uint32) required broadcast ram; setPlot(int8) required broadcast ram; setHeading(int16/10) required broadcast ram; - setPosition(int16/10, int16/10, int16/10) required broadcast ram; setOwnerIndex(int8) required broadcast ram; + setPosition(int16/10, int16/10, int16/10) required broadcast ram; plotEntered() airecv clsend; - removeItem(uint32) airecv clsend; + removeItem() airecv clsend; setMovie(uint8, uint32) broadcast ram; movieDone() airecv clsend; interactionDenied(uint32) broadcast ram; + setBoxDoId(uint32, uint8) broadcast ram; }; dclass DistributedGardenPlot : DistributedLawnDecor { - plantedItem(uint32) broadcast ram; - finishPlanting(uint32) airecv clsend; - finishRemoving(uint32) airecv clsend; - plantFlower(uint8, uint8, uint32) airecv clsend; - plantGagTree(uint8, uint8, uint32) airecv clsend; - plantStatuary(uint8, uint32) airecv clsend; - plantToonStatuary(uint8, uint16, uint32) airecv clsend; - plantNothing(uint8, uint32) airecv clsend; + plantFlower(uint8, uint8) airecv clsend; + plantGagTree(uint8, uint8) airecv clsend; + plantStatuary(uint8) airecv clsend; + plantToonStatuary(uint8, uint16) airecv clsend; + plantNothing(uint8) airecv clsend; }; dclass DistributedGardenBox : DistributedLawnDecor { @@ -2588,7 +2578,6 @@ dclass DistributedGardenBox : DistributedLawnDecor { }; dclass DistributedStatuary : DistributedLawnDecor { - setOwnerPlot(uint32) required broadcast ram; setTypeIndex(uint8) required broadcast ram; setWaterLevel(int8) required broadcast ram; setGrowthLevel(int8) required broadcast ram; @@ -2606,11 +2595,10 @@ dclass DistributedChangingStatuary : DistributedStatuary { }; dclass DistributedPlantBase : DistributedLawnDecor { - setOwnerPlot(uint32) required broadcast ram; setTypeIndex(uint8) required broadcast ram; setWaterLevel(int8) required broadcast ram; setGrowthLevel(int8) required broadcast ram; - waterPlant(uint32) airecv clsend; + waterPlant() airecv clsend; waterPlantDone() airecv clsend; }; @@ -2621,7 +2609,8 @@ dclass DistributedFlower : DistributedPlantBase { dclass DistributedGagTree : DistributedPlantBase { setWilted(int8) required broadcast ram; - requestHarvest(uint32) airecv clsend; + setFruiting(bool) required broadcast ram; + requestHarvest() airecv clsend; }; struct golfData { @@ -3044,34 +3033,34 @@ dclass DistributedFindFour : DistributedNode { tie() broadcast; }; -dclass DistributedLobbyManager : DistributedObject { - addLobby(uint32, uint32, string, string, int8, int8, activity [], decoration [], uint32[], uint16); - addLobbyRequest(uint32) airecv clsend; - addLobbyResponse(uint32, int8); - addLobbyResponseUdToAi(uint64, int8, lobby) airecv; +//dclass DistributedLobbyManager : DistributedObject { +// addLobby(uint32, uint32, string, string, int8, int8, activity [], decoration [], uint32[], uint16); +// addLobbyRequest(uint32) airecv clsend; +// addLobbyResponse(uint32, int8); +// addLobbyResponseUdToAi(uint64, int8, lobby) airecv; - getLobbyZone(uint32, uint32, uint8) clsend airecv; - receiveLobbyZone(uint32, uint64, uint32); - freeZoneIdFromCreatedLobby(uint32, uint32) clsend airecv; +// getLobbyZone(uint32, uint32, uint8) clsend airecv; +// receiveLobbyZone(uint32, uint64, uint32); +// freeZoneIdFromCreatedLobby(uint32, uint32) clsend airecv; - sendAvToPlayground(uint32, uint8); - exitParty(uint32) clsend airecv; +// sendAvToPlayground(uint32, uint8); +// exitParty(uint32) clsend airecv; - toonHasEnteredPartyAiToUd(uint32); - toonHasExitedPartyAiToUd(uint32); +// toonHasEnteredPartyAiToUd(uint32); +// toonHasExitedPartyAiToUd(uint32); - lobbyManagerAIStartingUp(uint32, uint32); - lobbyManagerAIGoingDown(uint32, uint32); - lobbyHasFinishedUdToAllAi(uint64 lobbyId) airecv; +// lobbyManagerAIStartingUp(uint32, uint32); +// lobbyManagerAIGoingDown(uint32, uint32); +// lobbyHasFinishedUdToAllAi(uint64 lobbyId) airecv; - requestShardIdZoneIdForHostId(uint32) clsend airecv; - sendShardIdZoneIdToAvatar(uint32, uint32); +// requestShardIdZoneIdForHostId(uint32) clsend airecv; +// sendShardIdZoneIdToAvatar(uint32, uint32); - lobbyManagerUdStartingUp() airecv; - lobbyManagerUdLost() airecv; +// lobbyManagerUdStartingUp() airecv; +// lobbyManagerUdLost() airecv; - receiveId(uint64 ids[]) airecv; -}; +// receiveId(uint64 ids[]) airecv; +//}; dclass DistributedPartyManager : DistributedObject { addParty(uint32, uint32, string, string, int8, int8, activity [], decoration [], uint32[], uint16); @@ -3124,16 +3113,16 @@ dclass DistributedPartyManager : DistributedObject { receiveId(uint64 ids[]) airecv; }; -dclass GlobalLobbyManager : DistributedObjectGlobal { - lobbyManagerAIHello(uint32 channel); - queryLobby(uint32 hostId); - addLobby(DoId avId, uint64 lobbyId); - toonJoinedLobby(uint64 lobbyId, uint32 avId); - toonLeftLobby(uint64 lobbyId, uint32 avId); - requestLobbySlot(uint64 lobbyId, uint32 avId); - lobbyDone(uint64 lobbyId); - allocIds(uint16 count); -}; +//dclass GlobalLobbyManager : DistributedObjectGlobal { +// lobbyManagerAIHello(uint32 channel); +// queryLobby(uint32 hostId); +// addLobby(DoId avId, uint64 lobbyId); +// toonJoinedLobby(uint64 lobbyId, uint32 avId); +// toonLeftLobby(uint64 lobbyId, uint32 avId); +// requestLobbySlot(uint64 lobbyId, uint32 avId); +// lobbyDone(uint64 lobbyId); +// allocIds(uint16 count); +//}; dclass GlobalPartyManager : DistributedObjectGlobal { partyManagerAIHello(uint32 channel); @@ -3188,11 +3177,11 @@ dclass TTCodeRedemptionMgr : DistributedObject { struct Friend { -uint32 doId; -string name; -blob dna; -uint16 adminAccess; -uint32 petId; + uint32 doId; + string name; + blob dna; + uint16 adminAccess; + uint32 petId; }; dclass TTSFriendsManager : DistributedObjectGlobal { diff --git a/dependencies/astron/libeay32.dll b/dependencies/astron/libeay32.dll old mode 100644 new mode 100755 diff --git a/dependencies/astron/msvcp120.dll b/dependencies/astron/msvcp120.dll old mode 100644 new mode 100755 diff --git a/dependencies/astron/msvcr120.dll b/dependencies/astron/msvcr120.dll old mode 100644 new mode 100755 diff --git a/dependencies/astron/prod/start-ai-server.sh b/dependencies/astron/prod/start-ai-server.sh old mode 100644 new mode 100755 diff --git a/dependencies/astron/prod/start-astron-cluster.sh b/dependencies/astron/prod/start-astron-cluster.sh old mode 100644 new mode 100755 diff --git a/dependencies/astron/prod/start-uberdog-server.sh b/dependencies/astron/prod/start-uberdog-server.sh old mode 100644 new mode 100755 diff --git a/dependencies/astron/ssleay32.dll b/dependencies/astron/ssleay32.dll old mode 100644 new mode 100755 diff --git a/dependencies/config/general.prc b/dependencies/config/general.prc index 07a99380..493aacbe 100644 --- a/dependencies/config/general.prc +++ b/dependencies/config/general.prc @@ -99,7 +99,6 @@ want-cogbuildings #t # Optional: show-total-population #t want-mat-all-tailors #t -want-talkative-tyler #f estate-day-night #t want-garden-game #f want-language-selection #t diff --git a/dependencies/config/release/dev.prc b/dependencies/config/release/dev.prc index 03c7bf6e..a3d97d2a 100644 --- a/dependencies/config/release/dev.prc +++ b/dependencies/config/release/dev.prc @@ -20,7 +20,7 @@ dc-file dependencies/astron/dclass/stride.dc # Core features: want-pets #t -want-parties #t +want-parties #f want-cogdominiums #t want-lawbot-cogdo #t want-anim-props #t @@ -29,6 +29,8 @@ want-find-four #t want-chinese-checkers #t want-checkers #t want-house-types #t +want-gifting #t +want-top-toons #f # Chat: want-whitelist #t @@ -36,6 +38,12 @@ want-whitelist #t # Developer options: show-population #t want-instant-parties #t +want-instant-delivery #t cogdo-pop-factor 1.5 cogdo-ratio 0.5 -default-directnotify-level info \ No newline at end of file +default-directnotify-level info + +# Crates: +dont-destroy-crate #t +get-key-reward-always #t +get-crate-reward-always #t \ No newline at end of file diff --git a/dependencies/libpandadna.pyd b/dependencies/libpandadna.pyd old mode 100644 new mode 100755 diff --git a/dependencies/libpandadna.so b/dependencies/libpandadna.so old mode 100644 new mode 100755 diff --git a/dev/win32/start-ai-server.bat b/dev/win32/start-ai-server.bat old mode 100644 new mode 100755 diff --git a/dev/win32/start-astron-cluster.bat b/dev/win32/start-astron-cluster.bat old mode 100644 new mode 100755 diff --git a/dev/win32/start-game.bat b/dev/win32/start-game.bat old mode 100644 new mode 100755 diff --git a/dev/win32/start-uberdog-server.bat b/dev/win32/start-uberdog-server.bat old mode 100644 new mode 100755 diff --git a/otp/avatar/Avatar.py b/otp/avatar/Avatar.py index d0129bc1..2b708a8c 100755 --- a/otp/avatar/Avatar.py +++ b/otp/avatar/Avatar.py @@ -17,7 +17,6 @@ from otp.nametag.Nametag import Nametag from otp.nametag.NametagGroup import NametagGroup from otp.nametag.NametagConstants import * - teleportNotify = DirectNotifyGlobal.directNotify.newCategory('Teleport') teleportNotify.showTime = True if config.GetBool('want-teleport-debug', 1): @@ -27,24 +26,15 @@ def reconsiderAllUnderstandable(): for av in Avatar.ActiveAvatars: av.considerUnderstandable() - class Avatar(Actor, ShadowCaster): notify = directNotify.newCategory('Avatar') ActiveAvatars = [] - ManagesNametagAmbientLightChanged = False def __init__(self, other = None): - self.name = '' - try: - self.Avatar_initialized - return - except: - self.Avatar_initialized = 1 - Actor.__init__(self, None, None, other, flattenable=0, setFinal=1) ShadowCaster.__init__(self) self.__font = OTPGlobals.getInterfaceFont() - self.__speechFont = OTPGlobals.getInterfaceFont() + self.name = '' self.soundChatBubble = None self.avatarType = '' self.nametagNodePath = None @@ -59,18 +49,11 @@ class Avatar(Actor, ShadowCaster): self.nametag3d = self.attachNewNode('nametag3d') self.nametag3d.setTag('cam', 'nametag') self.nametag3d.setLightOff() - if self.ManagesNametagAmbientLightChanged: - self.acceptNametagAmbientLightChange() - OTPRender.renderReflection(False, self.nametag3d, 'otp_avatar_nametag', None) self.getGeomNode().showThrough(OTPRender.ShadowCameraBitmask) self.nametag3d.hide(OTPRender.ShadowCameraBitmask) self.collTube = None - self.battleTube = None self.scale = 1.0 - self.nametagScale = 1.0 self.height = 0.0 - self.battleTubeHeight = 0.0 - self.battleTubeRadius = 0.0 self.style = None self.understandable = 1 self.setPlayerType(NametagGroup.CCNormal) @@ -91,11 +74,8 @@ class Avatar(Actor, ShadowCaster): except: self.deleteNametag3d() Actor.cleanup(self) - if self.ManagesNametagAmbientLightChanged: - self.ignoreNametagAmbientLightChange() self.Avatar_deleted = 1 del self.__font - del self.__speechFont del self.style del self.soundChatBubble self.nametag.destroy() @@ -104,12 +84,6 @@ class Avatar(Actor, ShadowCaster): ShadowCaster.delete(self) Actor.delete(self) - def acceptNametagAmbientLightChange(self): - self.accept('nametagAmbientLightChanged', self.nametagAmbientLightChanged) - - def ignoreNametagAmbientLightChange(self): - self.ignore('nametagAmbientLightChanged') - def isLocal(self): return 0 @@ -127,7 +101,7 @@ class Avatar(Actor, ShadowCaster): if self.isUnderstandable(): self.nametag.setColorCode(self.playerType) else: - self.nametag.setColorCode(NametagGroup.CCNoChat) + self.nametag.setColorCode(NametagGroup.CCNonPlayer) self.setNametagName() def considerUnderstandable(self): @@ -136,9 +110,6 @@ class Avatar(Actor, ShadowCaster): if hasattr(base, 'localAvatar') and (self == base.localAvatar): self.understandable = 1 self.setPlayerType(NametagGroup.CCNormal) - elif hasattr(self, 'adminAccess') and self.isAdmin(): - self.understandable = 2 - self.setPlayerType(NametagGroup.CCAdmin) elif self.playerType == NametagGroup.CCSuit: self.understandable = 1 self.setPlayerType(NametagGroup.CCSuit) @@ -154,6 +125,8 @@ class Avatar(Actor, ShadowCaster): else: self.understandable = 0 self.setPlayerType(NametagGroup.CCSpeedChat) + if hasattr(self, 'adminAccess') and self.isAdmin(): + self.understandable = 2 if not hasattr(self, 'nametag'): self.notify.warning('no nametag attributed, but would have been used') else: @@ -177,13 +150,6 @@ class Avatar(Actor, ShadowCaster): self.getGeomNode().setScale(scale) self.setHeight(self.height) - def getNametagScale(self): - return self.nametagScale - - def setNametagScale(self, scale): - self.nametagScale = scale - self.nametag3d.setScale(scale) - def adjustNametag3d(self, parentScale = 1.0): self.nametag3d.setPos(0, 0, self.height + 0.5) @@ -197,8 +163,6 @@ class Avatar(Actor, ShadowCaster): self.collTube.setPointB(0, 0, height - self.getRadius()) if self.collNodePath: self.collNodePath.forceRecomputeBounds() - if self.battleTube: - self.battleTube.setPointB(0, 0, height - self.getRadius()) def getRadius(self): return OTPGlobals.AvatarDefaultRadius @@ -245,13 +209,6 @@ class Avatar(Actor, ShadowCaster): self.__font = font self.nametag.setFont(font) - def getSpeechFont(self): - return self.__speechFont - - def setSpeechFont(self, font): - self.__speechFont = font - self.nametag.setSpeechFont(font) - def getStyle(self): return self.style @@ -349,9 +306,6 @@ class Avatar(Actor, ShadowCaster): self.nametag.setChat(chatString, chatFlags) self.playCurrentDialogue(dialogue, chatFlags, interrupt) - def setChatMuted(self, chatString, chatFlags, dialogue = None, interrupt = 1, quiet = 0): - pass - def displayTalk(self, chatString): if not base.localAvatar.isIgnored(self.doId): self.clearChat() @@ -364,11 +318,6 @@ class Avatar(Actor, ShadowCaster): def clearChat(self): self.nametag.clearChat() - def isInView(self): - pos = self.getPos(camera) - eyePos = Point3(pos[0], pos[1], pos[2] + self.getHeight()) - return base.camNode.isInView(eyePos) - def getNameVisible(self): return self.__nameVisible @@ -539,11 +488,6 @@ class Avatar(Actor, ShadowCaster): cJoint.clearNetTransforms() cJoint.addNetTransform(nametagNode) - def nametagAmbientLightChanged(self, newlight): - self.nametag3d.setLightOff() - if newlight: - self.nametag3d.setLight(newlight) - def deleteNametag3d(self): if self.nametagNodePath: self.nametagNodePath.removeNode() @@ -615,10 +559,5 @@ def target(): Returns the current Spellbook target. """ target = spellbook.getTarget() - print 'Called target.' - print 'Name: ' + target.getName() - doId = str(int(target.doId)) - print 'doId: ', doId - accessLevel = str(int(target.getAdminAccess())) - print 'Access Level: ', accessLevel - return 'Target: %s-%d [%d]' % (target.getName(), int(target.doId), int(target.getAdminAccess())) + + return 'Target: %s-%d [%d]' % (target.getName(), int(target.doId), int(target.getAdminAccess())) \ No newline at end of file diff --git a/otp/avatar/LocalAvatar.py b/otp/avatar/LocalAvatar.py index 21bdf275..6b4d393d 100755 --- a/otp/avatar/LocalAvatar.py +++ b/otp/avatar/LocalAvatar.py @@ -62,6 +62,7 @@ class LocalAvatar(DistributedAvatar.DistributedAvatar, DistributedSmoothNode.Dis self.sleepFlag = 0 self.isDisguised = 0 self.movingFlag = 0 + self.preventCameraDisable = False self.lastNeedH = None self.accept('friendOnline', self.__friendOnline) self.accept('friendOffline', self.__friendOffline) @@ -73,6 +74,9 @@ class LocalAvatar(DistributedAvatar.DistributedAvatar, DistributedSmoothNode.Dis self.accept('avatarMoving', self.clearPageUpDown) self.showNametag2d() self.setPickable(0) + + def setPreventCameraDisable(self, prevent): + self.preventCameraDisable = prevent def useSwimControls(self): self.controlManager.use('swim', self) @@ -421,7 +425,7 @@ class LocalAvatar(DistributedAvatar.DistributedAvatar, DistributedSmoothNode.Dis self.controlManager.setSpeeds(OTPGlobals.ToonForwardSlowSpeed, OTPGlobals.ToonJumpSlowForce, OTPGlobals.ToonReverseSlowSpeed, OTPGlobals.ToonRotateSlowSpeed) def pageUp(self): - if not self.avatarControlsEnabled: + if not (self.avatarControlsEnabled or self.preventCameraDisable): return self.wakeUp() if not self.isPageUp: @@ -433,7 +437,7 @@ class LocalAvatar(DistributedAvatar.DistributedAvatar, DistributedSmoothNode.Dis self.clearPageUpDown() def pageDown(self): - if not self.avatarControlsEnabled: + if not (self.avatarControlsEnabled and self.preventCameraDisable): return self.wakeUp() if not self.isPageDown: @@ -452,7 +456,7 @@ class LocalAvatar(DistributedAvatar.DistributedAvatar, DistributedSmoothNode.Dis self.setCameraPositionByIndex(self.cameraIndex) def nextCameraPos(self, forward): - if not self.avatarControlsEnabled: + if not (self.avatarControlsEnabled or self.preventCameraDisable): return self.wakeUp() self.__cameraHasBeenMoved = 1 @@ -465,6 +469,10 @@ class LocalAvatar(DistributedAvatar.DistributedAvatar, DistributedSmoothNode.Dis if self.cameraIndex < 0: self.cameraIndex = len(self.cameraPositions) - 1 self.setCameraPositionByIndex(self.cameraIndex) + + def setCameraPosition(self, index): + self.cameraIndex = index + self.setCameraPositionByIndex(index) def initCameraPositions(self): camHeight = self.getClampedAvatarHeight() diff --git a/otp/chat/ChatAgentUD.py b/otp/chat/ChatAgentUD.py index 2e13d84a..1ece070f 100755 --- a/otp/chat/ChatAgentUD.py +++ b/otp/chat/ChatAgentUD.py @@ -1,40 +1,83 @@ from direct.directnotify import DirectNotifyGlobal from direct.distributed.DistributedObjectGlobalUD import DistributedObjectGlobalUD +from direct.distributed.PyDatagram import PyDatagram +from direct.distributed.MsgTypes import * from otp.distributed import OtpDoGlobals - +from toontown.toonbase import TTLocalizer + +BLACKLIST = TTLocalizer.Blacklist +OFFENSE_MSGS = ('-- DEV CHAT -- word blocked: %s', 'Watch your language! This is your first offense. You said "%s".', + 'Watch your language! This is your second offense. Next offense you\'ll get banned for 24 hours. You said "%s".') + class ChatAgentUD(DistributedObjectGlobalUD): - notify = DirectNotifyGlobal.directNotify.newCategory("ChatAgentUD") - - def announceGenerate(self): - DistributedObjectGlobalUD.announceGenerate(self) - - self.chatMode2channel = { + notify = DirectNotifyGlobal.directNotify.newCategory('ChatAgentUD') + WantWhitelist = config.GetBool('want-whitelist', True) + + chatMode2channel = { 1 : OtpDoGlobals.OTP_MOD_CHANNEL, 2 : OtpDoGlobals.OTP_ADMIN_CHANNEL, 3 : OtpDoGlobals.OTP_SYSADMIN_CHANNEL, - } - self.chatMode2prefix = { + } + chatMode2prefix = { 1 : "[MOD] ", 2 : "[ADMIN] ", 3 : "[SYSADMIN] ", - } - + } + + def announceGenerate(self): + DistributedObjectGlobalUD.announceGenerate(self) + + self.offenses = {} + def chatMessage(self, message, chatMode): sender = self.air.getAvatarIdFromSender() - if sender == 0: - self.air.writeServerEvent('suspicious', accId=self.air.getAccountIdFromSender(), - issue='Account sent chat without an avatar', message=message) + self.air.writeServerEvent('suspicious', self.air.getAccountIdFromSender(), + 'Account sent chat without an avatar', message) return - - self.air.writeServerEvent('chat-said', avId=sender, chatMode=chatMode, msg=message) - - if chatMode != 0: - if message.startswith('.'): - message = '.' + self.chatMode2prefix.get(chatMode, "") + message[1:] - else: - message = self.chatMode2prefix.get(chatMode, "") + message - + + if chatMode == 0: + if self.detectBadWords(self.air.getMsgSender(), message): + return + + self.air.writeServerEvent('chat-said', sender, message) + DistributedAvatar = self.air.dclassesByName['DistributedAvatarUD'] - dg = DistributedAvatar.aiFormatUpdate('setTalk', sender, self.chatMode2channel.get(chatMode, sender), self.air.ourChannel, [message]) + dg = DistributedAvatar.aiFormatUpdate('setTalk', sender, sender, + self.air.ourChannel, + [message]) self.air.send(dg) + + def detectBadWords(self, sender, message): + words = message.split() + print words + for word in words: + if word.lower() in BLACKLIST: + accountId = (sender >> 32) & 0xFFFFFFFF + avId = sender & 0xFFFFFFFF + + if not sender in self.offenses: + self.offenses[sender] = 0 + + if self.air.friendsManager.getToonAccess(avId) < 300: + self.offenses[sender] += 1 + + if self.offenses[sender] >= 3: + msg = 'Banned' + + else: + msg = OFFENSE_MSGS[self.offenses[sender]] % word + dclass = self.air.dclassesByName['ClientServicesManagerUD'] + dg = dclass.aiFormatUpdate('systemMessage', + OtpDoGlobals.OTP_DO_ID_CLIENT_SERVICES_MANAGER, + sender, 1000000, [msg]) + self.air.send(dg) + #self.air.banManager.ban(sender, 2, 'language') + + self.air.writeServerEvent('chat-offense', accountId, word=word, num=self.offenses[sender], msg=msg) + if self.offenses[sender] >= 3: + del self.offenses[sender] + + return 1 + + return 0 \ No newline at end of file diff --git a/otp/chat/WhiteListData.py b/otp/chat/WhiteListData.py index da4b6509..e99854de 100755 --- a/otp/chat/WhiteListData.py +++ b/otp/chat/WhiteListData.py @@ -2886,6 +2886,7 @@ WHITELIST = [ 'be', 'be-awesome', 'be-yoink', + 'beach', 'beachcombers', 'beachead', 'beached', @@ -9980,6 +9981,7 @@ WHITELIST = [ 'deny', 'denying', 'deodorant', + 'deorro', 'depart', 'departed', 'departing', @@ -22308,6 +22310,8 @@ WHITELIST = [ 'masterly', 'masterpiece', 'masters', + 'mastervoltage', + 'mastervolty', 'mastery', 'mat', 'matata', @@ -30128,6 +30132,7 @@ WHITELIST = [ 'sins', 'sip', 'sir', + 'sirbiscuit', 'siren', "siren's", 'sirens', @@ -34728,6 +34733,7 @@ WHITELIST = [ 'volleyball', 'voltage', 'voltorn', + 'volty', 'volume', "volume's", 'volumed', @@ -36496,6 +36502,7 @@ WHITELIST = [ 'zebra', "zebra's", 'zebras', + 'zedd', 'zeddars', 'zeke', 'zelda', @@ -36862,4 +36869,4 @@ WHITELIST = [ 'zyyk', 'zzz', 'zzzzzs', -] +] \ No newline at end of file diff --git a/otp/distributed/DistributedDistrictAI.py b/otp/distributed/DistributedDistrictAI.py index b9870151..c80b2ac3 100755 --- a/otp/distributed/DistributedDistrictAI.py +++ b/otp/distributed/DistributedDistrictAI.py @@ -1,6 +1,5 @@ from direct.directnotify.DirectNotifyGlobal import directNotify from direct.distributed.DistributedObjectAI import DistributedObjectAI -from toontown.toonbase import ToontownGlobals class DistributedDistrictAI(DistributedObjectAI): notify = directNotify.newCategory('DistributedDistrictAI') @@ -8,16 +7,6 @@ class DistributedDistrictAI(DistributedObjectAI): name = 'District' available = 0 - def announceGenerate(self): - DistributedObjectAI.announceGenerate(self) - doId = self.doId - (self.doId % 100000000 % 1000000) - self.air.groupManager.shardGroups[doId] = { - ToontownGlobals.SellbotHQ: ['VP Group', []], - ToontownGlobals.CashbotHQ: ['CFO Group', []], - ToontownGlobals.LawbotHQ: ['CJ Group', []], - ToontownGlobals.BossbotHQ: ['CEO Group', []], - } - def setName(self, name): self.name = name diff --git a/otp/distributed/OTPClientRepository.py b/otp/distributed/OTPClientRepository.py index cfc6c23f..4ecb646a 100755 --- a/otp/distributed/OTPClientRepository.py +++ b/otp/distributed/OTPClientRepository.py @@ -1071,7 +1071,7 @@ class OTPClientRepository(ClientRepositoryBase): for s in self.activeDistrictMap.values(): if s.available: - list.append((s.doId, s.name, s.avatarCount, s.invasionStatus)) + list.append((s.doId, s.name, s.avatarCount, s.invasionStatus, s.groupAvCount)) return list diff --git a/otp/distributed/OtpDoGlobals.py b/otp/distributed/OtpDoGlobals.py index 771bfcfa..fbf3ca12 100755 --- a/otp/distributed/OtpDoGlobals.py +++ b/otp/distributed/OtpDoGlobals.py @@ -3,7 +3,6 @@ OTP_DO_ID_FRIEND_MANAGER = 4501 OTP_DO_ID_TOONTOWN = 1337 OTP_DO_ID_CLIENT_SERVICES_MANAGER = 4665 OTP_DO_ID_TTS_FRIENDS_MANAGER = 4666 -OPT_DO_ID_GROUP_MANAGER = 4667 OTP_DO_ID_GLOBAL_PARTY_MANAGER = 4477 OTP_DO_ID_GLOBAL_LOBBY_MANAGER = 4478 OTP_DO_ID_CHAT_MANAGER = 4681 diff --git a/otp/distributed/PotentialAvatar.py b/otp/distributed/PotentialAvatar.py index 3c979fc6..67bab13c 100755 --- a/otp/distributed/PotentialAvatar.py +++ b/otp/distributed/PotentialAvatar.py @@ -1,19 +1,11 @@ class PotentialAvatar: - def __init__(self, id, names, dna, position, allowedName, creator = 1, shared = 1, online = 0, wishState = 'CLOSED', wishName = '', defaultShard = 0, lastLogout = 0): + def __init__(self, id, names, dna, position, allowedName): self.id = id self.name = names[0] self.dna = dna - self.avatarType = None self.position = position self.wantName = names[1] self.approvedName = names[2] self.rejectedName = names[3] self.allowedName = allowedName - self.wishState = wishState - self.wishName = wishName - self.creator = creator - self.shared = shared - self.online = online - self.defaultShard = defaultShard - self.lastLogout = lastLogout diff --git a/otp/friends/FriendManager.py b/otp/friends/FriendManager.py index 4daf48b5..0315a272 100755 --- a/otp/friends/FriendManager.py +++ b/otp/friends/FriendManager.py @@ -91,3 +91,14 @@ class FriendManager(DistributedObject.DistributedObject): self.notify.debug('Client: inviteeCancelFriendQuery(%d)' % context) messenger.send('cancelFriendInvitation', [context]) self.up_inviteeAcknowledgeCancel(context) + + def requestTFCode(self, callback): + self.tfCallback = callback + self.sendUpdate('requestTFCode') + + def redeemTFCode(self, code, callback): + self.tfCallback = callback + self.sendUpdate('redeemTFCode', [code]) + + def tfResponse(self, response, code): + self.tfCallback(response, code) \ No newline at end of file diff --git a/otp/friends/FriendManagerAI.py b/otp/friends/FriendManagerAI.py index 16352791..b089526a 100755 --- a/otp/friends/FriendManagerAI.py +++ b/otp/friends/FriendManagerAI.py @@ -1,5 +1,58 @@ from direct.directnotify import DirectNotifyGlobal from direct.distributed.DistributedObjectAI import DistributedObjectAI +from otp.otpbase import OTPGlobals +from toontown.toonbase import ToontownGlobals +import datetime, uuid, time, string, random + +AVAILABLE_CHARS = string.ascii_lowercase + string.digits + +class AddTrueFriend: + + def __init__(self, manager, av, targetId, code): + self.air = manager.air + self.manager = manager + self.av = av + self.targetId = targetId + self.code = code + + def start(self): + self.air.dbInterface.queryObject(self.air.dbId, self.targetId, self.__gotAvatar) + + def __gotAvatar(self, dclass, fields): + dclasses = self.air.dclassesByName['DistributedToonAI'] + + if dclass != dclasses: + return + + friendsList = fields['setFriendsList'][0] + trueFriendsList = fields['setTrueFriends'][0] + name = fields['setName'][0] + avId = self.av.doId + + if avId in trueFriendsList: + self.manager.sendUpdateToAvatarId(avId, 'tfResponse', [ToontownGlobals.TF_ALREADY_FRIENDS_NAME, name]) + return + elif avId not in friendsList: + if len(friendsList) >= OTPGlobals.MaxFriends: + self.manager.sendUpdateToAvatarId(avId, 'tfResponse', [ToontownGlobals.TF_FRIENDS_LIST_FULL_HIM, name]) + return + + friendsList.append(avId) + + if self.targetId not in self.av.getFriendsList(): + self.av.extendFriendsList(self.targetId) + + if hasattr(self.manager, 'data'): + del self.manager.data[self.code] + else: + self.air.dbGlobalCursor.tfCodes.remove({'_id': self.code}) + + self.av.addTrueFriend(self.targetId) + trueFriendsList.append(avId) + self.air.send(dclasses.aiFormatUpdate('setFriendsList', self.targetId, self.targetId, self.air.ourChannel, [friendsList])) + self.air.send(dclasses.aiFormatUpdate('setTrueFriends', self.targetId, self.targetId, self.air.ourChannel, [trueFriendsList])) + self.manager.sendUpdateToAvatarId(avId, 'tfResponse', [ToontownGlobals.TF_SUCCESS, name]) + del self.manager.tfFsms[avId] class FriendManagerAI(DistributedObjectAI): notify = DirectNotifyGlobal.directNotify.newCategory("FriendManagerAI") @@ -9,6 +62,15 @@ class FriendManagerAI(DistributedObjectAI): self.air = air self.currentContext = 0 self.requests = {} + self.tfFsms = {} + self.connectToDatabase() + + def connectToDatabase(self): + if not self.air.dbConn: + self.notify.warning('Not using mongodb, true friends will be non-persistent') + self.data = {} + else: + self.air.dbGlobalCursor.tfCodes.ensure_index('date', expireAfterSeconds=ToontownGlobals.TF_EXPIRE_SECS) def friendQuery(self, requested): avId = self.air.getAvatarIdFromSender() @@ -118,3 +180,81 @@ class FriendManagerAI(DistributedObjectAI): return del self.requests[context] + + def getRandomCharSequence(self, count): + return ''.join(random.choice(AVAILABLE_CHARS) for i in xrange(count)) + + def getTFCode(self, tryNumber): + if tryNumber == ToontownGlobals.MAX_TF_TRIES: + return str(uuid.uuid4()) + + code = 'TT %s %s' % (self.getRandomCharSequence(3), self.getRandomCharSequence(3)) + + if (hasattr(self, 'data') and code in self.data) or (self.air.dbConn and self.air.dbGlobalCursor.tfCodes.find({'_id': code}).count() > 0): + return self.getTFCode(tryNumber + 1) + + return code + + def requestTFCode(self): + avId = self.air.getAvatarIdFromSender() + av = self.air.doId2do.get(avId) + + if not av: + return + + tfRequest = av.getTFRequest() + + if tfRequest[1] >= ToontownGlobals.MAX_TF_TRIES and tfRequest[0] >= time.time(): + self.sendUpdateToAvatarId(avId, 'tfResponse', [ToontownGlobals.TF_COOLDOWN, '']) + return + + code = self.getTFCode(0) + + if hasattr(self, 'data'): + self.data[code] = avId + else: + self.air.dbGlobalCursor.tfCodes.insert({'_id': code, 'date': datetime.datetime.utcnow(), 'avId': avId}) + + av.b_setTFRequest((time.time() + ToontownGlobals.TF_COOLDOWN_SECS, tfRequest[1] + 1)) + self.sendUpdateToAvatarId(avId, 'tfResponse', [ToontownGlobals.TF_SUCCESS, code]) + + def redeemTFCode(self, code): + avId = self.air.getAvatarIdFromSender() + + if avId in self.tfFsms: + self.sendUpdateToAvatarId(avId, 'tfResponse', [ToontownGlobals.TF_TOO_FAST, '']) + return + + av = self.air.doId2do.get(avId) + + if not av: + return + + if hasattr(self, 'data'): + if code not in self.data: + self.sendUpdateToAvatarId(avId, 'tfResponse', [ToontownGlobals.TF_UNKNOWN_SECRET, '']) + return + + targetId = self.data[code] + else: + fields = self.air.dbGlobalCursor.tfCodes.find_one({'_id': code}) + + if not fields: + self.sendUpdateToAvatarId(avId, 'tfResponse', [ToontownGlobals.TF_UNKNOWN_SECRET, '']) + return + + targetId = fields['avId'] + + if avId == targetId: + self.sendUpdateToAvatarId(avId, 'tfResponse', [ToontownGlobals.TF_SELF_SECRET, '']) + return + elif av.isTrueFriends(targetId): + self.sendUpdateToAvatarId(avId, 'tfResponse', [ToontownGlobals.TF_ALREADY_FRIENDS, '']) + return + elif targetId not in av.getFriendsList() and len(av.getFriendsList()) >= OTPGlobals.MaxFriends: + self.sendUpdateToAvatarId(avId, 'tfResponse', [ToontownGlobals.TF_FRIENDS_LIST_FULL_YOU, '']) + return + + tfOperation = AddTrueFriend(self, av, targetId, code) + tfOperation.start() + self.tfFsms[avId] = tfOperation \ No newline at end of file diff --git a/otp/nametag/NametagConstants.py b/otp/nametag/NametagConstants.py index d0de16f3..21585963 100644 --- a/otp/nametag/NametagConstants.py +++ b/otp/nametag/NametagConstants.py @@ -9,15 +9,12 @@ CFThought=2 CFTimeout=8 CCNormal = 0 -CCNoChat = 1 -CCNonPlayer = 2 -CCSuit = 3 -CCToonBuilding = 4 -CCSuitBuilding = 5 -CCHouseBuilding = 6 -CCSpeedChat = 7 -CCFreeChat = 8 -CCAdmin = 9 +CCNonPlayer = 1 +CCSuit = 2 +CCToonBuilding = 3 +CCSuitBuilding = 4 +CCHouseBuilding = 5 +CCSpeedChat = 6 NAMETAG_COLORS = { CCNormal: ( @@ -34,20 +31,6 @@ NAMETAG_COLORS = { ((0.3, 0.3, 0.7, 1.0), (0.8, 0.8, 0.8, 0.5), # Name (0.0, 0.0, 0.0, 1.0), (1.0, 1.0, 1.0, 1.0)), # Chat ), - CCNoChat: ( - # Normal FG BG - ((0.8, 0.4, 0.0, 1.0), (0.8, 0.8, 0.8, 0.5), # Name - (0.0, 0.0, 0.0, 1.0), (1.0, 1.0, 1.0, 1.0)), # Chat - # Click FG BG - ((1.0, 0.5, 0.5, 1.0), (0.2, 0.2, 0.2, 0.6), # Name - (1.0, 0.5, 0.5, 1.0), (1.0, 1.0, 1.0, 1.0)), # Chat - # Hover FG BG - ((1.0, 0.5, 0.0, 1.0), (1.0, 1.0, 1.0, 1.0), # Name - (0.0, 0.6, 0.6, 1.0), (1.0, 1.0, 1.0, 1.0)), # Chat - # Disable FG BG - ((0.8, 0.4, 0.0, 1.0), (0.8, 0.8, 0.8, 0.5), # Name - (0.0, 0.0, 0.0, 1.0), (1.0, 1.0, 1.0, 1.0)), # Chat - ), CCNonPlayer: ( # Normal FG BG ((0.8, 0.4, 0.0, 1.0), (0.8, 0.8, 0.8, 0.5), # Name @@ -131,35 +114,7 @@ NAMETAG_COLORS = { # Disable FG BG ((0.0, 0.6, 0.2, 1.0), (0.8, 0.8, 0.8, 0.5), # Name (0.0, 0.0, 0.0, 1.0), (1.0, 1.0, 1.0, 1.0)), # Chat - ), - CCFreeChat: ( - # Normal FG BG - ((0.3, 0.3, 0.7, 1.0), (0.8, 0.8, 0.8, 0.5), # Name - (0.0, 0.0, 0.0, 1.0), (1.0, 1.0, 1.0, 1.0)), # Chat - # Click FG BG - ((0.2, 0.2, 0.5, 1.0), (0.2, 0.2, 0.2, 0.6), # Name - (1.0, 0.5, 0.5, 1.0), (1.0, 1.0, 1.0, 1.0)), # Chat - # Hover FG BG - ((0.5, 0.5, 1.0, 1.0), (1.0, 1.0, 1.0, 1.0), # Name - (0.0, 0.6, 0.6, 1.0), (1.0, 1.0, 1.0, 1.0)), # Chat - # Disable FG BG - ((0.3, 0.3, 0.7, 1.0), (0.8, 0.8, 0.8, 0.5), # Name - (0.0, 0.0, 0.0, 1.0), (1.0, 1.0, 1.0, 1.0)), # Chat - ), - CCAdmin: ( - # Normal FG BG - ((1.0, 0.35, 0.25, 1.0), (0.8, 0.8, 0.8, 0.5), # Name - (0.0, 0.0, 0.0, 1.0), (1.0, 1.0, 1.0, 1.0)), # Chat - # Click FG BG - ((1.0, 0.35, 0.25, 1.0), (0.2, 0.2, 0.2, 0.6), # Name - (1.0, 0.5, 0.5, 1.0), (1.0, 1.0, 1.0, 1.0)), # Chat - # Hover FG BG - ((1.0, 0.5, 0.56, 1.0), (1.0, 1.0, 1.0, 1.0), # Name - (0.0, 0.6, 0.6, 1.0), (1.0, 1.0, 1.0, 1.0)), # Chat - # Disable FG BG - ((1.0, 0.35, 0.25, 1.0), (0.8, 0.8, 0.8, 0.5), # Name - (0.0, 0.0, 0.0, 1.0), (1.0, 1.0, 1.0, 1.0)), # Chat - ), + ) } ARROW_COLORS = { @@ -168,15 +123,12 @@ ARROW_COLORS = { DEFAULT_WORDWRAPS = { CCNormal: 7.5, - CCNoChat: 7.5, CCNonPlayer: 7.5, CCSuit: 7.5, CCToonBuilding: 8.5, CCSuitBuilding: 8.5, CCHouseBuilding: 10.0, - CCSpeedChat: 7.5, - CCFreeChat: 7.5, - CCAdmin: 7.5 + CCSpeedChat: 7.5 } WTNormal = 0 @@ -195,7 +147,7 @@ WHISPER_COLORS = { # Hover FG BG ((0.0, 0.0, 0.0, 1.0), (0.2, 0.7, 0.9, 0.6)), # Disable FG BG - ((0.0, 0.0, 0.0, 1.0), (0.2, 0.7, 0.8, 0.6)), + ((0.0, 0.0, 0.0, 1.0), (0.2, 0.7, 0.8, 0.6)) ), WTQuickTalker: ( # Normal FG BG @@ -205,7 +157,7 @@ WHISPER_COLORS = { # Hover FG BG ((0.0, 0.0, 0.0, 1.0), (0.2, 0.7, 0.9, 0.6)), # Disable FG BG - ((0.0, 0.0, 0.0, 1.0), (0.2, 0.7, 0.8, 0.6)), + ((0.0, 0.0, 0.0, 1.0), (0.2, 0.7, 0.8, 0.6)) ), WTSystem: ( # Normal FG BG @@ -215,9 +167,18 @@ WHISPER_COLORS = { # Hover FG BG ((0.0, 0.0, 0.0, 1.0), (0.8, 0.4, 1.0, 0.6)), # Disable FG BG - ((0.0, 0.0, 0.0, 1.0), (0.8, 0.3, 0.6, 0.6)), + ((0.0, 0.0, 0.0, 1.0), (0.8, 0.3, 0.6, 0.6)) + ), + WTBattleSOS: ( + # Normal FG BG + ((0.0, 0.0, 0.0, 1.0), (0.8, 0.3, 0.6, 0.6)), + # Click FG BG + ((1.0, 0.5, 0.5, 1.0), (1.0, 1.0, 1.0, 0.8)), + # Hover FG BG + ((0.0, 0.0, 0.0, 1.0), (0.8, 0.4, 0.0, 0.8)), + # Disable FG BG + ((0.0, 0.0, 0.0, 1.0), (0.8, 0.3, 0.6, 0.6)) ), - # TODO: WTBattleSOS WTEmote: ( # Normal FG BG ((0.0, 0.0, 0.0, 1.0), (0.9, 0.5, 0.1, 0.6)), @@ -226,7 +187,19 @@ WHISPER_COLORS = { # Hover FG BG ((0.0, 0.0, 0.0, 1.0), (0.9, 0.6, 0.2, 0.6)), # Disable FG BG - ((0.0, 0.0, 0.0, 1.0), (0.9, 0.6, 0.1, 0.6)), + ((0.0, 0.0, 0.0, 1.0), (0.9, 0.6, 0.1, 0.6)) ), - # TODO: WTToontownBoardingGroup + WTToontownBoardingGroup: ( + # Normal FG BG + ((0.0, 0.0, 0.0, 1.0), (0.9, 0.5, 0.1, 0.6)), + # Click FG BG + ((1.0, 0.5, 0.5, 1.0), (1.0, 1.0, 1.0, 0.8)), + # Hover FG BG + ((0.0, 0.0, 0.0, 1.0), (0.9, 0.6, 0.2, 0.6)), + # Disable FG BG + ((0.0, 0.0, 0.0, 1.0), (0.9, 0.6, 0.1, 0.6)) + ) } + +def getFriendColor(handle): + return CCNormal if settings['trueFriends'] and base.localAvatar.isTrueFriends(handle.doId) else CCSpeedChat \ No newline at end of file diff --git a/otp/nametag/NametagGroup.py b/otp/nametag/NametagGroup.py index 8f0a3e4f..04490c7f 100644 --- a/otp/nametag/NametagGroup.py +++ b/otp/nametag/NametagGroup.py @@ -2,18 +2,16 @@ from pandac.PandaModules import * from NametagConstants import * from Nametag3d import * from Nametag2d import * +import subprocess class NametagGroup: CCNormal = CCNormal - CCNoChat = CCNoChat CCNonPlayer = CCNonPlayer CCSuit = CCSuit CCToonBuilding = CCToonBuilding CCSuitBuilding = CCSuitBuilding CCHouseBuilding = CCHouseBuilding CCSpeedChat = CCSpeedChat - CCFreeChat = CCFreeChat - CCAdmin = CCAdmin CHAT_TIMEOUT_MAX = 12.0 CHAT_TIMEOUT_MIN = 4.0 @@ -244,6 +242,9 @@ class NametagGroup: tag.chatFlags = self.chatFlags tag.avatar = self.avatar tag.icon = self.icon + + if settings['talk2speech']: + subprocess.Popen('espeak "%s"' % tag.chatString) tag.update() diff --git a/otp/otpbase/OTPBase.py b/otp/otpbase/OTPBase.py index bbf96ae0..2071199e 100755 --- a/otp/otpbase/OTPBase.py +++ b/otp/otpbase/OTPBase.py @@ -7,7 +7,6 @@ import OTPGlobals, OTPRender, math class OTPBase(ShowBase): def __init__(self, windowType = None): - self.wantEnviroDR = False ShowBase.__init__(self, windowType=windowType) self.idTags = config.GetBool('want-id-tags', 0) if not self.idTags: @@ -15,9 +14,6 @@ class OTPBase(ShowBase): self.wantNametags = self.config.GetBool('want-nametags', 1) self.wantDynamicShadows = 1 self.stereoEnabled = False - self.enviroDR = None - self.enviroCam = None - self.pixelZoomSetup = False self.whiteList = None if config.GetBool('want-whitelist', True): @@ -27,159 +23,12 @@ class OTPBase(ShowBase): if config.GetBool('want-sequence-list', True): self.whiteList.setSequenceList(SequenceListData.SEQUENCES) - if base.cam: - if self.wantEnviroDR: - base.cam.node().setCameraMask(OTPRender.MainCameraBitmask) - else: - base.cam.node().setCameraMask(OTPRender.MainCameraBitmask | OTPRender.EnviroCameraBitmask) - taskMgr.setupTaskChain('net') - - def setTaskChainNetThreaded(self): - if base.config.GetBool('want-threaded-network', 0): - taskMgr.setupTaskChain('net', numThreads=1, frameBudget=0.001, threadPriority=TPLow) - - def setTaskChainNetNonthreaded(self): - taskMgr.setupTaskChain('net', numThreads=0, frameBudget=-1) - - def toggleStereo(self): - self.stereoEnabled = not self.stereoEnabled - if self.stereoEnabled: - if not base.win.isStereo(): - base.win.setRedBlueStereo(True, ColorWriteAttrib.CRed, ColorWriteAttrib.CGreen | ColorWriteAttrib.CBlue) - if self.wantEnviroDR: - self.setupEnviroCamera() - return - mainDR = base.camNode.getDisplayRegion(0) - if self.stereoEnabled: - if not mainDR.isStereo(): - base.win.removeDisplayRegion(mainDR) - mainDR = base.win.makeStereoDisplayRegion() - mainDR.getRightEye().setClearDepthActive(True) - mainDR.setCamera(base.cam) - elif mainDR.isStereo(): - base.win.removeDisplayRegion(mainDR) - mainDR = base.win.makeMonoDisplayRegion() - mainDR.setCamera(base.cam) - - def setupEnviroCamera(self): - clearColor = VBase4(0, 0, 0, 1) - if self.enviroDR: - clearColor = self.enviroDR.getClearColor() - self.win.removeDisplayRegion(self.enviroDR) - if not self.enviroCam: - self.enviroCam = self.cam.attachNewNode(Camera('enviroCam')) - mainDR = self.camNode.getDisplayRegion(0) - if self.stereoEnabled: - self.enviroDR = self.win.makeStereoDisplayRegion() - if not mainDR.isStereo(): - self.win.removeDisplayRegion(mainDR) - mainDR = self.win.makeStereoDisplayRegion() - mainDR.setCamera(self.cam) - ml = mainDR.getLeftEye() - mr = mainDR.getRightEye() - el = self.enviroDR.getLeftEye() - er = self.enviroDR.getRightEye() - el.setSort(-8) - ml.setSort(-6) - er.setSort(-4) - er.setClearDepthActive(True) - mr.setSort(-2) - mr.setClearDepthActive(False) - else: - self.enviroDR = self.win.makeMonoDisplayRegion() - if mainDR.isStereo(): - self.win.removeDisplayRegion(mainDR) - mainDR = self.win.makeMonoDisplayRegion() - mainDR.setCamera(self.cam) - self.enviroDR.setSort(-10) - self.enviroDR.setClearColor(clearColor) - self.win.setClearColor(clearColor) - self.enviroDR.setCamera(self.enviroCam) - self.enviroCamNode = self.enviroCam.node() - self.enviroCamNode.setLens(self.cam.node().getLens()) - self.enviroCamNode.setCameraMask(OTPRender.EnviroCameraBitmask) - render.hide(OTPRender.EnviroCameraBitmask) - self.camList.append(self.enviroCam) - self.backgroundDrawable = self.enviroDR - self.enviroDR.setTextureReloadPriority(-10) - if self.pixelZoomSetup: - self.setupAutoPixelZoom() - - def setupAutoPixelZoom(self): - self.win.setPixelZoom(1) - self.enviroDR.setPixelZoom(1) - if not self.stereoEnabled: - self.enviroDR.setClearColorActive(True) - self.enviroDR.setClearDepthActive(True) - self.win.setClearColorActive(False) - self.win.setClearDepthActive(False) - self.backgroundDrawable = self.enviroDR - else: - self.enviroDR.setClearColorActive(False) - self.enviroDR.setClearDepthActive(False) - self.enviroDR.getRightEye().setClearDepthActive(True) - self.win.setClearColorActive(True) - self.win.setClearDepthActive(True) - self.backgroundDrawable = self.win - self.pixelZoomSetup = True - self.targetPixelZoom = 1.0 - self.pixelZoomTask = None - self.pixelZoomCamHistory = 2.0 - self.pixelZoomCamMovedList = [] - self.pixelZoomStarted = None - flag = self.config.GetBool('enable-pixel-zoom', True) - self.enablePixelZoom(flag) - return - - def enablePixelZoom(self, flag): - if not self.backgroundDrawable.supportsPixelZoom(): - flag = False - self.pixelZoomEnabled = flag - taskMgr.remove('chasePixelZoom') - if flag: - taskMgr.add(self.__chasePixelZoom, 'chasePixelZoom', priority=-52) - else: - self.backgroundDrawable.setPixelZoom(1) - - def __chasePixelZoom(self, task): - now = globalClock.getFrameTime() - pos = base.cam.getNetTransform().getPos() - prevPos = base.cam.getNetPrevTransform().getPos() - d2 = (pos - prevPos).lengthSquared() - if d2: - d = math.sqrt(d2) - self.pixelZoomCamMovedList.append((now, d)) - while self.pixelZoomCamMovedList and self.pixelZoomCamMovedList[0][0] < now - self.pixelZoomCamHistory: - del self.pixelZoomCamMovedList[0] - - dist = sum(map(lambda pair: pair[1], self.pixelZoomCamMovedList)) - speed = dist / self.pixelZoomCamHistory - if speed < 5: - self.backgroundDrawable.setPixelZoom(4) - self.pixelZoomStart = None - elif speed > 10: - if self.pixelZoomStart == None: - self.pixelZoomStart = now - elapsed = now - self.pixelZoomStart - if elapsed > 10: - self.backgroundDrawable.setPixelZoom(16) - elif elapsed > 5: - self.backgroundDrawable.setPixelZoom(8) - return task.cont - - def getShardPopLimits(self): - return (100, 200, -1) + base.cam.node().setCameraMask(OTPRender.MainCameraBitmask) + taskMgr.setupTaskChain('net', numThreads=1, frameBudget=0.001, threadPriority=TPLow) def getRepository(self): return self.cr - def openMainWindow(self, *args, **kw): - result = ShowBase.openMainWindow(self, *args, **kw) - if result: - self.wantEnviroDR = not self.win.getGsg().isHardware() or config.GetBool('want-background-region', 1) - self.backgroundDrawable = self.win - return result - def run(self): try: taskMgr.run() diff --git a/otp/otpbase/OTPLocalizerEnglish.py b/otp/otpbase/OTPLocalizerEnglish.py index 401fcdb1..bf709ccf 100755 --- a/otp/otpbase/OTPLocalizerEnglish.py +++ b/otp/otpbase/OTPLocalizerEnglish.py @@ -132,7 +132,8 @@ CRBootedReasons = {100: 'You have been disconnected because someone else just lo 102: 'You are not authorized to use administrator privileges.', 103: 'You were banned by a moderator.\n\nBehave next time!', 105: 'Toontown Stride is now temporarily closed for maintenance. Everyone who was playing has been disconnected from the game.\n\nFor more information, please visit the Toontown Stride website.', - 153: 'The district you were playing on has been reset. Everyone who was playing on that district has been disconnected. However, you should be able to connect again and go right back into the game.'} + 153: 'The district you were playing on has been reset. Everyone who was playing on that district has been disconnected. However, you should be able to connect again and go right back into the game.', + 166: 'You were disconnected to prevent a district reset.'} CRBootedReasonUnknownCode = 'An unexpected problem has occurred (error code %s). Your connection has been lost, but you should be able to connect again and go right back into the game.' CRTryConnectAgain = '\n\nTry to connect again?' CRToontownUnavailable = 'The server appears to be temporarily unavailable, still trying...' @@ -233,6 +234,7 @@ FriendInviterConfirmRemove = 'Remove' FriendInviterYes = lYes FriendInviterNo = lNo FriendInviterClickToon = 'Click on the toon you would like to make friends with.' +FriendInviterTooMany = 'You have too many friends on your list to add another one now. You will have to remove some friends if you want to make friends with %s.' FriendInviterToonTooMany = 'You have too many toon friends on your list to add another one now. You will have to remove some toon friends if you want to make friends with %s.' FriendInviterNotYet = 'Would you like to make friends with %s?' FriendInviterCheckAvailability = 'Seeing if %s is available.' @@ -374,7 +376,7 @@ SuitFaceoffTaunts = {'b': ['Do you have a donation for me?', 'Good, it takes two to mingle.', "Let's mingle.", 'This looks like a good place to mingle.', - "Well,isn't this cozy?", + "Well, isn't this cozy?", "You're mingling with defeat.", "I'm going to mingle in your business.", "Are you sure you're ready to mingle?"], @@ -518,7 +520,7 @@ SuitFaceoffTaunts = {'b': ['Do you have a donation for me?', 'Care to take a few turns with me?', 'I have my own special spin on the subject.'], 'f': ["I'm gonna tell the boss about you!", - "I may be just a flunky - But I'm real spunky.", + "I may be just a Flunky - But I'm real spunky.", "I'm using you to step up the corporate ladder.", "You're not going to like the way I work.", 'The boss is counting on me to stop you.', @@ -541,7 +543,7 @@ SuitFaceoffTaunts = {'b': ['Do you have a donation for me?', 'Careful, I may leave a mark.'], 'ym': ["I'm positive you're not going to like this.", "I don't know the meaning of no.", - 'Want to meet? I say yes, anytime.', + 'Want to meet? I say yes, anytime.', 'You need some positive enforcement.', "I'm going to make a positive impression.", "I haven't been wrong yet.", @@ -590,7 +592,7 @@ SuitFaceoffTaunts = {'b': ['Do you have a donation for me?', 'Can I interest you in an insurance plan?', 'You should have missed my call.', "You won't be able to get rid of me now.", - 'This a bad time? Good.', + 'This a bad time? Good.', 'I was planning on running into you.', 'I will be reversing the charges for this call.', 'I have some costly items for you today.', @@ -620,7 +622,7 @@ SuitFaceoffTaunts = {'b': ['Do you have a donation for me?', 'Would you like some hand-me-downs?', 'Let me show you some of my handiwork.', 'I think the handwriting is on the wall.', - "I'll gladly handle your gags for you"], + "I'll gladly handle your gags for you."], 'sc': ['I will make short work of you.', "You're about to have money trouble.", "You're about to be overcharged.", @@ -642,7 +644,7 @@ SuitFaceoffTaunts = {'b': ['Do you have a donation for me?', "I've been asked to pinch-hit.", "I'll prove you're not dreaming.", 'Heads you lose, tails I win.', - 'A Penny for your gags.'], + 'A penny for your gags.'], 'tw': ['Things are about to get very tight.', "That's Mr. Tightwad to you.", "I'm going to cut off your funding.", @@ -2344,4 +2346,4 @@ AccessToString = { 500: '\x01androidGreen\x01Developer\x02', 600: '\x01cobalt\x01Admin\x02', 700: '\x01azure\x01System Admin\x02' -} +} \ No newline at end of file diff --git a/otp/otpbase/OTPRender.py b/otp/otpbase/OTPRender.py index fee55ca5..ecb99b74 100755 --- a/otp/otpbase/OTPRender.py +++ b/otp/otpbase/OTPRender.py @@ -4,7 +4,6 @@ ReflectionCameraBitmask = BitMask32.bit(1) ShadowCameraBitmask = BitMask32.bit(2) SkyReflectionCameraBitmask = BitMask32.bit(3) GlowCameraBitmask = BitMask32.bit(4) -EnviroCameraBitmask = BitMask32.bit(5) def setCameraBitmask(default, node_path, camera_bitmask, tag = None, tag_function = None, context = None): if node_path: diff --git a/otp/settings/Settings.py b/otp/settings/Settings.py index 5fa803ba..de87fe0e 100755 --- a/otp/settings/Settings.py +++ b/otp/settings/Settings.py @@ -17,7 +17,7 @@ class Settings(collections.MutableMapping): def write(self): with open(self.filename, 'w') as f: - json.dump(self.store, f) + json.dump(self.store, f, sort_keys=True, indent=2, separators=(',', ': ')) def __setitem__(self, key, value): self.store[key] = value diff --git a/toontown/ai/FishManagerAI.py b/toontown/ai/FishManagerAI.py index fe0b7c20..124a2e83 100755 --- a/toontown/ai/FishManagerAI.py +++ b/toontown/ai/FishManagerAI.py @@ -3,7 +3,8 @@ import random from otp.ai.MagicWordGlobal import * from toontown.fishing import FishGlobals from toontown.fishing.FishBase import FishBase -from toontown.toonbase import TTLocalizer +from toontown.toonbase import TTLocalizer, ToontownGlobals +from toontown.uberdog import TopToonsGlobals class FishManagerAI: @@ -50,6 +51,7 @@ class FishManagerAI: netlist = av.fishTank.getNetLists() av.d_setFishTank(netlist[0], netlist[1], netlist[2]) del self.requestedFish[av.doId] + av.addStat(ToontownGlobals.STAT_FISH) return [itemType, genus, species, weight] if itemType == FishGlobals.FishItem: success, genus, species, weight = FishGlobals.getRandomFishVitals(zoneId, av.getFishingRod()) @@ -66,6 +68,8 @@ class FishManagerAI: av.fishTank.addFish(fish) netlist = av.fishTank.getNetLists() av.d_setFishTank(netlist[0], netlist[1], netlist[2]) + messenger.send('topToonsManager-event', [av.doId, TopToonsGlobals.CAT_FISH, 1]) + av.addStat(ToontownGlobals.STAT_FISH) return [itemType, genus, species, weight] elif itemType == FishGlobals.BootItem: return [itemType, 0, 0, 0] @@ -89,6 +93,8 @@ class FishManagerAI: av.fishTank.addFish(fish) netlist = av.fishTank.getNetLists() av.d_setFishTank(netlist[0], netlist[1], netlist[2]) + messenger.send('topToonsManager-event', [av.doId, TopToonsGlobals.CAT_FISH, 1]) + av.addStat(ToontownGlobals.STAT_FISH) return [itemType, genus, species, weight] else: money = FishGlobals.Rod2JellybeanDict[av.getFishingRod()] diff --git a/toontown/ai/HolidayGlobals.py b/toontown/ai/HolidayGlobals.py index 1d5ae783..4935d6af 100644 --- a/toontown/ai/HolidayGlobals.py +++ b/toontown/ai/HolidayGlobals.py @@ -9,15 +9,6 @@ CAROLING_REWARD = 100 SCAVENGER_HUNT_LOCATIONS = 6 Holidays = { - ToontownGlobals.LAUGHING_MAN: { - 'startMonth': 6, - 'startDay': 22, - 'endMonth': 6, - 'endDay': 22, - 'startMessage': TTLocalizer.LaughingManHolidayStart, - 'ongoingMessage': TTLocalizer.LaughingManHolidayOngoing, - 'endMessage': TTLocalizer.LaughingManHolidayEnd - }, ToontownGlobals.GRAND_PRIX: { 'weekDay': 0, 'startMessage': TTLocalizer.CircuitRaceStart, diff --git a/toontown/ai/NewsManager.py b/toontown/ai/NewsManager.py index 8d0bfd07..13e5d7e0 100755 --- a/toontown/ai/NewsManager.py +++ b/toontown/ai/NewsManager.py @@ -52,10 +52,7 @@ class NewsManager(DistributedObject): self.endSpecialHoliday(id) def startSpecialHoliday(self, id): - if id == ToontownGlobals.LAUGHING_MAN: - for toon in base.cr.toons.values(): - toon.generateLaughingMan() - elif id == ToontownGlobals.APRIL_TOONS_WEEK: + if id == ToontownGlobals.APRIL_TOONS_WEEK: if isinstance(base.cr.playGame.getPlace(), Estate.Estate): base.localAvatar.startAprilToonsControls() @@ -68,10 +65,7 @@ class NewsManager(DistributedObject): base.localAvatar.chatMgr.chatInputSpeedChat.addWinterMenu() def endSpecialHoliday(self, id): - if id == ToontownGlobals.LAUGHING_MAN: - for toon in base.cr.toons.values(): - toon.swapToonHead(laughingMan=toon.getWantLaughingMan()) - elif id == ToontownGlobals.APRIL_TOONS_WEEK: + if id == ToontownGlobals.APRIL_TOONS_WEEK: if isinstance(base.cr.playGame.getPlace(), Estate.Estate): base.localAvatar.stopAprilToonsControls() diff --git a/toontown/ai/QuestManagerAI.py b/toontown/ai/QuestManagerAI.py index b965e85a..8be875d0 100755 --- a/toontown/ai/QuestManagerAI.py +++ b/toontown/ai/QuestManagerAI.py @@ -3,7 +3,8 @@ from toontown.building import FADoorCodes from otp.ai.MagicWordGlobal import * from toontown.hood import ZoneUtil from toontown.quest import Quests - +from toontown.uberdog import TopToonsGlobals +from toontown.toonbase import ToontownGlobals QuestIdIndex = 0 QuestFromNpcIdIndex = 1 @@ -75,6 +76,7 @@ class QuestManagerAI: # If they've completed a quest. if completeStatus == Quests.COMPLETE: # ToonUp the toon to max health. + messenger.send('topToonsManager-event', [av.doId, TopToonsGlobals.CAT_TASKS, 1]) av.toonUp(av.maxHp) # If it's a TrackChoiceQuest then present their track choices. @@ -91,6 +93,7 @@ class QuestManagerAI: # The toon has completed this quest. Give them a reward! npc.completeQuest(avId, questId, rewardId) self.completeQuest(av, questId) + av.addStat(ToontownGlobals.STAT_TASKS) break else: # They haven't completed any quests so we have to give them choices. @@ -289,6 +292,17 @@ class QuestManagerAI: questList.append(questDesc) av.b_setQuests(questList) + + def toonCalledClarabelle(self, av): + avQuests = av.getQuests() + questList = [] + for i in xrange(0, len(avQuests), 5): + questDesc = avQuests[i : i + 5] + questClass = Quests.getQuest(questDesc[QuestIdIndex]) + if isinstance(questClass, Quests.PhoneQuest) and questClass.getCompletionStatus(av, questDesc) == Quests.INCOMPLETE: + questDesc[QuestProgressIndex] += 1 + questList.append(questDesc) + av.b_setQuests(questList) def toonMadeNPCFriend(self, av, count, method): avQuests = av.getQuests() @@ -437,6 +451,7 @@ class QuestManagerAI: def toonKilledBuilding(self, av, type, difficulty, floors, zoneId, cogdo): # Get the avatars current quests. + messenger.send('topToonsManager-event', [av.doId, TopToonsGlobals.CAT_BLDG, 1]) avQuests = av.getQuests() questList = [] zoneId = ZoneUtil.getBranchZone(zoneId) @@ -491,6 +506,7 @@ class QuestManagerAI: def toonKilledCogs(self, av, suitsKilled, zoneId): # Get the avatar's current quests. + messenger.send('topToonsManager-event', [av.doId, TopToonsGlobals.CAT_COGS, len(suitsKilled)]) avQuests = av.getQuests() questList = [] diff --git a/toontown/ai/ServiceStart.py b/toontown/ai/ServiceStart.py index 78d05e9a..9854b017 100755 --- a/toontown/ai/ServiceStart.py +++ b/toontown/ai/ServiceStart.py @@ -19,6 +19,10 @@ sys.path.append( ) import argparse +import gc + +# Panda3D 1.10.0 is 63. +gc.disable() parser = argparse.ArgumentParser() parser.add_argument('--base-channel', help='The base channel that the server may use.') @@ -60,6 +64,7 @@ simbase.air.connect(host, port) try: run() + gc.enable() except SystemExit: raise except Exception: diff --git a/toontown/ai/ToontownAIRepository.py b/toontown/ai/ToontownAIRepository.py index 62b13812..f42a45b6 100755 --- a/toontown/ai/ToontownAIRepository.py +++ b/toontown/ai/ToontownAIRepository.py @@ -46,12 +46,12 @@ from toontown.racing.LeaderboardMgrAI import LeaderboardMgrAI from toontown.pets.PetManagerAI import PetManagerAI from toontown.safezone.SafeZoneManagerAI import SafeZoneManagerAI from toontown.suit.SuitInvasionManagerAI import SuitInvasionManagerAI -from toontown.groups.GroupManagerAI import GroupManagerAI from toontown.toon import NPCToons from toontown.toonbase import ToontownGlobals from toontown.tutorial.TutorialManagerAI import TutorialManagerAI from toontown.uberdog.DistributedPartyManagerAI import DistributedPartyManagerAI -from toontown.uberdog.DistributedLobbyManagerAI import DistributedLobbyManagerAI +from toontown.uberdog.TopToonsManagerAI import TopToonsManagerAI +#from toontown.uberdog.DistributedLobbyManagerAI import DistributedLobbyManagerAI class ToontownAIRepository(ToontownInternalRepository): def __init__(self, baseChannel, stateServerChannel, districtName): @@ -71,7 +71,6 @@ class ToontownAIRepository(ToontownInternalRepository): self.mintMgr = None self.lawOfficeMgr = None self.countryClubMgr = None - self.groupManager = GroupManagerAI(self) self.zoneAllocator = UniqueIdAllocator(ToontownGlobals.DynamicZonesBegin, ToontownGlobals.DynamicZonesEnd) @@ -86,6 +85,7 @@ class ToontownAIRepository(ToontownInternalRepository): self.wantCogbuildings = self.config.GetBool('want-cogbuildings', True) self.wantCogdominiums = self.config.GetBool('want-cogdominiums', True) self.wantTrackClsends = self.config.GetBool('want-track-clsends', False) + self.wantTopToons = self.config.GetBool('want-top-toons', True) self.baseXpMultiplier = self.config.GetFloat('base-xp-multiplier', 1.0) self.cogSuitMessageSent = False @@ -103,7 +103,7 @@ class ToontownAIRepository(ToontownInternalRepository): self.tutorialManager.generateWithRequired(2) self.friendManager = FriendManagerAI(self) self.friendManager.generateWithRequired(2) - self.questManager = QuestManagerAI(self) + self.questManager = QuestManagerAI(self) self.banManager = BanManagerAI.BanManagerAI(self) self.suitInvasionManager = SuitInvasionManagerAI(self) self.blackCatMgr = DistributedBlackCatMgrAI(self) @@ -119,7 +119,8 @@ class ToontownAIRepository(ToontownInternalRepository): self.codeRedemptionMgr.generateWithRequired(2) self.buildingQueryMgr = DistributedBuildingQueryMgrAI(self) self.buildingQueryMgr.generateWithRequired(2) - self.groupManager.generateWithRequired(2) + if self.wantTopToons: + self.topToonsMgr = TopToonsManagerAI(self) if self.wantKarts: self.leaderboardMgr = LeaderboardMgrAI(self) if self.wantFishing: @@ -136,10 +137,10 @@ class ToontownAIRepository(ToontownInternalRepository): self.partyManager.generateWithRequired(2) self.globalPartyMgr = self.generateGlobalObject( OTP_DO_ID_GLOBAL_PARTY_MANAGER, 'GlobalPartyManager') - self.lobbyManager = DistributedLobbyManagerAI(self) - self.lobbyManager.generateWithRequired(2) - self.globalLobbyMgr = self.generateGlobalObject( - OTP_DO_ID_GLOBAL_LOBBY_MANAGER, 'GlobalLobbyManager') + #self.lobbyManager = DistributedLobbyManagerAI(self) + #self.lobbyManager.generateWithRequired(2) + #self.globalLobbyMgr = self.generateGlobalObject( + # OTP_DO_ID_GLOBAL_LOBBY_MANAGER, 'GlobalLobbyManager') def createSafeZones(self): NPCToons.generateZone2NpcDict() @@ -178,6 +179,7 @@ class ToontownAIRepository(ToontownInternalRepository): self.cogHeadquarters.append(BossbotHQAI.BossbotHQAI(self)) def handleConnected(self): + ToontownInternalRepository.handleConnected(self) self.districtId = self.allocateChannel() self.notify.info('Creating ToontownDistrictAI(%d)...' % self.districtId) self.distributedDistrict = ToontownDistrictAI(self) diff --git a/toontown/battle/BattleCalculatorAI.py b/toontown/battle/BattleCalculatorAI.py index c3c97803..b32d25f8 100755 --- a/toontown/battle/BattleCalculatorAI.py +++ b/toontown/battle/BattleCalculatorAI.py @@ -721,7 +721,7 @@ class BattleCalculatorAI: 0, 0] self.toonSkillPtsGained[id] = expList - expList[trk] = expList[trk] + (lvl + 1) * self.__skillCreditMultiplier + expList[trk] = min(ExperienceCap, expList[trk] + (lvl + 1) * self.__skillCreditMultiplier) return def __clearTgtDied(self, tgt, lastAtk, currAtk): diff --git a/toontown/battle/BattleExperienceAI.py b/toontown/battle/BattleExperienceAI.py index 84d9c3d2..573b6793 100755 --- a/toontown/battle/BattleExperienceAI.py +++ b/toontown/battle/BattleExperienceAI.py @@ -1,5 +1,5 @@ from direct.directnotify import DirectNotifyGlobal -from toontown.toonbase import ToontownBattleGlobals +from toontown.toonbase import ToontownBattleGlobals, ToontownGlobals from toontown.suit import SuitDNA BattleExperienceAINotify = DirectNotifyGlobal.directNotify.newCategory('BattleExprienceAI') @@ -183,9 +183,15 @@ def assignRewards(activeToons, toonSkillPtsGained, suitsKilled, zoneId, helpfulT if helpfulToons and toon.doId in helpfulToons: simbase.air.questManager.toonKilledCogs(toon, suitsKilled, zoneId) simbase.air.cogPageManager.toonKilledCogs(toon, suitsKilled, zoneId) + addStats(toon, suitsKilled) else: BattleExperienceAINotify.debug('toon=%d unhelpful not getting killed cog quest credit' % toon.doId) else: simbase.air.questManager.toonKilledCogs(toon, suitsKilled, zoneId) simbase.air.cogPageManager.toonKilledCogs(toon, suitsKilled, zoneId) - return + addStats(toon, suitsKilled) + +def addStats(toon, suitsKilled): + toon.addStat(ToontownGlobals.STAT_COGS, len(suitsKilled)) + toon.addStat(ToontownGlobals.STAT_V2, len([suit for suit in suitsKilled if 'hasRevives' in suit and suit['hasRevives']])) + toon.addStat(ToontownGlobals.STAT_SKELE, len([suit for suit in suitsKilled if 'isSkelecog' in suit and suit['isSkelecog']])) \ No newline at end of file diff --git a/toontown/battle/DistributedBattleBaseAI.py b/toontown/battle/DistributedBattleBaseAI.py index d511b62c..95228535 100755 --- a/toontown/battle/DistributedBattleBaseAI.py +++ b/toontown/battle/DistributedBattleBaseAI.py @@ -1366,6 +1366,7 @@ class DistributedBattleBaseAI(DistributedObjectAI.DistributedObjectAI, BattleBas if check == -1: self.air.writeServerEvent('suspicious', toonId, 'Toon generating movie for non-existent gag track %s level %s' % (track, level)) self.notify.warning('generating movie for non-existent gag track %s level %s! avId: %s' % (track, level, toonId)) + toon.addStat(ToontownGlobals.STAT_GAGS) toon.d_setInventory(toon.inventory.makeNetString()) hps = attack[TOON_HP_COL] if track == SOS: diff --git a/toontown/battle/Movie.py b/toontown/battle/Movie.py index 54bb613d..232e80f5 100755 --- a/toontown/battle/Movie.py +++ b/toontown/battle/Movie.py @@ -338,7 +338,7 @@ class Movie(DirectObject.DirectObject): self.tutorialTom = Toon.Toon() dna = ToonDNA.ToonDNA() - dna.newToonFromProperties(*('dls', 'ms', 'm', 'm', 7, 0, 7, 7, 2, 6, 2, 6, 2, 16, 0)) + dna.newToonFromProperties(*('dls', 'ms', 'm', 'm', 7, 0, 7, 7, 2, 6, 2, 6, 2, 16)) self.tutorialTom.setDNA(dna) self.tutorialTom.setName(TTLocalizer.NPCToonNames[20000]) self.tutorialTom.setPickable(0) diff --git a/toontown/battle/MovieLure.py b/toontown/battle/MovieLure.py index f94932a1..6bec5aed 100755 --- a/toontown/battle/MovieLure.py +++ b/toontown/battle/MovieLure.py @@ -11,6 +11,7 @@ from toontown.toonbase import ToontownBattleGlobals import BattleParticles import BattleProps import MovieNPCSOS +import random notify = DirectNotifyGlobal.directNotify.newCategory('MovieLures') def safeWrtReparentTo(nodePath, parent): @@ -379,7 +380,7 @@ def __createSuitDamageTrack(battle, suit, hp, lure, trapProp): explosionTrack = Sequence(Wait(2.3), createTNTExplosionTrack(battle, trapProp=trapProp, relativeTo=parent)) suitTrack = Sequence(ActorInterval(suit, 'flail', duration=0.7), ActorInterval(suit, 'flail', startTime=0.7, endTime=0.0), ActorInterval(suit, 'neutral', duration=0.4), ActorInterval(suit, 'flail', startTime=0.6, endTime=0.7), Wait(0.4), ActorInterval(suit, 'slip-forward', startTime=2.48, duration=0.1), Func(battle.movie.needRestoreColor), Func(suit.setColorScale, Vec4(0.2, 0.2, 0.2, 1)), Func(trapProp.reparentTo, hidden), ActorInterval(suit, 'slip-forward', startTime=2.58), Func(suit.clearColorScale), Func(trapProp.sparksEffect.cleanup), Func(battle.movie.clearRestoreColor)) damageTrack = Sequence(Wait(2.3), Func(suit.showHpText, -hp, openEnded=0), Func(suit.updateHealthBar, hp)) - explosionSound = base.loadSfx('phase_3.5/audio/sfx/ENC_cogfall_apart.ogg') + explosionSound = base.loadSfx('phase_3.5/audio/sfx/ENC_cogfall_apart_%s.ogg' % random.randint(1, 6)) soundTrack = Sequence(SoundInterval(globalBattleSoundCache.getSound('TL_dynamite.ogg'), duration=2.0, node=suit), SoundInterval(explosionSound, duration=0.6, node=suit)) result.append(Parallel(tntTrack, suitTrack, damageTrack, explosionTrack, soundTrack)) elif trapName == 'traintrack': diff --git a/toontown/battle/MovieUtil.py b/toontown/battle/MovieUtil.py index a8f2e0ef..9d471241 100755 --- a/toontown/battle/MovieUtil.py +++ b/toontown/battle/MovieUtil.py @@ -267,7 +267,7 @@ def createSuitReviveTrack(suit, toon, battle, npcs = []): suitTrack.append(Func(suit.loop, 'neutral')) suitTrack.append(Func(messenger.send, suit.uniqueName('hpChange'))) spinningSound = base.loadSfx('phase_3.5/audio/sfx/Cog_Death.ogg') - deathSound = base.loadSfx('phase_3.5/audio/sfx/ENC_cogfall_apart.ogg') + deathSound = base.loadSfx('phase_3.5/audio/sfx/ENC_cogfall_apart_%s.ogg' % random.randint(1, 6)) deathSoundTrack = Sequence(Wait(0.8), SoundInterval(spinningSound, duration=1.2, startTime=1.5, volume=0.2), SoundInterval(spinningSound, duration=3.0, startTime=0.6, volume=0.8), SoundInterval(deathSound, volume=0.32)) BattleParticles.loadParticles() smallGears = BattleParticles.createParticleEffect(file='gearExplosionSmall') @@ -312,7 +312,7 @@ def createSuitDeathTrack(suit, toon, battle, npcs = []): suitTrack.append(Func(removeDeathSuit, suit, deathSuit, name='remove-death-suit')) suitTrack.append(Func(notify.debug, 'after removeDeathSuit')) spinningSound = base.loadSfx('phase_3.5/audio/sfx/Cog_Death.ogg') - deathSound = base.loadSfx('phase_3.5/audio/sfx/ENC_cogfall_apart.ogg') + deathSound = base.loadSfx('phase_3.5/audio/sfx/ENC_cogfall_apart_%s.ogg' % random.randint(1, 6)) deathSoundTrack = Sequence(Wait(0.8), SoundInterval(spinningSound, duration=1.2, startTime=1.5, volume=0.2), SoundInterval(spinningSound, duration=3.0, startTime=0.6, volume=0.8), SoundInterval(deathSound, volume=0.32)) BattleParticles.loadParticles() smallGears = BattleParticles.createParticleEffect(file='gearExplosionSmall') diff --git a/toontown/building/BoardingPartyBase.py b/toontown/building/BoardingPartyBase.py index 87c5ea18..fe470a4d 100755 --- a/toontown/building/BoardingPartyBase.py +++ b/toontown/building/BoardingPartyBase.py @@ -3,14 +3,13 @@ from toontown.toonbase import ToontownGlobals import copy BOARDCODE_OKAY = 1 BOARDCODE_MISSING = 0 -BOARDCODE_MINLAFF = -1 -BOARDCODE_PROMOTION = -2 -BOARDCODE_BATTLE = -3 -BOARDCODE_SPACE = -4 -BOARDCODE_DIFF_GROUP = -6 -BOARDCODE_PENDING_INVITE = -7 -BOARDCODE_IN_ELEVATOR = -8 -BOARDCODE_GROUPS_TO_LARGE = -9 # JBS +BOARDCODE_PROMOTION = -1 +BOARDCODE_BATTLE = -2 +BOARDCODE_SPACE = -3 +BOARDCODE_DIFF_GROUP = -4 +BOARDCODE_PENDING_INVITE = -5 +BOARDCODE_IN_ELEVATOR = -6 +BOARDCODE_GROUPS_TOO_LARGE = -7 # JBS INVITE_ACCEPT_FAIL_GROUP_FULL = -1 class BoardingPartyBase: diff --git a/toontown/building/DistributedBBElevatorAI.py b/toontown/building/DistributedBBElevatorAI.py index 41abeccd..8e2095d9 100755 --- a/toontown/building/DistributedBBElevatorAI.py +++ b/toontown/building/DistributedBBElevatorAI.py @@ -3,7 +3,7 @@ import DistributedBossElevatorAI class DistributedBBElevatorAI(DistributedBossElevatorAI.DistributedBossElevatorAI): - def __init__(self, air, bldg, zone, antiShuffle = 0, minLaff = 0): - DistributedBossElevatorAI.DistributedBossElevatorAI.__init__(self, air, bldg, zone, antiShuffle=antiShuffle, minLaff=0) + def __init__(self, air, bldg, zone, antiShuffle = 0): + DistributedBossElevatorAI.DistributedBossElevatorAI.__init__(self, air, bldg, zone, antiShuffle=antiShuffle) self.type = ELEVATOR_BB self.countdownTime = ElevatorData[self.type]['countdown'] \ No newline at end of file diff --git a/toontown/building/DistributedBoardingParty.py b/toontown/building/DistributedBoardingParty.py index 1da48700..c8267316 100755 --- a/toontown/building/DistributedBoardingParty.py +++ b/toontown/building/DistributedBoardingParty.py @@ -198,17 +198,10 @@ class DistributedBoardingParty(DistributedObject.DistributedObject, BoardingPart self.groupInviteePanel = None return - def postInviteNotQualify(self, avId, reason, elevatorId): + def postInviteNotQualify(self, avId, reason): messenger.send('updateGroupStatus') rejectText = '' - minLaff = TTLocalizer.BoardingMore - if elevatorId: - elevator = base.cr.doId2do.get(elevatorId) - if elevator: - minLaff = elevator.minLaff if avId == localAvatar.doId: - if reason == BoardingPartyBase.BOARDCODE_MINLAFF: - rejectText = TTLocalizer.BoardingInviteMinLaffInviter % minLaff if reason == BoardingPartyBase.BOARDCODE_PROMOTION: rejectText = TTLocalizer.BoardingInvitePromotionInviter else: @@ -217,8 +210,6 @@ class DistributedBoardingParty(DistributedObject.DistributedObject, BoardingPart avatarNameText = avatar.name else: avatarNameText = '' - if reason == BoardingPartyBase.BOARDCODE_MINLAFF: - rejectText = TTLocalizer.BoardingInviteMinLaffInvitee % (avatarNameText, minLaff) if reason == BoardingPartyBase.BOARDCODE_PROMOTION: rejectText = TTLocalizer.BoardingInvitePromotionInvitee % avatarNameText if reason == BoardingPartyBase.BOARDCODE_BATTLE: @@ -229,8 +220,8 @@ class DistributedBoardingParty(DistributedObject.DistributedObject, BoardingPart rejectText = TTLocalizer.BoardingInviteePendingIvite % avatarNameText if reason == BoardingPartyBase.BOARDCODE_IN_ELEVATOR: rejectText = TTLocalizer.BoardingInviteeInElevator % avatarNameText - if reason == BoardingPartyBase.BOARDCODE_GROUPS_TO_LARGE: # JBS - rejectText = TTLocalizer.BoardingGroupsToLarge % avatarNameText + if reason == BoardingPartyBase.BOARDCODE_GROUPS_TOO_LARGE: # JBS + rejectText = TTLocalizer.BoardingGroupsTooLarge % avatarNameText if self.inviterPanels.isInvitingPanelIdCorrect(avId) or avId == localAvatar.doId: self.inviterPanels.destroyInvitingPanel() self.showMe(rejectText) @@ -316,23 +307,8 @@ class DistributedBoardingParty(DistributedObject.DistributedObject, BoardingPart avatarText += secondLastName + ' ' + TTLocalizer.And + ' ' + lastName return avatarText - - if reason == BoardingPartyBase.BOARDCODE_MINLAFF: - self.notify.debug("%s 's group cannot board because it does not have enough laff points." % leaderId) - elevator = base.cr.doId2do.get(elevatorId) - if elevator: - minLaffPoints = elevator.minLaff - else: - minLaffPoints = TTLocalizer.BoardingMore - if leaderId in avatarsFailingRequirements: - rejectText = TTLocalizer.BoardcodeMinLaffLeader % minLaffPoints - else: - avatarNameText = getAvatarText(avatarsFailingRequirements) - if len(avatarsFailingRequirements) == 1: - rejectText = TTLocalizer.BoardcodeMinLaffNonLeaderSingular % (avatarNameText, minLaffPoints) - else: - rejectText = TTLocalizer.BoardcodeMinLaffNonLeaderPlural % (avatarNameText, minLaffPoints) - elif reason == BoardingPartyBase.BOARDCODE_PROMOTION: + + if reason == BoardingPartyBase.BOARDCODE_PROMOTION: self.notify.debug("%s 's group cannot board because it does not have enough promotion merits." % leaderId) if leaderId in avatarsFailingRequirements: rejectText = TTLocalizer.BoardcodePromotionLeader diff --git a/toontown/building/DistributedBoardingPartyAI.py b/toontown/building/DistributedBoardingPartyAI.py index 678a162a..8110179d 100755 --- a/toontown/building/DistributedBoardingPartyAI.py +++ b/toontown/building/DistributedBoardingPartyAI.py @@ -105,17 +105,17 @@ class DistributedBoardingPartyAI(DistributedObjectAI.DistributedObjectAI, Boardi merger = False if invitee and invitee.battleId != 0: reason = BoardingPartyBase.BOARDCODE_BATTLE - self.sendUpdateToAvatarId(inviterId, 'postInviteNotQualify', [inviteeId, reason, 0]) + self.sendUpdateToAvatarId(inviterId, 'postInviteNotQualify', [inviteeId, reason]) self.sendUpdateToAvatarId(inviteeId, 'postMessageInvitationFailed', [inviterId]) return if self.hasPendingInvite(inviteeId): reason = BoardingPartyBase.BOARDCODE_PENDING_INVITE - self.sendUpdateToAvatarId(inviterId, 'postInviteNotQualify', [inviteeId, reason, 0]) + self.sendUpdateToAvatarId(inviterId, 'postInviteNotQualify', [inviteeId, reason]) self.sendUpdateToAvatarId(inviteeId, 'postMessageInvitationFailed', [inviterId]) return if self.__isInElevator(inviteeId): reason = BoardingPartyBase.BOARDCODE_IN_ELEVATOR - self.sendUpdateToAvatarId(inviterId, 'postInviteNotQualify', [inviteeId, reason, 0]) + self.sendUpdateToAvatarId(inviterId, 'postInviteNotQualify', [inviteeId, reason]) self.sendUpdateToAvatarId(inviteeId, 'postMessageInvitationFailed', [inviterId]) return if self.hasActiveGroup(inviteeId): @@ -127,7 +127,7 @@ class DistributedBoardingPartyAI(DistributedObjectAI.DistributedObjectAI, Boardi # group merge already requested? if self.hasPendingInvite(inviteeLeaderId): reason = BoardingPartyBase.BOARDCODE_PENDING_INVITE - self.sendUpdateToAvatarId(inviterId, 'postInviteNotQualify', [inviteeId, reason, 0]) + self.sendUpdateToAvatarId(inviterId, 'postInviteNotQualify', [inviteeId, reason]) self.sendUpdateToAvatarId(inviteeId, 'postMessageInvitationFailed', [inviterId]) return @@ -137,13 +137,13 @@ class DistributedBoardingPartyAI(DistributedObjectAI.DistributedObjectAI, Boardi inviteeId = inviteeLeaderId merger = True else: - reason = BoardingPartyBase.BOARDCODE_GROUPS_TO_LARGE - self.sendUpdateToAvatarId(inviterId, 'postInviteNotQualify', [inviteeId, reason, 0]) + reason = BoardingPartyBase.BOARDCODE_GROUPS_TOO_LARGE + self.sendUpdateToAvatarId(inviterId, 'postInviteNotQualify', [inviteeId, reason]) self.sendUpdateToAvatarId(inviteeId, 'postMessageInvitationFailed', [inviterId]) return else: reason = BoardingPartyBase.BOARDCODE_DIFF_GROUP - self.sendUpdateToAvatarId(inviterId, 'postInviteNotQualify', [inviteeId, reason, 0]) + self.sendUpdateToAvatarId(inviterId, 'postInviteNotQualify', [inviteeId, reason]) self.sendUpdateToAvatarId(inviteeId, 'postMessageInvitationFailed', [inviterId]) return # Lets see what the invitee is currently doing @@ -152,20 +152,16 @@ class DistributedBoardingPartyAI(DistributedObjectAI.DistributedObjectAI, Boardi # I know there is an unexpected issue here when we are merging groups... lets think about this really hard.. if len(self.elevatorIdList) == 1: if inviteeOkay: - if inviteeOkay == REJECT_MINLAFF: - reason = BoardingPartyBase.BOARDCODE_MINLAFF - elif inviteeOkay == REJECT_PROMOTION: + if inviteeOkay == REJECT_PROMOTION: reason = BoardingPartyBase.BOARDCODE_PROMOTION - self.sendUpdateToAvatarId(inviterId, 'postInviteNotQualify', [inviteeId, reason, self.elevatorIdList[0]]) + self.sendUpdateToAvatarId(inviterId, 'postInviteNotQualify', [inviteeId, reason]) return else: inviterOkay = self.checkBoard(inviterId, self.elevatorIdList[0]) if inviterOkay: - if inviterOkay == REJECT_MINLAFF: - reason = BoardingPartyBase.BOARDCODE_MINLAFF - elif inviterOkay == REJECT_PROMOTION: + if inviterOkay == REJECT_PROMOTION: reason = BoardingPartyBase.BOARDCODE_PROMOTION - self.sendUpdateToAvatarId(inviterId, 'postInviteNotQualify', [inviterId, reason, self.elevatorIdList[0]]) + self.sendUpdateToAvatarId(inviterId, 'postInviteNotQualify', [inviterId, reason]) return # Is the inviter already in the avIdDict? It follows they either must be in a group or have a pending invite... if inviterId in self.avIdDict: @@ -277,8 +273,8 @@ class DistributedBoardingPartyAI(DistributedObjectAI.DistributedObjectAI, Boardi return # Lets make sure we still CAN merge them in if ((len(self.getGroupMemberList(leaderId)) + len(self.getGroupMemberList(inviteeId))) > self.maxSize): - reason = BoardingPartyBase.BOARDCODE_GROUPS_TO_LARGE - self.sendUpdateToAvatarId(inviterId, 'postInviteNotQualify', [inviteeId, reason, 0]) + reason = BoardingPartyBase.BOARDCODE_GROUPS_TOO_LARGE + self.sendUpdateToAvatarId(inviterId, 'postInviteNotQualify', [inviteeId, reason]) self.sendUpdateToAvatarId(inviteeId, 'postMessageInvitationFailed', [inviterId]) return group = self.groupListDict.get(leaderId) @@ -365,9 +361,7 @@ class DistributedBoardingPartyAI(DistributedObjectAI.DistributedObjectAI, Boardi avatar = simbase.air.doId2do.get(avId) if avatar: if elevator.checkBoard(avatar) != 0: - if elevator.checkBoard(avatar) == REJECT_MINLAFF: - boardOkay = BoardingPartyBase.BOARDCODE_MINLAFF - elif elevator.checkBoard(avatar) == REJECT_PROMOTION: + if elevator.checkBoard(avatar) == REJECT_PROMOTION: boardOkay = BoardingPartyBase.BOARDCODE_PROMOTION avatarsFailingRequirements.append(avId) elif avatar.battleId != 0: @@ -382,8 +376,6 @@ class DistributedBoardingPartyAI(DistributedObjectAI.DistributedObjectAI, Boardi boardOkay = BoardingPartyBase.BOARDCODE_SPACE if boardOkay != BoardingPartyBase.BOARDCODE_OKAY: self.notify.debug('Something is wrong with the group board request') - if boardOkay == BoardingPartyBase.BOARDCODE_MINLAFF: - self.notify.debug('An avatar did not meet the elevator laff requirements') if boardOkay == BoardingPartyBase.BOARDCODE_PROMOTION: self.notify.debug('An avatar did not meet the elevator promotion requirements') elif boardOkay == BoardingPartyBase.BOARDCODE_BATTLE: diff --git a/toontown/building/DistributedBossElevatorAI.py b/toontown/building/DistributedBossElevatorAI.py index 2ec7354f..a020c10d 100755 --- a/toontown/building/DistributedBossElevatorAI.py +++ b/toontown/building/DistributedBossElevatorAI.py @@ -12,8 +12,8 @@ from toontown.suit import DistributedSellbotBossAI class DistributedBossElevatorAI(DistributedElevatorExtAI.DistributedElevatorExtAI): - def __init__(self, air, bldg, zone, antiShuffle = 0, minLaff = 0): - DistributedElevatorExtAI.DistributedElevatorExtAI.__init__(self, air, bldg, numSeats=8, antiShuffle=antiShuffle, minLaff=minLaff) + def __init__(self, air, bldg, zone, antiShuffle = 0): + DistributedElevatorExtAI.DistributedElevatorExtAI.__init__(self, air, bldg, numSeats=8, antiShuffle=antiShuffle) self.zone = zone self.type = ELEVATOR_VP self.countdownTime = ElevatorData[self.type]['countdown'] @@ -53,8 +53,6 @@ class DistributedBossElevatorAI(DistributedElevatorExtAI.DistributedElevatorExtA def checkBoard(self, av): dept = ToontownGlobals.cogHQZoneId2deptIndex(self.zone) - if av.hp < self.minLaff: - return REJECT_MINLAFF if not av.readyForPromotion(dept): return REJECT_PROMOTION return 0 diff --git a/toontown/building/DistributedBuilding.py b/toontown/building/DistributedBuilding.py index 20cd8820..8793aeb6 100755 --- a/toontown/building/DistributedBuilding.py +++ b/toontown/building/DistributedBuilding.py @@ -435,7 +435,9 @@ class DistributedBuilding(DistributedObject.DistributedObject): return dnaStore = self.cr.playGame.dnaStore level = int(self.difficulty / 2) + 1 - suitNP = dnaStore.findNode('suit_landmark_' + chr(self.track) + str(level)) + if level > 5: + self.notify.warning('Level is bigger than 5: %s' % level) + suitNP = dnaStore.findNode('suit_landmark_' + chr(self.track) + str(min(level, 5))) zoneId = dnaStore.getZoneFromBlockNumber(self.block) newParentNP = base.cr.playGame.hood.loader.zoneDict[zoneId] suitBuildingNP = suitNP.copyTo(newParentNP) diff --git a/toontown/building/DistributedBuildingAI.py b/toontown/building/DistributedBuildingAI.py index dc7f4092..00f463d1 100755 --- a/toontown/building/DistributedBuildingAI.py +++ b/toontown/building/DistributedBuildingAI.py @@ -23,7 +23,7 @@ from toontown.cogdominium.CogdoLayout import CogdoLayout from toontown.cogdominium.SuitPlannerCogdoInteriorAI import SuitPlannerCogdoInteriorAI from toontown.hood import ZoneUtil from toontown.toonbase.ToontownGlobals import ToonHall - +from toontown.toonbase import ToontownGlobals class DistributedBuildingAI(DistributedObjectAI.DistributedObjectAI): def __init__(self, air, blockNumber, zoneId, trophyMgr): @@ -292,6 +292,7 @@ class DistributedBuildingAI(DistributedObjectAI.DistributedObjectAI): self.air.writeServerEvent('buildingDefeated', t, '%s|%s|%s|%s' % (self.track, self.numFloors, self.zoneId, victorList)) if toon is not None: self.air.questManager.toonKilledBuilding(toon, self.track, self.difficulty, self.numFloors, self.zoneId, 0) + toon.addStat(ToontownGlobals.STAT_BLDG) for i in xrange(0, 4): victor = victorList[i] if (victor is None) or (victor not in self.air.doId2do): @@ -329,6 +330,7 @@ class DistributedBuildingAI(DistributedObjectAI.DistributedObjectAI): if toon != None: self.air.questManager.toonKilledBuilding(toon, self.track, self.difficulty, 5, self.zoneId, 1) + toon.addStat(ToontownGlobals.STAT_COGDO) continue victorList.extend([None, None, None, None]) diff --git a/toontown/building/DistributedCFOElevatorAI.py b/toontown/building/DistributedCFOElevatorAI.py index 7a14bda3..4f75cd8d 100755 --- a/toontown/building/DistributedCFOElevatorAI.py +++ b/toontown/building/DistributedCFOElevatorAI.py @@ -3,7 +3,7 @@ import DistributedBossElevatorAI class DistributedCFOElevatorAI(DistributedBossElevatorAI.DistributedBossElevatorAI): - def __init__(self, air, bldg, zone, antiShuffle = 0, minLaff = 0): - DistributedBossElevatorAI.DistributedBossElevatorAI.__init__(self, air, bldg, zone, antiShuffle=antiShuffle, minLaff=minLaff) + def __init__(self, air, bldg, zone, antiShuffle = 0): + DistributedBossElevatorAI.DistributedBossElevatorAI.__init__(self, air, bldg, zone, antiShuffle=antiShuffle) self.type = ELEVATOR_CFO self.countdownTime = ElevatorData[self.type]['countdown'] diff --git a/toontown/building/DistributedCJElevatorAI.py b/toontown/building/DistributedCJElevatorAI.py index 1c63809f..d3821778 100755 --- a/toontown/building/DistributedCJElevatorAI.py +++ b/toontown/building/DistributedCJElevatorAI.py @@ -3,7 +3,7 @@ import DistributedBossElevatorAI class DistributedCJElevatorAI(DistributedBossElevatorAI.DistributedBossElevatorAI): - def __init__(self, air, bldg, zone, antiShuffle = 0, minLaff = 0): - DistributedBossElevatorAI.DistributedBossElevatorAI.__init__(self, air, bldg, zone, antiShuffle=antiShuffle, minLaff=minLaff) + def __init__(self, air, bldg, zone, antiShuffle = 0): + DistributedBossElevatorAI.DistributedBossElevatorAI.__init__(self, air, bldg, zone, antiShuffle=antiShuffle) self.type = ELEVATOR_CJ self.countdownTime = ElevatorData[self.type]['countdown'] diff --git a/toontown/building/DistributedClubElevatorAI.py b/toontown/building/DistributedClubElevatorAI.py index d4366360..9be1de41 100755 --- a/toontown/building/DistributedClubElevatorAI.py +++ b/toontown/building/DistributedClubElevatorAI.py @@ -41,8 +41,8 @@ class DistributedClubElevatorAI(DistributedElevatorFSMAI.DistributedElevatorFSMA id = 0 DoBlockedRoomCheck = simbase.config.GetBool('elevator-blocked-rooms-check', 1) - def __init__(self, air, lawOfficeId, bldg, avIds, markerId = None, numSeats = 4, antiShuffle = 0, minLaff = 0): - DistributedElevatorFSMAI.DistributedElevatorFSMAI.__init__(self, air, bldg, numSeats, antiShuffle = antiShuffle, minLaff = minLaff) + def __init__(self, air, lawOfficeId, bldg, avIds, markerId = None, numSeats = 4, antiShuffle = 0): + DistributedElevatorFSMAI.DistributedElevatorFSMAI.__init__(self, air, bldg, numSeats, antiShuffle = antiShuffle) FSM.__init__(self, 'ElevatorFloor_%s_FSM' % self.id) self.type = ElevatorConstants.ELEVATOR_COUNTRY_CLUB self.countdownTime = ElevatorConstants.ElevatorData[self.type]['countdown'] @@ -291,8 +291,6 @@ class DistributedClubElevatorAI(DistributedElevatorFSMAI.DistributedElevatorFSMA return self.latch def checkBoard(self, av): - if av.hp < self.minLaff: - return ElevatorConstants.REJECT_MINLAFF if self.DoBlockedRoomCheck and self.bldg: if hasattr(self.bldg, 'blockedRooms'): if self.bldg.blockedRooms: diff --git a/toontown/building/DistributedElevator.py b/toontown/building/DistributedElevator.py index 46c4047f..83b244fc 100755 --- a/toontown/building/DistributedElevator.py +++ b/toontown/building/DistributedElevator.py @@ -344,8 +344,6 @@ class DistributedElevator(DistributedObject.DistributedObject): if hasattr(base.localAvatar, 'elevatorNotifier'): if reason == REJECT_SHUFFLE: base.localAvatar.elevatorNotifier.showMe(TTLocalizer.ElevatorHoppedOff) - elif reason == REJECT_MINLAFF: - base.localAvatar.elevatorNotifier.showMe(TTLocalizer.ElevatorMinLaff % self.minLaff) elif reason == REJECT_PROMOTION: base.localAvatar.elevatorNotifier.showMe(TTLocalizer.BossElevatorRejectMessage) doneStatus = {'where': 'reject'} @@ -496,12 +494,6 @@ class DistributedElevator(DistributedObject.DistributedObject): def getAntiShuffle(self): return self.antiShuffle - def setMinLaff(self, minLaff): - self.minLaff = minLaff - - def getMinLaff(self): - return self.minLaff - def storeToonTrack(self, avId, track): self.clearToonTrack(avId) self.__toonTracks[avId] = track diff --git a/toontown/building/DistributedElevatorAI.py b/toontown/building/DistributedElevatorAI.py index 4bbfbc82..93151702 100755 --- a/toontown/building/DistributedElevatorAI.py +++ b/toontown/building/DistributedElevatorAI.py @@ -11,7 +11,7 @@ from direct.directnotify import DirectNotifyGlobal class DistributedElevatorAI(DistributedObjectAI.DistributedObjectAI): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedElevatorAI') - def __init__(self, air, bldg, numSeats = 4, antiShuffle = 0, minLaff = 0): + def __init__(self, air, bldg, numSeats = 4, antiShuffle = 0): DistributedObjectAI.DistributedObjectAI.__init__(self, air) self.type = ELEVATOR_NORMAL self.countdownTime = ElevatorData[self.type]['countdown'] @@ -19,7 +19,6 @@ class DistributedElevatorAI(DistributedObjectAI.DistributedObjectAI): self.bldgDoId = bldg.getDoId() self.seats = [] self.setAntiShuffle(antiShuffle) - self.setMinLaff(minLaff) if self.antiShuffle: if not hasattr(simbase.air, 'elevatorTripId'): simbase.air.elevatorTripId = 1 @@ -145,11 +144,9 @@ class DistributedElevatorAI(DistributedObjectAI.DistributedObjectAI): return self.fsm.getCurrentState().getName() def avIsOKToBoard(self, av): - return av.hp > self.minLaff and self.accepting + return self.accepting def checkBoard(self, av): - if av.hp < self.minLaff: - return REJECT_MINLAFF return 0 def requestBoard(self, *args): @@ -288,10 +285,4 @@ class DistributedElevatorAI(DistributedObjectAI.DistributedObjectAI): self.antiShuffle = antiShuffle def getAntiShuffle(self): - return self.antiShuffle - - def setMinLaff(self, minLaff): - self.minLaff = minLaff - - def getMinLaff(self): - return self.minLaff + return self.antiShuffle \ No newline at end of file diff --git a/toontown/building/DistributedElevatorExtAI.py b/toontown/building/DistributedElevatorExtAI.py index b399545a..58f3b041 100755 --- a/toontown/building/DistributedElevatorExtAI.py +++ b/toontown/building/DistributedElevatorExtAI.py @@ -11,8 +11,8 @@ from direct.directnotify import DirectNotifyGlobal class DistributedElevatorExtAI(DistributedElevatorAI.DistributedElevatorAI): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedElevatorExtAI') - def __init__(self, air, bldg, numSeats = 4, antiShuffle = 0, minLaff = 0): - DistributedElevatorAI.DistributedElevatorAI.__init__(self, air, bldg, numSeats, antiShuffle=antiShuffle, minLaff=minLaff) + def __init__(self, air, bldg, numSeats = 4, antiShuffle = 0): + DistributedElevatorAI.DistributedElevatorAI.__init__(self, air, bldg, numSeats, antiShuffle=antiShuffle) self.anyToonsBailed = 0 self.boardingParty = None return diff --git a/toontown/building/DistributedElevatorFSM.py b/toontown/building/DistributedElevatorFSM.py index fc272c03..e24c6110 100755 --- a/toontown/building/DistributedElevatorFSM.py +++ b/toontown/building/DistributedElevatorFSM.py @@ -316,8 +316,6 @@ class DistributedElevatorFSM(DistributedObject.DistributedObject, FSM): if hasattr(base.localAvatar, 'elevatorNotifier'): if reason == REJECT_SHUFFLE: base.localAvatar.elevatorNotifier.showMe(TTLocalizer.ElevatorHoppedOff) - elif reason == REJECT_MINLAFF: - base.localAvatar.elevatorNotifier.showMe(TTLocalizer.ElevatorMinLaff % self.minLaff) elif reason == REJECT_PROMOTION: base.localAvatar.elevatorNotifier.showMe(TTLocalizer.BossElevatorRejectMessage) elif reason == REJECT_BLOCKED_ROOM: @@ -475,11 +473,5 @@ class DistributedElevatorFSM(DistributedObject.DistributedObject, FSM): def getAntiShuffle(self): return self.antiShuffle - def setMinLaff(self, minLaff): - self.minLaff = minLaff - - def getMinLaff(self): - return self.minLaff - def getDestName(self): return None diff --git a/toontown/building/DistributedElevatorFSMAI.py b/toontown/building/DistributedElevatorFSMAI.py index 41e3760e..3284a81b 100755 --- a/toontown/building/DistributedElevatorFSMAI.py +++ b/toontown/building/DistributedElevatorFSMAI.py @@ -38,7 +38,7 @@ class DistributedElevatorFSMAI(DistributedObjectAI.DistributedObjectAI, FSM): 'Opening'] } id = 0 - def __init__(self, air, bldg, numSeats = 4, antiShuffle = 0, minLaff = 0): + def __init__(self, air, bldg, numSeats = 4, antiShuffle = 0): DistributedObjectAI.DistributedObjectAI.__init__(self, air) FSM.__init__(self, 'Elevator_%s_FSM' % self.id) self.type = ELEVATOR_NORMAL @@ -50,7 +50,6 @@ class DistributedElevatorFSMAI(DistributedObjectAI.DistributedObjectAI, FSM): self.seats.append(None) self.accepting = 0 self.setAntiShuffle(antiShuffle) - self.setMinLaff(minLaff) if self.antiShuffle: if not hasattr(simbase.air, 'elevatorTripId'): simbase.air.elevatorTripId = 1 @@ -146,13 +145,9 @@ class DistributedElevatorFSMAI(DistributedObjectAI.DistributedObjectAI, FSM): return self.state def avIsOKToBoard(self, av): - if av.hp > self.minLaff: - pass return self.accepting def checkBoard(self, av): - if av.hp < self.minLaff: - return REJECT_MINLAFF return 0 def requestBoard(self, *args): @@ -274,10 +269,4 @@ class DistributedElevatorFSMAI(DistributedObjectAI.DistributedObjectAI, FSM): self.antiShuffle = antiShuffle def getAntiShuffle(self): - return self.antiShuffle - - def setMinLaff(self, minLaff): - self.minLaff = minLaff - - def getMinLaff(self): - return self.minLaff + return self.antiShuffle \ No newline at end of file diff --git a/toontown/building/DistributedElevatorFloorAI.py b/toontown/building/DistributedElevatorFloorAI.py index e039a8db..32b9ea53 100755 --- a/toontown/building/DistributedElevatorFloorAI.py +++ b/toontown/building/DistributedElevatorFloorAI.py @@ -40,8 +40,8 @@ class DistributedElevatorFloorAI(DistributedElevatorFSMAI.DistributedElevatorFSM 'Opening'] } id = 0 - def __init__(self, air, lawOfficeId, bldg, avIds, markerId = None, numSeats = 4, antiShuffle = 0, minLaff = 0): - DistributedElevatorFSMAI.DistributedElevatorFSMAI.__init__(self, air, bldg, numSeats, antiShuffle = antiShuffle, minLaff = minLaff) + def __init__(self, air, lawOfficeId, bldg, avIds, markerId = None, numSeats = 4, antiShuffle = 0): + DistributedElevatorFSMAI.DistributedElevatorFSMAI.__init__(self, air, bldg, numSeats, antiShuffle = antiShuffle) FSM.__init__(self, 'ElevatorFloor_%s_FSM' % self.id) self.type = ELEVATOR_STAGE self.countdownTime = ElevatorData[self.type]['countdown'] diff --git a/toontown/building/DistributedSuitInterior.py b/toontown/building/DistributedSuitInterior.py index 3eab5c17..8d7688dd 100755 --- a/toontown/building/DistributedSuitInterior.py +++ b/toontown/building/DistributedSuitInterior.py @@ -10,6 +10,7 @@ from direct.distributed import DistributedObject from direct.fsm import State from toontown.battle import BattleBase from toontown.hood import ZoneUtil +from toontown.suit import SuitDNA class DistributedSuitInterior(DistributedObject.DistributedObject): id = 0 @@ -249,14 +250,15 @@ class DistributedSuitInterior(DistributedObject.DistributedObject): def __playElevator(self, ts, name, callback): SuitHs = [] SuitPositions = [] + DeptName = SuitDNA.suitDeptFilenames[self.suits[0].style.dept] if self.floorModel: self.floorModel.removeNode() if self.currentFloor == 0: - self.floorModel = loader.loadModel('phase_7/models/modules/suit_interior') + self.floorModel = loader.loadModel('phase_7/models/modules/suit_interior_%s' % DeptName) SuitHs = self.BottomFloor_SuitHs SuitPositions = self.BottomFloor_SuitPositions elif self.currentFloor == self.numFloors - 1: - self.floorModel = loader.loadModel('phase_7/models/modules/boss_suit_office') + self.floorModel = loader.loadModel('phase_7/models/modules/boss_suit_office_%s' % DeptName) SuitHs = self.BossOffice_SuitHs SuitPositions = self.BossOffice_SuitPositions else: diff --git a/toontown/building/DistributedVPElevatorAI.py b/toontown/building/DistributedVPElevatorAI.py index 1cc97feb..d172f705 100755 --- a/toontown/building/DistributedVPElevatorAI.py +++ b/toontown/building/DistributedVPElevatorAI.py @@ -3,7 +3,7 @@ import DistributedBossElevatorAI class DistributedVPElevatorAI(DistributedBossElevatorAI.DistributedBossElevatorAI): - def __init__(self, air, bldg, zone, antiShuffle = 0, minLaff = 0): - DistributedBossElevatorAI.DistributedBossElevatorAI.__init__(self, air, bldg, zone, antiShuffle=antiShuffle, minLaff=minLaff) + def __init__(self, air, bldg, zone, antiShuffle = 0): + DistributedBossElevatorAI.DistributedBossElevatorAI.__init__(self, air, bldg, zone, antiShuffle=antiShuffle) self.type = ELEVATOR_VP self.countdownTime = ElevatorData[self.type]['countdown'] diff --git a/toontown/building/ElevatorConstants.py b/toontown/building/ElevatorConstants.py index cc914bbb..dd483ed1 100755 --- a/toontown/building/ElevatorConstants.py +++ b/toontown/building/ElevatorConstants.py @@ -11,11 +11,10 @@ ELEVATOR_COUNTRY_CLUB = 8 ELEVATOR_FIELD = 9 REJECT_NOREASON = 0 REJECT_SHUFFLE = 1 -REJECT_MINLAFF = 2 -REJECT_NOSEAT = 3 -REJECT_PROMOTION = 4 -REJECT_BLOCKED_ROOM = 5 -REJECT_BOARDINGPARTY = 6 +REJECT_NOSEAT = 2 +REJECT_PROMOTION = 3 +REJECT_BLOCKED_ROOM = 4 +REJECT_BOARDINGPARTY = 5 MAX_GROUP_BOARDING_TIME = 6.0 ElevatorData = {ELEVATOR_NORMAL: {'openTime': 2.0, 'closeTime': 2.0, diff --git a/toontown/catalog/CatalogAccessoryItem.py b/toontown/catalog/CatalogAccessoryItem.py index 8f1121c9..d8f371e1 100755 --- a/toontown/catalog/CatalogAccessoryItem.py +++ b/toontown/catalog/CatalogAccessoryItem.py @@ -15,45 +15,6 @@ class CatalogAccessoryItem(CatalogItem.CatalogItem): self.isSpecial = isSpecial CatalogItem.CatalogItem.makeNewItem(self) - def storedInTrunk(self): - return 1 - - def notOfferedTo(self, avatar): - article = AccessoryTypes[self.accessoryType][ATArticle] - if article in [AHat, - AGlasses, - ABackpack, - AShoes]: - return 0 - forBoys = article in [ABoysHat, - ABoysGlasses, - ABoysBackpack, - ABoysShoes] - if avatar.getStyle().getGender() == 'm': - return not forBoys - else: - return forBoys - - def forBoysOnly(self): - article = AccessoryTypes[self.accessoryType][ATArticle] - if article in [ABoysHat, - ABoysGlasses, - ABoysBackpack, - ABoysShoes]: - return 1 - else: - return 0 - - def forGirlsOnly(self): - article = AccessoryTypes[self.accessoryType][ATArticle] - if article in [AGirlsHat, - AGirlsGlasses, - AGirlsBackpack, - AGirlsShoes]: - return 1 - else: - return 0 - def getPurchaseLimit(self): return 1 @@ -64,8 +25,6 @@ class CatalogAccessoryItem(CatalogItem.CatalogItem): return 1 if avatar.mailboxContents.count(self) != 0: return 1 - if self in avatar.awardMailboxContents or self in avatar.onAwardOrder: - return 1 str = AccessoryTypes[self.accessoryType][ATString] if self.isHat(): defn = ToonDNA.HatStyles[str] @@ -122,10 +81,7 @@ class CatalogAccessoryItem(CatalogItem.CatalogItem): def recordPurchase(self, avatar, optional): if avatar.isTrunkFull(): - if avatar.getMaxAccessories() == 0: - return ToontownGlobals.P_NoTrunk - else: - return ToontownGlobals.P_NoRoomForItem + return ToontownGlobals.P_NoRoomForItem str = AccessoryTypes[self.accessoryType][ATString] if self.isHat(): defn = ToonDNA.HatStyles[str] @@ -218,6 +174,9 @@ class CatalogAccessoryItem(CatalogItem.CatalogItem): avatar.d_catalogGenAccessories() return ToontownGlobals.P_ItemAvailable + def getDeliveryTime(self): + return 60 + def getPicture(self, avatar): model = self.loadModel() spin = 1 @@ -239,7 +198,6 @@ class CatalogAccessoryItem(CatalogItem.CatalogItem): model.setColorScale(color, 1) if needsAlpha: model.setTransparency(1) - return def loadModel(self): modelPath = self.getFilename() @@ -264,17 +222,14 @@ class CatalogAccessoryItem(CatalogItem.CatalogItem): from toontown.toontowngui import TTDialog avatar = base.localAvatar accessoriesOnOrder = 0 - for item in avatar.onOrder + avatar.mailboxContents: - if item.storedInTrunk(): + for item in avatar.onOrder + avatar.mailboxContents + avatar.onGiftOrder: + if hasattr(item, 'isHat'): accessoriesOnOrder += 1 if avatar.isTrunkFull(accessoriesOnOrder): self.requestPurchaseCleanup() buttonCallback = PythonUtil.Functor(self.__handleFullPurchaseDialog, phone, callback) - if avatar.getMaxAccessories() == 0: - text = TTLocalizer.CatalogPurchaseNoTrunk - else: - text = TTLocalizer.CatalogPurchaseTrunkFull + text = TTLocalizer.CatalogPurchaseTrunkFull self.dialog = TTDialog.TTDialog(style=TTDialog.YesNo, text=text, text_wordwrap=15, command=buttonCallback) self.dialog.show() else: @@ -305,25 +260,19 @@ class CatalogAccessoryItem(CatalogItem.CatalogItem): return TTLocalizer.CatalogAcceptShoes elif retcode == ToontownGlobals.P_NoRoomForItem: return TTLocalizer.CatalogAcceptTrunkFull - elif retcode == ToontownGlobals.P_NoTrunk: - return TTLocalizer.CatalogAcceptNoTrunk return CatalogItem.CatalogItem.getAcceptItemErrorText(self, retcode) def isHat(self): - article = AccessoryTypes[self.accessoryType][ATArticle] - return article in [AHat, ABoysHat, AGirlsHat] + return AccessoryTypes[self.accessoryType][ATArticle] == AHat def areGlasses(self): - article = AccessoryTypes[self.accessoryType][ATArticle] - return article in [AGlasses, ABoysGlasses, AGirlsGlasses] + return AccessoryTypes[self.accessoryType][ATArticle] == AGlasses def isBackpack(self): - article = AccessoryTypes[self.accessoryType][ATArticle] - return article in [ABackpack, ABoysBackpack, AGirlsBackpack] + return AccessoryTypes[self.accessoryType][ATArticle] == ABackpack def areShoes(self): - article = AccessoryTypes[self.accessoryType][ATArticle] - return article in [AShoes, ABoysShoes, AGirlsShoes] + return AccessoryTypes[self.accessoryType][ATArticle] == AShoes def output(self, store = -1): return 'CatalogAccessoryItem(%s%s)' % (self.accessoryType, self.formatOptionalData(store)) diff --git a/toontown/catalog/CatalogAccessoryItemGlobals.py b/toontown/catalog/CatalogAccessoryItemGlobals.py index 764c3da4..f72765a5 100755 --- a/toontown/catalog/CatalogAccessoryItemGlobals.py +++ b/toontown/catalog/CatalogAccessoryItemGlobals.py @@ -7,15 +7,6 @@ AHat = 0 AGlasses = 1 ABackpack = 2 AShoes = 3 -ABoysHat = 4 -ABoysGlasses = 5 -ABoysBackpack = 6 -ABoysShoes = 7 -AGirlsHat = 8 -AGirlsGlasses = 9 -AGirlsBackpack = 10 -AGirlsShoes = 11 -APriceTest = 5 APriceBasic = 250 APriceBasicPlus = 400 APriceCool = 800 @@ -28,7 +19,7 @@ AccessoryTypes = {101: (AHat, 'hsf1', APriceCool, 5), - 103: (AGirlsHat, + 103: (AHat, 'hrb1', APriceBasic, 1), @@ -40,11 +31,11 @@ AccessoryTypes = {101: (AHat, 'hsf3', APriceCool, 0), - 106: (AGirlsHat, + 106: (AHat, 'hrb2', APriceBasicPlus, 3), - 107: (AGirlsHat, + 107: (AHat, 'hrb3', APriceBasicPlus, 0), @@ -96,7 +87,7 @@ AccessoryTypes = {101: (AHat, 'hpb1', APriceBasicPlus, 6), - 120: (ABoysHat, + 120: (AHat, 'hcr1', 10000, 5), @@ -132,23 +123,23 @@ AccessoryTypes = {101: (AHat, 'hst1', APriceBasicPlus, 1), - 129: (AGirlsHat, + 129: (AHat, 'hsu1', APriceCool, 1), - 130: (AGirlsHat, + 130: (AHat, 'hrb4', APriceBasic, 1), - 131: (AGirlsHat, + 131: (AHat, 'hrb5', APriceBasicPlus, 4), - 132: (AGirlsHat, + 132: (AHat, 'hrb6', APriceBasic, 2), - 133: (AGirlsHat, + 133: (AHat, 'hrb7', APriceBasicPlus, 6), @@ -156,7 +147,7 @@ AccessoryTypes = {101: (AHat, 'hat1', APriceCool, 2), - 135: (AGirlsHat, + 135: (AHat, 'hhd1', APriceCool, 2), @@ -188,11 +179,11 @@ AccessoryTypes = {101: (AHat, 'hft2', APriceCool, 6), - 143: (ABoysHat, + 143: (AHat, 'hhd2', APriceCool, 3), - 144: (AGirlsHat, + 144: (AHat, 'hpc1', APriceCool, 5), @@ -208,7 +199,7 @@ AccessoryTypes = {101: (AHat, 'hat2', APriceCool, 2), - 148: (AGirlsHat, + 148: (AHat, 'htr1', 10000, 3), @@ -280,7 +271,7 @@ AccessoryTypes = {101: (AHat, 'hby1', APriceAwesome, 5), - 166: (AGirlsHat, + 166: (AHat, 'hrb8', APriceBasicPlus, 6), @@ -292,7 +283,7 @@ AccessoryTypes = {101: (AHat, 'hbb7', APriceBasic, 6), - 169: (AGirlsHat, + 169: (AHat, 'hrb9', APriceBasicPlus, 6), @@ -300,7 +291,7 @@ AccessoryTypes = {101: (AHat, 'hwt2', APriceAwesome, 4), - 171: (AGirlsHat, + 171: (AHat, 'hhw1', APriceBasicPlus, 7), @@ -412,11 +403,11 @@ AccessoryTypes = {101: (AHat, 'gsr1', APriceBasicPlus, 5), - 223: (ABoysGlasses, + 223: (AGlasses, 'ghw1', - APriceTest, + APriceBasic, 0), - 224: (ABoysGlasses, + 224: (AGlasses, 'ghw2', APriceBasic, 7), @@ -564,11 +555,11 @@ AccessoryTypes = {101: (AHat, 'scs1', APriceBasicPlus, 6), - 405: (ABoysShoes, + 405: (AShoes, 'swt1', APriceBasicPlus, 1), - 406: (AGirlsShoes, + 406: (AShoes, 'smj1', APriceBasicPlus, 1), @@ -604,11 +595,11 @@ AccessoryTypes = {101: (AHat, 'sht1', APriceAwesome, 4), - 415: (AGirlsShoes, + 415: (AShoes, 'smj2', APriceBasicPlus, 3), - 416: (AGirlsShoes, + 416: (AShoes, 'smj3', APriceBasicPlus, 4), @@ -664,7 +655,7 @@ AccessoryTypes = {101: (AHat, 'slf1', APriceBasicPlus, 3), - 430: (AGirlsShoes, + 430: (AShoes, 'smj4', APriceBasicPlus, 2), diff --git a/toontown/catalog/CatalogBeanItem.py b/toontown/catalog/CatalogBeanItem.py index b2f09b66..5ae535e7 100755 --- a/toontown/catalog/CatalogBeanItem.py +++ b/toontown/catalog/CatalogBeanItem.py @@ -16,9 +16,7 @@ class CatalogBeanItem(CatalogItem.CatalogItem): return 0 def reachedPurchaseLimit(self, avatar): - if self in avatar.onOrder or self in avatar.mailboxContents or self in avatar.onGiftOrder or self in avatar.awardMailboxContents or self in avatar.onAwardOrder: - return 1 - return 0 + return self in avatar.onOrder or self in avatar.mailboxContents or self in avatar.onGiftOrder def getAcceptItemErrorText(self, retcode): if retcode == ToontownGlobals.P_ItemAvailable: diff --git a/toontown/catalog/CatalogChatItem.py b/toontown/catalog/CatalogChatItem.py index 51f2e523..9e5f8ecc 100755 --- a/toontown/catalog/CatalogChatItem.py +++ b/toontown/catalog/CatalogChatItem.py @@ -15,9 +15,7 @@ class CatalogChatItem(CatalogItem.CatalogItem): return 1 def reachedPurchaseLimit(self, avatar): - if self in avatar.onOrder or self in avatar.mailboxContents or self in avatar.onGiftOrder or self in avatar.awardMailboxContents or self in avatar.onAwardOrder: - return 1 - return avatar.customMessages.count(self.customIndex) != 0 + return self in avatar.onOrder or self in avatar.mailboxContents or self in avatar.onGiftOrder or avatar.customMessages.count(self.customIndex) != 0 def getTypeName(self): return TTLocalizer.ChatTypeName diff --git a/toontown/catalog/CatalogClothingItem.py b/toontown/catalog/CatalogClothingItem.py index 6e4eae93..b1373508 100755 --- a/toontown/catalog/CatalogClothingItem.py +++ b/toontown/catalog/CatalogClothingItem.py @@ -291,7 +291,7 @@ ClothingTypes = {101: (ABoysShirt, 'bss1', 40), 1818: (AGirlsSkirt, 'sa_gs20', 5000), 1819: (AGirlsSkirt, 'sa_gs21', 5000), 1820: (AShirt, 'sa_ss55', 5000), - 1821: (AShirt, 'weed', 5000)} + 1821: (AShirt, 'flannel', 300)} class CatalogClothingItem(CatalogItem.CatalogItem): @@ -338,8 +338,6 @@ class CatalogClothingItem(CatalogItem.CatalogItem): return 1 if avatar.mailboxContents.count(self) != 0: return 1 - if self in avatar.awardMailboxContents or self in avatar.onAwardOrder: - return 1 str = ClothingTypes[self.clothingType][CTString] dna = avatar.getStyle() if self.isShirt(): @@ -374,7 +372,7 @@ class CatalogClothingItem(CatalogItem.CatalogItem): return TTLocalizer.ClothingArticleNames[article] def recordPurchase(self, avatar, optional): - if avatar.isClosetFull(): + if avatar.isClosetFull(1): return ToontownGlobals.P_NoRoomForItem str = ClothingTypes[self.clothingType][CTString] dna = avatar.getStyle() @@ -419,7 +417,7 @@ class CatalogClothingItem(CatalogItem.CatalogItem): return ToontownGlobals.P_ItemAvailable def getDeliveryTime(self): - return 1 + return 60 def getPicture(self, avatar): from toontown.toon import Toon diff --git a/toontown/catalog/CatalogEmoteItem.py b/toontown/catalog/CatalogEmoteItem.py index 7e139110..2849a58c 100755 --- a/toontown/catalog/CatalogEmoteItem.py +++ b/toontown/catalog/CatalogEmoteItem.py @@ -17,7 +17,7 @@ class CatalogEmoteItem(CatalogItem.CatalogItem): return 1 def reachedPurchaseLimit(self, avatar): - if self in avatar.onOrder or self in avatar.mailboxContents or self in avatar.onGiftOrder or self in avatar.awardMailboxContents or self in avatar.onAwardOrder: + if self in avatar.onOrder or self in avatar.mailboxContents or self in avatar.onGiftOrder: return 1 if self.emoteIndex >= len(avatar.emoteAccess): return 0 diff --git a/toontown/catalog/CatalogFurnitureItem.py b/toontown/catalog/CatalogFurnitureItem.py index 3e5716e8..089c403a 100755 --- a/toontown/catalog/CatalogFurnitureItem.py +++ b/toontown/catalog/CatalogFurnitureItem.py @@ -17,11 +17,14 @@ FLRug = 4 FLPainting = 8 FLOnTable = 16 FLIsTable = 32 -FLPhone = 64 -FLBillboard = 128 -FLTrunk = 256 -FLBoysOnly = 512 -FLGirlsOnly = 1024 +FLBillboard = 64 +FLPhone = 128 +FLCrate = 256 +FLChair = 512 +FLTV = 1024 +FLTrunk = 2048 +FLBoysOnly = 4096 +FLGirlsOnly = 8192 furnitureColors = [ (0.792, 0.353, 0.29, 1.0), (0.176, 0.592, 0.439, 1.0), @@ -70,20 +73,36 @@ for closetId, maxClothes in ClosetToClothes.items(): ClothesToCloset[maxClothes] += (closetId,) MaxClosetIds = (508, 518) -MaxTrunkIds = (4000, 4010) TvToPosScale = { 1530: ((-1.15, -0.5, 1.1), (2.5, 1.7, 1.4)), - 1531: ((-2.3, -0.2, 1.6), (5, 5, 5)), - 1532: ((-7, -0.2, 1.8), (15, 10, 8.5)) + 1531: ((-2.3, -0.2, 2.522), (5, 3.75, 3.187)), + 1532: ((-7, -0.2, 2.8), (15, 10, 7.8)) +} + +ChairToPosHpr = { + 100: ((0, -3.9, 0.88), (180, 0, 0), (0, -4.9, 0), -3.0), + 105: ((0, -3.9, 0.88), (180, 0, 0), (0, -4.9, 0), -3.0), + 110: ((0, -1.6, 0.5), (180, 0, 0), (0, -2.6, 0), 0.0), + 120: ((0, -1.6, 0.5), (180, 0, 0), (0, -2.6, 0), 0.0), + 130: ((0, -2.8, 0.5), (180, 0, 0), (0, -3.8, 0), -2.0), + 140: ((0, -1.6, 0.5), (180, 0, 0), (0, -2.6, 0), 0.0), + 145: ((0, -2.1, 0.2), (180, 0, 0), (0, -3.1, 0), 0.0), + 160: ((-1.7, 0, 0.9), (90, 0, 0), (-2.7, 0, 0), 0.0), + 170: ((0, 1.8, 0.4), (0, 0, 0), (0, 2.8, 0), 0.0), + 700: ((0, -1.2, 0.5), (180, 0, 0), (0, -2.2, 0), 0.0), + 705: ((0, -1.2, 0.5), (180, 0, 0), (0, -2.2, 0), 0.0), + 710: ((0, -1.1, 0.4), (180, 0, 0), (0, -2.1, 0), 0.0), + 715: ((0, -1.1, 0.4), (180, 0, 0), (0, -2.1, 0), 0.0), + 720: ((0, -2.7, 0.2), (180, 0, 0), (0, -3.7, 0), -3.0) } FurnitureTypes = { 100: ('phase_5.5/models/estate/chairA', # Model None, # Color None, # Color Options - 80), # Base Price - # Flags + 80, # Base Price + FLChair), # Flags # Scale 105: ('phase_5.5/models/estate/chairAdesat', None, @@ -93,27 +112,33 @@ FurnitureTypes = { 3: (('**/cushion*', furnitureColors[3]), ('**/arm*', furnitureColors[3])), 4: (('**/cushion*', furnitureColors[4]), ('**/arm*', furnitureColors[4])), 5: (('**/cushion*', furnitureColors[5]), ('**/arm*', furnitureColors[5]))}, - 160), + 160, + FLChair), 110: ('phase_3.5/models/modules/chair', None, None, - 40), + 40, + FLChair), 120: ('phase_5.5/models/estate/deskChair', None, None, - 60), + 60, + FLChair), 130: ('phase_5.5/models/estate/BugRoomChair', None, None, - 160), + 160, + FLChair), 140: ('phase_5.5/models/estate/UWlobsterChair', None, None, - 200), + 200, + FLChair), 145: ('phase_5.5/models/estate/UWlifeSaverChair', None, None, - 200), + 200, + FLChair), 150: ('phase_5.5/models/estate/West_saddleStool2', None, None, @@ -121,11 +146,13 @@ FurnitureTypes = { 160: ('phase_5.5/models/estate/West_nativeChair', None, None, - 160), + 160, + FLChair), 170: ('phase_5.5/models/estate/cupcakeChair', None, None, - 240), + 240, + FLChair), 200: ('phase_5.5/models/estate/regular_bed', None, None, @@ -415,7 +442,8 @@ FurnitureTypes = { 700: ('phase_3.5/models/modules/couch_1person', None, None, - 230), + 230, + FLChair), 705: ('phase_5.5/models/estate/couch_1personDesat', None, {0: (('**/*couch', furnitureColors[0]),), @@ -424,11 +452,13 @@ FurnitureTypes = { 3: (('**/*couch', furnitureColors[3]),), 4: (('**/*couch', furnitureColors[4]),), 5: (('**/*couch', furnitureColors[5]),)}, - 460), + 460, + FLChair), 710: ('phase_3.5/models/modules/couch_2person', None, None, - 230), + 230, + FLChair), 715: ('phase_5.5/models/estate/couch_2personDesat', None, {0: (('**/*couch', furnitureColors[0]),), @@ -437,11 +467,13 @@ FurnitureTypes = { 3: (('**/*couch', furnitureColors[3]),), 4: (('**/*couch', furnitureColors[4]),), 5: (('**/*couch', furnitureColors[5]),)}, - 460), + 460, + FLChair), 720: ('phase_5.5/models/estate/West_HayCouch', None, None, - 420), + 420, + FLChair), 730: ('phase_5.5/models/estate/twinkieCouch', None, None, @@ -721,15 +753,18 @@ FurnitureTypes = { 1530: ('phase_5.5/models/estate/bugRoomTV', None, None, - 675), + 675, + FLTV), 1531: ('phase_5.5/models/estate/bugRoomTV_50inch', None, None, - 1250), + 1250, + FLTV), 1532: ('phase_5.5/models/estate/bugRoomTV_100inch', None, None, - 5000), + 5000, + FLTV), 1600: ('phase_5.5/models/estate/vaseA_short', None, None, @@ -892,7 +927,13 @@ FurnitureTypes = { None, None, 200, - FLPainting) + FLPainting), + 10040: ('phase_10/models/cashbotHQ/CBWoodCrate', + None, + None, + 0, + FLCrate, + 0.5) } class CatalogFurnitureItem(CatalogAtticItem.CatalogAtticItem): @@ -910,7 +951,7 @@ class CatalogFurnitureItem(CatalogAtticItem.CatalogAtticItem): return 1 def replacesExisting(self): - return self.getFlags() & (FLCloset | FLBank | FLTrunk) != 0 + return self.getFlags() & (FLCloset | FLBank) != 0 def hasExisting(self): return 1 @@ -920,16 +961,14 @@ class CatalogFurnitureItem(CatalogAtticItem.CatalogAtticItem): return TTLocalizer.FurnitureYourOldCloset elif self.getFlags() & FLBank: return TTLocalizer.FurnitureYourOldBank - elif self.getFlags() & FLTrunk: - return TTLocalizer.FurnitureYourOldTrunk else: return None return None def notOfferedTo(self, avatar): - if self.getFlags() & FLCloset or self.getFlags() & FLTrunk: + if self.getFlags() & FLCloset: decade = self.furnitureType - self.furnitureType % 10 - forBoys = (decade == 500 or decade == 4000) + forBoys = decade == 500 if avatar.getStyle().getGender() == 'm': return not forBoys else: @@ -955,9 +994,6 @@ class CatalogFurnitureItem(CatalogAtticItem.CatalogAtticItem): def isDeletable(self): return self.getFlags() & (FLBank | FLCloset | FLPhone | FLTrunk) == 0 - def getMaxAccessories(self): - return ToontownGlobals.MaxAccessories - def getMaxBankMoney(self): return BankToMoney.get(self.furnitureType) @@ -975,11 +1011,6 @@ class CatalogFurnitureItem(CatalogAtticItem.CatalogAtticItem): return 1 if self in avatar.onOrder or self in avatar.mailboxContents: return 1 - if self.getFlags() & FLTrunk: - if self.getMaxAccessories() <= avatar.getMaxAccessories(): - return 1 - if self in avatar.onOrder or self in avatar.mailboxContents: - return 1 return 0 def getTypeName(self): @@ -1007,29 +1038,25 @@ class CatalogFurnitureItem(CatalogAtticItem.CatalogAtticItem): def isGift(self): if self.getEmblemPrices(): return 0 - if self.getFlags() & (FLCloset | FLBank | FLTrunk): + if self.getFlags() & (FLCloset | FLBank): return 0 else: return 1 def recordPurchase(self, avatar, optional): house, retcode = self.getHouseInfo(avatar) - self.giftTag = None if retcode >= 0: if self.getFlags() & FLCloset: if avatar.getMaxClothes() > self.getMaxClothes(): return ToontownGlobals.P_AlreadyOwnBiggerCloset avatar.b_setMaxClothes(self.getMaxClothes()) - if self.getFlags() & FLTrunk: - avatar.b_setMaxAccessories(self.getMaxAccessories()) if self.getFlags() & FLBank: avatar.b_setMaxBankMoney(self.getMaxBankMoney()) - return retcode house.addAtticItem(self) return retcode def getDeliveryTime(self): - return 1 + return 24 * 60 def getPicture(self, avatar): model = self.loadModel(animate=0) @@ -1084,38 +1111,7 @@ class CatalogFurnitureItem(CatalogAtticItem.CatalogAtticItem): model.setScale(scale) model.flattenLight() - if animate and self.furnitureType in TvToPosScale: - pos = TvToPosScale[self.furnitureType] - screen = NodePath(CardMaker('tv-screen').generate()) - - model.find('**/toonTownBugTV_screen').hide() - screen.reparentTo(model) - screen.setScale(*pos[1]) - screen.setPos(*pos[0]) - self.startVideo(screen) - return model - - def startVideo(self, model, file=None): - files = glob.glob('user/videos/*.mp4') - - if not files: - model.setTextureOff(TextureStage.getDefault()) - model.setColor(0.3, 0.3, 0.3, 1.0) - return - - if file is None: - file = random.randint(0, len(files) - 1) - elif file >= len(files): - file = 0 - - movie = loader.loadTexture(files[file]) - sound = loader.loadSfx(files[file]) - movie.synchronizeTo(sound) - model.setTexture(movie) - model.setTexScale(TextureStage.getDefault(), movie.getTexScale()) - self.videoSequence = Sequence(SoundInterval(sound, volume=1.0), Func(self.startVideo, model, file + 1)) - self.videoSequence.start() def decodeDatagram(self, di, versionNumber, store): CatalogAtticItem.CatalogAtticItem.decodeDatagram(self, di, versionNumber, store) @@ -1210,29 +1206,6 @@ def getAllBanks(): return list -def get50ItemTrunk(avatar, duplicateItems): - if config.GetBool('want-accessories', 1): - if avatar.getStyle().getGender() == 'm': - index = 0 - else: - index = 1 - trunkId = MaxTrunkIds[index] - item = CatalogFurnitureItem(trunkId) - if item in avatar.onOrder or item in avatar.mailboxContents: - return None - return item - # If we get here, we probably don't want accessories yet. - return None - - -def getMaxTrunks(): - list = [] - for trunkId in MaxTrunkIds: - list.append(CatalogFurnitureItem(trunkId)) - - return list - - def getAllFurnitures(index): list = [] colors = FurnitureTypes[index][FTColorOptions] diff --git a/toontown/catalog/CatalogGardenItem.py b/toontown/catalog/CatalogGardenItem.py index 1d340357..fba420ad 100755 --- a/toontown/catalog/CatalogGardenItem.py +++ b/toontown/catalog/CatalogGardenItem.py @@ -22,11 +22,6 @@ class CatalogGardenItem(CatalogItem.CatalogItem): else: return 100 - def reachedPurchaseLimit(self, avatar): - if self in avatar.onOrder or self in avatar.mailboxContents or self in avatar.onGiftOrder or self in avatar.awardMailboxContents or self in avatar.onAwardOrder: - return 1 - return 0 - def getAcceptItemErrorText(self, retcode): if retcode == ToontownGlobals.P_ItemAvailable: return TTLocalizer.CatalogAcceptGarden @@ -39,17 +34,16 @@ class CatalogGardenItem(CatalogItem.CatalogItem): return TTLocalizer.GardenTypeName def getName(self): - name = GardenGlobals.Specials[self.gardenIndex]['photoName'] - return name + return GardenGlobals.Specials[self.gardenIndex]['photoName'] def recordPurchase(self, avatar, optional): if avatar: avatar.addGardenItem(self.gardenIndex, self.numItems) - if 1: - return ToontownGlobals.P_ItemAvailable + return ToontownGlobals.P_ItemAvailable def getPicture(self, avatar): photoModel = GardenGlobals.Specials[self.gardenIndex]['photoModel'] + if 'photoAnimation' in GardenGlobals.Specials[self.gardenIndex]: modelPath = photoModel + GardenGlobals.Specials[self.gardenIndex]['photoAnimation'][0] animationName = GardenGlobals.Specials[self.gardenIndex]['photoAnimation'][1] @@ -75,7 +69,6 @@ class CatalogGardenItem(CatalogItem.CatalogItem): self.model.setScale(photoScale) self.hasPicture = True return (frame, None) - return None def cleanupPicture(self): CatalogItem.CatalogItem.cleanupPicture(self) @@ -126,7 +119,7 @@ class CatalogGardenItem(CatalogItem.CatalogItem): def getDeliveryTime(self): if self.gardenIndex == GardenGlobals.GardenAcceleratorSpecial: - return 1 + return 24 * 60 else: return 0 diff --git a/toontown/catalog/CatalogGardenStarterItem.py b/toontown/catalog/CatalogGardenStarterItem.py index 876bbafe..d33e5903 100755 --- a/toontown/catalog/CatalogGardenStarterItem.py +++ b/toontown/catalog/CatalogGardenStarterItem.py @@ -15,7 +15,7 @@ class CatalogGardenStarterItem(CatalogItem.CatalogItem): def getPurchaseLimit(self): return 0 - def reachedPurchaseLimit(self, avatar): + def reachedPurchaseLimit(self, avatar): if self in avatar.onOrder or self in avatar.mailboxContents or self in avatar.onGiftOrder or self in avatar.awardMailboxContents or self in avatar.onAwardOrder or hasattr(avatar, 'gardenStarted') and avatar.getGardenStarted(): return 1 return 0 @@ -31,13 +31,13 @@ class CatalogGardenStarterItem(CatalogItem.CatalogItem): def recordPurchase(self, avatar, optional): if avatar: - estate = simbase.air.estateManager.toon2estate.get(avatar) + self.notify.debug('rental -- has avatar') + estate = simbase.air.estateManager._lookupEstate(avatar) if estate: - av = simbase.air.doId2do.get(avatar) - if av: - av.b_setGardenStarted(True) - print('garden saved') - estate.placeStarterGarden(avatar) + self.notify.debug('rental -- has estate') + estate.placeStarterGarden(avatar.doId) + else: + self.notify.warning('rental -- something not there') return ToontownGlobals.P_ItemAvailable def getPicture(self, avatar): diff --git a/toontown/catalog/CatalogGenerator.py b/toontown/catalog/CatalogGenerator.py index 8160f265..618f01d2 100755 --- a/toontown/catalog/CatalogGenerator.py +++ b/toontown/catalog/CatalogGenerator.py @@ -1,7 +1,7 @@ from direct.directnotify import DirectNotifyGlobal import CatalogItem import CatalogItemList -from CatalogFurnitureItem import CatalogFurnitureItem, nextAvailableCloset, nextAvailableBank, getAllClosets, get50ItemCloset, getMaxClosets, get50ItemTrunk, getAllBanks +from CatalogFurnitureItem import CatalogFurnitureItem, nextAvailableCloset, nextAvailableBank, getAllClosets, get50ItemCloset, getMaxClosets, getAllBanks from CatalogAnimatedFurnitureItem import CatalogAnimatedFurnitureItem from CatalogClothingItem import CatalogClothingItem, getAllClothes from CatalogChatItem import CatalogChatItem, getChatRange @@ -12,8 +12,8 @@ from CatalogMouldingItem import CatalogMouldingItem, getAllMouldings from CatalogWainscotingItem import CatalogWainscotingItem, getAllWainscotings from CatalogWindowItem import CatalogWindowItem from CatalogPoleItem import nextAvailablePole, getAllPoles -from CatalogTankItem import nextAvailableTank, getAllTanks from CatalogPetTrickItem import CatalogPetTrickItem, getAllPetTricks +from CatalogTankItem import nextAvailableTank, getAllTanks from CatalogGardenItem import CatalogGardenItem from CatalogToonStatueItem import CatalogToonStatueItem from CatalogRentalItem import CatalogRentalItem @@ -26,7 +26,7 @@ from toontown.toonbase import ToontownGlobals import types import random import time -from panda3d.core import * +from pandac.PandaModules import * MetaItems = {100: getAllClothes(101, 102, 103, 104, 105, 106, 107, 108, 109, 109, 111, 115, 201, 202, 203, 204, 205, 206, 207, 208, 209, 209, 211, 215), 300: getAllClothes(301, 302, 303, 304, 305, 308, 401, 403, 404, 405, 407, 451, 452, 453), 2000: getChatRange(0, 1999), @@ -41,25 +41,20 @@ MetaItems = {100: getAllClothes(101, 102, 103, 104, 105, 106, 107, 108, 109, 109 2921: getChatRange(12050, 12099), 2930: getChatRange(13000, 13099), 2940: getChatRange(14000, 14099), - 3000: getWallpapers(1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100), 3010: getWallpapers(2200, 2300, 2400, 2500, 2600, 2700, 2800), 3020: getWallpapers(2900, 3000, 3100, 3200, 3300, 3400, 3500, 3600), 3030: getWallpapers(3700, 3800, 3900), - 3500: getAllWainscotings(1000, 1010), 3510: getAllWainscotings(1020), 3520: getAllWainscotings(1030), 3530: getAllWainscotings(1040), - 4000: getFloorings(1000, 1010, 1020, 1030, 1040, 1050, 1060, 1070, 1080, 1090, 1100), 4010: getFloorings(1110, 1120, 1130), 4020: getFloorings(1140, 1150, 1160, 1170, 1180, 1190), - 4500: getAllMouldings(1000, 1010), 4510: getAllMouldings(1020, 1030, 1040), 4520: getAllMouldings(1070), - 5000: getAllPetTricks()} MetaItemChatKeysSold = (2000, 2010, @@ -401,7 +396,29 @@ MonthlySchedule = ((7, 15, 8, 15, + 2010, + 2010, ((4, 2940),)), + (9, + 1, + 9, + 30, + (CatalogGardenItem(135, 1),)), + (1, + 1, + 1, + 31, + (CatalogGardenItem(135, 1),)), + (4, + 1, + 4, + 30, + (CatalogGardenItem(135, 1),)), + (6, + 1, + 6, + 30, + (CatalogGardenItem(135, 1),)), (6, 26, 7, @@ -460,16 +477,22 @@ MonthlySchedule = ((7, 9, 7, 15, + 2010, + 2010, (CatalogClothingItem(1751, 0),)), (6, 14, 7, 15, + 2010, + 2010, (CatalogClothingItem(1754, 0), CatalogClothingItem(1755, 0), CatalogClothingItem(1756, 0))), (7, 21, 8, 17, + 2010, + 2010, (CatalogClothingItem(1749, 0), CatalogClothingItem(1750, 0), CatalogClothingItem(1757, 0), @@ -478,6 +501,8 @@ MonthlySchedule = ((7, 25, 9, 21, + 2010, + 2010, (CatalogClothingItem(1763, 0),)), (6, 5, @@ -488,44 +513,49 @@ MonthlySchedule = ((7, 1, 12, 31, - ( - CatalogGardenItem(100, 1), + (CatalogGardenItem(100, 1), CatalogGardenItem(101, 1), CatalogGardenItem(103, 1), CatalogGardenItem(104, 1), CatalogToonStatueItem(105, endPoseIndex=108), CatalogRentalItem(1, 2880, 1000), - CatalogRentalItem(2, 2890, 1000), CatalogGardenStarterItem(), - CatalogNametagItem(0), CatalogFurnitureItem(1530), CatalogFurnitureItem(1531), - CatalogFurnitureItem(1532), + CatalogFurnitureItem(1532), + CatalogNametagItem(15), + CatalogNametagItem(16), + CatalogNametagItem(17), + CatalogClothingItem(1608, 0, True), CatalogClothingItem(1605, 0, True), CatalogClothingItem(1602, 0, True), + CatalogClothingItem(1607, 0, True), CatalogClothingItem(1604, 0, True), CatalogClothingItem(1601, 0, True), + CatalogClothingItem(1606, 0, True), CatalogClothingItem(1603, 0, True), CatalogClothingItem(1600, 0, True), + CatalogEmoteItem(25, True), + CatalogEmoteItem(26, True), CatalogEmoteItem(20, True), CatalogEmoteItem(21, True), CatalogEmoteItem(22, True), CatalogEmoteItem(23, True), CatalogEmoteItem(24, True), - CatalogEmoteItem(25, True), - CatalogEmoteItem(26, True), - CatalogNametagItem(15, True), - CatalogNametagItem(16, True), - CatalogNametagItem(17, True))), + CatalogClothingItem(1821, 0, True))), (5, 26, 6, 30, + 2013, + 2013, (CatalogAccessoryItem(175),)), (8, 27, 9, 5, + 2013, + 2013, ((3, 2900), CatalogChatItem(10003), CatalogClothingItem(1001, 0), @@ -575,6 +605,8 @@ MonthlySchedule = ((7, 3, 9, 12, + 2013, + 2013, ((3, 2910), CatalogFurnitureItem(680), CatalogFurnitureItem(681), @@ -609,6 +641,8 @@ MonthlySchedule = ((7, 20, 9, 19, + 2013, + 2013, (CatalogAccessoryItem(101), CatalogAccessoryItem(103), CatalogAccessoryItem(117), @@ -805,11 +839,7 @@ WeeklySchedule = ((100, 4000, 4500, CatalogFurnitureItem(110), - CatalogFurnitureItem(100), - nextAvailablePole, - nextAvailableCloset, - nextAvailableBank, - nextAvailableTank), + CatalogFurnitureItem(100)), (100, (5, 2000), CatalogFurnitureItem(1420), @@ -830,10 +860,7 @@ WeeklySchedule = ((100, CatalogAnimatedFurnitureItem(490), CatalogFurnitureItem(1000), CatalogClothingItem(117, 0), - CatalogClothingItem(217, 0), - nextAvailableCloset, - nextAvailableBank, - nextAvailableTank), + CatalogClothingItem(217, 0)), (100, (5, 2000), CatalogFurnitureItem(1430), @@ -853,11 +880,7 @@ WeeklySchedule = ((100, 4000, 4500, CatalogFurnitureItem(1210), - CatalogClothingItem(409, 0), - nextAvailablePole, - nextAvailableCloset, - nextAvailableBank, - nextAvailableTank), + CatalogClothingItem(409, 0)), (300, (5, 2000), CatalogEmoteItem(13), @@ -876,10 +899,7 @@ WeeklySchedule = ((100, CatalogFurnitureItem(910), CatalogFurnitureItem(1600), CatalogClothingItem(118, 0), - CatalogClothingItem(218, 0), - nextAvailableCloset, - nextAvailableBank, - nextAvailableTank), + CatalogClothingItem(218, 0)), (100, (5, 2000), 3000, @@ -896,11 +916,7 @@ WeeklySchedule = ((100, 3500, 4000, 4500, - CatalogFurnitureItem(620), - nextAvailablePole, - nextAvailableCloset, - nextAvailableBank, - nextAvailableTank), + CatalogFurnitureItem(620)), (300, (5, 2000), 3000, @@ -920,10 +936,7 @@ WeeklySchedule = ((100, CatalogFurnitureItem(630), CatalogFurnitureItem(1630), CatalogEmoteItem(11), - CatalogNametagItem(11), - nextAvailableCloset, - nextAvailableBank, - nextAvailableTank), + CatalogNametagItem(11)), (100, (2, 2000), (3, 2010), @@ -946,11 +959,7 @@ WeeklySchedule = ((100, CatalogFurnitureItem(120), CatalogClothingItem(120, 0), CatalogClothingItem(220, 0), - nextAvailablePole, - 5000, - nextAvailableCloset, - nextAvailableBank, - nextAvailableTank), + 5000), (100, (2, 2000), (3, 2010), @@ -971,10 +980,7 @@ WeeklySchedule = ((100, CatalogFurnitureItem(1120), CatalogFurnitureItem(930), CatalogFurnitureItem(1500), - CatalogEmoteItem(6), - nextAvailableCloset, - nextAvailableBank, - nextAvailableTank), + CatalogEmoteItem(6)), (300, (2, 2000), (3, 2010), @@ -997,7 +1003,6 @@ WeeklySchedule = ((100, CatalogFurnitureItem(940), CatalogClothingItem(121, 0), CatalogClothingItem(221, 0), - nextAvailablePole, 5000), (100, (2, 2000), @@ -1038,7 +1043,6 @@ WeeklySchedule = ((100, 4510, CatalogFurnitureItem(300), CatalogFurnitureItem(1220), - nextAvailablePole, 5000), (300, (2, 2000), @@ -1096,7 +1100,6 @@ WeeklySchedule = ((100, CatalogFurnitureItem(145), CatalogClothingItem(123, 0), CatalogClothingItem(224, 0), - nextAvailablePole, 5000), (100, (1, 2000), @@ -1137,8 +1140,7 @@ WeeklySchedule = ((100, 4520, CatalogWindowItem(90), CatalogClothingItem(124, 0), - CatalogClothingItem(411, 0), - nextAvailablePole), + CatalogClothingItem(411, 0)), (100, (1, 2000), (2, 2010), @@ -1184,7 +1186,6 @@ WeeklySchedule = ((100, 4020, 4520, CatalogFurnitureItem(1910), - nextAvailablePole, CatalogFurnitureItem(1000)), (300, (1, 2000), @@ -1236,7 +1237,6 @@ WeeklySchedule = ((100, 3530, 4020, 4520, - nextAvailablePole, CatalogWallpaperItem(3900), CatalogFurnitureItem(980), CatalogNametagItem(13)), @@ -1249,7 +1249,8 @@ WeeklySchedule = ((100, 4020, 4520, CatalogClothingItem(130, 0), - CatalogFurnitureItem(150)), + CatalogFurnitureItem(150), + CatalogNametagItem(14)), (100, (1, 2010), (2, 2020), @@ -1281,7 +1282,6 @@ WeeklySchedule = ((100, 3530, 4020, 4520, - nextAvailablePole, CatalogFurnitureItem(1930), CatalogFurnitureItem(670)), (300, @@ -1324,7 +1324,6 @@ WeeklySchedule = ((100, 3530, 4020, 4520, - nextAvailablePole, CatalogFurnitureItem(1940), CatalogWindowItem(130)), (300, @@ -1347,19 +1346,17 @@ WeeklySchedule = ((100, 4020, 4520, CatalogFurnitureItem(250), - CatalogFurnitureItem(1960), - nextAvailablePole), + CatalogFurnitureItem(1960)), Sale(CatalogFurnitureItem(210, 0), CatalogFurnitureItem(220, 0), CatalogFurnitureItem(1100), CatalogFurnitureItem(110), CatalogFurnitureItem(100), CatalogFurnitureItem(700), CatalogFurnitureItem(710), CatalogFurnitureItem(410), CatalogAnimatedFurnitureItem(490), CatalogFurnitureItem(1210), CatalogFurnitureItem(1200), CatalogFurnitureItem(800), CatalogFurnitureItem(1110), CatalogFurnitureItem(230), CatalogFurnitureItem(420), CatalogAnimatedFurnitureItem(480), CatalogFurnitureItem(120), CatalogFurnitureItem(1700), CatalogFurnitureItem(1120), CatalogFurnitureItem(430), CatalogAnimatedFurnitureItem(491), CatalogFurnitureItem(1130), CatalogFurnitureItem(130), CatalogFurnitureItem(300), CatalogFurnitureItem(1220), CatalogFurnitureItem(810), CatalogFurnitureItem(1230), CatalogFurnitureItem(310), CatalogFurnitureItem(1240), CatalogFurnitureItem(240), CatalogFurnitureItem(145), CatalogFurnitureItem(1725), CatalogFurnitureItem(140), CatalogFurnitureItem(950), CatalogFurnitureItem(1720)), Sale(CatalogClothingItem(116, 0), CatalogClothingItem(216, 0), CatalogClothingItem(408, 0), CatalogClothingItem(117, 0), CatalogClothingItem(217, 0), CatalogClothingItem(409, 0), CatalogClothingItem(118, 0), CatalogClothingItem(218, 0), CatalogClothingItem(410, 0), CatalogClothingItem(119, 0), CatalogClothingItem(219, 0), CatalogClothingItem(120, 0), CatalogClothingItem(220, 0), CatalogClothingItem(121, 0), CatalogClothingItem(221, 0), CatalogClothingItem(222, 0), CatalogClothingItem(123, 0), CatalogClothingItem(224, 0), CatalogClothingItem(411, 0), CatalogClothingItem(311, 0), CatalogClothingItem(310, 0)), Sale(CatalogWindowItem(40), CatalogWindowItem(70), CatalogWindowItem(50), CatalogWindowItem(60), CatalogWindowItem(80), CatalogWindowItem(100), CatalogWindowItem(90), CatalogWindowItem(110)), Sale(CatalogEmoteItem(5), CatalogEmoteItem(9), CatalogEmoteItem(13), CatalogEmoteItem(11), CatalogEmoteItem(6), CatalogEmoteItem(8), CatalogNametagItem(10)), - Sale(CatalogFurnitureItem(600), CatalogFurnitureItem(610), CatalogFurnitureItem(620), CatalogFurnitureItem(630), CatalogFurnitureItem(640), CatalogFurnitureItem(650), CatalogFurnitureItem(660), CatalogFurnitureItem(900), CatalogFurnitureItem(910), CatalogFurnitureItem(920), CatalogFurnitureItem(930), CatalogFurnitureItem(940), CatalogFurnitureItem(1000), CatalogFurnitureItem(1010), CatalogFurnitureItem(1020), CatalogFurnitureItem(1030), CatalogFurnitureItem(1400), CatalogFurnitureItem(1410), CatalogFurnitureItem(1420), CatalogFurnitureItem(1430), CatalogFurnitureItem(1440), CatalogFurnitureItem(1441), CatalogFurnitureItem(1442), CatalogFurnitureItem(1443), CatalogFurnitureItem(1500), CatalogFurnitureItem(1510), CatalogFurnitureItem(1520), CatalogFurnitureItem(1530), CatalogFurnitureItem(1531), CatalogFurnitureItem(1532), CatalogFurnitureItem(1600), CatalogFurnitureItem(1610), CatalogFurnitureItem(1620), CatalogFurnitureItem(1630), CatalogFurnitureItem(1640), CatalogFurnitureItem(1650), CatalogFurnitureItem(1660), CatalogFurnitureItem(1661), CatalogFurnitureItem(1710), CatalogFurnitureItem(1800), CatalogFurnitureItem(1810), CatalogFurnitureItem(1900), CatalogFurnitureItem(1910)), + Sale(CatalogFurnitureItem(600), CatalogFurnitureItem(610), CatalogFurnitureItem(620), CatalogFurnitureItem(630), CatalogFurnitureItem(640), CatalogFurnitureItem(650), CatalogFurnitureItem(660), CatalogFurnitureItem(900), CatalogFurnitureItem(910), CatalogFurnitureItem(920), CatalogFurnitureItem(930), CatalogFurnitureItem(940), CatalogFurnitureItem(1000), CatalogFurnitureItem(1010), CatalogFurnitureItem(1020), CatalogFurnitureItem(1030), CatalogFurnitureItem(1400), CatalogFurnitureItem(1410), CatalogFurnitureItem(1420), CatalogFurnitureItem(1430), CatalogFurnitureItem(1440), CatalogFurnitureItem(1441), CatalogFurnitureItem(1442), CatalogFurnitureItem(1443), CatalogFurnitureItem(1500), CatalogFurnitureItem(1510), CatalogFurnitureItem(1520), CatalogFurnitureItem(1530), CatalogFurnitureItem(1600), CatalogFurnitureItem(1531), CatalogFurnitureItem(1532), CatalogFurnitureItem(1610), CatalogFurnitureItem(1620), CatalogFurnitureItem(1630), CatalogFurnitureItem(1640), CatalogFurnitureItem(1650), CatalogFurnitureItem(1660), CatalogFurnitureItem(1661), CatalogFurnitureItem(1710), CatalogFurnitureItem(1800), CatalogFurnitureItem(1810), CatalogFurnitureItem(1900), CatalogFurnitureItem(1910)), (300, (1, 2020), (2, 2030), (3, 2040), - CatalogFurnitureItem(730), - nextAvailablePole), + CatalogFurnitureItem(730)), (100, (1, 2020), (2, 2030), @@ -1382,8 +1379,7 @@ WeeklySchedule = ((100, (1, 2020), (2, 2030), (3, 2040), - CatalogFurnitureItem(1140), - nextAvailablePole), + CatalogFurnitureItem(1140)), (100, (1, 2020), (2, 2030), @@ -1406,8 +1402,7 @@ WeeklySchedule = ((100, (2, 2040), (3, 2050), CatalogClothingItem(131, 0), - CatalogClothingItem(225, 0), - nextAvailablePole), + CatalogClothingItem(225, 0)), (300, (1, 2030), (2, 2040), @@ -1427,7 +1422,6 @@ WeeklySchedule = ((100, (1, 2030), (2, 2040), (3, 2050), - nextAvailablePole, CatalogEmoteItem(12), CatalogNametagItem(5)), (300, @@ -1451,8 +1445,7 @@ WeeklySchedule = ((100, (1, 2030), (2, 2040), (3, 2050), - CatalogFurnitureItem(1215), - nextAvailablePole), + CatalogFurnitureItem(1215)), (300, (1, 2030), (2, 2040), @@ -1472,17 +1465,19 @@ WeeklySchedule = ((100, (300, (1, 2030), (2, 2040), - (3, 2050), - nextAvailablePole)) + (3, 2050))) class CatalogGenerator: notify = DirectNotifyGlobal.directNotify.newCategory('CatalogGenerator') def __init__(self): self.__itemLists = {} + self.__releasedItemLists = {} - if config.GetBool('save-catalog-schedule', False): - self.outputSchedule('catalog-schedule.txt') + def getReleasedCatalogList(self, weekStart): + dayNumber = int(weekStart / (24 * 60)) + itemLists = self.__getReleasedItemLists(dayNumber, weekStart) + return itemLists def generateMonthlyCatalog(self, avatar, weekStart): dayNumber = int(weekStart / (24 * 60)) @@ -1512,25 +1507,24 @@ class CatalogGenerator: if nextAvailableCloset not in schedule: weeklyCatalog += self.__selectItem(avatar, nextAvailableCloset, monthlyCatalog, saleItem=0) - if nextAvailableBank not in schedule: - weeklyCatalog += self.__selectItem(avatar, nextAvailableBank, monthlyCatalog, saleItem=0) - + weeklyCatalog += self.__selectItem(avatar, nextAvailableBank, monthlyCatalog, saleItem = 0) if nextAvailableTank not in schedule: - weeklyCatalog += self.__selectItem(avatar, nextAvailableTank, monthlyCatalog, saleItem=0) + weeklyCatalog += self.__selectItem(avatar, nextAvailableTank, monthlyCatalog, saleItem = 0) + if nextAvailablePole not in schedule: + weeklyCatalog += self.__selectItem(avatar, nextAvailablePole, monthlyCatalog, saleItem = 0) + + def hasPetTrick(catalog): + for item in catalog: + if isinstance(item, CatalogPetTrickItem): + return 1 - weeklyCatalog += self.__selectItem(avatar, get50ItemTrunk, monthlyCatalog, saleItem=0) - if True: + return 0 - def hasPetTrick(catalog): - for item in catalog: - if isinstance(item, CatalogPetTrickItem): - return 1 + if not hasPetTrick(weeklyCatalog) and not hasPetTrick(avatar.weeklyCatalog) and not hasPetTrick(avatar.backCatalog): + self.notify.debug('Artificially adding pet trick to catalog') + weeklyCatalog += self.__selectItem(avatar, 5000, monthlyCatalog, saleItem=saleItem) - return 0 - - if not hasPetTrick(weeklyCatalog) and not hasPetTrick(avatar.weeklyCatalog) and not hasPetTrick(avatar.backCatalog): - weeklyCatalog += self.__selectItem(avatar, 5000, monthlyCatalog, saleItem=saleItem) self.notify.debug('Generated catalog: %s' % weeklyCatalog) return weeklyCatalog @@ -1559,12 +1553,45 @@ class CatalogGenerator: return backCatalog + def __getReleasedItemLists(self, dayNumber, weekStart): + itemLists = self.__releasedItemLists.get(dayNumber) + if itemLists != None: + return itemLists + else: + self.__releasedItemLists.clear() + testDaysAhead = simbase.config.GetInt('test-server-holiday-days-ahead', 0) + nowtuple = time.localtime(weekStart * 60 + testDaysAhead * 24 * 60 * 60) + year = nowtuple[0] + month = nowtuple[1] + day = nowtuple[2] + itemLists = [] + for monthlyItems in MonthlySchedule: + startMM = monthlyItems[0] + startDD = monthlyItems[1] + endMM = monthlyItems[2] + endDD = monthlyItems[3] + if len(monthlyItems) == 7: + startYYYY = monthlyItems[4] + endYYYY = monthlyItems[5] + list = monthlyItems[6] + else: + startYYYY = 1969 + endYYYY = year + list = monthlyItems[4] + pastStart = year > startYYYY or (year == startYYYY and (month > startMM or (month == startMM and day >= startDD))) + if pastStart: + itemLists.append(list) + + self.__releasedItemLists[dayNumber] = itemLists + return itemLists + def __getMonthlyItemLists(self, dayNumber, weekStart): itemLists = self.__itemLists.get(dayNumber) if itemLists != None: return itemLists - testDaysAhead = config.GetInt('test-server-holiday-days-ahead', 0) + testDaysAhead = simbase.config.GetInt('test-server-holiday-days-ahead', 0) nowtuple = time.localtime(weekStart * 60 + testDaysAhead * 24 * 60 * 60) + year = nowtuple[0] month = nowtuple[1] day = nowtuple[2] self.notify.debug('Generating seasonal itemLists for %s/%s.' % (month, day)) @@ -1574,9 +1601,16 @@ class CatalogGenerator: startDD = monthlyItems[1] endMM = monthlyItems[2] endDD = monthlyItems[3] - list = monthlyItems[4] - pastStart = month > startMM or (month == startMM and day >= startDD) - beforeEnd = month < endMM or (month == endMM and day <= endDD) + if len(monthlyItems) == 7: + startYYYY = monthlyItems[4] + endYYYY = monthlyItems[5] + list = monthlyItems[6] + else: + startYYYY = 1969 + endYYYY = year + list = monthlyItems[4] + pastStart = year >= startYYYY and (month > startMM or (month == startMM and day >= startDD)) + beforeEnd = year <= endYYYY and (month < endMM or (month == endMM and day <= endDD)) if endMM < startMM: if pastStart or beforeEnd: itemLists.append(list) @@ -1707,35 +1741,31 @@ class CatalogGenerator: def __recordSchedule(self, sched, weekCode, schedule): if isinstance(schedule, Sale): schedule = schedule.args - try: - for item in list(schedule): - if callable(item): - if item == nextAvailablePole: - item = getAllPoles() - elif item == nextAvailableCloset: - item = getAllClosets() - elif item == nextAvailableBank: - item = getAllBanks() - elif item == nextAvailableTank: - item = getAllTanks() - elif item == get50ItemCloset: - item = getMaxClosets() - elif item == get50ItemTrunk: - item = getMaxTrunks() - else: - self.notify.warning("Don't know how to interpret function " % repr(name)) - item = None - elif isinstance(item, types.TupleType): - item = item[1] - if isinstance(item, types.IntType): - item = MetaItems[item] - if isinstance(item, CatalogItem.CatalogItem): - self.__recordScheduleItem(sched, weekCode, None, item) - elif item != None: - for i in item: - self.__recordScheduleItem(sched, None, weekCode, i) - except: - print 'Wrong: %s' % schedule + for item in schedule: + if callable(item): + if item == nextAvailablePole: + item = getAllPoles() + elif item == nextAvailableCloset: + item = getAllClosets() + elif item == nextAvailableBank: + item = getAllBanks() + elif item == nextAvailableTank: + item == getAllTanks() + elif item == get50ItemCloset: + item = getMaxClosets() + else: + self.notify.warning("Don't know how to interpret function " % repr(name)) + item = None + elif isinstance(item, types.TupleType): + item = item[1] + if isinstance(item, types.IntType): + item = MetaItems[item] + if isinstance(item, CatalogItem.CatalogItem): + self.__recordScheduleItem(sched, weekCode, None, item) + elif item != None: + for i in item: + self.__recordScheduleItem(sched, None, weekCode, i) + return def __recordScheduleItem(self, sched, weekCode, maybeWeekCode, item): diff --git a/toontown/catalog/CatalogItem.py b/toontown/catalog/CatalogItem.py index 58c91f4d..f4633050 100755 --- a/toontown/catalog/CatalogItem.py +++ b/toontown/catalog/CatalogItem.py @@ -42,8 +42,8 @@ class CatalogItem: return def isAward(self): - result = self.specialEventId != 0 - return result + #result = self.specialEventId != 0 + return False def makeNewItem(self): pass @@ -78,9 +78,6 @@ class CatalogItem: def storedInCloset(self): return 0 - def storedInTrunk(self): - return 0 - def storedInAttic(self): return 0 @@ -196,6 +193,8 @@ class CatalogItem: return TTLocalizer.CatalogPurchaseGiftLimitReached elif retcode == ToontownGlobals.P_NotEnoughMoney: return TTLocalizer.CatalogPurchaseGiftNotEnoughMoney + elif retcode == ToontownGlobals.P_TooFast: + return TTLocalizer.CatalogPurchaseGiftTooFast else: return TTLocalizer.CatalogPurchaseGiftGeneralError % {'friend': '%s', 'error': retcode} @@ -277,9 +276,9 @@ class CatalogItem: x = di.getArg(STInt16, 10) y = di.getArg(STInt16, 10) z = di.getArg(STInt16, 100) - h = di.getArg(STInt8, 256.0 / 360.0) - p = di.getArg(STInt8, 256.0 / 360.0) - r = di.getArg(STInt8, 256.0 / 360.0) + h = di.getArg(STInt16, 256.0 / 360.0) + p = di.getArg(STInt16, 256.0 / 360.0) + r = di.getArg(STInt16, 256.0 / 360.0) self.posHpr = (x, y, z, @@ -287,7 +286,7 @@ class CatalogItem: p, r) if store & GiftTag: - self.giftTag = di.getString() + self.giftTag = di.getUint32() self.specialEventId = di.getUint8() def encodeDatagram(self, dg, store): @@ -297,9 +296,9 @@ class CatalogItem: dg.putArg(self.posHpr[0], STInt16, 10) dg.putArg(self.posHpr[1], STInt16, 10) dg.putArg(self.posHpr[2], STInt16, 100) - dg.putArg(self.posHpr[3], STInt8, 256.0 / 360.0) - dg.putArg(self.posHpr[4], STInt8, 256.0 / 360.0) - dg.putArg(self.posHpr[5], STInt8, 256.0 / 360.0) + dg.putArg(self.posHpr[3], STInt16, 256.0 / 360.0) + dg.putArg(self.posHpr[4], STInt16, 256.0 / 360.0) + dg.putArg(self.posHpr[5], STInt16, 256.0 / 360.0) if store & GiftTag: dg.addString(self.giftTag) dg.addUint8(self.specialEventId) diff --git a/toontown/catalog/CatalogItemPanel.py b/toontown/catalog/CatalogItemPanel.py index 3341f822..0513e36d 100755 --- a/toontown/catalog/CatalogItemPanel.py +++ b/toontown/catalog/CatalogItemPanel.py @@ -10,7 +10,6 @@ from CatalogFlooringItem import getAllFloorings from CatalogMouldingItem import getAllMouldings from CatalogWainscotingItem import getAllWainscotings from CatalogFurnitureItem import getAllFurnitures -from CatalogFurnitureItem import FLTrunk from otp.otpbase import OTPGlobals CATALOG_PANEL_WORDWRAP = 10 CATALOG_PANEL_CHAT_WORDWRAP = 9 @@ -292,11 +291,7 @@ class CatalogItemPanel(DirectFrame): auxText = TTLocalizer.CatalogOnOrderText else: auxText = '' - isNameTag = typeCode == CatalogItemTypes.NAMETAG_ITEM - if isNameTag and self['item'].nametagStyle == base.localAvatar.getNametagStyle(): - auxText = TTLocalizer.CatalogCurrent - self.buyButton['state'] = DGG.DISABLED - elif self['item'].reachedPurchaseLimit(base.localAvatar): + if self['item'].reachedPurchaseLimit(base.localAvatar): max = self['item'].getPurchaseLimit() if max <= 1: auxText = TTLocalizer.CatalogPurchasedText @@ -325,13 +320,9 @@ class CatalogItemPanel(DirectFrame): def __handlePurchaseRequest(self): if self['item'].replacesExisting() and self['item'].hasExisting(): - if self['item'].getFlags() & FLTrunk: - message = TTLocalizer.CatalogVerifyPurchase % {'item': self['item'].getName(), - 'price': self['item'].getPrice(self['type'])} - else: - message = TTLocalizer.CatalogOnlyOnePurchase % {'old': self['item'].getYourOldDesc(), - 'item': self['item'].getName(), - 'price': self['item'].getPrice(self['type'])} + message = TTLocalizer.CatalogOnlyOnePurchase % {'old': self['item'].getYourOldDesc(), + 'item': self['item'].getName(), + 'price': self['item'].getPrice(self['type'])} elif self['item'].isRental(): message = TTLocalizer.CatalogVerifyRent % {'item': self['item'].getName(), 'price': self['item'].getPrice(self['type'])} @@ -402,14 +393,9 @@ class CatalogItemPanel(DirectFrame): 'item': self['item'].getName(), 'price': self['item'].getPrice(self['type'])} else: - friendIndex = self.parentCatalogScreen.friendGiftIndex - friendText = 'Error' - numFriends = len(base.localAvatar.friendsList) + len(base.cr.avList) - 1 - if numFriends > 0: - friendText = self.parentCatalogScreen.receiverName message = TTLocalizer.CatalogVerifyGift % {'item': self['item'].getName(), 'price': self['item'].getPrice(self['type']), - 'friend': friendText} + 'friend': self.parentCatalogScreen.friendName if self.parentCatalogScreen.friendName else TTLocalizer.CatalogGiftError} self.verify = TTDialog.TTGlobalDialog(doneEvent='verifyGiftDone', message=message, style=TTDialog.TwoChoice) self.verify.show() self.accept('verifyGiftDone', self.__handleVerifyGift) @@ -441,44 +427,38 @@ class CatalogItemPanel(DirectFrame): def updateGiftButton(self, giftUpdate = 0): if not self.loaded: return + self.giftButton.show() + if giftUpdate == 0: return - self.auxText['text'] = ' ' - numFriends = len(base.localAvatar.friendsList) + len(base.cr.avList) - 1 - if numFriends > 0: - self.giftButton['state'] = DGG.DISABLED - self.giftButton.show() - auxText = ' ' - if self['item'].isGift() <= 0: - self.giftButton.show() - self.giftButton['state'] = DGG.DISABLED - auxText = TTLocalizer.CatalogNotAGift - self.auxText['text'] = auxText - return - elif self.parentCatalogScreen.gotAvatar == 1: - avatar = self.parentCatalogScreen.giftAvatar - if self['item'].forBoysOnly() and avatar.getStyle().getGender() == 'f' or self['item'].forGirlsOnly() and avatar.getStyle().getGender() == 'm': - self.giftButton.show() - self.giftButton['state'] = DGG.DISABLED - auxText = TTLocalizer.CatalogNoFit - self.auxText['text'] = auxText - return - elif self['item'].reachedPurchaseLimit(avatar): - self.giftButton.show() - self.giftButton['state'] = DGG.DISABLED - auxText = TTLocalizer.CatalogPurchasedGiftText - self.auxText['text'] = auxText - return - elif len(avatar.mailboxContents) + len(avatar.onGiftOrder) >= ToontownGlobals.MaxMailboxContents: - self.giftButton.show() - self.giftButton['state'] = DGG.DISABLED - auxText = TTLocalizer.CatalogMailboxFull - self.auxText['text'] = auxText - return - elif self['item'].getPrice(self['type']) <= base.localAvatar.getMoney() + base.localAvatar.getBankMoney(): - self.giftButton['state'] = DGG.NORMAL - self.giftButton.show() + + self.auxText['text'] = '' + self.giftButton['state'] = DGG.DISABLED + self.giftButton.show() + + if self['item'].isGift() <= 0: + self.auxText['text'] = TTLocalizer.CatalogNotAGift + return + + if not self.parentCatalogScreen.friend: + return + + avatar = self.parentCatalogScreen.friend + + if self['item'].forBoysOnly() and avatar.getStyle().getGender() == 'f' or self['item'].forGirlsOnly() and avatar.getStyle().getGender() == 'm': + self.auxText['text'] = TTLocalizer.CatalogNoFit + elif self['item'].reachedPurchaseLimit(avatar): + self.auxText['text'] = TTLocalizer.CatalogPurchasedGiftText + elif len(avatar.mailboxContents) + len(avatar.onOrder) + len(avatar.onGiftOrder) + 1 >= ToontownGlobals.MaxMailboxContents: + self.auxText['text'] = TTLocalizer.CatalogMailboxFull + else: + orderCount = avatar.onGiftOrder.count(self['item']) + + if orderCount: + self.auxText['text'] = TTLocalizer.CatalogOnOrderText if orderCount == 1 else '%d %s' % (orderCount, TTLocalizer.CatalogOnOrderText) + if self['item'].getPrice(self['type']) <= base.localAvatar.getMoney() + base.localAvatar.getBankMoney(): + self.giftButton['state'] = DGG.NORMAL def handleSoundOnButton(self): item = self.items[self.itemIndex] diff --git a/toontown/catalog/CatalogNametagItem.py b/toontown/catalog/CatalogNametagItem.py index 2d3ffd45..675660bb 100755 --- a/toontown/catalog/CatalogNametagItem.py +++ b/toontown/catalog/CatalogNametagItem.py @@ -17,11 +17,7 @@ class CatalogNametagItem(CatalogItem.CatalogItem): return 1 def reachedPurchaseLimit(self, avatar): - if self in avatar.onOrder or self in avatar.mailboxContents or self in avatar.onGiftOrder or self in avatar.awardMailboxContents or self in avatar.onAwardOrder: - return 1 - if avatar.nametagStyle == self.nametagStyle: - return 1 - return 0 + return self in avatar.onOrder or self in avatar.mailboxContents or self in avatar.onGiftOrder or self.nametagStyle in avatar.nametagStyles def getAcceptItemErrorText(self, retcode): if retcode == ToontownGlobals.P_ItemAvailable: @@ -45,6 +41,7 @@ class CatalogNametagItem(CatalogItem.CatalogItem): def recordPurchase(self, avatar, optional): if avatar: avatar.b_setNametagStyle(self.nametagStyle) + avatar.addNametagStyle(self.nametagStyle) return ToontownGlobals.P_ItemAvailable def getDeliveryTime(self): @@ -52,10 +49,7 @@ class CatalogNametagItem(CatalogItem.CatalogItem): def getPicture(self, avatar): frame = self.makeFrame() - if self.nametagStyle == 100: - inFont = ToontownGlobals.getToonFont() - else: - inFont = ToontownGlobals.getNametagFont(self.nametagStyle) + inFont = ToontownGlobals.getNametagFont(self.nametagStyle) nameTagDemo = DirectLabel(parent=frame, relief=None, pos=(0, 0, 0.24), scale=0.5, text=base.localAvatar.getName(), text_fg=(1.0, 1.0, 1.0, 1), text_shadow=(0, 0, 0, 1), text_font=inFont, text_wordwrap=9) self.hasPicture = True return (frame, None) @@ -71,16 +65,6 @@ class CatalogNametagItem(CatalogItem.CatalogItem): def getBasePrice(self): return 500 - cost = 500 - if self.nametagStyle == 0: - cost = 600 - elif self.nametagStyle == 1: - cost = 600 - elif self.nametagStyle == 2: - cost = 600 - elif self.nametagStyle == 100: - cost = 50 - return cost def decodeDatagram(self, di, versionNumber, store): CatalogItem.CatalogItem.decodeDatagram(self, di, versionNumber, store) @@ -92,9 +76,6 @@ class CatalogNametagItem(CatalogItem.CatalogItem): dg.addUint16(self.nametagStyle) dg.addBool(self.isSpecial) - def isGift(self): - return 0 - def getBackSticky(self): itemType = 1 numSticky = 4 diff --git a/toontown/catalog/CatalogPetTrickItem.py b/toontown/catalog/CatalogPetTrickItem.py index 7932ee07..c1372855 100755 --- a/toontown/catalog/CatalogPetTrickItem.py +++ b/toontown/catalog/CatalogPetTrickItem.py @@ -17,7 +17,7 @@ class CatalogPetTrickItem(CatalogItem.CatalogItem): return 1 def reachedPurchaseLimit(self, avatar): - if self in avatar.onOrder or self in avatar.mailboxContents or self in avatar.onGiftOrder or self in avatar.awardMailboxContents or self in avatar.onAwardOrder or not hasattr(avatar, 'petTrickPhrases'): + if self in avatar.onOrder or self in avatar.mailboxContents or self in avatar.onGiftOrder or not hasattr(avatar, 'petTrickPhrases'): return 1 return self.trickId in avatar.petTrickPhrases diff --git a/toontown/catalog/CatalogPoleItem.py b/toontown/catalog/CatalogPoleItem.py index 294bb23e..e277f1cf 100755 --- a/toontown/catalog/CatalogPoleItem.py +++ b/toontown/catalog/CatalogPoleItem.py @@ -16,7 +16,7 @@ class CatalogPoleItem(CatalogItem.CatalogItem): return 1 def reachedPurchaseLimit(self, avatar): - return avatar.getFishingRod() >= self.rodId or self in avatar.onOrder or self in avatar.mailboxContents + return avatar.getMaxFishingRod() >= self.rodId or self in avatar.onOrder or self in avatar.mailboxContents def saveHistory(self): return 1 @@ -31,17 +31,18 @@ class CatalogPoleItem(CatalogItem.CatalogItem): if self.rodId < 0 or self.rodId > FishGlobals.MaxRodId: self.notify.warning('Invalid fishing pole: %s for avatar %s' % (self.rodId, avatar.doId)) return ToontownGlobals.P_InvalidIndex - if self.rodId < avatar.getFishingRod(): + if self.rodId < avatar.getMaxFishingRod(): self.notify.warning('Avatar already has pole: %s for avatar %s' % (self.rodId, avatar.doId)) return ToontownGlobals.P_ItemUnneeded avatar.b_setFishingRod(self.rodId) + avatar.b_setMaxFishingRod(self.rodId) return ToontownGlobals.P_ItemAvailable def isGift(self): return 0 def getDeliveryTime(self): - return 1 + return 24 * 60 def getPicture(self, avatar): rodPath = FishGlobals.RodFileDict.get(self.rodId) @@ -83,7 +84,6 @@ class CatalogPoleItem(CatalogItem.CatalogItem): def decodeDatagram(self, di, versionNumber, store): CatalogItem.CatalogItem.decodeDatagram(self, di, versionNumber, store) self.rodId = di.getUint8() - price = FishGlobals.RodPriceDict[self.rodId] def encodeDatagram(self, dg, store): CatalogItem.CatalogItem.encodeDatagram(self, dg, store) @@ -91,7 +91,7 @@ class CatalogPoleItem(CatalogItem.CatalogItem): def nextAvailablePole(avatar, duplicateItems): - rodId = avatar.getFishingRod() + 1 + rodId = avatar.getMaxFishingRod() + 1 if rodId > FishGlobals.MaxRodId: return None item = CatalogPoleItem(rodId) diff --git a/toontown/catalog/CatalogRentalItem.py b/toontown/catalog/CatalogRentalItem.py index 51dd0ae2..40998d83 100755 --- a/toontown/catalog/CatalogRentalItem.py +++ b/toontown/catalog/CatalogRentalItem.py @@ -24,9 +24,7 @@ class CatalogRentalItem(CatalogItem.CatalogItem): return 0 def reachedPurchaseLimit(self, avatar): - if self in avatar.onOrder or self in avatar.mailboxContents or self in avatar.onGiftOrder or self in avatar.awardMailboxContents or self in avatar.onAwardOrder: - return 1 - return 0 + return self in avatar.onOrder or self in avatar.mailboxContents or self in avatar.onGiftOrder def saveHistory(self): return 1 diff --git a/toontown/catalog/CatalogScreen.py b/toontown/catalog/CatalogScreen.py index 30d3e947..0278f052 100755 --- a/toontown/catalog/CatalogScreen.py +++ b/toontown/catalog/CatalogScreen.py @@ -15,7 +15,7 @@ import random from toontown.toon import DistributedToon from direct.directnotify import DirectNotifyGlobal from otp.nametag.ChatBalloon import ChatBalloon -from otp.nametag import NametagGroup +from otp.nametag import NametagGroup, NametagConstants NUM_CATALOG_ROWS = 3 NUM_CATALOG_COLS = 2 @@ -31,8 +31,10 @@ class CatalogScreen(DirectFrame): notify = DirectNotifyGlobal.directNotify.newCategory('CatalogScreen') def __init__(self, parent = aspect2d, **kw): + self.gifting = -1 guiItems = loader.loadModel('phase_5.5/models/gui/catalog_gui') background = guiItems.find('**/catalog_background') + background.setBin("background", 10) guiButton = loader.loadModel('phase_3/models/gui/quit_button') guiBack = loader.loadModel('phase_5.5/models/gui/package_delivery_panel') optiondefs = (('scale', 0.667, None), @@ -43,19 +45,11 @@ class CatalogScreen(DirectFrame): ('relief', None, None)) self.defineoptions(kw, optiondefs) DirectFrame.__init__(self, parent) - self.friendGiftIndex = 0 - self.friendGiftHandle = None - self.frienddoId = None - self.receiverName = 'Error Nameless Toon' - self.friends = {} - self.family = {} - self.ffList = [] - self.textRolloverColor = Vec4(1, 1, 0, 1) - self.textDownColor = Vec4(0.5, 0.9, 1, 1) - self.textDisabledColor = Vec4(0.4, 0.8, 0.4, 1) - self.giftAvatar = None - self.gotAvatar = 0 - self.allowGetDetails = 1 + self.friend = None + self.friendAvId = None + self.friendName = None + self.friendList = [] + self.friends = [] self.load(guiItems, guiButton, guiBack) self.initialiseoptions(CatalogScreen) self.enableBackorderCatalogButton() @@ -65,10 +59,8 @@ class CatalogScreen(DirectFrame): self.hide() self.clarabelleChatNP = None self.clarabelleChatBalloon = None - self.gifting = -1 self.createdGiftGui = None self.viewing = None - return def show(self): self.accept('CatalogItemPurchaseRequest', self.__handlePurchaseRequest) @@ -90,9 +82,6 @@ class CatalogScreen(DirectFrame): taskMgr.doMethodLater(1.0, clarabelleGreeting, 'clarabelleGreeting') taskMgr.doMethodLater(12.0, clarabelleHelpText1, 'clarabelleHelpText1') - if hasattr(self, 'giftToggle'): - self.giftToggle['state'] = DGG.NORMAL - self.giftToggle['text'] = TTLocalizer.CatalogGiftToggleOn def hide(self): self.ignore('CatalogItemPurchaseRequest') @@ -542,15 +531,15 @@ class CatalogScreen(DirectFrame): -2.0, -1.45), image_scale=(1.0, 1.0, smash), image_pos=(0.0, 0.0, -1.9 + lift), image=backDown, pressEffect=0, command=self.showEmblemItems, text=TTLocalizer.CatalogEmblem, text_font=ToontownGlobals.getSignFont(), text_pos=(1.75, 0.132), text_scale=0.065, text_fg=(0.353, 0.627, 0.627, 1.0), text2_fg=(0.353, 0.427, 0.427, 1.0)) self.emblemCatalogButton2.hide() - self.__makeFFlist() - if len(self.ffList) > 0: + self.__makeFriendList() + if len(self.friendList) > 0: if config.GetBool('want-gifting', True): self.giftToggle = DirectButton(self.base, relief=None, pressEffect=0, image=(giftToggleUp, giftToggleDown, giftToggleUp), image_scale=(1.0, 1, 0.7), command=self.__giftToggle, text=TTLocalizer.CatalogGiftToggleOff, text_font=ToontownGlobals.getSignFont(), text_pos=TTLocalizer.CSgiftTogglePos, text_scale=TTLocalizer.CSgiftToggle, text_fg=(0.353, 0.627, 0.627, 1.0), text3_fg=(0.15, 0.3, 0.3, 1.0), text2_fg=(0.353, 0.427, 0.427, 1.0), image_color=Vec4(1.0, 1.0, 0.2, 1.0), image1_color=Vec4(0.9, 0.85, 0.2, 1.0), image2_color=Vec4(0.9, 0.85, 0.2, 1.0), image3_color=Vec4(0.5, 0.45, 0.2, 1.0)) self.giftToggle.setPos(0.0, 0, -0.035) self.giftLabel = DirectLabel(self.base, relief=None, image=giftFriends, image_scale=(1.15, 1, 1.14), text=' ', text_font=ToontownGlobals.getSignFont(), text_pos=(1.2, -0.97), text_scale=0.07, text_fg=(0.392, 0.549, 0.627, 1.0), sortOrder=100, textMayChange=1) self.giftLabel.setPos(-0.15, 0, 0.08) self.giftLabel.hide() - self.friendLabel = DirectLabel(self.base, relief=None, text='Friend Name', text_font=ToontownGlobals.getSignFont(), text_pos=(-0.25, 0.132), text_scale=0.068, text_align=TextNode.ALeft, text_fg=(0.992, 0.949, 0.327, 1.0), sortOrder=100, textMayChange=1) + self.friendLabel = DirectLabel(self.base, relief=None, text=TTLocalizer.CatalogGiftChoose, text_font=ToontownGlobals.getSignFont(), text_pos=(-0.25, 0.132), text_scale=0.068, text_align=TextNode.ALeft, text_fg=(0.992, 0.949, 0.327, 1.0), sortOrder=100, textMayChange=1) self.friendLabel.setPos(0.5, 0, -0.42) self.friendLabel.hide() gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui') @@ -569,9 +558,6 @@ class CatalogScreen(DirectFrame): clipNP = self.scrollList.attachNewNode(clipper) self.scrollList.setClipPlane(clipNP) self.__makeScrollList() - friendId = self.ffList[0] - self.__chooseFriend(self.ffList[0][0], self.ffList[0][1]) - self.update() self.createdGiftGui = 1 for i in xrange(4): self.newCatalogButton.component('text%d' % i).setR(90) @@ -828,8 +814,7 @@ class CatalogScreen(DirectFrame): taskMgr.remove('clarabelleGreeting') taskMgr.remove('clarabelleHelpText1') taskMgr.remove('clarabelleAskAnythingElse') - if self.giftAvatar: - base.cr.cancelAvatarDetailsRequest(self.giftAvatar) + taskMgr.remove('friendButtonsReady') self.hide() self.hangup.hide() self.destroy() @@ -861,16 +846,12 @@ class CatalogScreen(DirectFrame): del self.giftLabel del self.friendLabel del self.scrollList + del self.friend + del self.friends self.unloadClarabelle() if self.responseDialog: self.responseDialog.cleanup() self.responseDialog = None - if self.giftAvatar: - if hasattr(self.giftAvatar, 'doId'): - self.giftAvatar.delete() - else: - self.giftAvatar = None - return def unloadClarabelle(self): base.win.removeDisplayRegion(self.cDr) @@ -888,8 +869,6 @@ class CatalogScreen(DirectFrame): del self.clarabelleChatBalloon def hangUp(self): - if hasattr(self, 'giftAvatar') and self.giftAvatar: - self.giftAvatar.disable() self.setClarabelleChat(random.choice(TTLocalizer.CatalogGoodbyeList), type='goodbye') self.setPageIndex(-1) self.showPageItems() @@ -918,9 +897,8 @@ class CatalogScreen(DirectFrame): self.update() def update(self, task = None): - if not hasattr(self.giftAvatar, 'doId'): - if self.gifting == 1: - self.__giftToggle() + if (not self.friend) and self.gifting == 1: + self.__giftToggle() if hasattr(self, 'beanBank'): self.beanBank['text'] = str(base.localAvatar.getTotalMoney()) for item in self.panelList + self.backPanelList + self.specialPanelList + self.emblemPanelList: @@ -932,7 +910,7 @@ class CatalogScreen(DirectFrame): taskMgr.remove('clarabelleAskAnythingElse') def __handleGiftPurchaseRequest(self, item): - item.requestGiftPurchase(self['phone'], self.frienddoId, self.__handleGiftPurchaseResponse) + item.requestGiftPurchase(self['phone'], self.friendAvId, self.__handleGiftPurchaseResponse) taskMgr.remove('clarabelleAskAnythingElse') def __handlePurchaseResponse(self, retCode, item): @@ -951,7 +929,7 @@ class CatalogScreen(DirectFrame): return if self.isEmpty() or self.isHidden(): return - self.setClarabelleChat(item.getRequestGiftPurchaseErrorText(retCode) % self.receiverName) + self.setClarabelleChat(item.getRequestGiftPurchaseErrorText(retCode) % self.friendName) self.__loadFriend() def askAnythingElse(task): @@ -1007,81 +985,60 @@ class CatalogScreen(DirectFrame): self.silverLabel.hide() self.goldLabel.hide() - def checkFamily(self, doId): - test = 0 - for familyMember in base.cr.avList: - if familyMember.id == doId: - test = 1 - - return test - - def __makeFFlist(self): + def __makeFriendList(self): + for av in base.cr.avList: + if av.id != base.localAvatar.doId: + self.friendList.append((av.id, av.name, NametagGroup.CCNonPlayer)) + for id, handle in base.cr.friendsMap.items(): if isinstance(handle, FriendHandle.FriendHandle): - self.ffList.append((id, handle.getName(), None))#NametagGlobals.getFriendColor(handle))) + self.friendList.append((id, handle.getName(), NametagConstants.getFriendColor(handle))) def __makeScrollList(self): - for ff in self.ffList: - ffbutton = self.makeFamilyButton(ff[0], ff[1], ff[2]) - if ffbutton: - self.scrollList.addItem(ffbutton, refresh=0) - self.friends[ff] = ffbutton + for friend in self.friendList: + button = self.makeFriendButton(*friend) + self.scrollList.addItem(button, refresh=0) + self.friends.append(button) self.scrollList.refresh() - def makeFamilyButton(self, familyId, familyName, colorCode): - # fg = NametagGlobals.getNameFg(colorCode, PGButton.SInactive) - return DirectButton( - relief=None, - text=familyName, - text_scale=0.04, - text_align=TextNode.ALeft, - # text_fg=fg, - text1_bg=self.textDownColor, - text2_bg=self.textRolloverColor, - text3_fg=self.textDisabledColor, - textMayChange=0, - command=self.__chooseFriend, - extraArgs=[familyId, familyName] - ) + def makeFriendButton(self, avId, name, colorCode): + color = NametagConstants.NAMETAG_COLORS[colorCode] - def __chooseFriend(self, friendId, friendName): + return DirectButton(relief=None, text=name, text_scale=0.04, text_align=TextNode.ALeft, text_fg=color[0][0], text1_bg=(1, 1, 0, 1), + text2_bg=(0.5, 0.9, 1, 1), text3_fg=(0.4, 0.8, 0.4, 1), command=self.__chooseFriend, extraArgs=[avId, name]) + + def __chooseFriend(self, avId, name): messenger.send('wakeup') - self.frienddoId = friendId - self.receiverName = friendName - self.friendLabel['text'] = TTLocalizer.CatalogGiftTo % self.receiverName + + if self.friendAvId == avId: + return + + self.friendAvId = avId + self.friendName = name self.__loadFriend() def __loadFriend(self): - if self.allowGetDetails == 0: - CatalogScreen.notify.warning('smashing requests') - if self.frienddoId and self.allowGetDetails: - if self.giftAvatar: - if hasattr(self.giftAvatar, 'doId'): - self.giftAvatar.disable() - self.giftAvatar.delete() - self.giftAvatar = None - self.giftAvatar = DistributedToon.DistributedToon(base.cr) - self.giftAvatar.doId = self.frienddoId - self.giftAvatar.forceAllowDelayDelete() - self.giftAvatar.generate() - base.cr.getAvatarDetails(self.giftAvatar, self.__handleAvatarDetails, 'DistributedToon') - self.gotAvatar = 0 - self.allowGetDetails = 0 - self.scrollList['state'] = DGG.DISABLED - return - - def __handleAvatarDetails(self, gotData, avatar, dclass): - if self.giftAvatar.doId != avatar.doId or gotData == 0: - CatalogScreen.notify.error('Get Gift Avatar Failed') - self.gotAvatar = 0 + if not self.friendAvId: return - else: - self.gotAvatar = 1 - self.giftAvatar = avatar - self.scrollList['state'] = DGG.NORMAL - self.allowGetDetails = 1 + + for friendButton in self.friends: + friendButton['state'] = DGG.DISABLED + + self.friend = None + self.friendLabel['text'] = TTLocalizer.CatalogGiftUpdating + taskMgr.remove('friendButtonsReady') + self['phone'].requestGiftAvatar(self.friendAvId) + + def setFriendReady(self, friend): + self.friend = friend + self.friendLabel['text'] = TTLocalizer.CatalogGiftTo % self.friendName + taskMgr.doMethodLater(1.5, self.setFriendButtonsReady, 'friendButtonsReady') self.update() + + def setFriendButtonsReady(self, task=None): + for friendButton in self.friends: + friendButton['state'] = DGG.NORMAL def __giftToggle(self): messenger.send('wakeup') @@ -1092,12 +1049,16 @@ class CatalogScreen(DirectFrame): self.scrollList.show() self.hideEmblems() self.giftToggle['text'] = TTLocalizer.CatalogGiftToggleOn + self.friendLabel['text'] = TTLocalizer.CatalogGiftChoose self.__loadFriend() else: + self.friend = None + self.friendAvId = 0 + self.friendName = None self.gifting = -1 self.giftLabel.hide() self.friendLabel.hide() self.scrollList.hide() self.showEmblems() self.giftToggle['text'] = TTLocalizer.CatalogGiftToggleOff - self.update() + self.update() \ No newline at end of file diff --git a/toontown/catalog/CatalogSurfaceItem.py b/toontown/catalog/CatalogSurfaceItem.py index 62691408..83d6ac54 100755 --- a/toontown/catalog/CatalogSurfaceItem.py +++ b/toontown/catalog/CatalogSurfaceItem.py @@ -24,11 +24,10 @@ class CatalogSurfaceItem(CatalogAtticItem.CatalogAtticItem): return 1 def recordPurchase(self, avatar, optional): - self.giftTag = None house, retcode = self.getHouseInfo(avatar) if retcode >= 0: house.addWallpaper(self) return retcode def getDeliveryTime(self): - return 1 + return 60 diff --git a/toontown/catalog/CatalogTankItem.py b/toontown/catalog/CatalogTankItem.py index 21d87d84..c4cc612c 100644 --- a/toontown/catalog/CatalogTankItem.py +++ b/toontown/catalog/CatalogTankItem.py @@ -33,13 +33,13 @@ class CatalogTankItem(CatalogItem.CatalogItem): if self.maxTank <= avatar.getMaxFishTank(): return ToontownGlobals.P_ItemUnneeded avatar.b_setMaxFishTank(self.maxTank) - return ToontownGlobals.P_ItemAvailable + return ToontownGlobals.P_ItemOnOrder def isGift(self): return 0 def getDeliveryTime(self): - return 0 + return 1 def getPicture(self, avatar): gui = loader.loadModel('phase_4/models/gui/fishingGui') diff --git a/toontown/catalog/CatalogToonStatueItem.py b/toontown/catalog/CatalogToonStatueItem.py index 8c95d199..dcd4fe99 100755 --- a/toontown/catalog/CatalogToonStatueItem.py +++ b/toontown/catalog/CatalogToonStatueItem.py @@ -25,6 +25,7 @@ class CatalogToonStatueItem(CatalogGardenItem.CatalogGardenItem): model, ival = self.makeFrameModel(toonStatuary.toon, 1) self.pictureToonStatue = toonStatuary self.hasPicture = True + toonStatuary.toon.setBin('gui-popup', 60) return (model, ival) def cleanupPicture(self): diff --git a/toontown/catalog/CatalogWindowItem.py b/toontown/catalog/CatalogWindowItem.py index 91aee656..e9d0308d 100755 --- a/toontown/catalog/CatalogWindowItem.py +++ b/toontown/catalog/CatalogWindowItem.py @@ -37,14 +37,13 @@ class CatalogWindowItem(CatalogAtticItem.CatalogAtticItem): return TTLocalizer.WindowViewNames.get(self.windowType) def recordPurchase(self, avatar, optional): - self.giftTag = None house, retcode = self.getHouseInfo(avatar) if retcode >= 0: house.addWindow(self) return retcode def getDeliveryTime(self): - return 1 + return 4 * 60 def getPicture(self, avatar): frame = self.makeFrame() diff --git a/toontown/catalog/GiftAvatar.py b/toontown/catalog/GiftAvatar.py new file mode 100644 index 00000000..9905726f --- /dev/null +++ b/toontown/catalog/GiftAvatar.py @@ -0,0 +1,98 @@ +from toontown.toon import ToonDNA +import CatalogItem, CatalogItemList +import json, time + +def createFromJson(jsonData): + return createFromFields(json.loads(jsonData)) + +def createFromFields(fields): + avatar = GiftAvatar() + + for key, value in fields.iteritems(): + getattr(avatar, key)(value) + + return avatar + +class GiftAvatar: + + def getStyle(self): + return self.style + + def getHat(self): + return self.hat + + def getGlasses(self): + return self.glasses + + def getBackpack(self): + return self.backpack + + def getShoes(self): + return self.shoes + + def getGiftScheduleBlob(self): + return self.onGiftOrder.getBlob(store=CatalogItem.Customization | CatalogItem.DeliveryDate) + + def setDNAString(self, dnaString): + self.style = ToonDNA.ToonDNA() + self.style.makeFromNetString(dnaString.decode('base64')) + + def setMailboxContents(self, contents): + self.mailboxContents = CatalogItemList.CatalogItemList(contents.decode('base64'), store=CatalogItem.Customization) + + def setGiftSchedule(self, onOrder): + self.onGiftOrder = CatalogItemList.CatalogItemList(onOrder.decode('base64'), store=CatalogItem.Customization | CatalogItem.DeliveryDate) + + def setDeliverySchedule(self, onOrder): + self.onOrder = CatalogItemList.CatalogItemList(onOrder.decode('base64'), store=CatalogItem.Customization | CatalogItem.DeliveryDate) + + def setHat(self, hat): + self.hat = hat + + def setGlasses(self, glasses): + self.glasses = glasses + + def setBackpack(self, backpack): + self.backpack = backpack + + def setShoes(self, shoes): + self.shoes = shoes + + def setHatList(self, list): + self.hatList = list[0] + + def setGlassesList(self, list): + self.glassesList = list[0] + + def setBackpackList(self, list): + self.backpackList = list[0] + + def setShoesList(self, list): + self.shoesList = list[0] + + def setCustomMessages(self, customMessages): + self.customMessages = customMessages[0] + + def setClothesTopsList(self, clothesList): + self.clothesTopsList = clothesList[0] + + def setClothesBottomsList(self, clothesList): + self.clothesBottomsList = clothesList[0] + + def setEmoteAccess(self, emoteAccess): + self.emoteAccess = emoteAccess[0] + + def setPetTrickPhrases(self, tricks): + self.petTrickPhrases = tricks[0] + + def setNametagStyles(self, nametagStyles): + self.nametagStyles = nametagStyles[0] + + def addToGiftSchedule(self, avId, targetId, item, minutes=0): + if config.GetBool('want-instant-delivery', False): + minutes = 0 + + item.giftTag = avId + item.deliveryDate = int(time.time() / 60. + minutes + .5) + self.onGiftOrder.append(item) + simbase.air.send(simbase.air.dclassesByName['DistributedToonAI'].aiFormatUpdate('setGiftSchedule', targetId, targetId, simbase.air.ourChannel, [self.getGiftScheduleBlob()])) \ No newline at end of file diff --git a/toontown/catalog/MailboxScreen.py b/toontown/catalog/MailboxScreen.py index 7b2f62ac..d9ae600d 100755 --- a/toontown/catalog/MailboxScreen.py +++ b/toontown/catalog/MailboxScreen.py @@ -31,7 +31,6 @@ class MailboxScreen(DirectObject.DirectObject): self.dialogBox = None self.load() self.hide() - return def show(self): self.frame.show() @@ -79,7 +78,7 @@ class MailboxScreen(DirectObject.DirectObject): self.quitButton = DirectButton(parent=self.frame, relief=None, image=(gui2.find('**/QuitBtn_UP'), gui2.find('**/QuitBtn_DN'), gui2.find('**/QuitBtn_RLVR')), pos=(0.5, 1.0, -0.42), scale=0.9, text=TTLocalizer.MailboxExitButton, text_font=ToontownGlobals.getSignFont(), text0_fg=(0.152, 0.75, 0.258, 1), text1_fg=(0.152, 0.75, 0.258, 1), text2_fg=(0.977, 0.816, 0.133, 1), text_scale=0.045, text_pos=(0, -0.01), command=self.__handleExit) self.gettingText = DirectLabel(parent=self.frame, relief=None, text='', text_wordwrap=10, pos=(0.0, 0.0, 0.32), scale=0.09) self.gettingText.hide() - self.giftTagPanel = DirectLabel(parent=self.frame, relief=None, text='Gift TAG!!', text_wordwrap=16, pos=(0.0, 0.0, 0.01), scale=0.06) + self.giftTagPanel = DirectLabel(parent=self.frame, relief=None, text=TTLocalizer.MailboxGiftTag % TTLocalizer.MailboxGiftTagAnonymous, text_wordwrap=16, pos=(0.0, 0.0, 0.01), scale=0.06) self.giftTagPanel.hide() self.itemText = DirectLabel(parent=self.frame, relief=None, text='', text_wordwrap=16, pos=(0.0, 0.0, -0.022), scale=0.07) self.itemText.hide() @@ -249,10 +248,7 @@ class MailboxScreen(DirectObject.DirectObject): self.acceptingIndex = None if retcode < 0: self.notify.info('Could not take item %s: retcode %s' % (item, retcode)) - if retcode == ToontownGlobals.P_NoTrunk: - self.dialogBox = TTDialog.TTDialog(style=TTDialog.Acknowledge, text=TTLocalizer.CatalogAcceptNoTrunk, text_wordwrap=15, command=self.__acceptError) - else: - self.dialogBox = TTDialog.TTDialog(style=TTDialog.TwoChoiceCustom, text=item.getAcceptItemErrorText(retcode), text_wordwrap=15, command=self.__handleDiscard, buttonText=[TTLocalizer.MailboxDiscard, TTLocalizer.MailboxLeave]) + self.dialogBox = TTDialog.TTDialog(style=TTDialog.TwoChoiceCustom, text=item.getAcceptItemErrorText(retcode), text_wordwrap=15, command=self.__handleDiscard, buttonText=[TTLocalizer.MailboxDiscard, TTLocalizer.MailboxLeave]) self.dialogBox.show() elif hasattr(item, 'storedInAttic') and item.storedInAttic(): self.numAtticAccepted += 1 @@ -513,4 +509,11 @@ class MailboxScreen(DirectObject.DirectObject): def getSenderName(self, avId): sender = base.cr.identifyFriend(avId) - return sender.getName() if sender else TTLocalizer.MailboxGiftTagAnonymous + if sender: + return sender.getName() + + for av in base.cr.avList: + if av.id == avId: + return av.name + + return TTLocalizer.MailboxGiftTagAnonymous diff --git a/toontown/chat/ResistanceChat.py b/toontown/chat/ResistanceChat.py index 1c480829..99bb6800 100755 --- a/toontown/chat/ResistanceChat.py +++ b/toontown/chat/ResistanceChat.py @@ -23,6 +23,7 @@ RESISTANCE_MONEY = 2 RESISTANCE_TICKETS = 3 RESISTANCE_MERITS = 4 resistanceMenu = [RESISTANCE_TOONUP, RESISTANCE_RESTOCK, RESISTANCE_MONEY, RESISTANCE_TICKETS, RESISTANCE_MERITS] +randomResistanceMenu = [RESISTANCE_TOONUP, RESISTANCE_RESTOCK, RESISTANCE_MONEY, RESISTANCE_TICKETS] resistanceDict = { RESISTANCE_TOONUP: { 'menuName': TTLocalizer.ResistanceToonupMenu, @@ -138,7 +139,7 @@ def getItemValue(textId): def getRandomId(): - menuIndex = random.choice(resistanceMenu) + menuIndex = random.choice(randomResistanceMenu) itemIndex = random.choice(getItems(menuIndex)) return encodeId(menuIndex, itemIndex) diff --git a/toontown/coderedemption/TTCodeRedemptionMgrAI.py b/toontown/coderedemption/TTCodeRedemptionMgrAI.py index d4f7fe9f..6a0befa8 100755 --- a/toontown/coderedemption/TTCodeRedemptionMgrAI.py +++ b/toontown/coderedemption/TTCodeRedemptionMgrAI.py @@ -43,13 +43,6 @@ only include the comma if there are multiple arguments. class TTCodeRedemptionMgrAI(DistributedObjectAI): notify = DirectNotifyGlobal.directNotify.newCategory("TTCodeRedemptionMgrAI") codes = { - 'weed': { - 'items': [ - CatalogClothingItem.CatalogClothingItem(1821, 0) - ], - 'month': 4, - 'day': 20 - }, 'gardening': { 'items': [ CatalogGardenStarterItem.CatalogGardenStarterItem() @@ -75,15 +68,6 @@ class TTCodeRedemptionMgrAI(DistributedObjectAI): def announceGenerate(self): DistributedObjectAI.announceGenerate(self) - def getMailboxCount(self, items): - count = 0 - - for item in items: - if item.getDeliveryTime() > 0: - count += 1 - - return count - def redeemCode(self, code): avId = self.air.getAvatarIdFromSender() av = self.air.doId2do.get(avId) @@ -119,9 +103,7 @@ class TTCodeRedemptionMgrAI(DistributedObjectAI): self.air.writeServerEvent('suspicious', avId, 'Toon tried to redeem non-existent code %s' % code) def requestCodeRedeem(self, avId, av, items): - count = self.getMailboxCount(items) - - if len(av.onOrder) + count > 5 or len(av.mailboxContents) + len(av.onOrder) + count >= ToontownGlobals.MaxMailboxContents: + if len(av.mailboxContents) + len(av.onOrder) + len(av.onGiftOrder) + len(items) >= ToontownGlobals.MaxMailboxContents: self.sendUpdateToAvatarId(avId, 'redeemCodeResult', [3]) return @@ -129,8 +111,7 @@ class TTCodeRedemptionMgrAI(DistributedObjectAI): if item in av.onOrder: continue - item.deliveryDate = int(time.time() / 60) + 0.01 - av.onOrder.append(item) + av.addToDeliverySchedule(item) av.b_setDeliverySchedule(av.onOrder) self.sendUpdateToAvatarId(avId, 'redeemCodeResult', [0]) diff --git a/toontown/cogdominium/CogdoBarrelRoomMovies.py b/toontown/cogdominium/CogdoBarrelRoomMovies.py index affdff5e..651993b9 100755 --- a/toontown/cogdominium/CogdoBarrelRoomMovies.py +++ b/toontown/cogdominium/CogdoBarrelRoomMovies.py @@ -67,7 +67,7 @@ class CogdoBarrelRoomIntro(CogdoGameMovie): self.frame.hide() backgroundGui.removeNode() self.toonDNA = ToonDNA.ToonDNA() - self.toonDNA.newToonFromProperties('dss', 'ss', 'm', 'm', 2, 0, 2, 2, 1, 8, 1, 8, 1, 14, 0) + self.toonDNA.newToonFromProperties('dss', 'ss', 'm', 'm', 2, 0, 2, 2, 1, 8, 1, 8, 1, 14) self.toonHead = Toon.Toon() self.toonHead.setDNA(self.toonDNA) self.makeSuit('sc') diff --git a/toontown/cogdominium/CogdoElevatorMovie.py b/toontown/cogdominium/CogdoElevatorMovie.py index 293e6688..63a04afa 100755 --- a/toontown/cogdominium/CogdoElevatorMovie.py +++ b/toontown/cogdominium/CogdoElevatorMovie.py @@ -67,7 +67,7 @@ class CogdoElevatorMovie(CogdoGameMovie): self.frame.hide() backgroundGui.removeNode() self.toonDNA = ToonDNA.ToonDNA() - self.toonDNA.newToonFromProperties('dss', 'ss', 'm', 'm', 2, 0, 2, 2, 1, 8, 1, 8, 1, 14, 0) + self.toonDNA.newToonFromProperties('dss', 'ss', 'm', 'm', 2, 0, 2, 2, 1, 8, 1, 8, 1, 14) self.toonHead = Toon.Toon() self.toonHead.setDNA(self.toonDNA) self.makeSuit('sc') diff --git a/toontown/cogdominium/CogdoExecutiveSuiteMovies.py b/toontown/cogdominium/CogdoExecutiveSuiteMovies.py index fb3e6ccf..0227f849 100755 --- a/toontown/cogdominium/CogdoExecutiveSuiteMovies.py +++ b/toontown/cogdominium/CogdoExecutiveSuiteMovies.py @@ -71,7 +71,7 @@ class CogdoExecutiveSuiteIntro(CogdoGameMovie): self.frame.hide() backgroundGui.removeNode() self.toonDNA = ToonDNA.ToonDNA() - self.toonDNA.newToonFromProperties('dss', 'ss', 'm', 'm', 2, 0, 2, 2, 1, 8, 1, 8, 1, 14, 0) + self.toonDNA.newToonFromProperties('dss', 'ss', 'm', 'm', 2, 0, 2, 2, 1, 8, 1, 8, 1, 14) self.toonHead = Toon.Toon() self.toonHead.setDNA(self.toonDNA) self.makeSuit('sc') diff --git a/toontown/cogdominium/CogdoFlyingGameMovies.py b/toontown/cogdominium/CogdoFlyingGameMovies.py index 81f87d5c..3d32c9cb 100755 --- a/toontown/cogdominium/CogdoFlyingGameMovies.py +++ b/toontown/cogdominium/CogdoFlyingGameMovies.py @@ -53,7 +53,7 @@ class CogdoFlyingGameIntro(CogdoGameMovie): def load(self): CogdoGameMovie.load(self) self.toonDNA = ToonDNA.ToonDNA() - self.toonDNA.newToonFromProperties('dss', 'ss', 'm', 'm', 2, 0, 2, 2, 1, 8, 1, 8, 1, 14, 0) + self.toonDNA.newToonFromProperties('dss', 'ss', 'm', 'm', 2, 0, 2, 2, 1, 8, 1, 8, 1, 14) self.toonHead = Toon.Toon() self.toonHead.setDNA(self.toonDNA) self.makeSuit('sc') diff --git a/toontown/cogdominium/CogdoMazeGameGlobals.py b/toontown/cogdominium/CogdoMazeGameGlobals.py index 638f2736..53da6449 100755 --- a/toontown/cogdominium/CogdoMazeGameGlobals.py +++ b/toontown/cogdominium/CogdoMazeGameGlobals.py @@ -180,7 +180,7 @@ SfxFiles = {'toonHitByDrop': 'phase_5/audio/sfx/tt_s_ara_cmg_toonHit.ogg', 'throw': 'phase_3.5/audio/sfx/AA_pie_throw_only.ogg', 'splat': 'phase_5/audio/sfx/SA_watercooler_spray_only.ogg', 'cogSpin': 'phase_3.5/audio/sfx/Cog_Death.ogg', - 'cogDeath': 'phase_3.5/audio/sfx/ENC_cogfall_apart.ogg', + 'cogDeath': 'phase_3.5/audio/sfx/ENC_cogfall_apart_1.ogg', 'bossCogAngry': 'phase_5/audio/sfx/tt_s_ara_cmg_bossCogAngry.ogg', 'cogStomp': 'phase_5/audio/sfx/tt_s_ara_cmg_cogStomp.ogg', 'quake': 'phase_5/audio/sfx/tt_s_ara_cmg_groundquake.ogg', diff --git a/toontown/cogdominium/CogdoMazeGameMovies.py b/toontown/cogdominium/CogdoMazeGameMovies.py index 498db394..a38d31e6 100755 --- a/toontown/cogdominium/CogdoMazeGameMovies.py +++ b/toontown/cogdominium/CogdoMazeGameMovies.py @@ -56,7 +56,7 @@ class CogdoMazeGameIntro(CogdoGameMovie): def load(self): CogdoGameMovie.load(self) self.toonDNA = ToonDNA.ToonDNA() - self.toonDNA.newToonFromProperties('dss', 'ss', 'm', 'm', 2, 0, 2, 2, 1, 8, 1, 8, 1, 14, 0) + self.toonDNA.newToonFromProperties('dss', 'ss', 'm', 'm', 2, 0, 2, 2, 1, 8, 1, 8, 1, 14) self.toonHead = Toon.Toon() self.toonHead.setDNA(self.toonDNA) self.makeSuit('sc') diff --git a/toontown/coghq/DistributedBanquetTable.py b/toontown/coghq/DistributedBanquetTable.py index 2d3ca4eb..fdb8d76c 100755 --- a/toontown/coghq/DistributedBanquetTable.py +++ b/toontown/coghq/DistributedBanquetTable.py @@ -374,7 +374,7 @@ class DistributedBanquetTable(DistributedObject.DistributedObject, FSM.FSM, Banq deathSuit = diner.getLoseActor() ival = Sequence(Func(self.notify.debug, 'before actorinterval sit-lose'), ActorInterval(diner, 'sit-lose'), Func(self.notify.debug, 'before deathSuit.setHpr'), Func(deathSuit.setHpr, diner.getHpr()), Func(self.notify.debug, 'before diner.hide'), Func(diner.hide), Func(self.notify.debug, 'before deathSuit.reparentTo'), Func(deathSuit.reparentTo, self.chairLocators[chairIndex]), Func(self.notify.debug, 'befor ActorInterval lose'), ActorInterval(deathSuit, 'lose', duration=MovieUtil.SUIT_LOSE_DURATION), Func(self.notify.debug, 'before remove deathsuit'), Func(removeDeathSuit, diner, deathSuit, name='remove-death-suit-%d-%d' % (chairIndex, self.index)), Func(self.notify.debug, 'diner.stash'), Func(diner.stash)) spinningSound = base.loadSfx('phase_3.5/audio/sfx/Cog_Death.ogg') - deathSound = base.loadSfx('phase_3.5/audio/sfx/ENC_cogfall_apart.ogg') + deathSound = base.loadSfx('phase_3.5/audio/sfx/ENC_cogfall_apart_%s.ogg' % random.randint(1, 6)) deathSoundTrack = Sequence(Wait(0.8), SoundInterval(spinningSound, duration=1.2, startTime=1.5, volume=0.2, node=deathSuit), SoundInterval(spinningSound, duration=3.0, startTime=0.6, volume=0.8, node=deathSuit), SoundInterval(deathSound, volume=0.32, node=deathSuit)) intervalName = 'dinerDie-%d-%d' % (self.index, chairIndex) deathIval = Parallel(ival, deathSoundTrack) diff --git a/toontown/coghq/DistributedBattleFactoryAI.py b/toontown/coghq/DistributedBattleFactoryAI.py index c8ef63ed..bd675395 100755 --- a/toontown/coghq/DistributedBattleFactoryAI.py +++ b/toontown/coghq/DistributedBattleFactoryAI.py @@ -22,6 +22,7 @@ class DistributedBattleFactoryAI(DistributedLevelBattleAI.DistributedLevelBattle return self.level.factoryId def handleToonsWon(self, toons): + self.handleCrateReward(toons) for toon in toons: recovered, notRecovered = self.air.questManager.recoverItems(toon, self.suitsKilled, self.getTaskZoneId()) self.toonItems[toon.doId][0].extend(recovered) diff --git a/toontown/coghq/DistributedCogKart.py b/toontown/coghq/DistributedCogKart.py index 25be081f..2384dfa5 100755 --- a/toontown/coghq/DistributedCogKart.py +++ b/toontown/coghq/DistributedCogKart.py @@ -355,8 +355,6 @@ class DistributedCogKart(DistributedElevatorExt.DistributedElevatorExt): if hasattr(base.localAvatar, 'elevatorNotifier'): if reason == ElevatorConstants.REJECT_SHUFFLE: base.localAvatar.elevatorNotifier.showMe(TTLocalizer.ElevatorHoppedOff) - elif reason == ElevatorConstants.REJECT_MINLAFF: - base.localAvatar.elevatorNotifier.showMe(TTLocalizer.KartMinLaff % self.minLaff) elif reason == ElevatorConstants.REJECT_PROMOTION: base.localAvatar.elevatorNotifier.showMe(TTLocalizer.BossElevatorRejectMessage) doneStatus = {'where': 'reject'} diff --git a/toontown/coghq/DistributedCogKartAI.py b/toontown/coghq/DistributedCogKartAI.py index 3026ff45..c0eaa3c7 100755 --- a/toontown/coghq/DistributedCogKartAI.py +++ b/toontown/coghq/DistributedCogKartAI.py @@ -8,9 +8,9 @@ from toontown.toonbase import ToontownGlobals class DistributedCogKartAI(DistributedElevatorExtAI.DistributedElevatorExtAI): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedCogKartAI') - def __init__(self, air, index, x, y, z, h, p, r, bldg, minLaff): + def __init__(self, air, index, x, y, z, h, p, r, bldg): self.posHpr = (x, y, z, h, p, r) - DistributedElevatorExtAI.DistributedElevatorExtAI.__init__(self, air, bldg, minLaff = minLaff) + DistributedElevatorExtAI.DistributedElevatorExtAI.__init__(self, air, bldg) self.type = ElevatorConstants.ELEVATOR_COUNTRY_CLUB self.courseIndex = index if self.courseIndex == 0: diff --git a/toontown/coghq/DistributedCountryClubBattleAI.py b/toontown/coghq/DistributedCountryClubBattleAI.py index 25597265..6950a9e7 100755 --- a/toontown/coghq/DistributedCountryClubBattleAI.py +++ b/toontown/coghq/DistributedCountryClubBattleAI.py @@ -29,6 +29,7 @@ class DistributedCountryClubBattleAI(DistributedLevelBattleAI.DistributedLevelBa amount = ToontownGlobals.CountryClubCogBuckRewards[self.level.countryClubId] index = ToontownGlobals.cogHQZoneId2deptIndex(self.level.countryClubId) extraMerits[index] = amount + self.handleCrateReward(toons) for toon in toons: recovered, notRecovered = self.air.questManager.recoverItems(toon, self.suitsKilled, self.getTaskZoneId()) self.toonItems[toon.doId][0].extend(recovered) diff --git a/toontown/coghq/DistributedFactory.py b/toontown/coghq/DistributedFactory.py index 5aa044b4..c32e2d80 100755 --- a/toontown/coghq/DistributedFactory.py +++ b/toontown/coghq/DistributedFactory.py @@ -28,7 +28,6 @@ class DistributedFactory(DistributedLevel.DistributedLevel, FactoryBase.FactoryB self.joiningReserves = [] self.suitsInitialized = 0 self.goonClipPlanes = {} - base.localAvatar.physControls.setCollisionRayHeight(10.0) def createEntityCreator(self): return FactoryEntityCreator.FactoryEntityCreator(level=self) @@ -39,14 +38,15 @@ class DistributedFactory(DistributedLevel.DistributedLevel, FactoryBase.FactoryB self.factoryViews = FactoryCameraViews.FactoryCameraViews(self) base.localAvatar.chatMgr.chatInputSpeedChat.addFactoryMenu() self.accept('SOSPanelEnter', self.handleSOSPanel) + base.factory = self def delete(self): DistributedLevel.DistributedLevel.delete(self) base.localAvatar.chatMgr.chatInputSpeedChat.removeFactoryMenu() self.factoryViews.delete() del self.factoryViews + del base.factory self.ignore('SOSPanelEnter') - base.localAvatar.physControls.setCollisionRayHeight(CollisionHandlerRayStart) def setFactoryId(self, id): FactoryBase.FactoryBase.setFactoryId(self, id) @@ -166,10 +166,7 @@ def factoryWarp(zoneNum): """ Warp to a specific factory zone. """ - factory = [base.cr.doFind('DistributedFactory'), base.cr.doFind('DistributedMegaCorp')] - for f in factory: - if (not f) or (not isinstance(f, DistributedFactory)): - return 'You must be in a factory.' - factory = f - factory.warpToZone(zoneNum) + if not hasattr(base, 'factory'): + return 'You must be in a factory!' + base.factory.warpToZone(zoneNum) return 'Warped to zone: %d' % zoneNum diff --git a/toontown/coghq/DistributedFactoryElevatorExtAI.py b/toontown/coghq/DistributedFactoryElevatorExtAI.py index 9a2db1a4..b7207812 100755 --- a/toontown/coghq/DistributedFactoryElevatorExtAI.py +++ b/toontown/coghq/DistributedFactoryElevatorExtAI.py @@ -9,8 +9,8 @@ from direct.task import Task class DistributedFactoryElevatorExtAI(DistributedElevatorExtAI.DistributedElevatorExtAI): - def __init__(self, air, bldg, factoryId, entranceId, antiShuffle = 0, minLaff = 0): - DistributedElevatorExtAI.DistributedElevatorExtAI.__init__(self, air, bldg, antiShuffle=antiShuffle, minLaff=minLaff) + def __init__(self, air, bldg, factoryId, entranceId, antiShuffle = 0): + DistributedElevatorExtAI.DistributedElevatorExtAI.__init__(self, air, bldg, antiShuffle=antiShuffle) self.factoryId = factoryId self.entranceId = entranceId diff --git a/toontown/coghq/DistributedLawOfficeElevatorExtAI.py b/toontown/coghq/DistributedLawOfficeElevatorExtAI.py index 15c25014..41161e7a 100755 --- a/toontown/coghq/DistributedLawOfficeElevatorExtAI.py +++ b/toontown/coghq/DistributedLawOfficeElevatorExtAI.py @@ -9,8 +9,8 @@ from toontown.toonbase import ToontownGlobals class DistributedLawOfficeElevatorExtAI(DistributedElevatorExtAI.DistributedElevatorExtAI): - def __init__(self, air, bldg, lawOfficeId, entranceId, antiShuffle = 0, minLaff = 0): - DistributedElevatorExtAI.DistributedElevatorExtAI.__init__(self, air, bldg, antiShuffle = antiShuffle, minLaff = minLaff) + def __init__(self, air, bldg, lawOfficeId, entranceId, antiShuffle = 0): + DistributedElevatorExtAI.DistributedElevatorExtAI.__init__(self, air, bldg, antiShuffle = antiShuffle) self.lawOfficeId = lawOfficeId self.entranceId = entranceId diff --git a/toontown/coghq/DistributedLevelBattle.py b/toontown/coghq/DistributedLevelBattle.py index ad1d758e..2d94a34e 100755 --- a/toontown/coghq/DistributedLevelBattle.py +++ b/toontown/coghq/DistributedLevelBattle.py @@ -89,6 +89,15 @@ class DistributedLevelBattle(DistributedBattle.DistributedBattle): def onWaitingForJoin(self): self.lockLevelViz() + + def announceCrateReward(self): + track = Sequence() + + for i, message in enumerate(TTLocalizer.CrateRewardMessages): + track.append(Func(base.localAvatar.setSystemMessage, 0, message)) + track.append(Wait(1.5)) + + track.start() def __faceOff(self, ts, name, callback): if len(self.suits) == 0: diff --git a/toontown/coghq/DistributedLevelBattleAI.py b/toontown/coghq/DistributedLevelBattleAI.py index 8201ec92..6eac9f16 100755 --- a/toontown/coghq/DistributedLevelBattleAI.py +++ b/toontown/coghq/DistributedLevelBattleAI.py @@ -1,5 +1,6 @@ from toontown.battle import DistributedBattleAI from toontown.battle import DistributedBattleBaseAI +from toontown.catalog import CatalogFurnitureItem from direct.directnotify import DirectNotifyGlobal from direct.fsm import State from direct.fsm import ClassicFSM @@ -96,6 +97,16 @@ class DistributedLevelBattleAI(DistributedBattleAI.DistributedBattleAI): def handleToonsWon(self, toons): pass + + def handleCrateReward(self, toons): + if not (config.GetBool('get-crate-reward-always', False) or random.random() <= 0.25): + return + + self.sendUpdate('announceCrateReward') + item = CatalogFurnitureItem.CatalogFurnitureItem(10040) + + for toon in toons: + toon.addToDeliverySchedule(item) def enterFaceOff(self): self.notify.debug('DistributedLevelBattleAI.enterFaceOff()') diff --git a/toontown/coghq/DistributedMintBattleAI.py b/toontown/coghq/DistributedMintBattleAI.py index 1ffbbfc1..47f5f99c 100755 --- a/toontown/coghq/DistributedMintBattleAI.py +++ b/toontown/coghq/DistributedMintBattleAI.py @@ -28,6 +28,7 @@ class DistributedMintBattleAI(DistributedLevelBattleAI.DistributedLevelBattleAI) amount = ToontownGlobals.MintCogBuckRewards[self.level.mintId] index = ToontownGlobals.cogHQZoneId2deptIndex(self.level.mintId) extraMerits[index] = amount + self.handleCrateReward(toons) for toon in toons: recovered, notRecovered = self.air.questManager.recoverItems(toon, self.suitsKilled, self.getTaskZoneId()) self.toonItems[toon.doId][0].extend(recovered) diff --git a/toontown/coghq/DistributedMintElevatorExtAI.py b/toontown/coghq/DistributedMintElevatorExtAI.py index 7a066b84..d3fd5313 100755 --- a/toontown/coghq/DistributedMintElevatorExtAI.py +++ b/toontown/coghq/DistributedMintElevatorExtAI.py @@ -10,8 +10,8 @@ import CogDisguiseGlobals class DistributedMintElevatorExtAI(DistributedElevatorExtAI.DistributedElevatorExtAI): - def __init__(self, air, bldg, mintId, antiShuffle = 0, minLaff = 0): - DistributedElevatorExtAI.DistributedElevatorExtAI.__init__(self, air, bldg, antiShuffle=antiShuffle, minLaff=minLaff) + def __init__(self, air, bldg, mintId, antiShuffle = 0): + DistributedElevatorExtAI.DistributedElevatorExtAI.__init__(self, air, bldg, antiShuffle=antiShuffle) self.mintId = mintId self.cogDept = ToontownGlobals.cogHQZoneId2deptIndex(self.mintId) self.type = ELEVATOR_MINT diff --git a/toontown/coghq/DistributedStageBattleAI.py b/toontown/coghq/DistributedStageBattleAI.py index da1613d4..32e162ba 100755 --- a/toontown/coghq/DistributedStageBattleAI.py +++ b/toontown/coghq/DistributedStageBattleAI.py @@ -36,6 +36,7 @@ class DistributedStageBattleAI(DistributedLevelBattleAI.DistributedLevelBattleAI amount = ToontownGlobals.StageNoticeRewards[self.level.stageId] index = ToontownGlobals.cogHQZoneId2deptIndex(self.level.stageId) extraMerits[index] = amount + self.handleCrateReward(toons) for toon in toons: recovered, notRecovered = self.air.questManager.recoverItems(toon, self.suitsKilled, self.getTaskZoneId()) self.toonItems[toon.doId][0].extend(recovered) diff --git a/toontown/distributed/ShardStatusReceiver.py b/toontown/distributed/ShardStatusReceiver.py index e7c01afd..e297cdbb 100755 --- a/toontown/distributed/ShardStatusReceiver.py +++ b/toontown/distributed/ShardStatusReceiver.py @@ -5,10 +5,9 @@ class ShardStatusReceiver: self.shards = {} # Accept the shardStatus event: - self.air.netMessenger.accept('shardStatus', self, self.handleShardStatus) + self.air.accept('shardStatus', self.handleShardStatus) - # Query the status of any existing shards: - self.air.netMessenger.send('queryShardStatus') + self.air.sendNetEvent('queryShardStatus') def handleShardStatus(self, channel, status): self.shards.setdefault(channel, {}).update(status) diff --git a/toontown/distributed/ToontownClientRepository.py b/toontown/distributed/ToontownClientRepository.py index ff7dd89f..2a5cdbd8 100755 --- a/toontown/distributed/ToontownClientRepository.py +++ b/toontown/distributed/ToontownClientRepository.py @@ -30,6 +30,7 @@ from toontown.toonbase.ToontownGlobals import * from toontown.distributed import DelayDelete from toontown.friends import FriendHandle from toontown.friends import FriendsListPanel +from toontown.friends import ToontownFriendSecret from toontown.login import AvatarChooser from toontown.makeatoon import MakeAToon from toontown.pets import DistributedPet, PetDetail, PetHandle @@ -184,7 +185,6 @@ class ToontownClientRepository(OTPClientRepository.OTPClientRepository): TexturePool.garbageCollect() self.sendSetAvatarIdMsg(0) self.clearFriendState() - self.startHeartbeat() if self.music == None and base.musicManagerIsValid: self.music = base.musicManager.getSound('phase_3/audio/bgm/tt_theme.ogg') if self.music: @@ -409,6 +409,7 @@ class ToontownClientRepository(OTPClientRepository.OTPClientRepository): if self.objectManager != None: self.objectManager.destroy() self.objectManager = None + ToontownFriendSecret.unloadFriendSecret() FriendsListPanel.unloadFriendsList() messenger.send('cancelFriendInvitation') base.removeGlitchMessage() @@ -664,7 +665,6 @@ class ToontownClientRepository(OTPClientRepository.OTPClientRepository): def removeFriend(self, avatarId): self.ttsFriendsManager.d_removeFriend(avatarId) - base.localAvatar.removeTrueFriends(avatarId) def clearFriendState(self): self.friendsMap = {} diff --git a/toontown/distributed/ToontownDistrict.py b/toontown/distributed/ToontownDistrict.py index f3f38236..53130eb0 100755 --- a/toontown/distributed/ToontownDistrict.py +++ b/toontown/distributed/ToontownDistrict.py @@ -10,3 +10,4 @@ class ToontownDistrict(DistributedDistrict.DistributedDistrict): self.avatarCount = 0 self.invasionStatus = 0 self.suitStatus = '' + self.groupAvCount = [] diff --git a/toontown/distributed/ToontownDistrictAI.py b/toontown/distributed/ToontownDistrictAI.py index a98cb931..b8695e04 100755 --- a/toontown/distributed/ToontownDistrictAI.py +++ b/toontown/distributed/ToontownDistrictAI.py @@ -14,7 +14,7 @@ class ToontownDistrictAI(DistributedDistrictAI): # We want to handle shard status queries so that a ShardStatusReceiver # being created after we're generated will know where we're at: - self.air.netMessenger.accept('queryShardStatus', self, self.handleShardStatusQuery) + self.air.accept('queryShardStatus', self.handleShardStatusQuery) # Send a shard status update with the information we have: status = { @@ -22,12 +22,7 @@ class ToontownDistrictAI(DistributedDistrictAI): 'name': self.name, 'created': int(time.time()) } - self.air.netMessenger.send('shardStatus', [self.air.ourChannel, status]) - - # Add a post remove shard status update in-case we go down: - status = {'available': False} - datagram = self.air.netMessenger.prepare('shardStatus', [self.air.ourChannel, status]) - self.air.addPostRemove(datagram) + self.air.sendNetEvent('shardStatus', [self.air.ourChannel, status]) def handleShardStatusQuery(self): # Send a shard status update with the information we have: @@ -36,18 +31,18 @@ class ToontownDistrictAI(DistributedDistrictAI): 'name': self.name, 'created': int(time.time()) } - self.air.netMessenger.send('shardStatus', [self.air.ourChannel, status]) + self.air.sendNetEvent('shardStatus', [self.air.ourChannel, status]) def setName(self, name): DistributedDistrictAI.setName(self, name) # Send a shard status update containing our name: status = {'name': name} - self.air.netMessenger.send('shardStatus', [self.air.ourChannel, status]) + self.air.sendNetEvent('shardStatus', [self.air.ourChannel, status]) def setAvailable(self, available): DistributedDistrictAI.setAvailable(self, available) # Send a shard status update containing our availability: status = {'available': bool(available)} - self.air.netMessenger.send('shardStatus', [self.air.ourChannel, status]) + self.air.sendNetEvent('shardStatus', [self.air.ourChannel, status]) diff --git a/toontown/distributed/ToontownDistrictStats.py b/toontown/distributed/ToontownDistrictStats.py index 5cd119a7..344e123d 100755 --- a/toontown/distributed/ToontownDistrictStats.py +++ b/toontown/distributed/ToontownDistrictStats.py @@ -75,7 +75,14 @@ class ToontownDistrictStats(DistributedObject.DistributedObject): def setAvatarCount(self, avatarCount): if self.districtId in self.cr.activeDistrictMap: self.cr.activeDistrictMap[self.districtId].avatarCount = avatarCount + messenger.send('shardInfoUpdated') def setInvasionStatus(self, invasionStatus): if self.districtId in self.cr.activeDistrictMap: self.cr.activeDistrictMap[self.districtId].invasionStatus = invasionStatus + messenger.send('shardInfoUpdated') + + def setGroupAvCount(self, groupAvCount): + if self.districtId in self.cr.activeDistrictMap: + self.cr.activeDistrictMap[self.districtId].groupAvCount = groupAvCount + messenger.send('shardInfoUpdated') diff --git a/toontown/distributed/ToontownDistrictStatsAI.py b/toontown/distributed/ToontownDistrictStatsAI.py index 15a615b1..f578ea2a 100755 --- a/toontown/distributed/ToontownDistrictStatsAI.py +++ b/toontown/distributed/ToontownDistrictStatsAI.py @@ -1,5 +1,7 @@ from direct.directnotify.DirectNotifyGlobal import directNotify from direct.distributed.DistributedObjectAI import DistributedObjectAI +from toontown.toonbase import ToontownGlobals +from toontown.toon import DistributedToonAI class ToontownDistrictStatsAI(DistributedObjectAI): notify = directNotify.newCategory('ToontownDistrictStatsAI') @@ -7,18 +9,24 @@ class ToontownDistrictStatsAI(DistributedObjectAI): districtId = 0 avatarCount = 0 invasionStatus = 0 + groupAvCount = [0] * len(ToontownGlobals.GROUP_ZONES) def announceGenerate(self): DistributedObjectAI.announceGenerate(self) # We want to handle shard status queries so that a ShardStatusReceiver # being created after we're generated will know where we're at: - self.air.netMessenger.accept('queryShardStatus', self, self.handleShardStatusQuery) + self.air.accept('queryShardStatus', self.handleShardStatusQuery) + taskMgr.doMethodLater(15, self.__countGroups, self.uniqueName('countGroups')) + + def delete(self): + taskMgr.remove(self.uniqueName('countGroups')) + DistributedObjectAI.delete(self) def handleShardStatusQuery(self): # Send a shard status update containing our population: status = {'population': self.avatarCount} - self.air.netMessenger.send('shardStatus', [self.air.ourChannel, status]) + self.air.sendNetEvent('shardStatus', [self.air.ourChannel, status]) def setDistrictId(self, districtId): self.districtId = districtId @@ -38,7 +46,7 @@ class ToontownDistrictStatsAI(DistributedObjectAI): # Send a shard status update containing our population: status = {'population': self.avatarCount} - self.air.netMessenger.send('shardStatus', [self.air.ourChannel, status]) + self.air.sendNetEvent('shardStatus', [self.air.ourChannel, status]) def d_setAvatarCount(self, avatarCount): self.sendUpdate('setAvatarCount', [avatarCount]) @@ -62,3 +70,27 @@ class ToontownDistrictStatsAI(DistributedObjectAI): def getInvasionStatus(self): return self.invasionStatus + + def setGroupAvCount(self, groupAvCount): + self.groupAvCount = groupAvCount + + def d_setGroupAvCount(self, groupAvCount): + self.sendUpdate('setGroupAvCount', [groupAvCount]) + + def b_setGroupAvCount(self, groupAvCount): + self.setGroupAvCount(groupAvCount) + self.d_setGroupAvCount(groupAvCount) + + def getGroupAvCount(self): + return self.groupAvCount + + def __countGroups(self, task): + zones = ToontownGlobals.GROUP_ZONES + self.groupAvCount = [0] * len(zones) + + for av in self.air.doId2do.values(): + if isinstance(av, DistributedToonAI.DistributedToonAI) and av.isPlayerControlled() and av.zoneId in zones: + self.groupAvCount[zones.index(av.zoneId)] += 1 + + taskMgr.doMethodLater(15, self.__countGroups, self.uniqueName('countGroups')) + self.b_setGroupAvCount(self.groupAvCount) \ No newline at end of file diff --git a/toontown/distributed/ToontownInternalRepository.py b/toontown/distributed/ToontownInternalRepository.py index 084809ad..8a083f4b 100755 --- a/toontown/distributed/ToontownInternalRepository.py +++ b/toontown/distributed/ToontownInternalRepository.py @@ -1,5 +1,9 @@ from direct.distributed.AstronInternalRepository import AstronInternalRepository from otp.distributed.OtpDoGlobals import * +from toontown.distributed.ToontownNetMessengerAI import ToontownNetMessengerAI +from direct.distributed.PyDatagram import PyDatagram +import traceback +import sys class ToontownInternalRepository(AstronInternalRepository): GameGlobalsId = OTP_DO_ID_TOONTOWN @@ -10,20 +14,65 @@ class ToontownInternalRepository(AstronInternalRepository): AstronInternalRepository.__init__( self, baseChannel, serverId=serverId, dcFileNames=dcFileNames, dcSuffix=dcSuffix, connectMethod=connectMethod, threadedNet=threadedNet) - - self.netMessenger.register(0, 'shardStatus') - self.netMessenger.register(1, 'queryShardStatus') - self.netMessenger.register(2, 'startInvasion') - self.netMessenger.register(3, 'stopInvasion') + + def handleConnected(self): + self.__messenger = ToontownNetMessengerAI(self) + if config.GetBool('want-mongo', False): + import pymongo + self.dbConn = pymongo.MongoClient(config.GetString('mongodb-url', 'localhost')) + self.dbGlobalCursor = self.dbConn.toontownstride + self.dbCursor = self.dbGlobalCursor['air-%d' % self.ourChannel] + else: + self.dbConn = None + self.dbGlobalCursor = None + self.dbCursor = None + + def sendNetEvent(self, message, sentArgs=[]): + self.__messenger.send(message, sentArgs) + + def addExitEvent(self, message): + dg = self.__messenger.prepare(message) + self.addPostRemove(dg) + + def handleDatagram(self, di): + msgType = self.getMsgType() + + if msgType == self.__messenger.msgType: + self.__messenger.handle(msgType, di) + return + + AstronInternalRepository.handleDatagram(self, di) def getAvatarIdFromSender(self): - return self.getMsgSender() & 0xFFFFFFFF + return int(self.getMsgSender() & 0xFFFFFFFF) def getAccountIdFromSender(self): - return (self.getMsgSender()>>32) & 0xFFFFFFFF + return int((self.getMsgSender()>>32) & 0xFFFFFFFF) def _isValidPlayerLocation(self, parentId, zoneId): if zoneId < 1000 and zoneId != 1: return False return True + + def readerPollOnce(self): + try: + return AstronInternalRepository.readerPollOnce(self) + + except SystemExit, KeyboardInterrupt: + raise + + except Exception as e: + if self.getAvatarIdFromSender() > 100000000: + dg = PyDatagram() + dg.addServerHeader(self.getMsgSender(), self.ourChannel, CLIENTAGENT_EJECT) + dg.addUint16(166) + dg.addString('You were disconnected to prevent a district reset.') + self.send(dg) + + self.writeServerEvent('INTERNAL-EXCEPTION', self.getAvatarIdFromSender(), self.getAccountIdFromSender(), repr(e), traceback.format_exc()) + self.notify.warning('INTERNAL-EXCEPTION: %s (%s)' % (repr(e), self.getAvatarIdFromSender())) + print traceback.format_exc() + sys.exc_clear() + + return 1 diff --git a/toontown/distributed/ToontownNetMessengerAI.py b/toontown/distributed/ToontownNetMessengerAI.py new file mode 100644 index 00000000..81ef7ff8 --- /dev/null +++ b/toontown/distributed/ToontownNetMessengerAI.py @@ -0,0 +1,35 @@ +from direct.directnotify import DirectNotifyGlobal +from direct.distributed.PyDatagram import PyDatagram +import cPickle, zlib + +class ToontownNetMessengerAI: + """ + This works very much like the NetMessenger class except that + this is much simpler and makes much more sense. + """ + notify = DirectNotifyGlobal.directNotify.newCategory('ToontownNetMessengerAI') + + def __init__(self, air, msgChannel=40000, msgType=54321): + self.air = air + self.air.registerForChannel(msgChannel) + self.msgChannel = msgChannel + self.msgType = msgType + + def prepare(self, message, sentArgs=[]): + dg = PyDatagram() + dg.addServerHeader(self.msgChannel, self.air.ourChannel, self.msgType) + dg.addString(message) + dg.addString(zlib.compress(cPickle.dumps(sentArgs))) + return dg + + def send(self, message, sentArgs=[]): + self.notify.debug('sendNetEvent: %s %r' % (message, sentArgs)) + dg = self.prepare(message, sentArgs) + self.air.send(dg) + + def handle(self, msgType, di): + message = di.getString() + data = zlib.decompress(di.getString()) + sentArgs = cPickle.loads(data) + messenger.send(message, sentArgs) + \ No newline at end of file diff --git a/toontown/estate/DNAFurnitureReaderAI.py b/toontown/estate/DNAFurnitureReaderAI.py index 69fc1678..53248c27 100755 --- a/toontown/estate/DNAFurnitureReaderAI.py +++ b/toontown/estate/DNAFurnitureReaderAI.py @@ -9,9 +9,9 @@ DNA2Furniture = { 'chairA': 100, 'chair': 110, - 'regular_bed': 200, + 'regular_bed': (200, 210), 'FireplaceSq': 400, - 'closetBoy': 500, + 'closetBoy': (500, 510), 'lamp_short': 600, 'lamp_tall': 610, 'couch_1person': 700, @@ -27,7 +27,8 @@ DNA2Furniture = { 'bookcase': 1120, 'bookcase_low': 1130, 'ending_table': 1200, - 'jellybeanBank': 1300 + 'jellybeanBank': 1300, + 'trunkBoy': (4000, 4010) } @@ -38,8 +39,9 @@ class DNAFurnitureReaderAI: # house to the default furniture arrangement. notify = directNotify.newCategory("DNAFurnitureReaderAI") - def __init__(self, dnaData, phonePos): + def __init__(self, dnaData, gender, phonePos): self.dnaData = dnaData + self.gender = gender self.phonePos = phonePos self.itemList = None @@ -69,6 +71,8 @@ class DNAFurnitureReaderAI: itemId = DNA2Furniture[code] if itemId is None: continue + if hasattr(itemId, '__getitem__'): + itemId = itemId[self.gender] x, y, z = child.getPos() h, p, r = child.getHpr() diff --git a/toontown/estate/DistributedAnimatedStatuaryAI.py b/toontown/estate/DistributedAnimatedStatuaryAI.py index 40fe8781..e7ce70d7 100755 --- a/toontown/estate/DistributedAnimatedStatuaryAI.py +++ b/toontown/estate/DistributedAnimatedStatuaryAI.py @@ -4,6 +4,3 @@ from toontown.estate.DistributedStatuaryAI import DistributedStatuaryAI class DistributedAnimatedStatuaryAI(DistributedStatuaryAI): notify = DirectNotifyGlobal.directNotify.newCategory("DistributedAnimatedStatuaryAI") - def __init__(self, air, species): - self.air = air - self.species = species diff --git a/toontown/estate/DistributedCannonAI.py b/toontown/estate/DistributedCannonAI.py index 3562f330..d11cf3e9 100755 --- a/toontown/estate/DistributedCannonAI.py +++ b/toontown/estate/DistributedCannonAI.py @@ -1,101 +1,121 @@ -from direct.directnotify import DirectNotifyGlobal -from direct.distributed.DistributedObjectAI import DistributedObjectAI -from direct.distributed.ClockDelta import * -from toontown.minigame import CannonGameGlobals from toontown.toonbase import ToontownGlobals +from direct.distributed.ClockDelta import * +from direct.fsm import ClassicFSM +from direct.fsm import State +from direct.task import Task +from toontown.minigame import CannonGameGlobals +from direct.distributed import DistributedObjectAI +from toontown.minigame import Trajectory import CannonGlobals -class DistributedCannonAI(DistributedObjectAI): - notify = DirectNotifyGlobal.directNotify.newCategory("DistributedCannonAI") +class DistributedCannonAI(DistributedObjectAI.DistributedObjectAI): + notify = directNotify.newCategory('DistributedCannonAI') - def __init__(self, air): - DistributedObjectAI.__init__(self, air) - self.estateId = 0 - self.targetId = 0 - self.posHpr = (0, 0, 0, 0, 0, 0) - self.bumperPos = ToontownGlobals.PinballCannonBumperInitialPos - self.active = 0 + def __init__(self, air, estateId, targetId, x, y, z, h, p, r): + DistributedObjectAI.DistributedObjectAI.__init__(self, air) + self.posHpr = [x, + y, + z, + h, + p, + r] self.avId = 0 - - def setEstateId(self, estateId): self.estateId = estateId - - def getEstateId(self): - return self.estateId - - def setTargetId(self, targetId): + self.timeoutTask = None self.targetId = targetId + self.cannonBumperPos = list(ToontownGlobals.PinballCannonBumperInitialPos) + return - def getTargetId(self): - return self.targetId + def delete(self): + self.ignoreAll() + self.__stopTimeout() + DistributedObjectAI.DistributedObjectAI.delete(self) - def setPosHpr(self, x, y, z, h, p, r): - self.posHpr = (x, y, z, h, p, r) + def requestEnter(self): + avId = self.air.getAvatarIdFromSender() + if self.avId == 0: + self.avId = avId + self.__stopTimeout() + self.setMovie(CannonGlobals.CANNON_MOVIE_LOAD, self.avId) + self.acceptOnce(self.air.getAvatarExitEvent(avId), self.__handleUnexpectedExit, extraArgs=[avId]) + self.acceptOnce('bootAvFromEstate-' + str(avId), self.__handleBootMessage, extraArgs=[avId]) + self.__startTimeout(CannonGlobals.CANNON_TIMEOUT) + else: + self.air.writeServerEvent('suspicious', avId, 'DistributedCannonAI.requestEnter cannon already occupied') + self.notify.warning('requestEnter() - cannon already occupied') + self.sendUpdateToAvatarId(avId, 'requestExit', []) + + def setMovie(self, mode, avId): + self.avId = avId + self.sendUpdate('setMovie', [mode, avId]) + + def getCannonBumperPos(self): + self.notify.debug('---------getCannonBumperPos %s' % self.cannonBumperPos) + return self.cannonBumperPos + + def requestBumperMove(self, x, y, z): + self.cannonBumperPos = [x, y, z] + self.sendUpdate('setCannonBumperPos', [x, y, z]) def getPosHpr(self): return self.posHpr - def setActive(self, active): - self.active = active - self.sendUpdate("setActiveState", [active]) + def getEstateId(self): + return self.estateId - def requestEnter(self): + def getTargetId(self): + return self.targetId + + def setCannonPosition(self, zRot, angle): avId = self.air.getAvatarIdFromSender() - av = self.air.doId2do.get(avId) - if not av: + self.notify.debug('setCannonPosition: ' + str(avId) + ': zRot=' + str(zRot) + ', angle=' + str(angle)) + self.sendUpdate('updateCannonPosition', [avId, zRot, angle]) + + def setCannonLit(self, zRot, angle): + avId = self.air.getAvatarIdFromSender() + self.__stopTimeout() + self.notify.debug('setCannonLit: ' + str(avId) + ': zRot=' + str(zRot) + ', angle=' + str(angle)) + fireTime = CannonGameGlobals.FUSE_TIME + self.sendUpdate('setCannonWillFire', [avId, + fireTime, + zRot, + angle, + globalClockDelta.getRealNetworkTime()]) + + def setLanded(self): + self.ignore(self.air.getAvatarExitEvent(self.avId)) + self.setMovie(CannonGlobals.CANNON_MOVIE_LANDED, 0) + self.avId = 0 + + def setActive(self, active): + if active < 0 or active > 1: + self.air.writeServerEvent('suspicious', active, 'DistributedCannon.setActive value should be 0-1 range') return + self.active = active + self.sendUpdate('setActiveState', [active]) - if not self.avId: - self.avId = avId - self.d_setMovie(CannonGlobals.CANNON_MOVIE_LOAD) - self.acceptOnce(self.air.getAvatarExitEvent(avId), self.__handleUnexpectedExit, extraArgs=[avId]) - else: - self.air.writeServerEvent('suspicious', avId, 'DistributedCannonAI.requestEnter cannon already occupied') - self.notify.warning('requestEnter() - cannon already occupied') + def __startTimeout(self, timeLimit): + self.__stopTimeout() + self.timeoutTask = taskMgr.doMethodLater(timeLimit, self.__handleTimeout, self.taskName('timeout')) - def setMovie(self, mode, avId, extraInfo): - self.avId = avId - self.sendUpdate('setMovie', [mode, avId, extraInfo]) + def __stopTimeout(self): + if self.timeoutTask != None: + taskMgr.remove(self.timeoutTask) + self.timeoutTask = None + return + + def __handleTimeout(self, task): + self.notify.debug('Timeout expired!') + self.__doExit() + return Task.done def __handleUnexpectedExit(self, avId): self.notify.warning('avatar:' + str(avId) + ' has exited unexpectedly') self.__doExit() - def __doExit(self, movie=CannonGlobals.CANNON_MOVIE_FORCE_EXIT): - self.ignore(self.air.getAvatarExitEvent(self.avId)) - self.d_setMovie(movie) - self.avId = 0 + def __handleBootMessage(self, avId): + self.notify.warning('avatar:' + str(avId) + ' got booted ') + self.__doExit() - def requestExit(self): - pass - - def d_setMovie(self, movie): - self.sendUpdate("setMovie", [movie, self.avId]) - - def setCannonPosition(self, zRot, angle): - self.sendUpdate("updateCannonPosition", [self.avId, zRot, angle]) - - def setCannonLit(self, zRot, angle): - avId = self.air.getAvatarIdFromSender() - if avId != self.avId: - return - - fireTime = CannonGameGlobals.FUSE_TIME - self.sendUpdate('setCannonWillFire', [avId, fireTime, zRot, angle, globalClockDelta.getRealNetworkTime()]) - - def setFired(self): - pass - - def setLanded(self): - self.__doExit(CannonGlobals.CANNON_MOVIE_CLEAR) - self.sendUpdate('setCannonExit', [self.avId]) - - def setCannonExit(self, todo0): - pass - - def requestBumperMove(self, x, y, z): - self.bumperPos = (x, y, z) - self.sendUpdate('setCannonBumperPos', self.getCannonBumperPos()) - - def getCannonBumperPos(self): - return self.bumperPos + def __doExit(self): + self.setMovie(CannonGlobals.CANNON_MOVIE_FORCE_EXIT, self.avId) diff --git a/toontown/estate/DistributedChair.py b/toontown/estate/DistributedChair.py new file mode 100644 index 00000000..b68847bc --- /dev/null +++ b/toontown/estate/DistributedChair.py @@ -0,0 +1,136 @@ +from direct.interval.IntervalGlobal import * +from direct.gui.DirectGui import * +from toontown.catalog import CatalogFurnitureItem +from toontown.toonbase import ToontownGlobals, TTLocalizer +from toontown.toontowngui import TTDialog +from DistributedFurnitureItem import DistributedFurnitureItem + +class DistributedChair(DistributedFurnitureItem): + + def __init__(self, cr): + DistributedFurnitureItem.__init__(self, cr) + self.dialog = None + self.exitButton = None + self.avId = ToontownGlobals.CHAIR_NONE + self.accept('exitingStoppedState', self.destroyGui) + + def loadModel(self): + model = DistributedFurnitureItem.loadModel(self) + cSphere = CollisionSphere(0.0, self.getChair()[3], 1.0, 1.575) + cSphere.setTangible(0) + colNode = CollisionNode('Chair-%s' % self.doId) + colNode.addSolid(cSphere) + cSpherePath = model.attachNewNode(colNode) + cSpherePath.setCollideMask(ToontownGlobals.WallBitmask) + self.accept('enterChair-%s' % self.doId, self.__enterSphere) + return model + + def disable(self): + av = base.cr.doId2do.get(self.avId) + + if av: + self.resetAvatar(av) + + self.ignoreAll() + DistributedFurnitureItem.disable(self) + + def getChair(self): + return CatalogFurnitureItem.ChairToPosHpr[self.item.furnitureType] + + def destroyGui(self): + if self.exitButton: + self.exitButton.destroy() + self.exitButton = None + + if self.dialog: + self.dialog.destroy() + self.dialog = None + + def setupGui(self): + castGui = loader.loadModel('phase_4/models/gui/fishingGui') + self.exitButton = DirectButton(parent=base.a2dBottomRight, relief=None, text=('', TTLocalizer.FishingExit, TTLocalizer.FishingExit), text_align=TextNode.ACenter, text_scale=0.1, text_fg=Vec4(1, 1, 1, 1), text_shadow=Vec4(0, 0, 0, 1), text_pos=(0.0, -0.12), pos=(-0.158, 0, 0.14), image=(castGui.find('**/exit_buttonUp'), castGui.find('**/exit_buttonDown'), castGui.find('**/exit_buttonRollover')), command=self.sendUpdate, extraArgs=['requestSit', [ToontownGlobals.CHAIR_STOP]]) + castGui.removeNode() + + base.localAvatar.stopSleepWatch() + base.localAvatar.startSleepWatch(self.__handleFallingAsleep) + + def resetAvatar(self, av): + av.loop('neutral') + av.setPos(av.getPos(render)) + av.getGeomNode().setHpr(0, 0, 0) + av.setH(self.getH() + self.getChair()[1][0]) + av.reparentTo(render) + + if av == base.localAvatar: + base.localAvatar.setPreventCameraDisable(False) + base.cr.playGame.getPlace().setState('walk') + + def setAvId(self, avId): + if avId == ToontownGlobals.CHAIR_NONE: + self.avId = avId + return + + chair = self.getChair() + av = base.cr.doId2do.get(avId) + + if not av: + return + + sitStartDuration = av.getDuration('sit-start') + sequence = Sequence(Func(av.loop, 'walk'), av.getGeomNode().hprInterval(0.25, chair[1]), Parallel(Sequence(Wait(sitStartDuration * 0.25), av.posInterval(sitStartDuration * 0.25, chair[0])), ActorInterval(av, 'sit-start')), Func(av.setAnimState, 'Sit', 1.0)) + + av.setPosHpr(chair[2], (0, 0, 0)) + av.reparentTo(self) + + if av == base.localAvatar: + base.cr.playGame.getPlace().setState('walk') + base.localAvatar.setPreventCameraDisable(True) + base.cr.playGame.getPlace().setState('stopped') + sequence.append(Func(self.setupGui)) + + sequence.start() + self.avId = avId + + def setStatus(self, status): + av = base.cr.doId2do.get(self.avId) + + if not av: + return + + if status == ToontownGlobals.CHAIR_UNEXPECTED_EXIT: + self.resetAvatar(av) + else: + sitStartDuration = av.getDuration('sit-start') + self.destroyGui() + Sequence(Parallel(ActorInterval(av, 'sit-start', startTime=sitStartDuration, endTime=0.0), Sequence(Wait(sitStartDuration * 0.25), av.posInterval(sitStartDuration * 0.25, self.getChair()[2]))), Func(self.resetAvatar, av)).start() + + def resetAvatar(self, av): + av.loop('neutral') + av.setPos(av.getPos(render)) + av.getGeomNode().setHpr(0, 0, 0) + av.setH(self.getH() + self.getChair()[1][0]) + av.reparentTo(render) + + if av == base.localAvatar: + base.localAvatar.setPreventCameraDisable(False) + base.cr.playGame.getPlace().setState('walk') + self.destroyGui() + + def __enterSphere(self, collisionEntry): + if self.avId in base.cr.doId2do: + return + + base.cr.playGame.getPlace().setState('stopped') + self.dialog = TTDialog.TTDialog(style=TTDialog.TwoChoice, text=TTLocalizer.ChairAskToUse, fadeScreen=1, command=self.__handleDialogResponse) + + def __handleDialogResponse(self, response): + self.destroyGui() + + if response < 0: + base.cr.playGame.getPlace().setState('walk') + return + + self.sendUpdate('requestSit', [ToontownGlobals.CHAIR_START]) + + def __handleFallingAsleep(self, arg): + self.sendUpdate('requestSit', [ToontownGlobals.CHAIR_STOP]) \ No newline at end of file diff --git a/toontown/estate/DistributedChairAI.py b/toontown/estate/DistributedChairAI.py new file mode 100644 index 00000000..a07d58c7 --- /dev/null +++ b/toontown/estate/DistributedChairAI.py @@ -0,0 +1,57 @@ +from toontown.catalog import CatalogAccessoryItem, CatalogClothingItem, CatalogNametagItem, CatalogEmoteItem +from toontown.catalog.CatalogAccessoryItemGlobals import * +from toontown.toonbase import ToontownGlobals, TTLocalizer +from toontown.toon import ToonDNA +from toontown.quest import Quests +from DistributedFurnitureItemAI import DistributedFurnitureItemAI +import random, time + +class DistributedChairAI(DistributedFurnitureItemAI): + + def __init__(self, air, furnitureMgr, itemType): + DistributedFurnitureItemAI.__init__(self, air, furnitureMgr, itemType) + self.avId = ToontownGlobals.CHAIR_NONE + + def destroy(self): + self.ignoreAll() + DistributedFurnitureItemAI.destroy(self) + + def b_setAvId(self, avId): + self.avId = avId + self.sendUpdate('setAvId', [avId]) + + def b_resetAvId(self): + self.b_setAvId(ToontownGlobals.CHAIR_NONE) + + def b_resetAvWithAnim(self, reason): + self.sendUpdate('setStatus', [reason]) + self.b_resetAvId() + + def getAvId(self): + return self.avId + + def getSitResponse(self): + return ToontownGlobals.CHAIR_NONE + + def requestSit(self, requestCode): + avId = self.air.getAvatarIdFromSender() + av = self.air.doId2do.get(avId) + + if not av: + return + + if requestCode == ToontownGlobals.CHAIR_START: + if self.avId in self.air.doId2do: + return + + self.b_setAvId(avId) + self.acceptOnce(self.air.getAvatarExitEvent(avId), self.__handleUnexpectedExit) + elif requestCode == ToontownGlobals.CHAIR_STOP: + if self.avId != avId: + return + + self.b_resetAvWithAnim(ToontownGlobals.CHAIR_EXIT) + self.ignoreAll() + + def __handleUnexpectedExit(self): + self.b_resetAvWithAnim(ToontownGlobals.CHAIR_UNEXPECTED_EXIT) \ No newline at end of file diff --git a/toontown/estate/DistributedChangingStatuaryAI.py b/toontown/estate/DistributedChangingStatuaryAI.py index 36641bf5..cbdc1877 100755 --- a/toontown/estate/DistributedChangingStatuaryAI.py +++ b/toontown/estate/DistributedChangingStatuaryAI.py @@ -4,13 +4,6 @@ from toontown.estate.DistributedStatuaryAI import DistributedStatuaryAI class DistributedChangingStatuaryAI(DistributedStatuaryAI): notify = DirectNotifyGlobal.directNotify.newCategory("DistributedChangingStatuaryAI") - def __init__(self, air): - DistributedStatuaryAI.__init__(self, air) - self.air = air - self.growthLevel = -1 + def setGrowthLevel(self, todo0): + pass - def setGrowthLevel(self, growthLevel): - self.growthLevel = growthLevel - - def getGrowthLevel(self): - return self.growthLevel diff --git a/toontown/estate/DistributedEstate.py b/toontown/estate/DistributedEstate.py index e3e9cf69..a14acdbf 100755 --- a/toontown/estate/DistributedEstate.py +++ b/toontown/estate/DistributedEstate.py @@ -6,29 +6,16 @@ from direct.interval.IntervalGlobal import * import math from toontown.toonbase import ToontownGlobals from direct.distributed import DistributedObject -from direct.directnotify import DirectNotifyGlobal -from direct.fsm import ClassicFSM -from direct.fsm import State -from toontown.toon import Toon -from direct.showbase import RandomNumGen from direct.task.Task import Task from toontown.toonbase import TTLocalizer import random import cPickle import time -from direct.showbase import PythonUtil -from toontown.hood import Place -import Estate import HouseGlobals from toontown.estate import GardenGlobals -from toontown.estate import DistributedFlower -from toontown.estate import DistributedGagTree -from toontown.estate import DistributedStatuary -import GardenDropGame -import GardenProgressMeter from toontown.estate import FlowerSellGUI -from toontown.fishing import FishSellGUI from toontown.toontowngui import TTDialog +from toontown.fishing import FishSellGUI class DistributedEstate(DistributedObject.DistributedObject): notify = directNotify.newCategory('DistributedEstate') @@ -46,18 +33,15 @@ class DistributedEstate(DistributedObject.DistributedObject): self.initCamera() self.plotTable = [] self.idList = [] - base.estate = self self.flowerGuiDoneEvent = 'flowerGuiDone' self.fishGuiDoneEvent = 'fishGuiDone' - return def disable(self): self.notify.debug('disable') self.__stopBirds() self.__stopCrickets() DistributedObject.DistributedObject.disable(self) - self.ignore('enterFlowerSellBox') - self.ignore('enterFishSellBox') + self.ignoreAll() def delete(self): self.notify.debug('delete') @@ -67,7 +51,6 @@ class DistributedEstate(DistributedObject.DistributedObject): def load(self): self.defaultSignModel = loader.loadModel('phase_13/models/parties/eventSign') self.activityIconsModel = loader.loadModel('phase_4/models/parties/eventSignIcons') - self.lt = base.localAvatar if base.cr.newsManager.isHolidayRunning(ToontownGlobals.HALLOWEEN): self.loadWitch() else: @@ -76,8 +59,6 @@ class DistributedEstate(DistributedObject.DistributedObject): self.loadFishSellBox() self.oldClear = base.win.getClearColor() base.win.setClearColor(Vec4(0.09, 0.55, 0.21, 1.0)) - if config.GetBool('want-garden-game', False): - self.startGame() def unload(self): self.ignoreAll() @@ -108,19 +89,9 @@ class DistributedEstate(DistributedObject.DistributedObject): self.fishSellBox.removeNode() del self.fishSellBox self.fishSellBox = None - if config.GetBool('want-garden-game', False): - GardenDropGame.GardenDropGame().endGame() - return def announceGenerate(self): DistributedObject.DistributedObject.announceGenerate(self) - self.accept('gardenGame', self.startGame) - - def startGame(self): - if config.GetBool('want-garden-game', False): - self.game = GardenDropGame.GardenDropGame().playGardenDrop() - else: - self.game = GardenDropGame.GardenDropGame() def loadAirplane(self): self.airplane = loader.loadModel('phase_4/models/props/airplane.bam') @@ -131,12 +102,14 @@ class DistributedEstate(DistributedObject.DistributedObject): bannerText.setTextColor(1, 0, 0, 1) bannerText.setAlign(bannerText.ACenter) bannerText.setFont(ToontownGlobals.getSignFont()) - bannerText.setText('Cog invasion!!!') + bannerText.setText(TTLocalizer.EstatePlaneReturn) self.bn = self.banner.attachNewNode(bannerText.generate()) self.bn.setHpr(180, 0, 0) - self.bn.setPos(-1.8, 0.1, 0) - self.bn.setScale(0.35) - self.banner.hide() + self.bn.setPos(-5.8, 0.1, -0.25) + self.bn.setScale(0.95) + self.bn.setDepthTest(1) + self.bn.setDepthWrite(1) + self.bn.setDepthOffset(500) def loadWitch(self): if not self.airplane: @@ -148,15 +121,19 @@ class DistributedEstate(DistributedObject.DistributedObject): self.airplane = loader.loadModel('phase_4/models/props/tt_m_prp_ext_flyingWitch.bam') self.airplane.setScale(2) self.airplane.setPos(0, 0, 1) + self.airplane.find('**/').setH(180) bannerText = TextNode('bannerText') bannerText.setTextColor(1, 0, 0, 1) bannerText.setAlign(bannerText.ACenter) bannerText.setFont(ToontownGlobals.getSignFont()) - bannerText.setText('Happy halloween!!!') + bannerText.setText(TTLocalizer.EstatePlaneHoliday) self.bn = self.airplane.attachNewNode(bannerText.generate()) - self.bn.setHpr(0, 0, 0) - self.bn.setPos(20.0, -.1, 0) + self.bn.setPos(-20.0, -.1, 0) + self.bn.setH(180) self.bn.setScale(2.35) + self.bn.setDepthTest(1) + self.bn.setDepthWrite(1) + self.bn.setDepthOffset(500) replacement = Sequence(LerpColorScaleInterval(self.airplane, 0.1, Vec4(1, 1, 1, 0)), Func(__replaceAirplane__), LerpColorScaleInterval(self.airplane, 0.1, Vec4(1, 1, 1, 1))) replacement.start() @@ -175,12 +152,14 @@ class DistributedEstate(DistributedObject.DistributedObject): bannerText.setTextColor(1, 0, 0, 1) bannerText.setAlign(bannerText.ACenter) bannerText.setFont(ToontownGlobals.getSignFont()) - bannerText.setText('Happy halloween!!!') + bannerText.setText(TTLocalizer.EstatePlaneReturn) self.bn = self.banner.attachNewNode(bannerText.generate()) self.bn.setHpr(180, 0, 0) - self.bn.setPos(-1.8, 0.1, 0) - self.bn.setScale(0.35) - self.banner.hide() + self.bn.setPos(-5.8, 0.1, -0.25) + self.bn.setScale(0.95) + self.bn.setDepthTest(1) + self.bn.setDepthWrite(1) + self.bn.setDepthOffset(500) replacement = Sequence(LerpColorScaleInterval(self.airplane, 0.1, Vec4(1, 1, 1, 0)), Func(__replaceWitch__), LerpColorScaleInterval(self.airplane, 0.1, Vec4(1, 1, 1, 1))) replacement.start() @@ -189,6 +168,9 @@ class DistributedEstate(DistributedObject.DistributedObject): initCamPos = VBase3(0, -10, 5) initCamHpr = VBase3(0, -10, 0) + def setEstateType(self, index): + self.estateType = index + def setHouseInfo(self, houseInfo): self.notify.debug('setHouseInfo') houseType, housePos = cPickle.loads(houseInfo) @@ -200,7 +182,6 @@ class DistributedEstate(DistributedObject.DistributedObject): self.housePos = posList self.numHouses = len(self.houseType) self.house = [None] * self.numHouses - return def __startAirplaneTask(self): self.theta = 0 @@ -211,7 +192,7 @@ class DistributedEstate(DistributedObject.DistributedObject): def __pauseAirplaneTask(self): pause = 45 self.phi = 0 - self.airplane.hide() + self.airplane.reparentTo(hidden) self.theta = (self.theta + 10) % 360 taskMgr.remove(self.taskName('estate-airplane')) taskMgr.doMethodLater(pause, self.airplaneFlyTask, self.taskName('estate-airplane')) @@ -232,7 +213,7 @@ class DistributedEstate(DistributedObject.DistributedObject): y = rad * math.sin(angle) z = amp * sinPhi self.airplane.reparentTo(render) - self.airplane.setH(90 + self.theta + 180) + self.airplane.setH(90 + self.theta) self.airplane.setPos(x, y, z) return Task.cont @@ -280,7 +261,7 @@ class DistributedEstate(DistributedObject.DistributedObject): def __dayTimeTask(self, task): taskName = self.taskName('daytime') - track = Sequence(Parallel(LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, HouseGlobals.HALF_DAY_PERIOD, Vec4(1, 0.6, 0.6, 1)), LerpColorScaleInterval(base.cr.playGame.hood.sky, HouseGlobals.HALF_DAY_PERIOD, Vec4(1, 0.8, 0.8, 1))), Parallel(LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, HouseGlobals.HALF_NIGHT_PERIOD, Vec4(0.2, 0.2, 0.5, 1)), LerpColorScaleInterval(base.cr.playGame.hood.sky, HouseGlobals.HALF_NIGHT_PERIOD, Vec4(0.4, 0.4, 0.6, 1))), Parallel(LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, HouseGlobals.HALF_NIGHT_PERIOD, Vec4(0.6, 0.6, 0.8, 1)), LerpColorScaleInterval(base.cr.playGame.hood.sky, HouseGlobals.HALF_NIGHT_PERIOD, Vec4(0.7, 0.7, 0.8, 1))), Parallel(LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, HouseGlobals.HALF_DAY_PERIOD, Vec4(1, 1, 1, 1)), LerpColorScaleInterval(base.cr.playGame.hood.sky, HouseGlobals.HALF_DAY_PERIOD, Vec4(1, 1, 1, 1))), Func(base.cr.playGame.hood.loader.geom.clearColorScale), Func(base.cr.playGame.hood.sky.clearColorScale)) + track = Sequence(Parallel(LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, HouseGlobals.HALF_DAY_PERIOD, Vec4(1, 0.6, 0.6, 1)), LerpColorScaleInterval(base.cr.playGame.hood.sky, HouseGlobals.HALF_DAY_PERIOD, Vec4(1, 0.8, 0.8, 1))), Parallel(LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, HouseGlobals.HALF_NIGHT_PERIOD, Vec4(0.2, 0.2, 0.5, 1)), LerpColorScaleInterval(base.cr.playGame.hood.sky, HouseGlobals.HALF_NIGHT_PERIOD, Vec4(0.2, 0.2, 0.4, 1))), Parallel(LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, HouseGlobals.HALF_NIGHT_PERIOD, Vec4(0.6, 0.6, 0.8, 1)), LerpColorScaleInterval(base.cr.playGame.hood.sky, HouseGlobals.HALF_NIGHT_PERIOD, Vec4(0.5, 0.5, 0.6, 1))), Parallel(LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, HouseGlobals.HALF_DAY_PERIOD, Vec4(1, 1, 1, 1)), LerpColorScaleInterval(base.cr.playGame.hood.sky, HouseGlobals.HALF_DAY_PERIOD, Vec4(1, 1, 1, 1))), Func(base.cr.playGame.hood.loader.geom.clearColorScale), Func(base.cr.playGame.hood.sky.clearColorScale)) if self.dayTrack: self.dayTrack.finish() self.dayTrack = track @@ -344,8 +325,8 @@ class DistributedEstate(DistributedObject.DistributedObject): taskMgr.doMethodLater(1, self.__crickets, 'estate-crickets') def __crickets(self, task): - sfx = random.choice(base.cr.playGame.hood.loader.cricketSound) - track = Sequence(Func(base.playSfx, sfx), Wait(1)) + sfx = base.cr.playGame.hood.loader.cricketSound + track = Sequence(Func(base.playSfx, random.choice(sfx)), Wait(1)) track.start() t = random.random() * 20.0 + 1 taskMgr.doMethodLater(t, self.__crickets, 'estate-crickets') @@ -376,7 +357,7 @@ class DistributedEstate(DistributedObject.DistributedObject): if len(base.localAvatar.flowerBasket.flowerList): self.popupFlowerGUI() - def __handleFlowerSaleDone(self, sell = 0): + def __handleSaleDone(self, sell = 0): self.ignore(self.flowerGuiDoneEvent) self.sendUpdate('completeFlowerSale', [sell]) self.ignore('stoppedAsleep') @@ -384,10 +365,10 @@ class DistributedEstate(DistributedObject.DistributedObject): self.flowerGui = None def popupFlowerGUI(self): - self.acceptOnce(self.flowerGuiDoneEvent, self.__handleFlowerSaleDone) + self.acceptOnce(self.flowerGuiDoneEvent, self.__handleSaleDone) self.flowerGui = FlowerSellGUI.FlowerSellGUI(self.flowerGuiDoneEvent) self.accept('stoppedAsleep', self.__handleSaleDone) - + def loadFishSellBox(self): self.fishSellBox = loader.loadModel('phase_4/models/minigames/treasure_chest.bam') self.fishSellBox.setPos(45, -165.75, 0.025) @@ -408,10 +389,14 @@ class DistributedEstate(DistributedObject.DistributedObject): self.popupFishGUI() def __handleFishSaleDone(self, sell=0): + if sell: + self.sendUpdate('completeFishSale') + else: + base.localAvatar.setSystemMessage(0, TTLocalizer.STOREOWNER_NOFISH) + base.setCellsAvailable(base.bottomCells, 1) base.cr.playGame.getPlace().setState('walk') self.ignore(self.fishGuiDoneEvent) - self.sendUpdate('completeFishSale', [sell]) self.ignore('stoppedAsleep') self.fishGui.destroy() self.fishGui = None @@ -428,8 +413,6 @@ class DistributedEstate(DistributedObject.DistributedObject): base.localAvatar.setSystemMessage(0, TTLocalizer.STOREOWNER_TROPHY % (fish, maxFish)) elif mode == ToontownGlobals.FISHSALE_COMPLETE: base.localAvatar.setSystemMessage(0, TTLocalizer.STOREOWNER_THANKSFISH) - elif mode == ToontownGlobals.FISHSALE_NONE: - base.localAvatar.setSystemMessage(0, TTLocalizer.STOREOWNER_NOFISH) def closedAwardDialog(self, value): self.awardDialog.destroy() diff --git a/toontown/estate/DistributedEstateAI.py b/toontown/estate/DistributedEstateAI.py index 048776a3..172504a1 100755 --- a/toontown/estate/DistributedEstateAI.py +++ b/toontown/estate/DistributedEstateAI.py @@ -1,73 +1,434 @@ from direct.directnotify import DirectNotifyGlobal from direct.distributed.DistributedObjectAI import DistributedObjectAI from toontown.toonbase import ToontownGlobals +import HouseGlobals +import time, random + from toontown.fishing.DistributedFishingPondAI import DistributedFishingPondAI -from toontown.fishing.DistributedFishingTargetAI import DistributedFishingTargetAI from toontown.fishing.DistributedPondBingoManagerAI import DistributedPondBingoManagerAI -from toontown.fishing import FishingTargetGlobals -from toontown.safezone.DistributedFishingSpotAI import DistributedFishingSpotAI +from toontown.fishing import FishingTargetGlobals, FishGlobals +from toontown.safezone import TreasureGlobals from toontown.safezone.SZTreasurePlannerAI import SZTreasurePlannerAI from toontown.safezone import DistributedTreasureAI -from toontown.safezone import TreasureGlobals +from toontown.safezone import ButterflyGlobals +from toontown.safezone import DistributedButterflyAI +from toontown.safezone.DistributedFishingSpotAI import DistributedFishingSpotAI +from toontown.parties.DistributedPartyJukeboxActivityAI import DistributedPartyJukeboxActivityAI + +from DistributedGardenBoxAI import * +from DistributedGardenPlotAI import * +from DistributedGagTreeAI import * +from DistributedFlowerAI import * +from DistributedStatuaryAI import * +from DistributedToonStatuaryAI import * +from DistributedAnimatedStatuaryAI import * +from DistributedChangingStatuaryAI import * +import GardenGlobals + from DistributedCannonAI import * from DistributedTargetAI import * import CannonGlobals -import TableGlobals -import HouseGlobals -import GardenGlobals -from DistributedGardenPlotAI import DistributedGardenPlotAI -from DistributedGardenBoxAI import DistributedGardenBoxAI -from DistributedFlowerAI import DistributedFlowerAI -from DistributedGagTreeAI import DistributedGagTreeAI -from DistributedStatuaryAI import DistributedStatuaryAI -from DistributedToonStatuaryAI import DistributedToonStatuaryAI -import time -import random -from toontown.fishing import FishGlobals -from toontown.parties.DistributedPartyJukeboxActivityAI import DistributedPartyJukeboxActivityAI + +# planted, waterLevel, lastCheck, growthLevel, optional +NULL_PLANT = [-1, -1, 0, 0, 0] +NULL_TREES = [NULL_PLANT] * 8 +NULL_FLOWERS = [NULL_PLANT] * 10 +NULL_STATUARY = 0 + +NULL_DATA = {'trees': NULL_TREES, 'statuary': NULL_STATUARY, 'flowers': NULL_FLOWERS} + +from direct.distributed.PyDatagramIterator import * +from direct.distributed.PyDatagram import * + +class Garden: + notify = DirectNotifyGlobal.directNotify.newCategory('DistributedEstateAI') + + WANT_FLOWERS = True # puke + WANT_TREES = True + WANT_STATUARY = True + + def __init__(self, air, avId): + self.air = air + self.avId = avId + + self.trees = set() + self.flowers = set() + self.objects = set() + + if not self.air.dbConn: + self.notify.warning('Not using mongodb, garden data will be non-persistent') + self.data = NULL_DATA.copy() + + else: + d = self.air.dbGlobalCursor.gardens.find_one({'avId': avId}) + if d is None: + self.data = NULL_DATA.copy() + self.air.dbGlobalCursor.gardens.update({'avId': avId}, {'$set': NULL_DATA}, upsert=True) + + else: + self.data = d + + self.data.pop('_id', None) + + def destroy(self): + messenger.send('garden-%d-666-going-down' % self.avId) + + for tree in self.trees: + tree.requestDelete() + + for flower in self.flowers: + flower.requestDelete() + + for object in self.objects: + object.requestDelete() + + self.air = None + self.estateMgr = None + + def create(self, estateMgr): + self.estateMgr = estateMgr + + if self.avId not in estateMgr.toons: + estateMgr.notify.warning('Garden associated to unknown avatar %d, deleting...' % self.avId) + return False + + houseIndex = estateMgr.toons.index(self.avId) + + if self.WANT_FLOWERS: + boxIndex = 0 + boxes = [] + boxDefs = GardenGlobals.estateBoxes[houseIndex] + for x, y, h, boxType in boxDefs: + box = DistributedGardenBoxAI(self) + + box.setTypeIndex(boxType) + box.setPos(x, y, 0) + box.setH(h) + box.setOwnerIndex(houseIndex) + box.generateWithRequired(estateMgr.zoneId) + + self.objects.add(box) + boxes.append(box) + boxIndex += 1 + + self._boxes = boxes + + plots = GardenGlobals.estatePlots[houseIndex] + treeIndex = 0 + flowerIndex = 0 + for plot, (x, y, h, type) in enumerate(plots): + if type == GardenGlobals.GAG_TREE_TYPE and self.WANT_TREES: + data = self.data['trees'][treeIndex] + + planted, waterLevel, lastCheck, growthLevel, lastHarvested = data + + if planted != -1: + obj = self.plantTree(treeIndex, planted, waterLevel=waterLevel, + lastCheck=lastCheck, growthLevel=growthLevel, + lastHarvested=lastHarvested, generate=False) + + self.trees.add(obj) + + else: + obj = self.placePlot(treeIndex) + + obj.setPos(x, y, 0) + obj.setH(h) + obj.setPlot(plot) + obj.setOwnerIndex(houseIndex) + obj.generateWithRequired(estateMgr.zoneId) + treeIndex += 1 + + elif type == GardenGlobals.FLOWER_TYPE and self.WANT_FLOWERS: + data = self.data['flowers'][flowerIndex] + + planted, waterLevel, lastCheck, growthLevel, variety = data + + if planted != -1: + obj = self.plantFlower(flowerIndex, planted, variety, waterLevel=waterLevel, + lastCheck=lastCheck, growthLevel=growthLevel, + generate=False) + + else: + obj = self.placePlot(flowerIndex) + obj.flowerIndex = flowerIndex + + obj.setPlot(plot) + obj.setOwnerIndex(houseIndex) + obj.generateWithRequired(estateMgr.zoneId) + + index = (0, 1, 2, 2, 2, 3, 3, 3, 4, 4)[flowerIndex] + idx = (0, 0, 0, 1, 2, 0, 1, 2, 0, 1)[flowerIndex] + obj.sendUpdate('setBoxDoId', [boxes[index].doId, idx]) + flowerIndex += 1 + + elif type == GardenGlobals.STATUARY_TYPE and self.WANT_STATUARY: + data = self.data['statuary'] + if data == 0: + obj = self.placePlot(-1) + + else: + obj = self.placeStatuary(data, generate=False) + + obj.setPos(x, y, 0) + obj.setH(h) + obj.setPlot(plot) + obj.setOwnerIndex(houseIndex) + obj.generateWithRequired(estateMgr.zoneId) + + for tree in self.trees: + tree.calcDependencies() + + self.reconsiderAvatarOrganicBonus() + + return True + + def hasTree(self, track, index): + x = track * 7 + index + for tree in self.data['trees']: + if tree[0] == x: + return True + + return False + + def getTree(self, track, index): + for tree in self.trees: + if tree.typeIndex == track * 7 + index: + return tree + + def plantTree(self, treeIndex, value, plot=None, waterLevel=-1, + lastCheck=0, growthLevel=0, lastHarvested=0, + ownerIndex=-1, plotId=-1, pos=None, generate=True): + if not self.air: + return + + if plot: + if plot not in self.objects: + return + + plot.requestDelete() + self.objects.remove(plot) + + tree = DistributedGagTreeAI(self) + + tree.setTypeIndex(value) + tree.setWaterLevel(waterLevel) + tree.setGrowthLevel(growthLevel) + if ownerIndex != -1: + tree.setOwnerIndex(ownerIndex) + + if plotId != -1: + tree.setPlot(plotId) + + if pos is not None: + pos, h = pos + tree.setPos(pos) + tree.setH(h) + + tree.treeIndex = treeIndex + tree.calculate(lastHarvested, lastCheck) + self.trees.add(tree) + + if generate: + tree.generateWithRequired(self.estateMgr.zoneId) + + return tree + + def placePlot(self, treeIndex): + obj = DistributedGardenPlotAI(self) + obj.treeIndex = treeIndex + self.objects.add(obj) + + return obj + + def plantFlower(self, flowerIndex, species, variety, plot=None, waterLevel=-1, + lastCheck=0, growthLevel=0, ownerIndex=-1, plotId=-1, generate=True): + if not self.air: + return + + if plot: + if plot not in self.objects: + return + + plot.requestDelete() + self.objects.remove(plot) + + flower = DistributedFlowerAI(self) + + flower.setTypeIndex(species) + flower.setVariety(variety) + flower.setWaterLevel(waterLevel) + flower.setGrowthLevel(growthLevel) + if ownerIndex != -1: + flower.setOwnerIndex(ownerIndex) + + if plotId != -1: + flower.setPlot(plotId) + + flower.flowerIndex = flowerIndex + flower.calculate(lastCheck) + self.flowers.add(flower) + + if generate: + flower.generateWithRequired(self.estateMgr.zoneId) + + return flower + + def placeStatuary(self, data, plot=None, plotId=-1, ownerIndex=-1, + pos=None, generate=True): + if not self.air: + return + + if plot: + if plot not in self.objects: + return + + plot.requestDelete() + self.objects.remove(plot) + + data, lastCheck, index, growthLevel = self.S_unpack(data) + + dclass = DistributedStatuaryAI + if index in GardenGlobals.ToonStatuaryTypeIndices: + dclass = DistributedToonStatuaryAI + + elif index in GardenGlobals.ChangingStatuaryTypeIndices: + dclass = DistributedChangingStatuaryAI + + elif index in GardenGlobals.AnimatedStatuaryTypeIndices: + dclass = DistributedAnimatedStatuaryAI + + obj = dclass(self) + obj.growthLevel = growthLevel + obj.index = index + obj.data = data + + if ownerIndex != -1: + obj.setOwnerIndex(ownerIndex) + + if plotId != -1: + obj.setPlot(plotId) + + if pos is not None: + pos, h = pos + obj.setPos(pos) + obj.setH(h) + + obj.calculate(lastCheck) + + self.objects.add(obj) + + if generate: + obj.announceGenerate() + + return obj + + # Data structure + # VERY HIGH (vh) (64-bit) + # high high (H) = data (32-bit) + # high low (L) = lastCheck (32-bit) + # VERY LOW (vl) (16-bit) + # low high (h) = index (8-bit) + # low low (l) = growthLevel (8-bit) + + @staticmethod + def S_pack(data, lastCheck, index, growthLevel): + vh = data << 32 | lastCheck + vl = index << 8 | growthLevel + + return vh << 16 | vl + + @staticmethod + def S_unpack(x): + vh = x >> 16 + vl = x & 0xFFFF + + data = vh >> 32 + lastCheck = vh & 0xFFFFFFFF + + index = vl >> 8 + growthLevel = vl & 0xFF + + return data, lastCheck, index, growthLevel + + def getNullPlant(self): + return NULL_PLANT + + def reconsiderAvatarOrganicBonus(self): + av = self.air.doId2do.get(self.avId) + if not av: + return + + bonus = [-1] * 7 + for track in xrange(7): + for level in xrange(8):#7 + if not self.hasTree(track, level): + break + + tree = self.getTree(track, level) + if tree.getGrowthLevel() < tree.growthThresholds[1] or tree.getWilted(): + break + + bonus[track] = level - 1 + + av.b_setTrackBonusLevel(bonus) + + def update(self): + if self.air.dbConn: + self.air.dbGlobalCursor.gardens.update({'avId': self.avId}, {'$set': self.data}, upsert=True) + +class GardenManager: + def __init__(self, mgr): + self.mgr = mgr + self.gardens = {} + + def handleSingleGarden(self, avId): + g = Garden(self.mgr.air, avId) + g.gardenMgr = self + res = g.create(self.mgr) + if res: + self.gardens[avId] = g + + def destroy(self): + for garden in self.gardens.values(): + garden.destroy() + + del self.gardens class Rental: - def __init__(self, estate): self.estate = estate self.objects = set() - + def destroy(self): del self.estate - for obj in self.objects: - if not obj.isDeleted(): - obj.requestDelete() - taskMgr.remove(obj.uniqueName('delete')) + for object in self.objects: + if not object.isDeleted(): + object.requestDelete() + taskMgr.remove(object.uniqueName('delete')) self.objects = set() - + class CannonRental(Rental): - - def __init__(self, estate): - Rental.__init__(self, estate) - def generateObjects(self): target = DistributedTargetAI(self.estate.air) target.generateWithRequired(self.estate.zoneId) - + for drop in CannonGlobals.cannonDrops: - cannon = DistributedCannonAI(self.estate.air) - cannon.setEstateId(self.estate.doId) - cannon.setTargetId(target.doId) - cannon.setPosHpr(*drop) + cannon = DistributedCannonAI(self.estate.air, self.estate.zoneId, target.doId, *drop) cannon.generateWithRequired(self.estate.zoneId) self.objects.add(cannon) - + self.generateTreasures() self.estate.b_setClouds(1) - + def destroy(self): self.estate.b_setClouds(0) Rental.destroy(self) - + def generateTreasures(self): doIds = [] z = 35 - + for i in xrange(20): x = random.randint(100, 300) - 200 y = random.randint(100, 300) - 200 @@ -75,20 +436,21 @@ class CannonRental(Rental): treasure.generateWithRequired(self.estate.zoneId) self.objects.add(treasure) doIds.append(treasure.doId) - - self.estate.sendUpdate("setTreasureIds", [doIds]) - + + self.estate.sendUpdate('setTreasureIds', [doIds]) + def grabAttempt(self, avId, treasureId): av = self.estate.air.doId2do.get(avId) if av == None: self.estate.air.writeServerEvent('suspicious', avId, 'TreasurePlannerAI.grabAttempt unknown avatar') self.estate.notify.warning('avid: %s does not exist' % avId) return - + treasure = self.estate.air.doId2do.get(treasureId) if self.validAvatar(av): treasure.d_setGrab(avId) self.deleteTreasureSoon(treasure) + else: treasure.d_setReject() @@ -98,70 +460,60 @@ class CannonRental(Rental): def __deleteTreasureNow(self, treasure, taskName): treasure.requestDelete() - + def validAvatar(self, av): if av.getMaxHp() == av.getHp(): return 0 - + av.toonUp(3) return 1 -# Once we make rental game tables. -class TableRental(Rental): - - def __init__(self, estate): - Rental.__init__(self, estate) - - def generateObjects(self): - for drop in TableGlobals.tableDrops: - table = None - table.setEstateId(self.estate.doId) - table.setPosHpr(*drop) - table.generateWithRequired(self.estate.zoneId) - self.objects.add(table) - - def destroy(self): - Rental.destroy(self) - class DistributedEstateAI(DistributedObjectAI): - notify = DirectNotifyGlobal.directNotify.newCategory("DistributedEstateAI") - + notify = DirectNotifyGlobal.directNotify.newCategory('DistributedEstateAI') + def __init__(self, air): DistributedObjectAI.__init__(self, air) self.toons = [0, 0, 0, 0, 0, 0] self.items = [[], [], [], [], [], []] - self.boxes = [[], [], [], [], [], []] - self.plots = [[], [], [], [], [], []] - self.decorData = [] + self.estateType = 0 self.cloudType = 0 self.dawnTime = 0 self.lastEpochTimestamp = 0 - self.rentalType = 0 - self.rentalHandle = None self.rentalTimestamp = 0 self.houses = [None] * 6 + self.rentalType = 0 + self.rentalHandle = None + self.pond = None - self.spots = [] - self.targets = [] self.jukebox = None - self.owner = None + self.spots = [] + self.butterflies = [] + self.owner = None + + self.gardenManager = GardenManager(self) + self.__pendingGardens = {} + @property def hostId(self): return 1000000001 - + def generate(self): DistributedObjectAI.generate(self) - + self.pond = DistributedFishingPondAI(simbase.air) self.pond.setArea(ToontownGlobals.MyEstate) self.pond.generateWithRequired(self.zoneId) + self.pond.start() - for i in xrange(FishingTargetGlobals.getNumTargets(ToontownGlobals.MyEstate)): - target = DistributedFishingTargetAI(self.air) - target.setPondDoId(self.pond.getDoId()) - target.generateWithRequired(self.zoneId) - self.targets.append(target) + self.pond.bingoMgr = DistributedPondBingoManagerAI(simbase.air) + self.pond.bingoMgr.setPondDoId(self.pond.getDoId()) + self.pond.bingoMgr.generateWithRequired(self.zoneId) + self.pond.bingoMgr.initTasks() + + treasureType, healAmount, spawnPoints, spawnRate, maxTreasures = TreasureGlobals.SafeZoneTreasureSpawns[ToontownGlobals.MyEstate] + self.treasurePlanner = SZTreasurePlannerAI(self.zoneId, treasureType, healAmount, spawnPoints, spawnRate, maxTreasures) + self.treasurePlanner.start() spot = DistributedFishingSpotAI(self.air) spot.setPondDoId(self.pond.getDoId()) @@ -186,237 +538,165 @@ class DistributedEstateAI(DistributedObjectAI): spot.setPosHpr(46.8254, -113.682, 0.46015, 135, 0, 0) spot.generateWithRequired(self.zoneId) self.spots.append(spot) - - self.jukebox = DistributedPartyJukeboxActivityAI( - self.air, - self.doId, - (0, 0, 0, 0) - ) + + self.jukebox = DistributedPartyJukeboxActivityAI(self.air, self.doId, (0, 0, 0, 0)) self.jukebox.generateWithRequired(self.zoneId) self.jukebox.sendUpdate('setX', [-21.8630]) self.jukebox.sendUpdate('setY', [-154.669]) self.jukebox.sendUpdate('setH', [148.7050]) self.jukebox.sendUpdate('unloadSign') - self.createTreasurePlanner() - - def generateRegisteredObjects(self, slot): - if len(self.plots[slot]) > 0: - for item in self.items[slot]: - plotData = GardenGlobals.estatePlots[slot][item[0]] - if item[1] == GardenGlobals.FLOWER_TYPE: - newItem = DistributedFlowerAI(self.air) - newItem.setEstate(self.doId) - newItem.setOwnerPlot(self.plots[slot][item[0]].doId) - newItem.setPlot(item[0]) - newItem.setHeading(plotData[2]) - newItem.setPosition(plotData[0], plotData[1], 1.3) - newItem.setOwnerIndex(slot) - newItem.setWaterLevel(item[4]) - newItem.setGrowthLevel(item[5]) - newItem.setTypeIndex(item[2]) - newItem.setVariety(item[3]) - elif item[1] == GardenGlobals.GAG_TREE_TYPE: - newItem = DistributedGagTreeAI(self.air) - newItem.setEstate(self.doId) - newItem.setOwnerPlot(self.plots[slot][item[0]].doId) - newItem.setPlot(item[0]) - newItem.setHeading(plotData[2]) - newItem.setPosition(plotData[0], plotData[1], 1.3) - newItem.setOwnerIndex(slot) - newItem.setTypeIndex(item[2]) - newItem.setWaterLevel(item[4]) - newItem.setGrowthLevel(item[5]) - elif item[1] == GardenGlobals.STATUARY_TYPE: - newItem = DistributedStatuaryAI(self.air) - newItem.setEstate(self.doId) - newItem.setOwnerPlot(self.plots[slot][item[0]].doId) - newItem.setPlot(item[0]) - newItem.setHeading(plotData[2]) - newItem.setPosition(plotData[0], plotData[1], 1.3) - newItem.setOwnerIndex(slot) - newItem.setTypeIndex(item[2]) - newItem.setWaterLevel(item[4]) - newItem.setGrowthLevel(item[5]) - elif item[1] == GardenGlobals.TOON_STATUARY_TYPE: - newItem = DistributedToonStatuaryAI(self.air) - newItem.setEstate(self.doId) - newItem.setOwnerPlot(self.plots[slot][item[0]].doId) - newItem.setPlot(item[0]) - newItem.setHeading(plotData[2]) - newItem.setPosition(plotData[0], plotData[1], 1.3) - newItem.setOwnerIndex(slot) - newItem.setTypeIndex(item[2]) - newItem.setWaterLevel(item[4]) - newItem.setGrowthLevel(item[5]) - newItem.setOptional(item[6]) - else: - continue - newItem.generateWithRequired(self.zoneId) - self.plots[slot][item[0]].planted = newItem - self.plots[slot][item[0]].sendUpdate('plantedItem', [newItem.doId]) - self.plots[slot][item[0]].sendUpdate('setMovie', [GardenGlobals.MOVIE_PLANT, 999999999]) - + ButterflyGlobals.generateIndexes(self.zoneId, ButterflyGlobals.ESTATE) + for i in xrange(0, ButterflyGlobals.NUM_BUTTERFLY_AREAS[ButterflyGlobals.ESTATE]): + for j in xrange(0, ButterflyGlobals.NUM_BUTTERFLIES[ButterflyGlobals.ESTATE]): + butterfly = DistributedButterflyAI.DistributedButterflyAI(self.air, ButterflyGlobals.ESTATE, i, self.zoneId) + butterfly.generateWithRequired(self.zoneId) + butterfly.start() + self.butterflies.append(butterfly) def destroy(self): for house in self.houses: if house: house.requestDelete() + for butterfly in self.butterflies: + if butterfly: + butterfly.requestDelete() del self.houses[:] - if self.pond: - self.pond.requestDelete() for spot in self.spots: spot.requestDelete() - for target in self.targets: - target.requestDelete() - + self.spots = [] + self.pond.requestDelete() + self.pond = None if self.jukebox: self.jukebox.requestDelete() - if self.treasurePlanner: self.treasurePlanner.stop() - + + self.gardenManager.destroy() if self.rentalHandle: self.rentalHandle.destroy() self.rentalHandle = None - + self.requestDelete() - def setEstateReady(self): - pass + def addDistObj(self, distObj): + self.doId2do[distObj.doId] = distObj def setClientReady(self): self.sendUpdate('setEstateReady', []) - def setClosestHouse(self, todo0): - pass + def setEstateType(self, type): + self.estateType = type + + def d_setEstateType(self, type): + self.sendUpdate('setEstateType', [type]) + + def b_setEstateType(self, type): + self.setEstateType(type) + self.d_setEstateType(type) - def setTreasureIds(self, todo0): - pass - - def createTreasurePlanner(self): - treasureType, healAmount, spawnPoints, spawnRate, maxTreasures = TreasureGlobals.SafeZoneTreasureSpawns[ToontownGlobals.MyEstate] - self.treasurePlanner = SZTreasurePlannerAI(self.zoneId, treasureType, healAmount, spawnPoints, spawnRate, maxTreasures) - self.treasurePlanner.start() + def getEstateType(self): + return self.estateType def requestServerTime(self): avId = self.air.getAvatarIdFromSender() self.sendUpdateToAvatarId(avId, 'setServerTime', [time.time() % HouseGlobals.DAY_NIGHT_PERIOD]) - def setServerTime(self, todo0): - pass - def setDawnTime(self, dawnTime): self.dawnTime = dawnTime - + def d_setDawnTime(self, dawnTime): self.sendUpdate('setDawnTime', [dawnTime]) - + def b_setDawnTime(self, dawnTime): self.setDawnTime(dawnTime) self.d_setDawnTime(dawnTime) - + def getDawnTime(self): return self.dawnTime - def placeOnGround(self, todo0): - pass - - def setDecorData(self, decorData): - self.decorData = decorData - - def d_setDecorData(self, decorData): - self.sendUpdate('setDecorData', [decorData]) - - def b_setDecorData(self, decorData): - self.setDecorData(decorData) - self.d_setDecorData(decorData) - - def getDecorData(self): - return self.decorData - def setLastEpochTimeStamp(self, last): self.lastEpochTimestamp = last - + def d_setLastEpochTimeStamp(self, last): self.sendUpdate('setLastEpochTimeStamp', [last]) - + def b_setLastEpochTimeStamp(self, last): self.setLastEpochTimeStamp(last) self.d_setLastEpochTimeStamp(last) - + def getLastEpochTimeStamp(self): return self.lastEpochTimestamp def setRentalTimeStamp(self, rental): self.rentalTimestamp = rental - + def d_setRentalTimeStamp(self, rental): self.sendUpdate('setRentalTimeStamp', [rental]) - + def b_setRentalTimeStamp(self, rental): self.setRentalTimeStamp(rental) self.d_setRentalTimeStamp(rental) - + def getRentalTimeStamp(self): return self.rentalTimestamp def b_setRentalType(self, type): self.d_setRentalType(type) self.setRentalType(type) - + def d_setRentalType(self, type): - self.sendUpdate("setRentalType", [type]) - + self.sendUpdate('setRentalType', [type]) + def setRentalType(self, type): expirestamp = self.getRentalTimeStamp() if expirestamp == 0: expire = 0 + else: expire = int(expirestamp - time.time()) - + if expire < 0: self.rentalType = 0 self.d_setRentalType(0) self.b_setRentalTimeStamp(0) + else: if self.rentalType == type: return - + self.rentalType = type if self.rentalHandle: self.rentalHandle.destroy() self.rentalHandle = None - + if self.rentalType == ToontownGlobals.RentalCannon: self.rentalHandle = CannonRental(self) - elif self.rentalType == ToontownGlobals.RentalGameTable: - self.rentalHandle = TableRental(self) + else: self.notify.warning('Unknown rental %s' % self.rentalType) return - + self.rentalHandle.generateObjects() - + def getRentalType(self): return self.rentalType - + def rentItem(self, rentType, duration): - self.rentalType = rentType self.b_setRentalTimeStamp(time.time() + duration * 60) self.b_setRentalType(rentType) - + def setSlot0ToonId(self, id): self.toons[0] = id - + def d_setSlot0ToonId(self, id): self.sendUpdate('setSlot0ToonId', [id]) - + def b_setSlot0ToonId(self, id): self.setSlot0ToonId(id) self.d_setSlot0ToonId(id) - + def getSlot0ToonId(self): return self.toons[0] @@ -424,38 +704,38 @@ class DistributedEstateAI(DistributedObjectAI): self.items[0] = items def d_setSlot0Items(self, items): - self.sendUpdate('setSlot0Items', [items]) - + self.sendUpdate('setSlot5Items', [items]) + def b_setSlot0Items(self, items): self.setSlot0Items(items) self.d_setSlot0Items(items) - + def getSlot0Items(self): return self.items[0] - + def setSlot1ToonId(self, id): self.toons[1] = id def d_setSlot1ToonId(self, id): self.sendUpdate('setSlot1ToonId', [id]) - + def b_setSlot1ToonId(self, id): self.setSlot1ToonId(id) self.d_setSlot1ToonId(id) - + def getSlot1ToonId(self): return self.toons[1] - + def setSlot1Items(self, items): self.items[1] = items - + def d_setSlot1Items(self, items): - self.sendUpdate('setSlot1Items', [items]) - + self.sendUpdate('setSlot2Items', [items]) + def b_setSlot1Items(self, items): - self.setSlot1Items(items) - self.d_setSlot1Items(items) - + self.setSlot2Items(items) + self.d_setSlot2Items(items) + def getSlot1Items(self): return self.items[1] @@ -464,11 +744,11 @@ class DistributedEstateAI(DistributedObjectAI): def d_setSlot2ToonId(self, id): self.sendUpdate('setSlot2ToonId', [id]) - + def b_setSlot2ToonId(self, id): self.setSlot2ToonId(id) self.d_setSlot2ToonId(id) - + def getSlot2ToonId(self): return self.toons[2] @@ -477,89 +757,89 @@ class DistributedEstateAI(DistributedObjectAI): def d_setSlot2Items(self, items): self.sendUpdate('setSlot2Items', [items]) - + def b_setSlot2Items(self, items): self.setSlot2Items(items) self.d_setSlot2Items(items) - + def getSlot2Items(self): return self.items[2] def setSlot3ToonId(self, id): self.toons[3] = id - + def d_setSlot3ToonId(self, id): self.sendUpdate('setSlot3ToonId', [id]) - + def b_setSlot3ToonId(self, id): self.setSlot3ToonId(id) self.d_setSlot3ToonId(id) - + def getSlot3ToonId(self): return self.toons[3] def setSlot3Items(self, items): self.items[3] = items - + def d_setSlot3Items(self, items): self.sendUpdate('setSlot3Items', [items]) - + def b_setSlot3Items(self, items): self.setSlot3Items(items) self.d_setSlot3Items(items) - + def getSlot3Items(self): return self.items[3] def setSlot4ToonId(self, id): self.toons[4] = id - + def d_setSlot4ToonId(self, id): self.sendUpdate('setSlot4ToonId', [id]) - + def b_setSlot5ToonId(self, id): self.setSlot4ToonId(id) self.d_setSlot4ToonId(id) - + def getSlot4ToonId(self): return self.toons[4] def setSlot4Items(self, items): self.items[4] = items - + def d_setSlot4Items(self, items): self.sendUpdate('setSlot4Items', [items]) - + def b_setSlot4Items(self, items): self.setSlot4Items(items) self.d_setSlot4Items(items) - + def getSlot4Items(self): return self.items[4] def setSlot5ToonId(self, id): self.toons[5] = id - + def d_setSlot5ToonId(self, id): self.sendUpdate('setSlot5ToonId', [id]) - + def b_setSlot5ToonId(self, id): self.setSlot5ToonId(id) self.d_setSlot5ToonId(id) - + def getSlot5ToonId(self): return self.toons[5] def setSlot5Items(self, items): self.items[5] = items - + def d_setSlot5Items(self, items): self.sendUpdate('setSlot5Items', [items]) - + def b_setSlot5Items(self, items): self.setSlot5Items(items) self.d_setSlot5Items(items) - + def getSlot5Items(self): return self.items[5] @@ -568,107 +848,125 @@ class DistributedEstateAI(DistributedObjectAI): if i >= 6: return self.toons[i] = idList[i] - + def d_setIdList(self, idList): self.sendUpdate('setIdList', [idList]) - + def b_setIdList(self, idList): self.setIdList(idList) - self.d_setIdList(idList) - - def completeFlowerSale(self, todo0): - pass - - def completeFishSale(self, sell): + self.d_setIdLst(idList) + + def completeFlowerSale(self, flag): + if not flag: + return + avId = self.air.getAvatarIdFromSender() av = self.air.doId2do.get(avId) - if av: - if sell: - trophyResult = self.air.fishManager.creditFishTank(av) - if trophyResult: - self.sendUpdateToAvatarId(avId, 'thankSeller', [ToontownGlobals.FISHSALE_TROPHY, len(av.fishCollection), FishGlobals.getTotalNumFish()]) - else: - self.sendUpdateToAvatarId(avId, 'thankSeller', [ToontownGlobals.FISHSALE_COMPLETE, 0, 0]) - else: - self.sendUpdateToAvatarId(avId, 'thankSeller', [ToontownGlobals.FISHSALE_NONE, 0, 0]) - - def awardedTrophy(self, todo0): - pass + if not av: + return + + collection = av.flowerCollection + + earning = 0 + newSpecies = 0 + for flower in av.flowerBasket.getFlower(): + if collection.collectFlower(flower) == GardenGlobals.COLLECT_NEW_ENTRY: + newSpecies += 1 + + earning += flower.getValue() + + av.b_setFlowerBasket([], []) + av.d_setFlowerCollection(*av.flowerCollection.getNetLists()) + av.addMoney(earning) + + oldSpecies = len(collection) - newSpecies + dt = abs(len(collection) // 10 - oldSpecies // 10) + if dt: + self.notify.info('%d is getting a gardening trophy!' % avId) + + maxHp = av.getMaxHp() + maxHp = min(ToontownGlobals.MaxHpLimit, maxHp + dt) + av.b_setMaxHp(maxHp) + av.toonUp(maxHp) + + self.sendUpdate('awardedTrophy', [avId]) + + av.b_setGardenTrophies(range(len(collection) // 10)) + + def completeFishSale(self): + avId = self.air.getAvatarIdFromSender() + av = self.air.doId2do.get(avId) + + if not av: + return + if self.air.fishManager.creditFishTank(av): + self.sendUpdateToAvatarId(avId, 'thankSeller', [ToontownGlobals.FISHSALE_TROPHY, len(av.fishCollection), FishGlobals.getTotalNumFish()]) + else: + self.sendUpdateToAvatarId(avId, 'thankSeller', [ToontownGlobals.FISHSALE_COMPLETE, 0, 0]) + def setClouds(self, clouds): self.cloudType = clouds - + def d_setClouds(self, clouds): self.sendUpdate('setClouds', [clouds]) - + def b_setClouds(self, clouds): self.setClouds(clouds) self.d_setClouds(clouds) - + def getClouds(self): return self.cloudType + + # Garden methods + def getToonSlot(self, avId): + if avId not in self.toons: + return + + return self.toons.index(avId) + + def setSlot0Garden(self, flag): + self.__pendingGardens[0] = flag - def cannonsOver(self): - pass + def setSlot1Garden(self, flag): + self.__pendingGardens[1] = flag - def gameTableOver(self): - pass + def setSlot2Garden(self, flag): + self.__pendingGardens[2] = flag + + def setSlot3Garden(self, flag): + self.__pendingGardens[3] = flag + + def setSlot4Garden(self, flag): + self.__pendingGardens[4] = flag - def placeStarterGarden(self, avatar): - # TODO: Place garden if a toon already owns one. - avId = avatar.doId - slot = self.toons.index(avId) - plotPos = GardenGlobals.estatePlots[slot] - boxPos = GardenGlobals.estateBoxes[slot] - for p, n in enumerate(boxPos): - x, y, h, i = n - newBox = DistributedGardenBoxAI(self.air) - newBox.setEstate(self.doId) - newBox.setTypeIndex(i) - newBox.setPlot(p) - newBox.setOwnerIndex(slot) - newBox.setPosition(x, y, 0) - newBox.setHeading(h) - newBox.generateWithRequired(self.zoneId) - self.boxes[slot].append(newBox) - for p, n in enumerate(plotPos): - i = n[3] - if i in [GardenGlobals.GAG_TREE_TYPE, GardenGlobals.STATUARY_TYPE]: - x, y, h = n[:3] - newPlot = DistributedGardenPlotAI(self.air) - newPlot.setEstate(self.doId) - newPlot.setPlot(p) - newPlot.setOwnerIndex(slot) - newPlot.setPosition(x, y, 0) - newPlot.setHeading(h) - newPlot.generateWithRequired(self.zoneId) - self.plots[slot].append(newPlot) - elif i == GardenGlobals.FLOWER_TYPE: - # TODO: Place flower plots more accurately. - x, y, h = n[:3] - newPlot = DistributedGardenPlotAI(self.air) - newPlot.setEstate(self.doId) - newPlot.setPlot(p) - newPlot.setOwnerIndex(slot) - newPlot.setPosition(x, y, 1.3) - newPlot.setHeading(h) - newPlot.generateWithRequired(self.zoneId) - self.plots[slot].append(newPlot) - self.generateRegisteredObjects(slot) + def setSlot5Garden(self, flag): + self.__pendingGardens[5] = flag + + def placeStarterGarden(self, avId, record=1): + av = self.air.doId2do.get(avId) + if not av: + return - def updateToons(self): - self.d_setSlot0ToonId(self.toons[0]) - self.d_setSlot1ToonId(self.toons[1]) - self.d_setSlot2ToonId(self.toons[2]) - self.d_setSlot3ToonId(self.toons[3]) - self.d_setSlot4ToonId(self.toons[4]) - self.d_setSlot5ToonId(self.toons[5]) + slot = self.getToonSlot(avId) + if slot is None: + return + + if record: + av.b_setGardenStarted(1) + self.sendUpdate('setSlot%dGarden' % slot, ['started']) + + self.notify.info('placeStarterGarden %d %d' % (avId, slot)) + self.gardenManager.handleSingleGarden(avId) + + def announceGenerate(self): + DistributedObjectAI.announceGenerate(self) self.sendUpdate('setIdList', [self.toons]) - - def updateItems(self): - self.d_setSlot0Items(self.items[0]) - self.d_setSlot1Items(self.items[1]) - self.d_setSlot2Items(self.items[2]) - self.d_setSlot3Items(self.items[3]) - self.d_setSlot4Items(self.items[4]) - self.d_setSlot5Items(self.items[5]) + + for index, started in self.__pendingGardens.items(): + if started: + self.gardenManager.handleSingleGarden(self.toons[index]) + + self.__pendingGardens = {} + if config.GetBool('fake-garden-started-ai', False): + self.placeStarterGarden(100000002, 0) \ No newline at end of file diff --git a/toontown/estate/DistributedFlower.py b/toontown/estate/DistributedFlower.py index 324130c9..d6afcf94 100755 --- a/toontown/estate/DistributedFlower.py +++ b/toontown/estate/DistributedFlower.py @@ -1,14 +1,17 @@ -from toontown.estate import DistributedPlantBase from direct.directnotify import DirectNotifyGlobal +from toontown.estate import DistributedPlantBase +from toontown.estate.DistributedGardenBox import DistributedGardenBox from toontown.estate import FlowerBase from toontown.estate import GardenGlobals from toontown.toontowngui import TTDialog from toontown.toonbase import TTLocalizer + DIRT_AS_WATER_INDICATOR = True DIRT_MOUND_HEIGHT = 0.3 class DistributedFlower(DistributedPlantBase.DistributedPlantBase, FlowerBase.FlowerBase): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedFlower') + deferFor = 2 def __init__(self, cr): DistributedPlantBase.DistributedPlantBase.__init__(self, cr) @@ -17,16 +20,16 @@ class DistributedFlower(DistributedPlantBase.DistributedPlantBase, FlowerBase.Fl self.stickUp = 1.07 if DIRT_AS_WATER_INDICATOR: self.stickUp += DIRT_MOUND_HEIGHT - self.collSphereRadius = 2.8 + self.collSphereRadius = 2.2 self.shadowScale = 0.5 self.collSphereOffset = 0.0 self.dirtMound = None self.sandMound = None self.resultDialog = None - return def delete(self): DistributedPlantBase.DistributedPlantBase.delete(self) + del self.dirtMound del self.sandMound @@ -34,9 +37,6 @@ class DistributedFlower(DistributedPlantBase.DistributedPlantBase, FlowerBase.Fl DistributedPlantBase.DistributedPlantBase.setTypeIndex(self, typeIndex) self.setSpecies(typeIndex) - def getTypeIndex(self): - return self.typeIndex - def showWiltOrBloom(self): if not self.model: return @@ -74,7 +74,7 @@ class DistributedFlower(DistributedPlantBase.DistributedPlantBase, FlowerBase.Fl invFlowerScale = 1.0 / flowerScale self.model.setScale(flowerScale) if DIRT_AS_WATER_INDICATOR: - dirtMoundScale = invFlowerScale * 0.73 + dirtMoundScale = invFlowerScale * 0.63 self.dirtMound = loader.loadModel('phase_5.5/models/estate/dirt_mound') self.dirtMound.reparentTo(self.model) self.dirtMound.setScale(dirtMoundScale) @@ -132,7 +132,7 @@ class DistributedFlower(DistributedPlantBase.DistributedPlantBase, FlowerBase.Fl base.localAvatar.removeShovelRelatedDoId(self.doId) base.localAvatar.setInGardenAction(self) base.cr.playGame.getPlace().detectedGardenPlotUse() - self.sendUpdate('removeItem', [base.localAvatar.doId]) + self.sendUpdate('removeItem', []) def setWaterLevel(self, waterLevel): DistributedPlantBase.DistributedPlantBase.setWaterLevel(self, waterLevel) @@ -140,18 +140,15 @@ class DistributedFlower(DistributedPlantBase.DistributedPlantBase, FlowerBase.Fl if self.model: self.adjustWaterIndicator() - def getWaterLevel(self): - return self.waterLevel - def setGrowthLevel(self, growthLevel): origGrowthLevel = self.growthLevel self.growthLevel = growthLevel if origGrowthLevel > -1: self.loadModel() self.makeMovieNode() - - def getGrowthLevel(self): - return self.growthLevel + + if hasattr(self, '_boxDoId'): + self.setBoxDoId(*self._boxDoId) def makeMovieNode(self): self.movieNode = self.rotateNode.attachNewNode('moviePos') @@ -200,4 +197,17 @@ class DistributedFlower(DistributedPlantBase.DistributedPlantBase, FlowerBase.Fl self.resultDialog.destroy() self.resultDialog = None self.finishInteraction() - return + + def setBoxDoId(self, boxId, index): + self._boxDoId = (boxId, index) + box = base.cr.doId2do[boxId] + x = GardenGlobals.FLOWER_POS[box.typeIndex][index] + + self.setPos(0, 0, 0) + self.reparentTo(box) + self.setZ(1.5) + self.setX(x) + + def stick2Ground(self): + pass + \ No newline at end of file diff --git a/toontown/estate/DistributedFlowerAI.py b/toontown/estate/DistributedFlowerAI.py index e7d5621d..9f79ace6 100755 --- a/toontown/estate/DistributedFlowerAI.py +++ b/toontown/estate/DistributedFlowerAI.py @@ -1,26 +1,145 @@ from direct.directnotify import DirectNotifyGlobal -from toontown.estate.DistributedPlantBaseAI import DistributedPlantBaseAI +from otp.ai.MagicWordGlobal import * +from DistributedPlantBaseAI import DistributedPlantBaseAI +from FlowerBase import FlowerBase -# TODO: Add flower to basket when picking, give shovel skill only if the -# flower is player's tier. +import GardenGlobals +import time -class DistributedFlowerAI(DistributedPlantBaseAI): - notify = DirectNotifyGlobal.directNotify.newCategory("DistributedFlowerAI") +ONE_DAY = 86400 - def __init__(self, air): - DistributedPlantBaseAI.__init__(self, air) - self.air = air - self.typeIndex = None +class DistributedFlowerAI(DistributedPlantBaseAI, FlowerBase): + notify = DirectNotifyGlobal.directNotify.newCategory('DistributedFlowerAI') + + def setTypeIndex(self, value): + DistributedPlantBaseAI.setTypeIndex(self, value) + FlowerBase.setSpecies(self, value) + + def calculate(self, lastCheck): + now = int(time.time()) + if lastCheck == 0: + lastCheck = now + + grown = 0 + + # Water level + elapsed = now - lastCheck + while elapsed > ONE_DAY: + if self.waterLevel >= 0: + grown += 1 + + elapsed -= ONE_DAY + self.waterLevel -= 1 + + self.waterLevel = max(self.waterLevel, -2) + + # Growth level + maxGrowth = self.growthThresholds[2] + newGL = min(self.growthLevel + grown, maxGrowth) + self.setGrowthLevel(newGL) + + self.lastCheck = now - elapsed + self.update() + + def update(self): + mdata = map(list, self.mgr.data['flowers']) + mdata[self.flowerIndex] = [self.getSpecies(), self.waterLevel, self.lastCheck, self.getGrowthLevel(), self.getVariety()] + self.mgr.data['flowers'] = mdata + self.mgr.update() + + def removeItem(self, usingSatanPickAll=0): + avId = self.air.getAvatarIdFromSender() + if not usingSatanPickAll: + if avId != self.ownerDoId: + self.air.writeServerEvent('suspicious', avId, 'tried to remove someone else\'s flower!') + return - def setTypeIndex(self, typeIndex): - DistributedPlantBaseAI.setTypeIndex(self, typeIndex) - self.typeIndex = typeIndex + self.d_setMovie(GardenGlobals.MOVIE_REMOVE) + + action = 'remove' + if self.getGrowthLevel() >= self.growthThresholds[2]: + action = 'pick' + + def _remove(task): + if not self.air: + return + + av = self.air.doId2do.get(self.ownerDoId) + if not av: + return + + plot = self.mgr.placePlot(self.flowerIndex) + plot.flowerIndex = self.flowerIndex + plot.setPlot(self.plot) + plot.setOwnerIndex(self.ownerIndex) + plot.generateWithRequired(self.zoneId) + + index = (0, 1, 2, 2, 2, 3, 3, 3, 4, 4)[self.flowerIndex] + idx = (0, 0, 0, 1, 2, 0, 1, 2, 0, 1)[self.flowerIndex] + plot.sendUpdate('setBoxDoId', [self.mgr._boxes[index].doId, idx]) + + self.air.writeServerEvent('%s-flower' % action, avId, plot=self.plot) + self.requestDelete() + + self.mgr.flowers.remove(self) + + mdata = map(list, self.mgr.data['flowers']) + mdata[self.flowerIndex] = self.mgr.getNullPlant() + self.mgr.data['flowers'] = mdata + self.mgr.update() + + if action == 'pick': + av.b_setShovelSkill(av.getShovelSkill() + self.getValue()) + av.addFlowerToBasket(self.getSpecies(), self.getVariety()) + + if task: + return task.done + + if usingSatanPickAll: + _remove(None) + + else: + taskMgr.doMethodLater(7, _remove, self.uniqueName('do-remove')) + +@magicWord(category=CATEGORY_PROGRAMMER) +def satanGrowFlowers(): + av = spellbook.getTarget() + estate = av.air.estateManager._lookupEstate(av) + + if not estate: + return 'Estate not found!' + + garden = estate.gardenManager.gardens.get(av.doId) + if not garden: + return 'Garden not found!' - def getTypeIndex(self): - return self.typeIndex + now = int(time.time()) + i = 0 + for flower in garden.flowers.union(garden.trees): + flower.b_setWaterLevel(5) + flower.b_setGrowthLevel(2) + flower.update() + i += 1 + + return '%d disgusting flowers and trees grown' % i + +@magicWord(category=CATEGORY_PROGRAMMER) +def satanPickAll(): + av = spellbook.getTarget() + estate = av.air.estateManager._lookupEstate(av) + + if not estate: + return 'Estate not found!' + + garden = estate.gardenManager.gardens.get(av.doId) + if not garden: + return 'Garden not found!' - def setVariety(self, variety): - self.variety = variety - - def getVariety(self): - return self.variety + i = 0 + for flower in garden.flowers.copy(): + if flower.getGrowthLevel() >= flower.growthThresholds[2]: + flower.removeItem(1) + i += 1 + + return '%d disgusting flowers picked' % i + \ No newline at end of file diff --git a/toontown/estate/DistributedFurnitureItem.py b/toontown/estate/DistributedFurnitureItem.py index 75be8567..5b6e88a5 100755 --- a/toontown/estate/DistributedFurnitureItem.py +++ b/toontown/estate/DistributedFurnitureItem.py @@ -47,8 +47,6 @@ class DistributedFurnitureItem(DistributedHouseItem.DistributedHouseItem, Distri def delete(self): self.removeNode() - if hasattr(self.item, 'videoSequence') and self.item.videoSequence: - self.item.videoSequence.pause() del self.item DistributedHouseItem.DistributedHouseItem.delete(self) DistributedSmoothNode.DistributedSmoothNode.delete(self) diff --git a/toontown/estate/DistributedFurnitureManagerAI.py b/toontown/estate/DistributedFurnitureManagerAI.py index 5dba1b5e..5aab2dda 100755 --- a/toontown/estate/DistributedFurnitureManagerAI.py +++ b/toontown/estate/DistributedFurnitureManagerAI.py @@ -1,7 +1,7 @@ from direct.distributed.DistributedObjectAI import DistributedObjectAI from toontown.catalog.CatalogItemList import CatalogItemList from toontown.catalog import CatalogItem -from toontown.catalog.CatalogFurnitureItem import CatalogFurnitureItem, FLTrunk, FLCloset, FLBank, FLPhone +from toontown.catalog.CatalogFurnitureItem import CatalogFurnitureItem, FLTrunk, FLCloset, FLBank, FLPhone, FLCrate, FLChair, FLTV from toontown.catalog.CatalogWallpaperItem import CatalogWallpaperItem from toontown.catalog.CatalogMouldingItem import CatalogMouldingItem from toontown.catalog.CatalogFlooringItem import CatalogFlooringItem @@ -12,6 +12,9 @@ from DistributedPhoneAI import DistributedPhoneAI from DistributedClosetAI import DistributedClosetAI from DistributedTrunkAI import DistributedTrunkAI from DistributedBankAI import DistributedBankAI +from DistributedRewardCrateAI import DistributedRewardCrateAI +from DistributedChairAI import DistributedChairAI +from DistributedTVAI import DistributedTVAI from otp.ai.MagicWordGlobal import * class FurnitureError(Exception): @@ -92,53 +95,15 @@ class DistributedFurnitureManagerAI(DistributedObjectAI): self.interior.b_setWindows(self.windows.getBlob()) def setItems(self, items): - # Decode the blob: items = CatalogItemList(items, store=CatalogItem.Customization|CatalogItem.Location) - # Throw out our old items: for item in self.items: item.destroy() + self.items = [] - items.removeDuplicates(FLCloset) - - # Due to a bug, some people are missing their closets... - hasCloset = False for item in items: - if item.getFlags() & FLCloset: - hasCloset = True - break - - if not hasCloset and self.ownerId != 0: - item = CatalogFurnitureItem(500) # the basic closet... - item.posHpr = (0.0, 0.0, 0.0, 0.0, 0.0, 0.0) - items.append(item) - # Since we have modified the items list, should we save it back to the house? - - for item in items: - if item.getFlags() & FLTrunk: - if self.house.gender is 0: - if item.furnitureType - 4000 < 10: - item.furnitureType += 10 - elif item.furnitureType - 4000 > 10: - item.furnitureType -= 10 - do = DistributedTrunkAI(self.air, self, item) - elif item.getFlags() & FLCloset: - if self.house.gender is 0: - if item.furnitureType - 500 < 10: - item.furnitureType += 10 - elif item.furnitureType - 500 > 10: - item.furnitureType -= 10 - do = DistributedClosetAI(self.air, self, item) - elif item.getFlags() & FLBank: - do = DistributedBankAI(self.air, self, item) - elif item.getFlags() & FLPhone: - do = DistributedPhoneAI(self.air, self, item) - else: - do = DistributedFurnitureItemAI(self.air, self, item) - if self.isGenerated(): - do.generateWithRequired(self.zoneId) - self.items.append(do) + self.generateItem(item) def getItems(self): items = CatalogItemList(store=CatalogItem.Customization|CatalogItem.Location) @@ -271,6 +236,31 @@ class DistributedFurnitureManagerAI(DistributedObjectAI): pass # Furniture-manipulation: + + def generateItem(self, item): + if item.getFlags() & FLTrunk: + do = DistributedTrunkAI(self.air, self, item) + elif item.getFlags() & FLCloset: + do = DistributedClosetAI(self.air, self, item) + elif item.getFlags() & FLBank: + do = DistributedBankAI(self.air, self, item) + elif item.getFlags() & FLPhone: + do = DistributedPhoneAI(self.air, self, item) + elif item.getFlags() & FLCrate: + do = DistributedRewardCrateAI(self.air, self, item) + elif item.getFlags() & FLChair: + do = DistributedChairAI(self.air, self, item) + elif item.getFlags() & FLTV: + do = DistributedTVAI(self.air, self, item) + else: + do = DistributedFurnitureItemAI(self.air, self, item) + + if self.isGenerated(): + do.generateWithRequired(self.zoneId) + + self.items.append(do) + return do + def moveItemToAttic(self, doId): item = self.getItemObject(doId) @@ -289,32 +279,9 @@ class DistributedFurnitureManagerAI(DistributedObjectAI): self.d_setAtticItems(self.getAtticItems()) item.posHpr = (x, y, z, h, p, r) + object = self.generateItem(item) - if item.getFlags() & FLTrunk: - if self.house.gender is 0: - if item.furnitureType - 4000 < 10: - item.furnitureType += 10 - elif item.furnitureType - 4000 > 10: - item.furnitureType -= 10 - do = DistributedTrunkAI(self.air, self, item) - elif item.getFlags() & FLCloset: - if self.house.gender is 0: - if item.furnitureType - 500 < 10: - item.furnitureType += 10 - elif item.furnitureType - 500 > 10: - item.furnitureType -= 10 - do = DistributedClosetAI(self.air, self, item) - elif item.getFlags() & FLBank: - do = DistributedBankAI(self.air, self, item) - elif item.getFlags() & FLPhone: - do = DistributedPhoneAI(self.air, self, item) - else: - do = DistributedFurnitureItemAI(self.air, self, item) - - do.generateWithRequired(self.zoneId) - self.items.append(do) - - return (ToontownGlobals.FM_MovedItem, do.doId) + return (ToontownGlobals.FM_MovedItem, object.doId) def deleteItemFromAttic(self, blob, index): item = self.getAtticFurniture(self.atticItems, index) @@ -327,8 +294,21 @@ class DistributedFurnitureManagerAI(DistributedObjectAI): return ToontownGlobals.FM_DeletedItem - def deleteItemFromRoom(self, blob, doId): - pass + def deleteItemFromRoom(self, doId, addToTrash=True): + item = self.getItemObject(doId) + + if not item: + self.air.writeServerEvent('suspicious', avId=self.air.getAvatarIdFromSender(), issue='Tried to delete an invalid item with doId %s' % doId) + return ToontownGlobals.FM_InvalidIndex + + if addToTrash: + self.deletedItems.append(item.catalogItem) + self.d_setDeletedItems(self.getDeletedItems()) + + item.destroy() + self.items.remove(item) + + return ToontownGlobals.FM_DeletedItem def moveWallpaperFromAttic(self, index, room): retcode = ToontownGlobals.FM_SwappedItem @@ -414,7 +394,16 @@ class DistributedFurnitureManagerAI(DistributedObjectAI): return ToontownGlobals.FM_DeletedItem def recoverDeletedItem(self, blob, index): - pass + if len(self.deletedItems) <= index: + return + + item = self.deletedItems[index] + self.deletedItems.remove(item) + self.atticItems.append(item) + self.d_setDeletedItems(self.deletedItems) + self.d_setAtticItems(self.getAtticItems()) + + return ToontownGlobals.FM_MovedItem def handleMessage(self, func, response, *args): context = args[-1] @@ -451,7 +440,7 @@ class DistributedFurnitureManagerAI(DistributedObjectAI): self.handleMessage(self.deleteItemFromAttic, 'deleteItemFromAtticResponse', blob, index, context) def deleteItemFromRoomMessage(self, blob, doId, context): - self.handleMessage(self.deleteItemFromRoom, 'deleteItemFromRoomResponse', blob, doId, context) + self.handleMessage(self.deleteItemFromRoom, 'deleteItemFromRoomResponse', doId, context) def moveWallpaperFromAtticMessage(self, index, room, context): self.handleMessage(self.moveWallpaperFromAttic, 'moveWallpaperFromAtticResponse', index, room, context) @@ -493,96 +482,47 @@ class DistributedFurnitureManagerAI(DistributedObjectAI): return window return None -@magicWord(category=CATEGORY_PROGRAMMER, types=[]) -def findCloset(): - """ - find the closet - """ - target = spellbook.getTarget() - if not target: - target = spellbook.getInvoker() - if not target: - return "Strange.. who are we talking about?" - - if not hasattr(target, "estate") or not hasattr(target.estate, "houses"): - return "no houses in the state" - - for house in target.estate.houses: - if house.doId == target.houseId: - fm = house.interior.furnitureManager - for item in fm.items: - if item.catalogItem.getFlags() & FLCloset: - return 'items: %s'%(str(item.catalogItem)) - for item in fm.atticItems: - if item.getFlags() & FLCloset: - return 'atticItems: %s'%(str(item)) - return "I cannot find your closet" - -@magicWord(category=CATEGORY_PROGRAMMER, types=[]) -def recoverCloset(): - """ - recover the closet - """ - target = spellbook.getTarget() - if not target: - target = spellbook.getInvoker() - if not target: - return "Strange.. who are we talking about?" - - if not hasattr(target, "estate") or not hasattr(target.estate, "houses"): - return "no houses in the state" - - for house in target.estate.houses: - if house.doId == target.houseId: - fm = house.interior.furnitureManager - for item in reversed(fm.items): - if item.catalogItem.getFlags() & FLCloset: - fm.moveItemToAttic(item.doId); - return "Moved the closet" - fm.saveToHouse() - return "I cannot find your closet" - -@magicWord(category=CATEGORY_PROGRAMMER, types=[]) +@magicWord(category=CATEGORY_PROGRAMMER) def fillAttic(): """ - move everything to the attic + Move everything to the attic. """ target = spellbook.getTarget() - if not target: - target = spellbook.getInvoker() - if not target: - return "Strange.. who are we talking about?" if not hasattr(target, "estate") or not hasattr(target.estate, "houses"): - return "no houses in the state" + return "The target is not in an estate!" for house in target.estate.houses: if house.doId == target.houseId: - fm = house.interior.furnitureManager - for item in reversed(fm.items): - fm.moveItemToAttic(item.doId); - fm.saveToHouse() - return "everything has been moved to the attic" + manager = house.interior.furnitureManager -@magicWord(category=CATEGORY_PROGRAMMER, types=[]) + for item in reversed(manager.items): + manager.moveItemToAttic(item.doId) + + manager.saveToHouse() + return "Everything has been moved to the attic!" + + return "The target is not in his estate!" + +@magicWord(category=CATEGORY_PROGRAMMER) def emptyHouse(): """ - delete everything in the house + Delete everything in the house. """ target = spellbook.getTarget() - if not target: - target = spellbook.getInvoker() - if not target: - return "Strange.. who are we talking about?" if not hasattr(target, "estate") or not hasattr(target.estate, "houses"): - return "no houses in the state" + return "The target is not in an estate!" for house in target.estate.houses: if house.doId == target.houseId: - fm = house.interior.furnitureManager - for item in reversed(fm.items): + manager = house.interior.furnitureManager + + for item in reversed(manager.items): item.destroy() - fm.items.remove(item) - fm.saveToHouse() - return "The house is empty" + + manager.items = [] + manager.saveToHouse() + return "Everything has been deleted!" + + return "The target is not in his estate!" \ No newline at end of file diff --git a/toontown/estate/DistributedGagTree.py b/toontown/estate/DistributedGagTree.py index dc208312..0a09e61e 100755 --- a/toontown/estate/DistributedGagTree.py +++ b/toontown/estate/DistributedGagTree.py @@ -29,7 +29,7 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase): self.backupFruits = [] self.signHasBeenStuck2Ground = False self.setName('DistributedGagTree') - return + self.fruiting = 0 def delete(self): DistributedPlantBase.DistributedPlantBase.delete(self) @@ -141,8 +141,6 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase): self.confirmDialog.destroy() self.confirmDialog = None if value > 0: - base.localAvatar.showGardeningGui() - base.localAvatar.removeShovelRelatedDoId(self.doId) self.doPicking() else: self.finishInteraction() @@ -151,7 +149,7 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase): def doPicking(self): if not self.canBePicked(): return - self.sendUpdate('removeItem', [base.localAvatar.doId]) + self.sendUpdate('removeItem', []) def createBackupFruits(self): if not hasattr(self, 'fruits'): @@ -175,6 +173,11 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase): self.backupFruits.append(newFruit) def clearBackupFruits(self): + if self.fruits: + for fruit in self.fruits: + fruit.removeNode() + + self.fruits = None self.backupFruits = [] def doHarvesting(self): @@ -184,14 +187,7 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase): for fruit in self.backupFruits: fruit.show() - self.sendUpdate('requestHarvest', [base.localAvatar.doId]) - - def hideItems(self): - if hasattr(self, 'fruits') and self.fruits: - seq = Parallel() - for item in self.fruits: - seq.append(LerpFunc(item.setAlphaScale, fromData=1, toData=0, duration=1)) - seq.start() + self.sendUpdate('requestHarvest', []) def getTrack(self): return self.gagTrack @@ -268,7 +264,6 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase): self.movie.append(Func(toon.loop, 'neutral')) if avId == localAvatar.doId: self.movie.append(Func(self.finishInteraction)) - self.movie.append(Func(self.hideItems)) self.movie.append(Func(self.movieDone)) self.movie.append(Func(self.doResultDialog)) self.movie.start() @@ -299,7 +294,6 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase): for fruit in self.backupFruits: fruitTrack.append(Sequence(Func(fruit.show), LerpPosInterval(fruit, 1.5, pos, startPos=Point3(fruit.getX(), fruit.getY(), fruit.getZ() + self.model.getZ())), Func(fruit.removeNode))) - self.fruits = None harvestTrack = Sequence(fruitTrack, Func(self.clearBackupFruits)) return harvestTrack @@ -356,25 +350,7 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase): return Task.done def canBeHarvested(self): - myTrack, myLevel = GardenGlobals.getTreeTrackAndLevel(self.typeIndex) - levelsInTrack = [] - levelTreeDict = {} - allGagTrees = base.cr.doFindAll('DistributedGagTree') - for gagTree in allGagTrees: - if gagTree.getOwnerId() == localAvatar.doId: - curTrack, curLevel = GardenGlobals.getTreeTrackAndLevel(gagTree.typeIndex) - if curTrack == myTrack: - levelsInTrack.append(curLevel) - levelTreeDict[curLevel] = gagTree - - for levelToTest in xrange(myLevel): - if levelToTest not in levelsInTrack: - return False - curTree = levelTreeDict[levelToTest] - if not curTree.isGTEFullGrown(): - return False - - return True + return self.isFruiting() def hasDependentTrees(self): myTrack, myLevel = GardenGlobals.getTreeTrackAndLevel(self.typeIndex) @@ -417,3 +393,15 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase): if inventory.numItem(self.gagTrack, self.gagLevel) >= inventory.getMax(self.gagTrack, self.gagLevel): retval = False return retval + + def setFruiting(self, fruiting): + self.fruiting = fruiting + if self.model: + self.model.removeNode() + self.loadModel() + self.adjustWaterIndicator() + self.stick2Ground() + + def isFruiting(self): + return self.fruiting + \ No newline at end of file diff --git a/toontown/estate/DistributedGagTreeAI.py b/toontown/estate/DistributedGagTreeAI.py index 67d80265..285eb3cc 100755 --- a/toontown/estate/DistributedGagTreeAI.py +++ b/toontown/estate/DistributedGagTreeAI.py @@ -1,35 +1,223 @@ from direct.directnotify import DirectNotifyGlobal +from otp.ai.MagicWordGlobal import * from toontown.estate.DistributedPlantBaseAI import DistributedPlantBaseAI -import GardenGlobals +import GardenGlobals, time + +ONE_DAY = 86400 + +PROBLEM_WILTED = 1 +PROBLEM_NOT_GROWN = 2 +PROBLEM_HARVESTED_LATELY = 4 class DistributedGagTreeAI(DistributedPlantBaseAI): - notify = DirectNotifyGlobal.directNotify.newCategory("DistributedGagTreeAI") + notify = DirectNotifyGlobal.directNotify.newCategory('DistributedGagTreeAI') + GrowRate = config.GetBool('trees-grow-rate', 2) - def __init__(self, air): - DistributedPlantBaseAI.__init__(self, air) - self.air = air + def __init__(self, mgr): + DistributedPlantBaseAI.__init__(self, mgr) self.wilted = 0 - + def announceGenerate(self): DistributedPlantBaseAI.announceGenerate(self) - - def delete(self): - DistributedPlantBaseAI.delete(self) - - def disable(self): - DistributedPlantBaseAI.disable(self) - + messenger.send(self.getEventName('generate')) + def setWilted(self, wilted): self.wilted = wilted - + + def d_setWilted(self, wilted): + self.sendUpdate('setWilted', [wilted]) + + def b_setWilted(self, wilted): + self.setWilted(wilted) + self.d_setWilted(wilted) + def getWilted(self): return self.wilted + + def calculate(self, lastHarvested, lastCheck): + now = int(time.time()) + if lastCheck == 0: + lastCheck = now + + grown = 0 + + # Water level + elapsed = now - lastCheck + while elapsed > ONE_DAY: + if self.waterLevel >= 0: + grown += self.GrowRate + + elapsed -= ONE_DAY + self.waterLevel -= 1 + + self.waterLevel = max(self.waterLevel, -2) + + # Growth level + maxGrowth = self.growthThresholds[2] + newGL = min(self.growthLevel + grown, maxGrowth) + self.setGrowthLevel(newGL) + + self.setWilted(self.waterLevel == -2) + + self.lastCheck = now - elapsed + self.lastHarvested = lastHarvested + self.update() + + def calcDependencies(self): + if self.getWilted(): + return + + missingPrevIndex = 0 + track, value = GardenGlobals.getTreeTrackAndLevel(self.typeIndex) + while value: + value -= 1 + if not self.mgr.hasTree(track, value): + self.b_setWilted(1) + continue + + tree = self.mgr.getTree(track, value) + if not tree: + self.b_setWilted(1) + continue + + self.accept(self.getEventName('going-down', 666), self.ignoreAll) + self.accept(self.getEventName('remove', track * 7 + value), self.calcDependencies) + + def getEventName(self, string, typeIndex=None): + typeIndex = typeIndex if typeIndex is not None else self.typeIndex + return 'garden-%d-%d-%s' % (self.ownerDoId, typeIndex, string) + + def delete(self): + messenger.send(self.getEventName('remove')) + self.ignoreAll() + DistributedPlantBaseAI.delete(self) + + def update(self): + mdata = map(list, self.mgr.data['trees']) + mdata[self.treeIndex] = [self.typeIndex, self.waterLevel, self.lastCheck, self.getGrowthLevel(), self.lastHarvested] + self.mgr.data['trees'] = mdata + self.mgr.update() + + def isFruiting(self): + problem = 0 + if self.getWilted(): + problem |= PROBLEM_WILTED + + if self.getGrowthLevel() < self.growthThresholds[2]: + problem |= PROBLEM_NOT_GROWN + + if (self.lastCheck - self.lastHarvested) < ONE_DAY: + problem |= PROBLEM_HARVESTED_LATELY + + return problem + + def getFruiting(self): + return self.isFruiting() == 0 + + def requestHarvest(self): + avId = self.air.getAvatarIdFromSender() + av = self.air.doId2do.get(avId) + if not av: + return + + if avId != self.ownerDoId: + self.air.writeServerEvent('suspicious', avId, 'tried to harvest someone else\'s tree!') + return + + problem = self.isFruiting() + if problem: + self.air.writeServerEvent('suspicious', avId, 'tried to harvest a tree that\'s not fruiting!', problem=problem) + return - def requestHarvest(self, doId): - # TODO: Actually harvest the gags and add them to toon inventory. - av = simbase.air.doId2do.get(doId) harvested = 0 track, level = GardenGlobals.getTreeTrackAndLevel(self.typeIndex) while av.inventory.addItem(track, level) > 0 and harvested < 10: harvested += 1 - self.sendUpdate('setMovie', [GardenGlobals.MOVIE_HARVEST, doId]) + + av.d_setInventory(av.getInventory()) + + self.lastHarvested = int(time.time()) + self.sendUpdate('setFruiting', [self.getFruiting()]) + self.d_setMovie(GardenGlobals.MOVIE_HARVEST) + self.update() + + def removeItem(self): + avId = self.air.getAvatarIdFromSender() + self.d_setMovie(GardenGlobals.MOVIE_REMOVE) + + def _remove(task): + if not self.air: + return + + plot = self.mgr.placePlot(self.treeIndex) + plot.setPlot(self.plot) + plot.setPos(self.getPos()) + plot.setH(self.getH()) + plot.setOwnerIndex(self.ownerIndex) + plot.generateWithRequired(self.zoneId) + + self.air.writeServerEvent('remove-tree', avId, plot=self.plot) + self.requestDelete() + + self.mgr.trees.remove(self) + + mdata = map(list, self.mgr.data['trees']) + mdata[self.treeIndex] = self.mgr.getNullPlant() + self.mgr.data['trees'] = mdata + self.mgr.update() + + self.mgr.reconsiderAvatarOrganicBonus() + + return task.done + + taskMgr.doMethodLater(7, _remove, self.uniqueName('do-remove')) + + def doGrow(self, grown): + maxGrowth = self.growthThresholds[2] + newGL = max(0, min(self.growthLevel + grown, maxGrowth)) + oldGrowthLevel = self.growthLevel + + self.b_setGrowthLevel(newGL) + self.update() + + return newGL - oldGrowthLevel + +@magicWord(category=CATEGORY_PROGRAMMER, types=[int, int, int]) +def satanGrow(track, index, grown=21): + av = spellbook.getTarget() + estate = av.air.estateManager._lookupEstate(av) + + if not estate: + return 'Estate not found!' + + garden = estate.gardenManager.gardens.get(av.doId) + if not garden: + return 'Garden not found!' + + tree = garden.getTree(track, index) + if not tree: + return 'Tree not found!' + + result = tree.doGrow(grown) + return 'Satan has grown %d units!' % result + +@magicWord(category=CATEGORY_PROGRAMMER, types=[int, int]) +def satanFruit(track, index): + av = spellbook.getTarget() + estate = av.air.estateManager._lookupEstate(av) + + if not estate: + return 'Estate not found!' + + garden = estate.gardenManager.gardens.get(av.doId) + if not garden: + return 'Garden not found!' + + tree = garden.getTree(track, index) + if not tree: + return 'Tree not found!' + + tree.calculate(0, tree.lastCheck) + tree.sendUpdate('setFruiting', [tree.getFruiting()]) + return 'Satan is now fruiting!' + \ No newline at end of file diff --git a/toontown/estate/DistributedGarden.py b/toontown/estate/DistributedGarden.py index 46ee2ea5..8a559e34 100755 --- a/toontown/estate/DistributedGarden.py +++ b/toontown/estate/DistributedGarden.py @@ -12,7 +12,6 @@ class DistributedGarden(DistributedObject.DistributedObject): def __init__(self, cr): self.notify.debug('init') DistributedObject.DistributedObject.__init__(self, cr) - self.lt = base.localAvatar self.props = [] self.pos = None self.radius = 0 @@ -23,7 +22,6 @@ class DistributedGarden(DistributedObject.DistributedObject): self.dx = 1.0 / self.gridCells self.occupied = [] - return def generate(self): DistributedObject.DistributedObject.generate(self) diff --git a/toontown/estate/DistributedGardenAI.py b/toontown/estate/DistributedGardenAI.py index 302e02d0..34378ce2 100755 --- a/toontown/estate/DistributedGardenAI.py +++ b/toontown/estate/DistributedGardenAI.py @@ -4,25 +4,6 @@ from direct.distributed.DistributedObjectAI import DistributedObjectAI class DistributedGardenAI(DistributedObjectAI): notify = DirectNotifyGlobal.directNotify.newCategory("DistributedGardenAI") - def __init__(self, air): - DistributedObjectAI.__init__(self, air) - self.air = air - self.props = [] + def sendNewProp(self, todo0, todo1, todo2, todo3): + pass - def generate(self): - DistributedObjectAI.generate(self) - - def announceGenerate(self): - DistributedObjectAI.announceGenerate(self) - - def disable(self): - DistributedObjectAI.disable(self) - - def delete(self): - DistributedObjectAI.delete(self) - - def setProps(self, props): - self.props = props - - def d_sendNewProp(self, prop, x, y, z): - self.sendUpdate('sendNewProp', [prop, x, y, z]) diff --git a/toontown/estate/DistributedGardenBox.py b/toontown/estate/DistributedGardenBox.py index b62dcf13..48edda74 100755 --- a/toontown/estate/DistributedGardenBox.py +++ b/toontown/estate/DistributedGardenBox.py @@ -11,7 +11,7 @@ from pandac.PandaModules import Vec3 class DistributedGardenBox(DistributedLawnDecor.DistributedLawnDecor): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedGardenPlot') - + def __init__(self, cr): DistributedLawnDecor.DistributedLawnDecor.__init__(self, cr) self.plantPath = NodePath('plantPath') @@ -19,25 +19,21 @@ class DistributedGardenBox(DistributedLawnDecor.DistributedLawnDecor): self.plotScale = 1.0 self.plantingGuiDoneEvent = 'plantingGuiDone' self.defaultModel = 'phase_5.5/models/estate/planterC' - - def announceGenerate(self): - self.notify.debug('announceGenerate') - DistributedLawnDecor.DistributedLawnDecor.announceGenerate(self) - + def doModelSetup(self): if self.typeIndex == GardenGlobals.BOX_THREE: self.defaultModel = 'phase_5.5/models/estate/planterA' elif self.typeIndex == GardenGlobals.BOX_TWO: self.defaultModel = 'phase_5.5/models/estate/planterC' else: - self.defaultModel = 'phase_5.5/models/estate/planterB' + self.defaultModel = 'phase_5.5/models/estate/planterD' self.collSphereOffset = 0.0 self.collSphereRadius = self.collSphereRadius * 1.41 self.plotScale = Vec3(1.0, 1.0, 1.0) - + def setupShadow(self): pass - + def loadModel(self): self.rotateNode = self.plantPath.attachNewNode('rotate') self.model = None @@ -45,13 +41,13 @@ class DistributedGardenBox(DistributedLawnDecor.DistributedLawnDecor): self.model.setScale(self.plotScale) self.model.reparentTo(self.rotateNode) self.stick2Ground() - return - + def handleEnterPlot(self, entry = None): pass - + def handleExitPlot(self, entry = None): DistributedLawnDecor.DistributedLawnDecor.handleExitPlot(self, entry) - + def setTypeIndex(self, typeIndex): self.typeIndex = typeIndex + \ No newline at end of file diff --git a/toontown/estate/DistributedGardenBoxAI.py b/toontown/estate/DistributedGardenBoxAI.py index 1c24b315..eadd31a9 100755 --- a/toontown/estate/DistributedGardenBoxAI.py +++ b/toontown/estate/DistributedGardenBoxAI.py @@ -4,13 +4,9 @@ from toontown.estate.DistributedLawnDecorAI import DistributedLawnDecorAI class DistributedGardenBoxAI(DistributedLawnDecorAI): notify = DirectNotifyGlobal.directNotify.newCategory("DistributedGardenBoxAI") - def __init__(self, air): - DistributedLawnDecorAI.__init__(self, air) - self.air = air - self.typeIndex = 0 - def setTypeIndex(self, index): - self.typeIndex = index + self.index = index def getTypeIndex(self): - return self.typeIndex + return self.index + \ No newline at end of file diff --git a/toontown/estate/DistributedGardenPlot.py b/toontown/estate/DistributedGardenPlot.py index f613df9f..acfab9e6 100755 --- a/toontown/estate/DistributedGardenPlot.py +++ b/toontown/estate/DistributedGardenPlot.py @@ -2,6 +2,7 @@ import DistributedLawnDecor from direct.directnotify import DirectNotifyGlobal from direct.showbase.ShowBase import * from direct.interval.IntervalGlobal import * +from DistributedGardenBox import DistributedGardenBox import GardenGlobals from toontown.toonbase import TTLocalizer from toontown.estate import PlantingGUI @@ -14,6 +15,7 @@ import types class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedGardenPlot') + deferFor = 2 def __init__(self, cr): DistributedLawnDecor.DistributedLawnDecor.__init__(self, cr) @@ -25,7 +27,6 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor): self.defaultModel = 'phase_5.5/models/estate/dirt_mound' self.colorScaler = Vec4(1, 1, 1, 1) self.plantingGui = None - self.planted = None return def delete(self): @@ -43,7 +44,7 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor): elif self.plotType == GardenGlobals.FLOWER_TYPE: self.collSphereRadius = 2.0 self.collSphereOffset = 0.0 - self.plotScale = 0.7 + self.plotScale = 0.6 self.stickUp = 1.1 elif self.plotType == GardenGlobals.GAG_TREE_TYPE: self.collSphereRadius = 3.0 @@ -84,8 +85,6 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor): return self.getPlantingText() def handleEnterPlot(self, entry = None): - #Force Gardens -Zach - base.localAvatar.setGardenStarted(True) dist = self.getDistance(localAvatar) if self.canBePlanted(): base.localAvatar.addShovelRelatedDoId(self.doId) @@ -110,12 +109,7 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor): return plantText def canBePlanted(self): - retval = True - if not base.localAvatar.doId == self.getOwnerId(): - retval = False - if hasattr(self, 'planted') and self.planted: - retval = False - return retval + return base.localAvatar.doId == self.getOwnerId() def plantSomething(self): whatCanBePlanted = GardenGlobals.whatCanBePlanted(self.ownerIndex, self.plot) @@ -144,12 +138,12 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor): if recipeKey >= 0: species, variety = GardenGlobals.getSpeciesVarietyGivenRecipe(recipeKey) if species >= 0 and variety >= 0: - self.sendUpdate('plantFlower', [species, variety, base.localAvatar.doId]) + self.sendUpdate('plantFlower', [species, variety]) successPlanting = True else: self.notify.debug('%s %d is not a valid recipe' % (recipeStr, special)) burntBeans = len(recipeStr) - self.sendUpdate('plantNothing', [burntBeans, base.localAvatar.doId]) + self.sendUpdate('plantNothing', [burntBeans]) if successPlanting: flowerName = GardenGlobals.getFlowerVarietyName(species, variety) stringToShow = TTLocalizer.getResultPlantedSomethingSentence(flowerName) @@ -209,11 +203,11 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor): if species >= 205 and species <= 208: successToonStatue = True else: - self.sendUpdate('plantStatuary', [species, base.localAvatar.doId]) + self.sendUpdate('plantStatuary', [species]) else: self.notify.debug('%s %d is not a valid recipe' % (recipeStr, special)) burntBeans = len(recipeStr) - self.sendUpdate('plantNothing', [burntBeans, base.localAvatar.doId]) + self.sendUpdate('plantNothing', [burntBeans]) if successPlanting: itemName = GardenGlobals.PlantAttributes[species]['name'] stringToShow = TTLocalizer.getResultPlantedSomethingSentence(itemName) @@ -252,7 +246,7 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor): base.localAvatar.showGardeningGui() base.localAvatar.removeShovelRelatedDoId(self.doId) if willPlant: - self.sendUpdate('plantToonStatuary', [species, dnaCode, base.localAvatar.doId]) + self.sendUpdate('plantToonStatuary', [species, dnaCode]) else: self.popupItemPlantingGui() return @@ -271,21 +265,11 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor): base.localAvatar.showGardeningGui() base.localAvatar.removeShovelRelatedDoId(self.doId) if willPlant: - self.sendUpdate('plantGagTree', [gagTrack, gagLevel, base.localAvatar.doId]) + self.sendUpdate('plantGagTree', [gagTrack, gagLevel]) else: self.finishInteraction() return - def plantedItem(self, doId): - self.planted = doId - - def removePlanted(self): - if self.planted: - item = base.cr.doId2do.get(self.planted) - if item: - item.delete() - self.planted = None - def setMovie(self, mode, avId): if mode == GardenGlobals.MOVIE_PLANT: self.doPlaceItemTrack(avId) @@ -316,8 +300,8 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor): self.movie.append(Func(toon.detachShovel)) if self.model: pos = self.model.getPos() - pos.setZ(pos[2] + 1) - animProp = LerpPosInterval(self.model, 3, pos, self.model.getPos()) + pos.setZ(pos[2] - 1) + animProp = LerpPosInterval(self.model, 3, self.model.getPos(), pos) shrinkProp = LerpScaleInterval(self.model, 3, scale=self.plotScale, startScale=0.01) objAnimShrink = ParallelEndTogether(animProp, shrinkProp) self.movie.append(objAnimShrink) @@ -325,16 +309,10 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor): self.movie.append(Func(toon.loop, 'neutral')) if avId == localAvatar.doId: self.movie.append(Func(self.finishInteraction)) - self.movie.append(Func(self.removePlanted)) + self.movie.append(Func(self.movieDone)) self.movie.start() def doPlaceItemTrack(self, avId, item = None): - if avId == 999999999: - pos = self.model.getPos() - pos.setZ(pos[2] - 1) - self.model.setPos(pos) - self.model.setScale(0.01) - return toon = base.cr.doId2do.get(avId) if not toon: return @@ -348,24 +326,14 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor): self.movie = Sequence(self.startCamIval(avId), moveTrack, Func(shovel.show), placeItemTrack) if avId == localAvatar.doId: self.expectingReplacement = 1 - self.movie.append(Func(self.sendUpdate, 'finishPlanting', [avId])) + self.movie.append(Func(self.movieDone)) self.movie.start() def generatePlaceItemTrack(self, toon, item): sound = loader.loadSfx('phase_5.5/audio/sfx/burrow.ogg') sound.setPlayRate(0.5) placeItemTrack = Parallel() - placeItemTrack.append(Sequence(ActorInterval(toon, 'start-dig'), - Parallel(ActorInterval(toon, 'loop-dig', loop=1, duration=5.13), - Sequence(Wait(0.25), - SoundInterval(sound, node=toon, duration=0.55), - Wait(0.8), - SoundInterval(sound, node=toon, duration=0.55), - Wait(1.35), - SoundInterval(sound, node=toon, duration=0.55))), - ActorInterval(toon, 'start-dig', playRate=-1), - Func(toon.loop, 'neutral'), - Func(toon.detachShovel))) + placeItemTrack.append(Sequence(ActorInterval(toon, 'start-dig'), Parallel(ActorInterval(toon, 'loop-dig', loop=1, duration=5.13), Sequence(Wait(0.25), SoundInterval(sound, node=toon, duration=0.55), Wait(0.8), SoundInterval(sound, node=toon, duration=0.55), Wait(1.35), SoundInterval(sound, node=toon, duration=0.55))), ActorInterval(toon, 'start-dig', playRate=-1), Func(toon.loop, 'neutral'), Func(toon.detachShovel))) if self.model: pos = self.model.getPos() pos.setZ(pos[2] - 1) @@ -374,12 +342,7 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor): objAnimShrink = ParallelEndTogether(animProp, shrinkProp) placeItemTrack.append(objAnimShrink) if item: - placeItemTrack.append(Sequence(Func(item.reparentTo, toon.rightHand), - Wait(0.55), - Func(item.wrtReparentTo, render), - Parallel(LerpHprInterval(item, hpr=self.getHpr(render), duration=1.2), - ProjectileInterval(item, endPos=self.getPos(render), duration=1.2, gravityMult=0.45)), - Func(item.removeNode))) + placeItemTrack.append(Sequence(Func(item.reparentTo, toon.rightHand), Wait(0.55), Func(item.wrtReparentTo, render), Parallel(LerpHprInterval(item, hpr=self.getHpr(render), duration=1.2), ProjectileInterval(item, endPos=self.getPos(render), duration=1.2, gravityMult=0.45)), Func(item.removeNode))) return placeItemTrack def makeMovieNode(self): @@ -390,3 +353,25 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor): self.stick2Ground() else: DistributedLawnDecor.DistributedLawnDecor.makeMovieNode(self) + + def setBoxDoId(self, boxId, index): + self.index = index + if boxId in base.cr.doId2do: + self.setBox(base.cr.doId2do[boxId]) + else: + self.acceptOnce('generate-%d' % boxId, self.setBox) + + def setBox(self, box): + x = GardenGlobals.FLOWER_POS[box.typeIndex][self.index] + + self.setPos(0, 0, 0) + self.reparentTo(box) + self.setZ(1.2) + self.setX(x) + + def stick2Ground(self, *args, **kwargs): + plotType = GardenGlobals.whatCanBePlanted(self.ownerIndex, self.plot) + if plotType == GardenGlobals.FLOWER_TYPE: + return + + return DistributedLawnDecor.DistributedLawnDecor.stick2Ground(self, *args, **kwargs) diff --git a/toontown/estate/DistributedGardenPlotAI.py b/toontown/estate/DistributedGardenPlotAI.py index ad9f0376..648f9b38 100755 --- a/toontown/estate/DistributedGardenPlotAI.py +++ b/toontown/estate/DistributedGardenPlotAI.py @@ -1,189 +1,243 @@ from direct.directnotify import DirectNotifyGlobal -from toontown.estate.DistributedLawnDecorAI import DistributedLawnDecorAI -from DistributedToonStatuaryAI import DistributedToonStatuaryAI -from DistributedStatuaryAI import DistributedStatuaryAI -from DistributedGagTreeAI import DistributedGagTreeAI -from DistributedFlowerAI import DistributedFlowerAI +from otp.ai.MagicWordGlobal import * +from DistributedLawnDecorAI import DistributedLawnDecorAI import GardenGlobals -import datetime - -slots2plots = { - 0: GardenGlobals.plots0, - 1: GardenGlobals.plots1, - 2: GardenGlobals.plots2, - 3: GardenGlobals.plots3, - 4: GardenGlobals.plots4, - 5: GardenGlobals.plots5 -} class DistributedGardenPlotAI(DistributedLawnDecorAI): - notify = DirectNotifyGlobal.directNotify.newCategory("DistributedGardenPlotAI") - - def __init__(self, air): - DistributedLawnDecorAI.__init__(self, air) - self.air = air - self.planted = None - + notify = DirectNotifyGlobal.directNotify.newCategory('DistributedGardenPlotAI') + def announceGenerate(self): DistributedLawnDecorAI.announceGenerate(self) - - def delete(self): - DistributedLawnDecorAI.delete(self) - - def disable(self): - DistributedLawnDecorAI.disable(self) - - def finishPlanting(self, avId): - self.planted.generateWithRequired(self.zoneId) - self.addData() - self.sendUpdate('plantedItem', [self.planted.doId]) - self.planted.sendUpdate('setMovie', [GardenGlobals.MOVIE_FINISHPLANTING, avId]) - - def finishRemoving(self, avId): - self.removeData() - self.planted.removeNode() - self.planted.delete() - simbase.air.removeObject(self.planted.doId) - self.planted = None - self.sendUpdate('setMovie', [GardenGlobals.MOVIE_FINISHREMOVING, avId]) - - def addData(self): - estate = simbase.air.doId2do.get(self.getEstate()) - plantedAt = int(datetime.datetime.now().strftime('%Y%m%d%H%M')) # TODO: Possibly store this in mongodb/cPickle instead. - if isinstance(self.planted, DistributedFlowerAI): - data = [ - self.getPlot(), - GardenGlobals.FLOWER_TYPE, - self.planted.getTypeIndex(), - self.planted.getVariety(), - self.planted.getWaterLevel(), - self.planted.getGrowthLevel(), - 0, - plantedAt, - plantedAt - ] - elif isinstance(self.planted, DistributedGagTreeAI): - data = [ - self.getPlot(), - GardenGlobals.GAG_TREE_TYPE, - self.planted.getTypeIndex(), - 0, - self.planted.getWaterLevel(), - self.planted.getGrowthLevel(), - 0, - plantedAt, - plantedAt - ] - elif isinstance(self.planted, DistributedToonStatuaryAI): - data = [ - self.getPlot(), - GardenGlobals.TOON_STATUARY_TYPE, - self.planted.getTypeIndex(), - 0, - self.planted.getWaterLevel(), - self.planted.getGrowthLevel(), - self.planted.getOptional(), - plantedAt, - plantedAt - ] - elif isinstance(self.planted, DistributedStatuaryAI): - data = [ - self.getPlot(), - GardenGlobals.STATUARY_TYPE, - self.planted.getTypeIndex(), - 0, - self.planted.getWaterLevel(), - self.planted.getGrowthLevel(), - 0, - plantedAt, - plantedAt - ] - else: + self.plotType = GardenGlobals.whatCanBePlanted(self.ownerIndex, self.plot) + self.__plantingAvId = 0 + + def __initialSanityCheck(self, wantedType=None, forceOwner=False): + if self.__plantingAvId: + # Busy, silently ignore return - estate.items[self.getOwnerIndex()].append(tuple(data)) - estate.updateItems() + + avId = self.air.getAvatarIdFromSender() + + av = self.air.doId2do.get(avId) + if not av: + self.air.writeServerEvent('suspicious', avId, 'called DistributedGardenPlotAI method outside shard!') + return + + if wantedType is not None and self.plotType != wantedType: + self.air.writeServerEvent('suspicious', avId, 'called incorrect DistributedGardenPlotAI method!', plotType=self.plotType, + wantedType=wantedType) + return self.d_interactionDenied() + + + if avId != self.ownerDoId and not forceOwner: + self.air.writeServerEvent('suspicious', avId, 'called someone else\'s DistributedGardenPlotAI plant method!', + ownerDoId=self.ownerDoId) + return self.d_interactionDenied() + + return av - def removeData(self): - estate = simbase.air.doId2do.get(self.getEstate()) - dataIndex = -1 - for n, item in enumerate(estate.items[self.getOwnerIndex()]): - if item[0] == self.getPlot(): - dataIndex = n - if dataIndex >= 0: - del estate.items[self.getOwnerIndex()][dataIndex] - estate.updateItems() + def plantFlower(self, species, variety, usingSatanFlowerAll=0): + av = self.__initialSanityCheck(GardenGlobals.FLOWER_TYPE if not usingSatanFlowerAll else None, usingSatanFlowerAll) + if not av: + return + + def invalid(problem): + msg = 'tried to plant flower but something went wrong: %s' % problem + self.notify.warning('%d %s' % (av.doId, msg)) + self.air.writeServerEvent('suspicious', av.doId, msg) + if not usingSatanFlowerAll: + return self.d_setMovie(GardenGlobals.MOVIE_PLANT_REJECTED) + + attr = GardenGlobals.PlantAttributes.get(species, {}) + if attr.get('plantType') != GardenGlobals.FLOWER_TYPE: + return invalid('invalid species: %d' % species) + + if variety >= len(attr['varieties']): + return invalid('invalid variety: %d' % variety) + + if not usingSatanFlowerAll: + cost = len(GardenGlobals.Recipes[attr['varieties'][variety][0]]['beans']) + av.takeMoney(cost) + + self.d_setMovie(GardenGlobals.MOVIE_PLANT) + + def _plant(task): + flower = self.mgr.plantFlower(self.flowerIndex, species, variety, plot=self, + ownerIndex=self.ownerIndex, plotId=self.plot, + waterLevel=0) + index = (0, 1, 2, 2, 2, 3, 3, 3, 4, 4)[self.flowerIndex] + idx = (0, 0, 0, 1, 2, 0, 1, 2, 0, 1)[self.flowerIndex] + flower.sendUpdate('setBoxDoId', [self.mgr._boxes[index].doId, idx]) + + if not usingSatanFlowerAll: + flower.d_setMovie(GardenGlobals.MOVIE_FINISHPLANTING, self.__plantingAvId) + flower.d_setMovie(GardenGlobals.MOVIE_CLEAR, self.__plantingAvId) + + self.air.writeServerEvent('plant-flower', self.__plantingAvId, species=species, variety=variety, + plot=self.plot, name=attr.get('name', 'unknown satan flower')) + if task: + return task.done + + if usingSatanFlowerAll: + _plant(None) + + else: + taskMgr.doMethodLater(7, _plant, self.uniqueName('do-plant')) + + self.__plantingAvId = av.doId + return 1 + + def plantGagTree(self, track, index): + av = self.__initialSanityCheck(GardenGlobals.GAG_TREE_TYPE) + if not av: + return + + for i in xrange(index): + if not self.mgr.hasTree(track, i): + msg = 'tried to plant tree but an index is missing: %d' % index + self.notify.warning('%d %s' % (av.doId, msg)) + self.air.writeServerEvent('suspicious', av.doId, msg) + return self.d_setMovie(GardenGlobals.MOVIE_PLANT_REJECTED) + + if self.mgr.hasTree(track, index): + msg = 'tried to plant tree but gag already planted' + self.notify.warning('%d %s' % (av.doId, msg)) + self.air.writeServerEvent('suspicious', av.doId, msg) + return self.d_setMovie(GardenGlobals.MOVIE_PLANT_REJECTED) + + if av.inventory.useItem(track, index) == -1: + msg = 'tried to plant tree but not carrying selected gag' + self.notify.warning('%d %s' % (av.doId, msg)) + self.air.writeServerEvent('suspicious', av.doId, msg) + return self.d_setMovie(GardenGlobals.MOVIE_PLANT_REJECTED) + + av.d_setInventory(av.getInventory()) + self.d_setMovie(GardenGlobals.MOVIE_PLANT) + + def _plant(task): + if not self.air: + return + + tree = self.mgr.plantTree(self.treeIndex, track * 7 + index, plot=self, ownerIndex=self.ownerIndex, + plotId=self.plot, pos=(self.getPos(), self.getH())) + tree.d_setMovie(GardenGlobals.MOVIE_FINISHPLANTING, self.__plantingAvId) + tree.d_setMovie(GardenGlobals.MOVIE_CLEAR, self.__plantingAvId) + self.air.writeServerEvent('plant-tree', self.__plantingAvId, track=track, index=index, plot=self.plot) + return task.done + + taskMgr.doMethodLater(7, _plant, self.uniqueName('do-plant')) + self.__plantingAvId = av.doId - def plantFlower(self, species, variety, toon): - #free for now - #av = simbase.air.doId2do.get(toon) - #av.takeMoney(GardenGlobals.getNumBeansRequired(species, variety)) - self.planted = DistributedFlowerAI(self.air) - self.planted.setEstate(self.getEstate()) - self.planted.setOwnerPlot(self.doId) - self.planted.setPlot(self.getPlot()) - self.planted.setHeading(self.getHeading()) - self.planted.setPosition(*self.getPosition()) - self.planted.setOwnerIndex(self.getOwnerIndex()) - self.planted.setWaterLevel(0) - self.planted.setGrowthLevel(0) - self.planted.setTypeIndex(species) - self.planted.setVariety(variety) - self.sendUpdate('setMovie', [GardenGlobals.MOVIE_PLANT, toon]) + def plantStatuary(self, species): + av = self.__initialSanityCheck(GardenGlobals.STATUARY_TYPE) + if not av: + return + + def invalid(problem): + msg = 'tried to plant statuary but something went wrong: %s' % problem + self.notify.warning('%d %s' % (av.doId, msg)) + self.air.writeServerEvent('suspicious', av.doId, msg) + return self.d_setMovie(GardenGlobals.MOVIE_PLANT_REJECTED) + + attr = GardenGlobals.PlantAttributes.get(species, {}) + if attr.get('plantType') != GardenGlobals.STATUARY_TYPE: + return invalid('invalid species: %d' % species) + + it = species - 100 + if it == 134: + it = 135 + + if not av.removeGardenItem(it, 1): + return invalid('av doesn\'t own item: %d' % species) + + self.d_setMovie(GardenGlobals.MOVIE_PLANT) + + def _plant(task): + if not self.air: + return + + statuary = self.mgr.placeStatuary(self.mgr.S_pack(0, 0, species, 0), plot=self, + ownerIndex=self.ownerIndex, plotId=self.plot, + pos=(self.getPos(), self.getH()), generate=False) + statuary.generateWithRequired(self.zoneId) + statuary.d_setMovie(GardenGlobals.MOVIE_FINISHPLANTING, self.__plantingAvId) + statuary.d_setMovie(GardenGlobals.MOVIE_CLEAR, self.__plantingAvId) + self.air.writeServerEvent('plant-statuary', self.__plantingAvId, species=species, plot=self.plot) + return task.done + + taskMgr.doMethodLater(7, _plant, self.uniqueName('do-plant')) + self.__plantingAvId = av.doId - def plantGagTree(self, track, level, toon): - #free for now - #av = simbase.air.doId2do.get(toon) - #av.inventory.useItem(track, level) - #av.d_setInventory(av.inventory.makeNetString()) - self.planted = DistributedGagTreeAI(self.air) - self.planted.setEstate(self.getEstate()) - self.planted.setOwnerPlot(self.doId) - self.planted.setPlot(self.getPlot()) - self.planted.setHeading(self.getHeading()) - self.planted.setPosition(*self.getPosition()) - self.planted.setOwnerIndex(self.getOwnerIndex()) - self.planted.setTypeIndex(GardenGlobals.getTreeTypeIndex(track, level)) - self.planted.setWaterLevel(0) - self.planted.setGrowthLevel(0) - self.sendUpdate('setMovie', [GardenGlobals.MOVIE_PLANT, toon]) + def plantToonStatuary(self, species, dnaCode): + av = self.__initialSanityCheck(GardenGlobals.STATUARY_TYPE) + if not av: + return + + def invalid(problem): + msg = 'tried to plant statuary but something went wrong: %s' % problem + self.notify.warning('%d %s' % (av.doId, msg)) + self.air.writeServerEvent('suspicious', av.doId, msg) + return self.d_setMovie(GardenGlobals.MOVIE_PLANT_REJECTED) + + attr = GardenGlobals.PlantAttributes.get(species, {}) + if attr.get('plantType') != GardenGlobals.STATUARY_TYPE: + return invalid('invalid species: %d' % species) + + if not av.removeGardenItem(species - 100, 1): + return invalid('av doesn\'t own item: %d' % species) + + self.d_setMovie(GardenGlobals.MOVIE_PLANT) + + def _plant(task): + if not self.air: + return + + statuary = self.mgr.placeStatuary(self.mgr.S_pack(dnaCode, 0, species, 0), plot=self, + ownerIndex=self.ownerIndex, plotId=self.plot, + pos=(self.getPos(), self.getH()), generate=False) + statuary.generateWithRequired(self.zoneId) + statuary.d_setMovie(GardenGlobals.MOVIE_FINISHPLANTING, self.__plantingAvId) + self.air.writeServerEvent('plant-statuary', self.__plantingAvId, species=species, plot=self.plot) + return task.done + + taskMgr.doMethodLater(7, _plant, self.uniqueName('do-plant')) + self.__plantingAvId = av.doId - def plantStatuary(self, species, toon): - #free for now - #av = simbase.air.doId2do.get(toon) - #av.takeMoney(GardenGlobals.getNumBeansRequired(species, 0)) - self.planted = DistributedStatuaryAI(self.air) - self.planted.setEstate(self.getEstate()) - self.planted.setOwnerPlot(self.doId) - self.planted.setPlot(self.getPlot()) - self.planted.setHeading(self.getHeading()) - self.planted.setPosition(*self.getPosition()) - self.planted.setOwnerIndex(self.getOwnerIndex()) - self.planted.setTypeIndex(species) - self.planted.setWaterLevel(0) - self.planted.setGrowthLevel(0) - self.sendUpdate('setMovie', [GardenGlobals.MOVIE_PLANT, toon]) - - def plantToonStatuary(self, species, dnaCode, toon): - #free for now - #av = simbase.air.doId2do.get(toon) - #av.takeMoney(GardenGlobals.getNumBeansRequired(species, 0)) - self.planted = DistributedToonStatuaryAI(self.air) - self.planted.setEstate(self.getEstate()) - self.planted.setOwnerPlot(self.doId) - self.planted.setPlot(self.getPlot()) - self.planted.setHeading(self.getHeading()) - self.planted.setPosition(*self.getPosition()) - self.planted.setOwnerIndex(self.getOwnerIndex()) - self.planted.setTypeIndex(species) - self.planted.setWaterLevel(0) - self.planted.setGrowthLevel(0) - self.planted.setOptional(dnaCode) - self.sendUpdate('setMovie', [GardenGlobals.MOVIE_PLANT, toon]) - - def plantNothing(self, burntBeans, toon): - # TODO: Fix exploit. - sendAvId = self.air.getAvatarIdFromSender() - av = self.air.doId2do.get(sendAvId) + def plantNothing(self, burntBeans): + av = self.__initialSanityCheck() if av: av.takeMoney(burntBeans) - self.planted = None + +@magicWord(category=CATEGORY_PROGRAMMER, types=[int, int]) +def satanFlowerAll(species=49, variety=0): + invoker = spellbook.getInvoker() + av = spellbook.getTarget() + estate = av.air.estateManager._lookupEstate(av) + + if not estate: + return 'Estate not found!' + + garden = estate.gardenManager.gardens.get(av.doId) + if not garden: + return 'Garden not found!' + + i = 0 + for obj in garden.objects.copy(): + if isinstance(obj, DistributedGardenPlotAI): + if obj.plotType != GardenGlobals.FLOWER_TYPE: + continue + + if not obj.plantFlower(species, variety, 1): + return 'Error on plot %d' % i + + i += 1 + + return '%d disgusting flowers planted' % i + +@magicWord(category=CATEGORY_PROGRAMMER) +def gibSpecials(): + av = spellbook.getTarget() + av.gardenSpecials = [] + for x in (100, 101, 103, 105, 106, 107, 108, 130, 131, 135): + av.addGardenItem(x, 99) + \ No newline at end of file diff --git a/toontown/estate/DistributedHouseAI.py b/toontown/estate/DistributedHouseAI.py index 20cda9c6..407b5ac5 100755 --- a/toontown/estate/DistributedHouseAI.py +++ b/toontown/estate/DistributedHouseAI.py @@ -21,7 +21,7 @@ class DistributedHouseAI(DistributedObjectAI): self.name = '' self.color = 0 self.housePos = 0 - self.gender = 1 + self.gender = 0 self.isInteriorInitialized = 1 self.atticItems = CatalogItemList(store=Customization) @@ -55,12 +55,6 @@ class DistributedHouseAI(DistributedObjectAI): if self.avatarId: self.mailbox = DistributedMailboxAI(self.air, self) self.mailbox.generateWithRequired(self.zoneId) - - if not self.isInteriorInitialized: - self.notify.info('Initializing interior...') - self.interior.initialize() - self.b_setInteriorInitialized(1) - self.sendUpdate('setHouseReady', []) def delete(self): @@ -275,16 +269,17 @@ class DistributedHouseAI(DistributedObjectAI): self.atticItems.append(item) elif item.replacesExisting() and item.hasExisting(): if item.getFlags() & FLCloset: - closets = ClosetToClothes.keys() + items = ClosetToClothes.keys() if item.getFlags() & FLCloset else BankToMoney.keys() + for itItem in self.interiorItems: - if itItem.furnitureType in closets: + if itItem.furnitureType in items: posHpr = itItem.posHpr self.interiorItems.remove(itItem) item.posHpr = posHpr self.interiorItems.append(item) break for itItem in self.atticItems: - if itItem.furnitureType in closets: + if itItem.furnitureType in items: self.atticItems.remove(itItem) self.atticItems.append(item) break @@ -305,3 +300,9 @@ class DistributedHouseAI(DistributedObjectAI): self.atticWallpaper.append(item) self.d_setAtticWallpaper(self.atticWallpaper.getBlob()) self.interior.furnitureManager.loadFromHouse() + + def initializeInterior(self): + if (not self.isInteriorInitialized): + self.notify.info('Initializing interior...') + self.interior.initialize() + self.b_setInteriorInitialized(1) \ No newline at end of file diff --git a/toontown/estate/DistributedHouseInteriorAI.py b/toontown/estate/DistributedHouseInteriorAI.py index c48727ff..1805f1f0 100755 --- a/toontown/estate/DistributedHouseInteriorAI.py +++ b/toontown/estate/DistributedHouseInteriorAI.py @@ -70,7 +70,7 @@ class DistributedHouseInteriorAI(DistributedObjectAI): dnaData = loadDNAFileAI(dnaStorage, dnaFile) # Read it into furniture... - furnitureReader = DNAFurnitureReaderAI(dnaData, [-11, 2, 0, 0, 0, 0]) + furnitureReader = DNAFurnitureReaderAI(dnaData, self.house.gender, [-11, 2, 0, 0, 0, 0]) # Set furniture: self.furnitureManager.setItems(furnitureReader.getBlob()) diff --git a/toontown/estate/DistributedLawnDecor.py b/toontown/estate/DistributedLawnDecor.py index 9c42e2b7..1a2a7c1b 100755 --- a/toontown/estate/DistributedLawnDecor.py +++ b/toontown/estate/DistributedLawnDecor.py @@ -1,4 +1,4 @@ -from panda3d.core import * +from pandac.PandaModules import * from direct.interval.IntervalGlobal import * from direct.distributed import ClockDelta from direct.showbase.PythonUtil import lerp @@ -16,6 +16,7 @@ from otp.otpbase import OTPGlobals from toontown.estate import GardenGlobals def recurseParent(intoNode, ParentName): + # funny fact: cogtown had a func like this parent = intoNode.getParent(0) if not parent or parent.getName() == 'render': return 0 @@ -50,6 +51,7 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast return def setHeading(self, h): + self.notify.debug('setting h') DistributedNode.DistributedNode.setH(self, h) def generateInit(self): @@ -93,6 +95,11 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast if not self.rotateNode: self.rotateNode = self.plantPath.attachNewNode('rotate') self.model = None + if __dev__: + self.model = loader.loadModel(self.defaultModel) + self.model.setScale(0.4, 0.4, 0.1) + self.model.reparentTo(self.rotateNode) + return def setupShadow(self): self.shadowJoint = self.rotateNode.attachNewNode('shadow') @@ -121,6 +128,7 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast self.accept(self.exitMessageName, self.handleExitPlot) def handleEnterPlot(self, optional = None): + self.notify.debug('handleEnterPlot %d' % self.doId) self.sendUpdate('plotEntered', []) def handleExitPlot(self, optional = None): @@ -142,12 +150,6 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast taskMgr.remove(self.uniqueName('adjust tree')) return - def setEstate(self, estate): - self.estate = estate - - def getEstate(self): - return self.estate - def setPos(self, x, y, z): DistributedNode.DistributedNode.setPos(self, x, y, z) self.stick2Ground() @@ -197,12 +199,12 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast def stickParts(self): pass - def setH(self, h): - DistributedNode.DistributedNode.setH(self, h) - def setPlot(self, plot): self.plot = plot + def setH(self, h): + DistributedNode.DistributedNode.setH(self, h) + def getPlot(self): return self.plot @@ -242,7 +244,7 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast base.localAvatar.hideShovelButton() base.localAvatar.hideWateringCanButton() self.startInteraction() - self.sendUpdate('removeItem', [base.localAvatar.doId]) + self.sendUpdate('removeItem', []) def generateToonMoveTrack(self, toon): node = NodePath('tempNode') @@ -261,10 +263,7 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast finalY = node.getY(render) finalZ = node.getZ(render) node.removeNode() - toonTrack = Sequence(Parallel(ActorInterval(toon, 'walk', loop=True, duration=1), - Parallel(LerpPosInterval(toon, 1.0, Point3(finalX, finalY, toon.getZ(render)), fluid=True, bakeInStart=False)), - LerpHprInterval(toon, 1.0, hpr=hpr)), - Func(toon.loop, 'neutral')) + toonTrack = Sequence(Parallel(ActorInterval(toon, 'walk', loop=True, duration=1), Parallel(LerpPosInterval(toon, 1.0, Point3(finalX, finalY, toon.getZ(render)), fluid=True, bakeInStart=False)), LerpHprInterval(toon, 1.0, hpr=hpr)), Func(toon.loop, 'neutral')) return toonTrack def unprint(self, string): @@ -288,16 +287,13 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast def startCamIval(self, avId): track = Sequence() if avId == localAvatar.doId: - track = Sequence(Func(base.localAvatar.disableSmartCameraViews), - Func(base.localAvatar.setCameraPosForPetInteraction)) + track = Sequence(Func(base.localAvatar.disableSmartCameraViews), Func(base.localAvatar.setCameraPosForPetInteraction)) return track def stopCamIval(self, avId): track = Sequence() if avId == localAvatar.doId: - track = Sequence(Func(base.localAvatar.unsetCameraPosForPetInteraction), - Wait(0.8), - Func(base.localAvatar.enableSmartCameraViews)) + track = Sequence(Func(base.localAvatar.unsetCameraPosForPetInteraction), Wait(0.8), Func(base.localAvatar.enableSmartCameraViews)) return track def canBeWatered(self): @@ -332,8 +328,6 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast if not toon: return self.finishMovies() - if avId == localAvatar.doId: - self.startInteraction() self.model.setTransparency(1) self.model.setAlphaScale(1) shovel = toon.attachShovel() @@ -341,11 +335,9 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast moveTrack = self.generateToonMoveTrack(toon) digupTrack = self.generateDigupTrack(toon) self.movie = Sequence(self.startCamIval(avId), moveTrack, Func(shovel.show), digupTrack) - self.movie.append(Func(base.cr.removeObject, self.doId)) if avId == localAvatar.doId: - self.expectingReplacement = 1 - plotAv = base.cr.doId2do.get(self.getOwnerPlot()) - self.movie.append(Func(plotAv.sendUpdate, 'finishRemoving', [avId])) + # self.expectingReplacement = 1 + self.movie.append(Func(self.movieDone)) self.movie.start() def generateDigupTrack(self, toon): @@ -354,22 +346,7 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast pos = self.model.getPos() pos.setZ(pos[2] - 1) track = Parallel() - sq = Sequence(ActorInterval(toon, 'start-dig'), - Parallel(ActorInterval(toon, 'loop-dig', loop=1, duration=5.13), - Sequence(Wait(0.25), - SoundInterval(sound, node=toon, duration=0.55), - Wait(0.8), - SoundInterval(sound, node=toon, duration=0.55), - Wait(1.35), - SoundInterval(sound, node=toon, duration=0.55))), - ActorInterval(toon, 'start-dig', playRate=-1), - LerpFunc(self.model.setAlphaScale, fromData=1, toData=0, duration=1)) - if hasattr(self, 'signModel'): - sq.append(Parallel(LerpFunc(self.signModel.setAlphaScale, fromData=1, toData=0, duration=1), - LerpScaleInterval(self.signModel, 1, 0, 1))) - sq.append(Func(toon.loop, 'neutral')) - sq.append(Func(toon.detachShovel)) - track.append(sq) + track.append(Sequence(ActorInterval(toon, 'start-dig'), Parallel(ActorInterval(toon, 'loop-dig', loop=1, duration=5.13), Sequence(Wait(0.25), SoundInterval(sound, node=toon, duration=0.55), Wait(0.8), SoundInterval(sound, node=toon, duration=0.55), Wait(1.35), SoundInterval(sound, node=toon, duration=0.55))), ActorInterval(toon, 'start-dig', playRate=-1), LerpFunc(self.model.setAlphaScale, fromData=1, toData=0, duration=1), Func(toon.loop, 'neutral'), Func(toon.detachShovel))) return track def doFinishPlantingTrack(self, avId): diff --git a/toontown/estate/DistributedLawnDecorAI.py b/toontown/estate/DistributedLawnDecorAI.py index 3f297c48..6bc3c61d 100755 --- a/toontown/estate/DistributedLawnDecorAI.py +++ b/toontown/estate/DistributedLawnDecorAI.py @@ -1,68 +1,40 @@ from direct.directnotify import DirectNotifyGlobal from direct.distributed.DistributedNodeAI import DistributedNodeAI -import GardenGlobals class DistributedLawnDecorAI(DistributedNodeAI): notify = DirectNotifyGlobal.directNotify.newCategory("DistributedLawnDecorAI") - def __init__(self, air): - DistributedNodeAI.__init__(self, air) - self.air = air - self.plot = None - self.ownerIndex = None - - def announceGenerate(self): - DistributedNodeAI.announceGenerate(self) - - def delete(self): - DistributedNodeAI.delete(self) - - def disable(self): - DistributedNodeAI.disable(self) - - def setEstate(self, estate): - self.estate = estate - - def getEstate(self): - return self.estate - + def __init__(self, mgr): + self.mgr = mgr + DistributedNodeAI.__init__(self, self.mgr.air) + self.plot = 0 + self.ownerIndex = 0 + def setPlot(self, plot): self.plot = plot - + def getPlot(self): return self.plot - def setOwnerIndex(self, index): - self.ownerIndex = index + def getHeading(self): + return self.getH() + def getPosition(self): + return self.getPos() + + def setOwnerIndex(self, ownerIndex): + self.ownerIndex = ownerIndex + self.ownerDoId = self.mgr.gardenMgr.mgr.toons[ownerIndex] + self.owner = self.air.doId2do.get(self.ownerDoId) + def getOwnerIndex(self): return self.ownerIndex - def setPosition(self, x, y, z): - self.position = (x, y, z) - - def getPosition(self): - return self.position - - def setHeading(self, heading): - self.heading = heading - - def getHeading(self): - return self.heading - - def plotEntered(self): - pass - - def removeItem(self, avId): - self.inUseBy = avId - self.d_setMovie(GardenGlobals.MOVIE_REMOVE, avId) - - def d_setMovie(self, mode, avId): + def d_setMovie(self, mode, avId=None): + if avId is None: + avId = self.air.getAvatarIdFromSender() + self.sendUpdate('setMovie', [mode, avId]) - def movieDone(self): - if hasattr(self, 'inUseBy'): - del self.inUseBy - - def interactionDenied(self, todo0): - pass + def d_interactionDenied(self): + self.sendUpdate('interactionDenied', [self.air.getAvatarIdFromSender()]) diff --git a/toontown/estate/DistributedMailboxAI.py b/toontown/estate/DistributedMailboxAI.py index e939a7d8..46410a15 100755 --- a/toontown/estate/DistributedMailboxAI.py +++ b/toontown/estate/DistributedMailboxAI.py @@ -92,9 +92,13 @@ class DistributedMailboxAI(DistributedObjectAI): return item = av.mailboxContents[index] - del av.mailboxContents[index] - av.b_setMailboxContents(av.mailboxContents) - self.sendUpdateToAvatarId(avId, 'acceptItemResponse', [context, item.recordPurchase(av, optional)]) + returnCode = item.recordPurchase(av, optional) + + if returnCode == ToontownGlobals.P_ItemAvailable: + del av.mailboxContents[index] + av.b_setMailboxContents(av.mailboxContents) + + self.sendUpdateToAvatarId(avId, 'acceptItemResponse', [context, returnCode]) def discardItemMessage(self, context, item, index, optional): avId = self.air.getAvatarIdFromSender() diff --git a/toontown/estate/DistributedPhone.py b/toontown/estate/DistributedPhone.py index c97beede..ca461e18 100755 --- a/toontown/estate/DistributedPhone.py +++ b/toontown/estate/DistributedPhone.py @@ -2,6 +2,7 @@ from toontown.toonbase import ToontownGlobals import PhoneGlobals from toontown.catalog import CatalogScreen from toontown.catalog import CatalogItem +from toontown.catalog import GiftAvatar from toontown.toontowngui import TTDialog from toontown.toonbase import TTLocalizer import DistributedHouseInterior @@ -13,7 +14,6 @@ from direct.showutil import Rope from direct.directnotify.DirectNotifyGlobal import * from panda3d.core import * from direct.interval.IntervalGlobal import * -import string from toontown.quest import Quests from direct.task import Task @@ -44,7 +44,6 @@ class DistributedPhone(DistributedFurnitureItem.DistributedFurnitureItem): self.intervalAvatar = None self.phoneInUse = 0 self.origToonHpr = None - return def announceGenerate(self): self.notify.debug('announceGenerate') @@ -103,7 +102,7 @@ class DistributedPhone(DistributedFurnitureItem.DistributedFurnitureItem): if self.initialScale: mount.setScale(*self.initialScale) self.usedInitialScale = 1 - phoneSphere = CollisionSphere(0, -0.66, 0, 0.2) + phoneSphere = CollisionSphere(0, -0.88, 0, 0.2) phoneSphere.setTangible(0) phoneSphereNode = CollisionNode(self.phoneSphereEvent) phoneSphereNode.setIntoCollideMask(ToontownGlobals.WallBitmask) @@ -136,7 +135,6 @@ class DistributedPhone(DistributedFurnitureItem.DistributedFurnitureItem): (self.model.find('**/CurveNode7'), (0, 0, 0)))) self.cord.reparentTo(self.model) self.cord.node().setBounds(BoundingSphere(Point3(-1.0, -3.2, 2.6), 2.0)) - return def disable(self): self.notify.debug('disable') @@ -154,7 +152,6 @@ class DistributedPhone(DistributedFurnitureItem.DistributedFurnitureItem): self.freeAvatar() self.ignoreAll() DistributedFurnitureItem.DistributedFurnitureItem.disable(self) - return def delete(self): self.notify.debug('delete') @@ -168,16 +165,18 @@ class DistributedPhone(DistributedFurnitureItem.DistributedFurnitureItem): self.usedInitialScale = 1 def __handleEnterSphere(self, collEntry): - if self.smoothStarted: + if self.phoneGui or self.smoothStarted: return + if base.localAvatar.doId == self.lastAvId and globalClock.getFrameTime() <= self.lastTime + 0.5: self.notify.debug('Ignoring duplicate entry for avatar.') return + if self.hasLocalAvatar: self.freeAvatar() + self.notify.debug('Entering Phone Sphere....') taskMgr.remove(self.uniqueName('ringDoLater')) - self.ignore(self.phoneSphereEnterEvent) self.cr.playGame.getPlace().detectedPhoneCollision() self.hasLocalAvatar = 1 self.sendUpdate('avatarEnter', []) @@ -185,9 +184,8 @@ class DistributedPhone(DistributedFurnitureItem.DistributedFurnitureItem): def __handlePhoneDone(self): self.sendUpdate('avatarExit', []) self.ignore(self.phoneGuiDoneEvent) - self.accept(self.phoneSphereEnterEvent, self.__handleEnterSphere) + self.setPos(self.getPos()) self.phoneGui = None - return def freeAvatar(self): if self.hasLocalAvatar: @@ -198,9 +196,7 @@ class DistributedPhone(DistributedFurnitureItem.DistributedFurnitureItem): base.cr.playGame.getPlace().setState('walk') self.hasLocalAvatar = 0 self.ignore(self.pickupMovieDoneEvent) - self.accept(self.phoneSphereEnterEvent, self.__handleEnterSphere) self.lastTime = globalClock.getFrameTime() - return def setLimits(self, numHouseItems): self.numHouseItems = numHouseItems @@ -223,14 +219,6 @@ class DistributedPhone(DistributedFurnitureItem.DistributedFurnitureItem): if self.phoneInUse: self.clearInterval() self.phoneInUse = 0 - - elif mode == PhoneGlobals.PHONE_MOVIE_EMPTY: - self.notify.debug('setMovie: empty') - if isLocalToon: - self.phoneDialog = TTDialog.TTDialog(dialogName='PhoneEmpty', style=TTDialog.Acknowledge, text=TTLocalizer.DistributedPhoneEmpty, text_wordwrap=15, fadeScreen=1, command=self.__clearDialog) - self.numHouseItems = None - self.phoneInUse = 0 - elif mode == PhoneGlobals.PHONE_MOVIE_PICKUP: self.notify.debug('setMovie: gui') if avatar: @@ -241,7 +229,6 @@ class DistributedPhone(DistributedFurnitureItem.DistributedFurnitureItem): self.acceptOnce(self.pickupMovieDoneEvent, self.__showPhoneGui) self.playInterval(interval, elapsed, avatar) self.phoneInUse = 1 - elif mode == PhoneGlobals.PHONE_MOVIE_HANGUP: self.notify.debug('setMovie: gui') if avatar: @@ -249,10 +236,8 @@ class DistributedPhone(DistributedFurnitureItem.DistributedFurnitureItem): self.playInterval(interval, elapsed, avatar) self.numHouseItems = None self.phoneInUse = 0 - else: self.notify.warning('unknown mode in setMovie: %s' % mode) - return def __showPhoneGui(self): if self.toonScale: @@ -274,7 +259,6 @@ class DistributedPhone(DistributedFurnitureItem.DistributedFurnitureItem): self.sendUpdate('requestPurchaseMessage', [context, blob, optional]) def requestGiftPurchase(self, item, targetDoID, callback, optional = -1): - print 'in the client phone' blob = item.getBlob(store=CatalogItem.Customization) context = self.getCallbackContext(callback, [item]) self.sendUpdate('requestGiftPurchaseMessage', [context, targetDoID, blob, optional]) @@ -289,7 +273,6 @@ class DistributedPhone(DistributedFurnitureItem.DistributedFurnitureItem): self.phoneDialog.cleanup() self.phoneDialog = None self.freeAvatar() - return def takePhoneInterval(self, toon): torso = TextEncoder.upper(toon.style.torso[0]) @@ -349,7 +332,6 @@ class DistributedPhone(DistributedFurnitureItem.DistributedFurnitureItem): if avatar: self.accept(avatar.uniqueName('disable'), self.clearInterval) self.intervalAvatar = avatar - return def clearInterval(self): if self.interval != None: @@ -361,7 +343,6 @@ class DistributedPhone(DistributedFurnitureItem.DistributedFurnitureItem): self.__receiverToPhone() self.model.pose('SS_phoneOut', 0) self.phoneInUse = 0 - return def ringIfHasPhoneQuest(self, task): if Quests.avatarHasPhoneQuest(base.localAvatar) and not Quests.avatarHasCompletedPhoneQuest(base.localAvatar): @@ -381,4 +362,15 @@ class DistributedPhone(DistributedFurnitureItem.DistributedFurnitureItem): ringIval = Parallel(Func(base.playSfx, self.ringSfx), shakeSeq, Func(phone.setR, 0)) self.playInterval(ringIval, 0.0, None) - return + + def requestGiftAvatar(self, doId): + if not self.phoneGui: + return + + self.sendUpdate('requestGiftAvatar', [doId]) + + def setGiftAvatar(self, fields): + if not self.phoneGui: + return + + self.phoneGui.setFriendReady(GiftAvatar.createFromJson(fields)) \ No newline at end of file diff --git a/toontown/estate/DistributedPhoneAI.py b/toontown/estate/DistributedPhoneAI.py index 34f72eb1..041c62ce 100755 --- a/toontown/estate/DistributedPhoneAI.py +++ b/toontown/estate/DistributedPhoneAI.py @@ -1,138 +1,258 @@ -from toontown.estate.DistributedFurnitureItemAI import DistributedFurnitureItemAI -from toontown.toonbase import ToontownGlobals -from toontown.catalog import CatalogItem -from toontown.catalog.CatalogInvalidItem import CatalogInvalidItem -from toontown.catalog.CatalogItemList import CatalogItemList +from direct.directnotify import DirectNotifyGlobal from direct.distributed.ClockDelta import * -import time -import PhoneGlobals +from toontown.estate.DistributedFurnitureItemAI import DistributedFurnitureItemAI +from PhoneGlobals import * +from toontown.toonbase import ToontownGlobals +from toontown.catalog import CatalogItem, CatalogInvalidItem, GiftAvatar +from toontown.catalog.CatalogItemList import CatalogItemList +from toontown.uberdog import TopToonsGlobals + +import json + +class LoadGiftAvatar: + + def __init__(self, phone, avId, targetId, optional, callback): + self.air = phone.air + self.phone = phone + self.avId = avId + self.targetId = targetId + self.optional = optional + self.callback = callback + + def start(self): + self.air.dbInterface.queryObject(self.air.dbId, self.targetId, self.__gotAvatar) + + def copyDict(self, dict, *keys): + return {key: dict[key] for key in keys} + + def __gotAvatar(self, dclass, fields): + if dclass != self.air.dclassesByName['DistributedToonAI']: + return + + for key in ('setDNAString', 'setMailboxContents', 'setGiftSchedule', 'setDeliverySchedule'): + fields[key] = fields[key][0].encode('base64') + + newDict = self.copyDict(fields, 'setDNAString', 'setMailboxContents', 'setGiftSchedule', 'setDeliverySchedule', 'setHat', 'setGlasses', 'setBackpack', + 'setShoes', 'setHatList', 'setGlassesList', 'setBackpackList', 'setShoes', 'setShoesList', 'setCustomMessages', 'setEmoteAccess', + 'setClothesTopsList', 'setClothesBottomsList', 'setPetTrickPhrases', 'setNametagStyles') + + self.callback(self.avId, self.targetId, newDict, self.optional) + del self.phone.fsms[self.avId] class DistributedPhoneAI(DistributedFurnitureItemAI): - notify = directNotify.newCategory('DistributedPhoneAI') - - def __init__(self, air, furnitureMgr, item): - DistributedFurnitureItemAI.__init__(self, air, furnitureMgr, item) - - self.avId = None - + notify = DirectNotifyGlobal.directNotify.newCategory("DistributedPhoneAI") + + def __init__(self, air, furnitureMgr, catalogItem): + DistributedFurnitureItemAI.__init__(self, air, furnitureMgr, catalogItem) + self.fsms = {} + self.initialScale = (0.8, 0.8, 0.8) + self.inUse = False + self.currAvId = 0 + + def calcHouseItems(self, avatar): + houseId = avatar.houseId + + if not houseId: + self.notify.warning('Avatar %s has no houseId associated.' % avatar.doId) + return 0 + + house = simbase.air.doId2do.get(houseId) + if not house: + self.notify.warning('House %s (for avatar %s) not instantiated.' % (houseId, avatar.doId)) + return 0 + + mgr = house.interior.furnitureManager + attic = (mgr.atticItems, mgr.atticWallpaper, mgr.atticWindows) + numHouseItems = len(CatalogItemList(house.getInteriorItems(), store=CatalogItem.Customization | CatalogItem.Location)) + numAtticItems = sum(len(x) for x in attic) + + return numHouseItems + numAtticItems + + def setInitialScale(self, scale): + self.initialScale = scale + def getInitialScale(self): - return (0.8, 0.8, 0.8) - - def setNewScale(self, sx, sy, sz): - if sx + sy + sz < 5: - return - self.sendUpdate('setInitialScale', [sx, sy, sz]) + return self.initialScale def avatarEnter(self): avId = self.air.getAvatarIdFromSender() - if self.avId: - if self.avId == avId: - self.air.writeServerEvent('suspicious', avId, 'Tried to use a phone twice!') - return - self.sendUpdateToAvatarId(avId, 'freeAvatar', []) + if self.inUse: + self.ejectAvatar(avId) return - + av = self.air.doId2do.get(avId) - if not av: - return - - if not av.houseId: - self.d_setMovie(PhoneGlobals.PHONE_MOVIE_NO_HOUSE, avId, globalClockDelta.getRealNetworkTime(bits=32)) - taskMgr.doMethodLater(1, self.__resetMovie, 'resetMovie-%d' % self.getDoId(), extraArgs=[]) - return - - if len(av.monthlyCatalog) == 0 and len(av.weeklyCatalog) == 0 and len(av.backCatalog) == 0: - self.d_setMovie(PhoneGlobals.PHONE_MOVIE_EMPTY, avId, globalClockDelta.getRealNetworkTime(bits=32)) - taskMgr.doMethodLater(1, self.__resetMovie, 'resetMovie-%d' % self.getDoId(), extraArgs=[]) - return - - self.air.questManager.toonUsedPhone(avId) - self.avId = avId - self.d_setMovie(PhoneGlobals.PHONE_MOVIE_PICKUP, avId, globalClockDelta.getRealNetworkTime(bits=32)) - - house = self.air.doId2do.get(av.houseId) - if house: - numItems = len(house.interiorItems) + len(house.atticItems) + len(house.atticWallpaper) + len(house.atticWindows) + len (house.interiorWallpaper) + len(house.interiorWindows) - self.sendUpdateToAvatarId(avId, 'setLimits', [numItems]) - else: - self.air.dbInterface.queryObject(self.air.dbId, av.houseId, self.__gotHouse) - - av.b_setCatalogNotify(ToontownGlobals.NoItems, av.mailboxNotify) - - def __gotHouse(self, dclass, fields): - if dclass != self.air.dclassesByName['DistributedHouseAI']: - return - - numItems = len(CatalogItemList(fields['setInteriorItems'][0], store=CatalogItem.Customization)) + len(CatalogItemList(fields['setAtticItems'][0], store=CatalogItem.Customization)) + len(CatalogItemList(fields['setAtticWallpaper'][0], store=CatalogItem.Customization)) + len(CatalogItemList(fields['setAtticWindows'][0], store=CatalogItem.Customization)) + len(CatalogItemList(fields['setInteriorWallpaper'][0], store=CatalogItem.Customization)) + len(CatalogItemList(fields['setInteriorWindows'][0], store=CatalogItem.Customization)) - self.sendUpdateToAvatarId(fields['setAvatarId'][0], 'setLimits', [numItems]) - + if av: + self.setInUse(avId) + self.sendUpdateToAvatarId(avId, 'setLimits', [self.calcHouseItems(av)]) + self.d_setMovie(PHONE_MOVIE_PICKUP, avId) + av.b_setCatalogNotify(0, av.mailboxNotify) + + self.air.questManager.toonCalledClarabelle(av) + def avatarExit(self): - avId = self.air.getAvatarIdFromSender() - if avId != self.avId: - self.air.writeServerEvent('suspicious', avId, 'Tried to exit a phone they weren\'t using!') + if not self.inUse: + self.notify.warning('Requested avatarExit but phone isn\'t in use!') return - - self.avId = None - self.d_setMovie(PhoneGlobals.PHONE_MOVIE_HANGUP, avId, globalClockDelta.getRealNetworkTime(bits=32)) - taskMgr.doMethodLater(1, self.__resetMovie, 'resetMovie-%d' % self.getDoId(), extraArgs=[]) - - def d_setMovie(self, mode, avId, time): - self.sendUpdate('setMovie', [mode, avId, time]) - - def __resetMovie(self): - self.d_setMovie(PhoneGlobals.PHONE_MOVIE_CLEAR, 0, globalClockDelta.getRealNetworkTime(bits=32)) - - def requestPurchaseMessage(self, context, item, optional): avId = self.air.getAvatarIdFromSender() - if avId != self.avId: - self.air.writeServerEvent('suspicious', avId, 'Tried to purchase while not using the phone!') + if avId != self.currAvId: + self.notify.warning('Requested avatarExit from unknown avatar %s' %avId) return - + self.d_setMovie(PHONE_MOVIE_HANGUP, avId) + taskMgr.doMethodLater(1, self.resetMovie, self.taskName('resetMovie')) + self.setFree() + + def setFree(self): + self.inUse = False + self.currAvId = 0 + + def setInUse(self, avId): + self.inUse = True + self.currAvId = avId + + def d_setMovie(self, movie, avId): + self.sendUpdate('setMovie', args=[movie, avId, globalClockDelta.getRealNetworkTime(bits=32)]) + + def ejectAvatar(self, avId): + self.sendUpdateToAvatarId(avId, 'freeAvatar', []) + + def __getCaller(self): + avId = self.air.getAvatarIdFromSender() + if avId != self.currAvId: + self.air.writeServerEvent('suspicious', avId, 'tried purchasing item, but not using phone') + self.notify.warning('%d tried purchasing item, but not using phone' % avId) + return + av = self.air.doId2do.get(avId) if not av: - self.air.writeServerEvent('suspicious', avId, 'Used phone from other shard!') + self.air.writeServerEvent('suspicious', avId, 'tried purchasing item, but not on shard') + self.notify.warning('%d tried purchasing item, but not on shard' % avId) return + + return av + + def checkPurchaseLimit(self, recipient, item): + if len(recipient.mailboxContents) + len(recipient.onOrder) + len(recipient.onGiftOrder) + 1 >= ToontownGlobals.MaxMailboxContents: + return ToontownGlobals.P_MailboxFull + elif item.reachedPurchaseLimit(recipient): + return ToontownGlobals.P_ReachedPurchaseLimit - item = CatalogItem.getItem(item) - if isinstance(item, CatalogInvalidItem): - self.air.writeServerEvent('suspicious', avId, 'Tried to purchase invalid catalog item.') - return - if item in av.backCatalog: - price = item.getPrice(CatalogItem.CatalogTypeBackorder) - elif item in av.weeklyCatalog or item in av.monthlyCatalog: - price = item.getPrice(0) - elif item.hasEmblemPrices(): - price = 0 + return ToontownGlobals.P_ItemOnOrder + + def chargeAvatar(self, av, money, emblems): + av.takeMoney(money) + av.subtractEmblems(emblems) + + def attemptPurchase(self, context, av, blob, optional, gifting=False): + avId = av.doId + item = CatalogItem.getItem(blob, CatalogItem.Customization) + + if isinstance(item, CatalogInvalidItem.CatalogInvalidItem): + self.air.writeServerEvent('suspicious', avId, 'tried purchasing invalid item') + self.notify.warning('%d tried purchasing invalid item' % avId) + return ToontownGlobals.P_NotInCatalog + elif (not item.hasEmblemPrices()) and item not in av.backCatalog and item not in av.weeklyCatalog and item not in av.monthlyCatalog: + self.air.writeServerEvent('suspicious', avId, 'tried purchasing non-existing item') + self.notify.warning('%d tried purchasing non-existing item' % avId) + return ToontownGlobals.P_NotInCatalog + + if gifting and not item.isGift(): + return ToontownGlobals.P_NotAGift + + price = item.getPrice(CatalogItem.CatalogTypeBackorder if item in av.backCatalog else 0) + + if price > av.getTotalMoney() or (item.hasEmblemPrices() and not av.isEnoughEmblemsToBuy(item.getEmblemPrices())): + return ToontownGlobals.P_NotEnoughMoney + + if gifting: + return self.requestGiftAvatarOperation(avId, gifting, [context, item, price], self.attemptGiftPurchase) else: + returnCode = self.checkPurchaseLimit(av, item) + + if returnCode != ToontownGlobals.P_ItemOnOrder: + return returnCode + + if item.getDeliveryTime(): + self.chargeAvatar(av, price, item.getEmblemPrices()) + av.addToDeliverySchedule(item, item.getDeliveryTime()) + av.addStat(ToontownGlobals.STAT_ITEMS) + else: + returnCode = item.recordPurchase(av, optional) + + if returnCode == ToontownGlobals.P_ItemAvailable: + self.chargeAvatar(av, price, item.getEmblemPrices()) + av.addStat(ToontownGlobals.STAT_ITEMS) + + return returnCode + + return None + + def attemptGiftPurchase(self, avId, targetId, avatar, optional): + av = self.air.doId2do.get(avId) + + if not av: return - if item.getDeliveryTime(): - if len(av.onOrder) > 25: - self.sendUpdateToAvatarId(avId, 'requestPurchaseResponse', [context, ToontownGlobals.P_OnOrderListFull]) - return + recipient = GiftAvatar.createFromFields(avatar) + context = optional[0] + item = optional[1] + returnCode = self.checkPurchaseLimit(recipient, item) + + if returnCode != ToontownGlobals.P_ItemOnOrder: + self.sendGiftPurchaseResponse(context, avId, returnCode) + return - if len(av.mailboxContents) + len(av.onOrder) >= ToontownGlobals.MaxMailboxContents: - self.sendUpdateToAvatarId(avId, 'requestPurchaseResponse', [context, ToontownGlobals.P_MailboxFull]) + self.chargeAvatar(av, optional[2], item.getEmblemPrices()) + recipient.addToGiftSchedule(avId, targetId, item, item.getDeliveryTime()) + av.addStat(ToontownGlobals.STAT_ITEMS) - if not (av.takeMoney(price) and av.subtractEmblems(item.getEmblemPrices())): - return + self.sendGiftPurchaseResponse(context, avId, ToontownGlobals.P_ItemOnOrder) + + def sendGiftPurchaseResponse(self, context, avId, returnCode): + if returnCode in (ToontownGlobals.P_ItemOnOrder, ToontownGlobals.P_ItemAvailable): + messenger.send('topToonsManager-event', [avId, TopToonsGlobals.CAT_CATALOG | TopToonsGlobals.CAT_GIFTS, 1]) - item.deliveryDate = int(time.time()/60) + item.getDeliveryTime() - av.onOrder.append(item) - av.b_setDeliverySchedule(av.onOrder) - self.sendUpdateToAvatarId(avId, 'requestPurchaseResponse', [context, ToontownGlobals.P_ItemOnOrder]) - taskMgr.doMethodLater(0.2, self.sendUpdateToAvatarId, 'purchaseItemComplete-%d' % self.getDoId(), extraArgs=[avId, 'purchaseItemComplete', []]) - else: - if not (av.takeMoney(price) and av.subtractEmblems(item.getEmblemPrices())): - return + self.sendUpdateToAvatarId(avId, 'requestGiftPurchaseResponse', [context, returnCode]) - resp = item.recordPurchase(av, optional) - if resp < 0: - av.addMoney(price) + def requestPurchaseMessage(self, context, blob, optional): + av = self.__getCaller() - self.sendUpdateToAvatarId(avId, 'requestPurchaseResponse', [context, resp]) - taskMgr.doMethodLater(0.2, self.sendUpdateToAvatarId, 'purchaseItemComplete-%d' % self.getDoId(), extraArgs=[avId, 'purchaseItemComplete', []]) + if not av: + return - def requestGiftPurchaseMessage(self, context, avId, item, optional): - pass # TODO + returnCode = self.attemptPurchase(context, av, blob, optional) + + if returnCode in (ToontownGlobals.P_ItemOnOrder, ToontownGlobals.P_ItemAvailable): + messenger.send('topToonsManager-event', [av.doId, TopToonsGlobals.CAT_CATALOG, 1]) + + self.sendUpdateToAvatarId(av.doId, 'requestPurchaseResponse', [context, returnCode]) + + def requestGiftPurchaseMessage(self, context, targetId, blob, optional): + av = self.__getCaller() + + if not av: + return + + returnCode = self.attemptPurchase(context, av, blob, optional, gifting=targetId) + + if returnCode: + self.sendGiftPurchaseResponse(context, av.doId, returnCode) + + def requestGiftAvatar(self, doId): + self.requestGiftAvatarOperation(self.air.getAvatarIdFromSender(), doId, None, self.sendGiftAvatarResponse) + + def requestGiftAvatarOperation(self, avId, doId, optional, callback): + if avId in self.fsms: + return ToontownGlobals.P_TooFast + + loadOperation = LoadGiftAvatar(self, avId, doId, optional, callback) + loadOperation.start() + self.fsms[avId] = loadOperation + return None + + def sendGiftAvatarResponse(self, avId, targetId, avatar, optional): + self.sendUpdateToAvatarId(avId, 'setGiftAvatar', [json.dumps(avatar)]) + + def resetMovie(self, task): + self.d_setMovie(PHONE_MOVIE_CLEAR, 0) + return task.done \ No newline at end of file diff --git a/toontown/estate/DistributedPlantBase.py b/toontown/estate/DistributedPlantBase.py index 03453a52..4b1803c9 100755 --- a/toontown/estate/DistributedPlantBase.py +++ b/toontown/estate/DistributedPlantBase.py @@ -44,12 +44,6 @@ class DistributedPlantBase(DistributedLawnDecor.DistributedLawnDecor): DistributedLawnDecor.DistributedLawnDecor.setupShadow(self) self.adjustWaterIndicator() - def setOwnerPlot(self, owner): - self.ownerPlot = owner - - def getOwnerPlot(self): - return self.ownerPlot - def setTypeIndex(self, typeIndex): self.typeIndex = typeIndex self.attributes = GardenGlobals.PlantAttributes[typeIndex] @@ -69,9 +63,7 @@ class DistributedPlantBase(DistributedLawnDecor.DistributedLawnDecor): self.waterLevel = waterLevel def getWaterLevel(self): - if hasattr(self, 'waterLevel'): - return self.waterLevel - return 0 + return self.waterLevel def setGrowthLevel(self, growthLevel): self.growthLevel = growthLevel @@ -105,11 +97,11 @@ class DistributedPlantBase(DistributedLawnDecor.DistributedLawnDecor): def handleWatering(self): self.startInteraction() - self.sendUpdate('waterPlant', [localAvatar.doId]) + self.sendUpdate('waterPlant') def __handleWatering(self, plantToWaterId): if plantToWaterId == self.doId: - self.sendUpdate('waterPlant', [localAvatar.doId]) + self.sendUpdate('waterPlant') else: self.notify.debug('not sending water plant') diff --git a/toontown/estate/DistributedPlantBaseAI.py b/toontown/estate/DistributedPlantBaseAI.py index e59706cf..b2dcd3bf 100755 --- a/toontown/estate/DistributedPlantBaseAI.py +++ b/toontown/estate/DistributedPlantBaseAI.py @@ -1,84 +1,81 @@ from direct.directnotify import DirectNotifyGlobal from toontown.estate.DistributedLawnDecorAI import DistributedLawnDecorAI import GardenGlobals -import datetime class DistributedPlantBaseAI(DistributedLawnDecorAI): - notify = DirectNotifyGlobal.directNotify.newCategory("DistributedPlantBaseAI") - - def __init__(self, air): - DistributedLawnDecorAI.__init__(self, air) - self.air = air - self.growthLevel = -1 - - def announceGenerate(self): - DistributedLawnDecorAI.announceGenerate(self) - - def delete(self): - DistributedLawnDecorAI.delete(self) - - def disable(self): - DistributedLawnDecorAI.disable(self) - - def setOwnerPlot(self, owner): - self.ownerPlot = owner - - def getOwnerPlot(self): - return self.ownerPlot + notify = DirectNotifyGlobal.directNotify.newCategory('DistributedPlantBaseAI') + def __init__(self, mgr): + DistributedLawnDecorAI.__init__(self, mgr) + self.typeIndex = 0 + self.waterLevel = 0 + self.growthLevel = 0 + def setTypeIndex(self, typeIndex): self.typeIndex = typeIndex self.attributes = GardenGlobals.PlantAttributes[typeIndex] - self.name = self.attributes['name'] - self.plantType = self.attributes['plantType'] self.growthThresholds = self.attributes['growthThresholds'] - self.maxWaterLevel = self.attributes['maxWaterLevel'] - self.minWaterLevel = self.attributes['minWaterLevel'] - + + def d_setTypeIndex(self, typeIndex): + self.sendUpdate('setTypeIndex', [typeIndex]) + + def b_setTypeIndex(self, typeIndex): + self.setTypeIndex(typeIndex) + self.d_setTypeIndex(typeIndex) + def getTypeIndex(self): return self.typeIndex - def setWaterLevel(self, water): - self.waterLevel = water - + def setWaterLevel(self, waterLevel): + self.waterLevel = waterLevel + + def d_setWaterLevel(self, waterLevel): + self.sendUpdate('setWaterLevel', [waterLevel]) + + def b_setWaterLevel(self, waterLevel): + self.setWaterLevel(waterLevel) + self.d_setWaterLevel(waterLevel) + def getWaterLevel(self): return self.waterLevel - def setGrowthLevel(self, growth): - self.growthLevel = growth - + def setGrowthLevel(self, growthLevel): + self.growthLevel = growthLevel + + def d_setGrowthLevel(self, growthLevel): + self.sendUpdate('setGrowthLevel', [growthLevel]) + + def b_setGrowthLevel(self, growthLevel): + self.setGrowthLevel(growthLevel) + self.d_setGrowthLevel(growthLevel) + def getGrowthLevel(self): return self.growthLevel - def waterPlant(self, avId): - # TODO: Proper water threshold for watering can type. - # Not supposed to be 16 for all watering cans. - self.lastWateredBy = avId - newLevel = self.waterLevel + 1 - if newLevel > self.maxWaterLevel: - self.setWaterLevel(self.maxWaterLevel) - else: - self.setWaterLevel(newLevel) - self.sendUpdate('setMovie', [GardenGlobals.MOVIE_WATER, avId]) - self.sendUpdate('setWaterLevel', [self.getWaterLevel()]) + def waterPlant(self): + av = self.air.doId2do.get(self.air.getAvatarIdFromSender()) + if not av: + return + + level = max(1, self.getWaterLevel() + av.getWateringCan() + 1) + level = min(20, level) + self.b_setWaterLevel(level) + + self.d_setMovie(GardenGlobals.MOVIE_WATER) + self.update() def waterPlantDone(self): - if hasattr(self, 'lastWateredBy'): - av = simbase.air.doId2do.get(self.lastWateredBy) - skill = av.getWateringCanSkill() - skill += GardenGlobals.WateringCanAttributes[av.wateringCan]['skillPts'] / 100 - av.b_setWateringCanSkill(skill) - del self.lastWateredBy - estate = simbase.air.doId2do.get(self.getEstate()) - dataIndex = -1 - # TODO: Possibly store this in mongodb/cPickle instead. - for n, item in enumerate(estate.items[self.getOwnerIndex()]): - if item[0] == self.getPlot(): - dataIndex = n - if dataIndex >= 0: - dtime = int(datetime.datetime.now().strftime('%Y%m%d%H%M')) - data = list(estate.items[self.getOwnerIndex()][dataIndex]) - data[4] = self.getWaterLevel() - data[8] = dtime - estate.items[self.getOwnerIndex()][dataIndex] = tuple(data) - estate.updateItems() + av = self.air.doId2do.get(self.air.getAvatarIdFromSender()) + if not av: + return + + if self.waterLevel < 6: + av.b_setWateringCanSkill(av.getWateringCanSkill() + 1) + else: + av.b_setWateringCanSkill(av.getWateringCanSkill()) + + self.d_setMovie(GardenGlobals.MOVIE_CLEAR) + + def update(self): + pass + \ No newline at end of file diff --git a/toontown/estate/DistributedRewardCrate.py b/toontown/estate/DistributedRewardCrate.py new file mode 100644 index 00000000..cd291bc5 --- /dev/null +++ b/toontown/estate/DistributedRewardCrate.py @@ -0,0 +1,88 @@ +from direct.interval.IntervalGlobal import * +from toontown.effects import DustCloud +from toontown.toonbase import ToontownGlobals, TTLocalizer +from toontown.toontowngui import TTDialog +from toontown.quest import Quests +from DistributedFurnitureItem import DistributedFurnitureItem + +class DistributedRewardCrate(DistributedFurnitureItem): + + def __init__(self, cr): + DistributedFurnitureItem.__init__(self, cr) + self.dialog = None + self.accept('exitingStoppedState', self.destroyDialog) + + def loadModel(self): + model = DistributedFurnitureItem.loadModel(self) + cSphere = CollisionSphere(0.0, 0.0, 1.0, 2.25) + cSphere.setTangible(0) + colNode = CollisionNode('Crate-%s' % self.doId) + colNode.addSolid(cSphere) + cSpherePath = model.attachNewNode(colNode) + cSpherePath.setCollideMask(ToontownGlobals.WallBitmask) + self.accept('enterCrate-%s' % self.doId, self.__enterSphere) + return model + + def disable(self): + self.ignoreAll() + dustCloud = DustCloud.DustCloud(fBillboard=0, wantSound=1) + dustCloud.setBillboardAxis(2.0) + dustCloud.setScale(0.6) + dustCloud.createTrack() + Sequence(Func(dustCloud.reparentTo, render), Func(dustCloud.setPos, self.getPos()), dustCloud.track, Func(dustCloud.detachNode), Func(dustCloud.destroy)).start() + DistributedFurnitureItem.disable(self) + + def destroyDialog(self): + if self.dialog: + self.dialog.destroy() + self.dialog = None + + def showDialog(self, text): + base.cr.playGame.getPlace().setState('stopped') + self.dialog = TTDialog.TTDialog(style=TTDialog.Acknowledge, text=text, text_wordwrap=15, fadeScreen=1, command=self.__destroyDialog) + + def __destroyDialog(self, arg): + self.destroyDialog() + base.cr.playGame.getPlace().setState('walk') + + def __enterSphere(self, collisionEntry): + if base.localAvatar.doId != self.furnitureMgr.ownerId: + self.useKeyResponse(ToontownGlobals.CRATE_NOT_OWNER, 0) + return + elif not base.localAvatar.getCrateKeys(): + self.useKeyResponse(ToontownGlobals.CRATE_NO_KEYS, 0) + return + + base.cr.playGame.getPlace().setState('stopped') + self.dialog = TTDialog.TTDialog(style=TTDialog.TwoChoice, text=TTLocalizer.CrateAskToUse, fadeScreen=1, command=self.__handleDialogResponse) + + def __handleDialogResponse(self, response): + self.destroyDialog() + + if response < 0: + base.cr.playGame.getPlace().setState('walk') + return + + self.sendUpdate('requestKeyUsage') + + def useKeyResponse(self, responseCode, amount): + if responseCode == ToontownGlobals.CRATE_NOT_OWNER: + self.showDialog(TTLocalizer.CrateNotOwner) + return + elif responseCode == ToontownGlobals.CRATE_NO_KEYS: + self.showDialog(TTLocalizer.CrateNoKeys) + return + elif responseCode == ToontownGlobals.CRATE_BEANS: + self.showDialog(TTLocalizer.CrateBeanPrize % amount) + elif responseCode == ToontownGlobals.CRATE_BUFFS: + buff = Quests.RewardDict[amount] + + self.showDialog(TTLocalizer.CrateBuffPrize % buff[0](amount, buff[1:]).getString()) + elif responseCode == ToontownGlobals.CRATE_NAMETAGS: + self.showDialog(TTLocalizer.CrateNametagPrize) + elif responseCode == ToontownGlobals.CRATE_EMOTES: + self.showDialog(TTLocalizer.CrateEmotePrize) + elif responseCode == ToontownGlobals.CRATE_CLOTHING: + self.showDialog(TTLocalizer.CrateClothingPrize) + elif responseCode == ToontownGlobals.CRATE_ACCESSORIES: + self.showDialog(TTLocalizer.CrateAccessoryPrize) \ No newline at end of file diff --git a/toontown/estate/DistributedRewardCrateAI.py b/toontown/estate/DistributedRewardCrateAI.py new file mode 100644 index 00000000..8a173612 --- /dev/null +++ b/toontown/estate/DistributedRewardCrateAI.py @@ -0,0 +1,109 @@ +from toontown.catalog import CatalogAccessoryItem, CatalogClothingItem, CatalogNametagItem, CatalogEmoteItem +from toontown.catalog.CatalogAccessoryItemGlobals import * +from toontown.toonbase import ToontownGlobals, TTLocalizer +from toontown.toon import ToonDNA +from toontown.quest import Quests +from DistributedFurnitureItemAI import DistributedFurnitureItemAI +import random, time + +RANDOM_PRIZES = [ToontownGlobals.CRATE_BEANS] * 10 + [ToontownGlobals.CRATE_BUFFS] * 5 + [ToontownGlobals.CRATE_NAMETAGS] * 10 + [ToontownGlobals.CRATE_EMOTES] * 10 + [ToontownGlobals.CRATE_CLOTHING] * 30 + [ToontownGlobals.CRATE_ACCESSORIES] * 35 + +class DistributedRewardCrateAI(DistributedFurnitureItemAI): + + def requestKeyUsage(self): + avId = self.air.getAvatarIdFromSender() + av = self.air.doId2do.get(avId) + + if not av: + return + + if avId != self.furnitureMgr.ownerId: + self.sendUpdateToAvatarId(avId, 'useKeyResponse', [ToontownGlobals.CRATE_NOT_OWNER, 0]) + return + elif not av.getCrateKeys(): + self.sendUpdateToAvatarId(avId, 'useKeyResponse', [ToontownGlobals.CRATE_NO_KEYS, 0]) + return + + av.removeCrateKeys(1) + self.choosePrize(av) + + if not config.GetBool('dont-destroy-crate', False): + self.furnitureMgr.deleteItemFromRoom(self.doId, False) + + def choosePrize(self, av, tryNumber = 0): + if tryNumber == 10: + self.giveBeans(av) + return + + prizeType = random.choice(RANDOM_PRIZES) + + if prizeType == ToontownGlobals.CRATE_BEANS: + self.giveBeans(av) + elif prizeType == ToontownGlobals.CRATE_BUFFS: + buffId = random.choice(Quests.BuffRewardIds) + buff = Quests.RewardDict[buffId] + + buff[0](buffId, buff[1:]).sendRewardAI(av) + self.sendUpdateToAvatarId(av.doId, 'useKeyResponse', [ToontownGlobals.CRATE_BUFFS, buffId]) + elif prizeType == ToontownGlobals.CRATE_NAMETAGS: + allNametags = xrange(len(TTLocalizer.NametagFonts)) + playerNametags = av.nametagStyles + remainingNametags = [nametag for nametag in allNametags if nametag not in playerNametags] + + if not remainingNametags: + self.choosePrize(av, tryNumber + 1) + return + + nametag = random.choice(remainingNametags) + item = CatalogNametagItem.CatalogNametagItem(nametag, 0) + + if item.reachedPurchaseLimit(av): + return + + av.addToDeliverySchedule(item) + self.sendUpdateToAvatarId(av.doId, 'useKeyResponse', [ToontownGlobals.CRATE_NAMETAGS, 0]) + elif prizeType == ToontownGlobals.CRATE_EMOTES: + playerEmotes = av.emoteAccess + remainingEmotes = [i for i, access in enumerate(playerEmotes) if (not access) and access not in (17, 18, 19)] + + if not remainingEmotes: + self.choosePrize(av, tryNumber + 1) + return + + emote = random.choice(remainingEmotes) + item = CatalogEmoteItem.CatalogEmoteItem(emote, 0) + + if item.reachedPurchaseLimit(av): + self.choosePrize(av, tryNumber + 1) + return + + av.addToDeliverySchedule(item) + self.sendUpdateToAvatarId(av.doId, 'useKeyResponse', [ToontownGlobals.CRATE_EMOTES, 0]) + elif prizeType == ToontownGlobals.CRATE_CLOTHING: + clothing = CatalogClothingItem.ClothingTypes.keys() + random.shuffle(clothing) + + for id in clothing: + item = CatalogClothingItem.CatalogClothingItem(id, 0) + + if not item.notOfferedTo(av) and not item.reachedPurchaseLimit(av): + av.addToDeliverySchedule(item) + self.sendUpdateToAvatarId(av.doId, 'useKeyResponse', [ToontownGlobals.CRATE_CLOTHING, 0]) + return + elif prizeType == ToontownGlobals.CRATE_ACCESSORIES: + accessories = AccessoryTypes.keys() + random.shuffle(accessories) + + for id in accessories: + item = CatalogAccessoryItem.CatalogAccessoryItem(id, 0) + + if not item.reachedPurchaseLimit(av): + av.addToDeliverySchedule(item) + self.sendUpdateToAvatarId(av.doId, 'useKeyResponse', [ToontownGlobals.CRATE_ACCESSORIES, 0]) + return + + def giveBeans(self, av): + beans = random.randint(1, 15) * 100 + + av.addMoney(beans) + self.sendUpdateToAvatarId(av.doId, 'useKeyResponse', [ToontownGlobals.CRATE_BEANS, beans]) \ No newline at end of file diff --git a/toontown/estate/DistributedStatuary.py b/toontown/estate/DistributedStatuary.py index 9571696b..4d9680b1 100755 --- a/toontown/estate/DistributedStatuary.py +++ b/toontown/estate/DistributedStatuary.py @@ -37,12 +37,6 @@ class DistributedStatuary(DistributedLawnDecor.DistributedLawnDecor): attrib = GardenGlobals.PlantAttributes[self.typeIndex] self.stick2Ground() - def setOwnerPlot(self, owner): - self.ownerPlot = owner - - def getOwnerPlot(self): - return self.ownerPlot - def setTypeIndex(self, typeIndex): self.typeIndex = typeIndex self.name = GardenGlobals.PlantAttributes[typeIndex]['name'] diff --git a/toontown/estate/DistributedStatuaryAI.py b/toontown/estate/DistributedStatuaryAI.py index 066ffa06..20f24acd 100755 --- a/toontown/estate/DistributedStatuaryAI.py +++ b/toontown/estate/DistributedStatuaryAI.py @@ -1,33 +1,66 @@ from direct.directnotify import DirectNotifyGlobal -from toontown.estate.DistributedLawnDecorAI import DistributedLawnDecorAI +from DistributedLawnDecorAI import DistributedLawnDecorAI + +import GardenGlobals +import time + +FOUR_DAYS = 86400 * 4 class DistributedStatuaryAI(DistributedLawnDecorAI): notify = DirectNotifyGlobal.directNotify.newCategory("DistributedStatuaryAI") + + def calculate(self, lastCheck): + self.attributes = GardenGlobals.PlantAttributes[self.index] + self.growthThresholds = self.attributes.get('growthThresholds', (0, 0)) + + now = int(time.time()) + self.lastCheck = lastCheck + if self.lastCheck == 0: + self.lastCheck = now - def __init__(self, air): - DistributedLawnDecorAI.__init__(self, air) - self.air = air - - def setTypeIndex(self, typeIndex): - self.typeIndex = typeIndex + self.growthLevel = min((now - self.lastCheck) // FOUR_DAYS, self.growthThresholds[-1] + 1) + self.update() def getTypeIndex(self): - return self.typeIndex - - def setOwnerPlot(self, owner): - self.ownerPlot = owner - - def getOwnerPlot(self): - return self.ownerPlot - - def setWaterLevel(self, waterLevel): - self.waterLevel = waterLevel + return self.index def getWaterLevel(self): - return self.waterLevel - - def setGrowthLevel(self, growthLevel): - self.growthLevel = growthLevel + return 1 def getGrowthLevel(self): return self.growthLevel + + def getOptional(self): + return self.data + + def update(self): + self.mgr.data['statuary'] = self.mgr.S_pack(self.data, self.lastCheck, self.index, self.growthLevel) + self.mgr.update() + + def removeItem(self): + avId = self.air.getAvatarIdFromSender() + self.d_setMovie(GardenGlobals.MOVIE_REMOVE) + + def _remove(task): + if not self.air: + return + + plot = self.mgr.placePlot(-1) + plot.setPlot(self.plot) + plot.setPos(self.getPos()) + plot.setH(self.getH()) + plot.setOwnerIndex(self.ownerIndex) + plot.generateWithRequired(self.zoneId) + + self.air.writeServerEvent('remove-statuary', avId, plot=self.plot) + self.requestDelete() + + self.mgr.objects.remove(self) + + self.mgr.data['statuary'] = 0 + self.mgr.update() + + return task.done + + taskMgr.doMethodLater(7, _remove, self.uniqueName('do-remove')) + \ No newline at end of file diff --git a/toontown/estate/DistributedTV.py b/toontown/estate/DistributedTV.py new file mode 100644 index 00000000..97d10d71 --- /dev/null +++ b/toontown/estate/DistributedTV.py @@ -0,0 +1,137 @@ +from direct.gui.DirectGui import * +from otp.otpbase import OTPLocalizer +from toontown.catalog import CatalogFurnitureItem +from toontown.toonbase import ToontownGlobals, TTLocalizer +from toontown.toontowngui import TTDialog +from DistributedFurnitureItem import DistributedFurnitureItem +import glob, ntpath, os, time + +class DistributedTV(DistributedFurnitureItem): + + def __init__(self, cr): + DistributedFurnitureItem.__init__(self, cr) + self.dialog = None + self.screen = None + self.sound = None + self.accept('exitingStoppedState', self.destroyGui) + + def loadModel(self, animate=1): + model = DistributedFurnitureItem.loadModel(self) + + if animate: + pos = CatalogFurnitureItem.TvToPosScale[self.item.furnitureType] + self.screen = NodePath(CardMaker('tv-screen').generate()) + + model.find('**/toonTownBugTV_screen').hide() + self.screen.reparentTo(model) + self.screen.setScale(*pos[1]) + self.screen.setPos(*pos[0]) + self.resetScreen() + + cSphere = CollisionSphere(0.0, -1.5, 1.0, 1.575) + cSphere.setTangible(0) + colNode = CollisionNode('TV-%s' % self.doId) + colNode.addSolid(cSphere) + cSpherePath = model.attachNewNode(colNode) + cSpherePath.setCollideMask(ToontownGlobals.WallBitmask) + self.accept('enterTV-%s' % self.doId, self.__enterSphere) + return model + + def disable(self): + self.ignoreAll() + self.destroyGui() + self.destroySound() + DistributedFurnitureItem.disable(self) + + def setVideo(self, video, time): + if (not video) or (not time): + return + + self.destroySound() + self.startVideo(os.path.join('user', os.path.join('videos', video)), time) + + def getPack(self, name): + for pack in TTLocalizer.TVPacks: + if pack.lower() in name: + return pack + + return None + + def destroySound(self): + if self.sound: + self.sound.stop() + self.sound = None + + def destroyGui(self, arg=None): + if self.dialog: + self.dialog.destroy() + self.dialog = None + + def destroyGuiAndWalk(self, arg=None): + self.destroyGui() + base.cr.playGame.getPlace().setState('walk') + + def cutOff(self, string): + return string if len(string) < 24 else '%s...' % string[:24] + + def resetScreen(self): + self.screen.setTextureOff(TextureStage.getDefault()) + self.screen.setColor(0.3, 0.3, 0.3, 1.0) + + def startVideo(self, video, startTime): + if not os.path.exists(video): + pack = self.getPack(video) + base.localAvatar.setSystemMessage(0, TTLocalizer.TVUnknownVideoPack % pack if pack else TTLocalizer.TVUnknownVideo) + self.resetScreen() + return + + movie = loader.loadTexture(video) + self.sound = loader.loadSfx(video) + movie.synchronizeTo(self.sound) + self.screen.setColor(1, 1, 1, 1) + self.screen.setTexture(movie) + self.screen.setTexScale(TextureStage.getDefault(), movie.getTexScale()) + self.sound.setTime(min(self.sound.length(), int(time.time() - startTime))) + self.sound.play() + + def __enterSphere(self, collisionEntry): + if base.localAvatar.doId != self.furnitureMgr.ownerId: + return + + videos = [] + gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui') + buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui') + buttonImage = (gui.find('**/FndsLst_ScrollUp'), gui.find('**/FndsLst_ScrollDN'), gui.find('**/FndsLst_ScrollUp_Rllvr'), gui.find('**/FndsLst_ScrollUp')) + base.cr.playGame.getPlace().setState('stopped') + self.dialog = DirectFrame(relief=None, geom=DGG.getDefaultDialogGeom(), geom_color=ToontownGlobals.GlobalDialogColor, geom_scale=(1.33, 1, 1.4), + pos=(0, 0, 0), text=TTLocalizer.TVChooseVideo, text_scale=0.07, text_pos=(0, 0.575)) + + for file in sorted(glob.glob('user/videos/*.mp4')): + filename = ntpath.basename(file) + videos.append(DirectButton(relief=None, text=self.cutOff(filename[:-4]), text_pos=(0.0, -0.0225), text_scale=0.048, text_align=TextNode.ALeft, text_fg=(0, 0, 0, 1), text3_fg=(0.4, 0.8, 0.4, 1), text1_bg=(0.5, 0.9, 1, 1), text2_bg=(1, 1, 0, 1), command=self.chooseVideo, extraArgs=[filename])) + + scrollList = DirectScrolledList(parent=self.dialog, relief=None, pos=(-0.05, 0, 0), incButton_image=buttonImage, incButton_relief=None, incButton_scale=(1.3, 1.3, -1.3), + incButton_pos=(0.045, 0, -0.4), incButton_image3_color=(1, 1, 1, 0.2), decButton_image=buttonImage, decButton_relief=None, + decButton_scale=1.3, decButton_pos=(0.045, 0, 0.5), decButton_image3_color=(1, 1, 1, 0.2), itemFrame_pos=(-0.247, 0, 0.365), + itemFrame_scale=1.0, itemFrame_relief=DGG.SUNKEN, itemFrame_frameSize=(-0.02, 0.6, -0.7, 0.08), itemFrame_frameColor=(0.85, 0.95, 1, 1), + itemFrame_borderWidth=(0.01, 0.01), numItemsVisible=10, forceHeight=0.065, items=videos) + cancelButton = DirectButton(parent=self.dialog, relief=None, image=(buttons.find('**/CloseBtn_UP'), buttons.find('**/CloseBtn_DN'), buttons.find('**/CloseBtn_Rllvr')), pos=(0, 0, -0.55), text=OTPLocalizer.lCancel, text_scale=0.06, text_pos=(0, -0.1), command=self.destroyGuiAndWalk) + + gui.removeNode() + buttons.removeNode() + + def chooseVideo(self, video): + self.destroyGuiAndWalk() + self.sendUpdate('requestVideo', [video]) + + def showDialog(self, text): + base.cr.playGame.getPlace().setState('stopped') + self.dialog = TTDialog.TTDialog(style=TTDialog.Acknowledge, text=text, text_wordwrap=15, fadeScreen=1, command=self.destroyGuiAndWalk) + + def requestVideoResponse(self, response): + if response == ToontownGlobals.TV_NOT_OWNER: + self.showDialog(TTLocalizer.TVNotOwner) + elif response == ToontownGlobals.TV_INVALID_VIDEO: + self.showDialog(TTLocalizer.TVInvalidVideo) + elif response == ToontownGlobals.TV_OK: + self.showDialog(TTLocalizer.TVOK) \ No newline at end of file diff --git a/toontown/estate/DistributedTVAI.py b/toontown/estate/DistributedTVAI.py new file mode 100644 index 00000000..0f287b64 --- /dev/null +++ b/toontown/estate/DistributedTVAI.py @@ -0,0 +1,32 @@ +from toontown.toonbase import ToontownGlobals +from DistributedFurnitureItemAI import DistributedFurnitureItemAI +import time + +class DistributedTVAI(DistributedFurnitureItemAI): + + def __init__(self, air, furnitureMgr, item): + DistributedFurnitureItemAI.__init__(self, air, furnitureMgr, item) + self.video = ['', 0] + + def d_setVideo(self, video): + self.sendUpdate('setVideo', video) + + def getVideo(self): + return self.video + + def requestVideo(self, video): + avId = self.air.getAvatarIdFromSender() + av = self.air.doId2do.get(avId) + + if not av: + return + elif self.furnitureMgr.ownerId != avId: + self.sendUpdateToAvatarId(avId, 'requestVideoResponse', [ToontownGlobals.TV_NOT_OWNER]) + return + elif not video.endswith('.mp4'): + self.sendUpdateToAvatarId(avId, 'requestVideoResponse', [ToontownGlobals.TV_INVALID_VIDEO]) + return + + self.video = [video, int(time.time())] + self.d_setVideo(self.video) + self.sendUpdateToAvatarId(avId, 'requestVideoResponse', [ToontownGlobals.TV_OK]) \ No newline at end of file diff --git a/toontown/estate/DistributedToonStatuary.py b/toontown/estate/DistributedToonStatuary.py index faf96f76..3926a79e 100755 --- a/toontown/estate/DistributedToonStatuary.py +++ b/toontown/estate/DistributedToonStatuary.py @@ -2,7 +2,7 @@ from toontown.estate import DistributedStatuary from toontown.estate import DistributedLawnDecor from direct.directnotify import DirectNotifyGlobal from direct.showbase.ShowBase import * -from panda3d.core import * +from pandac.PandaModules import * from toontown.toon import Toon from toontown.toon import ToonDNA import GardenGlobals @@ -46,7 +46,7 @@ class DistributedToonStatuary(DistributedStatuary.DistributedStatuary): self.model.setScale(self.worldScale * 1.5, self.worldScale * 1.5, self.worldScale) self.getToonPropertiesFromOptional() dna = ToonDNA.ToonDNA() - dna.newToonFromProperties(self.headType, self.torsoType, self.legType, self.gender, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + dna.newToonFromProperties(self.headType, self.torsoType, self.legType, self.gender, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) self.setupStoneToon(dna) self.poseToonFromTypeIndex(self.typeIndex) self.toon.reparentTo(self.model) diff --git a/toontown/estate/DistributedToonStatuaryAI.py b/toontown/estate/DistributedToonStatuaryAI.py index 058ca7b0..880aa8b3 100755 --- a/toontown/estate/DistributedToonStatuaryAI.py +++ b/toontown/estate/DistributedToonStatuaryAI.py @@ -4,12 +4,6 @@ from toontown.estate.DistributedStatuaryAI import DistributedStatuaryAI class DistributedToonStatuaryAI(DistributedStatuaryAI): notify = DirectNotifyGlobal.directNotify.newCategory("DistributedToonStatuaryAI") - def __init__(self, air): - DistributedStatuaryAI.__init__(self, air) - self.air = air + def setOptional(self, todo0): + pass - def setOptional(self, optional): - self.optional = optional - - def getOptional(self): - return self.optional diff --git a/toontown/estate/EstateManagerAI.py b/toontown/estate/EstateManagerAI.py index 954259a0..573ba265 100755 --- a/toontown/estate/EstateManagerAI.py +++ b/toontown/estate/EstateManagerAI.py @@ -3,6 +3,7 @@ from direct.distributed.DistributedObjectAI import DistributedObjectAI from direct.fsm.FSM import FSM from toontown.estate.DistributedEstateAI import DistributedEstateAI from toontown.estate.DistributedHouseAI import DistributedHouseAI +from toontown.toon import ToonDNA import HouseGlobals import functools @@ -48,12 +49,16 @@ class LoadHouseFSM(FSM): self.demand('Off') def enterCreateHouse(self): + style = ToonDNA.ToonDNA() + style.makeFromNetString(self.toon['setDNAString'][0]) + self.mgr.air.dbInterface.createObject( self.mgr.air.dbId, self.mgr.air.dclassesByName['DistributedHouseAI'], { 'setName' : [self.toon['setName'][0]], 'setAvatarId' : [self.toon['ID']], + 'setGender': [0 if style.getGender() == 'm' else 1] }, self.__handleCreate) @@ -90,6 +95,7 @@ class LoadHouseFSM(FSM): def __gotHouse(self, house): self.house = house + house.initializeInterior() self.estate.houses[self.houseIndex] = self.house @@ -209,20 +215,34 @@ class LoadEstateFSM(FSM): if self.state != 'CreateEstate': return # We must have aborted or something... self.estateId = estateId + self.demand('StoreEstate') - # Update our account so we can store this new estate object. + def enterStoreEstate(self): + # store the estate in account + # congrats however wrote this for forgetting it! + self.mgr.air.dbInterface.updateObject( self.mgr.air.dbId, self.accountId, self.mgr.air.dclassesByName['AccountAI'], - { 'ESTATE_ID': estateId } - ) - + {'ESTATE_ID': self.estateId}, + {'ESTATE_ID': 0}, + self.__handleStoreEstate) + + def __handleStoreEstate(self, fields): + if fields: + self.notify.warning("Failed to associate Estate %d with account %d, loading anyway." % (self.estateId, self.accountId)) + self.demand('LoadEstate') def enterLoadEstate(self): # Activate the estate: - self.mgr.air.sendActivate(self.estateId, self.mgr.air.districtId, self.zoneId) + fields = {} + for i, toon in enumerate(self.toonIds): + fields['setSlot%dToonId' % i] = (toon,) + + self.mgr.air.sendActivate(self.estateId, self.mgr.air.districtId, self.zoneId, + self.mgr.air.dclassesByName['DistributedEstateAI'], fields) # Now we wait for the estate to show up... We do this by hanging a messenger # hook which the DistributedEstateAI throws once it spawns. @@ -232,9 +252,6 @@ class LoadEstateFSM(FSM): self.estate = estate estate.pets = [] - self.estate.toons = self.toonIds - self.estate.updateToons() - # Gotcha! Now we need to load houses: self.demand('LoadHouses') @@ -306,6 +323,7 @@ class EstateManagerAI(DistributedObjectAI): self.estate2toons = {} self.toon2estate = {} self.estate2timeout = {} + self.zoneId2owner = {} def getEstateZone(self, avId): senderId = self.air.getAvatarIdFromSender() @@ -369,11 +387,12 @@ class EstateManagerAI(DistributedObjectAI): # And I guess we won't need our zoneId anymore... self.air.deallocateZone(zoneId) + del self.zoneId2owner[zoneId] toon.loadEstateFSM = None self.acceptOnce(self.air.getAvatarExitEvent(toon.doId), self._unloadEstate, extraArgs=[toon]) - + self.zoneId2owner[zoneId] = avId toon.loadEstateFSM = LoadEstateFSM(self, estateLoaded) toon.loadEstateFSM.start(accId, zoneId) @@ -437,6 +456,7 @@ class EstateManagerAI(DistributedObjectAI): # Free estate's zone: self.air.deallocateZone(estate.zoneId) + del self.zoneId2owner[estate.zoneId] def _sendToonsToPlayground(self, estate, reason): for toon in self.estate2toons.get(estate, []): @@ -445,10 +465,12 @@ class EstateManagerAI(DistributedObjectAI): def _mapToEstate(self, toon, estate): self._unmapFromEstate(toon) - self.estate2toons.setdefault(estate, []).append(toon) self.toon2estate[toon] = estate + if hasattr(toon, 'enterEstate'): + toon.enterEstate(estate.owner.doId, estate.zoneId) + def _unmapFromEstate(self, toon): estate = self.toon2estate.get(toon) if not estate: return @@ -458,9 +480,19 @@ class EstateManagerAI(DistributedObjectAI): self.estate2toons[estate].remove(toon) except (KeyError, ValueError): pass + + if hasattr(toon, 'exitEstate'): + toon.exitEstate() def _lookupEstate(self, toon): return self.toon2estate.get(toon) - def getOwnerFromZone(self, avId): - return False + def getOwnerFromZone(self, zoneId): + return self.zoneId2owner.get(zoneId, 0) + + def getEstateZones(self, ownerId): + estate = self._lookupEstate(self.air.doId2do.get(ownerId)) + if estate: + return [estate.zoneId] + + return [] diff --git a/toontown/estate/GardenGlobals.py b/toontown/estate/GardenGlobals.py index 51d4ad13..770318ce 100755 --- a/toontown/estate/GardenGlobals.py +++ b/toontown/estate/GardenGlobals.py @@ -12,7 +12,6 @@ INVALID_TYPE = -1 GAG_TREE_TYPE = 0 FLOWER_TYPE = 1 STATUARY_TYPE = 2 -TOON_STATUARY_TYPE = 3 WATERING_CAN_SMALL = 0 WATERING_CAN_MEDIUM = 1 WATERING_CAN_LARGE = 2 @@ -683,7 +682,7 @@ def validatePlantAttributes(notify): notify.debug('plant attributes are ok') -plots0 = [(0, +plots0 = ((0, 0, 0.0, FLOWER_TYPE), @@ -758,45 +757,45 @@ plots0 = [(0, (-100, -43, -90.0, - STATUARY_TYPE)] -plots1 = [(85.0, - -67.0, + STATUARY_TYPE)) +plots1 = ((0, + 0, 0.0, FLOWER_TYPE), - (75, - -72, + (1, + 0, 0.0, FLOWER_TYPE), - (89.865, - -71.7725, + (2, + 0, 0.0, FLOWER_TYPE), - (91.0, - -74.0, + (2, + 1, 0.0, FLOWER_TYPE), - (92.135, - -76.2275, + (2, + 2, 0.0, FLOWER_TYPE), - (75.865, - -78.7725, + (3, + 0, 0.0, FLOWER_TYPE), - (77, - -81, + (3, + 1, 0.0, FLOWER_TYPE), - (78.135, - -83.2275, + (3, + 2, 0.0, FLOWER_TYPE), - (86.6518, - -86.6576, + (4, + 0, 0.0, FLOWER_TYPE), - (89.3482, - -85.3424, + (4, + 1, 0.0, FLOWER_TYPE), (62, @@ -834,8 +833,8 @@ plots1 = [(85.0, (47, -82, -30.0, - STATUARY_TYPE)] -plots2 = [(0, + STATUARY_TYPE)) +plots2 = ((0, 0, 0.0, FLOWER_TYPE), @@ -910,8 +909,8 @@ plots2 = [(0, (-97, -114, -60.0, - STATUARY_TYPE)] -plots3 = [(0, + STATUARY_TYPE)) +plots3 = ((0, 0, 0.0, FLOWER_TYPE), @@ -986,8 +985,8 @@ plots3 = [(0, (117, 27, 102.0, - STATUARY_TYPE)] -plots4 = [(0, + STATUARY_TYPE)) +plots4 = ((0, 0, 0.0, FLOWER_TYPE), @@ -1062,8 +1061,8 @@ plots4 = [(0, (16, 87, -140.0, - STATUARY_TYPE)] -plots5 = [(0, + STATUARY_TYPE)) +plots5 = ((0, 0, 0.0, FLOWER_TYPE), @@ -1138,7 +1137,7 @@ plots5 = [(0, (-55, 70, 213.0, - STATUARY_TYPE)] + STATUARY_TYPE)) estatePlots = (plots0, plots1, plots2, @@ -1148,7 +1147,8 @@ estatePlots = (plots0, BOX_ONE = 1 BOX_TWO = 2 BOX_THREE = 3 -flowerBoxes0 = [(-62.5, +FLOWER_POS = (None, (0,), (-1.5, 1.5), (-3.5, 0, 3.5)) +flowerBoxes0 = ((-62.5, -52.5, 182.0, BOX_ONE), @@ -1167,8 +1167,8 @@ flowerBoxes0 = [(-62.5, (-57, -33, 0.0, - BOX_TWO)] -flowerBoxes1 = [(85.0, + BOX_TWO)) +flowerBoxes1 = ((85.0, -67.0, 26.0, BOX_ONE), @@ -1187,8 +1187,8 @@ flowerBoxes1 = [(85.0, (88, -86, 206.0, - BOX_TWO)] -flowerBoxes2 = [(-62, + BOX_TWO)) +flowerBoxes2 = ((-62, -112, 350.0, BOX_ONE), @@ -1207,8 +1207,8 @@ flowerBoxes2 = [(-62, (-71, -129, 169.0, - BOX_TWO)] -flowerBoxes3 = [(72, + BOX_TWO)) +flowerBoxes3 = ((72, 5, 265.0, BOX_ONE), @@ -1227,8 +1227,8 @@ flowerBoxes3 = [(72, (54, 12, 86.0, - BOX_TWO)] -flowerBoxes4 = [(35.5, + BOX_TWO)) +flowerBoxes4 = ((35.5, 70, 152.0, BOX_ONE), @@ -1247,8 +1247,8 @@ flowerBoxes4 = [(35.5, (47, 86, -19.0, - BOX_TWO)] -flowerBoxes5 = [(-26.5, + BOX_TWO)) +flowerBoxes5 = ((-26.5, 37.5, 318.0, BOX_ONE), @@ -1267,7 +1267,7 @@ flowerBoxes5 = [(-26.5, (-45, 31, 124.0, - BOX_TWO)] + BOX_TWO)) estateBoxes = (flowerBoxes0, flowerBoxes1, flowerBoxes2, diff --git a/toontown/estate/PhoneGlobals.py b/toontown/estate/PhoneGlobals.py index 44e31f6a..d4a1e6a4 100755 --- a/toontown/estate/PhoneGlobals.py +++ b/toontown/estate/PhoneGlobals.py @@ -1,5 +1,3 @@ PHONE_MOVIE_CLEAR = 2 -PHONE_MOVIE_EMPTY = 3 -PHONE_MOVIE_PICKUP = 4 -PHONE_MOVIE_HANGUP = 5 -PHONE_MOVIE_NO_HOUSE = 6 +PHONE_MOVIE_PICKUP = 3 +PHONE_MOVIE_HANGUP = 4 \ No newline at end of file diff --git a/toontown/estate/ToonStatueSelectionGUI.py b/toontown/estate/ToonStatueSelectionGUI.py index 7fd5dcc1..0bfe95cf 100755 --- a/toontown/estate/ToonStatueSelectionGUI.py +++ b/toontown/estate/ToonStatueSelectionGUI.py @@ -9,7 +9,7 @@ from panda3d.core import * from toontown.estate import DistributedToonStatuary from toontown.estate import GardenGlobals from toontown.estate import PlantingGUI -from otp.nametag import NametagGlobals +from otp.nametag import NametagGlobals, NametagConstants from otp.nametag.NametagGroup import * from toontown.toon import DistributedToon from toontown.toon import Toon @@ -110,11 +110,7 @@ class ToonStatueSelectionGUI(DirectFrame): handle = base.cr.identifyFriend(friendId) if handle and not self.checkFamily(friendId): if hasattr(handle, 'getName'): - colorCode = CCSpeedChat - if flags & ToontownGlobals.FriendChat: - colorCode = CCFreeChat - newFF = (friendId, handle.getName(), colorCode) - self.ffList.append(newFF) + self.ffList.append((friendId, handle.getName(), NametagConstants.getFriendColor(handle))) else: self.notify.warning('Bad Handle for getName in makeFFlist') @@ -128,8 +124,7 @@ class ToonStatueSelectionGUI(DirectFrame): self.scrollList.refresh() def makeFamilyButton(self, familyId, familyName, colorCode): - fg = NametagGlobals.getNameFg(colorCode, PGButton.SInactive) - return DirectButton(relief=None, text=familyName, text_scale=0.04, text_align=TextNode.ALeft, text_fg=fg, text1_bg=self.textDownColor, text2_bg=self.textRolloverColor, text3_fg=self.textDisabledColor, textMayChange=0, command=self.__chooseFriend, extraArgs=[familyId, familyName]) + return DirectButton(relief=None, text=familyName, text_scale=0.04, text_align=TextNode.ALeft, text_fg=NametagConstants.NAMETAG_COLORS[colorCode][0][0], text1_bg=self.textDownColor, text2_bg=self.textRolloverColor, text3_fg=self.textDisabledColor, textMayChange=0, command=self.__chooseFriend, extraArgs=[familyId, familyName]) def __chooseFriend(self, friendId, friendName): messenger.send('wakeup') diff --git a/toontown/estate/TrunkGUI.py b/toontown/estate/TrunkGUI.py index c6b6b50f..7a26e96a 100755 --- a/toontown/estate/TrunkGUI.py +++ b/toontown/estate/TrunkGUI.py @@ -242,30 +242,14 @@ class TrunkGUI(StateData.StateData): self.glasses = [] self.backpacks = [] self.shoes = [] + choices = [0, 0, 0, 0] + currentAccessories = (self.toon.getHat(), self.toon.getGlasses(), self.toon.getBackpack(), self.toon.getShoes()) self.hats.append((0, 0, 0)) self.glasses.append((0, 0, 0)) self.backpacks.append((0, 0, 0)) self.shoes.append((0, 0, 0)) - self.hatChoice = 0 - self.glassesChoice = 0 - self.backpackChoice = 0 - self.shoesChoice = 0 - - if (self.toon.hat[0] != 0 or self.toon.hat[1] != 0 or self.toon.hat[2] != 0): - self.hatChoice = 1 - self.hats.append((self.toon.hat[0], self.toon.hat[1], self.toon.hat[2])) - if (self.toon.glasses[0] != 0 or self.toon.glasses[1] != 0 or self.toon.glasses[2] != 0): - self.glassesChoice = 1 - self.glasses.append((self.toon.glasses[0], self.toon.glasses[1], self.toon.glasses[2])) - if (self.toon.backpack[0] != 0 or self.toon.backpack[1] != 0 or self.toon.backpack[2] != 0): - self.backpackChoice = 1 - self.backpacks.append((self.toon.backpack[0], self.toon.backpack[1], self.toon.backpack[2])) - if (self.toon.shoes[0] != 0 or self.toon.shoes[1] != 0 or self.toon.shoes[2] != 0): - self.shoesChoice = 1 - self.shoes.append((self.toon.shoes[0], self.toon.shoes[1], self.toon.shoes[2])) - i = 0 while i < len(self.hatList): self.hats.append((self.hatList[i], self.hatList[i + 1], self.hatList[i + 2])) @@ -285,7 +269,17 @@ class TrunkGUI(StateData.StateData): while i < len(self.shoesList): self.shoes.append((self.shoesList[i], self.shoesList[i + 1], self.shoesList[i + 2])) i = i + 3 + + for i, list in enumerate((self.hats, self.glasses, self.backpacks, self.shoes)): + if len(list) >= 3: + index = list.index(currentAccessories[i]) + list[index], list[1] = list[1], list[index] + choices[i] = 1 + self.hatChoice = choices[0] + self.glassesChoice = choices[1] + self.backpackChoice = choices[2] + self.shoesChoice = choices[3] self.swapHat(0) self.swapGlasses(0) self.swapBackpack(0) diff --git a/toontown/fishing/DistributedPondBingoManagerAI.py b/toontown/fishing/DistributedPondBingoManagerAI.py index 2abd4284..f5d6e3e4 100755 --- a/toontown/fishing/DistributedPondBingoManagerAI.py +++ b/toontown/fishing/DistributedPondBingoManagerAI.py @@ -8,10 +8,9 @@ from toontown.fishing.ThreewayBingo import ThreewayBingo from toontown.fishing.DiagonalBingo import DiagonalBingo from toontown.fishing.BlockoutBingo import BlockoutBingo from toontown.fishing.FourCornerBingo import FourCornerBingo -from otp.ai.MagicWordGlobal import * from direct.task import Task from direct.distributed.ClockDelta import * -import random +import random, datetime RequestCard = {} @@ -25,26 +24,44 @@ class DistributedPondBingoManagerAI(DistributedObjectAI): self.tileSeed = None self.typeId = None self.state = 'Off' + self.pond = None self.canCall = False self.shouldStop = False self.lastUpdate = globalClockDelta.getRealNetworkTime() self.cardId = 0 + def initTasks(self): + now = datetime.datetime.now() + weekday = now.weekday() + targetday = 2 # Wednesday + if weekday in (3, 4): + targetday = 5 + togo = targetday - weekday + if togo < 0: + togo += 7 + s = now + datetime.timedelta(days=togo) + start = datetime.datetime(s.year, s.month, s.day) + secs = max(0, (start - now).total_seconds()) + self.notify.debug('Today it\'s %d, so we wait for %d, togo: %d %d' % (weekday, targetday, togo, secs)) + taskMgr.doMethodLater(secs, DistributedPondBingoManagerAI.startTask, self.taskName('start'), extraArgs=[self]) + + def startTask(self): + self.notify.debug('Starting game') + + def stop(task): + self.notify.debug('Stopping game') + self.shouldStop = True + return task.done + + taskMgr.doMethodLater(24 * 60 * 60, stop, self.taskName('stop')) + self.createGame() + def setPondDoId(self, pondId): self.pond = self.air.doId2do[pondId] def getPondDoId(self): return self.pond.getDoId() - def updateGameState(self, gameState, cellId): - pass - - def setCardState(self, cardId, typeId, tileSeed, gameState): - pass - - def setState(self, state, timeStamp): - pass - def cardUpdate(self, cardId, cellId, genus, species): avId = self.air.getAvatarIdFromSender() spot = self.pond.hasToon(avId) @@ -70,9 +87,6 @@ class DistributedPondBingoManagerAI(DistributedObjectAI): elif result == BingoGlobals.UPDATE: self.sendGameStateUpdate(cellId) - def enableBingo(self): - createGame() - def d_enableBingo(self): self.sendUpdate('enableBingo', []) @@ -150,8 +164,6 @@ class DistributedPondBingoManagerAI(DistributedObjectAI): taskMgr.doMethodLater(5, DistributedPondBingoManagerAI.startWait, 'startWait%d' % self.getDoId(), [self]) taskMgr.remove('finishGame%d' % self.getDoId()) - - def finishGame(self): self.state = 'GameOver' self.sendStateUpdate() diff --git a/toontown/fishing/FishGlobals.py b/toontown/fishing/FishGlobals.py index 54ec9f10..3cf288f1 100755 --- a/toontown/fishing/FishGlobals.py +++ b/toontown/fishing/FishGlobals.py @@ -367,7 +367,7 @@ __fishDict = {0: ((1, (5, 11, 1, - (TTG.DonaldsDreamland, TTG.MyEstate, TTG.OutdoorZone))), + (TTG.DonaldsDreamland, TTG.MyEstate, TTG.OutdoorZone, TTG.BedtimeBoulevard))), 4: ((2, 8, 1, @@ -470,7 +470,7 @@ __fishDict = {0: ((1, (6, 10, 7, - (TTG.LullabyLane,)), + (TTG.LullabyLane, TTG.BedtimeBoulevard)), (1, 1, 3, @@ -478,7 +478,7 @@ __fishDict = {0: ((1, (2, 6, 5, - (TTG.LullabyLane,)), + (TTG.LullabyLane, TTG.BedtimeBoulevard)), (10, 14, 3, diff --git a/toontown/fishing/FishingTargetGlobals.py b/toontown/fishing/FishingTargetGlobals.py index 14112014..044d4dd2 100755 --- a/toontown/fishing/FishingTargetGlobals.py +++ b/toontown/fishing/FishingTargetGlobals.py @@ -146,6 +146,12 @@ __targetInfoDict = {ToontownGlobals.ToontownCentral: (2, -2.1, 14, -2.1 - 0.378), + ToontownGlobals.BedtimeBoulevard: (2, + 378, + -355, + -2.04, + 14, + -2 - 0.483), ToontownGlobals.MyEstate: (5, 30, -126, diff --git a/toontown/friends/FriendsListManager.py b/toontown/friends/FriendsListManager.py index 5d7e2a1b..257d7eb3 100755 --- a/toontown/friends/FriendsListManager.py +++ b/toontown/friends/FriendsListManager.py @@ -5,6 +5,7 @@ import FriendInvitee import FriendNotifier from direct.directnotify import DirectNotifyGlobal from toontown.toon import ToonTeleportPanel +from toontown.friends import ToontownFriendSecret from toontown.pets import PetAvatarPanel from toontown.toon import ToonAvatarPanel from toontown.suit import SuitAvatarPanel @@ -73,6 +74,7 @@ class FriendsListManager: self.ignore('friendAvatar') self.ignore('avatarDetails') FriendsListPanel.hideFriendsList() + ToontownFriendSecret.hideFriendSecret() if base.cr.friendManager: base.cr.friendManager.setAvailable(0) self.ignore('friendInvitation') diff --git a/toontown/friends/FriendsListPanel.py b/toontown/friends/FriendsListPanel.py index 1abaf5fe..af2ff4e6 100755 --- a/toontown/friends/FriendsListPanel.py +++ b/toontown/friends/FriendsListPanel.py @@ -2,6 +2,7 @@ from panda3d.core import * from direct.gui.DirectGui import * from direct.fsm import StateData from toontown.toon import ToonAvatarPanel +from toontown.friends import ToontownFriendSecret from toontown.toonbase import ToontownGlobals from toontown.toonbase import TTLocalizer from otp.nametag.NametagGroup import * @@ -94,7 +95,6 @@ class FriendsListPanel(DirectFrame, StateData.StateData): self.textDownColor = Vec4(0.5, 0.9, 1, 1) self.textDisabledColor = Vec4(0.4, 0.8, 0.4, 1) self.panelType = FLPOnline - return def load(self): if self.isLoaded == 1: @@ -128,9 +128,12 @@ class FriendsListPanel(DirectFrame, StateData.StateData): gui.find('**/Horiz_Arrow_Rllvr'), gui.find('**/Horiz_Arrow_UP')), image3_color=Vec4(0.6, 0.6, 0.6, 0.6), pos=(0.17, 0, -0.38), command=self.__right) self.newFriend = DirectButton(parent=self, relief=None, pos=(-0.14, 0.0, 0.14), image=(auxGui.find('**/Frnds_Btn_UP'), auxGui.find('**/Frnds_Btn_DN'), auxGui.find('**/Frnds_Btn_RLVR')), text=('', TTLocalizer.FriendsListPanelNewFriend, TTLocalizer.FriendsListPanelNewFriend), text_scale=TTLocalizer.FLPnewFriend, text_fg=(0, 0, 0, 1), text_bg=(1, 1, 1, 1), text_pos=(0.1, -0.085), textMayChange=0, command=self.__newFriend) + self.trueFriends = DirectButton(parent=self, relief=None, pos=TTLocalizer.FLPtruefriendsPos, image=(auxGui.find('**/ChtBx_ChtBtn_UP'), auxGui.find('**/ChtBx_ChtBtn_DN'), auxGui.find('**/ChtBx_ChtBtn_RLVR')), text=('', + TTLocalizer.FriendsListPanelTrueFriends, + TTLocalizer.FriendsListPanelTrueFriends, + ''), text_scale=TTLocalizer.FLPtruefriends, text_fg=(0, 0, 0, 1), text_bg=(1, 1, 1, 1), text_pos=(-0.04, -0.085), textMayChange=0, command=self.__trueFriends) gui.removeNode() auxGui.removeNode() - return def unload(self): if self.isLoaded == 0: @@ -144,7 +147,6 @@ class FriendsListPanel(DirectFrame, StateData.StateData): del self.right del self.friends DirectFrame.destroy(self) - return None def makeFriendButton(self, avId, color): handle = base.cr.identifyFriend(avId) @@ -212,10 +214,13 @@ class FriendsListPanel(DirectFrame, StateData.StateData): self.__updateTitle() self.__updateArrows() + def __trueFriends(self): + messenger.send('wakeup') + ToontownFriendSecret.showFriendSecret() + def __newFriend(self): messenger.send('wakeup') messenger.send('friendAvatar', [None, None, None]) - return def __choseFriend(self, friendId): messenger.send('wakeup') @@ -271,7 +276,6 @@ class FriendsListPanel(DirectFrame, StateData.StateData): del self.friends[friendId] self.createButtons(petFriends, NAMETAG_COLORS[CCNonPlayer][0][0]) - self.createButtons(admins, NAMETAG_COLORS[CCAdmin][0][0]) self.createButtons(trueFriends, NAMETAG_COLORS[CCNormal][0][0]) self.createButtons(friends, NAMETAG_COLORS[CCSpeedChat][0][0]) diff --git a/toontown/friends/TTSFriendsManagerUD.py b/toontown/friends/TTSFriendsManagerUD.py index 39443f18..36e1bffc 100755 --- a/toontown/friends/TTSFriendsManagerUD.py +++ b/toontown/friends/TTSFriendsManagerUD.py @@ -95,10 +95,11 @@ class RemoveFriendOperation(OperationFSM): self.demand('Error', 'Distributed Class was not a Toon.') return - self.demand('Retrieved', fields['setFriendsList'][0]) + self.demand('Retrieved', fields['setFriendsList'][0], fields['setTrueFriends'][0]) - def enterRetrieved(self, friendsList): + def enterRetrieved(self, friendsList, trueFriendsList): friendsList.remove(self.target) + trueFriendsList.remove(self.target) if self.sender in self.mgr.onlineToons: dg = self.air.dclassesByName['DistributedToonUD'].aiFormatUpdate( 'setFriendsList', self.sender, self.sender, @@ -114,7 +115,7 @@ class RemoveFriendOperation(OperationFSM): self.air.dbInterface.updateObject(self.air.dbId, self.sender, self.air.dclassesByName['DistributedToonUD'], - {'setFriendsList' : [friendsList]}) + {'setFriendsList' : [friendsList], 'setTrueFriends' : [trueFriendsList]}) self.demand('Off') # -- Clear List -- @@ -149,6 +150,7 @@ class TTSFriendsManagerUD(DistributedObjectGlobalUD): self.onlineToons = [] self.tpRequests = {} self.whisperRequests = {} + self.toon2data = {} self.operations = [] self.delayTime = 1.0 @@ -252,6 +254,8 @@ class TTSFriendsManagerUD(DistributedObjectGlobalUD): self.sendUpdateToAvatarId(friendId, 'friendOffline', [doId]) if doId in self.onlineToons: self.onlineToons.remove(doId) + if doId in self.toon2data: + del self.toon2data[doId] self.air.dbInterface.queryObject(self.air.dbId, doId, handleToon) # -- Clear List -- @@ -356,3 +360,19 @@ class TTSFriendsManagerUD(DistributedObjectGlobalUD): def sleepAutoReply(self, toId): requester = self.air.getAvatarIdFromSender() self.sendUpdateToAvatarId(toId, 'setSleepAutoReply', [requester]) + + def getToonAccess(self, doId): + return self.toon2data.get(doId, {}).get('access', 0) + + def getToonName(self, doId): + return self.toon2data.get(doId, {}).get('name', '???') + + def getToonAccId(self, doId): + return self.toon2data.get(doId, {}).get('accId', 0) + + def addToonData(self, doId, fields): + data = {} + data['access'] = fields.get('setAdminAccess', [0])[0] + data['name'] = fields['setName'][0] + data['accId'] = fields.get('setDISLid', [0])[0] + self.toon2data[doId] = data diff --git a/toontown/friends/ToontownFriendSecret.py b/toontown/friends/ToontownFriendSecret.py new file mode 100644 index 00000000..1635a3c5 --- /dev/null +++ b/toontown/friends/ToontownFriendSecret.py @@ -0,0 +1,198 @@ +from pandac.PandaModules import * +from direct.gui.DirectGui import * +from direct.directnotify import DirectNotifyGlobal +from toontown.toonbase import TTLocalizer, ToontownGlobals +from otp.otpbase import OTPGlobals + +globalFriendSecret = None + +def showFriendSecret(): + global globalFriendSecret + if not settings['trueFriends']: + chatMgr = base.localAvatar.chatMgr + chatMgr.fsm.request('noTrueFriends') + else: + if globalFriendSecret != None: + globalFriendSecret.unload() + globalFriendSecret = ToontownFriendSecret() + globalFriendSecret.enter() + +def hideFriendSecret(): + if globalFriendSecret != None: + globalFriendSecret.exit() + +def unloadFriendSecret(): + global globalFriendSecret + if globalFriendSecret != None: + globalFriendSecret.unload() + globalFriendSecret = None + return + +class ToontownFriendSecret(DirectFrame): + notify = DirectNotifyGlobal.directNotify.newCategory('ToontownFriendSecret') + + def __init__(self): + 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)) + self.initialiseoptions(ToontownFriendSecret) + self.isLoaded = 0 + self.isEntered = 0 + + def unload(self): + if self.isLoaded == 0: + return None + self.isLoaded = 0 + self.exit() + del self.introText + del self.getSecret + del self.enterSecretText + del self.enterSecret + del self.ok1 + del self.ok2 + del self.cancel + del self.secretText + DirectFrame.destroy(self) + + 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=TTLocalizer.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=TTLocalizer.FSgetSecret, text=TTLocalizer.FriendSecretGetSecret, text_scale=TTLocalizer.FSgetSecretButton, text_pos=(0, -0.02), command=self.__getSecret) + self.getSecret.hide() + self.enterSecretText = DirectLabel(parent=self, relief=None, pos=TTLocalizer.FSenterSecretTextPos, scale=0.05, text=TTLocalizer.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.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=TTLocalizer.FSok1, text=TTLocalizer.FriendSecretEnter, text_scale=0.06, text_pos=(0, -0.02), pos=(0, 0, -0.5), command=self.__ok1) + self.ok1.hide() + self.ok2 = DirectButton(parent=self, relief=None, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=TTLocalizer.FSok2, text=TTLocalizer.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=TTLocalizer.FriendSecretCancel, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=TTLocalizer.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=TTLocalizer.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.08, text='', text_fg=(0, 0, 0, 1), text_wordwrap=30) + self.secretText.hide() + guiButton.removeNode() + + def enter(self): + if self.isEntered == 1: + return + self.isEntered = 1 + if self.isLoaded == 0: + self.load() + self.show() + 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') + self.enterSecret['focus'] = 1 + + def exit(self): + if self.isEntered == 0: + return + self.isEntered = 0 + self.__cleanupFirstPage() + self.hide() + + def __getSecret(self): + self.__cleanupFirstPage() + self.nextText['text'] = TTLocalizer.FriendSecretGettingSecret + self.nextText.setPos(0, 0, 0.3) + self.nextText.show() + self.ok1.hide() + self.cancel.show() + base.cr.friendManager.requestTFCode(self.gotSecret) + + def gotSecret(self, response, code): + if response == ToontownGlobals.TF_COOLDOWN: + self.rejectGetSecret(TTLocalizer.FriendSecretTooMany) + elif response == ToontownGlobals.TF_SUCCESS: + self.successGetSecret(code) + + def rejectGetSecret(self, reason): + self.nextText['text'] = reason + self.nextText.show() + self.secretText.show() + self.cancel.hide() + self.ok1.hide() + self.ok2.show() + + def successGetSecret(self, code): + self.nextText['text'] = TTLocalizer.FriendSecretGotSecret + self.nextText.setPos(*TTLocalizer.FSgotSecretPos) + self.secretText['text'] = code + self.secretText.setScale(0.1 if code.startswith('TT') else 0.08) + self.nextText.show() + self.secretText.show() + self.cancel.hide() + self.ok1.hide() + self.ok2.show() + + def __enterSecret(self, secret): + self.enterSecret.set('') + secret = secret.strip() + + if not secret: + self.exit() + return + + self.__cleanupFirstPage() + self.nextText['text'] = TTLocalizer.FriendSecretTryingSecret + base.cr.friendManager.redeemTFCode(secret, self.gotResponse) + self.nextText.setPos(0, 0, 0.3) + self.nextText.show() + self.cancel.hide() + self.ok1.hide() + self.ok2.show() + + def gotResponse(self, response, name): + if response == ToontownGlobals.TF_UNKNOWN_SECRET: + self.nextText['text'] = TTLocalizer.FriendSecretEnteredSecretUnknown + elif response == ToontownGlobals.TF_SELF_SECRET: + self.nextText['text'] = TTLocalizer.FriendSecretEnteredSecretSelf + elif response == ToontownGlobals.TF_TOO_FAST: + self.nextText['text'] = TTLocalizer.FriendSecretTooFast + elif response == ToontownGlobals.TF_FRIENDS_LIST_FULL_YOU: + self.nextText['text'] = TTLocalizer.FriendSecretEnteredSecretFullYou + elif response == ToontownGlobals.TF_FRIENDS_LIST_FULL_HIM: + self.nextText['text'] = TTLocalizer.FriendSecretEnteredSecretFullHim % name + elif response == ToontownGlobals.TF_ALREADY_FRIENDS: + self.nextText['text'] = TTLocalizer.FriendSecretAlreadyFriends + elif response == ToontownGlobals.TF_ALREADY_FRIENDS_NAME: + self.nextText['text'] = TTLocalizer.FriendSecretAlreadyFriendsName % name + elif response == ToontownGlobals.TF_SUCCESS: + self.nextText['text'] = TTLocalizer.FriendSecretNowFriends % name + self.nextText.show() + self.cancel.hide() + self.ok1.hide() + self.ok2.show() + + def __ok1(self): + secret = self.enterSecret.get() + self.__enterSecret(secret) + + def __ok2(self): + self.exit() + + def __cancel(self): + self.exit() + + def __cleanupFirstPage(self): + self.introText.hide() + self.getSecret.hide() + self.enterSecretText.hide() + self.enterSecret.hide() + base.localAvatar.chatMgr.fsm.request('mainMenu') diff --git a/toontown/golf/DistributedGolfCourseAI.py b/toontown/golf/DistributedGolfCourseAI.py index cb4b26e8..96e21b2f 100755 --- a/toontown/golf/DistributedGolfCourseAI.py +++ b/toontown/golf/DistributedGolfCourseAI.py @@ -6,6 +6,7 @@ from panda3d.core import * from direct.fsm.FSM import FSM from toontown.ai.ToonBarrier import * from toontown.golf import GolfGlobals +from toontown.uberdog import TopToonsGlobals INITIAL = 0 EXITED = 1 EXPECTED = 2 @@ -767,6 +768,7 @@ class DistributedGolfCourseAI(DistributedObjectAI.DistributedObjectAI, FSM): oldTrophies = GolfGlobals.calcTrophyListFromHistory(oldHistory) endingTrophies = GolfGlobals.calcTrophyListFromHistory(endingHistory) av.b_setGolfHistory(endingHistory) + av.addStat(ToontownGlobals.STAT_GOLF) newTrophies = [] for index in xrange(len(oldTrophies)): if not oldTrophies[index] and endingTrophies[index]: @@ -970,12 +972,17 @@ class DistributedGolfCourseAI(DistributedObjectAI.DistributedObjectAI, FSM): stillPlaying = self.getStillPlayingAvIds() for avId in stillPlaying: scoreList = self.scores[avId] + ns = 0 for holeIndex in xrange(len(scoreList)): strokes = scoreList[holeIndex] if strokes == 1: + ns +=1 holeId = self.holeIds[holeIndex] self.air.writeServerEvent('golf_ace', avId, '%d|%d|%s' % (self.courseId, holeId, stillPlaying)) + if ns: + messenger.send('topToonsManager-event', [avId, TopToonsGlobals.CAT_HOLE_IN_ONE, ns]) + def recordCourseUnderPar(self): coursePar = self.calcCoursePar() stillPlaying = self.getStillPlayingAvIds() @@ -984,7 +991,8 @@ class DistributedGolfCourseAI(DistributedObjectAI.DistributedObjectAI, FSM): netScore = totalScore - coursePar if netScore < 0: self.air.writeServerEvent('golf_underPar', avId, '%d|%d|%s' % (self.courseId, netScore, stillPlaying)) - + messenger.send('topToonsManager-event', [avId, TopToonsGlobals.CAT_COURSE_UNDER_PAR, 1]) + def addAimTime(self, avId, aimTime): if avId in self.aimTimes: self.aimTimes[avId] += aimTime diff --git a/toontown/groups/GlobalGroup.py b/toontown/groups/GlobalGroup.py deleted file mode 100755 index 143d8807..00000000 --- a/toontown/groups/GlobalGroup.py +++ /dev/null @@ -1,20 +0,0 @@ -class GlobalGroup: - - def __init__(self, groupType, groupId): - self.activePlayers = [] - self.groupType = groupType - self.groupId = groupId - - def getGroupPlayers(self): - return self.activePlayers - - def isInGroup(self, avId): - if avId in self.activePlayers: - return True - return False - - def addPlayerToGroup(self, avId): - self.activePlayers.append(avId) - - def removePlayerFromGroup(self, avId): - self.activePlayers.remove(avId) diff --git a/toontown/groups/GroupManager.py b/toontown/groups/GroupManager.py deleted file mode 100755 index 684a6009..00000000 --- a/toontown/groups/GroupManager.py +++ /dev/null @@ -1,78 +0,0 @@ -from panda3d.core import * -from direct.distributed import DistributedObject -from direct.directnotify import DirectNotifyGlobal -from toontown.toonbase.ToontownGlobals import * - -class GroupManager(DistributedObject.DistributedObject): - notify = DirectNotifyGlobal.directNotify.newCategory('GroupManager') - neverDisable = 1 - - def __init__(self, cr): - DistributedObject.DistributedObject.__init__(self, cr) - self.shardGroups = {} - self.groupPlayers = {} - self.id2type = { - SellbotHQ: 'VP', - CashbotHQ: 'CFO', - LawbotHQ: 'CJ', - BossbotHQ: 'CEO', - } - - def announceGenerate(self): - DistributedObject.DistributedObject.announceGenerate(self) - self.cr.groupManager = self - self.d_setChildId() - - def delete(self): - DistributedObject.DistributedObject.delete(self) - self.cr.groupManager = None - - def d_setChildId(self): - self.sendUpdate('setChildId', []) - - def isPlayerGrouped(self, avId): - for group in self.groupPlayers.values(): - if avId in group: - return True - return False - - def isInGroup(self, avId, groupId): - group = self.groupPlayers.get(groupId) - if group is None: - return False - if avId in group: - return True - return False - - def requestInfo(self): - self.sendUpdate('updateInfo', []) - - def getTypeFromId(self, groupId): - return self.id2type.get(groupId) - - def setGroups(self, shardGroups): - self.shardGroups = eval(shardGroups) - - def getGroups(self): - return self.shardGroups - - def setGroupPlayers(self, groupPlayers): - self.groupPlayers = eval(groupPlayers) - - def getGroupPlayers(self, groupId): - group = self.groupPlayers.get(groupId) - if group is None: - return [] - return group - - def d_createGroup(self, groupId, groupType): - self.sendUpdate('createGroup', [groupId, groupType]) - - def d_closeGroup(self, groupId): - self.sendUpdate('closeGroup', [groupId]) - - def d_addPlayerToGroup(self, groupId, avId): - self.sendUpdate('addPlayerToGroup', [groupId, avId]) - - def d_removePlayerFromGroup(self, groupId, avId): - self.sendUpdate('removePlayerFromGroup', [groupId, avId]) diff --git a/toontown/groups/GroupManagerAI.py b/toontown/groups/GroupManagerAI.py deleted file mode 100755 index 87dd2ff5..00000000 --- a/toontown/groups/GroupManagerAI.py +++ /dev/null @@ -1,129 +0,0 @@ -from panda3d.core import * -from direct.task import Task -from direct.distributed import DistributedObjectAI -from direct.directnotify import DirectNotifyGlobal -from toontown.toonbase.ToontownGlobals import * -from GlobalGroup import GlobalGroup - -class GroupManagerAI(DistributedObjectAI.DistributedObjectAI): - notify = DirectNotifyGlobal.directNotify.newCategory('GroupManagerAI') - - def __init__(self, air): - DistributedObjectAI.DistributedObjectAI.__init__(self, air) - self.sellGroup = GlobalGroup('VP', SellbotHQ) - self.cashGroup = GlobalGroup('CFO', CashbotHQ) - self.lawGroup = GlobalGroup('CJ', LawbotHQ) - self.bossGroup = GlobalGroup('CEO', BossbotHQ) - self.shardGroups = { - SellbotHQ: self.sellGroup, - CashbotHQ: self.cashGroup, - LawbotHQ: self.lawGroup, - BossbotHQ: self.bossGroup, - } - self.groupPlayers = { - SellbotHQ: [], - CashbotHQ: [], - LawbotHQ: [], - BossbotHQ: [], - } - self.id2type = { - SellbotHQ: 'VP', - CashbotHQ: 'CFO', - LawbotHQ: 'CJ', - BossbotHQ: 'CEO', - } - self.childId = None - - def announceGenerate(self): - DistributedObjectAI.DistributedObjectAI.announceGenerate(self) - self.air.groupManager = self - self.confirmActiveToons = taskMgr.doMethodLater(45, self.confirmToonsInGroup, 'confirmActiveToons') - - def delete(self): - DistributedObjectAI.DistributedObjectAI.delete(self) - taskMgr.remove('confirmActiveToons') - self.air.groupManager = None - - def setChildId(self): - doId = self.air.getAvatarIdFromSender() - self.childId = doId - self.sendUpdateToAvatarId(self.childId, 'requestInfo', []) - - def isPlayerGrouped(self, avId): - for group in self.shardGroups.values(): - if avId in group.getGroupPlayers(): - return True - return False - - def isInGroup(self, avId, groupId): - group = self.shardGroups.get(groupId) - if group is None: - return False - if avId in group.getGroupPlayers(): - return True - return False - - def confirmToonsInGroup(self, task): - for groupId, group in self.groupPlayers.items(): - for player in group: - toon = simbase.air.doId2do.get(player) - if (toon.zoneId != groupId) or (toon.zoneId + 100 != groupId): - self.removePlayerFromGroup(groupId, player) - return task.again - - def updateInfo(self): - self.d_setGroupPlayers(str(self.groupPlayers)) - self.d_setGroups(str(self.id2type)) - - def getTypeFromId(self, groupId): - return self.id2type.get(groupId) - - def d_setGroups(self, shardGroups): - self.sendUpdateToAvatarId(self.childId, 'setGroups', [shardGroups]) - - def getGroups(self): - return self.shardGroups - - def d_setGroupPlayers(self, groupPlayers): - self.sendUpdateToAvatarId(self.childId, 'setGroupPlayers', [groupPlayers]) - - def getGroupPlayers(self, groupId): - group = self.shardGroups.get(groupId) - if group is None: - return [] - players = group.getGroupPlayers() - return players - - def createGroup(self, groupId, groupType): - group = self.shardGroups.get(groupId) - if group is not None: - newGroup = DistributedGlobalGroupAI(self.air, groupType, groupId) - self.shardGroups.update(groupId, newGroup) - players = {groupId: self.getGroupPlayers(groupId)} - self.groupPlayers.update(players) - self.updateInfo() - - def closeGroup(self, groupId): - group = self.shardGroups.get(groupId) - if group is not None: - self.shardGroups.pop(groupId) - self.groupPlayers.pop(groupId) - self.updateInfo() - - def addPlayerToGroup(self, groupId, avId): - group = self.shardGroups.get(groupId) - if group is not None: - if not group.isInGroup(avId): - group.addPlayerToGroup(avId) - players = {groupId: self.getGroupPlayers(groupId)} - self.groupPlayers.update(players) - self.updateInfo() - - def removePlayerFromGroup(self, groupId, avId): - group = self.shardGroups.get(groupId) - if group is not None: - if group.isInGroup(avId): - group.removePlayerFromGroup(avId) - players = {groupId: self.getGroupPlayers(groupId)} - self.groupPlayers.update(players) - self.updateInfo() diff --git a/toontown/groups/GroupManagerUD.py b/toontown/groups/GroupManagerUD.py deleted file mode 100755 index 69de0f8b..00000000 --- a/toontown/groups/GroupManagerUD.py +++ /dev/null @@ -1,14 +0,0 @@ -from direct.distributed import DistributedObjectUD -from direct.directnotify import DirectNotifyGlobal - -class GroupManagerUD(DistributedObjectUD.DistributedObjectUD): - notify = DirectNotifyGlobal.directNotify.newCategory('GroupManagerUD') - - def __init__(self, air): - DistributedObjectUD.DistributedObjectUD.__init__(self, air) - - def announceGenerate(self): - DistributedObjectUD.DistributedObjectUD.announceGenerate(self) - - def delete(self): - DistributedObjectUD.DistributedObjectUD.delete(self) diff --git a/toontown/groups/__init__.py b/toontown/groups/__init__.py deleted file mode 100755 index e69de29b..00000000 diff --git a/toontown/hood/BossbotHQAI.py b/toontown/hood/BossbotHQAI.py index bf9217eb..d734ec9d 100755 --- a/toontown/hood/BossbotHQAI.py +++ b/toontown/hood/BossbotHQAI.py @@ -37,14 +37,13 @@ class BossbotHQAI(CogHQAI.CogHQAI): (-48.44, 15.308, 0) ) hprList = ((110.815, 0, 0), (61.231, 0, 0), (-105.481, 0, 0)) - mins = ToontownGlobals.FactoryLaffMinimums[3] for cogCourse in xrange(len(posList)): pos = posList[cogCourse] hpr = hprList[cogCourse] cogKart = DistributedCogKartAI.DistributedCogKartAI( self.air, cogCourse, pos[0], pos[1], pos[2], hpr[0], hpr[1], hpr[2], - self.air.countryClubMgr, minLaff=mins[cogCourse]) + self.air.countryClubMgr) cogKart.generateWithRequired(self.zoneId) self.cogKarts.append(cogKart) diff --git a/toontown/hood/CashbotHQAI.py b/toontown/hood/CashbotHQAI.py index 24223d28..eb69bd61 100755 --- a/toontown/hood/CashbotHQAI.py +++ b/toontown/hood/CashbotHQAI.py @@ -37,11 +37,10 @@ class CashbotHQAI(CogHQAI.CogHQAI): ToontownGlobals.CashbotMintIntB, ToontownGlobals.CashbotMintIntC ) - mins = ToontownGlobals.FactoryLaffMinimums[1] for i in xrange(len(destZones)): mintElevator = DistributedMintElevatorExtAI( self.air, self.air.mintMgr, destZones[i], - antiShuffle=0, minLaff=mins[i]) + antiShuffle=0) mintElevator.generateWithRequired(self.zoneId) self.mintElevators.append(mintElevator) diff --git a/toontown/hood/CogHQAI.py b/toontown/hood/CogHQAI.py index 7f5070bd..dfcd7a1a 100755 --- a/toontown/hood/CogHQAI.py +++ b/toontown/hood/CogHQAI.py @@ -61,7 +61,7 @@ class CogHQAI: doorIndex=intDoorIndex, lockValue=lock) intDoor.zoneId = destinationZone - extDoor = DistributedCogHQExteriorDoorAI.DistributedCogHQExteriorDoorAI( + extDoor = DistributedCogHQDoorAI.DistributedCogHQDoorAI( self.air, 0, DoorTypes.EXT_COGHQ, destinationZone, doorIndex=extDoorIndex, lockValue=lock) diff --git a/toontown/hood/DLHoodAI.py b/toontown/hood/DLHoodAI.py index 905311e1..2ee55fa2 100755 --- a/toontown/hood/DLHoodAI.py +++ b/toontown/hood/DLHoodAI.py @@ -1,5 +1,5 @@ from toontown.hood import HoodAI -from toontown.safezone import DistributedTrolleyAI, DistributedPillowAI +from toontown.safezone import DistributedTrolleyAI from toontown.toonbase import ToontownGlobals from toontown.ai import DistributedResistanceEmoteMgrAI from toontown.ai import DistributedEffectMgrAI @@ -29,13 +29,7 @@ class DLHoodAI(HoodAI.HoodAI): self.winterCarolingMgr = DistributedEffectMgrAI.DistributedEffectMgrAI(self.air, ToontownGlobals.CHRISTMAS, 14) self.winterCarolingMgr.generateWithRequired(9722) # Dream On Talent Agency, Pajama Place - self.createPillow() - def createTrolley(self): self.trolley = DistributedTrolleyAI.DistributedTrolleyAI(self.air) self.trolley.generateWithRequired(self.zoneId) - self.trolley.start() - - def createPillow(self): - self.pillow = DistributedPillowAI.DistributedPillowAI(self.air) - self.pillow.generateWithRequired(self.zoneId) + self.trolley.start() \ No newline at end of file diff --git a/toontown/hood/HoodAI.py b/toontown/hood/HoodAI.py index 592e302f..8b0446ad 100755 --- a/toontown/hood/HoodAI.py +++ b/toontown/hood/HoodAI.py @@ -5,6 +5,7 @@ from toontown.fishing.DistributedFishingPondAI import DistributedFishingPondAI from toontown.hood import ZoneUtil from toontown.safezone import TreasureGlobals from toontown.safezone.DistributedFishingSpotAI import DistributedFishingSpotAI +from toontown.fishing.DistributedPondBingoManagerAI import DistributedPondBingoManagerAI from toontown.safezone.DistributedPartyGateAI import DistributedPartyGateAI from toontown.safezone.SZTreasurePlannerAI import SZTreasurePlannerAI from toontown.suit import DistributedSuitPlannerAI @@ -90,6 +91,11 @@ class HoodAI: fishingPond.generateWithRequired(zoneId) fishingPond.start() + fishingPond.bingoMgr = DistributedPondBingoManagerAI(simbase.air) + fishingPond.bingoMgr.setPondDoId(fishingPond.getDoId()) + fishingPond.bingoMgr.generateWithRequired(zoneId) + fishingPond.bingoMgr.initTasks() + fishingPonds.append(fishingPond) elif isinstance(dnaGroup, DNAVisGroup): zoneId = int(dnaGroup.getName().split(':')[0]) diff --git a/toontown/hood/LawbotHQAI.py b/toontown/hood/LawbotHQAI.py index 01d1498c..a13eaaa5 100755 --- a/toontown/hood/LawbotHQAI.py +++ b/toontown/hood/LawbotHQAI.py @@ -50,11 +50,10 @@ class LawbotHQAI(CogHQAI.CogHQAI): ToontownGlobals.LawbotStageIntC, ToontownGlobals.LawbotStageIntD ) - mins = ToontownGlobals.FactoryLaffMinimums[2] for i in xrange(len(destZones)): lawOfficeElevator = DistributedLawOfficeElevatorExtAI( self.air, self.air.lawOfficeMgr, destZones[i], i, - antiShuffle=0, minLaff=mins[i]) + antiShuffle=0) lawOfficeElevator.generateWithRequired( ToontownGlobals.LawbotOfficeExt) self.lawOfficeElevators.append(lawOfficeElevator) diff --git a/toontown/hood/TTHoodAI.py b/toontown/hood/TTHoodAI.py index 809e0439..7fb90618 100755 --- a/toontown/hood/TTHoodAI.py +++ b/toontown/hood/TTHoodAI.py @@ -2,8 +2,6 @@ from toontown.hood import HoodAI from toontown.safezone import ButterflyGlobals from toontown.safezone import DistributedButterflyAI from toontown.safezone import DistributedTrolleyAI -from toontown.toon import NPCToons -from toontown.toonbase import TTLocalizer from toontown.toonbase import ToontownGlobals from toontown.ai import DistributedEffectMgrAI @@ -25,11 +23,6 @@ class TTHoodAI(HoodAI.HoodAI): if simbase.config.GetBool('want-butterflies', True): self.createButterflies() - NPCToons.createNPC( - simbase.air, 2021, - (ToontownGlobals.ToontownCentral, TTLocalizer.NPCToonNames[2021], ('dss', 'ls', 's', 'm', 13, 41, 13, 13, 1, 6, 1, 6, 0, 18, 0), 'm', 1, NPCToons.NPC_GLOVE), - ToontownGlobals.ToontownCentral, posIndex=0) - self.trickOrTreatMgr = DistributedEffectMgrAI.DistributedEffectMgrAI(self.air, ToontownGlobals.HALLOWEEN, 12) self.trickOrTreatMgr.generateWithRequired(2649) # All Fun and Games Shop, Silly Street diff --git a/toontown/login/AvatarChoice.py b/toontown/login/AvatarChoice.py index 0418936b..faf3665a 100755 --- a/toontown/login/AvatarChoice.py +++ b/toontown/login/AvatarChoice.py @@ -165,9 +165,7 @@ class AvatarChoice(DirectButton): self.verifyDeleteWithPassword() def verifyDeleteWithPassword(self): - deleteText = TTLocalizer.AvatarChoiceDeleteConfirmText % { - 'name': self.name, - 'confirm': TTLocalizer.AvatarChoiceDeleteConfirmUserTypes} + deleteText = TTLocalizer.AvatarChoiceDeleteConfirmText % {'name': self.name} if self.deleteWithPasswordFrame == None: buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui') nameBalloon = loader.loadModel('phase_3/models/props/chatbox_input') @@ -190,13 +188,12 @@ class AvatarChoice(DirectButton): return def __handleDeleteWithConfirmOK(self, *args): - if self.passwordEntry.get().lower() == TTLocalizer.AvatarChoiceDeleteConfirmUserTypes: + if self.passwordEntry.get().lower() == self.name.lower(): self.deleteWithPasswordFrame.hide() base.transitions.noTransitions() messenger.send(self.doneEvent, ['delete', self.position]) else: - self.deleteWithPasswordFrame['text'] = TTLocalizer.AvatarChoiceDeleteWrongConfirm % {'name': self.name, - 'confirm': TTLocalizer.AvatarChoiceDeleteConfirmUserTypes} + self.deleteWithPasswordFrame['text'] = TTLocalizer.AvatarChoiceDeleteWrongConfirm % {'name': self.name} self.passwordEntry['focus'] = 1 self.passwordEntry.enterText('') diff --git a/toontown/makeatoon/BodyShop.py b/toontown/makeatoon/BodyShop.py index deb5a39e..1ed6b4bd 100755 --- a/toontown/makeatoon/BodyShop.py +++ b/toontown/makeatoon/BodyShop.py @@ -165,7 +165,7 @@ class BodyShop(StateData.StateData): del self.legRButton self.shuffleButton.unload() self.ignore('MAT-newToonCreated') - + def __swapTorso(self, offset): gender = self.toon.style.getGender() if not self.clothesPicked: @@ -174,12 +174,6 @@ class BodyShop(StateData.StateData): elif gender == 'm': length = len(ToonDNA.toonTorsoTypes[:3]) torsoOffset = 0 - if self.dna.armColor not in ToonDNA.defaultBoyColorList: - self.dna.armColor = ToonDNA.defaultBoyColorList[0] - if self.dna.legColor not in ToonDNA.defaultBoyColorList: - self.dna.legColor = ToonDNA.defaultBoyColorList[0] - if self.dna.headColor not in ToonDNA.defaultBoyColorList: - self.dna.headColor = ToonDNA.defaultBoyColorList[0] if self.toon.style.topTex not in ToonDNA.MakeAToonBoyShirts: randomShirt = ToonDNA.getRandomTop(gender, ToonDNA.MAKE_A_TOON) shirtTex, shirtColor, sleeveTex, sleeveColor = randomShirt @@ -197,12 +191,6 @@ class BodyShop(StateData.StateData): torsoOffset = 3 else: torsoOffset = 0 - if self.dna.armColor not in ToonDNA.defaultGirlColorList: - self.dna.armColor = ToonDNA.defaultGirlColorList[0] - if self.dna.legColor not in ToonDNA.defaultGirlColorList: - self.dna.legColor = ToonDNA.defaultGirlColorList[0] - if self.dna.headColor not in ToonDNA.defaultGirlColorList: - self.dna.headColor = ToonDNA.defaultGirlColorList[0] if self.toon.style.topTex not in ToonDNA.MakeAToonGirlShirts: randomShirt = ToonDNA.getRandomTop(gender, ToonDNA.MAKE_A_TOON) shirtTex, shirtColor, sleeveTex, sleeveColor = randomShirt diff --git a/toontown/makeatoon/ColorShop.py b/toontown/makeatoon/ColorShop.py index 03e80e05..3f004a6d 100755 --- a/toontown/makeatoon/ColorShop.py +++ b/toontown/makeatoon/ColorShop.py @@ -3,9 +3,9 @@ from toontown.toon import ToonDNA from direct.fsm import StateData from direct.gui.DirectGui import * from MakeAToonGlobals import * -from toontown.toonbase import TTLocalizer +from toontown.toonbase import TTLocalizer, ToontownGlobals import ShuffleButton -import random +import random, colorsys from direct.directnotify import DirectNotifyGlobal class ColorShop(StateData.StateData): @@ -17,38 +17,26 @@ class ColorShop(StateData.StateData): self.colorAll = 1 return - def getGenderColorList(self, dna): - if self.dna.getGender() == 'm': - colorList = ToonDNA.defaultBoyColorList - else: - colorList = ToonDNA.defaultGirlColorList - - return colorList + def getColorList(self): + return ToonDNA.allColorsList def enter(self, toon, shopsVisited = []): base.disableMouse() self.toon = toon self.dna = toon.getStyle() - colorList = self.getGenderColorList(self.dna) - try: + colorList = self.getColorList() + self.allParts = (TTLocalizer.ColorAll, TTLocalizer.ColorShopHead, TTLocalizer.ColorShopBody, TTLocalizer.ColorShopGloves, TTLocalizer.ColorShopLegs) + if not hasattr(self, 'headChoice'): self.headChoice = colorList.index(self.dna.headColor) self.armChoice = colorList.index(self.dna.armColor) self.gloveChoice = colorList.index(self.dna.gloveColor) self.legChoice = colorList.index(self.dna.legColor) - except: - self.headChoice = random.choice(colorList) - self.armChoice = self.headChoice - self.gloveChoice = self.gloveChoice - self.legChoice = self.headChoice - self.__swapHeadColor(0) - self.__swapArmColor(0) - self.__swapGloveColor(0) - self.__swapLegColor(0) + self.partChoice = 0 self.startColor = 0 self.acceptOnce('last', self.__handleBackward) self.acceptOnce('next', self.__handleForward) - choicePool = [self.getGenderColorList(self.dna), self.getGenderColorList(self.dna), self.getGenderColorList(self.dna), self.getGenderColorList(self.dna)] + choicePool = [self.getColorList(), self.getColorList(), self.getColorList(), self.getColorList()] self.shuffleButton.setChoicePool(choicePool) self.accept(self.shuffleFetchMsg, self.changeColor) self.acceptOnce('MAT-newToonCreated', self.shuffleButton.cleanHistory) @@ -58,6 +46,7 @@ class ColorShop(StateData.StateData): def hideButtons(self): self.parentFrame.hide() + self.advancedFrame.hide() def exit(self): self.ignore('last') @@ -78,67 +67,47 @@ class ColorShop(StateData.StateData): guiRArrowDown = self.gui.find('**/tt_t_gui_mat_arrowDown') guiRArrowDisabled = self.gui.find('**/tt_t_gui_mat_arrowDisabled') shuffleFrame = self.gui.find('**/tt_t_gui_mat_shuffleFrame') - shuffleArrowUp = self.gui.find('**/tt_t_gui_mat_shuffleArrowUp') - shuffleArrowDown = self.gui.find('**/tt_t_gui_mat_shuffleArrowDown') - shuffleArrowRollover = self.gui.find('**/tt_t_gui_mat_shuffleArrowUp') - shuffleArrowDisabled = self.gui.find('**/tt_t_gui_mat_shuffleArrowDisabled') - self.parentFrame = DirectFrame(relief=DGG.RAISED, pos=(0.98, 0, 0.416), frameColor=(1, 0, 0, 0)) - self.parentFrame.setPos(-0.36, 0, -0.5) - self.parentFrame.reparentTo(base.a2dTopRight) + shuffleUp = self.gui.find('**/tt_t_gui_mat_shuffleUp') + shuffleDown = self.gui.find('**/tt_t_gui_mat_shuffleDown') + shuffleImage = (self.gui.find('**/tt_t_gui_mat_shuffleArrowUp'), self.gui.find('**/tt_t_gui_mat_shuffleArrowDown'), self.gui.find('**/tt_t_gui_mat_shuffleArrowUp'), self.gui.find('**/tt_t_gui_mat_shuffleArrowDisabled')) + self.parentFrame = self.getNewFrame() + self.advancedFrame = self.getNewFrame() self.toonFrame = DirectFrame(parent=self.parentFrame, image=shuffleFrame, image_scale=halfButtonInvertScale, relief=None, pos=(0, 0, 0.1), hpr=(0, 0, 0), scale=1.3, frameColor=(1, 1, 1, 1), text=TTLocalizer.ColorShopToon, text_scale=TTLocalizer.CStoonFrame, text_pos=(-0.001, -0.015), text_fg=(1, 1, 1, 1)) - self.allLButton = DirectButton(parent=self.toonFrame, relief=None, image=(shuffleArrowUp, - shuffleArrowDown, - shuffleArrowRollover, - shuffleArrowDisabled), image_scale=halfButtonScale, image1_scale=halfButtonHoverScale, image2_scale=halfButtonHoverScale, pos=(-0.2, 0, 0), command=self.__swapAllColor, extraArgs=[-1]) - self.allRButton = DirectButton(parent=self.toonFrame, relief=None, image=(shuffleArrowUp, - shuffleArrowDown, - shuffleArrowRollover, - shuffleArrowDisabled), image_scale=halfButtonInvertScale, image1_scale=halfButtonInvertHoverScale, image2_scale=halfButtonInvertHoverScale, pos=(0.2, 0, 0), command=self.__swapAllColor, extraArgs=[1]) + self.allLButton = DirectButton(parent=self.toonFrame, relief=None, image=shuffleImage, image_scale=halfButtonScale, image1_scale=halfButtonHoverScale, image2_scale=halfButtonHoverScale, pos=(-0.2, 0, 0), command=self.__swapAllColor, extraArgs=[-1]) + self.allRButton = DirectButton(parent=self.toonFrame, relief=None, image=shuffleImage, image_scale=halfButtonInvertScale, image1_scale=halfButtonInvertHoverScale, image2_scale=halfButtonInvertHoverScale, pos=(0.2, 0, 0), command=self.__swapAllColor, extraArgs=[1]) self.headFrame = DirectFrame(parent=self.parentFrame, image=shuffleFrame, image_scale=halfButtonInvertScale, relief=None, pos=(0, 0, -0.15), hpr=(0, 0, 2), scale=0.9, frameColor=(1, 1, 1, 1), text=TTLocalizer.ColorShopHead, text_scale=0.0625, text_pos=(-0.001, -0.015), text_fg=(1, 1, 1, 1)) - self.headLButton = DirectButton(parent=self.headFrame, relief=None, image=(shuffleArrowUp, - shuffleArrowDown, - shuffleArrowRollover, - shuffleArrowDisabled), image_scale=halfButtonScale, image1_scale=halfButtonHoverScale, image2_scale=halfButtonHoverScale, pos=(-0.2, 0, 0), command=self.__swapHeadColor, extraArgs=[-1]) - self.headRButton = DirectButton(parent=self.headFrame, relief=None, image=(shuffleArrowUp, - shuffleArrowDown, - shuffleArrowRollover, - shuffleArrowDisabled), image_scale=halfButtonInvertScale, image1_scale=halfButtonInvertHoverScale, image2_scale=halfButtonInvertHoverScale, pos=(0.2, 0, 0), command=self.__swapHeadColor, extraArgs=[1]) + self.headLButton = DirectButton(parent=self.headFrame, relief=None, image=shuffleImage, image_scale=halfButtonScale, image1_scale=halfButtonHoverScale, image2_scale=halfButtonHoverScale, pos=(-0.2, 0, 0), command=self.__swapHeadColor, extraArgs=[-1]) + self.headRButton = DirectButton(parent=self.headFrame, relief=None, image=shuffleImage, image_scale=halfButtonInvertScale, image1_scale=halfButtonInvertHoverScale, image2_scale=halfButtonInvertHoverScale, pos=(0.2, 0, 0), command=self.__swapHeadColor, extraArgs=[1]) self.bodyFrame = DirectFrame(parent=self.parentFrame, image=shuffleFrame, image_scale=halfButtonScale, relief=None, pos=(0, 0, -0.35), hpr=(0, 0, -2), scale=0.9, frameColor=(1, 1, 1, 1), text=TTLocalizer.ColorShopBody, text_scale=0.0625, text_pos=(-0.001, -0.015), text_fg=(1, 1, 1, 1)) - self.armLButton = DirectButton(parent=self.bodyFrame, relief=None, image=(shuffleArrowUp, - shuffleArrowDown, - shuffleArrowRollover, - shuffleArrowDisabled), image_scale=halfButtonScale, image1_scale=halfButtonHoverScale, image2_scale=halfButtonHoverScale, pos=(-0.2, 0, 0), command=self.__swapArmColor, extraArgs=[-1]) - self.armRButton = DirectButton(parent=self.bodyFrame, relief=None, image=(shuffleArrowUp, - shuffleArrowDown, - shuffleArrowRollover, - shuffleArrowDisabled), image_scale=halfButtonInvertScale, image1_scale=halfButtonInvertHoverScale, image2_scale=halfButtonInvertHoverScale, pos=(0.2, 0, 0), command=self.__swapArmColor, extraArgs=[1]) + self.armLButton = DirectButton(parent=self.bodyFrame, relief=None, image=shuffleImage, image_scale=halfButtonScale, image1_scale=halfButtonHoverScale, image2_scale=halfButtonHoverScale, pos=(-0.2, 0, 0), command=self.__swapArmColor, extraArgs=[-1]) + self.armRButton = DirectButton(parent=self.bodyFrame, relief=None, image=shuffleImage, image_scale=halfButtonInvertScale, image1_scale=halfButtonInvertHoverScale, image2_scale=halfButtonInvertHoverScale, pos=(0.2, 0, 0), command=self.__swapArmColor, extraArgs=[1]) self.gloveFrame = DirectFrame(parent=self.parentFrame, image=shuffleFrame, image_scale=halfButtonInvertScale, relief=None, pos=(0, 0, -0.55), hpr=(0, 0, 2), scale=0.9, frameColor=(1, 1, 1, 1), text=TTLocalizer.ColorShopGloves, text_scale=0.0625, text_pos=(-0.001, -0.015), text_fg=(1, 1, 1, 1)) - self.gloveLButton = DirectButton(parent=self.gloveFrame, relief=None, image=(shuffleArrowUp, - shuffleArrowDown, - shuffleArrowRollover, - shuffleArrowDisabled), image_scale=halfButtonScale, image1_scale=halfButtonHoverScale, image2_scale=halfButtonHoverScale, pos=(-0.2, 0, 0), command=self.__swapGloveColor, extraArgs=[-1]) - self.gloveRButton = DirectButton(parent=self.gloveFrame, relief=None, image=(shuffleArrowUp, - shuffleArrowDown, - shuffleArrowRollover, - shuffleArrowDisabled), image_scale=halfButtonInvertScale, image1_scale=halfButtonInvertHoverScale, image2_scale=halfButtonInvertHoverScale, pos=(0.2, 0, 0), command=self.__swapGloveColor, extraArgs=[1]) + self.gloveLButton = DirectButton(parent=self.gloveFrame, relief=None, image=shuffleImage, image_scale=halfButtonScale, image1_scale=halfButtonHoverScale, image2_scale=halfButtonHoverScale, pos=(-0.2, 0, 0), command=self.__swapGloveColor, extraArgs=[-1]) + self.gloveRButton = DirectButton(parent=self.gloveFrame, relief=None, image=shuffleImage, image_scale=halfButtonInvertScale, image1_scale=halfButtonInvertHoverScale, image2_scale=halfButtonInvertHoverScale, pos=(0.2, 0, 0), command=self.__swapGloveColor, extraArgs=[1]) self.legsFrame = DirectFrame(parent=self.parentFrame, image=shuffleFrame, image_scale=halfButtonInvertScale, relief=None, pos=(0, 0, -0.75), hpr=(0, 0, -2), scale=0.9, frameColor=(1, 1, 1, 1), text=TTLocalizer.ColorShopLegs, text_scale=0.0625, text_pos=(-0.001, -0.015), text_fg=(1, 1, 1, 1)) - self.legLButton = DirectButton(parent=self.legsFrame, relief=None, image=(shuffleArrowUp, - shuffleArrowDown, - shuffleArrowRollover, - shuffleArrowDisabled), image_scale=halfButtonScale, image1_scale=halfButtonHoverScale, image2_scale=halfButtonHoverScale, pos=(-0.2, 0, 0), command=self.__swapLegColor, extraArgs=[-1]) - self.legRButton = DirectButton(parent=self.legsFrame, relief=None, image=(shuffleArrowUp, - shuffleArrowDown, - shuffleArrowRollover, - shuffleArrowDisabled), image_scale=halfButtonInvertScale, image1_scale=halfButtonInvertHoverScale, image2_scale=halfButtonInvertHoverScale, pos=(0.2, 0, 0), command=self.__swapLegColor, extraArgs=[1]) + self.legLButton = DirectButton(parent=self.legsFrame, relief=None, image=shuffleImage, image_scale=halfButtonScale, image1_scale=halfButtonHoverScale, image2_scale=halfButtonHoverScale, pos=(-0.2, 0, 0), command=self.__swapLegColor, extraArgs=[-1]) + self.legRButton = DirectButton(parent=self.legsFrame, relief=None, image=shuffleImage, image_scale=halfButtonInvertScale, image1_scale=halfButtonInvertHoverScale, image2_scale=halfButtonInvertHoverScale, pos=(0.2, 0, 0), command=self.__swapLegColor, extraArgs=[1]) + self.advancedButton = DirectButton(parent=self.parentFrame, relief=None, image=(shuffleUp, shuffleDown, shuffleUp), image_scale=(-0.8, 0.6, 0.6), image1_scale=(-0.83, 0.6, 0.6), image2_scale=(-0.83, 0.6, 0.6), text=TTLocalizer.ColorAdvanced, text_font=ToontownGlobals.getInterfaceFont(), text_scale=TTLocalizer.SBshuffleBtn, text_pos=(0, -0.02), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), pos=(0, 0, -1.15), command=self.popupAdvancedMenu) + self.basicButton = DirectButton(parent=self.advancedFrame, relief=None, image=(shuffleUp, shuffleDown, shuffleUp), image_scale=(-0.8, 0.6, 0.6), image1_scale=(-0.83, 0.6, 0.6), image2_scale=(-0.83, 0.6, 0.6), text=TTLocalizer.ColorBasic, text_font=ToontownGlobals.getInterfaceFont(), text_scale=TTLocalizer.SBshuffleBtn, text_pos=(0, -0.02), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), pos=(0, 0, -1.15), command=self.popupBasicMenu) + self.pickContainer = DirectFrame(parent=self.advancedFrame, relief=None, pos=(-0.4, 0, -0.5), image='phase_3/maps/color_picker_container.png', scale=(0.7, 0.5, 0.55)) + self.pickContainer.setTransparency(True) + self.pickImage = PNMImage(int((ToontownGlobals.COLOR_SATURATION_MAX - ToontownGlobals.COLOR_SATURATION_MIN) * 100), int((ToontownGlobals.COLOR_VALUE_MAX - ToontownGlobals.COLOR_VALUE_MIN) * 100)) + self.hueSlider = DirectSlider(parent=self.advancedFrame, relief=None, image='phase_3/maps/color_picker_hue.jpg', scale=0.3, pos=(-0.05, 0, -0.43), image_scale=(0.1, 1.0, 1.0), pageSize=5, orientation=DGG.VERTICAL, command=self.__chooseHue) + self.pickButton = DirectButton(parent=self.advancedFrame, relief=None, image='phase_3/maps/color_picker_empty.png', scale=0.3, pos=(-0.45, 0, -0.43), frameColor=(1, 1, 1, 0.1), pressEffect=0) + self.pickButton.bind(DGG.B1CLICK, self.__pickColor) + self.partsFrame = DirectFrame(parent=self.advancedFrame, image=shuffleFrame, image_scale=halfButtonInvertScale, relief=None, pos=(-0.395, 0, -0.85), hpr=(0, 0, -2), scale=0.9, frameColor=(1, 1, 1, 1), text=TTLocalizer.ColorAll, text_scale=0.0625, text_pos=(-0.001, -0.015), text_fg=(1, 1, 1, 1)) + self.partLButton = DirectButton(parent=self.partsFrame, relief=None, image=shuffleImage, image_scale=halfButtonScale, image1_scale=halfButtonHoverScale, image2_scale=halfButtonHoverScale, pos=(-0.2, 0, 0), state=DGG.DISABLED, command=self.__swapPart, extraArgs=[-1]) + self.partRButton = DirectButton(parent=self.partsFrame, relief=None, image=shuffleImage, image_scale=halfButtonInvertScale, image1_scale=halfButtonInvertHoverScale, image2_scale=halfButtonInvertHoverScale, pos=(0.2, 0, 0), command=self.__swapPart, extraArgs=[1]) self.parentFrame.hide() + self.advancedFrame.hide() self.shuffleFetchMsg = 'ColorShopShuffle' self.shuffleButton = ShuffleButton.ShuffleButton(self, self.shuffleFetchMsg) - return def unload(self): self.gui.removeNode() del self.gui self.parentFrame.destroy() + self.advancedFrame.destroy() self.toonFrame.destroy() self.headFrame.destroy() self.bodyFrame.destroy() @@ -153,7 +122,16 @@ class ColorShop(StateData.StateData): self.legRButton.destroy() self.allLButton.destroy() self.allRButton.destroy() + self.advancedButton.destroy() + self.basicButton.destroy() + self.pickContainer.destroy() + self.hueSlider.destroy() + self.pickButton.destroy() + self.partsFrame.destroy() + self.partLButton.destroy() + self.partRButton.destroy() del self.parentFrame + del self.advancedFrame del self.toonFrame del self.headFrame del self.bodyFrame @@ -168,11 +146,76 @@ class ColorShop(StateData.StateData): del self.legRButton del self.allLButton del self.allRButton + del self.advancedButton + del self.basicButton + del self.pickContainer + del self.hueSlider + del self.pickButton + del self.partsFrame + del self.partLButton + del self.partRButton self.shuffleButton.unload() self.ignore('MAT-newToonCreated') + + def getNewFrame(self): + frame = DirectFrame(relief=DGG.RAISED, pos=(0.98, 0, 0.416), frameColor=(1, 0, 0, 0)) + frame.setPos(-0.36, 0, -0.5) + frame.reparentTo(base.a2dTopRight) + return frame + def popupAdvancedMenu(self): + self.parentFrame.hide() + self.advancedFrame.show() + + def popupBasicMenu(self): + self.parentFrame.show() + self.advancedFrame.hide() + + def calcRelative(self, value, baseMin, baseMax, limitMin, limitMax): + return ((limitMax - limitMin) * (value - baseMin) / (baseMax - baseMin)) + limitMin + + def __chooseHue(self): + for x in xrange(self.pickImage.getXSize()): + for y in xrange(self.pickImage.getYSize()): + self.pickImage.setXel(x, y, colorsys.hsv_to_rgb(self.hueSlider['value'], (x / 100.0) + ToontownGlobals.COLOR_SATURATION_MIN, (y / 100.0) + ToontownGlobals.COLOR_VALUE_MIN)) + + texture = Texture() + texture.load(self.pickImage) + self.pickButton['image'] = texture + + def __pickColor(self, pos): + x, y = pos.getMouse() + win_w, win_h = base.win.getSize() + + if win_w < win_h: + y *= 1. * win_h / win_w + else: + x *= 1. * win_w / win_h + + x -= self.pickButton.getX(aspect2d) + y -= self.pickButton.getZ(aspect2d) + image_scale = self.pickButton['image_scale'] + x = (.5 + x / (2. * self.pickButton.getSx(aspect2d) * image_scale[0])) + y = (.5 + y / -(2. * self.pickButton.getSz(aspect2d) * image_scale[2])) + rgb = colorsys.hsv_to_rgb(self.hueSlider['value'], self.calcRelative(x, 0.0, 1.0, 0.36, 0.7), self.calcRelative(y, 0.0, 1.0, 0.5, 0.8)) + (1,) + if self.partChoice in (0, 1): + self.dna.headColor = rgb + if self.partChoice in (0, 2): + self.dna.armColor = rgb + if self.partChoice in (0, 3): + self.dna.gloveColor = rgb + if self.partChoice in (0, 4): + self.dna.legColor = rgb + self.toon.swapToonColor(self.dna) + + def __swapPart(self, offset): + self.partChoice += offset + self.partLButton['state'] = DGG.DISABLED if self.partChoice <= 0 else DGG.NORMAL + self.partRButton['state'] = DGG.DISABLED if self.partChoice >= len(self.allParts) - 1 else DGG.NORMAL + self.partsFrame['text'] = self.allParts[self.partChoice] + def __swapAllColor(self, offset): - colorList = self.getGenderColorList(self.dna) + colorList = self.getColorList() length = len(colorList) choice = (self.headChoice + offset) % length self.__updateScrollButtons(choice, length, self.allLButton, self.allRButton) @@ -185,7 +228,7 @@ class ColorShop(StateData.StateData): self.__swapLegColor(choice - oldLegColorIndex) def __swapHeadColor(self, offset): - colorList = self.getGenderColorList(self.dna) + colorList = self.getColorList() length = len(colorList) self.headChoice = (self.headChoice + offset) % length self.__updateScrollButtons(self.headChoice, length, self.headLButton, self.headRButton) @@ -194,7 +237,7 @@ class ColorShop(StateData.StateData): self.toon.swapToonColor(self.dna) def __swapArmColor(self, offset): - colorList = self.getGenderColorList(self.dna) + colorList = self.getColorList() length = len(colorList) self.armChoice = (self.armChoice + offset) % length self.__updateScrollButtons(self.armChoice, length, self.armLButton, self.armRButton) @@ -203,7 +246,7 @@ class ColorShop(StateData.StateData): self.toon.swapToonColor(self.dna) def __swapGloveColor(self, offset): - colorList = self.getGenderColorList(self.dna) + colorList = self.getColorList() length = len(colorList) self.gloveChoice = (self.gloveChoice + offset) % length self.__updateScrollButtons(self.gloveChoice, length, self.gloveLButton, self.gloveRButton) @@ -212,7 +255,7 @@ class ColorShop(StateData.StateData): self.toon.swapToonColor(self.dna) def __swapLegColor(self, offset): - colorList = self.getGenderColorList(self.dna) + colorList = self.getColorList() length = len(colorList) self.legChoice = (self.legChoice + offset) % length self.__updateScrollButtons(self.legChoice, length, self.legLButton, self.legRButton) @@ -240,25 +283,27 @@ class ColorShop(StateData.StateData): def changeColor(self): self.notify.debug('Entering changeColor') - colorList = self.getGenderColorList(self.dna) + colorList = self.getColorList() newChoice = self.shuffleButton.getCurrChoice() - newHeadColorIndex = colorList.index(newChoice[0]) - newArmColorIndex = colorList.index(newChoice[1]) - newGloveColorIndex = colorList.index(newChoice[2]) - newLegColorIndex = colorList.index(newChoice[3]) - oldHeadColorIndex = colorList.index(self.toon.style.headColor) - oldArmColorIndex = colorList.index(self.toon.style.armColor) - oldGloveColorIndex = colorList.index(self.toon.style.gloveColor) - oldLegColorIndex = colorList.index(self.toon.style.legColor) - self.__swapHeadColor(newHeadColorIndex - oldHeadColorIndex) + newHeadColorIndex = self.indexOf(colorList, newChoice[0], 25) + newArmColorIndex = self.indexOf(colorList, newChoice[1], 25) + newGloveColorIndex = self.indexOf(colorList, newChoice[2], 0) + newLegColorIndex = self.indexOf(colorList, newChoice[3], 25) + self.__swapHeadColor(newHeadColorIndex - self.headChoice) if self.colorAll: - self.__swapArmColor(newHeadColorIndex - oldArmColorIndex) - self.__swapGloveColor(newHeadColorIndex - oldGloveColorIndex) - self.__swapLegColor(newHeadColorIndex - oldLegColorIndex) + self.__swapArmColor(newHeadColorIndex - self.armChoice) + self.__swapGloveColor(newHeadColorIndex - self.gloveChoice) + self.__swapLegColor(newHeadColorIndex - self.legChoice) else: - self.__swapArmColor(newArmColorIndex - oldArmColorIndex) - self.__swapGloveColor(newGloveColorIndex - oldGloveColorIndex) - self.__swapLegColor(newLegColorIndex - oldLegColorIndex) + self.__swapArmColor(newArmColorIndex - self.armChoice) + self.__swapGloveColor(newGloveColorIndex - self.gloveChoice) + self.__swapLegColor(newLegColorIndex - self.legChoice) + + def indexOf(self, list, item, default): + try: + return list.index(item) + except: + return default def getCurrToonSetting(self): return [self.dna.headColor, self.dna.armColor, self.dna.gloveColor, self.dna.legColor] diff --git a/toontown/makeatoon/NameShop.py b/toontown/makeatoon/NameShop.py index 3755cf9a..9ef6b73b 100755 --- a/toontown/makeatoon/NameShop.py +++ b/toontown/makeatoon/NameShop.py @@ -673,7 +673,7 @@ class NameShop(StateData.StateData): self.nameResult['text'] = self.names[0] def findTempName(self): - colorstring = TTLocalizer.NumToColor[self.toon.style.headColor] + colorstring = TTLocalizer.ColorfulToon animaltype = TTLocalizer.AnimalToSpecies[self.toon.style.getAnimal()] tempname = colorstring + ' ' + animaltype if not TTLocalizer.NScolorPrecede: diff --git a/toontown/makeatoon/ShuffleButton.py b/toontown/makeatoon/ShuffleButton.py index 7bd81a58..47168fbc 100755 --- a/toontown/makeatoon/ShuffleButton.py +++ b/toontown/makeatoon/ShuffleButton.py @@ -68,7 +68,6 @@ class ShuffleButton: del self.shuffleBtn del self.incBtn del self.decBtn - return def showButtons(self): self.shuffleFrame.show() diff --git a/toontown/minigame/ClerkPurchase.py b/toontown/minigame/ClerkPurchase.py index 31cf7552..6e9e06a5 100755 --- a/toontown/minigame/ClerkPurchase.py +++ b/toontown/minigame/ClerkPurchase.py @@ -22,7 +22,6 @@ class ClerkPurchase(PurchaseBase): self.timer.reparentTo(self.frame) self.timer.posInTopRightCorner() purchaseModels.removeNode() - return def unload(self): PurchaseBase.unload(self) @@ -36,7 +35,7 @@ class ClerkPurchase(PurchaseBase): self.handleDone(0) def __timerExpired(self): - self.handleDone(0) + self.handleDone(2) def enterPurchase(self): PurchaseBase.enterPurchase(self) diff --git a/toontown/minigame/DistributedCannonGame.py b/toontown/minigame/DistributedCannonGame.py index 52b3a451..873e7972 100755 --- a/toontown/minigame/DistributedCannonGame.py +++ b/toontown/minigame/DistributedCannonGame.py @@ -112,7 +112,7 @@ class DistributedCannonGame(DistributedMinigame): self.jarImage.reparentTo(hidden) self.rewardPanel = DirectLabel(parent=hidden, relief=None, pos=(-0.173, 0.0, -0.55), 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.loadMusic('phase_4/audio/bgm/MG_cannon_game.ogg') + self.music = base.loadMusic('phase_4/audio/bgm/MG_cannon_game_tug.ogg') self.sndCannonMove = base.loadSfx('phase_4/audio/sfx/MG_cannon_adjust.ogg') self.sndCannonFire = base.loadSfx('phase_4/audio/sfx/MG_cannon_fire_alt.ogg') self.sndHitGround = base.loadSfx('phase_4/audio/sfx/MG_cannon_hit_dirt.ogg') diff --git a/toontown/minigame/DistributedPatternGame.py b/toontown/minigame/DistributedPatternGame.py index aabf128c..30ce5942 100755 --- a/toontown/minigame/DistributedPatternGame.py +++ b/toontown/minigame/DistributedPatternGame.py @@ -122,13 +122,13 @@ class DistributedPatternGame(DistributedMinigame): minnieX.removeNode() minnieCircle.removeNode() matchingGameGui.removeNode() - self.blinky = NPCToons.createLocalNPC(7010) - self.blinky.reparentTo(hidden) + self.toon = NPCToons.createLocalNPC(7010) + self.toon.reparentTo(hidden) self.backRowHome = Point3(3, 11, 0) self.backRowXSpacing = 1.8 self.frontRowHome = Point3(0, 18, 0) self.frontRowXSpacing = 3.0 - self.stdNumDanceStepPingFrames = self.blinky.getNumFrames(self.toonAnimNames[0]) + self.stdNumDanceStepPingFrames = self.toon.getNumFrames(self.toonAnimNames[0]) self.stdNumDanceStepPingPongFrames = self.__numPingPongFrames(self.stdNumDanceStepPingFrames) self.buttonPressDelayPercent = (self.stdNumDanceStepPingFrames - 1.0) / self.stdNumDanceStepPingPongFrames self.animPlayRates = [] @@ -185,8 +185,8 @@ class DistributedPatternGame(DistributedMinigame): del self.statusBalls self.room.removeNode() del self.room - self.blinky.delete() - del self.blinky + self.toon.delete() + del self.toon self.removeChildGameFSM(self.gameFSM) del self.gameFSM @@ -238,19 +238,19 @@ class DistributedPatternGame(DistributedMinigame): self.arrowDict['lt'][k].setPos(0, 0, 1) self.formatStatusBalls(self.arrowDict['lt'][2], self.lt.nametag3d) - self.blinky.reparentTo(render) - self.blinky.setPos(-1.6, 20, 0) - self.blinky.setScale(1) - self.makeToonLookatCamera(self.blinky) - self.blinky.loop('neutral') - self.blinky.nametag.manage(base.marginManager) - self.blinky.nametag.getNametag3d().setChatWordwrap(8) + self.toon.reparentTo(render) + self.toon.setPos(-1.6, 20, 0) + self.toon.setScale(1) + self.makeToonLookatCamera(self.toon) + self.toon.loop('neutral') + self.toon.nametag.manage(base.marginManager) + self.toon.nametag.getNametag3d().setChatWordwrap(8) self.arrowDict['m'] = [self.arrows.pop(), self.xs.pop()] for k in xrange(0, 2): self.arrowDict['m'][k].setBillboardAxis() self.arrowDict['m'][k].setBin('fixed', 100) self.arrowDict['m'][k].setColor(self.arrowColor) - self.arrowDict['m'][k].reparentTo(self.blinky.nametag3d) + self.arrowDict['m'][k].reparentTo(self.toon.nametag3d) self.arrowDict['m'][k].setScale(4) self.arrowDict['m'][k].setPos(0, 0, 1.7) @@ -267,9 +267,9 @@ class DistributedPatternGame(DistributedMinigame): del self.arrowKeys self.room.reparentTo(hidden) self.roundText.hide() - self.blinky.nametag.unmanage(base.marginManager) - self.blinky.stop() - self.blinky.reparentTo(hidden) + self.toon.nametag.unmanage(base.marginManager) + self.toon.stop() + self.toon.reparentTo(hidden) self.lt.setScale(1) for avId in self.remoteAvIdList: toon = self.getAvatar(avId) @@ -387,7 +387,7 @@ class DistributedPatternGame(DistributedMinigame): def getDanceStepDuration(self): numFrames = self.stdNumDanceStepPingPongFrames - return numFrames / abs(self.animPlayRate * self.toonAnimSpeedMult[self.toonAnimNames[0]] * self.blinky.getFrameRate(self.toonAnimNames[0])) + return numFrames / abs(self.animPlayRate * self.toonAnimSpeedMult[self.toonAnimNames[0]] * self.toon.getFrameRate(self.toonAnimNames[0])) def __getDanceStepAnimTrack(self, toon, anim, speedScale): numFrames = toon.getNumFrames(anim) @@ -516,12 +516,12 @@ class DistributedPatternGame(DistributedMinigame): index = self.avIdList.index(avId) return self.__getRowPos(self.frontRowHome, self.frontRowXSpacing, index, len(self.avIdList)) - def __setBlinkyChat(self, str, giggle): + def __setToonChat(self, str, giggle): str = str.replace('%s', self.getAvatar(self.localAvId).getName()) - self.blinky.setChatAbsolute(str, CFSpeech) + self.toon.setChatAbsolute(str, CFSpeech) - def __clearBlinkyChat(self): - self.blinky.clearChat() + def __clearToonChat(self): + self.toon.clearChat() def enterOff(self): self.notify.debug('enterOff') @@ -557,13 +557,13 @@ class DistributedPatternGame(DistributedMinigame): toon.setPlayRate(self.animPlayRate * self.toonAnimSpeedMult[anim], anim) for anim in self.toonAnimNames: - self.blinky.setPlayRate(self.animPlayRate * self.toonAnimSpeedMult[anim], anim) + self.toon.setPlayRate(self.animPlayRate * self.toonAnimSpeedMult[anim], anim) text = self.strWatch - danceTrack = self.getDanceSequenceAnimTrack(self.blinky, self.__serverPattern) + danceTrack = self.getDanceSequenceAnimTrack(self.toon, self.__serverPattern) arrowTrack = self.getDanceArrowAnimTrack('m', self.__serverPattern, 0) soundTrack = self.getDanceSequenceButtonSoundTrack(self.__serverPattern) - self.showTrack = Sequence(Func(self.__setBlinkyChat, text, 1), Wait(0.5), Parallel(danceTrack, soundTrack, arrowTrack), Wait(0.2), Func(self.__clearBlinkyChat), Func(self.gameFSM.request, 'getUserInput')) + self.showTrack = Sequence(Func(self.__setToonChat, text, 1), Wait(0.5), Parallel(danceTrack, soundTrack, arrowTrack), Wait(0.2), Func(self.__clearToonChat), Func(self.gameFSM.request, 'getUserInput')) self.showTrack.start() def exitShowServerPattern(self): @@ -605,7 +605,7 @@ class DistributedPatternGame(DistributedMinigame): self.showStatusBalls(avId) self.__otherToonIndex[avId] = 0 - self.setupTrack = Sequence(Func(self.__setBlinkyChat, 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.__clearBlinkyChat), Func(self.setText, self.roundText, ' '), Func(self.roundText.setScale, 0.12), Func(self.setTextFG, self.roundText, self.normalTextColor)) + self.setupTrack = Sequence(Func(self.__setToonChat, 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.__clearToonChat), Func(self.setText, self.roundText, ' '), Func(self.roundText.setScale, 0.12), Func(self.setTextFG, self.roundText, self.normalTextColor)) self.setupTrack.start() return @@ -685,7 +685,7 @@ class DistributedPatternGame(DistributedMinigame): self.proceedTrack.pause() del self.setupTrack del self.proceedTrack - self.__clearBlinkyChat() + self.__clearToonChat() def enterWaitForPlayerPatterns(self): self.notify.debug('enterWaitForPlayerPatterns') @@ -751,7 +751,7 @@ class DistributedPatternGame(DistributedMinigame): sound = self.incorrectSound text = self.strWrong soundTrack = Sequence(Func(base.playSfx, sound), Wait(1.6)) - textTrack = Sequence(Wait(0.2), Func(self.__setBlinkyChat, text, 0), Wait(1.3), Func(self.__clearBlinkyChat)) + textTrack = Sequence(Wait(0.2), Func(self.__setToonChat, text, 0), Wait(1.3), Func(self.__clearToonChat)) self.playBackPatternsTrack = Sequence(Parallel(soundTrack, textTrack, jumpTrack), Func(self.gameFSM.request, 'checkGameOver')) self.playBackPatternsTrack.start() @@ -775,9 +775,9 @@ class DistributedPatternGame(DistributedMinigame): delay = 2.2 if self.celebrate: text = TTLocalizer.PatternGameImprov - self.__winTrack = Sequence(Func(self.__setBlinkyChat, text, 1), Func(base.playSfx, self.perfectSound), Sequence(self.returnCelebrationIntervals(1)), Sequence(self.returnCelebrationIntervals(0)), Func(self.__clearBlinkyChat), Func(self.gameOver)) + self.__winTrack = Sequence(Func(self.__setToonChat, text, 1), Func(base.playSfx, self.perfectSound), Sequence(self.returnCelebrationIntervals(1)), Sequence(self.returnCelebrationIntervals(0)), Func(self.__clearToonChat), Func(self.gameOver)) else: - self.__winTrack = Sequence(Func(self.__setBlinkyChat, text, 1), Func(base.playSfx, sound), Wait(delay), Func(self.__clearBlinkyChat), Func(self.gameOver)) + self.__winTrack = Sequence(Func(self.__setToonChat, text, 1), Func(base.playSfx, sound), Wait(delay), Func(self.__clearToonChat), Func(self.gameOver)) self.__winTrack.start() return diff --git a/toontown/minigame/DistributedTugOfWarGame.py b/toontown/minigame/DistributedTugOfWarGame.py index 4f755987..650eb7ea 100755 --- a/toontown/minigame/DistributedTugOfWarGame.py +++ b/toontown/minigame/DistributedTugOfWarGame.py @@ -24,7 +24,7 @@ from direct.task.Task import Task from otp.nametag import NametagGlobals class DistributedTugOfWarGame(DistributedMinigame): - bgm = 'phase_4/audio/bgm/MG_tug_o_war.ogg' + bgm = 'phase_4/audio/bgm/MG_cannon_game_tug.ogg' toonAnimNames = ['neutral', 'tug-o-war', 'slip-forward', @@ -163,7 +163,6 @@ class DistributedTugOfWarGame(DistributedMinigame): def unload(self): self.notify.debug('unload') DistributedMinigame.unload(self) - del self.lt self.timer.destroy() del self.timer self.room.removeNode() @@ -250,7 +249,6 @@ class DistributedTugOfWarGame(DistributedMinigame): 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) diff --git a/toontown/minigame/MinigameCreatorAI.py b/toontown/minigame/MinigameCreatorAI.py index 877e4255..154f98a5 100755 --- a/toontown/minigame/MinigameCreatorAI.py +++ b/toontown/minigame/MinigameCreatorAI.py @@ -20,7 +20,7 @@ import DistributedTwoDGameAI import DistributedVineGameAI from otp.ai.MagicWordGlobal import * from toontown.toonbase import ToontownGlobals - +from toontown.uberdog import TopToonsGlobals simbase.forcedMinigameId = simbase.config.GetInt('force-minigame', 0) RequestMinigame = {} @@ -84,6 +84,8 @@ def createMinigame(air, playerArray, trolleyZone, minigameZone=None, toon = simbase.air.doId2do.get(doId) if toon is not None: toons.append(toon) + for toon in toons: + messenger.send('topToonsManager-event', [toon.doId, TopToonsGlobals.CAT_TROLLEY, 1]) for toon in toons: simbase.air.questManager.toonPlayedMinigame(toon, toons) retVal = {} diff --git a/toontown/minigame/PurchaseBase.py b/toontown/minigame/PurchaseBase.py index d8b3e7a1..a5f76d8b 100755 --- a/toontown/minigame/PurchaseBase.py +++ b/toontown/minigame/PurchaseBase.py @@ -100,7 +100,7 @@ class PurchaseBase(StateData.StateData): return Task.done def handleDone(self, playAgain): - messenger.send(self.doneEvent) + messenger.send(self.doneEvent, [playAgain]) def enter(self): self.fsm.request('purchase') diff --git a/toontown/minigame/TwoDEnemy.py b/toontown/minigame/TwoDEnemy.py index ad62545f..a311f917 100755 --- a/toontown/minigame/TwoDEnemy.py +++ b/toontown/minigame/TwoDEnemy.py @@ -11,7 +11,7 @@ from toontown.battle.BattleProps import * from toontown.battle import MovieUtil from toontown.battle import BattleParticles, BattleProps from direct.particles import ParticleEffect -import math +import math, random COLOR_RED = VBase4(1, 0, 0, 0.3) class TwoDEnemy(DirectObject): @@ -232,7 +232,7 @@ class TwoDEnemy(DirectObject): treasureSpawnPoint = Point3(self.suit.getX(), self.suit.getY(), self.suit.getZ() + self.suit.height / 2.0) gearPoint = Point3(0, 0, self.suit.height / 2.0 + 2.0) spinningSound = base.loadSfx('phase_3.5/audio/sfx/Cog_Death.ogg') - deathSound = base.loadSfx('phase_3.5/audio/sfx/ENC_cogfall_apart.ogg') + deathSound = base.loadSfx('phase_3.5/audio/sfx/ENC_cogfall_apart_%s.ogg' % random.randint(1, 6)) smallGears = BattleParticles.createParticleEffect(file='gearExplosionSmall') singleGear = BattleParticles.createParticleEffect('GearExplosion', numParticles=1) smallGearExplosion = BattleParticles.createParticleEffect('GearExplosion', numParticles=10) diff --git a/toontown/parties/DistributedPartyAI.py b/toontown/parties/DistributedPartyAI.py index 7e4cd6ec..c0ecf45b 100755 --- a/toontown/parties/DistributedPartyAI.py +++ b/toontown/parties/DistributedPartyAI.py @@ -149,6 +149,7 @@ class DistributedPartyAI(DistributedObjectAI): def _removeAvatar(self, avId): if avId in self.avIdsAtParty: - print 'REMOVE FROM PARTTY!' + print 'REMOVE FROM PARTY!' self.air.globalPartyMgr.d_toonLeftParty(self.info.get('partyId', 0), avId) self.avIdsAtParty.remove(avId) +#Thanks Fooster for the typo fix diff --git a/toontown/parties/DistributedPartyTeamActivity.py b/toontown/parties/DistributedPartyTeamActivity.py index fb78ed5d..7324277f 100755 --- a/toontown/parties/DistributedPartyTeamActivity.py +++ b/toontown/parties/DistributedPartyTeamActivity.py @@ -20,7 +20,7 @@ class DistributedPartyTeamActivity(DistributedPartyActivity): self._minPlayersPerTeam = 0 self._duration = 0 self._startDelay = base.config.GetFloat('party-team-activity-start-delay', startDelay) - self._willBalanceTeams = balanceTeams + self._willBalanceTeams = False # balanceTeams self._currentStatus = '' return @@ -207,7 +207,7 @@ class DistributedPartyTeamActivity(DistributedPartyActivity): switchers = list(set(oldLeftTeam) & set(newRightTeam)) + list(set(oldRightTeam) & set(newLeftTeam)) else: switchers = [] - for i in xrange(len(PartyGlobals.TeamActivityTeams)): + for i in range(len(PartyGlobals.TeamActivityTeams)): persistentToons = set(oldToonIds[i]) & set(newToonIds[i]) for toonId in persistentToons: if oldToonIds[i].index(toonId) != newToonIds[i].index(toonId): @@ -240,7 +240,7 @@ class DistributedPartyTeamActivity(DistributedPartyActivity): return len(self.toonIds[team]) def getTeam(self, toonId): - for i in xrange(len(PartyGlobals.TeamActivityTeams)): + for i in range(len(PartyGlobals.TeamActivityTeams)): if self.toonIds[i].count(toonId) > 0: return i else: diff --git a/toontown/parties/DistributedPartyTeamActivityAI.py b/toontown/parties/DistributedPartyTeamActivityAI.py index af3ecd30..abdfc6de 100755 --- a/toontown/parties/DistributedPartyTeamActivityAI.py +++ b/toontown/parties/DistributedPartyTeamActivityAI.py @@ -1,35 +1,216 @@ from direct.directnotify import DirectNotifyGlobal -from toontown.parties.DistributedPartyActivityAI import DistributedPartyActivityAI +from direct.distributed.ClockDelta import globalClockDelta + +from DistributedPartyActivityAI import DistributedPartyActivityAI +from activityFSMs import TeamActivityAIFSM +import PartyGlobals + +''' +dclass DistributedPartyTeamActivity : DistributedPartyActivity { + toonJoinRequest(uint8(0-1)) airecv clsend; + toonExitRequest(uint8(0-1)) airecv clsend; + toonSwitchTeamRequest() airecv clsend; + setPlayersPerTeam(uint8, uint8) broadcast required; + setDuration(uint8) broadcast required; + setCanSwitchTeams(bool) broadcast required; + setState(string, int16, uint32) broadcast ram; + setToonsPlaying(uint32 [0-8], uint32 [0-8]) required broadcast ram; + setAdvantage(uint16/100); + switchTeamRequestDenied(uint8); +}; +''' + +'''self.defaultTransitions = {'WaitForEnough': ['WaitToStart'], + 'WaitToStart': ['WaitForEnough', 'WaitClientsReady'], + 'WaitClientsReady': ['WaitForEnough', 'Active'], + 'Active': ['WaitForEnough', 'Conclusion'], + 'Conclusion': ['WaitForEnough']}''' class DistributedPartyTeamActivityAI(DistributedPartyActivityAI): notify = DirectNotifyGlobal.directNotify.newCategory("DistributedPartyTeamActivityAI") + forbidTeamChanges = False + startDelay = PartyGlobals.TeamActivityStartDelay + + def __init__(self, air, parent, activityTuple): + self.toonIds = ([], []) + self.responses = set() + self.fsm = TeamActivityAIFSM(self) + + DistributedPartyActivityAI.__init__(self, air, parent, activityTuple) + + def announceGenerate(self): + self.b_setState('WaitForEnough') + DistributedPartyActivityAI.announceGenerate(self) - def toonJoinRequest(self, todo0): - pass + def toonJoinRequest(self, team): + av = self._getCaller() + if not av: + return + + if not self.fsm.state in ('WaitForEnough', 'WaitToStart'): + self.sendUpdateToAvatarId(av.doId, 'joinTeamRequestDenied', [PartyGlobals.DenialReasons.Default]) + return + + if len(self.toonIds[team]) >= self.getPlayersPerTeam()[1]: + self.sendUpdateToAvatarId(av.doId, 'joinTeamRequestDenied', [PartyGlobals.DenialReasons.Full]) + return + + if av.doId in self.toonsPlaying: + self.air.writeServerEvent('suspicious', av.doId, 'tried to join party team activity again!') + self.sendUpdateToAvatarId(av.doId, 'joinTeamRequestDenied', [PartyGlobals.DenialReasons.Default]) + return - def toonExitRequest(self, todo0): - pass + # idgaf if they exit unexpectedly in this case + self.toonIds[team].append(av.doId) + DistributedPartyActivityAI.toonJoinRequest(self) + self.__update() + + def toonExitRequest(self, team): + av = self._getCaller() + if not av: + return + + if not self.fsm.state in ('WaitForEnough', 'WaitToStart'): + self.sendUpdateToAvatarId(av.doId, 'exitRequestDenied', [PartyGlobals.DenialReasons.Default]) + return + + if not (av.doId in self.toonIds[0] or av.doId in self.toonIds[1]): + self.air.writeServerEvent('suspicious', avId, 'tried to switch DistributedPartyActivityAI team, but not in one') + self.sendUpdateToAvatarId(av.doId, 'exitRequestDenied', [PartyGlobals.DenialReasons.Default]) + return + + currentTeam = (1, 0)[av.doId in self.toonIds[0]] + self.toonIds[currentTeam].remove(av.doId) + + DistributedPartyActivityAI.toonExitRequest(self) + self.__update() def toonSwitchTeamRequest(self): - pass + av = self._getCaller() + if not av: + return + + if not self.getCanSwitchTeams(): + self.air.writeServerEvent('suspicious', avId, 'tried to switch DistributedPartyActivityAI team in bad time') + self.sendUpdateToAvatarId(av.doId, 'switchTeamRequestDenied', [PartyGlobals.DenialReasons.Default]) + return + + if not (av.doId in self.toonIds[0] or av.doId in self.toonIds[1]): + self.air.writeServerEvent('suspicious', avId, 'tried to switch DistributedPartyActivityAI team, but not in one') + self.sendUpdateToAvatarId(av.doId, 'switchTeamRequestDenied', [PartyGlobals.DenialReasons.Default]) + return + + currentTeam = (1, 0)[av.doId in self.toonIds[0]] + otherTeam = (1, 0)[currentTeam] + + if len(self.toonIds[otherTeam]) >= self.getPlayersPerTeam()[1]: + self.sendUpdateToAvatarId(av.doId, 'switchTeamRequestDenied', [PartyGlobals.DenialReasons.Full]) + return + + self.toonIds[currentTeam].remove(av.doId) + self.toonIds[otherTeam].append(av.doId) + + self.__update() - def setPlayersPerTeam(self, todo0, todo1): - pass + def getPlayersPerTeam(self): + return (PartyGlobals.CogActivityMinPlayersPerTeam, + PartyGlobals.CogActivityMaxPlayersPerTeam) + + def __areTeamsCorrect(self): + minPlayers = self.getPlayersPerTeam()[0] + return all(len(self.toonIds[i]) >= minPlayers for i in xrange(2)) - def setDuration(self, todo0): - pass + def getDuration(self): + raise NotImplementedError('getDuration() -- pure virtual') - def setCanSwitchTeams(self, todo0): - pass + def getCanSwitchTeams(self): + return self.fsm.state in ('Off', 'WaitForEnough', 'WaitToStart') and not self.forbidTeamChanges - def setState(self, todo0, todo1, todo2): - pass - - def setToonsPlaying(self, todo0, todo1): - pass + def updateToonsPlaying(self): + self.sendUpdate('setToonsPlaying', self.getToonsPlaying()) + + def getToonsPlaying(self): + return self.toonIds def setAdvantage(self, todo0): pass + + def b_setState(self, state, data=0): + self.fsm.request(state, data) + self.d_setState(state, data) + + def d_setState(self, state, data=0): + self.sendUpdate('setState', [state, globalClockDelta.getRealNetworkTime(), data]) - def switchTeamRequestDenied(self, todo0): + def _getCaller(self): + avId = self.air.getAvatarIdFromSender() + if avId not in self.air.doId2do: + self.air.writeServerEvent('suspicious', avId, 'called some DistributedPartyActivityAI method outside shard') + return None + + return self.air.doId2do[avId] + + def __update(self): + self.updateToonsPlaying() + + if self.fsm.state == 'WaitForEnough': + if self.__areTeamsCorrect(): + self.b_setState('WaitToStart') + + elif self.fsm.state == 'WaitToStart': + if not self.__areTeamsCorrect(): + self.b_setState('WaitForEnough') + + def startWaitForEnough(self, data): pass + + def finishWaitForEnough(self): + pass + + def startWaitToStart(self, data): + def advance(task): + self.fsm.request('WaitClientsReady') + self.d_setState('Rules') + return task.done + + taskMgr.doMethodLater(self.startDelay, advance, self.taskName('dostart')) + + def finishWaitToStart(self): + taskMgr.remove(self.taskName('dostart')) + + def __doStart(self, task = None): + self.b_setState('Active') + if task: return task.done + + def startWaitClientsReady(self): + self.responses = set() + taskMgr.doMethodLater(15, self.__doStart, self.taskName('clientready')) + + def finishWaitClientsReady(self): + taskMgr.remove(self.taskName('clientready')) + + def toonReady(self): + self.responses.add(self.air.getAvatarIdFromSender()) + if self.responses == set(self.toonsPlaying): + self.__doStart() + + def startActive(self, data): + taskMgr.doMethodLater(self.getDuration(), self.__finish, self.taskName('finish')) + + def finishActive(self): + taskMgr.remove(self.taskName('finish')) + + def __finish(self, task): + self.calcReward() + self.b_setState('Conclusion') + return task.done + + def calcReward(self): + raise NotImplementedError('calcReward() -- pure virtual') + + def startConclusion(self, data): + raise NotImplementedError('startConclusion() -- pure virtual') + + def finishConclusion(self): + raise NotImplementedError('finishConclusion() -- pure virtual') + \ No newline at end of file diff --git a/toontown/parties/DistributedPartyTugOfWarActivity.py b/toontown/parties/DistributedPartyTugOfWarActivity.py index 7a2989a9..cadba1a6 100755 --- a/toontown/parties/DistributedPartyTugOfWarActivity.py +++ b/toontown/parties/DistributedPartyTugOfWarActivity.py @@ -128,7 +128,7 @@ class DistributedPartyTugOfWarActivity(DistributedPartyTeamActivity): return def handleToonDisabled(self, toonId): - if toonId in self.toonIdsToAnimIntervals: + if self.toonIdsToAnimIntervals.has_key(toonId): if self.toonIdsToAnimIntervals[toonId]: if self.toonIdsToAnimIntervals[toonId].isPlaying(): self.toonIdsToAnimIntervals[toonId].finish() @@ -156,24 +156,24 @@ class DistributedPartyTugOfWarActivity(DistributedPartyTeamActivity): self.playArea.reparentTo(self.root) self.sign.reparentTo(self.playArea.find('**/TugOfWar_sign_locator')) self.dockPositions = [[], []] - for i in xrange(4): + for i in range(4): self.dockPositions[0].append(Point3(-PartyGlobals.TugOfWarInitialToonPositionsXOffset - PartyGlobals.TugOfWarToonPositionXSeparation * i, 0.0, PartyGlobals.TugOfWarToonPositionZ)) - for i in xrange(4): + for i in range(4): self.dockPositions[1].append(Point3(PartyGlobals.TugOfWarInitialToonPositionsXOffset + PartyGlobals.TugOfWarToonPositionXSeparation * i, 0.0, PartyGlobals.TugOfWarToonPositionZ)) self.hopOffPositions = [[], []] - for i in xrange(1, 5): + for i in range(1, 5): self.hopOffPositions[PartyGlobals.TeamActivityTeams.LeftTeam].append(self.playArea.find('**/leftTeamHopOff%d_locator' % i).getPos()) self.hopOffPositions[PartyGlobals.TeamActivityTeams.RightTeam].append(self.playArea.find('**/rightTeamHopOff%d_locator' % i).getPos()) - for i in xrange(1, 5): + for i in range(1, 5): pos = self.playArea.find('**/fallenToon%d_locator' % i).getPos() self.fallenPositions.append(pos) self.joinCollision = [] self.joinCollisionNodePaths = [] - for i in xrange(len(PartyGlobals.TeamActivityTeams)): + for i in range(len(PartyGlobals.TeamActivityTeams)): collShape = CollisionTube(PartyGlobals.TugOfWarJoinCollisionEndPoints[0], PartyGlobals.TugOfWarJoinCollisionEndPoints[1], PartyGlobals.TugOfWarJoinCollisionRadius) collShape.setTangible(True) self.joinCollision.append(CollisionNode('TugOfWarJoinCollision%d' % i)) @@ -187,7 +187,7 @@ class DistributedPartyTugOfWarActivity(DistributedPartyTeamActivity): ropeModel = loader.loadModel('phase_4/models/minigames/tug_of_war_rope') self.ropeTexture = ropeModel.findTexture('*') ropeModel.removeNode() - for i in xrange(PartyGlobals.TugOfWarMaximumPlayersPerTeam * 2 - 1): + for i in range(PartyGlobals.TugOfWarMaximumPlayersPerTeam * 2 - 1): rope = Rope(self.uniqueName('TugRope%d' % i)) if rope.showRope: rope.ropeNode.setRenderMode(RopeNode.RMBillboard) @@ -213,7 +213,7 @@ class DistributedPartyTugOfWarActivity(DistributedPartyTeamActivity): self.powerMeter.setPos(0.0, 0.0, 0.6) self.powerMeter.hide() self.arrows = [None] * 2 - for x in xrange(len(self.arrows)): + for x in range(len(self.arrows)): self.arrows[x] = loader.loadModel('phase_3/models/props/arrow') self.arrows[x].reparentTo(self.powerMeter) self.arrows[x].setScale(0.2 - 0.4 * x, 0.2, 0.2) @@ -228,7 +228,7 @@ class DistributedPartyTugOfWarActivity(DistributedPartyTeamActivity): def loadIntervals(self): self.updateIdealRateInterval = Sequence() self.updateIdealRateInterval.append(Wait(PartyGlobals.TugOfWarTargetRateList[0][0])) - for i in xrange(1, len(PartyGlobals.TugOfWarTargetRateList)): + for i in range(1, len(PartyGlobals.TugOfWarTargetRateList)): duration = PartyGlobals.TugOfWarTargetRateList[i][0] idealRate = PartyGlobals.TugOfWarTargetRateList[i][1] self.updateIdealRateInterval.append(Func(self.setIdealRate, idealRate)) @@ -328,11 +328,11 @@ class DistributedPartyTugOfWarActivity(DistributedPartyTeamActivity): del self.splashInterval def __enableCollisions(self): - for i in xrange(len(PartyGlobals.TeamActivityTeams)): + for i in range(len(PartyGlobals.TeamActivityTeams)): self.accept('enterTugOfWarJoinCollision%d' % i, getattr(self, '_join%s' % PartyGlobals.TeamActivityTeams.getString(i))) def __disableCollisions(self): - for i in xrange(len(PartyGlobals.TeamActivityTeams)): + for i in range(len(PartyGlobals.TeamActivityTeams)): self.ignore('enterTugOfWarJoinCollision%d' % i) def startWaitForEnough(self): @@ -481,12 +481,12 @@ class DistributedPartyTugOfWarActivity(DistributedPartyTeamActivity): for currTeam in teams: numToons = len(self.toonIds[currTeam]) if numToons > 1: - for i in xrange(numToons - 1, 0, -1): + for i in range(numToons - 1, 0, -1): toon1 = self.toonIds[currTeam][i] toon2 = self.toonIds[currTeam][i - 1] - if toon1 not in self.toonIdsToRightHands: + if not self.toonIdsToRightHands.has_key(toon1): self.notify.warning('Toon in tug of war activity but not properly setup: %s' % toon1) - elif toon2 not in self.toonIdsToRightHands: + elif not self.toonIdsToRightHands.has_key(toon2): self.notify.warning('Toon in tug of war activity but not properly setup: %s' % toon2) else: self.notify.debug('Connecting rope between toon %d and toon %d of team %d.' % (i, i - 1, currTeam)) @@ -522,10 +522,10 @@ class DistributedPartyTugOfWarActivity(DistributedPartyTeamActivity): self.idealForce = self.advantage * (4 + 0.4 * self.idealRate) def updateKeyPressRate(self): - for i in xrange(len(self.keyTTL)): + for i in range(len(self.keyTTL)): self.keyTTL[i] -= PartyGlobals.TugOfWarKeyPressUpdateRate - for i in xrange(len(self.keyTTL)): + for i in range(len(self.keyTTL)): if self.keyTTL[i] <= 0.0: a = self.keyTTL[0:i] del self.keyTTL @@ -579,7 +579,7 @@ class DistributedPartyTugOfWarActivity(DistributedPartyTeamActivity): if self.activityFSM.state != 'Active': return toon = self.getAvatar(toonId) - if toonId not in self.toonIdsToIsPullingFlags: + if not self.toonIdsToIsPullingFlags.has_key(toonId): if self.getTeam(toonId) == None: self.notify.warning("setAnimState called with toonId (%d) that wasn't in self.toonIds" % toonId) return @@ -671,7 +671,7 @@ class DistributedPartyTugOfWarActivity(DistributedPartyTeamActivity): if fallenPosIndex < 0 or fallenPosIndex >= 4: fallenPosIndex = 0 newPos = self.fallenPositions[fallenPosIndex] - if toonId in self.toonIdsToAnimIntervals and self.toonIdsToAnimIntervals[toonId] is not None: + if self.toonIdsToAnimIntervals.has_key(toonId) and self.toonIdsToAnimIntervals[toonId] is not None: if self.toonIdsToAnimIntervals[toonId].isPlaying(): self.toonIdsToAnimIntervals[toonId].finish() if toon: diff --git a/toontown/parties/DistributedPartyTugOfWarActivityAI.py b/toontown/parties/DistributedPartyTugOfWarActivityAI.py index 96f4634f..5e97e2c9 100755 --- a/toontown/parties/DistributedPartyTugOfWarActivityAI.py +++ b/toontown/parties/DistributedPartyTugOfWarActivityAI.py @@ -1,20 +1,133 @@ from direct.directnotify import DirectNotifyGlobal -from toontown.parties.DistributedPartyTeamActivityAI import DistributedPartyTeamActivityAI + +from DistributedPartyTeamActivityAI import DistributedPartyTeamActivityAI +from toontown.toonbase import TTLocalizer +import PartyGlobals + +''' +dclass DistributedPartyTugOfWarActivity : DistributedPartyTeamActivity { + reportKeyRateForce(uint32, int16/100) airecv clsend; + reportFallIn(uint8) airecv clsend; + setToonsPlaying(uint32 [0-4], uint32 [0-4]) required broadcast ram; + updateToonKeyRate(uint32, uint32) broadcast; + updateToonPositions(int16/1000) broadcast; +}; +''' + +scoreRef = {'tie': (PartyGlobals.TugOfWarTieReward, PartyGlobals.TugOfWarTieReward), + 0: (PartyGlobals.TugOfWarWinReward, PartyGlobals.TugOfWarLossReward), + 1: (PartyGlobals.TugOfWarLossReward, PartyGlobals.TugOfWarWinReward), + 10:(PartyGlobals.TugOfWarFallInWinReward, PartyGlobals.TugOfWarFallInLossReward), + 11: (PartyGlobals.TugOfWarFallInLossReward, PartyGlobals.TugOfWarFallInWinReward), + } class DistributedPartyTugOfWarActivityAI(DistributedPartyTeamActivityAI): notify = DirectNotifyGlobal.directNotify.newCategory("DistributedPartyTugOfWarActivityAI") + forbidTeamChanges = True + startDelay = PartyGlobals.TugOfWarStartDelay + + def getDuration(self): + return PartyGlobals.TugOfWarDuration - def reportKeyRateForce(self, todo0, todo1): - pass + def reportKeyRateForce(self, keyRate, force): + # Basic sanity check + av = self._getCaller() + if not av: + return + + avId = av.doId + + if not (avId in self.toonIds[0] or avId in self.toonIds[1]): + self.air.writeServerEvent('suspicious', avId, 'sent DistributedPartyTugOfWarActivityAI.reportKeyRateForce, but not playing') + return + + self.forces[avId] = force + self.sendUpdate('updateToonKeyRate', [avId, keyRate]) + self.d_updateToonPositions() + + def d_updateToonPositions(self): + _getTeamForce = lambda team: sum(self.forces.get(avId, 0) for avId in self.toonIds[team]) + + f0 = _getTeamForce(0) + f1 = _getTeamForce(1) + fr = f0 + f1 + + if fr != 0: + delta = (f0 - f1) / fr + self.pos += -delta * PartyGlobals.TugOfWarMovementFactor * 2 - def reportFallIn(self, todo0): - pass - - def setToonsPlaying(self, todo0, todo1): - pass - - def updateToonKeyRate(self, todo0, todo1): - pass - - def updateToonPositions(self, todo0): - pass + self.sendUpdate('updateToonPositions', [self.pos]) + + def reportFallIn(self, losingTeam): + if self.fsm.state != 'Active' or self._hasFall: + return + + # Basic sanity check + av = self._getCaller() + if not av: + return + + avId = av.doId + + if not (avId in self.toonIds[0] or avId in self.toonIds[1]): + self.air.writeServerEvent('suspicious', avId, 'sent DistributedPartyTugOfWarActivityAI.reportFallIn, but not playing') + return + + losers = int(self.pos < 0) + if losers != losingTeam: + self.air.writeServerEvent('suspicious', avId, 'called DistributedPartyTugOfWarActivityAI.reportFallIn with incorrect losingTeam') + + self._hasFall = 1 + + def _advance(task): + self.calcReward() + return task.done + + taskMgr.doMethodLater(1, _advance, self.taskName('fallIn-advance')) + taskMgr.remove(self.taskName('finish')) # Mitigate races + + def calcReward(self): + nobodyWins = abs(self.pos) <= 2 + if nobodyWins: + self._winnerTeam = 3 + self._teamScores = scoreRef['tie'] + + else: + self._winnerTeam = int(self.pos < 0) + self._teamScores = scoreRef[self._winnerTeam + self._hasFall * 10] + + self.b_setState('Conclusion', self._winnerTeam) + + def startActive(self, data): + self.forces = {} + self.pos = 0 + self._hasFall = 0 + DistributedPartyTeamActivityAI.startActive(self, data) + + def startConclusion(self, data): + taskMgr.doMethodLater(1, self.__exitConclusion, self.taskName('exitconc')) + + def finishConclusion(self): + taskMgr.remove(self.taskName('exitconc')) + + def __exitConclusion(self, task): + def _sendReward(team): + jb = self._teamScores[team] + msg = TTLocalizer.PartyTeamActivityRewardMessage % jb + + for avId in self.toonIds[team]: + av = self.air.doId2do.get(avId) + if av: + self.sendUpdateToAvatarId(avId, 'showJellybeanReward', [jb, av.getMoney(), msg]) + av.addMoney(jb) + + _sendReward(0) + _sendReward(1) + + self.toonsPlaying = [] + self.toonIds = ([], []) + + self.updateToonsPlaying() + + self.b_setState('WaitForEnough') + return task.done diff --git a/toontown/parties/PartyCogActivity.py b/toontown/parties/PartyCogActivity.py index 10b11005..b6b6699a 100755 --- a/toontown/parties/PartyCogActivity.py +++ b/toontown/parties/PartyCogActivity.py @@ -263,13 +263,13 @@ class PartyCogActivity(DirectObject): pos = self._doorStartPos[team] else: pos = (self._doorStartPos[team] + Point3(0, 0, -7.0),) - ival = self._arenaDoors[team].posInterval(0.75, pos, blendType='easeIn') + ival = self._arenaDoors[team].posInterval(0.75, Point3(0, 0, -7.0), blendType='easeIn') self._arenaDoorIvals[team] = ival ival.start() return def openArenaDoorForTeam(self, team): - self._playArenaDoorIval(team, opening=True) + self._playArenaDoorIval(team, opening=False) def closeArenaDoorForTeam(self, team): self._playArenaDoorIval(team, opening=False) diff --git a/toontown/parties/PartyEditorGrid.py b/toontown/parties/PartyEditorGrid.py index 485b59e0..f11463d2 100755 --- a/toontown/parties/PartyEditorGrid.py +++ b/toontown/parties/PartyEditorGrid.py @@ -290,8 +290,8 @@ class PartyEditorGrid: None, None, None]] - for y in xrange(len(self.grid)): - for x in xrange(len(self.grid[0])): + for y in range(len(self.grid)): + for x in range(len(self.grid[0])): if self.grid[y][x]: self.grid[y][x] = PartyEditorGridSquare(self.partyEditor, x, y) @@ -299,8 +299,8 @@ class PartyEditorGrid: def getActivitiesOnGrid(self): activities = [] - for y in xrange(len(self.grid)): - for x in xrange(len(self.grid[0])): + for y in range(len(self.grid)): + for x in range(len(self.grid[0])): if self.grid[y][x] and self.grid[y][x].gridElement: if not self.grid[y][x].gridElement.isDecoration: activityTuple = self.grid[y][x].gridElement.getActivityTuple(x, y) @@ -312,8 +312,8 @@ class PartyEditorGrid: def getActivitiesElementsOnGrid(self): activities = [] activityElems = [] - for y in xrange(len(self.grid)): - for x in xrange(len(self.grid[0])): + for y in range(len(self.grid)): + for x in range(len(self.grid[0])): if self.grid[y][x] and self.grid[y][x].gridElement: if not self.grid[y][x].gridElement.isDecoration: activityTuple = self.grid[y][x].gridElement.getActivityTuple(x, y) @@ -325,8 +325,8 @@ class PartyEditorGrid: def getDecorationsOnGrid(self): decorations = [] - for y in xrange(len(self.grid)): - for x in xrange(len(self.grid[0])): + for y in range(len(self.grid)): + for x in range(len(self.grid[0])): if self.grid[y][x] and self.grid[y][x].gridElement: if self.grid[y][x].gridElement.isDecoration: decorationTuple = self.grid[y][x].gridElement.getDecorationTuple(x, y) @@ -344,8 +344,8 @@ class PartyEditorGrid: def checkGridSquareForAvailability(self, gridSquare, size): xOffsetLow, xOffsetHigh, yOffset = self.getXYOffsets(size) - for y in xrange(int(gridSquare.y - size[1] / 2), int(gridSquare.y + size[1] / 2) + yOffset): - for x in xrange(int(gridSquare.x - size[0] / 2) + xOffsetLow, int(gridSquare.x + size[0] / 2) + xOffsetHigh): + for y in range(int(gridSquare.y - size[1] / 2), int(gridSquare.y + size[1] / 2) + yOffset): + for x in range(int(gridSquare.x - size[0] / 2) + xOffsetLow, int(gridSquare.x + size[0] / 2) + xOffsetHigh): testGridSquare = self.getGridSquare(x, y) if testGridSquare is None: return False @@ -361,8 +361,8 @@ class PartyEditorGrid: if self.grid[y][x] is not None: if self.checkGridSquareForAvailability(self.grid[y][x], size): return self.grid[y][x] - for y in xrange(PartyGlobals.PartyEditorGridSize[1]): - for x in xrange(PartyGlobals.PartyEditorGridSize[0]): + for y in range(PartyGlobals.PartyEditorGridSize[1]): + for x in range(PartyGlobals.PartyEditorGridSize[0]): if self.grid[y][x] is not None: if self.checkGridSquareForAvailability(self.grid[y][x], size): return self.grid[y][x] @@ -384,8 +384,8 @@ class PartyEditorGrid: def registerNewElement(self, gridElement, centerGridSquare, size): xOffsetLow, xOffsetHigh, yOffset = self.getXYOffsets(size) - for y in xrange(int(centerGridSquare.y - size[1] / 2), int(centerGridSquare.y + size[1] / 2) + yOffset): - for x in xrange(int(centerGridSquare.x - size[0] / 2) + xOffsetLow, int(centerGridSquare.x + size[0] / 2) + xOffsetHigh): + for y in range(int(centerGridSquare.y - size[1] / 2), int(centerGridSquare.y + size[1] / 2) + yOffset): + for x in range(int(centerGridSquare.x - size[0] / 2) + xOffsetLow, int(centerGridSquare.x + size[0] / 2) + xOffsetHigh): testGridSquare = self.getGridSquare(x, y) if testGridSquare is None: return False @@ -400,8 +400,8 @@ class PartyEditorGrid: def removeElement(self, centerGridSquare, size): xOffsetLow, xOffsetHigh, yOffset = self.getXYOffsets(size) - for y in xrange(int(centerGridSquare.y - size[1] / 2), int(centerGridSquare.y + size[1] / 2) + yOffset): - for x in xrange(int(centerGridSquare.x - size[0] / 2) + xOffsetLow, int(centerGridSquare.x + size[0] / 2) + xOffsetHigh): + for y in range(int(centerGridSquare.y - size[1] / 2), int(centerGridSquare.y + size[1] / 2) + yOffset): + for x in range(int(centerGridSquare.x - size[0] / 2) + xOffsetLow, int(centerGridSquare.x + size[0] / 2) + xOffsetHigh): testGridSquare = self.getGridSquare(x, y) if testGridSquare is None: return False @@ -414,8 +414,8 @@ class PartyEditorGrid: def destroy(self): self.partyEditor = None - for y in xrange(len(self.grid)): - for x in xrange(len(self.grid[0])): + for y in range(len(self.grid)): + for x in range(len(self.grid[0])): if self.grid[y][x]: self.grid[y][x].destroy() diff --git a/toontown/parties/PartyEditorListElement.py b/toontown/parties/PartyEditorListElement.py index 4c9e1bd1..dee8d94d 100755 --- a/toontown/parties/PartyEditorListElement.py +++ b/toontown/parties/PartyEditorListElement.py @@ -72,11 +72,11 @@ class PartyEditorListElement(DirectButton): self.bind(DirectGuiGlobals.B1RELEASE, self.released) self.partyEditorGridElements = [] if self.isDecoration: - for i in xrange(PartyGlobals.DecorationInformationDict[self.id]['limitPerParty']): + for i in range(PartyGlobals.DecorationInformationDict[self.id]['limitPerParty']): self.partyEditorGridElements.append(PartyEditorGridElement(self.partyEditor, self.id, self.isDecoration, self.checkSoldOutAndAffordability)) else: - for i in xrange(PartyGlobals.ActivityInformationDict[self.id]['limitPerParty']): + for i in range(PartyGlobals.ActivityInformationDict[self.id]['limitPerParty']): self.partyEditorGridElements.append(PartyEditorGridElement(self.partyEditor, self.id, self.isDecoration, self.checkSoldOutAndAffordability)) self.activeGridElementIndex = -1 @@ -130,14 +130,13 @@ class PartyEditorListElement(DirectButton): else: self.setTooExpensive(False) tooExpensive = False - for i in xrange(len(self.partyEditorGridElements)): + for i in range(len(self.partyEditorGridElements)): if not self.partyEditorGridElements[i].overValidSquare: if not tooExpensive: self.setSoldOut(False) return self.setSoldOut(True) - return def setTooExpensive(self, value): self.partyEditor.partyPlanner.elementBuyButton['text'] = TTLocalizer.PartyPlannerBuy @@ -165,14 +164,14 @@ class PartyEditorListElement(DirectButton): def clicked(self, mouseEvent): PartyEditorListElement.notify.debug("Element %s's icon was clicked" % self.name) self.partyEditor.listElementClicked() - for i in xrange(len(self.partyEditorGridElements)): + for i in range(len(self.partyEditorGridElements)): if not self.partyEditorGridElements[i].overValidSquare: self.partyEditorGridElements[i].attach(mouseEvent) self.activeGridElementIndex = i return def buyButtonClicked(self, desiredXY = None): - for i in xrange(len(self.partyEditorGridElements)): + for i in range(len(self.partyEditorGridElements)): if not self.partyEditorGridElements[i].overValidSquare: if self.partyEditorGridElements[i].placeInPartyGrounds(desiredXY): self.activeGridElementIndex = i diff --git a/toontown/pets/Pet.py b/toontown/pets/Pet.py index 62e5c869..6ccaf0d8 100755 --- a/toontown/pets/Pet.py +++ b/toontown/pets/Pet.py @@ -46,7 +46,7 @@ class Pet(Avatar.Avatar): Pet.SerialNum += 1 self.lockedDown = 0 self.setPickable(1) - self.setPlayerType(NametagGroup.CCNonPlayer) + self.setPlayerType(NametagGroup.CCSpeedChat) self.animFSM = ClassicFSM('petAnimFSM', [State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('neutralHappy', self.enterNeutralHappy, self.exitNeutralHappy), diff --git a/toontown/pets/PetAvatarPanel.py b/toontown/pets/PetAvatarPanel.py index ea398eee..131f091e 100755 --- a/toontown/pets/PetAvatarPanel.py +++ b/toontown/pets/PetAvatarPanel.py @@ -270,7 +270,7 @@ class PetAvatarPanel(AvatarPanel.AvatarPanel): def __fillPetInfo(self, avatar): self.notify.debug('__fillPetInfo(): doId=%s' % avatar.doId) self.petView = self.frame.attachNewNode('petView') - self.petView.setPos(0, 0, 5.4) + self.petView.setPos(0, 0, 5) if hasattr(avatar, 'announceGenerate'): avatar.announceGenerate() self.petModel = Pet.Pet(forGui=1) diff --git a/toontown/pets/PetManagerAI.py b/toontown/pets/PetManagerAI.py index 79c03f7b..a7128304 100755 --- a/toontown/pets/PetManagerAI.py +++ b/toontown/pets/PetManagerAI.py @@ -1,67 +1,68 @@ +import PetUtil, PetDNA from toontown.toonbase import ToontownGlobals, TTLocalizer -import PetUtil, PetDNA, time, random +import time, random, os -DAY = 24 * 60 * 60 +MINUTE = 60 +HOUR = 60 * MINUTE +DAY = 24 * HOUR def getDayId(): - return int(time.time() / DAY) - + return int(time.time() // DAY) + class PetManagerAI: - NUM_DAILY_PETS = 10 - + NUM_DAILY_PETS = 5 # per hood + def __init__(self, air): self.air = air - self.seeds = simbase.backups.load('pet-seeds', (self.air.districtId,), default={}) - - if self.seeds.get('day', -1) != getDayId(): - self.generateSeeds() - + self.generateSeeds() + def generateSeeds(self): seeds = range(0, 255) - random.shuffle(seeds) - + random.Random(getDayId()).shuffle(seeds) + self.seeds = {} for hood in (ToontownGlobals.ToontownCentral, ToontownGlobals.DonaldsDock, ToontownGlobals.DaisyGardens, - ToontownGlobals.MinniesMelodyland, ToontownGlobals.TheBrrrgh, ToontownGlobals.DonaldsDreamland): - self.seeds[str(hood)] = [seeds.pop() for _ in xrange(self.NUM_DAILY_PETS)] - + ToontownGlobals.MinniesMelodyland, ToontownGlobals.TheBrrrgh, ToontownGlobals.DonaldsDreamland, + ToontownGlobals.FunnyFarm): + self.seeds[hood] = [seeds.pop() for _ in xrange(self.NUM_DAILY_PETS)] + self.seeds['day'] = getDayId() - simbase.backups.save('pet-seeds', (self.air.districtId,), self.seeds) def getAvailablePets(self, safezoneId): if self.seeds.get('day', -1) != getDayId(): self.generateSeeds() - - return self.seeds.get(str(safezoneId), [random.randint(0, 255)]) + + return list(set(self.seeds.get(safezoneId, [random.randint(0, 255)]))) def createNewPetFromSeed(self, avId, seed, nameIndex, gender, safeZoneId): av = self.air.doId2do[avId] - + name = TTLocalizer.getPetName(nameIndex) _, dna, traitSeed = PetUtil.getPetInfoFromSeed(seed, safeZoneId) head, ears, nose, tail, body, color, cs, eye, _ = dna numGenders = len(PetDNA.PetGenders) gender %= numGenders - + fields = {'setOwnerId' : avId, 'setPetName' : name, 'setTraitSeed' : traitSeed, 'setSafeZone' : safeZoneId, 'setHead' : head, 'setEars' : ears, 'setNose' : nose, 'setTail' : tail, 'setBodyTexture' : body, 'setColor' : color, 'setColorScale' : cs, 'setEyeColor' : eye, 'setGender' : gender} - + def response(doId): if not doId: self.air.notify.warning("Cannot create pet for %s!" % avId) return - + self.air.writeServerEvent('bought-pet', avId, doId) av.b_setPetId(doId) - + self.air.dbInterface.createObject(self.air.dbId, self.air.dclassesByName['DistributedPetAI'], {k: (v,) for k,v in fields.items()}, response) - + def deleteToonsPet(self, avId): av = self.air.doId2do[avId] pet = av.getPetId() if pet: if pet in self.air.doId2do: self.air.doId2do[pet].requestDelete() - av.b_setPetId(0) + + av.b_setPetId(0) \ No newline at end of file diff --git a/toontown/pets/PetTricks.py b/toontown/pets/PetTricks.py index aed0914a..e5fcecf1 100755 --- a/toontown/pets/PetTricks.py +++ b/toontown/pets/PetTricks.py @@ -7,7 +7,7 @@ NonHappyMinActualTrickAptitude = 0.1 NonHappyMaxActualTrickAptitude = 0.6 MinActualTrickAptitude = 0.5 MaxActualTrickAptitude = 0.97 -AptitudeIncrementDidTrick = 0.0005 * config.GetFloat('pet-trick-aptitude-mult', 4) +AptitudeIncrementDidTrick = 0.0005 MaxAptitudeIncrementGotPraise = 0.0003 MaxTrickFatigue = 0.65 MinTrickFatigue = 0.1 diff --git a/toontown/quest/Quests.py b/toontown/quest/Quests.py index bcf746f8..b1d503fd 100755 --- a/toontown/quest/Quests.py +++ b/toontown/quest/Quests.py @@ -65,6 +65,7 @@ Easy = 75 Medium = 50 Hard = 25 VeryHard = 20 +Fun = 15 TT_TIER = 0 DD_TIER = 4 DG_TIER = 7 @@ -73,7 +74,8 @@ BR_TIER = 11 DL_TIER = 14 LAWBOT_HQ_TIER = 18 BOSSBOT_HQ_TIER = 32 -ELDER_TIER = 49 +PRE_ELDER_TIER = 49 +ELDER_TIER = 50 LOOPING_FINAL_TIER = ELDER_TIER VISIT_QUEST_ID = 1000 TROLLEY_QUEST_ID = 110 @@ -1675,6 +1677,7 @@ class PhoneQuest(Quest): def getObjectiveStrings(self): return [TTLocalizer.QuestsPhoneQuestString] + DefaultDialog = {GREETING: DefaultGreeting, QUEST: DefaultQuest, @@ -3024,7 +3027,7 @@ QuestDict = { 9503: (DL_TIER + 3, Start, (BuildingQuest, Anywhere, 25, Any, 3, 1), Any, ToonHQ, Any, NA, DefaultDialog), 9504: (DL_TIER + 3, Start, (BuildingQuest, Anywhere, 20, 's', 5, 1), Any, ToonHQ, Any, NA, DefaultDialog), 9505: (DL_TIER + 3, Start, (BuildingQuest, Anywhere, 20, 'l', 5, 1), Any, ToonHQ, Any, NA, DefaultDialog), - 9506: (DL_TIER + 3, Start, (RescueQuest, InFO, 10), Any, ToonHQ, Any, NA, DefaultDialog), + 9506: (DL_TIER + 3, Start, (RescueQuest, InFO, 10), Any, ToonHQ, Any, NA, DefaultDialog), 10100: (ELDER_TIER, Start, (CogQuest, Anywhere, 80, Any), Any, ToonHQ, Any, NA, DefaultDialog), 10101: (ELDER_TIER, Start, (CogQuest, Anywhere, 100, Any), Any, ToonHQ, Any, NA, DefaultDialog), 10102: (ELDER_TIER, Start, (CogQuest, Anywhere, 120, Any), Any, ToonHQ, Any, NA, DefaultDialog), @@ -4007,6 +4010,27 @@ class BuffReward(Reward): def getPosterString(self): return TTLocalizer.getBuffPosterString(self.getBuffId()) +class EPPReward(Reward): + trackNames = [TTLocalizer.Bossbot, + TTLocalizer.Lawbot, + TTLocalizer.Cashbot, + TTLocalizer.Sellbot] + + def sendRewardAI(self, av): + av.addEPP(self.reward[0]) + + def countReward(self, qrc): + pass + + def getCogTrackName(self): + return EPPReward.trackNames[self.reward[0]] + + def getString(self): + return TTLocalizer.QuestsEPPReward % self.getCogTrackName() + + def getPosterString(self): + return TTLocalizer.QuestsEPPRewardPoster % self.getCogTrackName() + def getRewardClass(id): reward = RewardDict.get(id) @@ -4401,9 +4425,14 @@ RewardDict = { 3001: (BuffReward, ToontownGlobals.BMovementSpeed, 30), 3002: (BuffReward, ToontownGlobals.BMovementSpeed, 60), 3003: (BuffReward, ToontownGlobals.BMovementSpeed, 180), - 3004: (BuffReward, ToontownGlobals.BMovementSpeed, 360) + 3004: (BuffReward, ToontownGlobals.BMovementSpeed, 360), + 10000: (EPPReward, 0), # Bossbot + 10001: (EPPReward, 1), # Lawbot + 10002: (EPPReward, 2), # Cashbot + 10003: (EPPReward, 3) # Sellbot } +BuffRewardIds = [3001, 3002, 3003, 3004] def getNumTiers(): return len(RequiredRewardTrackDict) - 1 @@ -4446,12 +4475,12 @@ RequiredRewardTrackDict = { MM_TIER + 1: (100, 801, 802, 203, 803, 804, 101, 805, 806, 102, 807, 808, 100, 809, 810, 101, 811, 812, 703, 813, 814, 815, 303), MM_TIER + 2: (900,), BR_TIER: (400,), - BR_TIER + 1: (100, 801, 802, 704, 803, 804, 101, 805, 806, 502, 807, 808, 102, 809, 810, 204, 811, 812, 100, 813, 814, 101, 815, 304), + BR_TIER + 1: (100, 801, 802, 704, 803, 804, 101, 805, 806, 502, 807, 808, 102, 809, 810, 204, 811, 812, 100, 813, 814, 101, 815, 304, 10003), BR_TIER + 2: (900,), DL_TIER: (4000, 100, 205, 101, 102, 705, 103, 305, 4001, 4002), DL_TIER + 1: (100, 206, 101, 4003, 4004, 4005, 102, 4006, 4007, 4008, 706, 103, 4009, 4010, 4011, 4000, 4001, 4002), DL_TIER + 2: (4006, 4007, 4008, 100, 4000, 4001, 4002, 4003, 101, 4004, 4005, 4009, 102, 103, 4010, 4011), - DL_TIER + 3: (4009, 4010, 4011, 100, 4000, 4001, 101, 4002, 4003, 102, 4004, 4005, 102, 4006, 4007, 707, 207, 4008), + DL_TIER + 3: (4009, 4010, 4011, 100, 4000, 4001, 101, 4002, 4003, 102, 4004, 4005, 102, 4006, 4007, 707, 207, 4008, 10002), LAWBOT_HQ_TIER: (4100,), LAWBOT_HQ_TIER + 1: (4101,), LAWBOT_HQ_TIER + 2: (4102,), @@ -4483,6 +4512,7 @@ RequiredRewardTrackDict = { BOSSBOT_HQ_TIER + 14: (4214,), BOSSBOT_HQ_TIER + 15: (4215,), BOSSBOT_HQ_TIER + 16: (4216,), + PRE_ELDER_TIER: (10001, 10000), ELDER_TIER: (4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011)} OptionalRewardTrackDict = { diff --git a/toontown/racing/DistributedRace.py b/toontown/racing/DistributedRace.py index 000069d5..7293057e 100755 --- a/toontown/racing/DistributedRace.py +++ b/toontown/racing/DistributedRace.py @@ -74,6 +74,7 @@ class DistributedRace(DistributedObject.DistributedObject): self.bananaSound = base.loadSfx('phase_6/audio/sfx/KART_tossBanana.ogg') self.anvilFall = base.loadSfx('phase_6/audio/sfx/KART_Gag_Hit_Anvil.ogg') self.accept('leaveRace', self.leaveRace) + self.accept('finishRace', self.finishRace) self.toonsToLink = [] self.curveTs = [] self.curvePoints = [] @@ -569,11 +570,7 @@ class DistributedRace(DistributedObject.DistributedObject): now = globalClock.getFrameTime() timestamp = globalClockDelta.localToNetworkTime(now) if self.laps == self.lapCount: - self.sendUpdate('heresMyT', [localAvatar.doId, - self.laps, - self.currLapT, - timestamp]) - self.fsm.request('finished') + self.finishRace() if self.laps > self.maxLap: self.maxLap = self.laps self.sendUpdate('heresMyT', [localAvatar.doId, @@ -1088,6 +1085,10 @@ class DistributedRace(DistributedObject.DistributedObject): def leaveRace(self): self.fsm.request('leave') + + def finishRace(self): + self.sendUpdate('heresMyT', [localAvatar.doId, self.lapCount, self.currLapT, globalClockDelta.localToNetworkTime(globalClock.getFrameTime())]) + self.fsm.request('finished') def racerLeft(self, avId): if avId != localAvatar.doId: @@ -1243,4 +1244,7 @@ def race(command): if command == 'leave': messenger.send('leaveRace') return 'You left the race!' + elif command == 'finish': + messenger.send('finishRace') + return 'You finished the race!' return 'Invalid command!' diff --git a/toontown/racing/DistributedRaceAI.py b/toontown/racing/DistributedRaceAI.py index 5a9f942f..a4cb502f 100755 --- a/toontown/racing/DistributedRaceAI.py +++ b/toontown/racing/DistributedRaceAI.py @@ -3,12 +3,13 @@ from direct.distributed.ClockDelta import * from direct.distributed.DistributedObjectAI import DistributedObjectAI from direct.fsm.FSM import FSM from direct.task import Task +from toontown.uberdog import TopToonsGlobals import random from toontown.racing import RaceGlobals from toontown.racing.DistributedGagAI import DistributedGagAI from toontown.racing.DistributedVehicleAI import DistributedVehicleAI -from toontown.toonbase import TTLocalizer +from toontown.toonbase import TTLocalizer, ToontownGlobals class DistributedRaceAI(DistributedObjectAI, FSM): @@ -317,9 +318,12 @@ class DistributedRaceAI(DistributedObjectAI, FSM): av.b_setTickets(av.getTickets() + winnings) if av.getTickets() > RaceGlobals.MaxTickets: av.b_setTickets(RaceGlobals.MaxTickets) + av.addStat(ToontownGlobals.STAT_RACING) self.sendUpdate('setPlace', [avId, totalTime, place, entryFee, qualify, max((winnings-entryFee), 0), bonus, trophies, [], 0]) def calculateTrophies(self, avId, won, qualify, time): + if won: + messenger.send('topToonsManager-event', [avId, TopToonsGlobals.CAT_RACE_WON, 1]) av = self.air.doId2do[avId] kartingHistory = av.getKartingHistory() avTrophies = av.getKartingTrophies() diff --git a/toontown/racing/LeaderboardMgrAI.py b/toontown/racing/LeaderboardMgrAI.py index aebbd059..682dac40 100644 --- a/toontown/racing/LeaderboardMgrAI.py +++ b/toontown/racing/LeaderboardMgrAI.py @@ -31,14 +31,14 @@ class LeaderboardMgrAI: originalRace = self.database[race][1] newRace = list(originalRace) - newRace.append((name, timestamp)) + newRace.append([name, timestamp]) sortedRace = self.trimList(sorted(newRace, key=operator.itemgetter(1))) if originalRace != sortedRace: self.database[race][1] = sortedRace self.saveDatabase() else: - self.database[race] = (time.time(), [(name, timestamp)]) + self.database[race] = [time.time(), [(name, timestamp)]] self.saveDatabase() @magicWord(category=CATEGORY_PROGRAMMER, types=[str, int, int, str, int]) diff --git a/toontown/rpc/ToontownRPCHandler.py b/toontown/rpc/ToontownRPCHandler.py index cf246871..c40c4850 100755 --- a/toontown/rpc/ToontownRPCHandler.py +++ b/toontown/rpc/ToontownRPCHandler.py @@ -626,7 +626,7 @@ class ToontownRPCHandler(ToontownRPCHandlerBase): { 'name': 'Toon Name', 'species': 'cat', - 'head-color': 'Red', + 'head-color': (1, 0, 0, 1), 'max-hp': 15, 'online': True } @@ -642,7 +642,7 @@ class ToontownRPCHandler(ToontownRPCHandlerBase): dna.makeFromNetString(fields['setDNAString'][0]) result['species'] = ToonDNA.getSpeciesName(dna.head) - result['head-color'] = TTLocalizer.NumToColor[dna.headColor] + result['head-color'] = dna.headColor result['max-hp'] = fields['setMaxHp'][0] result['online'] = (avId in self.air.friendsManager.onlineToons) @@ -716,7 +716,7 @@ class ToontownRPCHandler(ToontownRPCHandlerBase): = Extra invasion flags. = The invasion type. """ - self.air.netMessenger.send( + self.air.sendNetEvent( 'startInvasion', [shardId, suitDeptIndex, suitTypeIndex, flags, type]) @@ -730,7 +730,7 @@ class ToontownRPCHandler(ToontownRPCHandlerBase): [int shardId] = The ID of the shard that is running the invasion to be terminated. """ - self.air.netMessenger.send('stopInvasion', [shardId]) + self.air.sendNetEvent('stopInvasion', [shardId]) # --- NAME APPROVAL --- diff --git a/toontown/rpc/ToontownRPCHandlerBase.py b/toontown/rpc/ToontownRPCHandlerBase.py index dbf2ab7c..a5aaec0f 100755 --- a/toontown/rpc/ToontownRPCHandlerBase.py +++ b/toontown/rpc/ToontownRPCHandlerBase.py @@ -1,4 +1,3 @@ -import base64 from direct.directnotify.DirectNotifyGlobal import directNotify import json import time @@ -41,7 +40,7 @@ class ToontownRPCHandlerBase: """ # First, base64 decode the token: try: - token = base64.b64decode(token) + token = token.decode('base64') except TypeError: return (-32001, 'Token decode failure') diff --git a/toontown/safezone/DistributedFishingSpotAI.py b/toontown/safezone/DistributedFishingSpotAI.py index 65e82f25..2fef583a 100755 --- a/toontown/safezone/DistributedFishingSpotAI.py +++ b/toontown/safezone/DistributedFishingSpotAI.py @@ -103,7 +103,7 @@ class DistributedFishingSpotAI(DistributedObjectAI): if self.avId != avId: self.air.writeServerEvent('suspicious', avId, 'Toon tried to sell fish at a pier they\'re not using!') return - if self.air.doId2do[pondDoId].getArea() != ToontownGlobals.MyEstate: + if self.air.doId2do[self.pondDoId].getArea() != ToontownGlobals.MyEstate: self.air.writeServerEvent('suspicious', avId, 'Toon tried to sell fish at a pier not in their estate!') av = self.air.doId2do[avId] result = self.air.fishManager.creditFishTank(av) diff --git a/toontown/safezone/DistributedPillow.py b/toontown/safezone/DistributedPillow.py deleted file mode 100644 index 104111f8..00000000 --- a/toontown/safezone/DistributedPillow.py +++ /dev/null @@ -1,95 +0,0 @@ -from panda3d.core import Point3, NodePath -from pandac.PandaModules import CollisionPolygon -from otp.otpbase import OTPGlobals -from direct.distributed.DistributedObject import DistributedObject -from direct.fsm import ClassicFSM, State -from toontown.toonbase import ToontownGlobals - -class DistributedPillow(DistributedObject): - - points = [ - Point3(-62.2896, 59.2746, -6.0), - Point3(-119.969, 59.2746, -6.0), - Point3(-67.1297, 55.2920, -1.6), - Point3(-120.063, 55.2920, -1.6), - Point3(-64.9566, 35.6930, 1.0), - Point3(-119.993, 35.6930, 1.0), - Point3(-63.4717, 0.00000, 1.6), - Point3(-119.670, 0.00000, 1.6), - Point3(-64.9566, -35.6930, 1.0), - Point3(-119.993, -35.6930, 1.0), - Point3(-67.1297, -55.2920, -1.6), - Point3(-120.063, -55.2920, -1.6), - Point3(-62.2896, -58.3746, -6.0), - Point3(-119.969, -58.3746, -6.0), - Point3(-104.100, 59.2746, -6.0), - Point3(-104.100, -58.3746, -6.0), - Point3(-104.100, 55.2920, -6.0), - Point3(-104.100, -55.2920, -6.0), - ] - polygons = [[0, 1, 3, 2], [2, 3, 5, 4], [4, 5, 7, 6], - [6, 7, 9, 8], [8, 9, 11, 10], [10, 11, 13, 12]] - walls = [[0, 2], [2, 4], [4, 6], [6, 8], [8, 10], [10, 12], - [3, 1], [5, 3], [7, 5], [9, 7], [11, 9], [13, 11], - [3, 16], [17, 11], [16, 14], [15, 17]] - - def __init__(self, cr): - DistributedObject.__init__(self, cr) - self.floorpolys = [] - self.wallpolys = [] - self.npaths = [] - self.np = None - - def generate(self): - DistributedObject.generate(self) - self.loader = self.cr.playGame.hood.loader - self.np = NodePath('Pillow') - self.np.reparentTo(render) - for point in DistributedPillow.polygons: - orderedPoints = [] - for index in point: - orderedPoints.append(DistributedPillow.points[index]) - self.floorpolys.append(CollisionPolygon(*orderedPoints)) - for n, p in enumerate(self.floorpolys): - polyNode = CollisionNode("FloorPoly-%d" % n) - polyNode.addSolid(p) - polyNode.setFromCollideMask(OTPGlobals.FloorBitmask) - polyNodePath = self.np.attachNewNode(polyNode) - self.npaths.append(polyNodePath) - self.accept("enterFloorPoly-%d" % n, self.gravityHigh) - self.accept("enterdonalds_dreamland", self.gravityLow) - for wall in DistributedPillow.walls: - ab = DistributedPillow.points[wall[0]] - bb = DistributedPillow.points[wall[1]] - cb = Point3(bb.getX(), bb.getY(), bb.getZ() + 20) - db = Point3(ab.getX(), ab.getY(), ab.getZ() + 20) - self.wallpolys.append(CollisionPolygon(ab, bb, cb, db)) - for n, p in enumerate(self.wallpolys): - polyNode = CollisionNode("WallPoly-%d" % n) - polyNode.addSolid(p) - polyNode.setFromCollideMask(OTPGlobals.FloorBitmask) - polyNodePath = self.np.attachNewNode(polyNode) - self.npaths.append(polyNodePath) - - def disable(self): - DistributedObject.disable(self) - self.floorpolys = [] - self.wallpolys = [] - self.npaths = [] - if self.np: - self.np.removeNode() - self.np = None - if hasattr(self, 'loader'): - del self.loader - - def delete(self): - if self.np: - self.np.removeNode() - self.np = None - DistributedObject.delete(self) - - def gravityLow(self, entry): - base.localAvatar.controlManager.currentControls.setGravity(ToontownGlobals.GravityValue * 1.25) - - def gravityHigh(self, entry): - base.localAvatar.controlManager.currentControls.setGravity(ToontownGlobals.GravityValue * 2.00) diff --git a/toontown/safezone/DistributedPillowAI.py b/toontown/safezone/DistributedPillowAI.py deleted file mode 100644 index d4c43bf9..00000000 --- a/toontown/safezone/DistributedPillowAI.py +++ /dev/null @@ -1,13 +0,0 @@ -from direct.distributed.DistributedObjectAI import DistributedObjectAI -from direct.fsm import ClassicFSM, State - -class DistributedPillowAI(DistributedObjectAI): - - def __init__(self, air): - DistributedObjectAI.__init__(self, air) - - def generate(self): - DistributedObjectAI.generate(self) - - def delete(self): - DistributedObjectAI.delete(self) diff --git a/toontown/safezone/SafeZoneManagerAI.py b/toontown/safezone/SafeZoneManagerAI.py index d905c0c0..52854b1c 100755 --- a/toontown/safezone/SafeZoneManagerAI.py +++ b/toontown/safezone/SafeZoneManagerAI.py @@ -1,9 +1,6 @@ from direct.directnotify.DirectNotifyGlobal import * from direct.distributed import DistributedObjectAI - - -HealFrequency = 10.0 # The time in seconds between each Toon-up pulse. - +from toontown.toonbase import ToontownGlobals class SafeZoneManagerAI(DistributedObjectAI.DistributedObjectAI): notify = directNotify.newCategory('SafeZoneManagerAI') @@ -13,7 +10,7 @@ class SafeZoneManagerAI(DistributedObjectAI.DistributedObjectAI): av = self.air.doId2do.get(avId) if not av: return - av.startToonUp(HealFrequency) + av.startToonUp(ToontownGlobals.TOONUP_FREQUENCY) def exitSafeZone(self): avId = self.air.getAvatarIdFromSender() diff --git a/toontown/safezone/TreasureGlobals.py b/toontown/safezone/TreasureGlobals.py index d9f6d1aa..0d77e106 100755 --- a/toontown/safezone/TreasureGlobals.py +++ b/toontown/safezone/TreasureGlobals.py @@ -76,7 +76,7 @@ SafeZoneTreasureSpawns = { 5 # Maximum ), ToontownGlobals.DonaldsDock: ( - TreasureDD, 10, # DDTreasure heals 10 each... + TreasureDD, 6, # DDTreasure heals 6 each... [ (52.9072, -23.4768, -12.308), (35.3827, -51.9196, -12.308), @@ -109,7 +109,7 @@ SafeZoneTreasureSpawns = { 2 # Maximum ), ToontownGlobals.DaisyGardens: ( - TreasureDG, 10, # DGTreasure heals 10 each... + TreasureDG, 9, # DGTreasure heals 9 each... [ (-49, 156, 0.0), (-59, 50, 0.0), @@ -136,7 +136,7 @@ SafeZoneTreasureSpawns = { 2 # Maximum ), ToontownGlobals.TheBrrrgh: ( - TreasureBR, 12, # +12 laff + TreasureBR, 15, # +15 laff [ (-108, 46, 6.2), (-111, 74, 6.2), @@ -161,7 +161,7 @@ SafeZoneTreasureSpawns = { 2 # Maximum ), ToontownGlobals.MinniesMelodyland: ( - TreasureMM, 10, # +10 laff + TreasureMM, 12, # +12 laff [ (118, -39, 3.3), (118, 1, 3.3), @@ -187,7 +187,7 @@ SafeZoneTreasureSpawns = { 2 # Maximum ), ToontownGlobals.DonaldsDreamland: ( - TreasureDL, 12, # +12 laff + TreasureDL, 18, # +18 laff [ (86, 69, -17.4), (34, -48, -16.4), diff --git a/toontown/safezone/Walk.py b/toontown/safezone/Walk.py index 6e72faa9..bbd4c0aa 100755 --- a/toontown/safezone/Walk.py +++ b/toontown/safezone/Walk.py @@ -40,10 +40,11 @@ class Walk(StateData.StateData): self.fsm.request('off') self.ignore('control') base.localAvatar.disableAvatarControls() - base.localAvatar.stopUpdateSmartCamera() + if not base.localAvatar.preventCameraDisable: + base.localAvatar.stopUpdateSmartCamera() + base.localAvatar.detachCamera() base.localAvatar.stopPosHprBroadcast() base.localAvatar.stopBlink() - base.localAvatar.detachCamera() base.localAvatar.stopGlitchKiller() base.localAvatar.collisionsOff() base.localAvatar.controlManager.placeOnFloor() diff --git a/toontown/shtiker/InventoryPage.py b/toontown/shtiker/InventoryPage.py index 2531de01..247918f2 100755 --- a/toontown/shtiker/InventoryPage.py +++ b/toontown/shtiker/InventoryPage.py @@ -115,8 +115,6 @@ class InventoryPage(ShtikerPage.ShtikerPage): base.localAvatar.inventory.reparentTo(self) self.__moneyChange(base.localAvatar.getMoney()) self.__bankMoneyChange(base.localAvatar.getBankMoney()) - self.accept('enterBookDelete', self.enterDeleteMode) - self.accept('exitBookDelete', self.exitDeleteMode) self.accept('enterTrackFrame', self.updateTrackInfo) self.accept('exitTrackFrame', self.clearTrackInfo) self.accept(localAvatar.uniqueName('moneyChange'), self.__moneyChange) @@ -125,8 +123,6 @@ class InventoryPage(ShtikerPage.ShtikerPage): def exit(self): ShtikerPage.ShtikerPage.exit(self) self.clearTrackInfo(self.currentTrackInfo) - self.ignore('enterBookDelete') - self.ignore('exitBookDelete') self.ignore('enterTrackFrame') self.ignore('exitTrackFrame') self.ignore(localAvatar.uniqueName('moneyChange')) @@ -134,17 +130,6 @@ class InventoryPage(ShtikerPage.ShtikerPage): self.makePageWhite(None) base.localAvatar.inventory.hide() base.localAvatar.inventory.reparentTo(hidden) - self.exitDeleteMode() - - def enterDeleteMode(self): - self.title['text'] = TTLocalizer.InventoryPageDeleteTitle - self.title['text_fg'] = (0, 0, 0, 1) - self.book['image_color'] = Vec4(1, 1, 0, 1) - - def exitDeleteMode(self): - self.title['text'] = TTLocalizer.InventoryPageTitle - self.title['text_fg'] = (0, 0, 0, 1) - self.book['image_color'] = Vec4(1, 1, 1, 1) def updateTrackInfo(self, trackIndex): self.currentTrackInfo = trackIndex diff --git a/toontown/shtiker/OptionChooser.py b/toontown/shtiker/OptionChooser.py new file mode 100644 index 00000000..14f9345f --- /dev/null +++ b/toontown/shtiker/OptionChooser.py @@ -0,0 +1,57 @@ +from direct.gui.DirectGui import * + +class OptionChooser: + + def __init__(self, book, labelText, row, indexCommand, extraArgs, exitCommand): + options_text_scale = 0.052 + leftMargin = -0.72 + buttonbase_xcoord = 0.35 + textStartHeight = 0.45 + textRowHeight = 0.145 + y = textStartHeight - row * textRowHeight + matGui = loader.loadModel('phase_3/models/gui/tt_m_gui_mat_mainGui') + arrow_image = (matGui.find('**/tt_t_gui_mat_shuffleArrowUp'), matGui.find('**/tt_t_gui_mat_shuffleArrowDown')) + + self.indexCommand = indexCommand + self.extraArgs = extraArgs + self.exit = exitCommand + self.label = DirectLabel(book, relief=None, text=labelText, text_align=TextNode.ALeft, text_scale=options_text_scale, text_wordwrap=16, pos=(leftMargin, 0, y)) + self.display = DirectLabel(book, relief=None, scale=0.06, text_wordwrap=9, pos=(buttonbase_xcoord, 0, y)) + self.leftButton = DirectButton(book, relief=None, image=arrow_image, scale=0.45, pos=(textStartHeight - 0.4, 0, y), command=self.offsetIndex, extraArgs=[-1]) + self.rightButton = DirectButton(book, relief=None, image=arrow_image, scale=-0.45, pos=(textStartHeight + 0.2, 0, y), command=self.offsetIndex, extraArgs=[1]) + self.index = -1 + matGui.removeNode() + + def unload(self): + self.label.destroy() + del self.label + self.display.destroy() + del self.display + self.leftButton.destroy() + del self.leftButton + self.rightButton.destroy() + del self.rightButton + + def offsetIndex(self, offset): + self.index += offset + self.indexCommand(*self.extraArgs) + + def setIndex(self, index): + self.index = index + + def setDisplayText(self, text): + self.display['text'] = text + + def setDisplayFont(self, font): + self.display['text_font'] = font + + def decideButtons(self, minCount, maxCount): + if self.index <= minCount: + self.leftButton.hide() + else: + self.leftButton.show() + + if self.index >= maxCount: + self.rightButton.hide() + else: + self.rightButton.show() \ No newline at end of file diff --git a/toontown/shtiker/OptionsPage.py b/toontown/shtiker/OptionsPage.py index ebe40404..6da309cb 100755 --- a/toontown/shtiker/OptionsPage.py +++ b/toontown/shtiker/OptionsPage.py @@ -6,6 +6,7 @@ from panda3d.core import * import DisplaySettingsDialog import ShtikerPage +import OptionChooser from otp.speedchat import SCColorScheme from otp.speedchat import SCStaticTextTerminal from otp.speedchat import SpeedChat @@ -701,6 +702,7 @@ class ExtraOptionsTabPage(DirectFrame): def __init__(self, parent = aspect2d): self.parent = parent self.currentSizeIndex = None + self.optionChoosers = {} DirectFrame.__init__(self, parent=self.parent, relief=None, pos=(0.0, 0.0, 0.0), scale=(1.0, 1.0, 1.0)) @@ -711,6 +713,7 @@ class ExtraOptionsTabPage(DirectFrame): DirectFrame.destroy(self) def load(self): + self.optionChoosers = {} guiButton = loader.loadModel('phase_3/models/gui/quit_button') circleModel = loader.loadModel('phase_3/models/gui/tt_m_gui_mat_nameShop') titleHeight = 0.61 @@ -729,6 +732,7 @@ class ExtraOptionsTabPage(DirectFrame): self.speedchatPlus_label = DirectLabel(parent=self, relief=None, text='', text_align=TextNode.ALeft, text_scale=options_text_scale, text_wordwrap=16, pos=(leftMargin, 0, textStartHeight - textRowHeight)) self.trueFriends_label = DirectLabel(parent=self, relief=None, text='', text_align=TextNode.ALeft, text_scale=options_text_scale, text_wordwrap=16, pos=(leftMargin, 0, textStartHeight - 2 * textRowHeight)) self.cogInterface_label = DirectLabel(parent=self, relief=None, text='', text_align=TextNode.ALeft, text_scale=options_text_scale, text_wordwrap=16, pos=(leftMargin, 0, textStartHeight - 3 * textRowHeight)) + self.tpTransition_label = DirectLabel(parent=self, relief=None, text='', text_align=TextNode.ALeft, text_scale=options_text_scale, text_wordwrap=16, pos=(leftMargin, 0, textStartHeight - 4 * textRowHeight)) self.fov_slider = DirectSlider(parent=self, pos=(buttonbase_xcoord, 0.0, buttonbase_ycoord), value=settings['fov'], pageSize=5, range=(ToontownGlobals.DefaultCameraFov, ToontownGlobals.MaxCameraFov), command=self.__doFov, thumb_geom=(circleModel.find('**/tt_t_gui_mat_namePanelCircle')), thumb_relief=None, thumb_geom_scale=2) @@ -736,22 +740,34 @@ class ExtraOptionsTabPage(DirectFrame): self.speedchatPlus_toggleButton = DirectButton(parent=self, relief=None, image=button_image, image_scale=button_image_scale, text='', text_scale=options_text_scale, text_pos=button_textpos, pos=(buttonbase_xcoord, 0.0, buttonbase_ycoord - textRowHeight), command=self.__doToggleSpeedchatPlus) self.trueFriends_toggleButton = DirectButton(parent=self, relief=None, image=button_image, image_scale=button_image_scale, text='', text_scale=options_text_scale, text_pos=button_textpos, pos=(buttonbase_xcoord, 0.0, buttonbase_ycoord - 2 * textRowHeight), command=self.__doToggleTrueFriends) self.cogInterface_toggleButton = DirectButton(parent=self, relief=None, image=button_image, image_scale=button_image_scale, text='', text_scale=options_text_scale, text_pos=button_textpos, pos=(buttonbase_xcoord, 0.0, buttonbase_ycoord - 3 * textRowHeight), command=self.__doToggleCogInterface) + self.tpTransition_toggleButton = DirectButton(parent=self, relief=None, image=button_image, image_scale=button_image_scale, text='', text_scale=options_text_scale, text_pos=button_textpos, pos=(buttonbase_xcoord, 0.0, buttonbase_ycoord - 4 * textRowHeight), command=self.__doToggleTpTransition) self.bugReportButton = DirectButton(parent=self, relief=None, text=TTLocalizer.BugReportButton, image=button_image, image_scale=button_image_scale, text_pos=(0, -0.01), text_fg=(0, 0, 0, 1), command=self.showReportNotice, pos=(0.0, 0.0, -0.6), text_scale=(0.045)) guiButton.removeNode() circleModel.removeNode() + self.optionChoosers['pole'] = OptionChooser.OptionChooser(self, TTLocalizer.FishingPoleLabel, 5, self.__updateFishingPole, [False], self.__applyFishingPole) + self.optionChoosers['nametag_style'] = OptionChooser.OptionChooser(self, TTLocalizer.NametagStyleLabel, 6, self.__updateNametagStyle, [False], self.__applyNametagStyle) + def enter(self): self.show() self.settingsChanged = 0 self.__setSpeedchatPlusButton() self.__setTrueFriendsButton() self.__setCogInterfaceButton() + self.__setTpTransitionButton() + self.__updateNametagStyle() + self.__updateFishingPole() + self.accept('refreshNametagStyle', self.__updateNametagStyle) + self.accept('refreshFishingRod', self.__updateFishingPole) def exit(self): - self.ignore('confirmDone') + self.ignoreAll() self.destroyReportNotice() self.hide() + + for chooser in self.optionChoosers.values(): + chooser.exit(chooser.index) def unload(self): self.fov_label.destroy() @@ -764,9 +780,18 @@ class ExtraOptionsTabPage(DirectFrame): del self.trueFriends_label self.cogInterface_label.destroy() del self.cogInterface_label + self.speedchatPlus_toggleButton.destroy() + del speedchatPlus_toggleButton + self.trueFriends_toggleButton.destroy() + del self.trueFriends_toggleButton self.cogInterface_toggleButton.destroy() del self.cogInterface_toggleButton + self.bugReportButton.destroy() + del self.bugReportButton self.destroyReportNotice() + + for chooser in self.optionChoosers.values(): + optionChooser.unload() def __doFov(self): fov = self.fov_slider['value'] @@ -804,7 +829,46 @@ class ExtraOptionsTabPage(DirectFrame): def __setTrueFriendsButton(self): self.trueFriends_label['text'] = TTLocalizer.TrueFriendsLabelOn if settings['trueFriends'] else TTLocalizer.TrueFriendsLabelOff self.trueFriends_toggleButton['text'] = TTLocalizer.OptionsPageToggleOff if settings['trueFriends'] else TTLocalizer.OptionsPageToggleOn + + def __doToggleTpTransition(self): + messenger.send('wakeup') + settings['tpTransition'] = not settings['tpTransition'] + self.settingsChanged = 1 + self.__setTpTransitionButton() + def __setTpTransitionButton(self): + self.tpTransition_label['text'] = TTLocalizer.TpTransitionLabelOn if settings['tpTransition'] else TTLocalizer.TpTransitionLabelOff + self.tpTransition_toggleButton['text'] = TTLocalizer.OptionsPageToggleOff if settings['tpTransition'] else TTLocalizer.OptionsPageToggleOn + + def __updateNametagStyle(self, resetIndex=True): + chooser = self.optionChoosers['nametag_style'] + + if resetIndex: + chooser.setIndex(base.localAvatar.nametagStyles.index(base.localAvatar.getNametagStyle())) + + nametagId = base.localAvatar.nametagStyles[chooser.index] + chooser.setDisplayText('%s\n%s' % (base.localAvatar.getName(), TTLocalizer.NametagFontNames[nametagId])) + chooser.setDisplayFont(ToontownGlobals.getNametagFont(nametagId)) + chooser.decideButtons(0, len(base.localAvatar.nametagStyles) - 1) + + def __applyNametagStyle(self, index): + if index != -1 and index != base.localAvatar.nametagStyles.index(base.localAvatar.getNametagStyle()): + base.localAvatar.requestNametagStyle(base.localAvatar.nametagStyles[index]) + + def __updateFishingPole(self, resetIndex=True): + chooser = self.optionChoosers['pole'] + + if resetIndex: + print 'resetting index' + chooser.setIndex(base.localAvatar.getFishingRod()) + + chooser.setDisplayText(TTLocalizer.FishingRodNameDict[chooser.index]) + chooser.decideButtons(0, base.localAvatar.maxFishingRod) + + def __applyFishingPole(self, index): + if index != -1 and index != base.localAvatar.getFishingRod(): + base.localAvatar.requestFishingRod(index) + def destroyReportNotice(self): if hasattr(self, 'dialog'): self.dialog.destroy() diff --git a/toontown/shtiker/ShardPage.py b/toontown/shtiker/ShardPage.py index c2020fa8..fe0016ba 100755 --- a/toontown/shtiker/ShardPage.py +++ b/toontown/shtiker/ShardPage.py @@ -82,8 +82,9 @@ class ShardPage(ShtikerPage.ShtikerPage): self.showPop = config.GetBool('show-population', 0) self.showTotalPop = config.GetBool('show-total-population', 0) self.noTeleport = config.GetBool('shard-page-disable', 0) - self.shardGroups = None - self.currentGroupJoined = None + self.shardGroups = [] + self.shardText = [] + self.groupDialog = None def load(self): main_text_scale = 0.06 @@ -117,7 +118,7 @@ class ShardPage(ShtikerPage.ShtikerPage): curShardTuples.sort(compareShardTuples) actualShardId = base.localAvatar.defaultShard for i in xrange(len(curShardTuples)): - shardId, name, pop, invasionStatus = curShardTuples[i] + shardId, name, pop, invasionStatus, groupAvCount = curShardTuples[i] if shardId == actualShardId: self.currentBTP = buttonTuple[0] self.currentBTL = buttonTuple[1] @@ -126,7 +127,7 @@ class ShardPage(ShtikerPage.ShtikerPage): self.currentO = [pop, name, shardId] self.currentBTL['state'] = DGG.DISABLED self.currentBTR['state'] = DGG.DISABLED - self.reloadRightBrain(pop, name, shardId, buttonTuple) + self.reloadRightBrain(pop, name, groupAvCount, shardId, buttonTuple) def unload(self): self.gui.removeNode() @@ -165,7 +166,7 @@ class ShardPage(ShtikerPage.ShtikerPage): taskMgr.doMethodLater(self.ShardInfoUpdateInterval, self.askForShardInfoUpdate, 'ShardPageUpdateTask-doLater') return Task.done - def makeShardButton(self, shardId, shardName, shardPop): + def makeShardButton(self, shardId, groupAvCount, shardName, shardPop): shardButtonParent = DirectFrame() shardButtonL = DirectButton(parent=shardButtonParent, relief=None, text=shardName, text_scale=0.06, text_align=TextNode.ALeft, text_fg=Vec4(0, 0, 0, 1), text3_fg=self.textDisabledColor, text1_bg=self.textDownColor, text2_bg=self.textRolloverColor, textMayChange=0, command=self.reloadRightBrain) popText = str(shardPop) @@ -191,59 +192,62 @@ class ShardPage(ShtikerPage.ShtikerPage): invasionMarker.reparentTo(shardButtonParent) buttonTuple = (shardButtonParent, shardButtonR, shardButtonL, invasionMarker) - shardButtonL['extraArgs'] = extraArgs=[shardPop, shardName, shardId, buttonTuple] - shardButtonR['extraArgs'] = extraArgs=[shardPop, shardName, shardId, buttonTuple] + shardButtonL['extraArgs'] = extraArgs=[shardPop, shardName, groupAvCount, shardId, buttonTuple] + shardButtonR['extraArgs'] = extraArgs=[shardPop, shardName, groupAvCount, shardId, buttonTuple] return buttonTuple - def makeGroupButton(self, groupId, groupType): - groupPop = len(base.cr.groupManager.getGroupPlayers(groupId)) + def makeGroupButton(self, shardId, group, population): groupButtonParent = DirectFrame() - groupButtonL = DirectButton(parent=groupButtonParent, relief=None, text=groupType, text_pos=(0.0, -0.0225), text_scale=0.06, text_align=TextNode.ALeft, text_fg=Vec4(0, 0, 0, 1), text3_fg=self.textDisabledColor, text1_bg=self.textDownColor, text2_bg=self.textRolloverColor, textMayChange=0, command=self.joinGroup) - popText = str(groupPop) - if popText is None: - return - model = loader.loadModel('phase_3.5/models/gui/matching_game_gui') - button = model.find('**/minnieCircle') + groupButtonL = DirectButton(parent=groupButtonParent, relief=None, text=TTLocalizer.GlobalStreetNames[group][-1], text_pos=(0.0, -0.0225), text_scale=0.048, text_align=TextNode.ALeft, text_fg=Vec4(0, 0, 0, 1), text3_fg=self.textDisabledColor, text1_bg=self.textDownColor, text2_bg=self.textRolloverColor, command=self.joinGroup, extraArgs=[group, shardId]) groupButtonR = DirectButton(parent=groupButtonParent, relief=None, - image=button, - image_scale=(0.3, 1, 0.3), - image2_scale=(0.35, 1, 0.35), - image_color=Vec4(0, 0.8, 0, 1), pos=(0.58, 0, -0.0125), - text=popText, + text=str(population), text_scale=0.055, text_align=TextNode.ACenter, - text_pos=(-0.00575, -0.0125), text_fg=Vec4(0, 0, 0, 1), text3_fg=Vec4(0, 0, 0, 1), text1_bg=self.textRolloverColor, text2_bg=self.textRolloverColor, textMayChange=1) + command=self.joinGroup, + extraArgs=[group, shardId], + text_pos=(-0.00575, -0.0125), text_fg=Vec4(0, 0, 0, 1), text3_fg=Vec4(0, 0, 0, 1), text1_bg=self.textRolloverColor, text2_bg=self.textRolloverColor) - leaveButton = DirectButton(parent=groupButtonParent, relief=None, - image=button, - image_scale=(0.3, 1, 0.3), - image2_scale=(0.35, 1, 0.35), - image_color=Vec4(0, 0.8, 0, 1), - pos=(0.50, 0, -0.0125), - text='Leave', - text_scale=0.055, - text_align=TextNode.ACenter, - text_pos=(-0.00575, -0.0125), - text_fg=Vec4(0, 0, 0, 0), - text2_fg=Vec4(0, 0, 0, 1), - command=self.leaveGroup) + return (groupButtonParent, groupButtonL, groupButtonR) + + def joinGroup(self, group, shardId): + canonicalHoodId = ZoneUtil.getCanonicalHoodId(group) + shardName = base.cr.activeDistrictMap[shardId].name + hoodName = TTLocalizer.GlobalStreetNames[canonicalHoodId] + teleportAccess = base.localAvatar.hasTeleportAccess(canonicalHoodId) - leaveButton.hide() - model.removeNode() - button.removeNode() + if teleportAccess: + message = TTLocalizer.GroupAskAccess + elif base.localAvatar.defaultShard == shardId: + self.acceptOnce('groupDialogDone', self.cleanupGroupDialog) + self.groupDialog = TTDialog.TTGlobalDialog(style=TTDialog.Acknowledge, text=TTLocalizer.GroupAskNoAccessSame % (hoodName[0], hoodName[-1]), doneEvent='groupDialogDone') + self.groupDialog.show() + return + else: + message = TTLocalizer.GroupAskNoAccess + + self.acceptOnce('groupDialogDone', self.__handleGroupDialog, extraArgs=[canonicalHoodId if teleportAccess else base.localAvatar.lastHood, shardId]) + self.groupDialog = TTDialog.TTGlobalDialog(style=TTDialog.TwoChoice, text=message % (hoodName[0], hoodName[-1], shardName), doneEvent='groupDialogDone') + self.groupDialog.show() + + def cleanupGroupDialog(self): + self.ignore('groupDialogDone') + self.groupDialog.cleanup() + del self.groupDialog + + def __handleGroupDialog(self, canonicalHoodId, shardId): + response = self.groupDialog.doneStatus + self.cleanupGroupDialog() - buttonTuple = (groupButtonParent, groupButtonR, groupButtonL, leaveButton) - groupButtonL['extraArgs'] = [groupId, buttonTuple] - leaveButton['extraArgs'] = [groupId, buttonTuple] - return buttonTuple + if response == 'ok': + self.requestTeleport(canonicalHoodId, shardId) def removeRightBrain(self): self.districtInfo.find('**/*district-info').removeNode() - def reloadRightBrain(self, shardPop, shardName, shardId, buttonTuple): + def reloadRightBrain(self, shardPop, shardName, groupAvCount, shardId, buttonTuple): self.currentRightBrain = (shardPop, shardName, shardId, buttonTuple) if self.districtInfo.find('**/*district-info'): self.removeRightBrain() @@ -272,36 +276,31 @@ class ShardPage(ShtikerPage.ShtikerPage): if shardId == base.localAvatar.defaultShard: self.shardTeleportButton['state'] = DGG.DISABLED - if self.shardGroups is not None: - for button in self.shardGroups: - button.detachNode() - + for button in self.shardGroups + self.shardText: + button.removeNode() + self.shardGroups = [] + self.shardText = [] - for gid, gtype in base.cr.groupManager.id2type.items(): - btuple = self.makeGroupButton(gid, gtype) - if base.cr.groupManager.isInGroup(base.localAvatar.doId, gid): + for i, group in enumerate(ToontownGlobals.GROUP_ZONES): + btuple = self.makeGroupButton(shardId, group, groupAvCount[i]) + if ZoneUtil.getCanonicalHoodId(base.localAvatar.zoneId) == ZoneUtil.getCanonicalHoodId(group): btuple[1]['state'] = DGG.DISABLED btuple[2]['state'] = DGG.DISABLED - btuple[3].show() self.shardGroups.append(btuple[0]) + self.shardText.append(btuple[2]) + buttonImage = (self.gui.find('**/FndsLst_ScrollUp'), self.gui.find('**/FndsLst_ScrollDN'), self.gui.find('**/FndsLst_ScrollUp_Rllvr'), self.gui.find('**/FndsLst_ScrollUp')) self.districtGroups = DirectScrolledList(parent=districtInfoNode, relief=None, pos=(0.38, 0, -0.34), - incButton_image=(self.gui.find('**/FndsLst_ScrollUp'), - self.gui.find('**/FndsLst_ScrollDN'), - self.gui.find('**/FndsLst_ScrollUp_Rllvr'), - self.gui.find('**/FndsLst_ScrollUp')), + incButton_image=buttonImage, incButton_relief=None, incButton_scale=(self.arrowButtonScale, self.arrowButtonScale, -self.arrowButtonScale), incButton_pos=(self.buttonXstart + 0.005, 0, -0.125), incButton_image3_color=Vec4(1, 1, 1, 0.2), - decButton_image=(self.gui.find('**/FndsLst_ScrollUp'), - self.gui.find('**/FndsLst_ScrollDN'), - self.gui.find('**/FndsLst_ScrollUp_Rllvr'), - self.gui.find('**/FndsLst_ScrollUp')), + decButton_image=buttonImage, decButton_relief=None, decButton_scale=(self.arrowButtonScale, self.arrowButtonScale, @@ -317,103 +316,10 @@ class ShardPage(ShtikerPage.ShtikerPage): (self.listZorigin + self.listFrameSizeZ)/2.1), itemFrame_frameColor=(0.85, 0.95, 1, 1), itemFrame_borderWidth=(0.01, 0.01), - numItemsVisible=15, + numItemsVisible=7, forceHeight=0.065, items=self.shardGroups) - def joinGroup(self, groupId, buttonTuple): - self.acceptOnce('confJoin', self.confirmJoinGroup, extraArgs=[groupId, buttonTuple]) - self.joinDialog = TTDialog.TTGlobalDialog(message='Would you like to join this group?', doneEvent='confJoin', style=4) - - def rejectGroup(self, reason, suitType=0): - self.acceptOnce('remRjD', self.doneReject) - if reason == 1: - self.rejectDialog = TTDialog.TTGlobalDialog(message='You need more suit parts!', doneEvent='remRjD', style=1) - elif reason == 2: - if suitType == 0: - meritType = 'Stock Options' - elif suitType == 1: - meritType = 'Merits' - elif suitType == 2: - meritType = 'Cogbucks' - elif suitType == 3: - meritType = 'Notices' - self.rejectDialog = TTDialog.TTGlobalDialog(message='You need more %s!'%meritType, doneEvent='remRjD', style=1) - elif reason == 3: - self.rejectDialog = TTDialog.TTGlobalDialog(message='That group is full!', doneEvent='remRjD', style=1) - elif reason == 4: - self.rejectDialog = TTDialog.TTGlobalDialog(message='You\'re already in a group!', doneEvent='remRjD', style=1) - elif reason == 5: - self.rejectDialog = TTDialog.TTGlobalDialog(message='You can\'t leave the district while you\'re in a group!', doneEvent='remRjD', style=1) - - def doneReject(self): - self.rejectDialog.cleanup() - del self.rejectDialog - - def confirmJoinGroup(self, groupId, buttonTuple): - doneStatus = self.joinDialog.doneStatus - self.joinDialog.cleanup() - del self.joinDialog - if doneStatus is not 'ok': - return - for gid in base.cr.groupManager.id2type.keys(): - if base.cr.groupManager.isInGroup(base.localAvatar.doId, gid): - self.rejectGroup(4) - return - #if len(base.cr.groupManager.getGroupPlayers(groupId)) >= 8: - # self.rejectGroup(3) - # return - suitIdx = -1 - gids = {10000:0, 11000:1, 12000:2, 13000:3} - suitIdx = gids.get(groupId) - if suitIdx is not None: - merits = base.localAvatar.cogMerits[suitIdx] - if CogDisguiseGlobals.getTotalMerits(base.localAvatar, suitIdx) > merits: - self.rejectGroup(2, suitIdx) - return - parts = base.localAvatar.getCogParts() - if not CogDisguiseGlobals.isSuitComplete(parts, suitIdx): - self.rejectGroup(1) - return - base.cr.groupManager.d_addPlayerToGroup(groupId, base.localAvatar.doId) - self.currentGroupJoined = groupId - try: - place = base.cr.playGame.getPlace() - except: - try: - place = base.cr.playGame.hood.loader.place - except: - place = base.cr.playGame.hood.place - place.requestTeleport(groupId, groupId, base.localAvatar.defaultShard, -1) - - def leaveGroup(self, groupId, buttonTuple): - self.acceptOnce('confLeave', self.confirmLeaveGroup, extraArgs=[groupId, buttonTuple]) - self.joinDialog = TTDialog.TTGlobalDialog(message='Are you sure you want to leave this group?', doneEvent='confLeave', style=4) - - def confirmLeaveGroup(self, groupId, buttonTuple): - doneStatus = self.joinDialog.doneStatus - self.joinDialog.cleanup() - del self.joinDialog - if doneStatus is not 'ok': - return - if not base.cr.groupManager.isInGroup(base.localAvatar.doId, groupId): - return - base.cr.groupManager.d_removePlayerFromGroup(groupId, base.localAvatar.doId) - self.currentGroupJoined = None - try: - place = base.cr.playGame.getPlace() - except: - try: - place = base.cr.playGame.hood.loader.place - except: - place = base.cr.playGame.hood.place - hoodId = -1 - gids = {10000:1000, 11000:5000, 12000:9000, 13000:3000} - hoodId = gids.get(groupId) - if hoodId is None: - return - place.requestTeleport(hoodId, hoodId, base.localAvatar.defaultShard, -1) - def getPopColor(self, pop): if pop <= self.lowPop: newColor = POP_COLORS[0] @@ -483,7 +389,7 @@ class ShardPage(ShtikerPage.ShtikerPage): for i in xrange(len(curShardTuples)): - shardId, name, pop, invasionStatus = curShardTuples[i] + shardId, name, pop, invasionStatus, groupAvCount = curShardTuples[i] if shardId == actualShardId: actualShardName = name @@ -493,16 +399,19 @@ class ShardPage(ShtikerPage.ShtikerPage): buttonTuple = self.shardButtonMap.get(shardId) if buttonTuple == None: - buttonTuple = self.makeShardButton(shardId, name, pop) + buttonTuple = self.makeShardButton(shardId, groupAvCount, name, pop) self.shardButtonMap[shardId] = buttonTuple anyChanges = 1 else: buttonTuple[1]['image_color'] = self.getPopColor(pop) buttonTuple[1]['text'] = str(pop) buttonTuple[1]['command'] = self.reloadRightBrain - buttonTuple[1]['extraArgs'] = [pop, name, shardId, buttonTuple] + buttonTuple[1]['extraArgs'] = [pop, name, groupAvCount, shardId, buttonTuple] buttonTuple[2]['command'] = self.reloadRightBrain - buttonTuple[2]['extraArgs'] = [pop, name, shardId, buttonTuple] + buttonTuple[2]['extraArgs'] = [pop, name, groupAvCount, shardId, buttonTuple] + + for i, button in enumerate(self.shardText): + button['text'] = str(groupAvCount[i]) self.shardButtons.append(buttonTuple[0]) @@ -563,21 +472,18 @@ class ShardPage(ShtikerPage.ShtikerPage): del self.confirm def choseShard(self, shardId): - zoneId = self.getCurrentZoneId() - canonicalHoodId = ZoneUtil.getCanonicalHoodId(base.localAvatar.lastHood) - currentShardId = base.localAvatar.defaultShard + if not base.localAvatar.defaultShard == shardId: + self.requestTeleport(base.localAvatar.lastHood, shardId) + + def requestTeleport(self, hood, shardId): + canonicalHoodId = ZoneUtil.getCanonicalHoodId(hood) - if self.currentGroupJoined: - self.rejectGroup(5) - return - if shardId == currentShardId: - return - else: + try: + place = base.cr.playGame.getPlace() + except: try: - place = base.cr.playGame.getPlace() + place = base.cr.playGame.hood.loader.place except: - try: - place = base.cr.playGame.hood.loader.place - except: - place = base.cr.playGame.hood.place - place.requestTeleport(canonicalHoodId, canonicalHoodId, shardId, -1) + place = base.cr.playGame.hood.place + + place.requestTeleport(canonicalHoodId, canonicalHoodId, shardId, -1) \ No newline at end of file diff --git a/toontown/shtiker/ShtikerBook.py b/toontown/shtiker/ShtikerBook.py index bdd38eb2..0874ac99 100755 --- a/toontown/shtiker/ShtikerBook.py +++ b/toontown/shtiker/ShtikerBook.py @@ -45,8 +45,8 @@ class ShtikerBook(DirectFrame, StateData.StateData): TTLocalizer.GardenPageTitle, TTLocalizer.GolfPageTitle, TTLocalizer.PhotoPageTitle, - TTLocalizer.EventsPageName] - return + TTLocalizer.EventsPageName, + TTLocalizer.StatPageTitle] def setSafeMode(self, setting): self.safeMode = setting @@ -182,7 +182,7 @@ class ShtikerBook(DirectFrame, StateData.StateData): iconGeom = None iconImage = None iconScale = 1 - iconColor = Vec4(1) + iconColor = (1, 1, 1, 1) buttonPressedCommand = goToPage extraArgs = [] if pageName == TTLocalizer.OptionsPageTitle: @@ -251,6 +251,10 @@ class ShtikerBook(DirectFrame, StateData.StateData): iconGeom = iconModels = loader.loadModel('phase_4/models/minigames/photogame_filmroll') iconScale = (1.9, 1.5, 1.5) iconModels.detachNode() + elif pageName == TTLocalizer.StatPageTitle: + iconGeom = iconModels = loader.loadModel('phase_3.5/models/gui/name_star') + iconColor = (0, 0.6, 1, 1) + iconModels.detachNode() if pageName == TTLocalizer.OptionsPageTitle: pageName = TTLocalizer.OptionsTabTitle pageTab = DirectButton(parent=self.pageTabFrame, relief=DGG.RAISED, frameSize=(-0.575, diff --git a/toontown/shtiker/StatPage.py b/toontown/shtiker/StatPage.py new file mode 100644 index 00000000..9c38a7f8 --- /dev/null +++ b/toontown/shtiker/StatPage.py @@ -0,0 +1,79 @@ +from direct.gui.DirectGui import * +from toontown.toonbase import TTLocalizer +from toontown.toontowngui import TTDialog +import ShtikerPage + +STATS = ['cog', 'v2', 'skele', 'beanSpent', 'beanEarnt', 'task', 'vp', 'cfo', 'cj', 'ceo', 'sad', 'bldg', 'cogdo', 'item', 'fish', 'flower', 'race', 'golf', 'sos', 'unite', 'slip', 'gag'] + +class StatPage(ShtikerPage.ShtikerPage): + + def __init__(self): + ShtikerPage.ShtikerPage.__init__(self) + self.dialog = None + + def load(self): + guiButton = loader.loadModel('phase_3/models/gui/quit_button') + + self.rows = [None] * 2 + self.title = DirectLabel(parent=self, relief=None, text=TTLocalizer.StatPageTitle, text_scale=0.12, textMayChange=0, pos=(0, 0, 0.6)) + self.rows[0] = DirectLabel(parent=self, relief=None, text_align=TextNode.ALeft, text='', text_scale=0.06, text_wordwrap=16, pos=(-0.8, 0, 0.515)) + self.rows[1] = DirectLabel(parent=self, relief=None, text_align=TextNode.ALeft, text='', text_scale=0.06, text_wordwrap=16, pos=(0.05, 0, 0.515)) + self.resetButton = empty = DirectButton(parent=self, relief=None, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=(1.1, 1, 1), text='Reset stats', text_scale=0.055, text_pos=(0, -0.02), pos=(-0.55, 0.0, 0.65), command=self.__showDialog) + guiButton.removeNode() + + def enter(self): + self.show() + self.updateStats() + self.accept('refreshStats', self.updateStats) + + def exit(self): + self.ignoreAll() + self.unloadDialog() + self.hide() + + def unload(self): + for row in self.rows: + row.destroy() + + del self.rows + self.unloadDialog() + self.title.destroy() + del self.title + self.resetButton.destroy() + del self.resetButton + ShtikerPage.ShtikerPage.unload(self) + + def unloadDialog(self, arg=None): + if self.dialog: + self.dialog.destroy() + self.dialog = None + + def cutToChunks(self, list, size): + for i in xrange(0, len(list), size): + yield list[i:i+size] + + def updateStats(self): + dict = {} + stats = base.localAvatar.stats + + for i, string in enumerate(STATS): + dict[string] = "{:,}".format(stats[i]) + + textChunks = list(self.cutToChunks(TTLocalizer.Stats, 11)) + + for i, chunk in enumerate(textChunks): + self.rows[i]['text'] = '\n\n'.join(chunk) % dict + + def __showDialog(self): + self.dialog = TTDialog.TTDialog(style=TTDialog.TwoChoice, text=TTLocalizer.StatResetAsk, text_wordwrap=15, command=self.__handleDialogResponse) + self.dialog.show() + + def __handleDialogResponse(self, response): + self.unloadDialog() + + if response <= 0: + return + + base.localAvatar.wipeStats() + self.dialog = TTDialog.TTDialog(style=TTDialog.Acknowledge, text=TTLocalizer.StatResetDone, text_wordwrap=15, command=self.unloadDialog) + self.dialog.show() \ No newline at end of file diff --git a/toontown/shtiker/TIPPage.py b/toontown/shtiker/TIPPage.py deleted file mode 100755 index 06937bbc..00000000 --- a/toontown/shtiker/TIPPage.py +++ /dev/null @@ -1,34 +0,0 @@ -from panda3d.core import * -import ShtikerPage -from direct.gui.DirectGui import * -from toontown.toon import NPCToons -from toontown.hood import ZoneUtil -from toontown.toonbase import ToontownGlobals -from toontown.toonbase import TTLocalizer - -class TIPPage(ShtikerPage.ShtikerPage): - - def __init__(self): - ShtikerPage.ShtikerPage.__init__(self) - self.textRolloverColor = Vec4(1, 1, 0, 1) - self.textDownColor = Vec4(0.5, 0.9, 1, 1) - self.textDisabledColor = Vec4(0.4, 0.8, 0.4, 1) - - def load(self): - self.title = DirectLabel(parent=self, relief=None, text=TTLocalizer.TIPPageTitle, text_scale=0.12, textMayChange=0, pos=(0, 0, 0.6)) - return - - def unload(self): - del self.title - loader.unloadModel('phase_3.5/models/gui/stickerbook_gui') - ShtikerPage.ShtikerPage.unload(self) - - def updatePage(self): - pass - - def enter(self): - self.updatePage() - ShtikerPage.ShtikerPage.enter(self) - - def exit(self): - ShtikerPage.ShtikerPage.exit(self) diff --git a/toontown/suit/BossCog.py b/toontown/suit/BossCog.py index 3b88fd12..a3d861a2 100755 --- a/toontown/suit/BossCog.py +++ b/toontown/suit/BossCog.py @@ -34,7 +34,7 @@ class BossCog(Avatar.Avatar): def __init__(self): Avatar.Avatar.__init__(self) self.setFont(ToontownGlobals.getSuitFont()) - self.setSpeechFont(ToontownGlobals.getSuitFont()) + self.nametag.setSpeechFont(ToontownGlobals.getSuitFont()) self.setPlayerType(NametagGroup.CCSuit) self.setPickable(0) self.doorA = None @@ -56,7 +56,7 @@ class BossCog(Avatar.Avatar): self.healthCondition = 0 self.animDoneEvent = 'BossCogAnimDone' self.animIvalName = 'BossCogAnimIval' - return + self.warningSfx = loader.loadSfx('phase_9/audio/sfx/CHQ_GOON_tractor_beam_alarmed.ogg') def delete(self): Avatar.Avatar.delete(self) @@ -68,7 +68,6 @@ class BossCog(Avatar.Avatar): self.doorB.request('Off') self.doorA = None self.doorB = None - return def setDNAString(self, dnaString): self.dna = SuitDNA.SuitDNA() @@ -91,7 +90,7 @@ class BossCog(Avatar.Avatar): self.spinSfx = loader.loadSfx('phase_9/audio/sfx/CHQ_VP_spin.ogg') self.rainGearsSfx = loader.loadSfx('phase_9/audio/sfx/CHQ_VP_raining_gears.ogg') self.swishSfx = loader.loadSfx('phase_5/audio/sfx/General_throw_miss.ogg') - self.boomSfx = loader.loadSfx('phase_3.5/audio/sfx/ENC_cogfall_apart.ogg') + self.boomSfx = loader.loadSfx('phase_3.5/audio/sfx/ENC_cogfall_apart_%s.ogg' % random.randint(1, 6)) self.deathSfx = loader.loadSfx('phase_9/audio/sfx/CHQ_VP_big_death.ogg') self.upSfx = loader.loadSfx('phase_9/audio/sfx/CHQ_VP_raise_up.ogg') self.downSfx = loader.loadSfx('phase_9/audio/sfx/CHQ_VP_collapse.ogg') @@ -545,7 +544,10 @@ class BossCog(Avatar.Avatar): self.doAnimate(None, raised=1, happy=0, queueNeutral=0) else: self.doAnimate(None, raised=1, happy=1, queueNeutral=1) - ival = Parallel(ActorInterval(self, 'Fb_jump'), Sequence(Func(self.setChatAbsolute, random.choice(TTLocalizer.JumpBossTaunts[self.dna.dept]), CFSpeech | CFTimeout), SoundInterval(self.swishSfx, duration=1.1, node=self), SoundInterval(self.boomSfx, duration=1.9)), Sequence(Wait(1.21), Func(self.announceAreaAttack))) + ival = Sequence() + if self.dna.dept == 'm': + ival.append(Parallel(SoundInterval(self.warningSfx, node=self), Wait(5.0))) + ival.append(Parallel(ActorInterval(self, 'Fb_jump'), Sequence(Func(self.setChatAbsolute, random.choice(TTLocalizer.JumpBossTaunts[self.dna.dept]), CFSpeech | CFTimeout), SoundInterval(self.swishSfx, duration=1.1, node=self), SoundInterval(self.boomSfx, duration=1.9)), Sequence(Wait(1.21), Func(self.announceAreaAttack)))) if self.twoFaced: self.happy = 0 else: diff --git a/toontown/suit/DistributedBossCog.py b/toontown/suit/DistributedBossCog.py index c2a1089b..89704c59 100755 --- a/toontown/suit/DistributedBossCog.py +++ b/toontown/suit/DistributedBossCog.py @@ -44,6 +44,7 @@ class DistributedBossCog(DistributedAvatar.DistributedAvatar, BossCog.BossCog): self.battleB = None self.battleRequest = None self.arenaSide = 0 + self.keyReward = False self.toonSphere = None self.localToonIsSafe = 0 self.__toonsStuckToFloor = [] @@ -303,6 +304,9 @@ class DistributedBossCog(DistributedAvatar.DistributedAvatar, BossCog.BossCog): def setArenaSide(self, arenaSide): self.arenaSide = arenaSide + + def setKeyReward(self, reward): + self.keyReward = reward def setState(self, state): self.request(state) diff --git a/toontown/suit/DistributedBossCogAI.py b/toontown/suit/DistributedBossCogAI.py index 6b1ba371..7d82d1f3 100755 --- a/toontown/suit/DistributedBossCogAI.py +++ b/toontown/suit/DistributedBossCogAI.py @@ -13,6 +13,13 @@ import SuitDNA import random AllBossCogs = [] +BOSS_TO_STAT = { + 's': ToontownGlobals.STAT_VP, + 'm': ToontownGlobals.STAT_CFO, + 'l': ToontownGlobals.STAT_CJ, + 'c': ToontownGlobals.STAT_CEO +} + class DistributedBossCogAI(DistributedAvatarAI.DistributedAvatarAI): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedBossCogAI') @@ -44,8 +51,8 @@ class DistributedBossCogAI(DistributedAvatarAI.DistributedAvatarAI): self.attackCode = None self.attackAvId = 0 self.hitCount = 0 + self.keyReward = config.GetBool('get-key-reward-always', False) or random.random() <= 0.15 AllBossCogs.append(self) - return def delete(self): self.ignoreAll() @@ -145,6 +152,10 @@ class DistributedBossCogAI(DistributedAvatarAI.DistributedAvatarAI): def d_setBattleExperience(self): self.sendUpdate('setBattleExperience', self.getBattleExperience()) + for toonId in self.involvedToons: + toon = simbase.air.doId2do.get(toonId) + if toon: + self.air.topToonsMgr.toonKilledBoss(toon, self.BossName) def getBattleExperience(self): result = BattleExperienceAI.getBattleExperience(8, self.involvedToons, self.toonExp, self.toonSkillPtsGained, self.toonOrigQuests, self.toonItems, self.toonOrigMerits, self.toonMerits, self.toonParts, self.suitsKilled, self.helpfulToons) @@ -178,6 +189,9 @@ class DistributedBossCogAI(DistributedAvatarAI.DistributedAvatarAI): def getState(self): return self.state + + def getKeyReward(self): + return self.keyReward def formatReward(self): return 'unspecified' @@ -255,7 +269,7 @@ class DistributedBossCogAI(DistributedAvatarAI.DistributedAvatarAI): pass def enterEpilogue(self): - pass + self.giveKeyReward() def exitEpilogue(self): pass @@ -583,6 +597,8 @@ class DistributedBossCogAI(DistributedAvatarAI.DistributedAvatarAI): delayTime = ToontownGlobals.BossCogAttackTimes.get(attackCode) if delayTime == None: return + if self.dept == 'm' and attackCode == ToontownGlobals.BossCogAreaAttack: + delayTime += 5.0 self.waitForNextAttack(delayTime) return @@ -602,3 +618,22 @@ class DistributedBossCogAI(DistributedAvatarAI.DistributedAvatarAI): def doNextAttack(self, task): self.b_setAttackCode(ToontownGlobals.BossCogNoAttack) + + def giveKeyReward(self): + if not self.keyReward: + return + + for toonId in self.involvedToons: + toon = self.air.doId2do.get(toonId) + + if toon: + toon.addCrateKeys(1) + + def addStats(self): + stat = BOSS_TO_STAT[self.dept] + + for toonId in self.involvedToons: + toon = self.air.doId2do.get(toonId) + + if toon: + toon.addStat(stat) \ No newline at end of file diff --git a/toontown/suit/DistributedBossbotBoss.py b/toontown/suit/DistributedBossbotBoss.py index 0fb4c400..132fed89 100755 --- a/toontown/suit/DistributedBossbotBoss.py +++ b/toontown/suit/DistributedBossbotBoss.py @@ -861,6 +861,10 @@ class DistributedBossbotBoss(DistributedBossCog.DistributedBossCog, FSM.FSM): speech += TTLocalizer.BossbotRTHPBoost else: speech += TTLocalizer.BossbotRTMaxed % (ToontownGlobals.MaxCogSuitLevel + 1) + + if self.keyReward: + speech += TTLocalizer.BossRTKeyReward + return speech def __arrangeToonsAroundResistanceToonForReward(self): diff --git a/toontown/suit/DistributedBossbotBossAI.py b/toontown/suit/DistributedBossbotBossAI.py index ae453cec..c90dd4f1 100755 --- a/toontown/suit/DistributedBossbotBossAI.py +++ b/toontown/suit/DistributedBossbotBossAI.py @@ -28,6 +28,7 @@ class DistributedBossbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FS 2, 3, 4] + BossName = "CEO" def __init__(self, air): DistributedBossCogAI.DistributedBossCogAI.__init__(self, air, 'c') @@ -579,6 +580,7 @@ class DistributedBossbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FS 'isSupervisor': 0, 'isVirtual': 0, 'activeToons': self.involvedToons[:]}) + self.addStats() self.barrier = self.beginBarrier('Victory', self.involvedToons, 30, self.__doneVictory) return diff --git a/toontown/suit/DistributedCashbotBoss.py b/toontown/suit/DistributedCashbotBoss.py index ec868102..2b89025c 100755 --- a/toontown/suit/DistributedCashbotBoss.py +++ b/toontown/suit/DistributedCashbotBoss.py @@ -497,7 +497,7 @@ class DistributedCashbotBoss(DistributedBossCog.DistributedBossCog, FSM.FSM): car1 = loader.loadModel('phase_10/models/cogHQ/CashBotBoxCar') car2 = loader.loadModel('phase_10/models/cogHQ/CashBotTankCar') trainPassingSfx = base.loadSfx('phase_10/audio/sfx/CBHQ_TRAIN_pass.ogg') - boomSfx = loader.loadSfx('phase_3.5/audio/sfx/ENC_cogfall_apart.ogg') + boomSfx = loader.loadSfx('phase_3.5/audio/sfx/ENC_cogfall_apart_%s.ogg' % random.randint(1, 6)) rollThroughDoor = self.rollBossToPoint(fromPos=Point3(120, -280, 0), fromHpr=None, toPos=Point3(120, -250, 0), toHpr=None, reverse=0) rollTrack = Sequence(Func(self.getGeomNode().setH, 180), rollThroughDoor[0], Func(self.getGeomNode().setH, 0)) g = 80.0 / 300.0 @@ -659,6 +659,10 @@ class DistributedCashbotBoss(DistributedBossCog.DistributedBossCog, FSM.FSM): speech += TTLocalizer.ResistanceToonHPBoost else: speech += TTLocalizer.ResistanceToonMaxed % (ToontownGlobals.MaxCogSuitLevel + 1) + + if self.keyReward: + speech += TTLocalizer.BossRTKeyReward + return speech def enterOff(self): diff --git a/toontown/suit/DistributedCashbotBossAI.py b/toontown/suit/DistributedCashbotBossAI.py index 49e1f196..4dd14e16 100755 --- a/toontown/suit/DistributedCashbotBossAI.py +++ b/toontown/suit/DistributedCashbotBossAI.py @@ -17,6 +17,7 @@ import math class DistributedCashbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FSM): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedCashbotBossAI') maxGoons = 8 + BossName = "CFO" def __init__(self, air): DistributedBossCogAI.DistributedBossCogAI.__init__(self, air, 'm') @@ -142,10 +143,18 @@ class DistributedCashbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FS return def doNextAttack(self, task): - self.__doDirectedAttack() - if self.heldObject == None and not self.waitingForHelmet: - self.waitForNextHelmet() - return + if random.random() <= 0.2: + self.b_setAttackCode(ToontownGlobals.BossCogAreaAttack) + taskMgr.doMethodLater(9.36, self.__reviveGoons, self.uniqueName('reviveGoons')) + else: + self.__doDirectedAttack() + if self.heldObject == None and not self.waitingForHelmet: + self.waitForNextHelmet() + + def __reviveGoons(self, task): + for goon in self.goons: + if goon.state == 'Stunned': + goon.request('Recovery') def __doDirectedAttack(self): if self.toonsToAttack: @@ -166,7 +175,6 @@ class DistributedCashbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FS self.toonsToAttack.append(avId) def makeTreasure(self, goon): - return if self.state != 'BattleThree': return pos = goon.getPos(self) @@ -284,6 +292,7 @@ class DistributedCashbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FS def stopGoons(self): taskName = self.uniqueName('NextGoon') taskMgr.remove(taskName) + taskMgr.remove(self.uniqueName('reviveGoons')) def doNextGoon(self, task): if self.attackCode != ToontownGlobals.BossCogDizzy: @@ -462,6 +471,7 @@ class DistributedCashbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FS 'isSupervisor': 0, 'isVirtual': 0, 'activeToons': self.involvedToons[:]}) + self.addStats() self.barrier = self.beginBarrier('Victory', self.involvedToons, 30, self.__doneVictory) return diff --git a/toontown/suit/DistributedLawbotBoss.py b/toontown/suit/DistributedLawbotBoss.py index 683393f8..2ee4b9da 100755 --- a/toontown/suit/DistributedLawbotBoss.py +++ b/toontown/suit/DistributedLawbotBoss.py @@ -78,7 +78,6 @@ class DistributedLawbotBoss(DistributedBossCog.DistributedBossCog, FSM.FSM): self.evidenceHitSfx = None self.toonUpSfx = None self.bonusTimer = None - self.warningSfx = None self.juryMovesSfx = None self.baseColStashed = False self.battleDifficulty = 0 @@ -98,7 +97,6 @@ class DistributedLawbotBoss(DistributedBossCog.DistributedBossCog, FSM.FSM): self.piesRestockSfx = loader.loadSfx('phase_5/audio/sfx/LB_receive_evidence.ogg') self.rampSlideSfx = loader.loadSfx('phase_9/audio/sfx/CHQ_VP_ramp_slide.ogg') self.evidenceHitSfx = loader.loadSfx('phase_11/audio/sfx/LB_evidence_hit.ogg') - self.warningSfx = loader.loadSfx('phase_9/audio/sfx/CHQ_GOON_tractor_beam_alarmed.ogg') self.juryMovesSfx = loader.loadSfx('phase_11/audio/sfx/LB_jury_moves.ogg') self.toonUpSfx = loader.loadSfx('phase_11/audio/sfx/LB_toonup.ogg') self.strafeSfx = [] @@ -1643,6 +1641,10 @@ class DistributedLawbotBoss(DistributedBossCog.DistributedBossCog, FSM.FSM): speech += TTLocalizer.WitnessToonHPBoost else: speech += TTLocalizer.WitnessToonMaxed % (ToontownGlobals.MaxCogSuitLevel + 1) + + if self.keyReward: + speech += TTLocalizer.BossRTKeyReward + return speech def __positionToonsInFrontOfCannons(self): diff --git a/toontown/suit/DistributedLawbotBossAI.py b/toontown/suit/DistributedLawbotBossAI.py index 2f1fd77d..102ad9e4 100755 --- a/toontown/suit/DistributedLawbotBossAI.py +++ b/toontown/suit/DistributedLawbotBossAI.py @@ -29,6 +29,7 @@ class DistributedLawbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FSM hitCountDamage = 35 numPies = 10 maxToonLevels = 77 + BossName = "CJ" def __init__(self, air): DistributedBossCogAI.DistributedBossCogAI.__init__(self, air, 'l') @@ -637,6 +638,7 @@ class DistributedLawbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FSM 'isSupervisor': 0, 'isVirtual': 0, 'activeToons': self.involvedToons[:]}) + self.addStats() self.barrier = self.beginBarrier('Victory', self.involvedToons, 30, self.__doneVictory) return diff --git a/toontown/suit/DistributedSellbotBoss.py b/toontown/suit/DistributedSellbotBoss.py index 529bb821..d0386886 100755 --- a/toontown/suit/DistributedSellbotBoss.py +++ b/toontown/suit/DistributedSellbotBoss.py @@ -457,6 +457,12 @@ class DistributedSellbotBoss(DistributedBossCog.DistributedBossCog, FSM.FSM): speech += TTLocalizer.CagedToonHPBoost else: speech += TTLocalizer.CagedToonMaxed % (ToontownGlobals.MaxCogSuitLevel + 1) + + if self.keyReward: + speech += TTLocalizer.BossRTKeyReward + + return speech + return speech def __makeCageOpenMovie(self): diff --git a/toontown/suit/DistributedSellbotBossAI.py b/toontown/suit/DistributedSellbotBossAI.py index a5590795..82a740a2 100755 --- a/toontown/suit/DistributedSellbotBossAI.py +++ b/toontown/suit/DistributedSellbotBossAI.py @@ -20,6 +20,7 @@ class DistributedSellbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FS limitHitCount = 6 hitCountDamage = 35 numPies = ToontownGlobals.FullPies + BossName = "VP" def __init__(self, air): DistributedBossCogAI.DistributedBossCogAI.__init__(self, air, 's') @@ -338,6 +339,7 @@ class DistributedSellbotBossAI(DistributedBossCogAI.DistributedBossCogAI, FSM.FS 'isSupervisor': 0, 'isVirtual': 0, 'activeToons': self.involvedToons[:]}) + self.addStats() self.barrier = self.beginBarrier('Victory', self.involvedToons, 10, self.__doneVictory) return diff --git a/toontown/suit/GoonDeath.py b/toontown/suit/GoonDeath.py index a48c1fec..6bd3198c 100755 --- a/toontown/suit/GoonDeath.py +++ b/toontown/suit/GoonDeath.py @@ -2,6 +2,7 @@ from direct.interval.IntervalGlobal import * from panda3d.core import * from direct.particles import ParticleEffect from toontown.battle import BattleParticles +import random def createExplosionTrack(parent, deathNode, scale): explosion = loader.loadModel('phase_3.5/models/props/explosion.bam') @@ -19,5 +20,5 @@ def createGoonExplosion(parent, explosionPoint, scale): explosion = createExplosionTrack(parent, deathNode, scale) smallGearExplosion = BattleParticles.createParticleEffect('GearExplosion', numParticles=10) bigGearExplosion = BattleParticles.createParticleEffect('WideGearExplosion', numParticles=30) - deathSound = base.loadSfx('phase_3.5/audio/sfx/ENC_cogfall_apart.ogg') + deathSound = base.loadSfx('phase_3.5/audio/sfx/ENC_cogfall_apart_%s.ogg' % random.randint(1, 6)) return Parallel(explosion, SoundInterval(deathSound), ParticleInterval(smallGearExplosion, deathNode, worldRelative=0, duration=4.3, cleanup=True), ParticleInterval(bigGearExplosion, deathNode, worldRelative=0, duration=1.0, cleanup=True), name='gears2MTrack') diff --git a/toontown/suit/Suit.py b/toontown/suit/Suit.py index bd5afc57..f2b734f5 100755 --- a/toontown/suit/Suit.py +++ b/toontown/suit/Suit.py @@ -333,7 +333,7 @@ class Suit(Avatar.Avatar): Avatar.Avatar.__init__(self) self.setFont(ToontownGlobals.getSuitFont()) - self.setSpeechFont(ToontownGlobals.getSuitFont()) + self.nametag.setSpeechFont(ToontownGlobals.getSuitFont()) self.setPlayerType(NametagGroup.CCSuit) self.setPickable(1) self.leftHand = None diff --git a/toontown/suit/SuitDNA.py b/toontown/suit/SuitDNA.py index f2ebf1e3..62b039b1 100755 --- a/toontown/suit/SuitDNA.py +++ b/toontown/suit/SuitDNA.py @@ -86,6 +86,11 @@ suitDeptFullnamesP = {'c': TTLocalizer.BossbotP, 'l': TTLocalizer.LawbotP, 'm': TTLocalizer.CashbotP, 's': TTLocalizer.SellbotP} +suitDeptFilenames = {'c': 'boss', + 'l': 'law', + 'm': 'cash', + 's': 'sell' +} suitDeptModelPaths = {'c': '**/CorpIcon', 0: '**/CorpIcon', 'l': '**/LegalIcon', diff --git a/toontown/suit/SuitInvasionManagerAI.py b/toontown/suit/SuitInvasionManagerAI.py index cf1a595b..055bf96e 100755 --- a/toontown/suit/SuitInvasionManagerAI.py +++ b/toontown/suit/SuitInvasionManagerAI.py @@ -18,14 +18,14 @@ class SuitInvasionManagerAI: self.suitTypeIndex = None self.flags = 0 - self.air.netMessenger.accept( - 'startInvasion', self, self.handleStartInvasion) - self.air.netMessenger.accept( - 'stopInvasion', self, self.handleStopInvasion) + self.air.accept( + 'startInvasion', self.handleStartInvasion) + self.air.accept( + 'stopInvasion', self.handleStopInvasion) # We want to handle shard status queries so that a ShardStatusReceiver # being created after we're created will know where we're at: - self.air.netMessenger.accept('queryShardStatus', self, self.sendInvasionStatus) + self.air.accept('queryShardStatus', self.sendInvasionStatus) self.sendInvasionStatus() @@ -224,4 +224,4 @@ class SuitInvasionManagerAI: } else: status = {'invasion': None} - self.air.netMessenger.send('shardStatus', [self.air.ourChannel, status]) + self.air.sendNetEvent('shardStatus', [self.air.ourChannel, status]) diff --git a/toontown/toon/DistributedNPCClerk.py b/toontown/toon/DistributedNPCClerk.py index e36c8c1d..74cc15f0 100755 --- a/toontown/toon/DistributedNPCClerk.py +++ b/toontown/toon/DistributedNPCClerk.py @@ -1,120 +1,85 @@ -from direct.interval.IntervalGlobal import Sequence -from direct.task.Task import Task -from panda3d.core import * - -from DistributedNPCToonBase import * -import NPCToons -from toontown.hood import ZoneUtil +from otp.nametag.NametagConstants import CFSpeech, CFTimeout from toontown.minigame import ClerkPurchase -from toontown.shtiker.PurchaseManagerConstants import * -from toontown.toonbase import TTLocalizer -from otp.nametag.NametagConstants import * - +from toontown.toonbase import TTLocalizer, ToontownGlobals +from toontown.toon import NPCToons +from DistributedNPCToonBase import DistributedNPCToonBase +import time class DistributedNPCClerk(DistributedNPCToonBase): + def __init__(self, cr): DistributedNPCToonBase.__init__(self, cr) - - self.purchase = None - self.isLocalToon = 0 - self.av = None - self.purchaseDoneEvent = 'purchaseDone' + self.lastCollision = 0 + self.purchaseGui = None def disable(self): - self.ignoreAll() - taskMgr.remove(self.uniqueName('popupPurchaseGUI')) - taskMgr.remove(self.uniqueName('lerpCamera')) - if self.purchase: - self.purchase.exit() - self.purchase.unload() - self.purchase = None - self.av = None - base.localAvatar.posCamera(0, 0) - + self.destroyDialog() DistributedNPCToonBase.disable(self) - def handleCollisionSphereEnter(self, collEntry): - base.cr.playGame.getPlace().fsm.request('purchase') - self.sendUpdate('avatarEnter', []) - - def __handleUnexpectedExit(self): - self.notify.warning('unexpected exit') - self.av = None - - def resetClerk(self): + def destroyDialog(self): self.ignoreAll() + self.clearChat() taskMgr.remove(self.uniqueName('popupPurchaseGUI')) taskMgr.remove(self.uniqueName('lerpCamera')) - if self.purchase: - self.purchase.exit() - self.purchase.unload() - self.purchase = None - self.clearMat() - self.startLookAround() - self.detectAvatars() - if self.isLocalToon: - self.showNametag2d() - self.freeAvatar() - return Task.done - def setMovie(self, mode, npcId, avId, timestamp): - timeStamp = ClockDelta.globalClockDelta.localElapsedTime(timestamp) - self.remain = NPCToons.CLERK_COUNTDOWN_TIME - timeStamp - self.isLocalToon = avId == base.localAvatar.doId - if mode == NPCToons.PURCHASE_MOVIE_CLEAR: + if self.purchaseGui: + self.purchaseGui.exit() + self.purchaseGui.unload() + self.purchaseGui = None + + def freeAvatar(self): + base.localAvatar.posCamera(0, 0) + base.cr.playGame.getPlace().fsm.request('walk') + + def handleCollisionSphereEnter(self, collEntry): + if self.lastCollision > time.time(): return - if mode == NPCToons.PURCHASE_MOVIE_TIMEOUT: - taskMgr.remove(self.uniqueName('popupPurchaseGUI')) - taskMgr.remove(self.uniqueName('lerpCamera')) - if self.isLocalToon: - self.ignore(self.purchaseDoneEvent) - if self.purchase: - self.__handlePurchaseDone() - self.setChatAbsolute(TTLocalizer.STOREOWNER_TOOKTOOLONG, CFSpeech | CFTimeout) - self.resetClerk() - elif mode == NPCToons.PURCHASE_MOVIE_START: - if self.isLocalToon: - self.hideNametag2d() - self.av = base.cr.doId2do.get(avId) - if self.av is None: - self.notify.warning('Avatar %d not found in doId' % avId) - return - else: - self.accept(self.av.uniqueName('disable'), self.__handleUnexpectedExit) - self.setupAvatars(self.av) - if self.isLocalToon: - camera.wrtReparentTo(render) - seq = Sequence((camera.posQuatInterval(1, Vec3(-5, 9, self.getHeight() - 0.5), Vec3(-150, -2, 0), other=self, blendType='easeOut', name=self.uniqueName('lerpCamera')))) - seq.start() - self.setChatAbsolute(TTLocalizer.STOREOWNER_GREETING, CFSpeech | CFTimeout) - if self.isLocalToon: - taskMgr.doMethodLater(1.0, self.popupPurchaseGUI, self.uniqueName('popupPurchaseGUI')) - elif mode == NPCToons.PURCHASE_MOVIE_COMPLETE: - self.setChatAbsolute(TTLocalizer.STOREOWNER_GOODBYE, CFSpeech | CFTimeout) - self.resetClerk() - elif mode == NPCToons.PURCHASE_MOVIE_NO_MONEY: + + self.lastCollision = time.time() + ToontownGlobals.NPCCollisionDelay + + if not base.localAvatar.getMoney(): self.setChatAbsolute(TTLocalizer.STOREOWNER_NEEDJELLYBEANS, CFSpeech | CFTimeout) - self.resetClerk() - return + return + + self.d_setState(ToontownGlobals.CLERK_GREETING) + base.cr.playGame.getPlace().fsm.request('purchase') + camera.wrtReparentTo(render) + camera.posQuatInterval(1, Vec3(-5, 9, self.getHeight() - 0.5), Vec3(-150, -2, 0), other=self, blendType='easeOut', name=self.uniqueName('lerpCamera')).start() + taskMgr.doMethodLater(1.0, self.popupPurchaseGUI, self.uniqueName('popupPurchaseGUI')) + + def d_setInventory(self, inventory, money): + self.sendUpdate('setInventory', [inventory, money]) + + def d_setState(self, state): + self.sendUpdate('setState', [0, state]) + + def setState(self, avId, state): + av = base.cr.doId2do.get(avId) + if not av: + return + + if state == ToontownGlobals.CLERK_GOODBYE: + self.setChatAbsolute(TTLocalizer.STOREOWNER_GOODBYE, CFSpeech | CFTimeout) + elif state == ToontownGlobals.CLERK_GREETING: + self.lookAtAvatar(av) + self.setChatAbsolute(TTLocalizer.STOREOWNER_GREETING, CFSpeech | CFTimeout) + return + elif state == ToontownGlobals.CLERK_TOOKTOOLONG: + self.setChatAbsolute(TTLocalizer.STOREOWNER_TOOKTOOLONG, CFSpeech | CFTimeout) + + self.initToonState() + def popupPurchaseGUI(self, task): - self.setChatAbsolute('', CFSpeech) - self.acceptOnce(self.purchaseDoneEvent, self.__handlePurchaseDone) - self.accept('boughtGag', self.__handleBoughtGag) - self.purchase = ClerkPurchase.ClerkPurchase(base.localAvatar, self.remain, self.purchaseDoneEvent) - self.purchase.load() - self.purchase.enter() - return Task.done + self.clearChat() + self.acceptOnce('purchaseClerkDone', self.__handlePurchaseDone) + self.purchaseGui = ClerkPurchase.ClerkPurchase(base.localAvatar, NPCToons.CLERK_COUNTDOWN_TIME, 'purchaseClerkDone') + self.purchaseGui.load() + self.purchaseGui.enter() - def __handleBoughtGag(self): - self.d_setInventory(base.localAvatar.inventory.makeNetString(), base.localAvatar.getMoney(), 0) - - def __handlePurchaseDone(self): - self.ignore('boughtGag') - self.d_setInventory(base.localAvatar.inventory.makeNetString(), base.localAvatar.getMoney(), 1) - self.purchase.exit() - self.purchase.unload() - self.purchase = None - - def d_setInventory(self, invString, money, done): - self.sendUpdate('setInventory', [invString, money, done]) + def __handlePurchaseDone(self, state): + self.d_setInventory(base.localAvatar.inventory.makeNetString(), base.localAvatar.getMoney()) + self.destroyDialog() + self.freeAvatar() + self.detectAvatars() + self.d_setState(state) \ No newline at end of file diff --git a/toontown/toon/DistributedNPCClerkAI.py b/toontown/toon/DistributedNPCClerkAI.py index be608c6d..6e24e6bc 100755 --- a/toontown/toon/DistributedNPCClerkAI.py +++ b/toontown/toon/DistributedNPCClerkAI.py @@ -1,108 +1,15 @@ -from otp.ai.AIBaseGlobal import * -from direct.task.Task import Task -from panda3d.core import * -from DistributedNPCToonBaseAI import * +from DistributedNPCToonBaseAI import DistributedNPCToonBaseAI class DistributedNPCClerkAI(DistributedNPCToonBaseAI): - def __init__(self, air, npcId): - DistributedNPCToonBaseAI.__init__(self, air, npcId) - self.timedOut = 0 + def setInventory(self, inventory, money): + av = self.air.doId2do.get(self.air.getAvatarIdFromSender()) - def delete(self): - taskMgr.remove(self.uniqueName('clearMovie')) - self.ignoreAll() - DistributedNPCToonBaseAI.delete(self) - - def avatarEnter(self): - avId = self.air.getAvatarIdFromSender() - DistributedNPCToonBaseAI.avatarEnter(self) - av = self.air.doId2do.get(avId) - if av is None: - self.notify.warning('toon isnt there! toon: %s' % avId) + if not av: return - self.acceptOnce(self.air.getAvatarExitEvent(avId), self.__handleUnexpectedExit, extraArgs=[avId]) - if self.isBusy(): - self.freeAvatar(avId) - return - if av.getMoney(): - self.sendStartMovie(avId) - else: - self.sendNoMoneyMovie(avId) - def sendStartMovie(self, avId): - self.busy = avId - self.sendUpdate('setMovie', [NPCToons.PURCHASE_MOVIE_START, - self.npcId, - avId, - ClockDelta.globalClockDelta.getRealNetworkTime()]) - taskMgr.doMethodLater(NPCToons.CLERK_COUNTDOWN_TIME, self.sendTimeoutMovie, self.uniqueName('clearMovie')) - - def sendNoMoneyMovie(self, avId): - self.busy = avId - self.sendUpdate('setMovie', [NPCToons.PURCHASE_MOVIE_NO_MONEY, - self.npcId, - avId, - ClockDelta.globalClockDelta.getRealNetworkTime()]) - self.sendClearMovie(None) - return - - def sendTimeoutMovie(self, task): - self.timedOut = 1 - self.sendUpdate('setMovie', [NPCToons.PURCHASE_MOVIE_TIMEOUT, - self.npcId, - self.busy, - ClockDelta.globalClockDelta.getRealNetworkTime()]) - self.sendClearMovie(None) - return Task.done - - def sendClearMovie(self, task): - self.ignore(self.air.getAvatarExitEvent(self.busy)) - self.busy = 0 - self.timedOut = 0 - self.sendUpdate('setMovie', [NPCToons.PURCHASE_MOVIE_CLEAR, - self.npcId, - 0, - ClockDelta.globalClockDelta.getRealNetworkTime()]) - return Task.done - - def completePurchase(self, avId): - self.busy = avId - self.sendUpdate('setMovie', [NPCToons.PURCHASE_MOVIE_COMPLETE, - self.npcId, - avId, - ClockDelta.globalClockDelta.getRealNetworkTime()]) - self.sendClearMovie(None) - return - - def setInventory(self, blob, newMoney, done): - avId = self.air.getAvatarIdFromSender() - if self.busy != avId: - if self.busy != 0: - self.air.writeServerEvent('suspicious', avId, 'DistributedNPCClerkAI.setInventory busy with %s' % self.busy) - self.notify.warning('setInventory from unknown avId: %s busy: %s' % (avId, self.busy)) - return - if avId in self.air.doId2do: - av = self.air.doId2do[avId] - newInventory = av.inventory.makeFromNetString(blob) - currentMoney = av.getMoney() - if av.inventory.validatePurchase(newInventory, currentMoney, newMoney): - av.setMoney(newMoney) - if done: - av.d_setInventory(av.inventory.makeNetString()) - av.d_setMoney(newMoney) - else: - self.air.writeServerEvent('suspicious', avId, 'DistributedNPCClerkAI.setInventory invalid purchase') - self.notify.warning('Avatar ' + str(avId) + ' attempted an invalid purchase.') - av.d_setInventory(av.inventory.makeNetString()) - av.d_setMoney(av.getMoney()) - if self.timedOut: - return - if done: - taskMgr.remove(self.uniqueName('clearMovie')) - self.completePurchase(avId) - - def __handleUnexpectedExit(self, avId): - self.notify.warning('avatar:' + str(avId) + ' has exited unexpectedly') - self.sendTimeoutMovie(None) - return + av.b_setMoney(money if av.inventory.validatePurchase(av.inventory.makeFromNetString(inventory), av.getMoney(), money) else av.getMoney()) + av.d_setInventory(av.inventory.makeNetString()) + + def setState(self, avId, state): + self.sendUpdate('setState', [self.air.getAvatarIdFromSender(), state]) \ No newline at end of file diff --git a/toontown/toon/DistributedNPCGloveAI.py b/toontown/toon/DistributedNPCGloveAI.py index 0cc61df5..b6c57cd6 100755 --- a/toontown/toon/DistributedNPCGloveAI.py +++ b/toontown/toon/DistributedNPCGloveAI.py @@ -22,6 +22,6 @@ class DistributedNPCGloveAI(DistributedNPCToonBaseAI.DistributedNPCToonBaseAI): av.takeMoney(ToontownGlobals.GloveCost) newDNA = ToonDNA.ToonDNA() newDNA.makeFromNetString(av.getDNAString()) - newDNA.gloveColor = color + newDNA.gloveColor = ToonDNA.allColorsList[color] taskMgr.doMethodLater(1.0, lambda task: av.b_setDNAString(newDNA.makeNetString()), 'transform-%d' % avId) self.sendUpdate('changeGloveResult', [avId, GloveNPCGlobals.CHANGE_SUCCESSFUL]) diff --git a/toontown/toon/DistributedNPCLaffRestock.py b/toontown/toon/DistributedNPCLaffRestock.py index 56ca430b..733398fa 100755 --- a/toontown/toon/DistributedNPCLaffRestock.py +++ b/toontown/toon/DistributedNPCLaffRestock.py @@ -1,121 +1,71 @@ -from panda3d.core import * -from direct.distributed import ClockDelta from otp.nametag.NametagConstants import CFSpeech, CFTimeout from toontown.toonbase import TTLocalizer, ToontownGlobals -from toontown.toontowngui import TTDialog from toontown.toon import NPCToons from DistributedNPCToonBase import DistributedNPCToonBase -import LaffRestockGlobals -from LaffShopGui import * +import LaffRestockGlobals, LaffShopGui, time class DistributedNPCLaffRestock(DistributedNPCToonBase): - zone2id = { - 10000: 0, - 13000: 1, - 12000: 2, - 11000: 3, - } - def __init__(self, cr): DistributedNPCToonBase.__init__(self, cr) - self.isLocalToon = 0 - self.av = None - self.laffGui = None + self.lastCollision = 0 + self.laffDialog = None def disable(self): self.ignoreAll() - if self.laffGui: - self.laffGui.destroy() - self.laffGui = None - self.av = None + self.destroyDialog() DistributedNPCToonBase.disable(self) + def destroyDialog(self): + self.clearChat() + + if self.laffDialog: + self.laffDialog.destroy() + self.laffDialog = None + def initToonState(self): self.setAnimState('neutral', 0.9, None, None) + self.putOnSuit(ToontownGlobals.cogHQZoneId2deptIndex(self.zoneId), rental=True) + if self.name in NPCToons.LaffRestockPositions: pos = NPCToons.LaffRestockPositions[self.name] self.setPos(*pos[0]) self.setH(pos[1]) - self.putOnSuit(self.zone2id.get(self.zoneId, -1), rental=True) def getCollSphereRadius(self): - return 3.0 + return 1.25 def handleCollisionSphereEnter(self, collEntry): - base.cr.playGame.getPlace().fsm.request('purchase') - self.sendUpdate('avatarEnter', []) - - def __handleUnexpectedExit(self): - self.notify.warning('unexpected exit') - self.av = None - - def resetLaffClerk(self): - self.ignoreAll() - if self.laffGui: - self.laffGui.destroy() - self.laffGui = None - self.show() - self.startLookAround() - self.detectAvatars() - if self.isLocalToon: - self.showNametag2d() - self.freeAvatar() - return Task.done - - def setMovie(self, mode, npcId, avId, extraArgs, timestamp): - timeStamp = ClockDelta.globalClockDelta.localElapsedTime(timestamp) - self.remain = NPCToons.CLERK_COUNTDOWN_TIME - timeStamp - self.npcId = npcId - self.isLocalToon = avId == base.localAvatar.doId - if mode == NPCToons.SELL_MOVIE_CLEAR: + if self.lastCollision > time.time(): return - if mode == NPCToons.SELL_MOVIE_TIMEOUT: - if self.isLocalToon: - if self.laffGui: - self.laffGui.destroy() - self.laffGui = None - self.setChatAbsolute(TTLocalizer.STOREOWNER_TOOKTOOLONG, CFSpeech | CFTimeout) - self.resetLaffClerk() - elif mode == NPCToons.SELL_MOVIE_START: - self.av = base.cr.doId2do.get(avId) - if self.av is None: - self.notify.warning('Avatar %d not found in doId' % avId) - return - else: - self.accept(self.av.uniqueName('disable'), self.__handleUnexpectedExit) - self.setupAvatars(self.av) - if self.isLocalToon: - self.hideNametag2d() - laff = self.av.getMaxHp() - self.av.getHp() - cost = laff * ToontownGlobals.CostPerLaffRestock - self.popupLaffGUI(laff, cost) - elif mode == NPCToons.SELL_MOVIE_COMPLETE: - self.setChatAbsolute(TTLocalizer.RestockLaffMessage, CFSpeech | CFTimeout) - self.resetLaffClerk() - elif mode == LaffRestockGlobals.FullLaff: + + self.lastCollision = time.time() + ToontownGlobals.NPCCollisionDelay + self.lookAt(base.localAvatar) + + if base.localAvatar.getHp() >= base.localAvatar.getMaxHp(): self.setChatAbsolute(TTLocalizer.RestockFullLaffMessage, CFSpeech | CFTimeout) - self.resetLaffClerk() - elif mode == LaffRestockGlobals.NoMoney: - self.setChatAbsolute(TTLocalizer.RestockNoMoneyMessage, CFSpeech | CFTimeout) - self.resetLaffClerk() - elif mode == NPCToons.SELL_MOVIE_CHEATER: - self.setChatAbsolute(TTLocalizer.RestockCheaterMessage, CFSpeech | CFTimeout) - self.resetLaffClerk() + return + + base.cr.playGame.getPlace().fsm.request('stopped') + base.setCellsAvailable(base.bottomCells, 0) + self.destroyDialog() + self.acceptOnce('laffShopDone', self.__laffShopDone) + self.laffDialog = LaffShopGui.LaffShopGui() + + def freeAvatar(self): + base.cr.playGame.getPlace().fsm.request('walk') + base.setCellsAvailable(base.bottomCells, 1) + + def __laffShopDone(self, state, laff): + self.freeAvatar() - def __handleRestock(self, laff, cost): - self.sendUpdate('restock', [self.av.doId, laff, cost]) + if state == LaffRestockGlobals.TIMER_END: + self.setChatAbsolute(TTLocalizer.STOREOWNER_TOOKTOOLONG, CFSpeech|CFTimeout) + elif state == LaffRestockGlobals.USER_CANCEL: + self.setChatAbsolute(TTLocalizer.STOREOWNER_GOODBYE, CFSpeech|CFTimeout) + elif state == LaffRestockGlobals.RESTOCK: + self.sendUpdate('restock', [laff]) - def __handleGuiDone(self, bTimedOut=False): - self.ignoreAll() - if self.laffGui: - self.laffGui.destroy() - self.laffGui = None - if not bTimedOut: - self.sendUpdate('transactionDone') - - def popupLaffGUI(self, laff, cost): - self.setChatAbsolute('', CFSpeech) - self.accept('restockLaff', self.__handleRestock) - self.acceptOnce('guiDone', self.__handleGuiDone) - self.laffGui = LaffShopGui(text=TTLocalizer.RestockAskMessage % (laff, cost)) + def restockResult(self, state): + if state in LaffRestockGlobals.RestockMessages: + self.setChatAbsolute(LaffRestockGlobals.RestockMessages[state], CFSpeech | CFTimeout) \ No newline at end of file diff --git a/toontown/toon/DistributedNPCLaffRestockAI.py b/toontown/toon/DistributedNPCLaffRestockAI.py index 3cf30461..26aa9061 100755 --- a/toontown/toon/DistributedNPCLaffRestockAI.py +++ b/toontown/toon/DistributedNPCLaffRestockAI.py @@ -1,99 +1,29 @@ -from direct.distributed import ClockDelta from toontown.toonbase import ToontownGlobals -from DistributedNPCToonBaseAI import DistributedNPCToonBaseAI -from panda3d.core import * -from toontown.toonbase import TTLocalizer -from direct.task import Task -import LaffRestockGlobals -from toontown.toon import NPCToons +import LaffRestockGlobals, DistributedNPCToonBaseAI -class DistributedNPCLaffRestockAI(DistributedNPCToonBaseAI): +class DistributedNPCLaffRestockAI(DistributedNPCToonBaseAI.DistributedNPCToonBaseAI): - def __init__(self, air, npcId): - DistributedNPCToonBaseAI.__init__(self, air, npcId) - self.givesQuests = 0 - self.busy = 0 + def restock(self, laff): + av = simbase.air.doId2do.get(self.air.getAvatarIdFromSender()) - def delete(self): - taskMgr.remove(self.uniqueName('clearMovie')) - self.ignoreAll() - DistributedNPCToonBaseAI.delete(self) - - def d_setMovie(self, avId, flag, extraArgs=[]): - self.sendUpdate('setMovie', [flag, - self.npcId, - avId, - extraArgs, - ClockDelta.globalClockDelta.getRealNetworkTime()]) - - def avatarEnter(self): - avId = self.air.getAvatarIdFromSender() - if avId not in self.air.doId2do: - self.notify.warning('Avatar: %s not found' % avId) + if not av: return - if self.isBusy(): - self.freeAvatar(avId) + + newLaff = av.getHp() + laff + + if newLaff > av.getMaxHp(): + self.sendUpdate('restockResult', [LaffRestockGlobals.FULL_LAFF]) return - av = self.air.doId2do[avId] - self.busy = avId - self.acceptOnce(self.air.getAvatarExitEvent(avId), self.__handleUnexpectedExit, extraArgs=[avId]) - laff = av.getMaxHp() - av.getHp() + elif laff <= 0 or newLaff <= av.getHp(): + self.sendUpdate('restockResult', [LaffRestockGlobals.LESS_LAFF]) + return + cost = laff * ToontownGlobals.CostPerLaffRestock - if laff <= 0: - self.d_setMovie(avId, LaffRestockGlobals.FullLaff) - self.sendClearMovie(None) - elif cost > av.getTotalMoney(): - self.d_setMovie(avId, LaffRestockGlobals.NoMoney) - self.sendClearMovie(None) - else: - self.d_setMovie(avId, NPCToons.SELL_MOVIE_START) - taskMgr.doMethodLater(LaffRestockGlobals.LAFFCLERK_TIMER, self.sendTimeoutMovie, self.uniqueName('clearMovie')) - DistributedNPCToonBaseAI.avatarEnter(self) - def transactionDone(self): - avId = self.air.getAvatarIdFromSender() - if self.busy != avId: - self.air.writeServerEvent('suspicious', avId, 'DistributedNPCLaffRestockAI.transactionDone busy with %s' % self.busy) - self.notify.warning('somebody called transactionDone that I was not busy with! avId: %s' % avId) + if cost > av.getTotalMoney(): + self.sendUpdate('restockResult', [LaffRestockGlobals.NOT_ENOUGH_MONEY]) return - av = simbase.air.doId2do.get(avId) - if av: - self.d_setMovie(avId, NPCToons.SELL_MOVIE_COMPLETE, []) - self.sendClearMovie(None) - return - def __handleUnexpectedExit(self, avId): - self.notify.warning('avatar:' + str(avId) + ' has exited unexpectedly') - self.notify.warning('not busy with avId: %s, busy: %s ' % (avId, self.busy)) - taskMgr.remove(self.uniqueName('clearMovie')) - self.sendClearMovie(None) - return - - def sendTimeoutMovie(self, task): - self.d_setMovie(self.busy, NPCToons.SELL_MOVIE_TIMEOUT) - self.sendClearMovie(None) - return Task.done - - def sendClearMovie(self, task): - self.ignore(self.air.getAvatarExitEvent(self.busy)) - taskMgr.remove(self.uniqueName('clearMovie')) - self.busy = 0 - self.d_setMovie(0, NPCToons.SELL_MOVIE_CLEAR) - return Task.done - - def restock(self, avId, laff, cost): - sendAvId = self.air.getAvatarIdFromSender() - if self.busy != avId: - self.air.writeServerEvent('suspicious', avId, 'DistributedNPCLaffRestockAI.restock busy with %s' % self.busy) - self.notify.warning('somebody called restock that I was not busy with! avId: %s' % avId) - return - av = simbase.air.doId2do.get(avId) - if av: - if av.getMaxHp() < (av.getHp() + laff): - movieType = NPCToons.SELL_MOVIE_CHEATER - self.air.writeServerEvent('suspicious', avId, 'DistributedNPCLaffRestockAI.restock invalid restock') - self.notify.warning('somebody tried to buy an invalid hp restock! avId: %s' % avId) - else: - movieType = NPCToons.SELL_MOVIE_COMPLETE - av.takeMoney(cost) - av.b_setHp(av.getHp() + laff) + av.takeMoney(cost) + av.toonUp(laff) + self.sendUpdate('restockResult', [LaffRestockGlobals.RESTOCK_SUCCESSFUL]) \ No newline at end of file diff --git a/toontown/toon/DistributedNPCTailor.py b/toontown/toon/DistributedNPCTailor.py index ae701637..2e24dde2 100755 --- a/toontown/toon/DistributedNPCTailor.py +++ b/toontown/toon/DistributedNPCTailor.py @@ -215,7 +215,7 @@ class DistributedNPCTailor(DistributedNPCToonBase): print 'setDNA: which = %d, top = %d, bot = %d' % (which, self.clothesGUI.topChoice, self.clothesGUI.bottomChoice) if self.roomAvailable == 0: if self.isLocalToon: - if self.av.isClosetFull() or which & ClosetGlobals.SHIRT and which & ClosetGlobals.SHORTS: + if self.av.isClosetFull(1) or which & ClosetGlobals.SHIRT and which & ClosetGlobals.SHORTS: self.__enterConfirmLoss(2, which) self.clothesGUI.hideButtons() self.button.hide() diff --git a/toontown/toon/DistributedNPCToonBase.py b/toontown/toon/DistributedNPCToonBase.py index 1c5c7e6d..c04c9e50 100755 --- a/toontown/toon/DistributedNPCToonBase.py +++ b/toontown/toon/DistributedNPCToonBase.py @@ -56,7 +56,6 @@ class DistributedNPCToonBase(DistributedToon.DistributedToon): self.parentToonParts() self.rescaleToon() self.resetHeight() - self.generateLaughingMan() self.rightHands = [] self.leftHands = [] self.headParts = [] @@ -112,6 +111,9 @@ class DistributedNPCToonBase(DistributedToon.DistributedToon): def setupAvatars(self, av): self.ignoreAvatars() + self.lookAtAvatar(av) + + def lookAtAvatar(self, av): av.headsUp(self, 0, 0, 0) self.headsUp(av, 0, 0, 0) av.stopLookAround() diff --git a/toontown/toon/DistributedSmartNPC.py b/toontown/toon/DistributedSmartNPC.py deleted file mode 100755 index d557db75..00000000 --- a/toontown/toon/DistributedSmartNPC.py +++ /dev/null @@ -1,53 +0,0 @@ -from panda3d.core import * - -from DistributedNPCToonBase import * -from toontown.hood import ZoneUtil -from otp.nametag.NametagConstants import * -from toontown.quest import QuestChoiceGui -from toontown.quest import QuestParser -from toontown.quest import TrackChoiceGui -from toontown.toonbase import TTLocalizer - - -SPAMMING = 1 -DOUBLE_ENTRY = 2 - -class DistributedSmartNPC(DistributedNPCToonBase): - - def __init__(self, cr): - DistributedNPCToonBase.__init__(self, cr) - self.accept('chatUpdate', self.chatUpdate) - - def disable(self): - self.ignoreAll() - DistributedNPCToonBase.disable(self) - - def delayDelete(self): - DistributedNPCToonBase.delayDelete(self) - self.disable() - - def handleCollisionSphereEnter(self, collEntry): - self.sendUpdate('avatarEnter', []) - - def chatUpdate(self, message, chatFlags): - self.sendUpdate('talkMessage', [base.localAvatar.doId, message]) - - def greet(self, npcId, avId): - if avId in base.cr.doId2do: - avName = base.cr.doId2do.get(avId).getName() - self.setChatAbsolute('Hello, %s' % avName + '!', CFSpeech | CFTimeout) - - def dismiss(self, avId, statusCode): - if avId in base.cr.doId2do: - avName = base.cr.doId2do.get(avId).getName() - if statusCode == SPAMMING: - self.setChatAbsolute('Slow down there, %s' % avName + '. I can\'t even understand you!', CFSpeech | CFTimeout) - elif statusCode == DOUBLE_ENTRY: - self.setChatAbsolute('Well hey there %s' % avName + ', didn\'t we JUST talk?', CFSpeech | CFTimeout) - - def respond(self, npcId, message, avId): - try: - name = base.cr.doId2do.get(avId).getName() - self.setChatAbsolute(message, CFSpeech | CFTimeout) - except: - print 'Responding to non-available character!' diff --git a/toontown/toon/DistributedSmartNPCAI.py b/toontown/toon/DistributedSmartNPCAI.py deleted file mode 100755 index b7c9d366..00000000 --- a/toontown/toon/DistributedSmartNPCAI.py +++ /dev/null @@ -1,76 +0,0 @@ -from otp.ai.AIBaseGlobal import * -from direct.task.Task import Task -from panda3d.core import * -from DistributedNPCToonBaseAI import * -from toontown.quest import Quests -import time -from QuestionMgr import ChatterBotFactory, ChatterBotType -from direct.task import Task - -class DistributedSmartNPCAI(DistributedNPCToonBaseAI): - - def __init__(self, air, npcId, questCallback = None, hq = 0): - DistributedNPCToonBaseAI.__init__(self, air, npcId, questCallback) - self.air = air - self.personOfInterest = 0 - self.stopDouble = 0 - self.nameOfInterest = '' - self.factory = ChatterBotFactory() - self.engine = self.factory.create(ChatterBotType.CLEVERBOT) - self.brain = self.engine.create_session() - self.myTask = taskMgr.doMethodLater(0.5, self.tylerTask, 'tylerTask') - self.index = 0 - - def tylerTask(self, task): - if task.time >= 5: - self.index = 0 - if task.time <= 25: - return task.cont - self.response('I guess you don\'t want to talk anymore %s' % self.nameOfInterest + '...', self.personOfInterest) - self.stopDouble = self.personOfInterest - self.personOfInterest = 0 - self.nameOfInterest = '' - return task.done - - def restartTask(self): - taskMgr.remove(self.myTask) - taskMgr.add(self.myTask) - - def avatarEnter(self): - if not self.personOfInterest: - sender = self.air.getAvatarIdFromSender() - if not sender == self.stopDouble: - name = self.air.doId2do.get(sender).getName() - self.personOfInterest = sender - self.nameOfInterest = name - self.sendUpdate('greet', [self.npcId, sender]) - self.brain = self.engine.create_session() - else: - self.sendUpdate('dismiss', [sender, 2]) - pass - else: - #Tyler is busy! - pass - - def talkMessage(self, sender, message): - if sender == self.personOfInterest: - self.index += 1 - if self.index >= 4: - self.stopDouble = self.personOfInterest - self.personOfInterest = 0 - self.nameOfInterest = '' - taskMgr.remove(self.myTask) - self.index = 0 - self.sendUpdate('dismiss', [sender, 1]) - return - self.restartTask() - self.generateAnswer(message, sender) - - def generateAnswer(self, message, sender): - name = self.air.doId2do.get(sender).getName() - answer = self.brain.think(message) - self.response(answer, sender) - - def response(self, response, sendTo): - self.sendUpdate('respond', [self.npcId, response, sendTo]) - self.restartTask() diff --git a/toontown/toon/DistributedToon.py b/toontown/toon/DistributedToon.py index 159bfcdc..560b8354 100755 --- a/toontown/toon/DistributedToon.py +++ b/toontown/toon/DistributedToon.py @@ -13,7 +13,6 @@ import operator from panda3d.core import * import random import time - import Experience import InventoryNew import TTEmote @@ -119,7 +118,6 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute self.onOrder = CatalogItemList.CatalogItemList(store=CatalogItem.Customization | CatalogItem.DeliveryDate) self.onGiftOrder = CatalogItemList.CatalogItemList(store=CatalogItem.Customization | CatalogItem.DeliveryDate) self.mailboxContents = CatalogItemList.CatalogItemList(store=CatalogItem.Customization) - self.deliveryboxContentsContents = CatalogItemList.CatalogItemList(store=CatalogItem.Customization | CatalogItem.GiftTag) self.awardMailboxContents = CatalogItemList.CatalogItemList(store=CatalogItem.Customization) self.onAwardOrder = CatalogItemList.CatalogItemList(store=CatalogItem.Customization | CatalogItem.DeliveryDate) self.splash = None @@ -173,6 +171,7 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute self.ignored = [] self.reported = [] self.trueFriends = [] + self.specialInventory = [0, 0, 0, 0, 0] def disable(self): for soundSequence in self.soundSequenceList: @@ -499,12 +498,6 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute self.NPCFriendsDict = NPCFriendsDict - def setMaxAccessories(self, max): - self.maxAccessories = max - - def getMaxAccessories(self): - return self.maxAccessories - def setHatList(self, clothesList): self.hatList = clothesList @@ -531,7 +524,7 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute def isTrunkFull(self, extraAccessories = 0): numAccessories = (len(self.hatList) + len(self.glassesList) + len(self.backpackList) + len(self.shoesList)) / 3 - return numAccessories + extraAccessories >= self.maxAccessories + return numAccessories + extraAccessories >= ToontownGlobals.MaxAccessories def setMaxClothes(self, max): self.maxClothes = max @@ -874,9 +867,25 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute def setFishingRod(self, rodId): self.fishingRod = rodId + if self == base.localAvatar: + messenger.send('refreshFishingRod') def getFishingRod(self): return self.fishingRod + + def setMaxFishingRod(self, rodId): + self.maxFishingRod = rodId + if self == base.localAvatar: + messenger.send('refreshFishingRod') + + def getMaxFishingRod(self): + return self.maxFishingRod + + def requestFishingRod(self, rodId): + if not 0 <= rodId <= self.maxFishingRod: + return + + self.sendUpdate('requestFishingRod', [rodId]) def setFishingTrophies(self, trophyList): self.fishingTrophies = trophyList @@ -1927,13 +1936,16 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute return self.unlimitedSwing def getPinkSlips(self): - if hasattr(self, 'pinkSlips'): - return self.pinkSlips - else: - return 0 + return self.specialInventory[0] + + def getCrateKeys(self): + return self.specialInventory[1] - def setPinkSlips(self, pinkSlips): - self.pinkSlips = pinkSlips + def setSpecialInventory(self, specialInventory): + self.specialInventory = specialInventory + + def getSpecialInventory(self): + return self.specialInventory def setDisplayName(self, str): if not self.isDisguised: @@ -1967,6 +1979,20 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute nametagStyle = 0 self.nametagStyle = nametagStyle self.setDisplayName(self.getName()) + + def getNametagStyles(self): + return self.nametagStyles + + def setNametagStyles(self, nametagStyles): + self.nametagStyles = nametagStyles + if self == base.localAvatar: + messenger.send('refreshNametagStyle') + + def requestNametagStyle(self, nametagStyle): + if nametagStyle not in self.nametagStyles: + return + + self.sendUpdate('requestNametagStyle', [nametagStyle]) def getAvIdName(self): return '%s\n%s' % (self.getName(), self.doId) @@ -2049,10 +2075,6 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute def setChatAbsolute(self, chatString, chatFlags, dialogue = None, interrupt = 1, quiet = 0): DistributedAvatar.DistributedAvatar.setChatAbsolute(self, chatString, chatFlags, dialogue, interrupt) - def setChatMuted(self, chatString, chatFlags, dialogue=None, interrupt=1, quiet=0): - self.nametag.setChat(chatString, chatFlags) - self.playCurrentDialogue(dialogue, chatFlags - CFSpeech, interrupt) - def displayTalk(self, chatString): flags = CFSpeech | CFTimeout if ChatUtil.isThought(chatString): @@ -2361,30 +2383,13 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute if not self.isReported(doId): self.reported.append(doId) - def b_setTrueFriends(self, trueFriends): - self.setTrueFriends(trueFriends) - self.d_setTrueFriends(trueFriends) - def setTrueFriends(self, trueFriends): Toon.reconsiderAllToonsUnderstandable() self.trueFriends = trueFriends - def d_setTrueFriends(self, trueFriends): - self.sendUpdate('setTrueFriends', [trueFriends]) - def isTrueFriends(self, doId): return doId in self.trueFriends - def addTrueFriends(self, doId): - if not self.isTrueFriends(doId): - self.trueFriends.append(doId) - self.b_setTrueFriends(self.trueFriends) - - def removeTrueFriends(self, doId): - if self.isTrueFriends(doId): - self.trueFriends.remove(doId) - self.b_setTrueFriends(self.trueFriends) - def applyBuffs(self): for id, timestamp in enumerate(self.buffs): if id == ToontownGlobals.BMovementSpeed: @@ -2401,6 +2406,20 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute ToontownGlobals.ToonJumpForce, ToontownGlobals.ToonReverseSpeed * ToontownGlobals.BMovementSpeedMultiplier, ToontownGlobals.ToonRotateSpeed * ToontownGlobals.BMovementSpeedMultiplier) + + def setStats(self, stats): + self.stats = stats + if self == base.localAvatar: + messenger.send('refreshStats') + + def getStats(self): + return self.stats + + def getStat(self, index): + return self.stats[index] + + def wipeStats(self): + self.sendUpdate('wipeStats') @magicWord(category=CATEGORY_COMMUNITY_MANAGER) def globalTeleport(): diff --git a/toontown/toon/DistributedToonAI.py b/toontown/toon/DistributedToonAI.py index e4da0b2f..ab78b47f 100755 --- a/toontown/toon/DistributedToonAI.py +++ b/toontown/toon/DistributedToonAI.py @@ -32,6 +32,7 @@ from toontown.toonbase import TTLocalizer, ToontownBattleGlobals, ToontownGlobal from toontown.toonbase.ToontownGlobals import * from NPCToons import npcFriends import Experience, InventoryBase, ToonDNA, random, time +from toontown.uberdog import TopToonsGlobals if simbase.wantPets: from toontown.pets import PetLookerAI, PetObserve @@ -160,6 +161,8 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo self.trueFriends = [] self.fishBingoTutorialDone = False self.nextKnockHeal = 0 + self.tfRequest = (0, 0) + self.epp = [] def generate(self): DistributedPlayerAI.DistributedPlayerAI.generate(self) @@ -572,6 +575,7 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo self.NPCFriendsDict[npcFriend] = self.maxCallsPerNPC self.d_setNPCFriendsDict(self.NPCFriendsDict) self.air.questManager.toonMadeNPCFriend(self, numCalls, method) + self.addStat(ToontownGlobals.STAT_SOS, numCalls) return 1 def attemptSubtractNPCFriend(self, npcFriend): @@ -594,22 +598,9 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo for npcId in desiredNpcFriends: self.attemptAddNPCFriend(npcId) - def d_setMaxAccessories(self, max): - self.sendUpdate('setMaxAccessories', [self.maxAccessories]) - - def setMaxAccessories(self, max): - self.maxAccessories = max - - def b_setMaxAccessories(self, max): - self.setMaxAccessories(max) - self.d_setMaxAccessories(max) - - def getMaxAccessories(self): - return self.maxAccessories - def isTrunkFull(self, extraAccessories = 0): numAccessories = (len(self.hatList) + len(self.glassesList) + len(self.backpackList) + len(self.shoesList)) / 3 - return numAccessories + extraAccessories >= self.maxAccessories + return numAccessories + extraAccessories >= ToontownGlobals.MaxAccessories def d_setHatList(self, clothesList): self.sendUpdate('setHatList', [clothesList]) @@ -842,7 +833,7 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo return self.clothesTopsList def addToClothesTopsList(self, topTex, topTexColor, sleeveTex, sleeveTexColor): - if self.isClosetFull(): + if self.isClosetFull(1): return 0 index = 0 for i in xrange(0, len(self.clothesTopsList), 4): @@ -894,7 +885,7 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo return self.clothesBottomsList def addToClothesBottomsList(self, botTex, botTexColor): - if self.isClosetFull(): + if self.isClosetFull(1): self.notify.warning('clothes bottoms list is full') return 0 index = 0 @@ -943,11 +934,13 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo self.hp -= hpLost if self.hp <= 0: self.hp = -1 - messenger.send(self.getGoneSadMessage()) if not self.hpOwnedByBattle: self.hp = min(self.hp, self.maxHp) if sendTotal: self.d_setHp(self.hp) + + if self.hp <= 0: + self.addStat(ToontownGlobals.STAT_SAD) def b_setMaxHp(self, maxHp): if (maxHp > ToontownGlobals.MaxHpLimit): @@ -964,18 +957,6 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo else: self.sendUpdate('setMaxHp', [maxHp]) - @staticmethod - def getGoneSadMessageForAvId(avId): - return 'goneSad-%s' % avId - - def getGoneSadMessage(self): - return self.getGoneSadMessageForAvId(self.doId) - - def setHp(self, hp): - DistributedPlayerAI.DistributedPlayerAI.setHp(self, hp) - if hp <= 0: - messenger.send(self.getGoneSadMessage()) - def b_setTutorialAck(self, tutorialAck): self.d_setTutorialAck(tutorialAck) self.setTutorialAck(tutorialAck) @@ -1275,20 +1256,27 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo return self.cogMerits def b_promote(self, dept): - self.promote(dept) - self.d_promote(dept) - - def promote(self, dept): - if self.cogLevels[dept] < ToontownGlobals.MaxCogSuitLevel: - self.cogMerits[dept] = 0 + oldMerits = CogDisguiseGlobals.getTotalMerits(self, dept) self.incCogLevel(dept) - - def d_promote(self, dept): - merits = self.getCogMerits() + if self.cogLevels[dept] < ToontownGlobals.MaxCogSuitLevel: - merits[dept] = 0 - self.d_setCogMerits(merits) - + merits = self.getCogMerits() + + if not self.hasEPP(dept): + merits[dept] = 0 + + else: + # If we have EPP, check if the merit count is too much (i.e. enough to promote again) + if oldMerits >= CogDisguiseGlobals.getTotalMerits(self, dept): + # We have more merits than needed (i.e. promoting to another cog or earning laff) + # Therefore: + merits[dept] = 0 + + else: + merits[dept] = oldMerits + + self.d_setCogMerits(merits) + def readyForPromotion(self, dept): merits = self.cogMerits[dept] totalMerits = CogDisguiseGlobals.getTotalMerits(self, dept) @@ -1424,6 +1412,28 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo def getFishingRod(self): return self.fishingRod + def b_setMaxFishingRod(self, rodId): + if (not 0 <= rodId <= 4) or rodId <= self.maxFishingRod: + return + + self.d_setMaxFishingRod(rodId) + self.setMaxFishingRod(rodId) + + def d_setMaxFishingRod(self, rodId): + self.sendUpdate('setMaxFishingRod', [rodId]) + + def setMaxFishingRod(self, rodId): + self.maxFishingRod = rodId + + def getMaxFishingRod(self): + return self.maxFishingRod + + def requestFishingRod(self, rodId): + if not 0 <= rodId <= self.maxFishingRod: + return + + self.b_setFishingRod(rodId) + def b_setFishingTrophies(self, trophyList): self.setFishingTrophies(trophyList) self.d_setFishingTrophies(trophyList) @@ -2015,6 +2025,7 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo msgs.append([textId, 1]) self.b_setResistanceMessages(msgs) + self.addStat(ToontownGlobals.STAT_UNITES) def removeResistanceMessage(self, textId): msgs = self.getResistanceMessages() @@ -2088,6 +2099,14 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo def getCatalogNotify(self): return (self.catalogNotify, self.mailboxNotify) + + def addToDeliverySchedule(self, item, minutes=0): + if config.GetBool('want-instant-delivery', False): + minutes = 0 + + item.deliveryDate = int(time.time() / 60. + minutes + .5) + self.onOrder.append(item) + self.b_setDeliverySchedule(self.onOrder) def b_setDeliverySchedule(self, onOrder, doUpdateLater = True): self.setDeliverySchedule(onOrder, doUpdateLater) @@ -2096,6 +2115,9 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo def d_setDeliverySchedule(self, onOrder): self.sendUpdate('setDeliverySchedule', [onOrder.getBlob(store=CatalogItem.Customization | CatalogItem.DeliveryDate)]) + def d_setGiftSchedule(self, onGiftOrder): + self.sendUpdate('setGiftSchedule', [self.onGiftOrder.getBlob(store=CatalogItem.Customization | CatalogItem.DeliveryDate)]) + def setDeliverySchedule(self, onOrder, doUpdateLater = True): self.setBothSchedules(onOrder, None) @@ -2105,6 +2127,7 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo def b_setBothSchedules(self, onOrder, onGiftOrder, doUpdateLater = True): self.setBothSchedules(onOrder, onGiftOrder, doUpdateLater) self.d_setDeliverySchedule(onOrder) + self.d_setGiftSchedule(onGiftOrder) def setBothSchedules(self, onOrder, onGiftOrder, doUpdateLater = True): if onOrder != None: @@ -2178,7 +2201,7 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo self.b_setMailboxContents(self.mailboxContents + delivered) self.b_setCatalogNotify(self.catalogNotify, ToontownGlobals.NewItems) return Task.done - + def __deliverPurchase(self, task): now = int(time.time() / 60 + 0.5) delivered, remaining = self.onOrder.extractDeliveryItems(now) @@ -2272,6 +2295,8 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo return self.maxBankMoney def addMoney(self, deltaMoney): + if deltaMoney > 0: + messenger.send('topToonsManager-event', [self.doId, TopToonsGlobals.CAT_JELLYBEAN, deltaMoney]) money = deltaMoney + self.money pocketMoney = min(money, self.maxMoney) self.b_setMoney(pocketMoney) @@ -2279,6 +2304,7 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo if overflowMoney > 0: bankMoney = self.bankMoney + overflowMoney self.b_setBankMoney(bankMoney) + self.addStat(ToontownGlobals.STAT_BEANS_EARNT, deltaMoney) def takeMoney(self, deltaMoney, bUseBank = True): totalMoney = self.money @@ -2292,6 +2318,7 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo self.b_setMoney(0) else: self.b_setMoney(self.money - deltaMoney) + self.addStat(ToontownGlobals.STAT_BEANS_SPENT, deltaMoney) return True def b_setMoney(self, money): @@ -2415,14 +2442,20 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo def startToonUp(self, healFrequency): self.stopToonUp() - self.healFrequency = healFrequency + self.nextToonup = (healFrequency, self.indexOf(ToontownGlobals.TOONUP_PULSE_ZONES, ZoneUtil.getCanonicalHoodId(self.zoneId), 0) + 1) self.__waitForNextToonUp() + + def indexOf(self, list, element, default): + try: + return list.index(element) + except: + return default def __waitForNextToonUp(self): - taskMgr.doMethodLater(self.healFrequency, self.toonUpTask, self.uniqueName('safeZoneToonUp')) + taskMgr.doMethodLater(self.nextToonup[0], self.toonUpTask, self.uniqueName('safeZoneToonUp')) def toonUpTask(self, task): - self.toonUp(1) + self.toonUp(self.nextToonup[1]) self.__waitForNextToonUp() return Task.done @@ -2940,8 +2973,7 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo taskMgr.add(self._moveSphere, self._getMoveSphereTaskName(), priority=OTPGlobals.AICollMovePriority) self.inEstate = 1 self.estateOwnerId = ownerId - self.estateZones = simbase.air.estateMgr.getEstateZones(ownerId) - self.estateHouseZones = simbase.air.estateMgr.getEstateHouseZones(ownerId) + self.estateZones = [zoneId] self.enterPetLook() def _getPetLookerBodyNode(self): @@ -2965,7 +2997,6 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo self.collNodePath.removeNode() del self.collNodePath del self.estateOwnerId - del self.estateHouseZones del self.inEstate self._wasInEstate = 1 @@ -3329,9 +3360,10 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo self.gardenSpecials.append((index, newCount)) self.gardenSpecials.sort() self.b_setGardenSpecials(self.gardenSpecials) - return + return 1 self.notify.warning("removing garden item %d that toon doesn't have" % index) + return 0 def b_setFlowerCollection(self, speciesList, varietyList): self.setFlowerCollection(speciesList, varietyList) @@ -3385,6 +3417,7 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo return 0 elif self.flowerBasket.addFlower(species, variety): self.d_setFlowerBasket(*self.flowerBasket.getNetLists()) + self.addStat(ToontownGlobals.STAT_FLOWERS) return 1 else: self.notify.warning('addFlowerToBasket: addFlower failed') @@ -3639,27 +3672,45 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo self.sendUpdate('setUnlimitedSwing', [unlimitedSwing]) def b_setPinkSlips(self, pinkSlips): - self.d_setPinkSlips(pinkSlips) - self.setPinkSlips(pinkSlips) + self.specialInventory[0] = pinkSlips + self.b_setSpecialInventory(self.specialInventory) + + def b_setCrateKeys(self, crateKeys): + self.specialInventory[1] = crateKeys + self.b_setSpecialInventory(self.specialInventory) + + def b_setSpecialInventory(self, specialInventory): + self.d_setSpecialInventory(specialInventory) + self.setSpecialInventory(specialInventory) - def d_setPinkSlips(self, pinkSlips): - self.sendUpdate('setPinkSlips', [pinkSlips]) + def d_setSpecialInventory(self, specialInventory): + self.sendUpdate('setSpecialInventory', [specialInventory]) - def setPinkSlips(self, pinkSlips): - self.pinkSlips = pinkSlips + def setSpecialInventory(self, specialInventory): + self.specialInventory = specialInventory def getPinkSlips(self): - return self.pinkSlips + return self.specialInventory[0] + + def getCrateKeys(self): + return self.specialInventory[1] def addPinkSlips(self, amountToAdd): - pinkSlips = min(self.pinkSlips + amountToAdd, 255) + pinkSlips = min(self.getPinkSlips() + amountToAdd, 255) self.b_setPinkSlips(pinkSlips) + self.addStat(ToontownGlobals.STAT_SLIPS, amountToAdd) def removePinkSlips(self, amount): if hasattr(self, 'autoRestockPinkSlips') and self.autoRestockPinkSlips: amount = 0 - pinkSlips = max(self.pinkSlips - amount, 0) + pinkSlips = max(self.getPinkSlips() - amount, 0) self.b_setPinkSlips(pinkSlips) + + def addCrateKeys(self, amountToAdd): + self.b_setCrateKeys(min(self.getCrateKeys() + amountToAdd, 255)) + + def removeCrateKeys(self, amount): + self.b_setCrateKeys(max(self.getCrateKeys() - amount, 0)) def b_setNametagStyle(self, nametagStyle): self.d_setNametagStyle(nametagStyle) @@ -3673,6 +3724,32 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo def getNametagStyle(self): return self.nametagStyle + + def b_setNametagStyles(self, nametagStyles): + self.d_setNametagStyles(nametagStyles) + self.setNametagStyles(nametagStyles) + + def d_setNametagStyles(self, nametagStyles): + self.sendUpdate('setNametagStyles', [nametagStyles]) + + def setNametagStyles(self, nametagStyles): + self.nametagStyles = nametagStyles + + def addNametagStyle(self, nametagStyle): + if nametagStyle in self.nametagStyles: + return + + self.nametagStyles.append(nametagStyle) + self.b_setNametagStyles(self.nametagStyles) + + def getNametagStyles(self): + return self.nametagStyles + + def requestNametagStyle(self, nametagStyle): + if nametagStyle not in self.nametagStyles: + return + + self.b_setNametagStyle(nametagStyle) def b_setMail(self, mail): self.d_setMail(mail) @@ -4021,7 +4098,7 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo self.b_setRedeemedCodes(self.redeemedCodes) def setTrueFriends(self, trueFriends): - self.trueFriends = trueFriends[:OTPGlobals.MaxFriends] + self.trueFriends = trueFriends def d_setTrueFriends(self, trueFriends): self.sendUpdate('setTrueFriends', [trueFriends]) @@ -4029,6 +4106,16 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo def b_setTrueFriends(self, trueFriends): self.setTrueFriends(trueFriends) self.d_setTrueFriends(trueFriends) + + def isTrueFriends(self, avId): + return avId in self.trueFriends + + def addTrueFriend(self, avId): + if avId in self.trueFriends: + return + + self.trueFriends.append(avId) + self.b_setTrueFriends(self.trueFriends) def getTrueFriends(self, trueFriends): return self.trueFriends @@ -4045,6 +4132,69 @@ class DistributedToonAI(DistributedPlayerAI.DistributedPlayerAI, DistributedSmoo def getNextKnockHeal(self): return self.nextKnockHeal + + def setTFRequest(self, tfRequest): + self.tfRequest = tfRequest + + def d_setTFRequest(self, tfRequest): + self.sendUpdate('setTFRequest', [tfRequest]) + + def b_setTFRequest(self, tfRequest): + self.setTFRequest(tfRequest) + self.d_setTFRequest(tfRequest) + + def getTFRequest(self): + return self.tfRequest + + def setEPP(self, epp): + self.epp = epp + + def d_setEPP(self, epp): + self.sendUpdate("setEPP", [epp]) + + def b_setEPP(self, epp): + self.setEPP(epp) + self.d_setEPP(epp) + + def addEPP(self, dept): + self.epp.append(dept) + self.d_setEPP(self.epp) + + def removeEPP(self, dept): + if dept in self.epp: + self.epp.remove(dept) + + self.d_setEPP(self.epp) + + def hasEPP(self, dept): + return dept in self.epp + + def b_setStats(self, stats): + self.d_setStats(stats) + self.setStats(stats) + + def d_setStats(self, stats): + self.sendUpdate('setStats', [stats]) + + def setStats(self, stats): + self.stats = stats + + def getStats(self): + return self.stats + + def getStat(self, index): + return self.stats[index] + + def addStat(self, index, amount=1): + if amount <= 0: + return + + self.stats[index] += amount + self.d_setStats(self.stats) + + def wipeStats(self): + self.stats = [0] * 22 + self.d_setStats(self.stats) @magicWord(category=CATEGORY_PROGRAMMER, types=[str, int, int]) def cheesyEffect(value, hood=0, expire=0): @@ -4278,6 +4428,17 @@ def fires(count): invoker.b_setPinkSlips(count) return 'You were given %d fires.' % count +@magicWord(category=CATEGORY_PROGRAMMER, types=[int]) +def crateKeys(count): + """ + Modifies the invoker's crate key count. + """ + invoker = spellbook.getInvoker() + if not 0 <= count <= 255: + return 'Your crate key must be in range (0-255).' + invoker.b_setCrateKeys(count) + return 'You were given %d crate keys.' % count + @magicWord(category=CATEGORY_PROGRAMMER, types=[int]) def maxMoney(maxMoney): """ @@ -4335,6 +4496,7 @@ def fishingRod(rod): return 'Rod value must be in xrange (0-4).' target = spellbook.getTarget() target.b_setFishingRod(rod) + target.b_setMaxFishingRod(rod) return "Set %s's fishing rod to %d!" % (target.getName(), rod) @magicWord(category=CATEGORY_PROGRAMMER, types=[int]) @@ -4454,7 +4616,7 @@ def badName(): """ target = spellbook.getTarget() _name = target.getName() - colorString = TTLocalizer.NumToColor[target.dna.headColor] + colorString = TTLocalizer.ColorfulToon animalType = TTLocalizer.AnimalToSpecies[target.dna.getAnimal()] target.b_setName(colorString + ' ' + animalType) target.sendUpdate('setWishNameState', ['REJECTED']) @@ -4593,47 +4755,29 @@ def dna(part, value): return 'Legs set to: ' + dna.legs if part == 'headcolor': - if dna.gender not in ('m', 'f'): - return 'Unknown gender.' - if (dna.gender == 'm') and (value not in ToonDNA.defaultBoyColorList): - return 'Invalid male head color index: ' + str(value) - if (dna.gender == 'f') and (value not in ToonDNA.defaultGirlColorList): - return 'Invalid female head color index: ' + str(value) + if value not in ToonDNA.defaultColorList: + return 'Invalid head color index: ' + str(value) dna.headColor = value invoker.b_setDNAString(dna.makeNetString()) return 'Head color index set to: ' + str(dna.headColor) if part == 'armcolor': - if dna.gender not in ('m', 'f'): - return 'Unknown gender.' - if (dna.gender == 'm') and (value not in ToonDNA.defaultBoyColorList): - return 'Invalid male arm color index: ' + str(value) - if (dna.gender == 'f') and (value not in ToonDNA.defaultGirlColorList): - return 'Invalid female arm color index: ' + str(value) + if value not in ToonDNA.defaultColorList: + return 'Invalid arm color index: ' + str(value) dna.armColor = value invoker.b_setDNAString(dna.makeNetString()) return 'Arm color index set to: ' + str(dna.armColor) if part == 'legcolor': - if dna.gender not in ('m', 'f'): - return 'Unknown gender.' - if (dna.gender == 'm') and (value not in ToonDNA.defaultBoyColorList): - return 'Invalid male leg color index: ' + str(value) - if (dna.gender == 'f') and (value not in ToonDNA.defaultGirlColorList): - return 'Invalid female leg color index: ' + str(value) + if value not in ToonDNA.defaultColorList: + return 'Invalid leg color index: ' + str(value) dna.legColor = value invoker.b_setDNAString(dna.makeNetString()) return 'Leg color index set to: ' + str(dna.legColor) if part == 'color': - if dna.gender not in ('m', 'f'): - return 'Unknown gender.' - if (dna.gender == 'm') and (value not in ToonDNA.defaultBoyColorList): - if (value != 0x1a) and (value != 0x00): - return 'Invalid male color index: ' + str(value) - if (dna.gender == 'f') and (value not in ToonDNA.defaultGirlColorList): - if (value != 0x1a) and (value != 0x00): - return 'Invalid female color index: ' + str(value) + if (value not in ToonDNA.defaultColorList) and (value != 0x1a) and (value != 0x00): + return 'Invalid color index: ' + str(value) if (value == 0x1a) and (dna.getAnimal() != 'cat'): return 'Invalid color index for species: ' + dna.getAnimal() if (value == 0x00) and (dna.getAnimal() != 'bear'): @@ -4698,18 +4842,10 @@ def dna(part, value): invoker.b_setDNAString(dna.makeNetString()) return 'Bottom texture color index set to: ' + str(dna.botTexColor) - if part == 'laughingman': - if not value.isdigit(): - return 'Laughing Man can only be 0 or 1.' - value = int(value) - if value != 0 and value != 1: - return 'Laughing Man can only be 0 or 1.' - dna.laughingMan = value - invoker.b_setDNAString(dna.makeNetString()) - return 'Laughing Man set to: ' + str(dna.laughingMan) - if part == 'show': return dna.asTuple() + if part == 'showrandom': + return NPCToons.getRandomDNA(time.time(), value) return 'Invalid part: ' + part @magicWord(category=CATEGORY_ADMINISTRATOR, types=[int]) @@ -4815,11 +4951,11 @@ def getZone(): @magicWord(category=CATEGORY_MODERATOR, types=[int]) def nametagStyle(nametagStyle): - currentAccess = spellbook.getInvokerAccess() if nametagStyle >= len(TTLocalizer.NametagFontNames): return 'Invalid nametag style.' target = spellbook.getTarget() target.b_setNametagStyle(nametagStyle) + target.addNametagStyle(nametagStyle) return 'Nametag style set to: %s.' % TTLocalizer.NametagFontNames[nametagStyle] @magicWord(category=CATEGORY_PROGRAMMER, types=[str, int, int]) @@ -4913,3 +5049,33 @@ def canSkill(skill): """ av = spellbook.getTarget() av.b_setWateringCanSkill(skill) + +@magicWord(category=CATEGORY_PROGRAMMER, types=[int, str]) +def epp(dept, command="add"): + av = spellbook.getTarget() + if command == "add": + av.addEPP(dept) + + elif command == "remove": + av.removeEPP(dept) + + elif command == "get": + if dept == -1: + return av.epp + + return av.hasEPP(dept) + + else: + return "Unknown command!" + +@magicWord(category=CATEGORY_PROGRAMMER, types=[int]) +def promote(dept): + spellbook.getTarget().b_promote(dept) + +@magicWord(category=CATEGORY_PROGRAMMER) +def maxGarden(): + av = spellbook.getInvoker() + av.b_setShovel(3) + av.b_setWateringCan(3) + av.b_setShovelSkill(639) + av.b_setWateringCanSkill(999) diff --git a/toontown/toon/DistributedToonUD.py b/toontown/toon/DistributedToonUD.py index aba9771b..01b0d550 100755 --- a/toontown/toon/DistributedToonUD.py +++ b/toontown/toon/DistributedToonUD.py @@ -82,9 +82,6 @@ class DistributedToonUD(DistributedObjectUD): def setClothesBottomsList(self, todo0): pass - def setMaxAccessories(self, todo0): - pass - def setHatList(self, todo0): pass @@ -285,6 +282,9 @@ class DistributedToonUD(DistributedObjectUD): def setFishingRod(self, todo0): pass + + def setMaxFishingRod(self, todo0): + pass def setFishingTrophies(self, todo0): pass @@ -460,11 +460,14 @@ class DistributedToonUD(DistributedObjectUD): def forceLogoutWithNotify(self): pass - def setPinkSlips(self, todo0): + def setSpecialInventory(self, todo0): pass def setNametagStyle(self, todo0): pass + + def setNametagStyles(self, todo0): + return def setMail(self, todo0): pass @@ -513,3 +516,12 @@ class DistributedToonUD(DistributedObjectUD): def setTrueFriends(self, trueFriends): pass + + def setWishName(self, todo0): + pass + + def setWishNameState(self, todo0): + pass + + def setStats(self, todo0): + pass diff --git a/toontown/toon/GloveShopGui.py b/toontown/toon/GloveShopGui.py index cc2fc582..b786f73f 100644 --- a/toontown/toon/GloveShopGui.py +++ b/toontown/toon/GloveShopGui.py @@ -91,6 +91,7 @@ class GloveShopGui: def __updateIndex(self, offset): self.index += offset hitLimit = 0 + color = ToonDNA.allColorsList[self.index] if self.index <= 0: self.downArrow['state'] = DGG.DISABLED @@ -103,8 +104,8 @@ class GloveShopGui: hitLimit = 1 else: self.upArrow['state'] = DGG.NORMAL - - if self.lastGlove == self.index: + + if self.lastGlove == color: self.buyButton['state'] = DGG.DISABLED self.notice['text'] = TTLocalizer.GloveGuiSameColor else: @@ -112,8 +113,8 @@ class GloveShopGui: self.notice['text'] = TTLocalizer.GloveGuiNotice % ToontownGlobals.GloveCost self.color['text'] = TTLocalizer.NumToColor[self.index] - self.color['text_fg'] = ToonDNA.allColorsList[self.index] - self.setClientGlove(self.index) + self.color['text_fg'] = color + self.setClientGlove(color) return hitLimit def __runTask(self, task): diff --git a/toontown/toon/InventoryBase.py b/toontown/toon/InventoryBase.py index c72578b3..acb81c66 100755 --- a/toontown/toon/InventoryBase.py +++ b/toontown/toon/InventoryBase.py @@ -214,7 +214,7 @@ class InventoryBase(DirectObject.DirectObject): return self.countPropsInList(newInventory) - self.totalProps def validatePurchase(self, newInventory, currentMoney, newMoney): - if newMoney > currentMoney: + if newMoney > currentMoney or newMoney < 0: self.notify.warning('Somebody lied about their money! Rejecting purchase.') return 0 newItemTotal = self.countPropsInList(newInventory) diff --git a/toontown/toon/InventoryNew.py b/toontown/toon/InventoryNew.py index 07cdbb8d..4eb458fa 100755 --- a/toontown/toon/InventoryNew.py +++ b/toontown/toon/InventoryNew.py @@ -116,11 +116,20 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): DirectFrame.hide(self) def updateTotalPropsText(self): - textTotal = TTLocalizer.InventoryTotalGags % (self.totalProps, self.toon.getMaxCarry()) + textTotal = '%s\n\n' % (TTLocalizer.InventoryTotalGags % (self.totalProps, self.toon.getMaxCarry())) + if localAvatar.getPinkSlips() > 1: - textTotal = textTotal + '\n\n' + TTLocalizer.InventroyPinkSlips % localAvatar.getPinkSlips() + textTotal += TTLocalizer.InventoryPinkSlips % localAvatar.getPinkSlips() + textTotal += '\n' elif localAvatar.getPinkSlips() == 1: - textTotal = textTotal + '\n\n' + TTLocalizer.InventroyPinkSlip + textTotal += TTLocalizer.InventoryPinkSlip + textTotal += '\n' + + if localAvatar.getCrateKeys() > 1: + textTotal += TTLocalizer.InventoryCrateKeys % localAvatar.getCrateKeys() + elif localAvatar.getCrateKeys() == 1: + textTotal += TTLocalizer.InventoryCrateKey + self.totalLabel['text'] = textTotal def unload(self): @@ -139,6 +148,8 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): del self.battleFrame del self.purchaseFrame del self.storePurchaseFrame + self.deleteAllButton.destroy() + del self.deleteAllButton self.deleteEnterButton.destroy() del self.deleteEnterButton self.deleteExitButton.destroy() @@ -187,7 +198,9 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): self.purchaseFrame = None self.storePurchaseFrame = None trashcanGui = loader.loadModel('phase_3/models/gui/trashcan_gui') - self.deleteEnterButton = DirectButton(parent=self.invFrame, image=(trashcanGui.find('**/TrashCan_CLSD'), trashcanGui.find('**/TrashCan_OPEN'), trashcanGui.find('**/TrashCan_RLVR')), text=('', TTLocalizer.InventoryDelete, TTLocalizer.InventoryDelete), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), text_scale=0.1, text_pos=(0, -0.1), text_font=getInterfaceFont(), textMayChange=0, relief=None, pos=(-1, 0, -0.35), scale=1.0) + trashcanImage = (trashcanGui.find('**/TrashCan_CLSD'), trashcanGui.find('**/TrashCan_OPEN'), trashcanGui.find('**/TrashCan_RLVR')) + self.deleteEnterButton = DirectButton(parent=self.invFrame, image=trashcanImage, text=('', TTLocalizer.InventoryDelete, TTLocalizer.InventoryDelete), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), text_scale=0.1, text_pos=(0, -0.1), text_font=getInterfaceFont(), textMayChange=0, relief=None, pos=(-1, 0, -0.35), scale=1.0) + self.deleteAllButton = DirectButton(parent=self.invFrame, image=trashcanImage, text=('', TTLocalizer.InventoryDeleteAll, TTLocalizer.InventoryDeleteAll), text_fg=(1, 0, 0, 1), text_shadow=(1, 1, 1, 1), text_scale=0.1, text_pos=(0, -0.1), text_font=getInterfaceFont(), textMayChange=0, relief=None, pos=(-0.3, 0, -0.91), scale=0.75, command=self.__zeroInvAndUpdate) self.deleteExitButton = DirectButton(parent=self.invFrame, image=(trashcanGui.find('**/TrashCan_OPEN'), trashcanGui.find('**/TrashCan_CLSD'), trashcanGui.find('**/TrashCan_RLVR')), text=('', TTLocalizer.InventoryDone, TTLocalizer.InventoryDone), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), text_scale=0.1, text_pos=(0, -0.1), text_font=getInterfaceFont(), textMayChange=0, relief=None, pos=(-1, 0, -0.35), scale=1.0) trashcanGui.removeNode() self.deleteHelpText = DirectLabel(parent=self.invFrame, relief=None, pos=(0.272, 0.3, -0.907), text=TTLocalizer.InventoryDeleteHelp, text_fg=(0, 0, 0, 1), text_scale=0.08, textMayChange=0) @@ -234,10 +247,8 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): button.bind(DGG.EXIT, self.hideDetail) self.buttons[track].append(button) - return - def __handleSelection(self, track, level): - if self.activateMode == 'purchaseDelete' or self.activateMode == 'bookDelete' or self.activateMode == 'storePurchaseDelete': + if self.activateMode == 'purchaseDelete' or self.activateMode == 'storePurchaseDelete': if self.numItem(track, level): self.useItem(track, level) self.updateGUI(track, level) @@ -265,6 +276,10 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): def __handleBackToPlayground(self): messenger.send('inventory-back-to-playground') + + def __zeroInvAndUpdate(self): + self.zeroInv() + self.updateGUI() def showDetail(self, track, level, event = None): self.totalLabel.hide() @@ -312,6 +327,9 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): def setDetailCredit(self, track, credit): if credit != None: + if self.toon.earnedExperience: + maxCredit = ExperienceCap - self.toon.earnedExperience[track] + credit = min(credit, maxCredit) credit = int(credit * 10 + 0.5) if credit % 10 == 0: credit /= 10 @@ -373,11 +391,7 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): self.enableUberGags() def deactivateButtons(self): - if self.previousActivateMode == 'book': - self.bookDeactivateButtons() - elif self.previousActivateMode == 'bookDelete': - self.bookDeleteDeactivateButtons() - elif self.previousActivateMode == 'purchaseDelete': + if self.previousActivateMode == 'purchaseDelete': self.purchaseDeleteDeactivateButtons() elif self.previousActivateMode == 'purchase': self.purchaseDeactivateButtons() @@ -395,16 +409,11 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): self.storePurchaseBrokeDeactivateButtons() elif self.previousActivateMode == 'plantTree': self.plantTreeDeactivateButtons() - else: - self.notify.error('No such mode as %s' % self.previousActivateMode) - return None def __activateButtons(self): if hasattr(self, 'activateMode'): if self.activateMode == 'book': self.bookActivateButtons() - elif self.activateMode == 'bookDelete': - self.bookDeleteActivateButtons() elif self.activateMode == 'purchaseDelete': self.purchaseDeleteActivateButtons() elif self.activateMode == 'purchase': @@ -433,16 +442,12 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): self.detailFrame.setPos(-0.05, 0, -0.855) self.detailFrame.setScale(0.75) self.deleteEnterButton.hide() - self.deleteEnterButton.setPos(1.029, 0, -0.639) - self.deleteEnterButton.setScale(0.75) + self.deleteAllButton.hide() self.deleteExitButton.hide() - self.deleteExitButton.setPos(1.029, 0, -0.639) - self.deleteExitButton.setScale(0.75) self.invFrame.reparentTo(self) self.invFrame.setPos(0, 0, 0) self.invFrame.setScale(1) - self.deleteEnterButton['command'] = self.setActivateMode - self.deleteEnterButton['extraArgs'] = ['bookDelete'] + for track in xrange(len(Tracks)): if self.toon.hasTrackAccess(track): self.showTrack(track) @@ -457,28 +462,7 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): else: self.hideTrack(track) - return None - - def bookDeactivateButtons(self): - self.deleteEnterButton['command'] = None - return - - def bookDeleteActivateButtons(self): - messenger.send('enterBookDelete') - self.setPos(-0.2, 0, 0.4) - self.setScale(0.8) - self.deleteEnterButton.hide() - self.deleteEnterButton.setPos(1.029, 0, -0.639) - self.deleteEnterButton.setScale(0.75) - self.deleteExitButton.show() - self.deleteExitButton.setPos(1.029, 0, -0.639) - self.deleteExitButton.setScale(0.75) - self.deleteHelpText.show() - self.invFrame.reparentTo(self) - self.invFrame.setPos(0, 0, 0) - self.invFrame.setScale(1) - self.deleteExitButton['command'] = self.setActivateMode - self.deleteExitButton['extraArgs'] = [self.previousActivateMode] + def updateDeleteButtons(self): for track in xrange(len(Tracks)): if self.toon.hasTrackAccess(track): self.showTrack(track) @@ -486,21 +470,46 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): button = self.buttons[track][level] if self.itemIsUsable(track, level): button.show() - if self.numItem(track, level) <= 0: + if self.numItem(track, level) <= 0 or level >= UBER_GAG_LEVEL_INDEX: self.makeUnpressable(button, track, level) else: self.makeDeletePressable(button, track, level) else: button.hide() - else: self.hideTrack(track) - - def bookDeleteDeactivateButtons(self): - messenger.send('exitBookDelete') - self.deleteHelpText.hide() - self.deleteDeactivateButtons() - + + def updateUseableButtons(self): + for track in xrange(len(Tracks)): + if self.toon.hasTrackAccess(track): + self.showTrack(track) + for level in xrange(len(Levels[track])): + button = self.buttons[track][level] + if self.itemIsUsable(track, level): + button.show() + self.makeUnpressable(button, track, level) + else: + button.hide() + else: + self.hideTrack(track) + + def updatePurchaseButtons(self): + for track in xrange(len(Tracks)): + if self.toon.hasTrackAccess(track): + self.showTrack(track) + for level in xrange(len(Levels[track])): + button = self.buttons[track][level] + if self.itemIsUsable(track, level): + button.show() + if self.numItem(track, level) >= self.getMax(track, level) or self.totalProps == self.toon.getMaxCarry() or level > LAST_REGULAR_GAG_LEVEL: + self.makeUnpressable(button, track, level) + else: + self.makePressable(button, track, level) + else: + button.hide() + else: + self.hideTrack(track) + def purchaseDeleteActivateButtons(self): self.reparentTo(aspect2d) self.setPos(0.2, 0, -0.04) @@ -514,52 +523,20 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): self.detailFrame.setPos(1.17, 0, -0.02) self.detailFrame.setScale(1.25) self.deleteEnterButton.hide() - self.deleteEnterButton.setPos(-0.441, 0, -0.917) + self.deleteEnterButton.setPos(-0.8, 0, -0.917) self.deleteEnterButton.setScale(0.75) self.deleteExitButton.show() - self.deleteExitButton.setPos(-0.441, 0, -0.917) + self.deleteExitButton.setPos(-0.8, 0, -0.917) self.deleteExitButton.setScale(0.75) self.deleteExitButton['command'] = self.setActivateMode self.deleteExitButton['extraArgs'] = [self.previousActivateMode] - for track in xrange(len(Tracks)): - if self.toon.hasTrackAccess(track): - self.showTrack(track) - for level in xrange(len(Levels[track])): - button = self.buttons[track][level] - if self.itemIsUsable(track, level): - button.show() - if self.numItem(track, level) <= 0 or level >= UBER_GAG_LEVEL_INDEX: - self.makeUnpressable(button, track, level) - else: - self.makeDeletePressable(button, track, level) - else: - button.hide() - - else: - self.hideTrack(track) - - return + self.updateDeleteButtons() def purchaseDeleteDeactivateButtons(self): self.invFrame.reparentTo(self) self.purchaseFrame.hide() self.deleteDeactivateButtons() - for track in xrange(len(Tracks)): - if self.toon.hasTrackAccess(track): - self.showTrack(track) - for level in xrange(len(Levels[track])): - button = self.buttons[track][level] - if self.itemIsUsable(track, level): - button.show() - if self.numItem(track, level) <= 0 or level >= UBER_GAG_LEVEL_INDEX: - self.makeUnpressable(button, track, level) - else: - self.makeDeletePressable(button, track, level) - else: - button.hide() - - else: - self.hideTrack(track) + self.updateDeleteButtons() def storePurchaseDeleteActivateButtons(self): self.reparentTo(aspect2d) @@ -574,31 +551,14 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): self.detailFrame.setPos(1.175, 0, 0) self.detailFrame.setScale(1.25) self.deleteEnterButton.hide() - self.deleteEnterButton.setPos(-0.55, 0, -0.91) + self.deleteEnterButton.setPos(-0.8, 0, -0.91) self.deleteEnterButton.setScale(0.75) self.deleteExitButton.show() - self.deleteExitButton.setPos(-0.55, 0, -0.91) + self.deleteExitButton.setPos(-0.8, 0, -0.91) self.deleteExitButton.setScale(0.75) self.deleteExitButton['command'] = self.setActivateMode self.deleteExitButton['extraArgs'] = [self.previousActivateMode] - for track in xrange(len(Tracks)): - if self.toon.hasTrackAccess(track): - self.showTrack(track) - for level in xrange(len(Levels[track])): - button = self.buttons[track][level] - if self.itemIsUsable(track, level): - button.show() - if self.numItem(track, level) <= 0 or level >= UBER_GAG_LEVEL_INDEX: - self.makeUnpressable(button, track, level) - else: - self.makeDeletePressable(button, track, level) - else: - button.hide() - - else: - self.hideTrack(track) - - return + self.updateDeleteButtons() def storePurchaseDeleteDeactivateButtons(self): self.invFrame.reparentTo(self) @@ -617,27 +577,14 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): self.invFrame.setScale(0.81) self.detailFrame.setPos(1.175, 0, 0) self.detailFrame.setScale(1.25) + self.deleteAllButton.show() self.deleteEnterButton.show() - self.deleteEnterButton.setPos(-0.55, 0, -0.91) + self.deleteEnterButton.setPos(-0.8, 0, -0.91) self.deleteEnterButton.setScale(0.75) self.deleteExitButton.hide() - self.deleteExitButton.setPos(-0.551, 0, -0.91) + self.deleteExitButton.setPos(-0.8, 0, -0.91) self.deleteExitButton.setScale(0.75) - for track in xrange(len(Tracks)): - if self.toon.hasTrackAccess(track): - self.showTrack(track) - for level in xrange(len(Levels[track])): - button = self.buttons[track][level] - if self.itemIsUsable(track, level): - button.show() - self.makeUnpressable(button, track, level) - else: - button.hide() - - else: - self.hideTrack(track) - - return + self.updateUseableButtons() def storePurchaseBrokeDeactivateButtons(self): self.invFrame.reparentTo(self) @@ -686,36 +633,19 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): self.invFrame.setScale(0.81) self.detailFrame.setPos(1.17, 0, -0.02) self.detailFrame.setScale(1.25) - totalProps = self.totalProps - maxProps = self.toon.getMaxCarry() + self.deleteAllButton.show() self.deleteEnterButton.show() - self.deleteEnterButton.setPos(-0.441, 0, -0.917) + self.deleteEnterButton.setPos(-0.8, 0, -0.917) self.deleteEnterButton.setScale(0.75) self.deleteExitButton.hide() - self.deleteExitButton.setPos(-0.441, 0, -0.917) + self.deleteExitButton.setPos(-0.8, 0, -0.917) self.deleteExitButton.setScale(0.75) if self.gagTutMode: + self.deleteAllButton.hide() self.deleteEnterButton.hide() self.deleteEnterButton['command'] = self.setActivateMode self.deleteEnterButton['extraArgs'] = ['purchaseDelete'] - for track in xrange(len(Tracks)): - if self.toon.hasTrackAccess(track): - self.showTrack(track) - for level in xrange(len(Levels[track])): - button = self.buttons[track][level] - if self.itemIsUsable(track, level): - button.show() - if self.numItem(track, level) >= self.getMax(track, level) or totalProps == maxProps or level > LAST_REGULAR_GAG_LEVEL: - self.makeUnpressable(button, track, level) - else: - self.makePressable(button, track, level) - else: - button.hide() - - else: - self.hideTrack(track) - - return + self.updatePurchaseButtons() def purchaseDeactivateButtons(self): self.invFrame.reparentTo(self) @@ -733,31 +663,16 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): self.invFrame.setScale(0.81) self.detailFrame.setPos(1.175, 0, 0) self.detailFrame.setScale(1.25) - totalProps = self.totalProps - maxProps = self.toon.getMaxCarry() + self.deleteAllButton.show() self.deleteEnterButton.show() - self.deleteEnterButton.setPos(-0.55, 0, -0.91) + self.deleteEnterButton.setPos(-0.8, 0, -0.91) self.deleteEnterButton.setScale(0.75) self.deleteExitButton.hide() - self.deleteExitButton.setPos(-0.55, 0, -0.91) + self.deleteExitButton.setPos(-0.8, 0, -0.91) self.deleteExitButton.setScale(0.75) self.deleteEnterButton['command'] = self.setActivateMode self.deleteEnterButton['extraArgs'] = ['storePurchaseDelete'] - for track in xrange(len(Tracks)): - if self.toon.hasTrackAccess(track): - self.showTrack(track) - for level in xrange(len(Levels[track])): - button = self.buttons[track][level] - if self.itemIsUsable(track, level): - button.show() - if self.numItem(track, level) >= self.getMax(track, level) or totalProps == maxProps or level > LAST_REGULAR_GAG_LEVEL: - self.makeUnpressable(button, track, level) - else: - self.makePressable(button, track, level) - else: - button.hide() - else: - self.hideTrack(track) + self.updatePurchaseButtons() def storePurchaseDeactivateButtons(self): self.invFrame.reparentTo(self) @@ -775,13 +690,15 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): self.invFrame.setScale(0.81) self.detailFrame.setPos(1.17, 0, -0.02) self.detailFrame.setScale(1.25) + self.deleteAllButton.show() self.deleteEnterButton.show() - self.deleteEnterButton.setPos(-0.441, 0, -0.917) + self.deleteEnterButton.setPos(-0.8, 0, -0.917) self.deleteEnterButton.setScale(0.75) self.deleteExitButton.hide() - self.deleteExitButton.setPos(-0.441, 0, -0.917) + self.deleteExitButton.setPos(-0.8, 0, -0.917) self.deleteExitButton.setScale(0.75) if self.gagTutMode: + self.deleteAllButton.hide() self.deleteEnterButton.hide() for track in xrange(len(Tracks)): if self.toon.hasTrackAccess(track): @@ -816,28 +733,10 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): self.invFrame.setScale(0.81) self.detailFrame.setPos(1.17, 0, -0.02) self.detailFrame.setScale(1.25) - self.deleteEnterButton.show() - self.deleteEnterButton.setPos(-0.441, 0, -0.917) - self.deleteEnterButton.setScale(0.75) self.deleteExitButton.hide() - self.deleteExitButton.setPos(-0.441, 0, -0.917) - self.deleteExitButton.setScale(0.75) self.deleteEnterButton.hide() - for track in xrange(len(Tracks)): - if self.toon.hasTrackAccess(track): - self.showTrack(track) - for level in xrange(len(Levels[track])): - button = self.buttons[track][level] - if self.itemIsUsable(track, level): - button.show() - self.makeUnpressable(button, track, level) - else: - button.hide() - - else: - self.hideTrack(track) - - return + self.deleteAllButton.hide() + self.updateUseableButtons() def gagTutDisabledDeactivateButtons(self): self.invFrame.reparentTo(self) @@ -857,6 +756,7 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): self.invFrame.setScale(1) self.detailFrame.setPos(1.125, 0, -0.08) self.detailFrame.setScale(1) + self.deleteAllButton.hide() self.deleteEnterButton.hide() self.deleteExitButton.hide() if self.bldg == 1: @@ -919,10 +819,12 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): self.invFrame.setScale(1) self.detailFrame.setPos(1.125, 0, -0.08) self.detailFrame.setScale(1) + self.deleteAllButton.hide() self.deleteEnterButton.hide() self.deleteExitButton.hide() self.runButton.hide() self.sosButton.hide() + self.fireButton.hide() self.passButton['text'] = TTLocalizer.lCancel self.passButton.show() for track in xrange(len(Tracks)): @@ -960,7 +862,14 @@ class InventoryNew(InventoryBase.InventoryBase, DirectFrame): return 1 def itemIsCredit(self, track, level): - return self.battleCreditLevel == None or level < self.battleCreditLevel + if self.toon.earnedExperience: + if self.toon.earnedExperience[track] >= ExperienceCap: + return 0 + if self.battleCreditLevel == None: + return 1 + else: + return level < self.battleCreditLevel + return def getMax(self, track, level): if self.gagTutMode and (track not in (4, 5) or level > 0): diff --git a/toontown/toon/LaffRestockGlobals.py b/toontown/toon/LaffRestockGlobals.py index ecd817b9..5bef9aab 100755 --- a/toontown/toon/LaffRestockGlobals.py +++ b/toontown/toon/LaffRestockGlobals.py @@ -1,6 +1,21 @@ -LAFFCLERK_TIMER = 30 -FullLaff = 12 -NoMoney = 14 -Success = 1 -GuiOk = 'Ok' -GuiCancel = 'Cancel' +from toontown.toonbase import TTLocalizer + +TIMER_SECONDS = 30 + +# Laff Shop GUI +TIMER_END = 0 +USER_CANCEL = 1 +RESTOCK = 2 + +# Restock Results +FULL_LAFF = 0 +LESS_LAFF = 1 +NOT_ENOUGH_MONEY = 2 +RESTOCK_SUCCESSFUL = 3 + +RestockMessages = { + FULL_LAFF: TTLocalizer.RestockFullLaffMessage, + LESS_LAFF: TTLocalizer.RestockLessLaffMessage, + NOT_ENOUGH_MONEY: TTLocalizer.RestockNoMoneyMessage, + RESTOCK_SUCCESSFUL: TTLocalizer.RestockSuccessfulMessage +} \ No newline at end of file diff --git a/toontown/toon/LaffShopGui.py b/toontown/toon/LaffShopGui.py index ff2bc34f..f061598a 100755 --- a/toontown/toon/LaffShopGui.py +++ b/toontown/toon/LaffShopGui.py @@ -1,144 +1,117 @@ -from panda3d.core import * -from direct.directnotify import DirectNotifyGlobal -from direct.gui.DirectGui import * -from direct.showbase import DirectObject -from toontown.toonbase import ToontownGlobals -from toontown.toonbase import TTLocalizer +from direct.gui.DirectGui import DirectButton, DirectFrame, DGG from direct.task.Task import Task -from toontown.toonbase import ToontownTimer -import LaffRestockGlobals -from LaffMeter import LaffMeter +from otp.otpbase import OTPLocalizer +from toontown.toonbase import ToontownGlobals, TTLocalizer, ToontownTimer +import LaffMeter, LaffRestockGlobals class LaffShopGui(DirectFrame): - def __init__(self, text): - DirectFrame.__init__(self, parent=aspect2d, relief=None, geom=DGG.getDefaultDialogGeom(), geom_color=ToontownGlobals.GlobalDialogColor, geom_scale=(1.33, 1, 1.1), pos=(0, 0, 0), text=text, text_scale=0.07, text_pos=(0, 0.475)) + def __init__(self): + DirectFrame.__init__(self, parent=aspect2d, relief=None, geom=DGG.getDefaultDialogGeom(), geom_color=ToontownGlobals.GlobalDialogColor, geom_scale=(1.33, 1, 1.3), pos=(0, 0, 0), text='', text_scale=0.07, text_pos=(0, 0.475)) self.initialiseoptions(LaffShopGui) - self.text = text + + self.additionalLaff = 0 self.timer = ToontownTimer.ToontownTimer() self.timer.reparentTo(aspect2d) self.timer.posInTopRightCorner() - self.timer.accept('RESET_LAFFSHOP_TIMER', self.__resetTimer) - self.timer.countdown(LaffRestockGlobals.LAFFCLERK_TIMER, self.__timerExpired) - self.hp = base.localAvatar.getHp() - self.maxHp = base.localAvatar.getMaxHp() - self.floorLimit = self.hp - self.ceilLimit = 0 - money = base.localAvatar.getTotalMoney() - while self.ceilLimit * ToontownGlobals.CostPerLaffRestock < money: - self.ceilLimit += 1 - self.__additionalLaff = 0 - self.__setupButtons() - self.__bindButtons() - self.laffMeter = LaffMeter(base.localAvatar.style, self.hp, self.maxHp) + self.timer.countdown(LaffRestockGlobals.TIMER_SECONDS, self.__cancel, [LaffRestockGlobals.TIMER_END]) + self.setupButtons() + self.bindButtons() + self.laffMeter = LaffMeter.LaffMeter(base.localAvatar.style, base.localAvatar.getHp(), base.localAvatar.getMaxHp()) self.laffMeter.reparentTo(self) - self.laffMeter.setPos(0, 0, 0.165) + self.laffMeter.setPos(0, 0, 0.065) self.laffMeter.setScale(0.13) - self.__updateLaffMeter(0) + self.__updateLaffMeter(1) - def __setupButtons(self): + def setupButtons(self): buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui') arrowGui = loader.loadModel('phase_3/models/gui/create_a_toon_gui') - okImageList = (buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')) - cancelImageList = (buttons.find('**/CloseBtn_UP'), buttons.find('**/CloseBtn_DN'), buttons.find('**/CloseBtn_Rllvr')) arrowImageList = (arrowGui.find('**/CrtATn_R_Arrow_UP'), arrowGui.find('**/CrtATn_R_Arrow_DN'), arrowGui.find('**/CrtATn_R_Arrow_RLVR'), arrowGui.find('**/CrtATn_R_Arrow_UP')) - self.cancelButton = DirectButton(parent=self, relief=None, image=cancelImageList, pos=(-0.2, 0, -0.4), text=LaffRestockGlobals.GuiCancel, text_scale=0.06, text_pos=(0, -0.1), command=self.__cancel) - self.okButton = DirectButton(parent=self, relief=None, image=okImageList, pos=(0.2, 0, -0.4), text=LaffRestockGlobals.GuiOk, text_scale=0.06, text_pos=(0, -0.1), command=self.__requestLaff) - self.upArrow = DirectButton(parent=self, relief=None, image=arrowImageList, image_scale=(1, 1, 1), image3_color=Vec4(0.6, 0.6, 0.6, 0.25), pos=(0.2, 0, -0.165)) - self.downArrow = DirectButton(parent=self, relief=None, image=arrowImageList, image_scale=(-1, 1, 1), image3_color=Vec4(0.6, 0.6, 0.6, 0.25), pos=(-0.2, 0, -0.165)) + + self.cancelButton = DirectButton(parent=self, relief=None, image=(buttons.find('**/CloseBtn_UP'), buttons.find('**/CloseBtn_DN'), buttons.find('**/CloseBtn_Rllvr')), pos=(-0.2, 0, -0.5), text=OTPLocalizer.lCancel, text_scale=0.06, text_pos=(0, -0.1), command=self.__cancel, extraArgs=[LaffRestockGlobals.USER_CANCEL]) + self.okButton = DirectButton(parent=self, relief=None, image=(buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')), pos=(0.2, 0, -0.5), text=OTPLocalizer.lOK, text_scale=0.06, text_pos=(0, -0.1), command=self.__restock) + self.upArrow = DirectButton(parent=self, relief=None, image=arrowImageList, image_scale=(1, 1, 1), image3_color=Vec4(0.6, 0.6, 0.6, 0.25), pos=(0.2, 0, -0.265)) + self.downArrow = DirectButton(parent=self, relief=None, image=arrowImageList, image_scale=(-1, 1, 1), image3_color=Vec4(0.6, 0.6, 0.6, 0.25), pos=(-0.2, 0, -0.265)) + buttons.removeNode() arrowGui.removeNode() - def __bindButtons(self): - self.downArrow.bind(DGG.B1PRESS, self.__downButtonDown) - self.downArrow.bind(DGG.B1RELEASE, self.__downButtonUp) - self.upArrow.bind(DGG.B1PRESS, self.__upButtonDown) - self.upArrow.bind(DGG.B1RELEASE, self.__upButtonUp) + def bindButtons(self): + self.downArrow.bind(DGG.B1PRESS, self.__taskUpdate, extraArgs=[-1]) + self.downArrow.bind(DGG.B1RELEASE, self.__taskDone) + self.upArrow.bind(DGG.B1PRESS, self.__taskUpdate, extraArgs=[1]) + self.upArrow.bind(DGG.B1RELEASE, self.__taskDone) def destroy(self): self.ignoreAll() + if self.timer: self.timer.destroy() - taskMgr.remove(self.taskName('runCounter')) + + taskMgr.remove(self.taskName('runLaffCounter')) DirectFrame.destroy(self) - def __resetTimer(self): - if self.timer: - self.timer.stop() - self.timer.countdown(LaffRestockGlobals.LAFFCLERK_TIMER, self.__timerExpired) - - def __timerExpired(self): + def __cancel(self, state): self.destroy() - messenger.send('guiDone', [True]) + messenger.send('laffShopDone', [state, 0]) - def __cancel(self): + def __restock(self): self.destroy() - messenger.send('guiDone', [False]) + messenger.send('laffShopDone', [LaffRestockGlobals.RESTOCK, self.additionalLaff]) - def __requestLaff(self): - if self.timer: - self.ignoreAll() - self.destroy() - cost = self.__additionalLaff * ToontownGlobals.CostPerLaffRestock - messenger.send('restockLaff', [self.__additionalLaff, cost]) - messenger.send('guiDone', [False]) - - def __updateLaffMeter(self, amt): + def __updateLaffMeter(self, amount): + self.additionalLaff += amount hitLimit = 0 - self.__additionalLaff += amt - newLaff = self.hp + self.__additionalLaff - cost = self.__additionalLaff * ToontownGlobals.CostPerLaffRestock - if newLaff <= self.floorLimit: + newLaff = base.localAvatar.getHp() + self.additionalLaff + + if (newLaff - 1) <= base.localAvatar.getHp(): self.downArrow['state'] = DGG.DISABLED hitLimit = 1 else: self.downArrow['state'] = DGG.NORMAL - if newLaff >= self.maxHp or self.__additionalLaff >= self.ceilLimit: + + if newLaff >= base.localAvatar.getMaxHp(): self.upArrow['state'] = DGG.DISABLED hitLimit = 1 else: self.upArrow['state'] = DGG.NORMAL - self['text'] = TTLocalizer.RestockAskMessage % (self.__additionalLaff, cost) + + cost = self.additionalLaff * ToontownGlobals.CostPerLaffRestock + self['text'] = TTLocalizer.RestockAskMessage % (self.additionalLaff, cost) + + if cost > base.localAvatar.getTotalMoney(): + self.okButton['state'] = DGG.DISABLED + self['text'] += TTLocalizer.RestockNoMoneyGuiMessage + else: + self.okButton['state'] = DGG.NORMAL + self.laffMeter.hp = newLaff self.laffMeter.start() - return (hitLimit, newLaff, self.__additionalLaff) - def __runCounter(self, task): + return hitLimit + + def __runTask(self, task): if task.time - task.prevTime < task.delayTime: return Task.cont else: task.delayTime = max(0.05, task.delayTime * 0.75) task.prevTime = task.time - hitLimit, laff, trans = self.__updateLaffMeter(task.delta) - if hitLimit: - return Task.done - else: - return Task.cont + hitLimit = self.__updateLaffMeter(task.delta) - def __downButtonUp(self, event): - messenger.send('wakeup') - taskMgr.remove(self.taskName('runCounter')) + return Task.done if hitLimit else Task.cont - def __downButtonDown(self, event): + def __taskDone(self, event): messenger.send('wakeup') - task = Task(self.__runCounter) + taskMgr.remove(self.taskName('runLaffCounter')) + + def __taskUpdate(self, delta, event): + messenger.send('wakeup') + + task = Task(self.__runTask) task.delayTime = 0.4 task.prevTime = 0.0 - task.delta = -1 - hitLimit, laff, trans = self.__updateLaffMeter(task.delta) - if not hitLimit: - taskMgr.add(task, self.taskName('runCounter')) + task.delta = delta + hitLimit = self.__updateLaffMeter(delta) - def __upButtonUp(self, event): - messenger.send('wakeup') - taskMgr.remove(self.taskName('runCounter')) - - def __upButtonDown(self, event): - messenger.send('wakeup') - task = Task(self.__runCounter) - task.delayTime = 0.4 - task.prevTime = 0.0 - task.delta = 1 - hitLimit, laff, trans = self.__updateLaffMeter(task.delta) if not hitLimit: - taskMgr.add(task, self.taskName('runCounter')) + taskMgr.add(task, self.taskName('runLaffCounter')) \ No newline at end of file diff --git a/toontown/toon/LaughingManGlobals.py b/toontown/toon/LaughingManGlobals.py deleted file mode 100755 index 80dc05d6..00000000 --- a/toontown/toon/LaughingManGlobals.py +++ /dev/null @@ -1,43 +0,0 @@ -from panda3d.core import * - -def makeCard(book=False): - cardMaker = CardMaker('king-jake-cm') - cardMaker.setHasUvs(1) - cardMaker.setFrame(-0.5, 0.5, -0.5, 0.5) - - nodePath = NodePath('king-jake') - nodePath.setBillboardPointEye() - - lmBase = nodePath.attachNewNode(cardMaker.generate()) - lmBase.setTexture(loader.loadTexture('phase_3/maps/kj_base.png')) - lmBase.setY(-0.3) - lmBase.setScale(0.845) - lmBase.setTransparency(True) - - lmText = nodePath.attachNewNode(cardMaker.generate()) - lmText.setTexture(loader.loadTexture('phase_3/maps/kj_text.png')) - lmText.setY(-0.301) - lmText.setScale(0.845) - lmText.setTransparency(True) - lmText.hprInterval(10, (0, 0, -360)).loop() - - lmFace = nodePath.attachNewNode(cardMaker.generate()) - lmFace.setTexture(loader.loadTexture('phase_3/maps/lm_face.rgba')) - lmFace.setY(-0.302) - lmFace.setTransparency(True) - - return nodePath - -def addHeadEffect(head, book=False): - card = makeCard(book=book) - card.setScale(1.45 if book else 2.5) - card.setZ(0.05 if book else 0.5) - - for nodePath in head.getChildren(): - nodePath.hide() - - card.instanceTo(head) - -def addToonEffect(toon): - for lod in toon.getLODNames(): - addHeadEffect(toon.getPart('head', lod)) diff --git a/toontown/toon/LocalToon.py b/toontown/toon/LocalToon.py index 204215c2..580159a4 100755 --- a/toontown/toon/LocalToon.py +++ b/toontown/toon/LocalToon.py @@ -47,7 +47,7 @@ from toontown.shtiker import QuestPage from toontown.shtiker import ShardPage from toontown.shtiker import ShtikerBook from toontown.shtiker import SuitPage -from toontown.shtiker import TIPPage +from toontown.shtiker import StatPage from toontown.shtiker import TrackPage from toontown.toon import ElevatorNotifier from toontown.toon import ToonDNA @@ -168,6 +168,7 @@ class LocalToon(DistributedToon.DistributedToon, LocalAvatar.LocalAvatar): def setName(self, name): base.localAvatarName = name DistributedToon.DistributedToon.setName(self, name) + messenger.send('refreshNametagStyle') def wantLegacyLifter(self): return True @@ -338,6 +339,9 @@ class LocalToon(DistributedToon.DistributedToon, LocalAvatar.LocalAvatar): self.photoPage.load() self.book.addPage(self.photoPage, pageName=TTLocalizer.PhotoPageTitle) self.addEventsPage() + self.statPage = StatPage.StatPage() + self.statPage.load() + self.book.addPage(self.statPage, pageName=TTLocalizer.StatPageTitle) self.book.setPage(self.mapPage, enterPage=False) self.laffMeter = LaffMeter.LaffMeter(self.style, self.hp, self.maxHp) self.laffMeter.setAvatar(self) @@ -1133,9 +1137,9 @@ class LocalToon(DistributedToon.DistributedToon, LocalAvatar.LocalAvatar): if self.__gardeningGui: return gardenGuiCard = loader.loadModel('phase_5.5/models/gui/planting_gui') - self.__gardeningGui = DirectFrame(relief=None, geom=gardenGuiCard, geom_color=GlobalDialogColor, geom_scale=(0.17, 1.0, 0.3), pos=(-1.2, 0, 0.5), scale=1.0) + self.__gardeningGui = DirectFrame(relief=None, parent=base.a2dTopLeft, geom=gardenGuiCard, geom_color=GlobalDialogColor, geom_scale=(0.17, 1.0, 0.3), pos=(0.1335, 0.0, -0.50), scale=1.0) self.__gardeningGui.setName('gardeningFrame') - self.__gardeningGuiFake = DirectFrame(relief=None, geom=None, geom_color=GlobalDialogColor, geom_scale=(0.17, 1.0, 0.3), pos=(-1.2, 0, 0.5), scale=1.0) + self.__gardeningGuiFake = DirectFrame(relief=None, parent=base.a2dTopLeft, geom=None, geom_color=GlobalDialogColor, geom_scale=(0.17, 1.0, 0.3), pos=(0.1335, 0.0, -0.50), scale=1.0) self.__gardeningGuiFake.setName('gardeningFrameFake') iconScale = 1 iconColorWhite = Vec4(1.0, 1.0, 1.0, 1.0) @@ -1653,13 +1657,8 @@ class LocalToon(DistributedToon.DistributedToon, LocalAvatar.LocalAvatar): self.book.addPage(self.eventsPage, pageName=TTLocalizer.EventsPageName) return - def addTIPPage(self): - self.tipPage = TIPPage.TIPPage() - self.tipPage.load() - self.book.addPage(self.tipPage, pageName=TTLocalizer.TIPPageTitle) - - def setPinkSlips(self, pinkSlips): - DistributedToon.DistributedToon.setPinkSlips(self, pinkSlips) + def setSpecialInventory(self, specialInventory): + DistributedToon.DistributedToon.setSpecialInventory(self, specialInventory) self.inventory.updateTotalPropsText() def hasActiveBoardingGroup(self): diff --git a/toontown/toon/NPCToons.py b/toontown/toon/NPCToons.py index ec4cbe32..c4652bb9 100755 --- a/toontown/toon/NPCToons.py +++ b/toontown/toon/NPCToons.py @@ -67,9 +67,8 @@ NPC_PARTYPERSON = 8 NPC_SPECIALQUESTGIVER = 9 NPC_FLIPPYTOONHALL = 10 NPC_SCIENTIST = 11 -NPC_SMART = 12 -NPC_GLOVE = 13 -NPC_LAFF_RESTOCK = 14 +NPC_GLOVE = 12 +NPC_LAFF_RESTOCK = 13 CLERK_COUNTDOWN_TIME = 120 TAILOR_COUNTDOWN_TIME = 300 @@ -90,7 +89,6 @@ def createNPC(air, npcId, desc, zoneId, posIndex = 0, questCallback = None): import DistributedNPCSpecialQuestGiverAI import DistributedNPCFlippyInToonHallAI import DistributedNPCScientistAI - import DistributedSmartNPCAI import DistributedNPCGloveAI import DistributedNPCLaffRestockAI canonicalZoneId, name, dnaType, gender, protected, type = desc @@ -118,8 +116,6 @@ def createNPC(air, npcId, desc, zoneId, posIndex = 0, questCallback = None): npc = DistributedNPCFlippyInToonHallAI.DistributedNPCFlippyInToonHallAI(air, npcId) elif type == NPC_SCIENTIST: npc = DistributedNPCScientistAI.DistributedNPCScientistAI(air, npcId) - elif type == NPC_SMART: - npc = DistributedSmartNPCAI.DistributedSmartNPCAI(air, npcId) elif type == NPC_GLOVE: npc = DistributedNPCGloveAI.DistributedNPCGloveAI(air, npcId) elif type == NPC_LAFF_RESTOCK: @@ -161,9 +157,6 @@ def createNpcsInZone(air, zoneId): if npcDesc[5] == NPC_PARTYPERSON: if not air.wantParties: continue - if npcDesc[5] == NPC_SMART: - if not config.GetBool('want-talkative-tyler', False): - continue npcs.append(createNPC(air, npcId, npcDesc, zoneId, posIndex=i)) return npcs @@ -225,12 +218,6 @@ NPCToonDict = {20000: (-1, 'm', 1, NPC_SPECIALQUESTGIVER), - 998: (2000, - lnames[998], - 'r', - 'm', - 1, - NPC_SMART), 999: (-1, lnames[999], 'r', @@ -642,6 +629,25 @@ NPCToonDict = {20000: (-1, 'm', 1, NPC_SCIENTIST), + 2021: (2000, + lnames[2021], + ('dss', + 'ls', + 's', + 'm', + 13, + 0, + 13, + 13, + 1, + 6, + 1, + 6, + 0, + 18), + 'm', + 1, + NPC_GLOVE), 2101: (2601, lnames[2101], ('rll', @@ -11135,234 +11141,223 @@ NPCToonDict = {20000: (-1, 'm', 0, NPC_FISHERMAN), - 9301: (-1, + 9301: (9329, lnames[9301], - ('pss', - 'ms', + 'r', + 'm', + 0, + NPC_FISHERMAN), + 9302: (9802, + lnames[9302], + ('dss', + 'ld', 'l', - 'm', - 20, + 'f', + 17, 0, - 20, - 20, + 17, + 17, + 5, + 21, + 5, + 21, + 8, + 26), + 'f', + 0, + NPC_REGULAR), + 9303: (9826, + lnames[9303], + 'r', + 'm', + 0, + NPC_REGULAR), + 9304: (9804, + lnames[9304], + ('dss', + 'ls', + 's', + 'm', + 16, + 0, + 16, + 16, + 14, + 10, + 10, + 10, + 3, + 19), + 'm', + 0, + NPC_REGULAR), + 9305: (9829, + lnames[9305], + 'r', + 'm', + 0, + NPC_HQ), + 9306: (9829, + lnames[9306], + 'r', + 'm', + 0, + NPC_HQ), + 9307: (9829, + lnames[9307], + 'r', + 'f', + 0, + NPC_HQ), + 9308: (9829, + lnames[9308], + 'r', + 'f', + 0, + NPC_HQ), + 9309: (9808, + lnames[9309], + ('css', + 'ms', + 'm', + 'm', 26, 0, - 0, - 0, - 15, - 0), - 'm', - 0, - NPC_REGULAR), - 9302: (-1, - lnames[9302], - ('bsl', - 'ms', - 'm', - 'f', - 20, - 0, - 20, - 20, - 3, + 26, + 26, + 8, 4, - 0, - 0, - 5, - 18), - 'f', - 0, - NPC_REGULAR), - 9303: (-1, - lnames[9303], - ('bll', - 'ss', - 's', - 'm', - 11, - 0, - 11, - 11, - 3, - 6, - 0, - 0, - 1, - 2), - 'm', - 0, - NPC_REGULAR), - 9304: (-1, - lnames[9304], - ('ssl', - 'sd', - 'l', - 'f', - 13, - 0, - 13, - 13, - 1, - 2, - 0, - 0, - 0, - 10), - 'f', - 0, - NPC_REGULAR), - 9305: (-1, - lnames[9305], - ('hll', - 'ls', - 'l', - 'm', 8, - 0, - 8, - 8, - 1, - 3, - 0, - 0, - 1, - 16), - 'm', - 0, - NPC_REGULAR), - 9306: (-1, - lnames[9306], - ('dsl', - 'ms', - 's', - 'm', - 5, - 0, - 5, - 5, - 1, - 0, - 0, - 0, - 0, + 4, + 7, 4), 'm', 0, NPC_REGULAR), - 9307: (-1, - lnames[9307], - ('pls', - 'ls', - 's', - 'f', - 14, - 0, - 14, - 14, - 0, - 11, - 0, - 0, - 5, - 9), - 'f', - 0, - NPC_REGULAR), - 9308: (-1, - lnames[9308], - ('bsl', - 'ls', - 'l', - 'm', - 12, - 0, - 12, - 12, - 1, - 10, - 0, - 0, - 1, - 13), - 'm', - 0, - NPC_REGULAR), - 9309: (-1, - lnames[9309], - ('sss', - 'ms', - 'l', - 'm', - 2, - 0, - 2, - 2, - 0, - 4, - 0, - 0, - 0, - 6), - 'm', - 0, - NPC_REGULAR), - 9310: (-1, + 9310: (9820, lnames[9310], - ('fsl', - 'ls', - 'm', - 'm', - 17, - 0, - 17, - 17, - 4, - 4, - 0, - 0, - 0, - 10), + 'r', 'm', 0, NPC_REGULAR), - 9311: (-1, + 9311: (9809, lnames[9311], - ('mss', - 'sd', - 's', - 'f', + ('dls', + 'ls', + 'm', + 'm', 24, 0, - 24, - 24, - 3, + 18, + 18, + 11, + 7, + 0, + 7, 1, - 0, - 0, - 0, - 13), + 11), + 'm', + 0, + NPC_REGULAR), + 9312: (9828, + lnames[9312], + 'r', 'f', 0, NPC_REGULAR), - 9312: (-1, - lnames[9312], - ('pss', - 'sd', - 'l', - 'f', - 9, - 0, - 9, - 9, - 0, - 8, - 0, - 0, - 11, - 0), + 9313: (9827, + lnames[9313], + 'r', + 'm', + 0, + NPC_REGULAR), + 9314: (9812, + lnames[9314], + 'r', + 'm', + 0, + NPC_REGULAR), + 9315: (9813, + lnames[9315], + 'r', 'f', 0, NPC_REGULAR), + 9316: (9814, + lnames[9316], + 'r', + 'f', + 0, + NPC_REGULAR), + 9317: (9815, + lnames[9317], + ('css', + 'md', + 's', + 'f', + 22, + 0, + 22, + 22, + 7, + 4, + 7, + 4, + 8, + 11), + 'f', + 0, + NPC_REGULAR), + 9318: (9816, + lnames[9318], + 'r', + 'm', + 0, + NPC_REGULAR), + 9319: (9817, + lnames[9319], + ('css', + 'ls', + 'm', + 'm', + 26, + 0, + 26, + 26, + 5, + 11, + 5, + 11, + 5, + 11), + 'm', + 0, + NPC_REGULAR), + 9320: (9819, + lnames[9320], + 'r', + 'm', + 0, + NPC_REGULAR), + 9321: (9824, + lnames[9321], + ('dss', + 'ms', + 'm', + 'm', + 2, + 0, + 2, + 2, + 4, + 1, + 4, + 1, + 2, + 16), + 'm', + 0, + NPC_REGULAR), 7001: (-1, lnames[7001], ('bss', @@ -11536,20 +11531,21 @@ NPCToonDict = {20000: (-1, NPC_REGULAR), 7010: (-1, lnames[7010], - ('dss', + ('rll', 'ms', - 's', 'm', - 13, + 'm', + 2, 0, + 2, + 2, + 19, + 10, 13, - 13, - 4, - 4, - 4, - 4, - 1, - 4), + 10, + 7, + 14, + 0), 'm', 0, NPC_REGULAR), @@ -11568,88 +11564,258 @@ NPCToonDict = {20000: (-1, 0, 10, 5, - 27, - 0), + 27), 'm', 0, NPC_REGULAR), + 7012: (-1, + lnames[7012], + ('pss', + 'ms', + 'l', + 'm', + 20, + 0, + 20, + 20, + 26, + 0, + 0, + 0, + 15), + 'm', + 0, + NPC_REGULAR), + 7013: (-1, + lnames[7013], + ('bsl', + 'ms', + 'm', + 'f', + 20, + 0, + 20, + 20, + 3, + 4, + 0, + 0, + 5, + 18), + 'f', + 0, + NPC_REGULAR), + 7014: (-1, + lnames[7014], + ('bll', + 'ss', + 's', + 'm', + 11, + 0, + 11, + 11, + 3, + 6, + 0, + 0, + 1, + 2), + 'm', + 0, + NPC_REGULAR), + 7015: (-1, + lnames[7015], + ('ssl', + 'sd', + 'l', + 'f', + 13, + 0, + 13, + 13, + 1, + 2, + 0, + 0, + 0, + 10), + 'f', + 0, + NPC_REGULAR), + 7016: (-1, + lnames[7016], + ('hll', + 'ls', + 'l', + 'm', + 8, + 0, + 8, + 8, + 1, + 3, + 0, + 0, + 1, + 16), + 'm', + 0, + NPC_REGULAR), + 7017: (-1, + lnames[7017], + ('dsl', + 'ms', + 's', + 'm', + 5, + 0, + 5, + 5, + 1, + 0, + 0, + 0, + 0, + 4), + 'm', + 0, + NPC_REGULAR), + 7018: (-1, + lnames[7018], + ('pls', + 'ls', + 's', + 'f', + 14, + 0, + 14, + 14, + 0, + 11, + 0, + 0, + 5, + 9), + 'f', + 0, + NPC_REGULAR), + 7019: (-1, + lnames[7019], + ('bsl', + 'ls', + 'l', + 'm', + 12, + 0, + 12, + 12, + 1, + 10, + 0, + 0, + 1, + 13), + 'm', + 0, + NPC_REGULAR), + 7020: (-1, + lnames[7020], + ('sss', + 'ms', + 'l', + 'm', + 2, + 0, + 2, + 2, + 0, + 4, + 0, + 0, + 0, + 6), + 'm', + 0, + NPC_REGULAR), + 7021: (-1, + lnames[7021], + ('fsl', + 'ls', + 'm', + 'm', + 17, + 0, + 17, + 17, + 4, + 4, + 0, + 0, + 0, + 10), + 'm', + 0, + NPC_REGULAR), + 7022: (-1, + lnames[7022], + ('mss', + 'sd', + 's', + 'f', + 24, + 0, + 24, + 24, + 3, + 1, + 0, + 0, + 0, + 13), + 'f', + 0, + NPC_REGULAR), + 7023: (-1, + lnames[7023], + ('pss', + 'sd', + 'l', + 'f', + 9, + 0, + 9, + 9, + 0, + 8, + 0, + 0, + 11, + 0), + 'f', + 0, + NPC_REGULAR), 10001: (10000, lnames[10001], - ('fss', - 'md', - 'l', - 'f', - 11, - 0, - 11, - 11, - 0, - 3, - 0, - 3, - 4, - 7, - 0), + 'r', 'f', 0, NPC_LAFF_RESTOCK), 11001: (11000, lnames[11001], - ('dll', - 'ls', - 's', - 'm', - 6, - 0, - 6, - 6, - 9, - 3, - 9, - 3, - 2, - 4, - 0), + 'r', 'm', 0, NPC_LAFF_RESTOCK), 12001: (12000, lnames[12001], - ('mss', - 'ls', - 's', - 'm', - 8, - 0, - 8, - 8, - 5, - 12, - 5, - 12, - 7, - 16, - 0), + 'r', 'm', 0, NPC_LAFF_RESTOCK), 13001: (13000, lnames[13001], - ('dss', - 'ld', - 's', - 'f', - 17, - 0, - 17, - 17, - 1, - 24, - 1, - 24, - 0, - 9, - 0), + 'r', 'f', 0, NPC_LAFF_RESTOCK)} @@ -11696,7 +11862,7 @@ else: NPC_REGULAR) BlockerPositions = {TTLocalizer.Flippy: (Point3(207.4, 18.81, -0.475), 90.0)} LaffRestockPositions = {lnames[11001]: ((-27.0, -170.0, -19.6), 215.0), - lnames[12001]: ((361.9, -394.4, -23.5), 113.5), + lnames[12001]: ((361.9, -394.4, -23.5), 120.0), lnames[13001]: ((143.7, -381.4, -68.4), 0.0), lnames[10001]: ((135.0, 128.8, 0.025), -212.8)} GlovePositions = {lnames[2021]: ((101, -14, 4), -305)} @@ -11854,53 +12020,53 @@ HQnpcFriends = {2001: (ToontownBattleGlobals.HEAL_TRACK, ToontownBattleGlobals.DROP_TRACK, 0, 3)} -FOnpcFriends = {9310: (ToontownBattleGlobals.LURE_TRACK, - 1, - 0, - 0), - 9311: (ToontownBattleGlobals.LURE_TRACK, - 1, - 0, - 1), - 9312: (ToontownBattleGlobals.LURE_TRACK, +FOnpcFriends = {7012: (ToontownBattleGlobals.HEAL_TRACK, 3, - 0, - 2), - 9307: (ToontownBattleGlobals.SOUND_TRACK, - 1, 10, 0), - 9308: (ToontownBattleGlobals.SOUND_TRACK, + 7013: (ToontownBattleGlobals.HEAL_TRACK, 3, 20, 1), - 9309: (ToontownBattleGlobals.SOUND_TRACK, - 4, + 7014: (ToontownBattleGlobals.HEAL_TRACK, + 3, 30, 2), - 9304: (ToontownBattleGlobals.DROP_TRACK, + 7015: (ToontownBattleGlobals.DROP_TRACK, 1, 20, 0), - 9305: (ToontownBattleGlobals.DROP_TRACK, + 7016: (ToontownBattleGlobals.DROP_TRACK, 2, 35, 1), - 9306: (ToontownBattleGlobals.DROP_TRACK, + 7017: (ToontownBattleGlobals.DROP_TRACK, 3, 50, 2), - 9301: (ToontownBattleGlobals.HEAL_TRACK, - 3, + 7018: (ToontownBattleGlobals.SOUND_TRACK, + 1, 10, 0), - 9302: (ToontownBattleGlobals.HEAL_TRACK, + 7019: (ToontownBattleGlobals.SOUND_TRACK, 3, 20, 1), - 9303: (ToontownBattleGlobals.HEAL_TRACK, - 3, + 7020: (ToontownBattleGlobals.SOUND_TRACK, + 4, 30, + 2), + 7021: (ToontownBattleGlobals.LURE_TRACK, + 1, + 0, + 0), + 7022: (ToontownBattleGlobals.LURE_TRACK, + 1, + 0, + 1), + 7023: (ToontownBattleGlobals.LURE_TRACK, + 3, + 0, 2)} disabledSosCards = ConfigVariableList('disable-sos-card') diff --git a/toontown/toon/QuestionMgr.py b/toontown/toon/QuestionMgr.py deleted file mode 100755 index a61444ac..00000000 --- a/toontown/toon/QuestionMgr.py +++ /dev/null @@ -1,139 +0,0 @@ -# Embedded file name: /Users/pierredavidbelanger/Dev/chatter-bot-api/python/chatterbotapi.py -import md5 -import urllib -import urllib2 -import uuid -import xml.dom.minidom - -class ChatterBotType: - CLEVERBOT = 1 - JABBERWACKY = 2 - PANDORABOTS = 3 - - -class ChatterBotFactory: - - def create(self, type, arg = None): - if type == ChatterBotType.CLEVERBOT: - return _Cleverbot('http://www.cleverbot.com/webservicemin', 35) - elif type == ChatterBotType.JABBERWACKY: - return _Cleverbot('http://jabberwacky.com/webservicemin', 29) - elif type == ChatterBotType.PANDORABOTS: - if arg == None: - raise Exception('PANDORABOTS needs a botid arg') - return _Pandorabots(arg) - else: - return - - -class ChatterBot: - - def create_session(self): - return None - - -class ChatterBotSession: - - def think_thought(self, thought): - return thought - - def think(self, text): - thought = ChatterBotThought() - thought.text = text - return self.think_thought(thought).text - - -class ChatterBotThought: - pass - - -class _Cleverbot(ChatterBot): - - def __init__(self, url, endIndex): - self.url = url - self.endIndex = endIndex - - def create_session(self): - return _CleverbotSession(self) - - -class _CleverbotSession(ChatterBotSession): - - def __init__(self, bot): - self.bot = bot - self.vars = {} - self.vars['start'] = 'y' - self.vars['icognoid'] = 'wsf' - self.vars['fno'] = '0' - self.vars['sub'] = 'Say' - self.vars['islearning'] = '1' - self.vars['cleanslate'] = 'false' - - def think_thought(self, thought): - self.vars['stimulus'] = thought.text - data = urllib.urlencode(self.vars) - data_to_digest = data[9:self.bot.endIndex] - data_digest = md5.new(data_to_digest).hexdigest() - data = data + '&icognocheck=' + data_digest - url_response = urllib2.urlopen(self.bot.url, data) - response = url_response.read() - response_values = response.split('\r') - self.vars['sessionid'] = _utils_string_at_index(response_values, 1) - self.vars['logurl'] = _utils_string_at_index(response_values, 2) - self.vars['vText8'] = _utils_string_at_index(response_values, 3) - self.vars['vText7'] = _utils_string_at_index(response_values, 4) - self.vars['vText6'] = _utils_string_at_index(response_values, 5) - self.vars['vText5'] = _utils_string_at_index(response_values, 6) - self.vars['vText4'] = _utils_string_at_index(response_values, 7) - self.vars['vText3'] = _utils_string_at_index(response_values, 8) - self.vars['vText2'] = _utils_string_at_index(response_values, 9) - self.vars['prevref'] = _utils_string_at_index(response_values, 10) - self.vars['emotionalhistory'] = _utils_string_at_index(response_values, 12) - self.vars['ttsLocMP3'] = _utils_string_at_index(response_values, 13) - self.vars['ttsLocTXT'] = _utils_string_at_index(response_values, 14) - self.vars['ttsLocTXT3'] = _utils_string_at_index(response_values, 15) - self.vars['ttsText'] = _utils_string_at_index(response_values, 16) - self.vars['lineRef'] = _utils_string_at_index(response_values, 17) - self.vars['lineURL'] = _utils_string_at_index(response_values, 18) - self.vars['linePOST'] = _utils_string_at_index(response_values, 19) - self.vars['lineChoices'] = _utils_string_at_index(response_values, 20) - self.vars['lineChoicesAbbrev'] = _utils_string_at_index(response_values, 21) - self.vars['typingData'] = _utils_string_at_index(response_values, 22) - self.vars['divert'] = _utils_string_at_index(response_values, 23) - response_thought = ChatterBotThought() - response_thought.text = _utils_string_at_index(response_values, 16) - return response_thought - - -class _Pandorabots(ChatterBot): - - def __init__(self, botid): - self.botid = botid - - def create_session(self): - return _PandorabotsSession(self) - - -class _PandorabotsSession(ChatterBotSession): - - def __init__(self, bot): - self.vars = {} - self.vars['botid'] = bot.botid - self.vars['custid'] = uuid.uuid1() - - def think_thought(self, thought): - self.vars['input'] = thought.text - data = urllib.urlencode(self.vars) - url_response = urllib2.urlopen('http://www.pandorabots.com/pandora/talk-xml', data) - response = url_response.read() - response_dom = xml.dom.minidom.parseString(response) - response_thought = ChatterBotThought() - response_thought.text = response_dom.getElementsByTagName('that')[0].childNodes[0].data.strip() - return response_thought - - -def _utils_string_at_index(strings, index): - if len(strings) > index: - return strings[index] - else: - return '' diff --git a/toontown/toon/QuestionMgrCustom.py b/toontown/toon/QuestionMgrCustom.py deleted file mode 100755 index c1c10d30..00000000 --- a/toontown/toon/QuestionMgrCustom.py +++ /dev/null @@ -1,26 +0,0 @@ -import random - - -class QuestionMgr: - - def __init__(self): - self.greetings = ['hi', 'hello', 'hey', 'sup', 'howdy', 'yo'] - self.greetingResp = ['Hello there, ', 'Howdy there, ', 'Hows it hanging, ', 'How do you do, ', 'Whats up, ', 'Woah! You scared me there '] - self.response = '' - self.confused = 1 - - def ask(self, message, sender): - msg = message.lower() - vbls = msg.split() - for i in xrange(0, len(vbls)): - if vbls[i] in self.greetings: - index = random.randint(0, len(self.greetingResp) -1) - helloResp = self.greetingResp[index] - respFinal = helloResp + '%s' % sender + '!' - self.response += helloResp - self.confused = 0 - else: - if self.confused: - self.response += 'Dang, I really don\'t understand you.' - self.confused = 1 - return self.response diff --git a/toontown/toon/Toon.py b/toontown/toon/Toon.py index 67ad6e52..9778f10d 100755 --- a/toontown/toon/Toon.py +++ b/toontown/toon/Toon.py @@ -28,7 +28,6 @@ from otp.nametag.NametagGroup import * from toontown.suit import SuitDNA from toontown.toonbase import TTLocalizer from toontown.toonbase import ToontownGlobals -from toontown.toon import LaughingManGlobals def teleportDebug(requestStatus, msg, onlyIfToAv = True): if teleportNotify.getDebug(): @@ -453,7 +452,7 @@ class Toon(Avatar.Avatar, ToonHead): self.partyHat = None self.setTag('pieCode', str(ToontownGlobals.PieCodeToon)) self.setFont(ToontownGlobals.getToonFont()) - self.setSpeechFont(ToontownGlobals.getToonFont()) + self.nametag.setSpeechFont(ToontownGlobals.getToonFont()) self.soundChatBubble = base.loadSfx('phase_3/audio/sfx/GUI_balloon_popup.ogg') self.swimRunSfx = base.loadSfx('phase_4/audio/sfx/AV_footstep_runloop_water.ogg') self.swimRunLooping = False @@ -564,8 +563,8 @@ class Toon(Avatar.Avatar, ToonHead): def updateToonDNA(self, newDNA, fForce = 0): self.style.gender = newDNA.getGender() oldDNA = self.style - if fForce or newDNA.head != oldDNA.head or newDNA.laughingMan != oldDNA.laughingMan: - self.swapToonHead(newDNA.head, newDNA.laughingMan) + if fForce or newDNA.head != oldDNA.head: + self.swapToonHead(newDNA.head) if fForce or newDNA.torso != oldDNA.torso: self.swapToonTorso(newDNA.torso, genClothes=0) self.loop('neutral') @@ -644,7 +643,6 @@ class Toon(Avatar.Avatar, ToonHead): self.rescaleToon() self.resetHeight() self.setupToonNodes() - self.generateLaughingMan() def setupToonNodes(self): rightHand = NodePath('rightHand') @@ -829,7 +827,7 @@ class Toon(Avatar.Avatar, ToonHead): self.loadAnims(HeadAnimDict[self.style.head], 'head', '500') self.loadAnims(HeadAnimDict[self.style.head], 'head', '250') - def swapToonHead(self, headStyle=-1, laughingMan=0, copy = 1): + def swapToonHead(self, headStyle=-1, copy = 1): self.stopLookAroundNow() self.eyelids.request('open') self.unparentToonParts() @@ -848,8 +846,6 @@ class Toon(Avatar.Avatar, ToonHead): self.resetHeight() self.eyelids.request('open') self.startLookAround() - if laughingMan or self.getWantLaughingMan(): - LaughingManGlobals.addToonEffect(self) def generateToonColor(self): ToonHead.generateToonColor(self, self.style) @@ -860,17 +856,17 @@ class Toon(Avatar.Avatar, ToonHead): torso = self.getPart('torso', lodName) if len(self.style.torso) == 1: parts = torso.findAllMatches('**/torso*') - parts.setColor(armColor) + parts.setColor(*armColor) for pieceName in ('arms', 'neck'): piece = torso.find('**/' + pieceName) - piece.setColor(armColor) + piece.setColor(*armColor) hands = torso.find('**/hands') - hands.setColor(gloveColor) + hands.setColor(*gloveColor) legs = self.getPart('legs', lodName) for pieceName in ('legs', 'feet'): piece = legs.find('**/%s;+s' % pieceName) - piece.setColor(legColor) + piece.setColor(*legColor) if self.cheesyEffect == ToontownGlobals.CEGreenToon: self.reapplyCheesyEffect() @@ -983,10 +979,6 @@ class Toon(Avatar.Avatar, ToonHead): return swappedTorso - def generateLaughingMan(self): - if self.getWantLaughingMan(): - self.swapToonHead(laughingMan=True) - def generateHat(self, fromRTM = False): hat = self.getHat() if hat[0] >= len(ToonDNA.HatModels): @@ -1160,12 +1152,6 @@ class Toon(Avatar.Avatar, ToonHead): def getHat(self): return self.hat - def getWantLaughingMan(self): - return self.style.laughingMan or self.getWantLaughingManHoliday() - - def getWantLaughingManHoliday(self): - return base.cr.newsManager and base.cr.newsManager.isHolidayRunning(ToontownGlobals.LAUGHING_MAN) - def setGlasses(self, glassesIdx, textureIdx, colorIdx, fromRTM = False): self.glasses = (glassesIdx, textureIdx, colorIdx) self.generateGlasses(fromRTM=fromRTM) @@ -1818,6 +1804,20 @@ class Toon(Avatar.Avatar, ToonHead): self.getGeomNode().setClipPlane(self.holeClipPath) self.nametag3d.setClipPlane(self.holeClipPath) avHeight = max(self.getHeight(), 3) + + if self == base.localAvatar and settings['tpTransition'] and not ZoneUtil.isDynamicZone(self.zoneId): + def lerpCam(task): + degrees = task.time * 52.941 + radians = degrees * (math.pi / 180.0) + x = -12 * math.sin(radians) + y = -12 * math.cos(radians) + z = base.localAvatar.getHeight() + camera.setPos(x, y, z) + camera.setH(-degrees) + return task.done if task.time > 3.4 else task.cont + + taskMgr.add(lerpCam, 'lerpCam') + self.track.start(ts) self.setActiveShadow(0) @@ -2417,14 +2417,14 @@ class Toon(Avatar.Avatar, ToonHead): legColor = color headColor = color for piece in torsoPieces: - colorTrack.append(Func(piece.setColor, armColor)) + colorTrack.append(Func(piece.setColor, *armColor)) for piece in legPieces: - colorTrack.append(Func(piece.setColor, legColor)) + colorTrack.append(Func(piece.setColor, *legColor)) for piece in headPieces: if 'hatNode' not in str(piece) and 'glassesNode' not in str(piece): - colorTrack.append(Func(piece.setColor, headColor)) + colorTrack.append(Func(piece.setColor, *headColor)) track.append(colorTrack) return track @@ -2441,13 +2441,13 @@ class Toon(Avatar.Avatar, ToonHead): else: headColor = color for piece in earPieces: - colorTrack.append(Func(piece.setColor, headColor)) + colorTrack.append(Func(piece.setColor, *headColor)) else: if colorScale == None: colorScale = VBase4(1, 1, 1, 1) for piece in earPieces: - colorTrack.append(Func(piece.setColorScale, colorScale)) + colorTrack.append(Func(piece.setColorScale, *colorScale)) track.append(colorTrack) return track @@ -2748,7 +2748,7 @@ class Toon(Avatar.Avatar, ToonHead): self.suit.loop('neutral') self.isDisguised = 1 self.setFont(ToontownGlobals.getSuitFont()) - self.setSpeechFont(ToontownGlobals.getSuitFont()) + self.nametag.setSpeechFont(ToontownGlobals.getSuitFont()) if setDisplayName: if hasattr(base, 'idTags') and base.idTags: name = self.getAvIdName() @@ -2782,7 +2782,7 @@ class Toon(Avatar.Avatar, ToonHead): Emote.globalEmote.releaseAll(self) self.isDisguised = 0 self.setFont(ToontownGlobals.getToonFont()) - self.setSpeechFont(ToontownGlobals.getToonFont()) + self.nametag.setSpeechFont(ToontownGlobals.getToonFont()) self.nametag.setWordwrap(None) if hasattr(base, 'idTags') and base.idTags: name = self.getAvIdName() diff --git a/toontown/toon/ToonAvatarDetailPanel.py b/toontown/toon/ToonAvatarDetailPanel.py index bad3e2fb..5e28dff0 100755 --- a/toontown/toon/ToonAvatarDetailPanel.py +++ b/toontown/toon/ToonAvatarDetailPanel.py @@ -10,7 +10,7 @@ from toontown.friends import FriendInviter import ToonTeleportPanel from toontown.toonbase import TTLocalizer from toontown.hood import ZoneUtil -from toontown.toonbase.ToontownBattleGlobals import Tracks, Levels +from toontown.toonbase.ToontownBattleGlobals import Tracks, Levels, getAvPropDamage from toontown.toon import Toon globalAvatarDetail = None @@ -192,6 +192,9 @@ class ToonAvatarDetailPanel(DirectFrame): ySpacing = -0.115 inventory = self.avatar.inventory inventoryModels = loader.loadModel('phase_3.5/models/gui/inventory_gui') + rolloverFrame = DirectFrame(parent=self, relief=None, geom=DGG.getDefaultDialogGeom(), geom_color=(0, 0.5, 1, 1), geom_scale=(0.5, 0.3, 0.2), text_scale=0.05, text_pos=(0, 0.0125), text='', text_fg=(1, 1, 1, 1)) + rolloverFrame.setBin('gui-popup', 0) + rolloverFrame.hide() buttonModel = inventoryModels.find('**/InventoryButtonUp') for track in xrange(0, len(Tracks)): DirectLabel(parent=self, relief=None, text=TextEncoder.upper(TTLocalizer.BattleGlobalTracks[track]), text_scale=TTLocalizer.TADPtrackLabel, text_align=TextNode.ALeft, pos=(-0.9, 0, TTLocalizer.TADtrackLabelPosZ + track * ySpacing)) @@ -201,20 +204,30 @@ class ToonAvatarDetailPanel(DirectFrame): level = Levels[track][item] if curExp >= level: numItems = inventory.numItem(track, item) + organic = self.avatar.checkGagBonus(track, item) if numItems == 0: image_color = Vec4(0.5, 0.5, 0.5, 1) geom_color = Vec4(0.2, 0.2, 0.2, 0.5) - elif self.avatar.getTrackBonusLevel(track) >= item: + elif organic: image_color = Vec4(0, 0.8, 0.4, 1) geom_color = None else: image_color = Vec4(0, 0.6, 1, 1) geom_color = None - DirectLabel(parent=self, image=buttonModel, image_scale=(0.92, 1, 1), image_color=image_color, geom=inventory.invModels[track][item], geom_color=geom_color, geom_scale=0.6, relief=None, pos=(xOffset + item * xSpacing, 0, yOffset + track * ySpacing)) + pos = (xOffset + item * xSpacing, 0, yOffset + track * ySpacing) + label = DirectLabel(parent=self, image=buttonModel, image_scale=(0.92, 1, 1), image_color=image_color, geom=inventory.invModels[track][item], geom_color=geom_color, geom_scale=0.6, relief=None, pos=pos, state=DGG.NORMAL) + label.bind(DGG.ENTER, self.showInfo, extraArgs=[rolloverFrame, track, int(getAvPropDamage(track, item, curExp, organic)), numItems, (pos[0] + 0.37, pos[1], pos[2])]) + label.bind(DGG.EXIT, self.hideInfo, extraArgs=[rolloverFrame]) else: break + + def showInfo(self, frame, track, damage, numItems, pos, extra): + frame.setPos(*pos) + frame.show() + frame['text'] = TTLocalizer.GagPopup % (self.avatar.inventory.getToonupDmgStr(track, 0), damage, numItems) - return + def hideInfo(self, frame, extra): + frame.hide() def __updateTrophyInfo(self): if self.createdAvatar: diff --git a/toontown/toon/ToonAvatarPanel.py b/toontown/toon/ToonAvatarPanel.py index b93a5429..50def5d4 100755 --- a/toontown/toon/ToonAvatarPanel.py +++ b/toontown/toon/ToonAvatarPanel.py @@ -8,6 +8,7 @@ from direct.distributed import DistributedObject from direct.directnotify import DirectNotifyGlobal from toontown.toonbase import ToontownGlobals from toontown.toonbase import TTLocalizer +from toontown.friends import ToontownFriendSecret import ToonAvatarDetailPanel import AvatarPanelBase from toontown.toontowngui import TTDialog @@ -353,6 +354,10 @@ class ToonAvatarPanel(AvatarPanelBase.AvatarPanelBase): def __handleWhisper(self): base.localAvatar.chatMgr.whisperTo(self.avName, self.avId) + def __handleTrueFriends(self): + base.localAvatar.chatMgr.noWhisper() + ToontownFriendSecret.showFriendSecret() + def __handleFriend(self): base.localAvatar.chatMgr.noWhisper() messenger.send('friendAvatar', [self.avId, self.avName, self.avDisableName]) @@ -549,47 +554,4 @@ class ToonAvatarPanel(AvatarPanelBase.AvatarPanelBase): self.boardingInfoText = None groupInviteGui.removeNode() groupAvatarBgGui.removeNode() - helpGui.removeNode() - return - - def __handleTrueFriends(self): - if not settings['trueFriends']: - base.localAvatar.chatMgr.fsm.request('noTrueFriends') - return - - self.cleanupDialog() - base.cr.playGame.getPlace().fsm.request('stopped') - - if base.localAvatar.isTrueFriends(self.avatar.doId): - self.dialog = TTDialog.TTDialog(style=TTDialog.YesNo, text=TTLocalizer.TrueFriendsRemoveNotice % self.avatar.getName(), text_wordwrap=20, command=self.confirmTrueFriendsRemove) - self.dialog.show() - elif not base.cr.isFriend(self.avatar.doId): - self.dialog = TTDialog.TTDialog(style=TTDialog.Acknowledge, text=TTLocalizer.TrueFriendsNotFriends % self.avatar.getName(), text_wordwrap=20, command=self.cleanupDialogAndWalk) - self.dialog.show() - else: - self.dialog = TTDialog.TTDialog(style=TTDialog.YesNo, text=TTLocalizer.TrueFriendsAddNotice % self.avatar.getName(), text_wordwrap=20, command=self.confirmTrueFriendsAdd) - self.dialog.show() - - def confirmTrueFriendsAdd(self, state): - self.cleanupDialog() - - if state > 0: - base.localAvatar.addTrueFriends(self.avatar.doId) - self.dialog = TTDialog.TTDialog(style=TTDialog.Acknowledge, text=TTLocalizer.TrueFriendsAdded.replace('%s', self.avatar.getName()), text_wordwrap=20, command=self.cleanupDialogAndWalk) - self.dialog.show() - else: - base.cr.playGame.getPlace().fsm.request('walk') - - def confirmTrueFriendsRemove(self, state): - self.cleanupDialog() - - if state > 0: - base.localAvatar.removeTrueFriends(self.avatar.doId) - self.dialog = TTDialog.TTDialog(style=TTDialog.Acknowledge, text=TTLocalizer.TrueFriendsRemoved % self.avatar.getName(), text_wordwrap=20, command=self.cleanupDialogAndWalk) - self.dialog.show() - else: - base.cr.playGame.getPlace().fsm.request('walk') - - def cleanupDialogAndWalk(self, state=None): - self.cleanupDialog() - base.cr.playGame.getPlace().fsm.request('walk') + helpGui.removeNode() \ No newline at end of file diff --git a/toontown/toon/ToonDNA.py b/toontown/toon/ToonDNA.py index 39e294b1..0c326aa5 100755 --- a/toontown/toon/ToonDNA.py +++ b/toontown/toon/ToonDNA.py @@ -1,8 +1,9 @@ -import random +import random, colorsys from panda3d.core import * from direct.directnotify.DirectNotifyGlobal import * from direct.distributed.PyDatagram import PyDatagram from direct.distributed.PyDatagramIterator import PyDatagramIterator +from toontown.toonbase import ToontownGlobals notify = directNotify.newCategory('ToonDNA') mergeMATTailor = config.GetBool('want-mat-all-tailors', 0) toonSpeciesTypes = ['d', @@ -294,7 +295,7 @@ Shirts = ['phase_3/maps/desat_shirt_1.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', - 'phase_4/maps/WeedShirt.jpg'] + 'phase_4/maps/flannelshirt_red.jpg'] BoyShirts = [(0, 0), (1, 1), (2, 2), @@ -477,7 +478,7 @@ Sleeves = ['phase_3/maps/desat_sleeve_1.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', - 'phase_4/maps/WeedSleeve.jpg'] + 'phase_4/maps/flannelsleeve_red.jpg'] BoyShorts = ['phase_3/maps/desat_shorts_1.jpg', 'phase_3/maps/desat_shorts_2.jpg', 'phase_3/maps/desat_shorts_4.jpg', @@ -1202,7 +1203,7 @@ ShirtStyles = {'bss1': [0, 0, [(0, 0), 'jb_2': [113, 100, [(27, 27)]], 'ugcms': [117, 104, [(27, 27)]], 'lb_1': [119, 106, [(27, 27)]], - 'weed': [148, 135, [(27, 27)]]} + 'flannel': [148, 135, [(27, 27)]]} BottomStyles = {'bbs1': [0, [0, 1, 2, @@ -1891,47 +1892,47 @@ def getAllBottoms(gender, output = 'both'): return bottoms -allColorsList = [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), - VBase4(0.863281, 0.40625, 0.417969, 1.0), - VBase4(0.710938, 0.234375, 0.4375, 1.0), - VBase4(0.570312, 0.449219, 0.164062, 1.0), - VBase4(0.640625, 0.355469, 0.269531, 1.0), - VBase4(0.996094, 0.695312, 0.511719, 1.0), - VBase4(0.832031, 0.5, 0.296875, 1.0), - VBase4(0.992188, 0.480469, 0.167969, 1.0), - VBase4(0.996094, 0.898438, 0.320312, 1.0), - VBase4(0.996094, 0.957031, 0.597656, 1.0), - VBase4(0.855469, 0.933594, 0.492188, 1.0), - VBase4(0.550781, 0.824219, 0.324219, 1.0), - VBase4(0.242188, 0.742188, 0.515625, 1.0), - VBase4(0.304688, 0.96875, 0.402344, 1.0), - VBase4(0.433594, 0.90625, 0.835938, 1.0), - VBase4(0.347656, 0.820312, 0.953125, 1.0), - VBase4(0.191406, 0.5625, 0.773438, 1.0), - VBase4(0.558594, 0.589844, 0.875, 1.0), - VBase4(0.285156, 0.328125, 0.726562, 1.0), - VBase4(0.460938, 0.378906, 0.824219, 1.0), - VBase4(0.546875, 0.28125, 0.75, 1.0), - VBase4(0.726562, 0.472656, 0.859375, 1.0), - VBase4(0.898438, 0.617188, 0.90625, 1.0), - VBase4(0.7, 0.7, 0.8, 1.0), - VBase4(0.3, 0.3, 0.35, 1.0), - VBase4(0.0, 0.635294, 0.258823, 1.0), - VBase4(0.674509, 0.925490, 1.0, 1.0), - VBase4(0.988235, 0.894117, 0.745098, 1.0), - VBase4(0.749019, 1.0, 0.847058, 1.0), - VBase4(0.470588, 0.443137, 0.447058, 1.0), - VBase4(0.996078, 0.254901, 0.392156, 1.0), - VBase4(0.811764, 0.709803, 0.231372, 1.0), - VBase4(0.749019, 0.756862, 0.760784, 1.0), - VBase4(1.0, 0.639215, 0.262745, 1.0), - VBase4(0.0, 0.403921, 0.647058, 1.0), - VBase4(0.862745, 0.078431, 0.235294, 1.0), - VBase4(0.0, 0.635294, 0.513725, 1.0), - VBase4(0.803921, 0.498039, 0.196078, 1.0)] -defaultBoyColorList = [0, +allColorsList = [(1.0, 1.0, 1.0, 1.0), + (0.96, 0.69, 0.69, 1.0), + (0.93, 0.26, 0.28, 1.0), + (0.86, 0.40, 0.41, 1.0), + (0.71, 0.23, 0.43, 1.0), + (0.57, 0.44, 0.16, 1.0), + (0.64, 0.35, 0.26, 1.0), + (0.99, 0.69, 0.51, 1.0), + (0.83, 0.5, 0.29, 1.0), + (0.99, 0.48, 0.16, 1.0), + (0.99, 0.89, 0.32, 1.0), + (0.99, 0.95, 0.59, 1.0), + (0.85, 0.93, 0.49, 1.0), + (0.55, 0.82, 0.32, 1.0), + (0.24, 0.74, 0.51, 1.0), + (0.30, 0.96, 0.4, 1.0), + (0.43, 0.9, 0.83, 1.0), + (0.34, 0.82, 0.95, 1.0), + (0.19, 0.56, 0.77, 1.0), + (0.55, 0.58, 0.87, 1.0), + (0.28, 0.32, 0.72, 1.0), + (0.46, 0.37, 0.82, 1.0), + (0.54, 0.28, 0.75, 1.0), + (0.72, 0.47, 0.85, 1.0), + (0.89, 0.61, 0.9, 1.0), + (0.7, 0.7, 0.8, 1.0), + (0.3, 0.3, 0.35, 1.0), + (0.0, 0.63, 0.25, 1.0), + (0.67, 0.92, 1.0, 1.0), + (0.98, 0.89, 0.74, 1.0), + (0.74, 1.0, 0.84, 1.0), + (0.47, 0.44, 0.44, 1.0), + (0.99, 0.25, 0.39, 1.0), + (0.81, 0.7, 0.23, 1.0), + (0.74, 0.75, 0.76, 1.0), + (1.0, 0.63, 0.26, 1.0), + (0.0, 0.4, 0.64, 1.0), + (0.86, 0.07, 0.23, 1.0), + (0.0, 0.63, 0.51, 1.0), + (0.8, 0.49, 0.19, 1.0)] +defaultColorList = [0, 1, 32, 2, @@ -1971,48 +1972,6 @@ defaultBoyColorList = [0, 34, 31, 26] -defaultGirlColorList = [0, - 1, - 32, - 2, - 3, - 4, - 5, - 6, - 7, - 29, - 8, - 37, - 35, - 9, - 10, - 33, - 11, - 12, - 30, - 13, - 14, - 15, - 39, - 27, - 28, - 16, - 17, - 18, - 19, - 20, - 21, - 38, - 36, - 22, - 23, - 24, - 25, - 34, - 31, - 26] -allColorsListApproximations = map(lambda x: VBase4(round(x[0], 3), round(x[1], 3), round(x[2], 3), round(x[3], 3)), allColorsList) -allowedColors = set(map(lambda x: allColorsListApproximations[x], set([0] + defaultBoyColorList + defaultGirlColorList + [26]))) HatModels = [None, 'phase_4/models/accessories/tt_m_chr_avt_acc_hat_baseball', 'phase_4/models/accessories/tt_m_chr_avt_acc_hat_safari', @@ -2450,24 +2409,21 @@ class ToonDNA: self.newToonFromProperties(*dna.asTuple()) else: self.type = 'u' - self.cache = () - return def __str__(self): string = 'type = toon\n' string = string + 'gender = %s\n' % self.gender string = string + 'head = %s, torso = %s, legs = %s\n' % (self.head, self.torso, self.legs) - string = string + 'arm color = %d\n' % self.armColor - string = string + 'glove color = %d\n' % self.gloveColor - string = string + 'leg color = %d\n' % self.legColor - string = string + 'head color = %d\n' % self.headColor + string = string + 'arm color = %s\n' % (self.armColor,) + string = string + 'glove color = %s\n' % (self.gloveColor,) + string = string + 'leg color = %s\n' % (self.legColor,) + string = string + 'head color = %s\n' % (self.headColor,) string = string + 'top texture = %d\n' % self.topTex string = string + 'top texture color = %d\n' % self.topTexColor string = string + 'sleeve texture = %d\n' % self.sleeveTex string = string + 'sleeve texture color = %d\n' % self.sleeveTexColor string = string + 'bottom texture = %d\n' % self.botTex string = string + 'bottom texture color = %d\n' % self.botTexColor - string = string + 'laughing man = %d\n' % self.laughingMan return string def clone(self): @@ -2495,28 +2451,22 @@ class ToonDNA: dg.addUint8(self.sleeveTexColor) dg.addUint8(self.botTex) dg.addUint8(self.botTexColor) - dg.addUint8(self.armColor) - dg.addUint8(self.gloveColor) - dg.addUint8(self.legColor) - dg.addUint8(self.headColor) - dg.addUint8(self.laughingMan) + self.armColor = self.migrateColor(self.armColor) + self.gloveColor = self.migrateColor(self.gloveColor) + self.legColor = self.migrateColor(self.legColor) + self.headColor = self.migrateColor(self.headColor) + for colors in (self.armColor, self.gloveColor, self.legColor, self.headColor): + for color in colors[:-1]: + dg.addFloat64(color) elif self.type == 'u': notify.error('undefined avatar') else: notify.error('unknown avatar type: ', self.type) return dg.getMessage() - def getDatagramWithFallback(self, dgi, fallback=0): - try: - return dgi.getUint8() - except: - return fallback - def isValidNetString(self, string): dg = PyDatagram(string) dgi = PyDatagramIterator(dg) - if dgi.getRemainingSize() not in [15, 16]: - return False type = dgi.getFixedString(1) if type not in ('t',): return False @@ -2540,11 +2490,10 @@ class ToonDNA: sleeveTexColor = dgi.getUint8() botTex = dgi.getUint8() botTexColor = dgi.getUint8() - armColor = dgi.getUint8() - gloveColor = dgi.getUint8() - legColor = dgi.getUint8() - headColor = dgi.getUint8() - laughingMan = self.getDatagramWithFallback(dgi, 0) + armColor = (dgi.getFloat64(), dgi.getFloat64(), dgi.getFloat64(), 1.0) + gloveColor = (dgi.getFloat64(), dgi.getFloat64(), dgi.getFloat64(), 1.0) + legColor = (dgi.getFloat64(), dgi.getFloat64(), dgi.getFloat64(), 1.0) + headColor = (dgi.getFloat64(), dgi.getFloat64(), dgi.getFloat64(), 1.0) if topTex >= len(Shirts): return False if topTexColor >= len(ClothesColors): @@ -2557,15 +2506,22 @@ class ToonDNA: return False if botTexColor >= len(ClothesColors): return False - if armColor >= len(allColorsList): + if not self.isValid(armColor): return False - if legColor >= len(allColorsList): + if not self.isValid(gloveColor): return False - if headColor >= len(allColorsList): + if not self.isValid(legColor): return False - if laughingMan != 0 and laughingMan != 1: + if not self.isValid(headColor): return False return True + + def isValid(self, color): + if color in allColorsList: + return True + + hsv = colorsys.rgb_to_hsv(*color[:-1]) + return ToontownGlobals.COLOR_SATURATION_MIN <= hsv[1] <= ToontownGlobals.COLOR_SATURATION_MAX and ToontownGlobals.COLOR_VALUE_MIN <= hsv[2] <= ToontownGlobals.COLOR_VALUE_MAX def makeFromNetString(self, string): dg = PyDatagram(string) @@ -2589,25 +2545,16 @@ class ToonDNA: self.sleeveTexColor = dgi.getUint8() self.botTex = dgi.getUint8() self.botTexColor = dgi.getUint8() - self.armColor = dgi.getUint8() - self.gloveColor = dgi.getUint8() - self.legColor = dgi.getUint8() - self.headColor = dgi.getUint8() - self.laughingMan = self.getDatagramWithFallback(dgi, 0) + self.armColor = (dgi.getFloat64(), dgi.getFloat64(), dgi.getFloat64(), 1.0) + self.gloveColor = (dgi.getFloat64(), dgi.getFloat64(), dgi.getFloat64(), 1.0) + self.legColor = (dgi.getFloat64(), dgi.getFloat64(), dgi.getFloat64(), 1.0) + self.headColor = (dgi.getFloat64(), dgi.getFloat64(), dgi.getFloat64(), 1.0) else: notify.error('unknown avatar type: ', self.type) - return None def defaultColor(self): return 25 - def __defaultColors(self): - color = self.defaultColor() - self.armColor = color - self.gloveColor = 0 - self.legColor = color - self.headColor = color - def newToon(self, dna, color = None): if len(dna) == 4: self.type = 't' @@ -2622,35 +2569,36 @@ class ToonDNA: self.botTex = 0 self.botTexColor = 0 if color == None: - color = self.defaultColor() + color = 25 + color = self.migrateColor(color) self.armColor = color self.legColor = color self.headColor = color self.gloveColor = 0 - self.laughingMan = 0 else: notify.error("tuple must be in format ('%s', '%s', '%s', '%s')") - return + + def migrateColor(self, color): + return allColorsList[color] if isinstance(color, int) else color - def newToonFromProperties(self, head, torso, legs, gender, armColor, gloveColor, legColor, headColor, topTexture, topTextureColor, sleeveTexture, sleeveTextureColor, bottomTexture, bottomTextureColor, laughingMan=0): + def newToonFromProperties(self, head, torso, legs, gender, armColor, gloveColor, legColor, headColor, topTexture, topTextureColor, sleeveTexture, sleeveTextureColor, bottomTexture, bottomTextureColor): self.type = 't' self.head = head self.torso = torso self.legs = legs self.gender = gender - self.armColor = armColor - self.gloveColor = gloveColor - self.legColor = legColor - self.headColor = headColor + self.armColor = self.migrateColor(armColor) + self.gloveColor = self.migrateColor(gloveColor) + self.legColor = self.migrateColor(legColor) + self.headColor = self.migrateColor(headColor) self.topTex = topTexture self.topTexColor = topTextureColor self.sleeveTex = sleeveTexture self.sleeveTexColor = sleeveTextureColor self.botTex = bottomTexture self.botTexColor = bottomTextureColor - self.laughingMan = laughingMan - def updateToonProperties(self, head = None, torso = None, legs = None, gender = None, armColor = None, gloveColor = None, legColor = None, headColor = None, topTexture = None, topTextureColor = None, sleeveTexture = None, sleeveTextureColor = None, bottomTexture = None, bottomTextureColor = None, shirt = None, bottom = None, laughingMan = False): + def updateToonProperties(self, head = None, torso = None, legs = None, gender = None, armColor = None, gloveColor = None, legColor = None, headColor = None, topTexture = None, topTextureColor = None, sleeveTexture = None, sleeveTextureColor = None, bottomTexture = None, bottomTextureColor = None, shirt = None, bottom = None): if head: self.head = head if torso: @@ -2660,13 +2608,13 @@ class ToonDNA: if gender: self.gender = gender if armColor: - self.armColor = armColor + self.armColor = self.migrateColor(armColor) if gloveColor: - self.gloveColor = gloveColor + self.gloveColor = self.migrateColor(gloveColor) if legColor: - self.legColor = legColor + self.legColor = self.migrateColor(legColor) if headColor: - self.headColor = headColor + self.headColor = self.migrateColor(headColor) if topTexture: self.topTex = topTexture if topTextureColor: @@ -2679,7 +2627,6 @@ class ToonDNA: self.botTex = bottomTexture if bottomTextureColor: self.botTexColor = bottomTextureColor - self.laughingMan = laughingMan if shirt: str, colorIndex = shirt defn = ShirtStyles[str] @@ -2715,6 +2662,7 @@ class ToonDNA: self.head = generator.choice(toonHeadTypes[:22]) top, topColor, sleeve, sleeveColor = getRandomTop(gender, generator=generator) bottom, bottomColor = getRandomBottom(gender, generator=generator) + color = generator.choice(allColorsList) if gender == 'm': self.torso = generator.choice(toonTorsoTypes[:3]) self.topTex = top @@ -2723,10 +2671,6 @@ class ToonDNA: self.sleeveTexColor = sleeveColor self.botTex = bottom self.botTexColor = bottomColor - color = generator.choice(defaultBoyColorList) - self.armColor = color - self.legColor = color - self.headColor = color else: self.torso = generator.choice(toonTorsoTypes[:6]) self.topTex = top @@ -2739,12 +2683,10 @@ class ToonDNA: bottom, bottomColor = getRandomBottom(gender, generator=generator, girlBottomType=SHORTS) self.botTex = bottom self.botTexColor = bottomColor - color = generator.choice(defaultGirlColorList) - self.armColor = color - self.legColor = color - self.headColor = color - self.gloveColor = 0 - self.laughingMan = 0 + self.armColor = color + self.legColor = color + self.headColor = color + self.gloveColor = self.migrateColor(0) def asTuple(self): return (self.head, @@ -2760,8 +2702,7 @@ class ToonDNA: self.sleeveTex, self.sleeveTexColor, self.botTex, - self.botTexColor, - self.laughingMan) + self.botTexColor) def getType(self): if self.type == 't': @@ -2842,28 +2783,16 @@ class ToonDNA: notify.error('unknown clothing type: ', self.torso[1]) def getArmColor(self): - try: - return allColorsList[self.armColor] - except: - return allColorsList[0] + return self.armColor def getLegColor(self): - try: - return allColorsList[self.legColor] - except: - return allColorsList[0] + return self.legColor def getHeadColor(self): - try: - return allColorsList[self.headColor] - except: - return allColorsList[0] + return self.headColor def getGloveColor(self): - try: - return allColorsList[self.gloveColor] - except: - return allColorsList[0] + return self.gloveColor def getBlackColor(self): try: @@ -2872,24 +2801,4 @@ class ToonDNA: return allColorsList[0] def getWhiteColor(self): - return allColorsList[0] - - def isLaughingMan(self): - return self.laughingMan - - def setTemporary(self, newHead, newArmColor, newLegColor, newHeadColor): - if not self.cache and self.getArmColor != newArmColor: - self.cache = (self.head, - self.armColor, - self.legColor, - self.headColor) - self.updateToonProperties(head=newHead, armColor=newArmColor, legColor=newLegColor, headColor=newHeadColor) - - def restoreTemporary(self, oldStyle): - cache = () - if oldStyle: - cache = oldStyle.cache - if cache: - self.updateToonProperties(head=cache[0], armColor=cache[1], legColor=cache[2], headColor=cache[3]) - if oldStyle: - oldStyle.cache = () + return allColorsList[0] \ No newline at end of file diff --git a/toontown/toon/ToonHead.py b/toontown/toon/ToonHead.py index 85b73c14..5893bad3 100755 --- a/toontown/toon/ToonHead.py +++ b/toontown/toon/ToonHead.py @@ -8,7 +8,6 @@ from direct.interval.IntervalGlobal import * from direct.fsm.ClassicFSM import ClassicFSM from direct.fsm.State import State from direct.directnotify import DirectNotifyGlobal -from toontown.toon import LaughingManGlobals if not base.config.GetBool('want-new-anims', 1): HeadDict = {'dls': '/models/char/dogMM_Shorts-head-', @@ -196,8 +195,6 @@ class ToonHead(Actor.Actor): self.getGeomNode().setDepthTest(1) if dna.getAnimal() == 'dog': self.loop('neutral') - if dna.laughingMan: - LaughingManGlobals.addHeadEffect(self.getGeomNode(), book=forGui) def fitAndCenterHead(self, maxDim, forGui = 0): p1 = Point3() diff --git a/toontown/toonbase/TTLocalizerEnglish.py b/toontown/toonbase/TTLocalizerEnglish.py index 90a79f24..763e7d51 100755 --- a/toontown/toonbase/TTLocalizerEnglish.py +++ b/toontown/toonbase/TTLocalizerEnglish.py @@ -36,7 +36,7 @@ NametagFonts = ( 'phase_3/models/fonts/DinosaursAreAlive.ttf' ) NametagFontNames = ( - 'Default', + 'Basic', 'Plain', 'Shivering', 'Wonky', @@ -56,7 +56,6 @@ NametagFontNames = ( 'Dinosaurs' ) NametagLabel = ' Nametag' -BasicNameTag = 'Basic' ScreenshotPath = 'user/screenshots/' Flippy = 'Flippy' lTheBrrrgh = 'The Brrrgh' @@ -96,23 +95,23 @@ GlobalStreetNames = {20000: ('to', 'on', 'Tutorial Terrace'), 9100: ('to', 'on', 'Lullaby Lane'), 9200: ('to', 'on', 'Pajama Place'), 9300: ('to', 'on', 'Bedtime Boulevard'), - 10000: ('to', 'in', 'Bossbot HQ Country Club'), + 10000: ('to the', 'in the', 'Bossbot HQ Country Club'), 10100: ('to the', 'in the', 'Bossbot HQ Lobby'), - 10200: ('to the', 'in the', 'The Clubhouse'), - 10500: ('to the', 'in the', 'The Front Three'), - 10600: ('to the', 'in the', 'The Middle Six'), - 10700: ('to the', 'in the', 'The Back Nine'), + 10200: ('to', 'in', 'The Clubhouse'), + 10500: ('to', 'in', 'The Front Three'), + 10600: ('to', 'in', 'The Middle Six'), + 10700: ('to', 'in', 'The Back Nine'), 11000: ('to the', 'in the', 'Sellbot HQ Courtyard'), 11100: ('to the', 'in the', 'Sellbot HQ Lobby'), 11200: ('to the', 'in the', 'Sellbot Factory'), 11500: ('to the', 'in the', 'Sellbot Factory'), 11600: ('to the', 'in the', 'Sellbot Megacorp'), - 12000: ('to', 'in', 'Cashbot Train Yard'), + 12000: ('to the', 'in the', 'Cashbot Train Yard'), 12100: ('to the', 'in the', 'Cashbot HQ Lobby'), 12500: ('to the', 'in the', 'Cashbot Coin Mint'), 12600: ('to the', 'in the', 'Cashbot Dollar Mint'), 12700: ('to the', 'in the', 'Cashbot Bullion Mint'), - 13000: ('to', 'in', 'Lawbot HQ Courtyard'), + 13000: ('to the', 'in the', 'Lawbot HQ Courtyard'), 13100: ('to the', 'in the', 'Courthouse Lobby'), 13200: ('to the', 'in the', "DA's Office Lobby"), 13300: ('to the', 'in the', 'Lawbot A Office'), @@ -398,6 +397,8 @@ TIPQuestsClothingTicketRewardPoster = 'Reward: TIP Clothing Ticket' QuestsCheesyEffectRewardPoster = 'Reward: %s' QuestsCogSuitPartReward = 'You now have a %(cogTrack)s %(part)s Cog Suit Part.' QuestsCogSuitPartRewardPoster = 'Reward: %(cogTrack)s %(part)s Part' +QuestsEPPReward = 'You now have %s Easy Promotion Papers.' +QuestsEPPRewardPoster = 'Reward: %s Easy Promotion Papers' QuestsStreetLocationThisPlayground = 'in this playground' QuestsStreetLocationThisStreet = 'on this street' QuestsStreetLocationNamedPlayground = 'in the %s playground' @@ -3056,10 +3057,8 @@ ElevatorHopOff = 'Hop off' ElevatorStayOff = "If you hop off, you'll need to wait\nfor the elevator to leave or empty." ElevatorLeaderOff = 'Only your leader can decide when to hop off.' ElevatorHoppedOff = 'You need to wait for the next elevator.' -ElevatorMinLaff = 'You need %s laff points to ride this elevator.' ElevatorHopOK = 'Okay' ElevatorGroupMember = 'Only your group leader can\n decide when to board.' -KartMinLaff = 'You need %s laff points to ride this kart' CogsIncExt = ', Inc.' CogsIncModifier = '%s' + CogsIncExt CogsInc = Cogs.upper() + CogsIncExt @@ -3246,6 +3245,7 @@ FriendsListPanelNewFriend = 'New Friend' FriendsListPanelOnlineFriends = 'ONLINE TOON\nFRIENDS' FriendsListPanelAllFriends = 'ALL TOON\nFRIENDS' FriendsListPanelPets = 'NEARBY\nPETS' +FriendsListPanelTrueFriends = 'True Friends' FriendInviterClickToon = 'Click on the toon you would like to make friends with.\n\n(You have %s friends)' FriendInviterThatToon = 'That toon' FriendInviterToonTooMany = 'You have too many toon friends to add another one now. You will have to remove some toon friends if you want to make friends with %s.' @@ -3261,12 +3261,11 @@ AvatarChoiceNameRejected = 'Name\nRejected' AvatarChoiceNameApproved = 'Name\nApproved!' AvatarChoiceNameReview = 'Under\nReview' AvatarChoiceNameYourToon = 'Name\nYour Toon!' -AvatarChoiceDeleteConfirmText = 'Careful! This will delete %(name)s forever. If you are sure you want to do this, type "%(confirm)s" and click OK.' -AvatarChoiceDeleteConfirmUserTypes = 'delete' +AvatarChoiceDeleteConfirmText = "Careful! This will delete %(name)s forever. If you are sure you want to do this, type your toon's name and click OK." AvatarChoiceDeletePasswordTitle = 'Delete Toon?' AvatarChoiceDeletePasswordOK = lOK AvatarChoiceDeletePasswordCancel = lCancel -AvatarChoiceDeleteWrongConfirm = 'You didn\'t type the right thing. To delete %(name)s, type "%(confirm)s" and click OK. Do not type the quotation marks. Click Cancel if you have changed your mind.' +AvatarChoiceDeleteWrongConfirm = "You didn\'t type the right thing. To delete %(name)s, type your toon's name and click OK. Do not type the quotation marks. Click Cancel if you have changed your mind." AvatarChooserPickAToon = 'Pick A Toon To Play' AvatarChooserQuit = lQuit DateOfBirthEntryMonths = ['Jan', @@ -3294,7 +3293,6 @@ PhotoPageDirectory = 'Open Folder' PhotoPageTutorial = 'You haven\'t taken any snapshots yet! Press TAB to change your camera angle, and press F9 to take a snapshot.\n\n Once you\'ve made a snapshot, come here to manage and name them.' BuildingPageTitle = 'Buildings\n(Coming Soon)' InventoryPageTitle = 'Gags' -InventoryPageDeleteTitle = 'DELETE GAGS' InventoryPageTrackFull = 'You have all the gags in the %s track.' InventoryPagePluralPoints = 'You will get a new\n%(trackName)s gag when you\nget %(numPoints)s more %(trackName)s points.' InventoryPageSinglePoint = 'You will get a new\n%(trackName)s gag when you\nget %(numPoints)s more %(trackName)s point.' @@ -3978,13 +3976,16 @@ EmoteHappy = 'Happy' EmoteSad = 'Sad' EmoteAnnoyed = 'Annoyed' EmoteSleep = 'Sleepy' -TIPPageTitle = 'TIP' +StatPageTitle = 'Statistics' SuitBaseNameWithLevel = '%(name)s\n%(dept)s\nLevel %(level)s' HealthForceAcknowledgeMessage = 'You cannot leave the playground until your Laff meter is smiling!' InventoryTotalGags = 'Total gags\n%d / %d' -InventroyPinkSlips = '%s Pink Slips' -InventroyPinkSlip = '1 Pink Slip' +InventoryPinkSlips = '%s Pink Slips' +InventoryPinkSlip = '1 Pink Slip' +InventoryCrateKeys = '%s Crate Keys' +InventoryCrateKey = '1 Crate Key' InventoryDelete = 'DELETE' +InventoryDeleteAll = 'DELETE ALL' InventoryDone = 'DONE' InventoryDeleteHelp = 'Click on a gag to DELETE it.' InventorySkillCredit = 'Skill credit: %s' @@ -4278,6 +4279,8 @@ GardenTutorialPage2 = 'Flowers are finicky and require unique Jellybean recipes. GardenTutorialPage3 = 'Use a gag from your inventory to plant a tree. After a few days, that gag will do more damage! Remember to keep it healthy or the damage boost will go away.' GardenTutorialPage4 = 'Walk up to these spots to plant, water, dig up or harvest your garden.' GardenTutorialPage5 = "Statues can be purchased in Clarabelle's Cattlelog. Increase your skill to unlock the more extravagant statues!" +EstatePlaneReturn = "Cog invasion!!!" +EstatePlaneHoliday = "Happy halloween!!!" PlaygroundDeathAckMessage = TheCogs + ' took all your gags!\n\nYou are sad. You may not leave the playground until you are happy.' ForcedLeaveFactoryAckMsg = 'The ' + Foreman + ' was defeated before you could reach him. You did not recover any Cog parts.' ForcedLeaveMintAckMsg = 'The Mint Floor Supervisor was defeated before you could reach him. You did not recover any Cogbucks.' @@ -4310,8 +4313,8 @@ TugOfWarGameReady = 'Ready...' TugOfWarGameEnd = 'Good game!' TugOfWarGameTie = 'You tied!' TugOfWarPowerMeter = 'Power meter' -PatternGameTitle = 'Match Blinky' -PatternGameInstructions = 'Little Blinky will show you a dance sequence. ' + "Try to repeat Little Blinky's dance just the way you see it using the arrow keys!" +PatternGameTitle = 'Match Jaymo' +PatternGameInstructions = 'Jaymo will show you a dance sequence. ' + "Try to repeat Jaymo's dance just the way you see it using the arrow keys!" PatternGameWatch = 'Watch these dance steps...' PatternGameGo = 'GO!' PatternGameRight = 'Good, %s!' @@ -4596,15 +4599,15 @@ SuitInvasionEnd = [ ] SuitInvasionUpdate = [ 'Keep it up, Toons!!!', - 'The Cogs appear to be decreasing in numbers!!!' + "The Cogs are beginning to explode in laughter!!!" ] SuitInvasionBulletin = [ 'There is a Cog invasion in progress!!!', '%(plural)s have taken over Toontown!!!' ] SkelecogInvasionBegin = [ - "Hmm... We're getting a strange reading over here...", - 'The Cog factories are running out of parts to build new Cogs!', + "This just in, Sellbot HQ's factory is going bonkers!", + "Sellbot HQ's factory is pushing out incomplete cogs!", '%(singular)s Skelecogs have taken over Toontown!!!' ] SkelecogInvasionEnd = [ @@ -4613,35 +4616,35 @@ SkelecogInvasionEnd = [ ] SkelecogInvasionBulletin = [ 'There is a Cog invasion in progress!!!', - 'The Cog factories are running out of parts to build new Cogs!', + "Sellbot HQ's factory has pushed out incomplete Cogs!", '%(singular)s Skelecogs have taken over Toontown!!!' ] WaiterInvasionBegin = [ - 'It appears that the C.E.O. has fired all his waiters...', - 'The unemployed %(singular)s waiters are invading Toontown!!!' + 'Uh oh, it appears that the Cogs banquet has been rescheduled!', + 'The Waiter %(singular)s are invading Toontown!!!' ] WaiterInvasionEnd = [ - 'The unemployed %(singular)s waiters have been defeated!!!', + 'The Waiter %(singular)s waiters have been defeated!!!', 'The Toons have saved the day once again!!!' ] WaiterInvasionBulletin = [ 'There is a Cog invasion in progress!!!', - 'The C.E.O. has fired all of his waiters!!!', - 'The unemployed %(singular)s waiters are invading Toontown!!!' + 'The Cogs banquet has been rescheduled!!!', + 'The Waiter %(singular)s are invading Toontown!!!' ] V2InvasionBegin = [ - "Yikes!!! This isn't good, Toons!", - 'A major firmware update has been released to the Cogs!!!', - 'Version 2.0 %(plural)s have taken over Toontown!!!' + "Oh my, stock up on gags toons!", + 'The Toon HQ has spotted a Version 2.0 Cog Invasion!', + 'The V2 %(plural)s have taken over Toontown!!!' ] V2InvasionEnd = [ - 'The Version 2.0 %(singular)s invasion has ended!!!', + 'The V2 %(singular)s invasion has ended!!!', 'The Toons have saved the day once again!!!' ] V2InvasionBulletin = [ - 'There is a Cog invasion in progress!!!', - 'A major firmware update has been released to the Cogs!!!', - 'Version 2.0 %(plural)s have taken over Toontown!!!' + "There is a Cog invasion in progress!!!", + 'The Toon HQ has spotted a storm of Version 2.0 Cogs!', + 'The V2 %(plural)s have taken over Toontown!!!' ] LeaderboardTitle = 'Toon Platoon' QuestScript101_0 = 'Come here! Use the arrow keys to move.' @@ -5035,7 +5038,6 @@ MessageConfirmRent = 'Begin rental? Cancel to save the rental for later' MessageConfirmGarden = 'Are you sure you want to start a garden?' FurnitureYourOldCloset = 'your old wardrobe' FurnitureYourOldBank = 'your old bank' -FurnitureYourOldTrunk = 'your old trunk' TrunkHatGUI = 'Hats' TrunkGlassesGUI = 'Glasses' TrunkBackpackGUI = 'Backpacks' @@ -5186,7 +5188,8 @@ FurnitureNames = {100: 'Armchair', 10000: 'Short Pumpkin', 10010: 'Tall Pumpkin', 10020: 'Winter Tree', - 10030: 'Winter Wreath'} + 10030: 'Winter Wreath', + 10040: 'Cog Nation Crate'} ClothingArticleNames = ('Shirt', 'Shirt', 'Shirt', @@ -5273,7 +5276,7 @@ ClothingTypeNames = {1001: 'Ghost Shirt', 1784: 'Racing Skirt 1', 1801: 'Batty Moon Shirt', 1802: 'Mittens Shirt', - 1821: '420 BlazeIt Shirt'} + 1821: 'Plaid Punk Shirt'} AccessoryArticleNames = ('Hat', 'Glasses', 'Backpack', @@ -5427,8 +5430,6 @@ DistributedMailboxEmpty = 'Your mailbox is empty right now. Come back here to l DistributedMailboxWaiting = 'Your mailbox is empty right now, but the package you ordered is on its way. Check back later!' DistributedMailboxReady = 'Your order has arrived!' DistributedMailboxNotOwner = 'Sorry, this is not your mailbox.' -DistributedPhoneEmpty = "You can use any phone to order special items for you and your house. New items will become available to order over time.\n\nYou don't have any items available to order right now, but check back later!" -DistributedPhoneNoHouse = 'You must have a house to use the catalog!' Clarabelle = 'Clarabelle' MailboxExitButton = 'Close Mailbox' MailboxAcceptButton = 'Take this item' @@ -5462,20 +5463,21 @@ CatalogGoodbyeList = ['Bye now!', 'Bye!'] CatalogHelpText1 = 'Turn the page to see items for sale.' CatalogSeriesLabel = 'Series %s' +CatalogGiftError = 'Error' CatalogGiftFor = 'Buy Gift for:' CatalogGiftTo = 'To: %s' CatalogGiftToggleOn = 'Stop Gifting' CatalogGiftToggleOff = 'Buy Gifts' +CatalogGiftUpdating = 'Updating...' +CatalogGiftChoose = 'Choose a friend!' CatalogPurchaseItemAvailable = 'Congratulations on your new purchase! You can start using it right away.' CatalogPurchaseGiftItemAvailable = 'Excellent! %s can start using your gift right away.' CatalogPurchaseItemOnOrder = 'Congratulations! Your purchase will be delivered to your mailbox soon.' CatalogPurchaseGiftItemOnOrder = 'Excellent! Your gift to %s will be delivered to their mailbox.' CatalogAnythingElse = 'Anything else I can get you today?' CatalogPurchaseClosetFull = 'Your closet is full. You may purchase this item anyway, but if you do you will need to delete something from your closet to make room for it when it arrives.\n\nDo you still want to purchase this item?' -CatalogPurchaseNoTrunk = 'In order to wear this item, you need to buy a trunk.\n\nDo you still want to purchase this item?' CatalogPurchaseTrunkFull = 'Your trunk is full. If you purchase this item, you\xe2\x80\x99ll need to delete another item from your trunk to make more room.\n\nDo you still want to purchase this item?' CatalogAcceptClosetFull = 'Your closet is full. You must go inside and delete something from your closet to make room for this item before you can take it out of your mailbox.' -CatalogAcceptNoTrunk = "You don't have a trunk. You must buy a trunk before you can take this item out of your mailbox." CatalogAcceptTrunkFull = 'Your trunk is full. You must delete something from your trunk before you can take this item out of your mailbox.' CatalogAcceptShirt = 'You are now wearing your new hat. The hat you were wearing before has been moved to your trunk.' CatalogAcceptShorts = 'You are now wearing your new shorts. What you were wearing before has been moved to your closet.' @@ -5508,8 +5510,9 @@ CatalogPurchaseGeneralError = 'The item could not be purchased because of some i CatalogPurchaseGiftGeneralError = 'The item could not be gifted to %(friend)s because of some internal game error: error code %(error)s.' CatalogPurchaseGiftNotAGift = 'This item could not be sent to %s because it would be an unfair advantage.' CatalogPurchaseGiftWillNotFit = "This item could not be sent to %s because it doesn't fit them." -CatalogPurchaseGiftLimitReached = "This item could not be sent to %s because they've already have it." +CatalogPurchaseGiftLimitReached = "This item could not be sent to %s because they already have it." CatalogPurchaseGiftNotEnoughMoney = "This item could not be sent to %s because you can't afford it." +CatalogPurchaseGiftTooFast = "This item could not be sent to %s because you are sending gifts too fast." CatalogAcceptGeneralError = 'The item could not be removed from your mailbox because of some internal game error: error code %s.' CatalogAcceptRoomError = "You don't have any place to put this. You'll have to get rid of something." CatalogAcceptLimitError = "You already have as many of these as you can handle. You'll have to get rid of something." @@ -5564,7 +5567,6 @@ CatalogRentText = 'Rent' CatalogGiftText = 'Gift' CatalogOnOrderText = 'On Order' CatalogPurchasedText = 'Already\nPurchased' -CatalogCurrent = 'Current' CatalogGiftedText = 'Gifted\nTo You' CatalogPurchasedGiftText = 'Already\nOwned' CatalogMailboxFull = 'No Room' @@ -5584,11 +5586,9 @@ CatalogVerifyRent = 'Rent %(item)s for %(price)s Jellybeans?' CatalogVerifyGift = 'Purchase %(item)s for %(price)s Jellybeans as a gift for %(friend)s?' CatalogOnlyOnePurchase = 'You may only have one of these items at a time. If you purchase this one, it will replace %(old)s.\n\nAre you sure you want to purchase %(item)s for %(price)s Jellybeans?' CatalogExitButtonText = 'Hang Up' -CatalogCurrentButtonText = 'To Current Items' CatalogPastButtonText = 'To Past Items' TutorialHQOfficerName = 'HQ Harry' NPCToonNames = {20000: 'Tutorial Tom', - 998: 'Talkative Tyler', 999: 'Toon Tailor', 1000: lToonHQ, 20001: Flippy, @@ -5604,7 +5604,6 @@ NPCToonNames = {20000: 'Tutorial Tom', 2009: lHQOfficerF, 2010: lHQOfficerF, 2012: 'Fisherman Freddy', - 2018: 'Duff..err..TIP Man', 2013: 'Clerk Poppy', 2014: 'Clerk Peppy', 2015: 'Clerk Pappy', @@ -6221,18 +6220,27 @@ NPCToonNames = {20000: 'Tutorial Tom', 9235: lHQOfficerM, 9236: lHQOfficerM, 9237: 'Fisherman Jung', - 9301: 'Phil Bettur', - 9302: 'Emma Phatic', - 9303: 'GiggleMesh', - 9304: 'Anne Ville', - 9305: 'Bud Erfingerz', - 9306: 'J.S. Bark', - 9307: 'Bea Sharpe', - 9308: 'Otto Toon', - 9309: 'Al Capella', - 9310: 'Des Traction', - 9311: 'Dee Version', - 9312: 'Bo Nanapeel', + 9301: 'Fisherman John', + 9302: 'Blithesome Barbra', + 9303: 'Hasty John', + 9304: 'Angry Dan', + 9305: lHQOfficerM, + 9306: lHQOfficerM, + 9307: lHQOfficerF, + 9308: lHQOfficerF, + 9309: 'Ori-O', + 9310: 'Mr. Batty', + 9311: 'Doctor Flippenbrains', + 9312: 'Barden Betty', + 9313: 'Frekly Fred', + 9314: 'Robby', + 9315: 'Baker Penelope', + 9316: 'Angie Lerr', + 9317: 'Nocturnal Nattie', + 9318: 'Los Carlos', + 9319: 'Psyche', + 9320: 'Toony Bob', + 9321: 'Sir Biscuit', 7001: 'N. Prisoned', 7002: 'R.E. Leaseme', 7003: 'Lemmy Owte', @@ -6242,8 +6250,20 @@ NPCToonNames = {20000: 'Tutorial Tom', 7007: 'Dewin Tymme', 7008: 'Ima Cagedtoon', 7009: 'Jimmy Thelock', - 7010: 'Little Blinky', + 7010: 'Jaymo', 7011: 'Donald', + 7012: 'Phil Bettur', + 7013: 'Emma Phatic', + 7014: 'GiggleMesh', + 7015: 'Anne Ville', + 7016: 'Bud Erfingerz', + 7017: 'J.S. Bark', + 7018: 'Bea Sharpe', + 7019: 'Otto Toon', + 7020: 'Al Capella', + 7021: 'Des Traction', + 7022: 'Dee Version', + 7023: 'Bo Nanapeel', 10001: 'Healer Sara', 11001: 'Healer Gabriel', 12001: 'Healer Bill', @@ -6783,7 +6803,25 @@ zone2TitleDict = {2513: ('Toon Hall', ''), 3827: ('Choral Wreaths', ''), 3828: ("Snowman's Land", ''), 3829: ('Pinecone Zone', ''), - 3830: ('Wait and See Goggle Defogging', '')} + 3830: ('Wait and See Goggle Defogging', ''), + 9802: ("Barbra's Bohemian Art Supplies", ''), + 9804: ("Angry Dan's Garden Sprinklers", ''), + 9808: ("Ori-O's Creamery and Dairy", ''), + 9809: ('Rave of the Forks', ''), + 9812: ('Louds Silent-Shop', ''), + 9813: ('Bedpost Bakery', ''), + 9814: ("Amazing Angler's Silly Shop", ''), + 9815: ("Nattie's Catties", ''), + 9816: ('Carlos Carpentry BunkBeds Inc.', ''), + 9817: ('The Psyche-Ologist', ''), + 9819: ("Toony Bob's Fluffy Pillows", ''), + 9820: ("Batty's Bat Supply", ''), + 9824: ("Joe's Burnt Biscuits", ''), + 9826: ("Juste-A-Cote Taxi Service", ''), + 9827: ("Frekly Fred's Storage Shack", ''), + 9828: ("Barden Betty's Clingy Clothing", ''), + 9829: (lToonHQ, ''), +} ClosetTimeoutMessage = 'Sorry, you ran out\n of time.' ClosetNotOwnerMessage = "This isn't your closet, but you may try on the clothes." ClosetPopupOK = lOK @@ -6996,10 +7034,10 @@ TipDict = {TIP_NONE: ('',), 'If you wait too long to attack a lured Cog, it will wake up. Higher level lures last longer.', 'There are fishing ponds on every street in Toontown. Some streets have unique fish.'), TIP_MINIGAME: ('After you fill up your Jellybean jar, any Jellybeans you get from Trolley Games automatically spill over into your bank.', - 'You can use the arrow keys instead of the mouse in the "Match Blinky" Trolley Game.', + 'You can use the arrow keys instead of the mouse in the "Match Jaymo" Trolley Game.', 'In the Cannon Game you can use the arrow keys to move your cannon and press the "Control" key to fire.', 'In the Ring Game, bonus points are awarded when the entire group successfully swims through its rings.', - 'A perfect game of Match Blinky will double your points.', + 'A perfect game of Match Jaymo will double your points.', 'In the Tug-of-War you are awarded more Jellybeans if you play against a tougher Cog.', 'Trolley Game difficulty varies by neighborhood; ' + lToontownCentral + ' has the easiest and ' + lDonaldsDreamland + ' has the hardest.', 'Certain Trolley Games can only be played in a group.'), @@ -7989,9 +8027,6 @@ SpookyPropsHolidayStart = 'Silly Meter spins Toontown into spooky mode!' BlackCatHolidayStart = 'Create a Black Cat - today only!' BlackCatHolidayEnd = 'Black Cat day has ended!' SpookyBlackCatHolidayStart = 'Friday 13th means a Black Cat blast!' -LaughingManHolidayStart = 'Today is the day of the Laughing Man!' -LaughingManHolidayOngoing = 'Welcome! The day of the Laughing Man is currently in progress.' -LaughingManHolidayEnd = 'The day of the Laughing Man has ended. Hope you had fun!' TopToonsMarathonStart = "The Top Toons New Year's Day Marathon has begun!" TopToonsMarathonEnd = "The Top Toons New Year's Day Marathon has ended." WinterDecorationsStart = "It's Winter Holiday time in Toontown!" @@ -8041,9 +8076,6 @@ QuitBoardingPartyLeader = 'Disband' QuitBoardingPartyNonLeader = 'Leave' QuitBoardingPartyConfirm = 'Are you sure you want to quit this Boarding Group?' BoardcodeMissing = 'Something went wrong; try again later.' -BoardcodeMinLaffLeader = 'Your group cannot board because you have less than %s laff points.' -BoardcodeMinLaffNonLeaderSingular = 'Your group cannot board because %s has less than %s laff points.' -BoardcodeMinLaffNonLeaderPlural = 'Your group cannot board because %s have less than %s laff points.' BoardcodePromotionLeader = 'Your group cannot board because you do not have enough promotion merits.' BoardcodePromotionNonLeaderSingular = 'Your group cannot board because %s does not have enough promotion merits.' BoardcodePromotionNonLeaderPlural = 'Your group cannot board because %s do not have enough promotion merits.' @@ -8051,8 +8083,6 @@ BoardcodeSpace = 'Your group cannot board because there is not enough space.' BoardcodeBattleLeader = 'Your group cannot board because you are in battle.' BoardcodeBattleNonLeaderSingular = 'Your group cannot board because %s is in battle.' BoardcodeBattleNonLeaderPlural = 'Your group cannot board because %s are in battle.' -BoardingInviteMinLaffInviter = 'You need %s Laff Points before being a member of this Boarding Group.' -BoardingInviteMinLaffInvitee = '%s needs %s Laff Points before being a member of this Boarding Group.' BoardingInvitePromotionInviter = 'You need to earn a promotion before being a member of this Boarding Group.' BoardingInvitePromotionInvitee = '%s needs to earn a promotion before being a member of this Boarding Group.' BoardingInviteeInDiffGroup = '%s is already in a different Boarding Group.' @@ -8060,7 +8090,7 @@ BoardingInviteeInKickOutList = '%s had been removed by your leader. Only the lea BoardingInviteePendingIvite = '%s has a pending invite; try again later.' BoardingInviteeInElevator = '%s is currently busy; try again later.' BoardingInviteGroupFull = 'Your Boarding Group is already full.' -BoardingGroupsToLarge = '%s is already in a different Boarding Group that is too large to merge.' +BoardingGroupsTooLarge = '%s is already in a different Boarding Group that is too large to merge.' BoardingAlreadyInGroup = 'You cannot accept this invitation because you are part of another Boarding Group.' BoardingGroupAlreadyFull = 'You cannot accept this invitation because the group is already full.' BoardingKickOutConfirm = 'Are you sure you want to remove %s?' @@ -8114,13 +8144,14 @@ BossbotRTCongratulations = "You did it! You've demoted the C.E.O.!\x07Here, tak BossbotRTHPBoost = "\x07You've done a lot of work for the Resistance.\x07The Toon Council has decided to give you another Laff point. Congratulations!" BossbotRTMaxed = '\x07I see that you have a level %s Cog Suit. Very impressive!\x07On behalf of the Toon Council, thank you for coming back to defend more Toons!' BossbotRTLastPromotion = "\x07Wow, you've reached level %s on your Cog Suit!\x07Cogs don't get promoted higher than that.\x07You can't upgrade your Cog Suit anymore, but you can certainly keep working for the Resistance!" +BossRTKeyReward = '\x07By the way, thanks to your exquisite performance, the Toon Council has decided to offer to you a Cog Nation Crate key!\x07Using this, you will be able to open the crates you have earned in the cog factories.' GolfAreaAttackTaunt = 'Fore!' OvertimeAttackTaunts = ["It's time to reorganize.", "Now let's downsize."] ElevatorBossBotBoss = 'Bossbot Clubhouse' ElevatorBossBotCourse0 = 'The Front Three' ElevatorBossBotCourse1 = 'The Middle Six' ElevatorBossBotCourse2 = 'The Back Nine' -ElevatorCashBotBoss = 'Cashbot Treasury Vault' +ElevatorCashBotBoss = 'Cashbot Vault' ElevatorCashBotMint0 = 'Coin Mint' ElevatorCashBotMint1 = 'Dollar Mint' ElevatorCashBotMint2 = 'Bullion Mint' @@ -8470,11 +8501,13 @@ DonaldChatter = ["I'm glad you're here today!", 'I love to play tag. Do you?'] NPCFriendUnavailable = 'Unavailable' FireTalkMessage = "You're fired!" -RestockFullLaffMessage = "You're already happy!" -RestockNoMoneyMessage = "You need more jellybeans to restock your laff!" -RestockLaffMessage = "Have fun!" + RestockAskMessage = "Would you like to\nrestock %s laff for %s jellybeans?" -RestockCheaterMessage = "No cheaters allowed! Your transaction has been declined." +RestockNoMoneyGuiMessage = "\n\x01WLRed\x01Not enough jellybeans\x02" +RestockFullLaffMessage = "You're already happy!" +RestockLessLaffMessage = "Why would you want to be less happy than you are right now?" +RestockNoMoneyMessage = "You don't have enough jellybeans for that!" +RestockSuccessfulMessage = "You're welcome! Have fun!" InVP = ' in a V.P. Battle' InFieldOffice = ' in a Sellbot Field Office' CogPanelLevel = 'Level %s' @@ -8482,11 +8515,6 @@ CogPanelSkeleton = 'Skeleton' CogPanelVirtual = 'Virtual' CogPanelRevives = 'v%s.0' CogPanelWaiter = 'Waiter' -TrueFriendsRemoveNotice = 'Are you sure you want to remove %s as your True Friend?\n\nYou will no longer be able to chat without limits.' -TrueFriendsNotFriends = 'You cannot be True Friends with %s until you are regular friends first.' -TrueFriendsAddNotice = 'If you are playing Toontown with someone you trust, you can become True Friends.\n\nYou can chat using the keyboard with your True Friends.\n\nOther Toons won\'t understand what you\'re saying.\n\n\x01WLRed\x01However, this chat is completely unfiltered.\x02\n\nAre you sure you want to be True Friends with %s?' -TrueFriendsAdded = 'You are now True Friends with %s!\n\nYou can now understand everything %s says.\n\nHowever, chances are %s hasn\'t added you as a True Friend yet.\n\nIf this is the case, he cannot understand you yet. Please ask %s to add you as a True Friend aswell!' -TrueFriendsRemoved = 'You are no longer True Friends with %s.' def convertSecondsToDate(seconds): m, s = divmod(seconds, 60) @@ -8504,7 +8532,11 @@ SpeedchatPlusLabelOn = 'Speedchat Plus is on.' SpeedchatPlusLabelOff = 'Speedchat Plus is off.' TrueFriendsLabelOn = 'True Friends is on.' TrueFriendsLabelOff = 'True Friends is off.' +TpTransitionLabelOn = 'The teleport transition is on.' +TpTransitionLabelOff = 'The teleport transition is off.' FieldOfViewLabel = 'Field of View:' +NametagStyleLabel = 'Nametag Style:' +FishingPoleLabel = 'Fishing Rod:' BossLocations = { 'c': 'Bossbot Clubhouse\nBanquet', 'l': "Lawbot Courthouse\nBumpy Bumblebehr's Trial", @@ -8583,6 +8615,12 @@ JumpBossTaunts = { ], 'l': [ "You're all in contempt of court!" + ], + 'm': [ + "These Goons weren't free you know!", + 'HEY, THOSE ARE VINTAGE SAFES!', + 'This will cost you a lot more than candy!', + "I'll buy out Toontown if it means getting rid of you Toons!" ] } CEOSpeech = [ @@ -8599,4 +8637,1348 @@ CEOSpeech = [ 'And thus we, the Cog Nation, are striving.', 'I am very delighted by this news, I just wanted to thank you all for working so hard for this news.', "Wait, what's going on? I can't see but I hear explosions." -] # Len of words + 10 \ No newline at end of file +] # Len of words + 10 + +CrateRewardMessage1 = 'Nice! You have earned a crate! It will arrive in your mailbox shortly.' +CrateRewardMessage2 = 'You can open it with keys from boss battles.' +CrateRewardMessages = [CrateRewardMessage1, CrateRewardMessage2] +CrateNotOwner = 'Sorry, this is not your crate.' +CrateNoKeys = 'Sorry, but you have no keys. You can find some in the cog facilities.' +CrateAskToUse = 'Would you like to use a key to open this crate?' +CrateBeanPrize = "Congratulations! You found %s jellybeans. They've been automatically added to your jellybean bank!" +CrateBuffPrize = 'Congratulations! %s' +CrateNametagPrize = "Congratulations! You've received a nametag. Check your mailbox to find out which one!" +CrateEmotePrize = "Congratulations! You've unlocked a new emote. Check your mailbox to pick it up!" +CrateClothingPrize = "Congratulations! You've received a new clothing item. Check your mailbox to check it out!" +CrateAccessoryPrize = 'Congratulations! You found a new accessory for your Toon. Check your mailbox and rock it!' + +Stats = [ + 'Cogs defeated: %(cog)s', + 'V2.0 cogs defeated: %(v2)s', + 'Skelecogs defeated: %(skele)s', + 'Jellybeans spent: %(beanSpent)s', + 'Jellybeans earnt: %(beanEarnt)s', + 'Tasks completed: %(task)s', + 'Total VP defeats: %(vp)s', + 'Total CFO defeats: %(cfo)s', + 'Total CJ defeats: %(cj)s', + 'Total CEO defeats: %(ceo)s', + 'Gone sad: %(sad)s times', + 'Buildings liberated: %(bldg)s', + 'Field Offices defeated: %(cogdo)s', + 'Items purchased: %(item)s', + 'Fish caught: %(fish)s', + 'Flowers picked: %(flower)s', + 'Races completed: %(race)s', + 'Golf holes played: %(golf)s', + 'Total SOS cards: %(sos)s', + 'Total unites: %(unite)s', + 'Total pink slips: %(slip)s', + 'Total gags used: %(gag)s' +] +StatResetAsk = 'Are you sure you want to reset your stats? This is an irreversible action!' +StatResetDone = 'Your stats have been reset.' + +ChairAskToUse = 'Would you like to sit on this chair?' + +FriendSecretIntro = "If you are playing Toontown Stride with someone you know in the real world, you can become True Friends. You can chat using the keyboard with your True Friends. Other Toons won't understand what you're saying.\n\nYou do this by getting a True Friend Code. Tell the True Friend Code to your friend, but not to anyone else. When your friend types in your True Friend Code on his or her screen, you'll be True Friends in Toontown!" +FriendSecretGetSecret = 'Get a True Friend Code' +FriendSecretEnterSecret = 'If you have a True Friend Code from someone you know, type it here.' +FriendSecretOK = lOK +FriendSecretEnter = 'Enter True Friend Code' +FriendSecretCancel = lCancel +FriendSecretGettingSecret = 'Getting True Friend Code. . .' +FriendSecretGotSecret = "Here is your new True Friend Code. Be sure to write it down!\n\nYou may give this True Friend Code to one person only. Once someone types in your True Friend Code, it will not work for anyone else. If you want to give a True Friend Code to more than one person, get another True Friend Code.\n\nThe True Friend Code will only work for the next three days. Your friend will have to type it in before it goes away, or it won't work.\n\nYour True Friend Code is:" +FriendSecretTooMany = "Sorry, you can't have any more True Friend Codes today. You've already had more than your fair share!\n\nTry again tomorrow." +FriendSecretTryingSecret = 'Trying True Friend Code. . .' +FriendSecretEnteredSecretUnknown = "That's not anyone's True Friend Code. Are you sure you spelled it correctly?\n\nIf you did type it correctly, it may have expired. Ask your friend to get a new True Friend Code for you (or get a new one yourself and give it to your friend)." +FriendSecretEnteredSecretFullYou = "You can't be True Friends because you have too many friends on your friends list." +FriendSecretEnteredSecretFullHim = "You can't be True Friends because %s has too many friends on his friends list." +FriendSecretAlreadyFriends = 'You are already True Friends!' +FriendSecretAlreadyFriendsName = 'You are already True Friends with %s!' +FriendSecretEnteredSecretSelf = 'You just typed in your own True Friend Code!' +FriendSecretTooFast = 'You are redeeming codes too fast! Please wait a few seconds.' +FriendSecretNowFriends = 'You are now True Friends with %s!' + +GroupAskNoAccess = 'Sorry, but you have no teleport access %s %s.\n\nWould you still like to teleport to %s?' +GroupAskNoAccessSame = 'Sorry, but you have no teleport access %s %s.' +GroupAskAccess = 'Would you like to teleport %s %s in %s?' + +TVNotOwner = 'Sorry, but this is not your TV.' +TVInvalidVideo = "Sorry, but we can't play that video. Make sure it is a MP4 video." +TVUnknownVideo = "Oops! Looks like the owner has picked a video to play which isn't currently on your computer!" +TVUnknownVideoPack = 'Oops! Looks like the owner has picked a video to play, but you need to download the %s TV Pack in the launcher.' +TVChooseVideo = 'Choose a video to play!' +TVOK = 'The video you selected is now playing!' +TVPacks = ['QuackityHQ'] + +GagPopup = '%s: %s\nGags: %s' + +ColorfulToon = 'Vibrant' +ColorAdvanced = 'Advanced' +ColorBasic = 'Basic' +ColorAll = 'All' + +Blacklist = [ + "$1ut", + "$h1t", + "$hit", + "$lut", + "'ho", + "'hobag", + "a$$", + "anal", + "anus", + "ass", + "assmunch", + "b1tch", + "ballsack", + "bastard", + "beaner", + "beastiality", + "biatch", + "beeyotch", + "bitch", + "bitchy", + "blow job", + "blow me", + "blowjob", + "bollock", + "bollocks", + "bollok", + "boner", + "boob", + "bugger", + "buttplug", + "c-0-c-k", + "c-o-c-k", + "c-u-n-t", + "c.0.c.k", + "c.o.c.k.", + "c.u.n.t", + "jerk", + "jackoff", + "jackhole", + "j3rk0ff", + "homo", + "hom0", + "hobag", + "hell", + "h0mo", + "h0m0", + "goddamn", + "goddammit", + "godamnit", + "god damn", + "ghey", + "ghay", + "gfy", + "gay", + "fudgepacker", + "fudge packer", + "fuckwad", + "fucktard", + "fuckoff", + "fucker", + "fuck-tard", + "fuck off", + "fuck", + "fellatio", + "fellate", + "felching", + "felcher", + "felch", + "fartknocker", + "fart", + "fannybandit", + "fanny bandit", + "faggot", + "fagg", + "fag", + "f.u.c.k", + "f-u-c-k", + "f u c k", + "dyke", + "douchebag", + "douche", + "douch3", + "doosh", + "dildo", + "dike", + "dick", + "damnit", + "damn", + "dammit", + "d1ldo", + "d1ld0", + "d1ck", + "d0uche", + "d0uch3", + "cunt", + "cumstain", + "cum", + "crap", + "coon", + "cock", + "clitoris", + "clit", + "cl1t", + "cawk", + "c0ck", + "jerk0ff", + "jerkoff", + "jizz", + "knob end", + "knobend", + "labia", + "lmfao", + "lul", + "moolie", + "muff", + "nigga", + "nigger", + "p.u.s.s.y.", + "penis", + "piss", + "piss-off", + "pissoff", + "prick", + "pube", + "pussy", + "queer", + "retard", + "retarded", + "s hit", + "s-h-1-t", + "s-h-i-t", + "s.h.i.t.", + "scrotum", + "sex", + "sh1t", + "shit", + "slut", + "smegma", + "t1t", + "tard", + "terd", + "tit", + "tits", + "titties", + "turd", + "twat", + "vag", + "vagina", + "wank", + "wetback", + "whore", + "whoreface", + "F*ck", + "sh*t", + "pu$$y", + "p*ssy", + "diligaf", + "wtf", + "stfu", + "fu*ck", + "fack", + "shite", + "fxck", + "sh!t", + "@sshole", + "assh0le", + "assho!e", + "a$$hole", + "a$$h0le", + "a$$h0!e", + "a$$h01e", + "assho1e", + "wh0re", + "f@g", + "f@gg0t", + "f@ggot", + "motherf*cker", + "mofo", + "cuntlicker", + "cuntface", + "dickbag", + "douche waffle", + "jizz bag", + "cockknocker", + "beatch", + "fucknut", + "nucking futs", + "mams", + "carpet muncher", + "ass munch", + "ass hat", + "cunny", + "quim", + "clitty", + "fuck wad", + "kike", + "spic", + "wop", + "chink", + "wet back", + "mother humper", + "feltch", + "feltcher", + "FvCk", + "ahole", + "nads", + "spick", + "douchey", + "Bullturds", + "gonads", + "bitch", + "butt", + "fellatio", + "lmao", + "s-o-b", + "spunk", + "he11", + "jizm", + "jism", + "bukkake", + "shiz", + "wigger", + "gook", + "ritard", + "reetard", + "masterbate", + "masturbate", + "goatse", + "masterbating", + "masturbating", + "hitler", + "nazi", + "tubgirl", + "GTFO", + "FOAD", + "r-tard", + "rtard", + "hoor", + "g-spot", + "gspot", + "vulva", + "assmaster", + "viagra", + "Phuck", + "frack", + "fuckwit", + "assbang", + "assbanged", + "assbangs", + "asshole", + "assholes", + "asswipe", + "asswipes", + "b1tch", + "bastards", + "bitched", + "bitches", + "blow jobs", + "boners", + "bullshit", + "bullshits", + "bullshitted", + "cameltoe", + "camel toe", + "camel toes", + "chinc", + "chincs", + "chink", + "chode", + "chodes", + "clit", + "clits", + "cocks", + "coons", + "cumming", + "cunts", + "d1ck", + "dickhead", + "dickheads", + "doggie-style", + "dildos", + "douchebags", + "dumass", + "dumb ass", + "dumbasses", + "dykes", + "f-u-c-k", + "faggit", + "fags", + "fucked", + "fucker", + "fuckface", + "fucks", + "godamnit", + "gooks", + "humped", + "humping", + "jackass", + "jap", + "japs", + "jerk off", + "jizzed", + "kikes", + "knobend", + "kooch", + "kooches", + "kootch", + "mother fucker", + "mother fuckers", + "motherfucking", + "niggah", + "niggas", + "niggers", + "p.u.s.s.y.", + "porch monkey", + "porch monkeys", + "pussies", + "queers", + "rim job", + "rim jobs", + "sand nigger", + "sand niggers", + "s0b", + "shitface", + "shithead", + "shits", + "shitted", + "s.o.b.", + "spik", + "spiks", + "twats", + "whack off", + "whores", + "zoophile", + "m-fucking", + "mthrfucking", + "muthrfucking", + "mutherfucking", + "mutherfucker", + "mtherfucker", + "mthrfucker", + "mthrf*cker", + "whorehopper", + "maternal copulator", + "(!)", + "whoralicious", + "whorealicious", + "( Y )", + "(@ Y @)", + "(. Y .)", + "aeolus", + "Analprobe", + "Areola", + "areole", + "aryan", + "arian", + "asses", + "assfuck", + "azazel", + "baal", + "Babes", + "bang", + "banger", + "Barf", + "bawdy", + "Beardedclam", + "beater", + "Beaver", + "beer", + "bigtits", + "bimbo", + "Blew", + "blow", + "blowjobs", + "blowup", + "bod", + "bodily", + "boink", + "Bone", + "boned", + "bong", + "Boobies", + "Boobs", + "booby", + "booger", + "Bookie", + "Booky", + "bootee", + "bootie", + "Booty", + "Booze", + "boozer", + "boozy", + "bosom", + "bosomy", + "bowel", + "bowels", + "bra", + "Brassiere", + "breast", + "breasts", + "bung", + "babe", + "bush", + "buttfuck", + "cocaine", + "kinky", + "klan", + "panties", + "pedophile", + "pedophilia", + "pedophiliac", + "punkass", + "queaf", + "rape", + "scantily", + "essohbee", + "shithouse", + "smut", + "snatch", + "toots", + "doggie style", + "anorexia", + "bulimia", + "bulimiic", + "burp", + "busty", + "Buttfucker", + "caca", + "cahone", + "Carnal", + "Carpetmuncher", + "cervix", + "climax", + "Cocain", + "Cocksucker", + "Coital", + "coke", + "commie", + "condom", + "corpse", + "Coven", + "Crabs", + "crack", + "Crackwhore", + "crappy", + "cuervo", + "Cummin", + "Cumshot", + "cumshots", + "Cunnilingus", + "dago", + "dagos", + "damned", + "dick-ish", + "dickish", + "Dickweed", + "anorexic", + "prostitute", + "marijuana", + "LSD", + "PCP", + "diddle", + "dawgie-style", + "dimwit", + "dingle", + "doofus", + "dopey", + "douche", + "Drunk", + "Dummy", + "Ejaculate", + "enlargement", + "erect", + "erotic", + "exotic", + "extacy", + "Extasy", + "faerie", + "faery", + "fagged", + "fagot", + "Fairy", + "fisted", + "fisting", + "Fisty", + "floozy", + "fondle", + "foobar", + "foreskin", + "frigg", + "frigga", + "fubar", + "Fucking", + "fuckup", + "ganja", + "gays", + "glans", + "godamn", + "goddam", + "Goldenshower", + "gonad", + "gonads", + "Handjob", + "hebe", + "hemp", + "heroin", + "herpes", + "hijack", + "Hiv", + "Homey", + "Honky", + "hooch", + "hookah", + "Hooker", + "Hootch", + "hooter", + "hooters", + "hump", + "hussy", + "hymen", + "inbred", + "incest", + "injun", + "jerked", + "Jiz", + "Jizm", + "horny", + "junkie", + "junky", + "kill", + "kkk", + "kraut", + "kyke", + "lech", + "leper", + "lesbians", + "lesbos", + "Lez", + "Lezbian", + "lezbians", + "Lezbo", + "Lezbos", + "Lezzie", + "Lezzies", + "Lezzy", + "loin", + "loins", + "lube", + "Lust", + "lusty", + "Massa", + "Masterbation", + "Masturbation", + "maxi", + "Menses", + "Menstruate", + "Menstruation", + "meth", + "molest", + "moron", + "Motherfucka", + "Motherfucker", + "murder", + "Muthafucker", + "nad", + "naked", + "napalm", + "Nappy", + "nazism", + "negro", + "niggle", + "nimrod", + "ninny", + "Nipple", + "nooky", + "Nympho", + "Opiate", + "opium", + "oral", + "orally", + "organ", + "orgasm", + "orgies", + "orgy", + "ovary", + "ovum", + "ovums", + "Paddy", + "pantie", + "panty", + "Pastie", + "pasty", + "Pecker", + "pedo", + "pee", + "Peepee", + "Penetrate", + "Penetration", + "penial", + "penile", + "perversion", + "peyote", + "phalli", + "Phallic", + "Pillowbiter", + "pimp", + "pinko", + "pissed", + "pms", + "polack", + "porn", + "porno", + "pornography", + "pot", + "potty", + "prig", + "prude", + "pubic", + "pubis", + "punky", + "puss", + "Queef", + "quicky", + "Racist", + "racy", + "raped", + "Raper", + "rapist", + "raunch", + "rectal", + "rectum", + "rectus", + "reefer", + "reich", + "revue", + "risque", + "rum", + "rump", + "sadism", + "sadist", + "satan", + "scag", + "schizo", + "screw", + "Screwed", + "scrog", + "Scrot", + "Scrote", + "scrud", + "scum", + "seaman", + "seamen", + "seduce", + "semen", + "sex_story", + "sexual", + "Shithole", + "Shitter", + "shitty", + "s*o*b", + "sissy", + "skag", + "slave", + "sleaze", + "sleazy", + "sluts", + "smutty", + "sniper", + "snuff", + "sodom", + "souse", + "soused", + "sperm", + "spooge", + "Stab", + "steamy", + "Stiffy", + "stoned", + "strip", + "Stroke", + "whacking off", + "suck", + "sucked", + "sucking", + "tampon", + "tawdry", + "teat", + "teste", + "testee", + "testes", + "Testis", + "thrust", + "thug", + "tinkle", + "Titfuck", + "titi", + "titty", + "whacked off", + "toke", + "tramp", + "trashy", + "tush", + "undies", + "unwed", + "urinal", + "urine", + "uterus", + "uzi", + "valium", + "virgin", + "vixen", + "vodka", + "vomit", + "voyeur", + "vulgar", + "wad", + "wazoo", + "wedgie", + "weed", + "weenie", + "weewee", + "weiner", + "weirdo", + "wench", + "whitey", + "whiz", + "Whored", + "Whorehouse", + "Whoring", + "womb", + "woody", + "x-rated", + "xxx", + "B@lls", + "yeasty", + "yobbo", + "sumofabiatch", + "doggy-style", + "doggy style", + "wang", + "dong", + "d0ng", + "w@ng", + "wh0reface", + "wh0ref@ce", + "wh0r3f@ce", + "tittyfuck", + "tittyfucker", + "tittiefucker", + "cockholster", + "cockblock", + "gai", + "gey", + "faig", + "faigt", + "a55", + "a55hole", + "gae", + "corksucker", + "rumprammer", + "slutdumper", + "niggaz", + "muthafuckaz", + "gigolo", + "pussypounder", + "herp", + "herpy", + "transsexual", + "gender dysphoria", + "orgasmic", + "cunilingus", + "anilingus", + "dickdipper", + "dickwhipper", + "dicksipper", + "dickripper", + "dickflipper", + "dickzipper", + "homoey", + "queero", + "freex", + "cunthunter", + "shamedame", + "slutkiss", + "shiteater", + "slut devil", + "fuckass", + "fucka$$", + "clitorus", + "assfucker", + "dillweed", + "cracker", + "teabagging", + "shitt", + "azz", + "fuk", + "fucknugget", + "cuntlick", + "g@y", + "@ss", + "beotch", + "a55", + "anal", + "anus", + "ar5e", + "arrse", + "arse", + "ass", + "ass-fucker", + "asses", + "assfucker", + "assfukka", + "asshole", + "assholes", + "asswhole", + "a_s_s", + "b!tch", + "b00bs", + "b17ch", + "b1tch", + "ballbag", + "balls", + "ballsack", + "bastard", + "batard", + "beastial", + "beastiality", + "bellend", + "bestial", + "bestiality", + "bi\+ch", + "biatch", + "bitch", + "bitcher", + "bitchers", + "bitches", + "bitchin", + "bitching", + "bloody", + "blow job", + "blowjob", + "blowjobs", + "boiolas", + "bollock", + "bollok", + "boner", + "boob", + "boobs", + "booobs", + "boooobs", + "booooobs", + "booooooobs", + "breasts", + "buceta", + "bugger", + "bum", + "bunny fucker", + "butt", + "butthole", + "buttmuch", + "buttplug", + "c0ck", + "c0cksucker", + "carpet muncher", + "cawk", + "chink", + "chieuse", + "chieur", + "cipa", + "cl1t", + "clit", + "clitoris", + "clits", + "cnut", + "cock", + "cock-sucker", + "cock sucker", + "cockface", + "cockhead", + "cockmunch", + "cockmuncher", + "cocks", + "cocksuck", + "cocksucked", + "cocksucker", + "cocksucking", + "cocksucks", + "cocksuka", + "cocksukka", + "cok", + "cokmuncher", + "coksucka", + "coon", + "connard", + "connasse", + "conne", + "cox", + "crap", + "cum", + "cummer", + "cumming", + "cums", + "cumshot", + "cunilingus", + "cunillingus", + "cunnilingus", + "cunt", + "cuntlick", + "cuntlicker", + "cuntlicking", + "cunts", + "cyalis", + "cyberfuc", + "cyberfuck", + "cyberfucked", + "cyberfucker", + "cyberfuckers", + "cyberfucking", + "d1ck", + "damn", + "dick", + "dickhead", + "dildo", + "dildos", + "dink", + "dinks", + "dirsa", + "dlck", + "dog-fucker", + "doggin", + "dogging", + "donkeyribber", + "doosh", + "duche", + "dyke", + "ejaculate", + "ejaculated", + "ejaculates", + "ejaculating", + "ejaculatings", + "ejaculation", + "ejakulate", + "enculer", + "f u c k", + "f u c k e r", + "f4nny", + "fag", + "fagging", + "faggitt", + "faggot", + "faggs", + "fagot", + "fagots", + "fags", + "fanny", + "fannyflaps", + "fannyfucker", + "fanyy", + "fatass", + "fcuk", + "fcuker", + "fcuking", + "feck", + "fecker", + "felching", + "fellate", + "fellatio", + "fingerfuck", + "fingerfucked", + "fingerfucker", + "fingerfuckers", + "fingerfucking", + "fingerfucks", + "fistfuck", + "fistfucked", + "fistfucker", + "fistfuckers", + "fistfucking", + "fistfuckings", + "fistfucks", + "flange", + "fook", + "fooker", + "fuck", + "fucka", + "fucked", + "fucker", + "fuckers", + "fuckhead", + "fuckheads", + "fuckin", + "fucking", + "fuckings", + "fuckingshitmotherfucker", + "fuckme", + "fucks", + "fuckwhit", + "fuckwit", + "fudge packer", + "fudgepacker", + "fuk", + "fuker", + "fukker", + "fukkin", + "fuks", + "fukwhit", + "fukwit", + "fux", + "fux0r", + "f_u_c_k", + "gangbang", + "gangbanged", + "gangbangs", + "gaylord", + "gaysex", + "goatse", + "God", + "god-dam", + "god-damned", + "goddamn", + "goddamned", + "hardcoresex", + "hell", + "heshe", + "hoar", + "hoare", + "hoer", + "homo", + "hore", + "horniest", + "horny", + "hotsex", + "jack-off", + "jackoff", + "jap", + "jerk-off", + "jism", + "jiz", + "jizm", + "jizz", + "kawk", + "knob", + "knobead", + "knobed", + "knobend", + "knobhead", + "knobjocky", + "knobjokey", + "kock", + "kondum", + "kondums", + "kum", + "kummer", + "kumming", + "kums", + "kunilingus", + "l3i\+ch", + "l3itch", + "labia", + "lmfao", + "lust", + "lusting", + "m0f0", + "m0fo", + "m45terbate", + "ma5terb8", + "ma5terbate", + "masochist", + "master-bate", + "masterb8", + "masterbat", + "masterbat3", + "masterbate", + "masterbation", + "masterbations", + "masturbate", + "merde", + "mo-fo", + "mof0", + "mofo", + "mothafuck", + "mothafucka", + "mothafuckas", + "mothafuckaz", + "mothafucked", + "mothafucker", + "mothafuckers", + "mothafuckin", + "mothafucking", + "mothafuckings", + "mothafucks", + "motherfuck", + "motherfucked", + "motherfucker", + "motherfuckers", + "motherfuckin", + "motherfucking", + "motherfuckings", + "motherfuckka", + "motherfucks", + "muff", + "mutha", + "muthafecker", + "muthafuckker", + "muther", + "mutherfucker", + "n1gga", + "n1gger", + "nazi", + "nigg3r", + "nigg4h", + "nigga", + "niggah", + "niggas", + "niggaz", + "nigger", + "niggers", + "nique", + "niquer", + "nob", + "nobhead", + "nobjocky", + "nobjokey", + "numbnuts", + "nutsack", + "orgasim", + "orgasims", + "orgasm", + "orgasms", + "p0rn", + "pauvre con", + "pawn", + "pecker", + "penis", + "penisfucker", + "phonesex", + "phuck", + "phuk", + "phuked", + "phuking", + "phukked", + "phukking", + "phuks", + "phuq", + "pigfucker", + "pimpis", + "piss", + "pissed", + "pisser", + "pissers", + "pisses", + "pissflaps", + "pissin", + "pissing", + "pissoff", + "poop", + "porn", + "porno", + "pornography", + "pornos", + "prick", + "pron", + "pube", + "pusse", + "pussi", + "pussies", + "pussy", + "pute", + "putain", + "rectum", + "retard", + "rimjaw", + "rimming", + "s.o.b.", + "sadist", + "salaud", + "salop", + "salope", + "saloperie", + "schlong", + "screwing", + "scroat", + "scrote", + "scrotum", + "semen", + "sex", + "sh!\+", + "sh!t", + "sh1t", + "shag", + "shagger", + "shaggin", + "shagging", + "shemale", + "shi\+", + "shit", + "shitdick", + "shite", + "shited", + "shitey", + "shitfuck", + "shitfull", + "shithead", + "shiting", + "shits", + "shitted", + "shitter", + "shitting", + "shitty", + "skank", + "slut", + "sluts", + "smegma", + "smut", + "snatch", + "son-of-a-bitch", + "spac", + "spunk", + "s_h_i_t", + "t1tt1e5", + "t1tties", + "teets", + "teez", + "testical", + "testicle", + "tit", + "titfuck", + "tits", + "titt", + "tittie5", + "tittiefucker", + "titties", + "tittyfuck", + "tittywank", + "titwank", + "tosser", + "trou du cul", + "turd", + "tw4t", + "twat", + "twathead", + "twatty", + "twunt", + "twunter", + "v14gra", + "v1gra", + "vagina", + "viagra", + "vulva", + "w00se", + "wang", + "wank", + "wanker", + "wanky", + "whoar", + "whore", + "willies", + "willy", + "xrated", + "xxx" +] diff --git a/toontown/toonbase/TTLocalizerEnglishProperty.py b/toontown/toonbase/TTLocalizerEnglishProperty.py index 3073ad24..16038f24 100755 --- a/toontown/toonbase/TTLocalizerEnglishProperty.py +++ b/toontown/toonbase/TTLocalizerEnglishProperty.py @@ -56,6 +56,8 @@ FPnewEntry = 0.08 FPnewRecord = 0.08 GPgenus = 0.045 FLPnewFriend = 0.045 +FLPtruefriends = 0.045 +FLPtruefriendsPos = (0.152, 0.0, 0.14) FLPtitle = 0.04 FIbStop = 0.05 FIdirectFrame = 0.06 @@ -283,6 +285,14 @@ TPhaveFun = 0.1 TPjoinUs = 0.1 TBSOSPSPenter = 0.1 TexitButton = 0.8 +FSenterSecretTextPos = (0, 0, -0.25) +FSgotSecretPos = (0, 0, 0.47) +FSgetSecretButton = 0.06 +FSnextText = 1.0 +FSgetSecret = (1.55, 1, 1) +FSok1 = (1.55, 1, 1) +FSok2 = (0.6, 1, 1) +FScancel = (0.6, 1, 1) #Some languages need to change the word order SellbotFactoryPosPart1 = (0, -0.25) SellbotFactoryScalePart1 = 0.075 diff --git a/toontown/toonbase/ToonBase.py b/toontown/toonbase/ToonBase.py index 3b62fa8c..e4aa8e80 100755 --- a/toontown/toonbase/ToonBase.py +++ b/toontown/toonbase/ToonBase.py @@ -147,9 +147,6 @@ class ToonBase(OTPBase.OTPBase): self.setCursorAndIcon() return result - def windowEvent(self, win): - OTPBase.OTPBase.windowEvent(self, win) - def setCursorAndIcon(self): tempdir = tempfile.mkdtemp() atexit.register(shutil.rmtree, tempdir) @@ -419,13 +416,6 @@ class ToonBase(OTPBase.OTPBase): self.cr.sendDisconnect() sys.exit() - def getShardPopLimits(self): - return ( - config.GetInt('shard-low-pop', ToontownGlobals.LOW_POP), - config.GetInt('shard-mid-pop', ToontownGlobals.MID_POP), - config.GetInt('shard-high-pop', ToontownGlobals.HIGH_POP) - ) - def playMusic(self, music, looping = 0, interrupt = 1, volume = None, time = 0.0): OTPBase.OTPBase.playMusic(self, music, looping, interrupt, volume, time) diff --git a/toontown/toonbase/ToontownBattleGlobals.py b/toontown/toonbase/ToontownBattleGlobals.py index 55e2300a..c8552b78 100755 --- a/toontown/toonbase/ToontownBattleGlobals.py +++ b/toontown/toonbase/ToontownBattleGlobals.py @@ -92,6 +92,7 @@ Levels = [[0, regMaxSkill = 10000 UberSkill = 500 MaxSkill = UberSkill + regMaxSkill +ExperienceCap = 300 MaxToonAcc = 95 @@ -830,4 +831,4 @@ def getUberFlagSafe(flagMask, index): if flagMask == 'unknown' or flagMask < 0: return -1 else: - return getUberFlag(flagMask, index) \ No newline at end of file + return getUberFlag(flagMask, index) diff --git a/toontown/toonbase/ToontownGlobals.py b/toontown/toonbase/ToontownGlobals.py index 68b42ecf..d487e7e0 100755 --- a/toontown/toonbase/ToontownGlobals.py +++ b/toontown/toonbase/ToontownGlobals.py @@ -39,14 +39,14 @@ SpeedwayCameraFar = 8000.0 SpeedwayCameraNear = 1.0 MaxMailboxContents = 60 MaxHouseItems = 250 -MaxAccessories = 75 +MaxAccessories = 100 ExtraDeletedItems = 5 DeletedItemLifetime = 7 * 24 * 60 CatalogNumWeeksPerSeries = 13 CatalogNumWeeks = 78 PetFloorCollPriority = 5 PetPanelProximityPriority = 6 -P_NoTrunk = -28 +P_TooFast = -28 P_AlreadyOwnBiggerCloset = -27 P_ItemAlreadyRented = -26 P_OnAwardOrderListFull = -25 @@ -177,7 +177,7 @@ HoodHierarchy = {ToontownCentral: (SillyStreet, LoopyLane, PunchlinePlace), TheBrrrgh: (WalrusWay, SleetStreet, PolarPlace), MinniesMelodyland: (AltoAvenue, BaritoneBoulevard, TenorTerrace), DaisyGardens: (ElmStreet, MapleStreet, OakStreet), - DonaldsDreamland: (LullabyLane, PajamaPlace), + DonaldsDreamland: (LullabyLane, PajamaPlace, BedtimeBoulevard), GoofySpeedway: ()} BossbotHQ = 10000 BossbotLobby = 10100 @@ -347,7 +347,7 @@ MinigameNames = {'race': RaceGameId, 'cannon': CannonGameId, 'tag': TagGameId, 'pattern': PatternGameId, - 'minnie': PatternGameId, + 'jaymo': PatternGameId, 'match': PatternGameId, 'matching': PatternGameId, 'ring': RingGameId, @@ -577,7 +577,7 @@ BossCogOvertimeAttack = 20 BossCogAttackTimes = {BossCogElectricFence: 0, BossCogSwatLeft: 5.5, BossCogSwatRight: 5.5, - BossCogAreaAttack: 4.21, + BossCogAreaAttack: 4.5, BossCogFrontAttack: 2.65, BossCogRecoverDizzyAttack: 5.1, BossCogDirectedAttack: 4.84, @@ -941,7 +941,6 @@ JELLYBEAN_TROLLEY_HOLIDAY_MONTH = 113 JELLYBEAN_FISHING_HOLIDAY_MONTH = 114 JELLYBEAN_PARTIES_HOLIDAY_MONTH = 115 SILLYMETER_EXT_HOLIDAY = 116 -LAUGHING_MAN = 123 TOT_REWARD_JELLYBEAN_AMOUNT = 100 TOT_REWARD_END_OFFSET_AMOUNT = 0 LawbotBossMaxDamage = 2700 @@ -1426,13 +1425,6 @@ ColorNoChat = (0.8, 0.5, 0.1, 1) -FactoryLaffMinimums = [(0, 31, 0), - (0, 66, 71), - (0, - 81, - 86, - 96), - (0, 101, 106)] PICNIC_COUNTDOWN_TIME = 60 BossbotRTIntroStartPosHpr = (0, -64, @@ -1621,10 +1613,81 @@ BMovementSpeed = 0 BMovementSpeedMultiplier = 1.3 BugReportSite = 'https://bugs.launchpad.net/toontown-united/+filebug' -CostPerLaffRestock = 3 -FISHSALE_NONE = 0 -FISHSALE_COMPLETE = 1 -FISHSALE_TROPHY = 2 NPCCollisionDelay = 2.5 + +CostPerLaffRestock = 3 + +FISHSALE_COMPLETE = 0 +FISHSALE_TROPHY = 1 + +CLERK_GOODBYE = 0 +CLERK_GREETING = 1 +CLERK_TOOKTOOLONG = 2 + KnockKnockHeal = 12 KnockKnockCooldown = 600 + +CRATE_NOT_OWNER = 0 +CRATE_NO_KEYS = 1 +CRATE_BEANS = 2 +CRATE_BUFFS = 3 +CRATE_NAMETAGS = 4 +CRATE_EMOTES = 5 +CRATE_CLOTHING = 6 +CRATE_ACCESSORIES = 7 + +STAT_COGS = 0 +STAT_V2 = 1 +STAT_SKELE = 2 +STAT_BEANS_SPENT = 3 +STAT_BEANS_EARNT = 4 +STAT_TASKS = 5 +STAT_VP = 6 +STAT_CFO = 7 +STAT_CJ = 8 +STAT_CEO = 9 +STAT_SAD = 10 +STAT_BLDG = 11 +STAT_COGDO = 12 +STAT_ITEMS = 13 +STAT_FISH = 14 +STAT_FLOWERS = 15 +STAT_RACING = 16 +STAT_GOLF = 17 +STAT_SOS = 18 +STAT_UNITES = 19 +STAT_SLIPS = 20 +STAT_GAGS = 21 + +CHAIR_START = 0 +CHAIR_STOP = 1 +CHAIR_NONE = 0 +CHAIR_EXIT = 1 +CHAIR_UNEXPECTED_EXIT = 2 + +MAX_TF_TRIES = 5 +TF_COOLDOWN_SECS = 60 * 60 * 24 +TF_EXPIRE_SECS = 3 * 60 * 60 * 24 +TF_COOLDOWN = 0 +TF_UNKNOWN_SECRET = 1 +TF_SELF_SECRET = 2 +TF_TOO_FAST = 3 +TF_FRIENDS_LIST_FULL_YOU = 4 +TF_FRIENDS_LIST_FULL_HIM = 5 +TF_ALREADY_FRIENDS = 6 +TF_ALREADY_FRIENDS_NAME = 7 +TF_SUCCESS = 8 + +GROUP_ZONES = [11000, 11100, 11200, 12000, 12100, 13000, 13100, 13200, 10000, 10100] + +TOONUP_PULSE_ZONES = [ToontownCentral, DonaldsDock, DaisyGardens, MinniesMelodyland, TheBrrrgh, DonaldsDreamland] +TOONUP_FREQUENCY = 30 + +TV_NOT_OWNER = 0 +TV_INVALID_VIDEO = 1 +TV_OK = 2 + +COLOR_SATURATION_MIN = 0.36 +COLOR_SATURATION_MAX = 0.8 +COLOR_VALUE_MIN = 0.5 +COLOR_VALUE_MAX = 0.9 \ No newline at end of file diff --git a/toontown/toonbase/ToontownStart.py b/toontown/toonbase/ToontownStart.py index 54403947..ba86dacf 100644 --- a/toontown/toonbase/ToontownStart.py +++ b/toontown/toonbase/ToontownStart.py @@ -1,4 +1,8 @@ #!/usr/bin/env python2 +import gc + +gc.disable() + import __builtin__ __builtin__.process = 'client' @@ -98,8 +102,12 @@ if 'speedchatPlus' not in settings: settings['speedchatPlus'] = True if 'trueFriends' not in settings: settings['trueFriends'] = True +if 'tpTransition' not in settings: + settings['tpTransition'] = True if 'fov' not in settings: settings['fov'] = OTPGlobals.DefaultCameraFov +if 'talk2speech' not in settings: + settings['talk2speech'] = False loadPrcFileData('Settings: res', 'win-size %d %d' % tuple(settings['res'])) loadPrcFileData('Settings: fullscreen', 'fullscreen %s' % settings['fullscreen']) @@ -189,11 +197,15 @@ del version base.loader = base.loader __builtin__.loader = base.loader autoRun = ConfigVariableBool('toontown-auto-run', 1) + +gc.enable() +gc.collect() + if autoRun: try: base.run() except SystemExit: - raise + pass except: - print describeException() - raise + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/toontown/toontowngui/ToontownLoadingScreen.py b/toontown/toontowngui/ToontownLoadingScreen.py index 0aba400c..1f336db9 100755 --- a/toontown/toontowngui/ToontownLoadingScreen.py +++ b/toontown/toontowngui/ToontownLoadingScreen.py @@ -1,7 +1,6 @@ -from panda3d.core import * +from pandac.PandaModules import * from direct.gui.DirectGui import * -from toontown.toonbase import ToontownGlobals -from toontown.toonbase import TTLocalizer +from toontown.toonbase import ToontownGlobals, TTLocalizer from toontown.hood import ZoneUtil import random @@ -12,6 +11,10 @@ class ToontownLoadingScreen: def __init__(self): self.__expectedCount = 0 self.__count = 0 + self.textures = [(loader.loadTexture('phase_3.5/maps/loading/toon.jpg'), ToontownGlobals.getSignFont(), (0.2, 0.6, 0.9, 1)), + (loader.loadTexture('phase_3.5/maps/loading/cog.jpg'), ToontownGlobals.getSuitFont(), (1.0, 1.0, 1.0, 1)), + (loader.loadTexture('phase_3.5/maps/loading/default.jpg'), ToontownGlobals.getInterfaceFont(), (0, 0, 0.5, 1)) + ] self.gui = loader.loadModel('phase_3/models/gui/progress-background.bam') self.title = DirectLabel(guiId='ToontownLoadingScreenTitle', parent=self.gui, relief=None, pos=(base.a2dRight/5, 0, 0.235), text='', textMayChange=1, text_scale=0.08, text_fg=(0, 0, 0.5, 1), text_align=TextNode.ALeft, text_font=ToontownGlobals.getInterfaceFont()) self.tip = DirectLabel(guiId='ToontownLoadingScreenTip', parent=self.gui, relief=None, pos=(0, 0, 0.045), text='', textMayChange=1, text_scale=0.05, text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), text_align=TextNode.ACenter) @@ -35,135 +38,21 @@ class ToontownLoadingScreen: return TTLocalizer.TipTitle + ' ' + random.choice(TTLocalizer.TipDict.get(tipCategory)) def begin(self, range, label, gui, tipCategory, zoneId): - self.defaultTex = 'phase_3.5/maps/loading/default.jpg' - self.defaultFont = ToontownGlobals.getInterfaceFont() - self.defaultFontColor = (0, 0, 0.5, 1) - self.zone2picture = { - ToontownGlobals.GoofySpeedway : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.ToontownCentral : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.SillyStreet : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.LoopyLane : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.PunchlinePlace : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.DonaldsDock : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.BarnacleBoulevard : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.SeaweedStreet : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.LighthouseLane : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.DaisyGardens : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.ElmStreet : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.MapleStreet : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.OakStreet : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.MinniesMelodyland : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.AltoAvenue : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.BaritoneBoulevard : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.TenorTerrace : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.TheBrrrgh : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.WalrusWay : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.SleetStreet : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.PolarPlace : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.DonaldsDreamland : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.LullabyLane : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.PajamaPlace : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.OutdoorZone : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.GolfZone : 'phase_3.5/maps/loading/toon.jpg', - ToontownGlobals.SellbotHQ : 'phase_3.5/maps/loading/cog.jpg', - ToontownGlobals.SellbotFactoryExt : 'phase_3.5/maps/loading/cog.jpg', - ToontownGlobals.SellbotFactoryInt : 'phase_3.5/maps/loading/cog.jpg', - ToontownGlobals.SellbotMegaCorpInt : 'phase_3.5/maps/loading/cog.jpg', - ToontownGlobals.CashbotHQ : 'phase_3.5/maps/loading/cog.jpg', - ToontownGlobals.LawbotHQ : 'phase_3.5/maps/loading/cog.jpg', - ToontownGlobals.BossbotHQ : 'phase_3.5/maps/loading/cog.jpg' - } - self.zone2font = { - ToontownGlobals.GoofySpeedway : ToontownGlobals.getSignFont(), - ToontownGlobals.ToontownCentral : ToontownGlobals.getSignFont(), - ToontownGlobals.SillyStreet : ToontownGlobals.getSignFont(), - ToontownGlobals.LoopyLane : ToontownGlobals.getSignFont(), - ToontownGlobals.PunchlinePlace : ToontownGlobals.getSignFont(), - ToontownGlobals.DonaldsDock : ToontownGlobals.getSignFont(), - ToontownGlobals.BarnacleBoulevard : ToontownGlobals.getSignFont(), - ToontownGlobals.SeaweedStreet : ToontownGlobals.getSignFont(), - ToontownGlobals.LighthouseLane : ToontownGlobals.getSignFont(), - ToontownGlobals.DaisyGardens : ToontownGlobals.getSignFont(), - ToontownGlobals.ElmStreet : ToontownGlobals.getSignFont(), - ToontownGlobals.MapleStreet : ToontownGlobals.getSignFont(), - ToontownGlobals.OakStreet : ToontownGlobals.getSignFont(), - ToontownGlobals.MinniesMelodyland : ToontownGlobals.getSignFont(), - ToontownGlobals.AltoAvenue : ToontownGlobals.getSignFont(), - ToontownGlobals.BaritoneBoulevard : ToontownGlobals.getSignFont(), - ToontownGlobals.TenorTerrace : ToontownGlobals.getSignFont(), - ToontownGlobals.TheBrrrgh : ToontownGlobals.getSignFont(), - ToontownGlobals.WalrusWay : ToontownGlobals.getSignFont(), - ToontownGlobals.SleetStreet : ToontownGlobals.getSignFont(), - ToontownGlobals.PolarPlace : ToontownGlobals.getSignFont(), - ToontownGlobals.DonaldsDreamland : ToontownGlobals.getSignFont(), - ToontownGlobals.LullabyLane : ToontownGlobals.getSignFont(), - ToontownGlobals.PajamaPlace : ToontownGlobals.getSignFont(), - ToontownGlobals.OutdoorZone : ToontownGlobals.getSignFont(), - ToontownGlobals.GolfZone : ToontownGlobals.getSignFont(), - ToontownGlobals.SellbotHQ : ToontownGlobals.getSuitFont(), - ToontownGlobals.SellbotFactoryExt : ToontownGlobals.getSuitFont(), - ToontownGlobals.SellbotFactoryInt : ToontownGlobals.getSuitFont(), - ToontownGlobals.SellbotMegaCorpInt : ToontownGlobals.getSuitFont(), - ToontownGlobals.CashbotHQ : ToontownGlobals.getSuitFont(), - ToontownGlobals.LawbotHQ : ToontownGlobals.getSuitFont(), - ToontownGlobals.BossbotHQ : ToontownGlobals.getSuitFont() - } - self.zone2fontcolor = { - ToontownGlobals.GoofySpeedway : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.ToontownCentral : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.SillyStreet : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.LoopyLane : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.PunchlinePlace : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.DonaldsDock : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.BarnacleBoulevard : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.SeaweedStreet : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.LighthouseLane : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.DaisyGardens : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.ElmStreet : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.MapleStreet : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.OakStreet : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.MinniesMelodyland : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.AltoAvenue : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.BaritoneBoulevard : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.TenorTerrace : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.TheBrrrgh : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.WalrusWay : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.SleetStreet : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.PolarPlace : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.DonaldsDreamland : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.LullabyLane : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.PajamaPlace : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.OutdoorZone : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.GolfZone : VBase4(0.2, 0.6, 0.9, 1.0), - ToontownGlobals.SellbotHQ : (1.0, 1.0, 1.0, 1.0), - ToontownGlobals.SellbotFactoryExt : (1.0, 1.0, 1.0, 1.0), - ToontownGlobals.SellbotFactoryInt : (1.0, 1.0, 1.0, 1.0), - ToontownGlobals.SellbotMegaCorpInt : (1.0, 1.0, 1.0, 1.0), - ToontownGlobals.CashbotHQ : (1.0, 1.0, 1.0, 1.0), - ToontownGlobals.LawbotHQ : (1.0, 1.0, 1.0, 1.0), - ToontownGlobals.BossbotHQ : (1.0, 1.0, 1.0, 1.0) - } - + info = self.textures[ZoneUtil.isCogHQZone(zoneId) if zoneId else 2] self.waitBar['range'] = range self.title['text'] = label - self.loadingScreenTex = self.zone2picture.get(ZoneUtil.getBranchZone(zoneId), self.defaultTex) - self.loadingScreenFont = self.zone2font.get(ZoneUtil.getBranchZone(zoneId), self.defaultFont) - self.loadingScreenFontColor = self.zone2fontcolor.get(ZoneUtil.getBranchZone(zoneId), self.defaultFontColor) - self.background = loader.loadTexture(self.loadingScreenTex) self.__count = 0 self.__expectedCount = range if gui: self.waitBar['frameSize'] = (base.a2dLeft+(base.a2dRight/4.95), base.a2dRight-(base.a2dRight/4.95), -0.03, 0.03) - self.title['text_font'] = self.loadingScreenFont - self.title['text_fg'] = self.loadingScreenFontColor + self.title['text_font'] = info[1] + self.title['text_fg'] = info[2] self.title.reparentTo(base.a2dpBottomLeft, LOADING_SCREEN_SORT_INDEX) self.title.setPos(base.a2dRight/5, 0, 0.235) self.tip['text'] = self.getTip(tipCategory) self.gui.setPos(0, -0.1, 0) self.gui.reparentTo(aspect2d, LOADING_SCREEN_SORT_INDEX) - self.gui.setTexture(self.background, 1) - #if self.loadingScreenTex == self.defaultTex: - # self.logo.reparentTo(base.a2dpTopCenter, LOADING_SCREEN_SORT_INDEX) + self.gui.setTexture(info[0], 1) self.logo.reparentTo(base.a2dpTopCenter, LOADING_SCREEN_SORT_INDEX) else: self.title.reparentTo(base.a2dpBottomLeft, LOADING_SCREEN_SORT_INDEX) @@ -187,4 +76,4 @@ class ToontownLoadingScreen: def tick(self): self.__count = self.__count + 1 - self.waitBar.update(self.__count) + self.waitBar.update(self.__count) \ No newline at end of file diff --git a/toontown/town/TownBattle.py b/toontown/town/TownBattle.py index 79cb54b6..2f788092 100755 --- a/toontown/town/TownBattle.py +++ b/toontown/town/TownBattle.py @@ -359,9 +359,6 @@ class TownBattle(StateData.StateData): def enterAttack(self): self.attackPanel.enter() self.accept(self.attackPanelDoneEvent, self.__handleAttackPanelDone) - for toonPanel in self.toonPanels: - toonPanel.setValues(0, BattleBase.NO_ATTACK) - return None def exitAttack(self): diff --git a/toontown/town/TownBattleToonPanel.py b/toontown/town/TownBattleToonPanel.py index fbd77dea..932e7c54 100755 --- a/toontown/town/TownBattleToonPanel.py +++ b/toontown/town/TownBattleToonPanel.py @@ -49,7 +49,7 @@ class TownBattleToonPanel(DirectFrame): messenger.send(self.avatar.uniqueName('hpChange'), [avatar.hp, avatar.maxHp, 1]) return None else: - if self.avatar: + if self.avatar or self.laffMeter: self.cleanupLaffMeter() self.avatar = avatar self.laffMeter = LaffMeter.LaffMeter(avatar.style, avatar.hp, avatar.maxHp) diff --git a/toontown/uberdog/ClientServicesManagerUD.py b/toontown/uberdog/ClientServicesManagerUD.py index 8dd1c5f0..462b59d2 100755 --- a/toontown/uberdog/ClientServicesManagerUD.py +++ b/toontown/uberdog/ClientServicesManagerUD.py @@ -329,7 +329,7 @@ class LoginAccountFSM(OperationFSM): 'ACCOUNT_AV_SET': [0] * 6, 'ESTATE_ID': 0, 'ACCOUNT_AV_SET_DEL': [], - 'CREATED': time.time(), + 'CREATED': time.ctime(), 'LAST_LOGIN': time.ctime(), 'LAST_LOGIN_TS': time.time(), 'ACCOUNT_ID': str(self.userId), @@ -499,7 +499,7 @@ class CreateAvatarFSM(OperationFSM): def enterCreateAvatar(self): dna = ToonDNA() dna.makeFromNetString(self.dna) - colorString = TTLocalizer.NumToColor[dna.headColor] + colorString = TTLocalizer.ColorfulToon animalType = TTLocalizer.AnimalToSpecies[dna.getAnimal()] name = ' '.join((colorString, animalType)) toonFields = { @@ -689,7 +689,7 @@ class DeleteAvatarFSM(GetAvatarsFSM): estateId, self.csm.air.dclassesByName['DistributedEstateAI'], {'setSlot%dToonId' % index: [0], - 'setSlot%dItems' % index: [[]]} + 'setSlot%dGarden' % index: [[]]} ) self.csm.air.dbInterface.updateObject( @@ -919,6 +919,10 @@ class LoadAvatarFSM(AvatarOperationFSM): # Tell the GlobalPartyManager as well: self.csm.air.globalPartyMgr.avatarJoined(self.avId) + + fields = self.avatar + fields.update({'setAdminAccess': [self.account.get('ACCESS_LEVEL', 100)]}) + self.csm.air.friendsManager.addToonData(self.avId, fields) self.csm.air.writeServerEvent('avatarChosen', self.avId, self.target) self.demand('Off') @@ -969,7 +973,7 @@ class LoadAvatarFSM(AvatarOperationFSM): # Eliminate race conditions. taskMgr.doMethodLater(0.2, self.enterSetAvatarTask, 'avatarTask-%s' % self.avId, extraArgs=[channel], - appendTask=True) + appendTask=True) class UnloadAvatarFSM(OperationFSM): notify = directNotify.newCategory('UnloadAvatarFSM') diff --git a/toontown/uberdog/ToontownUberRepository.py b/toontown/uberdog/ToontownUberRepository.py index 720f10c0..52278f95 100755 --- a/toontown/uberdog/ToontownUberRepository.py +++ b/toontown/uberdog/ToontownUberRepository.py @@ -4,31 +4,21 @@ from otp.distributed.OtpDoGlobals import * from otp.distributed.DistributedDirectoryAI import DistributedDirectoryAI from toontown.distributed.ToontownInternalRepository import ToontownInternalRepository import toontown.minigame.MinigameCreatorAI +from toontown.uberdog.TopToonsManagerUD import TopToonsManagerUD if config.GetBool('want-rpc-server', False): from toontown.rpc.ToontownRPCServer import ToontownRPCServer from toontown.rpc.ToontownRPCHandler import ToontownRPCHandler -if config.GetBool('want-mongo-client', False): - import pymongo - class ToontownUberRepository(ToontownInternalRepository): def __init__(self, baseChannel, serverId): ToontownInternalRepository.__init__(self, baseChannel, serverId, dcSuffix='UD') - if config.GetBool('want-mongo-client', False): - url = config.GetString('mongodb-url', 'mongodb://localhost') - replicaset = config.GetString('mongodb-replicaset', '') - if replicaset: - self.mongo = pymongo.MongoClient(url, replicaset=replicaset) - else: - self.mongo = pymongo.MongoClient(url) - db = (urlparse.urlparse(url).path or '/test')[1:] - self.mongodb = self.mongo[db] - self.notify.setInfo(True) + self.wantTopToons = self.config.GetBool('want-top-toons', True) def handleConnected(self): + ToontownInternalRepository.handleConnected(self) rootObj = DistributedDirectoryAI(self) rootObj.generateWithRequiredAndId(self.getGameDoId(), 0, 0) @@ -49,4 +39,6 @@ class ToontownUberRepository(ToontownInternalRepository): self.chatAgent = simbase.air.generateGlobalObject(OTP_DO_ID_CHAT_MANAGER, 'ChatAgent') self.friendsManager = simbase.air.generateGlobalObject(OTP_DO_ID_TTS_FRIENDS_MANAGER, 'TTSFriendsManager') self.globalPartyMgr = simbase.air.generateGlobalObject(OTP_DO_ID_GLOBAL_PARTY_MANAGER, 'GlobalPartyManager') - self.groupManager = simbase.air.generateGlobalObject(OPT_DO_ID_GROUP_MANAGER, 'GroupManager') + if self.wantTopToons: + self.topToonsMgr = TopToonsManagerUD(self) + diff --git a/toontown/uberdog/TopToonsGlobals.py b/toontown/uberdog/TopToonsGlobals.py new file mode 100644 index 00000000..7786d828 --- /dev/null +++ b/toontown/uberdog/TopToonsGlobals.py @@ -0,0 +1,19 @@ +CAT_COGS = 1 +CAT_BLDG = 2 +CAT_CATALOG = 4 +CAT_GIFTS = 8 +CAT_TASKS = 16 +CAT_TROLLEY = 32 +CAT_RACE_WON = 64 +CAT_FISH = 128 +CAT_JELLYBEAN = 256 +CAT_HOLE_IN_ONE = 512 +CAT_COURSE_UNDER_PAR = 1024 +CAT_VP = 2048 +CAT_CFO = 4096 +CAT_CJ = 8192 +CAT_CEO = 16384 + +_CAT_BEGIN = CAT_COGS +_CAT_END = CAT_CEO +_CAT_ALL = (_CAT_END << 1) - 1 \ No newline at end of file diff --git a/toontown/uberdog/TopToonsManagerAI.py b/toontown/uberdog/TopToonsManagerAI.py new file mode 100644 index 00000000..5b41ac26 --- /dev/null +++ b/toontown/uberdog/TopToonsManagerAI.py @@ -0,0 +1,31 @@ +from direct.showbase.DirectObject import * +import TopToonsGlobals + +class TopToonsManagerAI(DirectObject): + def __init__(self, air): + self.air = air + + self.accept('topToonsManager-event', self.__handleEvent) + + def toonKilledBoss(self, av, boss): + cat = {'VP': TopToonsGlobals.CAT_VP, + 'CFO': TopToonsGlobals.CAT_CFO, + 'CJ': TopToonsGlobals.CAT_CJ, + 'CEO': TopToonsGlobals.CAT_CEO}.get(boss, 0) + self.__handleEvent(av.doId, cat, 1) + + def __handleEvent(self, *args): # avId, categories, score + self.air.sendNetEvent('topToonsManager-AI-score-site', list(args)) + +from otp.ai.MagicWordGlobal import * +@magicWord(types=[int, int]) +def topToon(score, cat=TopToonsGlobals._CAT_ALL): + av = spellbook.getTarget() + mgr = av.air.topToonsMgr + if not mgr: + return 'No manager!' + + if cat > TopToonsGlobals._CAT_ALL: + return 'Max value: %d' % TopToonsGlobals._CAT_ALL + + messenger.send('topToonsManager-event', [av.doId, cat, score]) \ No newline at end of file diff --git a/toontown/uberdog/TopToonsManagerUD.py b/toontown/uberdog/TopToonsManagerUD.py new file mode 100644 index 00000000..6bb752cb --- /dev/null +++ b/toontown/uberdog/TopToonsManagerUD.py @@ -0,0 +1,246 @@ +# CLEANUP IMPORTS + +from direct.directnotify import DirectNotifyGlobal +from direct.fsm.FSM import FSM +from direct.showbase.DirectObject import * +from toontown.toon.ToonDNA import ToonDNA, getSpeciesName +import TopToonsGlobals +import time, random +import datetime, json +import urllib +import urllib2 +import hashlib + +def getCurrentMonth(): + dt = datetime.date.today() + month = dt.month + year = dt.year + return year * 100 + month + +def getPrevMonth(): + current = getCurrentMonth() + year, month = divmod(current, 100) + month -= 1 + if not month: + month = 12 + year -= 1 + + return year * 100 + month + +def getNextMonth(): + current = getCurrentMonth() + year, month = divmod(current, 100) + month += 1 + if month > 12: + month = 1 + year += 1 + + return year * 100 + month + +def timeToNextMonth(): + now = datetime.datetime.now() + year, month = divmod(getNextMonth(), 100) + return (datetime.datetime(year, month, 1) - now).total_seconds() + +def getEmptySiteToonsColl(month): + coll = {} + + start = TopToonsGlobals._CAT_BEGIN + end = TopToonsGlobals._CAT_END + while start <= end: + coll[str(start)] = {} + start *= 2 + + coll['month'] = month + return coll + +class SiteUploadFSM(FSM): + notify = DirectNotifyGlobal.directNotify.newCategory('SiteUploadFSM') + URL = config.GetString('toptoons-api-endpoint', 'http://toontownstride.com/toptoons/post/') # Let's hope jumbleweed hasn't changed this + + def __init__(self, mgr, data): + FSM.__init__(self, 'SiteUploadFSM') + + self.mgr = mgr + self.data = {} + self.month = data.pop('month') + for category, avs in data.items(): + self.data[int(category)] = sorted(avs.items(), key=lambda x: -x[1]) + + self.__cat = TopToonsGlobals._CAT_BEGIN + self.__responses = {} + self.__cache = {} + self.__waiting = {} + self.__dataToSend = {} + self.__failures = -1 + + self.demand('QueryAvatars') + + def enterQueryAvatars(self): + avs = self.data[self.__cat] + cutoff = self.__failures + if cutoff == -1: + cutoff = 5 + selected, remaining = avs[:cutoff], avs[cutoff:] + self.data[self.__cat] = remaining + + self.__waiting = {int(x[0]): x[1] for x in selected} + avIds = self.__waiting.keys() + for avId in avIds: + if avId in self.__cache: + self.__responses[avId] = (self.__cache[avId][0], self.__waiting.pop(avId)) + + self.__failures = 0 + for avId in self.__waiting: + def response(x, y, avId=avId): + self.__handleToon(avId, x, y) + + self.mgr.air.dbInterface.queryObject(self.mgr.air.dbId, avId, response) + + if not self.__waiting: + self.demand('SortResults') + + def __handleToon(self, avId, dclass, fields): + if avId not in self.__waiting: + return + + if dclass != self.mgr.air.dclassesByName['DistributedToonUD']: + self.__failures += 1 + self.notify.warning('%d query failed!' % avId) + del self.__waiting[avId] + if not self.__waiting: + self.demand('QueryAvatars') + return + + name = fields['setName'][0] + hp = fields['setMaxHp'][0] + + dna = ToonDNA(fields['setDNAString'][0]) + species = getSpeciesName(dna.head) + color = dna.headColor + + if species == 'pig': + dna = 'pig' + + else: + if species == 'cat' and color == 26: + dna = 'blackcat' + + else: + if color > 23: + color = 0 + + dna = '%s_%s_%d' % (species, dna.head[1:], color) + + self.__responses[avId] = ((name, dna, hp), self.__waiting.pop(avId)) + + if not self.__waiting: + self.demand('QueryAvatars') + + def enterSortResults(self): + responses = sorted(self.__responses.values(), key=lambda x: -x[-1]) + self.__dataToSend[self.__cat] = responses + self.__cache.update(self.__responses) + self.__failures = -1 + self.__responses = {} + self.__cat *= 2 + if self.__cat * 2 == TopToonsGlobals._CAT_END: + self.demand('Upload') + return + + self.demand('QueryAvatars') + + def enterUpload(self): + self.__dataToSend['month'] = self.month + + (success, error), res = self.post(self.URL, self.__dataToSend) + print (success, error), res + + def post(self, url, data): + headers = {'User-Agent' : 'TTUberAgent'} + + innerData = json.dumps(data) + hmac = hashlib.sha512(innerData + self.mgr.air.getApiKey()).hexdigest() # XXX PROVIDE THE KEY HERE + + data = 'data=%s' % urllib.quote(innerData) + data += '&hmac=%s' % urllib.quote(hmac) + + success = True + error = None + res = {} + + try: + req = urllib2.Request(url, data, headers) + res = json.loads(urllib2.urlopen(req).read()) + success = res['success'] + error = res.get('error') + + except Exception as e: + if hasattr(e, 'read'): + with open('../e.html', 'wb') as f: + f.write(e.read()) + + success = False + error = str(e) + + return (success, error), res + +class TopToonsManagerUD(DirectObject): + notify = DirectNotifyGlobal.directNotify.newCategory('TopToonsManagerUD') + + def __init__(self, air): + self.air = air + + self.__curMonth = getCurrentMonth() + coll = None + if self.air.dbConn: + coll = self.air.dbGlobalCursor.strideToons.find_one({'month': self.__curMonth}) + if not coll: + lastMonthColl = self.air.dbGlobalCursor.strideToons.find_one({'month': getPrevMonth()}) + if lastMonthColl: + self.__uploadLastMonth(lastMonthColl) + + if not coll: + coll = getEmptySiteToonsColl(self.__curMonth) + + self.__topToonsData = coll + self.__topToonsData.pop('_id', None) + + self.accept('topToonsManager-AI-score-site', self.__topToonsScore) + self.waitForNextMonth() + + def __uploadLastMonth(self, data): + self.notify.info('Sending last month result to site...') + SiteUploadFSM(self, data) + + def waitForNextMonth(self): + def _nm(task): + self.__uploadLastMonth(self.__topToonsData) + + self.__curMonth = getCurrentMonth() + self.__topToonsData = getEmptySiteToonsColl(self.__curMonth) + + self.waitForNextMonth() + + return task.done + + taskMgr.doMethodLater(timeToNextMonth() + 1, _nm, 'TopToonsManagerUD-nextMonth') + + def saveSite(self): + if self.air.dbConn: + self.air.dbGlobalCursor.strideToons.update({'month': self.__curMonth}, {'$set': self.__topToonsData}, upsert=True) + + def __topToonsScore(self, avId, categories, score): + def _add(cat): + cd = self.__topToonsData[str(cat)] + cd[str(avId)] = cd.get(str(avId), 0) + score + + start = TopToonsGlobals._CAT_BEGIN + end = TopToonsGlobals._CAT_END + while start <= end: + if categories & start: + _add(start) + + start *= 2 + + self.saveSite() \ No newline at end of file