00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "beingmanager.h"
00023 #include "channelmanager.h"
00024 #include "commandhandler.h"
00025 #include "configuration.h"
00026 #include "effectmanager.h"
00027 #include "emoteshortcut.h"
00028 #include "engine.h"
00029 #include "flooritemmanager.h"
00030 #include "game.h"
00031 #include "graphics.h"
00032 #include "itemshortcut.h"
00033 #include "joystick.h"
00034 #include "keyboardconfig.h"
00035 #include "localplayer.h"
00036 #include "log.h"
00037 #include "map.h"
00038 #include "npc.h"
00039 #include "particle.h"
00040 #include "player_relations.h"
00041
00042 #include "gui/widgets/chattab.h"
00043 #include "gui/buy.h"
00044 #include "gui/buysell.h"
00045 #include "gui/chat.h"
00046 #include "gui/confirm_dialog.h"
00047 #include "gui/debugwindow.h"
00048 #include "gui/emoteshortcutcontainer.h"
00049 #include "gui/emotewindow.h"
00050 #include "gui/equipmentwindow.h"
00051 #include "gui/gui.h"
00052 #include "gui/help.h"
00053 #include "gui/inventorywindow.h"
00054 #include "gui/shortcutwindow.h"
00055 #include "gui/itemshortcutcontainer.h"
00056 #include "gui/menuwindow.h"
00057 #include "gui/minimap.h"
00058 #include "gui/ministatus.h"
00059 #include "gui/npcintegerdialog.h"
00060 #include "gui/npclistdialog.h"
00061 #include "gui/npcstringdialog.h"
00062 #include "gui/npc_text.h"
00063 #include "gui/ok_dialog.h"
00064 #include "gui/sdlinput.h"
00065 #include "gui/sell.h"
00066 #include "gui/setup.h"
00067 #include "gui/skill.h"
00068 #include "gui/status.h"
00069 #include "gui/trade.h"
00070 #include "gui/viewport.h"
00071 #include "gui/partywindow.h"
00072 #ifdef TMWSERV_SUPPORT
00073 #include "gui/buddywindow.h"
00074 #include "gui/guildwindow.h"
00075 #include "gui/magic.h"
00076 #include "gui/quitdialog.h"
00077 #endif
00078 #include "gui/npcpostdialog.h"
00079 #include "gui/storagewindow.h"
00080
00081 #include "net/generalhandler.h"
00082 #include "net/maphandler.h"
00083 #include "net/net.h"
00084
00085 #include "net/tmwserv/inventoryhandler.h"
00086 #include "net/ea/inventoryhandler.h"
00087
00088 #include "resources/imagewriter.h"
00089
00090 #include "utils/gettext.h"
00091
00092 #include <guichan/exception.hpp>
00093
00094 #include <fstream>
00095 #include <physfs.h>
00096 #include <sstream>
00097 #include <string>
00098
00099 std::string map_path;
00100
00101 bool done = false;
00102 volatile int tick_time;
00103 volatile int fps = 0, frame = 0;
00104
00105 Engine *engine = NULL;
00106 Joystick *joystick = NULL;
00107
00108 extern Window *weightNotice;
00109 extern Window *deathNotice;
00110 #ifdef TMWSERV_SUPPORT
00111 QuitDialog *quitDialog = NULL;
00112 #else
00113 ConfirmDialog *exitConfirm = NULL;
00114 #endif
00115 OkDialog *disconnectedDialog = NULL;
00116
00117 ChatWindow *chatWindow;
00118 MenuWindow *menuWindow;
00119 StatusWindow *statusWindow;
00120 MiniStatusWindow *miniStatusWindow;
00121 BuyDialog *buyDialog;
00122 SellDialog *sellDialog;
00123 #ifdef EATHENA_SUPPORT
00124 BuySellDialog *buySellDialog;
00125 #endif
00126 InventoryWindow *inventoryWindow;
00127 EmoteWindow *emoteWindow;
00128 NpcIntegerDialog *npcIntegerDialog;
00129 NpcListDialog *npcListDialog;
00130 NpcTextDialog *npcTextDialog;
00131 NpcStringDialog *npcStringDialog;
00132 SkillDialog *skillDialog;
00133 PartyWindow *partyWindow;
00134 #ifdef TMWSERV_SUPPORT
00135 BuddyWindow *buddyWindow;
00136 GuildWindow *guildWindow;
00137 MagicDialog *magicDialog;
00138 #endif
00139 NpcPostDialog *npcPostDialog;
00140 StorageWindow *storageWindow;
00141 Minimap *minimap;
00142 EquipmentWindow *equipmentWindow;
00143 TradeWindow *tradeWindow;
00144 HelpWindow *helpWindow;
00145 DebugWindow *debugWindow;
00146 ShortcutWindow *itemShortcutWindow;
00147 ShortcutWindow *emoteShortcutWindow;
00148
00149 BeingManager *beingManager = NULL;
00150 FloorItemManager *floorItemManager = NULL;
00151 ChannelManager *channelManager = NULL;
00152 CommandHandler *commandHandler = NULL;
00153 Particle *particleEngine = NULL;
00154 EffectManager *effectManager = NULL;
00155
00156 ChatTab *localChatTab = NULL;
00157
00158 const int MAX_TIME = 10000;
00159
00163 namespace {
00164 struct ExitListener : public gcn::ActionListener
00165 {
00166 void action(const gcn::ActionEvent &event)
00167 {
00168 if (event.getId() == "yes" || event.getId() == "ok")
00169 done = true;
00170
00171 #ifdef EATHENA_SUPPORT
00172 exitConfirm = NULL;
00173 #endif
00174 disconnectedDialog = NULL;
00175 }
00176 } exitListener;
00177 }
00178
00182 Uint32 nextTick(Uint32 interval, void *param)
00183 {
00184 tick_time++;
00185 if (tick_time == MAX_TIME) tick_time = 0;
00186 return interval;
00187 }
00188
00192 Uint32 nextSecond(Uint32 interval, void *param)
00193 {
00194 fps = frame;
00195 frame = 0;
00196
00197 return interval;
00198 }
00199
00200 int get_elapsed_time(int start_time)
00201 {
00202 if (start_time <= tick_time)
00203 return (tick_time - start_time) * 10;
00204 else
00205 return (tick_time + (MAX_TIME - start_time)) * 10;
00206 }
00207
00211 static void createGuiWindows()
00212 {
00213
00214 chatWindow = new ChatWindow;
00215 buyDialog = new BuyDialog;
00216 sellDialog = new SellDialog;
00217 tradeWindow = new TradeWindow;
00218 npcTextDialog = new NpcTextDialog;
00219 npcIntegerDialog = new NpcIntegerDialog;
00220 npcListDialog = new NpcListDialog;
00221 npcStringDialog = new NpcStringDialog;
00222 partyWindow = new PartyWindow;
00223 #ifdef TMWSERV_SUPPORT
00224 magicDialog = new MagicDialog;
00225 equipmentWindow = new EquipmentWindow(player_node->mEquipment.get());
00226 buddyWindow = new BuddyWindow;
00227 guildWindow = new GuildWindow;
00228 #else
00229 buySellDialog = new BuySellDialog;
00230 equipmentWindow = new EquipmentWindow;
00231 #endif
00232 npcPostDialog = new NpcPostDialog;
00233 storageWindow = new StorageWindow;
00234 menuWindow = new MenuWindow;
00235 statusWindow = new StatusWindow(player_node);
00236 miniStatusWindow = new MiniStatusWindow;
00237 inventoryWindow = new InventoryWindow;
00238 emoteWindow = new EmoteWindow;
00239 skillDialog = new SkillDialog;
00240 minimap = new Minimap;
00241 helpWindow = new HelpWindow;
00242 debugWindow = new DebugWindow;
00243 itemShortcutWindow = new ShortcutWindow("ItemShortcut",
00244 new ItemShortcutContainer);
00245 emoteShortcutWindow = new ShortcutWindow("EmoteShortcut",
00246 new EmoteShortcutContainer);
00247
00248 localChatTab = new ChatTab(_("General"));
00249
00250 if (config.getValue("logToChat", 0))
00251 {
00252 logger->setChatWindow(chatWindow);
00253 }
00254
00255 Net::getGeneralHandler()->guiWindowsLoaded();
00256 }
00257
00261 static void destroyGuiWindows()
00262 {
00263 Net::getGeneralHandler()->guiWindowsUnloaded();
00264 logger->setChatWindow(NULL);
00265 delete localChatTab;
00266 delete chatWindow;
00267 delete statusWindow;
00268 delete miniStatusWindow;
00269 delete menuWindow;
00270 delete buyDialog;
00271 delete sellDialog;
00272 #ifdef EATHENA_SUPPORT
00273 delete buySellDialog;
00274 #endif
00275 delete inventoryWindow;
00276 delete emoteWindow;
00277 delete npcIntegerDialog;
00278 delete npcListDialog;
00279 delete npcTextDialog;
00280 delete npcStringDialog;
00281 delete partyWindow;
00282 delete npcPostDialog;
00283 #ifdef TMWSERV_SUPPORT
00284 delete magicDialog;
00285 delete buddyWindow;
00286 delete guildWindow;
00287 #endif
00288 delete skillDialog;
00289 delete minimap;
00290 delete equipmentWindow;
00291 delete tradeWindow;
00292 delete helpWindow;
00293 delete debugWindow;
00294 delete itemShortcutWindow;
00295 delete emoteShortcutWindow;
00296 delete storageWindow;
00297 }
00298
00299 Game::Game():
00300 mLastTarget(Being::UNKNOWN),
00301 mLogicCounterId(0), mSecondsCounterId(0)
00302 {
00303 done = false;
00304
00305 createGuiWindows();
00306 engine = new Engine;
00307
00308 beingManager = new BeingManager;
00309 commandHandler = new CommandHandler;
00310 floorItemManager = new FloorItemManager;
00311 channelManager = new ChannelManager;
00312 effectManager = new EffectManager;
00313
00314 particleEngine = new Particle(NULL);
00315 particleEngine->setupEngine();
00316
00317
00318 tick_time = 0;
00319 mLogicCounterId = SDL_AddTimer(10, nextTick, NULL);
00320 mSecondsCounterId = SDL_AddTimer(1000, nextSecond, NULL);
00321
00322
00323 config.addListener("fpslimit", this);
00324 optionChanged("fpslimit");
00325
00326
00327 beingManager->setPlayer(player_node);
00328
00329 Joystick::init();
00330
00331
00332 if (Joystick::getNumberOfJoysticks() > 0)
00333 joystick = new Joystick(0);
00334
00335 #ifdef EATHENA_SUPPORT
00336 map_path = map_path.substr(0, map_path.rfind("."));
00337 engine->changeMap(map_path);
00338 #endif
00339
00340 setupWindow->setInGame(true);
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 Net::getMapHandler()->ping(tick_time);
00352 }
00353
00354 Game::~Game()
00355 {
00356 destroyGuiWindows();
00357
00358 delete beingManager;
00359 delete player_node;
00360 delete floorItemManager;
00361 delete channelManager;
00362 delete commandHandler;
00363 delete joystick;
00364 delete particleEngine;
00365 delete engine;
00366
00367 viewport->setMap(NULL);
00368 player_node = NULL;
00369 beingManager = NULL;
00370 floorItemManager = NULL;
00371 joystick = NULL;
00372
00373 SDL_RemoveTimer(mLogicCounterId);
00374 SDL_RemoveTimer(mSecondsCounterId);
00375 }
00376
00377 static bool saveScreenshot()
00378 {
00379 static unsigned int screenshotCount = 0;
00380
00381 SDL_Surface *screenshot = graphics->getScreenshot();
00382
00383
00384 std::stringstream filenameSuffix;
00385 std::stringstream filename;
00386 std::fstream testExists;
00387 bool found = false;
00388
00389 do {
00390 screenshotCount++;
00391 filename.str("");
00392 filenameSuffix.str("");
00393 filename << PHYSFS_getUserDir();
00394 #if (defined __USE_UNIX98 || defined __FreeBSD__)
00395 filenameSuffix << ".tmw/";
00396 #elif defined __APPLE__
00397 filenameSuffix << "Desktop/";
00398 #endif
00399 filenameSuffix << "TMW_Screenshot_" << screenshotCount << ".png";
00400 filename << filenameSuffix.str();
00401 testExists.open(filename.str().c_str(), std::ios::in);
00402 found = !testExists.is_open();
00403 testExists.close();
00404 } while (!found);
00405
00406 const bool success = ImageWriter::writePNG(screenshot, filename.str());
00407
00408 if (success)
00409 {
00410 std::stringstream chatlogentry;
00411 chatlogentry << _("Screenshot saved to ~/") << filenameSuffix.str();
00412 localChatTab->chatLog(chatlogentry.str(), BY_SERVER);
00413 }
00414 else
00415 {
00416 localChatTab->chatLog(_("Saving screenshot failed!"), BY_SERVER);
00417 logger->log("Error: could not save screenshot.");
00418 }
00419
00420 SDL_FreeSurface(screenshot);
00421
00422 return success;
00423 }
00424
00425 void Game::optionChanged(const std::string &name)
00426 {
00427 int fpsLimit = (int) config.getValue("fpslimit", 60);
00428
00429 mMinFrameTime = fpsLimit ? 1000 / fpsLimit : 0;
00430
00431
00432 mDrawTime = tick_time * 10;
00433 }
00434
00435 void Game::logic()
00436 {
00437
00438
00439 int gameTime = tick_time;
00440 mDrawTime = tick_time * 10;
00441
00442 while (!done)
00443 {
00444 if (Map *map = engine->getCurrentMap())
00445 map->update(get_elapsed_time(gameTime));
00446
00447
00448 while (get_elapsed_time(gameTime) > 0)
00449 {
00450 handleInput();
00451 engine->logic();
00452 gameTime++;
00453 }
00454
00455
00456 gameTime = tick_time;
00457
00458
00459 if (SDL_GetAppState() & SDL_APPACTIVE)
00460 {
00461
00462
00463 if (!mMinFrameTime ||
00464 get_elapsed_time(mDrawTime / 10) > mMinFrameTime)
00465 {
00466 frame++;
00467 gui->draw();
00468 graphics->updateScreen();
00469 mDrawTime += mMinFrameTime;
00470
00471
00472 if (mDrawTime > MAX_TIME * 10)
00473 mDrawTime -= MAX_TIME * 10;
00474 }
00475 else
00476 {
00477 SDL_Delay(10);
00478 }
00479 }
00480 else
00481 {
00482 SDL_Delay(10);
00483 mDrawTime = tick_time * 10;
00484 }
00485
00486
00487 Net::getGeneralHandler()->flushNetwork();
00488 if (!Net::getGeneralHandler()->isNetworkConnected())
00489 {
00490 if (!disconnectedDialog)
00491 {
00492 disconnectedDialog = new OkDialog(_("Network Error"),
00493 _("The connection to the "
00494 "server was lost, the "
00495 "program will now quit"));
00496 disconnectedDialog->addActionListener(&exitListener);
00497 disconnectedDialog->requestMoveToTop();
00498 }
00499 }
00500 }
00501 }
00502
00503 void Game::handleInput()
00504 {
00505 if (joystick)
00506 joystick->update();
00507
00508
00509 SDL_Event event;
00510 while (SDL_PollEvent(&event))
00511 {
00512 bool used = false;
00513
00514
00515 if (event.type == SDL_KEYDOWN)
00516 {
00517 gcn::Window *requestedWindow = NULL;
00518
00519 if (setupWindow->isVisible() &&
00520 keyboard.getNewKeyIndex() > keyboard.KEY_NO_VALUE)
00521 {
00522 keyboard.setNewKey((int) event.key.keysym.sym);
00523 keyboard.callbackNewKey();
00524 keyboard.setNewKeyIndex(keyboard.KEY_NO_VALUE);
00525 return;
00526 }
00527
00528
00529 if (npcPostDialog->isVisible())
00530 {
00531 try
00532 {
00533 guiInput->pushInput(event);
00534 }
00535 catch (gcn::Exception e)
00536 {
00537 const char* err = e.getMessage().c_str();
00538 logger->log("Warning: guichan input exception: %s", err);
00539 }
00540 return;
00541 }
00542
00543
00544 if (keyboard.isKeyActive(keyboard.KEY_EMOTE))
00545 {
00546
00547 int emotion = keyboard.getKeyEmoteOffset(event.key.keysym.sym);
00548 if (emotion)
00549 {
00550 emoteShortcut->useEmote(emotion);
00551 used = true;
00552 return;
00553 }
00554 }
00555
00556 if (!(chatWindow->isInputFocused() || deathNotice || weightNotice))
00557 if (keyboard.isKeyActive(keyboard.KEY_OK))
00558 {
00559 #ifdef TMWSERV_SUPPORT
00560
00561 if (quitDialog != NULL && quitDialog->isVisible())
00562 continue;
00563 #else
00564 if (exitConfirm &&
00565 keyboard.isKeyActive(keyboard.KEY_TOGGLE_CHAT))
00566 done = true;
00567 #endif
00568
00569 else if (helpWindow->isVisible() &&
00570 keyboard.isKeyActive(keyboard.KEY_OK))
00571 helpWindow->setVisible(false);
00572
00573 else if (setupWindow->isVisible() &&
00574 keyboard.isKeyActive(keyboard.KEY_OK))
00575 setupWindow->action(gcn::ActionEvent(NULL, "cancel"));
00576
00577 else if (npcStringDialog->isVisible() &&
00578 keyboard.isKeyActive(keyboard.KEY_OK))
00579 npcStringDialog->action(gcn::ActionEvent(NULL, "ok"));
00580
00581 else if (npcTextDialog->isVisible() &&
00582 keyboard.isKeyActive(keyboard.KEY_OK))
00583 npcTextDialog->action(gcn::ActionEvent(NULL, "ok"));
00584
00585 else if (npcListDialog->isVisible() &&
00586 keyboard.isKeyActive(keyboard.KEY_OK))
00587 npcListDialog->action(gcn::ActionEvent(NULL, "ok"));
00588
00589 else if (npcIntegerDialog->isVisible() &&
00590 keyboard.isKeyActive(keyboard.KEY_OK))
00591 npcIntegerDialog->action(gcn::ActionEvent(NULL, "ok"));
00592
00593
00594
00595
00596
00597
00598 }
00599 if (keyboard.isKeyActive(keyboard.KEY_TOGGLE_CHAT))
00600 {
00601 if (chatWindow->requestChatFocus())
00602 used = true;
00603 }
00604
00605
00606 if (!chatWindow->isInputFocused() || (event.key.keysym.mod & KMOD_ALT))
00607 {
00608 if (keyboard.isKeyActive(keyboard.KEY_PREV_CHAT_TAB))
00609 {
00610 chatWindow->prevTab();
00611 return;
00612 }
00613 else if (keyboard.isKeyActive(keyboard.KEY_NEXT_CHAT_TAB))
00614 {
00615 chatWindow->nextTab();
00616 return;
00617 }
00618 }
00619
00620 const int tKey = keyboard.getKeyIndex(event.key.keysym.sym);
00621 switch (tKey)
00622 {
00623 case KeyboardConfig::KEY_SCROLL_CHAT_UP:
00624 if (chatWindow->isVisible())
00625 {
00626 chatWindow->scroll(-DEFAULT_CHAT_WINDOW_SCROLL);
00627 used = true;
00628 }
00629 break;
00630 case KeyboardConfig::KEY_SCROLL_CHAT_DOWN:
00631 if (chatWindow->isVisible())
00632 {
00633 chatWindow->scroll(DEFAULT_CHAT_WINDOW_SCROLL);
00634 used = true;
00635 return;
00636 }
00637 break;
00638 case KeyboardConfig::KEY_WINDOW_HELP:
00639
00640 if (helpWindow->isVisible())
00641 helpWindow->setVisible(false);
00642 else
00643 {
00644 helpWindow->loadHelp("index");
00645 helpWindow->requestMoveToTop();
00646 }
00647 used = true;
00648 break;
00649
00650 case KeyboardConfig::KEY_QUIT:
00651 #ifdef TMWSERV_SUPPORT
00652 if (!quitDialog)
00653 {
00654 quitDialog = new QuitDialog(&done, &quitDialog);
00655 quitDialog->requestMoveToTop();
00656 }
00657 else
00658 {
00659 quitDialog->action(gcn::ActionEvent(NULL, "cancel"));
00660 }
00661 #else
00662 if (!exitConfirm)
00663 {
00664 exitConfirm = new ConfirmDialog(_("Quit"),
00665 _("Are you sure you "
00666 "want to quit?"));
00667 exitConfirm->addActionListener(&exitListener);
00668 exitConfirm->requestMoveToTop();
00669 }
00670 else
00671 {
00672 exitConfirm->action(gcn::ActionEvent(NULL, _("no")));
00673 }
00674 #endif
00675 break;
00676 default:
00677 break;
00678 }
00679 if (keyboard.isEnabled() && !chatWindow->isInputFocused()
00680 && !npcStringDialog->isInputFocused())
00681 {
00682 const int tKey = keyboard.getKeyIndex(event.key.keysym.sym);
00683
00684
00685 if (!tradeWindow->isVisible())
00686 {
00687
00688 for (int i = KeyboardConfig::KEY_SHORTCUT_1;
00689 i <= KeyboardConfig::KEY_SHORTCUT_12;
00690 i++)
00691 {
00692 if (tKey == i && !used)
00693 {
00694 itemShortcut->useItem(
00695 i - KeyboardConfig::KEY_SHORTCUT_1);
00696 break;
00697 }
00698 }
00699 }
00700
00701 switch (tKey)
00702 {
00703 case KeyboardConfig::KEY_PICKUP:
00704 {
00705 #ifdef TMWSERV_SUPPORT
00706 const Vector &pos = player_node->getPosition();
00707 Uint16 x = (int) pos.x / 32;
00708 Uint16 y = (int) pos.y / 32;
00709 #else
00710 Uint16 x = player_node->mX;
00711 Uint16 y = player_node->mY;
00712 #endif
00713 FloorItem *item =
00714 floorItemManager->findByCoordinates(x, y);
00715
00716
00717
00718 if (!item)
00719 {
00720
00721
00722 switch (player_node->getSpriteDirection())
00723 {
00724 case DIRECTION_UP : --y; break;
00725 case DIRECTION_DOWN : ++y; break;
00726 case DIRECTION_LEFT : --x; break;
00727 case DIRECTION_RIGHT: ++x; break;
00728 default: break;
00729 }
00730
00731 item = floorItemManager->findByCoordinates(
00732 x, y);
00733 }
00734
00735 if (item)
00736 player_node->pickUp(item);
00737
00738 used = true;
00739 }
00740 break;
00741 case KeyboardConfig::KEY_SIT:
00742
00743 player_node->toggleSit();
00744 used = true;
00745 break;
00746 case KeyboardConfig::KEY_HIDE_WINDOWS:
00747
00748 if (!chatWindow->isInputFocused())
00749 {
00750 statusWindow->setVisible(false);
00751 inventoryWindow->setVisible(false);
00752 emoteWindow->setVisible(false);
00753 skillDialog->setVisible(false);
00754 setupWindow->setVisible(false);
00755 equipmentWindow->setVisible(false);
00756 helpWindow->setVisible(false);
00757 debugWindow->setVisible(false);
00758 #ifdef TMWSERV_SUPPORT
00759 guildWindow->setVisible(false);
00760 buddyWindow->setVisible(false);
00761 #endif
00762 }
00763 break;
00764 case KeyboardConfig::KEY_WINDOW_STATUS:
00765 requestedWindow = statusWindow;
00766 break;
00767 case KeyboardConfig::KEY_WINDOW_INVENTORY:
00768 requestedWindow = inventoryWindow;
00769 break;
00770 case KeyboardConfig::KEY_WINDOW_EQUIPMENT:
00771 requestedWindow = equipmentWindow;
00772 break;
00773 case KeyboardConfig::KEY_WINDOW_SKILL:
00774 requestedWindow = skillDialog;
00775 break;
00776 case KeyboardConfig::KEY_WINDOW_MINIMAP:
00777 minimap->toggle();
00778 break;
00779 case KeyboardConfig::KEY_WINDOW_CHAT:
00780 requestedWindow = chatWindow;
00781 break;
00782 case KeyboardConfig::KEY_WINDOW_SHORTCUT:
00783 requestedWindow = itemShortcutWindow;
00784 break;
00785 case KeyboardConfig::KEY_WINDOW_SETUP:
00786 requestedWindow = setupWindow;
00787 break;
00788 case KeyboardConfig::KEY_WINDOW_DEBUG:
00789 requestedWindow = debugWindow;
00790 break;
00791 case KeyboardConfig::KEY_WINDOW_EMOTE:
00792 requestedWindow = emoteWindow;
00793 break;
00794 case KeyboardConfig::KEY_WINDOW_EMOTE_SHORTCUT:
00795 requestedWindow = emoteShortcutWindow;
00796 break;
00797 case KeyboardConfig::KEY_SCREENSHOT:
00798
00799 saveScreenshot();
00800 used = true;
00801 break;
00802 case KeyboardConfig::KEY_PATHFIND:
00803
00804 viewport->toggleDebugPath();
00805 used = true;
00806 break;
00807 case KeyboardConfig::KEY_TRADE:
00808
00809 unsigned int deflt = player_relations.getDefault();
00810 if (deflt & PlayerRelation::TRADE)
00811 {
00812 localChatTab->chatLog(
00813 _("Ignoring incoming trade requests"),
00814 BY_SERVER);
00815 deflt &= ~PlayerRelation::TRADE;
00816 }
00817 else
00818 {
00819 localChatTab->chatLog(
00820 _("Accepting incoming trade requests"),
00821 BY_SERVER);
00822 deflt |= PlayerRelation::TRADE;
00823 }
00824
00825 player_relations.setDefault(deflt);
00826
00827 used = true;
00828 break;
00829 }
00830 }
00831
00832 if (requestedWindow)
00833 {
00834 requestedWindow->setVisible(!requestedWindow->isVisible());
00835 if (requestedWindow->isVisible())
00836 requestedWindow->requestMoveToTop();
00837 used = true;
00838 }
00839 }
00840
00841 else if (event.type == SDL_QUIT)
00842 {
00843 done = true;
00844 }
00845
00846
00847 if (!used)
00848 {
00849 try
00850 {
00851 guiInput->pushInput(event);
00852 }
00853 catch (gcn::Exception e)
00854 {
00855 const char* err = e.getMessage().c_str();
00856 logger->log("Warning: guichan input exception: %s", err);
00857 }
00858 }
00859
00860 }
00861
00862
00863 if (!keyboard.isEnabled())
00864 return;
00865
00866
00867 if (player_node->mAction != Being::DEAD && current_npc == 0 &&
00868 !chatWindow->isInputFocused())
00869 {
00870
00871 keyboard.refreshActiveKeys();
00872
00873
00874
00875
00876 if (keyboard.isKeyActive(keyboard.KEY_IGNORE_INPUT_1) ||
00877 keyboard.isKeyActive(keyboard.KEY_IGNORE_INPUT_2))
00878 {
00879 return;
00880 }
00881
00882 #ifdef TMWSERV_SUPPORT
00883 const Vector &pos = player_node->getPosition();
00884 const Uint16 x = (int) pos.x / 32;
00885 const Uint16 y = (int) pos.y / 32;
00886 #else
00887 const Uint16 x = player_node->mX;
00888 const Uint16 y = player_node->mY;
00889 #endif
00890 unsigned char direction = 0;
00891
00892
00893 if (keyboard.isKeyActive(keyboard.KEY_MOVE_UP) ||
00894 (joystick && joystick->isUp()))
00895 {
00896 direction |= Being::UP;
00897 }
00898 else if (keyboard.isKeyActive(keyboard.KEY_MOVE_DOWN) ||
00899 (joystick && joystick->isDown()))
00900 {
00901 direction |= Being::DOWN;
00902 }
00903
00904 if (keyboard.isKeyActive(keyboard.KEY_MOVE_LEFT) ||
00905 (joystick && joystick->isLeft()))
00906 {
00907 direction |= Being::LEFT;
00908 }
00909 else if (keyboard.isKeyActive(keyboard.KEY_MOVE_RIGHT) ||
00910 (joystick && joystick->isRight()))
00911 {
00912 direction |= Being::RIGHT;
00913 }
00914
00915 #ifdef TMWSERV_SUPPORT
00916
00917
00918 if (direction == player_node->getWalkingDir())
00919 {
00920 player_node->setWalkingDir(direction);
00921 }
00922
00923
00924
00925 else if (direction && direction != player_node->getWalkingDir())
00926 {
00927 player_node->stopWalking(false);
00928 player_node->setWalkingDir(direction);
00929 }
00930
00931 else
00932 {
00933 player_node->stopWalking(true);
00934 }
00935 #else
00936 player_node->setWalkingDir(direction);
00937
00938
00939 if (keyboard.isKeyActive(keyboard.KEY_ATTACK) ||
00940 (joystick && joystick->buttonPressed(0)))
00941 {
00942 Being *target = NULL;
00943
00944 bool newTarget = !keyboard.isKeyActive(keyboard.KEY_TARGET);
00945
00946 if (newTarget || !player_node->getTarget())
00947 {
00948 Uint16 targetX = x, targetY = y;
00949
00950 switch (player_node->getSpriteDirection())
00951 {
00952 case DIRECTION_UP : --targetY; break;
00953 case DIRECTION_DOWN : ++targetY; break;
00954 case DIRECTION_LEFT : --targetX; break;
00955 case DIRECTION_RIGHT: ++targetX; break;
00956 default: break;
00957 }
00958
00959
00960 target = beingManager->findNearestLivingBeing(targetX, targetY,
00961 20, Being::MONSTER);
00962 }
00963
00964 player_node->attack(target, newTarget);
00965 }
00966 #endif
00967
00968
00969 if ((keyboard.isKeyActive(keyboard.KEY_TARGET_PLAYER) ||
00970 keyboard.isKeyActive(keyboard.KEY_TARGET_CLOSEST) ||
00971 keyboard.isKeyActive(keyboard.KEY_TARGET_NPC) ||
00972 (joystick && joystick->buttonPressed(3))) &&
00973 !keyboard.isKeyActive(keyboard.KEY_TARGET))
00974 {
00975 Being::Type currentTarget = Being::UNKNOWN;
00976 if (keyboard.isKeyActive(keyboard.KEY_TARGET_CLOSEST) ||
00977 (joystick && joystick->buttonPressed(3)))
00978 currentTarget = Being::MONSTER;
00979 else if (keyboard.isKeyActive(keyboard.KEY_TARGET_PLAYER))
00980 currentTarget = Being::PLAYER;
00981 else if (keyboard.isKeyActive(keyboard.KEY_TARGET_NPC))
00982 currentTarget = Being::NPC;
00983
00984 Being *target = beingManager->findNearestLivingBeing(player_node,
00985 20, currentTarget);
00986
00987 if (target && (target != player_node->getTarget() ||
00988 currentTarget != mLastTarget))
00989 {
00990 player_node->setTarget(target);
00991 mLastTarget = currentTarget;
00992 }
00993 } else mLastTarget = Being::UNKNOWN;
00994
00995
00996 if ( keyboard.isKeyActive(keyboard.KEY_TALK) )
00997 {
00998 if (!npcTextDialog->isVisible() && !npcListDialog->isVisible() &&
00999 !npcStringDialog->isVisible() && !npcIntegerDialog->isVisible())
01000 {
01001 Being *target = player_node->getTarget();
01002
01003 if (target)
01004 {
01005 if (target->getType() == Being::NPC)
01006 dynamic_cast<NPC*>(target)->talk();
01007 }
01008 }
01009 }
01010
01011
01012 if (keyboard.isKeyActive(keyboard.KEY_TARGET))
01013 {
01014 player_node->stopAttack();
01015 }
01016
01017 if (joystick)
01018 {
01019 if (joystick->buttonPressed(1))
01020 {
01021 FloorItem *item = floorItemManager->findByCoordinates(x, y);
01022
01023 if (item)
01024 player_node->pickUp(item);
01025 }
01026 else if (joystick->buttonPressed(2))
01027 {
01028 player_node->toggleSit();
01029 }
01030 }
01031 }
01032 }