Esempio n. 1
0
def draw_manual_page(pages, index, line, width, height, break_point):

    page = pages[index]
    page_counter = f'Page {index+1}/{len(pages)}'

    x = 0
    y = 0
    offset = 1  # ensures that strings aren't drawn on the borders

    # Create the window #
    window = tcod.console_new(width, height)
    window.caption = 'Manual'
    setup_console(window, borders=True, bordercolor=colors.darker_red)

    print_line(window, width - len(page_counter) - offset, 0, page_counter)
    print_line(window, offset, height - offset,
               '<Directional keys to navigate>')
    print_line(window, width - 15, height - offset, '<ESC to close>')

    for line_count, paragraph in enumerate(page[line:]):
        line_count += offset
        print_line(window, 1, line_count, paragraph)
        if line_count + break_point > height:
            breaker = '# MORE #'
            print_line(window,
                       width // 2 - len(breaker),
                       line_count + 1,
                       breaker,
                       color=colors.grey)
            break

    tcod.console_blit(window, 0, 0, width, height, 0, x, y, 1, 1)
    tcod.console_flush()

    return window
Esempio n. 2
0
def render_message_panel(message_log, title, con, panel_x, panel_y, width,
                         height, game):
    setup_console(con, caption=title, borders=True)

    current_turn = game.turn
    y = 1
    for message in reversed(message_log.messages):
        if current_turn - message.turn <= 1:
            color_coefficient = 1.0
        elif current_turn - message.turn <= 2:
            color_coefficient = 0.6
        elif current_turn - message.turn <= 3:
            color_coefficient = 0.4
        else:
            color_coefficient = 0.2

        print_line(con,
                   message_log.x,
                   y,
                   message.text,
                   fgcolor=message.color,
                   color_coefficient=color_coefficient)
        y += 1

    con.blit(game.root, panel_x, panel_y, 0, 0, width, height)
Esempio n. 3
0
def draw_bar(panel, x, y, total_width, name, value, maximum, bar_color,
             back_color):
    bar_width = int(float(value) / maximum * total_width)

    panel.draw_rect(x, y, total_width, 1, 0, bg=back_color)
    #tcod.console_set_default_background(panel, bar_color)
    if bar_width > 0:
        panel.draw_rect(x, y, bar_width, 1, 0, bg=bar_color)

    print_line(panel,
               int(x + total_width / 2),
               y,
               f'{name.title()}',
               alignment=tcod.CENTER,
               background=tcod.BKGND_NONE)
Esempio n. 4
0
def render_object_panel(game, con, panel_x, panel_y, width, height):
    setup_console(con, caption='Objects', borders=True)

    # check for objects in FOV
    spotted = [
        ent for ent in (game.item_ents + game.architecture_ents)
        if ent.is_visible(game.fov_map)
    ]
    #spotted = [ent for ent in game.entities if ent.is_visible(game.fov_map) and (ent.item is not None or ent.architecture is not None)]

    if len(spotted):
        spotted.sort(key=game.player.distance_to_ent
                     )  # sort the spotted array by distance to player

        # initial offsets from panel borders
        y = 2

        for ent in spotted:  # Go through the object names and wrap them according to the panel's width

            if y >= con.height - 2:  # If the limit's of the con are reached, cut the con off
                x = center_x_for_text(width, '~ ~ ~ MORE ~ ~ ~')
                print_line(con, x, y, '~ ~ ~ MORE ~ ~ ~')
                break

            # Draw creature name and stats #
            # Some symbols don't print properly with console_print, that's why it's split into put_char_ex and print
            if ent.pos == game.player.pos or (
                    ent.pos == game.cursor.pos and game.state
                    in (GameState.CURSOR_ACTIVE, GameState.CURSOR_TARGETING)):
                symbol = '*'
            else:
                symbol = f'{ent.char}'
            tcod.console_put_char_ex(con, 1, y, symbol, ent.color, tcod.black)
            #wrapped_name = textwrap.wrap(f'{ent.full_name}', width - 3)
            wrapped_name = dynamic_wrap(f'{ent.full_name}', width - 3)

            for i, line in enumerate(wrapped_name):
                print_line(con, 3 + i, y, line, color=ent.color)
                y += 2

    #tcod.console_blit(con, 0, 0, width, height, 0, panel_x, panel_y)
    con.blit(game.root, panel_x, panel_y, 0, 0, width, height)
