TalkActionResult_t Spells::playerSaySpell(Player* player, std::string& words) { std::string str_words = words; //strip trailing spaces trimString(str_words); InstantSpell* 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; } } } } if (instantSpell->playerCastInstant(player, param)) { words = instantSpell->getWords(); if (instantSpell->getHasParam() && !param.empty()) { words += " \"" + param + "\""; } return TALKACTION_BREAK; } return TALKACTION_FAILED; }
InstantSpell* Spells::getInstantSpell(const std::string& words) { 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; } return nullptr; }
ReturnValue Spells::onPlayerSay(Player* player, const std::string& words) { std::string reWords = words; trimString(reWords); InstantSpell* instantSpell = getInstantSpell(reWords); if(!instantSpell) return RET_NOTPOSSIBLE; size_t size = instantSpell->getWords().length(); std::string param = reWords.substr(size, reWords.length() - size), reParam = ""; if(instantSpell->getHasParam() && !param.empty() && param[0] == ' ') { size_t quote = param.find('"', 1); if(quote != std::string::npos) { size_t tmp = param.find('"', quote + 1); if(tmp == std::string::npos) tmp = param.length(); reParam = param.substr(quote + 1, tmp - quote - 1); } else if(param.find(' ', 1) == std::string::npos) reParam = param.substr(1, param.length()); trimString(reParam); } Position pos = player->getPosition(); if(!instantSpell->castInstant(player, reParam)) return RET_NEEDEXCHANGE; SpeakClasses type = SPEAK_SAY; if(g_config.getBool(ConfigManager::EMOTE_SPELLS)) type = SPEAK_MONSTER_SAY; if(!g_config.getBool(ConfigManager::SPELL_NAME_INSTEAD_WORDS)) { if(g_config.getBool(ConfigManager::UNIFIED_SPELLS)) { reWords = instantSpell->getWords(); if(instantSpell->getHasParam()) reWords += " \"" + param + "\""; } return g_game.internalCreatureSay(player, type, reWords, player->isGhost()) ? RET_NOERROR : RET_NOTPOSSIBLE; } std::string ret = instantSpell->getName(); if(param.length()) { trimString(param); size_t tmp = 0, rtmp = param.length(); if(param[0] == '"') tmp = 1; if(param[rtmp] == '"') rtmp -= 1; ret += ": " + param.substr(tmp, rtmp); } return g_game.internalCreatureSay(player, type, ret, player->isGhost(), NULL, &pos) ? RET_NOERROR : RET_NOTPOSSIBLE; }