From 7f712f1c9d00182660298d123d120444ef6a4996 Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Sun, 9 Jan 2011 12:12:41 +0100 Subject: [PATCH] Fix being direction discrepancies by syncing the BeingDirection. 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. --- src/game-server/being.cpp | 100 ++++++++++++++++++++++++++++++-- src/game-server/being.h | 13 ++++- src/game-server/gamehandler.cpp | 3 +- src/game-server/monster.cpp | 10 ++-- src/game-server/state.cpp | 1 + src/manaserv_protocol.h | 10 ++-- src/scripting/lua.cpp | 2 +- 7 files changed, 118 insertions(+), 21 deletions(-) diff --git a/src/game-server/being.cpp b/src/game-server/being.cpp index 65736774..567e19a3 100644 --- a/src/game-server/being.cpp +++ b/src/game-server/being.cpp @@ -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."); @@ -202,6 +202,89 @@ Path Being::findPath() return map->findPath(startX, startY, destX, destY, getWalkMask()); } +void Being::updateDirection(const Point ¤tPos, 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. @@ -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; @@ -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 @@ -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; } } diff --git a/src/game-server/being.h b/src/game-server/being.h index 07876a4a..11c5f753 100644 --- a/src/game-server/being.h +++ b/src/game-server/being.h @@ -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; } /** @@ -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 ¤tPos, + 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. */ diff --git a/src/game-server/gamehandler.cpp b/src/game-server/gamehandler.cpp index a9097286..55c18c2c 100644 --- a/src/game-server/gamehandler.cpp +++ b/src/game-server/gamehandler.cpp @@ -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: diff --git a/src/game-server/monster.cpp b/src/game-server/monster.cpp index 661aca5e..78268db1 100644 --- a/src/game-server/monster.cpp +++ b/src/game-server/monster.cpp @@ -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()); @@ -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); diff --git a/src/game-server/state.cpp b/src/game-server/state.cpp index bed47805..abfa2342 100644 --- a/src/game-server/state.cpp +++ b/src/game-server/state.cpp @@ -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: diff --git a/src/manaserv_protocol.h b/src/manaserv_protocol.h index da95207c..f0dc22b2 100644 --- a/src/manaserv_protocol.h +++ b/src/manaserv_protocol.h @@ -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 @@ -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 }; /** diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp index 2635974e..3a615412 100644 --- a/src/scripting/lua.cpp +++ b/src/scripting/lua.cpp @@ -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) {