Exemple #1
0
def holy_lance(actor, target, context):
    import actions
    x, y = context['origin']
    ui.render_explosion(x, y, context['burst'], libtcod.violet,
                        libtcod.light_yellow)

    spell_context = {
        'stamina_cost': context['stamina_cost'],
        'charges': context['charges'],
        'caster': actor,
        'team': actor.fighter.team,
    }
    lance = main.GameObject(
        x,
        y,
        chr(23),
        'Holy Lance',
        libtcod.light_azure,
        on_tick=lambda o: actions.invoke_ability(
            'ability_holy_lance_tick', o, spell_context=spell_context),
        summon_time=10)
    main.current_map.add_object(lance)

    for obj in main.get_fighters_in_burst(x, y, context['burst'], lance,
                                          actor.fighter.team):
        combat.attack_magical(actor.fighter, obj, 'ability_holy_lance')
    return 'success'
Exemple #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()
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)
Exemple #4
0
def blastcap_explode(blastcap, context):
    blastcap.fighter = None
    main.current_map.fighters.remove(blastcap)
    ui.render_explosion(blastcap.x,
                        blastcap.y,
                        1,
                        libtcod.gold,
                        libtcod.white,
                        distance_h='manhattan')
    ui.message('The blastcap explodes with a BANG, stunning nearby creatures!',
               libtcod.gold)
    for obj in main.current_map.fighters:
        if main.is_adjacent_orthogonal(blastcap.x, blastcap.y, obj.x, obj.y):
            if obj.fighter.apply_status_effect(
                    effects.stunned(duration=context['duration'])):
                ui.message(
                    '%s %s stunned!' %
                    (syntax.name(obj).capitalize(),
                     syntax.conjugate(obj is player.instance,
                                      ('are', 'is'))), libtcod.gold)

    if ui.selected_monster is blastcap:
        main.changed_tiles.append((blastcap.x, blastcap.y))
        ui.selected_monster = None
        ui.auto_target_monster()

    blastcap.destroy()
    return
Exemple #5
0
def acid_flask(actor, target, context):
    (x, y) = context['origin']
    ui.render_projectile((actor.x, actor.y), (x, y),
                         libtcod.lime,
                         character='!')
    ui.render_explosion(x, y, 1, libtcod.lightest_lime, libtcod.dark_lime)
    for t in target:
        combat.attack_magical(actor.fighter, t, 'ability_acid_flask')
Exemple #6
0
def castigate(actor, target, context):
    origin = context['origin']
    ui.render_explosion(origin[0], origin[1], 1, libtcod.violet,
                        libtcod.light_yellow)
    dc = context['save_dc'] + actor.fighter.spell_power(elements=['radiance'])
    for f in target:
        f.fighter.apply_status_effect(
            effects.judgement(stacks=main.roll_dice('3d8')), dc, actor)
def haste(actor, target, context):
    target.fighter.apply_status_effect(
        effects.hasted(duration=context['duration']))
    ui.render_explosion(target.x, target.y, 0, libtcod.lightest_fuchsia,
                        libtcod.fuchsia)
    ui.message(
        '%s %s hasted.' % (syntax.name(target).capitalize(),
                           syntax.conjugate(target is player.instance,
                                            ('are', 'is'))),
        spells.essence_colors['arcane'])
    return 'success'
Exemple #8
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 #9
0
def spatial_exchange(actor, target, context):
    if combat.attack_magical(actor.fighter,
                             target,
                             'ability_spatial_exchange',
                             accuracy_bonus=actor.fighter.spell_power(
                                 ['arcane'])) != 'missed':
        ui.render_explosion(actor.x, actor.y, 0, libtcod.white,
                            spells.essence_colors['arcane'])
        ui.render_explosion(target.x, target.y, 0, libtcod.white,
                            spells.essence_colors['arcane'])
        actor.swap_positions(target)
        combat.attack_magical(actor.fighter, target,
                              'data_ability_spatial_exchange')
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 #11
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']))
Exemple #12
0
def _timebomb_ticker(ticker):
    if ticker.ticks >= ticker.max_ticks:
        ticker.dead = True
        ui.message("The rune explodes!", spells.essence_colors['arcane'])
        ui.render_explosion(ticker.rune.x, ticker.rune.y, 1, libtcod.white,
                            spells.essence_colors['arcane'])
        x = ticker.rune.x
        y = ticker.rune.y
        ticker.rune.destroy()
        for adj in main.adjacent_inclusive(x, y):
            for f in main.current_map.fighters:
                if f.x == adj[0] and f.y == adj[1]:
                    combat.attack_magical(ticker.actor.fighter, f,
                                          'data_time_bomb_explosion')
def heal_other(actor, target, context):
    if actor is player.instance:
        ui.message('Yo implement this', libtcod.red)
        return 'failure'

    ui.render_explosion(target.x, target.y, 0, libtcod.lightest_green,
                        libtcod.green)
    amount = main.roll_dice('3d4')
    target.fighter.heal(amount)
    ui.message(
        '%s %s %s for %d damage.' %
        (syntax.name(actor).capitalize(),
         syntax.conjugate(actor is player.instance, ('heal', 'heals')),
         syntax.name(target, reflexive=actor), amount), libtcod.green)
    return 'success'
