diff --git a/toontown/catalog/CatalogChatItem.py b/toontown/catalog/CatalogChatItem.py index e7cb8dbc..1005e2e1 100644 --- a/toontown/catalog/CatalogChatItem.py +++ b/toontown/catalog/CatalogChatItem.py @@ -28,6 +28,9 @@ class CatalogChatItem(CatalogItem.CatalogItem): def getDisplayName(self): return OTPLocalizer.CustomSCStrings[self.customIndex] + def getDeliveryTime(self): + return 0 + def recordPurchase(self, avatar, optional): if avatar.customMessages.count(self.customIndex) != 0: return ToontownGlobals.P_ReachedPurchaseLimit diff --git a/toontown/catalog/CatalogNametagItem.py b/toontown/catalog/CatalogNametagItem.py index 6359c60d..21be9f90 100644 --- a/toontown/catalog/CatalogNametagItem.py +++ b/toontown/catalog/CatalogNametagItem.py @@ -55,6 +55,9 @@ class CatalogNametagItem(CatalogItem.CatalogItem): avatar.b_setNametagStyle(self.nametagStyle) return ToontownGlobals.P_ItemAvailable + def getDeliveryTime(self): + return 0 + def getPicture(self, avatar): frame = self.makeFrame() if self.nametagStyle == 100: diff --git a/toontown/catalog/CatalogRentalItem.py b/toontown/catalog/CatalogRentalItem.py index 41a3abac..fcef9c59 100644 --- a/toontown/catalog/CatalogRentalItem.py +++ b/toontown/catalog/CatalogRentalItem.py @@ -47,15 +47,14 @@ class CatalogRentalItem(CatalogItem.CatalogItem): return TTLocalizer.RentalTypeName def recordPurchase(self, avatar, optional): - self.notify.debug('rental -- record purchase') if avatar: - self.notify.debug('rental -- has avater') - estate = simbase.air.estateManager._lookupEstate(avatar.doId) + self.notify.debug('rental -- has avatar') + estate = simbase.air.estateManager._lookupEstate(avatar) if estate: self.notify.debug('rental -- has estate') estate.rentItem(self.typeIndex, self.duration) else: - self.notify.debug('rental -- something not there') + self.notify.warning('rental -- something not there') return ToontownGlobals.P_ItemAvailable def getPicture(self, avatar): @@ -106,6 +105,9 @@ class CatalogRentalItem(CatalogItem.CatalogItem): dg.addUint16(self.duration) dg.addUint16(self.typeIndex) + def getDeliveryTime(self): + return 1 + def isRental(self): return 1 diff --git a/toontown/estate/CannonGlobals.py b/toontown/estate/CannonGlobals.py index f187cf0c..0650f4b4 100644 --- a/toontown/estate/CannonGlobals.py +++ b/toontown/estate/CannonGlobals.py @@ -1,4 +1,4 @@ -CANNON_TIMEOUT = 20 +CANNON_TIMEOUT = 30 CANNON_MOVIE_LOAD = 1 CANNON_MOVIE_CLEAR = 2 CANNON_MOVIE_FORCE_EXIT = 3 diff --git a/toontown/estate/DistributedCannon.py b/toontown/estate/DistributedCannon.py index 96849318..79588af3 100644 --- a/toontown/estate/DistributedCannon.py +++ b/toontown/estate/DistributedCannon.py @@ -1,29 +1,29 @@ -from direct.controls.ControlManager import CollisionHandlerRayStart -from direct.distributed import DistributedObject +from pandac.PandaModules import * +from toontown.toonbase.ToonBaseGlobal import * +from toontown.toonbase import ToontownGlobals from direct.distributed.ClockDelta import * +from direct.interval.IntervalGlobal import * from direct.fsm import ClassicFSM, State from direct.fsm import State -from direct.gui.DirectGui import * -from direct.interval.IntervalGlobal import * -from direct.task.Task import Task -import math -from pandac.PandaModules import * -from pandac.PandaModules import * - -import CannonGlobals -from toontown.effects import DustCloud -from toontown.effects import Splash -from toontown.effects import Wake -from toontown.minigame import CannonGameGlobals -from toontown.minigame import Trajectory -from toontown.nametag.NametagFloat3d import NametagFloat3d -from toontown.toon import ToonHead -from toontown.toonbase import TTLocalizer -from toontown.toonbase import ToontownGlobals from toontown.toonbase import ToontownGlobals from toontown.toonbase import ToontownTimer -from toontown.toonbase.ToonBaseGlobal import * +from direct.task.Task import Task +from toontown.minigame import Trajectory +import math +from toontown.toon import ToonHead +from toontown.effects import Splash +from toontown.effects import DustCloud +from toontown.minigame import CannonGameGlobals +import CannonGlobals +from direct.gui.DirectGui import * +from pandac.PandaModules import * +from toontown.toonbase import TTLocalizer +from direct.distributed import DistributedObject +from toontown.effects import Wake +from direct.controls.ControlManager import CollisionHandlerRayStart +from toontown.nametag.NametagFloat3d import NametagFloat3d +from toontown.nametag.Nametag import Nametag LAND_TIME = 2 WORLD_SCALE = 2.0 @@ -267,7 +267,7 @@ class DistributedCannon(DistributedObject.DistributedObject): self.curPinballScore = 0 self.curPinballMultiplier = 1 self.incrementPinballInfo(0, 0) - if self.avId in self.cr.doId2do: + if self.cr.doId2do.has_key(self.avId): self.av = self.cr.doId2do[self.avId] self.acceptOnce(self.av.uniqueName('disable'), self.__avatarGone) self.av.stopSmooth() @@ -844,6 +844,7 @@ class DistributedCannon(DistributedObject.DistributedObject): flyTask.info = info seqTask = Task.sequence(shootTask, smokeTask, flyTask) if self.av == base.localAvatar: + print 'disable controls' base.localAvatar.disableAvatarControls() taskMgr.add(seqTask, self.taskName('flyingToon') + '-' + str(avId)) self.acceptOnce(self.uniqueName('stopFlyTask'), self.__stopFlyTask) @@ -865,6 +866,7 @@ class DistributedCannon(DistributedObject.DistributedObject): def removeAvFromCannon(self): place = base.cr.playGame.getPlace() + print 'removeAvFromCannon' self.notify.debug('self.inWater = %s' % self.inWater) if place: if not hasattr(place, 'fsm'): @@ -893,6 +895,7 @@ class DistributedCannon(DistributedObject.DistributedObject): self.av.startSmooth() self.av.setScale(1, 1, 1) if self.av == base.localAvatar: + print 'enable controls' base.localAvatar.enableAvatarControls() self.ignore(self.av.uniqueName('disable')) self.__destroyToonModels() @@ -1160,6 +1163,7 @@ class DistributedCannon(DistributedObject.DistributedObject): if hitP[2] > ToontownGlobals.EstateWakeWaterHeight: self.notify.debug('we hit the ground before we hit water') self.__hitGround(avatar, pos, extraArgs) + print 'but not really' return self.inWater = 1 self.notify.debug('hit water') @@ -1242,7 +1246,7 @@ class DistributedCannon(DistributedObject.DistributedObject): for id in doIds: t = self.cr.doId2do.get(id) if t: - pos = t.pos + pos = t.nodePath.getPos() rad = 10.5 height = 10.0 t_impact = trajectory.checkCollisionWithCylinderSides(pos, rad, height) @@ -1508,7 +1512,7 @@ class DistributedCannon(DistributedObject.DistributedObject): (0, 1, 5, 4), (0, 4, 7, 3), (1, 2, 6, 5)] - for i in xrange(len(vertices)): + for i in range(len(vertices)): vertex = vertices[i] vertexWriter.addData3f(vertex[0], vertex[1], vertex[2]) colorWriter.addData4f(*colors[i]) @@ -1577,4 +1581,5 @@ class DistributedCannon(DistributedObject.DistributedObject): def turnOnBumperCollision(self, whatever = 0): if self.bumperCol: - self.bumperCol.setCollideMask(ToontownGlobals.WallBitmask)# decompiled 0 files: 0 okay, 1 failed, 0 verify failed + self.bumperCol.setCollideMask(ToontownGlobals.WallBitmask) + diff --git a/toontown/estate/DistributedCannonAI.py b/toontown/estate/DistributedCannonAI.py index b98eda66..22f7d734 100644 --- a/toontown/estate/DistributedCannonAI.py +++ b/toontown/estate/DistributedCannonAI.py @@ -1,57 +1,102 @@ from direct.directnotify import DirectNotifyGlobal from direct.distributed.DistributedObjectAI import DistributedObjectAI +from direct.distributed.ClockDelta import * +from toontown.minigame import CannonGameGlobals +from toontown.toonbase import ToontownGlobals +import CannonGlobals class DistributedCannonAI(DistributedObjectAI): notify = DirectNotifyGlobal.directNotify.newCategory("DistributedCannonAI") - def setEstateId(self, todo0): - pass + def __init__(self, air): + DistributedObjectAI.__init__(self, air) + self.estateId = 0 + self.targetId = 0 + self.posHpr = (0, 0, 0, 0, 0, 0) + self.bumperPos = ToontownGlobals.PinballCannonBumperInitialPos + self.active = 0 + self.avId = 0 + + def setEstateId(self, estateId): + self.estateId = estateId + + def getEstateId(self): + return self.estateId - def setTargetId(self, todo0): - pass + def setTargetId(self, targetId): + self.targetId = targetId + + def getTargetId(self): + return self.targetId - def setPosHpr(self, todo0, todo1, todo2, todo3, todo4, todo5): - pass + def setPosHpr(self, x, y, z, h, p, r): + self.posHpr = (x, y, z, h, p, r) + + def getPosHpr(self): + return self.posHpr - def setActive(self, todo0): - pass - - def setActiveState(self, todo0): - pass + def setActive(self, active): + self.active = active + self.sendUpdate("setActiveState", [active]) def requestEnter(self): - pass + avId = self.air.getAvatarIdFromSender() + av = self.air.doId2do.get(avId) + if not av: + return + + if not self.avId: + self.avId = avId + self.d_setMovie(CannonGlobals.CANNON_MOVIE_LOAD) + self.acceptOnce(self.air.getAvatarExitEvent(avId), self.__handleUnexpectedExit, extraArgs=[avId]) + + else: + self.air.writeServerEvent('suspicious', avId, 'DistributedCannonAI.requestEnter cannon already occupied') + self.notify.warning('requestEnter() - cannon already occupied') + + def setMovie(self, mode, avId, extraInfo): + self.avId = avId + self.sendUpdate('setMovie', [mode, avId, extraInfo]) + + def __handleUnexpectedExit(self, avId): + self.notify.warning('avatar:' + str(avId) + ' has exited unexpectedly') + self.__doExit() + + def __doExit(self, movie=CannonGlobals.CANNON_MOVIE_FORCE_EXIT): + self.ignore(self.air.getAvatarExitEvent(self.avId)) + self.d_setMovie(movie) + self.avId = 0 def requestExit(self): pass - def setMovie(self, todo0, todo1): - pass + def d_setMovie(self, movie): + self.sendUpdate("setMovie", [movie, self.avId]) - def setCannonPosition(self, todo0, todo1): - pass + def setCannonPosition(self, zRot, angle): + self.sendUpdate("updateCannonPosition", [self.avId, zRot, angle]) - def setCannonLit(self, todo0, todo1): - pass + def setCannonLit(self, zRot, angle): + avId = self.air.getAvatarIdFromSender() + if avId != self.avId: + return + fireTime = CannonGameGlobals.FUSE_TIME + self.sendUpdate('setCannonWillFire', [avId, fireTime, zRot, angle, globalClockDelta.getRealNetworkTime()]) + def setFired(self): pass def setLanded(self): - pass - - def updateCannonPosition(self, todo0, todo1, todo2): - pass - - def setCannonWillFire(self, todo0, todo1, todo2, todo3, todo4): - pass + self.__doExit(CannonGlobals.CANNON_MOVIE_CLEAR) + self.sendUpdate('setCannonExit', [self.avId]) def setCannonExit(self, todo0): pass - def requestBumperMove(self, todo0, todo1, todo2): - pass - - def setCannonBumperPos(self, todo0, todo1, todo2): - pass + def requestBumperMove(self, x, y, z): + self.bumperPos = (x, y, z) + self.sendUpdate('setCannonBumperPos', self.getCannonBumperPos()) + def getCannonBumperPos(self): + return self.bumperPos diff --git a/toontown/estate/DistributedEstateAI.py b/toontown/estate/DistributedEstateAI.py index 9fb89cd0..b8df7120 100644 --- a/toontown/estate/DistributedEstateAI.py +++ b/toontown/estate/DistributedEstateAI.py @@ -149,6 +149,82 @@ class GardenManager: return packGardenData(NULL_FLOWERS + NULL_TREES, NULL_STATUARY, False) return packGardenData(g.flowersData + g.treesData, g.statuaryIndex) +class Rental: + def __init__(self, estate): + self.estate = estate + self.objects = set() + + def destroy(self): + del self.estate + for object in self.objects: + if not object.isDeleted(): + object.requestDelete() + taskMgr.remove(object.uniqueName('delete')) + self.objects = set() + +class CannonRental(Rental): + def generateObjects(self): + target = DistributedTargetAI(self.estate.air) + target.generateWithRequired(self.estate.zoneId) + + for drop in CannonGlobals.cannonDrops: + cannon = DistributedCannonAI(self.estate.air) + cannon.setEstateId(self.estate.doId) + cannon.setTargetId(target.doId) + cannon.setPosHpr(*drop) + cannon.generateWithRequired(self.estate.zoneId) + self.objects.add(cannon) + + self.generateTreasures() + self.estate.b_setClouds(1) + + def destroy(self): + self.estate.b_setClouds(0) + Rental.destroy(self) + + def generateTreasures(self): + doIds = [] + z = 35 + + for i in xrange(20): + x = random.randint(100, 300) - 200 + y = random.randint(100, 300) - 200 + treasure = DistributedTreasureAI.DistributedTreasureAI(self.estate.air, self, 9, x, y, z) + treasure.generateWithRequired(self.estate.zoneId) + self.objects.add(treasure) + doIds.append(treasure.doId) + + self.estate.sendUpdate("setTreasureIds", [doIds]) + + def grabAttempt(self, avId, treasureId): + av = self.estate.air.doId2do.get(avId) + if av == None: + self.estate.air.writeServerEvent('suspicious', avId, 'TreasurePlannerAI.grabAttempt unknown avatar') + self.estate.notify.warning('avid: %s does not exist' % avId) + return + + treasure = self.estate.air.doId2do.get(treasureId) + if self.validAvatar(av): + treasure.d_setGrab(avId) + self.deleteTreasureSoon(treasure) + + else: + treasure.d_setReject() + + def deleteTreasureSoon(self, treasure): + taskName = treasure.uniqueName('delete') + taskMgr.doMethodLater(5, self.__deleteTreasureNow, taskName, extraArgs=(treasure, taskName)) + + def __deleteTreasureNow(self, treasure, taskName): + treasure.requestDelete() + + def validAvatar(self, av): + if av.getMaxHp() == av.getHp(): + return 0 + + av.toonUp(3) + return 1 + class DistributedEstateAI(DistributedObjectAI): notify = DirectNotifyGlobal.directNotify.newCategory("DistributedEstateAI") def __init__(self, air): @@ -235,6 +311,9 @@ class DistributedEstateAI(DistributedObjectAI): self.pond.requestDelete() self.pond = None self.gardenManager.destroy() + if self.rentalHandle: + self.rentalHandle.destroy() + self.rentalHandle = None if self.treasurePlanner: self.treasurePlanner.stop() self.requestDelete() @@ -322,18 +401,58 @@ class DistributedEstateAI(DistributedObjectAI): self.sendUpdate('setRentalTimeStamp', [rental]) def b_setRentalTimeStamp(self, rental): - self.setRentalTimeStamp(self, rental) - self.b_setRentalTimeStamp(self, rental) + self.setRentalTimeStamp(rental) + self.d_setRentalTimeStamp(rental) def getRentalTimeStamp(self): return self.rentalTimestamp - def setRentalType(self, todo0): - pass + def b_setRentalType(self, type): + self.d_setRentalType(type) + self.setRentalType(type) + + def d_setRentalType(self, type): + self.sendUpdate("setRentalType", [type]) + + def setRentalType(self, type): + expirestamp = self.getRentalTimeStamp() + if expirestamp == 0: + expire = 0 + + else: + expire = int(expirestamp - time.time()) + + if expire < 0: + self.rentalType = 0 + self.d_setRentalType(0) + self.b_setRentalTimeStamp(0) + + else: + if self.rentalType == type: + return + + self.rentalType = type + if self.rentalHandle: + self.rentalHandle.destroy() + self.rentalHandle = None + + if self.rentalType == ToontownGlobals.RentalCannon: + self.rentalHandle = CannonRental(self) + + else: + self.notify.warning('Unknown rental %s' % self.rentalType) + return + + self.rentalHandle.generateObjects() def getRentalType(self): - return 0 - + return self.rentalType + + def rentItem(self, rentType, duration): + self.rentalType = rentType + self.b_setRentalTimeStamp(time.time() + duration * 60) + self.b_setRentalType(rentType) + def setSlot0ToonId(self, id): self.toons[0] = id diff --git a/toontown/estate/DistributedTarget.py b/toontown/estate/DistributedTarget.py index c56869de..95bf8bf8 100644 --- a/toontown/estate/DistributedTarget.py +++ b/toontown/estate/DistributedTarget.py @@ -155,12 +155,12 @@ class DistributedTarget(DistributedObject.DistributedObject): def showTimer(self): if base.localAvatar.animFSM.getCurrentState().getName() != 'ReadBook': - base.setCellsActive([base.rightCells[0]], 0) + base.setCellsAvailable([base.rightCells[0]], 0) self.timer.show() def hideTimer(self): self.timer.hide() - base.setCellsActive([base.rightCells[0]], 1) + base.setCellsAvailable([base.rightCells[0]], 1) def setPosition(self, x, y, z): self.geom.setPos(x, y, z) diff --git a/toontown/estate/DistributedTargetAI.py b/toontown/estate/DistributedTargetAI.py index 4d9a3a37..310e44d0 100644 --- a/toontown/estate/DistributedTargetAI.py +++ b/toontown/estate/DistributedTargetAI.py @@ -1,30 +1,86 @@ from direct.directnotify import DirectNotifyGlobal from direct.distributed.DistributedObjectAI import DistributedObjectAI +import CannonGlobals class DistributedTargetAI(DistributedObjectAI): notify = DirectNotifyGlobal.directNotify.newCategory("DistributedTargetAI") - def setPosition(self, todo0, todo1, todo2): + def __init__(self, air): + DistributedObjectAI.__init__(self, air) + self.enabled = 0 + self.highscore = 0 + self.scoreDict = {} + + self.__newGame() + + def announceGenerate(self): + DistributedObjectAI.announceGenerate(self) + taskMgr.doMethodLater(10, self.__startNewGame, self.taskName('newGame')) + + def __newGame(self): + self.power = 1 + self.time = CannonGlobals.CANNON_TIMEOUT + + def getPosition(self): + return (0, 0, 40) + + def getState(self): + return self.enabled, 2**self.power, self.time + + def d_updateState(self): + self.sendUpdate("setState", self.getState()) + + def d_setReward(self, reward): + self.sendUpdate("setReward", [reward]) + + def setResult(self, avId): + if avId and self.enabled: + self.power += 1 + self.time = int(CannonGlobals.CANNON_TIMEOUT / self.power) + taskMgr.remove(self.taskName('gameover')) + taskMgr.doMethodLater(self.time, self.__gameOver, self.taskName('gameover')) + self.d_updateState() + + def __gameOver(self, task): + self.enabled = 0 + self.time = 0 + self.d_updateState() + taskMgr.doMethodLater(10, self.__startNewGame, self.taskName('newGame')) + + for avId in self.scoreDict: + av = self.air.doId2do.get(avId) + if av: + if av.zoneId == self.zoneId: + av.toonUp(2 ** self.power) + + return task.done + + def __startNewGame(self, task): + self.enabled = 1 + self.__newGame() + self.d_updateState() + taskMgr.doMethodLater(self.time, self.__gameOver, self.taskName('gameover')) + return task.done + + def setBonus(self, bonus): pass - def setState(self, todo0, todo1, todo2): - pass + def setCurPinballScore(self, avId, score, bonus): + av = self.air.doId2do.get(avId) + if not av: + return + + S = score * bonus + self.scoreDict[avId] = S + if S > self.highscore: + self.highscore = S + self.d_updateHighscore(av, S) - def setReward(self, todo0): - pass + def d_updateHighscore(self, av, score): + self.sendUpdate("setPinballHiScorer", [av.getName()]) + self.sendUpdate("setPinballHiScore", [score]) - def setResult(self, todo0): - pass - - def setBonus(self, todo0): - pass - - def setCurPinballScore(self, todo0, todo1, todo2): - pass - - def setPinballHiScorer(self, todo0): - pass - - def setPinballHiScore(self, todo0): - pass + def delete(self): + taskMgr.remove(self.taskName('newGame')) + taskMgr.remove(self.taskName('gameover'))