diff options
author | Philipp Sehmisch <tmw@crushnet.org> | 2008-09-27 03:55:19 +0000 |
---|---|---|
committer | Philipp Sehmisch <tmw@crushnet.org> | 2008-09-27 03:55:19 +0000 |
commit | 29ae6d3f42ac55e7bc8c5ad0b044c7b0e662d358 (patch) | |
tree | 41ca7bb0f8b557e096a2b783f6c94ea4d3e5006a /src/game-server/being.cpp | |
parent | c27d73abc52bdc463a029a5f6a95e1db5df5abf6 (diff) | |
download | manaserv-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.cpp | 59 |
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); } } |