00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020
00021 #include "GameMapGump.h"
00022 #include "RenderSurface.h"
00023
00024 #include "Kernel.h"
00025
00026 #include "World.h"
00027 #include "Map.h"
00028 #include "CurrentMap.h"
00029 #include "Item.h"
00030 #include "Actor.h"
00031 #include "MainActor.h"
00032 #include "ItemSorter.h"
00033 #include "CameraProcess.h"
00034 #include "GUIApp.h"
00035 #include "ShapeInfo.h"
00036 #include "IDataSource.h"
00037 #include "ODataSource.h"
00038 #include "Mouse.h"
00039 #include "getObject.h"
00040 #include "AvatarMoverProcess.h"
00041 #include "MissileTracker.h"
00042 #include "Direction.h"
00043
00044
00045 #include "GravityProcess.h"
00046 #include "PathfinderProcess.h"
00047 #include "UCList.h"
00048 #include "LoopScript.h"
00049
00050
00051 #include "Texture.h"
00052 #include "FileSystem.h"
00053 #include "PNGWriter.h"
00054
00055
00056 DEFINE_RUNTIME_CLASSTYPE_CODE(GameMapGump,Gump);
00057
00058 bool GameMapGump::highlightItems = false;
00059
00060 GameMapGump::GameMapGump() :
00061 Gump(), display_dragging(false)
00062 {
00063 display_list = new ItemSorter();
00064 }
00065
00066 GameMapGump::GameMapGump(int X, int Y, int Width, int Height) :
00067 Gump(X,Y,Width,Height, 0, FLAG_DONT_SAVE | FLAG_CORE_GUMP, LAYER_GAMEMAP),
00068 display_list(0), display_dragging(false)
00069 {
00070
00071 dims.x -= dims.w/2;
00072 dims.y -= dims.h/2;
00073
00074 pout << "Create display_list ItemSorter object" << std::endl;
00075 display_list = new ItemSorter();
00076 }
00077
00078 GameMapGump::~GameMapGump()
00079 {
00080 delete display_list;
00081 }
00082
00083 bool GameMapGump::Run(const uint32 framenum)
00084 {
00085 Gump::Run(framenum);
00086
00087 return true;
00088
00089 }
00090
00091 void GameMapGump::GetCameraLocation(sint32& lx, sint32& ly, sint32& lz,
00092 int lerp_factor)
00093 {
00094 CameraProcess *camera = CameraProcess::GetCameraProcess();
00095 if (!camera)
00096 {
00097 CameraProcess::GetCameraLocation(lx,ly,lz);
00098 }
00099 else
00100 {
00101 camera->GetLerped(lx, ly, lz, lerp_factor);
00102 }
00103 }
00104
00105
00106 void GameMapGump::PaintThis(RenderSurface *surf, sint32 lerp_factor, bool scaled)
00107 {
00108 World *world = World::get_instance();
00109 if (!world) return;
00110
00111 CurrentMap *map = world->getCurrentMap();
00112 if (!map) return;
00113
00114
00115
00116 int lx, ly, lz;
00117 GetCameraLocation(lx, ly, lz, lerp_factor);
00118
00119 CameraProcess *camera = CameraProcess::GetCameraProcess();
00120
00121 uint16 roofid = 0;
00122 int zlimit = 1 << 16;
00123
00124 if (!camera)
00125 {
00126
00128 sint32 ax, ay, az, axd, ayd, azd;
00129 Actor* av = getMainActor();
00130 av->getLocation(ax, ay, az);
00131 av->getFootpadWorld(axd, ayd, azd);
00132 map->isValidPosition(ax, ay, az, 32, 32, 8, 0, 1, 0, &roofid);
00133 }
00134 else
00135 roofid = camera->FindRoof(lerp_factor);
00136
00137 Item* roof = getItem(roofid);
00138 if (roof) {
00139 zlimit = roof->getZ();
00140 }
00141
00142 display_list->BeginDisplayList(surf, lx, ly, lz);
00143
00144 uint32 gametick = Kernel::get_instance()->getFrameNum();
00145
00146 bool paintEditorItems = GUIApp::get_instance()->isPaintEditorItems();
00147
00148
00149 for (int cy = 0; cy < MAP_NUM_CHUNKS; cy++)
00150 {
00151 for (int cx = 0; cx < MAP_NUM_CHUNKS; cx++)
00152 {
00153
00154 if (!map->isChunkFast(cx,cy)) continue;
00155
00156 const std::list<Item*>* items = map->getItemList(cx,cy);
00157
00158 if (!items) continue;
00159
00160 std::list<Item*>::const_iterator it = items->begin();
00161 std::list<Item*>::const_iterator end = items->end();
00162 for (; it != end; ++it)
00163 {
00164 Item *item = *it;
00165 if (!item) continue;
00166
00167 item->setupLerp(gametick);
00168 item->doLerp(lerp_factor);
00169
00170 if (item->getZ() >= zlimit && !item->getShapeInfo()->is_draw())
00171 continue;
00172 if (!paintEditorItems && item->getShapeInfo()->is_editor())
00173 continue;
00174 if (item->getFlags() & Item::FLG_INVISIBLE)
00175 continue;
00176 display_list->AddItem(item);
00177 }
00178 }
00179 }
00180
00181
00182
00183 if (display_dragging) {
00184 display_list->AddItem(dragging_pos[0],dragging_pos[1],dragging_pos[2],
00185 dragging_shape, dragging_frame,
00186 dragging_flags, Item::EXT_TRANSPARENT);
00187 }
00188
00189
00190 display_list->PaintDisplayList(highlightItems);
00191 }
00192
00193
00194 uint16 GameMapGump::TraceObjId(int mx, int my)
00195 {
00196 uint16 objid = Gump::TraceObjId(mx,my);
00197 if (objid && objid != 65535) return objid;
00198
00199 ParentToGump(mx,my);
00200 return display_list->Trace(mx,my,0,highlightItems);
00201 }
00202
00203 uint16 GameMapGump::TraceCoordinates(int mx, int my, sint32 coords[3],
00204 int offsetx, int offsety, Item* item)
00205 {
00206 sint32 dxd = 0,dyd = 0,dzd = 0;
00207 if (item)
00208 item->getFootpadWorld(dxd,dyd,dzd);
00209
00210 sint32 cx, cy, cz;
00211 GetCameraLocation(cx, cy, cz);
00212
00213 ItemSorter::HitFace face;
00214 ObjId trace = display_list->Trace(mx,my,&face);
00215
00216 Item* hit = getItem(trace);
00217 if (!hit)
00218 return 0;
00219
00220 sint32 hx,hy,hz;
00221 sint32 hxd,hyd,hzd;
00222 hit->getLocation(hx,hy,hz);
00223 hit->getFootpadWorld(hxd,hyd,hzd);
00224
00225
00226 mx -= offsetx;
00227 my -= offsety;
00228
00229
00230
00231
00232
00233
00234
00235 switch (face) {
00236 case ItemSorter::Z_FACE:
00237 coords[0] = 2*mx + 4*(my+hz+hzd) + cx - 4*cz;
00238 coords[1] = -2*mx + 4*(my+hz+hzd) + cy - 4*cz;
00239 coords[2] = hz+hzd;
00240 break;
00241 case ItemSorter::X_FACE:
00242 coords[0] = hx+dxd;
00243 coords[1] = -4*mx + hx+dxd - cx + cy;
00244 coords[2] = -my + (hx+dxd)/4 - mx/2 - cx/4 + cz;
00245 break;
00246 case ItemSorter::Y_FACE:
00247 coords[0] = 4*mx + hy+dyd + cx - cy;
00248 coords[1] = hy+dyd;
00249 coords[2] = -my + mx/2 + (hy+dyd)/4 - cy/4 + cz;
00250 break;
00251 }
00252
00253 return trace;
00254 }
00255
00256 bool GameMapGump::GetLocationOfItem(uint16 itemid, int &gx, int &gy,
00257 sint32 lerp_factor)
00258 {
00259 Item *item = getItem(itemid);
00260
00261 if (!item) return false;
00262
00263 while (item->getParentAsContainer()) item = item->getParentAsContainer();
00264
00265 sint32 ix, iy, iz;
00266
00267
00268 item->setupLerp(Kernel::get_instance()->getFrameNum());
00269 item->doLerp(lerp_factor);
00270 item->getLerped(ix,iy,iz);
00271
00272
00273 sint32 cx, cy, cz;
00274 CameraProcess *cam = CameraProcess::GetCameraProcess();
00275 if (!cam) CameraProcess::GetCameraLocation(cx,cy,cz);
00276 else cam->GetLerped(cx,cy,cz,lerp_factor);
00277
00278
00279 gx = (ix - iy)/4;
00280
00281 gy = (ix + iy)/8 - iz;
00282
00283
00284 gx -= (cx - cy)/4;
00285
00286 gy -= (cx + cy)/8 - cz;
00287
00288 return true;
00289 }
00290
00291 Gump* GameMapGump::OnMouseDown(int button, int mx, int my)
00292 {
00293 int sx = mx, sy = my;
00294 ParentToGump(sx, sy);
00295 GumpToScreenSpace(sx, sy);
00296
00297 AvatarMoverProcess* amp = GUIApp::get_instance()->getAvatarMoverProcess();
00298 if (button == BUTTON_RIGHT || button == BUTTON_LEFT) {
00299 amp->OnMouseDown(button, sx, sy);
00300 }
00301
00302 if (button == BUTTON_LEFT || button == BUTTON_RIGHT ||
00303 button == BUTTON_MIDDLE)
00304 {
00305
00306 return this;
00307 }
00308
00309 return 0;
00310 }
00311
00312 void GameMapGump::OnMouseUp(int button, int mx, int my)
00313 {
00314 AvatarMoverProcess* amp = GUIApp::get_instance()->getAvatarMoverProcess();
00315 if (button == BUTTON_RIGHT || button == BUTTON_LEFT) {
00316 amp->OnMouseUp(button);
00317 }
00318 }
00319
00320 void GameMapGump::OnMouseClick(int button, int mx, int my)
00321 {
00322 MainActor* avatar = getMainActor();
00323 switch (button) {
00324 case BUTTON_LEFT:
00325 {
00326 if (avatar->isInCombat()) break;
00327
00328 if (GUIApp::get_instance()->isMouseDown(BUTTON_RIGHT)) break;
00329
00330 if (GUIApp::get_instance()->isAvatarInStasis()) {
00331 pout << "Can't: avatarInStasis" << std::endl;
00332 break;
00333 }
00334
00335 uint16 objID = TraceObjId(mx, my);
00336 Item *item = getItem(objID);
00337 if (item) {
00338 sint32 x,y,z;
00339 item->getLocation(x,y,z);
00340 item->dumpInfo();
00341
00342
00343 item->callUsecodeEvent_look();
00344 }
00345 break;
00346 }
00347 case BUTTON_MIDDLE:
00348 {
00349 uint16 objID = TraceObjId(mx, my);
00350 Item *item = getItem(objID);
00351 if (item) {
00352 sint32 x,y,z;
00353 item->getLocation(x,y,z);
00354 item->dumpInfo();
00355
00356 #if 1
00357 Actor* devon = getActor(1);
00358 PathfinderProcess* pfp = new PathfinderProcess(devon, x, y, z);
00359
00360 Kernel::get_instance()->addProcess(pfp);
00361 #elif 0
00362 if (p_dynamic_cast<Actor*>(item)) {
00363 p_dynamic_cast<Actor*>(item)->die(0);
00364 } else {
00365 item->destroy();
00366 }
00367 #elif 0
00368 UCList uclist(2);
00369 LOOPSCRIPT(script, LS_TOKEN_TRUE);
00370 World* world= World::get_instance();
00371 world->getCurrentMap()->surfaceSearch(&uclist, script,
00372 sizeof(script),
00373 item, true, false, true);
00374 for (uint32 i = 0; i < uclist.getSize(); i++)
00375 {
00376 Item *item2 = getItem(uclist.getuint16(i));
00377 if (!item2) continue;
00378 item2->setExtFlag(Item::EXT_HIGHLIGHT);
00379 }
00380 #elif 0
00381 item->receiveHit(1, 0, 1024, 0);
00382 #elif 0
00383 item->clearFlag(Item::FLG_HANGING);
00384 #endif
00385 }
00386 }
00387 default:
00388 break;
00389 }
00390 }
00391
00392 void GameMapGump::OnMouseDouble(int button, int mx, int my)
00393 {
00394 MainActor* avatar = getMainActor();
00395 switch (button) {
00396 case BUTTON_LEFT:
00397 {
00398 if (avatar->isInCombat()) break;
00399
00400 if (GUIApp::get_instance()->isMouseDown(BUTTON_RIGHT)) break;
00401
00402 if (GUIApp::get_instance()->isAvatarInStasis()) {
00403 pout << "Can't: avatarInStasis" << std::endl;
00404 break;
00405 }
00406
00407 uint16 objID = TraceObjId(mx, my);
00408 Item *item = getItem(objID);
00409 if (item) {
00410 sint32 x,y,z;
00411 item->getLocation(x,y,z);
00412 item->dumpInfo();
00413
00414 if (p_dynamic_cast<Actor*>(item) ||
00415 avatar->canReach(item, 128))
00416 {
00417
00418 item->use();
00419 } else {
00420 GUIApp::get_instance()->flashCrossCursor();
00421 }
00422 }
00423 break;
00424 }
00425 default:
00426 break;
00427 }
00428 }
00429
00430 void GameMapGump::IncSortOrder(int count)
00431 {
00432 if (count>0) display_list->IncSortLimit();
00433 else display_list->DecSortLimit();
00434 }
00435
00436 bool GameMapGump::StartDraggingItem(Item* item, int mx, int my)
00437 {
00438
00439
00440 if (!item->canDrag()) return false;
00441
00442 MainActor* avatar = getMainActor();
00443 if (!avatar->canReach(item, 128)) return false;
00444
00445
00446 int itemx, itemy;
00447 GetLocationOfItem(item->getObjId(), itemx, itemy);
00448 GUIApp::get_instance()->setDraggingOffset(mx - itemx, my - itemy);
00449
00450 return true;
00451 }
00452
00453 bool GameMapGump::DraggingItem(Item* item, int mx, int my)
00454 {
00455
00456 int dox, doy;
00457 GUIApp::get_instance()->getDraggingOffset(dox, doy);
00458
00459 dragging_shape = item->getShape();
00460 dragging_frame = item->getFrame();
00461 dragging_flags = item->getFlags();
00462 display_dragging = true;
00463
00464
00465
00466 ObjId trace = TraceCoordinates(mx, my, dragging_pos, dox, doy, item);
00467 if (!trace)
00468 return false;
00469
00470 MainActor* avatar = getMainActor();
00471 if (trace == 1) {
00472 ObjId bp = avatar->getEquip(7);
00473 Container* backpack = getContainer(bp);
00474 return backpack->CanAddItem(item, true);
00475 }
00476
00477 bool throwing = false;
00478 if (!avatar->canReach(item, 128,
00479 dragging_pos[0], dragging_pos[1], dragging_pos[2]))
00480 {
00481
00482 int throwrange = item->getThrowRange();
00483 if (throwrange && avatar->canReach(item, throwrange, dragging_pos[0],
00484 dragging_pos[1], dragging_pos[2]))
00485 {
00486 int speed = 64 - item->getTotalWeight() + avatar->getStr();
00487 if (speed < 1) speed = 1;
00488 sint32 ax,ay,az;
00489 avatar->getLocation(ax,ay,az);
00490 MissileTracker t(item, ax, ay, az,
00491 dragging_pos[0], dragging_pos[1], dragging_pos[2],
00492 speed, 4);
00493 if (t.isPathClear())
00494 throwing = true;
00495 else
00496 return false;
00497 } else {
00498 return false;
00499 }
00500 }
00501
00502 if (!item->canExistAt(dragging_pos[0], dragging_pos[1], dragging_pos[2]))
00503 return false;
00504
00505 if (throwing)
00506 GUIApp::get_instance()->setMouseCursor(GUIApp::MOUSE_TARGET);
00507
00508 return true;
00509 }
00510
00511 void GameMapGump::DraggingItemLeftGump(Item* item)
00512 {
00513 display_dragging = false;
00514 }
00515
00516
00517 void GameMapGump::StopDraggingItem(Item* item, bool moved)
00518 {
00519 display_dragging = false;
00520
00521 if (!moved) return;
00522
00523
00524 item->grab();
00525 }
00526
00527 void GameMapGump::DropItem(Item* item, int mx, int my)
00528 {
00529 int dox, doy;
00530 GUIApp::get_instance()->getDraggingOffset(dox, doy);
00531
00532 display_dragging = false;
00533 Actor* avatar = getMainActor();
00534
00535 ObjId trace = TraceCoordinates(mx, my, dragging_pos, dox, doy, item);
00536 if (trace == 1) {
00537 ObjId bp = avatar->getEquip(7);
00538 Container* backpack = getContainer(bp);
00539 if (backpack && item->moveToContainer(backpack)) {
00540 pout << "Dropped item in backpack" << std::endl;
00541 item->randomGumpLocation();
00542 return;
00543 }
00544 }
00545
00546 if (!avatar->canReach(item, 128,
00547 dragging_pos[0], dragging_pos[1], dragging_pos[2]))
00548 {
00549
00550 pout << "Throwing item to (" << dragging_pos[0] << ","
00551 << dragging_pos[1] << "," << dragging_pos[2] << ")" << std::endl;
00552 int speed = 64 - item->getTotalWeight() + avatar->getStr();
00553 if (speed < 1) speed = 1;
00554 sint32 ax,ay,az;
00555 avatar->getLocation(ax,ay,az);
00556
00557
00558 item->move(ax, ay, az+24);
00559 sint32 tx, ty;
00560 tx = dragging_pos[0];
00561 ty = dragging_pos[1];
00562 int inaccuracy = 4 * (30 - avatar->getDex());
00563 if (inaccuracy < 20) inaccuracy = 20;
00564 tx += (std::rand()%inaccuracy) - (std::rand()%inaccuracy);
00565 ty += (std::rand()%inaccuracy) - (std::rand()%inaccuracy);
00566 MissileTracker t(item, tx, ty, dragging_pos[2],
00567 speed, 4);
00568 t.launchItem();
00569
00570
00571
00572 #if 0
00573 avatar->doAnim(Animation::stand,
00574 Get_WorldDirection(dragging_pos[1]-ay,
00575 dragging_pos[0]-ax));
00576 #endif
00577 } else {
00578 pout << "Dropping item at (" << dragging_pos[0] << ","
00579 << dragging_pos[1] << "," << dragging_pos[2] << ")" << std::endl;
00580
00581
00582
00583
00584 item->collideMove(dragging_pos[0], dragging_pos[1], dragging_pos[2],
00585 true, true);
00586 item->fall();
00587 }
00588 }
00589
00590 void GameMapGump::ConCmd_toggleHighlightItems(const Console::ArgvType &argv)
00591 {
00592 GameMapGump::SetHighlightItems(!GameMapGump::isHighlightItems());
00593 }
00594
00595 void GameMapGump::ConCmd_dumpMap(const Console::ArgvType &)
00596 {
00597
00598 if (RenderSurface::format.s_bpp != 32) return;
00599
00600
00601 sint32 awidth = 8192;
00602 sint32 aheight = 8192;
00603
00604 sint32 xpos = 0;
00605 sint32 ypos = 0;
00606
00607 sint32 left = 16384;
00608 sint32 right = -16384;
00609 sint32 top = 16384;
00610 sint32 bot = -16384;
00611
00612 sint32 camheight = 256;
00613
00614
00615
00616 for (sint32 y = 0; y < 64; y++)
00617 {
00618 for (sint32 x = 0; x < 64; x++)
00619 {
00620 const std::list<Item *> *list =
00621 World::get_instance()->getCurrentMap()->getItemList(x,y);
00622
00623
00624
00625 if (list && list->size() != 0)
00626 {
00627 sint32 l = (x*512 - y*512)/4 - 128;
00628 sint32 r = (x*512 - y*512)/4 + 128;
00629 sint32 t = (x*512 + y*512)/8 - 256;
00630 sint32 b = (x*512 + y*512)/8;
00631
00632 t -= 256;
00633
00634 if (l < left) left = l;
00635 if (r > right) right = r;
00636 if (t < top) top = t;
00637 if (b > bot) bot = b;
00638 }
00639 }
00640 }
00641
00642 if (right == -16384) return;
00643
00644
00645 bot += camheight;
00646 top += camheight;
00647
00648 awidth = right-left;
00649 aheight = bot-top;
00650
00651 ypos = top;
00652 xpos = left;
00653
00654
00655 sint32 bwidth = awidth;
00656 sint32 bheight = 256;
00657
00658
00659 sint32 twidth = bwidth/8;
00660 sint32 theight = bheight;
00661
00662
00663 GameMapGump* g = new GameMapGump(0, 0, twidth, theight);
00664 bool isInvisible = (getMainActor()->getFlags() & Item::FLG_INVISIBLE) != 0;
00665 getMainActor()->setFlag(Item::FLG_INVISIBLE);
00666 World::get_instance()->getCurrentMap()->setWholeMapFast();
00667
00668 RenderSurface* s = RenderSurface::CreateSecondaryRenderSurface(bwidth,
00669 bheight);
00670 Texture* t = s->GetSurfaceAsTexture();
00671
00672 std::memset(t->buffer, 0, 4*bwidth*bheight);
00673
00674
00675
00676 std::string filename = "@home/mapdump";
00677 char buf[32];
00678 sprintf(buf, "%02d", World::get_instance()->getCurrentMap()->getNum());
00679 filename += buf;
00680 filename += ".png";
00681 ODataSource *ds = FileSystem::get_instance()->WriteFile(filename);
00682 std::string pngcomment = "Map ";
00683 pngcomment += buf;
00684 pngcomment += ", dumped by Pentagram.";
00685
00686 PNGWriter* pngw = new PNGWriter(ds);
00687 pngw->init(awidth, aheight, pngcomment);
00688
00689
00690 for (sint32 y = 0; y < aheight; y+=theight)
00691 {
00692 for (sint32 x = 0; x < awidth; x+=twidth)
00693 {
00694
00695 sint32 ex = xpos+x+twidth/2;
00696 sint32 ey = ypos+y+theight/2;
00697 sint32 wx = ex*2 + ey*4;
00698 sint32 wy = ey*4 - ex*2;
00699
00700 s->SetOrigin(x,y%bheight);
00701 CameraProcess::SetCameraProcess(
00702 new CameraProcess(wx+4*camheight, wy+4*camheight, camheight));
00703 g->Paint(s, 256, false);
00704
00705 }
00706
00707
00708 if (((y+theight)%bheight) == 0) {
00709 for (int i = 0; i < bwidth*bheight; ++i) {
00710
00711 uint8 r, g, b;
00712 UNPACK_RGB8(t->buffer[i],r,g,b);
00713 uint8 *buf = reinterpret_cast<uint8*>(&t->buffer[i]);
00714 buf[0] = b; buf[1] = g; buf[2] = r; buf[3] = 0xFF;
00715 }
00716
00717 pngw->writeRows(bheight, t);
00718
00719
00720 std::memset(t->buffer, 0, 4*bwidth*bheight);
00721 }
00722 }
00723
00724 pngw->finish();
00725 delete pngw;
00726
00727 delete ds;
00728
00729 delete g;
00730 delete s;
00731
00732 if (!isInvisible)
00733 getMainActor()->clearFlag(Item::FLG_INVISIBLE);
00734
00735 CameraProcess::SetCameraProcess(new CameraProcess(1));
00736
00737 pout << "Map stored in " << filename << "." << std::endl;
00738 }
00739
00740 void GameMapGump::RenderSurfaceChanged()
00741 {
00742 dims.x += dims.w/2;
00743 dims.y += dims.h/2;
00744
00745
00746 Pentagram::Rect new_dims;
00747 parent->GetDims(new_dims);
00748 dims.w = new_dims.w;
00749 dims.h = new_dims.h;
00750
00751 dims.x -= dims.w/2;
00752 dims.y -= dims.h/2;
00753
00754 Gump::RenderSurfaceChanged();
00755 }
00756
00757 void GameMapGump::saveData(ODataSource* ods)
00758 {
00759 CANT_HAPPEN_MSG("Trying to save GameMapGump");
00760 }
00761
00762 bool GameMapGump::loadData(IDataSource* ids, uint32 version)
00763 {
00764 CANT_HAPPEN_MSG("Trying to load GameMapGump");
00765
00766 return false;
00767 }
00768
00769
00770