예제 #1
0
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'
예제 #2
0
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()
예제 #3
0
 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
예제 #4
0
 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
예제 #5
0
    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))
예제 #6
0
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'
예제 #7
0
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)
예제 #8
0
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)
예제 #9
0
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]))
예제 #10
0
 def mark_unblocked(self, coord):
     for adj in main.adjacent_tiles_diagonal(coord[0], coord[1]):
         self.edge_to(adj, coord)