def wild_growth(actor, target, context):
    import mapgen
    terrain = main.current_map.tiles[target.x][target.y].tile_type
    if target.fighter and target.fighter.has_status('immobilized'):
        return 'cancelled'
    if terrain == 'grass floor':
        if target.fighter:
            if target is player.instance or fov.player_can_see(
                    target.x, target.y):
                ui.message('The grass sprouts a tangle of grasping vines!',
                           libtcod.lime)
            duration = main.roll_dice(context['root_duration'])
            immobilized = target.fighter.apply_status_effect(
                effects.immobilized(duration=duration), dc=context['save_dc'])
            if immobilized:
                target.fighter.apply_status_effect(effects.StatusEffect(
                    'wild growth',
                    time_limit=duration,
                    color=libtcod.lime,
                    on_tick=wild_growth_tick,
                    message='You are gripped by writhing vines!',
                    description='This unit will take damage every turn',
                    cleanseable=True),
                                                   dc=None)
    else:
        if target is player.instance or fov.player_can_see(target.x, target.y):
            ui.message('Grass springs from the %s...' % terrain, libtcod.lime)
        grass = mapgen.create_terrain_patch((target.x, target.y),
                                            'grass floor',
                                            min_patch=4,
                                            max_patch=12,
                                            overwrite=False)
        for tile in grass:
            main.changed_tiles.append(tile)
Exemple #2
0
def strangleweeds(actor, target, context):
    hit = False
    for f in main.get_fighters_in_burst(
            actor.x, actor.y, context['range'], actor,
            lambda o: o.fighter.team != actor.fighter.team):
        tile = main.current_map.tiles[f.x][f.y]
        if tile.tile_type == 'grass floor':
            if actor is player.instance or fov.player_can_see(f.x, f.y):
                ui.message(
                    'Writhing vines grip %s and hold %s in place!' %
                    (syntax.name(f), syntax.pronoun(f)),
                    spells.essence_colors['life'])
            f.fighter.apply_status_effect(
                effects.immobilized(duration=context['duration']))
            f.fighter.apply_status_effect(
                effects.StatusEffect(
                    'strangleweeds',
                    time_limit=context['duration'],
                    color=libtcod.lime,
                    on_tick=strangleweed_on_tick,
                    message='The strangleweeds crush you!',
                    description='This unit will take damage every turn',
                    cleanseable=True))
            hit = True
    if hit:
        return 'success'
    else:
        if actor is player.instance:
            ui.message("You can't see any susceptible targets.", libtcod.gray)
        return 'cancelled'
Exemple #3
0
def green_touch(actor, target, context):
    x, y = target
    import mapgen
    t = main.current_map.tiles[x][y]
    if not t.is_floor:
        if actor is player.instance:
            ui.message('You cannot grow grass here.', libtcod.gray)
        return 'cancelled'
    if actor is player.instance or fov.player_can_see(x, y):
        ui.message('Grass springs from the ground!',
                   spells.essence_colors['life'])
    grass = mapgen.create_terrain_patch((x, y),
                                        'grass floor',
                                        min_patch=4,
                                        max_patch=12)
    mapgen.scatter_reeds(grass, probability=30)
    for tile in grass:
        main.changed_tiles.append(tile)
        fov.set_fov_properties(
            tile[0],
            tile[1],
            len(main.get_objects(tile[0], tile[1],
                                 lambda o: o.blocks_sight)) > 0,
            elevation=main.current_map.tiles[tile[0]][tile[1]].elevation)
    return 'success'
