00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020 #include "ContainerGump.h"
00021
00022 #include "Shape.h"
00023 #include "ShapeFrame.h"
00024 #include "ShapeInfo.h"
00025 #include "Container.h"
00026 #include "RenderSurface.h"
00027 #include "GUIApp.h"
00028 #include "Kernel.h"
00029 #include "GameData.h"
00030 #include "MainShapeArchive.h"
00031 #include "Mouse.h"
00032 #include "SliderGump.h"
00033 #include "GumpNotifyProcess.h"
00034 #include "ItemFactory.h"
00035 #include "SplitItemProcess.h"
00036 #include "GameMapGump.h"
00037 #include "MainActor.h"
00038 #include "getObject.h"
00039
00040 #include "IDataSource.h"
00041 #include "ODataSource.h"
00042
00043 DEFINE_RUNTIME_CLASSTYPE_CODE(ContainerGump,ItemRelativeGump);
00044
00045 ContainerGump::ContainerGump()
00046 : ItemRelativeGump(), display_dragging(false)
00047 {
00048
00049 }
00050
00051 ContainerGump::ContainerGump(Shape* shape_, uint32 framenum_, uint16 owner,
00052 uint32 Flags_, sint32 layer)
00053 : ItemRelativeGump(0, 0, 5, 5, owner, Flags_, layer),
00054 display_dragging(false)
00055 {
00056 shape = shape_;
00057 framenum = framenum_;
00058 }
00059
00060 ContainerGump::~ContainerGump()
00061 {
00062
00063 }
00064
00065 void ContainerGump::InitGump(Gump* newparent, bool take_focus)
00066 {
00067 ShapeFrame* sf = shape->getFrame(framenum);
00068 assert(sf);
00069
00070 dims.w = sf->width;
00071 dims.h = sf->height;
00072
00073
00074 ItemRelativeGump::InitGump(newparent, take_focus);
00075
00076
00077 Container* c = getContainer(owner);
00078
00079 if (!c) return;
00080
00081
00082
00083 }
00084
00085 void ContainerGump::getItemCoords(Item* item, sint32& itemx, sint32& itemy)
00086 {
00087 item->getGumpLocation(itemx,itemy);
00088
00089 if (itemx == 0xFF && itemy == 0xFF) {
00090
00091
00092
00093 itemx = std::rand() % itemarea.w;
00094 itemy = std::rand() % itemarea.h;
00095
00096 item->setGumpLocation(itemx, itemy);
00097 }
00098
00099 itemx += itemarea.x;
00100 itemy += itemarea.y;
00101 }
00102
00103
00104 void ContainerGump::PaintThis(RenderSurface* surf, sint32 lerp_factor, bool scaled)
00105 {
00106
00107 ItemRelativeGump::PaintThis(surf, lerp_factor, scaled);
00108
00109 Container* c = getContainer(owner);
00110
00111 if (!c) {
00112
00113 Close();
00114 return;
00115 }
00116
00117 std::list<Item*>& contents = c->contents;
00118 sint32 gametick = Kernel::get_instance()->getFrameNum();
00119
00121 bool paintEditorItems = GUIApp::get_instance()->isPaintEditorItems();
00122
00123 std::list<Item*>::iterator iter;
00124 for (iter = contents.begin(); iter != contents.end(); ++iter) {
00125 Item* item = *iter;
00126 item->setupLerp(gametick);
00127
00128 if (!paintEditorItems && item->getShapeInfo()->is_editor())
00129 continue;
00130
00131 sint32 itemx,itemy;
00132 getItemCoords(item, itemx, itemy);
00133 Shape* s = item->getShapeObject();
00134 assert(s);
00135 surf->Paint(s, item->getFrame(), itemx, itemy);
00136 }
00137
00138
00139 if (display_dragging) {
00140 sint32 itemx, itemy;
00141 itemx = dragging_x + itemarea.x;
00142 itemy = dragging_y + itemarea.y;
00143 Shape* s = GameData::get_instance()->getMainShapes()->
00144 getShape(dragging_shape);
00145 assert(s);
00146 surf->PaintInvisible(s, dragging_frame, itemx, itemy, false, (dragging_flags&Item::FLG_FLIPPED)!=0);
00147 }
00148
00149 }
00150
00151
00152
00153 uint16 ContainerGump::TraceObjId(int mx, int my)
00154 {
00155 uint16 objid = Gump::TraceObjId(mx,my);
00156 if (objid && objid != 65535) return objid;
00157
00158 ParentToGump(mx,my);
00159
00160 Container* c = getContainer(owner);
00161
00162 if (!c) return 0;
00163
00164 bool paintEditorItems = GUIApp::get_instance()->isPaintEditorItems();
00165
00166 std::list<Item*>& contents = c->contents;
00167 std::list<Item*>::reverse_iterator iter;
00168
00169 for (iter = contents.rbegin(); iter != contents.rend(); ++iter) {
00170 Item* item = *iter;
00171 if (!paintEditorItems && item->getShapeInfo()->is_editor())
00172 continue;
00173
00174 sint32 itemx,itemy;
00175 getItemCoords(item, itemx, itemy);
00176 Shape* s = item->getShapeObject();
00177 assert(s);
00178 ShapeFrame* frame = s->getFrame(item->getFrame());
00179
00180 if (frame->hasPoint(mx - itemx, my - itemy))
00181 {
00182
00183 return item->getObjId();
00184 }
00185 }
00186
00187
00188 return getObjId();
00189 }
00190
00191
00192 bool ContainerGump::GetLocationOfItem(uint16 itemid, int &gx, int &gy,
00193 sint32 lerp_factor)
00194 {
00195 Item* item = getItem(itemid);
00196 Item* parent = item->getParentAsContainer();
00197 if (!parent) return false;
00198 if (parent->getObjId() != owner) return false;
00199
00201
00202 sint32 itemx, itemy;
00203 getItemCoords(item, itemx, itemy);
00204
00205 gx = itemx;
00206 gy = itemy;
00207
00208 return false;
00209 }
00210
00211
00212
00213 void ContainerGump::GetItemLocation(sint32 lerp_factor)
00214 {
00215 Item *it = getItem(owner);
00216
00217 if (!it) {
00218
00219
00220 Close();
00221 return;
00222 }
00223
00224 int gx, gy;
00225 Item* topitem = it;
00226
00227 Container *p = it->getParentAsContainer();
00228 if (p) {
00229 while (p->getParentAsContainer()) {
00230 p = p->getParentAsContainer();
00231 }
00232
00233 topitem = p;
00234 }
00235
00236 Gump *gump = GetRootGump()->FindGump(GameMapGump::ClassType);
00237 assert(gump);
00238 gump->GetLocationOfItem(topitem->getObjId(), gx, gy, lerp_factor);
00239
00240
00241
00242 gy = gy-it->getShapeInfo()->z*8-16;
00243 gump->GumpToScreenSpace(gx,gy);
00244
00245
00246 if (parent) parent->ScreenSpaceToGump(gx,gy);
00247
00248
00249 ix = gx-dims.w/2;
00250 iy = gy-dims.h;
00251 }
00252
00253 void ContainerGump::Close(bool no_del)
00254 {
00255
00256
00257 Container* c = getContainer(owner);
00258 if (!c) return;
00259
00260 std::list<Item*>& contents = c->contents;
00261 std::list<Item*>::iterator iter = contents.begin();
00262 while(iter != contents.end()) {
00263 Item* item = *iter;
00264 ++iter;
00265 Gump* g = getGump(item->getGump());
00266 if (g) {
00267 g->Close();
00268 }
00269 item->leaveFastArea();
00270 }
00271
00272 Item* o = getItem(owner);
00273 if (o)
00274 o->clearGump();
00275
00276 ItemRelativeGump::Close(no_del);
00277 }
00278
00279 Container* ContainerGump::getTargetContainer(Item* item, int mx, int my)
00280 {
00281 int px = mx, py = my;
00282 GumpToParent(px, py);
00283 Container* targetcontainer = getContainer(TraceObjId(px, py));
00284
00285 if (targetcontainer && targetcontainer->getObjId() == item->getObjId())
00286 targetcontainer = 0;
00287
00288 if (targetcontainer) {
00289 ShapeInfo * targetinfo = targetcontainer->getShapeInfo();
00290 if ((targetcontainer->getObjId() == item->getObjId()) ||
00291 targetinfo->is_land() ||
00292 (targetcontainer->getFlags() & Item::FLG_IN_NPC_LIST))
00293 {
00294 targetcontainer = 0;
00295 }
00296 }
00297
00298 if (!targetcontainer)
00299 targetcontainer = getContainer(owner);
00300
00301 return targetcontainer;
00302 }
00303
00304
00305 Gump* ContainerGump::OnMouseDown(int button, int mx, int my)
00306 {
00307 Gump* handled = Gump::OnMouseDown(button, mx, my);
00308 if (handled) return handled;
00309
00310
00311 if (button == BUTTON_LEFT)
00312 return this;
00313
00314 return 0;
00315 }
00316
00317 void ContainerGump::OnMouseClick(int button, int mx, int my)
00318 {
00319 if (button == BUTTON_LEFT)
00320 {
00321 if (GUIApp::get_instance()->isAvatarInStasis()) {
00322 pout << "Can't: avatarInStasis" << std::endl;
00323 return;
00324 }
00325
00326 uint16 objID = TraceObjId(mx, my);
00327
00328 Item *item = getItem(objID);
00329 if (item) {
00330 item->dumpInfo();
00331
00332
00333 item->callUsecodeEvent_look();
00334 }
00335 }
00336 }
00337
00338 void ContainerGump::OnMouseDouble(int button, int mx, int my)
00339 {
00340 if (button == BUTTON_LEFT)
00341 {
00342 if (GUIApp::get_instance()->isAvatarInStasis()) {
00343 pout << "Can't: avatarInStasis" << std::endl;
00344 return;
00345 }
00346
00347 uint16 objID = TraceObjId(mx, my);
00348
00349 if (objID == getObjId()) {
00350 objID = owner;
00351 }
00352
00353 Item *item = getItem(objID);
00354 if (item) {
00355 item->dumpInfo();
00356
00357 MainActor* avatar = getMainActor();
00358 if (objID == owner || avatar->canReach(item, 128)) {
00359
00360 item->use();
00361 } else {
00362 GUIApp::get_instance()->flashCrossCursor();
00363 }
00364 }
00365 }
00366 }
00367
00368
00369 bool ContainerGump::StartDraggingItem(Item* item, int mx, int my)
00370 {
00371
00372
00373
00374 Container* c = getContainer(owner);
00375 assert(c);
00376
00377
00378 MainActor* avatar = getMainActor();
00379 if (!avatar->canReach(c, 128)) return false;
00380
00381 sint32 itemx,itemy;
00382 getItemCoords(item, itemx, itemy);
00383
00384 GUIApp::get_instance()->setDraggingOffset(mx - itemx, my - itemy);
00385
00386 return true;
00387 }
00388
00389 bool ContainerGump::DraggingItem(Item* item, int mx, int my)
00390 {
00391 Container* c = getContainer(owner);
00392 assert(c);
00393
00394
00395 MainActor* avatar = getMainActor();
00396 if (!avatar->canReach(c, 128)) {
00397 display_dragging = false;
00398 return false;
00399 }
00400
00401 int dox, doy;
00402 GUIApp::get_instance()->getDraggingOffset(dox, doy);
00403 GUIApp::get_instance()->setMouseCursor(GUIApp::MOUSE_TARGET);
00404 display_dragging = true;
00405
00406 dragging_shape = item->getShape();
00407 dragging_frame = item->getFrame();
00408 dragging_flags = item->getFlags();
00409
00410
00411
00412 dragging_x = mx - itemarea.x - dox;
00413 dragging_y = my - itemarea.y - doy;
00414
00415 if (dragging_x < 0 || dragging_x >= itemarea.w ||
00416 dragging_y < 0 || dragging_y >= itemarea.h) {
00417 display_dragging = false;
00418 return false;
00419 }
00420
00421
00422 Container* target = getTargetContainer(item,mx,my);
00423 if (!target || !target->CanAddItem(item, true)) {
00424 display_dragging = false;
00425 return false;
00426 }
00427
00428 return true;
00429 }
00430
00431 void ContainerGump::DraggingItemLeftGump(Item* item)
00432 {
00433 display_dragging = false;
00434 }
00435
00436
00437 void ContainerGump::StopDraggingItem(Item* item, bool moved)
00438 {
00439 if (!moved) return;
00440 }
00441
00442 void ContainerGump::DropItem(Item* item, int mx, int my)
00443 {
00444 display_dragging = false;
00445
00446 int px = mx, py = my;
00447 GumpToParent(px, py);
00448
00449 Item* targetitem = getItem(TraceObjId(px, py));
00450 Container* targetcontainer = p_dynamic_cast<Container*>(targetitem);
00451
00452
00453 if (item->getShapeInfo()->hasQuantity() &&
00454 item->getQuality() > 1)
00455 {
00456
00457
00458 Item* splittarget = 0;
00459
00460
00461 if (targetitem && item->canMergeWith(targetitem)) {
00462 splittarget = targetitem;
00463 }
00464
00465 if (!splittarget) {
00466
00467 splittarget = ItemFactory::createItem(
00468 item->getShape(), item->getFrame(), 0,
00469 item->getFlags() & (Item::FLG_DISPOSABLE | Item::FLG_OWNED | Item::FLG_INVISIBLE | Item::FLG_FLIPPED | Item::FLG_FAST_ONLY | Item::FLG_LOW_FRICTION), item->getNpcNum(), item->getMapNum(),
00470 item->getExtFlags() & (Item::EXT_SPRITE | Item::EXT_HIGHLIGHT | Item::EXT_TRANSPARENT), true);
00471 if (!splittarget) {
00472 perr << "ContainerGump failed to create item ("
00473 << item->getShape() << "," << item->getFrame()
00474 << ") while splitting" << std::endl;
00475 return;
00476 }
00477
00478
00479 if (targetcontainer) {
00480 splittarget->moveToContainer(targetcontainer);
00481 splittarget->randomGumpLocation();
00482 } else {
00483 splittarget->moveToContainer(getContainer(owner));
00484 splittarget->setGumpLocation(dragging_x, dragging_y);
00485 }
00486 }
00487
00488 SliderGump* slidergump = new SliderGump(100, 100,
00489 0, item->getQuality(),
00490 item->getQuality());
00491 slidergump->InitGump(0);
00492 slidergump->CreateNotifier();
00493 Process* notifier = slidergump->GetNotifyProcess();
00494 SplitItemProcess* splitproc = new SplitItemProcess(item, splittarget);
00495 Kernel::get_instance()->addProcess(splitproc);
00496 splitproc->waitFor(notifier);
00497
00498 return;
00499 }
00500
00501 if (targetitem && item->getShapeInfo()->hasQuantity())
00502 {
00503
00504 if (item->canMergeWith(targetitem))
00505 {
00506 targetitem->setQuality(targetitem->getQuality() +
00507 item->getQuality());
00508 targetitem->callUsecodeEvent_combine();
00509
00510
00511 item->destroy(); item = 0;
00512 return;
00513 }
00514 }
00515
00516 targetcontainer = getTargetContainer(item,mx,my);
00517 assert(targetcontainer);
00518
00519 if (targetcontainer->getObjId() != owner) {
00520 if (item->getParent() == targetcontainer->getObjId()) {
00521
00522
00523 targetcontainer->moveItemToEnd(item);
00524 } else {
00525 item->moveToContainer(targetcontainer);
00526 item->randomGumpLocation();
00527 }
00528 } else {
00529
00530
00531 if (item->getParent() == owner) {
00532 targetcontainer->moveItemToEnd(item);
00533 } else {
00534 item->moveToContainer(targetcontainer);
00535 }
00536
00537 int dox, doy;
00538 GUIApp::get_instance()->getDraggingOffset(dox, doy);
00539 dragging_x = mx - itemarea.x - dox;
00540 dragging_y = my - itemarea.y - doy;
00541 item->setGumpLocation(dragging_x, dragging_y);
00542 }
00543 }
00544
00545 void ContainerGump::saveData(ODataSource* ods)
00546 {
00547 ItemRelativeGump::saveData(ods);
00548
00549 ods->write4(static_cast<uint32>(itemarea.x));
00550 ods->write4(static_cast<uint32>(itemarea.y));
00551 ods->write4(static_cast<uint32>(itemarea.w));
00552 ods->write4(static_cast<uint32>(itemarea.h));
00553 }
00554
00555 bool ContainerGump::loadData(IDataSource* ids, uint32 version)
00556 {
00557 if (!ItemRelativeGump::loadData(ids, version)) return false;
00558
00559 sint32 iax = static_cast<sint32>(ids->read4());
00560 sint32 iay = static_cast<sint32>(ids->read4());
00561 sint32 iaw = static_cast<sint32>(ids->read4());
00562 sint32 iah = static_cast<sint32>(ids->read4());
00563 itemarea.Set(iax, iay, iaw, iah);
00564
00565 return true;
00566 }