Esempio n. 5
0
def render_enemy_panel(game, con, panel_x, panel_y, width, height, color):
    setup_console(con, caption='Enemies', borders=True, bordercolor=color)

    # check for monsters in FOV
    spotted = [
        ent for ent in game.npc_ents
        if ent.is_visible(game.fov_map) and ent.f.hp > 0
    ]
    #spotted = [ent for ent in game.entities if ent.ai and ent.f.hp > 0 and ent.is_visible(game.fov_map)]

    if len(spotted):
        spotted.sort(key=game.player.distance_to_ent
                     )  # sort the spotted array by distance to player

        # initial offsets from panel borders
        y = 2

        for ent in spotted:  # Go through the object names and wrap them according to the panel's width
            if y >= con.height - 2:  # If the limit's of the con are reached, cut the con off
                tcod.console_set_default_foreground(con, colors.white)
                x = center_x_for_text(width, '~ ~ ~ MORE ~ ~ ~')
                print_line(con, x, y, '~ ~ ~ MORE ~ ~ ~')
                break

            char = '*' if ent.pos == game.cursor.pos and game.state in [
                GameState.CURSOR_ACTIVE, GameState.CURSOR_TARGETING
            ] else f'{ent.char}'

            # Draw creature name and stats #
            tcod.console_set_default_foreground(con, colors.gray)
            tcod.console_set_color_control(tcod.COLCTRL_1, ent.color,
                                           tcod.black)
            tcod.console_put_char_ex(con, 1, y, char, ent.color, tcod.black)
            print_line(con, 3, y, ent.full_name, color=ent.color)
            y += 1
            x = 1
            tcod.console_put_char_ex(con, x, y, chr(192), tcod.gray,
                                     tcod.black)
            tcod.console_set_color_control(tcod.COLCTRL_2, ent.f.hp_color,
                                           tcod.black)
            tcod.console_set_color_control(tcod.COLCTRL_3, ent.f.stamina_color,
                                           tcod.black)
            status_line = f'%c{ent.f.hp_string.title()}%c|%c{ent.f.stamina_string.title()}%c'\
                          % (tcod.COLCTRL_2, tcod.COLCTRL_STOP, tcod.COLCTRL_3, tcod.COLCTRL_STOP)
            for status, active in ent.f.effects.items(
            ):  # Todo does not consider number of status effects > width of panel
                if active:
                    status_line += f' %white%{status.name[0]}%%'

            print_line(con, x + 1, y, f'{status_line}')

            y += 1

    con.blit(game.root, panel_x, panel_y, 0, 0, width, height)
