summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt6
-rw-r--r--src/Makefile.am6
-rw-r--r--src/being.cpp196
-rw-r--r--src/being.h13
-rw-r--r--src/commandhandler.cpp68
-rw-r--r--src/commandhandler.h15
-rw-r--r--src/game.cpp78
-rw-r--r--src/gui/connectiondialog.cpp (renamed from src/gui/connection.cpp)2
-rw-r--r--src/gui/connectiondialog.h (renamed from src/gui/connection.h)0
-rw-r--r--src/gui/inventorywindow.cpp18
-rw-r--r--src/gui/inventorywindow.h1
-rw-r--r--src/gui/itemcontainer.cpp4
-rw-r--r--src/gui/outfitwindow.cpp306
-rw-r--r--src/gui/outfitwindow.h92
-rw-r--r--src/gui/viewport.cpp18
-rw-r--r--src/gui/widgets/whispertab.cpp23
-rw-r--r--src/gui/windowmenu.cpp1
-rw-r--r--src/keyboardconfig.cpp1
-rw-r--r--src/keyboardconfig.h1
-rw-r--r--src/localplayer.cpp74
-rw-r--r--src/localplayer.h4
-rw-r--r--src/main.cpp2
-rw-r--r--src/net/ea/beinghandler.cpp19
-rw-r--r--src/net/ea/playerhandler.cpp4
-rw-r--r--src/net/ea/playerhandler.h2
-rw-r--r--src/net/ea/protocol.h1
-rw-r--r--src/net/playerhandler.h2
-rw-r--r--src/net/tmwserv/beinghandler.cpp9
-rw-r--r--src/net/tmwserv/gameserver/player.cpp7
-rw-r--r--src/net/tmwserv/gameserver/player.h1
-rw-r--r--src/net/tmwserv/playerhandler.cpp9
-rw-r--r--src/net/tmwserv/playerhandler.h2
-rw-r--r--src/net/tmwserv/protocol.h8
-rw-r--r--src/resources/itemdb.cpp4
34 files changed, 761 insertions, 236 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 76fd3545..91fe8e06 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -169,6 +169,8 @@ SET(SRCS
gui/npcpostdialog.h
gui/okdialog.cpp
gui/okdialog.h
+ gui/outfitwindow.cpp
+ gui/outfitwindow.h
gui/palette.cpp
gui/palette.h
gui/partywindow.cpp
@@ -464,8 +466,8 @@ SET(SRCS_TMW
gui/buddywindow.h
gui/changeemaildialog.cpp
gui/changeemaildialog.h
- gui/connection.cpp
- gui/connection.h
+ gui/connectiondialog.cpp
+ gui/connectiondialog.h
gui/guildlistbox.cpp
gui/guildlistbox.h
gui/guildwindow.cpp
diff --git a/src/Makefile.am b/src/Makefile.am
index dd9177e4..23de64bc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -118,6 +118,8 @@ tmw_SOURCES = gui/widgets/avatar.cpp \
gui/npcpostdialog.h \
gui/okdialog.cpp \
gui/okdialog.h \
+ gui/outfitwindow.cpp \
+ gui/outfitwindow.h \
gui/palette.cpp \
gui/palette.h \
gui/partywindow.cpp \
@@ -368,8 +370,8 @@ tmw_SOURCES += \
gui/buddywindow.h \
gui/changeemaildialog.cpp \
gui/changeemaildialog.h \
- gui/connection.cpp \
- gui/connection.h \
+ gui/connectiondialog.cpp \
+ gui/connectiondialog.h \
gui/guildlistbox.cpp \
gui/guildlistbox.h \
gui/guildwindow.cpp \
diff --git a/src/being.cpp b/src/being.cpp
index 37cb6987..3593bb94 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -56,11 +56,6 @@
#include <cassert>
#include <cmath>
-namespace {
-const bool debug_movement = true;
-}
-
-
#define BEING_EFFECTS_FILE "effects.xml"
#define HAIR_FILE "hair.xml"
@@ -157,169 +152,66 @@ void Being::setDestination(Uint16 destX, Uint16 destY)
#endif
#ifdef TMWSERV_SUPPORT
-void Being::adjustCourse(int srcX, int srcY, int dstX, int dstY)
+
+void Being::adjustCourse(int srcX, int srcY)
+{
+ setDestination(srcX, srcY, mDest.x, mDest.y);
+}
+
+void Being::setDestination(int dstX, int dstY)
{
- if (debug_movement)
- printf("%p adjustCourse(%d, %d, %d, %d)\n",
- (void*) this, srcX, srcY, dstX, dstY);
+ setDestination(mPos.x, mPos.y, dstX, dstY);
+}
+void Being::setDestination(int srcX, int srcY, int dstX, int dstY)
+{
mDest.x = dstX;
mDest.y = dstY;
- // Find a path to the destination when it is at least a tile away
- if (mMap && fabsf((mDest - mPos).length()) > 32) {
- setPath(mMap->findPath((int) mPos.x / 32, (int) mPos.y / 32,
- dstX / 32, dstY / 32, getWalkMask()));
- } else {
- setPath(Path());
- }
+ Path thisPath;
- // TODO: Evaluate the implementation of this method
- /*
- if (mX / 32 == dstX / 32 && mY / 32 == dstY / 32)
+ if (mMap)
{
- // The being is already on the last tile of the path.
- Path p;
- p.push_back(Position(dstX, dstY));
- setPath(p);
- return;
- }
-
- Path p1;
- int p1_size, p1_length;
- Uint16 *p1_dist;
- int onPath = -1;
- if (srcX / 32 == dstX / 32 && srcY / 32 == dstY / 32)
- {
- p1_dist = new Uint16[1];
- p1_size = 1;
- p1_dist[0] = 0;
- p1_length = 0;
- }
- else
- {
- p1 = mMap->findPath(srcX / 32, srcY / 32, dstX / 32, dstY / 32, getWalkMask());
- if (p1.empty())
- {
- // No path, but don't teleport since it could be user input.
- setPath(p1);
- return;
- }
- p1_size = p1.size();
- p1_dist = new Uint16[p1_size];
- int j = 0;
- // Remove last tile so that it can be replaced by the exact destination.
- p1.pop_back();
- for (Path::iterator i = p1.begin(), i_end = p1.end(); i != i_end; ++i)
- {
- // Get distance from source to tile i.
- p1_dist[j] = mMap->getMetaTile(i->x, i->y)->Gcost;
- // Check if the being is already walking on the path.
- if (i->x == mX / 32 && i->y == mY / 32)
- {
- onPath = j;
- }
- // Do not set any offset for intermediate steps.
- i->x = i->x * 32;
- i->y = i->y * 32;
- ++j;
- }
- p1_length = mMap->getMetaTile(dstX / 32, dstY / 32)->Gcost;
- p1_dist[p1_size - 1] = p1_length;
- }
- p1.push_back(Position(dstX, dstY));
-
- if (mX / 32 == srcX / 32 && mY / 32 == srcY / 32)
+ thisPath = mMap->findPath((int) srcX / 32, (int) srcY / 32,
+ dstX / 32, dstY / 32, getWalkMask());
+ }
+ if (thisPath.empty())
{
- // The being is at the start of the path.
- setPath(p1);
- delete[] p1_dist;
+ setPath(Path());
return;
}
- if (onPath >= 0)
- {
- // The being is already on the path, but it needs to be slowed down.
- for (int j = onPath; j >= 0; --j)
- {
- p1.pop_front();
- }
- int r = p1_length - p1_dist[onPath]; // remaining length
- assert(r > 0);
- setPath(p1, p1_length * 1024 / r);
- delete[] p1_dist;
- return;
- }
+ // FIXME: Look into making this code neater.
+ // Interpolate the offsets. Also convert from tile based to pixel based
- Path bestPath;
- int bestRating = -1, bestStart = 0, bestLength = 0;
- int j = 0;
+ // Note: I divided the offsets by 32 then muilpied it back to get the top left
+ // Conner of where the tile is. (If you know a better way then please change it)
- for (Path::iterator i = p1.begin(), i_end = p1.end(); i != i_end; ++i)
- {
- // Look if it is worth passing by tile i.
- Path p2 = mMap->findPath(mX / 32, mY / 32, i->x / 32, i->y / 32, getWalkMask());
- if (!p2.empty())
- {
- int l1 = mMap->getMetaTile(i->x / 32, i->y / 32)->Gcost;
- int l2 = p1_length - p1_dist[j];
- int r = l1 + l2 / 2; // TODO: tune rating formula
- assert(r > 0);
- if (bestRating < 0 || r < bestRating)
- {
- bestPath.swap(p2);
- bestRating = r;
- bestStart = j;
- bestLength = l1 + l2;
- }
- }
- ++j;
- }
+ // Find the starting offset
+ int startX = srcX - ((srcX / 32) * 32 + 16);
+ int startY = srcY - ((srcY / 32) * 32 + 16);
- if (bestRating < 0)
- {
- // Unable to reach the path? Still, don't teleport since it could be
- // user input instead of server command.
- setPath(p1);
- delete[] p1_dist;
- return;
- }
+ // Find the ending offset
+ int endX = dstX - ((dstX / 32) * 32 + 16);
+ int endY = dstY - ((dstY / 32) * 32 + 16);
- bestPath.pop_back();
- for (Path::iterator i = bestPath.begin(), i_end = bestPath.end(); i != i_end; ++i)
- {
- i->x = i->x * 32;
- i->y = i->y * 32;
- }
+ // Find the distance, and divide it by the number of steps
+ int changeX = (endX - startX) / thisPath.size();
+ int changeY = (endY - startY) / thisPath.size();
- // Concatenate paths.
- for (int j = bestStart; j > 0; --j)
+ // Convert the map path to pixels over tiles
+ // And add interpolation between the starting and ending offsets
+ Path::iterator it = thisPath.begin();
+ int i = 0;
+ while(it != thisPath.end())
{
- p1.pop_front();
+ it->x = (it->x * 32 + 16) + startX + (changeX * i);
+ it->y = (it->y * 32 + 16) + startY + (changeY * i);
+ i++;
+ it++;
}
- p1.splice(p1.begin(), bestPath);
-
- assert(bestLength > 0);
- setPath(p1, p1_length * 1024 / bestLength);
- delete[] p1_dist;
- */
-}
-
-void Being::adjustCourse(int srcX, int srcY)
-{
- if (debug_movement)
- printf("%p adjustCourse(%d, %d)\n", (void*) this, srcX, srcY);
-
- if (!mPath.empty())
- adjustCourse(srcX, srcY, mPath.back().x * 32, mPath.back().y * 32);
-}
-
-void Being::setDestination(int destX, int destY)
-{
- if (debug_movement)
- printf("%p setDestination(%d, %d)\n", (void*) this, destX, destY);
- adjustCourse((int) mPos.x, (int) mPos.y, destX, destY);
+ setPath(thisPath);
}
#endif // TMWSERV_SUPPORT
@@ -332,7 +224,7 @@ void Being::setPath(const Path &path)
{
mPath = path;
#ifdef TMWSERV_SUPPORT
- std::cout << this << " New path: " << path << std::endl;
+// std::cout << this << " New path: " << path << std::endl;
#else
if (mAction != WALK && mAction != DEAD)
{
@@ -668,8 +560,8 @@ void Being::logic()
#ifdef TMWSERV_SUPPORT
const Vector dest = (mPath.empty()) ?
- mDest : Vector(mPath.front().x * 32 + 16,
- mPath.front().y * 32 + 16);
+ mDest : Vector(mPath.front().x,
+ mPath.front().y);
Vector dir = dest - mPos;
const float length = dir.length();
diff --git a/src/being.h b/src/being.h
index 6c849350..040d55a9 100644
--- a/src/being.h
+++ b/src/being.h
@@ -183,12 +183,15 @@ class Being : public Sprite, public ConfigListener
#ifdef EATHENA_SUPPORT
virtual void setDestination(Uint16 destX, Uint16 destY);
#else
- void setDestination(int x, int y);
+ /**
+ * Creates a path for the being from sx,sy to ex,ey
+ */
+ void setDestination(int sx, int sy, int ex, int ey);
/**
- * Returns the destination for this being.
+ * Creates a path for the being from currect position to ex and ey
*/
- const Vector &getDestination() const { return mDest; }
+ void setDestination(int ex, int ey);
/**
* Adjusts course to expected start point.
@@ -196,9 +199,9 @@ class Being : public Sprite, public ConfigListener
void adjustCourse(int srcX, int srcY);
/**
- * Adjusts course to expected start and end points.
+ * Returns the destination for this being.
*/
- void adjustCourse(int srcX, int srcY, int destX, int destY);
+ const Vector &getDestination() const { return mDest; }
#endif
/**
diff --git a/src/commandhandler.cpp b/src/commandhandler.cpp
index 0af77398..d2a303e8 100644
--- a/src/commandhandler.cpp
+++ b/src/commandhandler.cpp
@@ -25,6 +25,7 @@
#include "channel.h"
#include "game.h"
#include "localplayer.h"
+#include "playerrelations.h"
#include "gui/widgets/channeltab.h"
#include "gui/widgets/chattab.h"
@@ -76,6 +77,14 @@ void CommandHandler::handleCommand(const std::string &command, ChatTab *tab)
{
handleQuery(args, tab);
}
+ else if (type == "ignore")
+ {
+ handleIgnore(args, tab);
+ }
+ else if (type == "unignore")
+ {
+ handleUnignore(args, tab);
+ }
else if (type == "join")
{
handleJoin(args, tab);
@@ -154,6 +163,9 @@ void CommandHandler::handleHelp(const std::string &args, ChatTab *tab)
tab->chatLog(_("/query > Makes a tab for private messages with another user"));
tab->chatLog(_("/q > Alias of query"));
+ tab->chatLog(_("/ignore > ignore a player"));
+ tab->chatLog(_("/unignore > stop ignoring a player"));
+
tab->chatLog(_("/list > Display all public channels"));
tab->chatLog(_("/join > Join or create a channel"));
@@ -192,6 +204,12 @@ void CommandHandler::handleHelp(const std::string &args, ChatTab *tab)
tab->chatLog(_("Command: /clear"));
tab->chatLog(_("This command clears the chat log of previous chat."));
}
+ else if (args == "ignore")
+ {
+ tab->chatLog(_("Command: /ignore <player>"));
+ tab->chatLog(_("This command ignores the given player reguardless of "
+ "current relations."));
+ }
else if (args == "join")
{
tab->chatLog(_("Command: /join <channel>"));
@@ -257,6 +275,12 @@ void CommandHandler::handleHelp(const std::string &args, ChatTab *tab)
tab->chatLog(_("Command: /toggle"));
tab->chatLog(_("This command displays the return toggle status."));
}
+ else if (args == "unignore")
+ {
+ tab->chatLog(_("Command: /unignore <player>"));
+ tab->chatLog(_("This command stops ignoring the given player if they "
+ "are being ignored"));
+ }
else if (args == "where")
{
tab->chatLog(_("Command: /where"));
@@ -416,3 +440,47 @@ void CommandHandler::handlePresent(const std::string &args, ChatTab *tab)
{
chatWindow->doPresent();
}
+
+void CommandHandler::handleIgnore(const std::string &args, ChatTab *tab)
+{
+ if (args.empty())
+ {
+ tab->chatLog(_("Please specify a name."), BY_SERVER);
+ return;
+ }
+
+ if (player_relations.getRelation(args) == PlayerRelation::IGNORED)
+ {
+ tab->chatLog(_("Player already ignored!"), BY_SERVER);
+ return;
+ }
+ else
+ player_relations.setRelation(args, PlayerRelation::IGNORED);
+
+ if (player_relations.getRelation(args) == PlayerRelation::IGNORED)
+ tab->chatLog(_("Player successfully ignored!"), BY_SERVER);
+ else
+ tab->chatLog(_("Player could not be ignored!"), BY_SERVER);
+}
+
+void CommandHandler::handleUnignore(const std::string &args, ChatTab *tab)
+{
+ if (args.empty())
+ {
+ tab->chatLog(_("Please specify a name."), BY_SERVER);
+ return;
+ }
+
+ if (player_relations.getRelation(args) == PlayerRelation::IGNORED)
+ player_relations.removePlayer(args);
+ else
+ {
+ tab->chatLog(_("Player wasn't ignored!"), BY_SERVER);
+ return;
+ }
+
+ if (player_relations.getRelation(args) != PlayerRelation::IGNORED)
+ tab->chatLog(_("Player no longer ignored!"), BY_SERVER);
+ else
+ tab->chatLog(_("Player could not be unignored!"), BY_SERVER);
+}
diff --git a/src/commandhandler.h b/src/commandhandler.h
index 783e400d..eb73f239 100644
--- a/src/commandhandler.h
+++ b/src/commandhandler.h
@@ -54,7 +54,10 @@ class CommandHandler
static char parseBoolean(const std::string &value);
- private:
+ protected:
+ friend class ChatTab;
+ friend class WhisperTab;
+
/**
* Handle an announce command.
*/
@@ -124,6 +127,16 @@ class CommandHandler
* Handle a present command.
*/
void handlePresent(const std::string &args, ChatTab *tab);
+
+ /**
+ * Handle an ignore command.
+ */
+ void handleIgnore(const std::string &args, ChatTab *tab);
+
+ /**
+ * Handle an unignore command.
+ */
+ void handleUnignore(const std::string &args, ChatTab *tab);
};
extern CommandHandler *commandHandler;
diff --git a/src/game.cpp b/src/game.cpp
index 82750dac..f1df57cc 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -58,6 +58,7 @@
#include "gui/ministatus.h"
#include "gui/npcdialog.h"
#include "gui/okdialog.h"
+#include "gui/outfitwindow.h"
#include "gui/sdlinput.h"
#include "gui/sell.h"
#include "gui/setup.h"
@@ -139,6 +140,7 @@ HelpWindow *helpWindow;
DebugWindow *debugWindow;
ShortcutWindow *itemShortcutWindow;
ShortcutWindow *emoteShortcutWindow;
+OutfitWindow *outfitWindow;
BeingManager *beingManager = NULL;
FloorItemManager *floorItemManager = NULL;
@@ -233,6 +235,7 @@ static void createGuiWindows()
new ItemShortcutContainer);
emoteShortcutWindow = new ShortcutWindow("EmoteShortcut",
new EmoteShortcutContainer);
+ outfitWindow = new OutfitWindow();
localChatTab = new ChatTab(_("General"));
@@ -278,6 +281,7 @@ static void destroyGuiWindows()
delete itemShortcutWindow;
delete emoteShortcutWindow;
delete storageWindow;
+ delete outfitWindow;
}
Game::Game():
@@ -610,6 +614,65 @@ void Game::handleInput()
}
}
+ if (event.key.keysym.mod & KMOD_RCTRL && !chatWindow->isInputFocused())
+ {
+ switch (event.key.keysym.sym)
+ {
+ case SDLK_1:
+ outfitWindow->wearOutfit(0);
+ used = true;
+ break;
+
+ case SDLK_2:
+ outfitWindow->wearOutfit(1);
+ used = true;
+ break;
+
+ case SDLK_3:
+ outfitWindow->wearOutfit(2);
+ used = true;
+ break;
+
+ case SDLK_4:
+ outfitWindow->wearOutfit(3);
+ used = true;
+ break;
+
+ case SDLK_5:
+ outfitWindow->wearOutfit(4);
+ used = true;
+ break;
+
+ case SDLK_6:
+ outfitWindow->wearOutfit(5);
+ used = true;
+ break;
+
+ case SDLK_7:
+ outfitWindow->wearOutfit(6);
+ used = true;
+ break;
+
+ case SDLK_8:
+ outfitWindow->wearOutfit(7);
+ used = true;
+ break;
+
+ case SDLK_9:
+ outfitWindow->wearOutfit(8);
+ used = true;
+ break;
+
+ case SDLK_0:
+ outfitWindow->wearOutfit(9);
+ used = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+
const int tKey = keyboard.getKeyIndex(event.key.keysym.sym);
switch (tKey)
{
@@ -669,7 +732,7 @@ void Game::handleInput()
default:
break;
}
- if (keyboard.isEnabled() &&
+ if (keyboard.isEnabled() &&
!chatWindow->isInputFocused() && !npcDialog->isInputFocused())
{
const int tKey = keyboard.getKeyIndex(event.key.keysym.sym);
@@ -786,6 +849,9 @@ void Game::handleInput()
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();
@@ -926,7 +992,7 @@ void Game::handleInput()
}
#else
player_node->setWalkingDir(direction);
-
+#endif
// Attacking monsters
if (keyboard.isKeyActive(keyboard.KEY_ATTACK) ||
(joystick && joystick->buttonPressed(0)))
@@ -943,7 +1009,11 @@ void Game::handleInput()
// A set target has highest priority
if (!player_node->getTarget())
{
+#ifdef TMWSERV_SUPPORT
+ Uint16 targetX = x / 32, targetY = y / 32;
+#else
Uint16 targetX = x, targetY = y;
+#endif
// Only auto target Monsters
target = beingManager->findNearestLivingBeing(targetX, targetY,
20, Being::MONSTER);
@@ -951,8 +1021,6 @@ void Game::handleInput()
player_node->attack(target, newTarget);
}
-#endif
-
// Target the nearest player/monster/npc
if ((keyboard.isKeyActive(keyboard.KEY_TARGET_PLAYER) ||
keyboard.isKeyActive(keyboard.KEY_TARGET_CLOSEST) ||
@@ -996,7 +1064,7 @@ void Game::handleInput()
}
// Stop attacking if the right key is pressed
- if (!keyboard.isKeyActive(keyboard.KEY_ATTACK)
+ if (!keyboard.isKeyActive(keyboard.KEY_ATTACK)
&& keyboard.isKeyActive(keyboard.KEY_TARGET))
{
player_node->stopAttack();
diff --git a/src/gui/connection.cpp b/src/gui/connectiondialog.cpp
index 4863edcd..1c3b7ff5 100644
--- a/src/gui/connection.cpp
+++ b/src/gui/connectiondialog.cpp
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "connection.h"
+#include "connectiondialog.h"
#include "gui/widgets/button.h"
#include "gui/widgets/label.h"
diff --git a/src/gui/connection.h b/src/gui/connectiondialog.h
index d6059c3f..d6059c3f 100644
--- a/src/gui/connection.h
+++ b/src/gui/connectiondialog.h
diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp
index 47f66e76..06e43eac 100644
--- a/src/gui/inventorywindow.cpp
+++ b/src/gui/inventorywindow.cpp
@@ -79,6 +79,7 @@ InventoryWindow::InventoryWindow(int invSize):
mUseButton = new Button(longestUseString, "use", this);
mDropButton = new Button(_("Drop"), "drop", this);
mSplitButton = new Button(_("Split"), "split", this);
+ mOutfitButton = new Button(_("Outfits"), "outfit", this);
mItems = new ItemContainer(player_node->getInventory());
mItems->addSelectionListener(this);
@@ -103,6 +104,7 @@ InventoryWindow::InventoryWindow(int invSize):
place(0, 2, mUseButton);
place(1, 2, mDropButton);
place(2, 2, mSplitButton);
+ place(6, 2, mOutfitButton);
Layout &layout = getLayout();
layout.setRowHeight(1, Layout::AUTO_SET);
@@ -156,6 +158,16 @@ void InventoryWindow::logic()
void InventoryWindow::action(const gcn::ActionEvent &event)
{
+ if (event.getId() == "outfit")
+ {
+ extern Window *outfitWindow;
+ outfitWindow->setVisible(!outfitWindow->isVisible());
+ if (outfitWindow->isVisible())
+ {
+ outfitWindow->requestMoveToTop();
+ }
+ }
+
Item *item = mItems->getSelectedItem();
if (!item)
@@ -163,7 +175,7 @@ void InventoryWindow::action(const gcn::ActionEvent &event)
if (event.getId() == "use")
{
- if (item->isEquipment())
+ if (item->isEquipment())
{
if (item->isEquipped())
Net::getInventoryHandler()->unequipItem(item);
@@ -259,10 +271,10 @@ void InventoryWindow::updateButtons()
mDropButton->setEnabled(false);
return;
}
-
+
mUseButton->setEnabled(true);
mDropButton->setEnabled(true);
-
+
if (selectedItem->isEquipment())
{
if (selectedItem->isEquipped())
diff --git a/src/gui/inventorywindow.h b/src/gui/inventorywindow.h
index 6e34666d..fbda5ac7 100644
--- a/src/gui/inventorywindow.h
+++ b/src/gui/inventorywindow.h
@@ -109,6 +109,7 @@ class InventoryWindow : public Window,
gcn::Button *mUseButton;
gcn::Button *mDropButton;
gcn::Button *mSplitButton;
+ gcn::Button *mOutfitButton;
gcn::Label *mWeightLabel;
gcn::Label *mSlotsLabel;
diff --git a/src/gui/itemcontainer.cpp b/src/gui/itemcontainer.cpp
index 54aa818b..d8ae6e20 100644
--- a/src/gui/itemcontainer.cpp
+++ b/src/gui/itemcontainer.cpp
@@ -23,6 +23,7 @@
#include "gui/chat.h"
#include "gui/itempopup.h"
+#include "gui/outfitwindow.h"
#include "gui/palette.h"
#include "gui/sdlinput.h"
#include "gui/viewport.h"
@@ -162,6 +163,7 @@ void ItemContainer::selectNone()
{
setSelectedIndex(-1);
mSelectionStatus = SEL_NONE;
+ outfitWindow->setItemSelected(-1);
}
void ItemContainer::setSelectedIndex(int newIndex)
@@ -260,6 +262,8 @@ void ItemContainer::mousePressed(gcn::MouseEvent &event)
mSelectionStatus = SEL_SELECTING;
itemShortcut->setItemSelected(item->getId());
+ if (item->isEquipment())
+ outfitWindow->setItemSelected(item->getId());
}
else
{
diff --git a/src/gui/outfitwindow.cpp b/src/gui/outfitwindow.cpp
new file mode 100644
index 00000000..f43e1440
--- /dev/null
+++ b/src/gui/outfitwindow.cpp
@@ -0,0 +1,306 @@
+/*
+ * The Mana World
+ * Copyright (C) 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "outfitwindow.h"
+
+#include "configuration.h"
+#include "localplayer.h"
+#include "graphics.h"
+#include "inventory.h"
+#include "equipment.h"
+#include "item.h"
+
+#include "gui/widgets/button.h"
+#include "gui/widgets/checkbox.h"
+#include "gui/widgets/label.h"
+#include "gui/widgets/layout.h"
+
+#include "net/inventoryhandler.h"
+#include "net/net.h"
+
+#include "resources/image.h"
+
+#include "utils/gettext.h"
+#include "utils/stringutils.h"
+
+#include <vector>
+
+OutfitWindow::OutfitWindow():
+ Window(_("Outfits")),
+ mBoxWidth(33),
+ mBoxHeight(33),
+ mGridWidth(3),
+ mGridHeight(3),
+ mItemClicked(false),
+ mItemMoved(NULL),
+ mItemSelected(-1),
+ mCurrentOutfit(0)
+{
+ setWindowName("Outfits");
+ setCloseButton(true);
+ setDefaultSize(250, 250, 118, 180); //160
+
+ mPreviousButton = new Button("<", "previous", this);
+ mNextButton = new Button(">", "next", this);
+ mCurrentLabel = new Label("Outfit: 1");
+ mCurrentLabel->setAlignment(gcn::Graphics::CENTER);
+ mUnequipCheck = new CheckBox(_("Unequip first"),
+ config.getValue("OutfitUnequip", true));
+
+ place(0, 3, mPreviousButton, 1);
+ place(1, 3, mCurrentLabel, 2);
+ place(3, 3, mNextButton, 1);
+ place(0, 4, mUnequipCheck, 4);
+
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, Layout::AUTO_SET);
+ layout.setColWidth(4, Layout::CENTER);
+
+ loadWindowState();
+
+ load();
+}
+
+OutfitWindow::~OutfitWindow()
+{
+ save();
+}
+
+void OutfitWindow::load()
+{
+ memset(mItems, -1, sizeof(mItems));
+ for (int o = 0; o < 10; o++)
+ {
+ std::string outfit = config.getValue("Outfit" + toString(o), "-1");
+ std::string buf;
+ std::stringstream ss(outfit);
+
+ std::vector<int> tokens;
+
+ while (ss >> buf) {
+ tokens.push_back(atoi(buf.c_str()));
+ }
+
+ for (int i = 0; i < (int)tokens.size(); i++)
+ {
+ mItems[o][i] = tokens[i];
+ }
+ }
+}
+
+void OutfitWindow::save()
+{
+ std::string outfitStr;
+ for (int o = 0; o < 10; o++)
+ {
+ for (int i = 0; i < 9; i++)
+ {
+ outfitStr += mItems[o][i] ? toString(mItems[o][i]) : toString(-1);
+ if (i <8) outfitStr += " ";
+ }
+ config.setValue("Outfit" + toString(o), outfitStr);
+ outfitStr = "";
+ }
+ config.setValue("OutfitUnequip", mUnequipCheck->isSelected());
+}
+
+void OutfitWindow::action(const gcn::ActionEvent &event)
+{
+ if (event.getId() == "next")
+ {
+ if (mCurrentOutfit < 9) {
+ mCurrentOutfit++;
+ } else {
+ mCurrentOutfit = 0;
+ }
+ }
+ else if (event.getId() == "previous")
+ {
+ if (mCurrentOutfit > 0) {
+ mCurrentOutfit--;
+ } else {
+ mCurrentOutfit = 9;
+ }
+ }
+ mCurrentLabel->setCaption("Outfit: " + toString(mCurrentOutfit + 1));
+}
+
+void OutfitWindow::wearOutfit(int outfit)
+{
+ Item *item;
+ if (mUnequipCheck->isSelected())
+ {
+ for (int i = 0; i < 11; i++)
+ {
+ //non vis is 3,4,7
+ if (i != 3 && i != 4 && i != 7)
+ {
+#ifdef TMWSERV_SUPPORT
+ if (!(item = player_node->mEquipment.get()->getEquipment(i)))
+ continue;
+#else
+ if (!(item = player_node->getInventory()->getItem(
+ player_node->mEquipment.get()->getEquipment(i))))
+ continue;
+#endif
+ Net::getInventoryHandler()->unequipItem(item);
+ }
+ }
+ }
+
+ for (int i = 0; i < 9; i++)
+ {
+ item = player_node->getInventory()->findItem(mItems[outfit][i]);
+ if (item && item->getQuantity())
+ {
+ if (item->isEquipment()) {
+ Net::getInventoryHandler()->equipItem(item);
+ }
+ }
+ }
+}
+
+void OutfitWindow::draw(gcn::Graphics *graphics)
+{
+ Window::draw(graphics);
+ Graphics *g = static_cast<Graphics*>(graphics);
+
+ for (int i = 0; i < 9; i++)
+ {
+ const int itemX = 10 + (i % mGridWidth) * mBoxWidth;
+ const int itemY = 25 + (i / mGridWidth) * mBoxHeight;
+
+ graphics->setColor(gcn::Color(0, 0, 0, 64));
+ graphics->drawRectangle(gcn::Rectangle(itemX, itemY, 32, 32));
+ graphics->setColor(gcn::Color(255, 255, 255, 32));
+ graphics->fillRectangle(gcn::Rectangle(itemX, itemY, 32, 32));
+
+ if (mItems[mCurrentOutfit][i] < 0)
+ continue;
+
+ Item *item =
+ player_node->getInventory()->findItem(mItems[mCurrentOutfit][i]);
+ if (item) {
+ // Draw item icon.
+ Image* image = item->getImage();
+ if (image) {
+ g->drawImage(image, itemX, itemY);
+ }
+ }
+ }
+ if (mItemMoved)
+ {
+ // Draw the item image being dragged by the cursor.
+ Image* image = mItemMoved->getImage();
+ if (image)
+ {
+ const int tPosX = mCursorPosX - (image->getWidth() / 2);
+ const int tPosY = mCursorPosY - (image->getHeight() / 2);
+
+ g->drawImage(image, tPosX, tPosY);
+ }
+ }
+}
+
+
+void OutfitWindow::mouseDragged(gcn::MouseEvent &event)
+{
+ Window::mouseDragged(event);
+ if (event.getButton() == gcn::MouseEvent::LEFT) {
+ if (!mItemMoved && mItemClicked) {
+ const int index = getIndexFromGrid(event.getX(), event.getY());
+ if (index == -1) {
+ return;
+ }
+ const int itemId = mItems[mCurrentOutfit][index];
+ if (itemId < 0)
+ return;
+ Item *item = player_node->getInventory()->findItem(itemId);
+ if (item)
+ {
+ mItemMoved = item;
+ mItems[mCurrentOutfit][index] = -1;
+ }
+ }
+ if (mItemMoved) {
+ mCursorPosX = event.getX();
+ mCursorPosY = event.getY();
+ }
+ }
+}
+
+void OutfitWindow::mousePressed(gcn::MouseEvent &event)
+{
+ Window::mousePressed(event);
+ const int index = getIndexFromGrid(event.getX(), event.getY());
+ if (index == -1) {
+ return;
+ }
+
+ // Stores the selected item if there is one.
+ if (isItemSelected()) {
+ mItems[mCurrentOutfit][index] = mItemSelected;
+ mItemSelected = -1;
+ }
+ else if (mItems[mCurrentOutfit][index]) {
+ mItemClicked = true;
+ }
+}
+
+void OutfitWindow::mouseReleased(gcn::MouseEvent &event)
+{
+ Window::mouseReleased(event);
+ if (event.getButton() == gcn::MouseEvent::LEFT)
+ {
+ if (isItemSelected())
+ {
+ mItemSelected = -1;
+ }
+ const int index = getIndexFromGrid(event.getX(), event.getY());
+ if (index == -1) {
+ mItemMoved = NULL;
+ return;
+ }
+ if (mItemMoved) {
+ mItems[mCurrentOutfit][index] = mItemMoved->getId();
+ mItemMoved = NULL;
+ }
+ if (mItemClicked) {
+ mItemClicked = false;
+ }
+ }
+}
+
+int OutfitWindow::getIndexFromGrid(int pointX, int pointY) const
+{
+ const gcn::Rectangle tRect = gcn::Rectangle(
+ 10, 25, 10 + mGridWidth * mBoxWidth, 25 + mGridHeight * mBoxHeight);
+ if (!tRect.isPointInRect(pointX, pointY)) {
+ return -1;
+ }
+ const int index = (((pointY - 25) / mBoxHeight) * mGridWidth) +
+ (pointX - 10) / mBoxWidth;
+ if (index >= 9)
+ {
+ return -1;
+ }
+ return index;
+}
diff --git a/src/gui/outfitwindow.h b/src/gui/outfitwindow.h
new file mode 100644
index 00000000..3e70815c
--- /dev/null
+++ b/src/gui/outfitwindow.h
@@ -0,0 +1,92 @@
+/*
+ * The Mana World
+ * Copyright (C) 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef OUTFITWINDOW_H
+#define OUTFITWINDOW_H
+
+#include "gui/widgets/window.h"
+
+#include <guichan/actionlistener.hpp>
+
+class Button;
+class CheckBox;
+class Item;
+class Label;
+
+class OutfitWindow : public Window, gcn::ActionListener
+{
+ public:
+ /**
+ * Constructor.
+ */
+ OutfitWindow();
+
+ /**
+ * Destructor.
+ */
+ ~OutfitWindow();
+
+ void action(const gcn::ActionEvent &event);
+
+ void draw(gcn::Graphics *graphics);
+
+ void mousePressed(gcn::MouseEvent &event);
+
+ void mouseDragged(gcn::MouseEvent &event);
+
+ void mouseReleased(gcn::MouseEvent &event);
+
+ void load();
+
+ void setItemSelected(int itemId)
+ { mItemSelected = itemId; }
+
+ bool isItemSelected()
+ { return mItemSelected > -1; }
+
+ void wearOutfit(int outfit);
+
+ private:
+ Button *mPreviousButton;
+ Button *mNextButton;
+ Label *mCurrentLabel;
+ CheckBox *mUnequipCheck;
+
+ int getIndexFromGrid(int pointX, int pointY) const;
+
+ int mBoxWidth;
+ int mBoxHeight;
+ int mCursorPosX, mCursorPosY;
+ int mGridWidth, mGridHeight;
+ bool mItemClicked;
+ Item *mItemMoved;
+
+ void save();
+
+ int mItems[10][9];
+ int mItemSelected;
+
+ int mCurrentOutfit;
+};
+
+extern OutfitWindow *outfitWindow;
+
+#endif
diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp
index d954b99f..68b5fed3 100644
--- a/src/gui/viewport.cpp
+++ b/src/gui/viewport.cpp
@@ -202,9 +202,7 @@ void Viewport::draw(gcn::Graphics *gcnGraphics)
mMap->drawCollision(graphics,
(int) mPixelViewX,
(int) mPixelViewY);
-#if EATHENA_SUPPORT
drawDebugPath(graphics);
-#endif
}
}
@@ -364,24 +362,12 @@ void Viewport::mousePressed(gcn::MouseEvent &event)
if (player_node->withinAttackRange(being) ||
keyboard.isKeyActive(keyboard.KEY_ATTACK))
{
- player_node->setGotoTarget(being);
-//TODO: This can be changed when TMWServ moves to target based combat
-#ifdef TMWSERV_SUPPORT
- player_node->attack();
-#else
player_node->attack(being,
!keyboard.isKeyActive(keyboard.KEY_TARGET));
-#endif
-
}
else
{
-#ifdef TMWSERV_SUPPORT
- player_node->setDestination(event.getX() + (int) mPixelViewX,
- event.getY() + (int) mPixelViewY);
-#else
- player_node->setDestination(tilex, tiley);
-#endif
+ player_node->setGotoTarget(being);
}
break;
default:
@@ -410,9 +396,9 @@ void Viewport::mousePressed(gcn::MouseEvent &event)
event.getY() + (int) mPixelViewY);
}
#else
- player_node->stopAttack();
player_node->setDestination(tilex, tiley);
#endif
+ player_node->stopAttack();
mPlayerFollowMouse = true;
}
}
diff --git a/src/gui/widgets/whispertab.cpp b/src/gui/widgets/whispertab.cpp
index 23325108..43c63cc0 100644
--- a/src/gui/widgets/whispertab.cpp
+++ b/src/gui/widgets/whispertab.cpp
@@ -21,6 +21,7 @@
#include "whispertab.h"
+#include "commandhandler.h"
#include "localplayer.h"
#include "gui/palette.h"
@@ -65,6 +66,8 @@ void WhisperTab::handleCommand(const std::string &msg)
void WhisperTab::showHelp()
{
+ chatLog(_("/ignore > Ignore the other player"));
+ chatLog(_("/unignore > Stop ignoring the other player"));
chatLog(_("/close > Close the whisper tab"));
}
@@ -78,6 +81,18 @@ bool WhisperTab::handleCommand(const std::string &type,
chatLog(_("Command: /close"));
chatLog(_("This command closes the current whisper tab."));
}
+ else if (args == "ignore")
+ {
+ chatLog(_("Command: /ignore"));
+ chatLog(_("This command ignores the other player reguardless of "
+ "current relations."));
+ }
+ else if (args == "unignore")
+ {
+ chatLog(_("Command: /unignore <player>"));
+ chatLog(_("This command stops ignoring the other player if they "
+ "are being ignored"));
+ }
else
return false;
}
@@ -85,6 +100,14 @@ bool WhisperTab::handleCommand(const std::string &type,
{
delete this;
}
+ else if (type == "ignore")
+ {
+ commandHandler->handleIgnore(mNick, this);
+ }
+ else if (type == "unignore")
+ {
+ commandHandler->handleUnignore(mNick, this);
+ }
else
return false;
diff --git a/src/gui/windowmenu.cpp b/src/gui/windowmenu.cpp
index 5e33a4ed..8964f072 100644
--- a/src/gui/windowmenu.cpp
+++ b/src/gui/windowmenu.cpp
@@ -48,7 +48,6 @@ extern Window *guildWindow;
extern Window *magicDialog;
#endif
-
WindowMenu::WindowMenu():
mEmotePopup(0)
{
diff --git a/src/keyboardconfig.cpp b/src/keyboardconfig.cpp
index 670a96be..8e021aa6 100644
--- a/src/keyboardconfig.cpp
+++ b/src/keyboardconfig.cpp
@@ -80,6 +80,7 @@ static KeyData const keyData[KeyboardConfig::KEY_TOTAL] = {
{"keyWindowDebug", SDLK_F10, _("Debug Window")},
{"keyWindowParty", SDLK_F11, _("Party Window")},
{"keyWindowEmoteBar", SDLK_F12, _("Emote Shortcut Window")},
+ {"keyWindowOutfit", SDLK_o, _("Outfits Window")},
{"keyEmoteShortcut1", SDLK_1, strprintf(_("Emote Shortcut %d"), 1)},
{"keyEmoteShortcut2", SDLK_2, strprintf(_("Emote Shortcut %d"), 2)},
{"keyEmoteShortcut3", SDLK_3, strprintf(_("Emote Shortcut %d"), 3)},
diff --git a/src/keyboardconfig.h b/src/keyboardconfig.h
index 68a5efa6..b6a07f16 100644
--- a/src/keyboardconfig.h
+++ b/src/keyboardconfig.h
@@ -191,6 +191,7 @@ class KeyboardConfig
KEY_WINDOW_DEBUG,
KEY_WINDOW_PARTY,
KEY_WINDOW_EMOTE_SHORTCUT,
+ KEY_WINDOW_OUTFIT,
KEY_EMOTE_1,
KEY_EMOTE_2,
KEY_EMOTE_3,
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index e9bc30f2..782a461a 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -71,7 +71,10 @@
#include <cassert>
#ifdef TMWSERV_SUPPORT
-const short walkingKeyboardDelay = 100;
+// This is shorter then it really needs to be for normal use
+// But if we ever wanted to increase player speed, having this lower
+// Won't hurt
+const short walkingKeyboardDelay = 40;
#endif
LocalPlayer *player_node = NULL;
@@ -193,6 +196,8 @@ void LocalPlayer::logic()
mLastTarget = -1;
}
+#endif
+
if (mTarget)
{
if (mTarget->getType() == Being::NPC)
@@ -203,13 +208,18 @@ void LocalPlayer::logic()
}
else
{
+#ifdef TMWSERV_SUPPORT
+ // Find whether target is in range
+ const int rangeX = abs(mTarget->getPosition().x - getPosition().x);
+ const int rangeY = abs(mTarget->getPosition().y - getPosition().y);
+#else
// Find whether target is in range
const int rangeX = abs(mTarget->mX - mX);
const int rangeY = abs(mTarget->mY - mY);
+#endif
const int attackRange = getAttackRange();
const int inRange = rangeX > attackRange || rangeY > attackRange
? 1 : 0;
-
mTarget->setTargetAnimation(
mTargetCursor[inRange][mTarget->getTargetCursorSize()]);
@@ -220,7 +230,6 @@ void LocalPlayer::logic()
attack(mTarget, true);
}
}
-#endif
Player::logic();
}
@@ -280,9 +289,7 @@ void LocalPlayer::nextStep()
if (mGoingToTarget && mTarget && withinAttackRange(mTarget))
{
mAction = Being::STAND;
-#ifdef EATHENA_SUPPORT
attack(mTarget, true);
-#endif
mGoingToTarget = false;
mPath.clear();
return;
@@ -433,9 +440,9 @@ void LocalPlayer::walk(unsigned char dir)
int dScaler; // Distance to walk
- // Checks our path up to 5 tiles, if a blocking tile is found
+ // Checks our path up to 2 tiles, if a blocking tile is found
// We go to the last good tile, and break out of the loop
- for (dScaler = 1; dScaler <= 10; dScaler++)
+ for (dScaler = 1; dScaler <= 2; dScaler++)
{
if ( (dx || dy) &&
!mMap->getWalk( ((int) pos.x + (dx * dScaler)) / 32,
@@ -606,7 +613,7 @@ void LocalPlayer::emote(Uint8 emotion)
}
#ifdef TMWSERV_SUPPORT
-
+/*
void LocalPlayer::attack()
{
if (mLastAction != -1)
@@ -656,16 +663,25 @@ void LocalPlayer::attack()
}
Net::GameServer::Player::attack(getSpriteDirection());
}
-
+*/
void LocalPlayer::useSpecial(int special)
{
Net::GameServer::Player::useSpecial(special);
}
-#else
+#endif
void LocalPlayer::attack(Being *target, bool keep)
{
+#ifdef TMWSERV_SUPPORT
+ if (mLastAction != -1)
+ return;
+
+ // Can only attack when standing still
+ if (mAction != STAND && mAction != ATTACK)
+ return;
+#endif
+
mKeepAttacking = keep;
if (!target || target->getType() == Being::NPC)
@@ -676,14 +692,36 @@ void LocalPlayer::attack(Being *target, bool keep)
mLastTarget = -1;
setTarget(target);
}
-
+#ifdef TMWSERV_SUPPORT
+ Vector plaPos = this->getPosition();
+ Vector tarPos = mTarget->getPosition();
+ int dist_x = plaPos.x - tarPos.x;
+ int dist_y = plaPos.y - tarPos.y;
+#else
int dist_x = target->mX - mX;
int dist_y = target->mY - mY;
// Must be standing to attack
if (mAction != STAND)
return;
+#endif
+#ifdef TMWSERV_SUPPORT
+ if (abs(dist_y) >= abs(dist_x))
+ {
+ if (dist_y < 0)
+ setDirection(DOWN);
+ else
+ setDirection(UP);
+ }
+ else
+ {
+ if (dist_x < 0)
+ setDirection(RIGHT);
+ else
+ setDirection(LEFT);
+ }
+#else
if (abs(dist_y) >= abs(dist_x))
{
if (dist_y > 0)
@@ -698,9 +736,14 @@ void LocalPlayer::attack(Being *target, bool keep)
else
setDirection(LEFT);
}
+#endif
+#ifdef TMWSERV_SUPPORT
+ mLastAction = tick_time;
+#else
mWalkTime = tick_time;
mTargetTime = tick_time;
+#endif
setAction(ATTACK);
@@ -715,14 +758,13 @@ void LocalPlayer::attack(Being *target, bool keep)
sound.playSfx("sfx/fist-swish.ogg");
}
- Net::getPlayerHandler()->attack(target);
-
+ Net::getPlayerHandler()->attack(target->getId());
+#ifdef EATHENA_SUPPORT
if (!keep)
stopAttack();
+#endif
}
-#endif // no TMWSERV_SUPPORT
-
void LocalPlayer::stopAttack()
{
if (mTarget)
@@ -845,7 +887,7 @@ int LocalPlayer::getAttackRange()
const ItemInfo info = weapon->getInfo();
return info.getAttackRange();
}
- return 32; // unarmed range
+ return 48; // unarmed range
#else
return mAttackRange;
#endif
diff --git a/src/localplayer.h b/src/localplayer.h
index 4a85dd75..85681e03 100644
--- a/src/localplayer.h
+++ b/src/localplayer.h
@@ -214,11 +214,9 @@ class LocalPlayer : public Player
void setTrading(bool trading) { mTrading = trading; }
#ifdef TMWSERV_SUPPORT
- void attack();
void useSpecial(int id);
-#else
- void attack(Being *target = NULL, bool keep = false);
#endif
+ void attack(Being *target = NULL, bool keep = false);
/**
* Triggers whether or not to show the name as a GM name.
diff --git a/src/main.cpp b/src/main.cpp
index 16cbbdfe..f37f9de9 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -53,7 +53,7 @@
#include "gui/serverselectdialog.h"
#include "gui/setup.h"
#ifdef TMWSERV_SUPPORT
-#include "gui/connection.h"
+#include "gui/connectiondialog.h"
#include "gui/quitdialog.h"
#include "gui/serverdialog.h"
#endif
diff --git a/src/net/ea/beinghandler.cpp b/src/net/ea/beinghandler.cpp
index 34a0d70a..f149f15f 100644
--- a/src/net/ea/beinghandler.cpp
+++ b/src/net/ea/beinghandler.cpp
@@ -65,6 +65,7 @@ BeingHandler::BeingHandler(bool enableSync):
SMSG_PLAYER_MOVE_TO_ATTACK,
SMSG_PLAYER_STATUS_CHANGE,
SMSG_BEING_STATUS_CHANGE,
+ SMSG_BEING_RESURRECT,
0
};
handledMessages = _messages;
@@ -260,6 +261,24 @@ void BeingHandler::handleMessage(MessageIn &msg)
break;
+ case SMSG_BEING_RESURRECT:
+ // A being changed mortality status
+ id = msg.readInt32();
+
+ dstBeing = beingManager->findBeing(id);
+
+ if (!dstBeing)
+ break;
+
+ // If this is player's current target, clear it.
+ if (dstBeing == player_node->getTarget())
+ player_node->stopAttack();
+
+ if (msg.readInt8() == 1)
+ dstBeing->setAction(Being::STAND);
+
+ break;
+
case SMSG_BEING_ACTION:
srcBeing = beingManager->findBeing(msg.readInt32());
dstBeing = beingManager->findBeing(msg.readInt32());
diff --git a/src/net/ea/playerhandler.cpp b/src/net/ea/playerhandler.cpp
index 2d953df1..c1b7cc84 100644
--- a/src/net/ea/playerhandler.cpp
+++ b/src/net/ea/playerhandler.cpp
@@ -422,10 +422,10 @@ void PlayerHandler::handleMessage(MessageIn &msg)
}
}
-void PlayerHandler::attack(Being *being)
+void PlayerHandler::attack(int id)
{
MessageOut outMsg(CMSG_PLAYER_ATTACK);
- outMsg.writeInt32(being->getId());
+ outMsg.writeInt32(id);
outMsg.writeInt8(0);
}
diff --git a/src/net/ea/playerhandler.h b/src/net/ea/playerhandler.h
index 808cd0ec..5dbc171b 100644
--- a/src/net/ea/playerhandler.h
+++ b/src/net/ea/playerhandler.h
@@ -35,7 +35,7 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler
void handleMessage(MessageIn &msg);
- void attack(Being *being);
+ void attack(int id);
void emote(int emoteId);
diff --git a/src/net/ea/protocol.h b/src/net/ea/protocol.h
index f8caf4c1..b3759946 100644
--- a/src/net/ea/protocol.h
+++ b/src/net/ea/protocol.h
@@ -87,6 +87,7 @@ static const int STORAGE_OFFSET = 1;
#define SMSG_BEING_CHAT 0x008d /**< A being talks */
#define SMSG_BEING_NAME_RESPONSE 0x0095 /**< Has to be requested */
#define SMSG_BEING_CHANGE_DIRECTION 0x009c
+#define SMSG_BEING_RESURRECT 0x0148
#define SMSG_PLAYER_STATUS_CHANGE 0x0119
#define SMSG_BEING_STATUS_CHANGE 0x0196
diff --git a/src/net/playerhandler.h b/src/net/playerhandler.h
index df49756d..163b48f3 100644
--- a/src/net/playerhandler.h
+++ b/src/net/playerhandler.h
@@ -31,7 +31,7 @@ namespace Net {
class PlayerHandler
{
public:
- virtual void attack(Being *being) = 0;
+ virtual void attack(int id) = 0;
virtual void emote(int emoteId) = 0;
diff --git a/src/net/tmwserv/beinghandler.cpp b/src/net/tmwserv/beinghandler.cpp
index 1ec13800..99491203 100644
--- a/src/net/tmwserv/beinghandler.cpp
+++ b/src/net/tmwserv/beinghandler.cpp
@@ -191,11 +191,6 @@ void BeingHandler::handleBeingsMoveMessage(MessageIn &msg)
int dy = 0;
int speed = 0;
- printf("handleBeingsMoveMessage for %p (%s | %s)\n",
- (void*) being,
- (flags & MOVING_POSITION) ? "pos" : "",
- (flags & MOVING_DESTINATION) ? "dest" : "");
-
if (flags & MOVING_POSITION)
{
Uint16 sx2, sy2;
@@ -235,7 +230,7 @@ void BeingHandler::handleBeingsMoveMessage(MessageIn &msg)
// If being is a player, and he only moves a little, its ok to be a little out of sync
if (being->getType() == Being::PLAYER && abs(being->getPixelX() - dx) +
- abs(being->getPixelY() - dy) < 2 * 32 &&
+ abs(being->getPixelY() - dy) < 16 &&
(dx != being->getDestination().x && dy != being->getDestination().y))
{
being->setDestination(being->getPixelX(),being->getPixelY());
@@ -258,7 +253,7 @@ void BeingHandler::handleBeingsMoveMessage(MessageIn &msg)
}
else
{
- being->adjustCourse(sx, sy, dx, dy);
+ being->setDestination(sx, sy, dx, dy);
}
}
}
diff --git a/src/net/tmwserv/gameserver/player.cpp b/src/net/tmwserv/gameserver/player.cpp
index 3f05c954..93853681 100644
--- a/src/net/tmwserv/gameserver/player.cpp
+++ b/src/net/tmwserv/gameserver/player.cpp
@@ -58,13 +58,6 @@ void Net::GameServer::Player::moveItem(int oldSlot, int newSlot, int amount)
Net::GameServer::connection->send(msg);
}
-void Net::GameServer::Player::attack(int direction)
-{
- MessageOut msg(PGMSG_ATTACK);
- msg.writeInt8(direction);
- Net::GameServer::connection->send(msg);
-}
-
void Net::GameServer::Player::useSpecial(int special)
{
MessageOut msg(PGMSG_USE_SPECIAL);
diff --git a/src/net/tmwserv/gameserver/player.h b/src/net/tmwserv/gameserver/player.h
index eddd9102..24b25dc7 100644
--- a/src/net/tmwserv/gameserver/player.h
+++ b/src/net/tmwserv/gameserver/player.h
@@ -43,7 +43,6 @@ namespace Net
void walk(int x, int y);
void pickUp(int x, int y);
void moveItem(int oldSlot, int newSlot, int amount);
- void attack(int direction);
void useSpecial(int special);
void requestTrade(int id);
void acceptTrade(bool accept);
diff --git a/src/net/tmwserv/playerhandler.cpp b/src/net/tmwserv/playerhandler.cpp
index 931e4294..b378817f 100644
--- a/src/net/tmwserv/playerhandler.cpp
+++ b/src/net/tmwserv/playerhandler.cpp
@@ -332,9 +332,11 @@ void PlayerHandler::handleMapChangeMessage(MessageIn &msg)
viewport->scrollBy(scrollOffsetX, scrollOffsetY);
}
-void PlayerHandler::attack(Being *being)
+void PlayerHandler::attack(int id)
{
- // TODO
+ MessageOut msg(PGMSG_ATTACK);
+ msg.writeInt16(id);
+ Net::GameServer::connection->send(msg);
}
void PlayerHandler::emote(int emoteId)
@@ -371,9 +373,6 @@ void PlayerHandler::setDestination(int x, int y, int /* direction */)
msg.writeInt16(x);
msg.writeInt16(y);
Net::GameServer::connection->send(msg);
-
- // Debugging fire burst
- effectManager->trigger(15, x, y);
}
void PlayerHandler::changeAction(Being::Action action)
diff --git a/src/net/tmwserv/playerhandler.h b/src/net/tmwserv/playerhandler.h
index 13ae8f39..164d30ae 100644
--- a/src/net/tmwserv/playerhandler.h
+++ b/src/net/tmwserv/playerhandler.h
@@ -34,7 +34,7 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler
void handleMessage(MessageIn &msg);
- void attack(Being *being);
+ void attack(int id);
void emote(int emoteId);
diff --git a/src/net/tmwserv/protocol.h b/src/net/tmwserv/protocol.h
index 7fa3b372..6124263a 100644
--- a/src/net/tmwserv/protocol.h
+++ b/src/net/tmwserv/protocol.h
@@ -106,7 +106,7 @@ enum {
GPMSG_BEING_DIR_CHANGE = 0x0273, // W being id, B direction
GPMSG_BEINGS_MOVE = 0x0280, // { W being id, B flags [, C position, B speed] [, W*2 destination] }*
GPMSG_ITEMS = 0x0281, // { W item id, W*2 position }*
- PGMSG_ATTACK = 0x0290, // B direction
+ PGMSG_ATTACK = 0x0290, // W being id
PGMSG_USE_SPECIAL = 0x0292, // B specialID
GPMSG_BEING_ATTACK = 0x0291, // W being id
PGMSG_SAY = 0x02A0, // S text
@@ -162,9 +162,11 @@ enum {
CPMSG_GUILD_QUIT_RESPONSE = 0x0361, // B error
PCMSG_GUILD_PROMOTE_MEMBER = 0x0365, // W guild, S name, B rights
CPMSG_GUILD_PROMOTE_MEMBER_RESPONSE = 0x0366, // B error
+ PCMSG_GUILD_KICK_MEMBER = 0x0370, // W guild, S name
+ CPMSG_GUILD_KICK_MEMBER_RESPONSE = 0x0371, // B error
- CPMSG_GUILD_INVITED = 0x0370, // S char name, S guild name, W id
- CPMSG_GUILD_REJOIN = 0x0371, // S name, W guild, W rights, W channel, S announce
+ CPMSG_GUILD_INVITED = 0x0388, // S char name, S guild name, W id
+ CPMSG_GUILD_REJOIN = 0x0389, // S name, W guild, W rights, W channel, S announce
// Party
PCMSG_PARTY_INVITE = 0x03A0, // S name
diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp
index 9a17eb3a..b25f754f 100644
--- a/src/resources/itemdb.cpp
+++ b/src/resources/itemdb.cpp
@@ -215,6 +215,10 @@ void ItemDB::load()
}
}
+ if (weaponType > 0)
+ if (attackRange == 0)
+ logger->log("ItemDB: Missing attack range from weapon %i!", id);
+
#define CHECK_PARAM(param, error_value) \
if (param == error_value) \
logger->log("ItemDB: Missing " #param " attribute for item %i!",id)