00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef HAVE_CONFIG_H
00020 # include <config.h>
00021 #endif
00022
00023 #include "Face_stats.h"
00024 #include "Face_button.h"
00025 #include "Paperdoll_gump.h"
00026 #include "actors.h"
00027 #include "party.h"
00028 #include "exult_flx.h"
00029 #include "gamewin.h"
00030 #include "game.h"
00031 #include "Gump_manager.h"
00032
00033
00034 #define PALETTE_INDEX_RED 22
00035 #define PALETTE_INDEX_GREEN 64
00036 #define PALETTE_INDEX_BLUE 79
00037
00038 #define PORTRAIT_NUM_MODES 3
00039
00040 #define PORTRAIT_WIDTH 40
00041
00042 class Stat_bar : public Gump_button
00043 {
00044 Actor *actor;
00045 int prop;
00046 int prop_max;
00047 unsigned char colour;
00048
00049 int val;
00050 int max_val;
00051 public:
00052 Stat_bar(Gump *par, int px, int py, Actor *a, int s, int m, unsigned char c);
00053 virtual void double_clicked(int x, int y);
00054 virtual void paint();
00055
00056 virtual void activate() {}
00057 virtual void push() {}
00058 virtual void unpush() {}
00059
00060 virtual void update_widget();
00061
00062 virtual bool is_draggable() { return false; }
00063 };
00064
00065 Stat_bar::Stat_bar (Gump *par, int px, int py, Actor *a, int s, int m, unsigned char c)
00066 : Gump_button(par, EXULT_FLX_HP_BAR_SHP, px, py, SF_EXULT_FLX),
00067 actor(a), prop(s), prop_max(m), colour(c), val(-256), max_val(-256)
00068 {
00069
00070 gwin->add_dirty(get_rect());
00071 val = actor->get_effective_prop(prop);
00072 max_val = actor->get_effective_prop(prop_max);
00073 }
00074
00075 void Stat_bar::double_clicked(int x, int y)
00076 {
00077 gumpman->add_gump(actor, game->get_shape("gumps/statsdisplay"));
00078 }
00079
00080
00081
00082
00083
00084
00085
00086 void Stat_bar::paint
00087 (
00088 )
00089 {
00090 Gump_button::paint();
00091
00092 int width = (val * 32) / (max_val ? max_val : 1);
00093
00094 if (width > 0)
00095 {
00096 if (width > 32) width = 32;
00097
00098 int px = x;
00099 int py = y;
00100
00101 if (parent)
00102 {
00103 px += parent->get_x();
00104 py += parent->get_y();
00105 }
00106
00107 gwin->get_win()->fill8(colour, width, 3, px, py);
00108 }
00109 }
00110
00111
00112
00113
00114
00115 void Stat_bar::update_widget()
00116 {
00117 if (val != actor->get_effective_prop(prop) || max_val != actor->get_effective_prop(prop_max))
00118 gwin->add_dirty(get_rect());
00119
00120 val = actor->get_effective_prop(prop);
00121 max_val = actor->get_effective_prop(prop_max);
00122 }
00123
00124
00125
00126
00127
00128 class Portrait_button : public Face_button
00129 {
00130 protected:
00131 Stat_bar *hp;
00132 Stat_bar *mana;
00133 bool hit;
00134 int pois;
00135 int prot;
00136 public:
00137 Portrait_button(Gump *par, int px, int py, Actor *a);
00138 virtual ~Portrait_button();
00139 virtual void double_clicked(int x, int y);
00140 virtual void paint();
00141
00142
00143 virtual void update_widget();
00144
00145 virtual int on_button(int mx, int my);
00146
00147 virtual Rectangle get_rect();
00148
00149 virtual bool is_draggable() { return false; }
00150 };
00151
00152
00153 Portrait_button::Portrait_button(Gump *par, int px, int py, Actor *a)
00154 : Face_button(par, px+14, py-20, a), hp(0), mana(0)
00155 {
00156 hp = new Stat_bar(par, px+4, py - 10, a, Actor::health, Actor::strength, PALETTE_INDEX_RED);
00157
00158 if (actor->get_npc_num() == 0)
00159 mana = new Stat_bar(par, px+4, py - 5, a, Actor::mana, Actor::magic, PALETTE_INDEX_BLUE);
00160
00161 hit = actor->was_hit();
00162 pois = actor->get_flag(Obj_flags::poisoned);
00163 prot = actor->get_flag(Obj_flags::protection);
00164
00165 gwin->add_dirty(get_rect());
00166 }
00167
00168 Portrait_button::~Portrait_button()
00169 {
00170 if (hp) delete hp;
00171 if (mana) delete mana;
00172 }
00173
00174 void Portrait_button::double_clicked(int x, int y)
00175 {
00176 if (hp && hp->on_button(x, y))
00177 hp->double_clicked(x, y);
00178 else if (mana && mana->on_button(x, y))
00179 mana->double_clicked(x, y);
00180 else
00181 actor->show_inventory();
00182 }
00183
00184 int Portrait_button::on_button(int x, int y)
00185 {
00186 if (hp && hp->on_button(x, y))
00187 return true;
00188 else if (mana && mana->on_button(x, y))
00189 return true;
00190 else if (Face_button::on_button(x, y))
00191 return true;
00192
00193 return false;
00194 }
00195
00196 void Portrait_button::update_widget()
00197 {
00198 Face_button::update_widget();
00199 if (hp) hp->update_widget();
00200 if (mana) mana->update_widget();
00201
00202 if (hit != actor->was_hit() ||
00203 pois != actor->get_flag(Obj_flags::poisoned) ||
00204 prot != actor->get_flag(Obj_flags::protection))
00205 {
00206 Rectangle r = get_rect();
00207 gwin->add_dirty(r);
00208 hit = actor->was_hit();
00209 pois = actor->get_flag(Obj_flags::poisoned);
00210 prot = actor->get_flag(Obj_flags::protection);
00211 r = get_rect();
00212 gwin->add_dirty(r);
00213 }
00214 }
00215
00216
00217
00218
00219
00220 void Portrait_button::paint()
00221 {
00222 Face_button::paint();
00223
00224 Shape_frame *s = get_shape();
00225
00226 if (s)
00227 {
00228 int px = x;
00229 int py = y;
00230
00231 if (parent)
00232 {
00233 px += parent->get_x();
00234 py += parent->get_y();
00235 }
00236
00237 if (hit)
00238 {
00239 sman->paint_outline(px, py, s, HIT_PIXEL);
00240 }
00241 else if (pois)
00242 {
00243 sman->paint_outline(px, py, s, POISON_PIXEL);
00244 }
00245 else if (prot)
00246 {
00247 sman->paint_outline(px, py, s, PROTECT_PIXEL);
00248 }
00249 }
00250
00251 if (hp) hp->paint();
00252 if (mana) mana->paint();
00253 }
00254
00255 Rectangle Portrait_button::get_rect()
00256 {
00257 Rectangle rect = Face_button::get_rect();
00258 if (hit || pois || prot) rect.enlarge(2);
00259
00260 if (hp)
00261 {
00262 Rectangle r = hp->get_rect();
00263 rect.add(r);
00264 }
00265 if (mana)
00266 {
00267 Rectangle r = mana->get_rect();
00268 rect.add(r);
00269 }
00270
00271 return rect;
00272 }
00273
00274
00275
00276
00277
00278 Face_stats::Face_stats() : Gump(0, 0, 0, 0, SF_GUMPS_VGA)
00279 {
00280 if (self) throw exult_exception("Only 1 Set of Party Portraits Allowed!");
00281
00282 for (int i = 1; i < 8; i++)
00283 {
00284 npc_nums[i] = -1;
00285 party[i] = 0;
00286 }
00287
00288
00289 create_buttons();
00290
00291 self = this;
00292 }
00293
00294 Face_stats::~Face_stats()
00295 {
00296 delete_buttons();
00297
00298 gwin->set_all_dirty();
00299 self = 0;
00300 }
00301
00302
00303
00304
00305
00306 void Face_stats::paint
00307 (
00308 )
00309 {
00310 for (int i = 0; i < 8; i++)
00311 if (party[i]) party[i]->paint();
00312 }
00313
00314
00315
00316
00317
00318 Gump_button *Face_stats::on_button(int mx, int my)
00319 {
00320 for (int i = 0; i < 8; i++)
00321 if (party[i] && party[i]->on_button(mx, my))
00322 return party[i];
00323
00324
00325 return 0;
00326 }
00327
00328
00329 void Face_stats::update_gump()
00330 {
00331 if (has_changed())
00332 {
00333 delete_buttons();
00334 create_buttons();
00335 }
00336 else
00337 {
00338 for (int i = 0; i < 8; i++)
00339 if (party[i]) party[i]->update_widget();
00340 }
00341 }
00342
00343
00344 bool Face_stats::has_changed()
00345 {
00346 if (resx != gwin->get_width() || resy != gwin->get_height())
00347 return true;
00348
00349 if (party_size != partyman->get_count()) return true;
00350
00351 for (int i = 0; i < party_size; i++)
00352 if (npc_nums[i+1] != partyman->get_member(i))
00353 return true;
00354
00355 return false;
00356 }
00357
00358
00359 void Face_stats::delete_buttons()
00360 {
00361 gwin->add_dirty(get_rect());
00362
00363 for (int i = 0; i < 8; i++)
00364 {
00365 if (party[i])
00366 {
00367 delete party[i];
00368 party[i] = 0;
00369 }
00370 npc_nums[i] = -1;
00371 }
00372
00373 resx = 0;
00374 resy = 0;
00375 }
00376
00377 void Face_stats::create_buttons()
00378 {
00379 int i;
00380 int pos = 0;
00381 int width = PORTRAIT_WIDTH;
00382
00383 resx = gwin->get_width();
00384 resy = gwin->get_height();
00385 x = 0;
00386 y = resy;
00387
00388 party_size = partyman->get_count();
00389
00390 int num_to_paint = 0;
00391
00392
00393 for (i = 0; i < party_size; i++) {
00394 int num = partyman->get_member(i);
00395 if (GAME_SI || (num >= 0 && num <=10)) ++num_to_paint;
00396 }
00397
00398 if (mode == 0) pos = 0;
00399 else if (mode == 1) pos = (resx - (num_to_paint+1)*PORTRAIT_WIDTH)/2;
00400 else if (mode == 2)
00401 {
00402 pos = resx - PORTRAIT_WIDTH;
00403 width = - PORTRAIT_WIDTH;
00404 }
00405
00406 std::memset (party, 0, sizeof(party));
00407
00408 party[0] = new Portrait_button(this, pos, 0, gwin->get_main_actor());
00409
00410 for (i = 0; i < party_size; i++)
00411 {
00412 npc_nums[i+1] = partyman->get_member(i);
00413
00414 if (GAME_SI || (npc_nums[i+1] >= 0 && npc_nums[i+1] <=10)) {
00415 pos += width;
00416 party[i+1] = new Portrait_button(this, pos, 0, gwin->get_npc(npc_nums[i+1]));
00417 }
00418 else {
00419 party[i+1] = 0;
00420 }
00421 }
00422
00423 region.x = region.y = region.w = region.h = 0;
00424
00425 for (i = 0; i < 8; i++)
00426 if (party[i])
00427 {
00428 Rectangle r = party[i]->get_rect();
00429 region.add(r);
00430 }
00431 }
00432
00433 bool Face_stats::has_point(int x, int y)
00434 {
00435
00436 for (int i = 0; i < 8; i++)
00437 if (party[i] && party[i]->on_button(x, y)) return true;
00438
00439 return false;
00440 }
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 int Face_stats::add
00451 (
00452 Game_object *obj,
00453 int mx, int my,
00454 int sx, int sy,
00455 bool dont_check,
00456 bool combine
00457
00458 )
00459 {
00460 if (sx < 0 && sy < 0 && my < 0 && mx < 0) return 0;
00461
00462
00463 for (int i = 0; i < 8; i++)
00464 if (party[i] && party[i]->on_button(mx, my))
00465 return party[i]->get_actor()->add(obj, dont_check,
00466 combine);
00467
00468 return (0);
00469 }
00470
00471 Container_game_object *Face_stats::find_actor(int mx, int my)
00472 {
00473
00474 for (int i = 0; i < 8; i++) if (party[i] && party[i]->on_button(mx, my))
00475 return party[i]->get_actor();
00476
00477 return 0;
00478 }
00479
00480
00481
00482 int Face_stats::mode = 0;
00483 Face_stats *Face_stats::self = 0;
00484
00485
00486 void Face_stats::CreateGump()
00487 {
00488 if (!self)
00489 {
00490 new Face_stats();
00491 gumpman->add_gump(self);
00492 }
00493 }
00494
00495
00496 void Face_stats::RemoveGump()
00497 {
00498 if (self) gumpman->close_gump(self);
00499
00500 }
00501
00502
00503 void Face_stats::AdvanceState()
00504 {
00505 if (!self) CreateGump();
00506 else
00507 {
00508 RemoveGump();
00509
00510 mode++;
00511 mode %=PORTRAIT_NUM_MODES;
00512 if (mode) CreateGump();
00513 }
00514 }
00515
00516 void Face_stats::save_config(Configuration *config)
00517 {
00518 if(self)
00519 config->set("config/gameplay/facestats",mode,true);
00520 else
00521 config->set("config/gameplay/facestats",-1,true);
00522 }
00523
00524 void Face_stats::load_config(Configuration *config)
00525 {
00526 int nmode;
00527 if (Game::get_game_type() == EXULT_DEVEL_GAME)
00528 return;
00529 config->value("config/gameplay/facestats",nmode,-1);
00530 if(self)
00531 RemoveGump();
00532 if(nmode>=0) {
00533 mode = nmode%PORTRAIT_NUM_MODES;
00534 CreateGump();
00535 }
00536 }