def reload_animation(self): if SETTINGS.held_ammo[self.ammo_type] > 0 or SETTINGS.unlimited_ammo: #Change sprite list to reload. if self.current_img not in self.reload: self.current_img = self.reload[0] SOUND.play_sound(random.choice(self.sounds['magout']), 0) self.reload_busy = True #Make sure the magazine is out of view for some time. if (self.current_img == self.reload[3] and self.timer > self.rlspeed) or (self.current_img != self.reload[-1] and self.current_img != self.reload[3] and self.timer >= 0.15): x = self.reload.index(self.current_img) + 1 self.current_img = self.reload[x] self.timer = 0 elif self.current_img == self.reload[-1] and self.timer >= 0.15: #Done reloading self.current_img = self.aim[0] self.reload_busy = False self.timer = 0 SOUND.play_sound(random.choice(self.sounds['magin']), 0) #Change actual ammo if not SETTINGS.unlimited_ammo: taken_ammo = self.mag_size - self.current_mag if SETTINGS.held_ammo[self.ammo_type] >= taken_ammo: self.current_mag = self.mag_size SETTINGS.held_ammo[self.ammo_type] -= taken_ammo elif SETTINGS.held_ammo[self.ammo_type] < taken_ammo: self.current_mag = SETTINGS.held_ammo[ self.ammo_type] + self.current_mag SETTINGS.held_ammo[self.ammo_type] = 0 else: self.current_mag = self.mag_size
def do_call_for_help(self, number_of_allies): if self.can_call_for_help(): SOUND.play_sound(self.sounds['spot'], self.dist_from_player) self.seen_player() self.add_message("calling for backup") self.call_allies(id(self), number_of_allies, "hostile", SEARCHING, self.last_seen_player_position) return True return False
def get_clicked(self): if self.rect.collidepoint(pygame.mouse.get_pos()): if pygame.mouse.get_pressed()[0]: self.clicked = True if not pygame.mouse.get_pressed()[0] and self.clicked: self.clicked = False SOUND.play_sound(self.sound, 0) return True else: return False else: return False
def damage(self): if SETTINGS.middle_slice_len: target_npcs = [x for x in SETTINGS.npc_list if x.hit_rect.colliderect(self.hit_rect) and x.dist < SETTINGS.middle_slice_len] else: target_npcs = [x for x in SETTINGS.npc_list if x.hit_rect.colliderect(self.hit_rect)] if len(target_npcs) > 3: target_npcs = sorted(target_npcs, key=lambda x: x.sprite.theta)[:3] for npc in target_npcs: if npc.dist <= self.range and not npc.dead: if npc.dist <= SETTINGS.tile_size*2: cap = 100 else: cap = (self.hit_percent * 0.96 ** (npc.dist*((100-self.hit_percent)/100))) if cap >= random.randint(0,int(npc.dist*(1/self.range))): SOUND.play_sound(self.hit_marker, 0) #Damage less if NPC is far away from center. if self.hit_rect.width < 120 or (npc.hit_rect.centerx > self.hit_rect.left + self.hit_rect.width/3 and npc.hit_rect.centerx < self.hit_rect.right - self.hit_rect.width/3): #Critical hit if (npc.state == 'idle' or npc.state == 'patrouling') and not npc.player_in_view: npc.health -= self.dmg * 2 SETTINGS.statistics['last ddealt'] += self.dmg*2 else: npc.health -= self.dmg SETTINGS.statistics['last ddealt'] += self.dmg else: if (npc.state == 'idle' or npc.state == 'patrouling') and not npc.player_in_view: npc.health -= self.dmg SETTINGS.statistics['last ddealt'] += self.dmg*2 else: npc.health -= self.dmg / 2 SETTINGS.statistics['last ddealt'] += self.dmg npc.timer = 0 npc.hurting = True if npc.health <= 0: npc.knockback = self.dmg * (SETTINGS.tile_size/2)
def sesam_luk_dig_op(self): if self.open > SETTINGS.tile_size: self.open = SETTINGS.tile_size elif self.open < 0: self.open = 0 if self.state == 'closed': self.state = 'opening' elif self.state == 'opening': if self.open == 0: SOUND.play_sound(self.open_sound, self.distance) if self.open < SETTINGS.tile_size: self.open += SETTINGS.tile_size * SETTINGS.dt else: self.state = 'open' self.solid = False if self.open > SETTINGS.tile_size/1.4: self.solid = False elif self.state == 'open': self.timer += SETTINGS.dt if self.timer > 5 and not self.rect.colliderect(SETTINGS.player_rect): for i in SETTINGS.npc_list: if self.rect.colliderect(i.rect): break else: self.state = 'closing' self.solid = True self.timer = 0 elif self.state == 'closing': if self.open >= SETTINGS.tile_size: SOUND.play_sound(self.close_sound, self.distance) if self.open > 0: self.open -= SETTINGS.tile_size * SETTINGS.dt else: self.state = 'closed'
def __init__(self, name): """Construtor da classe :Param name: Nome do cômodo a ser criado :Type name: String """ self.__rooms = {} self.__port = None self.__name = name self.__numberOfPeoples = 0 self.__equipments = {} self.addEquipment("tv", TV()) self.addEquipment("som", SOUND()) self.__control = False self.__eventTimer = sched.scheduler(time.time, time.sleep) self.__cancelEventTimer = None
def control(self, canvas): #Make sure the collide list is complete if len(self.collide_list) != len(SETTINGS.all_solid_tiles + SETTINGS.npc_list): self.collide_list = SETTINGS.all_solid_tiles + SETTINGS.npc_list elif self.current_level != SETTINGS.current_level: self.collide_list = SETTINGS.all_solid_tiles + SETTINGS.npc_list self.current_level = SETTINGS.current_level elif self.update_collide_list: self.collide_list = SETTINGS.all_solid_tiles + SETTINGS.npc_list self.update_collide_list = False #Update health if self.health != SETTINGS.player_health and SETTINGS.player_states[ 'heal']: self.health = SETTINGS.player_health key = pygame.key.get_pressed() #Movement controls (WASD) if not SETTINGS.player_states['dead']: #Inventory open if not SETTINGS.player_states['invopen']: if SETTINGS.aiming: self.sensitivity = SETTINGS.sensitivity / 3 self.max_speed = SETTINGS.player_speed / 3 if self.speed > self.max_speed: self.speed = self.max_speed else: self.sensitivity = SETTINGS.sensitivity self.max_speed = SETTINGS.player_speed if key[pygame.K_a] or key[pygame.K_d] or key[ pygame.K_w] or key[pygame.K_s]: if self.speed < self.max_speed: self.speed += 50 if self.speed > self.max_speed: self.speed = self.max_speed else: if self.speed > 0: if self.last_call == 0: self.move(self.direction(90, self.speed * 0.8)) elif self.last_call == 1: self.move(self.direction(-90, self.speed * 0.8)) elif self.last_call == 2: self.move(self.direction(0, self.speed)) elif self.last_call == 3: self.move(self.direction(0, -self.speed * 0.5)) self.speed -= 80 if self.speed < 1: self.speed = 0 if key[pygame.K_a]: self.move(self.direction(90, self.speed * 0.8)) self.last_call = 0 if key[pygame.K_d]: self.move(self.direction(-90, self.speed * 0.8)) self.last_call = 1 if key[pygame.K_w]: self.move(self.direction(0, self.speed)) self.last_call = 2 if key[pygame.K_s]: self.move(self.direction(0, -self.speed * 0.5)) self.last_call = 3 SETTINGS.player_states['cspeed'] = self.speed #Shoot gun (Mouse input) if pygame.mouse.get_pressed()[2] and self.mouse2 < 1: SETTINGS.mouse2_btn_active = True self.mouse2 += 1 elif self.mouse2 >= 1: SETTINGS.mouse2_btn_active = False if not pygame.mouse.get_pressed()[2]: self.mouse2 = 0 if pygame.mouse.get_pressed( )[0] and not SETTINGS.player_states['dead']: SETTINGS.mouse_btn_active = True else: SETTINGS.mouse_btn_active = False if key[pygame.K_r]: SETTINGS.reload_key_active = True else: SETTINGS.reload_key_active = False #Change gun if key[pygame.K_1] and SETTINGS.inventory['primary']: SETTINGS.next_gun = SETTINGS.inventory['primary'] elif key[pygame.K_2] and SETTINGS.inventory['secondary']: SETTINGS.next_gun = SETTINGS.inventory['secondary'] elif key[pygame.K_3] and SETTINGS.inventory['melee']: SETTINGS.next_gun = SETTINGS.inventory['melee'] #Keep angle in place if self.angle >= 360: self.angle = 0 elif self.angle < 0: self.angle = 359 #Interact if key[pygame.K_e]: if SETTINGS.middle_slice: if SETTINGS.middle_slice_len <= SETTINGS.tile_size * 1.5 and ( SETTINGS.middle_slice.type == 'vdoor' or SETTINGS.middle_slice.type == 'hdoor'): SETTINGS.middle_slice.sesam_luk_dig_op() elif SETTINGS.middle_slice_len <= SETTINGS.tile_size and SETTINGS.middle_slice.type == 'end' and not SETTINGS.player_states[ 'fade']: SETTINGS.player_states['fade'] = True SETTINGS.changing_level = True SOUND.play_sound(self.change_level, 0) madd = self.mouse.get_rel()[0] * self.sensitivity if madd > 38: madd = 38 elif madd < -38: madd = -38 self.angle -= madd SETTINGS.player_angle = self.angle add_event_single(EVENT_PLAYER_VIEW_CHANGED, {'value': self.angle}) #Open inventory if key[pygame.K_i] and self.inventory < 1: if SETTINGS.player_states['invopen']: SETTINGS.player_states['invopen'] = False SETTINGS.inv_strings_updated = False else: SETTINGS.player_states['invopen'] = True self.inventory += 1 elif not key[pygame.K_i]: self.inventory = 0 #Use escape to close inventory if key[pygame.K_ESCAPE] and SETTINGS.player_states['invopen']: SETTINGS.player_states['invopen'] = False SETTINGS.inv_strings_updated = False self.dont_open_menu = True elif not key[ pygame.K_ESCAPE] and not SETTINGS.player_states['invopen']: self.dont_open_menu = False #Show menu if key[pygame.K_ESCAPE] and not self.dont_open_menu: self.esc_pressed = True elif self.esc_pressed and not self.dont_open_menu: SETTINGS.menu_showing = True self.esc_pressed = False #Is the player dead or taking damage? if self.health > SETTINGS.player_health: SETTINGS.statistics['last dtaken'] += (self.health - SETTINGS.player_health) self.health = SETTINGS.player_health SETTINGS.player_states['hurt'] = True SOUND.play_sound(self.hurt_sound, 0) if SETTINGS.player_health <= 0 and not SETTINGS.godmode: self.dead = True SETTINGS.player_states['dead'] = True if SETTINGS.player_health < 0: SETTINGS.player_health = 0 if SETTINGS.menu_showing or SETTINGS.player_states['invopen']: pygame.event.set_grab(False) self.mouse.set_visible(True) # elif key[pygame.K_q]: # pygame.event.set_grab(True) # self.mouse.set_visible(False) else: pygame.event.set_grab(True) self.mouse.set_visible(False)
def damage(self): if SETTINGS.middle_slice_len: target_npcs = [ x for x in SETTINGS.npc_list if x.hit_rect.colliderect(self.hit_rect) and x.dist < SETTINGS.middle_slice_len ] else: target_npcs = [ x for x in SETTINGS.npc_list if x.hit_rect.colliderect(self.hit_rect) ] if len(target_npcs) > 3: target_npcs = sorted(target_npcs, key=lambda x: x.sprite.theta)[:3] for npc in target_npcs: if npc.dist <= self.range and not npc.dead: if npc.dist <= SETTINGS.tile_size * 2: cap = 100 else: cap = (self.hit_percent * 0.96**(npc.dist * ((100 - self.hit_percent) / 100))) if cap >= random.randint(0, int(npc.dist * (1 / self.range))): SOUND.play_sound(self.hit_marker, 0) damage_to_be_done = self.dmg in_center = self.hit_rect.width < 120 or ( npc.hit_rect.centerx > self.hit_rect.left + self.hit_rect.width / 3 and npc.hit_rect.centerx < self.hit_rect.right - self.hit_rect.width / 3) #Damage less if NPC is far away from center. if in_center: #Critical hit if (npc.state == IDLE or npc.state == PATROLLING) and not npc.player_in_view: damage_to_be_done = damage_to_be_done * 2 else: pass else: if (npc.state == IDLE or npc.state == PATROLLING) and not npc.player_in_view: pass else: damage_to_be_done = damage_to_be_done / 2 if npc.side == SIDE_BACK and npc.state != ATTACKING: if in_center: if not npc.is_searching_for_player(): npc.add_message("instakill") damage_to_be_done = npc.health else: npc.add_message("I expected that attack") damage_to_be_done = damage_to_be_done * 1.5 SETTINGS.statistics['last ddealt'] += damage_to_be_done npc.health -= damage_to_be_done npc.timer = 0 npc.hurting = True if npc.health <= 0: npc.knockback = self.dmg * (SETTINGS.tile_size / 2)
def shoot_animation(self): if self.current_mag > 0 or self.guntype == 'melee': if self.firetimer >= self.firerate: #Hitscan gun animation if not self.aim_is_up and self.guntype != 'melee': #Hip fire if self.current_img not in self.hipfire: self.current_img = self.hipfire[random.randint(0, 1)] self.shoot_busy = True SOUND.play_sound(random.choice(self.sounds['shot']), 0) SETTINGS.screen_shake = self.dmg * 2 self.damage() self.timer = 0 elif self.hipfire.index( self.current_img ) <= 1 and self.timer >= self.shoottime: self.current_img = self.hipfire[-1] self.timer = 0 elif self.current_img == self.hipfire[ -1] and self.timer >= self.shoottime: self.current_img = self.aim[0] self.shoot_busy = False self.current_mag -= 1 SETTINGS.statistics['last shots'] += 1 if self.stats['magsize'] == 3.1415: self.current_mag -= 1 SETTINGS.statistics['last shots'] += 1 self.firetimer = 0 #Melee weapon animation elif self.guntype == 'melee': if self.current_img not in self.hipfire: self.current_img = self.hipfire[0] self.shoot_busy = True SOUND.play_sound(random.choice(self.sounds['shot']), 0) self.damage() self.timer = 0 elif self.hipfire.index( self.current_img ) < 2 and self.timer >= self.shoottime: self.current_img = self.hipfire[ self.hipfire.index(self.current_img) + 1] self.timer = 0 elif self.current_img == self.hipfire[ -1] and self.timer >= self.shoottime: self.current_img = self.aim[0] self.shoot_busy = False self.firetimer = 0 elif self.aim_is_up: #ADS fire if self.current_img not in self.aimdown: self.current_img = self.aimdown[random.randint(0, 1)] self.shoot_busy = True SOUND.play_sound(random.choice(self.sounds['shot']), 0) SETTINGS.screen_shake = self.dmg * 2 self.damage() self.timer = 0 elif self.aimdown.index( self.current_img ) <= 1 and self.timer >= self.shoottime: self.current_img = self.aimdown[-1] self.timer = 0 elif self.current_img == self.aimdown[ -1] and self.timer >= self.shoottime: self.current_img = self.aim[-1] self.shoot_busy = False self.current_mag -= 1 SETTINGS.statistics['last shots'] += 1 if self.stats['magsize'] == 3.1415: self.current_mag -= 1 SETTINGS.statistics['last shots'] += 1 self.firetimer = 0 else: if self.firetimer >= self.firerate: SOUND.play_sound(random.choice(self.sounds['click']), 0) self.firetimer = 0
def attack(self): if self.attack_move: self.move() else: if self.atcktype == 'melee': #Move close to player and keep attacking if self.dist <= SETTINGS.tile_size*0.7: self.set_path([]) self.moving = False if not self.attacking: if self.timer >= self.frame_interval * self.atckrate: self.attacking = True self.timer = 0 else: #Make the NPC not flinch when attacking if self.hurting: if random.randint(0,2) != 2 or self.attacking: self.animate(ATTACKING) self.hurting = False if random.randint(0,2) == 2: SOUND.play_sound(random.choice(self.sounds['damage']), self.dist) else: self.animate(ATTACKING) else: if self.dist_from_player > SETTINGS.tile_size * 0.7 and not self.has_a_path(): self.set_path_to_player() elif self.has_a_path(): try: if self.path[-1].map_pos != self.last_seen_player_position: near_conditions = [ self.dist_from_player <= (SETTINGS.render / 2) * SETTINGS.tile_size, random.randint(0, 5) == 5 ] if all(near_conditions): self.set_path_to_player() elif random.randint(0, 10) >= 8: self.set_path_to_player() else: self.move() except: pass elif self.atcktype == 'hitscan': # Move somewhat close to player and change position after attacking if self.dist_from_player <= SETTINGS.tile_size * self.range and ( self.dist_from_player >= SETTINGS.tile_size * 1.5 or ( SETTINGS.current_gun and SETTINGS.current_gun.guntype == 'melee')) and not self.attack_move: self.path = [] self.moving = False if not self.attacking: if random.randint(0, self.atckchance) == 5 and self.detect_player(): self.attacking = True self.atckchance += int(self.atckrate) self.movechance = 10 else: if random.randint(0, self.movechance) == 10: move_tile = PATHFINDING.find_walkable_tile_near_position(self.map_pos) self.set_path(move_tile.map_pos) self.attacking = False self.attack_move = True # This variable is to make sure the NPC doesn't just walk around without attacking. self.movechance += 3 self.atckchance = 5 # There is a chance the NPC will not flinch when shot while attacking elif self.attacking: if self.hurting: if random.randint(0,5) >= 3: self.animate(ATTACKING) self.hurting = False if random.randint(0,2) == 2: SOUND.play_sound(random.choice(self.sounds['damage']), self.dist) else: self.animate(ATTACKING) # Move away from player if too close elif self.dist_from_player < SETTINGS.tile_size * 1.5 and self.health <= 6: if self.rect.centerx > SETTINGS.player_rect.centerx: self.collide_update(self.speed, 0) self.animate(WALKING) elif self.rect.centerx < SETTINGS.player_rect.centerx: self.collide_update(-self.speed, 0) self.animate(WALKING) if self.rect.centery > SETTINGS.player_rect.centery: self.collide_update(0, self.speed) self.animate(WALKING) elif self.rect.centery < SETTINGS.player_rect.centery: self.collide_update(0, -self.speed) self.animate(WALKING) else: if not self.attack_move: if self.dist_from_player >= SETTINGS.tile_size * 2.5 and not self.has_a_path(): self.set_path_to_player() elif self.has_a_path(): try: if self.path[-1].map_pos != self.last_seen_player_position: near_conditions = [ self.dist_from_player <= (SETTINGS.render / 2) * SETTINGS.tile_size, random.randint(0, 5) == 5 ] if all(near_conditions): self.set_path_to_player() elif random.randint(0, 10) == 10: self.set_path_to_player() else: self.move() except: pass
def animate(self, animation): '''== Animate NPC ==\nanimation -> dying, walking, attacking, hurting''' if self.running_animation != animation: self.sprite.current_frame = 0 self.running_animation = animation #walk animation if animation == 'walking': self.sprite.texture = self.get_direction_texture()[self.sprite.current_frame] if self.timer >= self.frame_interval: self.sprite.last_frame = self.sprite.current_frame self.sprite.current_frame += 1 self.timer = 0 if self.sprite.current_frame == len(self.front_texture)-1: self.sprite.current_frame = 0 #die animation elif animation == 'dying': self.sprite.texture = self.die_texture[self.sprite.current_frame] if self.sprite.current_frame == 0 and not self.mein_leben: self.mein_leben = True SOUND.play_sound(random.choice(self.sounds['die']), self.dist) if self.timer >= self.frame_interval and self.sprite.current_frame < len(self.die_texture)-1: self.sprite.current_frame += 1 self.timer = 0 elif self.sprite.current_frame == len(self.die_texture)-1 and self.knockback == 0: self.dead = True self.drop_item() SETTINGS.statistics['last enemies'] += 1 elif self.knockback > 0: self.collide_update(-cos_radians(self.postheta)*self.knockback, 0) self.collide_update(0, sin_radians(self.postheta)*self.knockback) self.knockback = int(self.knockback*0.8) #hurt animation elif animation == 'hurting': self.sprite.texture = self.hurt_texture[0] self.moving = False if self.timer >= self.frame_interval*2: self.side = None self.hurting = False self.timer = 0 SOUND.play_sound(random.choice(self.sounds['damage']), self.dist_from_player) change_direction_conditions = [ self.state == IDLE, self.state == PATROLLING, self.state == FLEEING, self.state == SEARCHING, ] if any(change_direction_conditions): self.change_facing_direction() # attack animation elif animation == ATTACKING: # at the moment the only attack animation # is directly facing the player self.set_side(SIDE_FRONT) self.sprite.texture = self.hit_texture[self.sprite.current_frame] self.moving = False if self.timer >= self.frame_interval: self.sprite.current_frame += 1 self.timer = 0 if self.sprite.current_frame == len(self.hit_texture): SOUND.play_sound(self.sounds['attack'], self.dist) self.sprite.texture = self.stand_texture[0] self.sprite.current_frame = 0 self.attacking = False if random.randint(0,8) != 8: #A chance to miss if self.damage_player(): self.add_message("Did damage to player") self.seen_player() else: self.add_message("tried to attack but I don't have LOS?")
def animate(self, animation): '''== Animate NPC ==\nanimation -> dying, walking, attacking, hurting''' if self.running_animation != animation: self.current_frame = 0 self.running_animation = animation #walk animation if animation == 'walking': if self.side == 'front': self.sprite.texture = self.front_texture[self.current_frame] elif self.side == 'frontleft': self.sprite.texture = self.frontleft_texture[ self.current_frame] elif self.side == 'left': self.sprite.texture = self.left_texture[self.current_frame] elif self.side == 'backleft': self.sprite.texture = self.backleft_texture[self.current_frame] elif self.side == 'back': self.sprite.texture = self.back_texture[self.current_frame] elif self.side == 'backright': self.sprite.texture = self.backright_texture[ self.current_frame] elif self.side == 'right': self.sprite.texture = self.right_texture[self.current_frame] elif self.side == 'frontright': self.sprite.texture = self.frontright_texture[ self.current_frame] if self.timer >= self.frame_interval: self.current_frame += 1 self.timer = 0 if self.current_frame == len(self.front_texture) - 1: self.current_frame = 0 #die animation elif animation == 'dying': self.sprite.texture = self.die_texture[self.current_frame] if self.current_frame == 0 and not self.mein_leben: self.mein_leben = True SOUND.play_sound(random.choice(self.sounds['die']), self.dist) if self.timer >= self.frame_interval and self.current_frame < len( self.die_texture) - 1: self.current_frame += 1 self.timer = 0 elif self.current_frame == len( self.die_texture) - 1 and self.knockback == 0: self.dead = True self.drop_item() SETTINGS.statistics['last enemies'] += 1 elif self.knockback > 0: self.collide_update( -math.cos(math.radians(self.postheta)) * self.knockback, 0) self.collide_update( 0, math.sin(math.radians(self.postheta)) * self.knockback) self.knockback = int(self.knockback * 0.8) #hurt animation elif animation == 'hurting': self.sprite.texture = self.hurt_texture[0] self.moving = False if self.timer >= self.frame_interval * 2: self.side = None self.hurting = False self.timer = 0 SOUND.play_sound(random.choice(self.sounds['damage']), self.dist) if self.state == 'idle' or self.state == 'patrouling' or self.state == 'fleeing': self.face = self.face + self.theta if self.face >= 360: self.face -= 360 self.face = min([0, 90, 180, 270, 359], key=lambda x: abs(x - self.face)) #attack animation elif animation == 'attacking': self.sprite.texture = self.hit_texture[self.current_frame] self.moving = False if self.timer >= self.frame_interval: self.current_frame += 1 self.timer = 0 if self.current_frame == len(self.hit_texture): SOUND.play_sound(self.sounds['attack'], self.dist) self.sprite.texture = self.stand_texture[0] self.current_frame = 0 self.attacking = False if random.randint(0, 8) != 8: #A chance to miss if SETTINGS.player_armor > 0: SETTINGS.player_health -= int(self.dmg * 0.65) if SETTINGS.player_armor >= self.dmg * 2: SETTINGS.player_armor -= self.dmg * 2 else: SETTINGS.player_armor = 0 else: SETTINGS.player_health -= self.dmg
def attack(self): if self.attack_move: self.move() else: if self.atcktype == 'melee': #Move close to player and keep attacking if self.dist <= SETTINGS.tile_size * 0.7: self.path = [] self.moving = False if not self.attacking: if self.timer >= self.frame_interval * self.atckrate: self.attacking = True self.timer = 0 else: #Make the NPC not flinch when attacking if self.hurting: if random.randint(0, 2) != 2 or self.attacking: self.animate('attacking') self.hurting = False if random.randint(0, 2) == 2: SOUND.play_sound( random.choice(self.sounds['damage']), self.dist) else: self.animate('attacking') else: if self.dist > SETTINGS.tile_size*0.7 and self.path == []: self.path_progress = 0 self.path = PATHFINDING.pathfind( self.map_pos, SETTINGS.player_map_pos) elif self.path != []: try: if self.path[-1].map_pos != SETTINGS.player_map_pos: if self.dist <= ( SETTINGS.render / 2 ) * SETTINGS.tile_size and random.randint( 0, 5) == 5: self.path_progress = 0 self.path = PATHFINDING.pathfind( self.map_pos, SETTINGS.player_map_pos) elif random.randint(0, 10) >= 8: self.path_progress = 0 self.path = PATHFINDING.pathfind( self.map_pos, SETTINGS.player_map_pos) else: self.move() except: pass elif self.atcktype == 'hitscan': #Move somewhat close to player and change position after attacking if self.dist <= SETTINGS.tile_size * self.range and ( self.dist >= SETTINGS.tile_size * 1.5 or (SETTINGS.current_gun and SETTINGS.current_gun.guntype == 'melee')) and not self.attack_move: self.path = [] self.moving = False if not self.attacking: if random.randint( 0, self.atckchance) == 5 and self.detect_player(): self.attacking = True self.atckchance += int(self.atckrate) self.movechance = 10 else: if random.randint(0, self.movechance) == 10: move_pos = random.choice([ x for x in SETTINGS.walkable_area if (x.map_pos[0] <= self.map_pos[0] + 1 and x.map_pos[0] >= self.map_pos[0] - 1 ) and (x.map_pos[1] <= self.map_pos[1] + 1 and x.map_pos[1] >= self.map_pos[1] - 1) ]) self.path_progress = 0 self.path = PATHFINDING.pathfind( self.map_pos, move_pos.map_pos) self.attacking = False self.attack_move = True #This variable is to make sure the NPC doesn't just walk around without attacking. self.movechance += 3 self.atckchance = 5 #There is a chance the NPC will not flinch when shot while attacking elif self.attacking: if self.hurting: if random.randint(0, 5) >= 3: self.animate('attacking') self.hurting = False if random.randint(0, 2) == 2: SOUND.play_sound( random.choice(self.sounds['damage']), self.dist) else: self.animate('attacking') #Move away from player if too close elif self.dist < SETTINGS.tile_size * 1.5 and self.health <= 6: if self.rect.centerx > SETTINGS.player_rect.centerx: self.collide_update(self.speed, 0) self.animate('walking') elif self.rect.centerx < SETTINGS.player_rect.centerx: self.collide_update(-self.speed, 0) self.animate('walking') if self.rect.centery > SETTINGS.player_rect.centery: self.collide_update(0, self.speed) self.animate('walking') elif self.rect.centery < SETTINGS.player_rect.centery: self.collide_update(0, -self.speed) self.animate('walking') else: if not self.attack_move: if self.dist >= SETTINGS.tile_size * 2.5 and self.path == []: self.path_progress = 0 self.path = PATHFINDING.pathfind( self.map_pos, SETTINGS.player_map_pos) elif self.path != []: try: if self.path[ -1].map_pos != SETTINGS.player_map_pos: if self.dist <= ( SETTINGS.render / 2 ) * SETTINGS.tile_size and random.randint( 0, 5) == 5: self.path_progress = 0 self.path = PATHFINDING.pathfind( self.map_pos, SETTINGS.player_map_pos) elif random.randint(0, 10) == 10: self.path_progress = 0 self.path = PATHFINDING.pathfind( self.map_pos, SETTINGS.player_map_pos) else: self.move() except: pass
def think(self): self.map_pos = [ int(self.rect.centerx / SETTINGS.tile_size), int(self.rect.centery / SETTINGS.tile_size) ] if self.state == 'attacking' or self.state == 'fleeing': self.speed = self.OG_speed * 2 if not self.dead: self.timer += SETTINGS.dt self.update_timer += SETTINGS.dt if self.update_timer >= 2: self.update_timer = 0 if not self.dead and self.health > 0 and not SETTINGS.player_states[ 'dead']: self.render() if self.dist and self.dist <= SETTINGS.render * SETTINGS.tile_size * 1.2: #PASSIVE if self.mind == 'passive': if self.state == 'idle': self.idle() elif self.state == 'patrouling': self.move() #HOSTILE elif self.mind == 'hostile': if self.state == 'idle': self.idle() if not SETTINGS.ignore_player: if self.player_in_view: if self.detect_player(): self.path = [] SOUND.play_sound(self.sounds['spot'], self.dist) self.state = 'attacking' elif self.state == 'patrouling': if self.player_in_view and not SETTINGS.ignore_player and self.detect_player( ): self.path = [] SOUND.play_sound(self.sounds['spot'], self.dist) self.state = 'attacking' elif self.dist <= SETTINGS.tile_size / 2 and not SETTINGS.ignore_player: state = 'attacking' else: self.move() elif self.state == 'attacking': self.attack() #SHY elif self.mind == 'shy': if self.state == 'idle': self.idle() if not SETTINGS.ignore_player: if self.player_in_view: if self.detect_player(): self.path = [] SOUND.play_sound(self.sounds['spot'], self.dist) self.state = 'fleeing' elif self.dist <= SETTINGS.tile_size / 2: state = 'attacking' elif self.state == 'patrouling': if self.player_in_view: if not SETTINGS.ignore_player: if self.detect_player(): self.path = [] SOUND.play_sound(self.sounds['spot'], self.dist) self.state = 'fleeing' elif self.dist <= SETTINGS.tile_size / 2: if not SETTINGS.ignore_player: state = 'attacking' else: self.move() elif self.state == 'fleeing': self.move() #Run animations if self.hurting: self.animate('hurting') elif self.moving: self.animate('walking') if SETTINGS.player_states['dead']: self.face += 10 if self.face >= 360: self.face -= 360 self.render() elif self.health <= 0 and not self.dead: self.animate('dying') self.render()
def update(self): remove = False if self.rect: if SETTINGS.player_rect.colliderect(self.rect): if self.item_type == 'health': if SETTINGS.player_health < 100: SETTINGS.player_health += self.effect if SETTINGS.player_health > 100: SETTINGS.player_health = 100 SETTINGS.player_states['heal'] = True remove = True elif self.item_type == 'armor': if SETTINGS.player_armor < 100: SETTINGS.player_armor += self.effect if SETTINGS.player_armor > 100: SETTINGS.player_armor = 100 SETTINGS.player_states['armor'] = True remove = True elif self.item_type == 'bullet' or self.item_type == 'shell' or self.item_type == 'ferromag': if SETTINGS.held_ammo[self.item_type] < SETTINGS.max_ammo[ self.item_type]: SETTINGS.held_ammo[self.item_type] += self.effect if SETTINGS.held_ammo[ self.item_type] > SETTINGS.max_ammo[ self.item_type]: SETTINGS.held_ammo[ self.item_type] = SETTINGS.max_ammo[ self.item_type] #Same effect as armor SETTINGS.player_states['armor'] = True remove = True elif self.item_type == 'primary': if not SETTINGS.inventory['primary']: SETTINGS.inventory['primary'] = self.effect SETTINGS.next_gun = self.effect SETTINGS.player_states['armor'] = True remove = True else: SETTINGS.ground_weapon = self.effect elif self.item_type == 'secondary': if not SETTINGS.inventory['secondary']: SETTINGS.inventory['secondary'] = self.effect SETTINGS.next_gun = self.effect SETTINGS.player_states['armor'] = True remove = True else: SETTINGS.ground_weapon = self.effect elif self.item_type == 'melee': if not SETTINGS.inventory['melee']: SETTINGS.inventory['melee'] = self.effect SETTINGS.next_gun = self.effect SETTINGS.player_states['armor'] = True remove = True else: SETTINGS.ground_weapon = self.effect #Remove sprite and rect if self.sprite in SETTINGS.all_sprites and remove: SOUND.play_sound(self.sound, 0) SETTINGS.all_sprites.remove(self.sprite) self.rect = None