summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGuillaume Melquiond <guillaume.melquiond@gmail.com>2006-08-06 17:30:40 +0000
committerGuillaume Melquiond <guillaume.melquiond@gmail.com>2006-08-06 17:30:40 +0000
commit4c15d1d1dcedb3627e501fb5ddba4ae74281968c (patch)
treede4a44e603d05742b4eaffff75b759e1ac6ff85c /src
parentce849af300a70425b574b724c62dc9f5fce6016b (diff)
downloadmanaserv-4c15d1d1dcedb3627e501fb5ddba4ae74281968c.tar.gz
manaserv-4c15d1d1dcedb3627e501fb5ddba4ae74281968c.tar.bz2
manaserv-4c15d1d1dcedb3627e501fb5ddba4ae74281968c.tar.xz
manaserv-4c15d1d1dcedb3627e501fb5ddba4ae74281968c.zip
Implemented crude handling of being movements.
Diffstat (limited to 'src')
-rw-r--r--src/accounthandler.cpp11
-rw-r--r--src/being.cpp6
-rw-r--r--src/being.h9
-rw-r--r--src/client.cpp18
-rw-r--r--src/defines.h8
-rw-r--r--src/gamehandler.cpp17
-rw-r--r--src/map.cpp30
-rw-r--r--src/map.h27
-rw-r--r--src/object.cpp99
-rw-r--r--src/object.h36
-rw-r--r--src/state.cpp48
11 files changed, 242 insertions, 67 deletions
diff --git a/src/accounthandler.cpp b/src/accounthandler.cpp
index 271186c0..c7a7dd15 100644
--- a/src/accounthandler.cpp
+++ b/src/accounthandler.cpp
@@ -323,6 +323,9 @@ void AccountHandler::processMessage(NetComputer *comp, MessageIn &message)
LOG_INFO("Selected Character " << int(charNum)
<< ": " <<
selectedChar->getName(), 1);
+
+ selectedChar->setDestination(selectedChar->getX(), selectedChar->getY());
+ selectedChar->setSpeed(10); // TODO
}
break;
@@ -422,9 +425,10 @@ void AccountHandler::processMessage(NetComputer *comp, MessageIn &message)
if (computer.getCharacter().get() == NULL)
{
result.writeByte(ERRMSG_NO_CHARACTER_SELECTED);
- LOG_INFO("No character selected. Can't enter the world.", 2);
+ LOG_INFO("No character selected. Can't enter the world.", 1);
break; // no character selected
}
+ LOG_INFO(computer.getCharacter()->getName() << " is trying to enter the world.", 1);
std::string magic_token(32, ' ');
for (int i = 0; i < 32; ++i) {
magic_token[i] =
@@ -451,7 +455,7 @@ void AccountHandler::processMessage(NetComputer *comp, MessageIn &message)
if (computer.getCharacter().get() == NULL)
{
result.writeByte(ERRMSG_NO_CHARACTER_SELECTED);
- LOG_INFO("No character selected. Can't enter the chat.", 2);
+ LOG_INFO("No character selected. Can't enter the chat.", 1);
break; // no character selected
}
std::string magic_token(32, ' ');
@@ -472,7 +476,8 @@ void AccountHandler::processMessage(NetComputer *comp, MessageIn &message)
}
// return result
- computer.send(result.getPacket());
+ if (result.getDataSize() > 0)
+ computer.send(result.getPacket());
}
void
diff --git a/src/being.cpp b/src/being.cpp
index c95136af..ae339ad8 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -23,12 +23,6 @@
#include "being.h"
-
-PATH_NODE::PATH_NODE(unsigned short x, unsigned short y):
- x(x), y(y)
-{
-}
-
/**
* Update the internal status.
*/
diff --git a/src/being.h b/src/being.h
index 052d82de..6dec64d3 100644
--- a/src/being.h
+++ b/src/being.h
@@ -34,15 +34,6 @@
const unsigned int MAX_EQUIP_SLOTS = 5; /**< Maximum number of equipped slots */
-struct PATH_NODE {
- /**
- * Constructor.
- */
- PATH_NODE(unsigned short x, unsigned short y);
-
- unsigned short x, y;
-};
-
/**
* Raw statistics of a Player
*/
diff --git a/src/client.cpp b/src/client.cpp
index f1d73541..752d65d0 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -269,8 +269,8 @@ int main(int argc, char *argv[])
std::cin >> y;
msg.writeShort(PGMSG_WALK);
- msg.writeLong(x);
- msg.writeLong(y);
+ msg.writeShort(x);
+ msg.writeShort(y);
msgDestination = 1;
} break;
@@ -720,6 +720,20 @@ void parsePacket(char *data, int recvLength) {
}
} break;
+ case GPMSG_BEINGS_MOVE:
+ {
+ int nb = (recvLength - 2) / (1*4 + 4*2);
+ std::cout << "Beings are moving:" << std::endl;
+ for(; nb > 0; --nb) {
+ int id = msg.readLong();
+ int cx = msg.readShort(), cy = msg.readShort();
+ int dx = msg.readShort(), dy = msg.readShort();
+ std::cout << " ID " << id << " at ("
+ << cx << ", " << cy << ") toward ("
+ << dx << ", " << dy << ")." << std::endl;
+ }
+ } break;
+
case XXMSG_INVALID:
std::cout << "The server does not understand our message." << std::endl;
break;
diff --git a/src/defines.h b/src/defines.h
index 90896f81..0c0f95f9 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -95,10 +95,9 @@ const unsigned int MAX_CLIENTS = 1024,
// Screen Related
/**
- * Determine the area in which a character
- * can hear another one speak
+ * Determine the area in which a character is aware of other beings
*/
- AROUND_AREA_IN_TILES = 10;
+ AROUND_AREA = 320;
/**
@@ -150,7 +149,8 @@ enum {
GPMSG_BEING_ENTER = 0x0200, // B type, L being id
// player: S name, B hair style, B hair color, B gender
GPMSG_BEING_LEAVE = 0x0201, // B type, L being id
- PGMSG_WALK = 0x0260, // L*2 destination
+ PGMSG_WALK = 0x0260, // W*2 destination
+ GPMSG_BEINGS_MOVE = 0x0280, // { L being id, W*2 position, W*2 destination }*
PGMSG_SAY = 0x02A0, // S text
GPMSG_SAY = 0x02A1, // S being, S text
PGMSG_USE_ITEM = 0x0300, // L item id
diff --git a/src/gamehandler.cpp b/src/gamehandler.cpp
index b3dfb324..6dfab787 100644
--- a/src/gamehandler.cpp
+++ b/src/gamehandler.cpp
@@ -27,6 +27,7 @@
#include <map>
#include "gameclient.h"
+#include "map.h"
#include "messagein.h"
#include "messageout.h"
#include "netcomputer.h"
@@ -194,12 +195,10 @@ void GameHandler::processMessage(NetComputer *comp, MessageIn &message)
case PGMSG_WALK:
{
- long x = message.readLong();
- long y = message.readLong();
+ unsigned x = message.readShort();
+ unsigned y = message.readShort();
- // simplistic "teleport" walk
- computer.getCharacter()->setX(x);
- computer.getCharacter()->setY(y);
+ computer.getCharacter()->setDestination(x, y);
// no response should be required
} break;
@@ -220,7 +219,7 @@ void GameHandler::processMessage(NetComputer *comp, MessageIn &message)
break;
}
- if (result.getPacket()->length > 0)
+ if (result.getDataSize() > 0)
computer.send(result.getPacket());
}
@@ -248,10 +247,8 @@ void GameHandler::sayAround(GameClient &computer, std::string const &text)
std::pair<unsigned, unsigned> listenerXY = listener->getXY();
- if (abs(listenerXY.first - speakerXY.first) <=
- (int)AROUND_AREA_IN_TILES &&
- abs(listenerXY.second - speakerXY.second) <=
- (int)AROUND_AREA_IN_TILES)
+ if (areAround(listenerXY.first, listenerXY.second,
+ speakerXY.first, speakerXY.second))
{
(*i)->send(msg.getPacket());
}
diff --git a/src/map.cpp b/src/map.cpp
index 89c34ee6..8a768e07 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -123,30 +123,6 @@ Map::getMetaTile(int x, int y)
return &metaTiles[x + y * width];
}
-int
-Map::getWidth()
-{
- return width;
-}
-
-int
-Map::getHeight()
-{
- return height;
-}
-
-int
-Map::getTileWidth()
-{
- return tileWidth;
-}
-
-int
-Map::getTileHeight()
-{
- return tileHeight;
-}
-
std::list<PATH_NODE>
Map::findPath(int startX, int startY, int destX, int destY)
{
@@ -305,3 +281,9 @@ Map::findPath(int startX, int startY, int destX, int destY)
return path;
}
+
+bool areAround(unsigned x1, unsigned y1, unsigned x2, unsigned y2)
+{
+ return (abs(x1 - x2) <= (int)AROUND_AREA &&
+ abs(y1 - y2) <= (int)AROUND_AREA);
+}
diff --git a/src/map.h b/src/map.h
index 9cc07044..46144f56 100644
--- a/src/map.h
+++ b/src/map.h
@@ -30,7 +30,14 @@
#include "properties.h"
-struct PATH_NODE;
+
+struct PATH_NODE {
+ PATH_NODE(unsigned short u, unsigned short v)
+ : x(u), y(v)
+ {}
+
+ unsigned short x, y;
+};
/**
* A meta tile stores additional information about a location on a tile map.
@@ -129,26 +136,26 @@ class Map : public Properties
/**
* Returns the width of this map.
*/
- int
- getWidth();
+ int getWidth() const
+ { return width; }
/**
* Returns the height of this map.
*/
- int
- getHeight();
+ int getHeight() const
+ { return height; }
/**
* Returns the tile width of this map.
*/
- int
- getTileWidth();
+ int getTileWidth() const
+ { return tileWidth; }
/**
* Returns the tile height used by this map.
*/
- int
- getTileHeight();
+ int getTileHeight() const
+ { return tileHeight; }
/**
* Find a path from one location to the next.
@@ -167,4 +174,6 @@ class Map : public Properties
int onClosedList, onOpenList;
};
+bool areAround(unsigned x1, unsigned y1, unsigned x2, unsigned y2);
+
#endif
diff --git a/src/object.cpp b/src/object.cpp
index 5c03981a..f6863cd4 100644
--- a/src/object.cpp
+++ b/src/object.cpp
@@ -21,11 +21,110 @@
*/
#include <cassert>
+#include <cmath>
#include "object.h"
+#include "map.h"
+#include "mapmanager.h"
+
void Object::setID(int id)
{
assert(mID < 0);
mID = id;
}
+
+void MovingObject::move()
+{
+ unsigned mSrcX = getX(), mSrcY = getY();
+ if (mSrcX == mDstX && mSrcY == mDstY) {
+ mNewX = mDstX;
+ mNewY = mDstY;
+ return;
+ }
+
+ Map *map = MapManager::instance().getMap(getMapId());
+ int tileW = map->getTileWidth(), tileH = map->getTileHeight();
+ int tileD = (int) std::sqrt((double)(tileW * tileW + tileH * tileH));
+ int tileSX = mSrcX / tileW, fracSX = mSrcX % tileW - tileW / 2;
+ int tileSY = mSrcY / tileH, fracSY = mSrcY % tileH - tileH / 2;
+ int tileDX = mDstX / tileW, fracDX = mDstX % tileW - tileW / 2;
+ int tileDY = mDstY / tileH, fracDY = mDstY % tileH - tileH / 2;
+
+ std::list<PATH_NODE> path;
+ if (tileSX != tileDX || tileSY != tileDY) {
+ path = map->findPath(tileSX, tileSY, tileDX, tileDY);
+ if (path.empty()) {
+ mNewX = mDstX = mSrcX;
+ mNewY = mDstY = mSrcY;
+ return;
+ }
+ }
+
+ int tileCX = tileSX, tileCY = tileSY, fracCX = fracSX, fracCY = fracSY;
+ int tileNX = tileDX, tileNY = tileDY, left = mSpeed;
+ int vecX = 0, vecY = 0, cost = 0;
+
+ for (std::list<PATH_NODE>::const_iterator it = path.begin(),
+ it_end = path.end(); it != it_end; ++it) {
+
+ tileNX = it->x;
+ tileNY = it->y;
+ assert(tileNX != tileCX && tileNY != tileCY &&
+ tileNX != tileDX && tileNY != tileDY);
+
+ if (fracCX != 0 || fracCY != 0) {
+ // not at the tile center, move toward the next tile center
+ vecX = -fracCX + tileW * (tileNX - tileCX);
+ vecY = -fracCY + tileH * (tileNY - tileCY);
+ cost = (int) std::sqrt((double)(vecX * vecX + vecY * vecY));
+ } else {
+ // at a tile center and toward the next tile center
+ assert(abs(tileNX - tileCX) <= 1 && abs(tileNY - tileCY) <= 1);
+ if (tileNX != tileCX) {
+ vecX = tileW * (tileNX - tileCX);
+ if (tileNY != tileCY) {
+ vecY = tileH * (tileNY - tileCY);
+ cost = tileD;
+ } else {
+ vecY = 0;
+ cost = tileW;
+ }
+ } else {
+ assert(tileNY != tileCY);
+ vecX = 0;
+ vecY = tileH * (tileNY - tileCY);
+ cost = tileH;
+ }
+ }
+
+ if (cost > left) break;
+ // enough movement left to reach the next tile center
+ tileCX = tileNX;
+ tileCY = tileNY;
+ fracCX = 0;
+ fracCY = 0;
+ vecX = 0;
+ vecY = 0;
+ left -= cost;
+ }
+
+ if ((vecX == 0 && vecY == 0) && (fracCX != fracDX || fracCY != fracDY)) {
+ // walk toward the destination
+ vecX = fracDX - fracCX + tileW * (tileDX - tileCX);
+ vecY = fracDY - fracCY + tileH * (tileDY - tileCY);
+ cost = (int) std::sqrt((double)(vecX * vecX + vecY * vecY));
+ }
+
+ if (cost <= left) {
+ // enough movement left to perform the last step
+ mNewX = mDstX;
+ mNewY = mDstY;
+ return;
+ }
+
+ // linear interpolation along the vector
+ assert(cost > 0);
+ mNewX = tileCX * tileW + tileW / 2 + fracCX + vecX * left / cost;
+ mNewY = tileCY * tileH + tileH / 2 + fracCY + vecY * left / cost;
+}
diff --git a/src/object.h b/src/object.h
index 7c64719f..05b1f45d 100644
--- a/src/object.h
+++ b/src/object.h
@@ -165,6 +165,42 @@ class MovingObject: public Object
MovingObject(int type, int id)
: Object(type, id)
{}
+
+ /**
+ * Gets the destination coordinates of the object.
+ */
+ std::pair<unsigned, unsigned> getDestination() const
+ { return std::make_pair(mDstX, mDstY); }
+
+ /**
+ * Sets the destination coordinates of the object.
+ */
+ void setDestination(unsigned x, unsigned y)
+ { mDstX = x; mDstY = y; }
+
+ /**
+ * Gets the next coordinates of the object.
+ */
+ std::pair<unsigned, unsigned> getNextPosition() const
+ { return std::make_pair(mNewX, mNewY); }
+
+ /**
+ * Sets object speed.
+ */
+ void setSpeed(unsigned s)
+ { mSpeed = s; }
+
+ /**
+ * Moves the object toward its destination.
+ */
+ void move();
+
+ private:
+ unsigned mDstX; /**< target x coordinate */
+ unsigned mDstY; /**< target y coordinate */
+ unsigned mNewX; /**< next x coordinate */
+ unsigned mNewY; /**< next y coordinate */
+ unsigned mSpeed; /**< speed */
};
/**
diff --git a/src/state.cpp b/src/state.cpp
index ae3ceda4..2cb46aa2 100644
--- a/src/state.cpp
+++ b/src/state.cpp
@@ -46,9 +46,57 @@ void State::update()
// update game state (update AI, etc.)
for (std::map<unsigned int, MapComposite>::iterator m = maps.begin(),
m_end = maps.end(); m != m_end; ++m) {
+
+ typedef std::vector< utils::CountedPtr<MovingObject> > Movings;
+ Movings movings;
+
for (Objects::iterator o = m->second.objects.begin(),
o_end = m->second.objects.end(); o != o_end; ++o) {
(*o)->update();
+ int t = (*o)->getType();
+ if (t == OBJECT_NPC || t == OBJECT_PLAYER || t == OBJECT_MONSTER) {
+ utils::CountedPtr<MovingObject> ptr(*o);
+ ptr->move();
+ movings.push_back(ptr);
+ }
+ }
+
+
+ Players &players = m->second.players;
+ for (Players::iterator p = players.begin(),
+ p_end = players.end(); p != p_end; ++p) {
+ std::pair<unsigned, unsigned> ps = (*p)->getXY();
+ std::pair<unsigned, unsigned> pn = (*p)->getNextPosition();
+ MessageOut msg;
+ msg.writeShort(GPMSG_BEINGS_MOVE);
+
+ for (Movings::iterator o = movings.begin(),
+ o_end = movings.end(); o != o_end; ++o) {
+ std::pair<unsigned, unsigned> os = (*o)->getXY();
+ std::pair<unsigned, unsigned> on = (*o)->getNextPosition();
+
+ bool were = areAround(ps.first, ps.second, os.first, os.second);
+ bool will = areAround(pn.first, pn.second, on.first, on.second);
+ bool has_moved = os.first != on.first || os.second != on.second;
+ if (!(will && has_moved) && !(were != will))
+ continue;
+
+ std::pair<unsigned, unsigned> od = (*o)->getDestination();
+ msg.writeLong((*o)->getID());
+ msg.writeShort(on.first);
+ msg.writeShort(on.second);
+ msg.writeShort(od.first);
+ msg.writeShort(od.second);
+ }
+
+ if (msg.getDataSize() > 2)
+ gameHandler->sendTo(*p, msg);
+ }
+
+ for (Movings::iterator o = movings.begin(),
+ o_end = movings.end(); o != o_end; ++o) {
+ std::pair<unsigned, unsigned> pos = (*o)->getNextPosition();
+ (*o)->setXY(pos.first, pos.second);
}
}
}