예제 #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 disarm(target):
    if target is None or target.fighter is None:
        return 'failure'
    weapon = main.get_equipped_in_slot(target.fighter.inventory, 'right hand')
    if weapon is None:
        return 'failure'
    weapon.dequip(no_message=True)
    possible_tiles = []
    for x in range(target.x - 1, target.x + 2):
        for y in range(target.y - 1, target.y + 2):
            if not main.is_blocked(
                    x, y, from_coord=(target.x, target.y), movement_type=1):
                possible_tiles.append((x, y))
    if len(possible_tiles) == 0:
        selected_tile = main.find_closest_open_tile(target.x, target.y)
    else:
        selected_tile = possible_tiles[libtcod.random_get_int(
            0, 0,
            len(possible_tiles) - 1)]
    weapon.owner.item.drop(no_message=True)
    weapon.owner.x = selected_tile[0]
    weapon.owner.y = selected_tile[1]
    ui.message(
        '%s %s disarmed!' % (syntax.name(target).capitalize(),
                             syntax.conjugate(target is player.instance,
                                              ('are', 'is'))), libtcod.red)
    return 'success'
예제 #3
0
def spawn_vermin(actor, target, context):
    #Filthy hackery to add some state
    if not hasattr(actor, 'summons'):
        actor.summons = []

    for s in actor.summons:  # clear dead things from summoned list
        if not s.fighter:
            actor.summons.remove(s)

    if len(actor.summons) < context['max_summons']:
        summon_choice = main.random_choice_index(
            [e['weight'] for e in context['summons']])
        summon_tiles = []
        for y in range(5):
            for x in range(5):
                pos = actor.x - 2 + x, actor.y - 2 + y
                if main.in_bounds(pos[0], pos[1]) and not main.is_blocked(
                        pos[0], pos[1]):
                    summon_tiles.append(pos)
        for i in range(context['summons'][summon_choice]['count']):
            if len(summon_tiles) > 0:
                pos = summon_tiles[libtcod.random_get_int(
                    0, 0,
                    len(summon_tiles) - 1)]
                spawn = main.spawn_monster(
                    context['summons'][summon_choice]['monster'], pos[0],
                    pos[1])
                ui.message(
                    'A ' + spawn.name +
                    " crawls from beneath the verman's cloak.", actor.color)
                spawn.fighter.loot_table = None
                actor.summons.append(spawn)
                summon_tiles.remove(pos)
예제 #4
0
def spawn_spiders(actor, target, context):
    #Filthy hackery to add some state
    if not hasattr(actor, 'summons'):
        actor.summons = []

    for s in actor.summons:  # clear dead things from summoned list
        if not s.fighter:
            actor.summons.remove(s)

    if len(actor.summons) < context['max_summons']:
        summon_tiles = []
        for y in range(3):
            for x in range(3):
                pos = actor.x - 1 + x, actor.y - 1 + y
                if main.in_bounds(pos[0], pos[1]) and not main.is_blocked(
                        pos[0], pos[1]):
                    summon_tiles.append(pos)
        summon_count = main.roll_dice(context['summons_per_cast'])
        for i in range(summon_count):
            if len(summon_tiles) > 0 and len(
                    actor.summons) < context['max_summons']:
                pos = summon_tiles[libtcod.random_get_int(
                    0, 0,
                    len(summon_tiles) - 1)]
                spawn = main.spawn_monster('monster_tunnel_spider', pos[0],
                                           pos[1])
                ui.message(
                    'A ' + spawn.name + " crawls from beneath %s cloak." %
                    syntax.name(actor, possesive=True), actor.color)
                actor.summons.append(spawn)
                summon_tiles.remove(pos)
        return 'success'
    return 'cancelled'
예제 #5
0
def longstride(actor, target, context):
    if main.is_blocked(target[0], target[1],
                       movement_type=actor.movement_type):
        if actor is player.instance:
            ui.message('Something is in the way.', libtcod.gray)
        return 'cancelled'
    actor.set_position(target[0], target[1])
