summaryrefslogtreecommitdiff
path: root/src/game-server/being.cpp
diff options
context:
space:
mode:
authorPhilipp Sehmisch <tmw@crushnet.org>2008-09-27 03:55:19 +0000
committerPhilipp Sehmisch <tmw@crushnet.org>2008-09-27 03:55:19 +0000
commit29ae6d3f42ac55e7bc8c5ad0b044c7b0e662d358 (patch)
tree41ca7bb0f8b557e096a2b783f6c94ea4d3e5006a /src/game-server/being.cpp
parentc27d73abc52bdc463a029a5f6a95e1db5df5abf6 (diff)
downloadmanaserv-29ae6d3f42ac55e7bc8c5ad0b044c7b0e662d358.tar.gz
manaserv-29ae6d3f42ac55e7bc8c5ad0b044c7b0e662d358.tar.bz2
manaserv-29ae6d3f42ac55e7bc8c5ad0b044c7b0e662d358.tar.xz
manaserv-29ae6d3f42ac55e7bc8c5ad0b044c7b0e662d358.zip
Implemented getting the attack zone of weapons from the item database and implemented single target attacks useful for projectile weapons like bows.
Diffstat (limited to 'src/game-server/being.cpp')
-rw-r--r--src/game-server/being.cpp59
1 files changed, 52 insertions, 7 deletions
diff --git a/src/game-server/being.cpp b/src/game-server/being.cpp
index a6ba4023..bcbbc6d9 100644
--- a/src/game-server/being.cpp
+++ b/src/game-server/being.cpp
@@ -25,6 +25,7 @@
#include "game-server/being.hpp"
#include "defines.h"
+#include "game-server/attackzone.hpp"
#include "game-server/collisiondetection.hpp"
#include "game-server/eventlistener.hpp"
#include "game-server/mapcomposite.hpp"
@@ -126,7 +127,7 @@ void Being::move()
}
}
-void Being::performAttack(Damage const &damage, int range, int angle)
+void Being::performAttack(Damage const &damage, AttackZone const *attackZone)
{
Point ppos = getPosition();
int dir = getDirection();
@@ -151,8 +152,10 @@ void Being::performAttack(Damage const &damage, int range, int angle)
break;
}
+ std::list<Being *> victims;
+
for (MovingObjectIterator
- i(getMap()->getAroundObjectIterator(this, range)); i; ++i)
+ i(getMap()->getAroundObjectIterator(this, attackZone->range)); i; ++i)
{
MovingObject *o = *i;
if (o == this) continue;
@@ -163,13 +166,55 @@ void Being::performAttack(Damage const &damage, int range, int angle)
Point opos = o->getPosition();
- if (Collision::diskWithCircleSector(
- opos, o->getSize(),
- ppos, range, angle, attackAngle)
- )
+ switch (attackZone->shape)
+ {
+ case ATTZONESHAPE_CONE:
+ if (Collision::diskWithCircleSector(
+ opos, o->getSize(),
+ ppos, attackZone->range,
+ attackZone->angle/2, attackAngle)
+ )
+ {
+ victims.push_back(static_cast< Being * >(o));
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (attackZone->multiTarget)
+ {
+ // damage everyone
+ for (std::list<Being *>::iterator i = victims.begin();
+ i != victims.end();
+ i++)
+ {
+ (*i)->damage(this, damage);
+ }
+ }
+ else
+ {
+ // find the closest and damage this one
+ Being* closestVictim = NULL;
+ int closestDistance = INT_MAX;
+ for (std::list<Being *>::iterator i = victims.begin();
+ i != victims.end();
+ i++)
{
- static_cast< Being * >(o)->damage(this, damage);
+ Point opos = (*i)->getPosition();
+ int distance = abs(opos.x - ppos.x) + abs(opos.y - ppos.y);
+ /* not using pythagoras here is a) faster and b) results in more natural
+ target selection because targets closer to the center line of the
+ attack angle are prioritized
+ */
+ if (distance < closestDistance)
+ {
+ closestVictim = (*i);
+ closestDistance = distance;
+ }
}
+ if (closestVictim) closestVictim->damage(this, damage);
}
}