Oskar1121

Untitled

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