예제 #6
0
def on_damaged_teleport(actor, attacker, damage):
    valid_teleports = []
    for x in range(attacker.x - 5, attacker.x + 5):
        if x < 0 or x >= consts.MAP_WIDTH - 1:
            continue
        for y in range(attacker.y - 5, attacker.y + 5):
            if y < 0 or y >= consts.MAP_HEIGHT - 1:
                continue
            if fov.monster_can_see_tile(actor, x, y):
                if not main.is_blocked(x,
                                       y,
                                       movement_type=actor.movement_type,
                                       is_player=actor is player.instance):
                    valid_teleports.append((x, y))
    final_teleports = []
    if attacker is not None:
        for vt in valid_teleports:
            if fov.monster_can_see_tile(attacker, vt[0], vt[1]):
                final_teleports.append(vt)
    else:
        final_teleports = list(valid_teleports)
    final_teleports.sort(
        key=lambda o: main.distance(o[0], o[1], actor.x, actor.y))
    index = len(final_teleports) - main.roll_dice(
        '1d%d' % min(len(final_teleports), 5))
    teleport_position = final_teleports[index]

    ui.render_explosion(actor.x, actor.y, 0, libtcod.fuchsia, libtcod.white)
    actor.set_position(teleport_position[0], teleport_position[1])
    ui.render_explosion(actor.x, actor.y, 0, libtcod.fuchsia, libtcod.white)
예제 #7
0
def great_dive(actor, target, context):
    ui.message("{} {} into the ground!".format(
        syntax.name(actor).capitalize(),
        syntax.conjugate(actor is player.instance, ['slam', 'slams'])))

    for obj in main.current_map.fighters:
        if (obj.x, obj.y) in target:
            combat.attack_ex(actor.fighter, obj, 0)

    x, y = context['origin']
    if not main.is_blocked(x, y):
        actor.set_position(x, y)
    else:
        for t in target:
            if not main.is_blocked(t[0], t[1]):
                actor.set_position(t[0], t[1])
                break
예제 #8
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)
예제 #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 boomerang(actor, target, context):
    sprites = ['<', 'v', '>', '^']
    ui.render_projectile((actor.x, actor.y), (target.x, target.y),
                         libtcod.yellow, sprites)
    attack_result = actor.fighter.attack(target)
    if attack_result == 'failed':
        return 'didnt-take-turn'
    catch_skill = 30
    if actor.player_stats:
        catch_skill = actor.player_stats.agi
    if main.roll_dice('1d' + str(catch_skill)) >= 10:
        #catch boomerang
        ui.render_projectile((target.x, target.y), (actor.x, actor.y),
                             libtcod.yellow, sprites)
        if actor is player.instance:
            ui.message('You catch the boomerang as it returns to you',
                       libtcod.gray)
    else:
        possible_tiles = []
        for y in range(actor.y - 2, actor.y + 2):
            for x in range(actor.x - 2, actor.x + 2):
                if x >= 0 and y >= 0 and x < consts.MAP_WIDTH and y < consts.MAP_HEIGHT and not main.is_blocked(
                        x, y):
                    possible_tiles.append((x, y))
        if len(possible_tiles) == 0:
            selected_tile = main.find_closest_open_tile(target.x, target.y)
        else:
            selected_tile = possible_tiles[libtcod.random_get_int(
                0, 0,
                len(possible_tiles) - 1)]
        ui.render_projectile((target.x, target.y),
                             (selected_tile[0], selected_tile[1]),
                             libtcod.yellow, sprites)
        weapon = main.get_equipped_in_slot(actor.fighter.inventory,
                                           'right hand')
        weapon.owner.item.drop(no_message=True)
        weapon.owner.x = selected_tile[0]
        weapon.owner.y = selected_tile[1]
        if actor is player.instance or fov.player_can_see(actor.x, actor.y):
            ui.message(
                '%s boomerang falls to the ground.' %
                syntax.name(target, possesive=True).capitalize(), libtcod.gray)
        libtcod.console_flush()