Esempio n. 6
0
def draw_window(title, body, game, options:Optional[List]=None,
                window_x:Optional[int]=None, window_y:Optional[int]=None, padding_x:Optional[int]=1, padding_y:Optional[int]=2,
                sort_by = 'str', show_cancel_option=True, forced_width:Optional[int]=None, title_color=colors.white, options_colors=None, clear_screen=False):

    cancel_string = '<ESC TO CANCEL>'

    if clear_screen:
        game.root.clear()

    if options is None:
        options  = []

    # Calculate window width #
    if forced_width is not None:
        width = forced_width + padding_x * 2
    else:
        # calculate total width for the box, using the longest unwrapped string from either all possibly displayed strings
        all_strings = (options + [title, body])
        if show_cancel_option:
            all_strings.append(cancel_string)
        longest_string = max(all_strings, key=len)
        width = min(len(longest_string), round(cfg.SCREEN_WIDTH//2)) + padding_x * 2
        if longest_string in options:
            width += 4 # This accounts for the listing points (i.e.' (1) <option>')

    body_wrapped = dynamic_wrap(body, width-padding_x*2)
    options_wrapped = [dynamic_wrap(opt, width-padding_x*2-4) for opt in options] # substract 4 from width as otherwise the listing points break the wrapping

    # Calculate window height #
    height = padding_y * 2 + len(body_wrapped)
    if options:
        for opt in options_wrapped:
            height += len(opt) # opt is a list of strings
        if body_wrapped:
            height += 1 # gap between body-text and options

    # Create the window #
    window = tcod.console.Console(width, height)

    # Print the body to the window #
    y = padding_y
    if body_wrapped:
        for i, line in enumerate(body_wrapped):
            print_line(window, padding_x, y, line)
            y += 1
            if line.count('\n') > 0:
                y += 1
        if options:
            y += 1 # add a gap between body and options, if body exists

    # Print options to the window #
    if options:
        letter_idx = ord('a')
        line_idx = 0
        list_counter = 1
        for option in options_wrapped:
            if isinstance(sort_by, str):
                line = f'({chr(letter_idx)}) {option[0]}'
                letter_idx += 1  # cycle the alphabet by incrementing the ascii code referencing a letter
            elif isinstance(sort_by, int):
                line = f'({list_counter}) {option[0]}'
            else:
                line = option[0]

            color = options_colors[line_idx] if options_colors else colors.white
            print_line(window, padding_x, line_idx + y, f'{line}', color=color)
            line_idx += 1
            list_counter += 1

            if len(option) > 0: # if the option has been wrapped, add the following lines with sufficient spaces
                for line in option[1:]:
                    print_line(window, padding_x, line_idx + y, f'{" " * 4}{line}', color=color)
                    line_idx += 1

    draw_console_borders(window, color=colors.white)

    tcod.console_put_char(window, padding_x, 0, tcod.CHAR_TEEW)
    print_line(window, padding_x+1, 0, f'{title}', color=title_color)
    tcod.console_put_char(window, padding_x+len(title)+1, 0, tcod.CHAR_TEEE)

    if show_cancel_option:
        string = '<ESC TO CANCEL>'
        x = center_x_for_text(width, string)
        print_line(window, x, height - 1, string)

    window_x, window_y = set_window_on_screen(window_x, window_y, width, height)
    window.blit(game.root, window_x, window_y, 0, 0, width, height,)

    tcod.console_flush()

    return window
Esempio n. 7
0
def render_player_panel(game, con, panel_x, panel_y, width, height):
    setup_console(con, caption='Status', borders=True)

    player = game.player
    y = 0

    # Health & Stamina #
    y += 2
    hp_string = f'HIT: %c{player.f.hp}/{player.f.max_hp}%c'
    print_line(con, 1, y, hp_string, color=game.player.f.hp_color)
    hp_diff = player.statistics.hp_change
    if hp_diff != 0:
        col = colors.darker_green if hp_diff > 0 else colors.darker_red
        print_line(con, len(hp_string) - 2, y, f'(%{col}%{hp_diff}%%)')

    sta_string = f'STA: %c{player.f.stamina}/{player.f.max_stamina}%c'
    print_line(con, 1, y + 1, sta_string, color=game.player.f.stamina_color)
    sta_diff = player.statistics.sta_change
    if sta_diff != 0:
        col = colors.lighter_sea if sta_diff > 0 else colors.darker_sea
        print_line(con, len(sta_string) - 2, y + 1, f'(%{col}%{sta_diff}%%)')

    # Effects #
    # TODO can theoretically overflow if there a large number of effects (>6) at once
    y += 2
    x = 2
    for effect, active in player.effects.items():
        if active:
            print_line(con, x, y, f'*{effect.name[0]}', color=colors.red)
            x += 3

    # Equipment-derived stats #
    y += 1
    # Defensive Stats #
    surrounded = player.f.surrounded
    if surrounded == Surrounded.THREATENED:
        print_line(con, 3, y, '*THREATENED*', color=colors.orange)
    if surrounded == Surrounded.OVERWHELMED:
        print_line(con, 3, y, '*OVERWHELMED*', color=colors.red)

    print_line(con, 1, y + 1, f'STR: {player.f.strength}')
    color = colors.white if player.f.modded_defense >= player.f.defense else colors.dark_red
    print_line(con,
               1,
               y + 2,
               f'DEF: %c{player.f.modded_defense}%c',
               color=color)

    color = colors.panel_stat_active if player.f.is_dashing else colors.panel_inactive
    print_line(con, 9, y + 1, f'DASHING', color=color)
    #
    if player.f.shield and player.f.shield.block_def:
        col1 = colors.panel_inactive if not player.f.is_blocking else colors.panel_stat_active
        col2 = 'dark_red' if player.f.shield.block_def > player.f.modded_block_def else f'{col1}'
        print_line(con, 9, y + 2,
                   f'%{col1}%BLOCK:%% %{col2}%{player.f.modded_block_def}%%')

    # Weapon #
    y += 4
    if player.f.weapon_melee is not None:
        color = colors.panel_stat_active if player.f.weapon_melee.is_active_weapon(
            player) else colors.panel_inactive
        print_line(con, 1, y, f'%c{player.f.weapon_melee.name}%c', color=color)

    if player.f.weapon_ranged is not None:
        color = colors.panel_stat_active if player.f.weapon_ranged.is_active_weapon(
            player) else colors.panel_inactive
        x = 2 + len(player.f.weapon_melee.name
                    ) if player.f.weapon_melee is not None else 1
        print_line(con,
                   x,
                   y,
                   f'%c{player.f.weapon_ranged.name}%c',
                   color=color)

    if player.f.active_weapon is not None:
        print_line(
            con, 2, y + 1,
            f'ATK: {game.player.f.active_weapon.moveset.current_move}/{game.player.f.active_weapon.moveset.moves}'
        )
        # todo color depending on if its < or > base damage
        print_line(
            con, 2, y + 2,
            f'DAM: {game.player.f.modded_dmg_potential[0]}-{game.player.f.modded_dmg_potential[-1]}'
        )

        # Visualize targets for next attack
        x = 11
        print_line(con, x, y + 1, f'TAR:')
        for i, line in enumerate(player.f.active_weapon.moveset.targets_gui):
            print_line(con, x + 4, y + i, ''.join(line))

    # # Quick Slots #
    # y = 14
    # draw_quickslots(con, y, game)

    con.blit(game.root, panel_x, panel_y, 0, 0, width, height)