PaperdollGump.cpp

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2003-2005  The Pentagram Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (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 #include "pent_include.h"
00020 #include "PaperdollGump.h"
00021 
00022 #include "Shape.h"
00023 #include "ShapeFrame.h"
00024 #include "ShapeInfo.h"
00025 #include "Actor.h"
00026 #include "RenderSurface.h"
00027 #include "GameData.h"
00028 #include "MainShapeArchive.h"
00029 #include "Font.h"
00030 #include "FontManager.h"
00031 #include "RenderedText.h"
00032 #include "GumpShapeArchive.h"
00033 #include "ButtonWidget.h"
00034 #include "MiniStatsGump.h"
00035 #include "GUIApp.h"
00036 #include "getObject.h"
00037 
00038 #include "IDataSource.h"
00039 #include "ODataSource.h"
00040 
00041 DEFINE_RUNTIME_CLASSTYPE_CODE(PaperdollGump,ContainerGump);
00042 
00043 
00044 
00045 // lots of CONSTANTS...
00046 struct equipcoords_struct {
00047         int x, y;
00048 } equipcoords[] = {
00049         { 0, 0 },
00050         { 24, 60 }, // shield
00051         { 36, 50 }, // arm
00052         { 40, 26 }, // head
00053         { 40, 63 }, // body
00054         { 40, 92 }, // legs
00055         { 16, 18 }  // weapon
00056 };
00057 
00058 struct statcords_struct {
00059 
00060     int xd, x, y;
00061 } statcoords[] = {
00062         { 90, 130, 24 },
00063         { 90, 130, 33 },
00064         { 90, 130, 42 },
00065         { 90, 130, 51 },
00066         { 90, 130, 60 },
00067         { 90, 130, 69 },
00068         { 90, 130, 78 }
00069 };
00070 
00071 static const int statdescwidth = 29;
00072 static const int statwidth = 15;
00073 static const int statheight = 8;
00074 static const int statfont = 7;
00075 static const int statdescfont = 0;
00076 
00077 const Pentagram::Rect backpack_rect(49, 25, 10, 25);
00078 
00079 static const int statbuttonshape = 38;
00080 static const int statbuttonx = 81;
00081 static const int statbuttony = 84;
00082 
00083 
00084 PaperdollGump::PaperdollGump()
00085         : ContainerGump()
00086 {
00087         for (int i = 0; i < 14; ++i) // ! constant
00088                 cached_text[i] = 0;
00089 }
00090 
00091 PaperdollGump::PaperdollGump(Shape* shape_, uint32 framenum_, uint16 owner,
00092                                                          uint32 Flags_, sint32 layer)
00093         : ContainerGump(shape_, framenum_, owner, Flags_, layer)
00094 {
00095         statbuttongid = 0;
00096         for (int i = 0; i < 14; ++i) // ! constant
00097                 cached_text[i] = 0;
00098 }
00099 
00100 PaperdollGump::~PaperdollGump()
00101 {
00102         for (int i = 0; i < 14; ++i) { // ! constant
00103                 delete cached_text[i];
00104                 cached_text[i] = 0;
00105         }
00106 }
00107 
00108 void PaperdollGump::InitGump(Gump* newparent, bool take_focus)
00109 {
00110         ContainerGump::InitGump(newparent, take_focus);
00111 
00112         FrameID button_up(GameData::GUMPS, statbuttonshape, 0);
00113         FrameID button_down(GameData::GUMPS, statbuttonshape, 1);
00114 
00115         Gump *widget = new ButtonWidget(statbuttonx, statbuttony,
00116                                                                         button_up, button_down);
00117         statbuttongid = widget->getObjId();
00118         widget->InitGump(this);
00119 }
00120 
00121 void PaperdollGump::Close(bool no_del)
00122 {
00123         // NOTE: this does _not_ call its direct parent's Close function
00124         // because we do not want to close the Gumps of our contents.
00125 
00126         // Make every item leave the fast area
00127         Container* c = getContainer(owner);
00128         if (!c) return; // Container gone!?
00129 
00130         std::list<Item*>& contents = c->contents;
00131         std::list<Item*>::iterator iter = contents.begin();
00132         while(iter != contents.end()) {
00133                 Item* item = *iter;
00134                 ++iter;
00135                 item->leaveFastArea();  // Can destroy the item
00136         }
00137 
00138         Item* o = getItem(owner);
00139         if (o)
00140                 o->clearGump(); 
00141 
00142         ItemRelativeGump::Close(no_del);
00143 }
00144 
00145 void PaperdollGump::PaintStat(RenderSurface* surf, unsigned int n,
00146                                                           std::string text, int val)
00147 {
00148         assert(n < 7); // constant!
00149 
00150         Pentagram::Font *font, *descfont;
00151 
00152         font = FontManager::get_instance()->getGameFont(statfont);
00153         descfont = FontManager::get_instance()->getGameFont(statdescfont);
00154         char buf[16]; // enough for uint32
00155         unsigned int remaining;
00156 
00157         if (!cached_text[2*n])
00158                 cached_text[2*n] = descfont->renderText(text, remaining,
00159                                                                                                 statdescwidth, statheight,
00160                                                                                                 Pentagram::Font::TEXT_RIGHT);
00161         cached_text[2*n]->draw(surf, statcoords[n].xd, statcoords[n].y);
00162 
00163         if (!cached_text[2*n+1] || cached_val[n] != val) {
00164                 delete cached_text[2*n+1];
00165                 sprintf(buf, "%d", val);
00166                 cached_text[2*n+1] = font->renderText(buf, remaining,
00167                                                                                           statwidth, statheight,
00168                                                                                           Pentagram::Font::TEXT_RIGHT);
00169                 cached_val[n] = val;
00170         }
00171         cached_text[2*n+1]->draw(surf, statcoords[n].x, statcoords[n].y);
00172 }
00173 
00174 void PaperdollGump::PaintStats(RenderSurface* surf, sint32 lerp_factor)
00175 {
00176         Actor* a = getActor(owner);
00177         assert(a);
00178 
00179         PaintStat(surf, 0, _TL_("STR"), a->getStr());
00180         PaintStat(surf, 1, _TL_("INT"), a->getInt());
00181         PaintStat(surf, 2, _TL_("DEX"), a->getDex());
00182         PaintStat(surf, 3, _TL_("ARMR"), a->getArmourClass());
00183         PaintStat(surf, 4, _TL_("HITS"), a->getHP());
00184         PaintStat(surf, 5, _TL_("MANA"), a->getMana());
00185         PaintStat(surf, 6, _TL_("WGHT"), a->getTotalWeight()/10);
00186 }
00187 
00188 void PaperdollGump::PaintThis(RenderSurface* surf, sint32 lerp_factor, bool scaled)
00189 {
00190         // paint self
00191         ItemRelativeGump::PaintThis(surf, lerp_factor, scaled);
00192 
00193         Actor* a = getActor(owner);
00194 
00195         if (!a) {
00196                 // Actor gone!?
00197                 Close();
00198                 return;
00199         }
00200 
00201         PaintStats(surf, lerp_factor);
00202 
00203         for (int i = 6; i >= 1; --i) { // constants
00204                 Item* item = getItem(a->getEquip(i));
00205                 if (!item) continue;
00206                 sint32 itemx,itemy;
00207                 uint32 frame = item->getFrame() + 1;
00208 
00209                 itemx = equipcoords[i].x;
00210                 itemy = equipcoords[i].y;
00211                 itemx += itemarea.x;
00212                 itemy += itemarea.y;
00213                 Shape* s = item->getShapeObject();
00214                 assert(s);
00215                 surf->Paint(s, frame, itemx, itemy);
00216         }
00217 
00218         if (display_dragging) {
00219                 sint32 itemx, itemy;
00220                 itemx = dragging_x + itemarea.x;
00221                 itemy = dragging_y + itemarea.y;
00222                 Shape* s = GameData::get_instance()->getMainShapes()->
00223                         getShape(dragging_shape);
00224                 assert(s);
00225                 surf->PaintInvisible(s, dragging_frame, itemx, itemy, false, (dragging_flags&Item::FLG_FLIPPED)!=0);
00226         }
00227 }
00228 
00229 // Find object (if any) at (mx,my)
00230 // (mx,my) are relative to parent
00231 uint16 PaperdollGump::TraceObjId(int mx, int my)
00232 {
00233         uint16 objid = Gump::TraceObjId(mx,my);
00234         if (objid && objid != 65535) return objid;
00235 
00236         ParentToGump(mx,my);
00237 
00238         Actor* a = getActor(owner);
00239 
00240         if (!a) return 0; // Container gone!?
00241 
00242         for (int i = 1; i <= 6; ++i) {
00243                 Item* item = getItem(a->getEquip(i));
00244                 if (!item) continue;
00245                 sint32 itemx,itemy;
00246 
00247                 itemx = equipcoords[i].x;
00248                 itemy = equipcoords[i].y;
00249                 itemx += itemarea.x;
00250                 itemy += itemarea.y;
00251                 Shape* s = item->getShapeObject();
00252                 assert(s);
00253                 ShapeFrame* frame = s->getFrame(item->getFrame() + 1);
00254 
00255                 if (frame->hasPoint(mx - itemx, my - itemy))
00256                 {
00257                         // found it
00258                         return item->getObjId();
00259                 }
00260         }
00261 
00262         // try backpack
00263         if (backpack_rect.InRect(mx - itemarea.x, my - itemarea.y)) {
00264                 if (a->getEquip(7)) // constants
00265                         return a->getEquip(7);
00266         }
00267 
00268         // didn't find anything, so return self
00269         return getObjId();
00270 }
00271 
00272 // get item coords relative to self
00273 bool PaperdollGump::GetLocationOfItem(uint16 itemid, int &gx, int &gy,
00274                                                                           sint32 lerp_factor)
00275 {
00276 
00277         Item* item = getItem(itemid);
00278         Item* parent = item->getParentAsContainer();
00279         if (!parent) return false;
00280         if (parent->getObjId() != owner) return false;
00281 
00283 
00284         if (item->getShape() == 529) 
00285         {
00286                 gx = backpack_rect.x;
00287                 gy = backpack_rect.y;
00288         } else {
00289                 int equiptype = item->getZ();
00290                 assert(equiptype >= 0 && equiptype <= 6); 
00291                 gx = equipcoords[equiptype].x;
00292                 gy = equipcoords[equiptype].y;
00293         }
00294         gx += itemarea.x;
00295         gy += itemarea.y;
00296 
00297         return true;
00298 }
00299 
00300 bool PaperdollGump::StartDraggingItem(Item* item, int mx, int my)
00301 {
00302         // can't drag backpack
00303         if (item->getShape() == 529) { 
00304                 return false;
00305         }
00306 
00307         bool ret = ContainerGump::StartDraggingItem(item, mx, my);
00308 
00309         // set dragging offset to center of item
00310         Shape* s = item->getShapeObject();
00311         assert(s);
00312         ShapeFrame* frame = s->getFrame(item->getFrame());
00313         assert(frame);
00314         
00315         GUIApp::get_instance()->setDraggingOffset(frame->width/2-frame->xoff,
00316                                                                                           frame->height/2-frame->yoff);
00317 
00318         return ret;
00319 }
00320 
00321 
00322 bool PaperdollGump::DraggingItem(Item* item, int mx, int my)
00323 {
00324         if (!itemarea.InRect(mx, my)) {
00325                 display_dragging = false;
00326                 return false;
00327         }
00328 
00329         Actor* a = getActor(owner);
00330         assert(a);
00331 
00332         bool over_backpack = false;
00333         Container* backpack = getContainer(a->getEquip(7)); // constant!
00334                         
00335         if (backpack && backpack_rect.InRect(mx - itemarea.x, my - itemarea.y)) {
00336                 over_backpack = true;
00337         }
00338 
00339         display_dragging = true;
00340 
00341         dragging_shape = item->getShape();
00342         dragging_frame = item->getFrame();
00343         dragging_flags = item->getFlags();
00344 
00345         int equiptype = item->getShapeInfo()->equiptype;
00346         // determine target location and set dragging_x/y
00347         if (!over_backpack && equiptype) {
00348                 // check if item will fit (weight/volume/etc...)
00349                 if (!a->CanAddItem(item, true)) {
00350                         display_dragging = false;
00351                         return false;
00352                 }
00353 
00354                 dragging_frame++;
00355                 dragging_x = equipcoords[equiptype].x;
00356                 dragging_y = equipcoords[equiptype].y;
00357         } else {
00358                 // drop in backpack
00359 
00360                 if (!backpack->CanAddItem(item, true)) {
00361                         display_dragging = false;
00362                         return false;
00363                 }
00364 
00365                 dragging_x = backpack_rect.x + backpack_rect.w/2;
00366                 dragging_y = backpack_rect.y + backpack_rect.h/2;
00367         }
00368 
00369         return true;
00370 }
00371 
00372 void PaperdollGump::DropItem(Item* item, int mx, int my)
00373 {
00374         display_dragging = false;
00375 
00376         Actor* a = getActor(owner);
00377         assert(a);
00378 
00379         bool over_backpack = false;
00380         Container* backpack = getContainer(a->getEquip(7)); // constant!
00381                         
00382         if (backpack && backpack_rect.InRect(mx - itemarea.x, my - itemarea.y)) {
00383                 over_backpack = true;
00384         }
00385 
00386         int equiptype = item->getShapeInfo()->equiptype;
00387         if (!over_backpack && equiptype) {
00388                 item->moveToContainer(a);
00389         } else {
00390                 item->moveToContainer(backpack);
00391                 item->randomGumpLocation();
00392         }
00393 }
00394 
00395 void PaperdollGump::ChildNotify(Gump *child, uint32 message)
00396 {
00397         if (child->getObjId() == statbuttongid &&
00398                 message == ButtonWidget::BUTTON_CLICK)
00399         {
00400                 // check if there already is an open MiniStatsGump
00401                 Gump* desktop = GUIApp::get_instance()->getDesktopGump();
00402                 if (!desktop->FindGump(MiniStatsGump::ClassType)) {
00403                         Gump* gump = new MiniStatsGump(0, 0);
00404                         gump->InitGump(0);
00405                         gump->setRelativePosition(BOTTOM_RIGHT, -5, -5);
00406                 }
00407         }
00408 }
00409 
00410 
00411 void PaperdollGump::saveData(ODataSource* ods)
00412 {
00413         ContainerGump::saveData(ods);
00414 
00415         ods->write2(statbuttongid);
00416 }
00417 
00418 bool PaperdollGump::loadData(IDataSource* ids, uint32 version)
00419 {
00420         if (!ContainerGump::loadData(ids, version)) return false;
00421 
00422         statbuttongid = ids->read2();
00423 
00424         return true;
00425 }

Generated on Fri Jul 27 22:27:28 2007 for pentagram by  doxygen 1.4.7