Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 23 additions & 62 deletions src/creatures/combat/spells.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,13 @@
#include "lua/scripts/scripts.hpp"
#include "lib/di/container.hpp"

Spells::Spells() = default;
Spells::Spells() {
instants.reserve(1000);
}

Spells::~Spells() = default;

TalkActionResult_t Spells::playerSaySpell(const std::shared_ptr<Player> &player, std::string &words) {
TalkActionResult_t Spells::playerSaySpell(const std::shared_ptr<Player> &player, std::string &words, const std::string &lowerWords) {
auto maxOnline = g_configManager().getNumber(MAX_PLAYERS_PER_ACCOUNT);
const auto &tile = player->getTile();
if (maxOnline > 1 && player->getAccountType() < ACCOUNT_TYPE_GAMEMASTER && tile && !tile->hasFlag(TILESTATE_PROTECTIONZONE)) {
Expand All @@ -61,43 +64,27 @@ TalkActionResult_t Spells::playerSaySpell(const std::shared_ptr<Player> &player,
return TALKACTION_FAILED;
}

// strip trailing spaces
trimString(str_words);

const auto &instantSpell = getInstantSpell(str_words);
if (!instantSpell) {
return TALKACTION_CONTINUE;
}

std::string param;

if (instantSpell->getHasParam()) {
size_t spellLen = instantSpell->getWords().length();
size_t paramLen = str_words.length() - spellLen;
std::string paramText = str_words.substr(spellLen, paramLen);
if (!paramText.empty() && paramText.front() == ' ') {
size_t loc1 = paramText.find('"', 1);
if (loc1 != std::string::npos) {
size_t loc2 = paramText.find('"', loc1 + 1);
if (loc2 == std::string::npos) {
loc2 = paramText.length();
} else if (paramText.find_last_not_of(' ') != loc2) {
return TALKACTION_CONTINUE;
}

param = paramText.substr(loc1 + 1, loc2 - loc1 - 1);
} else {
trimString(paramText);
loc1 = paramText.find(' ', 0);
if (loc1 == std::string::npos) {
param = paramText;
} else {
return TALKACTION_CONTINUE;
}
std::string instantWords = lowerWords;
if (instantWords.size() >= 4 && instantWords.front() != '"') {
size_t qpos = instantWords.find('"');
if (qpos != std::string::npos && qpos > 0 && instantWords[qpos - 1] == ' ') {
param = words.substr(qpos + 1);
instantWords = instantWords.substr(0, qpos);
trim_right(instantWords, ' ');
if (!param.empty() && param.back() == '"') {
param.pop_back();
}
}
}

const auto &instantSpell = getInstantSpell(instantWords);
if (!instantSpell || (!param.empty() && !instantSpell->getHasParam()) || (param.empty() && instantSpell->getHasParam())) {
return TALKACTION_CONTINUE;
}

if (instantSpell->playerCastInstant(player, param)) {
if (!g_configManager().getBoolean(SPELL_NAME_INSTEAD_WORDS)) {
words = instantSpell->getWords();
Expand Down Expand Up @@ -193,7 +180,7 @@ std::list<uint16_t> Spells::getSpellsByVocation(uint16_t vocationId) {
return spellsList;
}

const std::map<std::string, std::shared_ptr<InstantSpell>> &Spells::getInstantSpells() const {
const phmap::flat_hash_map<std::string, std::shared_ptr<InstantSpell>> &Spells::getInstantSpells() const {
return instants;
}

Expand Down Expand Up @@ -232,35 +219,9 @@ std::shared_ptr<RuneSpell> Spells::getRuneSpellByName(const std::string &name) {
}

std::shared_ptr<InstantSpell> Spells::getInstantSpell(const std::string &words) {
std::shared_ptr<InstantSpell> result = nullptr;

for (auto &it : instants) {
const std::string &instantSpellWords = it.second->getWords();
size_t spellLen = instantSpellWords.length();
if (strncasecmp(instantSpellWords.c_str(), words.c_str(), spellLen) == 0) {
if (!result || spellLen > result->getWords().length()) {
result = it.second;
if (words.length() == spellLen) {
break;
}
}
}
}

if (result) {
const std::string &resultWords = result->getWords();
if (words.length() > resultWords.length()) {
if (!result->getHasParam()) {
return nullptr;
}

size_t spellLen = resultWords.length();
size_t paramLen = words.length() - spellLen;
if (paramLen < 2 || words[spellLen] != ' ') {
return nullptr;
}
}
return result;
auto it = instants.find(words);
if (it != instants.end()) {
return it->second;
}
return nullptr;
}
Expand Down
7 changes: 4 additions & 3 deletions src/creatures/combat/spells.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "lua/creature/actions.hpp"
#include "creatures/players/wheel/wheel_definitions.hpp"
#include <parallel_hashmap/phmap.h>

class InstantSpell;
class RuneSpell;
Expand Down Expand Up @@ -53,13 +54,13 @@ class Spells {

std::shared_ptr<InstantSpell> getInstantSpellById(uint16_t spellId);

TalkActionResult_t playerSaySpell(const std::shared_ptr<Player> &player, std::string &words);
TalkActionResult_t playerSaySpell(const std::shared_ptr<Player> &player, std::string &words, const std::string &lowerWords);

static Position getCasterPosition(const std::shared_ptr<Creature> &creature, Direction dir);

std::list<uint16_t> getSpellsByVocation(uint16_t vocationId);

[[nodiscard]] const std::map<std::string, std::shared_ptr<InstantSpell>> &getInstantSpells() const;
[[nodiscard]] const phmap::flat_hash_map<std::string, std::shared_ptr<InstantSpell>> &getInstantSpells() const;

[[nodiscard]] bool hasInstantSpell(const std::string &word) const;

Expand All @@ -71,7 +72,7 @@ class Spells {

private:
std::map<uint16_t, std::shared_ptr<RuneSpell>> runes;
std::map<std::string, std::shared_ptr<InstantSpell>> instants;
phmap::flat_hash_map<std::string, std::shared_ptr<InstantSpell>> instants;

friend class CombatSpell;
};
Expand Down
15 changes: 10 additions & 5 deletions src/game/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6541,7 +6541,7 @@ void Game::playerSay(uint32_t playerId, uint16_t channelId, SpeakClasses type, c
return;
}

if (!text.empty() && text.front() == '/' && player->isAccessPlayer()) {
if (text.front() == '/' && player->isAccessPlayer()) {
return;
}

Expand Down Expand Up @@ -6597,12 +6597,17 @@ bool Game::playerSaySpell(const std::shared_ptr<Player> &player, SpeakClasses ty
}

std::string words = text;
TalkActionResult_t result = g_talkActions().checkPlayerCanSayTalkAction(player, type, words, type == TALKTYPE_SAY ? (unsigned)CHANNEL_DEFAULT : channelId);
if (result == TALKACTION_BREAK) {
return true;
const std::string &lowerWords = asLowerCaseString(words);

TalkActionResult_t result = TALKACTION_FAILED;
if (text.front() == '/' || text.front() == '!') {
result = g_talkActions().checkPlayerCanSayTalkAction(player, type, words, type == TALKTYPE_SAY ? (unsigned)CHANNEL_DEFAULT : channelId);
if (result == TALKACTION_BREAK) {
return true;
}
}

result = g_spells().playerSaySpell(player, words);
result = g_spells().playerSaySpell(player, words, lowerWords);
if (result == TALKACTION_BREAK) {
if (!g_configManager().getBoolean(PUSH_WHEN_ATTACKING)) {
player->cancelPush();
Expand Down
5 changes: 4 additions & 1 deletion src/lua/creature/talkaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
#include "lua/scripts/scripts.hpp"
#include "lib/di/container.hpp"

TalkActions::TalkActions() = default;
TalkActions::TalkActions() {
talkActions.reserve(100);
}

TalkActions::~TalkActions() = default;

TalkActions &TalkActions::getInstance() {
Expand Down
5 changes: 3 additions & 2 deletions src/lua/creature/talkaction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "account/account.hpp"
#include "utils/utils_definitions.hpp"
#include "declarations.hpp"
#include <parallel_hashmap/phmap.h>

class Player;
class LuaScriptInterface;
Expand Down Expand Up @@ -105,12 +106,12 @@ class TalkActions {
bool registerLuaEvent(const TalkAction_ptr &talkAction);
void clear();

const std::map<std::string, std::shared_ptr<TalkAction>> &getTalkActionsMap() const {
const phmap::flat_hash_map<std::string, std::shared_ptr<TalkAction>> &getTalkActionsMap() const {
return talkActions;
};

private:
std::map<std::string, std::shared_ptr<TalkAction>> talkActions;
phmap::flat_hash_map<std::string, std::shared_ptr<TalkAction>> talkActions;
};

constexpr auto g_talkActions = TalkActions::getInstance;
2 changes: 1 addition & 1 deletion src/lua/functions/creatures/combat/spell_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,7 @@ int SpellFunctions::luaSpellWords(lua_State* L) {
sep = Lua::getString(L, 3);
}
spell->setWords(Lua::getString(L, 2));
spell->setSeparator(sep);
spell->setSeparator(sep.empty() ? std::string_view { "\"" } : std::string_view { sep });
Lua::pushBoolean(L, true);
}
} else {
Expand Down
3 changes: 2 additions & 1 deletion src/lua/functions/events/talk_action_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ int TalkActionFunctions::luaTalkActionSeparator(lua_State* L) {
return 1;
}

talkactionSharedPtr->setSeparator(Lua::getString(L, 2));
std::string sep = Lua::getString(L, 2);
talkactionSharedPtr->setSeparator(sep.empty() ? std::string("\"") : sep);
Lua::pushBoolean(L, true);
return 1;
}
Expand Down
5 changes: 3 additions & 2 deletions src/server/network/protocol/protocolgame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2098,8 +2098,9 @@ void ProtocolGame::parseSay(NetworkMessage &msg) {
break;
}

const std::string text = msg.getString();
if (text.length() > 255) {
std::string text = msg.getString();
trimString(text);
if (text.empty() || text.length() > 255) {
return;
}

Expand Down