Advertisement
Guest User

Untitled

a guest
May 3rd, 2021
38
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.63 KB | None | 0 0
  1. /**
  2. * The Forgotten Server - a free and open-source MMORPG server emulator
  3. * Copyright (C) 2019 Mark Samman <mark.samman@gmail.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. */
  19.  
  20. #include "otpch.h"
  21.  
  22. #include "actions.h"
  23. #include "bed.h"
  24. #include "configmanager.h"
  25. #include "container.h"
  26. #include "game.h"
  27. #include "pugicast.h"
  28. #include "spells.h"
  29. #include "rewardchest.h"
  30.  
  31. extern Game g_game;
  32. extern Spells* g_spells;
  33. extern Actions* g_actions;
  34. extern ConfigManager g_config;
  35.  
  36. Actions::Actions() :
  37. scriptInterface("Action Interface")
  38. {
  39. scriptInterface.initState();
  40. }
  41.  
  42. Actions::~Actions()
  43. {
  44. clear(false);
  45. }
  46.  
  47. void Actions::clearMap(ActionUseMap& map, bool fromLua)
  48. {
  49. for (auto it = map.begin(); it != map.end(); ) {
  50. if (fromLua == it->second.fromLua) {
  51. it = map.erase(it);
  52. } else {
  53. ++it;
  54. }
  55. }
  56. }
  57.  
  58. void Actions::clear(bool fromLua)
  59. {
  60. clearMap(useItemMap, fromLua);
  61. clearMap(uniqueItemMap, fromLua);
  62. clearMap(actionItemMap, fromLua);
  63.  
  64. reInitState(fromLua);
  65. }
  66.  
  67. LuaScriptInterface& Actions::getScriptInterface()
  68. {
  69. return scriptInterface;
  70. }
  71.  
  72. std::string Actions::getScriptBaseName() const
  73. {
  74. return "actions";
  75. }
  76.  
  77. Event_ptr Actions::getEvent(const std::string& nodeName)
  78. {
  79. if (strcasecmp(nodeName.c_str(), "action") != 0) {
  80. return nullptr;
  81. }
  82. return Event_ptr(new Action(&scriptInterface));
  83. }
  84.  
  85. bool Actions::registerEvent(Event_ptr event, const pugi::xml_node& node)
  86. {
  87. //event is guaranteed to be an Action
  88. Action_ptr action{static_cast<Action*>(event.release())};
  89.  
  90. pugi::xml_attribute attr;
  91. if ((attr = node.attribute("itemid"))) {
  92. uint16_t id = pugi::cast<uint16_t>(attr.value());
  93.  
  94. auto result = useItemMap.emplace(id, std::move(*action));
  95. if (!result.second) {
  96. std::cout << "[Warning - Actions::registerEvent] Duplicate \
  97. registered item with id: " << id << std::endl;
  98. }
  99. return result.second;
  100. } else if ((attr = node.attribute("fromid"))) {
  101. pugi::xml_attribute toIdAttribute = node.attribute("toid");
  102. if (!toIdAttribute) {
  103. std::cout << "[Warning - Actions::registerEvent] Missing toid in \
  104. fromid: " << attr.as_string() << std::endl;
  105. return false;
  106. }
  107.  
  108. uint16_t fromId = pugi::cast<uint16_t>(attr.value());
  109. uint16_t iterId = fromId;
  110. uint16_t toId = pugi::cast<uint16_t>(toIdAttribute.value());
  111.  
  112. auto result = useItemMap.emplace(iterId, *action);
  113. if (!result.second) {
  114. std::cout << "[Warning - Actions::registerEvent] Duplicate \
  115. registered item with id: " << iterId << " in fromid: " << fromId
  116. << ", toid: " << toId << std::endl;
  117. }
  118.  
  119. bool success = result.second;
  120. while (++iterId <= toId) {
  121. result = useItemMap.emplace(iterId, *action);
  122. if (!result.second) {
  123. std::cout << "[Warning - Actions::registerEvent] Duplicate registered item with id: " << iterId << " in fromid: " << fromId << ", toid: " << toId << std::endl;
  124. continue;
  125. }
  126. success = true;
  127. }
  128. return success;
  129. } else if ((attr = node.attribute("uniqueid"))) {
  130. uint16_t uid = pugi::cast<uint16_t>(attr.value());
  131.  
  132. auto result = uniqueItemMap.emplace(uid, std::move(*action));
  133. if (!result.second) {
  134. std::cout << "[Warning - Actions::registerEvent] Duplicate registered item with uniqueid: " << uid << std::endl;
  135. }
  136. return result.second;
  137. } else if ((attr = node.attribute("fromuid"))) {
  138. pugi::xml_attribute toUidAttribute = node.attribute("touid");
  139. if (!toUidAttribute) {
  140. std::cout << "[Warning - Actions::registerEvent] Missing touid in fromuid: " << attr.as_string() << std::endl;
  141. return false;
  142. }
  143.  
  144. uint16_t fromUid = pugi::cast<uint16_t>(attr.value());
  145. uint16_t iterUid = fromUid;
  146. uint16_t toUid = pugi::cast<uint16_t>(toUidAttribute.value());
  147.  
  148. auto result = uniqueItemMap.emplace(iterUid, *action);
  149. if (!result.second) {
  150. std::cout << "[Warning - Actions::registerEvent] Duplicate registered item with unique id: " << iterUid << " in fromuid: " << fromUid << ", touid: " << toUid << std::endl;
  151. }
  152.  
  153. bool success = result.second;
  154. while (++iterUid <= toUid) {
  155. result = uniqueItemMap.emplace(iterUid, *action);
  156. if (!result.second) {
  157. std::cout << "[Warning - Actions::registerEvent] Duplicate registered item with unique id: " << iterUid << " in fromuid: " << fromUid << ", touid: " << toUid << std::endl;
  158. continue;
  159. }
  160. success = true;
  161. }
  162. return success;
  163. } else if ((attr = node.attribute("actionid"))) {
  164. uint16_t aid = pugi::cast<uint16_t>(attr.value());
  165.  
  166. auto result = actionItemMap.emplace(aid, std::move(*action));
  167. if (!result.second) {
  168. std::cout << "[Warning - Actions::registerEvent] Duplicate registered item with actionid: " << aid << std::endl;
  169. }
  170. return result.second;
  171. } else if ((attr = node.attribute("fromaid"))) {
  172. pugi::xml_attribute toAidAttribute = node.attribute("toaid");
  173. if (!toAidAttribute) {
  174. std::cout << "[Warning - Actions::registerEvent] Missing toaid in fromaid: " << attr.as_string() << std::endl;
  175. return false;
  176. }
  177.  
  178. uint16_t fromAid = pugi::cast<uint16_t>(attr.value());
  179. uint16_t iterAid = fromAid;
  180. uint16_t toAid = pugi::cast<uint16_t>(toAidAttribute.value());
  181.  
  182. auto result = actionItemMap.emplace(iterAid, *action);
  183. if (!result.second) {
  184. std::cout << "[Warning - Actions::registerEvent] Duplicate registered item with action id: " << iterAid << " in fromaid: " << fromAid << ", toaid: " << toAid << std::endl;
  185. }
  186.  
  187. bool success = result.second;
  188. while (++iterAid <= toAid) {
  189. result = actionItemMap.emplace(iterAid, *action);
  190. if (!result.second) {
  191. std::cout << "[Warning - Actions::registerEvent] Duplicate registered item with action id: " << iterAid << " in fromaid: " << fromAid << ", toaid: " << toAid << std::endl;
  192. continue;
  193. }
  194. success = true;
  195. }
  196. return success;
  197. }
  198. return false;
  199. }
  200.  
  201. bool Actions::registerLuaEvent(Action* event)
  202. {
  203. Action_ptr action{ event };
  204. if (action->getItemIdRange().size() > 0) {
  205. if (action->getItemIdRange().size() == 1) {
  206. auto result = useItemMap.emplace(action->getItemIdRange().at(0), std::move(*action));
  207. if (!result.second) {
  208. std::cout << "[Warning - Actions::registerLuaEvent] Duplicate registered item with id: " << action->getItemIdRange().at(0) << std::endl;
  209. }
  210. return result.second;
  211. } else {
  212. auto v = action->getItemIdRange();
  213. for (auto i = v.begin(); i != v.end(); i++) {
  214. auto result = useItemMap.emplace(*i, std::move(*action));
  215. if (!result.second) {
  216. std::cout << "[Warning - Actions::registerLuaEvent] Duplicate registered item with id: " << *i << " in range from id: " << v.at(0) << ", to id: " << v.at(v.size() - 1) << std::endl;
  217. continue;
  218. }
  219. }
  220. return true;
  221. }
  222. } else if (action->getUniqueIdRange().size() > 0) {
  223. if (action->getUniqueIdRange().size() == 1) {
  224. auto result = uniqueItemMap.emplace(action->getUniqueIdRange().at(0), std::move(*action));
  225. if (!result.second) {
  226. std::cout << "[Warning - Actions::registerLuaEvent] Duplicate registered item with uid: " << action->getUniqueIdRange().at(0) << std::endl;
  227. }
  228. return result.second;
  229. } else {
  230. auto v = action->getUniqueIdRange();
  231. for (auto i = v.begin(); i != v.end(); i++) {
  232. auto result = uniqueItemMap.emplace(*i, std::move(*action));
  233. if (!result.second) {
  234. std::cout << "[Warning - Actions::registerLuaEvent] Duplicate registered item with uid: " << *i << " in range from uid: " << v.at(0) << ", to uid: " << v.at(v.size() - 1) << std::endl;
  235. continue;
  236. }
  237. }
  238. return true;
  239. }
  240. } else if (action->getActionIdRange().size() > 0) {
  241. if (action->getActionIdRange().size() == 1) {
  242. auto result = actionItemMap.emplace(action->getActionIdRange().at(0), std::move(*action));
  243. if (!result.second) {
  244. std::cout << "[Warning - Actions::registerLuaEvent] Duplicate registered item with aid: " << action->getActionIdRange().at(0) << std::endl;
  245. }
  246. return result.second;
  247. } else {
  248. auto v = action->getActionIdRange();
  249. for (auto i = v.begin(); i != v.end(); i++) {
  250. auto result = actionItemMap.emplace(*i, std::move(*action));
  251. if (!result.second) {
  252. std::cout << "[Warning - Actions::registerLuaEvent] Duplicate registered item with aid: " << *i << " in range from aid: " << v.at(0) << ", to aid: " << v.at(v.size() - 1) << std::endl;
  253. continue;
  254. }
  255. }
  256. return true;
  257. }
  258. } else {
  259. std::cout << "[Warning - Actions::registerLuaEvent] There is no id / aid / uid set for this event" << std::endl;
  260. return false;
  261. }
  262. }
  263.  
  264. ReturnValue Actions::canUse(const Player* player, const Position& pos)
  265. {
  266. if (pos.x != 0xFFFF) {
  267. const Position& playerPos = player->getPosition();
  268. if (playerPos.z != pos.z) {
  269. return playerPos.z > pos.z ? RETURNVALUE_FIRSTGOUPSTAIRS : RETURNVALUE_FIRSTGODOWNSTAIRS;
  270. }
  271.  
  272. if (!Position::areInRange<1, 1>(playerPos, pos)) {
  273. return RETURNVALUE_TOOFARAWAY;
  274. }
  275. }
  276. return RETURNVALUE_NOERROR;
  277. }
  278.  
  279. ReturnValue Actions::canUse(const Player* player, const Position& pos, const Item* item)
  280. {
  281. Action* action = getAction(item);
  282. if (action != nullptr) {
  283. return action->canExecuteAction(player, pos);
  284. }
  285. return RETURNVALUE_NOERROR;
  286. }
  287.  
  288. ReturnValue Actions::canUseFar(const Creature* creature, const Position& toPos,
  289. bool checkLineOfSight, bool checkFloor)
  290. {
  291. if (toPos.x == 0xFFFF) {
  292. return RETURNVALUE_NOERROR;
  293. }
  294.  
  295. const Position& creaturePos = creature->getPosition();
  296. if (checkFloor && creaturePos.z != toPos.z) {
  297. return creaturePos.z > toPos.z ?
  298. RETURNVALUE_FIRSTGOUPSTAIRS : RETURNVALUE_FIRSTGODOWNSTAIRS;
  299. }
  300.  
  301. if (!Position::areInRange<7, 5>(toPos, creaturePos)) {
  302. return RETURNVALUE_TOOFARAWAY;
  303. }
  304.  
  305. if (checkLineOfSight && !g_game.canThrowObjectTo(creaturePos, toPos)) {
  306. return RETURNVALUE_CANNOTTHROW;
  307. }
  308.  
  309. return RETURNVALUE_NOERROR;
  310. }
  311.  
  312. Action* Actions::getAction(const Item* item)
  313. {
  314. if (item->hasAttribute(ITEM_ATTRIBUTE_UNIQUEID)) {
  315. auto it = uniqueItemMap.find(item->getUniqueId());
  316. if (it != uniqueItemMap.end()) {
  317. return &it->second;
  318. }
  319. }
  320.  
  321. if (item->hasAttribute(ITEM_ATTRIBUTE_ACTIONID)) {
  322. auto it = actionItemMap.find(item->getActionId());
  323. if (it != actionItemMap.end()) {
  324. return &it->second;
  325. }
  326. }
  327.  
  328. auto it = useItemMap.find(item->getID());
  329. if (it != useItemMap.end()) {
  330. return &it->second;
  331. }
  332.  
  333. //rune items
  334. return g_spells->getRuneSpell(item->getID());
  335. }
  336.  
  337. ReturnValue Actions::internalUseItem(Player* player, const Position& pos, uint8_t index, Item* item, bool isHotkey)
  338. {
  339. if (Door* door = item->getDoor()) {
  340. if (!door->canUse(player)) {
  341. return RETURNVALUE_CANNOTUSETHISOBJECT;
  342. }
  343. }
  344.  
  345. Action* action = getAction(item);
  346. if (action != nullptr) {
  347. if (action->isScripted()) {
  348. if (action->executeUse(player, item, pos, nullptr, pos, isHotkey)) {
  349. return RETURNVALUE_NOERROR;
  350. }
  351.  
  352. if (item->isRemoved()) {
  353. return RETURNVALUE_CANNOTUSETHISOBJECT;
  354. }
  355. } else if (action->function) {
  356. if (action->function(player, item, pos, nullptr, pos, isHotkey)) {
  357. return RETURNVALUE_NOERROR;
  358. }
  359. }
  360. }
  361.  
  362. if (BedItem* bed = item->getBed()) {
  363. if (!bed->canUse(player)) {
  364. return RETURNVALUE_CANNOTUSETHISOBJECT;
  365. }
  366.  
  367. if (bed->trySleep(player)) {
  368. player->setBedItem(bed);
  369. g_game.sendOfflineTrainingDialog(player);
  370. }
  371.  
  372. return RETURNVALUE_NOERROR;
  373. }
  374.  
  375. if (Container* container = item->getContainer()) {
  376. Container* openContainer;
  377.  
  378. //depot container
  379. if (DepotLocker* depot = container->getDepotLocker()) {
  380. DepotLocker* myDepotLocker = player->getDepotLocker(depot->getDepotId());
  381. myDepotLocker->setParent(depot->getParent()->getTile());
  382. openContainer = myDepotLocker;
  383. player->setLastDepotId(depot->getDepotId());
  384. } else {
  385. openContainer = container;
  386. }
  387.  
  388. //reward chest
  389. if (container->getRewardChest() != nullptr) {
  390. RewardChest* myRewardChest = player->getRewardChest();
  391. if (myRewardChest->size() == 0) {
  392. return RETURNVALUE_REWARDCHESTISEMPTY;
  393. }
  394.  
  395. myRewardChest->setParent(container->getParent()->getTile());
  396. for (auto& it : player->rewardMap) {
  397. it.second->setParent(myRewardChest);
  398. }
  399.  
  400. openContainer = myRewardChest;
  401. }
  402.  
  403. //reward container proxy created when the boss dies
  404. if (container->getID() == ITEM_REWARD_CONTAINER && !container->getReward()) {
  405. if (Reward* reward = player->getReward(container->getIntAttr(ITEM_ATTRIBUTE_DATE), false)) {
  406. reward->setParent(container->getRealParent());
  407. openContainer = reward;
  408. } else {
  409. return RETURNVALUE_THISISIMPOSSIBLE;
  410. }
  411. }
  412.  
  413. uint32_t corpseOwner = container->getCorpseOwner();
  414. if (container->isRewardCorpse()) {
  415. //only players who participated in the fight can open the corpse
  416. if (player->getGroup()->id >= account::GROUP_TYPE_GAMEMASTER || player->getAccountType() >= account::ACCOUNT_TYPE_SENIORTUTOR) {
  417. return RETURNVALUE_YOUCANTOPENCORPSEADM;
  418. }
  419. if (!player->getReward(container->getIntAttr(ITEM_ATTRIBUTE_DATE), false)) {
  420. return RETURNVALUE_YOUARENOTTHEOWNER;
  421. }
  422.  
  423. if (corpseOwner != 0 && !player->canOpenCorpse(corpseOwner)) {
  424. return RETURNVALUE_YOUARENOTTHEOWNER;
  425. } else {
  426. if (player->canOpenCorpse(corpseOwner) && player->autoLootList.size() != 0) {
  427. if (player->getCapacity() > 100 * 100) { //Minimum of Capacity for autoloot works. (100 CAP)
  428. for (Item* item : container->getItemList()) {
  429. if (player->getItemFromAutoLoot(item->getID())) {
  430. std::ostringstream msgAutoLoot;
  431. msgAutoLoot << "You looted a " << item->getItemCount() << "x " << item->getName() << ".";
  432. g_game.internalMoveItem(container, player, CONST_SLOT_WHEREEVER, item, item->getItemCount(), nullptr);
  433. player->sendTextMessage(MESSAGE_INFO_DESCR, msgAutoLoot.str());
  434. }
  435. }
  436. } else {
  437. player->sendTextMessage(MESSAGE_INFO_DESCR, "Sorry, you don't have enough capacity to use auto loot, so it has been disabled. (100+ capacity is required)");
  438. }
  439. }
  440. }
  441.  
  442. //open/close container
  443. int32_t oldContainerId = player->getContainerID(openContainer);
  444. if (oldContainerId != -1) {
  445. player->onCloseContainer(openContainer);
  446. player->closeContainer(oldContainerId);
  447. } else {
  448. player->addContainer(index, openContainer);
  449. player->onSendContainer(openContainer);
  450. }
  451.  
  452. return RETURNVALUE_NOERROR;
  453. }
  454.  
  455. const ItemType& it = Item::items[item->getID()];
  456. if (it.canReadText) {
  457. if (it.canWriteText) {
  458. player->setWriteItem(item, it.maxTextLen);
  459. player->sendTextWindow(item, it.maxTextLen, true);
  460. } else {
  461. player->setWriteItem(nullptr);
  462. player->sendTextWindow(item, 0, false);
  463. }
  464.  
  465. return RETURNVALUE_NOERROR;
  466. }
  467.  
  468. return RETURNVALUE_CANNOTUSETHISOBJECT;
  469. }
  470.  
  471. bool Actions::useItem(Player* player, const Position& pos, uint8_t index, Item* item, bool isHotkey)
  472. {
  473. const ItemType& it = Item::items[item->getID()];
  474. if (it.isRune() || it.type == ITEM_TYPE_POTION) {
  475. if (player->walkExhausted()) {
  476. player->sendCancelMessage(RETURNVALUE_YOUAREEXHAUSTED);
  477. return false;
  478. }
  479.  
  480. player->setNextPotionAction(OTSYS_TIME() + g_config.getNumber(ConfigManager::ACTIONS_DELAY_INTERVAL));
  481. } else {
  482. player->setNextAction(OTSYS_TIME() + g_config.getNumber(ConfigManager::ACTIONS_DELAY_INTERVAL));
  483. }
  484.  
  485. if (isHotkey) {
  486. uint16_t subType = item->getSubType();
  487. showUseHotkeyMessage(player, item, player->getItemTypeCount(item->getID(), subType != item->getItemCount() ? subType : -1));
  488. }
  489.  
  490. ReturnValue ret = internalUseItem(player, pos, index, item, isHotkey);
  491. if (ret != RETURNVALUE_NOERROR) {
  492. player->sendCancelMessage(ret);
  493. return false;
  494. }
  495. return true;
  496. }
  497.  
  498. bool Actions::useItemEx(Player* player, const Position& fromPos, const Position& toPos,
  499. uint8_t toStackPos, Item* item, bool isHotkey, Creature* creature/* = nullptr*/)
  500. {
  501. const ItemType& it = Item::items[item->getID()];
  502. if (it.isRune() || it.type == ITEM_TYPE_POTION) {
  503. if (player->walkExhausted()) {
  504. player->sendCancelMessage(RETURNVALUE_YOUAREEXHAUSTED);
  505. return false;
  506. }
  507. player->setNextPotionAction(OTSYS_TIME() + g_config.getNumber(ConfigManager::EX_ACTIONS_DELAY_INTERVAL));
  508. } else {
  509. player->setNextAction(OTSYS_TIME() + g_config.getNumber(ConfigManager::EX_ACTIONS_DELAY_INTERVAL));
  510. }
  511.  
  512. Action* action = getAction(item);
  513. if (action == nullptr) {
  514. player->sendCancelMessage(RETURNVALUE_CANNOTUSETHISOBJECT);
  515. return false;
  516. }
  517.  
  518. ReturnValue ret = action->canExecuteAction(player, toPos);
  519. if (ret != RETURNVALUE_NOERROR) {
  520. player->sendCancelMessage(ret);
  521. return false;
  522. }
  523.  
  524. if (isHotkey) {
  525. uint16_t subType = item->getSubType();
  526. showUseHotkeyMessage(player, item, player->getItemTypeCount(item->getID(), subType != item->getItemCount() ? subType : -1));
  527. }
  528.  
  529. if (action->function) {
  530. if (action->function(player, item, fromPos, action->getTarget(player, creature, toPos, toStackPos), toPos, isHotkey)) {
  531. return true;
  532. }
  533. return false;
  534. }
  535.  
  536. if (!action->executeUse(player, item, fromPos, action->getTarget(player, creature, toPos, toStackPos), toPos, isHotkey)) {
  537. if (!action->hasOwnErrorHandler()) {
  538. player->sendCancelMessage(RETURNVALUE_CANNOTUSETHISOBJECT);
  539. }
  540. return false;
  541. }
  542. return true;
  543. }
  544.  
  545. void Actions::showUseHotkeyMessage(Player* player, const Item* item, uint32_t count)
  546. {
  547. std::ostringstream ss;
  548.  
  549. const ItemType& it = Item::items[item->getID()];
  550. if (!it.showCount) {
  551. ss << "Using one of " << item->getName() << "...";
  552. } else if (count == 1) {
  553. ss << "Using the last " << item->getName() << "...";
  554. } else {
  555. ss << "Using one of " << count << ' ' << item->getPluralName() << "...";
  556. }
  557. player->sendTextMessage(MESSAGE_HOTKEY_PRESSED, ss.str());
  558. }
  559.  
  560. Action::Action(LuaScriptInterface* interface) :
  561. Event(interface), function(nullptr), allowFarUse(false), checkFloor(true), checkLineOfSight(true) {}
  562.  
  563. bool Action::configureEvent(const pugi::xml_node& node)
  564. {
  565. pugi::xml_attribute allowFarUseAttr = node.attribute("allowfaruse");
  566. if (allowFarUseAttr != nullptr) {
  567. allowFarUse = allowFarUseAttr.as_bool();
  568. }
  569.  
  570. pugi::xml_attribute blockWallsAttr = node.attribute("blockwalls");
  571. if (blockWallsAttr != nullptr) {
  572. checkLineOfSight = blockWallsAttr.as_bool();
  573. }
  574.  
  575. pugi::xml_attribute checkFloorAttr = node.attribute("checkfloor");
  576. if (checkFloorAttr != nullptr) {
  577. checkFloor = checkFloorAttr.as_bool();
  578. }
  579.  
  580. return true;
  581. }
  582.  
  583. std::string Action::getScriptEventName() const
  584. {
  585. return "onUse";
  586. }
  587.  
  588. ReturnValue Action::canExecuteAction(const Player* player, const Position& toPos)
  589. {
  590. if (!allowFarUse) {
  591. return g_actions->canUse(player, toPos);
  592. }
  593.  
  594. return g_actions->canUseFar(player, toPos, checkLineOfSight, checkFloor);
  595. }
  596.  
  597. Thing* Action::getTarget(Player* player, Creature* targetCreature,
  598. const Position& toPosition, uint8_t toStackPos) const
  599. {
  600. if (targetCreature != nullptr) {
  601. return targetCreature;
  602. }
  603. return g_game.internalGetThing(player, toPosition, toStackPos, 0, STACKPOS_USETARGET);
  604. }
  605.  
  606. bool Action::executeUse(Player* player, Item* item, const Position& fromPosition, Thing* target, const Position& toPosition, bool isHotkey)
  607. {
  608. //onUse(player, item, fromPosition, target, toPosition, isHotkey)
  609. if (!scriptInterface->reserveScriptEnv()) {
  610. std::cout << "[Error - Action::executeUse"
  611. << " Player "
  612. << player->getName()
  613. << " on item "
  614. << item->getName()
  615. << "] Call stack overflow. Too many lua script calls being nested."
  616. << std::endl;
  617. return false;
  618. }
  619.  
  620. ScriptEnvironment* env = scriptInterface->getScriptEnv();
  621. env->setScriptId(scriptId, scriptInterface);
  622.  
  623. lua_State* L = scriptInterface->getLuaState();
  624.  
  625. scriptInterface->pushFunction(scriptId);
  626.  
  627. LuaScriptInterface::pushUserdata<Player>(L, player);
  628. LuaScriptInterface::setMetatable(L, -1, "Player");
  629.  
  630. LuaScriptInterface::pushThing(L, item);
  631. LuaScriptInterface::pushPosition(L, fromPosition);
  632.  
  633. LuaScriptInterface::pushThing(L, target);
  634. LuaScriptInterface::pushPosition(L, toPosition);
  635.  
  636. LuaScriptInterface::pushBoolean(L, isHotkey);
  637. return scriptInterface->callFunction(6);
  638. }
  639.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement