This commit is contained in:
Loudrob 2015-03-29 11:58:46 -04:00
commit 13a06febcf
36 changed files with 623 additions and 274 deletions

View file

@ -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);

View file

@ -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)

View file

@ -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,12 +1050,6 @@ 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)
else:
if not self.validate(toonId, track >= 0 and track <= MAX_TRACK_INDEX, 'requestAttack: invalid track %s' % track):
@ -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 = 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, zoneId)
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()

View file

@ -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:

View file

@ -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)

View file

@ -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:

View file

@ -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:

View file

@ -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

View file

@ -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)

View file

@ -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,7 +357,10 @@ class ToontownClientRepository(OTPClientRepository.OTPClientRepository):
pad = self.__queryAvatarMap.pop(avId)
pad.delayDelete.destroy()
def __sendGetAvatarDetails(self, 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):
@ -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()

View file

@ -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
@ -100,6 +101,35 @@ class LoadHouseFSM(FSM):
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,6 +260,28 @@ 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):
@ -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

View file

@ -41,6 +41,26 @@ class TTUFriendsManager(DistributedObjectGlobal):
]
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])

View file

@ -258,6 +258,26 @@ class TTUFriendsManagerUD(DistributedObjectGlobalUD):
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):
self.onlineToons.append(doId)

View file

@ -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()

View file

@ -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
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

View file

@ -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:

View file

@ -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

View file

@ -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',
@ -32,6 +28,10 @@ Component2IconDict = {'boredom': 'Bored',
'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')
SerialNum = 0
@ -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()

View file

@ -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,9 +55,7 @@ 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:
for avId, av in self.pet._getFullNearbyToonDict().items():
if isinstance(av, DistributedToonAI.DistributedToonAI):
av.toonUp(healAmt)
@ -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

View file

@ -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 looked:
if not self.pet._willDoTrick(trickId):
self.pet.trickFailLogger.addEvent(trickId)
trickId = PetTricks.Tricks.BALK
trickGoal = PetGoal.DoTrick(avatar, trickId)
self.goalMgr.addGoal(trickGoal)
self._doTrick(trickId, avatar)
phrase = observe.getPetPhrase()
avId = observe.getAvId()

View file

@ -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

View file

@ -1,2 +1,3 @@
if hasattr(simbase, 'wantPets') and simbase.wantPets:
import DistributedPetAI
import DistributedPetUD

View file

@ -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]

View file

@ -59,6 +59,7 @@ class PetHandle:
def updateMoodFromServer(self, callWhenDone = None):
def handleGotDetails(avatar, callWhenDone = callWhenDone):
avatar.announceGenerate()
self._grabMood(avatar)
if callWhenDone:
callWhenDone()

View file

@ -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)

View file

@ -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()
def getAvailablePets(self, numPets=5):
return random.sample(xrange(256), numPets)
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()
def createNewPetFromSeed(self, avId, petSeeds, nameIndex, gender, safeZoneId):
pass # TODO
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, seed, safezoneId):
if self.seeds.get('day', -1) != getDayId():
self.generateSeeds()
return self.seeds.get(safezoneId, [seed])
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)

177
toontown/pets/PetMoverAI.py Normal file
View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -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):

View file

@ -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()

View file

@ -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

View file

@ -140,6 +140,7 @@ class LocalToon(DistributedToon.DistributedToon, LocalAvatar.LocalAvatar):
self.shovelRelatedDoId = 0
self.shovelAbility = ''
self.plantToWater = 0
self.petId = 0
self.shovelButtonActiveCount = 0
self.wateringCanButtonActiveCount = 0
self.showingWateringCan = 0
@ -1877,10 +1878,23 @@ class LocalToon(DistributedToon.DistributedToon, LocalAvatar.LocalAvatar):
self.questMap.stop()
def getPetId(self):
return False
return self.petId
def hasPet(self):
return False
return self.petId != 0
def getPetDNA(self):
if self.hasPet():
pet = base.cr.doId2do(self.petId)
return pet.petDNA
return None
def setPetId(self, petId):
self.petId = petId
if petId == 0:
self.petDNA = None
elif self.isLocal():
base.cr.addPetToFriendsMap()
def setAchievements(self, achievements):
if base.wantAchievements:

View file

@ -0,0 +1,23 @@
from pandac.PandaModules import BitMask32
WallBitmask = BitMask32(1)
FloorBitmask = BitMask32(2)
CameraBitmask = BitMask32(4)
CameraTransparentBitmask = BitMask32(8)
SafetyNetBitmask = BitMask32(512)
SafetyGateBitmask = BitMask32(1024)
GhostBitmask = BitMask32(2048)
PathFindingBitmask = BitMask32.bit(29)
PickerBitmask = BitMask32(4096)
CeilingBitmask = BitMask32(256)
FloorEventBitmask = BitMask32(16)
PieBitmask = BitMask32(256)
PetBitmask = BitMask32(8)
CatchGameBitmask = BitMask32(16)
CashbotBossObjectBitmask = BitMask32(16)
FurnitureSideBitmask = BitMask32(32)
FurnitureTopBitmask = BitMask32(64)
FurnitureDragBitmask = BitMask32(128)
PetLookatPetBitmask = BitMask32(256)
PetLookatNonPetBitmask = BitMask32(512)
BanquetTableBitmask = BitMask32(1024)

View file

@ -248,6 +248,8 @@ class Street(BattlePlace.BattlePlace):
zoneId = requestStatus['zoneId']
if avId != -1:
if avId not in base.cr.doId2do:
friend = base.cr.identifyAvatar(avId)
if friend == None:
teleportDebug(requestStatus, "couldn't find friend %s" % avId)
handle = base.cr.identifyFriend(avId)
requestStatus = {'how': 'teleportIn',