Exemple #14
0
def fireball(actor, target, context):
    (x, y) = context['origin']
    if actor is not player.instance and not fov.monster_can_see_tile(
            actor, x, y):
        return 'cancelled'
    ui.message('The fireball explodes!', libtcod.flame)
    ui.render_explosion(x, y, 1, libtcod.yellow, libtcod.flame)
    for obj in target:
        combat.attack_magical(actor.fighter, obj, 'ability_fireball')
        if obj.fighter is not None:
            obj.fighter.apply_status_effect(effects.burning())

    for _x in range(x - 1, x + 2):
        for _y in range(y - 1, y + 2):
            main.melt_ice(_x, _y)
Exemple #15
0
def corpse_dance(actor, target, context):
    x, y = target
    ui.render_explosion(x, y, context['radius'], libtcod.violet,
                        libtcod.light_yellow)
    ui.message("{} calls the dead to dance!".format(
        syntax.conjugate(actor is player.instance,
                         ["You", actor.name.capitalize()])))

    for o in main.get_objects(x, y, None, context['radius']):
        if o is not None and o.is_corpse:
            main.raise_dead(actor, o)
        if o.fighter is not None and o.fighter.team == actor.fighter.team and o.fighter.subtype == 'undead':
            o.fighter.apply_status_effect(
                effects.swiftness(context['buff_duration']))
            o.fighter.apply_status_effect(
                effects.berserk(context['buff_duration']))
Exemple #16
0
def sacrifice(actor, target, context):
    actor.fighter.take_damage(min(30, int(actor.fighter.hp / 2)),
                              attacker=actor)
    damage_mod = float(actor.fighter.max_hp - actor.fighter.hp) / float(
        actor.fighter.max_hp)
    ui.render_explosion(actor.x, actor.y, 1, libtcod.violet,
                        libtcod.darkest_violet)
    for f in target:
        combat.attack_magical_ex(actor,
                                 f,
                                 accuracy=None,
                                 base_damage_dice=context['base_damage'],
                                 spell_dice_number=context['dice'],
                                 spell_elements=context['elements'],
                                 damage_mod=1 + damage_mod,
                                 defense_types=context['defense_types'],
                                 damage_types=context.get(
                                     'damage_types', context['elements']),
                                 attack_name=context['name'])
def thermal_instability(actor, target, context):
    ui.render_explosion(actor.x, actor.y, 0, libtcod.yellow,
                        libtcod.dark_flame, chr(19))
    actor.fighter.apply_status_effect(
        effects.unstable(context['buff_duration']))
Exemple #18
0
def holy_lance_tick(actor, target, context):
    caster = context['caster']
    ui.render_explosion(actor.x, actor.y, context['burst'], libtcod.violet,
                        libtcod.light_yellow)
    for f in target:
        combat.attack_magical(caster.fighter, f, 'ability_holy_lance_tick')
Exemple #19
0
def shatter_item(actor, target, context):
    x, y = 0, 0
    dc = context['save_dc']
    if actor is player.instance:  # player is casting
        ui.message_flush('Left-click a target tile, or right-click to cancel.',
                         libtcod.white)
        (x, y) = ui.target_tile()
        if x is None:
            return 'cancelled'
        choices = main.get_objects(
            x, y, lambda o: o.fighter and o.fighter.inventory and len(
                o.fighter.inventory) > 0)
        if len(choices) == 0:
            choices = main.get_objects(x, y, lambda o: o.item is not None)
        if len(choices) > 1:
            target = choices[ui.menu('Which target?',
                                     [i.name for i in choices], 24)]
        elif len(choices) > 0:
            target = choices[0]
        else:
            ui.message('No valid targets here', libtcod.gray)
            return 'cancelled'
        dc += 4
    else:
        x, y = target.x, target.y

    if target is None:
        return 'cancelled'
    item = None
    inventory = None
    if target.fighter is not None:
        inventory = target.fighter.inventory
        if inventory is None or len(inventory) == 0:
            if actor == player.instance:
                ui.message('Target has no items', libtcod.light_blue)
            return 'cancelled'
        item = inventory[libtcod.random_get_int(0, 0, len(inventory) - 1)]
        dc += 5
    elif target.item is not None:
        item = target

    if main.roll_dice('1d20') + main.roll_dice('1d{}'.format(
            actor.fighter.spell_power())) > dc:
        ui.render_explosion(x, y, 1, libtcod.yellow, libtcod.flame)
        ui.message("The {} shatters into pieces!".format(item.name),
                   libtcod.flame)
        if inventory is not None:
            inventory.remove(item)
        item.destroy()
        damage_factor = 4
        if item.equipment is not None:
            damage_factor = item.equipment.weight
        for obj in main.current_map.fighters:
            if obj.distance(x, y) <= context['burst']:
                combat.attack_magical_ex(
                    actor,
                    obj,
                    base_damage_dice='2d{}'.format(damage_factor),
                    spell_dice_number=context['dice'],
                    spell_elements=context['element'],
                    pierce=context['pierce'],
                    shred=context['shred'],
                    defense_types=context['defense_types'],
                    damage_types=context['damage_types'],
                    blockable=context['blockable'],
                    attack_name=context['name'])
        return 'success'
    else:
        ui.message("Shatter failed to break the {}!".format(item.name),
                   libtcod.yellow)
        return 'success'