def summon_ally(name, duration, x=None, y=None): adj = main.adjacent_tiles_diagonal(player.instance.x, player.instance.y) # Get viable summoning position. Return failure if no position is available if x is None or y is None: summon_positions = [] for tile in adj: if not main.is_blocked(tile[0], tile[1]): summon_positions.append(tile) if len(summon_positions) == 0: ui.message('There is no room to summon an ally here.') return summon_pos = summon_positions[libtcod.random_get_int( 0, 0, len(summon_positions) - 1)] else: summon_pos = (x, y) # Select monster type - default to goblin import monsters if name in monsters.proto.keys(): summon = main.spawn_monster(name, summon_pos[0], summon_pos[1], team='ally') if summon is not None: if summon.behavior is not None: summon.behavior.follow_target = player.instance # Set summon duration summon.summon_time = duration + libtcod.random_get_int( 0, 0, duration) return 'success' else: return 'didnt-take-turn'
def bomb_beetle_corpse_tick(object=None, context=None): if object is None: return object.bomb_timer -= 1 if object.bomb_timer > 2: object.color = libtcod.black elif object.bomb_timer > 1: object.color = libtcod.darkest_red elif object.bomb_timer > 0: object.color = libtcod.red elif object.bomb_timer <= 0: ui.message('The bomb beetle corpse explodes!', libtcod.orange) ui.render_explosion(object.x, object.y, 1, libtcod.yellow, libtcod.flame) main.create_fire(object.x, object.y, 10) for tile in main.adjacent_tiles_diagonal(object.x, object.y): if libtcod.random_get_int(0, 0, 3) != 0: main.create_fire(tile[0], tile[1], 10) main.melt_ice(tile[0], tile[1]) monster = main.get_objects(tile[0], tile[1], lambda o: o.fighter is not None) if len(monster) > 0: monster[0].fighter.take_damage(main.roll_dice('22d3')) if monster[0].fighter is not None: monster[0].fighter.apply_status_effect(effects.burning()) object.destroy()
def mark_blocked(self, coord): for adj in main.adjacent_tiles_diagonal(coord[0], coord[1]): if adj in self.edges: for e in self.edges[adj]: if e.coord == coord: for weight in e.weights.keys(): e.weights[weight] = None break
def is_accessible(self, coord, movement_type=NORMAL): for adj in main.adjacent_tiles_diagonal(coord[0], coord[1]): if adj in self.edges: for e in self.edges[adj]: if e.coord == coord: for weight in e.weights.keys(): if weight & movement_type == weight and e.weights[weight] is not None: return True return False
def initialize(self): for y in range(consts.MAP_HEIGHT): for x in range(consts.MAP_WIDTH): self.edges[(x, y)] = [] for tile in main.adjacent_tiles_diagonal(x, y): self.edge_to((x, y), tile) for obj in main.current_map.objects: if obj.blocks: self.mark_blocked((obj.x, obj.y))
def cleave_attack(actor, target, context): if actor is None: actor = player.instance if actor is player.instance: return player.cleave_attack(0, 0) if isinstance(target, main.GameObject): dist = main.distance(actor.x, actor.y, target.x, target.y) else: dist = main.distance(actor.x, actor.y, target[0], target[1]) if dist > 1: return 'didnt-take-turn' for adj in main.adjacent_tiles_diagonal(actor.x, actor.y): targets = main.get_objects( adj[0], adj[1], lambda o: o.fighter and o.fighter.team == 'ally') for t in targets: actor.fighter.attack(t) return 'success'
def shimmering_swords(actor, target, context): import pathfinding sp = actor.fighter.spell_power(context['element']) adjacent = [] for tile in main.adjacent_tiles_diagonal(actor.x, actor.y): if not main.is_blocked( tile[0], tile[1], movement_type=pathfinding.FLYING): adjacent.append(tile) for i in range(context['sword_count']): if len(adjacent) < 1: break summon_pos = adjacent[libtcod.random_get_int(0, 0, len(adjacent) - 1)] common.summon_ally( 'monster_shimmering_sword', context['duration_base'] + main.roll_dice('1d%d' % sp), summon_pos[0], summon_pos[1]) adjacent.remove(summon_pos)
def on_hit_chain_lightning(attacker, target, damage, zapped=None): if zapped is None: zapped = [target] else: zapped.append(target) if target.fighter is None: return damage = combat.roll_damage('1d10', '0d0', target.fighter.armor, 5, 'lightning', 1.0, target.fighter.resistances) if damage > 0: combat.attack_text(attacker.fighter, target, None, None, damage, 'lightning', float(damage) / float(target.fighter.max_hp)) target.fighter.take_damage(damage, attacker=attacker) for adj in main.adjacent_tiles_diagonal(target.x, target.y): for obj in main.current_map.fighters: if obj.x == adj[0] and obj.y == adj[ 1] and obj.fighter.team != attacker.fighter.team and obj not in zapped: on_hit_chain_lightning(attacker, obj, damage, zapped) else: ui.message('The shock does not damage %s' % syntax.name(target), libtcod.grey)
def summon_roaches(actor, attacker, damage): if not hasattr(actor, 'summon_limit') or not hasattr(actor, 'summons'): actor.summon_limit = 8 actor.summons = [] remove = [] for s in actor.summons: if s.fighter is None or not s in main.current_map.fighters: remove.append(s) for s in remove: actor.summons.remove(s) if len(actor.summons) >= actor.summon_limit: return if fov.player_can_see(actor.x, actor.y): ui.message( 'Cockroaches crawl from %s wounds!' % syntax.name(actor, possesive=True), libtcod.dark_magenta) for adj in main.adjacent_tiles_diagonal(actor.x, actor.y): if len(actor.summons) >= actor.summon_limit: break if not main.is_blocked( adj[0], adj[1]) and libtcod.random_get_int(0, 1, 10) <= 5: actor.summons.append( main.spawn_monster('monster_cockroach', adj[0], adj[1]))
def mark_unblocked(self, coord): for adj in main.adjacent_tiles_diagonal(coord[0], coord[1]): self.edge_to(adj, coord)