Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,346 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/gui/gui_button.h"
#include "ultima/nuvie/script/script.h"
#include "ultima/nuvie/views/view.h"
#include "ultima/nuvie/actors/actor.h"
#include "ultima/nuvie/core/party.h"
#include "ultima/nuvie/portraits/portrait.h"
#include "ultima/nuvie/views/actor_view.h"
#include "ultima/nuvie/fonts/font.h"
#include "ultima/nuvie/core/player.h"
#include "ultima/nuvie/core/events.h"
#include "ultima/nuvie/keybinding/keys.h"
namespace Ultima {
namespace Nuvie {
extern GUI_status inventoryViewButtonCallback(void *data);
extern GUI_status partyViewButtonCallback(void *data);
#define MD Game::get_game()->get_game_type()==NUVIE_GAME_MD
ActorView::ActorView(const Configuration *cfg) : View(cfg), portrait(nullptr),
portrait_data(nullptr), in_party(false), cursor_tile(nullptr),
show_cursor(false) {
cursor_pos.x = 2;
cursor_pos.px = cursor_pos.py = 0;
}
ActorView::~ActorView() {
if (portrait_data != nullptr)
free(portrait_data);
}
bool ActorView::init(Screen *tmp_screen, void *view_manager, uint16 x, uint16 y, Font *f, Party *p, TileManager *tm, ObjManager *om, Portrait *port) {
if (Game::get_game()->get_game_type() == NUVIE_GAME_U6)
View::init(x, y, f, p, tm, om);
else
View::init(x, y - 2, f, p, tm, om);
portrait = port;
add_command_icons(tmp_screen, view_manager);
set_party_member(0);
cursor_tile = tile_manager->get_cursor_tile();
return true;
}
bool ActorView::set_party_member(uint8 party_member) {
in_party = false;
if (View::set_party_member(party_member)
&& !Game::get_game()->get_event()->using_control_cheat()) {
in_party = true;
if (party_button) party_button->Show();
} else {
if (left_button) left_button->Hide();
if (right_button) right_button->Hide();
if (party_button) party_button->Hide();
}
if (portrait) { // this might not be set yet. if called from View::init()
if (portrait_data)
free(portrait_data);
if (in_party)
portrait_data = portrait->get_portrait_data(party->get_actor(cur_party_member));
else {
Player *player = Game::get_game()->get_player();
portrait_data = portrait->get_portrait_data(player->get_actor());
}
if (portrait_data == nullptr)
return false;
}
return true;
}
void ActorView::Display(bool full_redraw) {
if (portrait_data != nullptr && (full_redraw || update_display || Game::get_game()->is_original_plus_full_map())) {
update_display = false;
if (MD) {
fill_md_background(bg_color, area);
screen->blit(area.left + 1, area.top + 16, portrait_data, 8, portrait->get_portrait_width(), portrait->get_portrait_height(), portrait->get_portrait_width(), true);
} else {
screen->fill(bg_color, area.left, area.top, area.width(), area.height());
screen->blit(area.left, area.top + 8, portrait_data, 8, portrait->get_portrait_width(), portrait->get_portrait_height(), portrait->get_portrait_width(), false);
}
display_name();
display_actor_stats();
DisplayChildren(); //draw buttons
screen->update(area.left, area.top, area.width(), area.height());
}
if (show_cursor && cursor_tile != nullptr) {
screen->blit(cursor_pos.px, cursor_pos.py, (unsigned char *)cursor_tile->data,
8, 16, 16, 16, true, nullptr);
screen->update(cursor_pos.px, cursor_pos.py, 16, 16);
}
}
void ActorView::add_command_icons(Screen *tmp_screen, void *view_manager) {
int x_off = 0; // U6 and MD
int y = 80; // U6
Tile *tile;
Graphics::ManagedSurface *button_image;
Graphics::ManagedSurface *button_image2;
if (Game::get_game()->get_game_type() == NUVIE_GAME_SE) {
x_off = 1;
y = 96;
} else if (MD)
y = 100;
//FIX need to handle clicked button image, check image free on destruct.
tile = tile_manager->get_tile(MD ? 282 : 387); //left arrow icon
button_image = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
button_image2 = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
left_button = new GUI_Button(this, x_off, y, button_image, button_image2, this);
this->AddWidget(left_button);
tile = tile_manager->get_tile(MD ? 279 : 384); //party view icon
button_image = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
button_image2 = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
party_button = new GUI_Button(view_manager, 16 + x_off, y, button_image, button_image2, this);
this->AddWidget(party_button);
tile = tile_manager->get_tile(MD ? 281 : 386); //inventory view icon
button_image = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
button_image2 = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
inventory_button = new GUI_Button(view_manager, 2 * 16 + x_off, y, button_image, button_image2, this);
this->AddWidget(inventory_button);
tile = tile_manager->get_tile(MD ? 283 : 388); //right arrow icon
button_image = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
button_image2 = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
right_button = new GUI_Button(this, 3 * 16 + x_off, y, button_image, button_image2, this);
this->AddWidget(right_button);
return;
}
void ActorView::display_name() {
const char *name;
int y_off = 0;
if (MD)
y_off = 4;
else if (Game::get_game()->get_game_type() == NUVIE_GAME_SE)
y_off = 1;
if (in_party)
name = party->get_actor_name(cur_party_member);
else
name = Game::get_game()->get_player()->get_actor()->get_name(true);
if (name == nullptr)
return;
font->drawString(screen, name, area.left + ((136) - strlen(name) * 8) / 2, area.top + y_off);
return;
}
void ActorView::display_actor_stats() {
Actor *actor;
char buf[10];
int x_off = 0;
int y_off = 0;
uint8 hp_text_color = 0; //standard text color
if (in_party)
actor = party->get_actor(cur_party_member);
else
actor = Game::get_game()->get_player()->get_actor();
if (MD) {
x_off = -1;
} else if (Game::get_game()->get_game_type() == NUVIE_GAME_SE) {
x_off = 2;
y_off = - 6;
}
hp_text_color = actor->get_hp_text_color();
Common::sprintf_s(buf, "%d", Game::get_game()->get_script()->call_actor_str_adj(actor)); //actor->get_strength());
uint8 str_len = font->drawString(screen, "STR:", area.left + 5 * 16 + x_off, area.top + y_off + 16);
font->drawString(screen, buf, area.left + 5 * 16 + x_off + str_len, area.top + y_off + 16, actor->get_str_text_color(), 0);
Common::sprintf_s(buf, "%d", Game::get_game()->get_script()->call_actor_dex_adj(actor));
str_len = font->drawString(screen, "DEX:", area.left + 5 * 16 + x_off, area.top + y_off + 16 + 8);
font->drawString(screen, buf, area.left + 5 * 16 + x_off + str_len, area.top + y_off + 16 + 8, actor->get_dex_text_color(), 0);
Common::sprintf_s(buf, "INT:%d", Game::get_game()->get_script()->call_actor_int_adj(actor));
font->drawString(screen, buf, area.left + 5 * 16 + x_off, area.top + y_off + 16 + 2 * 8);
if (MD || Game::get_game()->get_game_type() == NUVIE_GAME_SE) {
Common::sprintf_s(buf, "%3d", actor->get_hp());
str_len = font->drawString(screen, "HP:", area.left + 5 * 16 + x_off, area.top + y_off + 16 + 3 * 8);
font->drawString(screen, buf, strlen(buf), area.left + 5 * 16 + x_off + str_len, area.top + y_off + 16 + 3 * 8, hp_text_color, 0);
Common::sprintf_s(buf, "HM:%3d", actor->get_maxhp());
font->drawString(screen, buf, area.left + 5 * 16 + x_off, area.top + y_off + 16 + 4 * 8);
Common::sprintf_s(buf, "Lev:%2d", actor->get_level());
font->drawString(screen, buf, area.left + 5 * 16 + x_off, area.top + y_off + 16 + 5 * 8);
font->drawString(screen, "Exper:", area.left + 5 * 16 + x_off, area.top + y_off + 16 + 6 * 8);
Common::sprintf_s(buf, "%6d", actor->get_exp());
font->drawString(screen, buf, area.left + 5 * 16 + x_off, area.top + y_off + 16 + 7 * 8);
return;
}
font->drawString(screen, "Magic", area.left + 5 * 16, area.top + 16 + 4 * 8);
Common::sprintf_s(buf, "%d/%d", actor->get_magic(), actor->get_maxmagic());
font->drawString(screen, buf, area.left + 5 * 16, area.top + 16 + 5 * 8);
font->drawString(screen, "Health", area.left + 5 * 16, area.top + 16 + 6 * 8);
Common::sprintf_s(buf, "%3d", actor->get_hp());
font->drawString(screen, buf, strlen(buf), area.left + 5 * 16, area.top + 16 + 7 * 8, hp_text_color, 0);
Common::sprintf_s(buf, " /%d", actor->get_maxhp());
font->drawString(screen, buf, area.left + 5 * 16, area.top + 16 + 7 * 8);
font->drawString(screen, "Lev/Exp", area.left + 5 * 16, area.top + 16 + 8 * 8);
Common::sprintf_s(buf, "%d/%d", actor->get_level(), actor->get_exp());
font->drawString(screen, buf, area.left + 5 * 16, area.top + 16 + 9 * 8);
return;
}
GUI_status ActorView::MouseWheel(sint32 x, sint32 y) {
int xpos, ypos;
screen->get_mouse_location(&xpos, &ypos);
xpos -= area.left;
ypos -= area.top;
if (xpos < 0 || ypos > area.top + area.height() - 7)
return GUI_PASS; // goes to MsgScroll
if (y > 0) {
View::callback(BUTTON_CB, left_button, Game::get_game()->get_view_manager());
} else if (y < 0) {
View::callback(BUTTON_CB, right_button, Game::get_game()->get_view_manager());
}
return GUI_YUM;
}
GUI_status ActorView::MouseDown(int x, int y, Events::MouseButton button) {
return GUI_PASS;
}
/* Move the cursor around and use command icons.
*/
GUI_status ActorView::KeyDown(const Common::KeyState &key) {
if (!show_cursor) // FIXME: don't rely on show_cursor to get/pass focus
return GUI_PASS;
KeyBinder *keybinder = Game::get_game()->get_keybinder();
ActionType a = keybinder->get_ActionType(key);
switch (keybinder->GetActionKeyType(a)) {
case SOUTH_WEST_KEY:
case NORTH_WEST_KEY:
case WEST_KEY:
moveCursorToButton(cursor_pos.x - 1);
break;
case NORTH_EAST_KEY:
case SOUTH_EAST_KEY:
case EAST_KEY:
moveCursorToButton(cursor_pos.x + 1);
break;
case DO_ACTION_KEY:
select_button();
break;
case NORTH_KEY: // would otherwise move invisible mapwindow cursor
case SOUTH_KEY:
break;
default:
// set_show_cursor(false); // newAction() can move cursor here
return GUI_PASS;
}
return GUI_YUM;
}
/* Put cursor over one of the command icons. */
void ActorView::moveCursorToButton(sint8 button_num) {
if (button_num < 0 || button_num > 3)
return;
cursor_pos.x = button_num;
update_cursor();
update_display = true;
}
/* Update on-screen location (px,py) of cursor.
*/
void ActorView::update_cursor() {
cursor_pos.px = ((cursor_pos.x + 1) * 16) - 16;
cursor_pos.py = party_button->area.top;
cursor_pos.px += area.left;
//cursor_pos.py += area.top;
}
void ActorView::set_show_cursor(bool state) {
show_cursor = state;
update_display = true;
}
void ActorView::select_button() {
ViewManager *view_manager = Game::get_game()->get_view_manager();
if (cursor_pos.x == 0) // left
View::callback(BUTTON_CB, left_button, view_manager);
if (cursor_pos.x == 1) // party
View::callback(BUTTON_CB, party_button, view_manager);
if (cursor_pos.x == 2) // inventory
View::callback(BUTTON_CB, inventory_button, view_manager);
if (cursor_pos.x == 3) // right
View::callback(BUTTON_CB, right_button, view_manager);
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,81 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_ACTOR_VIEW_H
#define NUVIE_VIEWS_ACTOR_VIEW_H
#include "ultima/nuvie/views/view.h"
namespace Ultima {
namespace Nuvie {
class Configuration;
class Screen;
class Font;
class TileManager;
class ObjManager;
class Portrait;
class Party;
class ActorView : public View {
Portrait *portrait;
unsigned char *portrait_data;
struct actcursor_pos_s {
uint8 x;
uint32 px, py;
} cursor_pos;
Tile *cursor_tile;
bool show_cursor;
public:
ActorView(const Configuration *cfg);
~ActorView() override;
bool init(Screen *tmp_screen, void *view_manager, uint16 x, uint16 y, Font *f, Party *p, TileManager *tm, ObjManager *om, Portrait *port);
bool set_party_member(uint8 party_member) override;
void Display(bool full_redraw) override;
void update() {
update_display = true;
}
void set_show_cursor(bool state);
void moveCursorToButton(sint8 button_num);
protected:
void add_command_icons(Screen *tmp_screen, void *view_manager);
void display_name();
void display_actor_stats();
bool in_party;
GUI_status MouseDown(int x, int y, Events::MouseButton button) override;
GUI_status KeyDown(const Common::KeyState &key) override;
GUI_status MouseWheel(sint32 x, sint32 y) override;
void update_cursor();
void select_button();
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,399 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/misc/u6_misc.h"
#include "ultima/nuvie/core/events.h"
#include "ultima/nuvie/gui/gui.h"
#include "ultima/nuvie/gui/gui_button.h"
#include "ultima/nuvie/core/u6_objects.h"
#include "ultima/nuvie/core/party.h"
#include "ultima/nuvie/actors/actor.h"
#include "ultima/nuvie/fonts/font.h"
#include "ultima/nuvie/views/view_manager.h"
#include "ultima/nuvie/fonts/font_manager.h"
#include "ultima/nuvie/views/container_widget_gump.h"
#include "ultima/nuvie/views/container_view_gump.h"
#include "ultima/nuvie/keybinding/keys.h"
namespace Ultima {
namespace Nuvie {
static const int CONTAINER_WIDGET_OFFSET = 29;
#define CHECK_X 0
ContainerViewGump::ContainerViewGump(const Configuration *cfg) : DraggableView(cfg),
gump_button(nullptr), up_arrow_button(nullptr), down_arrow_button(nullptr),
doll_button(nullptr), left_arrow_button(nullptr),
right_arrow_button(nullptr), container_widget(nullptr), font(nullptr),
actor(nullptr), container_obj(nullptr), container_widget_y_offset(0) {
}
ContainerViewGump::~ContainerViewGump() {
}
bool ContainerViewGump::init(Screen *tmp_screen, void *view_manager, uint16 x, uint16 y, Font *f, Party *p, TileManager *tm, ObjManager *om, Obj *container_obj_type) {
View::init(x, y, f, p, tm, om);
//actor = p->get_actor(p->get_leader()); don't have party leader as default, get owner of container obj or leave nullptr (moved to init_container_type)
Common::Path datadir = GUI::get_gui()->get_data_dir();
Common::Path imagefile;
Common::Path path;
build_path(datadir, "images", path);
datadir = path;
build_path(datadir, "gumps", path);
datadir = path;
init_container_type(datadir, container_obj_type);
set_bg_color_key(0, 0x70, 0xfc);
//font = new GUI_Font(GUI_FONT_GUMP);
//font->setColoring( 0x08, 0x08, 0x08, 0x80, 0x58, 0x30, 0x00, 0x00, 0x00);
font = f;
return true;
}
void ContainerViewGump::init_container_type(const Common::Path &datadir, Obj *obj_type) {
if (obj_type != nullptr) {
if (obj_type->is_in_inventory())
actor = obj_type->get_actor_holding_obj();
if (Game::get_game()->get_game_type() == NUVIE_GAME_U6) {
if (obj_type->obj_n == OBJ_U6_CHEST)
return init_chest(datadir);
else if (obj_type->obj_n == OBJ_U6_CRATE)
return init_crate(datadir);
else if (obj_type->obj_n == OBJ_U6_BARREL)
return init_barrel(datadir);
else if (obj_type->obj_n == OBJ_U6_DEAD_GARGOYLE)
return init_corpse(datadir, "corpse_gargoyle_bg.bmp");
else if (obj_type->obj_n == OBJ_U6_DEAD_BODY
|| obj_type->obj_n == OBJ_U6_GRAVE || obj_type->obj_n == OBJ_U6_REMAINS)
return init_corpse(datadir, "corpse_body_bg.bmp");
else if (obj_type->obj_n == OBJ_U6_DEAD_CYCLOPS)
return init_corpse(datadir, "corpse_cyclops_bg.bmp");
else if (obj_type->obj_n == OBJ_U6_DEAD_ANIMAL || obj_type->obj_n == OBJ_U6_MOUSE
|| obj_type->obj_n == OBJ_U6_MONGBAT || obj_type->obj_n == OBJ_U6_DRAKE
|| obj_type->obj_n == OBJ_U6_REAPER)
return init_corpse(datadir, "corpse_animal_bg.bmp");
}
}
return init_backpack(datadir, obj_type ? !obj_type->is_in_inventory() : true);
}
void ContainerViewGump::init_backpack(const Common::Path &datadir, bool extend_area_w) {
Common::Path imagefile, path;
uint8 check_y = 27;
gump_button = loadButton(datadir, "gump", CHECK_X, check_y);
build_path(datadir, "container", path);
up_arrow_button = loadButton(path, "cont_up", 83, 35);
down_arrow_button = loadButton(path, "cont_down", 83, 66);
build_path(path, "backpack_bg.bmp", imagefile);
bg_image = SDL_LoadBMP(imagefile);
doll_button = loadButton(path, "cont_doll", area.left + 18, area.top + bg_image->h);
left_arrow_button = loadButton(path, "cont_left", area.left + 18 + 11, area.top + bg_image->h);
right_arrow_button = loadButton(path, "cont_right", area.left + 18 + 22, area.top + bg_image->h);
SetRect(area.left, area.top, bg_image->w, bg_image->h + 16); //111, 101);
container_widget = new ContainerWidgetGump(config, this);
container_widget_y_offset = CONTAINER_WIDGET_OFFSET;
container_widget->init(actor, 21, container_widget_y_offset, 4, 3, tile_manager, obj_manager, font, CHECK_X, check_y);
AddWidget(container_widget);
if (extend_area_w) // text extends beyond the gump
area.right += 4;
}
void ContainerViewGump::init_chest(const Common::Path &datadir) {
Common::Path imagefile, path;
uint8 check_y = 56;
gump_button = loadButton(datadir, "gump", CHECK_X, check_y);
build_path(datadir, "container", path);
up_arrow_button = loadButton(path, "cont_up", 85, 31);
down_arrow_button = loadButton(path, "cont_down", 85, 47);
build_path(path, "chest_bg.bmp", imagefile);
bg_image = SDL_LoadBMP(imagefile);
SetRect(area.left, area.top, bg_image->w, bg_image->h + 16); //111, 101);
container_widget = new ContainerWidgetGump(config, this);
container_widget_y_offset = CONTAINER_WIDGET_OFFSET - 1;
container_widget->init(actor, 21, container_widget_y_offset, 4, 2, tile_manager, obj_manager, font, CHECK_X, check_y);
AddWidget(container_widget);
}
void ContainerViewGump::init_crate(const Common::Path &datadir) {
Common::Path imagefile, path;
uint8 check_y = 63;
gump_button = loadButton(datadir, "gump", CHECK_X, check_y);
build_path(datadir, "container", path);
up_arrow_button = loadButton(path, "cont_up", 100, 15);
down_arrow_button = loadButton(path, "cont_down", 100, 46);
build_path(path, "crate_bg.bmp", imagefile);
bg_image = SDL_LoadBMP(imagefile);
SetRect(area.left, area.top, bg_image->w, bg_image->h);
container_widget = new ContainerWidgetGump(config, this);
container_widget_y_offset = 10;
container_widget->init(actor, 21, container_widget_y_offset, 5, 3, tile_manager, obj_manager, font, CHECK_X, check_y);
AddWidget(container_widget);
}
void ContainerViewGump::init_barrel(const Common::Path &datadir) {
Common::Path imagefile, path;
uint8 check_y = 55;
gump_button = loadButton(datadir, "gump", CHECK_X, check_y);
build_path(datadir, "container", path);
up_arrow_button = loadButton(path, "cont_up", 102, 28);
down_arrow_button = loadButton(path, "cont_down", 102, 42);
build_path(path, "barrel_bg.bmp", imagefile);
bg_image = SDL_LoadBMP(imagefile);
SetRect(area.left, area.top, bg_image->w, bg_image->h);
container_widget = new ContainerWidgetGump(config, this);
container_widget_y_offset = 24;
container_widget->init(actor, 38, container_widget_y_offset, 4, 2, tile_manager, obj_manager, font, CHECK_X, check_y);
AddWidget(container_widget);
}
void ContainerViewGump::init_corpse(const Common::Path &datadir, Std::string bg_filename) {
Common::Path imagefile, path;
uint8 check_y = 25;
gump_button = loadButton(datadir, "gump", CHECK_X, check_y);
build_path(datadir, "container", path);
up_arrow_button = loadButton(path, "cont_up", 67, 28);
down_arrow_button = loadButton(path, "cont_down", 67, 78);
build_path(path, bg_filename, imagefile);
bg_image = SDL_LoadBMP(imagefile);
SetRect(area.left, area.top, bg_image->w, bg_image->h);
container_widget = new ContainerWidgetGump(config, this);
container_widget_y_offset = 26;
container_widget->init(actor, 20, container_widget_y_offset, 3, 4, tile_manager, obj_manager, font, CHECK_X, check_y);
AddWidget(container_widget);
}
void ContainerViewGump::set_actor(Actor *a) {
actor = a;
container_obj = nullptr;
container_widget->set_actor(a);
if (doll_button)
doll_button->Show();
if (party->get_member_num(a) >= 0) {
if (left_arrow_button)
left_arrow_button->Show();
if (right_arrow_button)
right_arrow_button->Show();
} else {
if (left_arrow_button)
left_arrow_button->Hide();
if (right_arrow_button)
right_arrow_button->Hide();
}
}
void ContainerViewGump::set_container_obj(Obj *o) {
container_obj = o;
container_widget->set_container(container_obj);
if (doll_button)
doll_button->Hide();
if (left_arrow_button)
left_arrow_button->Hide();
if (right_arrow_button)
right_arrow_button->Hide();
}
void ContainerViewGump::Display(bool full_redraw) {
//display_level_text();
//display_spell_list_text();
Common::Rect dst;
dst = area;
SDL_BlitSurface(bg_image, nullptr, surface, &dst);
DisplayChildren(full_redraw);
if (actor) {
font->drawString(screen, actor->get_name(), area.left + 18, area.top + 2, 15, 15);
display_inventory_weight();
}
update_display = false;
screen->update(area.left, area.top, area.width(), area.height());
return;
}
void ContainerViewGump::display_inventory_weight() {
uint8 strength = actor->get_strength();
unsigned int equip_weight = Game::get_game()->get_view_manager()->get_display_weight(actor->get_inventory_weight());
char string[11]; //I:nnn/nnns\0
snprintf(string, 10, "I:%u/%us", equip_weight, strength * 2);
font->drawString(screen, string, area.left + (container_obj ? 18 : 18 + 34), area.top + bg_image->h + 2, 15, 15);
}
void ContainerViewGump::left_arrow() {
sint8 party_mem_num = party->get_member_num(actor);
if (party_mem_num >= 0) {
if (party_mem_num > 0)
party_mem_num--;
else
party_mem_num = party->get_party_size() - 1;
set_actor(party->get_actor(party_mem_num));
force_full_redraw_if_needed();
}
}
void ContainerViewGump::right_arrow() {
set_actor(party->get_actor((party->get_member_num(actor) + 1) % party->get_party_size()));
force_full_redraw_if_needed();
}
GUI_status ContainerViewGump::callback(uint16 msg, GUI_CallBack *caller, void *data) {
//close gump and return control to Magic class for clean up.
if (caller == gump_button) {
Game::get_game()->get_view_manager()->close_gump(this);
return GUI_YUM;
} else if (caller == down_arrow_button) {
container_widget->down_arrow();
return GUI_YUM;
} else if (caller == up_arrow_button) {
container_widget->up_arrow();
return GUI_YUM;
} else if (doll_button && caller == doll_button) {
Game::get_game()->get_view_manager()->open_doll_view(actor);
return GUI_YUM;
} else if (left_arrow_button && caller == left_arrow_button) {
left_arrow();
return GUI_YUM;
} else if (right_arrow_button && caller == right_arrow_button) {
right_arrow();
return GUI_YUM;
}
return GUI_PASS;
}
GUI_status ContainerViewGump::KeyDown(const Common::KeyState &key) {
if (left_arrow_button && left_arrow_button->Status() == WIDGET_VISIBLE) { // okay to change member number
KeyBinder *keybinder = Game::get_game()->get_keybinder();
ActionType a = keybinder->get_ActionType(key);
switch (keybinder->GetActionKeyType(a)) {
case NEXT_PARTY_MEMBER_KEY:
right_arrow();
return GUI_YUM;
case PREVIOUS_PARTY_MEMBER_KEY:
left_arrow();
return GUI_YUM;
case HOME_KEY:
set_actor(party->get_actor(0));
force_full_redraw_if_needed();
return GUI_YUM;
case END_KEY:
set_actor(party->get_actor(party->get_party_size() - 1));
force_full_redraw_if_needed();
return GUI_YUM;
default:
break;
}
}
/* moved into container widget
switch(key.keycode)
{
case Common::KEYCODE_RETURN:
case Common::KEYCODE_KP_ENTER:
return GUI_YUM;
default:
break;
}
*/
return container_widget->KeyDown(key);
}
GUI_status ContainerViewGump::MouseWheel(sint32 x, sint32 y) {
int xpos, ypos;
screen->get_mouse_location(&xpos, &ypos);
ypos -= area.top;
if (ypos >= container_widget_y_offset && ypos < container_widget_y_offset + container_widget->H()) {
if (y > 0) {
container_widget->up_arrow();
} else if (y < 0) {
container_widget->down_arrow();
}
} else {
if (is_actor_container() && party->get_member_num(actor) >= 0) {
if (y > 0) {
left_arrow();
} else if (y < 0) {
right_arrow();
}
}
}
return GUI_YUM;
}
GUI_status ContainerViewGump::MouseDown(int x, int y, Events::MouseButton button) {
return DraggableView::MouseDown(x, y, button);
}
GUI_status ContainerViewGump::MouseUp(int x, int y, Events::MouseButton button) {
return DraggableView::MouseUp(x, y, button);
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,110 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_CONTAINER_VIEW_GUMP_H
#define NUVIE_VIEWS_CONTAINER_VIEW_GUMP_H
#include "ultima/nuvie/views/draggable_view.h"
namespace Ultima {
namespace Nuvie {
class Configuration;
class TileManager;
class ObjManager;
class Screen;
class Actor;
class Font;
class U6Bmp;
class Font;
class ContainerWidgetGump;
class ContainerViewGump : public DraggableView {
GUI_Button *gump_button;
GUI_Button *up_arrow_button;
GUI_Button *down_arrow_button;
GUI_Button *left_arrow_button;
GUI_Button *right_arrow_button;
GUI_Button *doll_button;
ContainerWidgetGump *container_widget;
uint16 container_widget_y_offset;
Font *font;
Actor *actor;
Obj *container_obj;
public:
ContainerViewGump(const Configuration *cfg);
~ContainerViewGump() override;
bool init(Screen *tmp_screen, void *view_manager, uint16 x, uint16 y, Font *f, Party *p, TileManager *tm, ObjManager *om, Obj *container_obj_type);
void Display(bool full_redraw) override;
void set_actor(Actor *a);
const Actor *get_actor() const {
return actor;
}
void set_container_obj(Obj *o);
const Obj *get_container_obj() const {
return container_obj;
}
bool is_actor_container() const {
return container_obj == nullptr;
}
GUI_status KeyDown(const Common::KeyState &key) override;
GUI_status MouseDown(int x, int y, Events::MouseButton button) override;
GUI_status MouseUp(int x, int y, Events::MouseButton button) override;
GUI_status MouseMotion(int x, int y, uint8 state) override {
return DraggableView::MouseMotion(x, y, state);
}
GUI_status MouseWheel(sint32 x, sint32 y) override;
void MoveRelative(int dx, int dy) override {
return DraggableView::MoveRelative(dx, dy);
}
GUI_status callback(uint16 msg, GUI_CallBack *caller, void *data) override;
protected:
void init_container_type(const Common::Path &datadir, Obj *obj_type);
void init_backpack(const Common::Path &datadir, bool extend_area_w);
void init_chest(const Common::Path &datadir);
void init_crate(const Common::Path &datadir);
void init_barrel(const Common::Path &datadir);
void init_corpse(const Common::Path &datadir, Std::string bg_filename);
void display_inventory_weight();
void left_arrow();
void right_arrow();
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,549 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/misc/u6_llist.h"
#include "ultima/nuvie/conf/configuration.h"
#include "ultima/nuvie/gui/gui.h"
#include "ultima/nuvie/screen/game_palette.h"
#include "ultima/nuvie/views/container_widget.h"
#include "ultima/nuvie/actors/actor.h"
#include "ultima/nuvie/core/game_clock.h"
#include "ultima/nuvie/core/events.h"
#include "ultima/nuvie/gui/widgets/msg_scroll.h"
#include "ultima/nuvie/core/timed_event.h"
#include "ultima/nuvie/usecode/usecode.h"
#include "ultima/nuvie/gui/widgets/map_window.h"
#include "ultima/nuvie/core/player.h"
#include "ultima/nuvie/actors/actor_manager.h"
#include "ultima/nuvie/script/script.h"
#include "ultima/nuvie/views/inventory_font.h"
#include "ultima/nuvie/views/view_manager.h"
namespace Ultima {
namespace Nuvie {
ContainerWidget::ContainerWidget(const Configuration *cfg, GUI_CallBack *callback)
: GUI_Widget(nullptr, 0, 0, 0, 0), config(cfg), callback_object(callback),
container_obj(nullptr), tile_manager(nullptr), obj_manager(nullptr),
selected_obj(nullptr), target_cont(nullptr), actor(nullptr),
target_obj(nullptr), fill_bg(false), empty_tile(nullptr), row_offset(0),
rows(0), cols(0), bg_color(0), obj_font_color(0) {
ready_obj = nullptr; // FIXME: this is unused but I might need it again -- SB-X
config->value("config/GameType", game_type);
}
ContainerWidget::~ContainerWidget() {
}
bool ContainerWidget::init(Actor *a, uint16 x, uint16 y, TileManager *tm, ObjManager *om, Font *f) {
tile_manager = tm;
obj_manager = om;
rows = CONTAINER_WIDGET_ROWS;
cols = CONTAINER_WIDGET_COLS;
bg_color = Game::get_game()->get_palette()->get_bg_color();
if (Game::get_game()->get_game_type() == NUVIE_GAME_U6)
obj_font_color = 0x48;
else
obj_font_color = 0;
fill_bg = true;
if (Game::get_game()->get_game_type() == NUVIE_GAME_U6)
empty_tile = tile_manager->get_tile(410);
else if (Game::get_game()->get_game_type() == NUVIE_GAME_MD) // FIXME: different depending on npc
empty_tile = tile_manager->get_tile(273);
else
empty_tile = tile_manager->get_tile(392);
GUI_Widget::Init(nullptr, x, y, cols * 16 + 8, (rows + 1) * 16);
set_actor(a);
set_accept_mouseclick(true, USE_BUTTON); // accept [double]clicks from button1 (even if double-click disabled we need clicks)
return true;
}
void ContainerWidget::set_actor(Actor *a) {
actor = a;
container_obj = nullptr;
row_offset = 0;
Redraw();
}
void ContainerWidget::Display(bool full_redraw) {
if (fill_bg) {
//clear the screen first inventory icons, 4 x 3 tiles
screen->fill(bg_color, area.left, area.top, area.width(), area.height());
}
display_inventory_list();
screen->update(area.left, area.top, area.width(), area.height());
}
void ContainerWidget::display_inventory_list() {
const Tile *tile;
U6LList *objlist;
U6Link *link;
Obj *obj = nullptr;
uint16 i, j;
uint16 skip_num;
if (container_obj)
objlist = container_obj->container;
else
objlist = actor->get_inventory_list();
if (objlist == nullptr)
link = nullptr;
else
link = objlist->start();
//skip row_offset rows of objects.
skip_num = row_offset * cols;
for (i = 0; link != nullptr && i < skip_num; link = link->next) {
obj = (Obj *)link->data;
if (obj->is_readied() == false)
i++;
}
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
if (link != nullptr) {
obj = (Obj *)link->data;
if (obj->is_readied()) { //skip any readied objects
for (; link != nullptr && obj->is_readied(); link = link->next)
obj = (Obj *)link->data;
} else
link = link->next;
tile = tile_manager->get_tile(obj_manager->get_obj_tile_num(obj) + obj->frame_n);
if (link == nullptr) {
if (obj->is_readied()) //last object is readied so skip it.
tile = empty_tile;
}
} else
tile = empty_tile;
//tile = tile_manager->get_tile(actor->indentory_tile());
screen->blit(area.left + j * 16, area.top + i * 16, (const unsigned char *)empty_tile->data, 8, 16, 16, 16, true);
if (tile != empty_tile) {
//draw qty string for stackable items
if (obj_manager->is_stackable(obj))
display_qty_string(area.left + j * 16, area.top + i * 16, obj->qty);
//draw special char for Keys.
if (game_type == NUVIE_GAME_U6 && obj->obj_n == 64)
display_special_char(area.left + j * 16, area.top + i * 16, obj->quality);
}
screen->blit(area.left + j * 16, area.top + i * 16, (const unsigned char *)tile->data, 8, 16, 16, 16, true);
}
}
}
void ContainerWidget::display_qty_string(uint16 x, uint16 y, uint16 qty) {
uint8 len, i, offset;
char buf[6];
Common::sprintf_s(buf, "%d", qty);
len = strlen(buf);
offset = (16 - len * 4) / 2;
for (i = 0; i < len; i++)
screen->blitbitmap(x + offset + 4 * i, y + 11, inventory_font[buf[i] - 48], 3, 5, obj_font_color, bg_color);
return;
}
void ContainerWidget::display_special_char(uint16 x, uint16 y, uint8 quality) {
if (quality + 9 >= NUVIE_MICRO_FONT_COUNT)
return;
screen->blitbitmap(x + 6, y + 11, inventory_font[quality + 9], 3, 5, obj_font_color, bg_color);
}
GUI_status ContainerWidget::MouseDown(int x, int y, Events::MouseButton button) {
//Events *event = Game::get_game()->get_event();
//MsgScroll *scroll = Game::get_game()->get_scroll();
x -= area.left;
y -= area.top;
// ABOEING
if (/*actor && */(button == USE_BUTTON || button == ACTION_BUTTON || button == DRAG_BUTTON)) {
Obj *obj; // FIXME: duplicating code in DollWidget
if ((obj = get_obj_at_location(x, y)) != nullptr) {
// send to View
if (callback_object->callback(INVSELECT_CB, this, obj) == GUI_PASS
&& button == DRAG_BUTTON)
selected_obj = obj; // start dragging
return GUI_YUM;
}
}
return GUI_PASS;
}
inline uint16 ContainerWidget::get_list_position(int x, int y) {
uint16 list_pos;
list_pos = (y / 16) * cols + x / 16;
list_pos += row_offset * cols;
return list_pos;
}
Obj *ContainerWidget::get_obj_at_location(int x, int y) {
uint8 location;
U6LList *inventory;
U6Link *link;
Obj *obj = nullptr;
uint16 i;
location = get_list_position(x, y); //find the position of the object we hit in the inventory
if (container_obj)
inventory = container_obj->container;
else
inventory = actor->get_inventory_list();
if (inventory == nullptr)
link = nullptr;
else
link = inventory->start();
for (i = 0; link != nullptr && i <= location; link = link->next) {
obj = (Obj *)link->data;
if (obj->is_readied() == false)
i++;
}
if (i > location && obj && obj->is_readied() == false) // don't return readied or non existent objects
return obj;
return nullptr;
}
// change container, ready/unready object, activate arrows
GUI_status ContainerWidget::MouseUp(int /*x*/, int /*y*/, Events::MouseButton button) {
if (button == USE_BUTTON) {
//x -= area.left;
//y -= area.top;
if (selected_obj) {
// only act now if objects can't be used with DoubleClick
if (!Game::get_game()->get_map_window()->is_doubleclick_enabled())
try_click();
else {
wait_for_mouseclick(USE_BUTTON);
ready_obj = selected_obj;
}
selected_obj = nullptr;
return GUI_YUM;
}
}
return GUI_PASS;
}
bool ContainerWidget::up_arrow() {
if (row_offset > 0) {
row_offset--;
return true;
}
return false;
}
bool ContainerWidget::down_arrow() {
uint32 num_objects;
if (container_obj)
num_objects = container_obj->container_count_objects();
else
num_objects = actor->inventory_count_objects(false);
if ((sint32)(num_objects - row_offset * cols) > (sint32)(rows * cols)) {
row_offset++;
return true;
}
return false;
}
GUI_status ContainerWidget::MouseMotion(int x, int y, uint8 state) {
Tile *tile;
if (selected_obj && !dragging) {
dragging = true;
tile = tile_manager->get_tile(obj_manager->get_obj_tile_num(selected_obj->obj_n) + selected_obj->frame_n);
bool out_of_range = false;
if (!selected_obj->is_in_inventory() && Game::get_game()->get_map_window()->is_interface_fullscreen_in_combat()) {
Obj *obj = selected_obj->is_in_container() ? selected_obj->get_container_obj(true) : selected_obj;
MapCoord obj_loc(obj->x, obj->y, obj->z);
Actor *player = Game::get_game()->get_player()->get_actor();
if (player->get_location().distance(obj_loc) > 1)
out_of_range = true;
}
return gui_drag_manager->start_drag(this, GUI_DRAG_OBJ, selected_obj, tile->data, 16, 16, 8, out_of_range);
}
return GUI_PASS;
}
void ContainerWidget::drag_drop_success(int x, int y, int message, void *data) {
DEBUG(0, LEVEL_DEBUGGING, "ContainerWidget::drag_drop_success()\n");
dragging = false;
// handled by drop target
// if(container_obj)
// container_obj->container->remove(selected_obj);
// else
// actor->inventory_remove_obj(selected_obj);
selected_obj = nullptr;
Redraw();
}
void ContainerWidget::drag_drop_failed(int x, int y, int message, void *data) {
DEBUG(0, LEVEL_DEBUGGING, "ContainerWidget::drag_drop_failed()\n");
dragging = false;
selected_obj = nullptr;
}
bool ContainerWidget::drag_set_target_obj(int x, int y) {
target_obj = get_obj_at_location(x, y);
target_cont = get_container();
return true;
}
bool ContainerWidget::drag_accept_drop(int x, int y, int message, void *data) {
DEBUG(0, LEVEL_DEBUGGING, "ContainerWidget::drag_accept_drop()\n");
if (message == GUI_DRAG_OBJ) {
Obj *obj = (Obj *)data;
x -= area.left;
y -= area.top;
if (target_obj == nullptr) { //we need to check this so we don't screw up target_obj on subsequent calls
if (drag_set_target_obj(x, y) == false) {
DEBUG(0, LEVEL_WARNING, "ContainerWidget: Didn't hit any widget object targets!\n");
return false;
}
}
Actor *container_owner = (container_obj ? container_obj->get_actor_holding_obj() : nullptr);
if (!container_owner)
container_owner = actor;
if (!obj->is_in_inventory()) {
if (container_owner) {
Game::get_game()->get_scroll()->display_string("Get-");
Game::get_game()->get_scroll()->display_string(obj_manager->look_obj(obj, OBJ_SHOW_PREFIX));
if (Game::get_game()->get_script()->call_actor_get_obj(container_owner, obj) == false) {
Game::get_game()->get_scroll()->message("\n\n");
return false;
}
Game::get_game()->get_scroll()->message("\n\n");
}
} else if (container_owner && obj->get_actor_holding_obj() != container_owner) {
Events *event = Game::get_game()->get_event();
event->display_move_text(container_owner, obj);
if (!event->can_move_obj_between_actors(obj, obj->get_actor_holding_obj(), container_owner, false)) {
Game::get_game()->get_scroll()->message("\n\n");
return false;
}
Game::get_game()->get_scroll()->message("\n\n");
}
if (!obj_manager->can_get_obj(obj)) {
Game::get_game()->get_scroll()->message("Not possible.\n\n");
return false;
}
Actor *grabber = actor;
if (!grabber)
grabber = Game::get_game()->get_player()->get_actor();
if (container_obj && !container_obj->is_in_inventory()
&& !Game::get_game()->get_map_window()->can_get_obj(grabber, container_obj)) {
Game::get_game()->get_scroll()->message("\n\nblocked\n\n");
return false;
}
if (!obj->is_in_inventory() && !obj->is_readied()) {
if (!Game::get_game()->get_map_window()->can_get_obj(grabber, obj)) {
Game::get_game()->get_scroll()->message("\n\nblocked\n\n");
return false;
}
if (obj_manager->obj_is_damaging(obj, Game::get_game()->get_player()->get_actor())) {
Game::get_game()->get_player()->subtract_movement_points(3);
return false;
}
}
UseCode *usecode = Game::get_game()->get_usecode();
if (usecode->is_chest(obj) && obj->frame_n == 0) //open chest
obj->frame_n = 1; //close the chest
DEBUG(0, LEVEL_DEBUGGING, "Drop Accepted\n");
return true;
}
DEBUG(0, LEVEL_DEBUGGING, "Drop Refused\n");
return false;
}
void ContainerWidget::drag_perform_drop(int /*x*/, int /*y*/, int message, void *data) {
DEBUG(0, LEVEL_DEBUGGING, "ContainerWidget::drag_perform_drop()\n");
Obj *obj;
//x -= area.left;
//y -= area.top;
if (message == GUI_DRAG_OBJ) {
DEBUG(0, LEVEL_DEBUGGING, "Drop into inventory.\n");
obj = (Obj *)data;
bool moving_between_actors = obj->get_actor_holding_obj() != actor;
if (moving_between_actors)
Game::get_game()->get_player()->subtract_movement_points(3);
if (target_cont && obj_manager->can_store_obj(target_cont, obj)) {
obj_manager->moveto_container(obj, target_cont);
} else if (target_obj && obj_manager->can_store_obj(target_obj, obj)) {
obj_manager->moveto_container(obj, target_obj);
} else {
if (obj->is_readied()) {
Game::get_game()->get_event()->unready(obj);
if (moving_between_actors)
obj_manager->moveto_inventory(obj, actor);
} else
obj_manager->moveto_inventory(obj, actor);
}
Redraw();
}
Game::get_game()->get_map_window()->updateBlacking();
target_obj = nullptr;
return;
}
void ContainerWidget::drag_draw(int x, int y, int message, void *data) {
Tile *tile;
if (!selected_obj)
return;
tile = tile_manager->get_tile(obj_manager->get_obj_tile_num(selected_obj) + selected_obj->frame_n);
int nx = x - 8;
int ny = y - 8;
if (nx + 16 >= screen->get_width())
nx = screen->get_width() - 17;
else if (nx < 0)
nx = 0;
if (ny + 16 >= screen->get_height())
ny = screen->get_height() - 17;
else if (ny < 0)
ny = 0;
screen->blit(nx, ny, tile->data, 8, 16, 16, 16, true);
screen->update(nx, ny, 16, 16);
}
void ContainerWidget::try_click() {
Events *event = Game::get_game()->get_event();
UseCode *usecode = Game::get_game()->get_usecode();
Actor *owner = nullptr;
if (!selected_obj)
selected_obj = ready_obj;
if (selected_obj)
owner = Game::get_game()->get_actor_manager()->get_actor(selected_obj->x);
if (!owner || !owner->is_in_party())
owner = Game::get_game()->get_player()->get_actor();
switch (event->get_mode()) {
case MOVE_MODE:
case EQUIP_MODE: {
if (!selected_obj)
return;
bool locked_chest = (usecode->is_chest(selected_obj) && selected_obj->frame_n > 1);
if (usecode->is_container(selected_obj) && !locked_chest) {
row_offset = 0;
container_obj = selected_obj;
if (usecode->is_chest(container_obj)) {
usecode->process_effects(container_obj, owner);
Redraw();
}
} else {
event->ready(selected_obj, owner);
Redraw();
}
break;
}
case GET_MODE:
event->perform_get(selected_obj, nullptr, Game::get_game()->get_player()->get_actor());
break;
case ATTACK_MODE:
event->close_gumps();
break;
default:
event->select_view_obj(selected_obj, owner);
break;
}
ready_obj = nullptr;
selected_obj = nullptr;
}
/* Use object. */
GUI_status ContainerWidget::MouseDouble(int x, int y, Events::MouseButton button) {
// we have to check if double-clicks are allowed here, since we use single-clicks
if (!Game::get_game()->get_map_window()->is_doubleclick_enabled())
return GUI_PASS;
Obj *obj = selected_obj;
ready_obj = nullptr;
selected_obj = nullptr;
// if(!actor)
// return(GUI_YUM);
if (!obj)
return MouseUp(x, y, button); // probably hit an arrow
Game::get_game()->get_view_manager()->double_click_obj(obj);
return GUI_PASS;
}
GUI_status ContainerWidget::MouseClick(int x, int y, Events::MouseButton button) {
return MouseUp(x, y, button);
}
// change container, ready/unready object, activate arrows
GUI_status ContainerWidget::MouseDelayed(int x, int y, Events::MouseButton button) {
if (ready_obj)
try_click();
return GUI_PASS;
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,124 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_CONTAINER_WIDGET_H
#define NUVIE_VIEWS_CONTAINER_WIDGET_H
#include "ultima/nuvie/gui/widgets/gui_widget.h"
#include "ultima/nuvie/core/obj_manager.h"
#include "ultima/nuvie/views/inventory_message.h"
namespace Ultima {
namespace Nuvie {
static const int CONTAINER_WIDGET_ROWS = 3;
static const int CONTAINER_WIDGET_COLS = 4;
class Configuration;
class TileManager;
class Actor;
class Font;
class ContainerWidget : public GUI_Widget {
protected:
const Configuration *config;
int game_type;
TileManager *tile_manager;
ObjManager *obj_manager;
Actor *actor;
Obj *container_obj;
Obj *selected_obj, *target_obj, *ready_obj;
Obj *target_cont;
uint16 rows, cols;
uint16 row_offset;
uint8 bg_color;
uint8 obj_font_color;
bool fill_bg;
const Tile *empty_tile;
public:
ContainerWidget(const Configuration *cfg, GUI_CallBack *callback = nullptr);
~ContainerWidget() override;
bool init(Actor *a, uint16 x, uint16 y, TileManager *tm, ObjManager *om, Font *f);
virtual void set_actor(Actor *a);
const Actor *get_actor() const {
return actor;
}
Obj *get_container() {
return container_obj;
}
void set_container(Obj *obj) {
container_obj = obj;
row_offset = 0;
Redraw();
}
bool is_showing_container() const {
return (container_obj != nullptr ? true : false);
}
void Display(bool full_redraw) override;
GUI_status MouseDown(int x, int y, Events::MouseButton button) override;
GUI_status MouseUp(int x, int y, Events::MouseButton button) override;
GUI_status MouseMotion(int x, int y, uint8 state) override;
GUI_status MouseDouble(int x, int y, Events::MouseButton button) override;
GUI_status MouseClick(int x, int y, Events::MouseButton button) override;
GUI_status MouseDelayed(int x, int y, Events::MouseButton button) override;
void drag_drop_success(int x, int y, int message, void *data) override;
void drag_drop_failed(int x, int y, int message, void *data) override;
bool drag_accept_drop(int x, int y, int message, void *data) override;
void drag_perform_drop(int x, int y, int message, void *data) override;
void drag_draw(int x, int y, int message, void *data) override;
protected:
GUI_CallBack *callback_object; // object-selected callback
inline uint16 get_list_position(int x, int y);
void display_inventory_list();
inline void display_qty_string(uint16 x, uint16 y, uint16 qty);
inline void display_special_char(uint16 x, uint16 y, uint8 quality);
void display_arrows();
bool drag_set_target_obj(int x, int y);
void try_click();
public:
bool up_arrow();
bool down_arrow();
Obj *get_obj_at_location(int x, int y);
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,193 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/conf/configuration.h"
#include "ultima/nuvie/gui/gui.h"
#include "ultima/nuvie/views/container_widget_gump.h"
#include "ultima/nuvie/keybinding/keys.h"
#include "ultima/nuvie/views/view_manager.h"
namespace Ultima {
namespace Nuvie {
static const Tile gump_empty_tile = {
0,
false,
false,
false,
false,
false,
true,
false,
false,
0,
//uint8 qty;
//uint8 flags;
0,
0,
0,
{
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 143, 142, 141, 141, 142, 143, 255, 255, 255, 255, 255,
255, 255, 255, 255, 143, 141, 141, 142, 142, 141, 141, 143, 255, 255, 255, 255,
255, 255, 255, 143, 141, 142, 143, 143, 143, 143, 142, 141, 143, 255, 255, 255,
255, 255, 143, 141, 142, 143, 0, 0, 0, 0, 143, 142, 141, 143, 255, 255,
255, 255, 142, 141, 143, 0, 0, 0, 0, 0, 0, 143, 141, 142, 255, 255,
255, 255, 141, 142, 143, 0, 0, 0, 0, 0, 0, 143, 142, 141, 255, 255,
255, 255, 141, 142, 143, 0, 0, 0, 0, 0, 0, 143, 142, 141, 255, 255,
255, 255, 142, 141, 143, 0, 0, 0, 0, 0, 0, 143, 141, 142, 255, 255,
255, 255, 143, 141, 142, 143, 0, 0, 0, 0, 143, 142, 141, 143, 255, 255,
255, 255, 255, 143, 141, 142, 143, 143, 143, 143, 142, 141, 143, 255, 255, 255,
255, 255, 255, 255, 143, 141, 141, 142, 142, 141, 141, 143, 255, 255, 255, 255,
255, 255, 255, 255, 255, 143, 142, 141, 141, 142, 143, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
}
};
ContainerWidgetGump::ContainerWidgetGump(const Configuration *cfg, GUI_CallBack *callback)
: ContainerWidget(cfg, callback), cursor_tile(nullptr), check_x(0), check_y(0),
cursor_x(0), cursor_y(0), show_cursor(true) {
empty_tile = &gump_empty_tile;
obj_font_color = 15;
bg_color = 0;
fill_bg = false;
}
ContainerWidgetGump::~ContainerWidgetGump() {
}
bool ContainerWidgetGump::init(Actor *a, uint16 x, uint16 y, uint8 Cols, uint8 Rows, TileManager *tm, ObjManager *om, Font *f, uint8 check_xoff, uint8 check_yoff) {
tile_manager = tm;
obj_manager = om;
rows = Rows;
cols = Cols;
check_x = - x + check_xoff;
check_y = - y + check_yoff;
//objlist_offset_x = 0;
//objlist_offset_y = 0;
//72 = 4 * 16 + 8
GUI_Widget::Init(nullptr, x, y, cols * 16, rows * 16);
set_actor(a);
set_accept_mouseclick(true, 0);//USE_BUTTON); // accept [double]clicks from button1 (even if double-click disabled we need clicks)
cursor_tile = tile_manager->get_gump_cursor_tile();
return true;
}
void ContainerWidgetGump::Display(bool full_redraw) {
display_inventory_list();
if (show_cursor) {
screen->blit(area.left + (cursor_x < 0 ? check_x : cursor_x * 16), area.top + (cursor_x < 0 ? check_y : cursor_y * 16),
(const unsigned char *)cursor_tile->data, 8, 16, 16, 16, true);
}
screen->update(area.left, area.top, area.width(), area.height());
}
void ContainerWidgetGump::cursor_right() {
if (cursor_x < cols - 1) {
if (get_obj_at_location((cursor_x + 1) * 16, cursor_y * 16) != nullptr) {
cursor_x++;
}
}
}
void ContainerWidgetGump::cursor_left() {
if (cursor_x > -1) {
cursor_x--;
}
}
void ContainerWidgetGump::cursor_up() {
if (cursor_y > 0) {
cursor_y--;
} else {
up_arrow();
}
}
void ContainerWidgetGump::cursor_down() {
if (get_obj_at_location(0, (cursor_y + 1) * 16) != nullptr) { //check that we can move down one row.
if (cursor_y < rows - 1) {
cursor_y++;
} else {
down_arrow();
}
for (; cursor_x > 0; cursor_x--) {
if (get_obj_at_location(cursor_x * 16, cursor_y * 16) != nullptr) {
break;
}
}
}
}
GUI_status ContainerWidgetGump::KeyDown(const Common::KeyState &key) {
KeyBinder *keybinder = Game::get_game()->get_keybinder();
ActionType a = keybinder->get_ActionType(key);
switch (keybinder->GetActionKeyType(a)) {
case NORTH_KEY:
cursor_up();
break;
case SOUTH_KEY:
cursor_down();
break;
case WEST_KEY:
cursor_left();
break;
case EAST_KEY:
cursor_right();
break;
case DO_ACTION_KEY:
if (cursor_x == -1) {
Game::get_game()->get_view_manager()->close_gump((DraggableView *)parent);
break;
}
selected_obj = get_obj_at_location(cursor_x * 16, cursor_y * 16);
if (selected_obj) {
try_click();
}
break;
default:
return GUI_PASS;
}
return GUI_YUM;
}
void ContainerWidgetGump::set_actor(Actor *a) {
cursor_x = cursor_y = 0;
ContainerWidget::set_actor(a);
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,67 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_CONTAINER_WIDGET_GUMP_H
#define NUVIE_VIEWS_CONTAINER_WIDGET_GUMP_H
#include "ultima/nuvie/gui/widgets/gui_widget.h"
#include "ultima/nuvie/core/obj_manager.h"
#include "ultima/nuvie/views/container_widget.h"
namespace Ultima {
namespace Nuvie {
class Configuration;
class TileManager;
class Actor;
class Font;
class ContainerWidgetGump : public ContainerWidget {
private:
sint16 cursor_x;
uint16 cursor_y;
sint16 check_x, check_y;
const Tile *cursor_tile;
bool show_cursor;
public:
ContainerWidgetGump(const Configuration *cfg, GUI_CallBack *callback = nullptr);
~ContainerWidgetGump() override;
bool init(Actor *a, uint16 x, uint16 y, uint8 Cols, uint8 Rows, TileManager *tm, ObjManager *om, Font *f, uint8 check_xoff, uint8 check_yoff);
void Display(bool full_redraw) override;
GUI_status KeyDown(const Common::KeyState &key) override;
void set_actor(Actor *a) override;
private:
void cursor_right();
void cursor_left();
void cursor_up();
void cursor_down();
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,684 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/misc/u6_misc.h"
#include "ultima/nuvie/core/events.h"
#include "ultima/nuvie/gui/gui.h"
#include "ultima/nuvie/gui/gui_button.h"
#include "ultima/nuvie/core/party.h"
#include "ultima/nuvie/actors/actor.h"
#include "ultima/nuvie/views/view_manager.h"
#include "ultima/nuvie/views/container_view_gump.h"
#include "ultima/nuvie/views/doll_widget.h"
#include "ultima/nuvie/views/doll_view_gump.h"
#include "ultima/nuvie/keybinding/keys.h"
namespace Ultima {
namespace Nuvie {
DollViewGump::DollViewGump(const Configuration *cfg)
: DraggableView(cfg), gump_button(nullptr), combat_button(nullptr),
heart_button(nullptr), party_button(nullptr), inventory_button(nullptr),
doll_widget(nullptr), actor_doll(nullptr), font(nullptr), actor(nullptr),
cursor_tile(nullptr), is_avatar(false), show_cursor(true),
cursor_pos(CURSOR_HEAD), cursor_xoff(50), cursor_yoff(16) {
}
DollViewGump::~DollViewGump() {
if (font)
delete font;
if (actor_doll)
delete actor_doll;
}
bool DollViewGump::init(Screen *tmp_screen, void *view_manager, uint16 x, uint16 y, Actor *a, Font *f, Party *p, TileManager *tm, ObjManager *om) {
View::init(x, y, f, p, tm, om);
SetRect(area.left, area.top, 108, 136);
actor = a;
is_avatar = actor->is_avatar();
cursor_tile = tile_manager->get_gump_cursor_tile();
doll_widget = new DollWidget(config, this);
doll_widget->init(actor, 26, 16, tile_manager, obj_manager);
AddWidget(doll_widget);
Common::Path datadir = GUI::get_gui()->get_data_dir();
Common::Path imagefile;
Common::Path path;
Graphics::ManagedSurface *image, *image1;
build_path(datadir, "images", path);
datadir = path;
build_path(datadir, "gumps", path);
datadir = path;
gump_button = loadButton(datadir, "gump", 0, 112);
build_path(datadir, "left_arrow.bmp", imagefile);
image = SDL_LoadBMP(imagefile);
image1 = SDL_LoadBMP(imagefile);
left_button = new GUI_Button(this, 23, 7, image, image1, this);
this->AddWidget(left_button);
build_path(datadir, "right_arrow.bmp", imagefile);
image = SDL_LoadBMP(imagefile);
image1 = SDL_LoadBMP(imagefile);
right_button = new GUI_Button(this, 86, 7, image, image1, this);
this->AddWidget(right_button);
build_path(datadir, "doll", path);
datadir = path;
build_path(datadir, "doll_bg.bmp", imagefile);
bg_image = SDL_LoadBMP(imagefile);
set_bg_color_key(0, 0x70, 0xfc);
build_path(datadir, "combat_btn_up.bmp", imagefile);
image = SDL_LoadBMP(imagefile);
build_path(datadir, "combat_btn_down.bmp", imagefile);
image1 = SDL_LoadBMP(imagefile);
combat_button = new GUI_Button(nullptr, 23, 92, image, image1, this);
this->AddWidget(combat_button);
heart_button = loadButton(datadir, "heart", 23, 108);
party_button = loadButton(datadir, "party", 47, 108);
inventory_button = loadButton(datadir, "inventory", 71, 108);
font = new GUI_Font(GUI_FONT_GUMP);
font->setColoring(0x08, 0x08, 0x08, 0x80, 0x58, 0x30, 0x00, 0x00, 0x00);
if (party->get_member_num(actor) < 0) {
if (Game::get_game()->get_event()->using_control_cheat() == false)
heart_button->Hide();
left_button->Hide();
right_button->Hide();
}
party_button->Hide();
is_avatar = actor->is_avatar();
ViewManager *vm = Game::get_game()->get_view_manager();
if (is_avatar)
actor_doll = vm->loadAvatarDollImage(actor_doll);
else
actor_doll = vm->loadCustomActorDollImage(actor_doll, actor->get_actor_num());
setColorKey(actor_doll);
return true;
}
void DollViewGump::setColorKey(Graphics::ManagedSurface *image) {
if (image) {
bg_color_key = image->format.RGBToColor(0xf1, 0x0f, 0xc4);
image->setTransparentColor(bg_color_key);
}
}
static const char combat_mode_tbl[][8] = {"COMMAND", "FRONT", "REAR", "FLANK", "BERSERK", "RETREAT", "ASSAULT"};
static const char combat_mode_tbl_se[][8] = {"COMMAND", "RANGED", "FLEE", "CLOSE"};
static const char combat_mode_tbl_md[][8] = {"COMMAND", "RANGED", "FLEE", "ATTACK"};
void DollViewGump::set_actor(Actor *a) {
actor = a;
if (actor) {
is_avatar = actor->is_avatar();
ViewManager *vm = Game::get_game()->get_view_manager();
if (is_avatar)
actor_doll = vm->loadAvatarDollImage(actor_doll);
else
actor_doll = vm->loadCustomActorDollImage(actor_doll, actor->get_actor_num());
setColorKey(actor_doll);
}
if (doll_widget)
doll_widget->set_actor(actor);
}
GUI_status DollViewGump::set_cursor_pos(gumpCursorPos pos) {
cursor_pos = pos;
switch (cursor_pos) {
case CURSOR_LEFT:
cursor_xoff = 18;
cursor_yoff = 2;
return GUI_YUM;
case CURSOR_RIGHT:
cursor_xoff = 82;
cursor_yoff = 2;
return GUI_YUM;
case CURSOR_HEAD:
cursor_xoff = 50;
cursor_yoff = 16;
return GUI_YUM;
case CURSOR_NECK:
cursor_xoff = 26;
cursor_yoff = 24;
return GUI_YUM;
case CURSOR_RIGHT_HAND:
cursor_xoff = 26;
cursor_yoff = 40;
return GUI_YUM;
case CURSOR_CHEST:
cursor_xoff = 74;
cursor_yoff = 24;
return GUI_YUM;
case CURSOR_LEFT_HAND:
cursor_xoff = 74;
cursor_yoff = 40;
return GUI_YUM;
case CURSOR_RIGHT_RING:
cursor_xoff = 26;
cursor_yoff = 57;
return GUI_YUM;
case CURSOR_LEFT_RING:
cursor_xoff = 74;
cursor_yoff = 57;
return GUI_YUM;
case CURSOR_FEET:
cursor_xoff = 50;
cursor_yoff = 63;
return GUI_YUM;
case CURSOR_CHECK:
cursor_xoff = 1;
cursor_yoff = 111;
return GUI_YUM;
case CURSOR_COMBAT:
cursor_xoff = 23;
cursor_yoff = 92;
return GUI_YUM;
case CURSOR_HEART:
cursor_xoff = 26;
cursor_yoff = 109;
return GUI_YUM;
case CURSOR_PARTY:
cursor_xoff = 50;
cursor_yoff = 109;
return GUI_YUM;
case CURSOR_INVENTORY:
default :
cursor_xoff = 74;
cursor_yoff = 109;
return GUI_YUM;
}
}
void DollViewGump::Display(bool full_redraw) {
//display_level_text();
//display_spell_list_text();
Common::Rect dst;
dst = area;
dst.setWidth(108);
dst.setHeight(136);
SDL_BlitSurface(bg_image, nullptr, surface, &dst);
if (actor_doll) {
dst.translate(45, 32);
SDL_BlitSurface(actor_doll, nullptr, surface, &dst);
}
uint8 w = font->getCenter(actor->get_name(), 58);
font->textOut(screen->get_sdl_surface(), area.left + 29 + w, area.top + 7, actor->get_name());
displayEquipWeight();
DisplayChildren(full_redraw);
displayCombatMode();
if (show_cursor)
screen->blit(area.left + cursor_xoff, area.top + cursor_yoff,
(const unsigned char *)cursor_tile->data, 8, 16, 16, 16, true);
update_display = false;
screen->update(area.left, area.top, area.width(), area.height());
return;
}
void DollViewGump::displayEquipWeight() {
uint8 strength = actor->get_strength();
unsigned int equip_weight = Game::get_game()->get_view_manager()->get_display_weight(actor->get_inventory_equip_weight());
char string[4]; //nnn\0
snprintf(string, 4, "%u", equip_weight);
font->textOut(screen->get_sdl_surface(), area.left + ((equip_weight > 9) ? 59 : 64), area.top + 82, string);
snprintf(string, 4, "%u", strength);
font->textOut(screen->get_sdl_surface(), area.left + ((strength > 9) ? 76 : 81), area.top + 82, string);
}
void DollViewGump::displayCombatMode() {
if (!actor->is_in_party() || party->get_member_num(actor) == 0)
return;
uint8 index = get_combat_mode_index(actor);
const char *text;
if (Game::get_game()->get_game_type() == NUVIE_GAME_U6)
text = combat_mode_tbl[index];
else if (Game::get_game()->get_game_type() == NUVIE_GAME_MD)
text = combat_mode_tbl_md[index];
else // SE
text = combat_mode_tbl_se[index];
uint8 c = font->getCenter(text, 55);
font->textOut(screen->get_sdl_surface(), area.left + 36 + c, area.top + 97, text);
}
void DollViewGump::left_arrow() {
if (party->get_member_num(actor) < 0)
return;
uint8 party_mem_num = party->get_member_num(actor);
if (party_mem_num > 0)
party_mem_num--;
else
party_mem_num = party->get_party_size() - 1;
set_actor(party->get_actor(party_mem_num));
}
void DollViewGump::right_arrow() {
if (party->get_member_num(actor) < 0)
return;
set_actor(party->get_actor((party->get_member_num(actor) + 1) % party->get_party_size()));
}
GUI_status DollViewGump::callback(uint16 msg, GUI_CallBack *caller, void *data) {
Events *event = Game::get_game()->get_event();
//close gump and return control to Magic class for clean up.
if (event->get_mode() == ATTACK_MODE || caller == gump_button) {
Game::get_game()->get_view_manager()->close_gump(this);
return GUI_YUM;
} else if (caller == right_button) {
right_arrow();
} else if (caller == left_button) {
left_arrow();
} else if (caller == inventory_button) {
Game::get_game()->get_view_manager()->open_container_view(actor);
} else if (caller == heart_button) {
Game::get_game()->get_view_manager()->open_portrait_gump(actor);
} else if (caller == combat_button) {
activate_combat_button();
} else if (caller == party_button) { // FIXME: What is this supposed to do?
} else if (caller == doll_widget) {
if (event->get_mode() != MOVE_MODE && event->get_mode() != EQUIP_MODE) {
Obj *obj = (Obj *)data;
event->select_view_obj(obj, actor);
return GUI_YUM;
}
}
return GUI_PASS;
}
GUI_status DollViewGump::moveCursorRelative(NuvieDir direction) {
gumpCursorPos cursor_left = actor->is_in_party() ? CURSOR_LEFT : CURSOR_HEAD; // don't allow pickpocket or control cheat into arrow area
gumpCursorPos cursor_right = actor->is_in_party() ? CURSOR_RIGHT : CURSOR_HEAD;
gumpCursorPos cursor_party; // no party button yet so skip it
gumpCursorPos cursor_heart; // not available in pickpocket mode
if (!actor->is_in_party() && !Game::get_game()->get_event()->using_control_cheat()) {
if (direction == NUVIE_DIR_SW || direction == NUVIE_DIR_W)
cursor_heart = CURSOR_CHECK;
else
cursor_heart = CURSOR_INVENTORY;
} else
cursor_heart = CURSOR_HEART;
if (direction == NUVIE_DIR_W || direction == NUVIE_DIR_SW)
cursor_party = cursor_heart;
else
cursor_party = CURSOR_INVENTORY;
switch (cursor_pos) {
case CURSOR_LEFT:
switch (direction) {
case NUVIE_DIR_NE:
case NUVIE_DIR_E:
return set_cursor_pos(CURSOR_RIGHT);
case NUVIE_DIR_SW:
case NUVIE_DIR_S:
return set_cursor_pos(CURSOR_NECK);
case NUVIE_DIR_SE:
return set_cursor_pos(CURSOR_HEAD);
default:
return GUI_YUM;
}
case CURSOR_RIGHT:
switch (direction) {
case NUVIE_DIR_W:
case NUVIE_DIR_NW:
return set_cursor_pos(CURSOR_LEFT);
case NUVIE_DIR_S:
case NUVIE_DIR_SE:
return set_cursor_pos(CURSOR_CHEST);
case NUVIE_DIR_SW:
return set_cursor_pos(CURSOR_HEAD);
default:
return GUI_YUM;
}
case CURSOR_HEAD:
switch (direction) {
case NUVIE_DIR_N:
case NUVIE_DIR_NW:
return set_cursor_pos(cursor_left);
case NUVIE_DIR_NE:
return set_cursor_pos(cursor_right);
case NUVIE_DIR_W:
case NUVIE_DIR_SW:
return set_cursor_pos(CURSOR_NECK);
case NUVIE_DIR_E:
case NUVIE_DIR_SE:
return set_cursor_pos(CURSOR_CHEST);
case NUVIE_DIR_S:
return set_cursor_pos(CURSOR_FEET);
default:
return GUI_YUM;
}
case CURSOR_NECK:
switch (direction) {
case NUVIE_DIR_N:
case NUVIE_DIR_NW:
return set_cursor_pos(cursor_left);
case NUVIE_DIR_E:
case NUVIE_DIR_NE:
return set_cursor_pos(CURSOR_HEAD);
case NUVIE_DIR_S:
case NUVIE_DIR_SW:
return set_cursor_pos(CURSOR_RIGHT_HAND);
case NUVIE_DIR_SE:
return set_cursor_pos(CURSOR_LEFT_HAND);
default:
return GUI_YUM;
}
case CURSOR_CHEST:
switch (direction) {
case NUVIE_DIR_N:
case NUVIE_DIR_NE:
return set_cursor_pos(cursor_right);
case NUVIE_DIR_W:
case NUVIE_DIR_NW:
return set_cursor_pos(CURSOR_HEAD);
case NUVIE_DIR_SW:
return set_cursor_pos(CURSOR_RIGHT_HAND);
case NUVIE_DIR_S:
case NUVIE_DIR_SE:
return set_cursor_pos(CURSOR_LEFT_HAND);
default:
return GUI_YUM;
}
case CURSOR_RIGHT_HAND:
switch (direction) {
case NUVIE_DIR_N:
case NUVIE_DIR_NW:
return set_cursor_pos(CURSOR_NECK);
case NUVIE_DIR_NE:
return set_cursor_pos(CURSOR_CHEST);
case NUVIE_DIR_E:
return set_cursor_pos(CURSOR_LEFT_HAND);
case NUVIE_DIR_SE:
return set_cursor_pos(CURSOR_FEET);
case NUVIE_DIR_S:
case NUVIE_DIR_SW:
return set_cursor_pos(CURSOR_RIGHT_RING);
default:
return GUI_YUM;
}
case CURSOR_LEFT_HAND:
switch (direction) {
case NUVIE_DIR_N:
case NUVIE_DIR_NE:
return set_cursor_pos(CURSOR_CHEST);
case NUVIE_DIR_NW:
return set_cursor_pos(CURSOR_HEAD);
case NUVIE_DIR_W:
return set_cursor_pos(CURSOR_RIGHT_HAND);
case NUVIE_DIR_SW:
return set_cursor_pos(CURSOR_FEET);
case NUVIE_DIR_S:
case NUVIE_DIR_SE:
return set_cursor_pos(CURSOR_LEFT_RING);
default:
return GUI_YUM;
}
case CURSOR_RIGHT_RING:
switch (direction) {
case NUVIE_DIR_N:
case NUVIE_DIR_NW:
return set_cursor_pos(CURSOR_RIGHT_HAND);
case NUVIE_DIR_NE:
return set_cursor_pos(CURSOR_LEFT_HAND);
case NUVIE_DIR_S:
case NUVIE_DIR_SE:
return set_cursor_pos(CURSOR_FEET);
case NUVIE_DIR_SW:
return set_cursor_pos(CURSOR_COMBAT);
case NUVIE_DIR_E:
return set_cursor_pos(CURSOR_LEFT_RING);
default:
return GUI_YUM;
}
case CURSOR_LEFT_RING:
switch (direction) {
case NUVIE_DIR_N:
case NUVIE_DIR_NE:
return set_cursor_pos(CURSOR_LEFT_HAND);
case NUVIE_DIR_NW:
return set_cursor_pos(CURSOR_RIGHT_HAND);
case NUVIE_DIR_W:
return set_cursor_pos(CURSOR_RIGHT_RING);
case NUVIE_DIR_S:
case NUVIE_DIR_SW:
return set_cursor_pos(CURSOR_FEET);
case NUVIE_DIR_SE:
return set_cursor_pos(CURSOR_COMBAT);
default:
return GUI_YUM;
}
case CURSOR_FEET:
switch (direction) {
case NUVIE_DIR_N:
return set_cursor_pos(CURSOR_HEAD);
case NUVIE_DIR_W:
case NUVIE_DIR_NW:
return set_cursor_pos(CURSOR_RIGHT_RING);
case NUVIE_DIR_E:
case NUVIE_DIR_NE:
return set_cursor_pos(CURSOR_LEFT_RING);
case NUVIE_DIR_S:
case NUVIE_DIR_SW:
case NUVIE_DIR_SE:
return set_cursor_pos(CURSOR_COMBAT);
default:
return GUI_YUM;
}
case CURSOR_COMBAT:
switch (direction) {
case NUVIE_DIR_N:
case NUVIE_DIR_NW:
return set_cursor_pos(CURSOR_RIGHT_RING);
case NUVIE_DIR_NE:
return set_cursor_pos(CURSOR_FEET);
case NUVIE_DIR_SW:
return set_cursor_pos(CURSOR_CHECK);
case NUVIE_DIR_SE:
return set_cursor_pos(cursor_party);
case NUVIE_DIR_S:
return set_cursor_pos(cursor_heart);
default:
return GUI_YUM;
}
case CURSOR_CHECK:
switch (direction) {
case NUVIE_DIR_NE:
return set_cursor_pos(CURSOR_COMBAT);
case NUVIE_DIR_E:
case NUVIE_DIR_SE:
return set_cursor_pos(cursor_heart);
default:
return GUI_YUM;
}
case CURSOR_HEART:
switch (direction) {
case NUVIE_DIR_N:
case NUVIE_DIR_NW:
case NUVIE_DIR_NE:
return set_cursor_pos(CURSOR_COMBAT);
case NUVIE_DIR_W:
case NUVIE_DIR_SW:
return set_cursor_pos(CURSOR_CHECK);
case NUVIE_DIR_E:
case NUVIE_DIR_SE:
return set_cursor_pos(cursor_party);
default:
return GUI_YUM;
}
case CURSOR_PARTY:
switch (direction) {
case NUVIE_DIR_N:
case NUVIE_DIR_NW:
case NUVIE_DIR_NE:
return set_cursor_pos(CURSOR_COMBAT);
case NUVIE_DIR_W:
case NUVIE_DIR_SW:
return set_cursor_pos(cursor_heart);
case NUVIE_DIR_E:
case NUVIE_DIR_SE:
return set_cursor_pos(CURSOR_INVENTORY);
default:
return GUI_YUM;
}
case CURSOR_INVENTORY:
switch (direction) {
case NUVIE_DIR_N:
case NUVIE_DIR_NW:
case NUVIE_DIR_NE:
return set_cursor_pos(CURSOR_COMBAT);
case NUVIE_DIR_W:
case NUVIE_DIR_SW:
return set_cursor_pos(cursor_party);
default:
return GUI_YUM;
}
default:
return GUI_YUM;
}
}
GUI_status DollViewGump::KeyDown(const Common::KeyState &key) {
// I was restricting numpad keys when in numlock but there shouldn't be any needed number input
// bool numlock = (key.flags & Common::KBD_NUM); // SDL doesn't get the proper num lock state in Windows
KeyBinder *keybinder = Game::get_game()->get_keybinder();
ActionType a = keybinder->get_ActionType(key);
switch (keybinder->GetActionKeyType(a)) {
case SOUTH_WEST_KEY:
return moveCursorRelative(NUVIE_DIR_SW);
case SOUTH_EAST_KEY:
return moveCursorRelative(NUVIE_DIR_SE);
case NORTH_WEST_KEY:
return moveCursorRelative(NUVIE_DIR_NW);
case NORTH_EAST_KEY:
return moveCursorRelative(NUVIE_DIR_NE);
case NORTH_KEY:
return moveCursorRelative(NUVIE_DIR_N);
case SOUTH_KEY:
return moveCursorRelative(NUVIE_DIR_S);
case WEST_KEY:
return moveCursorRelative(NUVIE_DIR_W);
case EAST_KEY:
return moveCursorRelative(NUVIE_DIR_E);
case NEXT_PARTY_MEMBER_KEY:
right_arrow();
return GUI_YUM;
case PREVIOUS_PARTY_MEMBER_KEY:
left_arrow();
return GUI_YUM;
case HOME_KEY:
set_actor(party->get_actor(0));
return GUI_YUM;
case END_KEY:
set_actor(party->get_actor(party->get_party_size() - 1));
return GUI_YUM;
case DO_ACTION_KEY: {
Events *event = Game::get_game()->get_event();
bool in_party = party->get_member_num(actor) >= 0;
if (event->get_mode() == ATTACK_MODE || cursor_pos == CURSOR_CHECK) {
Game::get_game()->get_view_manager()->close_gump(this);
} else if (cursor_pos == CURSOR_LEFT) {
left_arrow();
} else if (cursor_pos == CURSOR_RIGHT) {
right_arrow();
} else if (cursor_pos == CURSOR_COMBAT) {
activate_combat_button();
} else if (cursor_pos == CURSOR_HEART) {
if (in_party || event->using_control_cheat())
Game::get_game()->get_view_manager()->open_portrait_gump(actor);
} else if (cursor_pos == CURSOR_PARTY) {
if (in_party) {
}
} else if (cursor_pos == CURSOR_INVENTORY) {
Game::get_game()->get_view_manager()->open_container_view(actor);
} else {
Obj *obj = actor->inventory_get_readied_object((uint8)cursor_pos);
if (event->get_mode() == MOVE_MODE || event->get_mode() == EQUIP_MODE) {
if (obj)
event->unready(obj);
} else
event->select_view_obj(obj, actor);
}
return GUI_YUM;
}
default:
break;
}
return GUI_PASS;
}
void DollViewGump::activate_combat_button() {
Events *event = Game::get_game()->get_event();
if (actor->is_in_party() && party->get_member_num(actor) != 0) {
set_combat_mode(actor);
update_display = true;
} else if (event->get_mode() != INPUT_MODE && event->get_mode() != CAST_MODE
&& event->get_mode() != ATTACK_MODE)
event->newAction(COMBAT_MODE);
}
GUI_status DollViewGump::MouseWheel(sint32 x, sint32 y) {
if (y > 0) {
left_arrow();
} else if (y < 0) {
right_arrow();
}
return GUI_YUM;
}
GUI_status DollViewGump::MouseDown(int x, int y, Events::MouseButton button) {
return DraggableView::MouseDown(x, y, button);
}
GUI_status DollViewGump::MouseUp(int x, int y, Events::MouseButton button) {
return DraggableView::MouseUp(x, y, button);
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,107 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_DOLL_VIEW_GUMP_H
#define NUVIE_VIEWS_DOLL_VIEW_GUMP_H
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/views/draggable_view.h"
namespace Ultima {
namespace Nuvie {
class Configuration;
class TileManager;
class ObjManager;
class Screen;
class Actor;
class Font;
class DollWidget;
static const int DOLLVIEWGUMP_HEIGHT = 136;
class DollViewGump : public DraggableView {
GUI_Button *gump_button;
GUI_Button *combat_button;
GUI_Button *heart_button;
GUI_Button *party_button;
GUI_Button *inventory_button;
DollWidget *doll_widget;
GUI_Font *font;
Actor *actor;
bool is_avatar;
bool show_cursor;
const Tile *cursor_tile;
gumpCursorPos cursor_pos;
uint8 cursor_xoff, cursor_yoff;
Graphics::ManagedSurface *actor_doll;
public:
DollViewGump(const Configuration *cfg);
~DollViewGump() override;
bool init(Screen *tmp_screen, void *view_manager, uint16 x, uint16 y, Actor *a, Font *f, Party *p, TileManager *tm, ObjManager *om);
void set_actor(Actor *a);
Actor *get_actor() {
return actor;
}
void Display(bool full_redraw) override;
GUI_status MouseDown(int x, int y, Events::MouseButton button) override;
GUI_status MouseUp(int x, int y, Events::MouseButton button) override;
GUI_status MouseMotion(int x, int y, uint8 state) override {
return DraggableView::MouseMotion(x, y, state);
}
GUI_status MouseWheel(sint32 xpos, sint32 ypos) override;
void MoveRelative(int dx, int dy) override {
return DraggableView::MoveRelative(dx, dy);
}
GUI_status callback(uint16 msg, GUI_CallBack *caller, void *data) override;
protected:
void displayEquipWeight();
void displayCombatMode();
void left_arrow();
void right_arrow();
private:
void activate_combat_button();
void setColorKey(Graphics::ManagedSurface *image);
GUI_status set_cursor_pos(gumpCursorPos pos);
GUI_status moveCursorRelative(NuvieDir direction);
GUI_status KeyDown(const Common::KeyState &key) override;
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,557 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
// FIX need to subclass this class for U6, MD & SE
#include "ultima/nuvie/conf/configuration.h"
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/misc/u6_misc.h"
#include "ultima/nuvie/files/u6_lib_n.h"
#include "ultima/nuvie/files/u6_shape.h"
#include "ultima/nuvie/gui/widgets/msg_scroll.h"
#include "ultima/nuvie/core/events.h"
#include "ultima/nuvie/actors/actor.h"
#include "ultima/nuvie/actors/actor_manager.h"
#include "ultima/nuvie/screen/game_palette.h"
#include "ultima/nuvie/views/doll_widget.h"
#include "ultima/nuvie/gui/widgets/command_bar.h"
#include "ultima/nuvie/gui/widgets/map_window.h"
#include "ultima/nuvie/core/player.h"
#include "ultima/nuvie/views/view_manager.h"
#include "ultima/nuvie/files/nuvie_bmp_file.h"
namespace Ultima {
namespace Nuvie {
static const byte gump_blocked_tile_data[] = {
170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
170, 170, 170, 170, 64, 178, 55, 54, 54, 55, 178, 64, 170, 170, 170, 170,
170, 170, 170, 64, 55, 168, 64, 170, 170, 64, 168, 55, 64, 170, 170, 170,
170, 170, 64, 55, 64, 170, 170, 170, 170, 170, 12, 12, 55, 64, 170, 170,
170, 170, 178, 130, 170, 170, 170, 170, 170, 12, 12, 12, 168, 178, 170, 170,
170, 170, 55, 64, 170, 170, 170, 170, 12, 12, 12, 170, 64, 55, 170, 170,
170, 170, 54, 170, 170, 170, 170, 12, 12, 12, 170, 170, 170, 54, 170, 170,
170, 170, 54, 170, 170, 170, 12, 12, 12, 170, 170, 170, 170, 54, 170, 170,
170, 170, 55, 64, 170, 12, 12, 12, 170, 170, 170, 170, 64, 55, 170, 170,
170, 170, 178, 168, 12, 12, 12, 170, 170, 170, 170, 170, 168, 178, 170, 170,
170, 170, 64, 55, 12, 12, 170, 170, 170, 170, 170, 64, 55, 64, 170, 170,
170, 170, 170, 64, 55, 168, 64, 170, 170, 64, 168, 55, 64, 170, 170, 170,
170, 170, 170, 170, 64, 178, 55, 54, 54, 55, 178, 64, 170, 170, 170, 170,
170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170
};
static const byte gump_empty_tile_data[] = {
170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
170, 170, 170, 170, 64, 178, 55, 54, 54, 55, 178, 64, 170, 170, 170, 170,
170, 170, 170, 64, 55, 168, 64, 170, 170, 64, 168, 55, 64, 170, 170, 170,
170, 170, 64, 55, 64, 170, 170, 170, 170, 170, 170, 64, 55, 64, 170, 170,
170, 170, 178, 130, 170, 170, 170, 170, 170, 170, 170, 170, 168, 178, 170, 170,
170, 170, 55, 64, 170, 170, 170, 170, 170, 170, 170, 170, 64, 55, 170, 170,
170, 170, 54, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 54, 170, 170,
170, 170, 54, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 54, 170, 170,
170, 170, 55, 64, 170, 170, 170, 170, 170, 170, 170, 170, 64, 55, 170, 170,
170, 170, 178, 168, 170, 170, 170, 170, 170, 170, 170, 170, 168, 178, 170, 170,
170, 170, 64, 55, 64, 170, 170, 170, 170, 170, 170, 64, 55, 64, 170, 170,
170, 170, 170, 64, 55, 168, 64, 170, 170, 64, 168, 55, 64, 170, 170, 170,
170, 170, 170, 170, 64, 178, 55, 54, 54, 55, 178, 64, 170, 170, 170, 170,
170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170
};
DollWidget::DollWidget(const Configuration *cfg, GUI_CallBack *callback)
: GUI_Widget(nullptr, 0, 0, 0, 0), config(cfg), callback_object(callback),
actor(nullptr), tile_manager(nullptr), selected_obj(nullptr),
obj_manager(nullptr), unready_obj(nullptr), empty_tile(nullptr),
blocked_tile(nullptr), need_to_free_tiles(false), use_new_dolls(true),
old_use_new_dolls(true), actor_doll(nullptr), doll_bg(nullptr),
md_doll_shp(nullptr), is_in_portrait_view(false) {
bg_color = Game::get_game()->get_palette()->get_bg_color();
// Set up hit rects
item_hit_rects[0] = Common::Rect(24, 0, 24 + 16, 0 + 16); // ACTOR_HEAD
item_hit_rects[1] = Common::Rect(0, 8, 0 + 16, 8 + 16); // ACTOR_NECK
item_hit_rects[2] = Common::Rect(48, 8, 48 + 16, 8 + 16); // ACTOR_BODY
item_hit_rects[3] = Common::Rect(0, 24, 0 + 16, 24 + 16); // ACTOR_ARM
item_hit_rects[4] = Common::Rect(48, 24, 48 + 16, 24 + 16); // ACTOR_ARM_2
item_hit_rects[5] = Common::Rect(0, 40, 0 + 16, 40 + 16); // ACTOR_HAND
item_hit_rects[6] = Common::Rect(48, 40, 48 + 16, 40 + 16); // ACTOR_HAND_2
item_hit_rects[7] = Common::Rect(24, 48, 24 + 16, 48 + 16); // ACTOR_FOOT
}
DollWidget::~DollWidget() {
if (need_to_free_tiles) {
if (blocked_tile)
delete blocked_tile;
if (empty_tile)
delete empty_tile;
}
free_doll_shapes();
}
bool DollWidget::init(Actor *a, uint16 x, uint16 y, TileManager *tm, ObjManager *om, bool in_portrait_view) {
tile_manager = tm;
obj_manager = om;
is_in_portrait_view = in_portrait_view;
if (!Game::get_game()->is_new_style() || is_in_portrait_view) {
switch (Game::get_game()->get_game_type()) {
case NUVIE_GAME_U6 :
blocked_tile = tile_manager->get_tile(TILE_U6_BLOCKED_EQUIP);
empty_tile = tile_manager->get_tile(TILE_U6_EQUIP);
break;
case NUVIE_GAME_SE :
blocked_tile = tile_manager->get_tile(TILE_SE_BLOCKED_EQUIP);
empty_tile = tile_manager->get_tile(TILE_SE_EQUIP);
break;
case NUVIE_GAME_MD :
blocked_tile = tile_manager->get_tile(TILE_MD_BLOCKED_EQUIP); // FIXME: different depending on npc
empty_tile = tile_manager->get_tile(TILE_MD_EQUIP); // FIXME: different depending on npc
break;
}
} else {
blocked_tile = new Tile();
memcpy(&blocked_tile->data, &gump_blocked_tile_data, 256);
empty_tile = new Tile();
memcpy(&empty_tile->data, &gump_empty_tile_data, 256);
need_to_free_tiles = true;
}
GUI_Widget::Init(nullptr, x, y, 64, 64);
set_actor(a);
set_accept_mouseclick(true, USE_BUTTON); // accept [double]clicks from button1 (even if double-click disabled we need clicks)
return true;
}
void DollWidget::free_doll_shapes() {
if (actor_doll) {
delete actor_doll;
actor_doll = nullptr;
}
if (doll_bg) {
delete doll_bg;
doll_bg = nullptr;
}
if (md_doll_shp) {
delete md_doll_shp;
md_doll_shp = nullptr;
}
}
void DollWidget::setColorKey(Graphics::ManagedSurface *image) {
if (image) {
uint32 bg_color_key = image->format.RGBToColor(0xf1, 0x0f, 0xc4);
image->setTransparentColor(bg_color_key);
}
}
void DollWidget::set_actor(Actor *a) {
actor = a;
if (!Game::get_game()->is_new_style()) { // needed so it can be changed in the menus
config->value(config_get_game_key(config) + "/use_new_dolls", use_new_dolls, false);
if (old_use_new_dolls != use_new_dolls) {
if (!use_new_dolls)
free_doll_shapes();
old_use_new_dolls = use_new_dolls;
}
}
if (use_new_dolls) {
free_doll_shapes();
if (actor) {
ViewManager *vm = Game::get_game()->get_view_manager();
if (actor->is_avatar())
actor_doll = vm->loadAvatarDollImage(actor_doll, true);
else
actor_doll = vm->loadCustomActorDollImage(actor_doll, actor->get_actor_num(), true);
setColorKey(actor_doll);
if (actor_doll) {
Common::Path imagefile;
build_path(vm->getDollDataDirString(), "orig_style", imagefile);
build_path(imagefile, "doll_bg.bmp", imagefile);
NuvieBmpFile bmp;
doll_bg = bmp.getSdlSurface32(imagefile);
if (doll_bg) {
Common::Rect dst(3, 1, 30, 31);
SDL_BlitSurface(actor_doll, nullptr, doll_bg, &dst);
setColorKey(doll_bg);
}
}
}
} else if (Game::get_game()->get_game_type() == NUVIE_GAME_MD) {
load_md_doll_shp();
}
Redraw();
}
void DollWidget::load_md_doll_shp() {
if (actor == nullptr) {
return;
}
if (md_doll_shp)
delete md_doll_shp;
md_doll_shp = new U6Shape();
U6Lib_n file;
Common::Path filename;
config_get_path(config, "mdinv.lzc", filename);
file.open(filename, 4, NUVIE_GAME_MD);
uint8 num = actor->get_actor_num() + 1;
if (actor->is_avatar() && Game::get_game()->get_player()->get_gender() == 0) {
num--;
}
unsigned char *temp_buf = file.get_item(num);
if (temp_buf) {
md_doll_shp->load(temp_buf + 8);
free(temp_buf);
} else {
delete md_doll_shp;
md_doll_shp = nullptr;
}
}
const Common::Rect *DollWidget::get_item_hit_rect(uint8 location) const {
if (location < 8)
return &item_hit_rects[location];
return nullptr;
}
void DollWidget::Display(bool full_redraw) {
//if(full_redraw || update_display)
// {
update_display = false;
if (actor != nullptr)
display_doll();
screen->update(area.left, area.top, area.width(), area.height());
// }
}
inline void DollWidget::display_new_doll() {
if (doll_bg) {
Common::Rect dst;
dst = area;
dst.translate(15, 15);
dst.setWidth(33);
dst.setHeight(33);
SDL_BlitSurface(doll_bg, nullptr, surface, &dst);
}
}
inline void DollWidget::display_old_doll() {
Tile *tile;
uint16 i, j;
int tilenum = 368;
if (Game::get_game()->get_game_type() == NUVIE_GAME_MD) // FIXME: different depending on npc - Also needs npc doll info code
tilenum = 275;
else if (Game::get_game()->get_game_type() == NUVIE_GAME_SE) {
if (actor->get_obj_n() == 310 || actor->get_obj_n() == 311
|| actor->get_obj_n() == 312)
tilenum = 404;
else if (actor->get_obj_n() == 318)
tilenum = 408;
else
tilenum = 400;
}
// screen->fill(bg_color, area.left, area.top, area.width(), area.height()); // should be taken care of by the main view
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) { // draw doll
tile = tile_manager->get_tile(tilenum + i * 2 + j);
screen->blit(area.left + 16 + j * 16, area.top + 16 + i * 16, tile->data, 8, 16, 16, 16, true);
}
}
if (md_doll_shp) {
uint16 w, h;
md_doll_shp->get_size(&w, &h);
screen->blit(area.left + 20, area.top + 18, md_doll_shp->get_data(), 8, w, h, w, true);
}
}
inline void DollWidget::display_doll() {
if (!Game::get_game()->is_new_style() || is_in_portrait_view) {
if (use_new_dolls)
display_new_doll();
else
display_old_doll();
}
display_readied_object(ACTOR_NECK, area.left, (area.top + 8) + 0 * 16, actor, empty_tile);
display_readied_object(ACTOR_BODY, area.left + 3 * 16, (area.top + 8) + 0 * 16, actor, empty_tile);
display_readied_object(ACTOR_ARM, area.left, (area.top + 8) + 1 * 16, actor, empty_tile);
display_readied_object(ACTOR_ARM_2, area.left + 3 * 16, (area.top + 8) + 1 * 16, actor, actor->is_double_handed_obj_readied() ? blocked_tile : empty_tile);
display_readied_object(ACTOR_HAND, area.left, (area.top + 8) + 2 * 16, actor, empty_tile);
display_readied_object(ACTOR_HAND_2, area.left + 3 * 16, (area.top + 8) + 2 * 16, actor, empty_tile);
display_readied_object(ACTOR_HEAD, area.left + 16 + 8, area.top, actor, empty_tile);
display_readied_object(ACTOR_FOOT, area.left + 16 + 8, area.top + 3 * 16, actor, empty_tile);
return;
}
inline void DollWidget::display_readied_object(uint8 location, uint16 x, uint16 y, Actor *theActor, Tile *emptyTile) {
Obj *obj;
Tile *tile;
obj = theActor->inventory_get_readied_object(location);
if (obj)
tile = tile_manager->get_tile(obj_manager->get_obj_tile_num(obj->obj_n) + obj->frame_n);
else
tile = emptyTile;
screen->blit(x, y, tile->data, 8, 16, 16, 16, true);
return;
}
// when no action is pending the Use button may be used to start dragging,
// otherwise it has the same effect as ENTER (using InventoryView's callback)
GUI_status DollWidget::MouseDown(int x, int y, Events::MouseButton button) {
Events *event = Game::get_game()->get_event();
uint8 location;
Obj *obj;
x -= area.left;
y -= area.top;
CommandBar *command_bar = Game::get_game()->get_command_bar();
if (button == ACTION_BUTTON && event->get_mode() == MOVE_MODE
&& command_bar->get_selected_action() > 0) { // Exclude attack mode too
if (command_bar->try_selected_action() == false) // start new action
return GUI_YUM; // false if new event doesn't need target
}
if (actor && selected_obj == nullptr && (button == USE_BUTTON || button == ACTION_BUTTON || button == DRAG_BUTTON)) {
for (location = 0; location < 8; location++) {
if (HitRect(x, y, item_hit_rects[location])) { // FIXME: duplicating code in InventoryWidget
DEBUG(0, LEVEL_DEBUGGING, "Hit %d\n", location);
obj = actor->inventory_get_readied_object(location);
if (button == ACTION_BUTTON && command_bar->get_selected_action() > 0
&& event->get_mode() == INPUT_MODE) {
if (obj) {
event->select_obj(obj, actor);
return GUI_YUM;
} else {
// has not found a target yet
Game::get_game()->get_scroll()->display_string("nothing!\n");
event->endAction(true);
event->set_mode(MOVE_MODE);
}
return GUI_PASS;
}
if (obj) {
if ((event->get_mode() == MOVE_MODE || event->get_mode() == EQUIP_MODE)
&& button == DRAG_BUTTON)
selected_obj = obj; // start dragging
else // send to View
callback_object->callback(INVSELECT_CB, this, obj);
}
return GUI_YUM;
}
}
}
return GUI_PASS;
}
// un-ready selected item
GUI_status DollWidget::MouseUp(int x, int y, Events::MouseButton button) {
Events *event = Game::get_game()->get_event();
// only act now if double-click is disabled
if (selected_obj && !Game::get_game()->get_map_window()->is_doubleclick_enabled()) {
event->unready(selected_obj);
Redraw();
unready_obj = nullptr;
} else if (selected_obj) {
wait_for_mouseclick(USE_BUTTON);
unready_obj = selected_obj;
}
selected_obj = nullptr;
return GUI_PASS;
}
GUI_status DollWidget::MouseClick(int x, int y, Events::MouseButton button) {
return MouseUp(x, y, button);
}
GUI_status DollWidget::MouseMotion(int x, int y, uint8 state) {
Tile *tile;
if (selected_obj && !dragging && Game::get_game()->is_dragging_enabled()) {
dragging = true;
tile = tile_manager->get_tile(obj_manager->get_obj_tile_num(selected_obj->obj_n) + selected_obj->frame_n);
return gui_drag_manager->start_drag(this, GUI_DRAG_OBJ, selected_obj, tile->data, 16, 16, 8);
}
return GUI_PASS;
}
void DollWidget::drag_drop_success(int x, int y, int message, void *data) {
DEBUG(0, LEVEL_DEBUGGING, "DollWidget::drag_drop_success()\n");
dragging = false;
// handled by drop target
// actor->remove_readied_object(selected_obj);
// actor->inventory_remove_obj(selected_obj);
selected_obj = nullptr;
Redraw();
}
void DollWidget::drag_drop_failed(int x, int y, int message, void *data) {
DEBUG(0, LEVEL_DEBUGGING, "DollWidget::drag_drop_failed()\n");
dragging = false;
selected_obj = nullptr;
}
bool DollWidget::drag_accept_drop(int x, int y, int message, void *data) {
DEBUG(0, LEVEL_DEBUGGING, "DollWidget::drag_accept_drop()\n");
if (message == GUI_DRAG_OBJ) {
Obj *obj = (Obj *)data;
if (obj->is_readied() && obj->get_actor_holding_obj() == actor) {
// FIXME: need to detect ready location so player can switch hands
DEBUG(0, LEVEL_WARNING, "DollWidget: Object already equipped!\n");
return false;
}
if (obj->get_actor_holding_obj() != actor) {
if (obj->is_in_inventory()) {
Events *event = Game::get_game()->get_event();
event->display_move_text(actor, obj);
if (event->can_move_obj_between_actors(obj, obj->get_actor_holding_obj(), actor, false)) {
Game::get_game()->get_player()->subtract_movement_points(3);
DEBUG(0, LEVEL_DEBUGGING, "Drop Accepted\n");
return true;
}
}
}
if (obj->get_actor_holding_obj() == actor
|| Game::get_game()->get_map_window()->can_get_obj(actor, obj)) {
DEBUG(0, LEVEL_DEBUGGING, "Drop Accepted\n");
return true;
} else {
DEBUG(0, LEVEL_WARNING, "DollWidget: Must be holding object!\n");
return false;
}
}
DEBUG(0, LEVEL_DEBUGGING, "Drop Refused\n");
return false;
}
void DollWidget::drag_perform_drop(int /*x*/, int /*y*/, int message, void *data) {
DEBUG(0, LEVEL_DEBUGGING, "DollWidget::drag_perform_drop()\n");
Obj *obj;
//x -= area.left;
//y -= area.top;
if (message == GUI_DRAG_OBJ) {
DEBUG(0, LEVEL_DEBUGGING, "Ready item.\n");
obj = (Obj *)data;
bool can_equip = true;
if (!obj->is_in_inventory()) { // get
// event->newAction(GET_MODE);
Game::get_game()->get_scroll()->display_string("Get-");
can_equip = Game::get_game()->get_event()->perform_get(obj, nullptr, actor);
// if(!can_equip)
// {
// assert(!(obj->status & OBJ_STATUS_IN_CONTAINER));
// obj_manager->add_obj(obj); // add back to map
// }
} else
obj_manager->moveto_inventory(obj, actor);
if (can_equip) { // ready
assert(!obj->is_readied());
Game::get_game()->get_event()->ready(obj, actor);
}
Redraw();
}
return;
}
void DollWidget::drag_draw(int x, int y, int message, void *data) {
Tile *tile;
if (!selected_obj)
return;
tile = tile_manager->get_tile(obj_manager->get_obj_tile_num(selected_obj) + selected_obj->frame_n);
int nx = x - 8;
int ny = y - 8;
if (nx + 16 >= screen->get_width())
nx = screen->get_width() - 17;
else if (nx < 0)
nx = 0;
if (ny + 16 >= screen->get_height())
ny = screen->get_height() - 17;
else if (ny < 0)
ny = 0;
screen->blit(nx, ny, tile->data, 8, 16, 16, 16, true);
screen->update(nx, ny, 16, 16);
}
/* Use object.
*/
GUI_status DollWidget::MouseDouble(int x, int y, Events::MouseButton button) {
// we have to check if double-clicks are allowed here, since we use single-clicks
if (!Game::get_game()->get_map_window()->is_doubleclick_enabled())
return GUI_PASS;
Events *event = Game::get_game()->get_event();
Obj *obj = selected_obj;
unready_obj = nullptr;
selected_obj = nullptr;
if (!(actor && obj))
return GUI_YUM;
if (event->newAction(USE_MODE))
event->select_obj(obj);
return GUI_YUM;
}
// change container, ready/unready object, activate arrows
GUI_status DollWidget::MouseDelayed(int x, int y, Events::MouseButton button) {
Events *event = Game::get_game()->get_event();
if (unready_obj) {
event->unready(unready_obj);
Redraw();
unready_obj = nullptr;
}
return GUI_PASS;
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,101 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_DOLL_WIDGET_H
#define NUVIE_VIEWS_DOLL_WIDGET_H
#include "ultima/nuvie/gui/widgets/gui_widget.h"
#include "ultima/nuvie/core/tile_manager.h"
#include "ultima/nuvie/core/obj_manager.h"
#include "ultima/nuvie/views/inventory_message.h"
namespace Ultima {
namespace Nuvie {
class Configuration;
class Actor;
class U6Shape;
class DollWidget : public GUI_Widget {
const Configuration *config;
TileManager *tile_manager;
ObjManager *obj_manager;
Actor *actor;
bool use_new_dolls, old_use_new_dolls;
Obj *selected_obj, *unready_obj;
uint8 bg_color;
bool is_in_portrait_view;
bool need_to_free_tiles;
Tile *empty_tile, *blocked_tile;
U6Shape *md_doll_shp;
Graphics::ManagedSurface *actor_doll, *doll_bg;
public:
DollWidget(const Configuration *cfg, GUI_CallBack *callback = nullptr);
~DollWidget() override;
bool init(Actor *a, uint16 x, uint16 y, TileManager *tm, ObjManager *om, bool in_portrat_view = false);
void free_doll_shapes();
void setColorKey(Graphics::ManagedSurface *image);
void set_actor(Actor *a);
void Display(bool full_redraw) override;
GUI_status MouseDown(int x, int y, Events::MouseButton button) override;
GUI_status MouseUp(int x, int y, Events::MouseButton button) override;
GUI_status MouseMotion(int x, int y, uint8 state) override;
GUI_status MouseDouble(int x, int y, Events::MouseButton button) override;
GUI_status MouseClick(int x, int y, Events::MouseButton button) override;
GUI_status MouseDelayed(int x, int y, Events::MouseButton button) override;
void drag_drop_success(int x, int y, int message, void *data) override;
void drag_drop_failed(int x, int y, int message, void *data) override;
bool drag_accept_drop(int x, int y, int message, void *data) override;
void drag_perform_drop(int x, int y, int message, void *data) override;
void drag_draw(int x, int y, int message, void *data) override;
const Common::Rect *get_item_hit_rect(uint8 location) const;
protected:
GUI_CallBack *callback_object; // object-selected callback
void display_doll();
void display_old_doll();
void display_new_doll();
void display_readied_object(uint8 location, uint16 x, uint16 y, Actor *actor, Tile *emptyTile);
private:
Common::Rect item_hit_rects[8];
void load_md_doll_shp();
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,145 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/misc/u6_misc.h"
#include "ultima/nuvie/gui/gui.h"
#include "ultima/nuvie/gui/gui_button.h"
#include "ultima/nuvie/conf/configuration.h"
#include "ultima/nuvie/views/view_manager.h"
#include "ultima/nuvie/gui/widgets/msg_scroll.h"
#include "ultima/nuvie/views/draggable_view.h"
namespace Ultima {
namespace Nuvie {
DraggableView::DraggableView(const Configuration *cfg) : View(cfg),
drag(false), button_x(0), button_y(0), bg_image(nullptr),
bg_color_key(0), always_need_full_redraw_when_moved(false) {
Game *game = Game::get_game();
if (game->is_orig_style() || game->is_original_plus_cutoff_map()) {
need_full_redraw_when_moved = true;
always_need_full_redraw_when_moved = true;
} else if (game->get_game_width() < game->get_screen()->get_width()
|| game->get_game_height() < game->get_screen()->get_height()) {
need_full_redraw_when_moved = true;
always_need_full_redraw_when_moved = false;
} else // no need to set always_need_full_redraw_when_moved
need_full_redraw_when_moved = false;
}
DraggableView::~DraggableView() {
if (bg_image) {
delete bg_image;
bg_image = nullptr;
}
}
void DraggableView::set_bg_color_key(uint8 r, uint8 g, uint8 b) {
if (bg_image) {
bg_color_key = bg_image->format.RGBToColor(0, 0x70, 0xfc);
bg_image->setTransparentColor(bg_color_key);
}
}
GUI_status DraggableView::MouseDown(int x, int y, Events::MouseButton button) {
if (bg_image && HitRect(x, y)) {
uint32 pixel = sdl_getpixel(bg_image, x - area.left, y - area.top);
if (pixel == bg_color_key) {
return GUI_PASS;
}
}
drag = true;
button_x = x;
button_y = y;
moveToFront();
if (Game::get_game()->is_new_style()) {
Game::get_game()->get_scroll()->moveToFront();
}
grab_focus();
return GUI_YUM;
}
GUI_status DraggableView::MouseUp(int x, int y, Events::MouseButton button) {
drag = false;
release_focus();
if (button == Events::BUTTON_RIGHT) {
Game::get_game()->get_view_manager()->close_gump(this);
}
return GUI_YUM;
}
GUI_status DraggableView::MouseMotion(int x, int y, uint8 state) {
int dx, dy;
if (!drag || state == 0) //state is 0 if no button pressed
return GUI_PASS;
dx = x - button_x;
dy = y - button_y;
button_x = x;
button_y = y;
GUI::get_gui()->moveWidget(this, dx, dy);
// Redraw();
return GUI_YUM;
}
void DraggableView::force_full_redraw_if_needed() {
if (need_full_redraw_when_moved) {
if (always_need_full_redraw_when_moved // or over background
|| (area.right > Game::get_game()->get_game_width() + Game::get_game()->get_game_x_offset()
|| area.left < Game::get_game()->get_game_x_offset() || area.top < Game::get_game()->get_game_y_offset()
|| area.bottom > Game::get_game()->get_game_height() + Game::get_game()->get_game_y_offset()))
GUI::get_gui()->force_full_redraw();
}
}
void DraggableView::MoveRelative(int dx, int dy) {
int new_x = area.left + dx;
if (new_x < 0) {
dx = -area.left;
} else if (new_x + area.width() > screen->get_width()) {
dx = screen->get_width() - (area.left + area.width());
}
int new_y = area.top + dy;
if (new_y < 0) {
dy = -area.top;
} else if (new_y + area.height() > screen->get_height()) {
dy = screen->get_height() - (area.top + area.height());
}
force_full_redraw_if_needed(); // needs to happen before the move
GUI_Widget::MoveRelative(dx, dy);
return;
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,61 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_INVENTORY_FONT_H
#define NUVIE_VIEWS_INVENTORY_FONT_H
#include "ultima/nuvie/views/view.h"
#include "graphics/managed_surface.h"
namespace Ultima {
namespace Nuvie {
class Configuration;
class GUI_Button;
class DraggableView: public View {
protected:
Graphics::ManagedSurface *bg_image;
uint32 bg_color_key;
private:
bool drag, need_full_redraw_when_moved, always_need_full_redraw_when_moved;
int button_x, button_y;
public:
DraggableView(const Configuration *config);
~DraggableView() override;
/* events, used for dragging the area. */
GUI_status MouseDown(int x, int y, Events::MouseButton button) override;
GUI_status MouseUp(int x, int y, Events::MouseButton button) override;
GUI_status MouseMotion(int x, int y, uint8 state) override;
void MoveRelative(int dx, int dy) override;
protected:
void set_bg_color_key(uint8 r, uint8 g, uint8 b);
void force_full_redraw_if_needed();
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,244 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_INVENTORY_FONT_H
#define NUVIE_VIEWS_INVENTORY_FONT_H
namespace Ultima {
namespace Nuvie {
static const int NUVIE_MICRO_FONT_COUNT = 26;
const unsigned char inventory_font[NUVIE_MICRO_FONT_COUNT][15] = {
{
1, 1, 1,
1, 0, 1,
1, 0, 1,
1, 0, 1,
1, 1, 1
}
,
{
0, 0, 1,
0, 0, 1,
0, 0, 1,
0, 0, 1,
0, 0, 1
}
,
{
1, 1, 1,
0, 0, 1,
1, 1, 1,
1, 0, 0,
1, 1, 1
}
,
{
1, 1, 1,
0, 0, 1,
1, 1, 1,
0, 0, 1,
1, 1, 1
}
,
{
1, 0, 1,
1, 0, 1,
1, 1, 1,
0, 0, 1,
0, 0, 1
}
,
{
1, 1, 1,
1, 0, 0,
1, 1, 1,
0, 0, 1,
1, 1, 1
}
,
{
1, 1, 1,
1, 0, 0,
1, 1, 1,
1, 0, 1,
1, 1, 1
}
,
{
1, 1, 1,
0, 0, 1,
0, 0, 1,
0, 0, 1,
0, 0, 1
}
,
{
1, 1, 1,
1, 0, 1,
1, 1, 1,
1, 0, 1,
1, 1, 1
}
,
{
1, 1, 1,
1, 0, 1,
1, 1, 1,
0, 0, 1,
0, 0, 1
}
, // A
{
1, 1, 1,
1, 0, 1,
1, 1, 1,
1, 0, 1,
1, 0, 1
}
, // B
{
1, 1, 0,
1, 0, 1,
1, 1, 0,
1, 0, 1,
1, 1, 0
}
, // C
{
1, 1, 1,
1, 0, 0,
1, 0, 0,
1, 0, 0,
1, 1, 1
}
, // D
{
1, 1, 0,
1, 0, 1,
1, 0, 1,
1, 0, 1,
1, 1, 0
}
, // E
{
1, 1, 1,
1, 0, 0,
1, 1, 1,
1, 0, 0,
1, 1, 1
}
, // F
{
1, 1, 1,
1, 0, 0,
1, 1, 0,
1, 0, 0,
1, 0, 0
}
, // G
{
1, 1, 1,
1, 0, 0,
1, 0, 1,
1, 0, 1,
1, 1, 1
}
, // H
{
1, 0, 1,
1, 0, 1,
1, 1, 1,
1, 0, 1,
1, 0, 1
}
, // I
{
1, 1, 1,
0, 1, 0,
0, 1, 0,
0, 1, 0,
1, 1, 1
}
, // J
{
0, 0, 1,
0, 0, 1,
0, 0, 1,
1, 0, 1,
1, 1, 1
}
, // K
{
1, 0, 1,
1, 0, 1,
1, 1, 0,
1, 0, 1,
1, 0, 1
}
, // L
{
1, 0, 0,
1, 0, 0,
1, 0, 0,
1, 0, 0,
1, 1, 1
}
, // M
{
1, 0, 1,
1, 1, 1,
1, 0, 1,
1, 0, 1,
1, 0, 1
}
, // n
{
0, 0, 0,
0, 0, 0,
1, 1, 1,
1, 0, 1,
1, 0, 1
}
, // o
{
0, 0, 0,
0, 0, 0,
1, 1, 1,
1, 0, 1,
1, 1, 1
}
, // P
{
1, 1, 1,
1, 0, 1,
1, 1, 1,
1, 0, 0,
1, 0, 0
}
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,28 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_INVENTORY_MESSAGE_H
#define NUVIE_VIEWS_INVENTORY_MESSAGE_H
static const uint16 BUTTON_CB = 0x1;
static const uint16 INVSELECT_CB = 0x2;
#endif

View File

@@ -0,0 +1,700 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/screen/screen.h"
#include "ultima/nuvie/misc/u6_llist.h"
#include "ultima/nuvie/gui/gui_button.h"
#include "ultima/nuvie/views/doll_widget.h"
#include "ultima/nuvie/views/inventory_widget.h"
#include "ultima/nuvie/views/inventory_view.h"
#include "ultima/nuvie/core/party.h"
#include "ultima/nuvie/fonts/font.h"
#include "ultima/nuvie/actors/actor.h"
#include "ultima/nuvie/core/events.h"
#include "ultima/nuvie/gui/widgets/map_window.h"
#include "ultima/nuvie/usecode/usecode.h"
#include "ultima/nuvie/views/view_manager.h"
#include "ultima/nuvie/keybinding/keys.h"
namespace Ultima {
namespace Nuvie {
static const char combat_mode_tbl[][8] = {"COMMAND", " FRONT", " REAR", " FLANK", "BERSERK", "RETREAT", "ASSAULT"};
static const char combat_mode_tbl_se[][6] = {"CMND", "RANGE", "FLEE", "CLOSE"};
static const char combat_mode_tbl_md[][6] = {"CMND", "RANGE", "FLEE", "ATTK"};
#define MD Game::get_game()->get_game_type()==NUVIE_GAME_MD
InventoryView::InventoryView(const Configuration *cfg)
: View(cfg), doll_widget(nullptr), inventory_widget(nullptr),
combat_button(nullptr), cursor_tile(nullptr), show_cursor(false),
is_party_member(false), picking_pocket(false), outside_actor(nullptr),
lock_actor(false) {
cursor_pos.area = INVAREA_LIST;
cursor_pos.x = cursor_pos.y = 0;
cursor_pos.px = cursor_pos.py = 0;
}
InventoryView::~InventoryView() {
}
bool InventoryView::set_party_member(uint8 party_member) {
if (lock_actor || party_member >= party->get_party_size()) {
return false;
}
picking_pocket = false;
if (View::set_party_member(party_member)
&& !Game::get_game()->get_event()->using_control_cheat()) {
is_party_member = true;
if (doll_widget)
doll_widget->set_actor(party->get_actor(cur_party_member));
if (inventory_widget)
inventory_widget->set_actor(party->get_actor(cur_party_member));
show_buttons();
if (combat_button) {
if (party_member == 0)
combat_button->Hide();
else
combat_button->Show();
}
return true;
}
is_party_member = false;
hide_buttons();
if (actor_button) actor_button->Show();
return false;
}
bool InventoryView::set_actor(Actor *actor, bool pickpocket) {
if (lock_actor)
return false;
if (party->contains_actor(actor)) {
set_party_member(party->get_member_num(actor));
return true;
}
picking_pocket = pickpocket;
is_party_member = false;
outside_actor = actor;
if (doll_widget)
doll_widget->set_actor(actor);
if (inventory_widget)
inventory_widget->set_actor(actor);
if (picking_pocket) {
if (actor_button) actor_button->Hide();
}
hide_buttons();
return true;
}
bool InventoryView::init(Screen *tmp_screen, void *view_manager, uint16 x, uint16 y, Font *f, Party *p, TileManager *tm, ObjManager *om) {
if (Game::get_game()->get_game_type() == NUVIE_GAME_U6)
View::init(x, y, f, p, tm, om);
else
View::init(x, y - 2, f, p, tm, om);
doll_widget = new DollWidget(config, this);
doll_widget->init(party->get_actor(cur_party_member), 0, 8, tile_manager, obj_manager, true);
AddWidget(doll_widget);
inventory_widget = new InventoryWidget(config, this);
inventory_widget->init(party->get_actor(cur_party_member), 64, 8, tile_manager, obj_manager, font);
AddWidget(inventory_widget);
add_command_icons(tmp_screen, view_manager);
cursor_tile = tile_manager->get_cursor_tile();
return true;
}
void InventoryView::PlaceOnScreen(Screen *s, GUI_DragManager *dm, int x, int y) {
GUI_Widget::PlaceOnScreen(s, dm, x, y);
update_cursor(); // initial position; uses area
}
void InventoryView::Display(bool full_redraw) {
full_redraw = true;
if (full_redraw || update_display) {
if (MD)
fill_md_background(lock_actor ? 7 : bg_color, area);
else
screen->fill(bg_color, area.left, area.top, area.width(), area.height());
if (is_party_member)
display_combat_mode();
display_name();
display_inventory_weights();
}
DisplayChildren(full_redraw);
if (full_redraw || update_display) {
update_display = false;
screen->update(area.left, area.top, area.width(), area.height());
}
if (show_cursor && cursor_tile != nullptr) {
screen->blit(cursor_pos.px, cursor_pos.py, (unsigned char *)cursor_tile->data,
8, 16, 16, 16, true, nullptr);
screen->update(cursor_pos.px, cursor_pos.py, 16, 16);
}
return;
}
void InventoryView::display_name() {
const char *name;
int y_off = 0;
if (Game::get_game()->get_game_type() == NUVIE_GAME_SE)
y_off = 1;
if (is_party_member)
name = party->get_actor_name(cur_party_member);
else if (picking_pocket)
name = outside_actor->get_name();
else
name = Game::get_game()->get_player()->get_actor()->get_name(true);
if (name == nullptr)
return;
font->drawString(screen, name, area.left + ((136) - strlen(name) * 8) / 2, area.top + y_off);
return;
}
void InventoryView::add_command_icons(Screen *tmp_screen, void *view_manager) {
Tile *tile;
int y = 96;
if (MD)
y = 100;
else if (Game::get_game()->get_game_type() == NUVIE_GAME_U6)
y = 80;
Graphics::ManagedSurface *button_image;
Graphics::ManagedSurface *button_image2;
//FIX need to handle clicked button image, check image free on destruct.
tile = tile_manager->get_tile(MD ? 282 : 387); //left arrow icon
button_image = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
button_image2 = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
left_button = new GUI_Button(this, 0, y, button_image, button_image2, this);
this->AddWidget(left_button);
tile = tile_manager->get_tile(MD ? 279 : 384); //party view icon
button_image = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
button_image2 = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
party_button = new GUI_Button(view_manager, 16, y, button_image, button_image2, this);
this->AddWidget(party_button);
tile = tile_manager->get_tile(MD ? 280 : 385); //actor view icon
button_image = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
button_image2 = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
actor_button = new GUI_Button(view_manager, 2 * 16, y, button_image, button_image2, this);
this->AddWidget(actor_button);
tile = tile_manager->get_tile(MD ? 283 : 388); //right arrow icon
button_image = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
button_image2 = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
right_button = new GUI_Button(this, 3 * 16, y, button_image, button_image2, this);
this->AddWidget(right_button);
if (MD)
tile = tile_manager->get_tile(285); //combat icon
else if (Game::get_game()->get_game_type() == NUVIE_GAME_SE)
tile = tile_manager->get_tile(365); //combat icon
else
tile = tile_manager->get_tile(391); //combat icon
button_image = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
button_image2 = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
combat_button = new GUI_Button(this, 4 * 16, y, button_image, button_image2, this); //FIX combat
this->AddWidget(combat_button);
}
void InventoryView::display_inventory_weights() {
uint8 strength;
unsigned int inv_weight;
unsigned int equip_weight;
Actor *actor;
if (is_party_member)
actor = party->get_actor(cur_party_member);
else if (picking_pocket)
actor = outside_actor;
else
actor = Game::get_game()->get_player()->get_actor();
char string[9]; // "E:xx/xxs"
strength = actor->get_strength();
ViewManager *vm = Game::get_game()->get_view_manager();
inv_weight = vm->get_display_weight(actor->get_inventory_weight());
equip_weight = vm->get_display_weight(actor->get_inventory_equip_weight());
snprintf(string, 9, "E:%u/%us", equip_weight, strength);
font->drawString(screen, string, area.left, area.top + 72);
snprintf(string, 9, "I:%u/%us", inv_weight, strength * 2);
if (Game::get_game()->get_game_type() == NUVIE_GAME_U6)
font->drawString(screen, string, area.left + 4 * 16 + 8, area.top + 72);
else
font->drawString(screen, string, area.left, area.top + 80);
}
void InventoryView::display_combat_mode() {
Actor *actor = party->get_actor(cur_party_member);
uint8 index = get_combat_mode_index(actor);
if (Game::get_game()->get_game_type() != NUVIE_GAME_U6) {
int y_off = 96;
if (MD)
y_off = 100;
Tile *tile;
// Avatar combat text background (where command button is for other party members)
if (actor->get_actor_num() == 1 || actor->get_actor_num() == 0) {
if (MD)
tile = tile_manager->get_tile(284);
else
tile = tile_manager->get_tile(364);
screen->blit(area.left + 4 * 16, area.top + y_off, tile->data, 8, 16, 16, 16, true);
}
if (MD) // combat text background
tile = tile_manager->get_tile(286);
else // SE
tile = tile_manager->get_tile(366);
screen->blit(area.left + 5 * 16, area.top + y_off, tile->data, 8, 16, 16, 16, true);
screen->blit(area.left + 6 * 16, area.top + y_off, tile->data, 8, 16, 16, 16, true); // reuse
if (MD) // last combat text background
tile = tile_manager->get_tile(287);
else
tile = tile_manager->get_tile(368);
screen->blit(area.left + 7 * 16, area.top + y_off, tile->data, 8, 16, 16, 16, true);
if (MD)
font->drawString(screen, combat_mode_tbl_md[index], area.left + 5 * 16, area.top + 101);
else
font->drawString(screen, combat_mode_tbl_se[index], area.left + 5 * 16, area.top + 98);
} else
font->drawString(screen, combat_mode_tbl[index], area.left + 5 * 16, area.top + 88);
}
/* Move the cursor around, ready or unready objects, select objects, switch
* to container view, use command icons.
*/
GUI_status InventoryView::KeyDown(const Common::KeyState &key) {
if (!show_cursor) // FIXME: don't rely on show_cursor to get/pass focus
return GUI_PASS;
KeyBinder *keybinder = Game::get_game()->get_keybinder();
ActionType a = keybinder->get_ActionType(key);
switch (keybinder->GetActionKeyType(a)) {
// keypad arrow keys (moveCursorRelative doesn't accept diagonals)
case SOUTH_WEST_KEY:
moveCursorRelative(0, 1);
moveCursorRelative(-1, 0);
break;
case SOUTH_EAST_KEY:
moveCursorRelative(0, 1);
moveCursorRelative(1, 0);
break;
case NORTH_WEST_KEY:
moveCursorRelative(0, -1);
moveCursorRelative(-1, 0);
break;
case NORTH_EAST_KEY:
moveCursorRelative(0, -1);
moveCursorRelative(1, 0);
break;
case NORTH_KEY:
moveCursorRelative(0, -1);
break;
case SOUTH_KEY:
moveCursorRelative(0, 1);
break;
case WEST_KEY:
moveCursorRelative(-1, 0);
break;
case EAST_KEY:
moveCursorRelative(1, 0);
break;
case DO_ACTION_KEY:
select_objAtCursor();
break;
case TOGGLE_CURSOR_KEY :
if (is_party_member) { // when in pickpocket mode we don't want to allow tabing to map window.
set_show_cursor(false);
return GUI_PASS;
}
break;
default:
// set_show_cursor(false); // newAction() can move cursor here
return GUI_PASS;
}
return GUI_YUM;
}
/* Put cursor over one of the readied-item slots. */
void InventoryView::moveCursorToSlot(uint8 slot_num) {
cursor_pos.area = INVAREA_DOLL;
cursor_pos.x = slot_num;
}
/* Put cursor over one of the visible inventory slots. (column inv_x, row inv_y) */
void InventoryView::moveCursorToInventory(uint8 inv_x, uint8 inv_y) {
cursor_pos.area = INVAREA_LIST;
cursor_pos.x = inv_x;
cursor_pos.y = inv_y;
}
/* Put cursor over one of the command icons. */
void InventoryView::moveCursorToButton(uint8 button_num) {
cursor_pos.area = INVAREA_COMMAND;
cursor_pos.x = button_num;
}
/* Put cursor over the container or actor icon above the inventory widget. */
void InventoryView::moveCursorToTop() {
cursor_pos.area = INVAREA_TOP;
}
/* Put cursor over the next slot or icon in relative direction new_x, new_y. */
void InventoryView::moveCursorRelative(sint8 new_x, sint8 new_y) {
uint32 x = cursor_pos.x, y = cursor_pos.y;
if (cursor_pos.area == INVAREA_LIST) {
if (x == 0 && new_x < 0) {
if (y == 0)
moveCursorToSlot(2);
else if (y == 1)
moveCursorToSlot(4);
else if (y == 2)
moveCursorToSlot(6);
else if (y == 3) {
if (!picking_pocket)
moveCursorToButton(3);
}
} else if (y == 0 && new_y < 0) {
if (inventory_widget->up_arrow()) // scroll up
update_display = true;
else
moveCursorToTop(); // move to container icon
} else if (y == (uint8)(inventory_widget->get_num_rows() - 1) && new_y > 0) {
if (inventory_widget->down_arrow()) // scroll down
update_display = true;
else if (!picking_pocket)
moveCursorToButton((x == 0) ? 3 : 4); // move to command icon
} else if ((x + new_x) <= 3)
moveCursorToInventory(x + new_x, y + new_y);
} else if (cursor_pos.area == INVAREA_DOLL) {
// moves from these readied items can jump to inventory list
if (new_x > 0 && x == 2)
moveCursorToInventory(0, 0);
else if (new_x > 0 && x == 4)
moveCursorToInventory(0, 1);
else if (new_x > 0 && x == 6)
moveCursorToInventory(0, 2);
// moves from these readied items can jump to command icons
else if (new_y > 0 && x == 5 && !picking_pocket)
moveCursorToButton(0);
else if (new_y > 0 && x == 6 && !picking_pocket)
moveCursorToButton(2);
else if (new_y > 0 && x == 7 && !picking_pocket)
moveCursorToButton(1);
// the rest move between readied items
else if (x == 0)
moveCursorToSlot((new_x < 0) ? 1
: (new_x > 0) ? 2
: (new_y > 0) ? 7 : 0);
else if (x == 7)
moveCursorToSlot((new_x < 0) ? 5
: (new_x > 0) ? 6
: (new_y < 0) ? 0 : 7);
else if (x == 1)
moveCursorToSlot((new_x > 0) ? 0
: (new_y > 0) ? 3 : 1);
else if (x == 3)
moveCursorToSlot((new_x > 0) ? 4
: (new_y < 0) ? 1
: (new_y > 0) ? 5 : 3);
else if (x == 5)
moveCursorToSlot((new_x > 0) ? 7
: (new_y < 0) ? 3 : 5);
else if (x == 2)
moveCursorToSlot((new_x < 0) ? 0
: (new_y > 0) ? 4 : 2);
else if (x == 4)
moveCursorToSlot((new_x < 0) ? 3
: (new_y < 0) ? 2
: (new_y > 0) ? 6 : 4);
else if (x == 6)
moveCursorToSlot((new_x < 0) ? 7
: (new_y < 0) ? 4 : 6);
} else if (cursor_pos.area == INVAREA_COMMAND) {
if (new_y < 0) {
if (x == 0)
moveCursorToSlot(5);
else if (x == 1)
moveCursorToSlot(7);
else if (x == 2)
moveCursorToSlot(6);
else if (x == 3)
moveCursorToInventory(0, inventory_widget->get_num_rows() - 1);
else if (x == 4)
moveCursorToInventory(1, inventory_widget->get_num_rows() - 1);
} else if (((sint16)x + new_x) >= 0 && (x + new_x) <= 4)
moveCursorToButton(x + new_x);
update_display = true;
} else if (cursor_pos.area == INVAREA_TOP)
if (new_y > 0) {
moveCursorToInventory(cursor_pos.x, 0);
update_display = true;
}
update_cursor();
}
/* Update on-screen location (px,py) of cursor.
*/
void InventoryView::update_cursor() {
const Common::Rect *ready_loc;
nuvie_game_t gametype = Game::get_game()->get_game_type();
switch (cursor_pos.area) {
case INVAREA_LIST:
if (gametype == NUVIE_GAME_U6) {
cursor_pos.px = area.left + (4 * 16 + 8) + cursor_pos.x * 16;
} else {
cursor_pos.px = inventory_widget->area.left + cursor_pos.x * 16;
}
cursor_pos.py = area.top + 16 + 8 + cursor_pos.y * 16;
break;
case INVAREA_TOP:
cursor_pos.px = inventory_widget->area.left + (gametype == NUVIE_GAME_U6 ? 32 : (inventory_widget->area.width() - 16) / 2);
cursor_pos.py = inventory_widget->area.top;
break;
case INVAREA_DOLL:
ready_loc = doll_widget->get_item_hit_rect(cursor_pos.x);
cursor_pos.px = ready_loc->left + doll_widget->area.left;
cursor_pos.py = ready_loc->top + doll_widget->area.top;
break;
case INVAREA_COMMAND:
cursor_pos.px = ((cursor_pos.x + 1) * 16) - 16;
cursor_pos.py = left_button->area.top; //80;
cursor_pos.px += area.left;
//cursor_pos.py += area.top;
break;
}
}
void InventoryView::set_show_cursor(bool state) {
show_cursor = state;
update_display = true;
ViewManager *vm = Game::get_game()->get_view_manager();
if (state == true && vm->get_current_view() != this) // second comparison prevents endless loop
vm->set_inventory_mode();
}
void InventoryView::hide_buttons() {
if (left_button) left_button->Hide();
if (right_button) right_button->Hide();
// if(actor_button) actor_button->Hide();
if (party_button) party_button->Hide();
if (combat_button) combat_button->Hide();
}
void InventoryView::show_buttons() {
// if(left_button) left_button->Show(); // these two shouldn't be needed
// if(right_button) right_button->Show(); // and cause problems
if (actor_button) actor_button->Show();
if (party_button) party_button->Show();
if (combat_button) combat_button->Show();
}
/* Returns pointer to object at cursor position, or nullptr.
*/
Obj *InventoryView::get_objAtCursor() {
// emulate mouse; use center of cursor
uint32 hit_x = cursor_pos.px + 8 - inventory_widget->area.left,
hit_y = cursor_pos.py + 8 - inventory_widget->area.top;
if (cursor_pos.area == INVAREA_LIST)
return (inventory_widget->get_obj_at_location(hit_x, hit_y));
else if (cursor_pos.area == INVAREA_DOLL)
return (inventory_widget->get_actor()->inventory_get_readied_object(cursor_pos.x));
return nullptr;
}
/* Do an action with the object under the cursor, or call the function for a
selected button. This is called when pressing ENTER. */
void InventoryView::select_objAtCursor() {
Events *event = Game::get_game()->get_event();
ViewManager *view_manager = Game::get_game()->get_view_manager();
Obj *obj = get_objAtCursor();
if (cursor_pos.area == INVAREA_TOP && event->can_target_icon()) {
if (inventory_widget->is_showing_container() && event->get_last_mode() != PUSH_MODE)
select_obj((Obj *)inventory_widget->get_container());
else if (inventory_widget->is_showing_container()
&& inventory_widget->get_container()->get_engine_loc() == OBJ_LOC_CONT)
select_obj((Obj *)inventory_widget->get_container()->parent);
else
event->select_actor(inventory_widget->get_actor());
return;
}
if (is_party_member) {
// special areas
if (cursor_pos.area == INVAREA_COMMAND) {
if (cursor_pos.x == 0) // left
View::callback(BUTTON_CB, left_button, view_manager);
if (cursor_pos.x == 1) // party
View::callback(BUTTON_CB, party_button, view_manager);
if (cursor_pos.x == 2) // status
View::callback(BUTTON_CB, actor_button, view_manager);
if (cursor_pos.x == 3) // right
View::callback(BUTTON_CB, right_button, view_manager);
if (cursor_pos.x == 4) // strategy
callback(BUTTON_CB, combat_button, view_manager);
return;
} else if (cursor_pos.area == INVAREA_TOP) {
if (inventory_widget->is_showing_container())
inventory_widget->set_prev_container();
else
Game::get_game()->get_view_manager()->set_party_mode();
return;
}
}
if (cursor_pos.area == INVAREA_DOLL || cursor_pos.area == INVAREA_LIST)
select_obj(obj); // do action with an object
}
/* Ready an object or pass it to Events. Pass nullptr if an empty space is selected.
* Returns true if the object was "used". The caller is free to handle the
* object if false is returned.
*/
bool InventoryView::select_obj(Obj *obj) {
Events *event = Game::get_game()->get_event();
switch (event->get_mode()) {
case MOVE_MODE:
case EQUIP_MODE: {
if (!obj)
break;
bool locked_chest = (Game::get_game()->get_usecode()->is_chest(obj) && obj->frame_n > 1);
if (Game::get_game()->get_usecode()->is_container(obj) && !locked_chest)
inventory_widget->set_container(obj);
else {
if (obj->is_readied())
return event->unready(obj);
else
return event->ready(obj, inventory_widget->get_actor());
}
break;
}
case ATTACK_MODE:
set_show_cursor(false);
event->cancelAction();
return false;
default:
event->select_view_obj(obj, inventory_widget->get_actor());
return true;
}
return false;
}
GUI_status InventoryView::MouseDown(int x, int y, Events::MouseButton button) {
return GUI_PASS;
}
GUI_status InventoryView::MouseWheel(sint32 x, sint32 y) {
if (!is_party_member)
return GUI_PASS;
int xpos, ypos;
screen->get_mouse_location(&xpos, &ypos);
xpos -= area.left;
ypos -= area.top;
bool wheel_range = (xpos >= 0 && ypos < area.top + area.height() - 6);
if (y > 0 && wheel_range) {
View::callback(BUTTON_CB, left_button, Game::get_game()->get_view_manager());
return GUI_YUM;
} else if (y < 0 && wheel_range) {
View::callback(BUTTON_CB, right_button, Game::get_game()->get_view_manager());
return GUI_YUM;
}
return GUI_PASS; // goes to MsgScroll
}
/* Messages from child widgets, Inventory & Doll.
**INVSELECT is called when an object is selected with MouseDown.*
**BUTTON is called when one of the command buttons is selected.*
* Returns GUI_PASS if the data was not used.
*/
GUI_status InventoryView::callback(uint16 msg, GUI_CallBack *caller, void *data) {
if (msg != INVSELECT_CB) { // hit one of the command buttons
if (caller == combat_button) {
if (cur_party_member != 0) { // You can't change combat modes for the avatar.
Actor *actor = party->get_actor(cur_party_member);
set_combat_mode(actor);
update_display = true;
}
return GUI_YUM;
} else
return View::callback(msg, caller, data);
}
// selecting an object from InventoryWidget only works while getting input
Events *event = Game::get_game()->get_event();
if (event->get_mode() == INPUT_MODE) {
if (select_obj((Obj *)data))
return GUI_YUM;
}
return GUI_PASS;
}
void InventoryView::simulate_CB_callback() {
callback(BUTTON_CB, combat_button, Game::get_game()->get_view_manager());
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,112 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_INVENTORY_VIEW_H
#define NUVIE_VIEWS_INVENTORY_VIEW_H
#include "ultima/nuvie/views/view.h"
namespace Ultima {
namespace Nuvie {
class Configuration;
class TileManager;
class ObjManager;
class Screen;
class Actor;
class Font;
class Party;
class DollWidget;
class InventoryWidget;
class InventoryView : public View {
DollWidget *doll_widget;
InventoryWidget *inventory_widget;
GUI_Button *combat_button;
bool is_party_member;
bool picking_pocket;
Actor *outside_actor;
bool lock_actor;
enum invarea {
INVAREA_LIST = 0, // cursor is over the inventory list (x,y)
INVAREA_TOP, // the actor or container icon
INVAREA_DOLL, // the readied-items list (0-7)
INVAREA_COMMAND // the command icons (0-4)
};
struct invcursor_pos_s {
enum invarea area;
uint8 x, y; // y is only used for inventory list
uint32 px, py;
} cursor_pos;
Tile *cursor_tile;
bool show_cursor;
public:
InventoryView(const Configuration *cfg);
~InventoryView() override;
bool init(Screen *tmp_screen, void *view_manager, uint16 x, uint16 y, Font *f, Party *p, TileManager *tm, ObjManager *om);
bool set_party_member(uint8 party_member) override;
bool set_actor(Actor *actor, bool pickpocket = false);
void set_show_cursor(bool state);
void moveCursorToSlot(uint8 slot_num);
void moveCursorToInventory(uint8 inv_x = 0, uint8 inv_y = 0);
void moveCursorRelative(sint8 new_x, sint8 new_y);
void moveCursorToButton(uint8 button_num = 0);
void moveCursorToTop();
bool select_obj(Obj *obj);
void select_objAtCursor();
Obj *get_objAtCursor();
InventoryWidget *get_inventory_widget() {
return inventory_widget;
};
void Display(bool full_redraw) override;
void PlaceOnScreen(Screen *s, GUI_DragManager *dm, int x, int y) override;
GUI_status KeyDown(const Common::KeyState &key) override;
void simulate_CB_callback();
bool is_picking_pocket() const {
return picking_pocket;
}
void lock_to_actor(bool value) {
lock_actor = value;
}
protected:
void display_name();
void add_command_icons(Screen *tmp_screen, void *view_manager);
void display_inventory_weights();
void display_combat_mode();
void update_cursor();
void hide_buttons();
void show_buttons();
GUI_status MouseDown(int x, int y, Events::MouseButton button) override;
GUI_status MouseWheel(sint32 x, sint32 y) override;
GUI_status callback(uint16 msg, GUI_CallBack *caller, void *data) override;
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,668 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/misc/u6_llist.h"
#include "ultima/nuvie/conf/configuration.h"
#include "ultima/nuvie/gui/gui.h"
#include "ultima/nuvie/screen/game_palette.h"
#include "ultima/nuvie/views/inventory_widget.h"
#include "ultima/nuvie/actors/actor.h"
#include "ultima/nuvie/fonts/font.h"
#include "ultima/nuvie/core/game_clock.h"
#include "ultima/nuvie/core/events.h"
#include "ultima/nuvie/gui/widgets/msg_scroll.h"
#include "ultima/nuvie/core/timed_event.h"
#include "ultima/nuvie/usecode/usecode.h"
#include "ultima/nuvie/gui/widgets/map_window.h"
#include "ultima/nuvie/core/player.h"
#include "ultima/nuvie/gui/widgets/command_bar.h"
#include "ultima/nuvie/views/inventory_font.h"
#include "ultima/nuvie/views/view_manager.h"
namespace Ultima {
namespace Nuvie {
InventoryWidget::InventoryWidget(const Configuration *cfg, GUI_CallBack *callback)
: GUI_Widget(nullptr, 0, 0, 0, 0), config(cfg), callback_object(callback),
container_obj(nullptr), tile_manager(nullptr), obj_manager(nullptr),
selected_obj(nullptr), font(nullptr), actor(nullptr), target_obj(nullptr),
target_cont(nullptr), empty_tile(nullptr), row_offset(0), icon_x(0),
bg_color(0), objlist_offset_x(0), objlist_offset_y(0), obj_font_color(0) {
ready_obj = nullptr; // FIXME: this is unused but I might need it again -- SB-X
config->value("config/GameType", game_type);
arrow_rects[0] = Common::Rect(0, 16, 0 + 8, 16 + 8);
arrow_rects[1] = Common::Rect(0, 3 * 16 + 8, 0 + 8, 3 * 16 + 8 + 8);
}
InventoryWidget::~InventoryWidget() {
}
bool InventoryWidget::init(Actor *a, uint16 x, uint16 y, TileManager *tm, ObjManager *om, Font *f) {
tile_manager = tm;
obj_manager = om;
font = f;
bg_color = Game::get_game()->get_palette()->get_bg_color();
obj_font_color = 0;
if (Game::get_game()->get_game_type() == NUVIE_GAME_U6) {
icon_x = 32;
obj_font_color = 0x48;
objlist_offset_x = 8;
} else {
icon_x = 23;
objlist_offset_x = 0;
}
objlist_offset_y = 16;
if (Game::get_game()->get_game_type() == NUVIE_GAME_U6) {
empty_tile = tile_manager->get_tile(410);
GUI_Widget::Init(nullptr, x, y, 72, 64); //72 = 4 * 16 + 8
} else if (Game::get_game()->get_game_type() == NUVIE_GAME_MD) { // FIXME: different depending on npc
empty_tile = tile_manager->get_tile(273);
GUI_Widget::Init(nullptr, x, y, 64, 82);
} else { // SE
empty_tile = tile_manager->get_tile(392);
GUI_Widget::Init(nullptr, x + 2, y, 64, 82);
}
set_actor(a);
set_accept_mouseclick(true, USE_BUTTON); // accept [double]clicks from button1 (even if double-click disabled we need clicks)
return true;
}
void InventoryWidget::set_actor(Actor *a) {
actor = a;
container_obj = nullptr;
Redraw();
}
Obj *InventoryWidget::get_prev_container() {
if (container_obj && container_obj->get_engine_loc() == OBJ_LOC_CONT)
return (Obj *)container_obj->parent;
return nullptr;
}
void InventoryWidget::set_prev_container() {
if (!container_obj)
return;
if (container_obj->get_engine_loc() == OBJ_LOC_CONT)
set_container((Obj *)container_obj->parent);
else
set_container(nullptr);
return;
}
void InventoryWidget::Display(bool full_redraw) {
if (full_redraw || update_display) {
// screen->fill(bg_color, area.left, area.top, area.width(), area.height());
display_inventory_container();
if (Game::get_game()->get_game_type() == NUVIE_GAME_U6)
display_arrows();
}
//screen->blit(area.left+40,area.top+16,portrait_data,8,56,64,56,false);
//clear the screen first inventory icons, 4 x 3 tiles
// screen->fill(bg_color, area.left +objlist_offset_x, area.top + objlist_offset_y, 16 * 4, 16 * 3); // doesn't seem to be needed
display_inventory_list();
if (full_redraw || update_display) {
update_display = false;
screen->update(area.left, area.top, area.width(), area.height());
} else {
screen->update(area.left + objlist_offset_x, area.top + 16, area.width() - objlist_offset_x, area.height() - 16); // update only the inventory list
}
}
//either an Actor or an object container.
void InventoryWidget::display_inventory_container() {
Tile *tile;
if (!container_obj) //display actor
tile = tile_manager->get_tile(actor->get_downward_facing_tile_num());
else // display container object
tile = tile_manager->get_tile(obj_manager->get_obj_tile_num(container_obj) + container_obj->frame_n);
screen->blit(area.left + icon_x, area.top, tile->data, 8, 16, 16, 16, true);
return;
}
void InventoryWidget::display_inventory_list() {
const Tile *tile;
U6LList *inventory;
U6Link *link;
Obj *obj = nullptr;
uint16 i, j;
uint16 skip_num;
int max_rows = 4;
if (Game::get_game()->get_game_type() == NUVIE_GAME_U6)
max_rows = 3;
if (container_obj)
inventory = container_obj->container;
else
inventory = actor->get_inventory_list();
if (inventory == nullptr)
link = nullptr;
else
link = inventory->start();
//skip row_offset rows of objects.
skip_num = row_offset * 4;
for (i = 0; link != nullptr && i < skip_num; link = link->next) {
obj = (Obj *)link->data;
if (obj->is_readied() == false)
i++;
}
for (i = 0; i < max_rows; i++) {
for (j = 0; j < 4; j++) {
if (link != nullptr) {
obj = (Obj *)link->data;
if (obj->is_readied()) { //skip any readied objects
for (; link != nullptr && obj->is_readied(); link = link->next)
obj = (Obj *)link->data;
} else
link = link->next;
tile = tile_manager->get_tile(obj_manager->get_obj_tile_num(obj) + obj->frame_n);
if (link == nullptr) {
if (obj->is_readied()) //last object is readied so skip it.
tile = empty_tile;
}
} else
tile = empty_tile;
//tile = tile_manager->get_tile(actor->indentory_tile());
if (tile == empty_tile)
screen->blit((area.left + objlist_offset_x) + j * 16, area.top + objlist_offset_y + i * 16, (const unsigned char *)empty_tile->data, 8, 16, 16, 16, true);
if (tile != empty_tile) {
//draw qty string for stackable items
if (obj_manager->is_stackable(obj))
display_qty_string((area.left + objlist_offset_x) + j * 16, area.top + objlist_offset_y + i * 16, obj->qty);
//draw special char for Keys.
if (game_type == NUVIE_GAME_U6 && obj->obj_n == 64)
display_special_char((area.left + objlist_offset_x) + j * 16, area.top + objlist_offset_y + i * 16, obj->quality);
}
screen->blit((area.left + objlist_offset_x) + j * 16, area.top + objlist_offset_y + i * 16, (const unsigned char *)tile->data, 8, 16, 16, 16, true);
}
}
}
void InventoryWidget::display_qty_string(uint16 x, uint16 y, uint16 qty) {
uint8 len, i, offset;
char buf[6];
Common::sprintf_s(buf, "%d", qty);
len = strlen(buf);
offset = (16 - len * 4) / 2;
for (i = 0; i < len; i++)
screen->blitbitmap(x + offset + 4 * i, y + 11, inventory_font[buf[i] - 48], 3, 5, obj_font_color, bg_color);
return;
}
void InventoryWidget::display_special_char(uint16 x, uint16 y, uint8 quality) {
if (quality + 9 >= NUVIE_MICRO_FONT_COUNT)
return;
screen->blitbitmap(x + 6, y + 11, inventory_font[quality + 9], 3, 5, obj_font_color, bg_color);
}
void InventoryWidget::display_arrows() {
uint32 num_objects;
if (is_showing_container()) {
if (container_obj->container)
num_objects = container_obj->container->count();
else
num_objects = 0;
} else
num_objects = actor->inventory_count_objects(false);
if (num_objects <= 12) //reset row_offset if we only have one page of objects
row_offset = 0;
if (row_offset > 0) //display top arrow
font->drawChar(screen, 24, area.left, area.top + 16);
if (num_objects - row_offset * 4 > 12) //display bottom arrow
font->drawChar(screen, 25, area.left, area.top + 3 * 16 + 8);
}
GUI_status InventoryWidget::MouseDown(int x, int y, Events::MouseButton button) {
Events *event = Game::get_game()->get_event();
CommandBar *command_bar = Game::get_game()->get_command_bar();
x -= area.left;
y -= area.top;
if (y < 17)
return GUI_PASS;
Obj *obj = get_obj_at_location(x, y);
if (button == ACTION_BUTTON && event->get_mode() == MOVE_MODE
&& command_bar->get_selected_action() > 0) { // Exclude attack mode too
if (command_bar->try_selected_action() == false) // start new action
return GUI_PASS; // false if new event doesn't need target
}
if (button == ACTION_BUTTON && command_bar->get_selected_action() > 0
&& event->get_mode() == INPUT_MODE) {
if (obj)
event->select_obj(obj); // the returned location
else {
Game::get_game()->get_scroll()->display_string("nothing!\n");
event->endAction(true);
event->set_mode(MOVE_MODE);
}
return GUI_PASS;
}
// ABOEING
if (actor && (button == USE_BUTTON || button == ACTION_BUTTON || button == DRAG_BUTTON)) {
if (obj) { // FIXME: duplicating code in DollWidget
// send to View
if (callback_object->callback(INVSELECT_CB, this, obj) == GUI_PASS
&& button == DRAG_BUTTON)
selected_obj = obj; // start dragging
return GUI_YUM;
}
}
return GUI_PASS;
}
inline uint16 InventoryWidget::get_list_position(int x, int y) {
uint16 list_pos;
list_pos = ((y - objlist_offset_y) / 16) * 4 + (x - objlist_offset_x) / 16;
list_pos += row_offset * 4;
return list_pos;
}
Obj *InventoryWidget::get_obj_at_location(int x, int y) {
uint8 location;
U6LList *inventory;
U6Link *link;
Obj *obj = nullptr;
uint16 i;
if (x >= objlist_offset_x && y >= objlist_offset_y) {
location = get_list_position(x, y); //find the position of the object we hit in the inventory
if (container_obj)
inventory = container_obj->container;
else
inventory = actor->get_inventory_list();
if (inventory == nullptr)
link = nullptr;
else
link = inventory->start();
for (i = 0; link != nullptr && i <= location; link = link->next) {
obj = (Obj *)link->data;
if (obj->is_readied() == false)
i++;
}
if (i > location && obj && obj->is_readied() == false) // don't return readied or non existent objects
return obj;
}
return nullptr;
}
GUI_status InventoryWidget::MouseWheel(sint32 x, sint32 y) {
int xpos, ypos;
screen->get_mouse_location(&xpos, &ypos);
xpos -= area.left;
ypos -= area.top;
if (xpos < 0 || ypos > area.top + area.height() - 10)
return GUI_PASS; // goes to InventoryView
if (Game::get_game()->get_game_type() == NUVIE_GAME_U6) {
if (y > 0) {
up_arrow();
}
if (y < 0) {
down_arrow();
}
selected_obj = nullptr;
}
return GUI_YUM;
}
// change container, ready/unready object, activate arrows
GUI_status InventoryWidget::MouseUp(int x, int y, Events::MouseButton button) {
CommandBar *command_bar = Game::get_game()->get_command_bar();
if (button == USE_BUTTON || (button == ACTION_BUTTON
&& command_bar->get_selected_action() > 0)) { // Exclude attack mode too
x -= area.left;
y -= area.top;
if (x >= icon_x && x <= icon_x + 15 && // hit top icon either actor or container
y >= 0 && y <= 15) {
Events *event = Game::get_game()->get_event();
if (button == ACTION_BUTTON && event->get_mode() == MOVE_MODE) {
if (command_bar->try_selected_action() == false) // start new action
return GUI_PASS; // false if new event doesn't need target
}
if (event->can_target_icon()) {
if (is_showing_container() && event->get_last_mode() != PUSH_MODE)
event->select_obj((Obj *)container_obj, actor);
else if (is_showing_container() && get_container()->get_engine_loc() == OBJ_LOC_CONT)
event->select_obj((Obj *)get_container()->parent, actor);
else
event->select_actor(actor);
return GUI_YUM;
}
if (is_showing_container())
set_prev_container(); //return to previous container or main actor inventory
else if (!event->using_control_cheat())
Game::get_game()->get_view_manager()->set_party_mode();
Redraw();
}
if (Game::get_game()->get_game_type() == NUVIE_GAME_U6) {
if (HitRect(x, y, arrow_rects[0])) //up arrow hit rect
up_arrow();
else if (HitRect(x, y, arrow_rects[1])) //down arrow hit rect
down_arrow();
}
// only act now if objects can't be used with DoubleClick
if (selected_obj && !Game::get_game()->get_map_window()->is_doubleclick_enabled())
try_click();
else if (selected_obj) {
wait_for_mouseclick(USE_BUTTON);
ready_obj = selected_obj;
}
}
selected_obj = nullptr;
return GUI_YUM;
}
bool InventoryWidget::up_arrow() {
if (row_offset > 0) {
row_offset--;
Redraw();
return true;
}
return false;
}
bool InventoryWidget::down_arrow() {
uint32 num_objects;
if (container_obj)
num_objects = container_obj->container_count_objects();
else
num_objects = actor->inventory_count_objects(false);
if (num_objects - row_offset * 4 > 12) {
row_offset++;
Redraw();
return true;
}
return false;
}
GUI_status InventoryWidget::MouseMotion(int x, int y, uint8 state) {
Tile *tile;
if (selected_obj && !dragging && Game::get_game()->is_dragging_enabled()) {
dragging = true;
tile = tile_manager->get_tile(obj_manager->get_obj_tile_num(selected_obj) + selected_obj->frame_n);
return gui_drag_manager->start_drag(this, GUI_DRAG_OBJ, selected_obj, tile->data, 16, 16, 8);
}
return GUI_PASS;
}
void InventoryWidget::drag_drop_success(int x, int y, int message, void *data) {
DEBUG(0, LEVEL_DEBUGGING, "InventoryWidget::drag_drop_success()\n");
dragging = false;
// handled by drop target
// if(container_obj)
// container_obj->container->remove(selected_obj);
// else
// actor->inventory_remove_obj(selected_obj);
selected_obj = nullptr;
Redraw();
}
void InventoryWidget::drag_drop_failed(int x, int y, int message, void *data) {
DEBUG(0, LEVEL_DEBUGGING, "InventoryWidget::drag_drop_failed()\n");
dragging = false;
selected_obj = nullptr;
}
bool InventoryWidget::drag_set_target_obj(int x, int y) {
if (x >= 32 && x < 48 && y < 16) {
target_obj = nullptr;
target_cont = get_prev_container(); //returns parent container or nullptr if we're back at the inventory.
} else if (x >= objlist_offset_x && y >= objlist_offset_y) {
target_obj = get_obj_at_location(x, y);
target_cont = get_container();
} else {
return false;
}
return true;
}
bool InventoryWidget::drag_accept_drop(int x, int y, int message, void *data) {
GUI::get_gui()->force_full_redraw();
DEBUG(0, LEVEL_DEBUGGING, "InventoryWidget::drag_accept_drop()\n");
if (message == GUI_DRAG_OBJ) {
Obj *obj = (Obj *)data;
x -= area.left;
y -= area.top;
if (target_obj == nullptr) { //we need to check this so we don't screw up target_obj on subsequent calls
if (drag_set_target_obj(x, y) == false) {
DEBUG(0, LEVEL_WARNING, "InventoryWidget: Didn't hit any widget object targets!\n");
return false;
}
}
Actor *src_actor = Game::get_game()->get_player()->get_actor();
if (obj->get_actor_holding_obj() == actor)
src_actor = actor;
else if (!obj->is_in_inventory() && actor == Game::get_game()->get_player()->get_actor()) {
Game::get_game()->get_scroll()->display_string("Get-");
Game::get_game()->get_scroll()->display_string(obj_manager->look_obj(obj, OBJ_SHOW_PREFIX));
} else
Game::get_game()->get_event()->display_move_text(actor, obj);
if (!obj->is_in_inventory()
&& !Game::get_game()->get_map_window()->can_get_obj(actor, obj)) {
Game::get_game()->get_scroll()->message("\n\nblocked\n\n");
return false;
}
if ((Game::get_game()->get_usecode()->has_getcode(obj)
&& !Game::get_game()->get_usecode()->get_obj(obj, actor))
|| !Game::get_game()->get_event()->can_move_obj_between_actors(obj, src_actor, actor)) {
Game::get_game()->get_scroll()->message("\n\n");
return false;
} else if (!obj->is_in_inventory()
&& obj_manager->obj_is_damaging(obj, Game::get_game()->get_player()->get_actor())) {
Game::get_game()->get_player()->subtract_movement_points(3);
return false;
} else if (src_actor != actor || !obj->is_in_inventory())
Game::get_game()->get_scroll()->message("\n\n");
if (src_actor != actor) // get plus move
Game::get_game()->get_player()->subtract_movement_points(8);
else if (!obj->is_in_inventory()) // get
Game::get_game()->get_player()->subtract_movement_points(3);
UseCode *usecode = Game::get_game()->get_usecode();
if (usecode->is_chest(obj) && obj->frame_n == 0) //open chest
obj->frame_n = 1; //close the chest
DEBUG(0, LEVEL_DEBUGGING, "Drop Accepted\n");
return true;
}
DEBUG(0, LEVEL_DEBUGGING, "Drop Refused\n");
return false;
}
void InventoryWidget::drag_perform_drop(int /*x*/, int /*y*/, int message, void *data) {
DEBUG(0, LEVEL_DEBUGGING, "InventoryWidget::drag_perform_drop()\n");
Obj *obj;
//x -= area.left;
//y -= area.top;
if (message == GUI_DRAG_OBJ) {
DEBUG(0, LEVEL_DEBUGGING, "Drop into inventory.\n");
obj = (Obj *)data;
if (target_obj && obj_manager->can_store_obj(target_obj, obj)) {
obj_manager->moveto_container(obj, target_obj);
} else if (target_cont && obj_manager->can_store_obj(target_cont, obj)) {
obj_manager->moveto_container(obj, target_cont);
} else {
if (obj->is_readied())
Game::get_game()->get_event()->unready(obj);
else
obj_manager->moveto_inventory(obj, actor);
}
Redraw();
}
Game::get_game()->get_map_window()->updateBlacking();
target_obj = nullptr;
return;
}
void InventoryWidget::drag_draw(int x, int y, int message, void *data) {
Tile *tile;
if (!selected_obj)
return;
tile = tile_manager->get_tile(obj_manager->get_obj_tile_num(selected_obj) + selected_obj->frame_n);
int nx = x - 8;
int ny = y - 8;
if (nx + 16 >= screen->get_width())
nx = screen->get_width() - 17;
else if (nx < 0)
nx = 0;
if (ny + 16 >= screen->get_height())
ny = screen->get_height() - 17;
else if (ny < 0)
ny = 0;
screen->blit(nx, ny, tile->data, 8, 16, 16, 16, true);
screen->update(nx, ny, 16, 16);
}
void InventoryWidget::try_click() {
Events *event = Game::get_game()->get_event();
UseCode *usecode = Game::get_game()->get_usecode();
if (!selected_obj)
selected_obj = ready_obj;
if (!selected_obj)
return;
bool locked_chest = (usecode->is_chest(selected_obj) && selected_obj->frame_n > 1);
if (event->get_mode() == ATTACK_MODE)
event->cancelAction();
else if (usecode->is_container(selected_obj) && !locked_chest) { // open up the container.
container_obj = selected_obj;
if (usecode->is_chest(container_obj) && selected_obj->frame_n == 1)
usecode->process_effects(container_obj, actor);
Redraw();
} else { // attempt to ready selected object.
event->ready(selected_obj, actor);
Redraw();
}
ready_obj = nullptr;
selected_obj = nullptr;
}
/* Use object. */
GUI_status InventoryWidget::MouseDouble(int x, int y, Events::MouseButton button) {
// we have to check if double-clicks are allowed here, since we use single-clicks
if (!Game::get_game()->get_map_window()->is_doubleclick_enabled())
return GUI_PASS;
Obj *obj = selected_obj;
ready_obj = nullptr;
selected_obj = nullptr;
if (!actor)
return GUI_YUM;
if (!obj)
return MouseUp(x, y, button); // probably hit an arrow
Game::get_game()->get_view_manager()->double_click_obj(obj);
return GUI_PASS;
}
GUI_status InventoryWidget::MouseClick(int x, int y, Events::MouseButton button) {
return MouseUp(x, y, button);
}
// change container, ready/unready object, activate arrows
GUI_status InventoryWidget::MouseDelayed(int x, int y, Events::MouseButton button) {
if (ready_obj)
try_click();
return GUI_PASS;
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,128 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_INVENTORY_WIDGET_H
#define NUVIE_VIEWS_INVENTORY_WIDGET_H
#include "ultima/nuvie/gui/widgets/gui_widget.h"
#include "ultima/nuvie/core/obj_manager.h"
#include "ultima/nuvie/views/inventory_message.h"
namespace Ultima {
namespace Nuvie {
class Configuration;
class TileManager;
class Actor;
class Font;
class InventoryWidget : public GUI_Widget {
private:
Common::Rect arrow_rects[2];
protected:
const Configuration *config;
int game_type;
TileManager *tile_manager;
ObjManager *obj_manager;
Font *font;
Actor *actor;
Obj *container_obj;
Obj *selected_obj, *target_obj, *ready_obj;
Obj *target_cont;
uint16 row_offset;
uint8 icon_x;
uint8 bg_color;
uint8 objlist_offset_x, objlist_offset_y;
uint8 obj_font_color;
const Tile *empty_tile;
public:
InventoryWidget(const Configuration *cfg, GUI_CallBack *callback = nullptr);
~InventoryWidget() override;
bool init(Actor *a, uint16 x, uint16 y, TileManager *tm, ObjManager *om, Font *f);
void set_actor(Actor *a);
Actor *get_actor() {
return actor;
}
Obj *get_container() {
return container_obj;
}
void set_container(Obj *obj) {
container_obj = obj;
row_offset = 0;
Redraw();
}
Obj *get_prev_container();
void set_prev_container();
bool is_showing_container() {
return (container_obj != nullptr ? true : false);
}
void Display(bool full_redraw) override;
GUI_status MouseDown(int x, int y, Events::MouseButton button) override;
GUI_status MouseUp(int x, int y, Events::MouseButton button) override;
GUI_status MouseMotion(int x, int y, uint8 state) override;
GUI_status MouseDouble(int x, int y, Events::MouseButton button) override;
GUI_status MouseClick(int x, int y, Events::MouseButton button) override;
GUI_status MouseDelayed(int x, int y, Events::MouseButton button) override;
GUI_status MouseWheel(sint32 x, sint32 y) override;
void drag_drop_success(int x, int y, int message, void *data) override;
void drag_drop_failed(int x, int y, int message, void *data) override;
bool drag_accept_drop(int x, int y, int message, void *data) override;
void drag_perform_drop(int x, int y, int message, void *data) override;
void drag_draw(int x, int y, int message, void *data) override;
uint8 get_num_rows() const {
return game_type == NUVIE_GAME_U6 ? 3 : 4;
}
protected:
GUI_CallBack *callback_object; // object-selected callback
inline uint16 get_list_position(int x, int y);
void display_inventory_container();
void display_inventory_list();
inline void display_qty_string(uint16 x, uint16 y, uint16 qty);
inline void display_special_char(uint16 x, uint16 y, uint8 quality);
void display_arrows();
bool drag_set_target_obj(int x, int y);
void try_click();
public:
bool up_arrow();
bool down_arrow();
Obj *get_obj_at_location(int x, int y);
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,311 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/misc/u6_misc.h"
#include "ultima/nuvie/gui/gui.h"
#include "ultima/nuvie/gui/gui_button.h"
#include "ultima/nuvie/conf/configuration.h"
#include "ultima/nuvie/core/map.h"
#include "ultima/nuvie/gui/widgets/map_window.h"
#include "ultima/nuvie/views/view_manager.h"
#include "ultima/nuvie/views/map_editor_view.h"
#include "ultima/nuvie/keybinding/keys.h"
namespace Ultima {
namespace Nuvie {
static const int TILES_W = 5;
static const int TILES_H = 10;
MapEditorView::MapEditorView(const Configuration *cfg) : View(cfg), roof_tiles(nullptr),
map_window(nullptr), up_button(nullptr), down_button(nullptr),
selectedTile(0), tile_offset(0) {
}
MapEditorView::~MapEditorView() {
}
bool MapEditorView::init(Screen *tmp_screen, void *view_manager, uint16 x, uint16 y, Font *f, Party *p, TileManager *tm, ObjManager *om) {
View::init(x, y, f, p, tm, om);
SetRect(area.left, area.top, 90, 200);
bg_color = 119;
Common::Path datadir = GUI::get_gui()->get_data_dir();
Common::Path path;
build_path(datadir, "images", path);
datadir = path;
build_path(datadir, "gumps", path);
datadir = path;
build_path(datadir, "mapeditor", path);
datadir = path;
up_button = loadButton(datadir, "up", 0, 7);
down_button = loadButton(datadir, "down", 0, 186);
map_window = Game::get_game()->get_map_window();
roof_tiles = map_window->get_roof_tiles();
map_window->set_show_cursor(true);
map_window->moveCursor(7, 6);
map_window->set_roof_display_mode(ROOF_DISPLAY_FORCE_ON);
map_window->set_enable_blacking(false);
map_window->set_show_grid(false);
Game::get_game()->set_mouse_pointer(1); //crosshairs
tile_offset = 0;
selectedTile = 3;
return true;
}
void MapEditorView::Display(bool full_redraw) {
Common::Rect src(0, 0, 16, 16), dst(0, 0, 16, 16);
screen->fill(bg_color, area.left, area.top, area.width(), area.height());
DisplayChildren(full_redraw);
uint16 tile_num = tile_offset;
for (int i = 0; i < TILES_H; i++) {
for (int j = 0; j < TILES_W; j++) {
dst.left = area.left + 3 + (j * 17);
dst.top = area.top + 16 + (i * 17);
src.left = (tile_num % MAPWINDOW_ROOFTILES_IMG_W) * 16;
src.top = (tile_num / MAPWINDOW_ROOFTILES_IMG_W) * 16;
if (tile_num == selectedTile)
screen->fill(15, dst.left - 1, dst.top - 1, 18, 18);
SDL_BlitSurface(roof_tiles, &src, surface, &dst);
tile_num++;
}
}
screen->update(area.left, area.top, area.width(), area.height());
}
GUI_status MapEditorView::KeyDown(const Common::KeyState &key) {
MapCoord loc;
uint16 *roof_data;
KeyBinder *keybinder = Game::get_game()->get_keybinder();
ActionType a = keybinder->get_ActionType(key);
ActionKeyType action_type = keybinder->GetActionKeyType(a);
// alt input
if (key.flags & Common::KBD_ALT) {
Common::KeyState key_without_alt = key; // need to see what action is without alt
byte mod_without_flags = key_without_alt.flags; // this and next 2 lines are due SDL_Keymod not wanting to do the bitwise ~ operation
mod_without_flags &= ~Common::KBD_ALT;
key_without_alt.flags = mod_without_flags;
ActionType action_without_alt = keybinder->get_ActionType(key_without_alt);
if (keybinder->GetActionKeyType(action_without_alt) <= SOUTH_WEST_KEY)
action_type = keybinder->GetActionKeyType(action_without_alt);
switch (action_type) {
case NORTH_KEY:
if (selectedTile >= TILES_W)
update_selected_tile_relative(-TILES_W);
return GUI_YUM;
case SOUTH_KEY:
update_selected_tile_relative(TILES_W);
return GUI_YUM;
case WEST_KEY:
update_selected_tile_relative(-1);
return GUI_YUM;
case EAST_KEY:
update_selected_tile_relative(1);
return GUI_YUM;
case SOUTH_WEST_KEY:
update_selected_tile_relative(TILES_W);
if (selectedTile % TILES_W) // don't wrap
update_selected_tile_relative(-1);
return GUI_YUM;
case SOUTH_EAST_KEY:
update_selected_tile_relative(TILES_W);
if ((selectedTile + 1) % TILES_W) // don't wrap
update_selected_tile_relative(1);
return GUI_YUM;
case NORTH_WEST_KEY:
if (selectedTile >= TILES_W)
update_selected_tile_relative(-TILES_W);
if (selectedTile % TILES_W) // don't wrap
update_selected_tile_relative(-1);
return GUI_YUM;
case NORTH_EAST_KEY:
if (selectedTile >= TILES_W)
update_selected_tile_relative(-TILES_W);
if ((selectedTile + 1) % TILES_W) // don't wrap
update_selected_tile_relative(1);
return GUI_YUM;
default:
break;
}
} else if (key.flags == 0) {
if (key.keycode == Common::KEYCODE_g) {
toggleGrid();
return GUI_YUM;
} else if (key.keycode == Common::KEYCODE_s) {
Game::get_game()->get_game_map()->saveRoofData();
return GUI_YUM;
}
}
switch (action_type) {
case MSGSCROLL_UP_KEY:
update_selected_tile_relative(-(TILES_W * TILES_H));
break;
case MSGSCROLL_DOWN_KEY:
update_selected_tile_relative(TILES_W * TILES_H);
break;
case SOUTH_WEST_KEY:
map_window->moveMapRelative(-1, 1);
break;
case SOUTH_EAST_KEY:
map_window->moveMapRelative(1, 1);
break;
case NORTH_WEST_KEY:
map_window->moveMapRelative(-1, -1);
break;
case NORTH_EAST_KEY:
map_window->moveMapRelative(1, -1);
break;
case NORTH_KEY:
map_window->moveMapRelative(0, -1);
break;
case SOUTH_KEY:
map_window->moveMapRelative(0, 1);
break;
case WEST_KEY:
map_window->moveMapRelative(-1, 0);
break;
case EAST_KEY:
map_window->moveMapRelative(1, 0);
break;
case DO_ACTION_KEY:
loc = map_window->get_cursorCoord();
roof_data = Game::get_game()->get_game_map()->get_roof_data(loc.z);
if (roof_data) {
roof_data[loc.y * 1024 + loc.x] = selectedTile;
}
break;
case TOGGLE_CURSOR_KEY :
break;
case HOME_KEY:
selectedTile = 0;
tile_offset = 0;
break;
case END_KEY:
selectedTile = MAPWINDOW_ROOFTILES_IMG_W * MAPWINDOW_ROOFTILES_IMG_H - 1;
tile_offset = (TILES_W * TILES_H) * (selectedTile / (TILES_W * TILES_H));
break;
case CANCEL_ACTION_KEY:
//Game::get_game()->get_view_manager()->close_gump(this);
close_view();
GUI::get_gui()->removeWidget((GUI_Widget *)this);
break;
default:
keybinder->handle_always_available_keys(a);
break; // was GUI_PASS pefore action_type change
}
return GUI_YUM;
}
GUI_status MapEditorView::MouseDown(int x, int y, Events::MouseButton button) {
return GUI_YUM;
}
GUI_status MapEditorView::MouseUp(int x, int y, Events::MouseButton button) {
if (button == Events::BUTTON_RIGHT) {
//Game::get_game()->get_view_manager()->close_gump(this);
close_view();
GUI::get_gui()->removeWidget((GUI_Widget *)this);
} else if (HitRect(x, y)) {
x -= area.left;
x -= 3;
y -= area.top;
y -= 16;
selectedTile = tile_offset + (y / 17) * TILES_W + (x / 17);
} else {
int wx, wy;
uint8 level;
map_window->get_level(&level);
map_window->mouseToWorldCoords(x, y, wx, wy);
setTile((uint16)wx, (uint16)wy, level);
}
return GUI_YUM;
}
GUI_status MapEditorView::MouseMotion(int x, int y, uint8 state) {
return GUI_YUM;
}
void MapEditorView::setTile(uint16 x, uint16 y, uint8 level) {
uint16 *roof_data = Game::get_game()->get_game_map()->get_roof_data(level);
if (roof_data) {
roof_data[y * ((level == 0) ? 1024 : 256) + x] = selectedTile;
}
}
void MapEditorView::toggleGrid() {
map_window->set_show_grid(!map_window->is_grid_showing());
}
void MapEditorView::close_view() {
map_window->set_show_cursor(false);
map_window->set_roof_display_mode(ROOF_DISPLAY_NORMAL);
map_window->set_enable_blacking(true);
map_window->set_show_grid(false);
release_focus();
Hide();
}
void MapEditorView::update_selected_tile_relative(sint32 rel_value) {
if ((sint32)selectedTile + rel_value < 0 || (sint32)selectedTile + rel_value >= (MAPWINDOW_ROOFTILES_IMG_W * MAPWINDOW_ROOFTILES_IMG_H))
return;
selectedTile = selectedTile + rel_value;
tile_offset = (TILES_W * TILES_H) * (selectedTile / (TILES_W * TILES_H));
}
GUI_status MapEditorView::callback(uint16 msg, GUI_CallBack *caller, void *data) {
if (caller == up_button) {
update_selected_tile_relative(-(TILES_W * TILES_H));
return GUI_YUM;
} else if (caller == down_button) {
update_selected_tile_relative(TILES_W * TILES_H);
return GUI_YUM;
}
return GUI_PASS;
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,65 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_MAP_EDITOR_VIEW_H
#define NUVIE_VIEWS_MAP_EDITOR_VIEW_H
#include "ultima/nuvie/views/view.h"
namespace Ultima {
namespace Nuvie {
class Configuration;
class GUI_Button;
class MapWindow;
class MapEditorView: public View {
private:
Graphics::ManagedSurface *roof_tiles;
MapWindow *map_window;
uint16 selectedTile;
uint16 tile_offset;
GUI_Button *up_button;
GUI_Button *down_button;
public:
MapEditorView(const Configuration *config);
~MapEditorView() override;
bool init(Screen *tmp_screen, void *view_manager, uint16 x, uint16 y, Font *f, Party *p, TileManager *tm, ObjManager *om);
void Display(bool full_redraw) override;
GUI_status KeyDown(const Common::KeyState &key) override;
GUI_status MouseDown(int x, int y, Events::MouseButton button) override;
GUI_status MouseUp(int x, int y, Events::MouseButton button) override;
GUI_status MouseMotion(int x, int y, uint8 state) override;
void close_view() override;
GUI_status callback(uint16 msg, GUI_CallBack *caller, void *data) override;
protected:
void setTile(uint16 x, uint16 y, uint8 level);
void toggleGrid();
private:
void update_selected_tile_relative(sint32 rel_value);
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,87 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/misc/u6_misc.h"
#include "ultima/nuvie/conf/configuration.h"
#include "ultima/nuvie/core/game_clock.h"
#include "ultima/nuvie/files/u6_shape.h"
#include "ultima/nuvie/core/player.h"
#include "ultima/nuvie/views/md_sky_strip_widget.h"
namespace Ultima {
namespace Nuvie {
MDSkyStripWidget::MDSkyStripWidget(const Configuration *cfg, GameClock *c, Player *p)
: GUI_Widget(nullptr, 0, 0, 0, 0), config(cfg), player(p), _clock(c) {
}
MDSkyStripWidget::~MDSkyStripWidget() {
}
void MDSkyStripWidget::init(sint16 x, sint16 y) {
Common::Path filename;
GUI_Widget::Init(nullptr, x, y, 112, 11);
config_get_path(config, "mdscreen.lzc", filename);
strip1.load_from_lzc(filename, 2, 2);
strip2.load_from_lzc(filename, 2, 3);
}
void MDSkyStripWidget::Display(bool full_redraw) {
if (full_redraw || update_display) {
update_display = false;
uint8 z = player->get_actor() ? player->get_actor()->get_z() : 0;
if (z == 0) {
display_surface();
} else if (z == 1) {
screen->fill(0, area.left, area.top, area.width(), area.height());
} else {
screen->fill(7, area.left, area.top, area.width(), area.height());
}
screen->update(area.left, area.top, area.width(), area.height());
}
}
void MDSkyStripWidget::display_surface() {
uint16 w, h;
strip1.get_size(&w, &h);
uint8 hour = _clock->get_hour();
uint8 minute = _clock->get_minute();
unsigned char *shp_data = hour < 12 ? strip1.get_data() : strip2.get_data();
if (hour >= 12) {
hour -= 12;
}
shp_data += hour * 16 + (minute / 15) * 4;
screen->blit(area.left, area.top, shp_data, 8, area.width(), area.height(), w, false);
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,57 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_MD_SKY_STRIP_WIDGET_H
#define NUVIE_VIEWS_MD_SKY_STRIP_WIDGET_H
#include "ultima/nuvie/gui/widgets/gui_widget.h"
#include "ultima/nuvie/files/u6_shape.h"
namespace Ultima {
namespace Nuvie {
class GameClock;
class Configuration;
class Player;
class MDSkyStripWidget : public GUI_Widget {
protected:
const Configuration *config;
GameClock *_clock;
U6Shape strip1, strip2;
Player *player;
public:
MDSkyStripWidget(const Configuration *cfg, GameClock *c, Player *p);
~MDSkyStripWidget() override;
void init(sint16 x, sint16 y);
void Display(bool full_redraw) override;
private:
void display_surface();
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,388 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/actors/actor.h"
#include "ultima/nuvie/core/party.h"
#include "ultima/nuvie/core/player.h"
#include "ultima/nuvie/core/game_clock.h"
#include "ultima/nuvie/views/party_view.h"
#include "ultima/nuvie/fonts/font.h"
#include "ultima/nuvie/core/weather.h"
#include "ultima/nuvie/script/script.h"
#include "ultima/nuvie/gui/widgets/msg_scroll.h"
#include "ultima/nuvie/core/events.h"
#include "ultima/nuvie/conf/configuration.h"
#include "ultima/nuvie/gui/widgets/command_bar.h"
#include "ultima/nuvie/usecode/usecode.h"
#include "ultima/nuvie/gui/widgets/map_window.h"
#include "ultima/nuvie/views/sun_moon_strip_widget.h"
namespace Ultima {
namespace Nuvie {
extern GUI_status inventoryViewButtonCallback(void *data);
extern GUI_status actorViewButtonCallback(void *data);
#define U6 Game::get_game()->get_game_type()==NUVIE_GAME_U6
#define SE Game::get_game()->get_game_type()==NUVIE_GAME_SE
#define MD Game::get_game()->get_game_type()==NUVIE_GAME_MD
PartyView::PartyView(const Configuration *cfg) : View(cfg), player(nullptr),
view_manager(nullptr), party_view_targeting(false), row_offset(0),
sun_moon_widget(nullptr) {
}
PartyView::~PartyView() {
}
bool PartyView::init(void *vm, uint16 x, uint16 y, Font *f, Party *p, Player *pl, TileManager *tm, ObjManager *om) {
View::init(x, y, f, p, tm, om);
// PartyView is 8px wider than other Views, for the arrows
// ...and 3px taller, for the sky (SB-X)
if (U6)
SetRect(area.left, area.top, area.width() + 8, area.height() + 3);
else
SetRect(area.left, area.top, area.width(), area.height());
view_manager = vm;
player = pl;
if (U6) {
sun_moon_widget = new SunMoonStripWidget(player, tile_manager);
sun_moon_widget->init(area.left, area.top);
AddWidget(sun_moon_widget);
}
config->value("config/input/party_view_targeting", party_view_targeting, false);
return true;
}
GUI_status PartyView::MouseWheel(sint32 x, sint32 y) {
int xpos, ypos;
screen->get_mouse_location(&xpos, &ypos);
xpos -= area.left;
ypos -= area.top;
if (xpos < 0 || ypos > area.top + area.height() - 6)
return GUI_PASS; // goes to MsgScrollw
if (y > 0) {
if (up_arrow())
Redraw();
}
if (y < 0) {
if (down_arrow())
Redraw();
}
return GUI_YUM;
}
GUI_status PartyView::MouseUp(int x, int y, Events::MouseButton button) {
x -= area.left;
y -= area.top;
if (y < 18 && U6) // clicked on skydisplay
return GUI_PASS;
if (y < 4 && MD)
return GUI_PASS;
int rowH = 16;
if (MD)
rowH = 24;
uint8 party_size = party->get_party_size();
if (SE) {
if (party_size > 7) party_size = 7;
} else if (party_size > 5) party_size = 5; // can only display/handle 5 at a time
Common::Rect arrow_rects_U6[2] = { Common::Rect(0, 18, 0 + 8, 18 + 8), Common::Rect(0, 90, 0 + 8, 90 + 8) };
Common::Rect arrow_rects[2] = { Common::Rect(0, 6, 0 + 7, 6 + 8), Common::Rect(0, 102, 0 + 7, 102 + 8) };
Common::Rect arrow_up_rect_MD[1] = { Common::Rect(0, 15, 0 + 7, 15 + 8) };
if (HitRect(x, y, U6 ? arrow_rects_U6[0] : (MD ? arrow_up_rect_MD[0] : arrow_rects[0]))) { //up arrow hit rect
if (up_arrow())
Redraw();
return GUI_YUM;
}
if (HitRect(x, y, U6 ? arrow_rects_U6[1] : arrow_rects[1])) { //down arrow hit rect
if (down_arrow())
Redraw();
return GUI_YUM;
}
int x_offset = 7;
int y_offset = 18;
if (SE) {
x_offset = 6;
y_offset = 2;
} else if (MD)
y_offset = 4;
if (y > party_size * rowH + y_offset - 1) // clicked below actors
return GUI_YUM;
if (x >= x_offset) {
Events *event = Game::get_game()->get_event();
CommandBar *command_bar = Game::get_game()->get_command_bar();
if (button == ACTION_BUTTON && event->get_mode() == MOVE_MODE
&& command_bar->get_selected_action() > 0) { // Exclude attack mode too
if (command_bar->try_selected_action() == false) // start new action
return GUI_PASS; // false if new event doesn't need target
}
if ((party_view_targeting || (button == ACTION_BUTTON
&& command_bar->get_selected_action() > 0)) && event->can_target_icon()) {
x += area.left;
y += area.top;
Actor *actor = get_actor(x, y);
if (actor) {
event->select_actor(actor);
return GUI_YUM;
}
}
set_party_member(((y - y_offset) / rowH) + row_offset);
if (x >= x_offset + 17) { // clicked an actor name
actorViewButtonCallback(view_manager);
} else { // clicked an actor icon
inventoryViewButtonCallback(view_manager);
}
}
return GUI_YUM;
}
Actor *PartyView::get_actor(int x, int y) {
x -= area.left;
y -= area.top;
uint8 party_size = party->get_party_size();
int rowH = 16;
int y_offset = 18;
if (MD) {
rowH = 24;
y_offset = 0;
}
if (SE) {
y_offset = 2;
if (party_size > 7) party_size = 7;
} else if (party_size > 5) party_size = 5; // can only display/handle 5 at a time
if (y > party_size * rowH + y_offset) // clicked below actors
return nullptr;
if (x >= 8) {
return party->get_actor(((y - y_offset) / rowH) + row_offset);
}
return nullptr;
}
bool PartyView::drag_accept_drop(int x, int y, int message, void *data) {
GUI::get_gui()->force_full_redraw();
DEBUG(0, LEVEL_DEBUGGING, "PartyView::drag_accept_drop()\n");
if (message == GUI_DRAG_OBJ) {
MsgScroll *scroll = Game::get_game()->get_scroll();
Obj *obj = (Obj *)data;
Actor *actor = get_actor(x, y);
if (actor) {
Events *event = Game::get_game()->get_event();
event->display_move_text(actor, obj);
if (!obj->is_in_inventory()
&& !Game::get_game()->get_map_window()->can_get_obj(actor, obj)) {
Game::get_game()->get_scroll()->message("\n\nblocked\n\n");
return false;
}
if ((!Game::get_game()->get_usecode()->has_getcode(obj)
|| Game::get_game()->get_usecode()->get_obj(obj, actor))
&& event->can_move_obj_between_actors(obj, player->get_actor(), actor)) {
if (actor == player->get_actor()) // get
player->subtract_movement_points(3);
else // get plus move
player->subtract_movement_points(8);
if (!obj->is_in_inventory() &&
obj_manager->obj_is_damaging(obj, Game::get_game()->get_player()->get_actor()))
return false;
DEBUG(0, LEVEL_DEBUGGING, "Drop Accepted\n");
return true;
}
}
scroll->display_string("\n\n");
scroll->display_prompt();
}
Redraw();
DEBUG(0, LEVEL_DEBUGGING, "Drop Refused\n");
return false;
}
void PartyView::drag_perform_drop(int x, int y, int message, void *data) {
DEBUG(0, LEVEL_DEBUGGING, "InventoryWidget::drag_perform_drop()\n");
Obj *obj;
if (message == GUI_DRAG_OBJ) {
DEBUG(0, LEVEL_DEBUGGING, "Drop into inventory.\n");
obj = (Obj *)data;
Actor *actor = get_actor(x, y);
if (actor) {
obj_manager->moveto_inventory(obj, actor);
}
MsgScroll *scroll = Game::get_game()->get_scroll();
scroll->display_string("\n\n");
scroll->display_prompt();
Redraw();
}
return;
}
void PartyView::Display(bool full_redraw) {
if (full_redraw || update_display || MD || Game::get_game()->is_original_plus_full_map()) {
uint8 party_size = party->get_party_size();
int rowH = 16;
if (MD)
rowH = 24;
update_display = false;
uint8 end_offset = row_offset + 5;
if (MD)
fill_md_background(bg_color, area);
else
screen->fill(bg_color, area.left, area.top, area.width(), area.height());
//if(U6)
// display_sun_moon_strip();
display_arrows();
if (SE)
end_offset = row_offset + 7;
if (end_offset > party_size)
end_offset = party_size;
for (uint8 i = row_offset; i < end_offset; i++) {
Actor *actor = party->get_actor(i);
Tile *actor_tile = tile_manager->get_tile(actor->get_downward_facing_tile_num());
int x_offset = 8;
int y_offset = 18;
uint8 hp_text_color = 0; //standard text color
if (U6)
hp_text_color = 0x48; //standard text color
if (SE) {
x_offset = 6;
y_offset = 1;
}
if (MD) {
x_offset = 8;
y_offset = 6;
GameClock *clock = Game::get_game()->get_clock();
if (clock->get_purple_berry_counter(actor->get_actor_num()) > 0) {
screen->blit(area.left + x_offset + 16, area.top + y_offset + (i - row_offset)*rowH, tile_manager->get_tile(TILE_MD_PURPLE_BERRY_MARKER)->data, 8, 16, 16, 16, true);
}
if (clock->get_green_berry_counter(actor->get_actor_num()) > 0) {
screen->blit(area.left + x_offset + 32, area.top + y_offset + (i - row_offset)*rowH, tile_manager->get_tile(TILE_MD_GREEN_BERRY_MARKER)->data, 8, 16, 16, 16, true);
}
if (clock->get_brown_berry_counter(actor->get_actor_num()) > 0) {
screen->blit(area.left + x_offset + 32, area.top + y_offset + (i - row_offset)*rowH, tile_manager->get_tile(TILE_MD_BROWN_BERRY_MARKER)->data, 8, 16, 16, 16, true);
}
}
screen->blit(area.left + x_offset, area.top + y_offset + (i - row_offset)*rowH, actor_tile->data, 8, 16, 16, 16, true);
const char *actor_name = party->get_actor_name(i);
if (SE) {
x_offset = 4;
y_offset = 0;
}
if (MD)
y_offset = -3;
// FIXME: Martian Dreams text is somewhat center aligned
font->drawString(screen, actor_name, area.left + x_offset + 24, area.top + y_offset + (i - row_offset) * rowH + 8);
char hp_string[4];
Common::sprintf_s(hp_string, "%3d", actor->get_hp());
hp_text_color = actor->get_hp_text_color();
if (SE) {
x_offset = -7;
y_offset = 3;
}
if (MD) {
x_offset = -16;
y_offset = 14;
}
font->drawString(screen, hp_string, strlen(hp_string), area.left + x_offset + 112, area.top + y_offset + (i - row_offset) * rowH, hp_text_color, 0);
}
DisplayChildren(full_redraw);
screen->update(area.left, area.top, area.width(), area.height());
}
return;
}
bool PartyView::up_arrow() {
if (row_offset > 0) {
row_offset--;
return true;
}
return false;
}
bool PartyView::down_arrow() {
if ((row_offset + (SE ? 7 : 5)) < party->get_party_size()) {
row_offset++;
return true;
}
return false;
}
void PartyView::display_arrows() {
int x_offset = 0;
int y_offset = 0;
if (SE || MD) {
x_offset = 2;
y_offset = 12;
}
uint8 max_party_size = 5;
uint8 party_size = party->get_party_size();
if (SE)
max_party_size = 7;
if (party_size <= max_party_size) // reset
row_offset = 0;
if ((party_size - row_offset) > max_party_size) // display bottom arrow
font->drawChar(screen, 25, area.left - x_offset, area.top + 90 + y_offset);
if (MD)
y_offset = 3;
if (row_offset > 0) // display top arrow
font->drawChar(screen, 24, area.left - x_offset, area.top + 18 - y_offset);
}
// </SB-X>
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,87 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_PARTY_VIEW_H
#define NUVIE_VIEWS_PARTY_VIEW_H
#include "ultima/nuvie/views/view.h"
namespace Ultima {
namespace Nuvie {
class Configuration;
class TileManager;
class ObjManager;
class Screen;
class Font;
class Party;
class Player;
class Actor;
class SunMoonStripWidget;
class PartyView : public View {
Player *player;
void *view_manager;
uint16 row_offset; // first party member displayed
SunMoonStripWidget *sun_moon_widget;
public:
PartyView(const Configuration *cfg);
~PartyView() override;
bool init(void *vm, uint16 x, uint16 y, Font *f, Party *p, Player *pl, TileManager *tm, ObjManager *om);
GUI_status MouseUp(int x, int y, Events::MouseButton button) override;
GUI_status MouseDown(int x, int y, Events::MouseButton button) override {
return GUI_YUM;
}
GUI_status MouseWheel(sint32 x, sint32 y) override;
bool drag_accept_drop(int x, int y, int message, void *data) override;
void drag_perform_drop(int x, int y, int message, void *data) override;
void Display(bool full_redraw) override;
void update() {
update_display = true;
}
void display_sun_moon_strip();
void set_party_view_targeting(bool val) {
party_view_targeting = val;
}
protected:
void display_surface_strip();
void display_dungeon_strip();
void display_arrows();
void display_sun_moon(Tile *tile, uint8 pos);
void display_sun(uint8 hour, uint8 minute, bool eclipse);
void display_moons(uint8 day, uint8 hour, uint8 minute = 0);
bool up_arrow();
bool down_arrow();
bool party_view_targeting;
Actor *get_actor(int x, int y);
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,245 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/shared/std/string.h"
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/conf/configuration.h"
#include "ultima/nuvie/misc/u6_misc.h"
#include "ultima/nuvie/files/u6_lib_n.h"
#include "ultima/nuvie/files/u6_shape.h"
#include "ultima/nuvie/core/game.h"
#include "ultima/nuvie/actors/actor.h"
#include "ultima/nuvie/portraits/portrait.h"
#include "ultima/nuvie/fonts/font.h"
#include "ultima/nuvie/views/view_manager.h"
#include "ultima/nuvie/gui/widgets/msg_scroll.h"
#include "ultima/nuvie/gui/gui.h"
#include "ultima/nuvie/views/doll_widget.h"
#include "ultima/nuvie/views/portrait_view.h"
#include "ultima/nuvie/views/sun_moon_strip_widget.h"
namespace Ultima {
namespace Nuvie {
PortraitView::PortraitView(const Configuration *cfg) : View(cfg),
portrait_data(nullptr), portrait(nullptr), bg_data(nullptr),
name_string(new string), show_cursor(false), doll_widget(nullptr),
waiting(false), display_doll(false), cur_actor_num(0) {
gametype = get_game_type(cfg);
//FIXME: Portraits in SE/MD are different size than in U6! 79x85 76x83
switch (gametype) {
case NUVIE_GAME_U6:
portrait_width = 56;
portrait_height = 64;
break;
case NUVIE_GAME_SE:
portrait_width = 79;
portrait_height = 85;
break;
case NUVIE_GAME_MD:
portrait_width = 76;
portrait_height = 83;
break;
default:
error("Unsupported game type in PortraitView");
}
}
PortraitView::~PortraitView() {
if (portrait_data != nullptr)
free(portrait_data);
if (bg_data != nullptr)
delete bg_data;
delete name_string;
}
bool PortraitView::init(uint16 x, uint16 y, Font *f, Party *p, Player *player, TileManager *tm, ObjManager *om, Portrait *port) {
View::init(x, y, f, p, tm, om);
portrait = port;
doll_widget = new DollWidget(config, this);
doll_widget->init(nullptr, 0, 16, tile_manager, obj_manager, true);
AddWidget(doll_widget);
doll_widget->Hide();
if (gametype == NUVIE_GAME_U6) {
SunMoonStripWidget *sun_moon_widget = new SunMoonStripWidget(player, tile_manager);
sun_moon_widget->init(-8, -2);
AddWidget(sun_moon_widget);
} else if (gametype == NUVIE_GAME_MD) {
load_background("mdscreen.lzc", 1);
} else if (gametype == NUVIE_GAME_SE) {
load_background("bkgrnd.lzc", 0);
}
return true;
}
void PortraitView::load_background(const char *f, uint8 lib_offset) {
U6Lib_n file;
bg_data = new U6Shape();
Common::Path path;
config_get_path(config, f, path);
file.open(path, 4, gametype);
unsigned char *temp_buf = file.get_item(lib_offset);
bg_data->load(temp_buf + 8);
free(temp_buf);
}
void PortraitView::Display(bool full_redraw) {
if (Game::get_game()->is_new_style() || Game::get_game()->is_original_plus_full_map())
screen->fill(bg_color, area.left, area.top, area.width(), area.height());
if (portrait_data != nullptr/* && (full_redraw || update_display)*/) {
update_display = false;
if (gametype == NUVIE_GAME_U6) {
if (display_doll)
screen->blit(area.left + 72, area.top + 16, portrait_data, 8, portrait_width, portrait_height, portrait_width, false);
else
screen->blit(area.left + (area.width() - portrait_width) / 2, area.top + (area.height() - portrait_height) / 2, portrait_data, 8, portrait_width, portrait_height, portrait_width, true);
display_name(80);
} else if (gametype == NUVIE_GAME_MD) {
uint16 w, h;
bg_data->get_size(&w, &h);
screen->blit(area.left, area.top - 2, bg_data->get_data(), 8, w, h, w, true);
screen->blit(area.left + (area.width() - portrait_width) / 2, area.top + 6, portrait_data, 8, portrait_width, portrait_height, portrait_width, true);
display_name(100);
} else if (gametype == NUVIE_GAME_SE) {
uint16 w, h;
bg_data->get_size(&w, &h);
screen->blit(area.left, area.top, bg_data->get_data(), 8, w, h, w, true);
screen->blit(area.left + (area.width() - portrait_width) / 2 + 1, area.top + 1, portrait_data, 8, portrait_width, portrait_height, portrait_width, true);
display_name(98);
}
}
if (show_cursor && gametype == NUVIE_GAME_U6) { // FIXME: should we be using scroll's drawCursor?
screen->fill(bg_color, area.left, area.top + area.height() - 8, 8, 8);
Game::get_game()->get_scroll()->drawCursor(area.left, area.top + area.height() - 8);
}
DisplayChildren(full_redraw);
screen->update(area.left, area.top, area.width(), area.height());
}
bool PortraitView::set_portrait(Actor *actor, const char *name) {
if (Game::get_game()->is_new_style())
this->Show();
cur_actor_num = actor->get_actor_num();
int doll_x_offset = 0;
if (portrait_data != nullptr)
free(portrait_data);
portrait_data = portrait->get_portrait_data(actor);
if (gametype == NUVIE_GAME_U6 && actor->has_readied_objects()) {
if (portrait_data == nullptr)
doll_x_offset = 34;
doll_widget->MoveRelativeToParent(doll_x_offset, 16);
display_doll = true;
doll_widget->Show();
doll_widget->set_actor(actor);
} else {
display_doll = false;
doll_widget->Hide();
doll_widget->set_actor(nullptr);
if (portrait_data == nullptr)
return false;
}
if (name == nullptr)
name = actor->get_name();
if (name == nullptr)
name_string->assign(""); // just in case
else
name_string->assign(name);
if (screen)
screen->fill(bg_color, area.left, area.top, area.width(), area.height());
Redraw();
return true;
}
void PortraitView::display_name(uint16 y_offset) {
const char *name;
name = name_string->c_str();
font->drawString(screen, name, area.left + (area.width() - strlen(name) * 8) / 2, area.top + y_offset);
return;
}
/* On any input return to previous status view if waiting.
* Returns true if event was used.
*/
GUI_status PortraitView::HandleEvent(const Common::Event *event) {
if (waiting && (
event->type == Common::EVENT_LBUTTONDOWN
|| event->type == Common::EVENT_RBUTTONDOWN
|| event->type == Common::EVENT_MBUTTONDOWN
|| event->type == Common::EVENT_KEYDOWN)
) {
if (Game::get_game()->is_new_style())
this->Hide();
else // FIXME revert to previous status view
Game::get_game()->get_view_manager()->set_inventory_mode();
// Game::get_game()->get_scroll()->set_input_mode(false);
Game::get_game()->get_scroll()->message("\n");
set_waiting(false);
return GUI_YUM;
}
return GUI_PASS;
}
/* Start/stop waiting for input to continue, and (for now) steal cursor from
* MsgScroll.
*/
void PortraitView::set_waiting(bool state) {
if (state == true && display_doll == false && portrait_data == nullptr) { // don't wait for nothing
if (Game::get_game()->is_new_style())
this->Hide();
return;
}
waiting = state;
set_show_cursor(waiting);
Game::get_game()->get_scroll()->set_show_cursor(!waiting);
Game::get_game()->get_gui()->lock_input(waiting ? this : nullptr);
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,91 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_PORTRAIT_VIEW_H
#define NUVIE_VIEWS_PORTRAIT_VIEW_H
#include "ultima/nuvie/views/view.h"
namespace Ultima {
namespace Nuvie {
class Configuration;
class TileManager;
class Portrait;
class Screen;
class Font;
class ObjManager;
class Party;
class Player;
class Actor;
class DollWidget;
class U6Shape;
class PortraitView : public View {
nuvie_game_t gametype;
uint8 cur_actor_num;
Portrait *portrait;
Std::string *name_string;
unsigned char *portrait_data;
U6Shape *bg_data;
uint8 portrait_width;
uint8 portrait_height;
bool waiting; // waiting for input, then will return to previous view
bool show_cursor; // indicate waiting for input
// uint16 cursor_x, cursor_y;
DollWidget *doll_widget;
bool display_doll;
public:
PortraitView(const Configuration *cfg);
~PortraitView() override;
bool init(uint16 x, uint16 y, Font *f, Party *p, Player *player, TileManager *tm, ObjManager *om, Portrait *port);
void Display(bool full_redraw) override;
GUI_status HandleEvent(const Common::Event *event) override;
bool set_portrait(Actor *actor, const char *name);
void set_show_cursor(bool state) {
show_cursor = state;
}
void set_waiting(bool state);
bool get_waiting() const {
return waiting;
}
protected:
void display_name(uint16 y_offset);
private:
void load_background(const char *filename, uint8 lib_offset);
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,293 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/misc/u6_misc.h"
#include "ultima/nuvie/core/events.h"
#include "ultima/nuvie/gui/gui.h"
#include "ultima/nuvie/gui/gui_button.h"
#include "ultima/nuvie/core/party.h"
#include "ultima/nuvie/actors/actor.h"
#include "ultima/nuvie/portraits/portrait.h"
#include "ultima/nuvie/views/view_manager.h"
#include "ultima/nuvie/views/container_widget_gump.h"
#include "ultima/nuvie/views/portrait_view_gump.h"
#include "ultima/nuvie/keybinding/keys.h"
namespace Ultima {
namespace Nuvie {
PortraitViewGump::PortraitViewGump(const Configuration *cfg) : DraggableView(cfg),
portrait(nullptr), font(nullptr), gump_button(nullptr), portrait_data(nullptr),
actor(nullptr), cursor_tile(nullptr), show_cursor(true),
cursor_pos(CURSOR_CHECK), cursor_xoff(1), cursor_yoff(67) {
}
PortraitViewGump::~PortraitViewGump() {
if (font)
delete font;
if (portrait_data)
free(portrait_data);
}
bool PortraitViewGump::init(Screen *tmp_screen, void *view_manager, uint16 x, uint16 y, Font *f, Party *p, TileManager *tm, ObjManager *om, Portrait *por, Actor *a) {
View::init(x, y, f, p, tm, om);
SetRect(area.left, area.top, 188, 91);
portrait = por;
set_actor(a);
Common::Path datadir = GUI::get_gui()->get_data_dir();
Common::Path imagefile;
Common::Path path;
build_path(datadir, "images", path);
datadir = path;
build_path(datadir, "gumps", path);
datadir = path;
gump_button = loadButton(datadir, "gump", 0, 67);
build_path(datadir, "portrait_bg.bmp", imagefile);
bg_image = SDL_LoadBMP(imagefile);
set_bg_color_key(0, 0x70, 0xfc);
font = new GUI_Font(GUI_FONT_GUMP);
font->setColoring(0x08, 0x08, 0x08, 0x80, 0x58, 0x30, 0x00, 0x00, 0x00);
Graphics::ManagedSurface *image, *image1;
build_path(datadir, "left_arrow.bmp", imagefile);
image = SDL_LoadBMP(imagefile);
image1 = SDL_LoadBMP(imagefile);
left_button = new GUI_Button(this, 23, 6, image, image1, this);
this->AddWidget(left_button);
build_path(datadir, "right_arrow.bmp", imagefile);
image = SDL_LoadBMP(imagefile);
image1 = SDL_LoadBMP(imagefile);
right_button = new GUI_Button(this, 166, 6, image, image1, this);
this->AddWidget(right_button);
if (party->get_member_num(actor) < 0) {
left_button->Hide();
right_button->Hide();
}
cursor_tile = tile_manager->get_gump_cursor_tile();
return true;
}
void PortraitViewGump::set_actor(Actor *a) {
actor = a;
if (portrait_data)
free(portrait_data);
portrait_data = portrait->get_portrait_data(actor);
}
void PortraitViewGump::left_arrow() {
if (party->get_member_num(actor) < 0)
return;
uint8 party_mem_num = party->get_member_num(actor);
if (party_mem_num > 0)
party_mem_num--;
else
party_mem_num = party->get_party_size() - 1;
set_actor(party->get_actor(party_mem_num));
}
void PortraitViewGump::right_arrow() {
if (party->get_member_num(actor) < 0)
return;
set_actor(party->get_actor((party->get_member_num(actor) + 1) % party->get_party_size()));
}
void PortraitViewGump::Display(bool full_redraw) {
Common::String buf; //xxxxx\n
//display_level_text();
//display_spell_list_text();
Common::Rect dst;
dst = area;
SDL_BlitSurface(bg_image, nullptr, surface, &dst);
DisplayChildren(full_redraw);
screen->blit(area.left + 25, area.top + 17, portrait_data, 8, portrait->get_portrait_width(), portrait->get_portrait_height(), portrait->get_portrait_width(), false);
int w, h;
w = font->getCenter(actor->get_name(), 138);
font->setColoring(0x08, 0x08, 0x08, 0x80, 0x58, 0x30, 0x00, 0x00, 0x00);
font->textOut(screen->get_sdl_surface(), area.left + 29 + w, area.top + 6, actor->get_name());
buf = Common::String::format("%d", actor->get_strength());
font->textExtent(buf.c_str(), &w, &h);
font->textOut(screen->get_sdl_surface(), area.left + 170 - w, area.top + 18, buf.c_str());
buf = Common::String::format("%d", actor->get_dexterity());
font->textExtent(buf.c_str(), &w, &h);
font->textOut(screen->get_sdl_surface(), area.left + 170 - w, area.top + 27, buf.c_str());
buf = Common::String::format("%d", actor->get_intelligence());
font->textExtent(buf.c_str(), &w, &h);
font->textOut(screen->get_sdl_surface(), area.left + 170 - w, area.top + 36, buf.c_str());
font->setColoring(0x6c, 0x00, 0x00, 0xbc, 0x34, 0x00, 0x00, 0x00, 0x00);
buf = Common::String::format("%d", actor->get_magic());
font->textExtent(buf.c_str(), &w, &h);
font->textOut(screen->get_sdl_surface(), area.left + 142 - w, area.top + 55, buf.c_str());
buf = Common::String::format("%d", actor->get_maxmagic());
font->textExtent(buf.c_str(), &w, &h);
font->textOut(screen->get_sdl_surface(), area.left + 170 - w, area.top + 55, buf.c_str());
font->setColoring(0x00, 0x3c, 0x70, 0x74, 0x74, 0x74, 0x00, 0x00, 0x00);
buf = Common::String::format("%d", actor->get_hp());
font->textExtent(buf.c_str(), &w, &h);
font->textOut(screen->get_sdl_surface(), area.left + 142 - w, area.top + 64, buf.c_str());
buf = Common::String::format("%d", actor->get_maxhp());
font->textExtent(buf.c_str(), &w, &h);
font->textOut(screen->get_sdl_surface(), area.left + 170 - w, area.top + 64, buf.c_str());
font->setColoring(0xa8, 0x28, 0x00, 0xa8, 0x54, 0x00, 0x00, 0x00, 0x00);
buf = Common::String::format("%d", actor->get_level());
font->textExtent(buf.c_str(), &w, &h);
font->textOut(screen->get_sdl_surface(), area.left + 142 - w, area.top + 73, buf.c_str());
buf = Common::String::format("%d", actor->get_exp());
font->textExtent(buf.c_str(), &w, &h);
font->textOut(screen->get_sdl_surface(), area.left + 170 - w, area.top + 73, buf.c_str());
if (show_cursor) {
screen->blit(area.left + cursor_xoff, area.top + cursor_yoff, (const unsigned char *)cursor_tile->data, 8, 16, 16, 16, true);
}
update_display = false;
screen->update(area.left, area.top, area.width(), area.height());
}
GUI_status PortraitViewGump::set_cursor_pos(gumpCursorPos pos) {
if (party->get_member_num(actor) < 0)
return GUI_YUM;
cursor_pos = pos;
if (cursor_pos == CURSOR_CHECK) {
cursor_xoff = 1;
cursor_yoff = 67;
} else if (cursor_pos == CURSOR_LEFT) {
cursor_xoff = 18;
cursor_yoff = 1;
} else {
cursor_xoff = 162;
cursor_yoff = 1;
}
return GUI_YUM;
}
GUI_status PortraitViewGump::callback(uint16 msg, GUI_CallBack *caller, void *data) {
//close gump and return control to Magic class for clean up.
if (caller == gump_button) {
Game::get_game()->get_view_manager()->close_gump(this);
return GUI_YUM;
} else if (caller == left_button) {
left_arrow();
} else if (caller == right_button) {
right_arrow();
}
return GUI_PASS;
}
GUI_status PortraitViewGump::KeyDown(const Common::KeyState &key) {
// I was checking for numlock but probably don't need to
KeyBinder *keybinder = Game::get_game()->get_keybinder();
ActionType a = keybinder->get_ActionType(key);
switch (keybinder->GetActionKeyType(a)) {
case SOUTH_WEST_KEY:
case SOUTH_KEY:
return set_cursor_pos(CURSOR_CHECK);
case NORTH_KEY:
if (cursor_pos == CURSOR_CHECK)
return set_cursor_pos(CURSOR_LEFT);
return GUI_YUM;
case NORTH_WEST_KEY:
case WEST_KEY:
if (cursor_pos == CURSOR_RIGHT)
return set_cursor_pos(CURSOR_LEFT);
return set_cursor_pos(CURSOR_CHECK);
case NORTH_EAST_KEY:
case SOUTH_EAST_KEY:
case EAST_KEY:
if (cursor_pos == CURSOR_CHECK)
return set_cursor_pos(CURSOR_LEFT);
return set_cursor_pos(CURSOR_RIGHT);
case DO_ACTION_KEY:
if (cursor_pos == CURSOR_CHECK)
Game::get_game()->get_view_manager()->close_gump(this);
else if (cursor_pos == CURSOR_LEFT)
left_arrow();
else
right_arrow();
return GUI_YUM;
case NEXT_PARTY_MEMBER_KEY:
right_arrow();
return GUI_YUM;
case PREVIOUS_PARTY_MEMBER_KEY:
left_arrow();
return GUI_YUM;
case HOME_KEY:
if (party->get_member_num(actor) >= 0)
set_actor(party->get_actor(0));
return GUI_YUM;
case END_KEY:
if (party->get_member_num(actor) >= 0)
set_actor(party->get_actor(party->get_party_size() - 1));
return GUI_YUM;
default:
break;
}
return GUI_PASS;
}
GUI_status PortraitViewGump::MouseWheel(sint32 x, sint32 y) {
if (y > 0) {
left_arrow();
} else if (y < 0) {
right_arrow();
}
return GUI_YUM;
}
GUI_status PortraitViewGump::MouseDown(int x, int y, Events::MouseButton button) {
return DraggableView::MouseDown(x, y, button);
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,78 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_PORTRAIT_VIEW_GUMP_H
#define NUVIE_VIEWS_PORTRAIT_VIEW_GUMP_H
#include "ultima/nuvie/views/draggable_view.h"
namespace Ultima {
namespace Nuvie {
class Configuration;
class TileManager;
class ObjManager;
class Screen;
class Actor;
class Font;
class U6Bmp;
class Portrait;
class PortraitViewGump : public DraggableView {
GUI_Button *gump_button;
GUI_Font *font;
Portrait *portrait;
unsigned char *portrait_data;
Actor *actor;
bool show_cursor;
const Tile *cursor_tile;
gumpCursorPos cursor_pos;
uint8 cursor_xoff, cursor_yoff;
public:
PortraitViewGump(const Configuration *cfg);
~PortraitViewGump() override;
bool init(Screen *tmp_screen, void *view_manager, uint16 x, uint16 y, Font *f, Party *p, TileManager *tm, ObjManager *om, Portrait *por, Actor *a);
void Display(bool full_redraw) override;
GUI_status callback(uint16 msg, GUI_CallBack *caller, void *data) override;
GUI_status MouseDown(int x, int y, Events::MouseButton button) override;
GUI_status MouseWheel(sint32 x, sint32 y) override;
protected:
void set_actor(Actor *a);
void left_arrow();
void right_arrow();
GUI_status KeyDown(const Common::KeyState &key) override;
GUI_status set_cursor_pos(gumpCursorPos pos);
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,121 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/misc/u6_misc.h"
#include "ultima/nuvie/core/events.h"
#include "ultima/nuvie/gui/gui.h"
#include "ultima/nuvie/fonts/font_manager.h"
#include "ultima/nuvie/views/view_manager.h"
#include "ultima/nuvie/views/scroll_widget_gump.h"
#include "ultima/nuvie/views/scroll_view_gump.h"
namespace Ultima {
namespace Nuvie {
static const int SIGN_BG_W = (SCROLLWIDGETGUMP_W + 16);
static const int SIGN_BG_H = (SCROLLWIDGETGUMP_H + 16);
ScrollViewGump::ScrollViewGump(const Configuration *cfg) : DraggableView(cfg), scroll_widget(nullptr) {
}
ScrollViewGump::~ScrollViewGump() {
}
bool ScrollViewGump::init(Screen *tmp_screen, void *view_manager, Font *f, Party *p, TileManager *tm, ObjManager *om, Std::string text_string) {
uint16 x_off = Game::get_game()->get_game_x_offset();
uint16 y_off = Game::get_game()->get_game_y_offset();
x_off += (Game::get_game()->get_game_width() - SIGN_BG_W) / 2;
y_off += (Game::get_game()->get_game_height() - SIGN_BG_H) / 2;
View::init(x_off, y_off, f, p, tm, om);
SetRect(area.left, area.top, SIGN_BG_W, SIGN_BG_H);
/*
Std::string datadir = GUI::get_gui()->get_data_dir();
Std::string imagefile;
Std::string path;
build_path(datadir, "images", path);
datadir = path;
build_path(datadir, "gumps", path);
datadir = path;
build_path(datadir, "sign", path);
datadir = path;
build_path(datadir, "sign_bg.bmp", imagefile);
bg_image = SDL_LoadBMP(imagefile.c_str());
set_bg_color_key(0, 0x70, 0xfc);
*/
scroll_widget = new ScrollWidgetGump(config, tmp_screen);
scroll_widget->init(config, Game::get_game()->get_font_manager()->get_conv_font());
scroll_widget->display_string(text_string);
AddWidget(scroll_widget);
return true;
}
void ScrollViewGump::Display(bool full_redraw) {
/*
Common::Rect dst;
dst = area;
SDL_BlitSurface(bg_image, nullptr, surface, &dst);
*/
screen->fill(26, area.left, area.top, area.width(), area.height());
DisplayChildren(full_redraw);
//font->textOut(screen->get_sdl_surface(), area.left + 29, area.top + 6, "This is a test sign");
//font->drawString(screen, sign_text, strlen(sign_text), area.left + (area.width() - font->getStringWidth(sign_text)) / 2, area.top + (area.height() - 19) / 2, 0, 0);
update_display = false;
screen->update(area.left, area.top, area.width(), area.height());
return;
}
GUI_status ScrollViewGump::MouseDown(int x, int y, Events::MouseButton button) {
if (scroll_widget->MouseDown(x, y, button) != GUI_YUM) {
Game::get_game()->get_view_manager()->close_gump(this);
}
return GUI_YUM;
}
GUI_status ScrollViewGump::KeyDown(const Common::KeyState &key) {
if (scroll_widget->KeyDown(key) != GUI_YUM) {
Game::get_game()->get_view_manager()->close_gump(this);
}
return GUI_YUM;
}
GUI_status ScrollViewGump::callback(uint16 msg, GUI_CallBack *caller, void *data) {
Game::get_game()->get_view_manager()->close_gump(this);
return GUI_YUM;
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,60 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_SCROLL_VIEW_GUMP_H
#define NUVIE_VIEWS_SCROLL_VIEW_GUMP_H
#include "ultima/nuvie/views/draggable_view.h"
namespace Ultima {
namespace Nuvie {
class Configuration;
class TileManager;
class ObjManager;
class Screen;
class ScrollWidgetGump;
class ScrollViewGump : public DraggableView {
ScrollWidgetGump *scroll_widget;
public:
ScrollViewGump(const Configuration *cfg);
~ScrollViewGump() override;
bool init(Screen *tmp_screen, void *view_manager, Font *f, Party *p, TileManager *tm, ObjManager *om, Std::string text_string);
void Display(bool full_redraw) override;
GUI_status callback(uint16 msg, GUI_CallBack *caller, void *data) override;
GUI_status MouseDown(int x, int y, Events::MouseButton button) override;
GUI_status MouseUp(int x, int y, Events::MouseButton button) override {
return GUI_YUM;
}
GUI_status KeyDown(const Common::KeyState &key) override;
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,307 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/shared/std/string.h"
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/conf/configuration.h"
#include "ultima/nuvie/misc/u6_misc.h"
#include "ultima/nuvie/fonts/font_manager.h"
#include "ultima/nuvie/fonts/font.h"
#include "ultima/nuvie/screen/game_palette.h"
#include "ultima/nuvie/gui/gui.h"
#include "ultima/nuvie/gui/widgets/msg_scroll.h"
#include "ultima/nuvie/portraits/portrait.h"
#include "ultima/nuvie/core/player.h"
#include "ultima/nuvie/fonts/conv_font.h"
#include "ultima/nuvie/views/scroll_widget_gump.h"
#include "ultima/nuvie/actors/actor_manager.h"
#include "ultima/nuvie/core/timed_event.h"
#include "ultima/nuvie/keybinding/keys.h"
namespace Ultima {
namespace Nuvie {
// ScrollWidgetGump Class
ScrollWidgetGump::ScrollWidgetGump(const Configuration *cfg, Screen *s) :
arrow_up_rect(SCROLLWIDGETGUMP_W - 8 - 1, 4 + 1,
SCROLLWIDGETGUMP_W - 8 - 1 + 7, 4 + 1 + 5),
arrow_down_rect(SCROLLWIDGETGUMP_W - 8 - 1, SCROLLWIDGETGUMP_H - 8 + 3,
SCROLLWIDGETGUMP_W - 8 - 1 + 7, SCROLLWIDGETGUMP_H - 8 + 3 + 5) {
drop_target = false; //we don't participate in drag and drop.
font_normal = Game::get_game()->get_font_manager()->get_conv_font();
font_garg = Game::get_game()->get_font_manager()->get_conv_garg_font();
init(cfg, font_normal);
font_color = 0; // black
font_highlight = FONT_COLOR_U6_HIGHLIGHT;
scroll_width = 40;
scroll_height = 10;
show_up_arrow = false;
show_down_arrow = false;
GUI_Widget::Init(nullptr, 0, 0, SCROLLWIDGETGUMP_W, SCROLLWIDGETGUMP_H);
add_new_line(); //MsgScroll requires a line to start.
position = 0;
// ignore_page_breaks = true;
}
ScrollWidgetGump::~ScrollWidgetGump() {
// ignore_page_breaks = false;
}
void ScrollWidgetGump::set_font(uint8 font_type) {
if (font_type == NUVIE_FONT_NORMAL) {
font = font_normal;
} else {
font = font_garg;
}
}
bool ScrollWidgetGump::is_garg_font() {
return (font == font_garg);
}
bool ScrollWidgetGump::can_fit_token_on_msgline(MsgLine *msg_line, MsgText *token) {
if (msg_line->get_display_width() + token->getDisplayWidth() > SCROLLWIDGETGUMP_W - 8 - 8) {
return false; //token doesn't fit on the current line.
}
return true;
}
bool ScrollWidgetGump::parse_token(MsgText *token) {
if (token->s[0] == '*') // We don't want page breaks in the scroll widget.
return true;
return MsgScroll::parse_token(token);
}
void ScrollWidgetGump::display_string(const Std::string &s) {
MsgScroll::display_string(s);
update_arrows();
}
void ScrollWidgetGump::Display(bool full_redraw) {
MsgText *token;
uint16 y = area.top + 4;
Std::list<MsgLine *>::iterator iter;
if (show_up_arrow) {
font_normal->drawChar(screen, FONT_UP_ARROW_CHAR, area.left + SCROLLWIDGETGUMP_W - 8, area.top + 4);
}
if (show_down_arrow) {
font_normal->drawChar(screen, FONT_DOWN_ARROW_CHAR, area.left + SCROLLWIDGETGUMP_W - 8, area.top + SCROLLWIDGETGUMP_H - 8);
}
iter = msg_buf.begin();
for (uint16 i = 0; i < position && iter != msg_buf.end(); i++)
iter++;
for (uint16 i = 0; i < scroll_height && iter != msg_buf.end(); i++, iter++) {
MsgLine *msg_line = *iter;
Std::list<MsgText *>::iterator iter1;
iter1 = msg_line->text.begin();
//if not last record or if last record is not an empty line.
if (i + position < ((int)msg_buf.size() - 1) || (iter1 != msg_line->text.end() && ((*iter)->total_length != 0))) {
//screen->fill(26, area.left, y + (i==0?-4:4), scroll_width * 7 + 8, (i==0?18:10));
for (uint16 total_length = 0; iter1 != msg_line->text.end() ; iter1++) {
token = *iter1;
total_length += token->font->drawString(screen, token->s.c_str(), area.left + 4 + 4 + total_length, y + 4, font_color, font_highlight); //FIX for hardcoded font height
}
y += 10;
}
}
screen->update(area.left, area.top, area.width(), area.height());
}
GUI_status ScrollWidgetGump::KeyDown(const Common::KeyState &key) {
ScrollEventType event = SCROLL_ESCAPE;
KeyBinder *keybinder = Game::get_game()->get_keybinder();
ActionType a = keybinder->get_ActionType(key);
switch (keybinder->GetActionKeyType(a)) {
case MSGSCROLL_DOWN_KEY:
event = SCROLL_PAGE_DOWN;
break;
case SOUTH_KEY:
event = SCROLL_DOWN;
break;
case MSGSCROLL_UP_KEY:
event = SCROLL_PAGE_UP;
break;
case NORTH_KEY:
event = SCROLL_UP;
break;
case HOME_KEY:
event = SCROLL_TO_BEGINNING;
break;
case END_KEY:
event = SCROLL_TO_END;
break;
default :
break;
}
if (scroll_movement_event(event) == GUI_YUM)
return GUI_YUM;
return MsgScroll::KeyDown(key);
}
GUI_status ScrollWidgetGump::MouseWheel(sint32 x, sint32 y) {
ScrollEventType event = SCROLL_ESCAPE;
if (y > 0)
event = SCROLL_UP;
if (y < 0)
event = SCROLL_DOWN;
return scroll_movement_event(event);
}
GUI_status ScrollWidgetGump::MouseDown(int x, int y, Events::MouseButton button) {
ScrollEventType event = SCROLL_ESCAPE;
switch (button) {
case Events::BUTTON_LEFT : {
x -= area.left;
y -= area.top;
if (HitRect(x, y, arrow_up_rect))
event = SCROLL_UP;
else if (HitRect(x, y, arrow_down_rect))
event = SCROLL_DOWN;
// FIXME - uncomment when we get a checkmark
// else if(show_down_arrow || show_up_arrow) // don't close if scrollable
// return GUI_YUM;
break;
}
default :
break;
}
return scroll_movement_event(event);
}
GUI_status ScrollWidgetGump::scroll_movement_event(ScrollEventType event) {
switch (event) {
case SCROLL_UP :
if (position > 0) {
//timer = new TimedCallback(this, nullptr, 2000);
position--;
update_arrows();
//grab_focus();
}
return GUI_YUM;
case SCROLL_DOWN :
//timer = new TimedCallback(this, nullptr, 2000);
if (page_break && position + scroll_height >= (int)msg_buf.size()) {
if (position + scroll_height == (int)msg_buf.size()) // break was just off the page so advance text
position++;
process_page_break();
update_arrows();
} else if (position + scroll_height < (int)msg_buf.size()) {
position++;
update_arrows();
}
return GUI_YUM;
case SCROLL_PAGE_UP:
if (position > 0) {
position = position > scroll_height ? position - scroll_height : 0;
update_arrows();
}
return GUI_YUM;
case SCROLL_PAGE_DOWN:
if (position + scroll_height < (int)msg_buf.size() || page_break) {
if (position + scroll_height >= (int)msg_buf.size())
position = (int)msg_buf.size();
else {
position += scroll_height;
update_arrows();
return GUI_YUM;
}
if (page_break) { // we didn't have enough text showing to fill out the current page.
position = msg_buf.size();
process_page_break();
}
update_arrows();
}
return GUI_YUM;
case SCROLL_TO_BEGINNING :
if (position > 0) {
position = 0;
update_arrows();
}
return GUI_YUM;
case SCROLL_TO_END :
if (position + scroll_height < (int)msg_buf.size() || page_break) {
while (position + scroll_height < (int)msg_buf.size() || page_break) {
if (page_break)
process_page_break();
else // added else just in case noting is added to the buffer
position++;
}
update_arrows();
}
return GUI_YUM;
default :
//release_focus();
//new TimedCallback(this, nullptr, 50);
break;
}
return GUI_PASS;
}
void ScrollWidgetGump::update_arrows() {
if (position == 0) {
show_up_arrow = false;
} else {
show_up_arrow = true;
}
if (position + scroll_height < (int)msg_buf.size() || page_break) {
show_down_arrow = true;
} else {
show_down_arrow = false;
}
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,119 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_SCROLL_WIDGET_GUMP_H
#define NUVIE_VIEWS_SCROLL_WIDGET_GUMP_H
#include "ultima/nuvie/misc/call_back.h"
#include "ultima/nuvie/gui/widgets/gui_widget.h"
#include "ultima/nuvie/gui/widgets/msg_scroll.h"
#include "ultima/nuvie/fonts/font.h"
#include "ultima/shared/std/containers.h"
#include "ultima/shared/std/string.h"
namespace Ultima {
namespace Nuvie {
using Std::list;
class Configuration;
class Actor;
class CallBack;
typedef enum {
SCROLL_UP,
SCROLL_DOWN,
SCROLL_PAGE_UP,
SCROLL_PAGE_DOWN,
SCROLL_ESCAPE,
SCROLL_TO_BEGINNING,
SCROLL_TO_END
} ScrollEventType;
static const int SCROLLWIDGETGUMP_W = 200;
static const int SCROLLWIDGETGUMP_H = 100;
class ScrollWidgetGump: public MsgScroll {
Font *font_normal;
Font *font_garg;
uint8 font_color;
uint8 font_highlight;
uint16 position;
Std::string trailing_whitespace;
bool show_up_arrow;
bool show_down_arrow;
public:
ScrollWidgetGump(const Configuration *cfg, Screen *s);
~ScrollWidgetGump() override;
bool parse_token(MsgText *token) override;
bool can_display_prompt() const override {
return false;
}
void Display(bool full_redraw) override;
void display_prompt() override {}
void display_string(const Std::string &s);
void display_string(const Std::string &s, Font *f, bool include_on_map_window) override {
return MsgScroll::display_string(s, f, include_on_map_window);
}
void set_font(uint8 font_type) override;
bool is_garg_font() override;
bool can_fit_token_on_msgline(MsgLine *msg_line, MsgText *token) override;
GUI_status KeyDown(const Common::KeyState &key) override;
GUI_status MouseDown(int x, int y, Events::MouseButton button) override;
GUI_status MouseUp(int x, int y, Events::MouseButton button) override {
return GUI_YUM; // otherwise we do Msgscroll::MouseUp
}
GUI_status MouseWheel(sint32 x, sint32 y) override;
void move_scroll_down() override {
scroll_movement_event(SCROLL_DOWN);
}
void move_scroll_up() override {
scroll_movement_event(SCROLL_UP);
}
private:
const Common::Rect arrow_up_rect;
const Common::Rect arrow_down_rect;
GUI_status scroll_movement_event(ScrollEventType event);
void update_arrows();
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,131 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/misc/u6_misc.h"
#include "ultima/nuvie/core/events.h"
#include "ultima/nuvie/gui/gui.h"
#include "ultima/nuvie/fonts/bmp_font.h"
#include "ultima/nuvie/views/view_manager.h"
#include "ultima/nuvie/views/sign_view_gump.h"
namespace Ultima {
namespace Nuvie {
static const int SIGN_BG_W = 246;
static const int SIGN_BG_H = 101;
SignViewGump::SignViewGump(const Configuration *cfg) : DraggableView(cfg), sign_text(nullptr) {
font = new BMPFont();
Common::Path datadir = GUI::get_gui()->get_data_dir();
Common::Path imagefile;
Common::Path path;
build_path(datadir, "images", path);
datadir = path;
build_path(datadir, "gumps", path);
datadir = path;
build_path(datadir, "sign", path);
datadir = path;
build_path(datadir, "sign_font", imagefile);
((BMPFont *)font)->init(imagefile, true);
}
SignViewGump::~SignViewGump() {
if (font)
delete font;
if (sign_text) {
free(sign_text);
}
}
bool SignViewGump::init(Screen *tmp_screen, void *view_manager, Font *f, Party *p, TileManager *tm, ObjManager *om, const char *text_string, uint16 length) {
uint16 x_off = Game::get_game()->get_game_x_offset();
uint16 y_off = Game::get_game()->get_game_y_offset();
x_off += (Game::get_game()->get_game_width() - SIGN_BG_W) / 2;
y_off += (Game::get_game()->get_game_height() - SIGN_BG_H) / 2;
View::init(x_off, y_off, f, p, tm, om);
SetRect(area.left, area.top, SIGN_BG_W, SIGN_BG_H);
Common::Path datadir = GUI::get_gui()->get_data_dir();
Common::Path imagefile;
Common::Path path;
build_path(datadir, "images", path);
datadir = path;
build_path(datadir, "gumps", path);
datadir = path;
build_path(datadir, "sign", path);
datadir = path;
build_path(datadir, "sign_bg.bmp", imagefile);
bg_image = SDL_LoadBMP(imagefile);
set_bg_color_key(0, 0x70, 0xfc);
sign_text = (char *)malloc(length + 1);
memcpy(sign_text, text_string, length);
sign_text[length] = '\0';
return true;
}
void SignViewGump::Display(bool full_redraw) {
Common::Rect dst;
dst = area;
SDL_BlitSurface(bg_image, nullptr, surface, &dst);
DisplayChildren(full_redraw);
//font->textOut(screen->get_sdl_surface(), area.left + 29, area.top + 6, "This is a test sign");
font->drawString(screen, sign_text, strlen(sign_text), area.left + (area.width() - font->getStringWidth(sign_text)) / 2, area.top + (area.height() - 19) / 2, 0, 0);
update_display = false;
screen->update(area.left, area.top, area.width(), area.height());
return;
}
GUI_status SignViewGump::MouseDown(int x, int y, Events::MouseButton button) {
Game::get_game()->get_view_manager()->close_gump(this);
return GUI_YUM;
}
GUI_status SignViewGump::KeyDown(const Common::KeyState &key) {
Game::get_game()->get_view_manager()->close_gump(this);
return GUI_YUM;
}
GUI_status SignViewGump::callback(uint16 msg, GUI_CallBack *caller, void *data) {
Game::get_game()->get_view_manager()->close_gump(this);
return GUI_YUM;
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,59 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_SIGN_VIEW_GUMP_H
#define NUVIE_VIEWS_SIGN_VIEW_GUMP_H
#include "ultima/nuvie/views/draggable_view.h"
namespace Ultima {
namespace Nuvie {
class Configuration;
class TileManager;
class ObjManager;
class Screen;
class Font;
//class BMPFont;
class SignViewGump : public DraggableView {
Font *font;
char *sign_text;
public:
SignViewGump(const Configuration *cfg);
~SignViewGump() override;
bool init(Screen *tmp_screen, void *view_manager, Font *f, Party *p, TileManager *tm, ObjManager *om, const char *text_string, uint16 length);
void Display(bool full_redraw) override;
GUI_status callback(uint16 msg, GUI_CallBack *caller, void *data) override;
GUI_status MouseDown(int x, int y, Events::MouseButton button) override;
GUI_status KeyDown(const Common::KeyState &key) override;
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,540 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/screen/screen.h"
#include "ultima/nuvie/misc/u6_llist.h"
#include "ultima/nuvie/misc/u6_misc.h"
#include "ultima/nuvie/files/u6_bmp.h"
#include "ultima/nuvie/gui/gui.h"
#include "ultima/nuvie/gui/gui_button.h"
#include "ultima/nuvie/views/doll_widget.h"
#include "ultima/nuvie/views/inventory_widget.h"
#include "ultima/nuvie/views/spell_view.h"
#include "ultima/nuvie/core/party.h"
#include "ultima/nuvie/fonts/font.h"
#include "ultima/nuvie/actors/actor.h"
#include "ultima/nuvie/core/events.h"
#include "ultima/nuvie/gui/widgets/map_window.h"
#include "ultima/nuvie/gui/widgets/msg_scroll.h"
#include "ultima/nuvie/usecode/usecode.h"
#include "ultima/nuvie/views/view_manager.h"
#include "ultima/nuvie/script/script.h"
#include "ultima/nuvie/core/u6_objects.h"
#include "ultima/nuvie/core/magic.h"
#include "ultima/nuvie/keybinding/keys.h"
namespace Ultima {
namespace Nuvie {
static const char circle_num_tbl[][8] = {"1ST", "2ND", "3RD", "4TH", "5TH", "6TH", "7TH", "8TH"};
static const int obj_n_reagent[8] = {OBJ_U6_MANDRAKE_ROOT, OBJ_U6_NIGHTSHADE, OBJ_U6_BLACK_PEARL, OBJ_U6_BLOOD_MOSS, OBJ_U6_SPIDER_SILK, OBJ_U6_GARLIC, OBJ_U6_GINSENG, OBJ_U6_SULFUROUS_ASH};
static const int NEWMAGIC_BMP_W = 144;
static const int NEWMAGIC_BMP_H = 82;
SpellView::SpellView(const Configuration *cfg) : DraggableView(cfg), spell_container(nullptr),
background(nullptr), level(1), all_spells_mode(false), spell_num(0),
event_mode(false), num_spells_per_page(8), caster(nullptr) {
}
SpellView::~SpellView() {
if (background) {
delete background;
}
}
bool SpellView::init(Screen *tmp_screen, void *view_manager, uint16 x, uint16 y, Font *f, Party *p, TileManager *tm, ObjManager *om) {
View::init(x, y, f, p, tm, om);
SetRect(area.left, area.top, NEWMAGIC_BMP_W, NEWMAGIC_BMP_H + 16);
Common::Path filename;
config_get_path(config, "newmagic.bmp", filename);
background = new U6Bmp();
if (background->load(filename) == false)
return false;
add_command_icons(tmp_screen, view_manager);
return true;
}
void SpellView::PlaceOnScreen(Screen *s, GUI_DragManager *dm, int x, int y) {
GUI_Widget::PlaceOnScreen(s, dm, x, y);
}
void SpellView::set_spell_caster(Actor *actor, Obj *s_container, bool eventMode) {
caster = actor;
spell_container = s_container;
event_mode = eventMode;
for (int shift = 0; shift < 8; shift++) {
caster_reagents[shift] = caster->inventory_count_object(obj_n_reagent[shift]);
}
level = (spell_container->quality / 16) + 1;
spell_num = spell_container->quality - (16 * level);
if (Game::get_game()->has_unlimited_casting() || spell_container->find_in_container(OBJ_U6_SPELL, MAGIC_ALL_SPELLS, OBJ_MATCH_QUALITY))
all_spells_mode = true;
else
all_spells_mode = false;
fill_cur_spell_list();
update_buttons();
Game::get_game()->set_mouse_pointer(1); // crosshairs
}
void SpellView::Display(bool full_redraw) {
if (full_redraw || update_display) {
screen->fill(bg_color, area.left, area.top + NEWMAGIC_BMP_H, area.width(), area.height() - NEWMAGIC_BMP_H);
screen->blit(area.left, area.top, background->get_data(), 8, NEWMAGIC_BMP_W, NEWMAGIC_BMP_H, NEWMAGIC_BMP_W, true);
}
display_level_text();
display_spell_list_text();
DisplayChildren(full_redraw);
#if 1 // FIXME: This shouldn't need to be in the loop
update_buttons(); // It doesn't seem to hurt speed though
screen->update(area.left, area.top, area.width(), area.height());
#else
if (full_redraw || update_display) {
update_display = false;
screen->update(area.left, area.top, area.width(), area.height());
}
#endif
}
uint8 SpellView::fill_cur_spell_list() {
Magic *m = Game::get_game()->get_magic();
int j = 0;
for (int i = 0; i < 16; i++) {
cur_spells[i] = -1;
if (m->get_spell((level - 1) * 16 + i) != nullptr && (all_spells_mode || spell_container->find_in_container(OBJ_U6_SPELL, (level - 1) * 16 + i, OBJ_MATCH_QUALITY)))
cur_spells[j++] = (level - 1) * 16 + i;
}
return j;
}
sint8 SpellView::get_selected_index() const {
for (uint8 i = 0; i < 16; i++) {
if (cur_spells[i] == spell_container->quality) {
return (sint8)i;
}
}
return -1;
}
void SpellView::set_prev_level() {
if (level == 1)
return;
uint8 old_level = level;
uint8 num_spells = 0;
for (; num_spells == 0;) {
level--;
if (level == 0)
break;
num_spells = fill_cur_spell_list();
}
if (num_spells == 0) {
level = old_level;
fill_cur_spell_list();
}
if (num_spells > num_spells_per_page)
spell_container->quality = cur_spells[num_spells_per_page];
else {
spell_container->quality = cur_spells[0];
}
}
void SpellView::set_next_level() {
if (level == 8)
return;
uint8 old_level = level;
uint8 num_spells = 0;
for (; num_spells == 0;) {
level++;
if (level == 9)
break;
num_spells = fill_cur_spell_list();
}
if (num_spells == 0) {
level = old_level;
fill_cur_spell_list();
} else
spell_container->quality = cur_spells[0];
}
void SpellView::move_left() {
sint8 index = get_selected_index();
if (index < 0)
index = 0;
if (index >= num_spells_per_page) {
spell_container->quality = cur_spells[0];
} else {
set_prev_level();
}
update_buttons();
update_display = true;
}
void SpellView::move_right() {
sint8 index = get_selected_index();
if (index < 0)
index = 0;
if (index >= num_spells_per_page || cur_spells[num_spells_per_page] == -1) {
set_next_level();
} else {
spell_container->quality = cur_spells[num_spells_per_page];
}
update_buttons();
update_display = true;
}
GUI_status SpellView::move_up() {
sint8 index = get_selected_index();
if (index > 0 && index != num_spells_per_page) {
spell_container->quality = cur_spells[index - 1];
update_display = true;
} else
move_left();
return GUI_YUM;
}
GUI_status SpellView::move_down() {
sint8 index = get_selected_index();
if (index != -1 && index < 15 && index != (num_spells_per_page - 1)) {
if (cur_spells[index + 1] != -1) {
spell_container->quality = cur_spells[index + 1];
update_display = true;
} else
move_right();
} else
move_right();
return GUI_YUM;
}
void SpellView::display_level_text() {
font->drawString(screen, circle_num_tbl[level - 1], area.left + 96 + 8, area.top + NEWMAGIC_BMP_H);
font->drawString(screen, "level", area.left + 96, area.top + NEWMAGIC_BMP_H + 8);
return;
}
void SpellView::display_spell_list_text() {
Magic *m = Game::get_game()->get_magic();
sint8 index = get_selected_index();
if (index >= num_spells_per_page)
index = num_spells_per_page;
else
index = 0;
for (uint8 i = 0; i < num_spells_per_page; i++) {
sint16 spellNum = cur_spells[i + index];
if (spellNum != -1) {
Spell *spell = m->get_spell((uint8)spellNum);
display_spell_text(spell, i, spell_container->quality);
}
}
}
void SpellView::display_spell_text(Spell *spell, uint16 line_num, uint8 selected_spell) {
line_num++;
font->drawString(screen, spell->name, area.left + 16, area.top + (line_num * 8));
font->drawString(screen, Common::String::format("%d", get_available_spell_count(spell)).c_str(), area.left + NEWMAGIC_BMP_W - 24, area.top + (line_num * 8));
if (spell->num == selected_spell)
font->drawChar(screen, 26, area.left + 8, area.top + (line_num * 8));
}
uint16 SpellView::get_available_spell_count(const Spell *s) const {
if (s->reagents == 0) // Help and Armageddon
return 1;
if (Game::get_game()->has_unlimited_casting())
return 99;
sint32 min_reagents = -1;
for (int shift = 0; shift < 8; shift++) {
if (1 << shift & s->reagents) {
if (min_reagents == -1 || caster_reagents[shift] < min_reagents)
min_reagents = caster_reagents[shift];
}
}
if (min_reagents == -1)
min_reagents = 0;
return (uint16)min_reagents;
}
void SpellView::add_command_icons(Screen *tmp_screen, void *view_manager) {
Tile *tile;
Graphics::ManagedSurface *button_image;
Graphics::ManagedSurface *button_image2;
tile = tile_manager->get_tile(412); //left arrow icon
button_image = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
button_image2 = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
left_button = new GUI_Button(this, 2 * 16, NEWMAGIC_BMP_H, button_image, button_image2, this);
this->AddWidget(left_button);
tile = tile_manager->get_tile(413); //right arrow icon
button_image = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
button_image2 = tmp_screen->create_sdl_surface_from(tile->data, 8, 16, 16, 16);
right_button = new GUI_Button(this, 3 * 16, NEWMAGIC_BMP_H, button_image, button_image2, this);
this->AddWidget(right_button);
}
void SpellView::event_mode_select_spell() {
sint16 spellNum = get_selected_spell();
Game::get_game()->get_event()->select_spell_num(spellNum);
release_focus();
}
/* Move the cursor around
*/
GUI_status SpellView::KeyDown(const Common::KeyState &key) {
KeyBinder *keybinder = Game::get_game()->get_keybinder();
ActionType a = keybinder->get_ActionType(key);
switch (keybinder->GetActionKeyType(a)) {
case NORTH_KEY:
return move_up();
case SOUTH_KEY:
return move_down();
case WEST_KEY:
case PREVIOUS_PARTY_MEMBER_KEY:
move_left();
break;
case EAST_KEY:
case NEXT_PARTY_MEMBER_KEY:
move_right();
break;
case HOME_KEY:
// TODO - add going to first viable page
break;
case END_KEY:
// TODO - add going to last viable page
break;
case DO_ACTION_KEY:
if (Game::get_game()->get_event()->is_looking_at_spellbook()) {
show_spell_description();
return GUI_YUM;
}
if (event_mode) {
event_mode_select_spell();
return GUI_YUM;
}
return GUI_PASS;
case CANCEL_ACTION_KEY:
return cancel_spell();
case TOGGLE_CURSOR_KEY :
break;
default:
return GUI_PASS;
}
return GUI_YUM;
}
GUI_status SpellView::cancel_spell() {
Events *event = Game::get_game()->get_event();
if (event->is_looking_at_spellbook()) {
close_look();
return GUI_YUM;
} else if (event_mode) {
event->select_spell_num(-1);
release_focus();
return GUI_YUM;
}
event->set_mode(CAST_MODE);
event->cancelAction();
return GUI_YUM;
}
GUI_status SpellView::MouseWheel(sint32 x, sint32 y) {
if (y > 0)
return move_up();
if (y < 0)
return move_down();
return GUI_YUM;
}
GUI_status SpellView::MouseDown(int x, int y, Events::MouseButton button) {
y -= area.top;
x -= area.left;
Events *event = Game::get_game()->get_event();
bool selecting_spell_target, canceling_spell, doing_nothing;
if (Game::get_game()->is_original_plus()) {
if (Game::get_game()->is_original_plus_full_map())
selecting_spell_target = (x < -7 || y > 194);
else
selecting_spell_target = (x < -7);
canceling_spell = (x > 1 && (y > 101 || x > 137));
doing_nothing = ((x > -8 && x < 16) || (x > -8 && (y < 8 || (y > 71 && y < 195))));
} else {
selecting_spell_target = (x < 0 && y > 0 && y < 162);
canceling_spell = (x > 1 && (y > 101 || x > 137));
doing_nothing = (y < 8 || y > 71 || x < 16 || x > 134);
}
if (button == Events::BUTTON_RIGHT)
return cancel_spell();
if (selecting_spell_target && !event_mode) { // cast selected spell on the map
if (event->is_looking_at_spellbook()) {
close_look();
return GUI_YUM;
}
event->target_spell();
if (event->get_mode() == INPUT_MODE) {
y += area.top;
x += area.left;
Game::get_game()->get_map_window()->select_target(x, y);
}
return GUI_YUM;
}
if (canceling_spell) // cancel spell
return cancel_spell();
if (doing_nothing) // do nothing
return GUI_YUM;
// selecting spell index
sint8 index = get_selected_index();
if (index >= num_spells_per_page)
index = num_spells_per_page;
else
index = 0;
y = (y / num_spells_per_page) - 1;
//printf("x = %d, y = %d index=%d\n", x, y, index);
if (cur_spells[index + y] != -1) {
spell_container->quality = cur_spells[index + y];
update_display = true;
if (event->is_looking_at_spellbook())
show_spell_description();
else if (event_mode)
event_mode_select_spell();
else
Game::get_game()->get_event()->target_spell();
}
return GUI_YUM;
}
void SpellView::hide_buttons() {
if (left_button) left_button->Hide();
if (right_button) right_button->Hide();
}
void SpellView::show_buttons() {
if (left_button) left_button->Show();
if (right_button) right_button->Show();
}
void SpellView::update_buttons() {
show_buttons();
sint8 index = get_selected_index();
if (level == 1 && index <= (num_spells_per_page - 1) && left_button)
left_button->Hide();
uint8 old_level = level;
uint8 num_spells = 0;
for (; num_spells == 0;) {
level++;
if (level == 9)
break;
num_spells = fill_cur_spell_list();
}
level = old_level;
fill_cur_spell_list();
if (right_button && ((level < 8 && num_spells == 0) || level == 8)
&& cur_spells[num_spells_per_page * (1 + index / num_spells_per_page)] == -1)
right_button->Hide();
}
void SpellView::close_look() {
Game::get_game()->get_event()->set_looking_at_spellbook(false);
Game::get_game()->get_scroll()->display_prompt();
Game::get_game()->get_view_manager()->close_spell_mode();
Game::get_game()->get_event()->endAction();
}
void SpellView::show_spell_description() {
if (get_selected_index() != -1) {
sint16 index = get_selected_spell();
if (index < 256 && index > -1)
Game::get_game()->get_magic()->show_spell_description((uint8)index);
}
close_look();
}
GUI_status SpellView::callback(uint16 msg, GUI_CallBack *caller, void *data) {
if (caller == left_button) {
move_left();
return GUI_YUM;
} else if (caller == right_button) {
move_right();
return GUI_YUM;
}
return GUI_PASS;
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,136 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_SPELL_VIEW_H
#define NUVIE_VIEWS_SPELL_VIEW_H
#include "ultima/nuvie/views/draggable_view.h"
#include "ultima/nuvie/core/obj.h"
namespace Ultima {
namespace Nuvie {
class Configuration;
class TileManager;
class ObjManager;
class Screen;
class Actor;
class Font;
class U6Bmp;
class Spell;
class SpellView : public DraggableView {
U6Bmp *background;
bool all_spells_mode;
protected:
bool event_mode; //this means we are reporting the spell_num back to the event class. Used by the enchant spell.
Obj *spell_container;
Actor *caster;
uint16 caster_reagents[8];
uint8 level;
uint8 spell_num;
sint16 cur_spells[16];
uint8 num_spells_per_page;
public:
SpellView(const Configuration *cfg);
~SpellView() override;
virtual bool init(Screen *tmp_screen, void *view_manager, uint16 x, uint16 y, Font *f, Party *p, TileManager *tm, ObjManager *om);
void set_spell_caster(Actor *actor, Obj *s_container, bool eventMode);
sint16 get_selected_spell() const {
if (spell_container) {
return spell_container->quality;
} else return -1;
}
void Display(bool full_redraw) override;
void PlaceOnScreen(Screen *s, GUI_DragManager *dm, int x, int y) override;
void close_look();
GUI_status KeyDown(const Common::KeyState &key) override;
GUI_status MouseDown(int x, int y, Events::MouseButton button) override;
GUI_status MouseUp(int x, int y, Events::MouseButton button) override {
return GUI_YUM;
}
GUI_status MouseMotion(int x, int y, uint8 state) override {
return GUI_YUM;
}
GUI_status MouseEnter(uint8 state) override {
return GUI_YUM;
}
GUI_status MouseLeave(uint8 state) override {
return GUI_YUM;
}
GUI_status MouseClick(int x, int y, Events::MouseButton button) override {
return GUI_YUM;
}
GUI_status MouseDouble(int x, int y, Events::MouseButton button) override {
return GUI_YUM;
}
GUI_status MouseDelayed(int x, int y, Events::MouseButton button) override {
return GUI_YUM;
}
GUI_status MouseHeld(int x, int y, Events::MouseButton button) override {
return GUI_YUM;
}
GUI_status MouseWheel(sint32 x, sint32 y) override;
protected:
void event_mode_select_spell();
void add_command_icons(Screen *tmp_screen, void *view_manager);
void hide_buttons();
void show_buttons();
void update_buttons();
void move_left();
void move_right();
GUI_status move_up();
GUI_status move_down();
void set_prev_level();
void set_next_level();
virtual uint8 fill_cur_spell_list();
sint8 get_selected_index() const;
void display_level_text();
void display_spell_list_text();
void display_spell_text(Spell *spell, uint16 line_num, uint8 selected_spell);
void show_spell_description();
GUI_status cancel_spell();
uint16 get_available_spell_count(const Spell *s) const;
GUI_status callback(uint16 msg, GUI_CallBack *caller, void *data) override;
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,356 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/misc/u6_misc.h"
#include "ultima/nuvie/core/events.h"
#include "ultima/nuvie/gui/gui.h"
#include "ultima/nuvie/gui/gui_button.h"
#include "ultima/nuvie/core/magic.h"
#include "ultima/nuvie/views/spell_view_gump.h"
#include "ultima/nuvie/gui/widgets/map_window.h"
#include "ultima/nuvie/files/nuvie_bmp_file.h"
namespace Ultima {
namespace Nuvie {
SpellViewGump::SpellViewGump(const Configuration *cfg) : SpellView(cfg),
gump_button(nullptr), font(nullptr), selected_spell(-1) {
num_spells_per_page = 10;
bg_image = nullptr;
}
SpellViewGump::~SpellViewGump() {
delete font;
}
bool SpellViewGump::init(Screen *tmp_screen, void *view_manager, uint16 x, uint16 y, Font *f, Party *p, TileManager *tm, ObjManager *om) {
View::init(x, y, f, p, tm, om);
SetRect(area.left, area.top, 162, 108);
Common::Path datadir = GUI::get_gui()->get_data_dir();
Common::Path imagefile;
Common::Path path;
Graphics::ManagedSurface *image, *image1;
build_path(datadir, "images", path);
datadir = path;
build_path(datadir, "gumps", path);
datadir = path;
build_path(datadir, "gump_btn_up.bmp", imagefile);
image = SDL_LoadBMP(imagefile);
build_path(datadir, "gump_btn_down.bmp", imagefile);
image1 = SDL_LoadBMP(imagefile);
gump_button = new GUI_Button(nullptr, 0, 9, image, image1, this);
this->AddWidget(gump_button);
build_path(datadir, "spellbook", path);
datadir = path;
build_path(datadir, "spellbook_left_arrow.bmp", imagefile);
image = SDL_LoadBMP(imagefile); //we load this twice as they are freed in ~GUI_Button()
image1 = SDL_LoadBMP(imagefile);
left_button = new GUI_Button(this, 27, 4, image, image1, this);
this->AddWidget(left_button);
build_path(datadir, "spellbook_right_arrow.bmp", imagefile);
image = SDL_LoadBMP(imagefile);
image1 = SDL_LoadBMP(imagefile);
right_button = new GUI_Button(this, 132, 4, image, image1, this);
this->AddWidget(right_button);
font = new GUI_Font(GUI_FONT_GUMP);
font->setColoring(0x7c, 0x00, 0x00, 0xd0, 0x70, 0x00, 0x00, 0x00, 0x00);
return true;
}
uint8 SpellViewGump::fill_cur_spell_list() {
uint8 count = SpellView::fill_cur_spell_list();
//load spell images
Common::Path datadir = GUI::get_gui()->get_data_dir();
Common::Path path;
build_path(datadir, "images", path);
datadir = path;
build_path(datadir, "gumps", path);
datadir = path;
build_path(datadir, "spellbook", path);
datadir = path;
Common::Path imagefile;
build_path(datadir, "spellbook_bg.bmp", imagefile);
delete bg_image;
bg_image = bmp.getSdlSurface32(imagefile);
if (bg_image == nullptr) {
DEBUG(0, LEVEL_ERROR, "Failed to load spellbook_bg.bmp from '%s' directory\n", datadir.toString().c_str());
return count;
}
set_bg_color_key(0, 0x70, 0xfc);
for (int i = 0; i < count; i++) {
char filename[24]; // spellbook_spell_xxx.bmp\0
Common::sprintf_s(filename, "spellbook_spell_%03d.bmp", cur_spells[i]);
build_path(datadir, filename, imagefile);
Graphics::ManagedSurface *spell_image = bmp.getSdlSurface32(imagefile);
if (spell_image == nullptr) {
DEBUG(0, LEVEL_ERROR, "Failed to load %s from '%s' directory\n", filename, datadir.toString().c_str());
} else {
Common::Rect dst;
uint8 base = (level - 1) * 16;
uint8 spell = cur_spells[i] - base;
dst.left = ((spell < 5) ? 25 : 88);
dst.top = 18 + (spell % 5) * 14;
dst.setWidth(58);
dst.setHeight(13);
SDL_BlitSurface(spell_image, nullptr, bg_image, &dst);
delete spell_image;
printSpellQty(cur_spells[i], dst.left + ((spell < 5) ? 50 : 48), dst.top);
}
}
loadCircleString(datadir);
return count;
}
void SpellViewGump::loadCircleString(const Common::Path &datadir) {
Common::Path imagefile;
char filename[7]; // n.bmp\0
Common::sprintf_s(filename, "%d.bmp", level);
build_path(datadir, filename, imagefile);
Common::ScopedPtr<Graphics::ManagedSurface> s(bmp.getSdlSurface32(imagefile));
if (s) {
Common::Rect dst;
dst = Common::Rect(70, 7, 74, 13);
SDL_BlitSurface(s.get(), nullptr, bg_image, &dst);
}
switch (level) {
case 1 :
loadCircleSuffix(datadir, "st.bmp");
break;
case 2 :
loadCircleSuffix(datadir, "nd.bmp");
break;
case 3 :
loadCircleSuffix(datadir, "rd.bmp");
break;
default:
break;
}
}
void SpellViewGump::loadCircleSuffix(const Common::Path &datadir, const Std::string &image) {
Common::Path imagefile;
build_path(datadir, image, imagefile);
Common::ScopedPtr<Graphics::ManagedSurface> s(bmp.getSdlSurface32(imagefile));
if (s) {
Common::Rect dst;
dst = Common::Rect(75, 7, 82, 13);
SDL_BlitSurface(s.get(), nullptr, bg_image, &dst);
}
}
void SpellViewGump::printSpellQty(uint8 spellNum, uint16 x, uint16 y) {
Magic *m = Game::get_game()->get_magic();
Spell *spell = m->get_spell((uint8)spellNum);
uint16 qty = get_available_spell_count(spell);
if (qty < 10)
x += 5;
font->textOut(bg_image, x, y, Common::String::format("%d", qty).c_str());
}
void SpellViewGump::Display(bool full_redraw) {
//display_level_text();
//display_spell_list_text();
Common::Rect dst;
dst = area;
dst.setWidth(162);
dst.setHeight(108);
SDL_BlitSurface(bg_image, nullptr, surface, &dst);
DisplayChildren(full_redraw);
sint16 spell = get_selected_spell();
if (spell < 0)
spell = 0;
spell = spell % 16;
screen->fill(248, area.left + ((spell < 5) ? 75 : 136), area.top + 18 + 7 + (spell % 5) * 14, 10, 1);
update_display = false;
screen->update(area.left, area.top, area.width(), area.height());
return;
}
GUI_status SpellViewGump::callback(uint16 msg, GUI_CallBack *caller, void *data) {
//close gump and return control to Magic class for clean up.
if (caller == gump_button) {
if (Game::get_game()->get_event()->is_looking_at_spellbook())
close_look();
else
close_spellbook();
return GUI_YUM;
} else if (caller == left_button) {
move_left();
return GUI_YUM;
} else if (caller == right_button) {
move_right();
return GUI_YUM;
}
return GUI_PASS;
}
void SpellViewGump::close_spellbook() {
Game::get_game()->get_event()->close_spellbook();
}
sint16 SpellViewGump::getSpell(int x, int y) const {
int localy = y - area.top;
int localx = x - area.left;
localy += 3; //align the pointer in the center of the crosshair cursor.
localx += 3;
if (localy < 21 || localy > 88 || localx < 28 || localx > 148) {
return -1;
}
uint8 spell = (level - 1) * 16;
if (localx >= 89)
spell += 5;
spell += (localy - 20) / 14;
for (uint8 i = 0; cur_spells[i] != -1 && i < 16; i++) {
if (cur_spells[i] == spell) {
return spell;
}
}
return -1;
}
GUI_status SpellViewGump::MouseWheel(sint32 x, sint32 y) {
if (y > 0) {
move_left();
} else if (y < 0) {
move_right();
}
return GUI_YUM;
}
GUI_status SpellViewGump::MouseDown(int x, int y, Events::MouseButton button) {
if (button == Events::BUTTON_RIGHT) {
close_spellbook();
return GUI_YUM;
}
sint16 clicked_spell = getSpell(x, y);
if (clicked_spell != -1) {
selected_spell = clicked_spell;
return GUI_YUM;
}
bool can_target = true; // maybe put this check into GUI_widget
if (HitRect(x, y)) {
if (bg_image) {
uint32 pixel = sdl_getpixel(bg_image, x - area.left, y - area.top);
if (pixel != bg_color_key)
can_target = false;
} else
can_target = false;
}
if (can_target) {
Events *event = Game::get_game()->get_event();
if (event->is_looking_at_spellbook()) {
close_spellbook();
return GUI_YUM;
}
if (!event_mode)
event->target_spell(); //Simulate a global key down event.
if (event->get_mode() == INPUT_MODE)
Game::get_game()->get_map_window()->select_target(x, y);
if (event->get_mode() != MOVE_MODE)
close_spellbook();
return GUI_YUM;
}
return DraggableView::MouseDown(x, y, button);
}
GUI_status SpellViewGump::MouseUp(int x, int y, Events::MouseButton button) {
if (button == Events::BUTTON_RIGHT)
return GUI_YUM;
sint16 spell = getSpell(x, y);
if (spell != -1 && spell == selected_spell) {
spell_container->quality = spell;
if (Game::get_game()->get_event()->is_looking_at_spellbook())
show_spell_description();
else if (event_mode) {
event_mode_select_spell();
} else {
//Simulate a global key down event.
Game::get_game()->get_event()->target_spell();
}
return GUI_YUM;
}
auto ret = DraggableView::MouseUp(x, y, button);
grab_focus(); // Dragging releases focus, grab it again
return ret;
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,83 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_SPELL_VIEW_GUMP_H
#define NUVIE_VIEWS_SPELL_VIEW_GUMP_H
#include "ultima/nuvie/views/spell_view.h"
#include "ultima/nuvie/files/nuvie_bmp_file.h"
namespace Ultima {
namespace Nuvie {
class Configuration;
class TileManager;
class ObjManager;
class Screen;
class Actor;
class Font;
class U6Bmp;
class Spell;
static const int SPELLVIEWGUMP_WIDTH = 162;
class SpellViewGump : public SpellView {
GUI_Button *gump_button;
sint16 selected_spell;
GUI_Font *font;
NuvieBmpFile bmp;
public:
SpellViewGump(const Configuration *cfg);
~SpellViewGump() override;
bool init(Screen *tmp_screen, void *view_manager, uint16 x, uint16 y, Font *f, Party *p, TileManager *tm, ObjManager *om) override;
void Display(bool full_redraw) override;
GUI_status MouseDown(int x, int y, Events::MouseButton button) override;
GUI_status MouseUp(int x, int y, Events::MouseButton button) override;
GUI_status MouseMotion(int x, int y, uint8 state) override {
return DraggableView::MouseMotion(x, y, state);
}
GUI_status MouseWheel(sint32 x, sint32 y) override;
void MoveRelative(int dx, int dy) override {
return DraggableView::MoveRelative(dx, dy);
}
GUI_status callback(uint16 msg, GUI_CallBack *caller, void *data) override;
protected:
sint16 getSpell(int x, int y) const;
uint8 fill_cur_spell_list() override;
void loadCircleString(const Common::Path &datadir);
void loadCircleSuffix(const Common::Path &datadir, const Std::string &image);
void printSpellQty(uint8 spell_num, uint16 x, uint16 y);
void close_spellbook();
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,228 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/misc/u6_misc.h"
#include "ultima/nuvie/files/nuvie_bmp_file.h"
#include "ultima/nuvie/core/player.h"
#include "ultima/nuvie/core/weather.h"
#include "ultima/nuvie/core/game_clock.h"
#include "ultima/nuvie/views/sun_moon_ribbon.h"
#include "ultima/nuvie/gui/gui.h"
namespace Ultima {
namespace Nuvie {
static const int SUNMOON_RIBBON_END_WIDTH = 5;
static const int SUNMOON_RIBBON_WIDTH = 48;
static const int SUNMOON_RIBBON_HEIGHT = 14;
static const int SUNMOON_RIBBON_DIR_WIDTH = 14;
static const int SUNMOON_RIBBON_TOTAL_WIDTH = (SUNMOON_RIBBON_WIDTH + SUNMOON_RIBBON_DIR_WIDTH);
SunMoonRibbon::SunMoonRibbon(Player *p, Weather *w, TileManager *tm)
: SunMoonStripWidget(p, tm), bg_data(nullptr), weather(w), retracted(true),
current_time(0) {
}
SunMoonRibbon::~SunMoonRibbon() {
}
void SunMoonRibbon::init(Screen *) {
GUI_Widget::Init(nullptr, Game::get_game()->get_game_x_offset()
+ Game::get_game()->get_game_width() - SUNMOON_RIBBON_TOTAL_WIDTH,
Game::get_game()->get_game_y_offset(),
SUNMOON_RIBBON_TOTAL_WIDTH,SUNMOON_RIBBON_HEIGHT);
loadBgImage(0);
}
void SunMoonRibbon::loadBgImage(uint8 num) {
char filename[6]; // "n.bmp\0"
Common::Path datadir = GUI::get_gui()->get_data_dir();
Common::Path imagefile;
Common::Path path;
NuvieBmpFile bmp;
build_path(datadir, "images", path);
datadir = path;
build_path(datadir, "gumps", path);
datadir = path;
build_path(datadir, "celestial", path);
datadir = path;
Common::sprintf_s(filename, "%d.bmp", num);
build_path(datadir, filename, imagefile);
if (bg_data)
delete bg_data;
bg_data = bmp.getSdlSurface32(imagefile);
uint32 bg_color_key = bg_data->format.RGBToColor(0xb3, 0x94, 0x78);
bg_data->setTransparentColor(bg_color_key);
}
void SunMoonRibbon::Display(bool full_redraw) {
update_display = false;
uint8 level = player->get_location_level();
GameClock *clock = Game::get_game()->get_clock();
uint16 time = 324; //not completely dark - used when in dungeons
if (level == 0 || level == 5)
time = clock->get_hour() * 60 + clock->get_minute();
update_hour(time);
if (!retracted && (level == 0 || level == 5))
display_surface_strip();
else
display_dungeon_strip();
}
void SunMoonRibbon::update_hour(uint16 time) {
static const uint8 dawn_tbl[] = {8, 7, 7, 6, 5, 4, 3, 2, 1, 0};
static const uint8 dusk_tbl[] = {1, 2, 3, 4, 5, 6, 7, 7, 7, 8};
time = time / 6;
if (current_time != time || bg_data == nullptr) {
current_time = time;
uint8 bg_num = 8; //night
if (current_time >= 50 && current_time < 60) {
bg_num = dawn_tbl[current_time - 50]; //dawn
} else if (current_time >= 60 && current_time < 190) {
bg_num = 0; //day time
} else if (current_time >= 190 && current_time < 200) { //dusk
bg_num = dusk_tbl[current_time - 190]; //dusk
}
loadBgImage(bg_num);
}
}
void SunMoonRibbon::display_sun_moon(const Tile *tile, uint8 pos) {
static const struct {
sint16 x, y;
} skypos[15] = { // sky positions relative to area
{ SUNMOON_RIBBON_WIDTH - 0 * 3, 7 },
{ SUNMOON_RIBBON_WIDTH - 1 * 3, 6 },
{ SUNMOON_RIBBON_WIDTH - 2 * 3, 5 },
{ SUNMOON_RIBBON_WIDTH - 3 * 3, 4 },
{ SUNMOON_RIBBON_WIDTH - 4 * 3, 3 },
{ SUNMOON_RIBBON_WIDTH - 5 * 3, 2 },
{ SUNMOON_RIBBON_WIDTH - 6 * 3, 1 },
{ SUNMOON_RIBBON_WIDTH - 7 * 3, 0 },
{ SUNMOON_RIBBON_WIDTH - 8 * 3, 1 },
{ SUNMOON_RIBBON_WIDTH - 9 * 3, 2 },
{ SUNMOON_RIBBON_WIDTH - 10 * 3, 3 },
{ SUNMOON_RIBBON_WIDTH - 11 * 3, 4 },
{ SUNMOON_RIBBON_WIDTH - 12 * 3, 5 },
{ SUNMOON_RIBBON_WIDTH - 13 * 3, 6 },
{ SUNMOON_RIBBON_WIDTH - 14 * 3, 7 }
};
uint16 x = area.left + skypos[pos].x - 10, y = area.top + skypos[pos].y;
screen->blit(x, y, tile->data, 8 , 16, area.height() - skypos[pos].y > 16 ? 16 : area.height() - skypos[pos].y, 16, true);
}
void SunMoonRibbon::display_surface_strip() {
Common::Rect src = Common::Rect(SUNMOON_RIBBON_WIDTH, SUNMOON_RIBBON_HEIGHT);
Common::Rect dest = area;
dest.setWidth(SUNMOON_RIBBON_WIDTH);
dest.setHeight(SUNMOON_RIBBON_HEIGHT);
SDL_BlitSurface(bg_data, &src, surface, &dest);
GameClock *clock = Game::get_game()->get_clock();
bool eclipse = weather->is_eclipse();
display_sun(clock->get_hour(), 0/*minutes*/, eclipse);
if (!eclipse)
display_moons(clock->get_day(), clock->get_hour());
src.left = SUNMOON_RIBBON_WIDTH + weather->get_wind_dir() * SUNMOON_RIBBON_DIR_WIDTH;
uint8 dir;
if (weather->is_displaying_from_wind_dir()) { // points dir wind is coming from
const uint8 from_wind_pos[] = { 1, 3, 5, 7, 2, 4, 6, 8, 0 };
dir = from_wind_pos[weather->get_wind_dir()];
} else { // points dir wind is blowing to
const uint8 to_wind_pos[] = { 5, 7, 1, 3, 6, 8, 2, 4, 0 };
dir = to_wind_pos[weather->get_wind_dir()];
}
src.left = SUNMOON_RIBBON_WIDTH + dir * SUNMOON_RIBBON_DIR_WIDTH;
src.top = 0;
src.setWidth(SUNMOON_RIBBON_DIR_WIDTH);
src.setHeight(SUNMOON_RIBBON_HEIGHT);
dest = area;
dest.left = area.left + SUNMOON_RIBBON_WIDTH;
dest.setWidth(SUNMOON_RIBBON_DIR_WIDTH);
dest.setHeight(SUNMOON_RIBBON_HEIGHT);
SDL_BlitSurface(bg_data, &src, surface, &dest);
screen->update(area.left, area.top, area.width(), area.height());
}
void SunMoonRibbon::display_dungeon_strip() {
Common::Rect src;
Common::Rect dest;
src = Common::Rect(SUNMOON_RIBBON_END_WIDTH, SUNMOON_RIBBON_HEIGHT);
dest.left = area.left + SUNMOON_RIBBON_TOTAL_WIDTH - SUNMOON_RIBBON_END_WIDTH;
dest.top = area.top;
dest.setWidth(SUNMOON_RIBBON_END_WIDTH);
dest.setHeight(SUNMOON_RIBBON_HEIGHT);
SDL_BlitSurface(bg_data, &src, surface, &dest);
screen->update(dest.left, dest.top, dest.width(), dest.height());
}
GUI_status SunMoonRibbon::MouseDown(int x, int y, Events::MouseButton button) {
Common::Rect rect = area;
if (retracted) {
rect.left = area.left + SUNMOON_RIBBON_TOTAL_WIDTH - SUNMOON_RIBBON_END_WIDTH;
rect.setWidth(SUNMOON_RIBBON_END_WIDTH);
if (HitRect(x, y, rect)) {
retracted = false;
return GUI_YUM;
}
} else {
if (HitRect(x, y, rect)) {
retracted = true;
return GUI_YUM;
}
}
return GUI_PASS;
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,68 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_SUN_MOON_RIBBON_H
#define NUVIE_VIEWS_SUN_MOON_RIBBON_H
#include "ultima/nuvie/views/sun_moon_strip_widget.h"
namespace Ultima {
namespace Nuvie {
class SunMoonRibbon : public SunMoonStripWidget {
private:
Graphics::ManagedSurface *bg_data;
Weather *weather;
bool retracted;
uint16 current_time;
public:
SunMoonRibbon(Player *p, Weather *w, TileManager *tm);
~SunMoonRibbon() override;
void init(Screen *screen);
void Display(bool full_redraw) override;
GUI_status MouseDown(int x, int y, Events::MouseButton button) override;
void extend() {
retracted = false;
}
void retract() {
retracted = true;
}
protected:
void display_sun_moon(const Tile *tile, uint8 pos) override;
private:
void loadBgImage(uint8 num);
void display_surface_strip();
void display_dungeon_strip();
void update_hour(uint16 time);
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,155 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/core/player.h"
#include "ultima/nuvie/core/weather.h"
#include "ultima/nuvie/core/game_clock.h"
#include "ultima/nuvie/views/sun_moon_strip_widget.h"
namespace Ultima {
namespace Nuvie {
SunMoonStripWidget::SunMoonStripWidget(Player *p, TileManager *tm)
: GUI_Widget(nullptr, 0, 0, 0, 0), player(p), tile_manager(tm) {
}
SunMoonStripWidget::~SunMoonStripWidget() {
}
void SunMoonStripWidget::init(sint16 x, sint16 y) {
GUI_Widget::Init(nullptr, x, y, 100, 20);
}
void SunMoonStripWidget::Display(bool full_redraw) {
//if(full_redraw || update_display)
// {
update_display = false;
uint8 level = player->get_location_level();
if (level == 0 || level == 5)
display_surface_strip();
else
display_dungeon_strip();
screen->update(area.left, area.top, area.width(), area.height());
// }
}
void SunMoonStripWidget::display_surface_strip() {
GameClock *clock = Game::get_game()->get_clock();
Weather *weather = Game::get_game()->get_weather();
bool eclipse = weather->is_eclipse();
display_sun(clock->get_hour(), 0/*minutes*/, eclipse);
if (!eclipse)
display_moons(clock->get_day(), clock->get_hour());
for (int i = 0; i < 9; i++) {
Tile *tile = tile_manager->get_tile(352 + i);
screen->blit(area.left + 8 + i * 16, area.top, tile->data, 8, 16, 16, 16, true);
}
return;
}
void SunMoonStripWidget::display_dungeon_strip() {
Tile *tile = tile_manager->get_tile(372);
screen->blit(area.left + 8, area.top, tile->data, 8, 16, 16, 16, true);
tile = tile_manager->get_tile(373);
for (int i = 1; i < 8; i++) {
screen->blit(area.left + 8 + i * 16, area.top, tile->data, 8, 16, 16, 16, true);
}
tile = tile_manager->get_tile(374);
screen->blit(area.left + 8 + 7 * 16 + 8, area.top, tile->data, 8, 16, 16, 16, true);
return;
}
// <SB-X>
void SunMoonStripWidget::display_sun_moon(const Tile *tile, uint8 pos) {
struct {
sint16 x, y;
} skypos[15] = { // sky positions relative to area
{ 8 + 7 * 16 - 0 * 8, 6 }, // 7*16 is the first position on the right side
{ 8 + 7 * 16 - 1 * 8, 3 },
{ 8 + 7 * 16 - 2 * 8, 1 },
{ 8 + 7 * 16 - 3 * 8, -1 },
{ 8 + 7 * 16 - 4 * 8, -2 },
{ 8 + 7 * 16 - 5 * 8, -3 },
{ 8 + 7 * 16 - 6 * 8, -4 },
{ 8 + 7 * 16 - 7 * 8, -4 },
{ 8 + 7 * 16 - 8 * 8, -4 },
{ 8 + 7 * 16 - 9 * 8, -3 },
{ 8 + 7 * 16 - 10 * 8, -2 },
{ 8 + 7 * 16 - 11 * 8, -1 },
{ 8 + 7 * 16 - 12 * 8, 1 },
{ 8 + 7 * 16 - 13 * 8, 3 },
{ 8 + 7 * 16 - 14 * 8, 6 }
};
int height = 16;
uint16 x = area.left + skypos[pos].x, y = area.top + skypos[pos].y;
if (skypos[pos].y == 6) // goes through the bottom if not reduced
height = 10;
screen->blit(x, y, tile->data, 8 , 16, height, 16, true);
}
void SunMoonStripWidget::display_sun(uint8 hour, uint8 minute, bool eclipse) {
uint16 sun_tile = 0;
if (eclipse)
sun_tile = 363; //eclipsed sun
else if (hour == 5 || hour == 19)
sun_tile = 361; //orange sun
else if (hour > 5 && hour < 19)
sun_tile = 362; //yellow sun
else return; //no sun
display_sun_moon(tile_manager->get_tile(sun_tile), hour - 5);
}
void SunMoonStripWidget::display_moons(uint8 day, uint8 hour, uint8 minute) {
// trammel (starts 1 hour ahead of sun)
uint8 phase = uint8(nearbyint((day - 1) / TRAMMEL_PHASE)) % 8;
Tile *tileA = tile_manager->get_tile((phase == 0) ? 584 : 584 + (8 - phase)); // reverse order in tilelist
uint8 posA = ((hour + 1) + 3 * phase) % 24; // advance 3 positions each phase-change
// felucca (starts 1 hour behind sun)
// ...my FELUCCA_PHASE may be wrong but this method works with it...
sint8 phaseb = (day - 1) % uint8(nearbyint(FELUCCA_PHASE * 8)) - 1;
phase = (phaseb >= 0) ? phaseb : 0;
Tile *tileB = tile_manager->get_tile((phase == 0) ? 584 : 584 + (8 - phase)); // reverse order in tilelist
uint8 posB = ((hour - 1) + 3 * phase) % 24; // advance 3 positions per phase-change
if (posA >= 5 && posA <= 19)
display_sun_moon(tileA, posA - 5);
if (posB >= 5 && posB <= 19)
display_sun_moon(tileB, posB - 5);
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,59 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_SUN_MOON_STRIP_WIDGET_H
#define NUVIE_VIEWS_SUN_MOON_STRIP_WIDGET_H
#include "ultima/nuvie/gui/widgets/gui_widget.h"
#include "ultima/nuvie/core/tile_manager.h"
namespace Ultima {
namespace Nuvie {
class Player;
class SunMoonStripWidget : public GUI_Widget {
protected:
TileManager *tile_manager;
Player *player;
public:
SunMoonStripWidget(Player *p, TileManager *tm);
~SunMoonStripWidget() override;
void init(sint16 x, sint16 y);
void Display(bool full_redraw) override;
protected:
virtual void display_sun_moon(const Tile *tile, uint8 pos);
void display_sun(uint8 hour, uint8 minute, bool eclipse);
void display_moons(uint8 day, uint8 hour, uint8 minute = 0);
private:
void display_surface_strip();
void display_dungeon_strip();
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,211 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/misc/u6_misc.h"
#include "ultima/nuvie/core/party.h"
#include "ultima/nuvie/screen/game_palette.h"
#include "ultima/nuvie/views/view_manager.h"
#include "ultima/nuvie/views/view.h"
#include "ultima/nuvie/actors/actor.h"
#include "ultima/nuvie/gui/widgets/gui_widget.h"
#include "ultima/nuvie/gui/gui_button.h"
namespace Ultima {
namespace Nuvie {
View::View(const Configuration *cfg) : GUI_Widget(nullptr, 0, 0, 0, 0),
config(cfg), new_ui_mode(false), left_button(nullptr), font(nullptr),
tile_manager(nullptr), right_button(nullptr), obj_manager(nullptr),
party(nullptr), party_button(nullptr), inventory_button(nullptr),
actor_button(nullptr), bg_color(0), cur_party_member(0) {
}
View::~View() {
}
bool View::init(uint16 x, uint16 y, Font *f, Party *p, TileManager *tm, ObjManager *om) {
if (Game::get_game()->get_game_type() == NUVIE_GAME_U6)
GUI_Widget::Init(nullptr, x, y, 136, 96);
else if (Game::get_game()->get_game_type() == NUVIE_GAME_SE)
GUI_Widget::Init(nullptr, x + 7, y - 2, 132, 113);
else
GUI_Widget::Init(nullptr, x + 8, y - 4, 128, 118);
Hide();
font = f;
party = p;
tile_manager = tm;
obj_manager = om;
set_party_member(0);
bg_color = Game::get_game()->get_palette()->get_bg_color();
new_ui_mode = Game::get_game()->is_new_style();
return true;
}
bool View::set_party_member(uint8 party_member) {
uint16 size = party->get_party_size();
if (party_member < size) {
cur_party_member = party_member;
if (left_button && right_button) {
if (party_member == 0)
left_button->Hide();
else
left_button->Show();
if (party_member == size - 1)
right_button->Hide();
else
right_button->Show();
}
Redraw();
return true;
}
return false;
}
bool View::next_party_member() {
if ((cur_party_member + 1) < party->get_party_size())
return set_party_member(cur_party_member + 1);
return false;
}
bool View::prev_party_member() {
if (cur_party_member != 0)
return set_party_member(cur_party_member - 1);
return false;
}
void View::fill_md_background(uint8 color, const Common::Rect &r) {
Screen *scr = Game::get_game()->get_screen();
scr->fill(color, r.left + 1, r.top + 9, 1, 1); // left pillar
scr->fill(color, r.left + 2, r.top + 6, 1, 4); // left pillar
scr->fill(color, r.left + 3, r.top + 3, 1, 11); // left pillar
scr->fill(color, r.left + r.width() - 2, r.top + 9, 1, 1); // right pillar
scr->fill(color, r.left + r.width() - 3, r.top + 6, 1, 4); // right pillar
scr->fill(color, r.left + r.width() - 4, r.top + 3, 1, 11); // right pillar
scr->fill(color, r.left + 4, r.top, r.width() - 8, 15); // top center
scr->fill(color, r.left, r.top + 14, r.width(), r.height() - 14); // bottom
//scr->fill(15, r.left, r.top, r.width(), r.height()); // bottom
}
void View::set_combat_mode(Actor *actor) {
uint8 combat_mode = actor->get_combat_mode();
if (Game::get_game()->get_game_type() == NUVIE_GAME_U6) {
combat_mode++;
if (combat_mode > ACTOR_WT_ASSAULT)
combat_mode = ACTOR_WT_PLAYER;
} else {
if (combat_mode == ACTOR_WT_PLAYER)
combat_mode = ACTOR_WT_RANGED;
else if (combat_mode == ACTOR_WT_RANGED)
combat_mode = ACTOR_WT_RETREAT;
else if (combat_mode == ACTOR_WT_RETREAT)
combat_mode = ACTOR_WT_ASSAULT;
else if (combat_mode == ACTOR_WT_ASSAULT)
combat_mode = ACTOR_WT_PLAYER;
}
actor->set_combat_mode(combat_mode);
}
uint8 View::get_combat_mode_index(const Actor *actor) const {
uint8 combat_mode = actor->get_combat_mode();
if (Game::get_game()->get_game_type() == NUVIE_GAME_U6)
return combat_mode - 2;
else {
uint8 combat_mode_index = 0;
if (combat_mode == ACTOR_WT_PLAYER)
combat_mode_index = 0;
else if (combat_mode == ACTOR_WT_RANGED)
combat_mode_index = 1;
else if (combat_mode == ACTOR_WT_RETREAT)
combat_mode_index = 2;
else if (combat_mode == ACTOR_WT_ASSAULT)
combat_mode_index = 3;
return combat_mode_index;
}
}
GUI_status View::callback(uint16 msg, GUI_CallBack *caller, void *data) {
ViewManager *view_manager;
if (caller == left_button) {
prev_party_member();
return GUI_YUM;
}
if (caller == right_button) {
next_party_member();
return GUI_YUM;
}
if (caller == actor_button) {
view_manager = (ViewManager *)data;
view_manager->set_actor_mode();
return GUI_YUM;
}
if (caller == party_button) {
view_manager = (ViewManager *)data;
view_manager->set_party_mode();
return GUI_YUM;
}
if (caller == inventory_button) {
view_manager = (ViewManager *)data;
view_manager->set_inventory_mode();
return GUI_YUM;
}
return GUI_PASS;
}
GUI_Button *View::loadButton(const Common::Path &dir, Std::string name, uint16 x, uint16 y) {
GUI_Button *button;
Common::Path imagefile;
Graphics::ManagedSurface *image, *image1;
build_path(dir, name + "_btn_up.bmp", imagefile);
image = SDL_LoadBMP(imagefile);
build_path(dir, name + "_btn_down.bmp", imagefile);
image1 = SDL_LoadBMP(imagefile);
button = new GUI_Button(nullptr, x, y, image, image1, this);
this->AddWidget(button);
return button;
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,85 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_VIEW_H
#define NUVIE_VIEWS_VIEW_H
#include "ultima/nuvie/gui/widgets/gui_widget.h"
namespace Ultima {
namespace Nuvie {
GUI_status viewLeftButtonCallback(void *data);
GUI_status viewRightButtonCallback(void *data);
class Configuration;
class TileManager;
class Screen;
class Font;
class ObjManager;
class Party;
class GUI_Button;
class Actor;
class View: public GUI_Widget {
protected:
const Configuration *config;
GUI_Button *left_button, *right_button, *actor_button, *party_button, *inventory_button;
Font *font;
TileManager *tile_manager;
ObjManager *obj_manager;
Party *party;
uint8 cur_party_member;
uint8 bg_color;
bool new_ui_mode;
public:
View(const Configuration *cfg);
~View() override;
bool init(uint16 x, uint16 y, Font *f, Party *p, TileManager *tm, ObjManager *om);
virtual bool set_party_member(uint8 party_member);
uint8 get_party_member_num() const {
return cur_party_member;
}
bool next_party_member();
bool prev_party_member();
void fill_md_background(uint8 color, const Common::Rect &r);
void set_combat_mode(Actor *actor);
uint8 get_combat_mode_index(const Actor *actor) const;
virtual void close_view() {}
protected:
GUI_status callback(uint16 msg, GUI_CallBack *caller, void *data) override;
GUI_Button *loadButton(const Common::Path &dir, Std::string name, uint16 x, uint16 y);
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif

View File

@@ -0,0 +1,586 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/conf/configuration.h"
#include "ultima/nuvie/misc/u6_misc.h"
#include "ultima/nuvie/gui/gui.h"
#include "ultima/nuvie/views/view_manager.h"
#include "ultima/nuvie/actors/actor.h"
#include "ultima/nuvie/views/actor_view.h"
#include "ultima/nuvie/views/portrait_view.h"
#include "ultima/nuvie/views/inventory_view.h"
#include "ultima/nuvie/views/doll_view_gump.h"
#include "ultima/nuvie/views/container_view_gump.h"
#include "ultima/nuvie/views/portrait_view_gump.h"
#include "ultima/nuvie/views/sign_view_gump.h"
#include "ultima/nuvie/views/scroll_view_gump.h"
#include "ultima/nuvie/views/party_view.h"
#include "ultima/nuvie/views/spell_view.h"
#include "ultima/nuvie/views/spell_view_gump.h"
#include "ultima/nuvie/views/sun_moon_ribbon.h"
#include "ultima/nuvie/gui/widgets/map_window.h"
#include "ultima/nuvie/views/map_editor_view.h"
#include "ultima/nuvie/gui/widgets/msg_scroll.h"
#include "ultima/nuvie/core/party.h"
#include "ultima/nuvie/core/events.h"
#include "ultima/nuvie/portraits/portrait.h"
#include "ultima/nuvie/usecode/usecode.h"
#include "ultima/nuvie/files/nuvie_bmp_file.h"
#include "ultima/nuvie/views/md_sky_strip_widget.h"
namespace Ultima {
namespace Nuvie {
ViewManager::ViewManager(const Configuration *cfg) : config(cfg),
current_view(nullptr), gui(nullptr), font(nullptr), tile_manager(nullptr),
obj_manager(nullptr), party(nullptr), portrait(nullptr), actor_view(nullptr),
inventory_view(nullptr), portrait_view(nullptr), party_view(nullptr),
spell_view(nullptr), doll_next_party_member(0), ribbon(nullptr),
mdSkyWidget(nullptr) {
config->value("config/GameType", game_type);
}
ViewManager::~ViewManager() {
// only delete the views that are not currently active
if (current_view != actor_view) delete actor_view;
if (current_view != inventory_view) delete inventory_view;
if (current_view != party_view) delete party_view;
if (current_view != portrait_view) delete portrait_view;
if (current_view != spell_view) delete spell_view;
}
bool ViewManager::init(GUI *g, Font *f, Party *p, Player *player, TileManager *tm, ObjManager *om, Portrait *por) {
gui = g;
font = f;
party = p;
tile_manager = tm;
obj_manager = om;
portrait = por;
uint16 x_off = Game::get_game()->get_game_x_offset();
uint16 y_off = Game::get_game()->get_game_y_offset();
if (Game::get_game()->is_original_plus())
x_off += Game::get_game()->get_game_width() - 320;
inventory_view = new InventoryView(config);
inventory_view->init(gui->get_screen(), this, 176 + x_off, 8 + y_off, font, party, tile_manager, obj_manager);
portrait_view = new PortraitView(config);
portrait_view->init(176 + x_off, 8 + y_off, font, party, player, tile_manager, obj_manager, portrait);
if (!Game::get_game()->is_new_style()) {
//inventory_view = new InventoryView(config);
//inventory_view->init(gui->get_screen(), this, 176+x_off,8+y_off, font, party, tile_manager, obj_manager);
actor_view = new ActorView(config);
actor_view->init(gui->get_screen(), this, 176 + x_off, 8 + y_off, font, party, tile_manager, obj_manager, portrait);
party_view = new PartyView(config);
if (game_type == NUVIE_GAME_U6) {
party_view->init(this, 168 + x_off, 6 + y_off, font, party, player, tile_manager, obj_manager);
spell_view = new SpellView(config);
} else {
party_view->init(this, 176 + x_off, 6 + y_off, font, party, player, tile_manager, obj_manager);
}
if (game_type == NUVIE_GAME_MD) {
if (Game::get_game()->is_new_style() == false) {
mdSkyWidget = new MDSkyStripWidget(config, Game::get_game()->get_clock(), player);
mdSkyWidget->init(32 + x_off, 2 + y_off);
gui->AddWidget(mdSkyWidget);
if (Game::get_game()->is_original_plus())
mdSkyWidget->Hide();
}
}
} else {
//inventory_view = new InventoryViewGump(config);
//inventory_view->init(gui->get_screen(), this, 176+x_off,8+y_off, font, party, tile_manager, obj_manager);
if (game_type == NUVIE_GAME_U6) {
spell_view = new SpellViewGump(config);
ribbon = new SunMoonRibbon(player, Game::get_game()->get_weather(), tile_manager);
ribbon->init(gui->get_screen());
gui->AddWidget(ribbon);
ribbon->Hide(); //will be shown on first call to update()
}
}
uint16 spell_x_offset = 168 + x_off;
if (Game::get_game()->is_new_style()) {
spell_x_offset = Game::get_game()->get_game_width() - SPELLVIEWGUMP_WIDTH + x_off;
}
if (spell_view) {
spell_view->init(gui->get_screen(), this, spell_x_offset, 6 + y_off, font, party, tile_manager, obj_manager);
}
//set_current_view((View *)party_view);
return true;
}
void ViewManager::reload() {
if (!Game::get_game()->is_new_style())
actor_view->set_party_member(0);
inventory_view->lock_to_actor(false);
inventory_view->set_party_member(0);
set_party_mode();
update();
}
bool ViewManager::set_current_view(View *view) {
uint8 cur_party_member;
//actor_view->set_party_member(cur_party_member);
if (view == nullptr) // || game_type != NUVIE_GAME_U6) //HACK! remove this when views support MD and SE
return false;
if (current_view == view) // nothing to do if view is already the current_view.
return false;
if (current_view != nullptr) {
gui->removeWidget((GUI_Widget *)current_view);//remove current widget from gui
cur_party_member = current_view->get_party_member_num();
view->set_party_member(cur_party_member);
}
current_view = view;
view->Show();
gui->AddWidget((GUI_Widget *)view);
view->Redraw();
gui->Display();
if (actor_view) {
if (view != actor_view) {
actor_view->set_show_cursor(false);
actor_view->release_focus();
}
}
if (inventory_view) {
if (view != inventory_view) {
inventory_view->set_show_cursor(false);
inventory_view->release_focus();
}
}
return true;
}
void ViewManager::close_current_view() {
if (current_view == nullptr)
return;
gui->removeWidget((GUI_Widget *)current_view);//remove current widget from gui
current_view = nullptr;
}
void ViewManager::update() {
if (current_view)
current_view->Redraw();
if (ribbon && ribbon->Status() == WIDGET_HIDDEN) {
ribbon->Show();
}
if (mdSkyWidget) {
mdSkyWidget->Redraw();
}
return;
}
// We only change to portrait mode if the actor has a portrait.
void ViewManager::set_portrait_mode(Actor *actor, const char *name) {
if (portrait_view->set_portrait(actor, name) == true) {
set_current_view((View *)portrait_view);
}
}
void ViewManager::set_inventory_mode() {
set_current_view((View *)inventory_view);
Events *event = Game::get_game()->get_event();
if (event->get_mode() == EQUIP_MODE || event->get_mode() == INPUT_MODE
|| event->get_mode() == ATTACK_MODE)
inventory_view->set_show_cursor(true);
}
void ViewManager::set_party_mode() {
Events *event = Game::get_game()->get_event();
if (event->get_mode() == EQUIP_MODE)
event->cancelAction();
else if (event->get_mode() == INPUT_MODE || event->get_mode() == ATTACK_MODE)
event->moveCursorToMapWindow();
if (!Game::get_game()->is_new_style())
set_current_view((View *)party_view);
return;
}
void ViewManager::set_actor_mode() {
set_current_view((View *)actor_view);
Events *event = Game::get_game()->get_event();
if (event->get_mode() == EQUIP_MODE || event->get_mode() == INPUT_MODE
|| event->get_mode() == ATTACK_MODE) {
actor_view->set_show_cursor(true);
actor_view->moveCursorToButton(2);
}
}
void ViewManager::set_spell_mode(Actor *caster, Obj *spell_container, bool eventMode) {
if (spell_view != nullptr) {
spell_view->set_spell_caster(caster, spell_container, eventMode);
set_current_view((View *)spell_view);
}
return;
}
void ViewManager::close_spell_mode() {
if (spell_view) {
//FIXME this should set previous view. Don't default to inventory view.
spell_view->release_focus();
if (!Game::get_game()->is_new_style())
set_inventory_mode();
else
close_current_view();
}
}
void ViewManager::open_doll_view(Actor *actor) {
Screen *screen = Game::get_game()->get_screen();
if (Game::get_game()->is_new_style()) {
if (actor == nullptr) {
actor = doll_view_get_next_party_member();
}
DollViewGump *doll = get_doll_view(actor);
if (doll == nullptr) {
uint16 x_off = Game::get_game()->get_game_x_offset();
uint16 y_off = Game::get_game()->get_game_y_offset();
uint8 num_doll_gumps = doll_gumps.size();
doll = new DollViewGump(config);
uint16 x = 12 * num_doll_gumps;
uint16 y = 12 * num_doll_gumps;
if (y + DOLLVIEWGUMP_HEIGHT > screen->get_height())
y = screen->get_height() - DOLLVIEWGUMP_HEIGHT;
doll->init(Game::get_game()->get_screen(), this, x + x_off, y + y_off, actor, font, party, tile_manager, obj_manager);
add_view((View *)doll);
add_gump(doll);
doll_gumps.push_back(doll);
} else {
move_gump_to_top(doll);
}
}
}
Actor *ViewManager::doll_view_get_next_party_member() {
if (doll_gumps.empty()) {
doll_next_party_member = 0; //reset to first party member when there are no doll gumps on screen.
}
Actor *a = party->get_actor(doll_next_party_member);
doll_next_party_member = (doll_next_party_member + 1) % party->get_party_size();
return a;
}
DollViewGump *ViewManager::get_doll_view(Actor *actor) {
for (DraggableView *draggable : doll_gumps) {
DollViewGump *view = (DollViewGump *)draggable;
if (view->get_actor() == actor) {
return view;
}
}
return nullptr;
}
ContainerViewGump *ViewManager::get_container_view(Actor *actor, Obj *obj) {
for (DraggableView *draggable : container_gumps) {
ContainerViewGump *view = (ContainerViewGump *)draggable;
if (actor) {
if (view->is_actor_container() && view->get_actor() == actor) {
return view;
}
} else if (obj) {
if (!view->is_actor_container() && view->get_container_obj() == obj) {
return view;
}
}
}
return nullptr;
}
void ViewManager::open_container_view(Actor *actor, Obj *obj) {
ContainerViewGump *view = get_container_view(actor, obj);
if (view == nullptr) {
uint16 x_off = Game::get_game()->get_game_x_offset();
uint16 y_off = Game::get_game()->get_game_y_offset();
uint16 container_x, container_y;
if (!Game::get_game()->is_new_style()) {
container_x = x_off;
container_y = y_off;
} else {
container_x = Game::get_game()->get_game_width() - 120 + x_off;
container_y = 20 + y_off;
}
view = new ContainerViewGump(config);
view->init(Game::get_game()->get_screen(), this, container_x, container_y, font, party, tile_manager, obj_manager, obj);
if (actor)
view->set_actor(actor);
else
view->set_container_obj(obj);
container_gumps.push_back(view);
add_gump(view);
add_view((View *)view);
} else {
move_gump_to_top(view);
}
}
void ViewManager::close_container_view(Actor *actor) {
ContainerViewGump *view = get_container_view(actor, nullptr);
if (view) {
close_gump(view);
}
}
void ViewManager::open_mapeditor_view() {
if (Game::get_game()->is_new_style() && Game::get_game()->is_roof_mode()) {
uint16 x_off = Game::get_game()->get_game_x_offset();
uint16 y_off = Game::get_game()->get_game_y_offset();
x_off += Game::get_game()->get_game_width() - 90;
MapEditorView *view = new MapEditorView(config);
view->init(Game::get_game()->get_screen(), this, x_off , y_off, font, party, tile_manager, obj_manager);
add_view((View *)view);
view->grab_focus();
}
}
void ViewManager::open_portrait_gump(Actor *a) {
if (Game::get_game()->is_new_style()) {
uint16 x_off = Game::get_game()->get_game_x_offset();
uint16 y_off = Game::get_game()->get_game_y_offset();
PortraitViewGump *view = new PortraitViewGump(config);
view->init(Game::get_game()->get_screen(), this, 62 + x_off, y_off, font, party, tile_manager, obj_manager, portrait, a);
add_view((View *)view);
add_gump(view);
view->grab_focus();
}
}
void ViewManager::open_sign_gump(const char *sign_text, uint16 length) {
if (Game::get_game()->is_using_text_gumps()) { // check should be useless
SignViewGump *view = new SignViewGump(config);
view->init(Game::get_game()->get_screen(), this, font, party, tile_manager, obj_manager, sign_text, length);
add_view((View *)view);
add_gump(view);
view->grab_focus();
}
}
void ViewManager::open_scroll_gump(const char *text, uint16 length) {
if (Game::get_game()->is_using_text_gumps()) { // check should be useless
ScrollViewGump *view = new ScrollViewGump(config);
view->init(Game::get_game()->get_screen(), this, font, party, tile_manager, obj_manager, string(text, length));
add_view((View *)view);
add_gump(view);
view->grab_focus();
}
}
void ViewManager::add_view(View *view) {
view->Show();
gui->AddWidget((GUI_Widget *)view);
if (Game::get_game()->is_new_style()) {
Game::get_game()->get_scroll()->moveToFront();
}
view->Redraw();
gui->Display();
}
void ViewManager::add_gump(DraggableView *gump) {
gumps.push_back(gump);
Game::get_game()->get_map_window()->set_walking(false);
if (ribbon) {
ribbon->extend();
}
}
void ViewManager::close_gump(DraggableView *gump) {
gumps.remove(gump);
container_gumps.remove(gump);
doll_gumps.remove(gump);
gump->close_view();
gump->Delete();
//gui->removeWidget((GUI_Widget *)gump);
if (gumps.empty() && ribbon != nullptr) {
ribbon->retract();
}
}
void ViewManager::close_all_gumps() {
while (!gumps.empty())
close_gump(gumps.front());
//TODO make sure all gump objects have been deleted by GUI.
}
void ViewManager::move_gump_to_top(DraggableView *gump) {
gump->moveToFront();
Game::get_game()->get_scroll()->moveToFront();
}
// callbacks for switching views
GUI_status partyViewButtonCallback(void *data) {
ViewManager *view_manager;
view_manager = (ViewManager *)data;
view_manager->set_party_mode();
return GUI_YUM;
}
GUI_status actorViewButtonCallback(void *data) {
ViewManager *view_manager;
view_manager = (ViewManager *)data;
view_manager->set_actor_mode();
return GUI_YUM;
}
GUI_status inventoryViewButtonCallback(void *data) {
ViewManager *view_manager;
view_manager = (ViewManager *)data;
view_manager->set_inventory_mode();
return GUI_YUM;
}
void ViewManager::double_click_obj(Obj *obj) {
Events *event = Game::get_game()->get_event();
if (Game::get_game()->get_usecode()->is_readable(obj)) { // look at a scroll or book
event->set_mode(LOOK_MODE);
event->look(obj);
event->endAction(false); // FIXME: should be in look()
} else if (event->newAction(USE_MODE))
event->select_obj(obj);
}
unsigned int ViewManager::get_display_weight(float weight) {
if (weight > 1)
return static_cast<unsigned int>(roundf(weight));
else if (weight > 0)
return 1;
else // weight == 0 (or somehow negative)
return 0;
}
// beginning of custom doll functions shared between DollWidget and DollViewGump
Common::Path ViewManager::getDollDataDirString() {
if (!DollDataDirString.empty())
return DollDataDirString;
DollDataDirString = GUI::get_gui()->get_data_dir();
Common::Path path;
build_path(DollDataDirString, "images", path);
DollDataDirString = path;
build_path(DollDataDirString, "gumps", path);
DollDataDirString = path;
build_path(DollDataDirString, "doll", path);
DollDataDirString = path;
return DollDataDirString;
}
Graphics::ManagedSurface *ViewManager::loadAvatarDollImage(Graphics::ManagedSurface *avatar_doll, bool orig) {
char filename[17]; //avatar_nn_nn.bmp\0
Common::Path imagefile;
uint8 portrait_num = Game::get_game()->get_portrait()->get_avatar_portrait_num();
Common::sprintf_s(filename, "avatar_%s_%02d.bmp", get_game_tag(Game::get_game()->get_game_type()), portrait_num);
if (orig) {
build_path(getDollDataDirString(), "orig_style", imagefile);
build_path(imagefile, filename, imagefile);
} else {
build_path(getDollDataDirString(), filename, imagefile);
}
if (avatar_doll)
delete avatar_doll;
NuvieBmpFile bmp;
avatar_doll = bmp.getSdlSurface32(imagefile);
if (avatar_doll == nullptr)
avatar_doll = loadGenericDollImage(orig);
return avatar_doll;
}
Graphics::ManagedSurface *ViewManager::loadCustomActorDollImage(Graphics::ManagedSurface *actor_doll, uint8 actor_num, bool orig) {
char filename[17]; //actor_nn_nnn.bmp\0
Common::Path imagefile;
if (actor_doll)
delete actor_doll;
Common::sprintf_s(filename, "actor_%s_%03d.bmp", get_game_tag(Game::get_game()->get_game_type()), actor_num);
if (orig) {
build_path(getDollDataDirString(), "orig_style", imagefile);
build_path(imagefile, filename, imagefile);
} else {
build_path(getDollDataDirString(), filename, imagefile);
}
NuvieBmpFile bmp;
actor_doll = bmp.getSdlSurface32(imagefile);
if (actor_doll == nullptr)
actor_doll = loadGenericDollImage(orig);
return actor_doll;
}
Graphics::ManagedSurface *ViewManager::loadGenericDollImage(bool orig) {
char filename[14]; //avatar_nn.bmp\0
Common::Path imagefile;
Common::sprintf_s(filename, "actor_%s.bmp", get_game_tag(Game::get_game()->get_game_type()));
if (orig) {
build_path(getDollDataDirString(), "orig_style", imagefile);
build_path(imagefile, filename, imagefile);
} else {
build_path(getDollDataDirString(), filename, imagefile);
}
NuvieBmpFile bmp;
return bmp.getSdlSurface32(imagefile);
}
} // End of namespace Nuvie
} // End of namespace Ultima

View File

@@ -0,0 +1,175 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUVIE_VIEWS_VIEW_MANAGER_H
#define NUVIE_VIEWS_VIEW_MANAGER_H
namespace Ultima {
namespace Nuvie {
class Configuration;
class GUI;
class TileManager;
class ObjManager;
class Portrait;
class Party;
class Player;
class Font;
class Actor;
class Obj;
class View;
class PartyView;
class PortraitView;
class InventoryView;
class ActorView;
class SpellView;
class ContainerViewGump;
class DollViewGump;
class DraggableView;
class SunMoonRibbon;
class MDSkyStripWidget;
using Std::list;
typedef enum { CURSOR_HEAD, CURSOR_NECK, CURSOR_CHEST, CURSOR_RIGHT_HAND, CURSOR_LEFT_HAND, CURSOR_RIGHT_RING, CURSOR_LEFT_RING, CURSOR_FEET,
CURSOR_LEFT, CURSOR_RIGHT, CURSOR_COMBAT, CURSOR_CHECK, CURSOR_HEART, CURSOR_PARTY, CURSOR_INVENTORY
} gumpCursorPos;
class ViewManager {
protected:
const Configuration *config;
int game_type;
GUI *gui;
Font *font;
TileManager *tile_manager;
ObjManager *obj_manager;
Party *party;
Portrait *portrait;
ActorView *actor_view;
InventoryView *inventory_view;
PortraitView *portrait_view;
PartyView *party_view;
SpellView *spell_view;
View *current_view;
Std::list<DraggableView *> container_gumps;
Std::list<DraggableView *> doll_gumps;
Std::list<DraggableView *> gumps;
uint8 doll_next_party_member;
SunMoonRibbon *ribbon;
MDSkyStripWidget *mdSkyWidget;
Common::Path DollDataDirString;
public:
ViewManager(const Configuration *cfg);
virtual ~ViewManager();
bool init(GUI *g, Font *f, Party *p, Player *player, TileManager *tm, ObjManager *om, Portrait *por);
void reload();
void update();
void set_portrait_mode(Actor *actor, const char *name);
void set_inventory_mode();
void set_party_mode();
void set_actor_mode();
void set_spell_mode(Actor *caster, Obj *spell_container, bool eventMode = false);
void close_spell_mode();
View *get_current_view() {
return current_view;
}
ActorView *get_actor_view() {
return actor_view;
}
InventoryView *get_inventory_view() {
return inventory_view;
}
PortraitView *get_portrait_view() {
return portrait_view;
}
PartyView *get_party_view() {
return party_view;
}
SpellView *get_spell_view() {
return spell_view;
}
MDSkyStripWidget *get_mdSkyWidget() {
return mdSkyWidget;
}
void close_current_view();
void open_doll_view(Actor *actor);
void open_container_view(Obj *obj) {
open_container_view(nullptr, obj);
}
void open_container_view(Actor *actor) {
open_container_view(actor, nullptr);
}
void close_container_view(Actor *actor);
void open_mapeditor_view();
void open_portrait_gump(Actor *a);
void open_sign_gump(const char *sign_text, uint16 length);
void open_scroll_gump(const char *text, uint16 length);
void close_gump(DraggableView *gump);
void close_all_gumps();
bool gumps_are_active() {
return !gumps.empty();
}
bool set_current_view(View *view);
void double_click_obj(Obj *obj);
unsigned int get_display_weight(float weight);
// custom doll functions shared between DollWidget and DollViewGump
Common::Path getDollDataDirString();
Graphics::ManagedSurface *loadAvatarDollImage(Graphics::ManagedSurface *avatar_doll, bool orig = false);
Graphics::ManagedSurface *loadCustomActorDollImage(Graphics::ManagedSurface *actor_doll, uint8 actor_num, bool orig = false);
Graphics::ManagedSurface *loadGenericDollImage(bool orig);
protected:
Actor *doll_view_get_next_party_member();
DollViewGump *get_doll_view(Actor *actor);
ContainerViewGump *get_container_view(Actor *actor, Obj *obj);
void open_container_view(Actor *actor, Obj *obj);
void add_gump(DraggableView *gump);
void add_view(View *view);
void move_gump_to_top(DraggableView *gump);
};
} // End of namespace Nuvie
} // End of namespace Ultima
#endif