def dragonweed_pull(actor, target, context):
    if target.fighter.hp > 0:
        ui.message(
            "The dragonweed's stem lashes out at %s!" % syntax.name(target),
            libtcod.dark_green)
        result = combat.attack_ex(actor.fighter,
                                  target,
                                  0,
                                  accuracy_modifier=1.5,
                                  damage_multiplier=0.75,
                                  verb=('pull', 'pulls'))
        if result == 'hit' and target.fighter is not None:
            if 'displacement' in target.fighter.immunities:
                if fov.player_can_see(target.x, target.y):
                    ui.message(
                        '%s %s.' % (syntax.name(target).capitalize(),
                                    syntax.conjugate(target is player.instance,
                                                     ('resist', 'resists'))),
                        libtcod.gray)
                return 'success'
            beam = main.beam(actor.x, actor.y, target.x, target.y)
            pull_to = beam[max(len(beam) - 3, 0)]
            target.set_position(pull_to[0], pull_to[1])
            if main.roll_dice('1d10') <= 5:
                target.fighter.apply_status_effect(
                    effects.immobilized(duration=2), context['save_dc'], actor)
Exemple #5
0
def flash_frost(actor, target, context):
    target.fighter.apply_status_effect(effects.frozen(5))
    if actor is player.instance or fov.player_can_see(target.x, target.y):
        ui.message(
            '%s %s frozen solid!' %
            (syntax.name(target).capitalize(),
             syntax.conjugate(target is player.instance,
                              ('are', 'is'))), spells.essence_colors['cold'])
Exemple #6
0
def teleport(actor, x, y):
    if actor is None:
        actor = player.instance

    if actor is player.instance or fov.player_can_see(actor.x, actor.y):
        ui.message(
            '%s %s in a crackle of magical energy!' %
            (syntax.name(actor).capitalize(),
             syntax.conjugate(actor is player.instance,
                              ('vanish', 'vanishes'))),
            spells.essence_colors['arcane'])
    actor.set_position(x, y)
    if actor is not player.instance and fov.player_can_see(actor.x, actor.y):
        ui.message(
            '%s appears out of thin air!' % syntax.name(actor).capitalize(),
            spells.essence_colors['arcane'])
    return 'success'
def step_on_blightweed(weed, obj):
    if obj.fighter:
        obj.fighter.time_since_last_damaged = 0
        if obj.fighter.armor > 0:
            obj.fighter.get_shredded(1)
            if fov.player_can_see(obj.x, obj.y):
                ui.message(
                    'The blightweed thorns shred %s armor!' %
                    syntax.name(obj, possesive=True), libtcod.desaturated_red)
Exemple #8
0
def hardness(target):
    target.fighter.shred = 0
    target.fighter.apply_status_effect(effects.stoneskin(21))
    if target is player.instance or fov.player_can_see(target.x, target.y):
        ui.message(
            '%s armor is repaired and %s skin becomes as hard as stone.' %
            (syntax.name(target, possesive=True).capitalize(),
             syntax.pronoun(target, possesive=True)),
            spells.essence_colors['earth'])
    return 'success'
def web_bomb(actor, target, context):
    if actor is player.instance:
        ui.message('Yo implement this', libtcod.red)
        return 'failure'

    main.tunnel_spider_spawn_web(target)
    if actor is player.instance or fov.player_can_see(target.x, target.y):
        ui.message('%s summons spiderwebs.' % syntax.name(actor).capitalize(),
                   actor.color)
    return 'success'
Exemple #10
0
def firebomb(actor, target, context):
    (x, y) = context['origin']
    ui.render_projectile((actor.x, actor.y), (x, y),
                         spells.essence_colors['fire'], chr(7))
    ui.render_explosion(x, y, 1, libtcod.yellow, libtcod.flame)
    if actor is player.instance or fov.player_can_see(x, y):
        ui.message('The firebomb explodes!', spells.essence_colors['fire'])
    for f in target:
        if combat.attack_magical(
                actor.fighter, f,
                'ability_fire_bomb') == 'hit' and f.fighter is not None:
            f.fighter.apply_status_effect(effects.burning())
