summaryrefslogtreecommitdiff
path: root/src/game-server
diff options
context:
space:
mode:
authorPhilipp Sehmisch <tmw@crushnet.org>2007-03-02 23:30:17 +0000
committerPhilipp Sehmisch <tmw@crushnet.org>2007-03-02 23:30:17 +0000
commitaf1ce69940a9c0b46907402e7d69e6ac9ea96912 (patch)
tree016a6a8a4734f794e56093e1611530749eb7fab0 /src/game-server
parent07782116ae9158c20165dd4d60bdb96017ac009f (diff)
downloadmanaserv-af1ce69940a9c0b46907402e7d69e6ac9ea96912.tar.gz
manaserv-af1ce69940a9c0b46907402e7d69e6ac9ea96912.tar.bz2
manaserv-af1ce69940a9c0b46907402e7d69e6ac9ea96912.tar.xz
manaserv-af1ce69940a9c0b46907402e7d69e6ac9ea96912.zip
Implemented being death, removal of dead mobs and sitting.
Diffstat (limited to 'src/game-server')
-rw-r--r--src/game-server/being.cpp42
-rw-r--r--src/game-server/being.hpp71
-rw-r--r--src/game-server/gamehandler.cpp25
-rw-r--r--src/game-server/object.hpp14
-rw-r--r--src/game-server/player.cpp6
-rw-r--r--src/game-server/player.hpp21
-rw-r--r--src/game-server/state.cpp52
-rw-r--r--src/game-server/testing.cpp1
8 files changed, 167 insertions, 65 deletions
diff --git a/src/game-server/being.cpp b/src/game-server/being.cpp
index 7f2ec2f4..6924f3b9 100644
--- a/src/game-server/being.cpp
+++ b/src/game-server/being.cpp
@@ -29,13 +29,43 @@
void Being::damage(Damage damage)
{
+ if (mAction == DEAD) return;
+
int HPloss;
HPloss = damage; // TODO: Implement complex damage calculation here
+ if (HPloss > mHitpoints) HPloss = mHitpoints;
+
mHitpoints -= HPloss;
mHitsTaken.push_back(HPloss);
- LOG_DEBUG("Being " << getPublicID() << " got hit");
+ LOG_INFO("Being " << getPublicID() << " got hit");
+
+ if (mHitpoints == 0) die();
+}
+
+void Being::die()
+{
+ LOG_INFO("Being " << getPublicID() << " died");
+ setAction(DEAD);
+ // dead beings stay where they are
+ setDestination(getPosition());
+}
+
+void Being::move()
+{
+ MovingObject::move();
+ if (mAction == WALK || mAction == STAND)
+ {
+ if (mActionTime)
+ {
+ mAction = WALK;
+ }
+ else
+ {
+ mAction = STAND;
+ }
+ }
}
void Being::performAttack(MapComposite *map)
@@ -95,3 +125,13 @@ void Being::performAttack(MapComposite *map)
}
}
}
+
+void Being::setAction(Action action)
+{
+ mAction = action;
+ if (action != Being::ATTACK && // The players are informed about these actions
+ action != Being::WALK) // by other messages
+ {
+ raiseUpdateFlags(UPDATEFLAG_ACTIONCHANGE);
+ }
+}
diff --git a/src/game-server/being.hpp b/src/game-server/being.hpp
index 327783ce..2eaffa16 100644
--- a/src/game-server/being.hpp
+++ b/src/game-server/being.hpp
@@ -65,31 +65,6 @@ struct BeingState
};
/**
- * Moves enum for beings and actors for others players vision.
- */
-enum
-{
- ACTION_DEFAULT = 0,
- ACTION_STAND,
- ACTION_WALK,
- ACTION_RUN,
- ACTION_JUMP,
- ACTION_CRAWL,
- ACTION_ATTACK,
- ACTION_ATTACK_SWING,
- ACTION_ATTACK_STAB,
- ACTION_ATTACK_BOW,
- ACTION_ATTACK_THROW,
- ACTION_CAST_MAGIC,
- ACTION_USE_ITEM,
- ACTION_SIT,
- ACTION_SLEEP,
- ACTION_HURT,
- ACTION_DEAD,
- ACTION_INVALID
-};
-
-/**
* Beings and actors directions
*/
enum
@@ -141,10 +116,24 @@ class Being : public MovingObject
{
public:
/**
+ * Moves enum for beings and actors for others players vision.
+ * WARNING: Has to be in sync with the same enum in the Being class
+ * of the client!
+ */
+ enum Action {
+ STAND,
+ WALK,
+ ATTACK,
+ SIT,
+ DEAD,
+ HURT
+ };
+ /**
* Proxy constructor.
*/
Being(int type, int id)
- : MovingObject(type, id)
+ : MovingObject(type, id),
+ mAction(STAND)
{}
/**
@@ -166,6 +155,12 @@ class Being : public MovingObject
{ return mStats.stats[numStat]; }
/**
+ * sets the hit points
+ */
+ void setHitpoints(int hp)
+ { mHitpoints = hp; }
+
+ /**
* Takes a damage structure, computes the real damage based on the
* stats, deducts the result from the hitpoints and adds the result to
* the HitsTaken list.
@@ -173,6 +168,11 @@ class Being : public MovingObject
void damage(Damage);
/**
+ * Kills the being
+ */
+ virtual void die();
+
+ /**
* Gets the damage list.
*/
Hits const &getHitsTaken() const
@@ -189,14 +189,29 @@ class Being : public MovingObject
*/
void performAttack(MapComposite *);
+ /**
+ * Sets the current action.
+ */
+ virtual void setAction(Action action);
+
+ virtual Action getAction() const
+ { return mAction; }
+
+ /**
+ * Moves the being toward its destination.
+ */
+ virtual void move();
+
+ protected:
+ int mHitpoints; /**< Hitpoints of the being */
+ Action mAction;
+
private:
Being(Being const &rhs);
Being &operator=(Being const &rhs);
Statistics mStats; /**< stats modifiers or computed stats */
- int mHitpoints; /**< Hitpoints of the being */
-
Hits mHitsTaken; /**< List of punches taken since last update */
};
diff --git a/src/game-server/gamehandler.cpp b/src/game-server/gamehandler.cpp
index 5801c6fe..768a2cd9 100644
--- a/src/game-server/gamehandler.cpp
+++ b/src/game-server/gamehandler.cpp
@@ -301,7 +301,30 @@ void GameHandler::processMessage(NetComputer *comp, MessageIn &message)
LOG_DEBUG("Player " << computer.character->getPublicID()
<< " attacks");
computer.character->setDirection(message.readByte());
- computer.character->setAction(PLAYER_ATTACK);
+ computer.character->setAction(Being::ATTACK);
+ } break;
+
+ case PGMSG_ACTION_CHANGE:
+ {
+ Being::Action action = (Being::Action)message.readByte();
+ Being::Action current = (Being::Action)computer.character->getAction();
+
+ switch (action)
+ {
+ case Being::STAND:
+ {
+ if (current == Being::SIT)
+ computer.character->setAction(Being::STAND);
+ } break;
+ case Being::SIT:
+ {
+ if (current == Being::STAND)
+ computer.character->setAction(Being::SIT);
+ } break;
+ default:
+ break;
+ }
+
} break;
case PGMSG_DISCONNECT:
diff --git a/src/game-server/object.hpp b/src/game-server/object.hpp
index e0443f93..b067b34b 100644
--- a/src/game-server/object.hpp
+++ b/src/game-server/object.hpp
@@ -44,9 +44,11 @@ class MapComposite;
enum
{
- NEW_ON_MAP = 1,
- NEW_DESTINATION = 2,
- ATTACK = 4
+ UPDATEFLAG_NEW_ON_MAP = 1,
+ UPDATEFLAG_NEW_DESTINATION = 2,
+ UPDATEFLAG_ATTACK = 4,
+ UPDATEFLAG_ACTIONCHANGE = 8,
+ UPDATEFLAG_REMOVE = 16
};
/**
@@ -198,7 +200,7 @@ class MovingObject: public Object
* Sets the destination coordinates of the object.
*/
void setDestination(Point dst)
- { mDst = dst; raiseUpdateFlags(NEW_DESTINATION); mPath.clear(); }
+ { mDst = dst; raiseUpdateFlags(UPDATEFLAG_NEW_DESTINATION); mPath.clear(); }
/**
* Gets the old coordinates of the object.
@@ -239,7 +241,7 @@ class MovingObject: public Object
/**
* Moves the object toward its destination.
*/
- void move();
+ virtual void move();
/**
* Get public ID.
@@ -261,12 +263,12 @@ class MovingObject: public Object
Point mDst; /**< target coordinates */
Point mOld; /**< old coordinates */
unsigned short mSpeed; /**< speed */
- unsigned mSize; /**< radius of bounding circle */
std::list<PATH_NODE> mPath;
protected:
unsigned char mDirection; /**< Facing direction */
unsigned short mActionTime; /**< delay until next action */
+ unsigned mSize; /**< radius of bounding circle */
};
#endif // _TMWSERV_OBJECT_H_
diff --git a/src/game-server/player.cpp b/src/game-server/player.cpp
index f687cba6..5580d094 100644
--- a/src/game-server/player.cpp
+++ b/src/game-server/player.cpp
@@ -39,15 +39,15 @@ void Player::update()
setStat(STAT_SPEED, getRawStat(STAT_DEXTERITY));
// attacking
- if (mAction == PLAYER_ATTACK)
+ if (mAction == ATTACK)
{
// plausibility check of attack command
if (mActionTime <= 0)
{
// request perform attack
mActionTime = 1000;
- mAction = PLAYER_STAND;
- raiseUpdateFlags(ATTACK);
+ mAction = STAND;
+ raiseUpdateFlags(UPDATEFLAG_ATTACK);
}
}
}
diff --git a/src/game-server/player.hpp b/src/game-server/player.hpp
index 426738d7..bd1ec997 100644
--- a/src/game-server/player.hpp
+++ b/src/game-server/player.hpp
@@ -51,9 +51,11 @@ class Player : public Being, public PlayerData
Player(std::string const &name, int id = -1)
: Being(OBJECT_PLAYER, 65535),
PlayerData(name, id),
- mClient(NULL),
- mAction(PLAYER_STAND)
- {}
+ mClient(NULL)
+ {
+ mHitpoints=5;
+ mSize = 16;
+ }
/**
* Updates the internal status.
@@ -61,18 +63,6 @@ class Player : public Being, public PlayerData
void update();
/**
- * Sets next action.
- **/
- void setAction(int s)
- { mAction = s; }
-
- /**
- * Gets next action.
- **/
- int getAction() const
- { return mAction; }
-
- /**
* Gets client computer.
*/
GameClient *getClient() const
@@ -89,7 +79,6 @@ class Player : public Being, public PlayerData
Player &operator=(Player const &);
GameClient *mClient; /**< Client computer. */
- unsigned char mAction; /**< Player state. */
};
#endif // _TMWSERV_PLAYER_H_
diff --git a/src/game-server/state.cpp b/src/game-server/state.cpp
index 58949ce7..09513b95 100644
--- a/src/game-server/state.cpp
+++ b/src/game-server/state.cpp
@@ -57,7 +57,7 @@ void State::updateMap(MapComposite *map)
for (MovingObjectIterator i(map->getWholeMapIterator()); i; ++i)
{
MovingObject *o = *i;
- if (o->getUpdateFlags() & ATTACK)
+ if (o->getUpdateFlags() & UPDATEFLAG_ATTACK)
{
static_cast< Being * >(o)->performAttack(map);
}
@@ -68,6 +68,17 @@ void State::updateMap(MapComposite *map)
{
(*i)->move();
}
+
+ // 4. remove dead beings
+ for (MovingObjectIterator i(map->getWholeMapIterator()); i; ++i)
+ {
+ if ((*i)->getUpdateFlags() & UPDATEFLAG_REMOVE)
+ {
+ DelayedEvent e = { EVENT_REMOVE};
+ enqueueEvent((*i), e);
+ }
+ }
+
map->update();
}
@@ -91,13 +102,30 @@ void State::informPlayer(MapComposite *map, Player *p)
if (willBeInRange)
{
// Send attack messages.
- if ((oflags & ATTACK) && oid != pid)
+ if ((oflags & UPDATEFLAG_ATTACK) && oid != pid)
{
MessageOut AttackMsg(GPMSG_BEING_ATTACK);
AttackMsg.writeShort(oid);
gameHandler->sendTo(p, AttackMsg);
}
+ // Send state change messages.
+ if ((oflags & UPDATEFLAG_ACTIONCHANGE))
+ {
+ MessageOut ActionMsg(GPMSG_BEING_ACTION_CHANGE);
+ ActionMsg.writeShort(oid);
+ ActionMsg.writeByte(static_cast< Being * >(o)->getAction());
+ gameHandler->sendTo(p, ActionMsg);
+ }
+
+ // Send leave messages of dead beings
+ if ((oflags & UPDATEFLAG_REMOVE))
+ {
+ MessageOut leaveMsg(GPMSG_BEING_LEAVE);
+ leaveMsg.writeShort(oid);
+ gameHandler->sendTo(p, leaveMsg);
+ }
+
// Send damage messages.
if (o->canFight())
{
@@ -114,7 +142,7 @@ void State::informPlayer(MapComposite *map, Player *p)
// Check if this player and this moving object were around.
bool wereInRange = pold.inRangeOf(oold, AROUND_AREA) &&
- !((pflags | oflags) & NEW_ON_MAP);
+ !((pflags | oflags) & UPDATEFLAG_NEW_ON_MAP);
// Send enter/leaver messages.
if (!wereInRange)
@@ -125,11 +153,14 @@ void State::informPlayer(MapComposite *map, Player *p)
// Nothing to report: o will not be inside p's range.
continue;
}
- flags |= MOVING_DESTINATION;
+ flags |= MOVING_POSITION;
MessageOut enterMsg(GPMSG_BEING_ENTER);
enterMsg.writeByte(otype);
enterMsg.writeShort(oid);
+ enterMsg.writeByte(static_cast< Being *>(o)->getAction());
+ enterMsg.writeShort(opos.x);
+ enterMsg.writeShort(opos.y);
switch (otype) {
case OBJECT_PLAYER:
{
@@ -147,6 +178,7 @@ void State::informPlayer(MapComposite *map, Player *p)
assert(false); // TODO
}
gameHandler->sendTo(p, enterMsg);
+ continue;
}
else if (!willBeInRange)
{
@@ -156,7 +188,7 @@ void State::informPlayer(MapComposite *map, Player *p)
gameHandler->sendTo(p, leaveMsg);
continue;
}
- else if (oold.x == opos.x && oold.y == opos.y)
+ else if (oold == opos)
{
// o does not move, nothing to report.
continue;
@@ -166,10 +198,10 @@ void State::informPlayer(MapComposite *map, Player *p)
moving inside p's range. Report o's movements. */
Point odst = o->getDestination();
- if (opos.x != odst.x || opos.y != odst.y)
+ if (opos != odst)
{
flags |= MOVING_POSITION;
- if (oflags & NEW_DESTINATION)
+ if (oflags & UPDATEFLAG_NEW_DESTINATION)
{
flags |= MOVING_DESTINATION;
}
@@ -210,11 +242,11 @@ void State::informPlayer(MapComposite *map, Player *p)
int oflags = o->getUpdateFlags();
bool willBeInRange = ppos.inRangeOf(opos, AROUND_AREA);
bool wereInRange = pold.inRangeOf(opos, AROUND_AREA) &&
- !((pflags | oflags) & NEW_ON_MAP);
+ !((pflags | oflags) & UPDATEFLAG_NEW_ON_MAP);
if (willBeInRange ^ wereInRange)
{
- if (oflags & NEW_ON_MAP)
+ if (oflags & UPDATEFLAG_NEW_ON_MAP)
{
MessageOut appearMsg(GPMSG_ITEM_APPEAR);
appearMsg.writeShort(o->getItemClass()->getDatabaseID());
@@ -329,7 +361,7 @@ void State::insert(Thing *ptr)
if (ptr->isVisible())
{
Object *obj = static_cast< Object * >(ptr);
- obj->raiseUpdateFlags(NEW_ON_MAP);
+ obj->raiseUpdateFlags(UPDATEFLAG_NEW_ON_MAP);
if (obj->getType() != OBJECT_PLAYER) return;
/* Since the player doesn't know yet where on the world he is after
diff --git a/src/game-server/testing.cpp b/src/game-server/testing.cpp
index 86f47f2c..4f269e29 100644
--- a/src/game-server/testing.cpp
+++ b/src/game-server/testing.cpp
@@ -37,6 +37,7 @@ void testingMap(int id)
Being *being = new Controlled(OBJECT_MONSTER);
being->setSpeed(150);
being->setSize(8);
+ being->setHitpoints(3);
being->setMapId(1);
Point pos = { 720, 900 };
being->setPosition(pos);