Face_stats.cc

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2001-2004 The Exult Team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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           // update dirty region, if required
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  *  Paint on screen.
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  *  Update Dirty Region
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  *  Portrait_button
00126  */
00127 
00128 class Portrait_button : public Face_button
00129 {
00130 protected:
00131   Stat_bar  *hp;    // Bar for HP
00132   Stat_bar  *mana;    // Bar for 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           // update dirty region, if required
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  *  Paint on screen.
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  *  Face_stats
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  *  Paint on screen.
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  *  On a Button?
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 // add dirty region, if dirty
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 // Has this changed?
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 // Delete all the buttons
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   // In BG only Npc's 0 to 10 have paperdolls/gumps
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     // In BG only Npc's 0 to 10 have paperdolls/gumps
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  *  Add an object.  If mx, my, sx, sy are all -1, the object's position
00444  *  is calculated by 'paint()'.  If they're all -2, it's assumed that
00445  *  obj->cx, obj->cy are already correct.
00446  *
00447  *  Output: 0 if cannot add it.
00448  */
00449 
00450 int Face_stats::add
00451   (
00452   Game_object *obj,
00453   int mx, int my,     // Mouse location.
00454   int sx, int sy,     // Screen location of obj's hotspot.
00455   bool dont_check,    // Skip volume check.
00456   bool combine      // True to try to combine obj.  MAY
00457           //   cause obj to be deleted.
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 // Statics
00481 
00482 int Face_stats::mode = 0;
00483 Face_stats *Face_stats::self = 0;
00484 
00485 // Creates if doesn't already exist
00486 void Face_stats::CreateGump()
00487 {
00488   if (!self)
00489   {
00490     new Face_stats();
00491     gumpman->add_gump(self);
00492   }
00493 }
00494 
00495 // Removes is exists
00496 void Face_stats::RemoveGump()
00497 {
00498   if (self) gumpman->close_gump(self);
00499   //delete self;
00500 }
00501 
00502 // Increments the state of the gump
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;     // FOR NOW, skip if new game.
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 }

Generated on Mon Jul 9 14:42:46 2007 for ExultEngine by  doxygen 1.5.1