Exemple #11
0
def knock_back(actor, target):
    # check for resistance
    if 'displacement' in target.fighter.immunities:
        if fov.player_can_see(target.x, target.y):
            ui.message(
                '%s %s.' % (syntax.name(target).capitalize(),
                            syntax.conjugate(target is player.instance,
                                             ('resist', 'resists'))),
                libtcod.gray)
        return 'resisted'

    # knock the target back one space. Stun it if it cannot move.
    direction = target.x - actor.x, target.y - actor.y  # assumes the instance is adjacent
    stun = False
    against = ''
    against_tile = main.current_map.tiles[target.x +
                                          direction[0]][target.y +
                                                        direction[1]]
    if against_tile.blocks and not against_tile.is_pit:
        stun = True
        against = main.current_map.tiles[target.x +
                                         direction[0]][target.y +
                                                       direction[1]].name
    elif against_tile.elevation != target.elevation and against_tile.tile_type != 'ramp' and \
                    main.current_map.tiles[target.x][target.y] != 'ramp':
        stun = True
        against = 'cliff'
    else:
        for obj in main.current_map.objects:
            if obj.x == target.x + direction[
                    0] and obj.y == target.y + direction[1] and obj.blocks:
                stun = True
                against = obj.name
                break

    if stun:
        #  stun the target
        if target.fighter.apply_status_effect(effects.stunned(duration=2)):
            ui.message(
                '%s %s with the %s, stunning %s!' %
                (syntax.name(target).capitalize(),
                 syntax.conjugate(target is actor,
                                  ('collide', 'collides')), against,
                 syntax.pronoun(target, objective=True)), libtcod.gold)
    else:
        ui.message(
            '%s %s knocked backwards.' %
            (syntax.name(target).capitalize(),
             syntax.conjugate(target is actor, ('are', 'is'))), libtcod.gray)
        target.set_position(target.x + direction[0], target.y + direction[1])
        main.render_map()
        libtcod.console_flush()
def lightning_storm(actor, target, context):
    for tile in target:
        obj = main.get_monster_at_tile(tile[0], tile[1])
        ui.render_explosion(tile[0], tile[1], 0, libtcod.light_green,
                            libtcod.lightest_blue, chr(251))
        if obj is not None and obj is not actor:
            if fov.player_can_see(tile[0],
                                  tile[1]) or actor is player.instance:
                ui.message(
                    '%s is struck by a bolt of lightning!' %
                    syntax.name(obj).capitalize(), libtcod.lightest_blue)
            combat.attack_magical(actor.fighter, obj,
                                  'ability_lightning_storm')
Exemple #13
0
def icebomb(actor, target, context):
    (x, y) = context['origin']
    ui.render_projectile((actor.x, actor.y), (x, y),
                         spells.essence_colors['cold'], chr(7))
    ui.render_explosion(x, y, 1, libtcod.white, libtcod.light_sky)
    if actor is player.instance or fov.player_can_see(x, y):
        ui.message('The icebomb explodes!', spells.essence_colors['cold'])
    for f in target:
        if combat.attack_magical(
                actor.fighter, f,
                'ability_ice_bomb') == 'hit' and f.fighter is not None:
            f.fighter.apply_status_effect(
                effects.frozen(duration=context['freeze_duration']))
def silence(actor, target, context):
    if target.fighter.apply_status_effect(
            effects.silence(duration=context.get('duration', 10)),
            dc=context.get('base_dc', 20) +
            actor.fighter.spell_power(['arcane']),
            source_fighter=actor.fighter,
            supress_message=True):
        if actor is player.instance or target is player.instance or fov.player_can_see(
                target.x, target.y):
            ui.message(
                '%s %s silenced!' %
                (syntax.name(target).capitalize(),
                 syntax.conjugate(target is player.instance,
                                  ('are', 'is'))), libtcod.light_blue)
