summaryrefslogtreecommitdiff
path: root/src/game.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game.cpp')
-rw-r--r--src/game.cpp571
1 files changed, 304 insertions, 267 deletions
diff --git a/src/game.cpp b/src/game.cpp
index 9fa0129e..93bec013 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -26,11 +26,12 @@
#include <sstream>
#include <string>
-#include <guichan/sdl/sdlinput.hpp>
#include <guichan/exception.hpp>
+#include <guichan/sdl/sdlinput.hpp>
#include "beingmanager.h"
#include "configuration.h"
+#include "effectmanager.h"
#include "engine.h"
#include "flooritemmanager.h"
#include "graphics.h"
@@ -74,9 +75,11 @@
#include "net/equipmenthandler.h"
#include "net/inventoryhandler.h"
#include "net/itemhandler.h"
+#include "net/messageout.h"
#include "net/network.h"
#include "net/npchandler.h"
#include "net/playerhandler.h"
+#include "net/protocol.h"
#include "net/skillhandler.h"
#include "net/tradehandler.h"
#include "net/messageout.h"
@@ -93,6 +96,7 @@ std::string map_path;
bool done = false;
volatile int tick_time;
volatile int fps = 0, frame = 0;
+
Engine *engine = NULL;
Joystick *joystick = NULL;
@@ -112,7 +116,6 @@ InventoryWindow *inventoryWindow;
NpcListDialog *npcListDialog;
NpcTextDialog *npcTextDialog;
SkillDialog *skillDialog;
-//NewSkillDialog *newSkillWindow;
Setup* setupWindow;
Minimap *minimap;
EquipmentWindow *equipmentWindow;
@@ -126,11 +129,12 @@ ItemShortcutWindow *itemShortcutWindow;
BeingManager *beingManager = NULL;
FloorItemManager *floorItemManager = NULL;
Particle* particleEngine = NULL;
+EffectManager *effectManager = NULL;
const int MAX_TIME = 10000;
/**
- * Listener used for exitting handling.
+ * Listener used for exiting handling.
*/
namespace {
struct ExitListener : public gcn::ActionListener
@@ -163,15 +167,18 @@ Uint32 nextSecond(Uint32 interval, void *param)
{
fps = frame;
frame = 0;
+
return interval;
}
int get_elapsed_time(int start_time)
{
- if (start_time <= tick_time) {
+ if (start_time <= tick_time)
+ {
return (tick_time - start_time) * 10;
}
- else {
+ else
+ {
return (tick_time + (MAX_TIME - start_time)) * 10;
}
}
@@ -193,7 +200,6 @@ void createGuiWindows(Network *network)
npcTextDialog = new NpcTextDialog();
npcListDialog = new NpcListDialog();
skillDialog = new SkillDialog();
- //newSkillWindow = new NewSkillDialog();
setupWindow = new Setup();
minimap = new Minimap();
equipmentWindow = new EquipmentWindow(player_node->mEquipment.get());
@@ -215,8 +221,7 @@ void createGuiWindows(Network *network)
chatWindow->setVisible((bool) config.getValue(
chatWindow->getWindowName() + "Visible", true));
miniStatusWindow->setVisible((bool) config.getValue(
- miniStatusWindow->getWindowName() + "Visible",
- true));
+ miniStatusWindow->getWindowName() + "Visible", true));
buyDialog->setVisible(false);
sellDialog->setVisible(false);
tradeWindow->setVisible(false);
@@ -251,7 +256,6 @@ void destroyGuiWindows()
delete minimap;
delete equipmentWindow;
//delete chargeDialog;
- //delete newSkillWindow;
delete tradeWindow;
//delete buddyWindow;
delete helpWindow;
@@ -277,6 +281,8 @@ Game::Game(Network *network):
beingManager = new BeingManager(network);
floorItemManager = new FloorItemManager();
+ effectManager = new EffectManager();
+
particleEngine = new Particle(NULL);
particleEngine->setupEngine();
@@ -311,17 +317,13 @@ Game::Game(Network *network):
network->registerHandler(mTradeHandler.get());
/*
- * THIS IS A TEMPORARY WORKAROUND!
- *
- * To prevent the server from sending data before the client has
- * initialized, it's been modified to wait for a "ping" from the client to
- * complete its initialization.
+ * To prevent the server from sending data before the client
+ * has initialized, I've modified it to wait for a "ping"
+ * from the client to complete its initialization
*
- * The real fix is to make sure we are not throwing away messages in the
- * network buffer due to not having registered the handlers above straight
- * after receiving a login success from the map server.
- *
- * The response from eAthena on this packet is ignored by the client.
+ * Note: This only affects the latest eAthena version. This
+ * packet is handled by the older version, but its response
+ * is ignored by the client
*/
MessageOut msg(mNetwork);
msg.writeInt16(CMSG_CLIENT_PING);
@@ -356,17 +358,17 @@ bool saveScreenshot(SDL_Surface *screenshot)
bool found = false;
do {
- screenshotCount++;
- filename.str("");
+ screenshotCount++;
+ filename.str("");
#if (defined __USE_UNIX98 || defined __FreeBSD__)
- filename << PHYSFS_getUserDir() << ".tmw/";
+ filename << PHYSFS_getUserDir() << ".aethyra/";
#elif defined __APPLE__
- filename << PHYSFS_getUserDir() << "Desktop/";
+ filename << PHYSFS_getUserDir() << "Desktop/";
#endif
- filename << "TMW_Screenshot_" << screenshotCount << ".png";
- testExists.open(filename.str().c_str(), std::ios::in);
- found = !testExists.is_open();
- testExists.close();
+ filename << "Ae_Screenshot_" << screenshotCount << ".png";
+ testExists.open(filename.str().c_str(), std::ios::in);
+ found = !testExists.is_open();
+ testExists.close();
} while (!found);
if (ImageWriter::writePNG(screenshot, filename.str()))
@@ -403,61 +405,61 @@ void Game::logic()
while (!done)
{
- // Handle all necessary game logic
- while (get_elapsed_time(gameTime) > 0)
- {
- handleInput();
- engine->logic();
- gameTime++;
- }
+ // Handle all necessary game logic
+ while (get_elapsed_time(gameTime) > 0)
+ {
+ handleInput();
+ engine->logic();
+ gameTime++;
+ }
- // This is done because at some point tick_time will wrap.
- gameTime = tick_time;
+ // This is done because at some point tick_time will wrap.
+ gameTime = tick_time;
- // Update the screen when application is active, delay otherwise.
- if (SDL_GetAppState() & SDL_APPACTIVE)
+ // Update the screen when application is active, delay otherwise.
+ if (SDL_GetAppState() & SDL_APPACTIVE)
+ {
+ // Draw a frame if either frames are not limited or enough time has
+ // passed since the last frame.
+ if (!mMinFrameTime ||
+ get_elapsed_time(mDrawTime / 10) > mMinFrameTime)
{
- // Draw a frame if either frames are not limited or enough time has
- // passed since the last frame.
- if (!mMinFrameTime ||
- get_elapsed_time(mDrawTime / 10) > mMinFrameTime)
- {
- frame++;
- gui->draw();
- graphics->updateScreen();
- mDrawTime += mMinFrameTime;
-
- // Make sure to wrap mDrawTime, since tick_time will wrap.
- if (mDrawTime > MAX_TIME * 10)
- mDrawTime -= MAX_TIME * 10;
- }
- else
- {
- SDL_Delay(10);
- }
+ frame++;
+ gui->draw();
+ graphics->updateScreen();
+ mDrawTime += mMinFrameTime;
+
+ // Make sure to wrap mDrawTime, since tick_time will wrap.
+ if (mDrawTime > MAX_TIME * 10)
+ mDrawTime -= MAX_TIME * 10;
}
else
{
SDL_Delay(10);
- mDrawTime = tick_time * 10;
}
+ }
+ else
+ {
+ SDL_Delay(10);
+ mDrawTime = tick_time * 10;
+ }
- // Handle network stuff
- mNetwork->flush();
- mNetwork->dispatchMessages();
+ // Handle network stuff
+ mNetwork->flush();
+ mNetwork->dispatchMessages();
- if (!mNetwork->isConnected())
+ if (!mNetwork->isConnected())
+ {
+ if (!disconnectedDialog)
{
- if (!disconnectedDialog)
- {
- disconnectedDialog = new
- OkDialog("Network Error",
- "The connection to the server was lost, the program will now quit");
- disconnectedDialog->addActionListener(&exitListener);
- disconnectedDialog->requestMoveToTop();
- }
+ disconnectedDialog = new
+ OkDialog("Network Error",
+ "The connection to the server was lost, the program will now quit");
+ disconnectedDialog->addActionListener(&exitListener);
+ disconnectedDialog->requestMoveToTop();
}
}
+ }
}
void Game::handleInput()
@@ -478,7 +480,7 @@ void Game::handleInput()
{
gcn::Window *requestedWindow = NULL;
- if (setupWindow->isVisible() &&
+ if (setupWindow->isVisible() &&
keyboard.getNewKeyIndex() > keyboard.KEY_NO_VALUE)
{
keyboard.setNewKey((int) event.key.keysym.sym);
@@ -534,194 +536,202 @@ void Game::handleInput()
}
used = true;
break;
- }
}
+ }
- // Smilie
- if (keyboard.isKeyActive(keyboard.KEY_SMILIE))
+ // Smilie
+ if (keyboard.isKeyActive(keyboard.KEY_SMILIE))
+ {
+ // Emotions
+ Uint8 emotion;
+ switch (event.key.keysym.sym)
{
- // Emotions
- Uint8 emotion;
- switch (event.key.keysym.sym)
+ case SDLK_1: emotion = 1; break;
+ case SDLK_2: emotion = 2; break;
+ case SDLK_3: emotion = 3; break;
+ case SDLK_4: emotion = 4; break;
+ case SDLK_5: emotion = 5; break;
+ case SDLK_6: emotion = 6; break;
+ case SDLK_7: emotion = 7; break;
+ case SDLK_8: emotion = 8; break;
+ case SDLK_9: emotion = 9; break;
+ case SDLK_0: emotion = 10; break;
+ case SDLK_MINUS: emotion = 11; break;
+ case SDLK_EQUALS: emotion = 12; break;
+ default: emotion = 0; break;
+ }
+
+ if (emotion)
+ {
+ player_node->emote(emotion);
+ used = true;
+ }
+ }
+ switch (event.key.keysym.sym)
+ {
+ case SDLK_PAGEUP:
+ if (chatWindow->isVisible())
{
- case SDLK_1: emotion = 1; break;
- case SDLK_2: emotion = 2; break;
- case SDLK_3: emotion = 3; break;
- case SDLK_4: emotion = 4; break;
- case SDLK_5: emotion = 5; break;
- case SDLK_6: emotion = 6; break;
- case SDLK_7: emotion = 7; break;
- case SDLK_8: emotion = 8; break;
- case SDLK_9: emotion = 9; break;
- case SDLK_0: emotion = 10; break;
- case SDLK_MINUS: emotion = 11; break;
- case SDLK_EQUALS: emotion = 12; break;
- default: emotion = 0; break;
+ chatWindow->scroll(-DEFAULT_CHAT_WINDOW_SCROLL);
+ used = true;
}
+ break;
- if (emotion)
+ case SDLK_PAGEDOWN:
+ if (chatWindow->isVisible())
{
- player_node->emote(emotion);
+ chatWindow->scroll(DEFAULT_CHAT_WINDOW_SCROLL);
used = true;
return;
}
- }
- switch (event.key.keysym.sym)
- {
- case SDLK_PAGEUP:
- if (chatWindow->isVisible())
- {
- chatWindow->scroll(-DEFAULT_CHAT_WINDOW_SCROLL);
- used = true;
- }
- break;
+ break;
- case SDLK_PAGEDOWN:
- if (chatWindow->isVisible())
- {
- chatWindow->scroll(DEFAULT_CHAT_WINDOW_SCROLL);
- used = true;
- }
+ case SDLK_F1:
+ // In-game Help
+ if (helpWindow->isVisible())
+ {
+ helpWindow->setVisible(false);
+ }
+ else
+ {
+ helpWindow->loadHelp("index");
+ helpWindow->requestMoveToTop();
+ }
+ used = true;
+ break;
+
+ case SDLK_F2: requestedWindow = statusWindow; break;
+ case SDLK_F3: requestedWindow = inventoryWindow; break;
+ case SDLK_F4: requestedWindow = equipmentWindow; break;
+ case SDLK_F5: requestedWindow = skillDialog; break;
+ case SDLK_F6: requestedWindow = minimap; break;
+ case SDLK_F7: requestedWindow = chatWindow; break;
+ case SDLK_F8: requestedWindow = itemShortcutWindow; break;
+ case SDLK_F9: requestedWindow = setupWindow; break;
+ case SDLK_F10: requestedWindow = debugWindow; break;
+
+ case SDLK_RETURN:
+ // Input chat window
+ if (chatWindow->isInputFocused() ||
+ deathNotice != NULL ||
+ weightNotice != NULL)
+ {
break;
+ }
- case SDLK_F1:
- // In-game Help
- if (helpWindow->isVisible())
- {
- helpWindow->setVisible(false);
- }
- else
- {
- helpWindow->loadHelp("index");
- helpWindow->requestMoveToTop();
- }
+ // Quit by pressing Enter if the exit confirm is there
+ if (exitConfirm)
+ {
+ done = true;
+ }
+ // Close the Browser if opened
+ else if (helpWindow->isVisible())
+ {
+ helpWindow->setVisible(false);
+ }
+ // Close the config window, cancelling changes if opened
+ else if (setupWindow->isVisible())
+ {
+ setupWindow->action(gcn::ActionEvent(NULL, "cancel"));
+ }
+ // Proceed to the next dialog option, or close the window
+ else if (npcTextDialog->isVisible())
+ {
+ npcTextDialog->action(gcn::ActionEvent(NULL, "ok"));
+ }
+ // Choose the currently highlighted dialogue option
+ else if (npcListDialog->isVisible())
+ {
+ npcListDialog->action(gcn::ActionEvent(NULL, "ok"));
+ }
+ // Else, open the chat edit box
+ else
+ {
+ chatWindow->requestChatFocus();
used = true;
- break;
-
- case SDLK_F2: requestedWindow = statusWindow; break;
- case SDLK_F3: requestedWindow = inventoryWindow; break;
- case SDLK_F4: requestedWindow = equipmentWindow; break;
- case SDLK_F5: requestedWindow = skillDialog; break;
- case SDLK_F6: requestedWindow = minimap; break;
- case SDLK_F7: requestedWindow = chatWindow; break;
- case SDLK_F8: requestedWindow = itemShortcutWindow; break;
- case SDLK_F9: requestedWindow = setupWindow; break;
- case SDLK_F10: requestedWindow = debugWindow; break;
- //case SDLK_F11: requestedWindow = newSkillWindow; break;
-
- case SDLK_RETURN:
- // Input chat window
- if (chatWindow->isInputFocused() ||
- deathNotice != NULL ||
- weightNotice != NULL)
- {
- break;
- }
+ }
+ break;
+ // Quitting confirmation dialog
+ case SDLK_ESCAPE:
+ if (!exitConfirm) {
+ exitConfirm = new ConfirmDialog(
+ "Quit", "Are you sure you want to quit?");
+ exitConfirm->addActionListener(&exitListener);
+ exitConfirm->requestMoveToTop();
+ }
+ else
+ {
+ exitConfirm->action(gcn::ActionEvent(NULL, "no"));
+ }
+ break;
- // Quit by pressing Enter if the exit confirm is there
- if (exitConfirm)
- {
- done = true;
- }
- // Close the Browser if opened
- else if (helpWindow->isVisible())
- {
- helpWindow->setVisible(false);
- }
- // Close the config window, cancelling changes if opened
- else if (setupWindow->isVisible())
- {
- setupWindow->action(gcn::ActionEvent(NULL, "cancel"));
- }
- // Else, open the chat edit box
- else
- {
- chatWindow->requestChatFocus();
- used = true;
- }
- break;
- // Quitting confirmation dialog
- case SDLK_ESCAPE:
- if (!exitConfirm) {
- exitConfirm = new ConfirmDialog(
- "Quit", "Are you sure you want to quit?");
- exitConfirm->addActionListener(&exitListener);
- exitConfirm->requestMoveToTop();
- }
- else
- {
- exitConfirm->action(gcn::ActionEvent(NULL, "no"));
- }
- break;
+ default:
+ break;
+ }
+ if (keyboard.isEnabled() && !chatWindow->isInputFocused())
+ {
+ const int tKey = keyboard.getKeyIndex(event.key.keysym.sym);
- default:
- break;
- }
- if (keyboard.isEnabled() && !chatWindow->isInputFocused())
+ // Do not activate shortcuts if tradewindow is visible
+ if (!tradeWindow->isVisible())
{
- const int tKey = keyboard.getKeyIndex(event.key.keysym.sym);
- // Do not activate shortcuts if tradewindow is visible
- if (!tradeWindow->isVisible())
+ // Checks if any item shortcut is pressed.
+ for (int i = KeyboardConfig::KEY_SHORTCUT_0;
+ i <= KeyboardConfig::KEY_SHORTCUT_9;
+ i++)
{
- // Checks if any item shortcut is pressed.
- for (int i = KeyboardConfig::KEY_SHORTCUT_0;
- i <= KeyboardConfig::KEY_SHORTCUT_9;
- i++)
- {
- if (tKey == i && !used) {
- itemShortcut->useItem(
- i - KeyboardConfig::KEY_SHORTCUT_0);
- break;
- }
+ if (tKey == i && !used) {
+ itemShortcut->useItem(i - KeyboardConfig::KEY_SHORTCUT_0);
+ break;
}
}
- switch (tKey) {
- case KeyboardConfig::KEY_PICKUP:
+ }
+ switch (tKey) {
+ case KeyboardConfig::KEY_PICKUP:
+ {
+ FloorItem *item = floorItemManager->findByCoordinates(
+ player_node->mX, player_node->mY);
+
+ // If none below the player, try the tile in front
+ // of the player
+ if (!item) {
+ Uint16 x = player_node->mX;
+ Uint16 y = player_node->mY;
+ switch (player_node->getSpriteDirection())
{
- FloorItem *item = floorItemManager->findByCoordinates(
- player_node->mX, player_node->mY);
-
- // If none below the player, try the tile in front of
- // the player
- if (!item) {
- Uint16 x = player_node->mX;
- Uint16 y = player_node->mY;
- if (player_node->getDirection() & Being::UP)
- y--;
- if (player_node->getDirection() & Being::DOWN)
- y++;
- if (player_node->getDirection() & Being::LEFT)
- x--;
- if (player_node->getDirection() & Being::RIGHT)
- x++;
-
- item = floorItemManager->findByCoordinates(x, y);
- }
+ case DIRECTION_UP : --y; break;
+ case DIRECTION_DOWN : ++y; break;
+ case DIRECTION_LEFT : --x; break;
+ case DIRECTION_RIGHT: ++x; break;
+ default: break;
+ }
+ item = floorItemManager->findByCoordinates(x, y);
+ }
- if (item)
- player_node->pickUp(item);
+ if (item)
+ player_node->pickUp(item);
- used = true;
- }
- break;
- case KeyboardConfig::KEY_SIT:
- // Player sit action
- player_node->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);
- }
- break;
+ used = true;
+ }
+ break;
+ case KeyboardConfig::KEY_SIT:
+ // Player sit action
+ player_node->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);
+ }
+ break;
}
}
@@ -756,7 +766,6 @@ void Game::handleInput()
logger->log("Warning: guichan input exception: %s", err);
}
}
-
} // End while
// If the user is configuring the keys then don't respond.
if (!keyboard.isEnabled())
@@ -782,7 +791,7 @@ void Game::handleInput()
direction |= Being::UP;
}
else if (keyboard.isKeyActive(keyboard.KEY_MOVE_DOWN) ||
- (joystick && joystick->isDown()))
+ (joystick && joystick->isDown()))
{
direction |= Being::DOWN;
}
@@ -802,60 +811,88 @@ void Game::handleInput()
// Attacking monsters
if (keyboard.isKeyActive(keyboard.KEY_ATTACK) ||
- (joystick && joystick->buttonPressed(0)))
+ (joystick && joystick->buttonPressed(0)))
{
- Being *target = NULL;
- bool newTarget = keyboard.isKeyActive(keyboard.KEY_TARGET);
+ Being *target = beingManager->findNearestLivingBeing(x, y, 20, Being::MONSTER);
+
+ bool newTarget = !keyboard.isKeyActive(keyboard.KEY_TARGET);
// A set target has highest priority
if (newTarget || !player_node->getTarget())
{
Uint16 targetX = x, targetY = y;
- if (player_node->getDirection() & Being::UP)
- targetY--;
- if (player_node->getDirection() & Being::DOWN)
- targetY++;
- if (player_node->getDirection() & Being::LEFT)
- targetX--;
- if (player_node->getDirection() & Being::RIGHT)
- targetX++;
+ switch (player_node->getSpriteDirection())
+ {
+ case DIRECTION_UP : --targetY; break;
+ case DIRECTION_DOWN : ++targetY; break;
+ case DIRECTION_LEFT : --targetX; break;
+ case DIRECTION_RIGHT: ++targetX; break;
+ default: break;
+ }
// Attack priorioty is: Monster, Player, auto target
- target = beingManager->findBeing(
- targetX, targetY, Being::MONSTER);
+ target = beingManager->findBeing(targetX, targetY, Being::MONSTER);
if (!target)
- target = beingManager->findBeing(
- targetX, targetY, Being::PLAYER);
+ target = beingManager->findBeing(targetX, targetY, Being::PLAYER);
}
player_node->attack(target, newTarget);
}
- // Target the nearest player
- if (keyboard.isKeyActive(keyboard.KEY_TARGET_PLAYER))
+ // Target the nearest player if 'q' is pressed
+ if ( keyboard.isKeyActive(keyboard.KEY_TARGET_PLAYER) &&
+ !keyboard.isKeyActive(keyboard.KEY_TARGET) )
{
- Being *target = beingManager->findNearestLivingBeing(
- player_node, 20, Being::PLAYER);
+ Being *target = beingManager->findNearestLivingBeing(player_node, 20, Being::PLAYER);
- if (target)
- {
- player_node->setTarget(target);
- }
+ player_node->setTarget(target);
+ }
+
+ // Target the nearest monster if 'a' pressed
+ if ((keyboard.isKeyActive(keyboard.KEY_TARGET_CLOSEST) ||
+ (joystick && joystick->buttonPressed(3))) &&
+ !keyboard.isKeyActive(keyboard.KEY_TARGET))
+ {
+ Being *target = beingManager->findNearestLivingBeing(x, y, 20, Being::MONSTER);
+
+ player_node->setTarget(target);
}
- // Target the nearest monster
- if (keyboard.isKeyActive(keyboard.KEY_TARGET_CLOSEST)
- || (joystick && joystick->buttonPressed(3)))
+ // Target the nearest npc if 'n' pressed
+ if ( keyboard.isKeyActive(keyboard.KEY_TARGET_NPC) &&
+ !keyboard.isKeyActive(keyboard.KEY_TARGET) )
{
- Being *target =
- beingManager->findNearestLivingBeing(x, y, 20, Being::MONSTER);
+ Being *target = beingManager->findNearestLivingBeing(x, y, 20, Being::NPC);
- if (target)
+ player_node->setTarget(target);
+ }
+
+ // Talk to the nearest NPC if 't' pressed
+ if ( keyboard.isKeyActive(keyboard.KEY_TALK) )
+ {
+ if (!npcTextDialog->isVisible() && !npcListDialog->isVisible())
{
- player_node->setTarget(target);
+ Being *target = player_node->getTarget();
+
+ if (!target)
+ {
+ target = beingManager->findNearestLivingBeing(x, y, 20, Being::NPC);
+ }
+
+ if (target)
+ {
+ if (target->getType() == Being::NPC)
+ dynamic_cast<NPC*>(target)->talk();
+ }
}
}
+ // Stop attacking if shift is pressed
+ if (keyboard.isKeyActive(keyboard.KEY_TARGET))
+ {
+ player_node->stopAttack();
+ }
+
if (joystick)
{
if (joystick->buttonPressed(1))