def watchMood(self): ''' Go left to right, try to vertically align with the player, then try to bite or fire beam. Roar every now and again. ''' p = system.engine.player while True: # why is this necessary? O_o #self.interruptable = True #self._state = None s = 0 #used to increase stare chance for n in range(ika.Random( 6, 12)): #min 6 attacks before next roar state if s >= 20: s -= 10 c = ika.Random(0, 100) + s if c < 75: s = 0 x = self.x + self.ent.hotwidth / 2 d = dir.fromDelta(p.x - x, 0) yield self.moveState(d, abs(p.x - x)) if c > 30: yield self.biteState() else: s = 40 #increase chance of staring again if just stared for multiple shots yield self.stareState() if ika.Random(0, 100) > 40: #extra stare state! yield self.stareState() yield self.roarState()
def defaultState(self): p = system.engine.player self.anim = 'grow' while not self._animator.kill: if not self.creator: self.check = False break yield None self.anim = 'die' yield None while not self._animator.kill: if self.ent.specframe == 3 and self.creator in engine.entities: if not self.hit and self.check: ents = self.detectCollision( (0, 0, self.ent.hotwidth, self.ent.hotheight)) for e in ents: if e is p: p.hurt( self.damage, self.recoil, dir.fromDelta(self.creator.x - p.x, self.creator.y - p.y)) self.hit = True yield None engine.destroyEntity(self)
def attackMood(self): ATTACK_RANGE = 150 p = system.engine.player def calcDist(pt): return math.hypot(pt[0] - self.x, pt[1] - self.y) oldx = self.x oldy = self.y curspot = None # sniping position to move to while True: # Archers are inexplicably only able to aim in the four cardinal directions. # That means there are four places the goblin wants to be. # (either directly above, below, or to the side of the player) # Find the closest one and head toward it. # If close enough to a happy spot, start shooting. if (self.x == oldx and self.y == oldy) or curspot is None: spots = ( (p.x, self.y), (self.x, p.y), ) dist = map(calcDist, spots) min_dist = min(dist) curspot = spots[dist.index(min(dist))] else: min_dist = calcDist(curspot) oldx = self.x oldy = self.y if min_dist <= 8: # FIXME: because of this, goblins will shoot diagonally. Is this okay? d = dir.fromDelta(p.x - self.x, p.y - self.y) curspot = None yield self.attackState(d) yield self.idleState(60) else: d = dir.fromDelta(curspot[0] - self.x, curspot[1] - self.y) yield self.walkState(d, 8)
def fleeMood(self): MIN_DIST = 150 p = system.engine.player for q in range(5): d = dir.fromDelta(p.x - self.x, p.y - self.y) dist = math.hypot(p.x - self.x, p.y - self.y) if dist > MIN_DIST: break yield self.walkState(dir.invert[d], MIN_DIST - dist) self.mood = self.passiveMood yield self.idleState()
def attackMood(self): # if we want to be uber, we can remove this hack. # for now fuckit. Attack the player!! p = system.engine.player for q in range(5): d = dir.fromDelta(p.x - self.x, p.y - self.y) dist = math.hypot(p.x - self.x, p.y - self.y) if dist < 40: yield self.attackState(d) yield self.idleState(40) else: yield self.walkState(d, min(30, dist))
def attackMood(self): # if we want to be uber, we can remove this hack. # for now fuckit. Attack the player!! p = system.engine.player for q in range(5): # compensate for the yeti's gigantic sprite: sx = self.x + 16 sy = self.y + 16 d = dir.fromDelta(p.x - sx, p.y - sy) dist = math.hypot(p.x - sx, p.y - sy) if dist < 50: yield self.attackState(d) yield self.idleState(20 + ika.Random(0, 20)) else: yield self.walkState(d, min(90, dist))
def walkState(self, direction, dist): ox, oy = self.x, self.y self.move(direction, dist) self.anim = 'walk' yield None while self.moving: ents = self.detectCollision((0, 0, self.ent.hotwidth, self.ent.hotheight)) for e in ents: if isinstance(e, player.Player): d = max(1, self.stats.att - e.stats.pres) e.hurt(d, 150, dir.fromDelta(e.x - ox, e.y - oy)) self.stop() break if (ox, oy) == (self.x, self.y): break yield None self.stop()
def attackMood(self): # if we want to be uber, we can remove this hack. # for now fuckit. Attack the player!! p = system.engine.player for q in range(5): d = dir.fromDelta(p.x - self.x, p.y - self.y) dist = math.hypot(p.x - self.x, p.y - self.y) if dist <= 32: #attack range! yield self.attackState(d) yield self.idleState(20) else: #attempt to move closer r= ika.Random(0,8) if r>=6: yield self.walkState(dir.rotateCounterCW[d], min(30, dist)) elif r>=4: yield self.walkState(dir.rotateCW[d], min(30, dist)) else: yield self.walkState(d, min(30, dist))
def attackMood(self): p = engine.player self.anim = 'idle' cnt = 0 while True: dist = math.hypot(p.x - self.x, p.y - self.y) if dist < 40: yield self.attackState( dir.fromDelta(p.x - self.x, p.y - self.y)) if cnt >= 500: self.mood = self.submergeMood yield self.idleState() break else: cnt += 1 yield self.idleState(1)
def playerDir(self): p = system.engine.player return dir.fromDelta(p.x - self.x - 10, p.y - self.y - 7)
def boltState(self): self.stop() self.anim = 'thrust' costperhit=6 if self.stats.mp < costperhit or not self.stats.bolt: sound.menuBuzz.Play() return for i in range(8): #8 cycle delay before attack starts yield None offsetx = offsety = 0 #hack, should use a dict but lazy if self.direction == dir.DOWN: offsetx=8 offsety=30 elif self.direction == dir.UP: offsetx=5 offsety=-25 elif self.direction in [dir.RIGHT, dir.UPRIGHT, dir.DOWNRIGHT]: offsetx=34 offsety=-2 elif self.direction in [dir.LEFT, dir.UPLEFT, dir.DOWNLEFT]: offsetx=-24 offsety=-2 ents = self.detectCollision(( -96, -96, 192, 192, self.layer )) #costmp=False self.invincible=True destroyents = [] n=0 for e in ents: if e and (isinstance(e, Enemy) and not e.invincible) or isinstance(e, IceWall) or isinstance(e, Crystal): if self.stats.mp>=costperhit: self.stats.mp -= costperhit else: sound.menuBuzz.Play() break #if not costmp: # costmp=True # self.stats.mp -= costperhit if isinstance(e, Enemy): d = dir.invert[dir.fromDelta(self.x - e.x, self.y - e.y)] if(isinstance(e, Serpent)): #he resists, half damage to prevent bolt spam! e.hurt( int( ((self.stats.att + self.stats.mag) + ika.Random(1, int(self.stats.mag))) / 2), 300, d) else: e.hurt(int(self.stats.att + self.stats.mag) + ika.Random(1, int(self.stats.mag)), 300, d) elif isinstance(e, IceWall) or isinstance(e, Crystal): setattr(savedata, e.flagName, 'True') destroyents.append(e) system.engine.addThing(Bolt(self.x+offsetx, self.y+offsety, e.x+(e.ent.hotwidth/2), e.y+(e.ent.hotheight/2), ika.RGB(240,40,128) )) system.engine.addThing(Nova(self.x+offsetx, self.y+offsety, 0.5, 24, speed=0.5, color = ika.RGB(240, 100, 128, 255), filled=True )) system.engine.addThing(Nova(e.x+(e.ent.hotwidth/2), e.y+(e.ent.hotheight/2), 0.5, 24, speed=0.5, color = ika.RGB(240, 100, 128, 255), filled=True )) #if n % 3==0: #sound.boltStorm.StopAllSounds() sound.boltStorm.Play() #only play sound every 4 to minimize noise n+=1 for i in range(5): #wait a few frames before attacking next enemy yield None for e in destroyents: system.engine.destroyEntity(e) self.stop() self.invincible=False for i in range(40): yield None