def use_ability(self, game_map, ability, target=None): results = [] targeting = False area = ability.target_area include_self = ability.target_self if include_self: target = self.owner results = self.owner.fighter.attack(target, ability) msgs = self.owner.status_effects.process_effects(game_map=game_map, self_targeting=True) if msgs: results.extend(msgs) elif not target: radius = ability.get_range() entities = get_neighbours(self.owner, game_map.tiles, radius, fighters=True, include_self=include_self, algorithm=area, mark_area=True) if not entities and not include_self: msg = Message("There are no available targets in range.") results.append(msg) elif len(entities) == 1 and not ability.requires_targeting: target = entities[0] results = self.owner.fighter.attack(target, ability) else: msg = Message(msg="Use '{0}' on which target? Range: {1}".format( ability.name, radius), style="question") results.append(msg) target = entities[0] targeting = True else: results = self.owner.fighter.attack(target, ability) return results, target, targeting
def ally_actions(self): for entity in self.owner.levels.current_map.entities["allies"]: visible = self.owner.player.light_source.fov_map.fov[entity.y, entity.x] if visible: if entity.fighter: entity.status_effects.process_effects() self.owner.render_functions.draw_stats(entity) if self.owner.player.fighter.dead: kill_msg = self.owner.player.kill() self.owner.game_state = GameStates.PLAYER_DEAD self.owner.message_log.send(kill_msg) self.owner.render_functions.draw_stats() self.owner.fov_recompute = True break if entity.fighter and entity.fighter.dead: kill_msg = entity.kill() self.owner.levels.current_map.tiles[entity.x][ entity.y].blocking_entity = None self.owner.message_log.send(kill_msg) self.owner.fov_recompute = True elif entity.fighter and entity.fighter.paralyzed: self.owner.message_log.send( Message("Your {0} friend is paralyzed!".format( entity.name))) self.owner.game_state = GameStates.PLAYER_TURN elif entity.ai: target = self.owner.player prev_pos_x, prev_pos_y = entity.x, entity.y targets = get_neighbours( entity, self.owner.levels.current_map.tiles, radius=3, fighters=True, exclude_player=True) if targets: target = targets[0] combat_msg = entity.ai.take_turn( target, self.owner.levels.current_map, self.owner.levels.current_map.entities, self.owner.time_counter) self.owner.levels.current_map.tiles[prev_pos_x][ prev_pos_y].remove_entity(entity) self.owner.levels.current_map.tiles[entity.x][ entity.y].add_entity(entity) if entity.occupied_tiles is not None: self.owner.levels.current_map.tiles[prev_pos_x][ prev_pos_y + 1].remove_entity(entity) self.owner.levels.current_map.tiles[prev_pos_x + 1][ prev_pos_y + 1].remove_entity(entity) self.owner.levels.current_map.tiles[ prev_pos_x + 1][prev_pos_y].remove_entity(entity) self.owner.levels.current_map.tiles[entity.x][ entity.y + 1].add_entity(entity) self.owner.levels.current_map.tiles[entity.x + 1][ entity.y + 1].add_entity(entity) self.owner.levels.current_map.tiles[entity.x + 1][ entity.y].add_entity(entity) self.owner.fov_recompute = True if combat_msg: self.owner.message_log.send(combat_msg) self.owner.render_functions.draw_stats(entity) if self.owner.player.fighter.dead: kill_msg = self.owner.player.kill() self.owner.game_state = GameStates.PLAYER_DEAD self.owner.message_log.send(kill_msg) self.owner.render_functions.draw_stats() break # Functions on monster death if entity.fighter and entity.fighter.dead: level_up_msg = self.owner.player.player.handle_player_exp( entity.fighter) kill_msg = entity.kill() self.owner.levels.current_map.tiles[entity.x][ entity.y].blocking_entity = None self.owner.message_log.send(kill_msg) self.owner.message_log.send( Message("I feel my power returning!")) if level_up_msg: self.owner.message_log.send(level_up_msg) self.owner.fov_recompute = True
def targeting_actions(self, move=False, examine=False, main_menu=False, use_ability=False, interact=False): if move: if self.owner.cursor.cursor.targeting_ability: include_self = self.owner.cursor.cursor.targeting_ability.target_self radius = self.owner.cursor.cursor.targeting_ability.get_range() entities = get_neighbours(self.owner.player, self.owner.levels.current_map.tiles, radius, include_self=include_self, fighters=True, mark_area=True) entities_in_range = list( filter( lambda entity: self.owner.player.light_source.fov_map. fov[entity.y, entity.x], entities)) msg = self.owner.cursor.cursor.select_next( entities_in_range, self.owner.levels.current_map.tiles) if msg: self.owner.message_log.send(msg) self.owner.fov_recompute = True else: dx, dy = move destination_x = self.owner.cursor.x + dx destination_y = self.owner.cursor.y + dy x, y = self.owner.game_camera.get_coordinates( destination_x, destination_y) if 0 < x < self.owner.game_camera.width - 1 and 0 < y < self.owner.game_camera.height - 1: prev_pos_x, prev_pos_y = self.owner.cursor.x, self.owner.cursor.y self.owner.cursor.move(dx, dy) self.owner.levels.current_map.tiles[prev_pos_x][ prev_pos_y].remove_entity(self.owner.cursor) self.owner.levels.current_map.tiles[self.owner.cursor.x][ self.owner.cursor.y].add_entity(self.owner.cursor) self.owner.fov_recompute = True elif main_menu or examine: self.owner.game_state = GameStates.PLAYER_TURN self.owner.levels.current_map.tiles[self.owner.cursor.x][ self.owner.cursor.y].remove_entity(self.owner.cursor) del self.owner.levels.current_map.entities["cursor"] self.owner.cursor = None self.owner.fov_recompute = True return True elif (use_ability or interact) and self.owner.cursor.cursor.targeting_ability: target = self.owner.levels.current_map.tiles[self.owner.cursor.x][ self.owner.cursor.y].blocking_entity result, target, targeting = self.owner.player.player.use_ability( self.owner.levels.current_map, self.owner.cursor.cursor.targeting_ability, target) if target: self.owner.render_functions.draw_stats(target) self.owner.time_counter.take_turn(1) self.owner.game_state = GameStates.ENEMY_TURN self.owner.message_log.send(result) self.owner.levels.current_map.tiles[self.owner.cursor.x][ self.owner.cursor.y].remove_entity(self.owner.cursor) del self.owner.levels.current_map.entities["cursor"] self.owner.cursor = None self.owner.fov_recompute = True # if self.owner.player.fighter.paralyzed: # self.owner.message_log.send("You are paralyzed!") # self.owner.time_counter.take_turn(1) # self.owner.game_state = GameStates.ENEMY_TURN return False
def turn_taking_actions(self, wait=None, move=None, interact=None, pickup=None, stairs=None, examine=None, use_ability=None, key=None): if wait or move or interact or pickup or stairs or use_ability and not self.owner.player.fighter.dead: self.owner.player.status_effects.process_effects( game_map=self.owner.levels.current_map) if self.owner.player.fighter.paralyzed: msg = Message("You are paralyzed!") self.owner.message_log.send(msg) self.owner.time_counter.take_turn(1) if wait: self.owner.time_counter.take_turn(1) # player.player.spirit_power -= 1 msg = Message("You wait a turn.") self.owner.message_log.send(msg) self.owner.game_state = GameStates.ENEMY_TURN self.owner.fov_recompute = True elif move: dx, dy = move destination_x = self.owner.player.x + dx destination_y = self.owner.player.y + dy # Handle player attack if not self.owner.levels.current_map.is_blocked( destination_x, destination_y): target = self.owner.levels.current_map.tiles[destination_x][ destination_y].blocking_entity if target: results = self.owner.player.fighter.attack( target, self.owner.player.player.sel_weapon) self.owner.message_log.send(results) # player.player.spirit_power -= 0.5 self.owner.time_counter.take_turn(1) self.owner.render_functions.draw_stats(target) else: if self.owner.player.fighter.mv_spd <= 0: msg = Message("You are unable to move!") self.owner.message_log.send(msg) self.owner.time_counter.take_turn(1) else: prev_pos_x, prev_pos_y = self.owner.player.x, self.owner.player.y self.owner.player.move(dx, dy) self.owner.time_counter.take_turn( 1 / self.owner.player.fighter.mv_spd) self.owner.fov_recompute = True self.owner.levels.current_map.tiles[prev_pos_x][ prev_pos_y].remove_entity(self.owner.player) self.owner.levels.current_map.tiles[ self.owner.player.x][ self.owner.player.y].add_entity( self.owner.player) self.owner.game_state = GameStates.ENEMY_TURN elif self.owner.levels.current_map.tiles[destination_x][ destination_y].is_door: door = self.owner.levels.current_map.tiles[destination_x][ destination_y].door interact_msg = door.interaction(self.owner.levels.current_map) self.owner.message_log.send(interact_msg) self.owner.time_counter.take_turn(1) self.owner.game_state = GameStates.ENEMY_TURN self.owner.fov_recompute = True elif interact: entities = get_neighbours(self.owner.player, self.owner.levels.current_map.tiles) interact_msg = None for entity in entities: if entity.door: interact_msg = entity.door.interaction( self.owner.levels.current_map) self.owner.message_log.send(interact_msg) elif entity.item: interact_msg = entity.item.interaction( self.owner.levels.current_map) self.owner.message_log.send(interact_msg) if interact_msg: self.owner.time_counter.take_turn(1) self.owner.game_state = GameStates.ENEMY_TURN self.owner.fov_recompute = True elif pickup: pickup_msg = self.owner.player.inventory.add_item( self.owner.levels.current_map) if pickup_msg: self.owner.message_log.send(pickup_msg) self.owner.time_counter.take_turn(1) self.owner.game_state = GameStates.ENEMY_TURN self.owner.fov_recompute = True else: msg = Message("There is nothing here to pick up.") self.owner.message_log.send(msg) elif stairs: stairs_component = self.owner.levels.current_map.tiles[ self.owner.player.x][self.owner.player.y].stairs if stairs_component: results = stairs_component.interaction(self.owner.levels) self.owner.message_log.send(results) self.owner.time_counter.take_turn(1) self.owner.render_functions.draw_messages() self.owner.fov_recompute = True elif examine: self.owner.game_state = GameStates.TARGETING cursor_component = Cursor() cursor = Entity(self.owner.player.x, self.owner.player.y, 5, 0xE800 + 1746, "light yellow", "cursor", cursor=cursor_component, stand_on_messages=False) self.owner.cursor = cursor self.owner.levels.current_map.tiles[self.owner.cursor.x][ self.owner.cursor.y].add_entity(self.owner.cursor) self.owner.levels.current_map.entities["cursor"] = [ self.owner.cursor ] self.owner.fov_recompute = True elif use_ability: if key == blt.TK_Z: ability = self.owner.player.player.sel_utility else: ability = self.owner.player.player.sel_attack result, target, targeting = self.owner.player.player.use_ability( self.owner.levels.current_map, ability) if target: self.owner.render_functions.draw_stats(target) if targeting: self.owner.game_state = GameStates.TARGETING cursor_component = Cursor(targeting_ability=ability) cursor = Entity(target.x, target.y, 5, 0xE800 + 1746, "light yellow", "cursor", cursor=cursor_component, stand_on_messages=False) self.owner.cursor = cursor self.owner.levels.current_map.tiles[self.owner.cursor.x][ self.owner.cursor.y].add_entity(self.owner.cursor) self.owner.levels.current_map.entities["cursor"] = [ self.owner.cursor ] else: self.owner.time_counter.take_turn(1) self.owner.game_state = GameStates.ENEMY_TURN self.owner.message_log.send(result) self.owner.fov_recompute = True if self.owner.player.fighter.summoning: msg = self.owner.player.summoner.process( game_map=self.owner.levels.current_map) if msg: self.owner.message_log.send(msg) self.owner.fov_recompute = True
def process(self, game_map=None): msg = None if self.process_instantly: self.process_instantly = False if self.source.dead and self.name == "strangle": self.duration = 0 if self.heal: msg = self.owner.heal(self.power[self.rank]) return self, msg if self.duration <= 0: if self.hit_penalty: self.owner.hit_penalty -= self.hit_penalty[self.rank] if self.drain_stats: self.owner.ac += self.drain_stats[self.rank] self.owner.ev += self.drain_stats[self.rank] if self.slow_amount: self.owner.mv_spd += self.slow_amount if self.delayed_damage: self.owner.take_damage(self.delayed_damage) if self.paralyze: self.owner.paralyzed = False if self.fly: self.owner.ev -= self.fly_ev_boost self.owner.flying = False if self.reveal: self.owner.revealing = False if self.summoning: self.summoning = None self.owner.owner.summoner.summoning = None self.owner.owner.summoner.rank = self.rank self.owner.effects.remove(self.description) return self, msg if self.summoning: self.owner.summoning = True self.owner.owner.summoner.summoning = self.summoning self.owner.owner.summoner.rank = self.rank if self.dps: self.owner.take_damage(self.dps[self.rank]) if self.hit_penalty: if self.description not in self.owner.effects: self.owner.hit_penalty += self.hit_penalty[self.rank] if self.drain_stats: if self.description not in self.owner.effects: self.owner.hit_penalty -= self.drain_stats[self.rank] self.owner.ac -= self.drain_stats[self.rank] self.owner.ev -= self.drain_stats[self.rank] if self.slow: if self.description not in self.owner.effects: self.slow_amount = self.owner.mv_spd - self.owner.mv_spd * self.slow[self.rank] self.owner.mv_spd -= self.slow_amount if self.paralyze: if random() <= self.chance[self.rank]: self.owner.paralyzed = True else: self.owner.paralyzed = True if self.fly: if self.description not in self.owner.effects: self.fly_ev_boost = ceil(self.owner.ev * self.power[self.rank] - self.owner.ev) self.owner.ev += self.fly_ev_boost self.owner.flying = True if self.reveal: neighbours = get_neighbours(self.owner.owner, game_map.tiles, include_self=False, fighters=False, mark_area=True, radius=self.reveal.radius[self.rank], algorithm="square") for entity in neighbours: if entity.hidden: entity.hidden = False if self.description not in self.owner.effects: self.owner.revealing = True if self.description not in self.owner.effects: self.owner.effects.append(self.description) self.duration -= 1 return None, msg
def process(self, game_map): msgs = [] if not self.summoning and self.summoned_entities: summons = [] for entity in self.summoned_entities: summons.append(entity.name) game_map.entities["allies"].remove(entity) game_map.tiles[entity.x][entity.y].remove_entity(entity) del entity self.summoned_entities = [] self.owner.fighter.summoning = False self.summoning = [""] if len(summons) > 1: msg = Message( "Your trusty companions {0} return back to the spirit plane!" .format(", ".join(summons))) else: msg = Message( "Your trusty companion {0} returns back to the spirit plane!" .format(summons[0])) msgs.append(msg) return msgs elif self.summoning and not self.summoned_entities: if len(self.summoning) <= self.rank: name = self.summoning[-1] else: name = self.summoning[self.rank] char = tilemap()["monsters"][name] color = get_monster_color(name) f_data = json_data.data.fighters[name] remarks = f_data["remarks"] fighter_component = Fighter(hp=f_data["hp"], ac=f_data["ac"], ev=f_data["ev"], power=f_data["power"], mv_spd=f_data["mv_spd"], atk_spd=f_data["atk_spd"], size=f_data["size"], fov=f_data["fov"]) ai_component = BasicMonster(ally=True) light_component = LightSource(radius=fighter_component.fov) abilities_component = Abilities(name) status_effects_component = StatusEffects(name) neighbours = get_neighbours(self.owner, game_map=game_map.tiles, radius=3, algorithm="square", empty_tiles=True) summon_tile = choice(neighbours) entity_name = name monster = Entity(summon_tile.x, summon_tile.y, 3, char, color, entity_name, blocks=True, fighter=fighter_component, ai=ai_component, light_source=light_component, abilities=abilities_component, status_effects=status_effects_component, remarks=remarks, indicator_color="light green") monster.light_source.initialize_fov(game_map) game_map.tiles[summon_tile.x][summon_tile.y].add_entity(monster) game_map.entities["allies"].append(monster) self.summoned_entities.append(monster) msg = Message("A friendly {0} appears!".format(entity_name)) msgs.append(msg) remark_str = "{0}: {1}".format(monster.colored_name, choice(monster.remarks)) remark_msg = Message(msg=remark_str, style="dialog") msgs.append(remark_msg) return msgs return msgs
def take_turn(self, target, game_map, entities, time): monster = self.owner if not self.action_begin: self.last_action = time.get_last_turn() time_to_act = time.get_turn() - self.last_action action_cost = 0 combat_msgs = [] self.owner.light_source.recompute_fov(monster.x, monster.y) if self.ally and target.player: if monster.distance_to(target) > 1: monster.move_astar(target, entities, game_map) elif randint(0, 4) == 0: tiles = get_neighbours(self.owner, game_map.tiles, algorithm="square", empty_tiles=True) target_tile = choice(tiles) self.owner.move_to_tile(target_tile.x, target_tile.y) if self.owner.remarks: remark = choice(self.owner.remarks) combat_msgs.append( Message("{0}: {1}".format(self.owner.colored_name, remark), style="dialog")) elif self.owner.light_source.fov_map.fov[target.y, target.x]: self.target_seen = True self.target_last_seen_x = target.x self.target_last_seen_y = target.y self.action_begin = True while action_cost < time_to_act: if monster.distance_to( target ) == 1 and self.owner.fighter.atk_spd <= time_to_act - action_cost: if target.fighter.hp > 0: combat_msg, skill = self.choose_skill() if skill is None: combat_msgs.extend(combat_msg) return combat_msgs combat_msg = monster.fighter.attack(target, skill) combat_msgs.extend(combat_msg) action_cost += 1 #self.last_action += action_cost else: break elif 1 / self.owner.fighter.mv_spd <= time_to_act - action_cost and monster.distance_to( target) >= 2: if randint(0, 4) == 0: if self.owner.remarks: remark = choice(self.owner.remarks) combat_msgs.append( Message(msg="{0}: {1}".format( self.owner.colored_name, remark), style="dialog")) monster.move_astar(target, entities, game_map) action_cost += 1 / monster.fighter.mv_spd #self.last_action += action_cost else: break self.last_action += action_cost elif self.target_seen: self.action_begin = False if not monster.x == self.target_last_seen_x and not monster.y == self.target_last_seen_y: monster.move_astar(target, entities, game_map) else: self.action_begin = False return combat_msgs