summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <bjorn@lindeijer.nl>2024-08-19 16:03:09 +0200
committerThorbjørn Lindeijer <bjorn@lindeijer.nl>2025-03-07 22:27:48 +0100
commit3556885ee1027b79c8151e3fb2aeb5906483d3d3 (patch)
tree7d3c714fb1eec3d50a3efe9999da7f07f4cafa02 /src
parentca0b74e0f52aef36b929a2059fab62c192c620f6 (diff)
downloadmana-3556885ee1027b79c8151e3fb2aeb5906483d3d3.tar.gz
mana-3556885ee1027b79c8151e3fb2aeb5906483d3d3.tar.bz2
mana-3556885ee1027b79c8151e3fb2aeb5906483d3d3.tar.xz
mana-3556885ee1027b79c8151e3fb2aeb5906483d3d3.zip
Support triggering attacks and play use ability animations
For now, PlayerHandler::attack just tries to trigger the "Strike" ability. Adjusted the AbilityDB to the removal of ability categories and the addition of the useaction attribute (mana/manaserv@81f126ae001b1446dc0be37341f133dca5ab2923)
Diffstat (limited to 'src')
-rw-r--r--src/being.cpp9
-rw-r--r--src/being.h5
-rw-r--r--src/net/manaserv/beinghandler.cpp19
-rw-r--r--src/net/manaserv/playerhandler.cpp29
-rw-r--r--src/resources/abilitydb.cpp60
-rw-r--r--src/resources/abilitydb.h19
-rw-r--r--src/resources/settingsmanager.cpp5
7 files changed, 96 insertions, 50 deletions
diff --git a/src/being.cpp b/src/being.cpp
index d1934aef..9beb5355 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -666,7 +666,6 @@ void Being::setAction(Action action, int attackId)
}
effectManager->trigger(effectId, this, rotation);
}
-
}
break;
@@ -696,6 +695,14 @@ void Being::setAction(Action action, int attackId)
mActionTimer.set();
}
+void Being::setAction(const std::string &action)
+{
+ // Actions are triggered by strings from abilities when using manaserv,
+ // it's not necessarily an attack, but it seems the most appropriate value.
+ mAction = ATTACK;
+ mSprites.play(action);
+}
+
void Being::lookAt(const Vector &destPos)
{
// We first handle simple cases
diff --git a/src/being.h b/src/being.h
index ab5e33c3..1cfac80f 100644
--- a/src/being.h
+++ b/src/being.h
@@ -333,6 +333,11 @@ class Being : public ActorSprite, public EventListener
virtual void setAction(Action action, int attackId = 1);
/**
+ * Sets the current action by name.
+ */
+ void setAction(const std::string &action);
+
+ /**
* Get the being's action currently performed.
*/
Action getCurrentAction() const { return mAction; }
diff --git a/src/net/manaserv/beinghandler.cpp b/src/net/manaserv/beinghandler.cpp
index d8f47297..7f16ae19 100644
--- a/src/net/manaserv/beinghandler.cpp
+++ b/src/net/manaserv/beinghandler.cpp
@@ -36,6 +36,7 @@
#include "net/manaserv/manaserv_protocol.h"
#include "playerrelations.h"
+#include "resources/abilitydb.h"
#include "resources/emotedb.h"
#include "resources/hairdb.h"
@@ -281,7 +282,10 @@ void BeingHandler::handleBeingAbilityPointMessage(MessageIn &msg)
const int x = msg.readInt16();
const int y = msg.readInt16();
- std::cout << "GPMSG_BEING_ABILITY_POINT(" << abilityId << ", " << x << ", " << y << ")" << std::endl;
+ being->lookAt(Vector(x, y));
+
+ if (auto ability = AbilityDB::get(abilityId))
+ being->setAction(ability->useAction);
}
void BeingHandler::handleBeingAbilityBeingMessage(MessageIn &msg)
@@ -293,7 +297,11 @@ void BeingHandler::handleBeingAbilityBeingMessage(MessageIn &msg)
const int abilityId = msg.readInt8();
const int targetId = msg.readInt16();
- std::cout << "GPMSG_BEING_ABILITY_BEING(" << abilityId << ", " << targetId << ")" << std::endl;
+ if (Being *target = actorSpriteManager->findBeing(targetId))
+ being->lookAt(target->getPosition());
+
+ if (auto ability = AbilityDB::get(abilityId))
+ being->setAction(ability->useAction);
}
void BeingHandler::handleBeingAbilityDirectionMessage(MessageIn &msg)
@@ -305,7 +313,10 @@ void BeingHandler::handleBeingAbilityDirectionMessage(MessageIn &msg)
const int abilityId = msg.readInt8();
const int direction = msg.readInt8();
- std::cout << "GPMSG_BEING_ABILITY_DIRECTION(" << abilityId << ", " << direction << ")" << std::endl;
+ being->setDirection(direction);
+
+ if (auto ability = AbilityDB::get(abilityId))
+ being->setAction(ability->useAction);
}
void BeingHandler::handleBeingsDamageMessage(MessageIn &msg)
@@ -315,9 +326,7 @@ void BeingHandler::handleBeingsDamageMessage(MessageIn &msg)
Being *being = actorSpriteManager->findBeing(msg.readInt16());
int damage = msg.readInt16();
if (being)
- {
being->takeDamage(nullptr, damage, Being::HIT);
- }
}
}
diff --git a/src/net/manaserv/playerhandler.cpp b/src/net/manaserv/playerhandler.cpp
index 02712214..8ee9ed80 100644
--- a/src/net/manaserv/playerhandler.cpp
+++ b/src/net/manaserv/playerhandler.cpp
@@ -29,17 +29,18 @@
#include "log.h"
#include "particle.h"
#include "playerinfo.h"
-#include "configuration.h"
#include "gui/viewport.h"
#include "net/net.h"
+#include "net/abilityhandler.h"
#include "net/manaserv/connection.h"
#include "net/manaserv/messagein.h"
#include "net/manaserv/messageout.h"
#include "net/manaserv/manaserv_protocol.h"
+#include "resources/abilitydb.h"
#include "resources/attributes.h"
/**
@@ -50,6 +51,7 @@
const int MAP_TELEPORT_SCROLL_DISTANCE = 256;
extern Net::PlayerHandler *playerHandler;
+extern Net::AbilityHandler *abilityHandler;
namespace ManaServ {
@@ -290,14 +292,31 @@ void PlayerHandler::handleMapChangeMessage(MessageIn &msg)
void PlayerHandler::attack(int id)
{
- // MessageOut msg(PGMSG_ATTACK);
- // msg.writeInt16(id);
- // gameServerConnection->send(msg);
+ auto ability = AbilityDB::find("Strike");
+ if (!ability)
+ {
+ logger->log("PlayerHandler::attack: 'Strike' ability not found.");
+ return;
+ }
+
+ switch (ability->targetMode) {
+ case AbilityInfo::TARGET_BEING:
+ abilityHandler->useOn(ability->id, id);
+ break;
+ case AbilityInfo::TARGET_POINT:
+ logger->log("PlayerHandler::attack: Unsupported target mode 'point' for 'Strike' ability.");
+ break;
+ case AbilityInfo::TARGET_DIRECTION:
+ abilityHandler->useInDirection(ability->id, local_player->getDirection());
+ break;
+ }
}
void PlayerHandler::emote(int emoteId)
{
- // TODO
+ MessageOut msg(PGMSG_BEING_EMOTE);
+ msg.writeInt8(emoteId);
+ gameServerConnection->send(msg);
}
void PlayerHandler::increaseAttribute(int attr)
diff --git a/src/resources/abilitydb.cpp b/src/resources/abilitydb.cpp
index a22fb28e..311ee9eb 100644
--- a/src/resources/abilitydb.cpp
+++ b/src/resources/abilitydb.cpp
@@ -32,12 +32,14 @@ namespace
bool mLoaded = false;
}
-AbilityInfo::TargetMode AbilityDB::targetModeFromString(const std::string& str)
+static AbilityInfo::TargetMode targetModeFromString(const std::string& str)
{
if (str == "being")
return AbilityInfo::TARGET_BEING;
if (str == "point")
return AbilityInfo::TARGET_POINT;
+ if (str == "direction")
+ return AbilityInfo::TARGET_DIRECTION;
logger->log("AbilityDB: Warning, unknown target mode \"%s\"", str.c_str() );
return AbilityInfo::TARGET_BEING;
@@ -50,33 +52,25 @@ void AbilityDB::init()
unload();
}
-void AbilityDB::readAbilityCategoryNode(XML::Node node, const std::string &filename)
+void AbilityDB::readAbilityNode(XML::Node node, const std::string &filename)
{
- std::string categoryName = node.getProperty("name", "Actions");
-
- for (auto ability : node.children())
- {
- if (ability.name() == "ability")
- {
- auto *info = new AbilityInfo();
- int id = ability.getProperty("id", 0);
- info->id = id;
- info->category = categoryName;
- info->name = ability.getProperty("name", "");
- info->icon = ability.getProperty("icon", "");
-
- info->targetMode = targetModeFromString(ability.getProperty("target", "being"));
-
- info->rechargeable = ability.getBoolProperty("rechargeable", true);
- info->rechargeNeeded = 0;
- info->rechargeCurrent = 0;
-
- if (mAbilityInfos.find(id) != mAbilityInfos.end())
- logger->log("AbilityDB: Duplicate ability ID %d in %s, ignoring", id, filename.c_str());
- else
- mAbilityInfos[id] = info;
- }
- }
+ auto *info = new AbilityInfo();
+ int id = node.getProperty("id", 0);
+ info->id = id;
+ info->name = node.getProperty("name", std::string());
+ info->icon = node.getProperty("icon", std::string());
+ info->useAction = node.getProperty("useaction", std::string());
+
+ info->targetMode = targetModeFromString(node.getProperty("target", "being"));
+
+ info->rechargeable = node.getBoolProperty("rechargeable", true);
+ info->rechargeNeeded = 0;
+ info->rechargeCurrent = 0;
+
+ if (mAbilityInfos.find(id) != mAbilityInfos.end())
+ logger->log("AbilityDB: Duplicate ability ID %d in %s, ignoring", id, filename.c_str());
+ else
+ mAbilityInfos[id] = info;
}
void AbilityDB::checkStatus()
@@ -86,7 +80,6 @@ void AbilityDB::checkStatus()
void AbilityDB::unload()
{
-
delete_all(mAbilityInfos);
mAbilityInfos.clear();
@@ -97,8 +90,17 @@ AbilityInfo *AbilityDB::get(int id)
{
auto i = mAbilityInfos.find(id);
if (i != mAbilityInfos.end())
- {
return i->second;
+
+ return nullptr;
+}
+
+AbilityInfo *AbilityDB::find(std::string_view name)
+{
+ for (auto &[_, abilityInfo] : mAbilityInfos)
+ {
+ if (abilityInfo->name == name)
+ return abilityInfo;
}
return nullptr;
}
diff --git a/src/resources/abilitydb.h b/src/resources/abilitydb.h
index c595d016..6b3de5a6 100644
--- a/src/resources/abilitydb.h
+++ b/src/resources/abilitydb.h
@@ -27,15 +27,16 @@ struct AbilityInfo
{
enum TargetMode
{
- TARGET_BEING, // target any being
- TARGET_POINT // target map location
+ TARGET_BEING, // target any being
+ TARGET_POINT, // target map location
+ TARGET_DIRECTION // target a direction
};
int id;
- std::string category; // tab on which the ability is shown
std::string name; // displayed name of ability
std::string icon; // filename of graphical icon
+ std::string useAction; // action when using the ability
- TargetMode targetMode; // target mode
+ TargetMode targetMode;
bool rechargeable; // true when the ability has a recharge bar
int rechargeNeeded; // maximum recharge when applicable
@@ -49,16 +50,20 @@ namespace AbilityDB
{
void init();
- void readAbilityCategoryNode(XML::Node node, const std::string &filename);
+ void readAbilityNode(XML::Node node, const std::string &filename);
void checkStatus();
void unload();
- /** gets the ability info for ID. Will return 0 when it is
+ /** Gets the ability info for ID. Will return nullptr when it is
* a server-specific ability.
*/
AbilityInfo *get(int id);
- AbilityInfo::TargetMode targetModeFromString(const std::string& str);
+ /**
+ * Finds an ability by name. Returns nullptr when the ability could not be
+ * found.
+ */
+ AbilityInfo *find(std::string_view name);
}
diff --git a/src/resources/settingsmanager.cpp b/src/resources/settingsmanager.cpp
index d3c92387..78bf617b 100644
--- a/src/resources/settingsmanager.cpp
+++ b/src/resources/settingsmanager.cpp
@@ -181,7 +181,6 @@ namespace SettingsManager
}
else if (childNode.name() == "attribute")
{
- // map config
Attributes::readAttributeNode(childNode, filename);
}
else if (childNode.name() == "points")
@@ -214,9 +213,9 @@ namespace SettingsManager
{
MonsterDB::readMonsterNode(childNode, filename);
}
- else if (childNode.name() == "ability-category")
+ else if (childNode.name() == "ability")
{
- AbilityDB::readAbilityCategoryNode(childNode, filename);
+ AbilityDB::readAbilityNode(childNode, filename);
}
else if (childNode.name() == "npc")
{