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()
def enterStationSlot(self, slot): self.cr.playGame.getPlace().fsm.request('station') camera.reparentTo(self) numSlots = len(self.circles) camera.setPos(self.numPlayers2CamPos[numSlots]) camera.setPos(camera.getPos(render)) camera.reparentTo(render) camera.lookAt(self) base.localAvatar.headsUp(slot) base.localAvatar.setAnimState('run') runTrack = NPCWalkInterval(base.localAvatar, slot.getPos(render), 0.1, startPos=base.localAvatar.getPos(render)) runTrack.setDoneEvent('SlotEnterDone') runTrack.start() base.acceptOnce('SlotEnterDone', self.__handleSlotEntrance)
def doPath(): global path if not len(path): suit.loop('neutral') return endX, endY = path[0] endPoint = Point3(endX, endY, 0) startPoint = suit.getPos(render) path.remove(path[0]) ival = NPCWalkInterval(suit, endPoint, 0.2, startPoint) ival.setDoneEvent(suit.uniqueName('guardWalkDone')) base.acceptOnce(suit.uniqueName('guardWalkDone'), doPath) ival.start() suit.loop('walk')
def enterStationSlot(self, slot): self.cr.playGame.getPlace().fsm.request('station') camera.reparentTo(self) numSlots = len(self.circles) camera.setPos(self.numPlayers2CamPos[numSlots]) camera.setPos(camera.getPos(render)) camera.reparentTo(render) camera.lookAt(self) base.localAvatar.headsUp(slot) base.localAvatar.b_setAnimState('run') runTrack = NPCWalkInterval(base.localAvatar, slot.getPos(render), 0.1, startPos=base.localAvatar.getPos(render)) runTrack.setDoneEvent('SlotEnterDone') runTrack.start() base.acceptOnce('SlotEnterDone', self.__handleSlotEntrance)
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 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 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 DistributedSuitAI(DistributedAvatarAI, DistributedSmoothNodeAI): notify = directNotify.newCategory("DistributedSuitAI") def __init__(self, air): try: self.DistributedSuitAI_initialized return except: self.DistributedSuitAI_initialized = 1 DistributedAvatarAI.__init__(self, air) DistributedSmoothNodeAI.__init__(self, air) self.itemDropper = SuitItemDropper(self) self.avatarType = CIGlobals.Suit self.aiChar = None self.aiBehaviors = None self.walkTrack = None self.name = "" self.anim = "neutral" self.state = "alive" self.damage = 0 self.health = 132 self.type = "A" self.team = "c" self.head = "bigcheese" self.name = "The Big Cheese" self.skeleton = 0 self.dmg_lbl = None self.lbl_int = None self.bean = None self.boss = None self.brain = None self.startPoint = -1 self.endPoint = -1 self.suitState = 0 self.walkPaused = 0 self.attacking = False self.suitHealTrack = None self.continuePathId = 0 self.attackId = 0 self.mgr = None self.backup = 0 self.difficulty = None self.track = None self.lateX = 0 self.lateY = 0 self.stateTimestamp = 0 self.animState2animId = { 'off': 13, 'neutral': 10, 'walk': 9, 'die': 5, 'attack': 7, 'flydown': 1, 'pie': 4, 'win': 12, 'flyaway': 14, 'rollodex': 3, 'flyNeutral': 15, 'flail': 0, 'drop': 6, 'drop-react': 16, 'squirt-large': 8, 'squirt-small': 11, 'soak': 2, } self.animId2animState = { v: k for k, v in self.animState2animId.items() } self.level = 0 self.currentPathQueue = [] return def resetPathQueue(self): self.currentPathQueue = [] def setLevel(self, level): self.level = level def d_setLevel(self, level): self.sendUpdate('setLevel', [level]) def b_setLevel(self, level): self.d_setLevel(level) self.setLevel(level) def getLevel(self): return self.level def setLatePos(self, x, y): self.lateX = x self.lateY = y def getLatePos(self): return [self.lateX, self.lateY] def setSuitState(self, index, startPoint, endPoint): if index == 0: self.setLatePos(self.getX(render), self.getY(render)) self.suitState = index self.startPoint = startPoint self.endPoint = endPoint def d_setSuitState(self, index, startPoint, endPoint): self.stateTimestamp = globalClockDelta.getFrameNetworkTime() self.sendUpdate('setSuitState', [index, startPoint, endPoint, self.stateTimestamp]) def b_setSuitState(self, index, startPoint, endPoint): self.d_setSuitState(index, startPoint, endPoint) self.setSuitState(index, startPoint, endPoint) def getSuitState(self): return [ self.suitState, self.startPoint, self.endPoint, self.stateTimestamp ] def setDifficulty(self, difficulty): self.difficulty = difficulty def getDifficulty(self): return self.difficulty def setBackup(self, backup): self.backup = backup def isBackup(self): return self.backup def setManager(self, mgr): self.mgr = mgr self.hood = CogBattleGlobals.HoodIndex2HoodName[ self.getManager().getBattle().getHoodIndex()] def getManager(self): return self.mgr def printPos(self, task): print self.getPos(render) print self.getHpr(render) return task.cont def spawn(self): self.brain = CogBrainAI.CogBrain(self) landspot = random.choice(CIGlobals.SuitSpawnPoints[self.hood].keys()) path = CIGlobals.SuitSpawnPoints[self.hood][landspot] index = CIGlobals.SuitSpawnPoints[self.hood].keys().index(landspot) self.b_setSuitState(2, index, index) self.currentPath = landspot track = self.posInterval(3, path, startPos=path + (0, 0, 50)) track.start() yaw = random.uniform(0.0, 360.0) self.setH(yaw) if self.track: self.track.pause() self.track = None self.track = Sequence(Wait(5.4), Func(self.b_setAnimState, 'neutral'), Wait(1.0), Func(self.startRoaming)) self.track.start() self.b_setParent(CIGlobals.SPRender) def startRoaming(self): if self.head == "vp" or self.isBackup(): # If this is a vp or a backup cog, do the random attacks. self.startAttacks() taskMgr.add(self.monitorHealth, self.uniqueName('monitorHealth')) if self.head == "vp": self.boss = SuitBoss.SuitBoss(self) self.boss.startBoss() else: self.brain.start() def startAttacks(self): if self.head != "vp": attackTime = random.randint(8, 20) else: attackTime = random.randint(8, 12) taskMgr.doMethodLater(attackTime, self.attackTask, self.uniqueName('attackTask')) def attackTask(self, task): if self.brain.fsm.getCurrentState().getName() == "runAway": # Attack while running away... ain't nobody got time for that! delay = random.randint(6, 12) task.delayTime = delay return task.again if self.head == "vp": # We can't attack while we're flying if not self.boss.getFlying(): self.chooseVictim() else: self.chooseVictim() if self.head != "vp": delay = random.randint(6, 15) else: delay = random.randint(6, 12) task.delayTime = delay return task.again def enableMovement(self): self.brain.start() if self.head != "vp": attackTime = random.randint(8, 20) else: attackTime = random.randint(8, 12) taskMgr.doMethodLater(attackTime, self.attackTask, self.uniqueName('attackTask')) def disableMovement(self): taskMgr.remove(self.uniqueName('attackTask')) taskMgr.remove(self.uniqueName('continueSuitRoam')) if self.suitHealTrack: self.suitHealTrack.pause() self.suitHealTrack = None self.brain.end() self.b_setSuitState(3, -1, -1) if self.head != "vp": if self.walkTrack: self.ignore(self.walkTrack.getName()) self.walkTrack.clearToInitial() self.walkTrack = None self.d_interruptAttack() def chooseVictim(self): toons = [] for key in self.air.doId2do.keys(): val = self.air.doId2do[key] if val.__class__.__name__ == "DistributedToonAI" or val.__class__.__name__ == "DistributedSuitAI" or val.__class__.__name__ == "DistributedPieTurretAI": if val.zoneId == self.zoneId: if val.__class__.__name__ == "DistributedSuitAI" and val.head == "vp" \ and val.doId != self.doId or val.__class__.__name__ == "DistributedToonAI" or val.__class__.__name__ == "DistributedPieTurretAI": # We can be a medic and heal the fellow VP... if not val.isDead(): if self.getDistance(val) <= 40: if val.__class__.__name__ == "DistributedToonAI": if not val.getGhost(): toons.append(val) else: toons.append(val) if toons == []: return toon = random.randint(0, len(toons) - 1) self.disableMovement() self.headsUp(toons[toon]) self.attackToon(toons[toon]) self.setAttacking(True) def attackToon(self, av): if av.__class__.__name__ in [ "DistributedSuitAI", "DistributedPieTurretAI" ]: # Why would I pick pocket my boss? attack = random.randint(0, 6) attackName = SuitAttacks.SuitAttackLengths.keys()[attack] else: if self.head in ['vp']: attack = random.randint(0, 6) attackName = SuitAttacks.SuitAttackLengths.keys()[attack] else: attackName = random.choice( SuitAttacks.SuitAttackLengths.keys()) attack = SuitAttacks.SuitAttackLengths.keys().index(attackName) attackTaunt = random.randint( 0, len(CIGlobals.SuitAttackTaunts[attackName]) - 1) timestamp = globalClockDelta.getFrameNetworkTime() self.sendUpdate('doAttack', [attack, av.doId, timestamp]) if av.__class__.__name__ in [ "DistributedSuitAI", "DistributedPieTurretAI" ]: distance = self.getDistance(av) speed = 50.0 if attackName == "glowerpower": speed = 100.0 timeUntilHeal = distance / speed if av.__class__.__name__ == "DistributedSuitAI": self.d_setChat(CIGlobals.SuitHealTaunt) else: self.d_setChat( CIGlobals.SuitAttackTaunts[attackName][attackTaunt]) if attackName != "glowerpower": if self.type == "C": timeUntilRelease = 2.2 else: timeUntilRelease = 3.0 else: timeUntilRelease = 1.0 currentBossPos = av.getPos(render) hp = int(self.maxHealth / SuitAttacks.SuitAttackDamageFactors[attackName]) self.suitHealTrack = Sequence( Wait(timeUntilRelease + timeUntilHeal), Func(self.attemptToHealBoss, av, currentBossPos, hp)) self.suitHealTrack.start() else: self.d_setChat(CIGlobals.SuitAttackTaunts[attackName][attackTaunt]) time = SuitAttacks.SuitAttackLengths[attackName] if self.track: self.track.pause() self.track = None taskMgr.doMethodLater(SuitAttacks.SuitAttackLengths[attackName], self.continuePathTask, self.uniqueName('continueSuitRoam')) def attemptToHealBoss(self, boss, currBossPos, hp): if not boss.isEmpty(): if (boss.getPos(render) - currBossPos).length() <= 1: if not boss.isDead(): if boss.__class__.__name__ == "DistributedSuitAI": boss.b_setHealth(boss.getHealth() + hp) boss.d_announceHealth(1, hp) else: # Turret boss.b_setHealth(boss.getHealth() - hp) boss.d_announceHealth(0, hp) self.d_handleWeaponTouch() def continuePathTask(self, task): self.setAttacking(False) if self.head != "vp": if self.brain.fsm.getCurrentState().getName() == "followBoss": # If we're protecting the boss, don't walk away from him! return task.done else: self.brain.neutral_startLookingForToons() self.brain.start() return task.done self.continuePath() return task.done def d_handleWeaponTouch(self): self.sendUpdate("handleWeaponTouch", []) def continuePath(self): # Create a new path for the Suit if they are stuck... if self.head != "vp": if self.walkTrack: self.ignore(self.walkTrack.getName()) self.walkTrack.clearToInitial() self.walkTrack = None self.brain.end() self.brain.start() else: self.b_setAnimState("neutral") def setAttacking(self, value): self.attacking = value def getAttacking(self): return self.attacking def monitorHealth(self, task): if self.health <= 0: taskMgr.remove(self.uniqueName('attackTask')) taskMgr.remove(self.uniqueName('continueSuitRoam')) if self.suitHealTrack: self.suitHealTrack.pause() self.suitHealTrack = None self.b_setSuitState(3, -1, -1) if self.walkTrack: self.ignore(self.walkTrack.getName()) self.walkTrack.clearToInitial() self.walkTrack = None self.d_interruptAttack() self.brain.end() if self.head == "vp": self.boss.stopBoss() if self.track: self.track.pause() self.track = None anim2WaitTime = { 'pie': 2.0, 'drop': 6.0, 'drop-react': 3.5, 'squirt-small': 4.0, 'squirt-large': 4.9, 'soak': 6.5, 'neutral': 0.0, 'walk': 0.0 } self.track = Sequence(Wait(anim2WaitTime[self.getAnimStateStr()]), Func(self.killSuit)) self.track.start() return task.done return task.cont def isWalking(self): if self.walkTrack: return self.walkTrack.isPlaying() else: return False def killSuit(self): self.b_setAnimState('die') if self.track: self.track.pause() self.track = None self.track = Sequence(Wait(6.0), Func(self.closeSuit)) self.track.start() def closeSuit(self): # Drop the jellybeans I stole before I die! self.itemDropper.drop() self.getManager().deadSuit(self.doId) self.disable() self.requestDelete() def createPath(self, path_key=None, durationFactor=0.2, fromCurPos=False): if path_key == None and not len(self.currentPathQueue): path_key_list = CIGlobals.SuitPathData[self.hood][self.currentPath] path_key = random.choice(path_key_list) elif len(self.currentPathQueue): path_key = self.currentPathQueue[0] self.currentPathQueue.remove(path_key) endIndex = CIGlobals.SuitSpawnPoints[self.hood].keys().index(path_key) path = CIGlobals.SuitSpawnPoints[self.hood][path_key] if self.walkTrack: self.ignore(self.walkTrack.getDoneEvent()) self.walkTrack.clearToInitial() self.walkTrack = None if not self.currentPath or fromCurPos: startIndex = -1 else: oldPath = self.currentPath startIndex = CIGlobals.SuitSpawnPoints[self.hood].keys().index( oldPath) self.currentPath = path_key pathName = self.uniqueName('suitPath') self.walkTrack = NPCWalkInterval(self, path, startPos=self.getPos(render), name=pathName, durationFactor=durationFactor, fluid=1) self.walkTrack.setDoneEvent(self.walkTrack.getName()) self.startFollow() self.b_setSuitState(1, startIndex, endIndex) def startFollow(self): #self.b_setAnimState('walk') if self.walkTrack: self.acceptOnce(self.walkTrack.getName(), self.walkDone) self.walkTrack.start() def walkDone(self): if self.walkTrack: self.walkTrack.finish() self.walkTrack = None self.b_setAnimState('neutral') self.createPath() def toonHitByWeapon(self, weaponId, avId): sender = self.air.getMsgSender() weapon = SuitAttacks.SuitAttackLengths.keys()[weaponId] if not weapon in [ "pickpocket", "fountainpen", "hangup", "buzzword", "razzledazzle", "jargon", "mumbojumbo", 'doubletalk', 'schmooze', 'fingerwag', 'filibuster' ]: self.d_handleWeaponTouch() dmg = int(self.maxHealth / SuitAttacks.SuitAttackDamageFactors[weapon]) toon = self.air.doId2do.get(avId, None) if toon: hp = toon.getHealth() - dmg if hp < 0: hp = 0 toon.b_setHealth(hp) toon.d_announceHealth(0, dmg) if toon.isDead(): self.b_setAnimState('win') taskMgr.remove(self.uniqueName('continueSuitRoam')) taskMgr.doMethodLater(6.0, self.continuePathTask, self.uniqueName('continueSuitRoam')) def turretHitByWeapon(weaponId, avId): weapon = SuitAttacks.SuitAttackLengths.keys()[weaponId] if not weapon in ["pickpocket", "fountainpen", "hangup"]: self.d_handleWeaponTouch() dmg = int(self.maxHealth / CIGlobals.SuitAttackDamageFactors[weapon]) turret = self.air.doId2do.get(avId, None) if turret: turret.b_setHealth(turret.getHealth() - 1) turret.d_announceHealth(0, dmg) def setSuit(self, suitType, head, team, skeleton): self.type = suitType self.head = head self.team = team self.skeleton = skeleton self.health = CIGlobals.getSuitHP(self.level) self.maxHealth = self.health self.itemDropper.calculate() def b_setSuit(self, suitType, head, team, skeleton): self.d_setSuit(suitType, head, team, skeleton) self.setSuit(suitType, head, team, skeleton) def d_setSuit(self, suitType, head, team, skeleton): self.sendUpdate("setSuit", [suitType, head, team, skeleton]) def getSuit(self): return tuple((self.type, self.head, self.team, self.skeleton)) def setAnimState(self, anim): self.anim = anim def b_setAnimState(self, anim): if type(anim) == types.StringType: anim = self.animState2animId[anim] self.d_setAnimState(anim) self.setAnimState(anim) def d_setAnimState(self, anim): timestamp = globalClockDelta.getFrameNetworkTime() self.sendUpdate("setAnimState", [anim, timestamp]) def getAnimState(self): return self.anim def getAnimStateStr(self): return self.animId2animState[self.getAnimState()] def d_interruptAttack(self): self.sendUpdate("interruptAttack", []) def d_setAttack(self, attack): self.sendUpdate("setAttack", [attack]) def announceGenerate(self): DistributedAvatarAI.announceGenerate(self) if self.track: self.track.pause() self.track = None Sequence(Wait(0.1), Func(self.spawn)).start() def generate(self): DistributedAvatarAI.generate(self) DistributedSmoothNodeAI.generate(self) def disable(self): try: self.DistributedSuitAI_disabled except: self.DistributedSuitAI_disabled = 1 if self.track: self.track.pause() self.track = None taskMgr.remove(self.uniqueName('monitorHealth')) taskMgr.remove(self.uniqueName('attackTask')) taskMgr.remove(self.uniqueName('continueSuitRoam')) if self.suitHealTrack: self.suitHealTrack.pause() self.suitHealTrack = None if self.walkTrack: self.ignore(self.walkTrack.getName()) self.walkTrack.clearToInitial() self.walkTrack = None if self.boss: self.boss.stopBoss() self.boss = None if self.brain: self.brain.end() self.brain = None self.itemDropper.cleanup() self.itemDropper = None self.aiChar = None self.aiBehaviors = None self.continuePathId = None self.attackId = None self.name = None self.anim = None self.state = None self.damage = None self.health = None self.backup = None self.type = None self.team = None self.head = None self.skeleton = 0 self.dmg_lbl = None self.currentPath = None self.lbl_int = None self.bean = None self.avatarType = None self.lateX = None self.lateY = None self.currentPathQueue = None DistributedAvatarAI.disable(self) return def delete(self): try: self.DistributedSuitAI_deleted except: self.DistributedSuitAI_deleted = 1 del self.aiChar del self.brain del self.aiBehaviors del self.boss del self.continuePathId del self.attackId del self.name del self.anim del self.state del self.damage del self.health del self.type del self.team del self.head del self.skeleton del self.dmg_lbl del self.lbl_int del self.bean del self.currentPath del self.avatarType del self.walkTrack del self.suitHealTrack del self.backup del self.lateX del self.lateY del self.currentPathQueue DistributedAvatarAI.delete(self) DistributedSmoothNodeAI.delete(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 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()