Facebook
From ghosciu, 6 Years ago, written in C++.
Embed
Download Paste or View Raw
Hits: 271
  1. ////////////////////////////////////////////////////////////////////////
  2. // OpenTibia - an opensource roleplaying game
  3. ////////////////////////////////////////////////////////////////////////
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16. ////////////////////////////////////////////////////////////////////////
  17. #include "otpch.h"
  18. #include "const.h"
  19. #include <libxml/xmlmemory.h>
  20. #include <libxml/parser.h>
  21.  
  22. #include "spells.h"
  23. #include "tools.h"
  24.  
  25. #include "house.h"
  26. #include "housetile.h"
  27. #include "combat.h"
  28.  
  29. #include "monsters.h"
  30. #include "configmanager.h"
  31. #include "game.h"
  32.  
  33. extern Game g_game;
  34. extern Spells* g_spells;
  35. extern Monsters g_monsters;
  36. extern ConfigManager g_config;
  37.  
  38. Spells::Spells():
  39. m_interface("Spell Interface")
  40. {
  41.         m_interface.initState();
  42. }
  43.  
  44. ReturnValue Spells::onPlayerSay(Player* player, const std::string& words)
  45. {
  46.         std::string reWords = words;
  47.         trimString(reWords);
  48.  
  49.         InstantSpell* instantSpell = getInstantSpell(reWords);
  50.         if(!instantSpell)
  51.                 return RET_NOTPOSSIBLE;
  52.  
  53.         size_t size = instantSpell->getWords().length();
  54.         std::string param = reWords.substr(size, reWords.length() - size), reParam = "";
  55.         if(instantSpell->getHasParam() && !param.empty() && param[0] == ' ')
  56.         {
  57.                 size_t quote = param.find('"', 1);
  58.                 if(quote != std::string::npos)
  59.                 {
  60.                         size_t tmp = param.find('"', quote + 1);
  61.                         if(tmp == std::string::npos)
  62.                                 tmp = param.length();
  63.  
  64.                         reParam = param.substr(quote + 1, tmp - quote - 1);
  65.                 }
  66.                 else if(param.find(' ', 1) == std::string::npos)
  67.                         reParam = param.substr(1, param.length());
  68.  
  69.                 trimString(reParam);
  70.         }
  71.  
  72.         Position pos = player->getPosition();
  73.         if(!instantSpell->castInstant(player, reParam))
  74.                 return RET_NEEDEXCHANGE;
  75.  
  76.         SpeakClasses type = SPEAK_SAY;
  77.         if(g_config.getBool(ConfigManager::EMOTE_SPELLS))
  78.                 type = SPEAK_MONSTER_SAY;
  79.  
  80.         if(!g_config.getBool(ConfigManager::SPELL_NAME_INSTEAD_WORDS))
  81.                 return g_game.internalCreatureSay(player, type, reWords, player->isGhost()) ?
  82.                         RET_NOERROR : RET_NOTPOSSIBLE;
  83.  
  84.         std::string ret = instantSpell->getName();
  85.         if(param.length())
  86.         {
  87.                 trimString(param);
  88.                 size_t tmp = 0, rtmp = param.length();
  89.                 if(param[0] == '"')
  90.                         tmp = 1;
  91.  
  92.                 if(param[rtmp] == '"')
  93.                         rtmp -= 1;
  94.  
  95.                 ret += ": " + param.substr(tmp, rtmp);
  96.         }
  97.  
  98.         return g_game.internalCreatureSay(player, type, ret, player->isGhost(),
  99.                 NULL, &pos) ? RET_NOERROR : RET_NOTPOSSIBLE;
  100. }
  101.  
  102. void Spells::clear()
  103. {
  104.         for(RunesMap::iterator rit = runes.begin(); rit != runes.end(); ++rit)
  105.                 delete rit->second;
  106.  
  107.         runes.clear();
  108.         for(InstantsMap::iterator it = instants.begin(); it != instants.end(); ++it)
  109.                 delete it->second;
  110.  
  111.         instants.clear();
  112.         m_interface.reInitState();
  113. }
  114.  
  115. Event* Spells::getEvent(const std::string& nodeName)
  116. {
  117.         std::string tmpNodeName = asLowerCaseString(nodeName);
  118.         if(tmpNodeName == "rune")
  119.                 return new RuneSpell(&m_interface);
  120.  
  121.         if(tmpNodeName == "instant")
  122.                 return new InstantSpell(&m_interface);
  123.  
  124.         if(tmpNodeName == "conjure")
  125.                 return new ConjureSpell(&m_interface);
  126.  
  127.         return NULL;
  128. }
  129.  
  130. bool Spells::registerEvent(Event* event, xmlNodePtr, bool override)
  131. {
  132.         if(InstantSpell* instant = dynamic_cast<InstantSpell*>(event))
  133.         {
  134.                 InstantsMap::iterator it = instants.find(instant->getWords());
  135.                 if(it == instants.end())
  136.                 {
  137.                         instants[instant->getWords()] = instant;
  138.                         return true;
  139.                 }
  140.  
  141.                 if(override)
  142.                 {
  143.                         delete it->second;
  144.                         it->second = instant;
  145.                         return true;
  146.                 }
  147.  
  148.                 std::clog << "[Warning - Spells::registerEvent] Duplicate registered instant spell with words: " << instant->getWords() << std::endl;
  149.                 return false;
  150.         }
  151.  
  152.         if(RuneSpell* rune = dynamic_cast<RuneSpell*>(event))
  153.         {
  154.                 RunesMap::iterator it = runes.find(rune->getRuneItemId());
  155.                 if(it == runes.end())
  156.                 {
  157.                         runes[rune->getRuneItemId()] = rune;
  158.                         return true;
  159.                 }
  160.  
  161.                 if(override)
  162.                 {
  163.                         delete it->second;
  164.                         it->second = rune;
  165.                         return true;
  166.                 }
  167.  
  168.                 std::clog << "[Warning - Spells::registerEvent] Duplicate registered rune with id: " << rune->getRuneItemId() << std::endl;
  169.                 return false;
  170.         }
  171.  
  172.         return false;
  173. }
  174.  
  175. Spell* Spells::getSpellByName(const std::string& name)
  176. {
  177.         Spell* spell;
  178.         if((spell = getRuneSpellByName(name)) || (spell = getInstantSpellByName(name)))
  179.                 return spell;
  180.  
  181.         return NULL;
  182. }
  183.  
  184. RuneSpell* Spells::getRuneSpell(uint32_t id)
  185. {
  186.         RunesMap::iterator it = runes.find(id);
  187.         if(it != runes.end())
  188.                 return it->second;
  189.  
  190.         return NULL;
  191. }
  192.  
  193. RuneSpell* Spells::getRuneSpellByName(const std::string& name)
  194. {
  195.         for(RunesMap::iterator it = runes.begin(); it != runes.end(); ++it)
  196.         {
  197.                 if(strcasecmp(it->second->getName().c_str(), name.c_str()) == 0)
  198.                         return it->second;
  199.         }
  200.  
  201.         return NULL;
  202. }
  203.  
  204. InstantSpell* Spells::getInstantSpell(const std::string& words)
  205. {
  206.         InstantSpell* result = NULL;
  207.         for(InstantsMap::iterator it = instants.begin(); it != instants.end(); ++it)
  208.         {
  209.                 InstantSpell* instantSpell = it->second;
  210.                 if(strncasecmp(instantSpell->getWords().c_str(), words.c_str(), instantSpell->getWords().length()) == 0)
  211.                 {
  212.                         if(!result || instantSpell->getWords().length() > result->getWords().length())
  213.                                 result = instantSpell;
  214.                 }
  215.         }
  216.  
  217.         if(result && words.length() > result->getWords().length())
  218.         {
  219.                 std::string param = words.substr(result->getWords().length(), words.length());
  220.                 if(param[0] != ' ' || (param.length() > 1 && (!result->getHasParam() || param.find(' ', 1) != std::string::npos) && param[1] != '"'))
  221.                         return NULL;
  222.         }
  223.  
  224.         return result;
  225. }
  226.  
  227. uint32_t Spells::getInstantSpellCount(const Player* player)
  228. {
  229.         uint32_t count = 0;
  230.         for(InstantsMap::iterator it = instants.begin(); it != instants.end(); ++it)
  231.         {
  232.                 if(it->second->canCast(player))
  233.                         ++count;
  234.         }
  235.  
  236.         return count;
  237. }
  238.  
  239. InstantSpell* Spells::getInstantSpellByIndex(const Player* player, uint32_t index)
  240. {
  241.         uint32_t count = 0;
  242.         for(InstantsMap::iterator it = instants.begin(); it != instants.end(); ++it)
  243.         {
  244.                 InstantSpell* instantSpell = it->second;
  245.                 if(!instantSpell->canCast(player))
  246.                         continue;
  247.  
  248.                 if(count == index)
  249.                         return instantSpell;
  250.  
  251.                 ++count;
  252.         }
  253.  
  254.         return NULL;
  255. }
  256.  
  257. InstantSpell* Spells::getInstantSpellByName(const std::string& name)
  258. {
  259.         std::string tmpName = asLowerCaseString(name);
  260.         for(InstantsMap::iterator it = instants.begin(); it != instants.end(); ++it)
  261.         {
  262.                 if(tmpName == asLowerCaseString(it->second->getName()))
  263.                         return it->second;
  264.         }
  265.  
  266.         return NULL;
  267. }
  268.  
  269. Position Spells::getCasterPosition(Creature* creature, Direction dir)
  270. {
  271.         return getNextPosition(dir, creature->getPosition());
  272. }
  273.  
  274. bool BaseSpell::castSpell(Creature* creature)
  275. {
  276.         if(!creature)
  277.                 return false;
  278.  
  279.         bool success = true;
  280.         CreatureEventList castEvents = creature->getCreatureEvents(CREATURE_EVENT_CAST);
  281.         for(CreatureEventList::iterator it = castEvents.begin(); it != castEvents.end(); ++it)
  282.         {
  283.                 if(!(*it)->executeCast(creature) && success)
  284.                         success = false;
  285.         }
  286.  
  287.         return success;
  288. }
  289.  
  290. bool BaseSpell::castSpell(Creature* creature, Creature* target)
  291. {
  292.         if(!creature || !target)
  293.                 return false;
  294.  
  295.         bool success = true;
  296.         CreatureEventList castEvents = creature->getCreatureEvents(CREATURE_EVENT_CAST);
  297.         for(CreatureEventList::iterator it = castEvents.begin(); it != castEvents.end(); ++it)
  298.         {
  299.                 if(!(*it)->executeCast(creature, target) && success)
  300.                         success = false;
  301.         }
  302.  
  303.         return success;
  304. }
  305.  
  306. CombatSpell::CombatSpell(Combat* _combat, bool _needTarget, bool _needDirection) :
  307.         Event(&g_spells->getInterface())
  308. {
  309.         combat =_combat;
  310.         needTarget = _needTarget;
  311.         needDirection = _needDirection;
  312. }
  313.  
  314. CombatSpell::~CombatSpell()
  315. {
  316.         if(combat)
  317.                 delete combat;
  318. }
  319.  
  320. bool CombatSpell::loadScriptCombat()
  321. {
  322.         if(m_interface->reserveEnv())
  323.         {
  324.                 ScriptEnviroment* env = m_interface->getEnv();
  325.                 combat = env->getCombatObject(env->getLastCombatId());
  326.  
  327.                 env->resetCallback();
  328.                 m_interface->releaseEnv();
  329.         }
  330.  
  331.         return combat != NULL;
  332. }
  333.  
  334. bool CombatSpell::castSpell(Creature* creature)
  335. {
  336.         if(!BaseSpell::castSpell(creature))
  337.                 return false;
  338.  
  339.         if(isScripted())
  340.         {
  341.                 LuaVariant var;
  342.                 var.type = VARIANT_POSITION;
  343.                 if(needDirection)
  344.                         var.pos = Spells::getCasterPosition(creature, creature->getDirection());
  345.                 else
  346.                         var.pos = creature->getPosition();
  347.  
  348.                 return executeCastSpell(creature, var);
  349.         }
  350.  
  351.         Position pos;
  352.         if(needDirection)
  353.                 pos = Spells::getCasterPosition(creature, creature->getDirection());
  354.         else
  355.                 pos = creature->getPosition();
  356.  
  357.         combat->doCombat(creature, pos);
  358.         return true;
  359. }
  360.  
  361. bool CombatSpell::castSpell(Creature* creature, Creature* target)
  362. {
  363.         if(!BaseSpell::castSpell(creature, target))
  364.                 return false;
  365.  
  366.         if(isScripted())
  367.         {
  368.                 LuaVariant var;
  369.                 if(combat->hasArea())
  370.                 {
  371.                         var.type = VARIANT_POSITION;
  372.                         if(needTarget)
  373.                                 var.pos = target->getPosition();
  374.                         else if(needDirection)
  375.                                 var.pos = Spells::getCasterPosition(creature, creature->getDirection());
  376.                         else
  377.                                 var.pos = creature->getPosition();
  378.                 }
  379.                 else
  380.                 {
  381.                         var.type = VARIANT_NUMBER;
  382.                         var.number = target->getID();
  383.                 }
  384.  
  385.                 return executeCastSpell(creature, var);
  386.         }
  387.  
  388.         if(combat->hasArea())
  389.         {
  390.                 if(!needTarget)
  391.                         return castSpell(creature);
  392.  
  393.                 combat->doCombat(creature, target->getPosition());
  394.         }
  395.         else
  396.                 combat->doCombat(creature, target);
  397.  
  398.         return true;
  399. }
  400.  
  401. bool CombatSpell::executeCastSpell(Creature* creature, const LuaVariant& var)
  402. {
  403.         //onCastSpell(cid, var)
  404.         if(m_interface->reserveEnv())
  405.         {
  406.                 ScriptEnviroment* env = m_interface->getEnv();
  407.                 if(m_scripted == EVENT_SCRIPT_BUFFER)
  408.                 {
  409.                         env->setRealPos(creature->getPosition());
  410.                         std::stringstream scriptstream;
  411.  
  412.                         scriptstream << "local cid = " << env->addThing(creature) << std::endl;
  413.                         env->streamVariant(scriptstream, "var", var);
  414.  
  415.                         scriptstream << m_scriptData;
  416.                         bool result = true;
  417.                         if(m_interface->loadBuffer(scriptstream.str()))
  418.                         {
  419.                                 lua_State* L = m_interface->getState();
  420.                                 result = m_interface->getGlobalBool(L, "_result", true);
  421.                         }
  422.  
  423.                         m_interface->releaseEnv();
  424.                         return result;
  425.                 }
  426.                 else
  427.                 {
  428.                         #ifdef __DEBUG_LUASCRIPTS__
  429.                         char desc[60];
  430.                         sprintf(desc, "onCastSpell - %s", creature->getName().c_str());
  431.                         env->setEvent(desc);
  432.                         #endif
  433.  
  434.                         env->setScriptId(m_scriptId, m_interface);
  435.                         env->setRealPos(creature->getPosition());
  436.                         lua_State* L = m_interface->getState();
  437.  
  438.                         m_interface->pushFunction(m_scriptId);
  439.                         lua_pushnumber(L, env->addThing(creature));
  440.                         m_interface->pushVariant(L, var);
  441.  
  442.                         bool result = m_interface->callFunction(2);
  443.                         m_interface->releaseEnv();
  444.                         return result;
  445.                 }
  446.         }
  447.         else
  448.         {
  449.                 std::clog << "[Error - CombatSpell::executeCastSpell] Call stack overflow." << std::endl;
  450.                 return false;
  451.         }
  452. }
  453.  
  454. Spell::Spell()
  455. {
  456.         level = 0;
  457.         magLevel = 0;
  458.         mana = 0;
  459.         manaPercent = 0;
  460.         soul = 0;
  461.         range = -1;
  462.         exhaustion = 1000;
  463.         needTarget = false;
  464.         needWeapon = false;
  465.         selfTarget = false;
  466.         blockingSolid = false;
  467.         blockingCreature = false;
  468.         enabled = true;
  469.         premium = false;
  470.         isAggressive = true;
  471.         learnable = false;
  472.         isCombo1 = false;
  473.         isCombo2 = false;
  474. }
  475.  
  476. bool Spell::configureSpell(xmlNodePtr p)
  477. {
  478.         int32_t intValue;
  479.         std::string strValue;
  480.         if(readXMLString(p, "name", strValue))
  481.         {
  482.                 name = strValue;
  483.                 const char* reservedList[] =
  484.                 {
  485.                         "melee", "physical", "poison", "earth", "fire", "ice", "freeze", "energy", "drown", "death", "curse", "holy",
  486.                         "lifedrain", "manadrain", "healing", "speed", "outfit", "invisible", "drunk", "firefield", "poisonfield",
  487.                         "energyfield", "firecondition", "poisoncondition", "energycondition", "drowncondition", "freezecondition",
  488.                         "cursecondition"
  489.                 };
  490.  
  491.                 for(uint32_t i = 0; i < sizeof(reservedList) / sizeof(const char*); ++i)
  492.                 {
  493.                         if(!strcasecmp(reservedList[i], name.c_str()))
  494.                         {
  495.                                 std::clog << "Error: [Spell::configureSpell] Spell is using a reserved name: " << reservedList[i] << std::endl;
  496.                                 return false;
  497.                         }
  498.                 }
  499.         }
  500.         else
  501.         {
  502.                 std::clog << "Error: [Spell::configureSpell] Spell without name." << std::endl;
  503.                 return false;
  504.         }
  505.  
  506.         if(readXMLInteger(p, "lvl", intValue) || readXMLInteger(p, "level", intValue))
  507.                 level = intValue;
  508.  
  509.         if(readXMLInteger(p, "maglv", intValue) || readXMLInteger(p, "magiclevel", intValue))
  510.                 magLevel = intValue;
  511.  
  512.         if(readXMLInteger(p, "mana", intValue))
  513.                 mana = intValue;
  514.  
  515.         if(readXMLInteger(p, "manapercent", intValue))
  516.                 manaPercent = intValue;
  517.  
  518.         if(readXMLInteger(p, "soul", intValue))
  519.                 soul = intValue;
  520.  
  521.         if(readXMLInteger(p, "exhaustion", intValue))
  522.                 exhaustion = intValue;
  523.  
  524.         if(readXMLString(p, "enabled", strValue))
  525.                 enabled = booleanString(strValue);
  526.  
  527.         if(readXMLString(p, "prem", strValue) || readXMLString(p, "premium", strValue))
  528.                 premium = booleanString(strValue);
  529.  
  530.         if(readXMLString(p, "needtarget", strValue))
  531.                 needTarget = booleanString(strValue);
  532.  
  533.         if(readXMLString(p, "needweapon", strValue))
  534.                 needWeapon = booleanString(strValue);
  535.  
  536.         if(readXMLString(p, "selftarget", strValue))
  537.                 selfTarget = booleanString(strValue);
  538.  
  539.         if(readXMLString(p, "needlearn", strValue))
  540.                 learnable = booleanString(strValue);
  541.  
  542.         if(readXMLInteger(p, "range", intValue))
  543.                 range = intValue;
  544.  
  545.         if(readXMLString(p, "blocking", strValue))
  546.                 blockingCreature = blockingSolid = booleanString(strValue);
  547.  
  548.         if(readXMLString(p, "blocktype", strValue))
  549.         {
  550.                 std::string tmpStrValue = asLowerCaseString(strValue);
  551.                 if(tmpStrValue == "all")
  552.                         blockingCreature = blockingSolid = true;
  553.                 else if(tmpStrValue == "solid")
  554.                         blockingSolid = true;
  555.                 else if(tmpStrValue == "creature")
  556.                         blockingCreature = true;
  557.                 else
  558.                         std::clog << "[Warning - Spell::configureSpell] Blocktype \"" <<strValue << "\" does not exist." << std::endl;
  559.         }
  560.  
  561.         if(readXMLString(p, "aggressive", strValue))
  562.                 isAggressive = booleanString(strValue);
  563.         if(readXMLString(p, "iscombo1", strValue))
  564.                 isCombo1 = booleanString(strValue);
  565.         if(readXMLString(p, "iscombo2", strValue))
  566.                 isCombo2 = booleanString(strValue);
  567.  
  568.         std::string error = "";
  569.         xmlNodePtr vocationNode = p->children;
  570.         while(vocationNode)
  571.         {
  572.                 if(!parseVocationNode(vocationNode, vocSpellMap, vocStringVec, error))
  573.                         std::clog << "[Warning - Spell::configureSpell] " << error << std::endl;
  574.  
  575.                 vocationNode = vocationNode->next;
  576.         }
  577.  
  578.         return true;
  579. }
  580.  
  581. bool Spell::checkSpell(Player* player) const
  582. {
  583.         if(player->hasFlag(PlayerFlag_CannotUseSpells))
  584.                 return false;
  585.  
  586.         if(player->hasFlag(PlayerFlag_IgnoreSpellCheck))
  587.                 return true;
  588.  
  589.         if(!isEnabled())
  590.                 return false;
  591. //GHOST_START
  592.         bool exhausted = false;
  593.         bool exhausted1 = false;
  594.         bool exhausted2 = false;
  595.         if(isAggressive)
  596.         {
  597.                 if(!player->hasFlag(PlayerFlag_IgnoreProtectionZone) && player->getZone() == ZONE_PROTECTION)
  598.                 {
  599.                         player->sendCancelMessage(RET_ACTIONNOTPERMITTEDINPROTECTIONZONE);
  600.                         return false;
  601.                 }
  602.  
  603.                 if(player->hasCondition(CONDITION_EXHAUST, EXHAUST_COMBAT)){
  604.                         std::clog << "player->hasCondition(CONDITION_EXHAUST, EXHAUST_COMBAT\n";
  605.                         exhausted = true;}
  606.  
  607.                        
  608.  
  609.         }
  610.  
  611.  
  612.  
  613.  
  614.         else if(player->hasCondition(CONDITION_EXHAUST, EXHAUST_HEALING)){
  615.                 std::clog << "player->hasConditsadwasdion(CONDITION_EXHAUST, EXHAUST_HEALING\n";
  616.  
  617.                 exhausted = true;}
  618.                
  619.  
  620.         if(player->hasCondition(CONDITION_EXHAUST, EXHAUST_COMBO1)){
  621.                 std::clog << "player->hasConssssdition(CONDITION_EXHAUST, EXHAUST_COMBO1\n";
  622.                 exhausted1 = true;}
  623.  
  624.        
  625.         if(player->hasCondition(CONDITION_EXHAUST, EXHAUST_COMBO2)){
  626.                 std::clog << "player->hasConditsdawion(CONDITION_EXHAUST, EXHAUST_COMBO2\n";
  627.                 exhausted2 = true;}
  628.  
  629.         if(exhausted && !player->hasFlag(PlayerFlag_HasNoExhaustion))
  630.         {
  631.                 player->sendCancelMessage(RET_YOUAREEXHAUSTED);
  632.                 if(isInstant())
  633.                         g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  634.  
  635.  
  636. std::clog << "EXHAUST_RET FALSE PUFF\n";
  637.                 return false;
  638.         }
  639.  
  640.         if(exhausted1 && !player->hasFlag(PlayerFlag_HasNoExhaustion))
  641.         {
  642.                 player->sendCancelMessage(RET_YOUAREEXHAUSTED);
  643.                 if(isInstant())
  644.                         g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  645.  
  646.  
  647. std::clog << "EXHAUST_RET FALSE PUFF exh1\n";
  648.                 return false;
  649.         }
  650.  
  651.         if(exhausted2 && !player->hasFlag(PlayerFlag_HasNoExhaustion))
  652.         {
  653.                 player->sendCancelMessage(RET_YOUAREEXHAUSTED);
  654.                 if(isInstant())
  655.                         g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  656.  
  657.  
  658. std::clog << "EXHAUST_RET FALSE PUFF exh2\n";
  659.                 return false;   //GHOST_KONIEC
  660.         }
  661.  
  662.         if(isPremium() && !player->isPremium())
  663.         {
  664.                 player->sendCancelMessage(RET_YOUNEEDPREMIUMACCOUNT);
  665.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  666.                 return false;
  667.         }
  668.  
  669.         if((int32_t)player->getLevel() < level)
  670.         {
  671.                 player->sendCancelMessage(RET_NOTENOUGHLEVEL);
  672.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  673.                 return false;
  674.         }
  675.  
  676.         if((int32_t)player->getMagicLevel() < magLevel)
  677.         {
  678.                 player->sendCancelMessage(RET_NOTENOUGHMAGICLEVEL);
  679.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  680.                 return false;
  681.         }
  682.  
  683.         if(player->getMana() < getManaCost(player) && !player->hasFlag(PlayerFlag_HasInfiniteMana))
  684.         {
  685.                 player->sendCancelMessage(RET_NOTENOUGHMANA);
  686.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  687.                 return false;
  688.         }
  689.  
  690.         if(player->getSoul() < soul && !player->hasFlag(PlayerFlag_HasInfiniteSoul))
  691.         {
  692.                 player->sendCancelMessage(RET_NOTENOUGHSOUL);
  693.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  694.                 return false;
  695.         }
  696.  
  697.         if(isInstant() && isLearnable() && !player->hasLearnedInstantSpell(getName()))
  698.         {
  699.                 player->sendCancelMessage(RET_YOUNEEDTOLEARNTHISSPELL);
  700.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  701.                 return false;
  702.         }
  703.  
  704.         if(!vocSpellMap.empty())
  705.         {
  706.                 if(vocSpellMap.find(player->getVocationId()) == vocSpellMap.end())
  707.                 {
  708.                         player->sendCancelMessage(RET_YOURVOCATIONCANNOTUSETHISSPELL);
  709.                         g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  710.                         return false;
  711.                 }
  712.         }
  713.  
  714.         if(needWeapon)
  715.         {
  716.                 switch(player->getWeaponType())
  717.                 {
  718.                         case WEAPON_SWORD:
  719.                         case WEAPON_CLUB:
  720.                         case WEAPON_AXE:
  721.                         case WEAPON_FIST:
  722.                                 break;
  723.  
  724.                         default:
  725.                         {
  726.                                 player->sendCancelMessage(RET_YOUNEEDAWEAPONTOUSETHISSPELL);
  727.                                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  728.                                 return false;
  729.                         }
  730.                 }
  731.         }
  732.  
  733.         return true;
  734. }
  735.  
  736. bool Spell::checkInstantSpell(Player* player, Creature* creature)
  737. {
  738.         if(!checkSpell(player))
  739.                 return false;
  740.  
  741.         const Position& toPos = creature->getPosition();
  742.         const Position& playerPos = player->getPosition();
  743.         if(playerPos.z > toPos.z)
  744.         {
  745.                 player->sendCancelMessage(RET_FIRSTGOUPSTAIRS);
  746.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  747.                 return false;
  748.         }
  749.  
  750.         if(playerPos.z < toPos.z)
  751.         {
  752.                 player->sendCancelMessage(RET_FIRSTGODOWNSTAIRS);
  753.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  754.                 return false;
  755.         }
  756.  
  757.         Tile* tile = g_game.getTile(toPos);
  758.         if(!tile)
  759.         {
  760.                 tile = new StaticTile(toPos.x, toPos.y, toPos.z);
  761.                 g_game.setTile(tile);
  762.         }
  763.  
  764.         ReturnValue ret;
  765.         if((ret = Combat::canDoCombat(player, tile, isAggressive)) != RET_NOERROR)
  766.         {
  767.                 player->sendCancelMessage(ret);
  768.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  769.                 return false;
  770.         }
  771.  
  772.         if(blockingCreature && creature)
  773.         {
  774.                 player->sendCancelMessage(RET_NOTENOUGHROOM);
  775.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  776.                 return false;
  777.         }
  778.  
  779.         if(blockingSolid && tile->hasProperty(BLOCKSOLID))
  780.         {
  781.                 player->sendCancelMessage(RET_NOTENOUGHROOM);
  782.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  783.                 return false;
  784.         }
  785.  
  786.         if(!needTarget)
  787.         {
  788.                 if(!isAggressive || player->getSkull() != SKULL_BLACK)
  789.                         return true;
  790.  
  791.                 player->sendCancelMessage(RET_YOUMAYNOTCASTAREAONBLACKSKULL);
  792.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  793.                 return false;
  794.         }
  795.  
  796.         if(!creature)
  797.         {
  798.                 player->sendCancelMessage(RET_NOTPOSSIBLE);
  799.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  800.                 return false;
  801.         }
  802.  
  803.         Player* targetPlayer = creature->getPlayer();
  804.         if(!isAggressive || !targetPlayer || Combat::isInPvpZone(player, targetPlayer)
  805.                 || player->getSkullType(targetPlayer) != SKULL_NONE)
  806.                 return true;
  807.  
  808.         if(player->getSecureMode() == SECUREMODE_ON)
  809.         {
  810.                 player->sendCancelMessage(RET_TURNSECUREMODETOATTACKUNMARKEDPLAYERS);
  811.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  812.                 return false;
  813.         }
  814.  
  815.         if(player->getSkull() == SKULL_BLACK)
  816.         {
  817.                 player->sendCancelMessage(RET_YOUMAYNOTATTACKTHISPLAYER);
  818.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  819.                 return false;
  820.         }
  821.  
  822.         return true;
  823. }
  824.  
  825. bool Spell::checkInstantSpell(Player* player, const Position& toPos)
  826. {
  827.         if(!checkSpell(player))
  828.                 return false;
  829.  
  830.         if(toPos.x == 0xFFFF)
  831.                 return true;
  832.  
  833.         const Position& playerPos = player->getPosition();
  834.         if(playerPos.z > toPos.z)
  835.         {
  836.                 player->sendCancelMessage(RET_FIRSTGOUPSTAIRS);
  837.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  838.                 return false;
  839.         }
  840.  
  841.         if(playerPos.z < toPos.z)
  842.         {
  843.                 player->sendCancelMessage(RET_FIRSTGODOWNSTAIRS);
  844.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  845.                 return false;
  846.         }
  847.  
  848.         Tile* tile = g_game.getTile(toPos);
  849.         if(!tile)
  850.         {
  851.                 tile = new StaticTile(toPos.x, toPos.y, toPos.z);
  852.                 g_game.setTile(tile);
  853.         }
  854.  
  855.         ReturnValue ret;
  856.         if((ret = Combat::canDoCombat(player, tile, isAggressive)) != RET_NOERROR)
  857.         {
  858.                 player->sendCancelMessage(ret);
  859.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  860.                 return false;
  861.         }
  862.  
  863.         if(blockingCreature && tile->getTopVisibleCreature(player))
  864.         {
  865.                 player->sendCancelMessage(RET_NOTENOUGHROOM);
  866.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  867.                 return false;
  868.         }
  869.  
  870.         if(blockingSolid && tile->hasProperty(BLOCKSOLID))
  871.         {
  872.                 player->sendCancelMessage(RET_NOTENOUGHROOM);
  873.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  874.                 return false;
  875.         }
  876.  
  877.         if(player->getSkull() == SKULL_BLACK && isAggressive && range == -1) //-1 is (usually?) an area spell
  878.         {
  879.                 player->sendCancelMessage(RET_YOUMAYNOTCASTAREAONBLACKSKULL);
  880.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  881.                 return false;
  882.         }
  883.  
  884.         return true;
  885. }
  886.  
  887. bool Spell::checkRuneSpell(Player* player, const Position& toPos)
  888. {
  889.         if(!checkSpell(player))
  890.                 return false;
  891.  
  892.         if(toPos.x == 0xFFFF)
  893.                 return true;
  894.  
  895.         const Position& playerPos = player->getPosition();
  896.         if(playerPos.z > toPos.z)
  897.         {
  898.                 player->sendCancelMessage(RET_FIRSTGOUPSTAIRS);
  899.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  900.                 return false;
  901.         }
  902.  
  903.         if(playerPos.z < toPos.z)
  904.         {
  905.                 player->sendCancelMessage(RET_FIRSTGODOWNSTAIRS);
  906.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  907.                 return false;
  908.         }
  909.  
  910.         Tile* tile = g_game.getTile(toPos);
  911.         if(!tile)
  912.         {
  913.                 player->sendCancelMessage(RET_NOTPOSSIBLE);
  914.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  915.                 return false;
  916.         }
  917.  
  918.         if(range != -1 && !g_game.canThrowObjectTo(playerPos, toPos, true, range, range))
  919.         {
  920.                 player->sendCancelMessage(RET_DESTINATIONOUTOFREACH);
  921.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  922.                 return false;
  923.         }
  924.  
  925.         ReturnValue ret;
  926.         if((ret = Combat::canDoCombat(player, tile, isAggressive)) != RET_NOERROR)
  927.         {
  928.                 player->sendCancelMessage(ret);
  929.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  930.                 return false;
  931.         }
  932.  
  933.         Creature* targetCreature = tile->getTopVisibleCreature(player);
  934.         if(blockingCreature && targetCreature)
  935.         {
  936.                 player->sendCancelMessage(RET_NOTENOUGHROOM);
  937.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  938.                 return false;
  939.         }
  940.  
  941.         if(blockingSolid && tile->hasProperty(BLOCKSOLID))
  942.         {
  943.                 player->sendCancelMessage(RET_NOTENOUGHROOM);
  944.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  945.                 return false;
  946.         }
  947.  
  948.         if(!needTarget)
  949.         {
  950.                 if(!isAggressive || player->getSkull() != SKULL_BLACK)
  951.                         return true;
  952.  
  953.                 player->sendCancelMessage(RET_YOUMAYNOTCASTAREAONBLACKSKULL);
  954.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  955.                 return false;
  956.         }
  957.  
  958.         if(!targetCreature)
  959.         {
  960.                 player->sendCancelMessage(RET_CANONLYUSETHISRUNEONCREATURES);
  961.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  962.                 return false;
  963.         }
  964.  
  965.         Player* targetPlayer = targetCreature->getPlayer();
  966.         if(!isAggressive || !targetPlayer || Combat::isInPvpZone(player, targetPlayer)
  967.                 || player->getSkullType(targetPlayer) != SKULL_NONE)
  968.                 return true;
  969.  
  970.         if(player->getSecureMode() == SECUREMODE_ON)
  971.         {
  972.                 player->sendCancelMessage(RET_TURNSECUREMODETOATTACKUNMARKEDPLAYERS);
  973.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  974.                 return false;
  975.         }
  976.  
  977.         if(player->getSkull() == SKULL_BLACK)
  978.         {
  979.                 player->sendCancelMessage(RET_YOUMAYNOTATTACKTHISPLAYER);
  980.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  981.                 return false;
  982.         }
  983.  
  984.         return true;
  985. }
  986.  
  987. void Spell::postSpell(Player* player, bool finishedCast /*= true*/, bool payCost /*= true*/) const
  988. {
  989.         if(finishedCast)
  990.         {
  991.                 if(!player->hasFlag(PlayerFlag_HasNoExhaustion) && exhaustion > 0)
  992.                         if(isAggressive && !isCombo1 && !isCombo2){
  993.                                 player->addExhaust(exhaustion, EXHAUST_COMBAT);
  994.                                 std::clog << "COMBAT\n";}
  995.                         if(!isAggressive && !isCombo1 && !isCombo2){
  996.                                 player->addExhaust(exhaustion, EXHAUST_HEALING);
  997. std::clog << "Healing \n";}
  998.                         if(isCombo1){
  999.                                 player->addExhaust(exhaustion, EXHAUST_COMBO1);
  1000. std::clog << "combo1 \n";}
  1001.                         if(isCombo2){
  1002.                                 player->addExhaust(exhaustion, EXHAUST_COMBO2);
  1003. std::clog << "combo2\n";}
  1004.  
  1005.                 if(isAggressive && !player->hasFlag(PlayerFlag_NotGainInFight))
  1006.                         player->addInFightTicks(false);
  1007.         }
  1008.  
  1009.         if(payCost)
  1010.                 postSpell(player, (uint32_t)getManaCost(player), (uint32_t)getSoulCost());
  1011. }
  1012.  
  1013. void Spell::postSpell(Player* player, uint32_t manaCost, uint32_t soulCost) const
  1014. {
  1015.         if(manaCost > 0)
  1016.         {
  1017.                 player->changeMana(-(int32_t)manaCost);
  1018.                 if(!player->hasFlag(PlayerFlag_NotGainMana) && (player->getZone() != ZONE_HARDCORE
  1019.                         || g_config.getBool(ConfigManager::PVPZONE_ADDMANASPENT)))
  1020.                         player->addManaSpent(manaCost);
  1021.         }
  1022.  
  1023.         if(soulCost > 0)
  1024.                 player->changeSoul(-(int32_t)soulCost);
  1025. }
  1026.  
  1027. int32_t Spell::getManaCost(const Player* player) const
  1028. {
  1029.         if(player && manaPercent)
  1030.                 return (int32_t)std::floor(double(player->getMaxMana() * manaPercent) / 100);
  1031.  
  1032.         return mana;
  1033. }
  1034.  
  1035. ReturnValue Spell::CreateIllusion(Creature* creature, const Outfit_t& outfit, int32_t time)
  1036. {
  1037.         ConditionOutfit* outfitCondition = new ConditionOutfit(CONDITIONID_COMBAT, CONDITION_OUTFIT, time, false, 0);
  1038.         if(!outfitCondition)
  1039.                 return RET_NOTPOSSIBLE;
  1040.  
  1041.         outfitCondition->addOutfit(outfit);
  1042.         creature->addCondition(outfitCondition);
  1043.         return RET_NOERROR;
  1044. }
  1045.  
  1046. ReturnValue Spell::CreateIllusion(Creature* creature, const std::string& name, int32_t time)
  1047. {
  1048.         uint32_t mId = g_monsters.getIdByName(name);
  1049.         if(!mId)
  1050.                 return RET_CREATUREDOESNOTEXIST;
  1051.  
  1052.         const MonsterType* mType = g_monsters.getMonsterType(mId);
  1053.         if(!mType)
  1054.                 return RET_CREATUREDOESNOTEXIST;
  1055.  
  1056.         Player* player = creature->getPlayer();
  1057.         if(player && !player->hasFlag(PlayerFlag_CanIllusionAll) && !mType->isIllusionable)
  1058.                 return RET_NOTPOSSIBLE;
  1059.  
  1060.         return CreateIllusion(creature, mType->outfit, time);
  1061. }
  1062.  
  1063. ReturnValue Spell::CreateIllusion(Creature* creature, uint32_t itemId, int32_t time)
  1064. {
  1065.         const ItemType& it = Item::items[itemId];
  1066.         if(!it.id)
  1067.                 return RET_NOTPOSSIBLE;
  1068.  
  1069.         Outfit_t outfit;
  1070.         outfit.lookTypeEx = itemId;
  1071.         return CreateIllusion(creature, outfit, time);
  1072. }
  1073.  
  1074. InstantSpell::InstantSpell(LuaInterface* _interface) : TalkAction(_interface)
  1075. {
  1076.         needDirection = false;
  1077.         hasParam = false;
  1078.         checkLineOfSight = true;
  1079.         casterTargetOrDirection = false;
  1080.         limitRange = 0;
  1081.         function = NULL;
  1082. }
  1083.  
  1084. bool InstantSpell::configureEvent(xmlNodePtr p)
  1085. {
  1086.         if(!Spell::configureSpell(p))
  1087.                 return false;
  1088.  
  1089.         if(!TalkAction::configureEvent(p))
  1090.                 return false;
  1091.  
  1092.         std::string strValue;
  1093.         if(readXMLString(p, "param", strValue) || readXMLString(p, "params", strValue))
  1094.                 hasParam = booleanString(strValue);
  1095.  
  1096.         if(readXMLString(p, "direction", strValue))
  1097.                 needDirection = booleanString(strValue);
  1098.  
  1099.         if(readXMLString(p, "casterTargetOrDirection", strValue))
  1100.                 casterTargetOrDirection = booleanString(strValue);
  1101.  
  1102.         if(readXMLString(p, "blockwalls", strValue))
  1103.                 checkLineOfSight = booleanString(strValue);
  1104.  
  1105.         int32_t intValue;
  1106.         if(readXMLInteger(p, "limitRange", intValue))
  1107.                 limitRange = intValue;
  1108.  
  1109.         return true;
  1110. }
  1111.  
  1112. bool InstantSpell::loadFunction(const std::string& functionName)
  1113. {
  1114.         std::string tmpFunctionName = asLowerCaseString(functionName);
  1115.         if(tmpFunctionName == "summonmonster")
  1116.                 function = SummonMonster;
  1117.         else if(tmpFunctionName == "searchplayer")
  1118.         {
  1119.                 isAggressive = false;
  1120.                 function = SearchPlayer;
  1121.         }
  1122.         else if(tmpFunctionName == "levitate")
  1123.         {
  1124.                 isAggressive = false;
  1125.                 function = Levitate;
  1126.         }
  1127.         else if(tmpFunctionName == "illusion")
  1128.         {
  1129.                 isAggressive = false;
  1130.                 function = Illusion;
  1131.         }
  1132.         else
  1133.         {
  1134.                 std::clog << "[Warning - InstantSpell::loadFunction] Function \"" << functionName << "\" does not exist." << std::endl;
  1135.                 return false;
  1136.         }
  1137.  
  1138.         m_scripted = EVENT_SCRIPT_FALSE;
  1139.         return true;
  1140. }
  1141.  
  1142. bool InstantSpell::castInstant(Player* player, const std::string& param)
  1143. {
  1144.         LuaVariant var;
  1145.         if(selfTarget)
  1146.         {
  1147.                 var.type = VARIANT_NUMBER;
  1148.                 var.number = player->getID();
  1149.                 if(!checkInstantSpell(player, player))
  1150.                         return false;
  1151.         }
  1152.         else if(needTarget || casterTargetOrDirection)
  1153.         {
  1154.                 Creature* target = NULL;
  1155.                 if(hasParam)
  1156.                 {
  1157.                         Player* targetPlayer = NULL;
  1158.                         ReturnValue ret = g_game.getPlayerByNameWildcard(param, targetPlayer);
  1159.  
  1160.                         target = targetPlayer;
  1161.                         if(limitRange && target && !Position::areInRange(Position(limitRange,
  1162.                                 limitRange, 0), target->getPosition(), player->getPosition()))
  1163.                                 target = NULL;
  1164.  
  1165.                         if((!target || target->getHealth() <= 0) && !casterTargetOrDirection)
  1166.                         {
  1167.                                 player->sendCancelMessage(ret);
  1168.                                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1169.                                 return false;
  1170.                         }
  1171.                 }
  1172.                 else
  1173.                 {
  1174.                         target = player->getAttackedCreature();
  1175.                         if(limitRange && target && !Position::areInRange(Position(limitRange,
  1176.                                 limitRange, 0), target->getPosition(), player->getPosition()))
  1177.                                 target = NULL;
  1178.  
  1179.                         if((!target || target->getHealth() <= 0) && !casterTargetOrDirection)
  1180.                         {
  1181.                                 player->sendCancelMessage(RET_YOUCANONLYUSEITONCREATURES);
  1182.                                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1183.                                 return false;
  1184.                         }
  1185.                 }
  1186.  
  1187.                 if(target)
  1188.                 {
  1189.                         bool canSee = player->canSeeCreature(target);
  1190.                         if(!canSee || !canThrowSpell(player, target))
  1191.                         {
  1192.                                 player->sendCancelMessage(canSee ? RET_CREATUREISNOTREACHABLE : RET_PLAYERWITHTHISNAMEISNOTONLINE);
  1193.                                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1194.                                 return false;
  1195.                         }
  1196.  
  1197.                         var.type = VARIANT_NUMBER;
  1198.                         var.number = target->getID();
  1199.                         if(!checkInstantSpell(player, target))
  1200.                                 return false;
  1201.                 }
  1202.                 else
  1203.                 {
  1204.                         var.type = VARIANT_POSITION;
  1205.                         var.pos = Spells::getCasterPosition(player, player->getDirection());
  1206.                         if(!checkInstantSpell(player, var.pos))
  1207.                                 return false;
  1208.                 }
  1209.         }
  1210.         else if(hasParam)
  1211.         {
  1212.                 var.type = VARIANT_STRING;
  1213.                 var.text = param;
  1214.                 if(!checkSpell(player))
  1215.                         return false;
  1216.         }
  1217.         else
  1218.         {
  1219.                 var.type = VARIANT_POSITION;
  1220.                 if(needDirection)
  1221.                         var.pos = Spells::getCasterPosition(player, player->getDirection());
  1222.                 else
  1223.                         var.pos = player->getPosition();
  1224.  
  1225.                 if(!checkInstantSpell(player, var.pos))
  1226.                         return false;
  1227.         }
  1228.  
  1229.         if(!internalCastSpell(player, var))
  1230.                 return false;
  1231.  
  1232.         Spell::postSpell(player);
  1233.         return true;
  1234. }
  1235.  
  1236. bool InstantSpell::canThrowSpell(const Creature* creature, const Creature* target) const
  1237. {
  1238.         const Position& fromPos = creature->getPosition();
  1239.         const Position& toPos = target->getPosition();
  1240.         return (!(fromPos.z != toPos.z || (range == -1 && !g_game.canThrowObjectTo(fromPos, toPos, checkLineOfSight))
  1241.                 || (range != -1 && !g_game.canThrowObjectTo(fromPos, toPos, checkLineOfSight, range, range))));
  1242. }
  1243.  
  1244. bool InstantSpell::castSpell(Creature* creature)
  1245. {
  1246.         if(!BaseSpell::castSpell(creature))
  1247.                 return false;
  1248.  
  1249.         LuaVariant var;
  1250.         if(casterTargetOrDirection)
  1251.         {
  1252.                 Creature* target = creature->getAttackedCreature();
  1253.                 if(target && target->getHealth() > 0)
  1254.                 {
  1255.                         if(!creature->canSeeCreature(target) || !canThrowSpell(creature, target))
  1256.                                 return false;
  1257.  
  1258.                         var.type = VARIANT_NUMBER;
  1259.                         var.number = target->getID();
  1260.                         return internalCastSpell(creature, var);
  1261.                 }
  1262.  
  1263.                 return false;
  1264.         }
  1265.  
  1266.         if(needDirection)
  1267.         {
  1268.                 var.type = VARIANT_POSITION;
  1269.                 var.pos = Spells::getCasterPosition(creature, creature->getDirection());
  1270.         }
  1271.         else
  1272.         {
  1273.                 var.type = VARIANT_POSITION;
  1274.                 var.pos = creature->getPosition();
  1275.         }
  1276.  
  1277.         return internalCastSpell(creature, var);
  1278. }
  1279.  
  1280. bool InstantSpell::castSpell(Creature* creature, Creature* target)
  1281. {
  1282.         if(!BaseSpell::castSpell(creature, target))
  1283.                 return false;
  1284.  
  1285.         if(!needTarget)
  1286.                 return castSpell(creature);
  1287.  
  1288.         LuaVariant var;
  1289.         var.type = VARIANT_NUMBER;
  1290.         var.number = target->getID();
  1291.         return internalCastSpell(creature, var);
  1292. }
  1293.  
  1294. bool InstantSpell::internalCastSpell(Creature* creature, const LuaVariant& var)
  1295. {
  1296.         if(isScripted())
  1297.                 return executeCastSpell(creature, var);
  1298.  
  1299.         return function ? function(this, creature, var.text) : false;
  1300. }
  1301.  
  1302. bool InstantSpell::executeCastSpell(Creature* creature, const LuaVariant& var)
  1303. {
  1304.         //onCastSpell(cid, var)
  1305.         if(m_interface->reserveEnv())
  1306.         {
  1307.                 ScriptEnviroment* env = m_interface->getEnv();
  1308.                 if(m_scripted == EVENT_SCRIPT_BUFFER)
  1309.                 {
  1310.                         env->setRealPos(creature->getPosition());
  1311.                         std::stringstream scriptstream;
  1312.  
  1313.                         scriptstream << "local cid = " << env->addThing(creature) << std::endl;
  1314.                         env->streamVariant(scriptstream, "var", var);
  1315.  
  1316.                         scriptstream << m_scriptData;
  1317.                         bool result = true;
  1318.                         if(m_interface->loadBuffer(scriptstream.str()))
  1319.                         {
  1320.                                 lua_State* L = m_interface->getState();
  1321.                                 result = m_interface->getGlobalBool(L, "_result", true);
  1322.                         }
  1323.  
  1324.                         m_interface->releaseEnv();
  1325.                         return result;
  1326.                 }
  1327.                 else
  1328.                 {
  1329.                         #ifdef __DEBUG_LUASCRIPTS__
  1330.                         char desc[60];
  1331.                         sprintf(desc, "onCastSpell - %s", creature->getName().c_str());
  1332.                         env->setEvent(desc);
  1333.                         #endif
  1334.  
  1335.                         env->setScriptId(m_scriptId, m_interface);
  1336.                         env->setRealPos(creature->getPosition());
  1337.                         lua_State* L = m_interface->getState();
  1338.  
  1339.                         m_interface->pushFunction(m_scriptId);
  1340.                         lua_pushnumber(L, env->addThing(creature));
  1341.                         m_interface->pushVariant(L, var);
  1342.  
  1343.                         bool result = m_interface->callFunction(2);
  1344.                         m_interface->releaseEnv();
  1345.                         return result;
  1346.                 }
  1347.         }
  1348.         else
  1349.         {
  1350.                 std::clog << "[Error - InstantSpell::executeCastSpell] Call stack overflow." << std::endl;
  1351.                 return false;
  1352.         }
  1353. }
  1354.  
  1355. bool InstantSpell::SearchPlayer(const InstantSpell*, Creature* creature, const std::string& param)
  1356. {
  1357.         Player* player = creature->getPlayer();
  1358.         if(!player || player->isRemoved())
  1359.                 return false;
  1360.  
  1361.         Player* targetPlayer = NULL;
  1362.         ReturnValue ret = g_game.getPlayerByNameWildcard(param, targetPlayer);
  1363.         if(ret != RET_NOERROR || !targetPlayer || targetPlayer->isRemoved())
  1364.         {
  1365.                 player->sendCancelMessage(ret);
  1366.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1367.                 return false;
  1368.         }
  1369.  
  1370.         if(targetPlayer->hasCustomFlag(PlayerCustomFlag_NotSearchable) && !player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges))
  1371.         {
  1372.                 player->sendCancelMessage(RET_PLAYERWITHTHISNAMEISNOTONLINE);
  1373.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1374.                 return false;
  1375.         }
  1376.  
  1377.         std::stringstream ss;
  1378.         ss << targetPlayer->getName() << " " << g_game.getSearchString(player->getPosition(), targetPlayer->getPosition(), true, true) << ".";
  1379.         player->sendTextMessage(MSG_INFO_DESCR, ss.str().c_str());
  1380.  
  1381.         g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_WRAPS_BLUE);
  1382.         return true;
  1383. }
  1384.  
  1385. bool InstantSpell::SummonMonster(const InstantSpell* spell, Creature* creature, const std::string& param)
  1386. {
  1387.         Player* player = creature->getPlayer();
  1388.         if(!player)
  1389.                 return false;
  1390.  
  1391.         MonsterType* mType = g_monsters.getMonsterType(param);
  1392.         if(!mType)
  1393.         {
  1394.                 player->sendCancelMessage(RET_NOTPOSSIBLE);
  1395.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1396.                 return false;
  1397.         }
  1398.  
  1399.         int32_t manaCost = (int32_t)(mType->manaCost * g_config.getDouble(ConfigManager::RATE_MONSTER_MANA));
  1400.         if(!player->hasFlag(PlayerFlag_CanSummonAll))
  1401.         {
  1402.                 if(player->getSkull() == SKULL_BLACK)
  1403.                 {
  1404.                         player->sendCancelMessage(RET_NOTPOSSIBLE);
  1405.                         g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1406.                         return false;
  1407.                 }
  1408.  
  1409.                 if(!mType->isSummonable)
  1410.                 {
  1411.                         player->sendCancelMessage(RET_NOTPOSSIBLE);
  1412.                         g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1413.                         return false;
  1414.                 }
  1415.  
  1416.                 if(player->getMana() < manaCost)
  1417.                 {
  1418.                         player->sendCancelMessage(RET_NOTENOUGHMANA);
  1419.                         g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1420.                         return false;
  1421.                 }
  1422.  
  1423.                 if((int32_t)player->getSummonCount() >= g_config.getNumber(ConfigManager::MAX_PLAYER_SUMMONS))
  1424.                 {
  1425.                         player->sendCancel("You cannot summon more creatures.");
  1426.                         g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1427.                         return false;
  1428.                 }
  1429.         }
  1430.  
  1431.         ReturnValue ret = g_game.placeSummon(creature, param);
  1432.         if(ret == RET_NOERROR)
  1433.         {
  1434.                 spell->postSpell(player, (uint32_t)manaCost, (uint32_t)spell->getSoulCost());
  1435.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_WRAPS_BLUE);
  1436.                 return true;
  1437.         }
  1438.  
  1439.         player->sendCancelMessage(ret);
  1440.         g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1441.         return false;
  1442. }
  1443.  
  1444. bool InstantSpell::Levitate(const InstantSpell*, Creature* creature, const std::string& param)
  1445. {
  1446.         Player* player = creature->getPlayer();
  1447.         if(!player)
  1448.                 return false;
  1449.  
  1450.         uint16_t floor = 7;
  1451.         ReturnValue ret = RET_NOERROR;
  1452.         const Position& position = creature->getPosition();
  1453.         Position destination = Spells::getCasterPosition(creature, creature->getDirection());
  1454.  
  1455.         std::string tmpParam = asLowerCaseString(param);
  1456.         if(tmpParam == "up")
  1457.                 floor = 8;
  1458.         else if(tmpParam != "down")
  1459.                 ret = RET_NOTPOSSIBLE;
  1460.  
  1461.         if(ret == RET_NOERROR)
  1462.         {
  1463.                 ret = RET_NOTPOSSIBLE;
  1464.                 if(position.z != floor)
  1465.                 {
  1466.                         Tile* tmpTile = NULL;
  1467.                         if(floor != 7)
  1468.                         {
  1469.                                 tmpTile = g_game.getTile(position.x, position.y, position.z - 1);
  1470.                                 destination.z--;
  1471.                         }
  1472.                         else
  1473.                         {
  1474.                                 tmpTile = g_game.getTile(destination);
  1475.                                 destination.z++;
  1476.                         }
  1477.  
  1478.                         if(!tmpTile || (!tmpTile->ground && !tmpTile->hasProperty(IMMOVABLEBLOCKSOLID)))
  1479.                         {
  1480.                                 Tile* tile = player->getTile();
  1481.                                 tmpTile = g_game.getTile(destination);
  1482.                                 if(tile && tmpTile && tmpTile->ground && !tmpTile->hasProperty(IMMOVABLEBLOCKSOLID) &&
  1483.                                         !tmpTile->floorChange() && tile->hasFlag(TILESTATE_HOUSE) == tmpTile->hasFlag(TILESTATE_HOUSE)
  1484.                                         && tile->hasFlag(TILESTATE_PROTECTIONZONE) == tmpTile->hasFlag(TILESTATE_PROTECTIONZONE))
  1485.                                         ret = g_game.internalMoveCreature(NULL, player, tile, tmpTile, FLAG_IGNOREBLOCKITEM | FLAG_IGNOREBLOCKCREATURE);
  1486.                         }
  1487.                 }
  1488.         }
  1489.  
  1490.         if(ret == RET_NOERROR)
  1491.         {
  1492.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_TELEPORT, player->isGhost());
  1493.                 return true;
  1494.         }
  1495.  
  1496.         player->sendCancelMessage(ret);
  1497.         g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF, player->isGhost());
  1498.         return false;
  1499. }
  1500.  
  1501. bool InstantSpell::Illusion(const InstantSpell*, Creature* creature, const std::string& param)
  1502. {
  1503.         Player* player = creature->getPlayer();
  1504.         if(!player)
  1505.                 return false;
  1506.  
  1507.         ReturnValue ret = CreateIllusion(creature, param, 60000);
  1508.         if(ret == RET_NOERROR)
  1509.         {
  1510.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_WRAPS_RED);
  1511.                 return true;
  1512.         }
  1513.  
  1514.         player->sendCancelMessage(ret);
  1515.         g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1516.         return (ret == RET_NOERROR);
  1517. }
  1518.  
  1519. bool InstantSpell::canCast(const Player* player) const
  1520. {
  1521.         if(player->hasFlag(PlayerFlag_CannotUseSpells))
  1522.                 return false;
  1523.  
  1524.         if(player->hasFlag(PlayerFlag_IgnoreSpellCheck) || (!isLearnable() && (vocSpellMap.empty()
  1525.                 || vocSpellMap.find(player->getVocationId()) != vocSpellMap.end())))
  1526.                 return true;
  1527.  
  1528.         return player->hasLearnedInstantSpell(getName());
  1529. }
  1530.  
  1531. ConjureSpell::ConjureSpell(LuaInterface* _interface):
  1532.         InstantSpell(_interface)
  1533. {
  1534.         isAggressive = false;
  1535.         conjureId = 0;
  1536.         conjureCount = 1;
  1537.         conjureReagentId = 0;
  1538. }
  1539.  
  1540. bool ConjureSpell::configureEvent(xmlNodePtr p)
  1541. {
  1542.         if(!InstantSpell::configureEvent(p))
  1543.                 return false;
  1544.  
  1545.         int32_t intValue;
  1546.         if(readXMLInteger(p, "conjureId", intValue))
  1547.                 conjureId = intValue;
  1548.  
  1549.         if(readXMLInteger(p, "conjureCount", intValue))
  1550.                 conjureCount = intValue;
  1551.         else if(conjureId != 0)
  1552.         {
  1553.                 //load the default charge from items.xml
  1554.                 const ItemType& it = Item::items[conjureId];
  1555.                 if(it.charges != 0)
  1556.                         conjureCount = it.charges;
  1557.         }
  1558.  
  1559.         if(readXMLInteger(p, "reagentId", intValue))
  1560.                 conjureReagentId = intValue;
  1561.  
  1562.         return true;
  1563. }
  1564.  
  1565. bool ConjureSpell::loadFunction(const std::string& functionName)
  1566. {
  1567.         std::string tmpFunctionName = asLowerCaseString(functionName);
  1568.         if(tmpFunctionName == "conjureitem" || tmpFunctionName == "conjurerune")
  1569.                 function = ConjureItem;
  1570.         else
  1571.         {
  1572.                 std::clog << "[Warning - ConjureSpell::loadFunction] Function \"" << functionName << "\" does not exist." << std::endl;
  1573.                 return false;
  1574.         }
  1575.  
  1576.         m_scripted = EVENT_SCRIPT_FALSE;
  1577.         return true;
  1578. }
  1579.  
  1580. ReturnValue ConjureSpell::internalConjureItem(Player* player, uint32_t conjureId, uint32_t conjureCount,
  1581.         bool transform/* = false*/, uint32_t reagentId/* = 0*/, slots_t slot/* = SLOT_WHEREVER*/, bool test/* = false*/)
  1582. {
  1583.         if(!transform)
  1584.         {
  1585.                 Item* newItem = Item::CreateItem(conjureId, conjureCount);
  1586.                 if(!newItem)
  1587.                         return RET_NOTPOSSIBLE;
  1588.  
  1589.                 ReturnValue ret = g_game.internalPlayerAddItem(player, player, newItem, true);
  1590.                 if(ret != RET_NOERROR)
  1591.                         delete newItem;
  1592.  
  1593.                 return ret;
  1594.         }
  1595.  
  1596.         if(!reagentId)
  1597.                 return RET_NOTPOSSIBLE;
  1598.  
  1599.         Item* item = player->getInventoryItem(slot);
  1600.         if(item && item->getID() == reagentId)
  1601.         {
  1602.                 if(item->isStackable() && item->getItemCount() != 1)
  1603.                         return RET_YOUNEEDTOSPLITYOURSPEARS;
  1604.  
  1605.                 if(test)
  1606.                         return RET_NOERROR;
  1607.  
  1608.                 Item* newItem = g_game.transformItem(item, conjureId, conjureCount);
  1609.                 if(!newItem)
  1610.                         return RET_NOTPOSSIBLE;
  1611.  
  1612.                 g_game.startDecay(newItem);
  1613.                 return RET_NOERROR;
  1614.         }
  1615.  
  1616.         return RET_YOUNEEDAMAGICITEMTOCASTSPELL;
  1617. }
  1618.  
  1619. bool ConjureSpell::ConjureItem(const ConjureSpell* spell, Creature* creature, const std::string&)
  1620. {
  1621.         Player* player = creature->getPlayer();
  1622.         if(!player)
  1623.                 return false;
  1624.  
  1625.         if(!player->hasFlag(PlayerFlag_IgnoreSpellCheck) && player->getZone() == ZONE_HARDCORE)
  1626.         {
  1627.                 player->sendCancelMessage(RET_CANNOTCONJUREITEMHERE);
  1628.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1629.                 return false;
  1630.         }
  1631.  
  1632.         ReturnValue result = RET_NOERROR;
  1633.         if(spell->getReagentId() != 0)
  1634.         {
  1635.                 ReturnValue resLeft = internalConjureItem(player, spell->getConjureId(), spell->getConjureCount(),
  1636.                         true, spell->getReagentId(), SLOT_LEFT, true);
  1637.                 if(resLeft == RET_NOERROR)
  1638.                 {
  1639.                         resLeft = internalConjureItem(player, spell->getConjureId(), spell->getConjureCount(),
  1640.                                 true, spell->getReagentId(), SLOT_LEFT);
  1641.                         if(resLeft == RET_NOERROR)
  1642.                                 spell->postSpell(player, false);
  1643.                 }
  1644.  
  1645.                 ReturnValue resRight = internalConjureItem(player, spell->getConjureId(), spell->getConjureCount(),
  1646.                         true, spell->getReagentId(), SLOT_RIGHT, true);
  1647.                 if(resRight == RET_NOERROR)
  1648.                 {
  1649.                         if(resLeft == RET_NOERROR && !spell->checkSpell(player))
  1650.                                 return false;
  1651.  
  1652.                         resRight = internalConjureItem(player, spell->getConjureId(), spell->getConjureCount(),
  1653.                                 true, spell->getReagentId(), SLOT_RIGHT);
  1654.                         if(resRight == RET_NOERROR)
  1655.                                 spell->postSpell(player, false);
  1656.                 }
  1657.  
  1658.                 if(resLeft == RET_NOERROR || resRight == RET_NOERROR)
  1659.                 {
  1660.                         spell->postSpell(player, true, false);
  1661.                         g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_WRAPS_RED);
  1662.                         return true;
  1663.                 }
  1664.  
  1665.                 result = resLeft;
  1666.                 if((result == RET_NOERROR && resRight != RET_NOERROR) ||
  1667.                         (result == RET_YOUNEEDAMAGICITEMTOCASTSPELL && resRight == RET_YOUNEEDTOSPLITYOURSPEARS))
  1668.                         result = resRight;
  1669.         }
  1670.         else if(internalConjureItem(player, spell->getConjureId(), spell->getConjureCount()) == RET_NOERROR)
  1671.         {
  1672.                 spell->postSpell(player);
  1673.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_WRAPS_RED);
  1674.                 return true;
  1675.         }
  1676.  
  1677.         if(result != RET_NOERROR)
  1678.                 player->sendCancelMessage(result);
  1679.  
  1680.         g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1681.         return false;
  1682. }
  1683.  
  1684. bool ConjureSpell::castInstant(Player* player, const std::string& param)
  1685. {
  1686.         if(!checkSpell(player))
  1687.                 return false;
  1688.  
  1689.         if(!isScripted())
  1690.                 return function ? function(this, player, param) : false;
  1691.  
  1692.         LuaVariant var;
  1693.         var.type = VARIANT_STRING;
  1694.         var.text = param;
  1695.         return executeCastSpell(player, var);
  1696. }
  1697.  
  1698. RuneSpell::RuneSpell(LuaInterface* _interface):
  1699. Action(_interface)
  1700. {
  1701.         runeId = 0;
  1702.         function = NULL;
  1703.         hasCharges = allowFarUse = true;
  1704. }
  1705.  
  1706. bool RuneSpell::configureEvent(xmlNodePtr p)
  1707. {
  1708.         if(!Spell::configureSpell(p))
  1709.                 return false;
  1710.  
  1711.         if(!Action::configureEvent(p))
  1712.                 return false;
  1713.  
  1714.         int32_t intValue;
  1715.         if(readXMLInteger(p, "id", intValue))
  1716.                 runeId = intValue;
  1717.         else
  1718.         {
  1719.                 std::clog << "Error: [RuneSpell::configureSpell] Rune spell without id." << std::endl;
  1720.                 return false;
  1721.         }
  1722.  
  1723.         std::string strValue;
  1724.         if(readXMLString(p, "charges", strValue))
  1725.                 hasCharges = booleanString(strValue);
  1726.  
  1727.         ItemType& it = Item::items.getItemType(runeId);
  1728.         if(level && level != it.runeLevel)
  1729.                 it.runeLevel = level;
  1730.  
  1731.         if(magLevel && magLevel != it.runeMagLevel)
  1732.                 it.runeMagLevel = magLevel;
  1733.  
  1734.         it.vocationString = parseVocationString(vocStringVec);
  1735.         return true;
  1736. }
  1737.  
  1738. bool RuneSpell::loadFunction(const std::string& functionName)
  1739. {
  1740.         std::string tmpFunctionName = asLowerCaseString(functionName);
  1741.         if(tmpFunctionName == "chameleon")
  1742.                 function = Illusion;
  1743.         else if(tmpFunctionName == "convince")
  1744.                 function = Convince;
  1745.         else
  1746.         {
  1747.                 std::clog << "[Warning - RuneSpell::loadFunction] Function \"" << functionName << "\" does not exist." << std::endl;
  1748.                 return false;
  1749.         }
  1750.  
  1751.         m_scripted = EVENT_SCRIPT_FALSE;
  1752.         return true;
  1753. }
  1754.  
  1755. bool RuneSpell::Illusion(const RuneSpell*, Creature* creature, Item*, const Position&, const Position& posTo)
  1756. {
  1757.         Player* player = creature->getPlayer();
  1758.         if(!player)
  1759.                 return false;
  1760.  
  1761.         Thing* thing = g_game.internalGetThing(player, posTo, 0, 0, STACKPOS_MOVE);
  1762.         if(!thing)
  1763.         {
  1764.                 player->sendCancelMessage(RET_NOTPOSSIBLE);
  1765.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1766.                 return false;
  1767.         }
  1768.  
  1769.         Item* illusionItem = thing->getItem();
  1770.         if(!illusionItem || !illusionItem->isMoveable())
  1771.         {
  1772.                 player->sendCancelMessage(RET_NOTPOSSIBLE);
  1773.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1774.                 return false;
  1775.         }
  1776.  
  1777.         ReturnValue ret = CreateIllusion(creature, illusionItem->getID(), 60000);
  1778.         if(ret == RET_NOERROR)
  1779.         {
  1780.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_WRAPS_RED);
  1781.                 return true;
  1782.         }
  1783.  
  1784.         player->sendCancelMessage(ret);
  1785.         g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1786.         return false;
  1787. }
  1788.  
  1789. bool RuneSpell::Convince(const RuneSpell* spell, Creature* creature, Item*, const Position&, const Position& posTo)
  1790. {
  1791.         Player* player = creature->getPlayer();
  1792.         if(!player)
  1793.                 return false;
  1794.  
  1795.         if(!player->hasFlag(PlayerFlag_CanConvinceAll))
  1796.         {
  1797.                 if(player->getSkull() == SKULL_BLACK)
  1798.                 {
  1799.                         player->sendCancelMessage(RET_NOTPOSSIBLE);
  1800.                         g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1801.                         return false;
  1802.                 }
  1803.  
  1804.                 if((int32_t)player->getSummonCount() >= g_config.getNumber(ConfigManager::MAX_PLAYER_SUMMONS))
  1805.                 {
  1806.                         player->sendCancelMessage(RET_NOTPOSSIBLE);
  1807.                         g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1808.                         return false;
  1809.                 }
  1810.         }
  1811.  
  1812.         Thing* thing = g_game.internalGetThing(player, posTo, 0, 0, STACKPOS_LOOK);
  1813.         if(!thing)
  1814.         {
  1815.                 player->sendCancelMessage(RET_NOTPOSSIBLE);
  1816.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1817.                 return false;
  1818.         }
  1819.  
  1820.         Creature* convinceCreature = thing->getCreature();
  1821.         if(!convinceCreature)
  1822.         {
  1823.                 player->sendCancelMessage(RET_NOTPOSSIBLE);
  1824.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1825.                 return false;
  1826.         }
  1827.  
  1828.         int32_t manaCost = 0;
  1829.         if(Monster* monster = convinceCreature->getMonster())
  1830.                 manaCost = (int32_t)(monster->getManaCost() * g_config.getDouble(ConfigManager::RATE_MONSTER_MANA));
  1831.  
  1832.         if(!player->hasFlag(PlayerFlag_HasInfiniteMana) && player->getMana() < manaCost)
  1833.         {
  1834.                 player->sendCancelMessage(RET_NOTENOUGHMANA);
  1835.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1836.                 return false;
  1837.         }
  1838.  
  1839.         if(!convinceCreature->convinceCreature(creature))
  1840.         {
  1841.                 player->sendCancelMessage(RET_NOTPOSSIBLE);
  1842.                 g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  1843.                 return false;
  1844.         }
  1845.  
  1846.         spell->postSpell(player, (uint32_t)manaCost, (uint32_t)spell->getSoulCost());
  1847.         g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_WRAPS_RED);
  1848.         return true;
  1849. }
  1850.  
  1851. ReturnValue RuneSpell::canExecuteAction(const Player* player, const Position& toPos)
  1852. {
  1853.         if(player->hasFlag(PlayerFlag_CannotUseSpells))
  1854.                 return RET_CANNOTUSETHISOBJECT;
  1855.  
  1856.         ReturnValue ret = Action::canExecuteAction(player, toPos);
  1857.         if(ret != RET_NOERROR)
  1858.                 return ret;
  1859.  
  1860.         if(toPos.x == 0xFFFF)
  1861.         {
  1862.                 if(needTarget)
  1863.                         return RET_CANONLYUSETHISRUNEONCREATURES;
  1864.  
  1865.                 if(!selfTarget)
  1866.                         return RET_NOTENOUGHROOM;
  1867.         }
  1868.  
  1869.         return RET_NOERROR;
  1870. }
  1871.  
  1872. bool RuneSpell::executeUse(Player* player, Item* item, const PositionEx& posFrom,
  1873.         const PositionEx& posTo, bool, uint32_t creatureId)
  1874. {
  1875.         if(!checkRuneSpell(player, posTo))
  1876.                 return false;
  1877.  
  1878.         bool result = false;
  1879.         if(isScripted())
  1880.         {
  1881.                 LuaVariant var;
  1882.                 if(creatureId && needTarget)
  1883.                 {
  1884.                         var.type = VARIANT_NUMBER;
  1885.                         var.number = creatureId;
  1886.                 }
  1887.                 else
  1888.                 {
  1889.                         var.type = VARIANT_POSITION;
  1890.                         var.pos = posTo;
  1891.                 }
  1892.  
  1893.                 result = internalCastSpell(player, var);
  1894.         }
  1895.         else if(function)
  1896.                 result = function(this, player, item, posFrom, posTo);
  1897.  
  1898.         if(result)
  1899.         {
  1900.                 Spell::postSpell(player);
  1901.                 if(hasCharges && item && g_config.getBool(ConfigManager::REMOVE_RUNE_CHARGES))
  1902.                         g_game.transformItem(item, item->getID(), std::max((int32_t)0, ((int32_t)item->getItemCount()) - 1));
  1903.         }
  1904.  
  1905.         return result;
  1906. }
  1907.  
  1908. bool RuneSpell::castSpell(Creature* creature)
  1909. {
  1910.         if(!BaseSpell::castSpell(creature))
  1911.                 return false;
  1912.  
  1913.         LuaVariant var;
  1914.         var.type = VARIANT_NUMBER;
  1915.         var.number = creature->getID();
  1916.         return internalCastSpell(creature, var);
  1917. }
  1918.  
  1919. bool RuneSpell::castSpell(Creature* creature, Creature* target)
  1920. {
  1921.         if(!BaseSpell::castSpell(creature, target))
  1922.                 return false;
  1923.  
  1924.         LuaVariant var;
  1925.         var.type = VARIANT_NUMBER;
  1926.         var.number = target->getID();
  1927.         return internalCastSpell(creature, var);
  1928. }
  1929.  
  1930. bool RuneSpell::internalCastSpell(Creature* creature, const LuaVariant& var)
  1931. {
  1932.         return isScripted() ? executeCastSpell(creature, var) : false;
  1933. }
  1934.  
  1935. bool RuneSpell::executeCastSpell(Creature* creature, const LuaVariant& var)
  1936. {
  1937.         //onCastSpell(cid, var)
  1938.         if(m_interface->reserveEnv())
  1939.         {
  1940.                 ScriptEnviroment* env = m_interface->getEnv();
  1941.                 if(m_scripted == EVENT_SCRIPT_BUFFER)
  1942.                 {
  1943.                         env->setRealPos(creature->getPosition());
  1944.                         std::stringstream scriptstream;
  1945.  
  1946.                         scriptstream << "local cid = " << env->addThing(creature) << std::endl;
  1947.                         env->streamVariant(scriptstream, "var", var);
  1948.  
  1949.                         scriptstream << m_scriptData;
  1950.                         bool result = true;
  1951.                         if(m_interface->loadBuffer(scriptstream.str()))
  1952.                         {
  1953.                                 lua_State* L = m_interface->getState();
  1954.                                 result = m_interface->getGlobalBool(L, "_result", true);
  1955.                         }
  1956.  
  1957.                         m_interface->releaseEnv();
  1958.                         return result;
  1959.                 }
  1960.                 else
  1961.                 {
  1962.                         #ifdef __DEBUG_LUASCRIPTS__
  1963.                         char desc[60];
  1964.                         sprintf(desc, "onCastSpell - %s", creature->getName().c_str());
  1965.                         env->setEvent(desc);
  1966.                         #endif
  1967.  
  1968.                         env->setScriptId(m_scriptId, m_interface);
  1969.                         env->setRealPos(creature->getPosition());
  1970.                         lua_State* L = m_interface->getState();
  1971.  
  1972.                         m_interface->pushFunction(m_scriptId);
  1973.                         lua_pushnumber(L, env->addThing(creature));
  1974.                         m_interface->pushVariant(L, var);
  1975.  
  1976.                         bool result = m_interface->callFunction(2);
  1977.                         m_interface->releaseEnv();
  1978.                         return result;
  1979.                 }
  1980.         }
  1981.         else
  1982.         {
  1983.                 std::clog << "[Error - RuneSpell::executeCastSpell] Call stack overflow." << std::endl;
  1984.                 return false;
  1985.         }
  1986. }
  1987.