Exemple #15
0
def summon_equipment_on_tick(ticker):
    dead_flag = False
    dropped = False
    owner = ticker.owner
    if not owner or not owner.fighter:
        dead_flag = True
    elif not ticker.equipment.equipment.is_equipped:
        if owner is player.instance or fov.player_can_see(owner.x, owner.y):
            ui.message(
                'The %s fades away as %s %s it from %s grasp.' %
                (ticker.equipment.name.title(), syntax.name(owner),
                 syntax.conjugate(owner is player.instance,
                                  ('release', 'releases')),
                 syntax.pronoun(owner, possesive=True)), libtcod.light_blue)
        dead_flag = True
        dropped = True
    elif ticker.ticks > ticker.max_ticks:
        dead_flag = True
        if owner is player.instance or fov.player_can_see(owner.x, owner.y):
            ui.message(
                "The %s fades away as it's essence depletes." %
                ticker.equipment.name.title(), libtcod.light_blue)
    if dead_flag:
        ticker.dead = True
        if ticker.equipment is not None:
            if hasattr(ticker.equipment.equipment, 'raised'):
                ticker.equipment.equipment.sh_raise()
            ticker.equipment.item.drop(no_message=True)
            ticker.equipment.destroy()
        if owner and owner.fighter:
            owner.fighter.remove_status('summoned equipment')
        if not dropped and owner and owner.fighter:
            if ticker.old_equipment is not None:
                ticker.old_equipment.equip()
            if ticker.old_left is not None:
                ticker.old_left.equip()
Exemple #16
0
def timebomb(actor, target, context):
    (x, y) = target[0], target[1]
    rune = main.GameObject(
        x,
        y,
        chr(21),
        'time bomb',
        spells.essence_colors['arcane'],
        description='"I prepared explosive runes this morning"')
    main.current_map.add_object(rune)
    rune_ticker = main.Ticker(context['delay'], _timebomb_ticker)
    rune_ticker.rune = rune
    rune_ticker.actor = actor
    main.current_map.tickers.append(rune_ticker)
    if actor is player.instance or fov.player_can_see(x, y):
        ui.message('A glowing rune forms...', spells.essence_colors['arcane'])
Exemple #17
0
def fungal_growth(actor, target, context):
    x, y = target
    corpse = main.get_objects(x, y, lambda o: o.is_corpse)
    if len(corpse) == 0:
        ui.message('No suitable corpses here.', libtcod.gray)
        return 'cancelled'
    target = corpse[0]

    if not target.is_corpse:
        return 'failure'
    main.spawn_monster('monster_blastcap', target.x, target.y)
    if actor is player.instance or fov.player_can_see(target.x, target.y):
        ui.message('A blastcap grows from %s.' % syntax.name(target),
                   spells.essence_colors['life'])
    target.destroy()
    return 'success'
Exemple #18
0
def create_teleportal(actor, target, context):
    x, y = target
    portal = main.GameObject(x,
                             y,
                             9,
                             'teleportal',
                             spells.essence_colors['arcane'],
                             on_tick=teleportal_on_tick)
    portal.timer = 4
    main.current_map.add_object(portal)
    main.changed_tiles.append((x, y))
    if fov.player_can_see(x, y):
        ui.message(
            'A volatile portal opens. In a few moments it will teleport creatures standing near it.',
            spells.essence_colors['arcane'])
    return 'success'
Exemple #19
0
def dig_line(x, y, dx, dy, length, actor=None):
    if actor is None: actor = player.instance
    result = 'failure'
    for i in range(length):
        d = dig(x + dx * i, y + dy * i)
        if result != 'success':
            result = d
    if result == 'success':
        if actor is player.instance or fov.player_can_see(actor.x, actor.y):
            ui.message('The earth parts before %s.' % syntax.name(actor),
                       spells.essence_colors['earth'])
    else:
        if actor is player.instance:
            ui.message('There is nothing to dig in that direction.',
                       libtcod.gray)
    return result
