From f38f910638c1f52c601ad0c86c6f70b5b4af8051 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 29 Mar 2015 18:41:02 +0300 Subject: [PATCH] Upstream update --- astron/dclass/united.dc | 3 + toontown/battle/BattleCalculatorAI.py | 2 +- toontown/battle/DistributedBattleBaseAI.py | 98 ++++++---- toontown/battle/MovieDrop.py | 2 +- toontown/battle/MovieSound.py | 2 +- toontown/battle/MovieSquirt.py | 2 + toontown/battle/MovieThrow.py | 4 + toontown/building/PetshopBuildingAI.py | 24 +-- toontown/catalog/CatalogPetTrickItem.py | 2 +- .../distributed/ToontownClientRepository.py | 12 +- toontown/estate/EstateManagerAI.py | 57 +++++- toontown/friends/TTUFriendsManager.py | 20 ++ toontown/friends/TTUFriendsManagerUD.py | 20 ++ toontown/hood/Place.py | 11 +- toontown/pets/DistributedPetAI.py | 109 ++--------- toontown/pets/DistributedPetProxyAI.py | 1 - toontown/pets/DistributedPetUD.py | 55 ++++++ toontown/pets/Pet.py | 38 ++-- toontown/pets/PetActionFSM.py | 54 +----- toontown/pets/PetBrain.py | 20 +- toontown/pets/PetChase.py | 3 + toontown/pets/PetDCImportsAI.py | 1 + toontown/pets/PetDNA.py | 2 +- toontown/pets/PetHandle.py | 1 + toontown/pets/PetLookerAI.py | 10 +- toontown/pets/PetManagerAI.py | 82 +++++++- toontown/pets/PetMoverAI.py | 177 ++++++++++++++++++ toontown/pets/PetTricks.py | 2 +- toontown/pets/PetWander.py | 6 +- toontown/pets/PetshopGUI.py | 3 +- toontown/toon/DistributedNPCPetclerkAI.py | 6 +- toontown/toon/DistributedToon.py | 3 - toontown/toon/Documents - Shortcut.lnk | Bin 922 -> 0 bytes toontown/toon/LocalToon.py | 18 +- toontown/toonbase/BitmaskGlobals.py | 23 +++ toontown/town/Street.py | 24 +-- 36 files changed, 623 insertions(+), 274 deletions(-) create mode 100644 toontown/pets/DistributedPetUD.py create mode 100644 toontown/pets/PetMoverAI.py delete mode 100644 toontown/toon/Documents - Shortcut.lnk create mode 100644 toontown/toonbase/BitmaskGlobals.py diff --git a/astron/dclass/united.dc b/astron/dclass/united.dc index 5db015ae..5eedd98d 100644 --- a/astron/dclass/united.dc +++ b/astron/dclass/united.dc @@ -3740,6 +3740,9 @@ dclass TTUFriendsManager : DistributedObjectGlobal { getAvatarDetails(uint32) clsend; friendDetails(uint32, blob, uint16[], uint16, int16, int16, uint32, uint32, blob, blob, int8[]); + getPetDetails(uint32) clsend; + petDetails(uint32, uint32, string, uint32, uint32, uint16/1000[], PetTrait[], int8[], uint32); + routeTeleportQuery(uint32 toId) clsend; teleportQuery(uint32 fromId); diff --git a/toontown/battle/BattleCalculatorAI.py b/toontown/battle/BattleCalculatorAI.py index 81f271fa..f54d2323 100644 --- a/toontown/battle/BattleCalculatorAI.py +++ b/toontown/battle/BattleCalculatorAI.py @@ -769,7 +769,7 @@ class BattleCalculatorAI: return tgts = self.__createToonTargetList(toonId) for currTgt in tgts: - tgtPos = self.battle.suits.index(currTgt) + tgtPos = self.battle.activeSuits.index(currTgt) attackerId = self.toonAtkOrder[attackIndex] attack = self.battle.toonAttacks[attackerId] track = self.__getActualTrack(attack) diff --git a/toontown/battle/DistributedBattleBaseAI.py b/toontown/battle/DistributedBattleBaseAI.py index 55afec64..da8e39b8 100644 --- a/toontown/battle/DistributedBattleBaseAI.py +++ b/toontown/battle/DistributedBattleBaseAI.py @@ -76,7 +76,6 @@ class DistributedBattleBaseAI(DistributedObjectAI.DistributedObjectAI, BattleBas self.numNPCAttacks = 0 self.npcAttacks = {} self.pets = {} - self.fireCount = 0 self.fsm = ClassicFSM.ClassicFSM('DistributedBattleAI', [State.State('FaceOff', self.enterFaceOff, self.exitFaceOff, ['WaitForInput', 'Resume']), State.State('WaitForJoin', self.enterWaitForJoin, self.exitWaitForJoin, ['WaitForInput', 'Resume']), State.State('WaitForInput', self.enterWaitForInput, self.exitWaitForInput, ['MakeMovie', 'Resume']), @@ -1051,13 +1050,7 @@ class DistributedBattleBaseAI(DistributedObjectAI.DistributedObjectAI, BattleBas elif track == PASS: self.toonAttacks[toonId] = getToonAttack(toonId, track=PASS) elif track == FIRE: - if simbase.air.doId2do[toonId].getPinkSlips() < self.getFireCount() + 1: - #Not allowed to fire, force them to pass >:D - self.toonAttacks[toonId] = getToonAttack(toonId, track=PASS) - else: - #Allowed to fire - self.setFireCount(self.fireCount + 1) - self.toonAttacks[toonId] = getToonAttack(toonId, track=FIRE, target=av) + self.toonAttacks[toonId] = getToonAttack(toonId, track=FIRE, target=av) else: if not self.validate(toonId, track >= 0 and track <= MAX_TRACK_INDEX, 'requestAttack: invalid track %s' % track): return @@ -1104,25 +1097,65 @@ class DistributedBattleBaseAI(DistributedObjectAI.DistributedObjectAI, BattleBas petId = toon.getPetId() zoneId = self.zoneId if petId == av: - if toonId not in self.pets: - - def handleGetPetProxy(success, petProxy, petId = petId, zoneId = zoneId, toonId = toonId): + if not toonId in self.pets: + def handleGetPetProxy(success, pet, petId = petId, zoneId = zoneId, toonId = toonId): if success: - if petId not in simbase.air.doId2do: - simbase.air.requestDeleteDoId(petId) - else: - petDO = simbase.air.doId2do[petId] - petDO.requestDelete() - simbase.air.deleteDistObject(petDO) - petProxy.dbObject = 1 - petProxy.generateWithRequiredAndId(petId, self.air.districtId, zoneId) - petProxy.broadcastDominantMood() - self.pets[toonId] = petProxy + petProxy = DistributedPetProxyAI.DistributedPetProxyAI(self.air) + petProxy.setOwnerId(pet.getOwnerId()) + petProxy.setPetName(pet.getPetName()) + petProxy.setTraitSeed(pet.getTraitSeed()) + petProxy.setSafeZone(pet.getSafeZone()) + petProxy.setForgetfulness(pet.getForgetfulness()) + petProxy.setBoredomThreshold(pet.getBoredomThreshold()) + petProxy.setRestlessnessThreshold(pet.getRestlessnessThreshold()) + petProxy.setPlayfulnessThreshold(pet.getPlayfulnessThreshold()) + petProxy.setLonelinessThreshold(pet.getLonelinessThreshold()) + petProxy.setSadnessThreshold(pet.getSadnessThreshold()) + petProxy.setFatigueThreshold(pet.getFatigueThreshold()) + petProxy.setHungerThreshold(pet.getHungerThreshold()) + petProxy.setConfusionThreshold(pet.getConfusionThreshold()) + petProxy.setExcitementThreshold(pet.getExcitementThreshold()) + petProxy.setAngerThreshold(pet.getAngerThreshold()) + petProxy.setSurpriseThreshold(pet.getSurpriseThreshold()) + petProxy.setAffectionThreshold(pet.getAffectionThreshold()) + petProxy.setHead(pet.getHead()) + petProxy.setEars(pet.getEars()) + petProxy.setNose(pet.getNose()) + petProxy.setTail(pet.getTail()) + petProxy.setBodyTexture(pet.getBodyTexture()) + petProxy.setColor(pet.getColor()) + petProxy.setColorScale(pet.getColorScale()) + petProxy.setEyeColor(pet.getEyeColor()) + petProxy.setGender(pet.getGender()) + petProxy.setLastSeenTimestamp(pet.getLastSeenTimestamp()) + petProxy.setBoredom(pet.getBoredom()) + petProxy.setRestlessness(pet.getRestlessness()) + petProxy.setPlayfulness(pet.getPlayfulness()) + petProxy.setLoneliness(pet.getLoneliness()) + petProxy.setSadness(pet.getSadness()) + petProxy.setAffection(pet.getAffection()) + petProxy.setHunger(pet.getHunger()) + petProxy.setConfusion(pet.getConfusion()) + petProxy.setExcitement(pet.getExcitement()) + petProxy.setFatigue(pet.getFatigue()) + petProxy.setAnger(pet.getAnger()) + petProxy.setSurprise(pet.getSurprise()) + pet.requestDelete() + def deleted(task): + petProxy.dbObject = 1 + petProxy.generateWithRequiredAndId(petId, self.air.districtId, self.zoneId) + petProxy.broadcastDominantMood() + self.pets[toonId] = petProxy + return task.done + + self.acceptOnce(self.air.getAvatarExitEvent(petId), + lambda: taskMgr.doMethodLater(0, + deleted, self.uniqueName('petdel-%d' % petId))) + else: self.notify.warning('error generating petProxy: %s' % petId) self.getPetProxyObject(petId, handleGetPetProxy) - return def suitCanJoin(self): return len(self.suits) < self.maxSuits and self.isJoinable() @@ -1809,18 +1842,12 @@ class DistributedBattleBaseAI(DistributedObjectAI.DistributedObjectAI, BattleBas return None def getPetProxyObject(self, petId, callback): - doneEvent = 'readPet-%s' % self._getNextSerialNum() - dbo = DatabaseObject.DatabaseObject(self.air, petId, doneEvent=doneEvent) - pet = dbo.readPetProxy() + doneEvent = 'generate-%d' % petId - def handlePetProxyRead(dbo, retCode, callback = callback, pet = pet): - success = retCode == 0 - if not success: - self.notify.warning('pet DB read failed') - pet = None - callback(success, pet) - return + def handlePetProxyRead(pet): + callback(1, pet) + self.air.sendActivate(petId, self.air.districtId, 0) self.acceptOnce(doneEvent, handlePetProxyRead) def _getNextSerialNum(self): @@ -1828,13 +1855,8 @@ class DistributedBattleBaseAI(DistributedObjectAI.DistributedObjectAI, BattleBas self.serialNum += 1 return num - def setFireCount(self, amount): - self.fireCount = amount - def getFireCount(self): - return self.fireCount - -@magicWord(category=CATEGORY_PROGRAMMER) +@magicWord(category=CATEGORY_MODERATOR) def skipMovie(): invoker = spellbook.getInvoker() battleId = invoker.getBattleId() diff --git a/toontown/battle/MovieDrop.py b/toontown/battle/MovieDrop.py index d7a1f063..f1e13d61 100644 --- a/toontown/battle/MovieDrop.py +++ b/toontown/battle/MovieDrop.py @@ -411,7 +411,7 @@ def __createSuitTrack(drop, delay, level, alreadyDodged, alreadyTeased, target, suitTrack.append(suitGettingHit) bonusTrack = None if hpbonus > 0: - bonusTrack = Sequence(Wait(delay + tObjectAppears + 0.75), Func(suit.showHpText, -hpbonus, 1, openEnded=0)) + bonusTrack = Sequence(Wait(delay + tObjectAppears + 0.75), Func(suit.showHpText, -hpbonus, 1, openEnded=0), Func(suit.updateHealthBar, hpbonus)) if revived != 0: suitTrack.append(MovieUtil.createSuitReviveTrack(suit, toon, battle, npcs)) elif died != 0: diff --git a/toontown/battle/MovieSound.py b/toontown/battle/MovieSound.py index b52c9175..2f81c76d 100644 --- a/toontown/battle/MovieSound.py +++ b/toontown/battle/MovieSound.py @@ -102,7 +102,7 @@ def __getSuitTrack(sound, lastSoundThatHit, delay, hitCount, targets, totalDamag suitTrack.append(Func(battle.unlureSuit, suit)) bonusTrack = None if hpbonus > 0: - bonusTrack = Sequence(Wait(delay + tSuitReact + delay + 0.75 + uberDelay), Func(suit.showHpText, -hpbonus, 1, openEnded=0)) + bonusTrack = Sequence(Wait(delay + tSuitReact + delay + 0.75 + uberDelay), Func(suit.showHpText, -hpbonus, 1, openEnded=0), Func(suit.updateHealthBar, hpbonus)) suitTrack.append(Func(suit.loop, 'neutral')) if bonusTrack == None: tracks.append(suitTrack) diff --git a/toontown/battle/MovieSquirt.py b/toontown/battle/MovieSquirt.py index 72ba13eb..9866c94d 100644 --- a/toontown/battle/MovieSquirt.py +++ b/toontown/battle/MovieSquirt.py @@ -206,9 +206,11 @@ def __getSuitTrack(suit, tContact, tDodge, hp, hpbonus, kbbonus, anim, died, lef if kbbonus > 0: bonusTrack.append(Wait(0.75)) bonusTrack.append(Func(suit.showHpText, -kbbonus, 2, openEnded=0, attackTrack=SQUIRT_TRACK)) + bonusTrack.append(Func(suit.updateHealthBar, kbbonus)) if hpbonus > 0: bonusTrack.append(Wait(0.75)) bonusTrack.append(Func(suit.showHpText, -hpbonus, 1, openEnded=0, attackTrack=SQUIRT_TRACK)) + bonusTrack.append(Func(suit.updateHealthBar, hpbonus)) if died != 0: suitTrack.append(MovieUtil.createSuitDeathTrack(suit, toon, battle)) else: diff --git a/toontown/battle/MovieThrow.py b/toontown/battle/MovieThrow.py index a80684ae..be458bbb 100644 --- a/toontown/battle/MovieThrow.py +++ b/toontown/battle/MovieThrow.py @@ -367,9 +367,11 @@ def __throwPie(throw, delay, hitCount): if kbbonus > 0: bonusTrack.append(Wait(0.75)) bonusTrack.append(Func(suit.showHpText, -kbbonus, 2, openEnded=0, attackTrack=THROW_TRACK)) + bonusTrack.append(Func(suit.updateHealthBar, kbbonus)) if hpbonus > 0: bonusTrack.append(Wait(0.75)) bonusTrack.append(Func(suit.showHpText, -hpbonus, 1, openEnded=0, attackTrack=THROW_TRACK)) + bonusTrack.append(Func(suit.updateHealthBar, hpbonus)) if revived != 0: suitResponseTrack.append(MovieUtil.createSuitReviveTrack(suit, toon, battle)) elif died != 0: @@ -563,9 +565,11 @@ def __throwGroupPie(throw, delay, groupHitDict): if kbbonus > 0: bonusTrack.append(Wait(0.75)) bonusTrack.append(Func(suit.showHpText, -kbbonus, 2, openEnded=0, attackTrack=THROW_TRACK)) + bonusTrack.append(Func(suit.updateHealthBar, kbbonus)) if hpbonus > 0: bonusTrack.append(Wait(0.75)) bonusTrack.append(Func(suit.showHpText, -hpbonus, 1, openEnded=0, attackTrack=THROW_TRACK)) + bonusTrack.append(Func(suit.updateHealthBar, hpbonus)) if revived != 0: singleSuitResponseTrack.append(MovieUtil.createSuitReviveTrack(suit, toon, battle)) elif died != 0: diff --git a/toontown/building/PetshopBuildingAI.py b/toontown/building/PetshopBuildingAI.py index 6c1ca6cb..d0216bf3 100644 --- a/toontown/building/PetshopBuildingAI.py +++ b/toontown/building/PetshopBuildingAI.py @@ -1,14 +1,17 @@ +from pandac.PandaModules import * +from direct.directnotify import DirectNotifyGlobal import DistributedDoorAI import DistributedPetshopInteriorAI +import FADoorCodes import DoorTypes -from pandac.PandaModules import * -from toontown.hood import ZoneUtil -# from toontown.pets import DistributedPetAI, PetTraits, PetUtil from toontown.toon import NPCToons from toontown.toonbase import ToontownGlobals - +from toontown.quest import Quests +from toontown.hood import ZoneUtil class PetshopBuildingAI: + notify = DirectNotifyGlobal.directNotify.newCategory('PetshopBuildingAI') + def __init__(self, air, exteriorZone, interiorZone, blockNumber): self.air = air self.exteriorZone = exteriorZone @@ -33,6 +36,8 @@ class PetshopBuildingAI: self.npcs = NPCToons.createNpcsInZone(self.air, self.interiorZone) + seeds = self.air.petMgr.getAvailablePets(1, len(self.npcs)) + door = DistributedDoorAI.DistributedDoorAI( self.air, blockNumber, DoorTypes.EXT_STANDARD) insideDoor = DistributedDoorAI.DistributedDoorAI( @@ -47,13 +52,4 @@ class PetshopBuildingAI: self.insideDoor = insideDoor def createPet(self, ownerId, seed): - zoneId = self.interiorZone - safeZoneId = ZoneUtil.getCanonicalSafeZoneId(zoneId) - (name, dna, traitSeed) = PetUtil.getPetInfoFromSeed(seed, safeZoneId) - pet = DistributedPetAI.DistributedPetAI(self.air, dna=dna) - pet.setOwnerId(ownerId) - pet.setPetName(name) - pet.traits = PetTraits.PetTraits(traitSeed=traitSeed, safeZoneId=safeZoneId) - pet.generateWithRequired(zoneId) - pet.setPos(0, 0, 0) - pet.b_setParent(ToontownGlobals.SPRender) + return \ No newline at end of file diff --git a/toontown/catalog/CatalogPetTrickItem.py b/toontown/catalog/CatalogPetTrickItem.py index a9ae44bf..ed6f8b62 100644 --- a/toontown/catalog/CatalogPetTrickItem.py +++ b/toontown/catalog/CatalogPetTrickItem.py @@ -44,7 +44,7 @@ class CatalogPetTrickItem(CatalogItem.CatalogItem): def getPicture(self, avatar): from toontown.pets import PetDNA, Pet pet = Pet.Pet(forGui=1) - dna = avatar.petDNA + dna = avatar.getPetDNA() if dna == None: dna = PetDNA.getRandomPetDNA() pet.setDNA(dna) diff --git a/toontown/distributed/ToontownClientRepository.py b/toontown/distributed/ToontownClientRepository.py index 074e8738..0f90876b 100644 --- a/toontown/distributed/ToontownClientRepository.py +++ b/toontown/distributed/ToontownClientRepository.py @@ -349,7 +349,7 @@ class ToontownClientRepository(OTPClientRepository.OTPClientRepository): pad.avatar = avatar pad.delayDelete = DelayDelete.DelayDelete(avatar, 'getAvatarDetails') self.__queryAvatarMap[avatar.doId] = pad - self.__sendGetAvatarDetails(avatar.doId) + self.__sendGetAvatarDetails(avatar.doId, pet=(args[0].endswith("Pet"))) def cancelAvatarDetailsRequest(self, avatar): avId = avatar.doId @@ -357,8 +357,11 @@ class ToontownClientRepository(OTPClientRepository.OTPClientRepository): pad = self.__queryAvatarMap.pop(avId) pad.delayDelete.destroy() - def __sendGetAvatarDetails(self, avId): - self.ttuFriendsManager.d_getAvatarDetails(avId) + def __sendGetAvatarDetails(self, avId, pet=0): + if pet: + self.ttuFriendsManager.d_getPetDetails(avId) + else: + self.ttuFriendsManager.d_getAvatarDetails(avId) def n_handleGetAvatarDetailsResp(self, avId, fields): self.notify.info('Query reponse for avId %d' % avId) @@ -759,12 +762,13 @@ class ToontownClientRepository(OTPClientRepository.OTPClientRepository): def addPetToFriendsMap(self, callback = None): doId = base.localAvatar.getPetId() - if doId not in self.friendsMap: + if not doId or doId in self.friendsMap: if callback: callback() return def petDetailsCallback(petAvatar): + petAvatar.announceGenerate() handle = PetHandle.PetHandle(petAvatar) self.friendsMap[doId] = handle petAvatar.disable() diff --git a/toontown/estate/EstateManagerAI.py b/toontown/estate/EstateManagerAI.py index da5a4a01..07a17f17 100644 --- a/toontown/estate/EstateManagerAI.py +++ b/toontown/estate/EstateManagerAI.py @@ -7,6 +7,7 @@ import HouseGlobals import functools class LoadHouseFSM(FSM): + notify = DirectNotifyGlobal.directNotify.newCategory('LoadHouseFSM') def __init__(self, mgr, estate, houseIndex, toon, callback): FSM.__init__(self, 'LoadHouseFSM') self.mgr = mgr @@ -99,7 +100,36 @@ class LoadHouseFSM(FSM): def enterOff(self): self.done = True self.callback(self.house) + +class LoadPetFSM(FSM): + def __init__(self, mgr, estate, toon, callback): + FSM.__init__(self, 'LoadPetFSM') + self.mgr = mgr + self.estate = estate + self.toon = toon + self.callback = callback + self.pet = None + self.done = False + + def start(self): + self.petId = self.toon['setPetId'][0] + if not self.petId in self.mgr.air.doId2do: + self.mgr.air.sendActivate(self.petId, self.mgr.air.districtId, self.estate.zoneId) + self.acceptOnce('generate-%d' % self.petId, self.__generated) + + else: + self.__generated(self.mgr.air.doId2do[self.petId]) + + def __generated(self, pet): + self.pet = pet + self.estate.pets.append(pet) + self.demand('Off') + + def enterOff(self): + self.done = True + self.callback(self.pet) + class LoadEstateFSM(FSM): def __init__(self, mgr, callback): FSM.__init__(self, 'LoadEstateFSM') @@ -201,6 +231,7 @@ class LoadEstateFSM(FSM): def __gotEstate(self, estate): self.estate = estate + self.estate.pets = [] self.estate.toons = self.toonIds self.estate.updateToons() @@ -229,7 +260,29 @@ class LoadEstateFSM(FSM): # A houseFSM just finished! Let's see if all of them are done: if all(houseFSM.done for houseFSM in self.houseFSMs): + self.demand('LoadPets') + + def enterLoadPets(self): + self.petFSMs = [] + for houseIndex in range(6): + toon = self.toons[houseIndex] + if toon and toon['setPetId'][0] != 0: + fsm = LoadPetFSM(self.mgr, self.estate, toon, self.__petDone) + self.petFSMs.append(fsm) + fsm.start() + else: + continue + + if not self.petFSMs: self.demand('Finished') + + def __petDone(self, pet): + if self.state != 'LoadPets': + pet.requestDelete() + return + + if all(petFSM.done for petFSM in self.petFSMs): + self.demand('Finished') def enterFinished(self): self.callback(True) @@ -403,5 +456,7 @@ class EstateManagerAI(DistributedObjectAI): pass def _lookupEstate(self, toon): - print(self.toon2estate) return self.toon2estate.get(toon) + + def getOwnerFromZone(self, avId): + return False \ No newline at end of file diff --git a/toontown/friends/TTUFriendsManager.py b/toontown/friends/TTUFriendsManager.py index ff8c6614..87237c36 100644 --- a/toontown/friends/TTUFriendsManager.py +++ b/toontown/friends/TTUFriendsManager.py @@ -40,6 +40,26 @@ class TTUFriendsManager(DistributedObjectGlobal): ['setDNAString' , dnaString], ] base.cr.n_handleGetAvatarDetailsResp(avId, fields=fields) + + def d_getPetDetails(self, avId): + self.sendUpdate('getPetDetails', [avId]) + + def petDetails(self, avId, ownerId, petName, traitSeed, sz, traits, moods, dna, lastSeen): + fields = list(zip(("setHead", "setEars", "setNose", "setTail", "setBodyTexture", "setColor", "setColorScale", "setEyeColor", "setGender"), dna)) + fields.extend(zip(("setBoredom", "setRestlessness", "setPlayfulness", "setLoneliness", + "setSadness", "setAffection", "setHunger", "setConfusion", "setExcitement", + "setFatigue", "setAnger", "setSurprise"), moods)) + fields.extend(zip(("setForgetfulness", "setBoredomThreshold", "setRestlessnessThreshold", + "setPlayfulnessThreshold", "setLonelinessThreshold", "setSadnessThreshold", + "setFatigueThreshold", "setHungerThreshold", "setConfusionThreshold", + "setExcitementThreshold", "setAngerThreshold", "setSurpriseThreshold", + "setAffectionThreshold"), traits)) + fields.append(("setOwnerId", ownerId)) + fields.append(("setPetName", petName)) + fields.append(("setTraitSeed", traitSeed)) + fields.append(("setSafeZone", sz)) + fields.append(("setLastSeenTimestamp", lastSeen)) + base.cr.n_handleGetAvatarDetailsResp(avId, fields=fields) def d_teleportQuery(self, toId): self.sendUpdate('routeTeleportQuery', [toId]) diff --git a/toontown/friends/TTUFriendsManagerUD.py b/toontown/friends/TTUFriendsManagerUD.py index 776fedb7..4bc68240 100644 --- a/toontown/friends/TTUFriendsManagerUD.py +++ b/toontown/friends/TTUFriendsManagerUD.py @@ -257,6 +257,26 @@ class TTUFriendsManagerUD(DistributedObjectGlobalUD): # Inventory, trackAccess, trophies, Hp, maxHp, defaultshard, lastHood, dnastring self.sendUpdateToAvatarId(senderId, 'friendDetails', [avId, inventory, trackAccess, trophies, hp, maxHp, defaultShard, lastHood, dnaString, experience, trackBonusLevel]) self.air.dbInterface.queryObject(self.air.dbId, avId, handleToon) + + def getPetDetails(self, avId): + senderId = self.air.getAvatarIdFromSender() + def handlePet(dclass, fields): + if dclass != self.air.dclassesByName['DistributedPetUD']: + return + dna = [fields.get(x, [0])[0] for x in ("setHead", "setEars", "setNose", "setTail", "setBodyTexture", "setColor", + "setColorScale", "setEyeColor", "setGender")] + moods = [fields.get(x, [0])[0] for x in ("setBoredom", "setRestlessness", "setPlayfulness", "setLoneliness", + "setSadness", "setAffection", "setHunger", "setConfusion", "setExcitement", + "setFatigue", "setAnger", "setSurprise")] + traits = [fields.get(x, [0])[0] for x in ("setForgetfulness", "setBoredomThreshold", "setRestlessnessThreshold", + "setPlayfulnessThreshold", "setLonelinessThreshold", "setSadnessThreshold", + "setFatigueThreshold", "setHungerThreshold", "setConfusionThreshold", + "setExcitementThreshold", "setAngerThreshold", "setSurpriseThreshold", + "setAffectionThreshold")] + self.sendUpdateToAvatarId(senderId, 'petDetails', [avId, fields.get("setOwnerId", [0])[0], fields.get("setPetName", ["???"])[0], + fields.get("setTraitSeed", [0])[0], fields.get("setSafeZone", [0])[0], + traits, moods, dna, fields.get("setLastSeenTimestamp", [0])[0]]) + self.air.dbInterface.queryObject(self.air.dbId, avId, handlePet) # -- Toon Online/Offline -- def toonOnline(self, doId, friendsList): diff --git a/toontown/hood/Place.py b/toontown/hood/Place.py index 86d10b5c..9c837764 100644 --- a/toontown/hood/Place.py +++ b/toontown/hood/Place.py @@ -720,10 +720,17 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): base.localAvatar.b_teleportGreeting(avId) else: friend = base.cr.identifyAvatar(avId) - if friend != None: + if friend == None: teleportDebug(requestStatus, 'friend not here, giving up') base.localAvatar.setSystemMessage(avId, OTPLocalizer.WhisperTargetLeftVisit % (friend.getName(),)) friend.d_teleportGiveup(base.localAvatar.doId) + else: + def doTeleport(task): + avatar = base.cr.doId2do[friend.getDoId()] + base.localAvatar.gotoNode(avatar) + base.localAvatar.b_teleportGreeting(friend.getDoId()) + return task.done + self.acceptOnce('generate-%d' % friend.getDoId(), lambda x: taskMgr.doMethodLater(1, doTeleport, uniqueName('doTeleport'))) base.transitions.irisIn() self.nextState = requestStatus.get('nextState', 'walk') base.localAvatar.attachCamera() @@ -925,4 +932,4 @@ class Place(StateData.StateData, FriendsListManager.FriendsListManager): def handleQuietZoneDone(self): how = base.cr.handlerArgs['how'] - self.fsm.request(how, [base.cr.handlerArgs]) + self.fsm.request(how, [base.cr.handlerArgs]) \ No newline at end of file diff --git a/toontown/pets/DistributedPetAI.py b/toontown/pets/DistributedPetAI.py index dc507627..8a848a70 100644 --- a/toontown/pets/DistributedPetAI.py +++ b/toontown/pets/DistributedPetAI.py @@ -9,9 +9,7 @@ from direct.fsm import ClassicFSM, State from direct.interval.IntervalGlobal import * from toontown.toonbase import ToontownGlobals from direct.task import Task -from otp.movement import Mover -from toontown.pets import PetChase, PetFlee, PetWander, PetLeash -from toontown.pets import PetCollider, PetSphere, PetLookerAI +from toontown.pets import PetLookerAI from toontown.pets import PetConstants, PetDNA, PetTraits from toontown.pets import PetObserve, PetBrain, PetMood from toontown.pets import PetActionFSM, PetBase, PetGoal, PetTricks @@ -24,6 +22,8 @@ import string import copy from direct.showbase.PythonUtil import StackTrace +from PetMoverAI import PetMoverAI + class DistributedPetAI(DistributedSmoothNodeAI.DistributedSmoothNodeAI, PetLookerAI.PetLookerAI, PetBase.PetBase): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedPetAI') movieTimeSwitch = {PetConstants.PET_MOVIE_FEED: PetConstants.FEED_TIME, @@ -126,18 +126,16 @@ class DistributedPetAI(DistributedSmoothNodeAI.DistributedSmoothNodeAI, PetLooke def handleLogicalZoneChange(self, newZoneId, oldZoneId): DistributedSmoothNodeAI.DistributedSmoothNodeAI.handleLogicalZoneChange(self, newZoneId, oldZoneId) self.announceZoneChange(newZoneId, oldZoneId) - self.destroySphereImpulse() - self.createSphereImpulse() def announceZoneChange(self, newZoneId, oldZoneId): DistributedPetAI.notify.debug('%s.announceZoneChange: %s->%s' % (self.doId, oldZoneId, newZoneId)) broadcastZones = list2dict([newZoneId, oldZoneId]) - self.estateOwnerId = simbase.air.estateMgr.getOwnerFromZone(newZoneId) + self.estateOwnerId = simbase.air.estateManager.getOwnerFromZone(newZoneId) if self.estateOwnerId: if __dev__: pass self.inEstate = 1 - self.estateZones = simbase.air.estateMgr.getEstateZones(self.estateOwnerId) + self.estateZones = simbase.air.estateManager.getEstateZones(self.estateOwnerId) else: self.inEstate = 0 self.estateZones = [] @@ -475,8 +473,8 @@ class DistributedPetAI(DistributedSmoothNodeAI.DistributedSmoothNodeAI, PetLooke else: self.setTrickAptitudes(aptitudes, local=1) - def generate(self): - DistributedSmoothNodeAI.DistributedSmoothNodeAI.generate(self) + def announceGenerate(self): + DistributedSmoothNodeAI.DistributedSmoothNodeAI.announceGenerate(self) self._hasCleanedUp = False self.setHasRequestedDelete(False) self.b_setParent(ToontownGlobals.SPHidden) @@ -517,9 +515,7 @@ class DistributedPetAI(DistributedSmoothNodeAI.DistributedSmoothNodeAI, PetLooke self.requiredMoodComponents = {} self.brain = PetBrain.PetBrain(self) - self.mover = Mover.Mover(self) - self.lockMover = Mover.Mover(self) - self.createImpulses() + self.mover = PetMoverAI(self) self.enterPetLook() self.actionFSM = PetActionFSM.PetActionFSM(self) self.teleportIn() @@ -591,11 +587,8 @@ class DistributedPetAI(DistributedSmoothNodeAI.DistributedSmoothNodeAI, PetLooke self.actionFSM.destroy() del self.actionFSM self.exitPetLook() - self.destroyImpulses() self.mover.destroy() del self.mover - self.lockMover.destroy() - del self.lockMover self.stopPosHprBroadcast() if hasattr(self, 'mood'): self.mood.destroy() @@ -645,37 +638,6 @@ class DistributedPetAI(DistributedSmoothNodeAI.DistributedSmoothNodeAI, PetLooke self.ignoreAll() return - def createImpulses(self): - self.createSphereImpulse() - self.chaseImpulse = PetChase() - self.fleeImpulse = PetFlee() - self.wanderImpulse = PetWander.PetWander() - self.lockChaseImpulse = PetChase() - - def destroyImpulses(self): - self.wanderImpulse.destroy() - del self.chaseImpulse - del self.fleeImpulse - del self.wanderImpulse - self.destroySphereImpulse() - del self.lockChaseImpulse - - def createSphereImpulse(self): - petRadius = 1.0 - collTrav = self.getCollTrav() - if collTrav is None: - DistributedPetAI.notify.warning('no collision traverser for zone %s' % self.zoneId) - else: - self.sphereImpulse = PetSphere.PetSphere(petRadius, collTrav) - self.mover.addImpulse('sphere', self.sphereImpulse) - return - - def destroySphereImpulse(self): - self.mover.removeImpulse('sphere') - if hasattr(self, 'sphereImpulse'): - self.sphereImpulse.destroy() - del self.sphereImpulse - def getMoveTaskName(self): return 'petMove-%s' % self.doId @@ -684,15 +646,10 @@ class DistributedPetAI(DistributedSmoothNodeAI.DistributedSmoothNodeAI, PetLooke def move(self, task = None): if self.isEmpty(): - try: - self.air.writeServerEvent('Late Pet Move Call', self.doId, ' ') - except: - pass - + self.air.writeServerEvent('Late Pet Move Call', self.doId, ' ') taskMgr.remove(task.name) return Task.done - if not self.isLockMoverEnabled(): - self.mover.move() + numNearby = len(self.brain.nearbyAvs) - 1 minNearby = 5 if numNearby > minNearby: @@ -784,6 +741,7 @@ class DistributedPetAI(DistributedSmoothNodeAI.DistributedSmoothNodeAI, PetLooke def lockPet(self): DistributedPetAI.notify.debug('%s: lockPet' % self.doId) if not self.lockedDown: + self.mover.lock() self.stopPosHprBroadcast() self.lockedDown += 1 @@ -840,18 +798,6 @@ class DistributedPetAI(DistributedSmoothNodeAI.DistributedSmoothNodeAI, PetLooke def unstickEnterOn(self): self._collisionTimestamps = [] - self.accept(self.mover.getCollisionEventName(), self._handleCollided) - - def _handleCollided(self, collEntry): - now = globalClock.getFrameTime() - self._collisionTimestamps.append(now) - while now - self._collisionTimestamps[0] > PetConstants.UnstickSampleWindow: - del self._collisionTimestamps[0:1] - - if len(self._collisionTimestamps) > PetConstants.UnstickCollisionThreshold: - self._collisionTimestamps = [] - DistributedPetAI.notify.debug('unsticking pet %s' % self.doId) - self.brain._unstick() def unstickExitOn(self): pass @@ -987,14 +933,10 @@ class DistributedPetAI(DistributedSmoothNodeAI.DistributedSmoothNodeAI, PetLooke def startLockPetMove(self, avId): self.enableLockMover() - self.lockChaseImpulse.setTarget(self.air.doId2do.get(avId)) - self.lockMover.addImpulse('LockTarget', self.lockChaseImpulse) - self.lockMover.setFwdSpeed(self.mover.getFwdSpeed()) - self.lockMover.setRotSpeed(self.mover.getRotSpeed()) dist_Callable = self.movieDistSwitch.get(self.movieMode) dist = dist_Callable(self.air.doId2do.get(avId).getStyle().getLegSize()) - self.lockChaseImpulse.setMinDist(dist) self.distList = [0, 0, 0] + self.mover.walkToAvatar(self.air.doId2do[avId], callback=lambda: self.endLockPetMove(avId)) self.__lockPetMoveTask(avId) def getAverageDist(self): @@ -1005,33 +947,12 @@ class DistributedPetAI(DistributedSmoothNodeAI.DistributedSmoothNodeAI, PetLooke return sum / 3.0 def __lockPetMoveTask(self, avId): - if not hasattr(self, 'air') or avId not in self.air.doId2do: - self.notify.warning('avId: %s gone or self deleted!' % avId) - return Task.done - av = self.air.doId2do.get(avId) - dist = av.getDistance(self) - self.distList.append(dist) - if len(self.distList) > 3: - self.distList.pop(0) - if self.movieMode in self.movieDistSwitch: - dist_Callable = self.movieDistSwitch.get(self.movieMode) - movieDist = dist_Callable(av.getStyle().getLegSize()) - else: - self.notify.warning('movieMode: %s not in movieSwitchDist map!' % self.movieMode) - return Task.done - avgDist = self.getAverageDist() - if dist - movieDist > 0.25 and abs(avgDist - dist) > 0.1: - self.lockMover.move() - taskMgr.doMethodLater(simbase.petMovePeriod, self.__lockPetMoveTask, self.getLockMoveTaskName(), [avId]) - else: - self.endLockPetMove(avId) return Task.done def endLockPetMove(self, avId): del self.distList taskMgr.remove(self.getLockMoveTaskName()) self.lockPet() - self.lockMover.removeImpulse('LockTarget') self.__petMovieStart(avId) def enableLockMover(self): @@ -1060,7 +981,7 @@ class DistributedPetAI(DistributedSmoothNodeAI.DistributedSmoothNodeAI, PetLooke if self.mood.isComponentActive('fatigue'): cutoff *= 0.5 cutoff *= PetTricks.TrickAccuracies[trickId] - DistributedPetAI.notify.debug('_willDoTrick: %s / %s' % (randVal, cutoff)) + DistributedPetAI.notify.info('_willDoTrick: %s / %s' % (randVal, cutoff)) # .debug return randVal < cutoff def _handleDidTrick(self, trickId): @@ -1081,13 +1002,9 @@ class DistributedPetAI(DistributedSmoothNodeAI.DistributedSmoothNodeAI, PetLooke if self.leashMode: self.leashMode = 0 self.leashAvId = None - self.brain.goalMgr.removeGoal(self.leashGoal) - del self.leashGoal response = 'leash OFF' else: self.leashMode = 1 self.leashAvId = avId - self.leashGoal = PetGoal.ChaseAvatarLeash(avId) - self.brain.goalMgr.addGoal(self.leashGoal) response = 'leash ON' return response diff --git a/toontown/pets/DistributedPetProxyAI.py b/toontown/pets/DistributedPetProxyAI.py index 1b9f91b9..ae83e489 100644 --- a/toontown/pets/DistributedPetProxyAI.py +++ b/toontown/pets/DistributedPetProxyAI.py @@ -356,7 +356,6 @@ class DistributedPetProxyAI(DistributedObjectAI.DistributedObjectAI): def generate(self): DistributedObjectAI.DistributedObjectAI.generate(self) self.traits = PetTraits.PetTraits(self.traitSeed, self.safeZone) - print self.traits.traits for i in xrange(len(self.traitList)): value = self.traitList[i] if value == 0.0: diff --git a/toontown/pets/DistributedPetUD.py b/toontown/pets/DistributedPetUD.py new file mode 100644 index 00000000..7dbf0d2b --- /dev/null +++ b/toontown/pets/DistributedPetUD.py @@ -0,0 +1,55 @@ +from direct.directnotify import DirectNotifyGlobal +from direct.distributed.DistributedObjectUD import DistributedObjectUD + +class DistributedPetUD(DistributedObjectUD): + notify = DirectNotifyGlobal.directNotify.newCategory("DistributedPetUD") + + def setDNA(self, dna): + pass + + def setOwnerId(self, ownerId): + pass + + def setTraitSeed(self, traitSeed): + pass + + def setSafeZone(self, safeZone): + pass + + def setHead(self, head): + pass + + def setEars(self, ears): + pass + + def setNose(self, nose): + pass + + def setTail(self, tail): + pass + + def setBodyTexture(self, bodyTexture): + pass + + def setColor(self, color): + pass + + def setColorScale(self, colorScale): + pass + + def setEyeColor(self, eyeColor): + pass + + def setGender(self, gender): + pass + + def setLastSeenTimestamp(self, timestamp): + pass + + def setTrickAptitudes(self, aptitudes): + pass + + def setLastSeenTimestamp(self, timestamp): + pass + + \ No newline at end of file diff --git a/toontown/pets/Pet.py b/toontown/pets/Pet.py index e3a73496..d37d14f2 100644 --- a/toontown/pets/Pet.py +++ b/toontown/pets/Pet.py @@ -1,24 +1,20 @@ -from direct.actor import Actor +from pandac.PandaModules import * from direct.directnotify import DirectNotifyGlobal -from direct.distributed.ClockDelta import globalClockDelta +from direct.interval.IntervalGlobal import * from direct.fsm.ClassicFSM import * from direct.fsm.State import * -from direct.interval.IntervalGlobal import * -from direct.showbase import PythonUtil -from direct.task import Task -from pandac.PandaModules import * -import random -import types - -from PetDNA import HeadParts, EarParts, NoseParts, TailParts, BodyTypes, BodyTextures, AllPetColors, getColors, ColorScales, PetEyeColors, EarTextures, TailTextures, getFootTexture, getEarTexture, GiraffeTail, LeopardTail, PetGenders +from direct.distributed.ClockDelta import globalClockDelta from otp.avatar import Avatar -from toontown.chat.ChatGlobals import * -from toontown.nametag import NametagGlobals +from direct.actor import Actor +from direct.task import Task from toontown.pets import PetDNA +from PetDNA import HeadParts, EarParts, NoseParts, TailParts, BodyTypes, BodyTextures, AllPetColors, getColors, ColorScales, PetEyeColors, EarTextures, TailTextures, getFootTexture, getEarTexture, GiraffeTail, LeopardTail, PetGenders +from toontown.toonbase.BitmaskGlobals import PieBitmask from toontown.toonbase import TTLocalizer from toontown.toonbase import ToontownGlobals - - +from direct.showbase import PythonUtil +import random +import types Component2IconDict = {'boredom': 'Bored', 'restlessness': None, 'playfulness': 'Play', @@ -31,6 +27,10 @@ Component2IconDict = {'boredom': 'Bored', 'anger': 'Angry', 'surprise': 'Surprised', 'affection': 'Love'} + +from toontown.nametag import * +from toontown.nametag.NametagGlobals import * +from toontown.nametag.NametagGroup import * class Pet(Avatar.Avatar): notify = DirectNotifyGlobal.directNotify.newCategory('Pet') @@ -268,7 +268,7 @@ class Pet(Avatar.Avatar): def initializeBodyCollisions(self, collIdStr): Avatar.Avatar.initializeBodyCollisions(self, collIdStr) if not self.ghostMode: - self.collNode.setCollideMask(self.collNode.getIntoCollideMask() | ToontownGlobals.PieBitmask) + self.collNode.setCollideMask(self.collNode.getIntoCollideMask() | PieBitmask) def amplifyColor(self, color, scale): color = color * scale @@ -284,7 +284,7 @@ class Pet(Avatar.Avatar): self.moodIcons.setScale(2.0) self.moodIcons.setZ(3.65) moods = moodIcons.findAllMatches('**/+GeomNode') - for moodNum in xrange(0, moods.getNumPaths()): + for moodNum in range(0, moods.getNumPaths()): mood = moods.getPath(moodNum) mood.reparentTo(self.moodIcons) mood.setBillboardPointEye() @@ -327,9 +327,9 @@ class Pet(Avatar.Avatar): if self.moodModel: self.moodModel.hide() if base.config.GetBool('want-speech-bubble', 1): - self.nametag.setChatText(random.choice(TTLocalizer.SpokenMoods[mood])) + self.nametag.setChat(random.choice(TTLocalizer.SpokenMoods[mood]), CFSpeech) else: - self.nametag.setChatText(random.choice(TTLocalizer.SpokenMoods[mood])) + self.nametag.setChat(random.choice(TTLocalizer.SpokenMoods[mood]), CFThought) def getGenderString(self): if self.style: @@ -653,7 +653,7 @@ def gridPets(): offsetX = 0 offsetY = 0 startPos = base.localAvatar.getPos() - for body in xrange(0, len(BodyTypes)): + for body in range(0, len(BodyTypes)): colors = getColors(body) for color in colors: p = Pet() diff --git a/toontown/pets/PetActionFSM.py b/toontown/pets/PetActionFSM.py index 2f11cf0b..6566e70f 100644 --- a/toontown/pets/PetActionFSM.py +++ b/toontown/pets/PetActionFSM.py @@ -18,70 +18,30 @@ class PetActionFSM(FSM.FSM): def destroy(self): self.cleanup() - def enterNeutral(self): - PetActionFSM.notify.debug('enterNeutral') - - def exitNeutral(self): - pass - def enterChase(self, target): PetActionFSM.notify.debug('enterChase: %s' % target) - self.pet.chaseImpulse.setTarget(target) - self.pet.mover.addImpulse('chase', self.pet.chaseImpulse) self.pet.unstickFSM.request('on') def exitChase(self): self.pet.unstickFSM.request('off') - self.pet.mover.removeImpulse('chase') def enterFlee(self, chaser): PetActionFSM.notify.debug('enterFlee: %s' % chaser) - self.pet.fleeImpulse.setChaser(chaser) - self.pet.mover.addImpulse('flee', self.pet.fleeImpulse) self.pet.unstickFSM.request('on') def exitFlee(self): self.pet.unstickFSM.request('off') - self.pet.mover.removeImpulse('flee') - - def enterWander(self): - PetActionFSM.notify.debug('enterWander') - self.pet.mover.addImpulse('wander', self.pet.wanderImpulse) - - def exitWander(self): - self.pet.mover.removeImpulse('wander') - - def enterUnstick(self): - PetActionFSM.notify.debug('enterUnstick') - self.pet.mover.addImpulse('unstick', self.pet.wanderImpulse) - - def exitUnstick(self): - self.pet.mover.removeImpulse('unstick') def enterInspectSpot(self, spot): PetActionFSM.notify.debug('enterInspectSpot') - self.pet.chaseImpulse.setTarget(spot) - self.pet.mover.addImpulse('inspect', self.pet.chaseImpulse) self.pet.unstickFSM.request('on') def exitInspectSpot(self): self.pet.unstickFSM.request('off') - self.pet.mover.removeImpulse('inspect') - - def enterStay(self, avatar): - PetActionFSM.notify.debug('enterStay') - - def exitStay(self): - pass def enterHeal(self, avatar): PetActionFSM.notify.debug('enterHeal') avatar.toonUp(3) - self.pet.chaseImpulse.setTarget(avatar) - self.pet.mover.addImpulse('chase', self.pet.chaseImpulse) - - def exitHeal(self): - self.pet.mover.removeImpulse('chase') def enterTrick(self, avatar, trickId): PetActionFSM.notify.debug('enterTrick') @@ -95,11 +55,9 @@ class PetActionFSM(FSM.FSM): aptitude = self.pet.getTrickAptitude(trickId) healAmt = int(lerp(healRange[0], healRange[1], aptitude)) if healAmt: - for avId in self.pet.brain.getAvIdsLookingAtUs(): - av = self.pet.air.doId2do.get(avId) - if av: - if isinstance(av, DistributedToonAI.DistributedToonAI): - av.toonUp(healAmt) + for avId, av in self.pet._getFullNearbyToonDict().items(): + if isinstance(av, DistributedToonAI.DistributedToonAI): + av.toonUp(healAmt) self.pet._handleDidTrick(trickId) if not self.pet.isLockedDown(): @@ -124,9 +82,3 @@ class PetActionFSM(FSM.FSM): if self.pet.isLockedDown(): self.pet.unlockPet() del self.trickDoneEvent - - def enterMovie(self): - PetActionFSM.notify.debug('enterMovie') - - def exitMovie(self): - pass diff --git a/toontown/pets/PetBrain.py b/toontown/pets/PetBrain.py index 33044296..581f9d6e 100644 --- a/toontown/pets/PetBrain.py +++ b/toontown/pets/PetBrain.py @@ -2,11 +2,10 @@ from pandac.PandaModules import * from direct.showbase.PythonUtil import weightedChoice, randFloat, Functor from direct.showbase.PythonUtil import list2dict from direct.showbase import DirectObject -from direct.distributed import DistributedObjectAI +from direct.distributed import DistributedObject, DistributedObjectAI from direct.directnotify import DirectNotifyGlobal from direct.task import Task from direct.fsm import FSM -from toontown.toon import DistributedToonAI from toontown.pets import PetConstants, PetObserve, PetGoal, PetGoalMgr from toontown.pets import PetTricks, PetLookerAI import random, types @@ -387,13 +386,13 @@ class PetBrain(DirectObject.DirectObject): def _handleComeHere(avId, self = self): avatar = simbase.air.doId2do.get(avId) if avatar: - self._chase(avatar) + self.pet.mover.walkToAvatar(avatar) avatar.setHatePets(0) def _handleFollowMe(avId, self = self): avatar = simbase.air.doId2do.get(avId) if avatar: - self._chase(avatar) + self.pet.mover.walkToAvatar(avatar) avatar.setHatePets(0) def _handleStay(avId, self = self): @@ -421,15 +420,14 @@ class PetBrain(DirectObject.DirectObject): return def _handleDoTrick(trickId, avId, self = self): + looked = self.lookedAtBy(avId) or config.GetBool('pet-brain-ignore-looked-tricks', True) avatar = simbase.air.doId2do.get(avId) if avatar: - if self.lookedAtBy(avatar.doId): - if not self.goalMgr.hasTrickGoal(): - if not self.pet._willDoTrick(trickId): - self.pet.trickFailLogger.addEvent(trickId) - trickId = PetTricks.Tricks.BALK - trickGoal = PetGoal.DoTrick(avatar, trickId) - self.goalMgr.addGoal(trickGoal) + if looked: + if not self.pet._willDoTrick(trickId): + self.pet.trickFailLogger.addEvent(trickId) + trickId = PetTricks.Tricks.BALK + self._doTrick(trickId, avatar) phrase = observe.getPetPhrase() avId = observe.getAvId() diff --git a/toontown/pets/PetChase.py b/toontown/pets/PetChase.py index 599770aa..a178aaf7 100644 --- a/toontown/pets/PetChase.py +++ b/toontown/pets/PetChase.py @@ -69,3 +69,6 @@ class PetChase(Impulse.Impulse): if vH: self.rotVel.setX(vH) self.mover.addRotShove(self.rotVel) + + def setMinDist(self, minDist): + self.minDist = minDist diff --git a/toontown/pets/PetDCImportsAI.py b/toontown/pets/PetDCImportsAI.py index fb2b5c86..1c92bbeb 100644 --- a/toontown/pets/PetDCImportsAI.py +++ b/toontown/pets/PetDCImportsAI.py @@ -1,2 +1,3 @@ if hasattr(simbase, 'wantPets') and simbase.wantPets: import DistributedPetAI + import DistributedPetUD diff --git a/toontown/pets/PetDNA.py b/toontown/pets/PetDNA.py index f7b2d708..3395464f 100644 --- a/toontown/pets/PetDNA.py +++ b/toontown/pets/PetDNA.py @@ -240,7 +240,7 @@ def getBodyRarity(bodyIndex): for zoneId in PetRarities['body']: for body in PetRarities['body'][zoneId]: totalWeight += PetRarities['body'][zoneId][body] - if body in weight: + if weight.has_key(body): weight[body] += PetRarities['body'][zoneId][body] else: weight[body] = PetRarities['body'][zoneId][body] diff --git a/toontown/pets/PetHandle.py b/toontown/pets/PetHandle.py index 1eecdf1f..c377310a 100644 --- a/toontown/pets/PetHandle.py +++ b/toontown/pets/PetHandle.py @@ -59,6 +59,7 @@ class PetHandle: def updateMoodFromServer(self, callWhenDone = None): def handleGotDetails(avatar, callWhenDone = callWhenDone): + avatar.announceGenerate() self._grabMood(avatar) if callWhenDone: callWhenDone() diff --git a/toontown/pets/PetLookerAI.py b/toontown/pets/PetLookerAI.py index 6cbdd42d..b9bede67 100644 --- a/toontown/pets/PetLookerAI.py +++ b/toontown/pets/PetLookerAI.py @@ -2,7 +2,7 @@ from pandac.PandaModules import * from direct.directnotify import DirectNotifyGlobal from direct.showbase import DirectObject from otp.ai.AIZoneData import AIZoneData -from toontown.toonbase import ToontownGlobals +from toontown.toonbase.BitmaskGlobals import PetLookatPetBitmask, PetLookatNonPetBitmask from toontown.pets import PetConstants def getStartLookingAtOtherEvent(lookingAvId): @@ -83,11 +83,11 @@ class PetLookerAI: lookSphereNode.addSolid(lookSphere) lookSphereNode.setFromCollideMask(BitMask32.allOff()) if isPet: - intoCollideMask = ToontownGlobals.PetLookatPetBitmask - fromCollideMask = ToontownGlobals.PetLookatPetBitmask | ToontownGlobals.PetLookatNonPetBitmask + intoCollideMask = PetLookatPetBitmask + fromCollideMask = PetLookatPetBitmask | PetLookatNonPetBitmask else: - intoCollideMask = ToontownGlobals.PetLookatNonPetBitmask - fromCollideMask = ToontownGlobals.PetLookatPetBitmask + intoCollideMask = PetLookatNonPetBitmask + fromCollideMask = PetLookatPetBitmask lookSphereNode.setIntoCollideMask(intoCollideMask) lookSphereNode.setFromCollideMask(fromCollideMask) self.lookSphereNodePath = self.__collNode.attachNewNode(lookSphereNode) diff --git a/toontown/pets/PetManagerAI.py b/toontown/pets/PetManagerAI.py index fbdaeb6e..da991ce3 100644 --- a/toontown/pets/PetManagerAI.py +++ b/toontown/pets/PetManagerAI.py @@ -1,12 +1,86 @@ +from direct.directnotify import DirectNotifyGlobal +from direct.fsm.FSM import FSM +import PetUtil, PetDNA +from toontown.hood import ZoneUtil +from toontown.building import PetshopBuildingAI +from toontown.toonbase import ToontownGlobals, TTLocalizer import random +import cPickle, time, random, os +MINUTE = 60 +HOUR = 60 * MINUTE +DAY = 24 * HOUR +def getDayId(): + return int(time.time() // DAY) + class PetManagerAI: + NUM_DAILY_PETS = 5 + cachePath = config.GetString('air-pet-cache', 'astron/databases/air_cache/') def __init__(self, air): self.air = air + self.cacheFile = '%spets_%d.pets' % (self.cachePath, self.air.districtId) + if os.path.isfile(self.cacheFile): + with open(self.cacheFile, 'rb') as f: + data = f.read() + + self.seeds = cPickle.loads(data) + if self.seeds.get('day', -1) != getDayId() or len(self.seeds.get(ToontownGlobals.ToontownCentral, [])) != self.NUM_DAILY_PETS: + self.generateSeeds() + + else: + self.generateSeeds() + + def generateSeeds(self): + seeds = range(0, 255) + random.shuffle(seeds) + + self.seeds = {} + for hood in (ToontownGlobals.ToontownCentral, ToontownGlobals.DonaldsDock, ToontownGlobals.DaisyGardens, + ToontownGlobals.MinniesMelodyland, ToontownGlobals.TheBrrrgh, ToontownGlobals.DonaldsDreamland): + self.seeds[hood] = [seeds.pop() for _ in xrange(self.NUM_DAILY_PETS)] + + self.seeds['day'] = getDayId() + + with open(self.cacheFile, 'wb') as f: + f.write(cPickle.dumps(self.seeds)) - def getAvailablePets(self, numPets=5): - return random.sample(xrange(256), numPets) + + def getAvailablePets(self, seed, safezoneId): + if self.seeds.get('day', -1) != getDayId(): + self.generateSeeds() + + return self.seeds.get(safezoneId, [seed]) - def createNewPetFromSeed(self, avId, petSeeds, nameIndex, gender, safeZoneId): - pass # TODO + 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) \ No newline at end of file diff --git a/toontown/pets/PetMoverAI.py b/toontown/pets/PetMoverAI.py new file mode 100644 index 00000000..f0502e51 --- /dev/null +++ b/toontown/pets/PetMoverAI.py @@ -0,0 +1,177 @@ +from panda3d.core import * +from direct.interval.IntervalGlobal import * +from direct.fsm.FSM import * +import random, math + +estateRadius = 130 +estateCenter = (0, -40) + +houseRadius = 15 +houses = ((60, 10), (42, 75), (-37, 35), (80, -80), (-70, -120), (-55, -40)) + +def inCircle(x, y, c=estateCenter, r=estateRadius): + center_x, center_y = c + square_dist = (center_x - x) ** 2 + (center_y - y) ** 2 + return square_dist <= r ** 2 + +def housePointCollision(x, y): + for i, h in enumerate(houses): + if inCircle(x, y, h, houseRadius): + return 1 + + return 0 + +def generatePos(): + def get(): + r = random.randint(0, estateRadius) - estateRadius / 2 + r2 = random.randint(0, estateRadius) - estateRadius / 2 + x = r + estateCenter[0] + y = r2 + estateCenter[1] + assert inCircle(x, y) + return x, y + + p = get() + while housePointCollision(*p): + p = get() + + return p + +def lineInCircle(pt1, pt2, circlePoint, circleRadius=houseRadius): + x1, y1 = pt1 + x2, y2 = pt2 + + dist = math.hypot(x2 - x1, y2 - y1) + if dist == 0: + return 0 + + dx = (x2 - x1) / dist + dy = (y2 - y1) / dist + + t = dx * (circlePoint[0] - x1) + dy * (circlePoint[1] - y1) + + ex = t * dx + x1 + ey = t * dy + y1 + + d2 = math.hypot(ex - circlePoint[0], ey - circlePoint[1]) + return d2 <= circleRadius + +def houseCollision(pt1, pt2): + for i, h in enumerate(houses): + if lineInCircle(pt1, pt2, h): + return 1 + + return 0 + +def generatePath(start, end): + points = [start] + if not houseCollision(start, end): + points.append(end) + return points + + while True: + next = generatePos() + while houseCollision(points[-1], next): + next = generatePos() + + points.append(next) + if not houseCollision(next, end): + points.append(end) + return points + +class PetMoverAI(FSM): + def __init__(self, pet): + self.pet = pet + FSM.__init__(self, 'PetMoverAI-%d' % self.pet.doId) + self.chaseTarget = None + self.__seq = None + self.fwdSpeed = 10.0 + self.rotSpeed = 360.0 + self.__moveFromStill() + self.__chaseCallback = None + + def enterStill(self): + taskMgr.doMethodLater(random.randint(15, 60), self.__moveFromStill, self.pet.uniqueName('next-state')) + + def exitStill(self): + taskMgr.remove(self.pet.uniqueName('next-state')) + + def __moveFromStill(self, task=None): + choices = ["Wander"] + # if self.pet._getNearbyAvatarDict(): + # choices.append("Chase") + + nextState = random.choice(choices) + self.request(nextState) + + def enterWander(self): + target = self.getPoint() + self.walkToPoint(target) + + def getPoint(self): + x, y = generatePos() + return Point3(x, y, 0) + + def walkToPoint(self, target): + here = self.pet.getPos() + dist = Vec3((here - target)).length() + dist = dist * 0.9 + self.__seq = Sequence(Func(self.pet.lookAt, target), self.pet.posInterval(dist / self.fwdSpeed, target, here), + Func(self.__stateComplete)) + self.__seq.start() + + def exitWander(self): + if self.__seq: + self.__seq.pause() + + self.__seq = None + + def __stateComplete(self): + try: + self.request("Still") + + except: + pass + + def destroy(self): + self.demand("Off") + + def setFwdSpeed(self, speed): + self.fwdSpeed = speed + + def getFwdSpeed(self): + return self.fwdSpeed + + def setRotSpeed(self, speed): + self.rotSpeed = speed + + def getRotSpeed(self): + return self.rotSpeed + + def lock(self): + if self.state != "Still": + self.demand("Still") + + def enterChase(self, target=None): + if not target: + target = hidden.attachNewNode('target') + target.setPos(self.getPoint()) + + self.walkToPoint(target.getPos()) + + + def exitChase(self): + if self.__chaseCallback: + self.__chaseCallback() + self.__chaseCallback = None + + if self.__seq: + self.__seq.pause() + + self.__seq = None + + def walkToAvatar(self, av, callback=None): + if callback: + self.__chaseCallback = callback + + self.demand("Chase", av) + \ No newline at end of file diff --git a/toontown/pets/PetTricks.py b/toontown/pets/PetTricks.py index e5fcecf1..aed0914a 100644 --- 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 +AptitudeIncrementDidTrick = 0.0005 * config.GetFloat('pet-trick-aptitude-mult', 4) MaxAptitudeIncrementGotPraise = 0.0003 MaxTrickFatigue = 0.65 MinTrickFatigue = 0.1 diff --git a/toontown/pets/PetWander.py b/toontown/pets/PetWander.py index fa700a38..e2374708 100644 --- a/toontown/pets/PetWander.py +++ b/toontown/pets/PetWander.py @@ -24,14 +24,14 @@ class PetWander(PetChase, DirectObject.DirectObject): return def _setMover(self, mover): - CPetChase.setMover(self, mover) + PetChase._setMover(self, mover) self.mover = mover self.__ignoreCollisions() self.collEvent = mover.getCollisionEventName() self.accept(self.collEvent, self._handleCollision) def _clearMover(self, mover): - CPetChase.clearMover(self, mover) + PetChase._clearMover(self, mover) self.__ignoreCollisions() def _handleCollision(self, collEntry): @@ -58,4 +58,4 @@ class PetWander(PetChase, DirectObject.DirectObject): target.setY(target, distance) duration = distance / self.mover.getFwdSpeed() self.targetMoveCountdown = duration * randFloat(1.2, 3.0) - CPetChase.process(self, dt) + PetChase._process(self, dt) diff --git a/toontown/pets/PetshopGUI.py b/toontown/pets/PetshopGUI.py index caaf1a99..b9360b4e 100644 --- a/toontown/pets/PetshopGUI.py +++ b/toontown/pets/PetshopGUI.py @@ -254,6 +254,7 @@ class PetshopGUI(DirectObject): self.okButton = DirectButton(parent=self, relief=None, image=okImageList, geom=checkIcon, scale=modelScale, text=('', TTLocalizer.PetshopReturn), text_pos=(5.8, 4.4), text_scale=0.7, pressEffect=False, command=lambda : messenger.send(doneEvent, [1])) self.petView = self.attachNewNode('petView') self.petView.setPos(-0.15, 0, 0.8) + avatar.announceGenerate() self.petModel = Pet.Pet(forGui=1) self.petModel.setDNA(avatar.getDNA()) self.petModel.fitAndCenterHead(0.395, forGui=1) @@ -342,7 +343,7 @@ class PetshopGUI(DirectObject): descList.append('\t%s' % trait) descList.append(TTLocalizer.PetshopDescCost % cost) - self.petDesc.append(string.join(descList, '\n')) + self.petDesc.append('\n'.join(descList)) self.petCost.append(cost) def destroy(self): diff --git a/toontown/toon/DistributedNPCPetclerkAI.py b/toontown/toon/DistributedNPCPetclerkAI.py index 46a620fd..9833f518 100644 --- a/toontown/toon/DistributedNPCPetclerkAI.py +++ b/toontown/toon/DistributedNPCPetclerkAI.py @@ -5,6 +5,7 @@ from toontown.toonbase import TTLocalizer from direct.task import Task from toontown.fishing import FishGlobals from toontown.pets import PetUtil, PetDNA, PetConstants +from toontown.hood import ZoneUtil class DistributedNPCPetclerkAI(DistributedNPCToonBaseAI): @@ -20,13 +21,13 @@ class DistributedNPCPetclerkAI(DistributedNPCToonBaseAI): def avatarEnter(self): avId = self.air.getAvatarIdFromSender() - if avId not in self.air.doId2do: + if not self.air.doId2do.has_key(avId): self.notify.warning('Avatar: %s not found' % avId) return if self.isBusy(): self.freeAvatar(avId) return - self.petSeeds = simbase.air.petMgr.getAvailablePets(5) + self.petSeeds = self.petMgr.getAvailablePets(3, ZoneUtil.getCanonicalSafeZoneId(self.zoneId)) numGenders = len(PetDNA.PetGenders) self.petSeeds *= numGenders self.petSeeds.sort() @@ -125,6 +126,7 @@ class DistributedNPCPetclerkAI(DistributedNPCToonBaseAI): if av: simbase.air.petMgr.deleteToonsPet(avId) self.transactionType = 'return' + self.transactionDone() def transactionDone(self): avId = self.air.getAvatarIdFromSender() diff --git a/toontown/toon/DistributedToon.py b/toontown/toon/DistributedToon.py index 8e977dc2..522db9a3 100644 --- a/toontown/toon/DistributedToon.py +++ b/toontown/toon/DistributedToon.py @@ -1758,9 +1758,6 @@ class DistributedToon(DistributedPlayer.DistributedPlayer, Toon.Toon, Distribute def getPetId(self): return self.petId - def getPetId(self): - return self.petId - def hasPet(self): return self.petId != 0 diff --git a/toontown/toon/Documents - Shortcut.lnk b/toontown/toon/Documents - Shortcut.lnk deleted file mode 100644 index 1abdc0623c2f1e861cc91e1571e505e91b6d3516..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 922 zcmah{Ur1A76#qFZv_WpnB5dR+mPTydZI*KoWOvL3mZLQ=xzJ>;G;}NP2HH~uL1ocH z3@j*CRQ6B=k@R4R^wLv03Ze`mqNgOpH=(3{=U&@`34NE}`G3xLzH?7IfQniRDKKSF zL`F~rJLOEzx=n?jGZoXHhCH*$Qkg?B11n5crcuycxgm}&;1t2@=(Jvgj|v#I<*I+N33g_oc950wkn0!0E5 zLYlHtFWr2%bZz^S$m3`I7owGYuf;dVc~sMvpzMps;y;v^vnnpNjV+cO_w*CnT4?Vf zP)|6BE_5S>UeZAf!-Ynu2(gI-bfjt1u~Wj0bCpzze!biodC?wJCw@7u?-(7JmPxIV z2r0Uoh{FRPv4`**k`FB$UJ!c?1gMEGK(9hufV7D;NV{Yk?dv5%nh_z4EMJ(%0N;~AjxPc>5;X+&3;BH5STXs* z