class WayPointTest: def __init__(self, point, number, wayPointsToTest): self.point = point self.number = number self.wayPointsToTest = wayPointsToTest del self.wayPointsToTest[number] self.finalList = [] self.currentWayPointTestKey = None self.numberOfTests = -1 self.movementIval = None self.allTestsDone = False print "Testing waypoint: " + str(number) self.testNextWayPoint() def allTestsCompleted(self): print "Done testing waypoint: " + str(self.number) self.allTestsDone = True def testNextWayPoint(self): self.numberOfTests += 1 if self.movementIval: self.movementIval.pause() self.movementIval = None if self.numberOfTests > len(self.wayPointsToTest.keys()) - 1: self.allTestsCompleted() return print "Test number " + str(self.numberOfTests) + " on waypoint " + str( self.number) self.currentWayPointTestKey = self.wayPointsToTest.keys()[ self.numberOfTests] self.movementIval = NPCWalkInterval( node, Point3(*self.wayPointsToTest[self.currentWayPointTestKey]['pos']), 0.005, startPos=self.point, fluid=1) self.movementIval.setDoneEvent('testWayPointDone') base.acceptOnce(self.movementIval.getDoneEvent(), self.currentTestSucceeded) base.acceptOnce("sensors-into", self.handleBadTest) self.movementIval.start() def handleBadTest(self, entry): print "Failed" base.ignore("sensors-into") base.ignore("sensors-out") base.ignore(self.movementIval.getDoneEvent()) self.movementIval.pause() self.movementIval = None self.testNextWayPoint() def currentTestSucceeded(self): print "Passed" base.ignore("sensors-into") base.ignore("sensors-out") base.ignore(self.movementIval.getDoneEvent()) self.finalList.append(self.currentWayPointTestKey) print self.finalList self.testNextWayPoint()
class DistributedDeliveryGameSuitAI(DistributedSuitAI): notify = directNotify.newCategory('DistributedDeliveryGameSuitAI') def __init__(self, air, mg): DistributedSuitAI.__init__(self, air) self.mg = mg self.truck = random.choice(self.mg.trucks) self.truckIndex = self.mg.trucks.index(self.truck) self.spawnPoint = None return def walkToTruck(self): index = DGG.WalkToTruckIndex pos = DGG.TruckSuitPointsByIndex[self.truckIndex] startPos = self.getPos(render) self.b_setSuitState(1, -1, index) durationFactor = 0.2 pathName = self.uniqueName('WalkToTruck') self.walkTrack = NPCWalkInterval(self, pos, startPos=startPos, name=pathName, durationFactor=durationFactor, fluid=1) self.walkTrack.setDoneEvent(self.walkTrack.getName()) self.acceptOnce(self.walkTrack.getDoneEvent(), self.__walkedToTruck) self.walkTrack.start() self.b_setAnimState(SuitGlobals.getAnimId(SuitGlobals.getAnimByName('walk'))) def __walkedToTruck(self): self.truck.suitPickUpBarrel(self.doId) self.walkBackToSpawnPointWithBarrel() def walkBackToSpawnPointWithBarrel(self): pos = DGG.SpawnPoints[self.spawnPoint] startPos = self.getPos(render) self.b_setSuitState(1, -1, self.spawnPoint) durationFactor = 0.2 pathName = self.uniqueName('WalkBackToSpawn') self.walkTrack = NPCWalkInterval(self, pos, startPos=startPos, name=pathName, durationFactor=durationFactor, fluid=1) self.walkTrack.setDoneEvent(self.walkTrack.getName()) self.acceptOnce(self.walkTrack.getDoneEvent(), self.__walkedBack2Spawn) self.walkTrack.start() self.b_setAnimState(SuitGlobals.getAnimId(SuitGlobals.getAnimByName('tray-walk'))) def __walkedBack2Spawn(self): self.b_setSuitState(3, self.spawnPoint, self.spawnPoint) base.taskMgr.doMethodLater(10, self.__finished, self.uniqueName('finishSuit')) def __finished(self, task): self.mg.suits.remove(self) self.truck.barrelDroppedOff() self.requestDelete() return task.done def spawn(self): pos = random.choice(DGG.SpawnPoints) index = DGG.SpawnPoints.index(pos) self.spawnPoint = index self.b_setSuitState(2, index, index) flyTrack = self.posInterval(3, pos, startPos=pos + (0, 0, 50)) flyTrack.start() self.track = Sequence() self.track.append(Wait(5.4)) self.track.append(Func(self.b_setAnimState, 'neutral')) self.track.append(Wait(1.0)) self.track.append(Func(self.walkToTruck)) self.track.start() self.b_setParent(CIGlobals.SPRender) def delete(self): base.taskMgr.remove(self.uniqueName('finishSuit')) if hasattr(self, 'walkTrack') and self.walkTrack: self.ignore(self.walkTrack.getDoneEvent()) self.walkTrack.finish() self.walkTrack = None self.mg = None self.truck = None self.truckIndex = None self.spawnPoint = None DistributedSuitAI.delete(self) return
class FactorySneakGuardSuit(Suit, FSM): notify = directNotify.newCategory('FactorySneakGuardSuit') SUIT = 'mrhollywood' VIEW_DISTANCE_TASK_NAME = 'ViewDistanceTask' MAX_VIEW_DISTANCE = 100.0 GUARD_DIED_DELAY = 6.0 MAX_HP = 200 PROWLER_DISTANCE = 40.0 IN_VIEW = 'somethingInSight' HEARD = 'heard' TRY_TO_CONFIRM_TIME = 5.0 def __init__(self, world, guardKey): Suit.__init__(self) FSM.__init__(self, 'FactorySneakGuardSuit') self.gameWorld = world self.guardKey = guardKey self.viewDistanceTaskName = self.VIEW_DISTANCE_TASK_NAME + '-' + str( id(self)) self.diedTaskName = 'GuardDied-' + str(id(self)) self.health = 0 self.maxHealth = self.MAX_HP self.eyeLight = None self.eyeLens = None self.eyeNode = None self.moveTrack = None self.trav = None self.rayNP = None self.queue = None self.currentKey = self.guardKey self.firstPoint = CGG.GuardPointData[self.guardKey] self.walkTrack = None self.pathQueue = [] self.currentPathIndex = 0 return def enterGuard(self): self.loop('neutral') pos, hpr = CGG.FactoryGuardPoints[self.guardKey] self.setHpr(hpr - (180, 0, 0)) self.setPos(pos) base.taskMgr.add(self.__guard, self.taskName('guard')) def __checkToon(self): self.rayNP.lookAt(base.localAvatar) self.trav.traverse(render) if self.queue.getNumEntries() > 0: self.queue.sortEntries() hitObj = self.queue.getEntry(0).getIntoNodePath() print hitObj isLocalAvatar = hitObj.getParent().getPythonTag('localAvatar') if isLocalAvatar == 1: return 1 return 0 def __guard(self, task): if self.eyeNode.node().isInView(base.localAvatar.getPos( self.eyeNode)) and self.getDistance( base.localAvatar) <= self.PROWLER_DISTANCE: if self.__checkToon(): self.request('SeekTarget', self.IN_VIEW) return task.done return task.cont def exitGuard(self): base.taskMgr.remove(self.taskName('guard')) def enterTurnToGuardSpot(self): self.loop('walk') _, hpr = CGG.FactoryGuardPoints[self.guardKey] self.moveTrack = LerpHprInterval(self, duration=1.0, hpr=hpr, startHpr=self.getHpr()) self.moveTrack.setDoneEvent(self.uniqueName('TurnedToGuardSpot')) self.acceptOnce(self.moveTrack.getDoneEvent(), self.request, ['Guard']) self.moveTrack.start() def exitTurnToGuardSpot(self): if self.moveTrack: self.ignore(self.moveTrack.getDoneEvent()) self.moveTrack.finish() self.moveTrack = None return def enterSeekTarget(self, event): dialogue = random.choice(CGG.GuardDialog[event]) self.setChat(dialogue) self.loop('walk') self.moveTrack = NPCLookInterval(self, base.localAvatar) self.moveTrack.setDoneEvent(self.uniqueName('SeekLocalAvatar')) self.acceptOnce(self.moveTrack.getDoneEvent(), self.request, ['TryToConfirmTarget']) self.moveTrack.start() def exitSeekTarget(self): if self.moveTrack: self.ignore(self.moveTrack.getDoneEvent()) self.moveTrack.finish() self.moveTrack = None return def enterTryToConfirmTarget(self): self.loop('neutral') base.taskMgr.add(self.__tryToConfirmTarget, self.uniqueName('TryToConfirmTarget')) def __tryToConfirmTarget(self, task): if task.time >= self.TRY_TO_CONFIRM_TIME: chat = random.choice(CGG.GuardDialog['disregard']) self.setChat(chat) self.request('TurnToGuardSpot') return task.done if self.eyeNode.node().isInView(base.localAvatar.getPos( self.eyeNode)) and self.getDistance( base.localAvatar) <= self.PROWLER_DISTANCE: if self.__checkToon(): chat = random.choice(CGG.GuardDialog['spot']) self.setChat(chat) self.request('Pursue') return task.done return task.cont def exitTryToConfirmTarget(self): base.taskMgr.remove(self.uniqueName('TryToConfirmTarget')) def enterGoBackToGuardSpot(self): self.walkBackToGuardSpot() def walkBackToGuardSpot(self): self.currentPathIndex = 0 self.pathQueue = SuitPathFinder.find_path(CGG.FactoryWalkPoints, CGG.FactoryWayPointData, self.currentKey, self.guardKey) self.currentKey = self.guardKey self.walk(0.2) self.loop('walk') def exitGoBackToGuardSpot(self): pass def enterPursue(self): self.numTries = 0 self.maxTries = 3 self.runToClosestPoint() self.setPlayRate(1.5, 'walk') self.loop('walk') messenger.send('guardPursue') def getClosestPoint(self): closestPoint = None pointKey2range = {} for key, point in CGG.FactoryWalkPoints.items(): dummyNode = render.attachNewNode('dummyNode') dummyNode.setPos(point) pointKey2range[key] = base.localAvatar.getDistance(dummyNode) dummyNode.removeNode() ranges = [] for distance in pointKey2range.values(): ranges.append(distance) ranges.sort() for key in pointKey2range.keys(): distance = pointKey2range[key] if distance == ranges[0]: closestPoint = key break return closestPoint def runToClosestPoint(self): self.numTries += 1 closestPoint = self.getClosestPoint() self.currentPathIndex = 0 startKey = None if self.currentKey == self.guardKey and self.firstPoint in CGG.GuardPointData: startKey = CGG.GuardPointData[self.firstPoint] else: startKey = self.currentKey self.pathQueue = SuitPathFinder.find_path(CGG.FactoryWalkPoints, CGG.FactoryWayPointData, startKey, closestPoint) if self.currentKey == self.guardKey: self.pathQueue.insert(0, 1) else: self.pathQueue.insert(0, 0) self.currentKey = closestPoint self.walk(0.1) return def walk(self, speed=0.2): self.currentPathIndex += 1 if len(self.pathQueue) <= self.currentPathIndex: if self.getCurrentOrNextState() == 'Pursue': if self.getClosestPoint() != self.currentKey: if self.numTries >= self.maxTries: self.request('GoBackToGuardSpot') else: self.runToClosestPoint() else: if self.getCurrentOrNextState() == 'GoBackToGuardSpot': self.request('Guard') return print self.pathQueue[self.currentPathIndex] if self.currentPathIndex == 1 and self.pathQueue[0] == 1: startPoint = self.getPos(render) endPoint = CGG.FactoryWalkPoints[self.firstPoint] else: if self.pathQueue[0] == 0: self.pathQueue.remove(self.pathQueue[0]) key = self.pathQueue[self.currentPathIndex] endPoint = CGG.FactoryWalkPoints[key] oldKey = self.pathQueue[self.currentPathIndex - 1] startPoint = CGG.FactoryWalkPoints[oldKey] self.walkTrack = NPCWalkInterval(self, endPoint, speed, startPoint) self.walkTrack.setDoneEvent(self.uniqueName('guardWalkDone')) self.acceptOnce(self.uniqueName('guardWalkDone'), self.walk) self.walkTrack.start() def exitPursue(self): self.setPlayRate(1.0, 'walk') del self.numTries if self.walkTrack: self.ignore(self.walkTrack.getDoneEvent()) self.walkTrack.pause() self.walkTrack = None messenger.send('guardStopPursue') return def uniqueName(self, name): return self.taskName(name) def taskName(self, name): return name + '-' + str(id(self)) def setHealth(self, hp): self.health = hp def getHealth(self): return self.health def shot(self): dialogue = random.choice(CGG.GuardDialog['shot']) self.setChat(dialogue) def dead(self): self.request('Off') self.animFSM.request('die') base.taskMgr.doMethodLater(self.GUARD_DIED_DELAY, self.__diedDone, self.diedTaskName) def __diedDone(self, task): self.gameWorld.deleteGuard(self) return task.done def generate(self): data = CIGlobals.SuitBodyData[self.SUIT] type = data[0] team = data[1] self.team = team self.level = 12 self.suit = type Suit.generate(self, SuitBank.MrHollywood, 0, hideFirst=False) self.suit = type base.taskMgr.add(self.__viewDistance, self.viewDistanceTaskName) self.setPythonTag('guard', self) self.eyeLight = Spotlight('eyes') self.eyeLens = PerspectiveLens() self.eyeLens.setMinFov(90.0 / (4.0 / 3.0)) self.eyeLight.setLens(self.eyeLens) self.eyeNode = self.headModel.attachNewNode(self.eyeLight) self.eyeNode.setZ(-5) self.eyeNode.setY(-4.5) self.trav = CollisionTraverser(self.uniqueName('eyeTrav')) ray = CollisionRay(0, 0, 0, 0, 1, 0) rayNode = CollisionNode('ToonFPS.rayNode') rayNode.addSolid(ray) rayNode.setFromCollideMask(CGG.GuardBitmask | CIGlobals.WallBitmask) rayNode.setIntoCollideMask(BitMask32.allOff()) self.rayNP = base.camera.attachNewNode(rayNode) self.rayNP.setZ(3) self.queue = CollisionHandlerQueue() self.trav.addCollider(self.rayNP, self.queue) self.trav.addCollider(self.gameWorld.mg.avatarBody, self.queue) self.request('Guard') def __viewDistance(self, task): if self.getDistance(base.localAvatar) > self.MAX_VIEW_DISTANCE: if not self.isHidden(): self.hide() else: if self.isHidden(): self.show() task.delayTime = 1.0 return task.again def disable(self): self.request('Off') base.taskMgr.remove(self.taskName('guard')) base.taskMgr.remove(self.diedTaskName) base.taskMgr.remove(self.viewDistanceTaskName) self.trav = None if self.rayNP: self.rayNP.removeNode() self.rayNP = None self.queue = None self.currentPathIndex = None if self.eyeNode: self.eyeNode.removeNode() self.eyeNode = None self.eyeLens = None self.eyeLight = None self.viewDistanceTaskName = None self.guardKey = None self.gameWorld = None self.pathQueue = None if self.walkTrack: self.ignore(self.walkTrack.getDoneEvent()) self.walkTrack.finish() self.walkTrack = None Suit.disable(self) return
class DistributedEagleSuitAI(DistributedSuitAI): notify = directNotify.newCategory("DistributedEagleSuitAI") def __init__(self, air): DistributedSuitAI.__init__(self, air) self.mg = None self.flyTrack = None self.currentFlyPoint = None self.flySpeed = 0.0 def setMinigame(self, mg): self.mg = mg def getMinigame(self): return self.mg def handleGotHit(self): self.b_setAnimState('flail') if self.flyTrack: self.ignore(self.flyTrack.getDoneEvent()) self.flyTrack.pause() self.flyTrack = None self.sendUpdate('fallAndExplode', []) self.b_setSuitState(6, -1, -1) self.flyTrack = Sequence( LerpPosInterval( self, duration = 4.0, pos = self.getPos(render) - (0, 0, 75), startPos = self.getPos(render), blendType = 'easeIn' ), Wait(1.5), Func(self.killMe) ) self.flyTrack.start() def killMe(self): self.disable() self.requestDelete() def setFlySpeed(self, value): self.flySpeed = value def b_setFlySpeed(self, value): self.sendUpdate('setFlySpeed', [value]) self.setFlySpeed(value) def getFlySpeed(self): return self.flySpeed def spawn(self): # spawn() also exists in DistributedSuitAI, but we're not doing # anything that a normal suit would do here, so don't even call # DistributedSuitAI.spawn. if not self.getMinigame(): self.notify.error("Tried to spawn before self.mg was set!") self.b_setAnimState('flyNeutral') point = random.choice(EGG.EAGLE_FLY_POINTS) self.setPos(point) self.d_setPos(*point) self.b_setFlySpeed(EGG.ROUND_2_EAGLE_SPEED[self.getMinigame().getRound()]) self.createFlyPath() self.b_setParent(CIGlobals.SPRender) def createFlyPath(self): self.b_setAnimState('flyNeutral') if self.flyTrack: self.ignore(self.flyTrack.getDoneEvent()) self.flyTrack.pause() self.flyTrack = None point = random.choice(EGG.EAGLE_FLY_POINTS) if self.currentFlyPoint == point: self.createFlyPath() return if self.currentFlyPoint == None: point_list = list(EGG.EAGLE_FLY_POINTS) point_list.remove(point) startIndex = point_list.index(random.choice(point_list)) else: startIndex = -1 self.b_setSuitState(5, startIndex, EGG.EAGLE_FLY_POINTS.index(point)) mgRound = self.getMinigame().getRound() if mgRound: self.flyTrack = NPCWalkInterval(self, point, durationFactor = EGG.ROUND_2_EAGLE_SPEED[mgRound], startPos = self.getPos(render), fluid = 1, name = self.uniqueName('DEagleSuitAI-flyTrack')) self.flyTrack.setDoneEvent(self.flyTrack.getName()) self.acceptOnce(self.flyTrack.getDoneEvent(), self.handleFlyDone) self.flyTrack.start() self.currentFlyPoint = point else: return def handleFlyDone(self): self.createFlyPath() def delete(self): del self.currentFlyPoint del self.mg if self.flyTrack: self.ignore(self.flyTrack.getDoneEvent()) self.flyTrack.pause() self.flyTrack = None DistributedSuitAI.delete(self)
class DistributedEagleSuitAI(DistributedSuitAI): notify = directNotify.newCategory('DistributedEagleSuitAI') def __init__(self, air): DistributedSuitAI.__init__(self, air) self.mg = None self.flyTrack = None self.currentFlyPoint = None self.flySpeed = 0.0 return def setMinigame(self, mg): self.mg = mg def getMinigame(self): return self.mg def handleGotHit(self): self.b_setAnimState('flail') if self.flyTrack: self.ignore(self.flyTrack.getDoneEvent()) self.flyTrack.pause() self.flyTrack = None self.sendUpdate('fallAndExplode', []) self.b_setSuitState(6, -1, -1) self.flyTrack = Sequence(LerpPosInterval(self, duration=4.0, pos=self.getPos(render) - (0, 0, 75), startPos=self.getPos(render), blendType='easeIn'), Wait(1.5), Func(self.killMe)) self.flyTrack.start() return def killMe(self): self.disable() self.requestDelete() def setFlySpeed(self, value): self.flySpeed = value def b_setFlySpeed(self, value): self.sendUpdate('setFlySpeed', [value]) self.setFlySpeed(value) def getFlySpeed(self): return self.flySpeed def spawn(self): if not self.getMinigame(): self.notify.error('Tried to spawn before self.mg was set!') self.b_setAnimState('flyNeutral') point = random.choice(EGG.EAGLE_FLY_POINTS) self.setPos(point) self.d_setPos(*point) self.b_setFlySpeed(EGG.ROUND_2_EAGLE_SPEED[self.getMinigame().getRound()]) self.createFlyPath() self.b_setParent(CIGlobals.SPRender) def createFlyPath(self): self.b_setAnimState('flyNeutral') if self.flyTrack: self.ignore(self.flyTrack.getDoneEvent()) self.flyTrack.pause() self.flyTrack = None point = random.choice(EGG.EAGLE_FLY_POINTS) if self.currentFlyPoint == point: self.createFlyPath() return else: if self.currentFlyPoint == None: point_list = list(EGG.EAGLE_FLY_POINTS) point_list.remove(point) startIndex = point_list.index(random.choice(point_list)) else: startIndex = -1 self.b_setSuitState(5, startIndex, EGG.EAGLE_FLY_POINTS.index(point)) mgRound = self.getMinigame().getRound() if mgRound: self.flyTrack = NPCWalkInterval(self, point, durationFactor=EGG.ROUND_2_EAGLE_SPEED[mgRound], startPos=self.getPos(render), fluid=1, name=self.uniqueName('DEagleSuitAI-flyTrack')) self.flyTrack.setDoneEvent(self.flyTrack.getName()) self.acceptOnce(self.flyTrack.getDoneEvent(), self.handleFlyDone) self.flyTrack.start() self.currentFlyPoint = point else: return return def handleFlyDone(self): self.createFlyPath() def delete(self): del self.currentFlyPoint del self.mg if self.flyTrack: self.ignore(self.flyTrack.getDoneEvent()) self.flyTrack.pause() self.flyTrack = None DistributedSuitAI.delete(self) return
class DistributedDeliveryGameSuitAI(DistributedSuitAI): notify = directNotify.newCategory('DistributedDeliveryGameSuitAI') def __init__(self, air, mg): DistributedSuitAI.__init__(self, air) self.mg = mg self.truck = random.choice(self.mg.trucks) self.truckIndex = self.mg.trucks.index(self.truck) self.spawnPoint = None def walkToTruck(self): index = DGG.WalkToTruckIndex pos = DGG.TruckSuitPointsByIndex[self.truckIndex] startPos = self.getPos(render) self.b_setSuitState(1, -1, index) durationFactor = 0.2 pathName = self.uniqueName('WalkToTruck') self.walkTrack = NPCWalkInterval(self, pos, startPos=startPos, name=pathName, durationFactor=durationFactor, fluid=1) self.walkTrack.setDoneEvent(self.walkTrack.getName()) self.acceptOnce(self.walkTrack.getDoneEvent(), self.__walkedToTruck) self.walkTrack.start() self.b_setAnimState( SuitGlobals.getAnimId(SuitGlobals.getAnimByName('walk'))) def __walkedToTruck(self): self.truck.suitPickUpBarrel(self.doId) self.walkBackToSpawnPointWithBarrel() def walkBackToSpawnPointWithBarrel(self): pos = DGG.SpawnPoints[self.spawnPoint] startPos = self.getPos(render) self.b_setSuitState(1, -1, self.spawnPoint) durationFactor = 0.2 pathName = self.uniqueName('WalkBackToSpawn') self.walkTrack = NPCWalkInterval(self, pos, startPos=startPos, name=pathName, durationFactor=durationFactor, fluid=1) self.walkTrack.setDoneEvent(self.walkTrack.getName()) self.acceptOnce(self.walkTrack.getDoneEvent(), self.__walkedBack2Spawn) self.walkTrack.start() self.b_setAnimState( SuitGlobals.getAnimId(SuitGlobals.getAnimByName('tray-walk'))) def __walkedBack2Spawn(self): self.b_setSuitState(3, self.spawnPoint, self.spawnPoint) base.taskMgr.doMethodLater(10, self.__finished, self.uniqueName('finishSuit')) def __finished(self, task): self.mg.suits.remove(self) self.truck.barrelDroppedOff() self.requestDelete() return task.done def spawn(self): pos = random.choice(DGG.SpawnPoints) index = DGG.SpawnPoints.index(pos) self.spawnPoint = index self.b_setSuitState(2, index, index) flyTrack = self.posInterval(3, pos, startPos=pos + (0, 0, 50)) flyTrack.start() self.track = Sequence() self.track.append(Wait(5.4)) self.track.append(Func(self.b_setAnimState, 'neutral')) self.track.append(Wait(1.0)) self.track.append(Func(self.walkToTruck)) self.track.start() self.b_setParent(CIGlobals.SPRender) def delete(self): base.taskMgr.remove(self.uniqueName('finishSuit')) if hasattr(self, 'walkTrack') and self.walkTrack: self.ignore(self.walkTrack.getDoneEvent()) self.walkTrack.finish() self.walkTrack = None self.mg = None self.truck = None self.truckIndex = None self.spawnPoint = None DistributedSuitAI.delete(self)
class FactorySneakGuardSuit(Suit, FSM): notify = directNotify.newCategory("FactorySneakGuardSuit") SUIT = "mrhollywood" VIEW_DISTANCE_TASK_NAME = "ViewDistanceTask" MAX_VIEW_DISTANCE = 100.0 GUARD_DIED_DELAY = 6.0 MAX_HP = 200 PROWLER_DISTANCE = 40.0 IN_VIEW = "somethingInSight" HEARD = "heard" TRY_TO_CONFIRM_TIME = 5.0 def __init__(self, world, guardKey): Suit.__init__(self) FSM.__init__(self, 'FactorySneakGuardSuit') self.gameWorld = world self.guardKey = guardKey self.viewDistanceTaskName = self.VIEW_DISTANCE_TASK_NAME + "-" + str( id(self)) self.diedTaskName = "GuardDied-" + str(id(self)) self.health = 0 self.maxHealth = self.MAX_HP self.eyeLight = None self.eyeLens = None self.eyeNode = None self.moveTrack = None self.trav = None self.rayNP = None self.queue = None self.currentKey = self.guardKey self.firstPoint = CGG.GuardPointData[self.guardKey] self.walkTrack = None self.pathQueue = [] self.currentPathIndex = 0 def enterGuard(self): self.loop('neutral') pos, hpr = CGG.FactoryGuardPoints[self.guardKey] self.setHpr(hpr - (180, 0, 0)) self.setPos(pos) base.taskMgr.add(self.__guard, self.taskName("guard")) def __checkToon(self): self.rayNP.lookAt(base.localAvatar) self.trav.traverse(render) if self.queue.getNumEntries() > 0: self.queue.sortEntries() hitObj = self.queue.getEntry(0).getIntoNodePath() print hitObj isLocalAvatar = hitObj.getParent().getPythonTag('localAvatar') if isLocalAvatar == 1: # Yes! We see the prowler! return 1 return 0 def __guard(self, task): # Let me check if the target is my frustrum, and if it's a close enough distance from me. if (self.eyeNode.node().isInView(base.localAvatar.getPos(self.eyeNode)) and self.getDistance(base.localAvatar) <= self.PROWLER_DISTANCE): # Now, let me check if the toon is standing right in front of me; not occluded. if self.__checkToon(): # Yes! We see some one! self.request('SeekTarget', self.IN_VIEW) return task.done return task.cont def exitGuard(self): base.taskMgr.remove(self.taskName("guard")) def enterTurnToGuardSpot(self): self.loop('walk') _, hpr = CGG.FactoryGuardPoints[self.guardKey] self.moveTrack = LerpHprInterval(self, duration=1.0, hpr=hpr, startHpr=self.getHpr()) self.moveTrack.setDoneEvent(self.uniqueName('TurnedToGuardSpot')) self.acceptOnce(self.moveTrack.getDoneEvent(), self.request, ['Guard']) self.moveTrack.start() def exitTurnToGuardSpot(self): if self.moveTrack: self.ignore(self.moveTrack.getDoneEvent()) self.moveTrack.finish() self.moveTrack = None def enterSeekTarget(self, event): dialogue = random.choice(CGG.GuardDialog[event]) self.setChat(dialogue) self.loop('walk') self.moveTrack = NPCLookInterval(self, base.localAvatar) self.moveTrack.setDoneEvent(self.uniqueName("SeekLocalAvatar")) self.acceptOnce(self.moveTrack.getDoneEvent(), self.request, ['TryToConfirmTarget']) self.moveTrack.start() def exitSeekTarget(self): if self.moveTrack: self.ignore(self.moveTrack.getDoneEvent()) self.moveTrack.finish() self.moveTrack = None def enterTryToConfirmTarget(self): self.loop('neutral') base.taskMgr.add(self.__tryToConfirmTarget, self.uniqueName('TryToConfirmTarget')) def __tryToConfirmTarget(self, task): if task.time >= self.TRY_TO_CONFIRM_TIME: # Hmm, I guess it was nothing. chat = random.choice(CGG.GuardDialog['disregard']) self.setChat(chat) self.request('TurnToGuardSpot') return task.done # Let me see the target again, so I know it's actually something. if (self.eyeNode.node().isInView(base.localAvatar.getPos(self.eyeNode)) and self.getDistance(base.localAvatar) <= self.PROWLER_DISTANCE): # Now, let me check if the toon is standing right in front of me; not occluded. if self.__checkToon(): # There he is! chat = random.choice(CGG.GuardDialog['spot']) self.setChat(chat) self.request('Pursue') return task.done return task.cont def exitTryToConfirmTarget(self): base.taskMgr.remove(self.uniqueName('TryToConfirmTarget')) def enterGoBackToGuardSpot(self): self.walkBackToGuardSpot() def walkBackToGuardSpot(self): self.currentPathIndex = 0 self.pathQueue = SuitPathFinder.find_path(CGG.FactoryWalkPoints, CGG.FactoryWayPointData, self.currentKey, self.guardKey) self.currentKey = self.guardKey self.walk(0.2) self.loop('walk') def exitGoBackToGuardSpot(self): pass def enterPursue(self): self.numTries = 0 self.maxTries = 3 self.runToClosestPoint() self.setPlayRate(1.5, 'walk') self.loop('walk') messenger.send('guardPursue') def getClosestPoint(self): # Return the key of the closest point to the localAvatar. closestPoint = None pointKey2range = {} for key, point in CGG.FactoryWalkPoints.items(): dummyNode = render.attachNewNode('dummyNode') dummyNode.setPos(point) pointKey2range[key] = base.localAvatar.getDistance(dummyNode) dummyNode.removeNode() ranges = [] for distance in pointKey2range.values(): ranges.append(distance) ranges.sort() for key in pointKey2range.keys(): distance = pointKey2range[key] if distance == ranges[0]: closestPoint = key break return closestPoint def runToClosestPoint(self): self.numTries += 1 closestPoint = self.getClosestPoint() self.currentPathIndex = 0 startKey = None if self.currentKey == self.guardKey: startKey = CGG.GuardPointData[self.firstPoint] else: startKey = self.currentKey self.pathQueue = SuitPathFinder.find_path(CGG.FactoryWalkPoints, CGG.FactoryWayPointData, startKey, closestPoint) if self.currentKey == self.guardKey: self.pathQueue.insert(0, 1) else: self.pathQueue.insert(0, 0) self.currentKey = closestPoint self.walk(0.1) def walk(self, speed=0.2): self.currentPathIndex += 1 if len(self.pathQueue) <= self.currentPathIndex: if self.getCurrentOrNextState() == 'Pursue': if self.getClosestPoint() != self.currentKey: # Wow, the player ran off somewhere else! Go there! if self.numTries >= self.maxTries: # Dang it, give up, we can't get to them! self.request('GoBackToGuardSpot') else: self.runToClosestPoint() elif self.getCurrentOrNextState() == 'GoBackToGuardSpot': self.request('Guard') return print self.pathQueue[self.currentPathIndex] if self.currentPathIndex == 1 and self.pathQueue[0] == 1: # We need to walk from our guard point to the first waypoint in our path startPoint = self.getPos(render) endPoint = CGG.FactoryWalkPoints[self.firstPoint] else: if self.pathQueue[0] == 0: self.pathQueue.remove(self.pathQueue[0]) key = self.pathQueue[self.currentPathIndex] endPoint = CGG.FactoryWalkPoints[key] oldKey = self.pathQueue[self.currentPathIndex - 1] startPoint = CGG.FactoryWalkPoints[oldKey] self.walkTrack = NPCWalkInterval(self, endPoint, speed, startPoint) self.walkTrack.setDoneEvent(self.uniqueName('guardWalkDone')) self.acceptOnce(self.uniqueName('guardWalkDone'), self.walk) self.walkTrack.start() def exitPursue(self): self.setPlayRate(1.0, 'walk') del self.numTries if self.walkTrack: self.ignore(self.walkTrack.getDoneEvent()) self.walkTrack.pause() self.walkTrack = None messenger.send('guardStopPursue') def uniqueName(self, name): return self.taskName(name) def taskName(self, name): return name + "-" + str(id(self)) def setHealth(self, hp): self.health = hp def getHealth(self): return self.health def shot(self): dialogue = random.choice(CGG.GuardDialog['shot']) self.setChat(dialogue) def dead(self): self.request('Off') self.animFSM.request('die') base.taskMgr.doMethodLater(self.GUARD_DIED_DELAY, self.__diedDone, self.diedTaskName) def __diedDone(self, task): self.gameWorld.deleteGuard(self) return task.done def generate(self): data = CIGlobals.SuitBodyData[self.SUIT] type = data[0] team = data[1] self.generateSuit(type, self.SUIT, team, self.MAX_HP, 0, False) base.taskMgr.add(self.__viewDistance, self.viewDistanceTaskName) self.setPythonTag('guard', self) self.eyeLight = Spotlight('eyes') self.eyeLens = PerspectiveLens() self.eyeLens.setMinFov(90.0 / (4. / 3.)) self.eyeLight.setLens(self.eyeLens) self.eyeNode = self.headModel.attachNewNode(self.eyeLight) self.eyeNode.setZ(-5) self.eyeNode.setY(-4.5) self.trav = CollisionTraverser(self.uniqueName('eyeTrav')) ray = CollisionRay(0, 0, 0, 0, 1, 0) rayNode = CollisionNode('ToonFPS.rayNode') rayNode.addSolid(ray) rayNode.setFromCollideMask(CGG.GuardBitmask | CIGlobals.WallBitmask) rayNode.setIntoCollideMask(BitMask32.allOff()) self.rayNP = base.camera.attachNewNode(rayNode) self.rayNP.setZ(3) self.queue = CollisionHandlerQueue() self.trav.addCollider(self.rayNP, self.queue) self.trav.addCollider(self.gameWorld.mg.avatarBody, self.queue) self.request('Guard') def __viewDistance(self, task): # All the guards in the warehouse eat up a lot of frames. This task will # hide the guard geometry if it's too far away. if self.getDistance(base.localAvatar) > self.MAX_VIEW_DISTANCE: if not self.isHidden(): self.hide() else: if self.isHidden(): self.show() task.delayTime = 1.0 return task.again def disable(self): self.request('Off') base.taskMgr.remove(self.taskName("guard")) base.taskMgr.remove(self.diedTaskName) base.taskMgr.remove(self.viewDistanceTaskName) self.trav = None if self.rayNP: self.rayNP.removeNode() self.rayNP = None self.queue = None self.currentPathIndex = None if self.eyeNode: self.eyeNode.removeNode() self.eyeNode = None self.eyeLens = None self.eyeLight = None self.viewDistanceTaskName = None self.guardKey = None self.gameWorld = None self.pathQueue = None if self.walkTrack: self.ignore(self.walkTrack.getDoneEvent()) self.walkTrack.finish() self.walkTrack = None Suit.disable(self)
class DistributedTutorialSuitAI(DistributedSuitAI): notify = directNotify.newCategory('DistributedTutorialSuitAI') ATTACK_IVAL_RANGE = [3, 15] def __init__(self, air, index, tut, avatarId): DistributedSuitAI.__init__(self, air) self.tutPartIndex = index self.tutorial = tut self.avatarId = avatarId self.currentPath = None self.walkTrack = None return def delete(self): base.taskMgr.remove(self.uniqueName('monitorHealth')) base.taskMgr.remove(self.uniqueName('doAttack')) base.taskMgr.remove(self.uniqueName('scwaa')) self.stopAttacks() if self.track: self.track.pause() self.track = None if self.walkTrack: self.walkTrack.pause() self.walkTrack = None if self.currentPath: self.currentPath = None self.tutorial = None self.tutPartIndex = None self.avatarId = None DistributedSuitAI.delete(self) return def spawn(self): pos = TutorialGlobals.SUIT_POINTS[TutorialGlobals.SUIT_SPAWN_POINT] index = TutorialGlobals.SUIT_POINTS.index(pos) self.spawnPoint = index self.b_setSuitState(2, index, index) flyTrack = self.posInterval(3, pos, startPos=pos + (0, 0, 50)) flyTrack.start() self.track = Sequence() self.track.append(Wait(5.4)) self.track.append(Func(self.b_setAnimState, 'neutral')) self.track.append(Wait(1.0)) self.track.append(Func(self.startAI)) self.track.start() self.b_setParent(CIGlobals.SPRender) taskMgr.add(self.monitorHealth, self.uniqueName('monitorHealth')) def createPath(self, fromCurPos = False): durationFactor = 0.2 if not hasattr(self, 'currentPath'): self.currentPath = None if self.currentPath == None: path = random.choice(TutorialGlobals.SUIT_POINTS) self.currentPath = TutorialGlobals.SUIT_POINTS.index(path) startIndex = -1 else: if fromCurPos == False: startIndex = int(self.currentPath) else: startIndex = -1 self.currentPath += 1 if self.currentPath >= len(TutorialGlobals.SUIT_POINTS): self.currentPath = 0 path = TutorialGlobals.SUIT_POINTS[self.currentPath] endIndex = self.currentPath startPos = self.getPos(render) pathName = self.uniqueName('suitPath') self.walkTrack = NPCWalkInterval(self, path, startPos=startPos, name=pathName, durationFactor=durationFactor, fluid=1) self.walkTrack.setDoneEvent(self.walkTrack.getName()) self.acceptOnce(self.walkTrack.getDoneEvent(), self.createPath) self.walkTrack.start() self.b_setAnimState('walk') self.b_setSuitState(1, startIndex, endIndex) return def monitorHealth(self, task): if self.health <= 0: self.tutorial.sendUpdateToAvatarId(self.avatarId, 'suitNoHealth', [self.tutPartIndex]) if self.walkTrack: self.ignore(self.walkTrack.getDoneEvent()) self.walkTrack.pause() self.walkTrack = None self.b_setSuitState(0, -1, -1) currentAnim = SuitGlobals.getAnimByName(self.anim) self.clearTrack() base.taskMgr.remove(self.uniqueName('scwaa')) self.stopAttacks() if currentAnim: self.track = Sequence(Wait(currentAnim.getDeathHoldTime()), Func(self.killSuit)) self.track.start() else: self.killSuit() return Task.done else: return Task.cont def setSuit(self, plan, variant = 0): DistributedSuitAI.setSuit(self, plan, variant, self.tutorial) def closeSuit(self): DistributedSuitAI.closeSuit(self) self.tutorial.sendUpdateToAvatarId(self.avatarId, 'suitExploded', [self.tutPartIndex]) def startAttacks(self): base.taskMgr.doMethodLater(random.randint(*self.ATTACK_IVAL_RANGE), self.__doAttack, self.uniqueName('doAttack')) def __doAttack(self, task): base.taskMgr.remove(self.uniqueName('scwaa')) target = self.air.doId2do.get(self.avatarId) if not target: return task.done self.clearTrack() self.b_setSuitState(0, -1, -1) self.b_setAnimState('neutral') self.headsUp(target) attack = random.choice(self.suitPlan.getAttacks()) attackIndex = SuitAttacks.SuitAttackLengths.keys().index(attack) attackTaunt = random.randint(0, len(CIGlobals.SuitAttackTaunts[attack]) - 1) timestamp = globalClockDelta.getFrameNetworkTime() if self.isDead(): self.stopAttacks() return task.done self.sendUpdate('doAttack', [attackIndex, target.doId, timestamp]) self.d_setChat(CIGlobals.SuitAttackTaunts[attack][attackTaunt]) attackLength = SuitAttacks.SuitAttackLengths[attack] base.taskMgr.doMethodLater(attackLength, self.__suitContinueWalkAfterAttack, self.uniqueName('scwaa')) task.delayTime = random.randint(*self.ATTACK_IVAL_RANGE) return task.again def __suitContinueWalkAfterAttack(self, task): self.createPath(fromCurPos=True) return task.done def stopAttacks(self): base.taskMgr.remove(self.uniqueName('doAttack')) def startAI(self): if self.tutPartIndex == 0: self.b_setAnimState('neutral') elif self.tutPartIndex == 1: self.createPath() elif self.tutPartIndex == 2: self.createPath() self.startAttacks()
class SuitPathBehavior(SuitBehaviorBase): def __init__(self, suit, exitOnWalkFinish = True): SuitBehaviorBase.__init__(self, suit) self.walkTrack = None self.exitOnWalkFinish = exitOnWalkFinish self.isEntered = 0 return def unload(self): SuitBehaviorBase.unload(self) self.clearWalkTrack() del self.exitOnWalkFinish del self.walkTrack def createPath(self, pathKey = None, durationFactor = 0.2, fromCurPos = False): currentPathQueue = self.suit.getCurrentPathQueue() currentPath = self.suit.getCurrentPath() if pathKey == None: pathKeyList = CIGlobals.SuitPathData[self.suit.getHood()][self.suit.getCurrentPath()] pathKey = random.choice(pathKeyList) elif len(currentPathQueue): pathKey = currentPathQueue[0] currentPathQueue.remove(pathKey) endIndex = CIGlobals.SuitSpawnPoints[self.suit.getHood()].keys().index(pathKey) path = CIGlobals.SuitSpawnPoints[self.suit.getHood()][pathKey] self.clearWalkTrack() if not currentPath or fromCurPos: startIndex = -1 else: oldPath = currentPath startIndex = CIGlobals.SuitSpawnPoints[self.suit.getHood()].keys().index(oldPath) self.suit.currentPath = pathKey startPos = self.suit.getPos(render) pathName = self.suit.uniqueName('suitPath') self.walkTrack = NPCWalkInterval(self.suit, path, startPos=startPos, name=pathName, durationFactor=durationFactor, fluid=1) self.walkTrack.setDoneEvent(self.walkTrack.getName()) self.startFollow() self.suit.b_setSuitState(1, startIndex, endIndex) return def getDistance(self, point1, point2): return (point1.getXy() - point2.getXy()).length() def getPath(self, start_key, target_key, nodes): path = [] for node in nodes: if node.key == start_key: start_node = node elif node.key == target_key: target_node = node current_node = target_node while current_node.parent != start_node: path.append(current_node.key) current_node = current_node.parent path.append(start_key) return list(reversed(path)) def findPath(self, area, start_key, target_key): start_point = CIGlobals.SuitSpawnPoints[area][start_key] target_point = CIGlobals.SuitSpawnPoints[area][target_key] nodes = [] open_nodes = [] closed_nodes = [] for key, point in CIGlobals.SuitSpawnPoints[area].items(): g_cost = self.getDistance(point, start_point) h_cost = self.getDistance(point, target_point) node = Node(g_cost, h_cost, key, point) nodes.append(node) for node in nodes: if node.key == start_key: open_nodes.append(node) while len(open_nodes): f_cost_list = [] for node in open_nodes: f_cost_list.append(node.f_cost) lowest_f_cost = min(f_cost_list) current = None for node in open_nodes: if lowest_f_cost == node.f_cost: current = node open_nodes.remove(current) closed_nodes.append(current) if current.key == target_key: return self.getPath(start_key, target_key, nodes) neighbor_keys = CIGlobals.SuitPathData[area][current.key] for neighbor_key in neighbor_keys: isClosed = False for node in closed_nodes: if node.key == neighbor_key: isClosed = True break if isClosed: continue neighbor = None for node in nodes: if node.key == neighbor_key: neighbor = node break nm_cost_2_neighbor = current.g_cost + self.getDistance(current.point, neighbor.point) if neighbor not in open_nodes or nm_cost_2_neighbor < neighbor.g_cost: neighbor.g_cost = nm_cost_2_neighbor neighbor.h_cost = self.getDistance(target_point, neighbor.point) neighbor.f_cost = neighbor.g_cost + neighbor.h_cost neighbor.parent = current if neighbor not in open_nodes: open_nodes.append(neighbor) return def clearWalkTrack(self): if self.walkTrack: self.ignore(self.walkTrack.getDoneEvent()) self.walkTrack.clearToInitial() self.walkTrack = None if hasattr(self, 'suit'): self.suit.d_stopMoveInterval() return def startFollow(self): self.suit.b_setAnimState('walk') if self.walkTrack: self.acceptOnce(self.walkTrack.getName(), self.__walkDone) self.walkTrack.start() def __walkDone(self): self.clearWalkTrack() if not self.suit.isDead(): self.suit.b_setAnimState('neutral') if self.exitOnWalkFinish == True: self.exit() def getWalkTrack(self): return self.walkTrack def isWalking(self): if self.walkTrack: return self.walkTrack.isPlaying() return False
class DistributedTutorialSuitAI(DistributedSuitAI): notify = directNotify.newCategory('DistributedTutorialSuitAI') ATTACK_IVAL_RANGE = [3, 15] def __init__(self, air, index, tut, avatarId): DistributedSuitAI.__init__(self, air) self.tutPartIndex = index self.tutorial = tut self.avatarId = avatarId self.currentPath = None self.walkTrack = None def delete(self): base.taskMgr.remove(self.uniqueName('monitorHealth')) base.taskMgr.remove(self.uniqueName('doAttack')) base.taskMgr.remove(self.uniqueName('scwaa')) self.stopAttacks() if self.track: self.track.pause() self.track = None if self.walkTrack: self.walkTrack.pause() self.walkTrack = None if self.currentPath: self.currentPath = None self.tutorial = None self.tutPartIndex = None self.avatarId = None DistributedSuitAI.delete(self) def spawn(self): pos = TutorialGlobals.SUIT_POINTS[TutorialGlobals.SUIT_SPAWN_POINT] index = TutorialGlobals.SUIT_POINTS.index(pos) self.spawnPoint = index self.b_setSuitState(2, index, index) flyTrack = self.posInterval(3, pos, startPos=pos + (0, 0, 50)) flyTrack.start() self.track = Sequence() self.track.append(Wait(6.5)) self.track.append(Func(self.b_setAnimState, 'neutral')) self.track.append(Wait(1.0)) self.track.append(Func(self.startAI)) self.track.start() self.b_setParent(CIGlobals.SPRender) taskMgr.add(self.monitorHealth, self.uniqueName('monitorHealth')) def createPath(self, fromCurPos=False): durationFactor = 0.2 if not hasattr(self, 'currentPath'): self.currentPath = None if self.currentPath == None: path = random.choice(TutorialGlobals.SUIT_POINTS) self.currentPath = TutorialGlobals.SUIT_POINTS.index(path) startIndex = -1 else: if fromCurPos == False: startIndex = int(self.currentPath) else: startIndex = -1 self.currentPath += 1 if self.currentPath >= len(TutorialGlobals.SUIT_POINTS): self.currentPath = 0 path = TutorialGlobals.SUIT_POINTS[self.currentPath] endIndex = self.currentPath startPos = self.getPos(render) pathName = self.uniqueName('suitPath') self.walkTrack = NPCWalkInterval(self, path, startPos=startPos, name=pathName, durationFactor=durationFactor, fluid=1) self.walkTrack.setDoneEvent(self.walkTrack.getName()) self.acceptOnce(self.walkTrack.getDoneEvent(), self.createPath) self.walkTrack.start() self.b_setAnimState('walk') self.b_setSuitState(1, startIndex, endIndex) def monitorHealth(self, task): if self.health <= 0: self.tutorial.sendUpdateToAvatarId(self.avatarId, 'suitNoHealth', [self.tutPartIndex]) if self.walkTrack: self.ignore(self.walkTrack.getDoneEvent()) self.walkTrack.pause() self.walkTrack = None self.b_setSuitState(0, -1, -1) currentAnim = SuitGlobals.getAnimByName(self.anim) self.clearTrack() base.taskMgr.remove(self.uniqueName('scwaa')) self.stopAttacks() if currentAnim: self.track = Sequence(Wait(currentAnim.getDeathHoldTime()), Func(self.killSuit)) self.track.start() else: self.killSuit() return Task.done return Task.cont def setSuit(self, plan, variant=0): DistributedSuitAI.setSuit(self, plan, variant, self.tutorial) def closeSuit(self): DistributedSuitAI.closeSuit(self) self.tutorial.sendUpdateToAvatarId(self.avatarId, 'suitExploded', [self.tutPartIndex]) def startAttacks(self): base.taskMgr.doMethodLater(random.randint(*self.ATTACK_IVAL_RANGE), self.__doAttack, self.uniqueName('doAttack')) def __doAttack(self, task): base.taskMgr.remove(self.uniqueName('scwaa')) target = self.air.doId2do.get(self.avatarId) if not target: return task.done self.clearTrack() self.b_setSuitState(0, -1, -1) self.b_setAnimState('neutral') self.headsUp(target) # Choose a random attack and start it. attack = random.choice(self.suitPlan.getAttacks()) attackIndex = SuitAttacks.SuitAttackLengths.keys().index(attack) attackTaunt = random.randint( 0, len(CIGlobals.SuitAttackTaunts[attack]) - 1) timestamp = globalClockDelta.getFrameNetworkTime() if self.isDead(): self.stopAttacks() return task.done self.sendUpdate('doAttack', [attackIndex, target.doId, timestamp]) self.d_setChat(CIGlobals.SuitAttackTaunts[attack][attackTaunt]) attackLength = SuitAttacks.SuitAttackLengths[attack] base.taskMgr.doMethodLater(attackLength, self.__suitContinueWalkAfterAttack, self.uniqueName('scwaa')) task.delayTime = random.randint(*self.ATTACK_IVAL_RANGE) return task.again def __suitContinueWalkAfterAttack(self, task): self.createPath(fromCurPos=True) return task.done def stopAttacks(self): base.taskMgr.remove(self.uniqueName('doAttack')) def startAI(self): if self.tutPartIndex == 0: # This is part one, all we do is stand still and wait to die. self.b_setAnimState('neutral') elif self.tutPartIndex == 1: # This is part two, we just walk around and wait to die. self.createPath() elif self.tutPartIndex == 2: # This is part three, we walk around, attack a bit, and wait to die. self.createPath() self.startAttacks()