diff options
author | Thorbjørn Lindeijer <bjorn@lindeijer.nl> | 2025-05-28 10:02:31 +0200 |
---|---|---|
committer | Thorbjørn Lindeijer <bjorn@lindeijer.nl> | 2025-06-11 11:44:03 +0200 |
commit | 015675ecabdb4730073ade93f643b29929420f78 (patch) | |
tree | 93d26d1e967f8a1f08d0f93b5a8ed3cb85ef739e | |
parent | e35fd4085a9ca3044fa415e79490d6cf192a4ba4 (diff) | |
download | mana-015675ecabdb4730073ade93f643b29929420f78.tar.gz mana-015675ecabdb4730073ade93f643b29929420f78.tar.bz2 mana-015675ecabdb4730073ade93f643b29929420f78.tar.xz mana-015675ecabdb4730073ade93f643b29929420f78.zip |
Cleaned up game input handling a little
This avoids some duplicated code between `Client` and `Game` and reduces
code indentation. Now only the `Client` calls `SDL_PollEvent` and
handles `SDL_WINDOWEVENT_SIZE_CHANGED`.
This also fixes the Keyboard setup tab to allow assigning keys before
starting the game.
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | src/client.cpp | 87 | ||||
-rw-r--r-- | src/game.cpp | 841 | ||||
-rw-r--r-- | src/game.h | 2 |
4 files changed, 445 insertions, 486 deletions
@@ -61,6 +61,7 @@ - Fixed storing of player relations - Fixed handling of custom port in update URL - Fixed stutter when new music starts playing +- Fixed keyboard setup to allow assigning keys before starting the game - Updated to tmwAthena protocol changes - Updated to Manaserv protocol changes (specials, guilds, debug mode, skills, text particles) - CMake: Use GNUInstallDirs and made PKG_DATADIR / PKG_BINDIR paths modifiable diff --git a/src/client.cpp b/src/client.cpp index f0254d50..b86b44b9 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -87,6 +87,8 @@ #include <sys/stat.h> #include <cassert> +#include <guichan/exception.hpp> + // TODO: Get rid of these globals std::string errorMessage; LoginData loginData; @@ -443,51 +445,70 @@ int Client::exec() { Time::beginFrame(); - if (mGame) + // Handle SDL events + SDL_Event event; + while (SDL_PollEvent(&event)) { - // Let the game handle the events while it is active - mGame->handleInput(); - } - else - { - // Handle SDL events - SDL_Event event; - while (SDL_PollEvent(&event)) + switch (event.type) { - switch (event.type) - { - case SDL_QUIT: - mState = STATE_EXIT; - break; - - case SDL_WINDOWEVENT: - switch (event.window.event) { - case SDL_WINDOWEVENT_SIZE_CHANGED: - handleWindowSizeChanged(event.window.data1, - event.window.data2); - break; - } + case SDL_QUIT: + mState = STATE_EXIT; + break; + + case SDL_WINDOWEVENT: + switch (event.window.event) { + case SDL_WINDOWEVENT_SIZE_CHANGED: + handleWindowSizeChanged(event.window.data1, + event.window.data2); break; + } + break; - case SDL_KEYDOWN: - if (keyboard.isEnabled()) + case SDL_KEYDOWN: + if (keyboard.isEnabled()) + { + const int tKey = keyboard.getKeyIndex(event.key.keysym.sym); + if (tKey == KeyboardConfig::KEY_WINDOW_SETUP) { - const int tKey = keyboard.getKeyIndex(event.key.keysym.sym); - if (tKey == KeyboardConfig::KEY_WINDOW_SETUP) - { - setupWindow->setVisible(!setupWindow->isVisible()); - if (setupWindow->isVisible()) - setupWindow->requestMoveToTop(); - continue; - } + setupWindow->setVisible(!setupWindow->isVisible()); + if (setupWindow->isVisible()) + setupWindow->requestMoveToTop(); + continue; } - break; } + if (setupWindow->isVisible() && + keyboard.getNewKeyIndex() > KeyboardConfig::KEY_NO_VALUE) + { + keyboard.setNewKey(event.key.keysym.sym); + keyboard.callbackNewKey(); + keyboard.setNewKeyIndex(KeyboardConfig::KEY_NO_VALUE); + continue; + } + + // Check whether the game will handle the event + if (mGame && mGame->keyDownEvent(event.key)) + continue; + + break; + } + + // Push input to GUI when not used + try + { guiInput->pushInput(event); } + catch (gcn::Exception e) + { + const char *err = e.getMessage().c_str(); + logger->log("Warning: guichan input exception: %s", err); + } } + // Let the game handle continuous input while it is active + if (mGame) + mGame->handleInput(); + if (Net::getGeneralHandler()) Net::getGeneralHandler()->flushNetwork(); diff --git a/src/game.cpp b/src/game.cpp index a6764fcf..660a19db 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -54,7 +54,6 @@ #include "gui/okdialog.h" #include "gui/outfitwindow.h" #include "gui/quitdialog.h" -#include "gui/sdlinput.h" #include "gui/setup.h" #include "gui/socialwindow.h" #include "gui/abilitieswindow.h" @@ -79,7 +78,6 @@ #include "utils/gettext.h" #include "utils/mkdir.h" -#include <guichan/exception.hpp> #include <guichan/focushandler.hpp> #include <fstream> @@ -387,516 +385,453 @@ static void handleItemPickUp() } /** - * The huge input handling method. + * Handles an SDL_KEYDOWN event and returns whether it was consumed. */ -void Game::handleInput() +bool Game::keyDownEvent(SDL_KeyboardEvent &event) { - if (joystick) - joystick->update(); + gcn::Window *requestedWindow = nullptr; - // Events - SDL_Event event; - while (SDL_PollEvent(&event)) + // send straight to gui for certain windows + if (quitDialog || TextDialog::isActive() || + PlayerInfo::getNPCPostCount() > 0) { - bool used = false; + return false; + } - if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) + if (keyboard.isKeyActive(KeyboardConfig::KEY_EMOTE)) + { + int emotion = keyboard.getKeyEmoteOffset(event.keysym.sym); + if (emotion != -1) { - // Let the client deal with this one (it'll pass down from there) - Client::instance()->handleWindowSizeChanged(event.window.data1, - event.window.data2); + emoteShortcut->useEmote(emotion); + return true; } - // Keyboard events (for discontinuous keys) - else if (event.type == SDL_KEYDOWN) - { - gcn::Window *requestedWindow = nullptr; + } - if (setupWindow->isVisible() && - keyboard.getNewKeyIndex() > KeyboardConfig::KEY_NO_VALUE) - { - keyboard.setNewKey(event.key.keysym.sym); - keyboard.callbackNewKey(); - keyboard.setNewKeyIndex(KeyboardConfig::KEY_NO_VALUE); - return; - } + if (!chatWindow->isInputFocused() + && !gui->getFocusHandler()->getModalFocused()) + { + NpcDialog *dialog = NpcDialog::getActive(); + if (keyboard.isKeyActive(KeyboardConfig::KEY_OK) + && (!dialog || !dialog->isTextInputFocused())) + { + // Close the Browser if opened + if (helpWindow->isVisible()) + helpWindow->setVisible(false); + // Close the config window, cancelling changes if opened + else if (setupWindow->isVisible()) + setupWindow->action(gcn::ActionEvent(nullptr, "cancel")); + else if (dialog) + dialog->action(gcn::ActionEvent(nullptr, "ok")); + } + if (keyboard.isKeyActive(KeyboardConfig::KEY_TOGGLE_CHAT)) + { + if (chatWindow->requestChatFocus()) + return true; + } + if (dialog) + { + if (keyboard.isKeyActive(KeyboardConfig::KEY_MOVE_UP)) + dialog->move(1); + else if (keyboard.isKeyActive(KeyboardConfig::KEY_MOVE_DOWN)) + dialog->move(-1); + } + } - // send straight to gui for certain windows - if (quitDialog || TextDialog::isActive() || - PlayerInfo::getNPCPostCount() > 0) - { - try - { - guiInput->pushInput(event); - } - catch (gcn::Exception e) - { - const char* err = e.getMessage().c_str(); - logger->log("Warning: guichan input exception: %s", err); - } - return; - } + if (!chatWindow->isInputFocused() || (event.keysym.mod & KMOD_ALT)) + { + if (keyboard.isKeyActive(KeyboardConfig::KEY_PREV_CHAT_TAB)) + { + chatWindow->prevTab(); + return true; + } + if (keyboard.isKeyActive(KeyboardConfig::KEY_NEXT_CHAT_TAB)) + { + chatWindow->nextTab(); + return true; + } + } - // Mode switch to emotes - if (keyboard.isKeyActive(KeyboardConfig::KEY_EMOTE)) - { - // Emotions - int emotion = keyboard.getKeyEmoteOffset(event.key.keysym.sym); - if (emotion != -1) - { - emoteShortcut->useEmote(emotion); - used = true; - return; - } - } + if (!chatWindow->isInputFocused()) + { + bool wearOutfit = false; + bool copyOutfit = false; - if (!chatWindow->isInputFocused() - && !gui->getFocusHandler()->getModalFocused()) - { - NpcDialog *dialog = NpcDialog::getActive(); - if (keyboard.isKeyActive(KeyboardConfig::KEY_OK) - && (!dialog || !dialog->isTextInputFocused())) - { - // Close the Browser if opened - if (helpWindow->isVisible()) - helpWindow->setVisible(false); - // Close the config window, cancelling changes if opened - else if (setupWindow->isVisible()) - setupWindow->action(gcn::ActionEvent(nullptr, "cancel")); - else if (dialog) - dialog->action(gcn::ActionEvent(nullptr, "ok")); - } - if (keyboard.isKeyActive(KeyboardConfig::KEY_TOGGLE_CHAT)) - { - if (chatWindow->requestChatFocus()) - used = true; - } - if (dialog) - { - if (keyboard.isKeyActive(KeyboardConfig::KEY_MOVE_UP)) - dialog->move(1); - else if (keyboard.isKeyActive(KeyboardConfig::KEY_MOVE_DOWN)) - dialog->move(-1); - } - } + if (keyboard.isKeyActive(KeyboardConfig::KEY_WEAR_OUTFIT)) + wearOutfit = true; + if (keyboard.isKeyActive(KeyboardConfig::KEY_COPY_OUTFIT)) + copyOutfit = true; - if (!chatWindow->isInputFocused() || (event.key.keysym.mod & - KMOD_ALT)) + if (wearOutfit || copyOutfit) + { + int outfitNum = -1; + switch (event.keysym.sym) { - if (keyboard.isKeyActive(KeyboardConfig::KEY_PREV_CHAT_TAB)) - { - chatWindow->prevTab(); - return; - } - else if (keyboard.isKeyActive(KeyboardConfig::KEY_NEXT_CHAT_TAB)) - { - chatWindow->nextTab(); - return; - } + case SDLK_1: + case SDLK_2: + case SDLK_3: + case SDLK_4: + case SDLK_5: + case SDLK_6: + case SDLK_7: + case SDLK_8: + case SDLK_9: + outfitNum = event.keysym.sym - SDLK_1; + break; + + case SDLK_0: + outfitNum = 9; + break; + + case SDLK_MINUS: + outfitNum = 10; + break; + + case SDLK_EQUALS: + outfitNum = 11; + break; + + case SDLK_BACKSPACE: + outfitNum = 12; + break; + + case SDLK_INSERT: + outfitNum = 13; + break; + + case SDLK_HOME: + outfitNum = 14; + break; + + default: + break; } - - if (!chatWindow->isInputFocused()) + if (outfitNum >= 0) { - bool wearOutfit = false; - bool copyOutfit = false; + if (wearOutfit) + outfitWindow->wearOutfit(outfitNum); + else if (copyOutfit) + outfitWindow->copyOutfit(outfitNum); + return true; + } + } + } - if (keyboard.isKeyActive(KeyboardConfig::KEY_WEAR_OUTFIT)) - wearOutfit = true; + const int tKey = keyboard.getKeyIndex(event.keysym.sym); + switch (tKey) + { + case KeyboardConfig::KEY_SCROLL_CHAT_UP: + if (chatWindow->isVisible()) + { + chatWindow->scroll(-DEFAULT_CHAT_WINDOW_SCROLL); + return true; + } + break; + case KeyboardConfig::KEY_SCROLL_CHAT_DOWN: + if (chatWindow->isVisible()) + { + chatWindow->scroll(DEFAULT_CHAT_WINDOW_SCROLL); + return true; + } + break; + case KeyboardConfig::KEY_WINDOW_HELP: + // In-game Help + if (helpWindow->isVisible()) + { + helpWindow->setVisible(false); + } + else + { + helpWindow->loadHelp("index"); + helpWindow->requestMoveToTop(); + } + return true; - if (keyboard.isKeyActive(KeyboardConfig::KEY_COPY_OUTFIT)) - copyOutfit = true; + case KeyboardConfig::KEY_QUIT: + { + // Close possible stuck NPC dialogs. + NpcDialog *npcDialog = NpcDialog::getActive(); + if (npcDialog && npcDialog->isWaitingForTheServer()) + { + npcDialog->close(); + return true; + } - if (wearOutfit || copyOutfit) - { - int outfitNum = -1; - switch (event.key.keysym.sym) - { - case SDLK_1: - case SDLK_2: - case SDLK_3: - case SDLK_4: - case SDLK_5: - case SDLK_6: - case SDLK_7: - case SDLK_8: - case SDLK_9: - outfitNum = event.key.keysym.sym - SDLK_1; - break; - - case SDLK_0: - outfitNum = 9; - break; - - case SDLK_MINUS: - outfitNum = 10; - break; - - case SDLK_EQUALS: - outfitNum = 11; - break; - - case SDLK_BACKSPACE: - outfitNum = 12; - break; - - case SDLK_INSERT: - outfitNum = 13; - break; - - case SDLK_HOME: - outfitNum = 14; - break; - - default: - break; - } - if (outfitNum >= 0) - { - used = true; - if (wearOutfit) - outfitWindow->wearOutfit(outfitNum); - else if (copyOutfit) - outfitWindow->copyOutfit(outfitNum); - } - } - } + // Otherwise, show the quit confirmation dialog. + quitDialog = new QuitDialog(&quitDialog); + quitDialog->requestMoveToTop(); + return true; + } + default: + break; + } - const int tKey = keyboard.getKeyIndex(event.key.keysym.sym); - switch (tKey) - { - case KeyboardConfig::KEY_SCROLL_CHAT_UP: - if (chatWindow->isVisible()) - { - chatWindow->scroll(-DEFAULT_CHAT_WINDOW_SCROLL); - used = true; - } - break; - case KeyboardConfig::KEY_SCROLL_CHAT_DOWN: - if (chatWindow->isVisible()) - { - chatWindow->scroll(DEFAULT_CHAT_WINDOW_SCROLL); - used = true; - return; - } - break; - case KeyboardConfig::KEY_WINDOW_HELP: - // In-game Help - if (helpWindow->isVisible()) - helpWindow->setVisible(false); - else - { - helpWindow->loadHelp("index"); - helpWindow->requestMoveToTop(); - } - used = true; - break; - case KeyboardConfig::KEY_QUIT: - { - // Close possible stuck NPC dialogs. - NpcDialog *npcDialog = NpcDialog::getActive(); - if (npcDialog && npcDialog->isWaitingForTheServer()) - { - npcDialog->close(); - return; - } - - // Otherwise, show the quit confirmation dialog. - quitDialog = new QuitDialog(&quitDialog); - quitDialog->requestMoveToTop(); - return; - } - default: - break; - } - if (keyboard.isEnabled() && !chatWindow->isInputFocused() && - !NpcDialog::isAnyInputFocused() && !InventoryWindow::isAnyInputFocused()) + if (keyboard.isEnabled() && !chatWindow->isInputFocused() && + !NpcDialog::isAnyInputFocused() && !InventoryWindow::isAnyInputFocused()) + { + // Do not activate shortcuts if tradewindow is visible + if (!tradeWindow->isVisible() && !setupWindow->isVisible()) + { + // Checks if any item shortcut is pressed. + for (int i = KeyboardConfig::KEY_SHORTCUT_1; + i <= KeyboardConfig::KEY_SHORTCUT_12; + i++) { - // Do not activate shortcuts if tradewindow is visible - if (!tradeWindow->isVisible() && !setupWindow->isVisible()) - { - // Checks if any item shortcut is pressed. - for (int i = KeyboardConfig::KEY_SHORTCUT_1; - i <= KeyboardConfig::KEY_SHORTCUT_12; - i++) - { - if (tKey == i && !used) - { - itemShortcut->useItem( - i - KeyboardConfig::KEY_SHORTCUT_1); - break; - } - } - } - - switch (tKey) + if (tKey == i) { - case KeyboardConfig::KEY_PICKUP: - { - handleItemPickUp(); - - used = true; - } - break; - case KeyboardConfig::KEY_SIT: - // Player sit action - local_player->toggleSit(); - used = true; - break; - case KeyboardConfig::KEY_HIDE_WINDOWS: - // Hide certain windows - if (!chatWindow->isInputFocused()) - { - statusWindow->setVisible(false); - inventoryWindow->setVisible(false); - skillDialog->setVisible(false); - setupWindow->setVisible(false); - equipmentWindow->setVisible(false); - helpWindow->setVisible(false); - debugWindow->setVisible(false); - socialWindow->setVisible(false); - } - break; - case KeyboardConfig::KEY_WINDOW_STATUS: - requestedWindow = statusWindow; - break; - case KeyboardConfig::KEY_WINDOW_INVENTORY: - requestedWindow = inventoryWindow; - break; - case KeyboardConfig::KEY_WINDOW_EQUIPMENT: - requestedWindow = equipmentWindow; - break; - case KeyboardConfig::KEY_WINDOW_SKILL: - requestedWindow = skillDialog; - break; - case KeyboardConfig::KEY_WINDOW_MINIMAP: - minimap->toggle(); - break; - case KeyboardConfig::KEY_WINDOW_CHAT: - requestedWindow = chatWindow; - break; - case KeyboardConfig::KEY_WINDOW_SHORTCUT: - requestedWindow = itemShortcutWindow; - break; - case KeyboardConfig::KEY_WINDOW_SETUP: - requestedWindow = setupWindow; - break; - case KeyboardConfig::KEY_WINDOW_DEBUG: - requestedWindow = debugWindow; - break; - case KeyboardConfig::KEY_WINDOW_SOCIAL: - requestedWindow = socialWindow; - break; - case KeyboardConfig::KEY_WINDOW_EMOTE_SHORTCUT: - requestedWindow = emoteShortcutWindow; - break; - case KeyboardConfig::KEY_WINDOW_OUTFIT: - requestedWindow = outfitWindow; - break; - case KeyboardConfig::KEY_SCREENSHOT: - // Screenshot (picture, hence the p) - saveScreenshot(); - used = true; - break; - case KeyboardConfig::KEY_TRADE: - // Toggle accepting of incoming trade requests - unsigned int deflt = player_relations.getDefault(); - if (deflt & PlayerPermissions::TRADE) - { - serverNotice(_("Ignoring incoming trade requests")); - deflt &= ~PlayerPermissions::TRADE; - } - else - { - serverNotice(_("Accepting incoming trade requests")); - deflt |= PlayerPermissions::TRADE; - } - - player_relations.setDefault(deflt); - - used = true; - break; + itemShortcut->useItem( + i - KeyboardConfig::KEY_SHORTCUT_1); + return true; } } - - if (requestedWindow) - { - requestedWindow->setVisible(!requestedWindow->isVisible()); - if (requestedWindow->isVisible()) - requestedWindow->requestMoveToTop(); - used = true; - } - } - // Quit event - else if (event.type == SDL_QUIT) - { - Client::setState(STATE_EXIT); } - // Push input to GUI when not used - if (!used) + switch (tKey) + { + case KeyboardConfig::KEY_PICKUP: + handleItemPickUp(); + return true; + + case KeyboardConfig::KEY_SIT: + local_player->toggleSit(); + return true; + + case KeyboardConfig::KEY_HIDE_WINDOWS: + // Hide certain windows + statusWindow->setVisible(false); + inventoryWindow->setVisible(false); + skillDialog->setVisible(false); + setupWindow->setVisible(false); + equipmentWindow->setVisible(false); + helpWindow->setVisible(false); + debugWindow->setVisible(false); + socialWindow->setVisible(false); + break; + + case KeyboardConfig::KEY_WINDOW_STATUS: + requestedWindow = statusWindow; + break; + case KeyboardConfig::KEY_WINDOW_INVENTORY: + requestedWindow = inventoryWindow; + break; + case KeyboardConfig::KEY_WINDOW_EQUIPMENT: + requestedWindow = equipmentWindow; + break; + case KeyboardConfig::KEY_WINDOW_SKILL: + requestedWindow = skillDialog; + break; + case KeyboardConfig::KEY_WINDOW_MINIMAP: + minimap->toggle(); + return true; + case KeyboardConfig::KEY_WINDOW_CHAT: + requestedWindow = chatWindow; + break; + case KeyboardConfig::KEY_WINDOW_SHORTCUT: + requestedWindow = itemShortcutWindow; + break; + case KeyboardConfig::KEY_WINDOW_SETUP: + requestedWindow = setupWindow; + break; + case KeyboardConfig::KEY_WINDOW_DEBUG: + requestedWindow = debugWindow; + break; + case KeyboardConfig::KEY_WINDOW_SOCIAL: + requestedWindow = socialWindow; + break; + case KeyboardConfig::KEY_WINDOW_EMOTE_SHORTCUT: + requestedWindow = emoteShortcutWindow; + break; + case KeyboardConfig::KEY_WINDOW_OUTFIT: + requestedWindow = outfitWindow; + break; + case KeyboardConfig::KEY_SCREENSHOT: + saveScreenshot(); + return true; + + case KeyboardConfig::KEY_TRADE: { - try + // Toggle accepting of incoming trade requests + unsigned int deflt = player_relations.getDefault(); + if (deflt & PlayerPermissions::TRADE) { - guiInput->pushInput(event); + serverNotice(_("Ignoring incoming trade requests")); + deflt &= ~PlayerPermissions::TRADE; } - catch (gcn::Exception e) + else { - const char *err = e.getMessage().c_str(); - logger->log("Warning: guichan input exception: %s", err); + serverNotice(_("Accepting incoming trade requests")); + deflt |= PlayerPermissions::TRADE; } + + player_relations.setDefault(deflt); + + return true; + } + + case KeyboardConfig::KEY_TALK: + if (Being *target = local_player->getTarget()) + if (target->canTalk()) + target->talkTo(); + return true; } + } - } // End while + if (requestedWindow) + { + requestedWindow->setVisible(!requestedWindow->isVisible()); + if (requestedWindow->isVisible()) + requestedWindow->requestMoveToTop(); + return true; + } + + return false; +} + +/** + * Continuous input handling. + */ +void Game::handleInput() +{ + if (joystick) + joystick->update(); // If the user is configuring the keys then don't respond. if (!keyboard.isEnabled()) return; + if (!local_player->isAlive()) + return; + if (PlayerInfo::isTalking()) + return; + if (chatWindow->isInputFocused() || quitDialog || TextDialog::isActive()) + return; // Moving player around - if (local_player->isAlive() && !PlayerInfo::isTalking() && - !chatWindow->isInputFocused() && !quitDialog && !TextDialog::isActive()) - { - // Get the state of the keyboard keys - keyboard.refreshActiveKeys(); - // Ignore input if either "ignore" key is pressed - // Stops the character moving about if the user's window manager - // uses "ignore+arrow key" to switch virtual desktops. - if (keyboard.isKeyActive(KeyboardConfig::KEY_IGNORE_INPUT_1) || - keyboard.isKeyActive(KeyboardConfig::KEY_IGNORE_INPUT_2)) - { - return; - } + // Get the state of the keyboard keys + keyboard.refreshActiveKeys(); - unsigned char direction = 0; + // Ignore input if either "ignore" key is pressed + // Stops the character moving about if the user's window manager + // uses "ignore+arrow key" to switch virtual desktops. + if (keyboard.isKeyActive(KeyboardConfig::KEY_IGNORE_INPUT_1) || + keyboard.isKeyActive(KeyboardConfig::KEY_IGNORE_INPUT_2)) + { + return; + } - // Translate pressed keys to movement and direction - if (keyboard.isKeyActive(KeyboardConfig::KEY_MOVE_UP) || - (joystick && joystick->isUp())) - { - direction |= Being::UP; - } - else if (keyboard.isKeyActive(KeyboardConfig::KEY_MOVE_DOWN) || - (joystick && joystick->isDown())) - { - direction |= Being::DOWN; - } + unsigned char direction = 0; - if (keyboard.isKeyActive(KeyboardConfig::KEY_MOVE_LEFT) || - (joystick && joystick->isLeft())) - { - direction |= Being::LEFT; - } - else if (keyboard.isKeyActive(KeyboardConfig::KEY_MOVE_RIGHT) || - (joystick && joystick->isRight())) - { - direction |= Being::RIGHT; - } + // Translate pressed keys to movement and direction + if (keyboard.isKeyActive(KeyboardConfig::KEY_MOVE_UP) || + (joystick && joystick->isUp())) + { + direction |= Being::UP; + } + else if (keyboard.isKeyActive(KeyboardConfig::KEY_MOVE_DOWN) || + (joystick && joystick->isDown())) + { + direction |= Being::DOWN; + } - if (keyboard.isKeyActive(KeyboardConfig::KEY_EMOTE) && direction != 0) - { - if (local_player->getDirection() != direction) - { - local_player->setDirection(direction); - Net::getPlayerHandler()->setDirection(direction); - } - direction = 0; - } - else - { - local_player->setWalkingDir(direction); - } + if (keyboard.isKeyActive(KeyboardConfig::KEY_MOVE_LEFT) || + (joystick && joystick->isLeft())) + { + direction |= Being::LEFT; + } + else if (keyboard.isKeyActive(KeyboardConfig::KEY_MOVE_RIGHT) || + (joystick && joystick->isRight())) + { + direction |= Being::RIGHT; + } - // Attacking monsters - if (keyboard.isKeyActive(KeyboardConfig::KEY_ATTACK) || - (joystick && joystick->buttonPressed(0))) + if (keyboard.isKeyActive(KeyboardConfig::KEY_EMOTE) && direction != 0) + { + if (local_player->getDirection() != direction) { - if (local_player->getTarget()) - local_player->attack(local_player->getTarget(), true); + local_player->setDirection(direction); + Net::getPlayerHandler()->setDirection(direction); } + } + else + { + local_player->setWalkingDir(direction); + } - if (keyboard.isKeyActive(KeyboardConfig::KEY_TARGET_ATTACK)) - { - Being *target = local_player->getTarget(); + // Attacking monsters + if (keyboard.isKeyActive(KeyboardConfig::KEY_ATTACK) || + (joystick && joystick->buttonPressed(0))) + { + if (local_player->getTarget()) + local_player->attack(local_player->getTarget(), true); + } - bool newTarget = !keyboard.isKeyActive(KeyboardConfig::KEY_TARGET); - // A set target has highest priority - if (!target) - { - // Only auto target Monsters - target = actorSpriteManager->findNearestLivingBeing(local_player, - 20, ActorSprite::MONSTER); - } - local_player->attack(target, newTarget); - } + if (keyboard.isKeyActive(KeyboardConfig::KEY_TARGET_ATTACK)) + { + Being *target = local_player->getTarget(); - // Target the nearest player/monster/npc - if ((keyboard.isKeyActive(KeyboardConfig::KEY_TARGET_PLAYER) || - keyboard.isKeyActive(KeyboardConfig::KEY_TARGET_CLOSEST) || - keyboard.isKeyActive(KeyboardConfig::KEY_TARGET_NPC) || - (joystick && joystick->buttonPressed(3))) && - !keyboard.isKeyActive(KeyboardConfig::KEY_TARGET)) + bool newTarget = !keyboard.isKeyActive(KeyboardConfig::KEY_TARGET); + // A set target has highest priority + if (!target) { - ActorSprite::Type currentTarget = ActorSprite::UNKNOWN; - if (keyboard.isKeyActive(KeyboardConfig::KEY_TARGET_CLOSEST) || - (joystick && joystick->buttonPressed(3))) - currentTarget = ActorSprite::MONSTER; - else if (keyboard.isKeyActive(KeyboardConfig::KEY_TARGET_PLAYER)) - currentTarget = ActorSprite::PLAYER; - else if (keyboard.isKeyActive(KeyboardConfig::KEY_TARGET_NPC)) - currentTarget = ActorSprite::NPC; - - Being *target = actorSpriteManager->findNearestLivingBeing(local_player, - 20, currentTarget); - - if (target && (target != local_player->getTarget() || - currentTarget != mLastTarget)) - { - local_player->setTarget(target); - mLastTarget = currentTarget; - } - } - else - { - mLastTarget = ActorSprite::UNKNOWN; // Reset last target + // Only auto target Monsters + target = actorSpriteManager->findNearestLivingBeing(local_player, + 20, ActorSprite::MONSTER); } + local_player->attack(target, newTarget); + } - // Talk to the nearest NPC if 't' pressed - if (event.type == SDL_KEYDOWN && - keyboard.getKeyIndex(event.key.keysym.sym) == KeyboardConfig::KEY_TALK) + // Target the nearest player/monster/npc + if ((keyboard.isKeyActive(KeyboardConfig::KEY_TARGET_PLAYER) || + keyboard.isKeyActive(KeyboardConfig::KEY_TARGET_CLOSEST) || + keyboard.isKeyActive(KeyboardConfig::KEY_TARGET_NPC) || + (joystick && joystick->buttonPressed(3))) && + !keyboard.isKeyActive(KeyboardConfig::KEY_TARGET)) + { + ActorSprite::Type currentTarget = ActorSprite::UNKNOWN; + if (keyboard.isKeyActive(KeyboardConfig::KEY_TARGET_CLOSEST) || + (joystick && joystick->buttonPressed(3))) + currentTarget = ActorSprite::MONSTER; + else if (keyboard.isKeyActive(KeyboardConfig::KEY_TARGET_PLAYER)) + currentTarget = ActorSprite::PLAYER; + else if (keyboard.isKeyActive(KeyboardConfig::KEY_TARGET_NPC)) + currentTarget = ActorSprite::NPC; + + Being *target = actorSpriteManager->findNearestLivingBeing(local_player, + 20, currentTarget); + + if (target && (target != local_player->getTarget() || + currentTarget != mLastTarget)) { - Being *target = local_player->getTarget(); - - if (target) - { - if (target->canTalk()) - target->talkTo(); - } + local_player->setTarget(target); + mLastTarget = currentTarget; } + } + else + { + mLastTarget = ActorSprite::UNKNOWN; // Reset last target + } - // Stop attacking if the right key is pressed - if (!keyboard.isKeyActive(KeyboardConfig::KEY_ATTACK) - && keyboard.isKeyActive(KeyboardConfig::KEY_TARGET)) - { - local_player->stopAttack(); - } + // Stop attacking if the right key is pressed + if (!keyboard.isKeyActive(KeyboardConfig::KEY_ATTACK) + && keyboard.isKeyActive(KeyboardConfig::KEY_TARGET)) + { + local_player->stopAttack(); + } - if (joystick) + if (joystick) + { + if (joystick->buttonPressed(1)) { - if (joystick->buttonPressed(1)) - { - const int x = local_player->getTileX(); - const int y = local_player->getTileY(); - - FloorItem *item = actorSpriteManager->findItem(x, y); + const int x = local_player->getTileX(); + const int y = local_player->getTileY(); - if (item) - local_player->pickUp(item); - } - else if (joystick->buttonPressed(2)) - { - local_player->toggleSit(); - } + if (FloorItem *item = actorSpriteManager->findItem(x, y)) + local_player->pickUp(item); + } + else if (joystick->buttonPressed(2)) + { + local_player->toggleSit(); } } } @@ -58,6 +58,8 @@ class Game */ void logic(); + bool keyDownEvent(SDL_KeyboardEvent &event); + void handleInput(); void changeMap(const std::string &mapName); |