Exemple #20
0
def on_hit_knockback(attacker, target, damage, force=6):
    if target.fighter is None:
        return

    if 'displacement' in target.fighter.immunities:
        if fov.player_can_see(target.x, target.y):
            ui.message(
                '%s %s.' % (syntax.name(target).capitalize(),
                            syntax.conjugate(target is player.instance,
                                             ('resist', 'resists'))),
                libtcod.gray)
        return

    diff_x = target.x - attacker.x
    diff_y = target.y - attacker.y
    if diff_x > 0:
        diff_x = diff_x / abs(diff_x)
    if diff_y > 0:
        diff_y = diff_y / abs(diff_y)
    direction = (diff_x, diff_y)

    steps = 0
    while steps <= force:
        steps += 1
        against = main.get_objects(target.x + direction[0],
                                   target.y + direction[1], lambda o: o.blocks)
        if against is None or len(against) == 0:
            against = syntax.name(
                main.current_map.tiles[target.x + direction[0]][target.y +
                                                                direction[1]])
        else:
            against = 'the ' + against.name
        if not target.move(direction[0], direction[1]):
            # Could not move
            damage = combat.roll_damage('%dd4' % steps, '0d0',
                                        target.fighter.armor, 0, 'budgeoning',
                                        1.0, target.fighter.resistances)
            ui.message(
                '%s %s backwards and collides with %s, taking %d damage.' %
                (syntax.name(target).capitalize(),
                 syntax.conjugate(target is player.instance,
                                  ('fly', 'flies')), against, damage),
                libtcod.gray)
            target.fighter.take_damage(damage, attacker=attacker)
            steps = force + 1
Exemple #21
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()
def frog_tongue(actor, target, context):
    if target.fighter.hp > 0:
        ui.message("The frog's tongue lashes out at %s!" % syntax.name(target),
                   libtcod.dark_green)
        result = combat.attack_ex(actor.fighter,
                                  target,
                                  0,
                                  accuracy_modifier=1.5,
                                  damage_multiplier=1.5,
                                  verb=('pull', 'pulls'))
        if result == 'hit':
            if 'displacement' in target.fighter.immunities:
                if fov.player_can_see(target.x, target.y):
                    ui.message(
                        '%s %s.' % (syntax.name(target).capitalize(),
                                    syntax.conjugate(target is player.instance,
                                                     ('resist', 'resists'))),
                        libtcod.gray)
                return 'success'
            beam = main.beam(actor.x, actor.y, target.x, target.y)
            pull_to = beam[max(len(beam) - 3, 0)]
            target.set_position(pull_to[0], pull_to[1])
def reeker_breath(actor, target, context):
    #TODO: Upgrade this to use auto targeting
    x = target.x
    y = target.y
    tiles = main.cone(actor.x, actor.y, x, y, max_range=context['range'])

    if tiles is None or len(tiles) == 0 or tiles[0] is None:
        return 'cancelled'

    if fov.player_can_see(target.x, target.y) or actor is player.instance:
        ui.message(
            '%s %s a cloud of acrid fumes!' %
            (syntax.name(actor).capitalize(),
             syntax.conjugate(actor is player.instance,
                              ('breathe', 'breathes'))), libtcod.fuchsia)
    for tile in tiles:
        main.create_reeker_gas(tile[0],
                               tile[1],
                               duration=main.roll_dice('1d6') + 3)
        for obj in main.current_map.fighters:
            if obj.x == tile[0] and obj.y == tile[1]:
                combat.attack_magical(actor.fighter, obj,
                                      'ability_reeker_breath')
Exemple #24
0
def summon_dragonweed(actor, target, context):
    x, y = target
    tile = main.current_map.tiles[x][y]
    if tile.tile_type != 'grass floor':
        if actor is player.instance:
            ui.message('The dragonseed must be planted on grass.',
                       libtcod.gray)
        return 'cancelled'
    seed = main.GameObject(
        x,
        y,
        'w',
        'dragonweed sapling',
        libtcod.dark_chartreuse,
        description=
        'A small, scaly blulb surrounded by sharp, thin leaves. In a few turns, '
        'it will grow into a full-sized Dragonweed.')
    main.current_map.add_object(seed)
    seed_ticker = main.Ticker(4, _dragonseed_ticker)
    seed_ticker.seed = seed
    main.current_map.tickers.append(seed_ticker)
    if actor is player.instance or fov.player_can_see(x, y):
        ui.message('A dragonseed is planted...', libtcod.dark_chartreuse)
    return 'success'
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]))