/* * Copyright (C) 2002-2007 The Warp Rogue Team * Part of the Warp Rogue Project * * This software is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License. * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY. * * See the license.txt file for more details. */ /* * Module Name: Ui * Description: - */ /* * Game screen */ #define Uses_Util #define Uses_Terrain #define Uses_Object #define Uses_Character #define Uses_CharacterAdvancement #define Uses_Stats #define Uses_Area #define Uses_Faction #define Uses_Party #define Uses_World #define Uses_ProgramManager #define Uses_Perception #include "mheader.h" #include "ui.h" #define ACTION_WINDOW_WIDTH 68 #define ACTION_WINDOW_HEIGHT 24 #define ACTION_WINDOW_MIN_Y 3 #define ACTION_WINDOW_MIN_X GAME_SCREEN_MIN_X #define ACTION_WINDOW_MAX_Y (ACTION_WINDOW_MIN_Y + ACTION_WINDOW_HEIGHT) #define ACTION_WINDOW_MAX_X (ACTION_WINDOW_MIN_X + ACTION_WINDOW_WIDTH) #define PARTY_WINDOW_MIN_Y (ACTION_WINDOW_MAX_Y + 2) #define PARTY_WINDOW_MIN_X GAME_SCREEN_MIN_X #define PARTY_WINDOW_MAX_Y GAME_SCREEN_MAX_Y #define LOCATION_WINDOW_MIN_Y PARTY_WINDOW_MIN_Y #define CHARACTER_WINDOW_WIDTH 20 #define INFO_BAR_WIDTH (CHARACTER_WINDOW_WIDTH + 4) #define INFO_BAR_MIN_X (ACTION_WINDOW_MAX_X + 4) #define INFO_BAR_MAX_X (INFO_BAR_MIN_X + INFO_BAR_WIDTH) #define SYMBOL_MACHINE_PARTS '%' #define SYMBOL_CORPSE '%' #define SYMBOL_BODY_PART '`' static void render_action_window(void); static void render_sector(SCREEN_COORD, SCREEN_COORD, const SECTOR *); static void render_gory_terrain(SCREEN_COORD, SCREEN_COORD, const TERRAIN *); static void render_character_info_windows(const CHARACTER *); static void render_weapon_status_window(const CHARACTER *); static void render_armour_status_window(const CHARACTER *); static void render_party_window(void); static void render_location_windows(void); /* * renders the game screen */ void render_game_screen(void) { render_background(); render_message_window(); render_action_window(); render_character_info_windows(player_controlled_character()); render_party_window(); } /* * renders the message window */ void render_message_window(void) { clear_text_window( GAME_SCREEN_MESSAGE_ROW, GAME_SCREEN_MIN_X, GAME_SCREEN_MESSAGE_ROW, GAME_SCREEN_MAX_X ); render_text_at(C_TEXT, GAME_SCREEN_MESSAGE_ROW, GAME_SCREEN_MIN_X, game_screen_message_buffer() ); } /* * renders the action window */ static void render_action_window(void) { SCREEN_COORD y, x; const AREA_SECTION *visible_area; clear_text_window(ACTION_WINDOW_MIN_Y, ACTION_WINDOW_MIN_X, ACTION_WINDOW_MAX_Y, ACTION_WINDOW_MAX_X ); visible_area = get_visible_area(); for (y = ACTION_WINDOW_MIN_Y; y <= ACTION_WINDOW_MAX_Y; y++) { for (x = ACTION_WINDOW_MIN_X; x <= ACTION_WINDOW_MAX_X; x++) { AREA_POINT p; p.y = visible_area->top + y - ACTION_WINDOW_MIN_Y; p.x = visible_area->left + x - ACTION_WINDOW_MIN_X; render_sector(y, x, sector_at(&p)); } } } /* * renders the passed sector at the passed location */ static void render_sector(SCREEN_COORD wy, SCREEN_COORD wx, const SECTOR *sector) { CHARACTER *character; OBJECT *object; TERRAIN *terrain; character = sector->character; if (character != NULL) { if (character->is_hostile && character_unnoticed(character)) { /* DO NOT RENDER */ } else { render_char_at(character->colour, wy, wx, character->symbol ); return; } } object = sector->object; if (object != NULL) { if (object->gore_level == GORE_LEVEL_ZERO) { render_char_at(object->colour, wy, wx, object_static_data(object)->symbol ); } else if (object->gore_level >= GORE_LEVEL_BLOOD) { render_char_at(C_BLOOD, wy, wx, object_static_data(object)->symbol ); } return; } terrain = sector->terrain; if (terrain != NULL) { if (terrain->gore_level == GORE_LEVEL_ZERO) { render_char_at(terrain->colour, wy, wx, terrain_static_data(terrain)->symbol ); } else { render_gory_terrain(wy, wx, terrain); } } } /* * renders gory terrain */ static void render_gory_terrain(SCREEN_COORD y, SCREEN_COORD x, const TERRAIN *terrain ) { SYMBOL symbol; COLOUR colour; switch (terrain->gore_level) { case GORE_LEVEL_MACHINE_PARTS: colour = C_MACHINE; symbol = SYMBOL_MACHINE_PARTS; break; case GORE_LEVEL_POISONED_CORPSE: colour = C_POISONED; symbol = SYMBOL_CORPSE; break; case GORE_LEVEL_BLOOD: colour = C_BLOOD; symbol = terrain_static_data(terrain)->symbol; break; case GORE_LEVEL_BODY_PART: colour = C_BLOOD; symbol = SYMBOL_BODY_PART; break; case GORE_LEVEL_CORPSE: colour = C_BLOOD; symbol = SYMBOL_CORPSE; break; default: die("*** CORE ERROR *** invalid gore level"); /* NEVER REACHED */ return; } render_char_at(colour, y, x, symbol); } /* * renders the character info windows */ static void render_character_info_windows(const CHARACTER *character) { clear_text_window(3, INFO_BAR_MIN_X, 3, INFO_BAR_MAX_X); render_text_at(C_FIELD_VALUE, 3, INFO_BAR_MIN_X, character->name); clear_text_window(5, INFO_BAR_MIN_X, 5, INFO_BAR_MAX_X); place_cursor_at(5, INFO_BAR_MIN_X); if (character->ep_total == EP_LIMIT) { render_text(C_FIELD_VALUE, "Hero"); } else { render_text(C_FIELD_VALUE, "%d EP", character->ep); } clear_text_window(7, INFO_BAR_MIN_X, 15, INFO_BAR_MAX_X); render_stats_at(character, 7, INFO_BAR_MIN_X); render_weapon_status_window(character); render_armour_status_window(character); render_location_windows(); } /* * renders the weapon status window */ static void render_weapon_status_window(const CHARACTER *character) { OBJECT *weapon; clear_text_window(17, INFO_BAR_MIN_X, 18, INFO_BAR_MAX_X); weapon = character->weapon; if (weapon == NULL) { return; } render_lstring_at(C_FIELD_VALUE, 17, INFO_BAR_MIN_X, object_static_data(weapon)->name, 24 ); if (weapon->charge != CHARGE_NIL) { render_text_at(C_FIELD_VALUE, 18, INFO_BAR_MIN_X, "[%d]", weapon->charge ); } if (!weapon->functional) { render_text(C_FIELD_VALUE, " (jammed)"); } } /* * renders the armour status window */ static void render_armour_status_window(const CHARACTER *character) { COLOUR colour; clear_text_window(20, INFO_BAR_MIN_X, 21, INFO_BAR_MAX_X); render_text_at(C_FIELD_NAME, 21, INFO_BAR_MIN_X, "%-13s: ", "Armour Value" ); if (character->armour_rating.current > character->armour_rating.total) { colour = C_FIELD_VALUE_INCREASED; } else { colour = C_FIELD_VALUE; } render_text(colour, "%d", character->armour_rating.current ); if (character->armour == NULL) return; render_lstring_at(C_FIELD_VALUE, 20, INFO_BAR_MIN_X, object_static_data(character->armour)->name, 24 ); } /* * renders the party window */ static void render_party_window(void) { SCREEN_COORD min_y, max_y; LIST_NODE *node; min_y = PARTY_WINDOW_MIN_Y; max_y = PARTY_WINDOW_MAX_Y; for (node = party_player()->head; node != NULL; node = node->next) { SCREEN_COORD min_x, max_x; CHARACTER *character; character = (CHARACTER *)node->data; min_x = PARTY_WINDOW_MIN_X; min_x += character->type * (CHARACTER_WINDOW_WIDTH + 4); max_x = min_x + CHARACTER_WINDOW_WIDTH; clear_text_window(min_y, min_x, max_y, max_x); render_char_at(C_HOTKEY_BRACKET, min_y, min_x, '['); render_key_name(C_HOTKEY, command_key(CM_CHARACTER_1 + character->type) ); render_char(C_HOTKEY_BRACKET, ']'); render_lstring_at(C_FIELD_VALUE, min_y, min_x + 4, character->name, CHARACTER_WINDOW_WIDTH - 4 ); place_cursor_at(min_y + 1, min_x); render_character_status(character, max_y, false); } } /* * renders the location windows */ static void render_location_windows(void) { AREA *area; area = active_area(); clear_text_window(LOCATION_WINDOW_MIN_Y, INFO_BAR_MIN_X, LOCATION_WINDOW_MIN_Y + 1, INFO_BAR_MAX_X ); render_text_at(C_FIELD_VALUE, LOCATION_WINDOW_MIN_Y, INFO_BAR_MIN_X, world()->name ); render_text_at(C_FIELD_VALUE, LOCATION_WINDOW_MIN_Y + 1, INFO_BAR_MIN_X, "%d, %d", area->location.y, area->location.x ); clear_text_window(LOCATION_WINDOW_MIN_Y + 3, INFO_BAR_MIN_X, LOCATION_WINDOW_MIN_Y + 4, INFO_BAR_MAX_X ); render_text_at(C_FIELD_VALUE, LOCATION_WINDOW_MIN_Y + 3, INFO_BAR_MIN_X, area->name ); render_text_at(C_FIELD_VALUE, LOCATION_WINDOW_MIN_Y + 4, INFO_BAR_MIN_X, "Level %d", area->location.z ); }