Skip to content
This repository has been archived by the owner on Sep 25, 2018. It is now read-only.

Commit

Permalink
Fix being direction discrepancies by syncing the BeingDirection.
Browse files Browse the repository at this point in the history
The server was actually using the bitmask enum while the the client
still sent another one, creating discrepancies.
A second problem is that the being direction was not properly
initialized and not updated while it was moving.

Reviewed-by: Jaxad.
  • Loading branch information
Yohann Ferreira committed Jan 9, 2011
1 parent 8ff3e66 commit 7f712f1
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 21 deletions.
100 changes: 94 additions & 6 deletions src/game-server/being.cpp
Expand Up @@ -39,7 +39,7 @@ Being::Being(ThingType type):
Actor(type),
mAction(STAND),
mTarget(NULL),
mDirection(0)
mDirection(DOWN)
{
const AttributeScopes &attr = attributeManager->getAttributeInfoForType(ATTR_BEING);
LOG_DEBUG("Being creation: initialisation of " << attr.size() << " attributes.");
Expand Down Expand Up @@ -202,6 +202,89 @@ Path Being::findPath()
return map->findPath(startX, startY, destX, destY, getWalkMask());
}

void Being::updateDirection(const Point &currentPos, const Point &destPos)
{
// We update the being direction on each tile to permit other beings
// entering in range to always see the being with a direction value.

// We first handle simple cases

// If the character has reached its destination,
// don't update the direction since it's only a matter of keeping
// the previous one.
if (currentPos == destPos)
return;

if (currentPos.x == destPos.x)
{
if (currentPos.y > destPos.y)
setDirection(UP);
else
setDirection(DOWN);
return;
}

if (currentPos.y == destPos.y)
{
if (currentPos.x > destPos.x)
setDirection(LEFT);
else
setDirection(RIGHT);
return;
}

// Now let's handle diagonal cases
// First, find the lower angle:
if (currentPos.x < destPos.x)
{
// Up-right direction
if (currentPos.y > destPos.y)
{
// Compute tan of the angle
if ((currentPos.y - destPos.y) / (destPos.x - currentPos.x) < 1)
// The angle is less than 45°, we look to the right
setDirection(RIGHT);
else
setDirection(UP);
return;
}
else // Down-right
{
// Compute tan of the angle
if ((destPos.y - currentPos.y) / (destPos.x - currentPos.x) < 1)
// The angle is less than 45°, we look to the right
setDirection(RIGHT);
else
setDirection(DOWN);
return;
}
}
else
{
// Up-left direction
if (currentPos.y > destPos.y)
{
// Compute tan of the angle
if ((currentPos.y - destPos.y) / (currentPos.x - destPos.x) < 1)
// The angle is less than 45°, we look to the right
setDirection(LEFT);
else
setDirection(UP);
return;
}
else // Down-left
{
// Compute tan of the angle
if ((destPos.y - currentPos.y) / (currentPos.x - destPos.x) < 1)
// The angle is less than 45°, we look to the right
setDirection(LEFT);
else
setDirection(DOWN);
return;
}
}
}

