diff options
author | Thorbjørn Lindeijer <bjorn@lindeijer.nl> | 2024-08-19 16:03:09 +0200 |
---|---|---|
committer | Thorbjørn Lindeijer <bjorn@lindeijer.nl> | 2025-03-07 22:27:48 +0100 |
commit | 3556885ee1027b79c8151e3fb2aeb5906483d3d3 (patch) | |
tree | 7d3c714fb1eec3d50a3efe9999da7f07f4cafa02 /src | |
parent | ca0b74e0f52aef36b929a2059fab62c192c620f6 (diff) | |
download | mana-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.cpp | 9 | ||||
-rw-r--r-- | src/being.h | 5 | ||||
-rw-r--r-- | src/net/manaserv/beinghandler.cpp | 19 | ||||
-rw-r--r-- | src/net/manaserv/playerhandler.cpp | 29 | ||||
-rw-r--r-- | src/resources/abilitydb.cpp | 60 | ||||
-rw-r--r-- | src/resources/abilitydb.h | 19 | ||||
-rw-r--r-- | src/resources/settingsmanager.cpp | 5 |
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") { |