summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Athay <ko2fan@gmail.com>2009-05-18 18:42:33 +0100
committerDavid Athay <ko2fan@gmail.com>2009-05-18 18:42:33 +0100
commitc3c5ff134ac2e31560b421d125b35a9a73a25e5c (patch)
treedeeff273aa8f93f89ee9d4eba59cc1b6fdca1d4b
parent9bf793b93df88fb38c2f29d5ec7643d11899ef2f (diff)
downloadmanaserv-c3c5ff134ac2e31560b421d125b35a9a73a25e5c.tar.gz
manaserv-c3c5ff134ac2e31560b421d125b35a9a73a25e5c.tar.bz2
manaserv-c3c5ff134ac2e31560b421d125b35a9a73a25e5c.tar.xz
manaserv-c3c5ff134ac2e31560b421d125b35a9a73a25e5c.zip
Added target combat
-rw-r--r--src/game-server/being.cpp139
-rw-r--r--src/game-server/being.hpp15
-rw-r--r--src/game-server/character.cpp9
-rw-r--r--src/game-server/gamehandler.cpp10
-rw-r--r--src/game-server/monster.cpp2
5 files changed, 41 insertions, 134 deletions
diff --git a/src/game-server/being.cpp b/src/game-server/being.cpp
index a1991551..b43b789a 100644
--- a/src/game-server/being.cpp
+++ b/src/game-server/being.cpp
@@ -33,6 +33,7 @@
Being::Being(ThingType type):
Actor(type),
mAction(STAND),
+ mTarget(NULL),
mSpeed(0),
mDirection(0),
mHpRegenTimer(0)
@@ -105,6 +106,9 @@ void Being::died()
// dead beings stay where they are
clearDestination();
+ // reset target
+ mTarget = NULL;
+
for (Listeners::iterator i = mListeners.begin(),
i_end = mListeners.end(); i != i_end;)
{
@@ -218,138 +222,19 @@ int Being::directionToAngle(int direction)
}
}
-void Being::performAttack(const Damage &damage, const AttackZone *attackZone)
+void Being::performAttack(const Damage &damage)
{
- Point ppos = getPosition();
- const int attackAngle = directionToAngle(getDirection());
-
- 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));
- }
+ " Target:"<<mTarget->getName());
- for (BeingIterator
- i(getMap()->getAroundActorIterator(this, attackZone->range)); i; ++i)
- {
- Being *b = *i;
-
- if (b == this)
- continue;
+ if (!mTarget || mTarget == this || mTarget->getAction() == Being::DEAD || !mTarget->canFight())
+ return;
- const ThingType type = b->getType();
- if (type != OBJECT_CHARACTER && type != OBJECT_MONSTER)
- continue;
-
- if (getMap()->getPvP() == PVP_NONE &&
- type == OBJECT_CHARACTER &&
- getType() == OBJECT_CHARACTER)
- 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);
-
- const Point &opos = b->getPosition();
-
- switch (attackZone->shape)
- {
- case ATTZONESHAPE_CONE:
- if (Collision::diskWithCircleSector(
- opos, b->getSize(),
- ppos, attackZone->range,
- attackZone->angle / 2, attackAngle)
- )
- {
- victims.push_back(b);
- }
- break;
- case ATTZONESHAPE_RECT:
- defPos.x = opos.x - b->getSize();
- defPos.y = opos.y - b->getSize();
- defSize.x = b->getSize() * 2;
- defSize.y = b->getSize() * 2;
- if (Collision::rectWithRect(attPos, attSize, defPos, defSize))
- {
- victims.push_back(b);
- }
- break;
- default:
- break;
- }
- }
+ if (getMap()->getPvP() == PVP_NONE && mTarget->getType() == OBJECT_CHARACTER &&
+ getType() == OBJECT_CHARACTER)
+ return;
- 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++)
- {
- 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);
- }
+ mTarget->damage(this, damage);
}
void Being::setAction(Action action)
diff --git a/src/game-server/being.hpp b/src/game-server/being.hpp
index 92957096..96af1092 100644
--- a/src/game-server/being.hpp
+++ b/src/game-server/being.hpp
@@ -205,7 +205,7 @@ class Being : public Actor
/**
* Performs an attack.
*/
- void performAttack(const Damage &, const AttackZone *attackZone);
+ void performAttack(const Damage &);
/**
* Sets the current action.
@@ -278,10 +278,23 @@ class Being : public Actor
*/
static int directionToAngle(int direction);
+ /**
+ * Get Target
+ */
+ Being* getTarget() const
+ { return mTarget; }
+
+ /**
+ * Set Target
+ */
+ void setTarget(Being *target)
+ { mTarget = target; }
+
protected:
static const int TICKS_PER_HP_REGENERATION = 100;
Action mAction;
std::vector< Attribute > mAttributes;
+ Being *mTarget;
private:
Being(const Being &rhs);
diff --git a/src/game-server/character.cpp b/src/game-server/character.cpp
index f9a9b588..e17abc2b 100644
--- a/src/game-server/character.cpp
+++ b/src/game-server/character.cpp
@@ -116,7 +116,7 @@ void Character::update()
void Character::perform()
{
- if (mAction != ATTACK || mActionTime > 0) return;
+ if (mAction != ATTACK || mActionTime > 0 || mTarget == NULL) return;
mActionTime = 1000;
mAction = STAND;
@@ -141,13 +141,13 @@ void Character::perform()
// weapon fighting
const ItemModifiers &mods = ic->getModifiers();
damage.element = mods.getValue(MOD_ELEMENT_TYPE);
- performAttack(damage, ic->getAttackZone());
+ performAttack(damage);
}
else
{
// No-weapon fighting.
damage.element = ELEMENT_NEUTRAL;
- performAttack(damage, &UNARMED_ATTACK_ZONE);
+ performAttack(damage);
}
}
@@ -170,6 +170,9 @@ void Character::respawn()
setAction(STAND);
mAttributes[BASE_ATTR_HP].mod = -mAttributes[BASE_ATTR_HP].base + 1;
modifiedAttribute(BASE_ATTR_HP);
+
+ // reset target
+ mTarget = NULL;
}
void Character::useSpecial(int id)
diff --git a/src/game-server/gamehandler.cpp b/src/game-server/gamehandler.cpp
index d4b13e74..68af5314 100644
--- a/src/game-server/gamehandler.cpp
+++ b/src/game-server/gamehandler.cpp
@@ -354,8 +354,14 @@ void GameHandler::processMessage(NetComputer *comp, MessageIn &message)
{
LOG_DEBUG("Character " << computer.character->getPublicID()
<< " attacks");
- computer.character->setDirection(message.readByte());
- computer.character->setAction(Being::ATTACK);
+ int id = message.readShort();
+ Actor *o = findActorNear(computer.character, id);
+ if (o && o->getType() != OBJECT_NPC)
+ {
+ Being *being = static_cast<Being*>(o);
+ computer.character->setTarget(being);
+ computer.character->setAction(Being::ATTACK);
+ }
} break;
case PGMSG_USE_SPECIAL:
diff --git a/src/game-server/monster.cpp b/src/game-server/monster.cpp
index 9c5fb044..eaab71f2 100644
--- a/src/game-server/monster.cpp
+++ b/src/game-server/monster.cpp
@@ -123,7 +123,7 @@ void Monster::perform()
damage.cth = getModifiedAttribute(BASE_ATTR_HIT);
damage.element = mCurrentAttack->element;
damage.type = mCurrentAttack->type;
- performAttack(damage, &mCurrentAttack->attackZone);
+ performAttack(damage);
}
if (!mAttackTime)
{