void Being::move()
{
// Immobile beings cannot move.
Expand Down Expand Up @@ -229,6 +312,8 @@ void Being::move()
if (mAction == WALK)
setAction(STAND);
// Moving while staying on the same tile is free
// We only update the direction in that case.
updateDirection(mOld, mDst);
setPosition(mDst);
mMoveTime = 0;
return;
Expand Down Expand Up @@ -281,6 +366,9 @@ void Being::move()
getModifiedAttribute(ATTR_MOVE_SPEED_RAW) :
getModifiedAttribute(ATTR_MOVE_SPEED_RAW) * SQRT2;

// Update the being direction also
updateDirection(prev, next);

if (mPath.empty())
{
// skip last tile center
Expand All @@ -302,11 +390,11 @@ int Being::directionToAngle(int direction)
{
switch (direction)
{
case DIRECTION_UP: return 90;
case DIRECTION_DOWN: return 270;
case DIRECTION_RIGHT: return 180;
case DIRECTION_LEFT:
default: return 0;
case UP: return 90;
case DOWN: return 270;
case RIGHT: return 180;
case LEFT:
default: return 0;
}
}

Expand Down
13 changes: 10 additions & 3 deletions src/game-server/being.h
Expand Up @@ -127,10 +127,10 @@ class Being : public Actor
/**
* Sets the facing direction of the being.
*/
void setDirection(int direction)
void setDirection(BeingDirection direction)
{ mDirection = direction; raiseUpdateFlags(UPDATEFLAG_DIRCHANGE); }

int getDirection() const
BeingDirection getDirection() const
{ return mDirection; }

/**
Expand Down Expand Up @@ -320,8 +320,15 @@ class Being : public Actor
Being(const Being &rhs);
Being &operator=(const Being &rhs);

/**
* Update the being direction when moving so avoid directions desyncs
* with other clients.
*/
void updateDirection(const Point &currentPos,
const Point &destPos);

Path mPath;
unsigned char mDirection; /**< Facing direction. */
BeingDirection mDirection; /**< Facing direction. */

std::string mName;
Hits mHitsTaken; /**< List of punches taken since last update. */
Expand Down
3 changes: 2 additions & 1 deletion src/game-server/gamehandler.cpp
Expand Up @@ -419,7 +419,8 @@ void GameHandler::processMessage(NetComputer *comp, MessageIn &message)

case PGMSG_DIRECTION_CHANGE:
{
computer.character->setDirection(message.readInt8());
computer.character->setDirection(
(BeingDirection)message.readInt8());
} break;

case PGMSG_DISCONNECT:
Expand Down
10 changes: 5 additions & 5 deletions src/game-server/monster.cpp
Expand Up @@ -112,10 +112,10 @@ Monster::Monster(MonsterClass *specy):

// Set positions relative to target from which the monster can attack
int dist = specy->getAttackDistance();
mAttackPositions.push_back(AttackPosition(dist, 0, DIRECTION_LEFT));
mAttackPositions.push_back(AttackPosition(-dist, 0, DIRECTION_RIGHT));
mAttackPositions.push_back(AttackPosition(0, -dist, DIRECTION_DOWN));
mAttackPositions.push_back(AttackPosition(0, dist, DIRECTION_UP));
mAttackPositions.push_back(AttackPosition(dist, 0, LEFT));
mAttackPositions.push_back(AttackPosition(-dist, 0, RIGHT));
mAttackPositions.push_back(AttackPosition(0, -dist, DOWN));
mAttackPositions.push_back(AttackPosition(0, dist, UP));

// Load default script
loadScript(specy->getScript());
Expand Down Expand Up @@ -224,7 +224,7 @@ void Monster::update()
Being *bestAttackTarget = mTarget = NULL;
int bestTargetPriority = 0;
Point bestAttackPosition;
BeingDirection bestAttackDirection = DIRECTION_DOWN;
BeingDirection bestAttackDirection = DOWN;

// Iterate through objects nearby
int aroundArea = Configuration::getValue("game_visualRange", 448);
Expand Down
1 change: 1 addition & 0 deletions src/game-server/state.cpp
Expand Up @@ -270,6 +270,7 @@ static void informPlayer(MapComposite *map, Character *p)
enterMsg.writeInt8(static_cast< Being *>(o)->getAction());
enterMsg.writeInt16(opos.x);
enterMsg.writeInt16(opos.y);
enterMsg.writeInt8(o->getDirection());
switch (otype)
{
case OBJECT_CHARACTER:
Expand Down
10 changes: 5 additions & 5 deletions src/manaserv_protocol.h
Expand Up @@ -103,7 +103,7 @@ enum {
PGMSG_LOWER_ATTRIBUTE = 0x0170, // W attribute
GPMSG_LOWER_ATTRIBUTE_RESPONSE = 0x0171, // B error, W attribute
PGMSG_RESPAWN = 0x0180, // -
GPMSG_BEING_ENTER = 0x0200, // B type, W being id, B action, W*2 position
GPMSG_BEING_ENTER = 0x0200, // B type, W being id, B action, W*2 position, B direction
// character: S name, B hair style, B hair color, B gender, B item bitmask, { W item id }*
// monster: W type id
// npc: W type id
Expand Down Expand Up @@ -415,10 +415,10 @@ enum AttackType
*/
enum BeingDirection
{
DIRECTION_UP = 1,
DIRECTION_DOWN,
DIRECTION_LEFT,
DIRECTION_RIGHT
DOWN = 1,
LEFT = 2,
UP = 4,
RIGHT = 8
};

/**
Expand Down
2 changes: 1 addition & 1 deletion src/scripting/lua.cpp
Expand Up @@ -852,7 +852,7 @@ static int being_set_direction(lua_State *s)
{
Being *being = getBeing(s, 1);

int dir = lua_tointeger(s, 2);
BeingDirection dir = (BeingDirection) lua_tointeger(s, 2);

if (being)
{
Expand Down

0 comments on commit 7f712f1

Please sign in to comment.