summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--src/game.cpp942
-rw-r--r--src/net/beinghandler.cpp28
-rw-r--r--src/net/protocol.h4
4 files changed, 520 insertions, 462 deletions
diff --git a/ChangeLog b/ChangeLog
index 206b3f4b..90fed5cd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2008-07-22 Lloyd Bryant ("Sanga") <lloyd_bryant@netzero.net>
+
+ * Added handler for 0x0086 movement packet (new eAthena).
+ * Changed startup sequence for game.cpp to send a ping packet
+ to the server after all the handlers have been initialized.
+ This is required by the new eAthena version.
+ * Added #deines for some "ping" packets.
+
2008-07-19 Lloyd Bryant ("Sanga") <lloyd_bryant@netzero.net>
* Removed unnecessary check ("weight") from itemdb loader
diff --git a/src/game.cpp b/src/game.cpp
index d018852b..070cab52 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -68,6 +68,7 @@
#include "gui/status.h"
#include "gui/trade.h"
#include "gui/viewport.h"
+#include "net/protocol.h"
#include "net/beinghandler.h"
#include "net/buysellhandler.h"
#include "net/chathandler.h"
@@ -79,6 +80,7 @@
#include "net/playerhandler.h"
#include "net/skillhandler.h"
#include "net/tradehandler.h"
+#include "net/messageout.h"
#include "resources/imagewriter.h"
@@ -92,6 +94,7 @@ std::string map_path;
bool done = false;
volatile int tick_time;
volatile int fps = 0, frame = 0;
+
Engine *engine = NULL;
Joystick *joystick = NULL;
@@ -134,14 +137,14 @@ const int MAX_TIME = 10000;
namespace {
struct ExitListener : public gcn::ActionListener
{
- void action(const gcn::ActionEvent &event)
- {
- if (event.getId() == "yes" || event.getId() == "ok") {
- done = true;
- }
- exitConfirm = NULL;
- disconnectedDialog = NULL;
- }
+ void action(const gcn::ActionEvent &event)
+ {
+ if (event.getId() == "yes" || event.getId() == "ok") {
+ done = true;
+ }
+ exitConfirm = NULL;
+ disconnectedDialog = NULL;
+ }
} exitListener;
}
@@ -162,16 +165,17 @@ Uint32 nextSecond(Uint32 interval, void *param)
{
fps = frame;
frame = 0;
+
return interval;
}
int get_elapsed_time(int start_time)
{
if (start_time <= tick_time) {
- return (tick_time - start_time) * 10;
+ return (tick_time - start_time) * 10;
}
else {
- return (tick_time + (MAX_TIME - start_time)) * 10;
+ return (tick_time + (MAX_TIME - start_time)) * 10;
}
}
@@ -218,7 +222,7 @@ void createGuiWindows(Network *network)
if (config.getValue("logToChat", 0))
{
- logger->setChatWindow(chatWindow);
+ logger->setChatWindow(chatWindow);
}
}
@@ -283,14 +287,13 @@ Game::Game(Network *network):
// Initialize beings
beingManager->setPlayer(player_node);
player_node->setNetwork(network);
- engine->changeMap(map_path);
Joystick::init();
// TODO: The user should be able to choose which one to use
// Open the first device
if (Joystick::getNumberOfJoysticks() > 0)
{
- joystick = new Joystick(0);
+ joystick = new Joystick(0);
}
network->registerHandler(mBeingHandler.get());
@@ -303,6 +306,21 @@ Game::Game(Network *network):
network->registerHandler(mPlayerHandler.get());
network->registerHandler(mSkillHandler.get());
network->registerHandler(mTradeHandler.get());
+
+ /*
+ * 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
+ *
+ * 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);
+ msg.writeInt32(tick_time);
+
+ engine->changeMap(map_path);
}
Game::~Game()
@@ -331,30 +349,30 @@ bool saveScreenshot(SDL_Surface *screenshot)
bool found = false;
do {
- screenshotCount++;
- filename.str("");
+ screenshotCount++;
+ filename.str("");
#if (defined __USE_UNIX98 || defined __FreeBSD__)
- filename << PHYSFS_getUserDir() << ".tme/";
+ filename << PHYSFS_getUserDir() << ".tme/";
#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 << "TMW_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()))
{
- std::stringstream chatlogentry;
- chatlogentry << "Screenshot saved to " << filename.str().c_str();
- chatWindow->chatLog(chatlogentry.str(), BY_SERVER);
- return true;
+ std::stringstream chatlogentry;
+ chatlogentry << "Screenshot saved to " << filename.str().c_str();
+ chatWindow->chatLog(chatlogentry.str(), BY_SERVER);
+ return true;
}
else
{
- chatWindow->chatLog("Saving screenshot failed!", BY_SERVER);
- return false;
+ chatWindow->chatLog("Saving screenshot failed!", BY_SERVER);
+ return false;
}
}
@@ -378,61 +396,61 @@ void Game::logic()
while (!done)
{
- // 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;
-
- // 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)
- {
- 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);
- }
- }
- else
- {
- SDL_Delay(10);
- mDrawTime = tick_time * 10;
- }
-
- // Handle network stuff
- mNetwork->flush();
- mNetwork->dispatchMessages();
-
- if (!mNetwork->isConnected())
- {
- if (!disconnectedDialog)
- {
- disconnectedDialog = new
- OkDialog("Network Error",
- "The connection to the server was lost, the "
+ // 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;
+
+ // 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)
+ {
+ 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);
+ }
+ }
+ else
+ {
+ SDL_Delay(10);
+ mDrawTime = tick_time * 10;
+ }
+
+ // Handle network stuff
+ mNetwork->flush();
+ mNetwork->dispatchMessages();
+
+ if (!mNetwork->isConnected())
+ {
+ 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->addActionListener(&exitListener);
+ disconnectedDialog->requestMoveToTop();
+ }
+ }
}
}
@@ -440,296 +458,296 @@ void Game::handleInput()
{
if (joystick != NULL)
{
- joystick->update();
+ joystick->update();
}
// Events
SDL_Event event;
while (SDL_PollEvent(&event))
{
- bool used = false;
-
- // Keyboard events (for discontinuous keys)
- if (event.type == SDL_KEYDOWN)
- {
- gcn::Window *requestedWindow = NULL;
-
- if (setupWindow->isVisible() &&
- keyboard.getNewKeyIndex() > keyboard.KEY_NO_VALUE)
- {
- keyboard.setNewKey((int) event.key.keysym.sym);
- keyboard.callbackNewKey();
- keyboard.setNewKeyIndex(keyboard.KEY_NO_VALUE);
- return;
- }
- // Keys pressed together with Alt/Meta
- // Emotions and some internal gui windows
- #ifndef __APPLE__
- if (event.key.keysym.mod & KMOD_ALT)
- #else
- if (event.key.keysym.mod & KMOD_LMETA)
- #endif
- {
- switch (event.key.keysym.sym)
- {
- case SDLK_p:
- // Screenshot (picture, hence the p)
- {
- SDL_Surface *screenshot =
+ bool used = false;
+
+ // Keyboard events (for discontinuous keys)
+ if (event.type == SDL_KEYDOWN)
+ {
+ gcn::Window *requestedWindow = NULL;
+
+ if (setupWindow->isVisible() &&
+ keyboard.getNewKeyIndex() > keyboard.KEY_NO_VALUE)
+ {
+ keyboard.setNewKey((int) event.key.keysym.sym);
+ keyboard.callbackNewKey();
+ keyboard.setNewKeyIndex(keyboard.KEY_NO_VALUE);
+ return;
+ }
+ // Keys pressed together with Alt/Meta
+ // Emotions and some internal gui windows
+ #ifndef __APPLE__
+ if (event.key.keysym.mod & KMOD_ALT)
+ #else
+ if (event.key.keysym.mod & KMOD_LMETA)
+ #endif
+ {
+ switch (event.key.keysym.sym)
+ {
+ case SDLK_p:
+ // Screenshot (picture, hence the p)
+ {
+ SDL_Surface *screenshot =
graphics->getScreenshot();
- if (!saveScreenshot(screenshot))
- {
- logger->
+ if (!saveScreenshot(screenshot))
+ {
+ logger->
log("Error: could not save Screenshot.");
- }
- SDL_FreeSurface(screenshot);
- }
- used = true;
- break;
-
- default:
- break;
-
- case SDLK_f:
- // Find path to mouse (debug purpose)
- viewport->toggleDebugPath();
- used = true;
- break;
-
- case SDLK_t:
- // Toggle accepting of incoming trade requests
- {
- unsigned int deflt = player_relations.getDefault();
- if (deflt & PlayerRelation::TRADE) {
- chatWindow->
+ }
+ SDL_FreeSurface(screenshot);
+ }
+ used = true;
+ break;
+
+ default:
+ break;
+
+ case SDLK_f:
+ // Find path to mouse (debug purpose)
+ viewport->toggleDebugPath();
+ used = true;
+ break;
+
+ case SDLK_t:
+ // Toggle accepting of incoming trade requests
+ {
+ unsigned int deflt = player_relations.getDefault();
+ if (deflt & PlayerRelation::TRADE) {
+ chatWindow->
chatLog("Ignoring incoming trade requests",
BY_SERVER);
- deflt &= ~PlayerRelation::TRADE;
- } else {
- chatWindow->chatLog("Accepting incoming trade "
+ deflt &= ~PlayerRelation::TRADE;
+ } else {
+ chatWindow->chatLog("Accepting incoming trade "
"requests", BY_SERVER);
- deflt |= PlayerRelation::TRADE;
- }
-
- player_relations.setDefault(deflt);
- }
- used = true;
- break;
- }
-
- // 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())
- {
- chatWindow->scroll(-DEFAULT_CHAT_WINDOW_SCROLL);
- used = true;
- }
- break;
-
- case SDLK_PAGEDOWN:
- if (chatWindow->isVisible())
- {
- chatWindow->scroll(DEFAULT_CHAT_WINDOW_SCROLL);
- used = true;
- }
- break;
-
- 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_F11: requestedWindow = newSkillWindow; break;
-
- case SDLK_RETURN:
- // Input chat window
- if (chatWindow->isInputFocused() ||
- deathNotice != NULL ||
- weightNotice != NULL)
- {
- 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);
- // 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;
- }
- }
- switch (tKey) {
- case KeyboardConfig::KEY_PICKUP:
- {
- FloorItem *item =
+ deflt |= PlayerRelation::TRADE;
+ }
+
+ player_relations.setDefault(deflt);
+ }
+ used = true;
+ break;
+ }
+
+ // 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())
+ {
+ chatWindow->scroll(-DEFAULT_CHAT_WINDOW_SCROLL);
+ used = true;
+ }
+ break;
+
+ case SDLK_PAGEDOWN:
+ if (chatWindow->isVisible())
+ {
+ chatWindow->scroll(DEFAULT_CHAT_WINDOW_SCROLL);
+ used = true;
+ }
+ break;
+
+ 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_F11: requestedWindow = newSkillWindow; break;
+
+ case SDLK_RETURN:
+ // Input chat window
+ if (chatWindow->isInputFocused() ||
+ deathNotice != NULL ||
+ weightNotice != NULL)
+ {
+ 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);
+ // 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;
+ }
+ }
+ 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;
- 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->
+ 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);
- }
-
- 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;
- }
- }
-
- if (requestedWindow)
- {
- requestedWindow->setVisible(!requestedWindow->isVisible());
- if (requestedWindow->isVisible())
- {
- requestedWindow->requestMoveToTop();
- }
- used = true;
- }
-
- }
-
- // Quit event
- else if (event.type == SDL_QUIT)
- {
- done = true;
- }
-
- // Push input to GUI when not used
- if (!used)
- {
- try
- {
- guiInput->pushInput(event);
- }
- catch (gcn::Exception e)
- {
- const char* err = e.getMessage().c_str();
- logger->log("Warning: guichan input exception: %s", err);
- }
- }
+ }
+
+ 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;
+ }
+ }
+
+ if (requestedWindow)
+ {
+ requestedWindow->setVisible(!requestedWindow->isVisible());
+ if (requestedWindow->isVisible())
+ {
+ requestedWindow->requestMoveToTop();
+ }
+ used = true;
+ }
+
+ }
+
+ // Quit event
+ else if (event.type == SDL_QUIT)
+ {
+ done = true;
+ }
+
+ // Push input to GUI when not used
+ if (!used)
+ {
+ try
+ {
+ guiInput->pushInput(event);
+ }
+ catch (gcn::Exception e)
+ {
+ const char* err = e.getMessage().c_str();
+ logger->log("Warning: guichan input exception: %s", err);
+ }
+ }
} // End while
// If the user is configuring the keys then don't respond.
@@ -739,112 +757,112 @@ void Game::handleInput()
}
// Moving player around
if (player_node->mAction != Being::DEAD &&
- current_npc == 0 &&
- !chatWindow->isInputFocused())
+ current_npc == 0 &&
+ !chatWindow->isInputFocused())
+ {
+ // Get the state of the keyboard keys
+ keyboard.refreshActiveKeys();
+
+ const Uint16 x = player_node->mX;
+ const Uint16 y = player_node->mY;
+ unsigned char direction = 0;
+
+ // Translate pressed keys to movement and direction
+ if (keyboard.isKeyActive(keyboard.KEY_MOVE_UP) ||
+ (joystick && joystick->isUp()))
+ {
+ direction |= Being::UP;
+ }
+ else if (keyboard.isKeyActive(keyboard.KEY_MOVE_DOWN) ||
+ (joystick && joystick->isDown()))
+ {
+ direction |= Being::DOWN;
+ }
+
+ if (keyboard.isKeyActive(keyboard.KEY_MOVE_LEFT) ||
+ (joystick && joystick->isLeft()))
+ {
+ direction |= Being::LEFT;
+ }
+ else if (keyboard.isKeyActive(keyboard.KEY_MOVE_RIGHT) ||
+ (joystick && joystick->isRight()))
+ {
+ direction |= Being::RIGHT;
+ }
+
+ player_node->setWalkingDir(direction);
+
+ // Attacking monsters
+ if (keyboard.isKeyActive(keyboard.KEY_ATTACK) ||
+ (joystick && joystick->buttonPressed(0)))
{
- // Get the state of the keyboard keys
- keyboard.refreshActiveKeys();
-
- const Uint16 x = player_node->mX;
- const Uint16 y = player_node->mY;
- unsigned char direction = 0;
-
- // Translate pressed keys to movement and direction
- if (keyboard.isKeyActive(keyboard.KEY_MOVE_UP) ||
- (joystick && joystick->isUp()))
- {
- direction |= Being::UP;
- }
- else if (keyboard.isKeyActive(keyboard.KEY_MOVE_DOWN) ||
- (joystick && joystick->isDown()))
- {
- direction |= Being::DOWN;
- }
-
- if (keyboard.isKeyActive(keyboard.KEY_MOVE_LEFT) ||
- (joystick && joystick->isLeft()))
- {
- direction |= Being::LEFT;
- }
- else if (keyboard.isKeyActive(keyboard.KEY_MOVE_RIGHT) ||
- (joystick && joystick->isRight()))
- {
- direction |= Being::RIGHT;
- }
-
- player_node->setWalkingDir(direction);
-
- // Attacking monsters
- if (keyboard.isKeyActive(keyboard.KEY_ATTACK) ||
- (joystick && joystick->buttonPressed(0)))
- {
- Being *target = NULL;
- 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++;
-
- // Attack priorioty is: Monster, Player, auto target
- target = beingManager->findBeing(
- targetX, targetY, Being::MONSTER);
- if (!target)
- target = beingManager->findBeing(
- targetX, targetY, Being::PLAYER);
- }
-
- player_node->attack(target, newTarget);
- }
-
- // Target the nearest player if 'q' is pressed
- if ( keyboard.isKeyActive(keyboard.KEY_TARGET_PLAYER) )
- //if (keys[SDLK_q])
- {
- Being *target =
- beingManager->
+ Being *target = NULL;
+ 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++;
+
+ // Attack priorioty is: Monster, Player, auto target
+ target = beingManager->findBeing(
+ targetX, targetY, Being::MONSTER);
+ if (!target)
+ target = beingManager->findBeing(
+ targetX, targetY, Being::PLAYER);
+ }
+
+ player_node->attack(target, newTarget);
+ }
+
+ // Target the nearest player if 'q' is pressed
+ if ( keyboard.isKeyActive(keyboard.KEY_TARGET_PLAYER) )
+ //if (keys[SDLK_q])
+ {
+ Being *target =
+ beingManager->
findNearestLivingBeing(player_node, 20, Being::PLAYER);
- if (target)
- {
- player_node->setTarget(target);
- }
- }
-
- // Target the nearest monster if 'a' pressed
- if ( keyboard.isKeyActive(keyboard.KEY_TARGET_CLOSEST) )
- //if (keys[SDLK_a])
- {
- Being *target =
- beingManager->findNearestLivingBeing(x, y, 20, Being::MONSTER);
-
- if (target)
- {
- player_node->setTarget(target);
- }
- }
-
- if (joystick)
- {
- if (joystick->buttonPressed(1))
- {
- FloorItem *item = floorItemManager->findByCoordinates(x, y);
-
- if (item)
- player_node->pickUp(item);
- }
- else if (joystick->buttonPressed(2))
- {
- player_node->toggleSit();
- }
- }
+ if (target)
+ {
+ player_node->setTarget(target);
+ }
+ }
+
+ // Target the nearest monster if 'a' pressed
+ if ( keyboard.isKeyActive(keyboard.KEY_TARGET_CLOSEST) )
+ //if (keys[SDLK_a])
+ {
+ Being *target =
+ beingManager->findNearestLivingBeing(x, y, 20, Being::MONSTER);
+
+ if (target)
+ {
+ player_node->setTarget(target);
+ }
+ }
+
+ if (joystick)
+ {
+ if (joystick->buttonPressed(1))
+ {
+ FloorItem *item = floorItemManager->findByCoordinates(x, y);
+
+ if (item)
+ player_node->pickUp(item);
+ }
+ else if (joystick->buttonPressed(2))
+ {
+ player_node->toggleSit();
+ }
+ }
}
}
diff --git a/src/net/beinghandler.cpp b/src/net/beinghandler.cpp
index f3c0cfb4..778c8cfe 100644
--- a/src/net/beinghandler.cpp
+++ b/src/net/beinghandler.cpp
@@ -45,6 +45,7 @@ BeingHandler::BeingHandler()
static const Uint16 _messages[] = {
SMSG_BEING_VISIBLE,
SMSG_BEING_MOVE,
+ SMSG_BEING_MOVE2,
SMSG_BEING_REMOVE,
SMSG_BEING_ACTION,
SMSG_BEING_LEVELUP,
@@ -164,6 +165,33 @@ void BeingHandler::handleMessage(MessageIn *msg)
msg->readInt8(); // unknown / sit
break;
+ case SMSG_BEING_MOVE2:
+ /*
+ * A simplified movement packet, used by the
+ * later versions of eAthena for both mobs and
+ * players
+ */
+ dstBeing = beingManager->findBeing(msg->readInt32());
+
+ Uint16 srcX, srcY, dstX, dstY;
+ msg->readCoordinatePair(srcX, srcY, dstX, dstY);
+ msg->readInt32(); // Server tick
+
+ /*
+ * This packet doesn't have enough info to actually
+ * create a new being, so if the being isn't found,
+ * we'll just pretend the packet didn't happen
+ */
+
+ if (dstBeing) {
+ dstBeing->setAction(Being::STAND);
+ dstBeing->mX = srcX;
+ dstBeing->mY = srcY;
+ dstBeing->setDestination(dstX, dstY);
+ }
+
+ break;
+
case SMSG_BEING_REMOVE:
// A being should be removed or has died
dstBeing = beingManager->findBeing(msg->readInt32());
diff --git a/src/net/protocol.h b/src/net/protocol.h
index f90fcba3..53f245b5 100644
--- a/src/net/protocol.h
+++ b/src/net/protocol.h
@@ -26,6 +26,7 @@
// Packets from server to client
#define SMSG_LOGIN_SUCCESS 0x0073 /**< Contains starting location */
+#define SMSG_SERVER_PING 0x007f /**< Contains server tick */
#define SMSG_PLAYER_UPDATE_1 0x01d8
#define SMSG_PLAYER_UPDATE_2 0x01d9
#define SMSG_PLAYER_MOVE 0x01da /**< A nearby player moves */
@@ -57,6 +58,8 @@
#define SMSG_ITEM_REMOVE 0x00a1 /**< An item disappers */
#define SMSG_BEING_VISIBLE 0x0078
#define SMSG_BEING_MOVE 0x007b /**< A nearby monster moves */
+#define SMSG_BEING_SPAWN 0x007c /**< A being spawns nearby */
+#define SMSG_BEING_MOVE2 0x0086 /**< New eAthena being moves */
#define SMSG_BEING_REMOVE 0x0080
#define SMSG_BEING_CHANGE_LOOKS 0x00c3
#define SMSG_BEING_CHANGE_LOOKS2 0x01d7 /**< Same as 0x00c3, but 16 bit ID */
@@ -102,6 +105,7 @@
#define SMSG_PARTY_MESSAGE 0x0109
// Packets from client to server
+#define CMSG_CLIENT_PING 0x007e /**< Send to server with tick */
#define CMSG_TRADE_RESPONSE 0x00e6
#define CMSG_ITEM_PICKUP 0x009f
#define CMSG_MAP_LOADED 0x007d