summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Sehmisch <crush@themanaworld.org>2008-11-20 16:52:48 +0100
committerPhilipp Sehmisch <crush@themanaworld.org>2008-11-20 16:52:48 +0100
commitd9189cba9db278b20c07bcb31ae481ad9804aaa5 (patch)
treeece36de0b3a6c833f5e79dc6d4c8a22278f757d1
parent8481413ea17177945d3d280b1518eb6f1f25cd5d (diff)
downloadmanaserv-d9189cba9db278b20c07bcb31ae481ad9804aaa5.tar.gz
manaserv-d9189cba9db278b20c07bcb31ae481ad9804aaa5.tar.bz2
manaserv-d9189cba9db278b20c07bcb31ae481ad9804aaa5.tar.xz
manaserv-d9189cba9db278b20c07bcb31ae481ad9804aaa5.zip
Added rectangular attack zones which are faster and simpler than cone-shaped ones and sufficient for most situations.
-rw-r--r--ChangeLog8
-rw-r--r--src/game-server/attackzone.hpp4
-rw-r--r--src/game-server/being.cpp66
-rw-r--r--src/game-server/character.cpp2
-rw-r--r--src/game-server/collisiondetection.cpp25
-rw-r--r--src/game-server/collisiondetection.hpp5
6 files changed, 98 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index 219baaae..2f379c8f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2008-11-20 Philipp Sehmisch <tmw@crushnet.org>
+
+ * src/game-server/attackzone.hpp, src/game-server/being.cpp,
+ src/game-server/character.cpp, src/game-server/collisiondetection.cpp,
+ src/game-server/collisiondetection.hpp: Added rectangular attack zones
+ which are faster and simpler to calculate than the cone-shaped ones.
+ Currently used by the characters unarmed attack.
+
2008-11-09 Bjørn Lindeijer <bjorn@lindeijer.nl>
* src/game-server/character.cpp: Fixed crash when a script can't be
diff --git a/src/game-server/attackzone.hpp b/src/game-server/attackzone.hpp
index 7cb003b4..1f611ba9 100644
--- a/src/game-server/attackzone.hpp
+++ b/src/game-server/attackzone.hpp
@@ -28,8 +28,8 @@
*/
enum AttackZoneShape
{
- ATTZONESHAPE_CONE
- //yes, there is currently only one but it is planned to add different kinds of attack zones
+ ATTZONESHAPE_CONE,
+ ATTZONESHAPE_RECT
};
struct AttackZone
diff --git a/src/game-server/being.cpp b/src/game-server/being.cpp
index 8ec0ea62..c07bff71 100644
--- a/src/game-server/being.cpp
+++ b/src/game-server/being.cpp
@@ -136,7 +136,48 @@ void Being::performAttack(Damage const &damage, AttackZone const *attackZone)
Point ppos = getPosition();
const int attackAngle = directionToAngle(getDirection());
- std::list<Being *> victims;
+ std::list<Being *> victims;
+
+ LOG_DEBUG("Direction:"<<getDirection()<<
+ " range:"<<attackZone->range<<
+ " angle:"<<attackZone->angle);
+
+ Point attPos, attSize, defPos, defSize;
+ if (attackZone->shape == ATTZONESHAPE_RECT)
+ {
+ if (getDirection() == DIRECTION_UP)
+ {
+ attPos.x = ppos.x - attackZone->angle;
+ attPos.y = ppos.y - attackZone->range;
+ attSize.x = attackZone->angle * 2;
+ attSize.y = attackZone->range;
+ }
+ if (getDirection() == DIRECTION_DOWN)
+ {
+ attPos.x = ppos.x - attackZone->angle;
+ attPos.y = ppos.y;
+ attSize.x = attackZone->angle * 2;
+ attSize.y = attackZone->range;
+ }
+ if (getDirection() == DIRECTION_RIGHT)
+ {
+ attPos.x = ppos.x;
+ attPos.y = ppos.y - attackZone->angle;
+ attSize.x = attackZone->range;
+ attSize.y = attackZone->angle * 2;
+ }
+ if (getDirection() == DIRECTION_LEFT)
+ {
+ attPos.x = ppos.x - attackZone->range;
+ attPos.y = ppos.y - attackZone->angle;
+ attSize.x = attackZone->range;
+ attSize.y = attackZone->angle * 2;
+ }
+ /* debug effect to see when and where the server pictures the attack - should
+ * be moved to the client side when the attack detection works statisfactory.
+ */
+ Effects::show(26, getMap(), Point(attPos.x + attSize.x / 2, attPos.y + attSize.y / 2));
+ }
for (MovingObjectIterator
i(getMap()->getAroundObjectIterator(this, attackZone->range)); i; ++i)
@@ -147,9 +188,16 @@ void Being::performAttack(Damage const &damage, AttackZone const *attackZone)
if (o == this) continue;
int type = o->getType();
-
- if (type != OBJECT_CHARACTER && type != OBJECT_MONSTER) continue;
-
+ if (type != OBJECT_CHARACTER && type != OBJECT_MONSTER) continue;
+
+ LOG_DEBUG("Attack Zone:"<<
+ attPos.x<<":"<<attPos.y<<
+ " "<<
+ attSize.x<<"x"<<attSize.y);
+ LOG_DEBUG("Defender Zone:"<<
+ defPos.x<<":"<<defPos.y<<
+ " "<<
+ defSize.x<<"x"<<defSize.y);
switch (attackZone->shape)
{
@@ -161,6 +209,16 @@ void Being::performAttack(Damage const &damage, AttackZone const *attackZone)
)
{
victims.push_back(static_cast< Being * >(o));
+ }
+ break;
+ case ATTZONESHAPE_RECT:
+ defPos.x = opos.x - o->getSize();
+ defPos.y = opos.y - o->getSize();
+ defSize.x = o->getSize() * 2;
+ defSize.y = o->getSize() * 2;
+ if (Collision::rectWithRect(attPos, attSize, defPos, defSize))
+ {
+ victims.push_back(static_cast< Being * >(o));
}
break;
default:
diff --git a/src/game-server/character.cpp b/src/game-server/character.cpp
index 3f0f3dad..c4a806a0 100644
--- a/src/game-server/character.cpp
+++ b/src/game-server/character.cpp
@@ -48,7 +48,7 @@
const float Character::EXPCURVE_EXPONENT = 3.0f;
const float Character::EXPCURVE_FACTOR = 10.0f;
const float Character::LEVEL_SKILL_PRECEDENCE_FACTOR = 0.75f;
-const AttackZone Character::UNARMED_ATTACK_ZONE = {ATTZONESHAPE_CONE, true, 32, 90};
+const AttackZone Character::UNARMED_ATTACK_ZONE = {ATTZONESHAPE_RECT, true, 48, 16};
Character::Character(MessageIn &msg):
Being(OBJECT_CHARACTER, 65535),
diff --git a/src/game-server/collisiondetection.cpp b/src/game-server/collisiondetection.cpp
index 49858e17..be77024c 100644
--- a/src/game-server/collisiondetection.cpp
+++ b/src/game-server/collisiondetection.cpp
@@ -103,7 +103,7 @@ bool Collision::diskWithCircleSector(const Point &diskCenter, int diskRadius,
// d^2 > r1^2 + r2^2
if(d > ((r1+r2) * (r1+r2)))
return false; // The two circles do not touch
-
+
float s1 = placeAngle - halfTopAngle,
s2 = placeAngle + halfTopAngle;
@@ -123,14 +123,14 @@ bool Collision::diskWithCircleSector(const Point &diskCenter, int diskRadius,
float c2dc1 = atan2(dy,dx) * R_TO_D;
if (c2dc1 < 0)
c2dc1 += 360;
-
+
if (test_degrees(c2dc1, s1, s2))
return true;
-
+
// Since we are well within range, we might be
// Too close, so we need to make sure two circles intersect
d = sqrt(d);
- r1 = d;
+ r1 = d;
} else {
d = sqrt(d);
}
@@ -144,7 +144,7 @@ bool Collision::diskWithCircleSector(const Point &diskCenter, int diskRadius,
iy1 = ayd - ((h * dy) / d),
ix2 = axd - ((h * dx) / d),
iy2 = ayd + ((h * dy) / d);
-
+
float idc1 = atan2(iy1,ix1) * R_TO_D;
if(idc1 < 0)
idc1 += 360;
@@ -288,3 +288,18 @@ Collision::CircleWithCircle(const Point &center1, int radius1,
double dist = sqrt((distx * distx) + (disty * disty));
return (dist < radius1 + radius2);
}
+
+bool
+Collision::rectWithRect(const Point &pos1, const Point &size1,
+ const Point &pos2, const Point &size2)
+{
+ return(
+ pos1.x < (pos2.x + size2.x) //left edge 1 left of right edge 2
+ &&
+ (pos1.x + size1.x) > pos2.x //right edge 1 right of left edge 2
+ &&
+ pos1.y < (pos2.y + size2.y) //upper edge 1 above lower edge 2
+ &&
+ (pos1.y + size1.y) > pos2.y //lower edge 1 under upper edge 2
+ );
+}
diff --git a/src/game-server/collisiondetection.hpp b/src/game-server/collisiondetection.hpp
index eb30a4c4..c60d9d64 100644
--- a/src/game-server/collisiondetection.hpp
+++ b/src/game-server/collisiondetection.hpp
@@ -53,6 +53,11 @@ namespace Collision
CircleWithCircle(const Point &center1, int radius1,
const Point &center2, int radius2);
+ /** checks if two rectangles intersect */
+ bool
+ rectWithRect(const Point &pos1, const Point &size1,
+ const Point &pos2, const Point &size2);
+
}
#endif