Guest User

Untitled

a guest
Aug 24th, 2019
248
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 40.44 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.  
  19. #include "creature.h"
  20. #include "player.h"
  21. #include "npc.h"
  22. #include "monster.h"
  23.  
  24. #include "condition.h"
  25. #include "combat.h"
  26.  
  27. #include "container.h"
  28. #if defined __EXCEPTION_TRACER__
  29. #include "exception.h"
  30. #endif
  31.  
  32. #include "configmanager.h"
  33. #include "game.h"
  34.  
  35. boost::recursive_mutex AutoId::lock;
  36. uint32_t AutoId::count = 1000;
  37. AutoId::List AutoId::list;
  38.  
  39. extern Game g_game;
  40. extern ConfigManager g_config;
  41. extern CreatureEvents* g_creatureEvents;
  42.  
  43. Creature::Creature()
  44. {
  45. id = 0;
  46. _tile = NULL;
  47. direction = SOUTH;
  48. master = NULL;
  49. lootDrop = LOOT_DROP_FULL;
  50. skillLoss = true;
  51. hideName = hideHealth = cannotMove = false;
  52. speakType = SPEAK_CLASS_NONE;
  53. skull = SKULL_NONE;
  54. partyShield = SHIELD_NONE;
  55. guildEmblem = EMBLEM_NONE;
  56.  
  57. health = 1000;
  58. healthMax = 1000;
  59. mana = 0;
  60. manaMax = 0;
  61.  
  62. lastStep = 0;
  63. lastStepCost = 1;
  64. baseSpeed = 220;
  65. varSpeed = 0;
  66.  
  67. masterRadius = -1;
  68. masterPosition = Position();
  69.  
  70. followCreature = NULL;
  71. hasFollowPath = false;
  72. removed = false;
  73. eventWalk = 0;
  74. cancelNextWalk = false;
  75. forceUpdateFollowPath = false;
  76. isMapLoaded = false;
  77. isUpdatingPath = false;
  78. checked = false;
  79. memset(localMapCache, false, sizeof(localMapCache));
  80.  
  81. attackedCreature = NULL;
  82. lastHitCreature = 0;
  83. lastDamageSource = COMBAT_NONE;
  84. blockCount = 0;
  85. blockTicks = 0;
  86. walkUpdateTicks = 0;
  87. checkVector = -1;
  88.  
  89. onIdleStatus();
  90. }
  91.  
  92. Creature::~Creature()
  93. {
  94. attackedCreature = NULL;
  95. removeConditions(CONDITIONEND_CLEANUP, false);
  96. for(std::list<Creature*>::iterator cit = summons.begin(); cit != summons.end(); ++cit)
  97. {
  98. (*cit)->setAttackedCreature(NULL);
  99. (*cit)->setMaster(NULL);
  100. (*cit)->unRef();
  101. }
  102.  
  103. summons.clear();
  104. conditions.clear();
  105. eventsList.clear();
  106. }
  107.  
  108. bool Creature::canSee(const Position& myPos, const Position& pos, uint32_t viewRangeX, uint32_t viewRangeY)
  109. {
  110. if(myPos.z <= 7)
  111. {
  112. //we are on ground level or above (7 -> 0)
  113. //view is from 7 -> 0
  114. if(pos.z > 7)
  115. return false;
  116. }
  117. else if(myPos.z >= 8)
  118. {
  119. //we are underground (8 -> 15)
  120. //view is +/- 2 from the floor we stand on
  121. if(std::abs(myPos.z - pos.z) > 2)
  122. return false;
  123. }
  124.  
  125. int32_t offsetz = myPos.z - pos.z;
  126. return (((uint32_t)pos.x >= myPos.x - viewRangeX + offsetz) && ((uint32_t)pos.x <= myPos.x + viewRangeX + offsetz) &&
  127. ((uint32_t)pos.y >= myPos.y - viewRangeY + offsetz) && ((uint32_t)pos.y <= myPos.y + viewRangeY + offsetz));
  128. }
  129.  
  130. bool Creature::canSee(const Position& pos) const
  131. {
  132. return canSee(getPosition(), pos, Map::maxViewportX, Map::maxViewportY);
  133. }
  134.  
  135. bool Creature::canSeeCreature(const Creature* creature) const
  136. {
  137. return creature == this || (!creature->isGhost() && (!creature->isInvisible() || canSeeInvisibility()));
  138. }
  139.  
  140. bool Creature::canWalkthrough(const Creature* creature) const
  141. {
  142. if(creature == this)
  143. return true;
  144.  
  145. if(const Creature* _master = creature->getMaster())
  146. {
  147. if(_master != this && canWalkthrough(_master))
  148. return true;
  149. }
  150.  
  151. return creature->isGhost() || creature->isWalkable() || (master &&
  152. master != creature && master->canWalkthrough(creature));
  153. }
  154.  
  155. int64_t Creature::getTimeSinceLastMove() const
  156. {
  157. if(lastStep)
  158. return OTSYS_TIME() - lastStep;
  159.  
  160. return 0x7FFFFFFFFFFFFFFFLL;
  161. }
  162.  
  163. int32_t Creature::getWalkDelay(Direction dir) const
  164. {
  165. if(lastStep)
  166. return getStepDuration(dir) - (OTSYS_TIME() - lastStep);
  167.  
  168. return 0;
  169. }
  170.  
  171. int32_t Creature::getWalkDelay() const
  172. {
  173. if(lastStep)
  174. return getStepDuration() - (OTSYS_TIME() - lastStep);
  175.  
  176. return 0;
  177. }
  178.  
  179. void Creature::onThink(uint32_t interval)
  180. {
  181. if(!isMapLoaded && useCacheMap())
  182. {
  183. isMapLoaded = true;
  184. updateMapCache();
  185. }
  186.  
  187. if(followCreature && master != followCreature && !canSeeCreature(followCreature))
  188. internalCreatureDisappear(followCreature, false);
  189.  
  190. if(attackedCreature && master != attackedCreature && !canSeeCreature(attackedCreature))
  191. internalCreatureDisappear(attackedCreature, false);
  192.  
  193. blockTicks += interval;
  194. if(blockTicks >= 1000)
  195. {
  196. blockCount = std::min((uint32_t)blockCount + 1, (uint32_t)2);
  197. blockTicks = 0;
  198. }
  199.  
  200. if(followCreature)
  201. {
  202. walkUpdateTicks += interval;
  203. if(forceUpdateFollowPath || walkUpdateTicks >= 2000)
  204. {
  205. walkUpdateTicks = 0;
  206. forceUpdateFollowPath = false;
  207. isUpdatingPath = true;
  208. }
  209. }
  210.  
  211. if(isUpdatingPath)
  212. {
  213. isUpdatingPath = false;
  214. goToFollowCreature();
  215. }
  216.  
  217. onAttacking(interval);
  218. executeConditions(interval);
  219.  
  220. CreatureEventList thinkEvents = getCreatureEvents(CREATURE_EVENT_THINK);
  221. for(CreatureEventList::iterator it = thinkEvents.begin(); it != thinkEvents.end(); ++it)
  222. (*it)->executeThink(this, interval);
  223. }
  224.  
  225. void Creature::onAttacking(uint32_t interval)
  226. {
  227. if(!attackedCreature)
  228. return;
  229.  
  230. CreatureEventList attackEvents = getCreatureEvents(CREATURE_EVENT_ATTACK);
  231. for(CreatureEventList::iterator it = attackEvents.begin(); it != attackEvents.end(); ++it)
  232. {
  233. if(!(*it)->executeAttack(this, attackedCreature) && attackedCreature)
  234. setAttackedCreature(NULL);
  235. }
  236.  
  237. if(!attackedCreature)
  238. return;
  239.  
  240. onAttacked();
  241. attackedCreature->onAttacked();
  242. if(g_game.isSightClear(getPosition(), attackedCreature->getPosition(), true))
  243. doAttacking(interval);
  244. }
  245.  
  246. void Creature::onWalk()
  247. {
  248. if(getWalkDelay() <= 0)
  249. {
  250. Direction dir;
  251. uint32_t flags = FLAG_IGNOREFIELDDAMAGE;
  252. if(!getNextStep(dir, flags))
  253. {
  254. if(listWalkDir.empty())
  255. onWalkComplete();
  256.  
  257. stopEventWalk();
  258. }
  259. else if(g_game.internalMoveCreature(this, dir, flags) != RET_NOERROR)
  260. forceUpdateFollowPath = true;
  261. }
  262.  
  263. if(cancelNextWalk)
  264. {
  265. cancelNextWalk = false;
  266. listWalkDir.clear();
  267. onWalkAborted();
  268. }
  269.  
  270. if(eventWalk)
  271. {
  272. eventWalk = 0;
  273. addEventWalk();
  274. }
  275. }
  276.  
  277. void Creature::onWalk(Direction& dir)
  278. {
  279. if(!hasCondition(CONDITION_DRUNK))
  280. return;
  281.  
  282. uint32_t r = random_range(0, 16);
  283. if(r > 4)
  284. return;
  285.  
  286. switch(r)
  287. {
  288. case 0:
  289. dir = NORTH;
  290. break;
  291. case 1:
  292. dir = WEST;
  293. break;
  294. case 3:
  295. dir = SOUTH;
  296. break;
  297. case 4:
  298. dir = EAST;
  299. break;
  300. }
  301.  
  302. g_game.internalCreatureSay(this, SPEAK_MONSTER_SAY, "Hicks!", isGhost());
  303. }
  304.  
  305. bool Creature::getNextStep(Direction& dir, uint32_t&)
  306. {
  307. if(listWalkDir.empty())
  308. return false;
  309.  
  310. dir = listWalkDir.front();
  311. listWalkDir.pop_front();
  312. onWalk(dir);
  313. return true;
  314. }
  315.  
  316. bool Creature::startAutoWalk(std::list<Direction>& listDir)
  317. {
  318. if(getPlayer() && getPlayer()->getNoMove())
  319. {
  320. getPlayer()->sendCancelWalk();
  321. return false;
  322. }
  323.  
  324. listWalkDir = listDir;
  325. addEventWalk(listDir.size() == 1);
  326. return true;
  327. }
  328.  
  329. void Creature::addEventWalk(bool firstStep/* = false*/)
  330. {
  331. cancelNextWalk = false;
  332. if(getStepSpeed() < 1 || eventWalk)
  333. return;
  334.  
  335. int64_t ticks = getEventStepTicks(firstStep);
  336. if(ticks < 1)
  337. return;
  338.  
  339. if(ticks == 1)
  340. g_game.checkCreatureWalk(getID());
  341.  
  342. eventWalk = Scheduler::getInstance().addEvent(createSchedulerTask(std::max((int64_t)SCHEDULER_MINTICKS, ticks),
  343. boost::bind(&Game::checkCreatureWalk, &g_game, id)));
  344. }
  345.  
  346. void Creature::stopEventWalk()
  347. {
  348. if(!eventWalk)
  349. return;
  350.  
  351. Scheduler::getInstance().stopEvent(eventWalk);
  352. eventWalk = 0;
  353. }
  354.  
  355. void Creature::updateMapCache()
  356. {
  357. const Position& pos = getPosition();
  358. Position dest(0, 0, pos.z);
  359.  
  360. Tile* tile = NULL;
  361. for(int32_t y = -((mapWalkHeight - 1) / 2); y <= ((mapWalkHeight - 1) / 2); ++y)
  362. {
  363. for(int32_t x = -((mapWalkWidth - 1) / 2); x <= ((mapWalkWidth - 1) / 2); ++x)
  364. {
  365. dest.x = pos.x + x;
  366. dest.y = pos.y + y;
  367. if((tile = g_game.getTile(dest)))
  368. updateTileCache(tile, dest);
  369. }
  370. }
  371. }
  372.  
  373. #ifdef __DEBUG__
  374. void Creature::validateMapCache()
  375. {
  376. const Position& myPos = getPosition();
  377. for(int32_t y = -((mapWalkHeight - 1) / 2); y <= ((mapWalkHeight - 1) / 2); ++y)
  378. {
  379. for(int32_t x = -((mapWalkWidth - 1) / 2); x <= ((mapWalkWidth - 1) / 2); ++x)
  380. getWalkCache(Position(myPos.x + x, myPos.y + y, myPos.z));
  381. }
  382. }
  383. #endif
  384.  
  385. void Creature::updateTileCache(const Tile* tile, int32_t dx, int32_t dy)
  386. {
  387. if((std::abs(dx) <= (mapWalkWidth - 1) / 2) && (std::abs(dy) <= (mapWalkHeight - 1) / 2))
  388. {
  389. int32_t x = (mapWalkWidth - 1) / 2 + dx, y = (mapWalkHeight - 1) / 2 + dy;
  390. localMapCache[y][x] = (tile && tile->__queryAdd(0, this, 1,
  391. FLAG_PATHFINDING | FLAG_IGNOREFIELDDAMAGE) == RET_NOERROR);
  392. }
  393. #ifdef __DEBUG__
  394. else
  395. std::clog << "Creature::updateTileCache out of range." << std::endl;
  396. #endif
  397. }
  398.  
  399. void Creature::updateTileCache(const Tile* tile, const Position& pos)
  400. {
  401. const Position& myPos = getPosition();
  402. if(pos.z == myPos.z)
  403. updateTileCache(tile, pos.x - myPos.x, pos.y - myPos.y);
  404. }
  405.  
  406. void Creature::updateTileCache(const Tile* tile)
  407. {
  408. if(isMapLoaded && tile->getPosition().z == getPosition().z)
  409. updateTileCache(tile, tile->getPosition());
  410. }
  411.  
  412. int32_t Creature::getWalkCache(const Position& pos) const
  413. {
  414. if(!useCacheMap())
  415. return 2;
  416.  
  417. const Position& myPos = getPosition();
  418. if(myPos.z != pos.z)
  419. return 0;
  420.  
  421. if(pos == myPos)
  422. return 1;
  423.  
  424. int32_t dx = pos.x - myPos.x, dy = pos.y - myPos.y;
  425. if((std::abs(dx) <= (mapWalkWidth - 1) / 2) && (std::abs(dy) <= (mapWalkHeight - 1) / 2))
  426. {
  427. int32_t x = (mapWalkWidth - 1) / 2 + dx, y = (mapWalkHeight - 1) / 2 + dy;
  428. #ifdef __DEBUG__
  429. //testing
  430. Tile* tile = g_game.getTile(pos);
  431. if(tile && (tile->__queryAdd(0, this, 1, FLAG_PATHFINDING | FLAG_IGNOREFIELDDAMAGE) == RET_NOERROR))
  432. {
  433. if(!localMapCache[y][x])
  434. std::clog << "Wrong cache value" << std::endl;
  435. }
  436. else if(localMapCache[y][x])
  437. std::clog << "Wrong cache value" << std::endl;
  438.  
  439. #endif
  440. if(localMapCache[y][x])
  441. return 1;
  442.  
  443. return 0;
  444. }
  445.  
  446. //out of range
  447. return 2;
  448. }
  449.  
  450. void Creature::onAddTileItem(const Tile* tile, const Position& pos, const Item*)
  451. {
  452. if(isMapLoaded && pos.z == getPosition().z)
  453. updateTileCache(tile, pos);
  454. }
  455.  
  456. void Creature::onUpdateTileItem(const Tile* tile, const Position& pos, const Item*,
  457. const ItemType& oldType, const Item*, const ItemType& newType)
  458. {
  459. if(isMapLoaded && (oldType.blockSolid || oldType.blockPathFind || newType.blockPathFind
  460. || newType.blockSolid) && pos.z == getPosition().z)
  461. updateTileCache(tile, pos);
  462. }
  463.  
  464. void Creature::onRemoveTileItem(const Tile* tile, const Position& pos, const ItemType& iType, const Item*)
  465. {
  466. if(isMapLoaded && (iType.blockSolid || iType.blockPathFind ||
  467. iType.isGroundTile()) && pos.z == getPosition().z)
  468. updateTileCache(tile, pos);
  469. }
  470.  
  471. void Creature::onCreatureAppear(const Creature* creature)
  472. {
  473. if(creature == this)
  474. {
  475. if(useCacheMap())
  476. {
  477. isMapLoaded = true;
  478. updateMapCache();
  479. }
  480. }
  481. else if(isMapLoaded && creature->getPosition().z == getPosition().z)
  482. updateTileCache(creature->getTile(), creature->getPosition());
  483. }
  484.  
  485. void Creature::internalCreatureDisappear(const Creature* creature, bool isLogout)
  486. {
  487. if(attackedCreature == creature)
  488. {
  489. setAttackedCreature(NULL);
  490. onAttackedCreatureDisappear(isLogout);
  491. }
  492.  
  493. if(followCreature == creature)
  494. {
  495. setFollowCreature(NULL);
  496. onFollowCreatureDisappear(isLogout);
  497. }
  498. }
  499.  
  500. void Creature::onRemovedCreature()
  501. {
  502. setRemoved();
  503. removeList();
  504. if(master && !master->isRemoved())
  505. master->removeSummon(this);
  506. }
  507.  
  508. void Creature::onChangeZone(ZoneType_t zone)
  509. {
  510. if(attackedCreature && zone == ZONE_PROTECTION)
  511. internalCreatureDisappear(attackedCreature, false);
  512. }
  513.  
  514. void Creature::onAttackedCreatureChangeZone(ZoneType_t zone)
  515. {
  516. if(zone == ZONE_PROTECTION)
  517. internalCreatureDisappear(attackedCreature, false);
  518. }
  519.  
  520. void Creature::onCreatureMove(const Creature* creature, const Tile* newTile, const Position& newPos,
  521. const Tile* oldTile, const Position& oldPos, bool teleport)
  522. {
  523. if(creature == this)
  524. {
  525. lastStep = OTSYS_TIME();
  526. lastStepCost = 1;
  527.  
  528. setLastPosition(oldPos);
  529. if(!teleport)
  530. {
  531. if(std::abs(newPos.x - oldPos.x) >= 1 && std::abs(newPos.y - oldPos.y) >= 1)
  532. lastStepCost = 3;
  533. }
  534. else
  535. stopEventWalk();
  536.  
  537. if(!summons.empty() && (!g_config.getBool(ConfigManager::TELEPORT_SUMMONS) ||
  538. (g_config.getBool(ConfigManager::TELEPORT_PLAYER_SUMMONS) && !getPlayer())))
  539. {
  540. std::list<Creature*>::iterator cit;
  541. std::list<Creature*> despawnList;
  542. for(cit = summons.begin(); cit != summons.end(); ++cit)
  543. {
  544. const Position pos = (*cit)->getPosition();
  545. if((std::abs(pos.z - newPos.z) > 2) || (std::max(std::abs((
  546. newPos.x) - pos.x), std::abs((newPos.y - 1) - pos.y)) > 30))
  547. despawnList.push_back(*cit);
  548. }
  549.  
  550. for(cit = despawnList.begin(); cit != despawnList.end(); ++cit)
  551. g_game.removeCreature((*cit), true);
  552. }
  553.  
  554. if(newTile->getZone() != oldTile->getZone())
  555. onChangeZone(getZone());
  556.  
  557. //update map cache
  558. if(isMapLoaded)
  559. {
  560. if(!teleport && oldPos.z == newPos.z)
  561. {
  562. Tile* tile = NULL;
  563. const Position& myPos = getPosition();
  564. if(oldPos.y > newPos.y) //north
  565. {
  566. //shift y south
  567. for(int32_t y = mapWalkHeight - 1 - 1; y >= 0; --y)
  568. memcpy(localMapCache[y + 1], localMapCache[y], sizeof(localMapCache[y]));
  569.  
  570. //update 0
  571. for(int32_t x = -((mapWalkWidth - 1) / 2); x <= ((mapWalkWidth - 1) / 2); ++x)
  572. {
  573. tile = g_game.getTile(myPos.x + x, myPos.y - ((mapWalkHeight - 1) / 2), myPos.z);
  574. updateTileCache(tile, x, -((mapWalkHeight - 1) / 2));
  575. }
  576. }
  577. else if(oldPos.y < newPos.y) // south
  578. {
  579. //shift y north
  580. for(int32_t y = 0; y <= mapWalkHeight - 1 - 1; ++y)
  581. memcpy(localMapCache[y], localMapCache[y + 1], sizeof(localMapCache[y]));
  582.  
  583. //update mapWalkHeight - 1
  584. for(int32_t x = -((mapWalkWidth - 1) / 2); x <= ((mapWalkWidth - 1) / 2); ++x)
  585. {
  586. tile = g_game.getTile(myPos.x + x, myPos.y + ((mapWalkHeight - 1) / 2), myPos.z);
  587. updateTileCache(tile, x, (mapWalkHeight - 1) / 2);
  588. }
  589. }
  590.  
  591. if(oldPos.x < newPos.x) // east
  592. {
  593. //shift y west
  594. int32_t starty = 0, endy = mapWalkHeight - 1, dy = (oldPos.y - newPos.y);
  595. if(dy < 0)
  596. endy = endy + dy;
  597. else if(dy > 0)
  598. starty = starty + dy;
  599.  
  600. for(int32_t y = starty; y <= endy; ++y)
  601. {
  602. for(int32_t x = 0; x <= mapWalkWidth - 1 - 1; ++x)
  603. localMapCache[y][x] = localMapCache[y][x + 1];
  604. }
  605.  
  606. //update mapWalkWidth - 1
  607. for(int32_t y = -((mapWalkHeight - 1) / 2); y <= ((mapWalkHeight - 1) / 2); ++y)
  608. {
  609. tile = g_game.getTile(myPos.x + ((mapWalkWidth - 1) / 2), myPos.y + y, myPos.z);
  610. updateTileCache(tile, (mapWalkWidth - 1) / 2, y);
  611. }
  612. }
  613. else if(oldPos.x > newPos.x) // west
  614. {
  615. //shift y east
  616. int32_t starty = 0, endy = mapWalkHeight - 1, dy = (oldPos.y - newPos.y);
  617. if(dy < 0)
  618. endy = endy + dy;
  619. else if(dy > 0)
  620. starty = starty + dy;
  621.  
  622. for(int32_t y = starty; y <= endy; ++y)
  623. {
  624. for(int32_t x = mapWalkWidth - 1 - 1; x >= 0; --x)
  625. localMapCache[y][x + 1] = localMapCache[y][x];
  626. }
  627.  
  628. //update 0
  629. for(int32_t y = -((mapWalkHeight - 1) / 2); y <= ((mapWalkHeight - 1) / 2); ++y)
  630. {
  631. tile = g_game.getTile(myPos.x - ((mapWalkWidth - 1) / 2), myPos.y + y, myPos.z);
  632. updateTileCache(tile, -((mapWalkWidth - 1) / 2), y);
  633. }
  634. }
  635.  
  636. updateTileCache(oldTile, oldPos);
  637. #ifdef __DEBUG__
  638. validateMapCache();
  639. #endif
  640. }
  641. else
  642. updateMapCache();
  643. }
  644. }
  645. else if(isMapLoaded)
  646. {
  647. const Position& myPos = getPosition();
  648. if(newPos.z == myPos.z)
  649. updateTileCache(newTile, newPos);
  650.  
  651. if(oldPos.z == myPos.z)
  652. updateTileCache(oldTile, oldPos);
  653. }
  654.  
  655. if(creature == followCreature || (creature == this && followCreature))
  656. {
  657. if(hasFollowPath)
  658. {
  659. isUpdatingPath = true;
  660. Dispatcher::getInstance().addTask(createTask(
  661. boost::bind(&Game::updateCreatureWalk, &g_game, getID())));
  662. }
  663.  
  664. if(newPos.z != oldPos.z || !canSee(followCreature->getPosition()))
  665. internalCreatureDisappear(followCreature, false);
  666. }
  667.  
  668. if(creature == attackedCreature || (creature == this && attackedCreature))
  669. {
  670. if(newPos.z == oldPos.z && canSee(attackedCreature->getPosition()))
  671. {
  672. if(hasExtraSwing()) //our target is moving lets see if we can get in hit
  673. Dispatcher::getInstance().addTask(createTask(
  674. boost::bind(&Game::checkCreatureAttack, &g_game, getID())));
  675.  
  676. if(newTile->getZone() != oldTile->getZone())
  677. onAttackedCreatureChangeZone(attackedCreature->getZone());
  678. }
  679. else
  680. internalCreatureDisappear(attackedCreature, false);
  681. }
  682. }
  683.  
  684. bool Creature::onDeath()
  685. {
  686. DeathList deathList = getKillers();
  687. bool deny = false;
  688.  
  689. CreatureEventList prepareDeathEvents = getCreatureEvents(CREATURE_EVENT_PREPAREDEATH);
  690. for(CreatureEventList::iterator it = prepareDeathEvents.begin(); it != prepareDeathEvents.end(); ++it)
  691. {
  692. if(!(*it)->executePrepareDeath(this, deathList) && !deny)
  693. deny = true;
  694. }
  695.  
  696. if(deny)
  697. return false;
  698.  
  699. int32_t i = 0, size = deathList.size(), limit = g_config.getNumber(ConfigManager::DEATH_ASSISTS) + 1;
  700. if(limit > 0 && size > limit)
  701. size = limit;
  702.  
  703. Creature* tmp = NULL;
  704. CreatureVector justifyVec;
  705. for(DeathList::iterator it = deathList.begin(); it != deathList.end(); ++it, ++i)
  706. {
  707. if(it->isNameKill())
  708. continue;
  709.  
  710. if(it == deathList.begin())
  711. it->setLast();
  712.  
  713. if(i < size)
  714. {
  715. if(it->getKillerCreature()->getPlayer())
  716. tmp = it->getKillerCreature();
  717. else if(it->getKillerCreature()->getPlayerMaster())
  718. tmp = it->getKillerCreature()->getMaster();
  719. }
  720.  
  721. if(tmp)
  722. {
  723. if(std::find(justifyVec.begin(), justifyVec.end(), tmp) == justifyVec.end())
  724. {
  725. it->setJustify();
  726. justifyVec.push_back(tmp);
  727. }
  728.  
  729. tmp = NULL;
  730. }
  731.  
  732. if(!it->getKillerCreature()->onKilledCreature(this, (*it)) && it->isLast())
  733. return false;
  734. }
  735.  
  736. for(CountMap::iterator it = damageMap.begin(); it != damageMap.end(); ++it)
  737. {
  738. if((tmp = g_game.getCreatureByID(it->first)))
  739. tmp->onAttackedCreatureKilled(this);
  740. }
  741.  
  742. dropCorpse(deathList);
  743. if(master)
  744. master->removeSummon(this);
  745.  
  746. return true;
  747. }
  748.  
  749. void Creature::dropCorpse(DeathList deathList)
  750. {
  751. Item* corpse = createCorpse(deathList);
  752. if(corpse)
  753. corpse->setParent(VirtualCylinder::virtualCylinder);
  754.  
  755. bool deny = false;
  756. CreatureEventList deathEvents = getCreatureEvents(CREATURE_EVENT_DEATH);
  757. for(CreatureEventList::iterator it = deathEvents.begin(); it != deathEvents.end(); ++it)
  758. {
  759. if(!(*it)->executeDeath(this, corpse, deathList) && !deny)
  760. deny = true;
  761. }
  762.  
  763. if(!corpse)
  764. return;
  765.  
  766. corpse->setParent(NULL);
  767. if(deny)
  768. return;
  769.  
  770. Tile* tile = getTile();
  771. if(!tile)
  772. return;
  773.  
  774. Item* splash = NULL;
  775. switch(getRace())
  776. {
  777. case RACE_VENOM:
  778. splash = Item::CreateItem(ITEM_FULLSPLASH, FLUID_GREEN);
  779. break;
  780.  
  781. case RACE_BLOOD:
  782. splash = Item::CreateItem(ITEM_FULLSPLASH, FLUID_BLOOD);
  783. break;
  784.  
  785. default:
  786. break;
  787. }
  788.  
  789. if(splash)
  790. {
  791. g_game.internalAddItem(NULL, tile, splash, INDEX_WHEREEVER, FLAG_NOLIMIT);
  792. g_game.startDecay(splash);
  793. }
  794.  
  795. g_game.internalAddItem(NULL, tile, corpse, INDEX_WHEREEVER, FLAG_NOLIMIT);
  796. dropLoot(corpse->getContainer());
  797. g_game.startDecay(corpse);
  798. }
  799.  
  800. DeathList Creature::getKillers()
  801. {
  802. DeathList list;
  803. CountMap::const_iterator it;
  804.  
  805. Creature* lhc = NULL;
  806. if((lhc = g_game.getCreatureByID(lastHitCreature)))
  807. {
  808. int32_t damage = 0;
  809. it = damageMap.find(lastHitCreature);
  810. if(it != damageMap.end())
  811. damage = it->second.total;
  812.  
  813. list.push_back(DeathEntry(lhc, damage));
  814. }
  815. else
  816. list.push_back(DeathEntry(getCombatName(lastDamageSource), 0));
  817.  
  818. int32_t requiredTime = g_config.getNumber(ConfigManager::DEATHLIST_REQUIRED_TIME);
  819. int64_t now = OTSYS_TIME();
  820.  
  821. CountBlock_t cb;
  822. for(it = damageMap.begin(); it != damageMap.end(); ++it)
  823. {
  824. cb = it->second;
  825. if((now - cb.ticks) > requiredTime)
  826. continue;
  827.  
  828. Creature* mdc = g_game.getCreatureByID(it->first);
  829. if(!mdc || mdc == lhc || (lhc && (mdc->getMaster() == lhc || lhc->getMaster() == mdc)))
  830. continue;
  831.  
  832. bool deny = false;
  833. for(DeathList::iterator fit = list.begin(); fit != list.end(); ++fit)
  834. {
  835. if(fit->isNameKill())
  836. continue;
  837.  
  838. Creature* tmp = fit->getKillerCreature();
  839. if(!(mdc->getName() == tmp->getName() && mdc->getMaster() == tmp->getMaster()) &&
  840. (!mdc->getMaster() || (mdc->getMaster() != tmp && mdc->getMaster() != tmp->getMaster()))
  841. && (mdc->getSummonCount() <= 0 || tmp->getMaster() != mdc))
  842. continue;
  843.  
  844. deny = true;
  845. break;
  846. }
  847.  
  848. if(!deny)
  849. list.push_back(DeathEntry(mdc, cb.total));
  850. }
  851.  
  852. if(list.size() > 1)
  853. std::sort(list.begin() + 1, list.end(), DeathLessThan());
  854.  
  855. return list;
  856. }
  857.  
  858. bool Creature::hasBeenAttacked(uint32_t attackerId) const
  859. {
  860. CountMap::const_iterator it = damageMap.find(attackerId);
  861. if(it != damageMap.end())
  862. return (OTSYS_TIME() - it->second.ticks) <= g_config.getNumber(ConfigManager::PZ_LOCKED);
  863.  
  864. return false;
  865. }
  866.  
  867. Item* Creature::createCorpse(DeathList)
  868. {
  869. return Item::CreateItem(getLookCorpse());
  870. }
  871.  
  872. void Creature::changeHealth(int32_t healthChange)
  873. {
  874. if(healthChange > 0)
  875. health += std::min(healthChange, getMaxHealth() - health);
  876. else
  877. health = std::max((int32_t)0, health + healthChange);
  878.  
  879. g_game.addCreatureHealth(this);
  880. }
  881.  
  882. void Creature::changeMana(int32_t manaChange)
  883. {
  884. if(manaChange > 0)
  885. mana += std::min(manaChange, getMaxMana() - mana);
  886. else
  887. mana = std::max((int32_t)0, mana + manaChange);
  888. }
  889.  
  890. bool Creature::getStorage(const std::string& key, std::string& value) const
  891. {
  892. StorageMap::const_iterator it = storageMap.find(key);
  893. if(it != storageMap.end())
  894. {
  895. value = it->second;
  896. return true;
  897. }
  898.  
  899. value = "-1";
  900. return false;
  901. }
  902.  
  903. bool Creature::setStorage(const std::string& key, const std::string& value)
  904. {
  905. storageMap[key] = value;
  906. return true;
  907. }
  908.  
  909. void Creature::gainHealth(Creature* caster, int32_t healthGain)
  910. {
  911. if(healthGain > 0)
  912. {
  913. int32_t prevHealth = getHealth();
  914. changeHealth(healthGain);
  915.  
  916. int32_t effectiveGain = getHealth() - prevHealth;
  917. if(caster)
  918. caster->onTargetCreatureGainHealth(this, effectiveGain);
  919. }
  920. else
  921. changeHealth(healthGain);
  922. }
  923.  
  924. void Creature::drainHealth(Creature* attacker, CombatType_t combatType, int32_t damage)
  925. {
  926. lastDamageSource = combatType;
  927. onAttacked();
  928.  
  929. changeHealth(-damage);
  930. if(attacker)
  931. attacker->onAttackedCreatureDrainHealth(this, damage);
  932. }
  933.  
  934. void Creature::drainMana(Creature* attacker, CombatType_t combatType, int32_t damage)
  935. {
  936. lastDamageSource = combatType;
  937. onAttacked();
  938.  
  939. changeMana(-damage);
  940. if(attacker)
  941. attacker->onAttackedCreatureDrainMana(this, damage);
  942. }
  943.  
  944. BlockType_t Creature::blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage,
  945. bool checkDefense/* = false*/, bool checkArmor/* = false*/, bool /*reflect = true*/)
  946. {
  947. BlockType_t blockType = BLOCK_NONE;
  948. if(isImmune(combatType))
  949. {
  950. damage = 0;
  951. blockType = BLOCK_IMMUNITY;
  952. }
  953. else if(checkDefense || checkArmor)
  954. {
  955. bool hasDefense = false;
  956. if(blockCount > 0)
  957. {
  958. --blockCount;
  959. hasDefense = true;
  960. }
  961.  
  962. if(checkDefense && hasDefense)
  963. {
  964. int32_t maxDefense = getDefense(), minDefense = maxDefense / 2;
  965. damage -= random_range(minDefense, maxDefense);
  966. if(damage <= 0)
  967. {
  968. damage = 0;
  969. blockType = BLOCK_DEFENSE;
  970. checkArmor = false;
  971. }
  972. }
  973.  
  974. if(checkArmor)
  975. {
  976. int32_t armorValue = getArmor(), minArmorReduction = 0,
  977. maxArmorReduction = 0;
  978. if(armorValue > 1)
  979. {
  980. minArmorReduction = (int32_t)std::ceil(armorValue * 0.475);
  981. maxArmorReduction = (int32_t)std::ceil(
  982. ((armorValue * 0.475) - 1) + minArmorReduction);
  983. }
  984. else if(armorValue == 1)
  985. {
  986. minArmorReduction = 1;
  987. maxArmorReduction = 1;
  988. }
  989.  
  990. damage -= random_range(minArmorReduction, maxArmorReduction);
  991. if(damage <= 0)
  992. {
  993. damage = 0;
  994. blockType = BLOCK_ARMOR;
  995. }
  996. }
  997.  
  998. if(hasDefense && blockType != BLOCK_NONE)
  999. onBlockHit(blockType);
  1000. }
  1001.  
  1002. if(attacker)
  1003. {
  1004. attacker->onAttackedCreature(this);
  1005. attacker->onAttackedCreatureBlockHit(this, blockType);
  1006. }
  1007.  
  1008. onAttacked();
  1009. return blockType;
  1010. }
  1011.  
  1012. bool Creature::setAttackedCreature(Creature* creature)
  1013. {
  1014. if(creature)
  1015. {
  1016. const Position& creaturePos = creature->getPosition();
  1017. if(creaturePos.z != getPosition().z || !canSee(creaturePos))
  1018. {
  1019. attackedCreature = NULL;
  1020. return false;
  1021. }
  1022. }
  1023.  
  1024. attackedCreature = creature;
  1025. if(attackedCreature)
  1026. {
  1027. onAttackedCreature(attackedCreature);
  1028. attackedCreature->onAttacked();
  1029. }
  1030.  
  1031. for(std::list<Creature*>::iterator cit = summons.begin(); cit != summons.end(); ++cit)
  1032. (*cit)->setAttackedCreature(creature);
  1033.  
  1034. return true;
  1035. }
  1036.  
  1037. void Creature::getPathSearchParams(const Creature*, FindPathParams& fpp) const
  1038. {
  1039. fpp.fullPathSearch = !hasFollowPath;
  1040. fpp.clearSight = true;
  1041. fpp.maxSearchDist = 12;
  1042. fpp.minTargetDist = fpp.maxTargetDist = 1;
  1043. }
  1044.  
  1045. void Creature::goToFollowCreature()
  1046. {
  1047. if(followCreature)
  1048. {
  1049. FindPathParams fpp;
  1050. getPathSearchParams(followCreature, fpp);
  1051. if(g_game.getPathToEx(this, followCreature->getPosition(), listWalkDir, fpp))
  1052. {
  1053. hasFollowPath = true;
  1054. startAutoWalk(listWalkDir);
  1055. }
  1056. else
  1057. hasFollowPath = false;
  1058. }
  1059.  
  1060. onFollowCreatureComplete(followCreature);
  1061. }
  1062.  
  1063. bool Creature::setFollowCreature(Creature* creature, bool /*fullPathSearch = false*/)
  1064. {
  1065. if(creature)
  1066. {
  1067. if(followCreature == creature)
  1068. return true;
  1069.  
  1070. const Position& creaturePos = creature->getPosition();
  1071. if(creaturePos.z != getPosition().z || !canSee(creaturePos))
  1072. {
  1073. followCreature = NULL;
  1074. return false;
  1075. }
  1076.  
  1077. if(!listWalkDir.empty())
  1078. {
  1079. listWalkDir.clear();
  1080. onWalkAborted();
  1081. }
  1082.  
  1083. hasFollowPath = forceUpdateFollowPath = false;
  1084. followCreature = creature;
  1085. isUpdatingPath = true;
  1086. }
  1087. else
  1088. {
  1089. isUpdatingPath = false;
  1090. followCreature = NULL;
  1091. }
  1092.  
  1093. g_game.updateCreatureWalk(id);
  1094. onFollowCreature(creature);
  1095. return true;
  1096. }
  1097.  
  1098. double Creature::getDamageRatio(Creature* attacker) const
  1099. {
  1100. double totalDamage = 0, attackerDamage = 0;
  1101. for(CountMap::const_iterator it = damageMap.begin(); it != damageMap.end(); ++it)
  1102. {
  1103. totalDamage += it->second.total;
  1104. if(it->first == attacker->getID())
  1105. attackerDamage += it->second.total;
  1106. }
  1107.  
  1108. return attackerDamage / totalDamage;
  1109. }
  1110.  
  1111. void Creature::addDamagePoints(Creature* attacker, int32_t damagePoints)
  1112. {
  1113. uint32_t attackerId = 0;
  1114. if(attacker)
  1115. attackerId = attacker->getID();
  1116.  
  1117. CountMap::iterator it = damageMap.find(attackerId);
  1118. if(it != damageMap.end())
  1119. {
  1120. it->second.ticks = OTSYS_TIME();
  1121. if(damagePoints > 0)
  1122. it->second.total += damagePoints;
  1123. }
  1124. else
  1125. damageMap[attackerId] = CountBlock_t(damagePoints);
  1126.  
  1127. if(damagePoints > 0)
  1128. lastHitCreature = attackerId;
  1129. }
  1130.  
  1131. void Creature::addHealPoints(Creature* caster, int32_t healthPoints)
  1132. {
  1133. if(healthPoints <= 0)
  1134. return;
  1135.  
  1136. uint32_t casterId = 0;
  1137. if(caster)
  1138. casterId = caster->getID();
  1139.  
  1140. CountMap::iterator it = healMap.find(casterId);
  1141. if(it != healMap.end())
  1142. {
  1143. it->second.ticks = OTSYS_TIME();
  1144. it->second.total += healthPoints;
  1145. }
  1146. else
  1147. healMap[casterId] = CountBlock_t(healthPoints);
  1148. }
  1149.  
  1150. void Creature::onAddCondition(ConditionType_t type, bool hadCondition)
  1151. {
  1152. if(type == CONDITION_INVISIBLE)
  1153. {
  1154. if(!hadCondition)
  1155. g_game.internalCreatureChangeVisible(this, VISIBLE_DISAPPEAR);
  1156. }
  1157. else if(type == CONDITION_PARALYZE)
  1158. {
  1159. if(hasCondition(CONDITION_HASTE))
  1160. removeCondition(CONDITION_HASTE);
  1161. }
  1162. else if(type == CONDITION_HASTE)
  1163. {
  1164. if(hasCondition(CONDITION_PARALYZE))
  1165. removeCondition(CONDITION_PARALYZE);
  1166. }
  1167. }
  1168.  
  1169. void Creature::onEndCondition(ConditionType_t type)
  1170. {
  1171. if(type == CONDITION_INVISIBLE && !hasCondition(CONDITION_INVISIBLE, -1, false))
  1172. g_game.internalCreatureChangeVisible(this, VISIBLE_APPEAR);
  1173. }
  1174.  
  1175. void Creature::onTickCondition(ConditionType_t type, int32_t, bool& _remove)
  1176. {
  1177. if(const MagicField* field = getTile()->getFieldItem())
  1178. {
  1179. switch(type)
  1180. {
  1181. case CONDITION_FIRE:
  1182. _remove = field->getCombatType() != COMBAT_FIREDAMAGE;
  1183. break;
  1184. case CONDITION_ENERGY:
  1185. _remove = field->getCombatType() != COMBAT_ENERGYDAMAGE;
  1186. break;
  1187. case CONDITION_POISON:
  1188. _remove = field->getCombatType() != COMBAT_EARTHDAMAGE;
  1189. break;
  1190. case CONDITION_DROWN:
  1191. _remove = field->getCombatType() != COMBAT_DROWNDAMAGE;
  1192. break;
  1193. default:
  1194. break;
  1195. }
  1196. }
  1197. }
  1198.  
  1199. void Creature::onCombatRemoveCondition(const Creature*, Condition* condition)
  1200. {
  1201. removeCondition(condition);
  1202. }
  1203.  
  1204. void Creature::onIdleStatus()
  1205. {
  1206. if(getHealth() > 0)
  1207. {
  1208. healMap.clear();
  1209. damageMap.clear();
  1210. }
  1211. }
  1212.  
  1213. void Creature::onAttackedCreatureDrainHealth(Creature* target, int32_t points)
  1214. {
  1215. onAttackedCreatureDrain(target, points);
  1216. }
  1217.  
  1218. void Creature::onAttackedCreatureDrainMana(Creature* target, int32_t points)
  1219. {
  1220. onAttackedCreatureDrain(target, points);
  1221. }
  1222.  
  1223. void Creature::onAttackedCreatureDrain(Creature* target, int32_t points)
  1224. {
  1225. target->addDamagePoints(this, points);
  1226. }
  1227.  
  1228. void Creature::onTargetCreatureGainHealth(Creature* target, int32_t points)
  1229. {
  1230. target->addHealPoints(this, points);
  1231. }
  1232.  
  1233. void Creature::onAttackedCreatureKilled(Creature* target)
  1234. {
  1235. if(target == this)
  1236. return;
  1237.  
  1238. double gainExp = target->getGainedExperience(this);
  1239. onGainExperience(gainExp, !target->getPlayer(), false);
  1240. }
  1241.  
  1242. bool Creature::onKilledCreature(Creature* target, DeathEntry& entry)
  1243. {
  1244. bool ret = true;
  1245. if(master)
  1246. ret = master->onKilledCreature(target, entry);
  1247.  
  1248. CreatureEventList killEvents = getCreatureEvents(CREATURE_EVENT_KILL);
  1249. if(!entry.isLast())
  1250. {
  1251. for(CreatureEventList::iterator it = killEvents.begin(); it != killEvents.end(); ++it)
  1252. (*it)->executeKill(this, target, entry);
  1253.  
  1254. return true;
  1255. }
  1256.  
  1257. for(CreatureEventList::iterator it = killEvents.begin(); it != killEvents.end(); ++it)
  1258. {
  1259. if(!(*it)->executeKill(this, target, entry) && ret)
  1260. ret = false;
  1261. }
  1262.  
  1263. return ret;
  1264. }
  1265.  
  1266. void Creature::onGainExperience(double& gainExp, bool fromMonster, bool multiplied)
  1267. {
  1268. if(gainExp <= 0)
  1269. return;
  1270.  
  1271. if(master)
  1272. {
  1273. gainExp = gainExp / 2;
  1274. master->onGainExperience(gainExp, fromMonster, multiplied);
  1275. }
  1276. else if(!multiplied)
  1277. gainExp *= g_config.getDouble(ConfigManager::RATE_EXPERIENCE);
  1278.  
  1279. int16_t color = g_config.getNumber(ConfigManager::EXPERIENCE_COLOR);
  1280. if(color < 0)
  1281. color = random_range(0, 255);
  1282.  
  1283. std::stringstream ss;
  1284. ss << (uint64_t)gainExp;
  1285. g_game.addAnimatedText(getPosition(), (uint8_t)color, ss.str());
  1286. }
  1287.  
  1288. void Creature::onGainSharedExperience(double& gainExp, bool fromMonster, bool multiplied)
  1289. {
  1290. if(gainExp <= 0)
  1291. return;
  1292.  
  1293. if(master)
  1294. {
  1295. gainExp = gainExp / 2;
  1296. master->onGainSharedExperience(gainExp, fromMonster, multiplied);
  1297. }
  1298. else if(!multiplied)
  1299. gainExp *= g_config.getDouble(ConfigManager::RATE_EXPERIENCE);
  1300.  
  1301. int16_t color = g_config.getNumber(ConfigManager::EXPERIENCE_COLOR);
  1302. if(color < 0)
  1303. color = random_range(0, 255);
  1304.  
  1305. std::stringstream ss;
  1306. ss << (uint64_t)gainExp;
  1307. g_game.addAnimatedText(getPosition(), (uint8_t)color, ss.str());
  1308. }
  1309.  
  1310. void Creature::addSummon(Creature* creature)
  1311. {
  1312. creature->setDropLoot(LOOT_DROP_NONE);
  1313. creature->setLossSkill(false);
  1314.  
  1315. creature->setMaster(this);
  1316. creature->addRef();
  1317. summons.push_back(creature);
  1318. }
  1319.  
  1320. void Creature::removeSummon(const Creature* creature)
  1321. {
  1322. std::list<Creature*>::iterator it = std::find(summons.begin(), summons.end(), creature);
  1323. if(it == summons.end())
  1324. return;
  1325.  
  1326. (*it)->setMaster(NULL);
  1327. (*it)->unRef();
  1328. summons.erase(it);
  1329. }
  1330.  
  1331. void Creature::destroySummons()
  1332. {
  1333. for(std::list<Creature*>::iterator it = summons.begin(); it != summons.end(); ++it)
  1334. {
  1335. (*it)->setAttackedCreature(NULL);
  1336. (*it)->changeHealth(-(*it)->getHealth());
  1337.  
  1338. (*it)->setMaster(NULL);
  1339. (*it)->unRef();
  1340. }
  1341.  
  1342. summons.clear();
  1343. }
  1344.  
  1345. bool Creature::addCondition(Condition* condition)
  1346. {
  1347. if(!condition)
  1348. return false;
  1349.  
  1350. bool hadCondition = hasCondition(condition->getType(), -1, false);
  1351. if(Condition* previous = getCondition(condition->getType(), condition->getId(), condition->getSubId()))
  1352. {
  1353. previous->addCondition(this, condition);
  1354. delete condition;
  1355. return true;
  1356. }
  1357.  
  1358. if(condition->startCondition(this))
  1359. {
  1360. conditions.push_back(condition);
  1361. onAddCondition(condition->getType(), hadCondition);
  1362. return true;
  1363. }
  1364.  
  1365. delete condition;
  1366. return false;
  1367. }
  1368.  
  1369. bool Creature::addCombatCondition(Condition* condition)
  1370. {
  1371. bool hadCondition = hasCondition(condition->getType(), -1, false);
  1372. //Caution: condition variable could be deleted after the call to addCondition
  1373. ConditionType_t type = condition->getType();
  1374. if(!addCondition(condition))
  1375. return false;
  1376.  
  1377. onAddCombatCondition(type, hadCondition);
  1378. return true;
  1379. }
  1380.  
  1381. void Creature::removeCondition(ConditionType_t type)
  1382. {
  1383. for(ConditionList::iterator it = conditions.begin(); it != conditions.end();)
  1384. {
  1385. if((*it)->getType() != type)
  1386. {
  1387. ++it;
  1388. continue;
  1389. }
  1390.  
  1391. Condition* condition = *it;
  1392. it = conditions.erase(it);
  1393.  
  1394. condition->endCondition(this, CONDITIONEND_ABORT);
  1395. onEndCondition(condition->getType());
  1396. delete condition;
  1397. }
  1398. }
  1399.  
  1400. void Creature::removeCondition(ConditionType_t type, ConditionId_t id)
  1401. {
  1402. for(ConditionList::iterator it = conditions.begin(); it != conditions.end();)
  1403. {
  1404. if((*it)->getType() != type || (*it)->getId() != id)
  1405. {
  1406. ++it;
  1407. continue;
  1408. }
  1409.  
  1410. Condition* condition = *it;
  1411. it = conditions.erase(it);
  1412.  
  1413. condition->endCondition(this, CONDITIONEND_ABORT);
  1414. onEndCondition(condition->getType());
  1415. delete condition;
  1416. }
  1417. }
  1418.  
  1419. void Creature::removeCondition(Condition* condition)
  1420. {
  1421. ConditionList::iterator it = std::find(conditions.begin(), conditions.end(), condition);
  1422. if(it != conditions.end())
  1423. {
  1424. Condition* condition = *it;
  1425. it = conditions.erase(it);
  1426.  
  1427. condition->endCondition(this, CONDITIONEND_ABORT);
  1428. onEndCondition(condition->getType());
  1429. delete condition;
  1430. }
  1431. }
  1432.  
  1433. void Creature::removeCondition(const Creature* attacker, ConditionType_t type)
  1434. {
  1435. ConditionList tmpList = conditions;
  1436. for(ConditionList::iterator it = tmpList.begin(); it != tmpList.end(); ++it)
  1437. {
  1438. if((*it)->getType() == type)
  1439. onCombatRemoveCondition(attacker, *it);
  1440. }
  1441. }
  1442.  
  1443. void Creature::removeConditions(ConditionEnd_t reason, bool onlyPersistent/* = true*/)
  1444. {
  1445. for(ConditionList::iterator it = conditions.begin(); it != conditions.end();)
  1446. {
  1447. if(onlyPersistent && !(*it)->isPersistent())
  1448. {
  1449. ++it;
  1450. continue;
  1451. }
  1452.  
  1453. Condition* condition = *it;
  1454. it = conditions.erase(it);
  1455.  
  1456. condition->endCondition(this, reason);
  1457. onEndCondition(condition->getType());
  1458. delete condition;
  1459. }
  1460. }
  1461.  
  1462. Condition* Creature::getCondition(ConditionType_t type, ConditionId_t id, uint32_t subId/* = 0*/) const
  1463. {
  1464. for(ConditionList::const_iterator it = conditions.begin(); it != conditions.end(); ++it)
  1465. {
  1466. if((*it)->getType() == type && (*it)->getId() == id && (*it)->getSubId() == subId)
  1467. return *it;
  1468. }
  1469.  
  1470. return NULL;
  1471. }
  1472.  
  1473. void Creature::executeConditions(uint32_t interval)
  1474. {
  1475. for(ConditionList::iterator it = conditions.begin(); it != conditions.end();)
  1476. {
  1477. if((*it)->executeCondition(this, interval))
  1478. {
  1479. ++it;
  1480. continue;
  1481. }
  1482.  
  1483. Condition* condition = *it;
  1484. it = conditions.erase(it);
  1485.  
  1486. condition->endCondition(this, CONDITIONEND_TICKS);
  1487. onEndCondition(condition->getType());
  1488. delete condition;
  1489. }
  1490. }
  1491.  
  1492. bool Creature::hasCondition(ConditionType_t type, int32_t subId/* = 0*/, bool checkTime/* = true*/) const
  1493. {
  1494. if(isSuppress(type))
  1495. return false;
  1496.  
  1497. for(ConditionList::const_iterator it = conditions.begin(); it != conditions.end(); ++it)
  1498. {
  1499. if((*it)->getType() != type || (subId != -1 && (*it)->getSubId() != (uint32_t)subId))
  1500. continue;
  1501.  
  1502. if(!checkTime || !(*it)->getEndTime() || (*it)->getEndTime() >= OTSYS_TIME())
  1503. return true;
  1504. }
  1505.  
  1506. return false;
  1507. }
  1508.  
  1509. bool Creature::isImmune(CombatType_t type) const
  1510. {
  1511. return ((getDamageImmunities() & (uint32_t)type) == (uint32_t)type);
  1512. }
  1513.  
  1514. bool Creature::isImmune(ConditionType_t type) const
  1515. {
  1516. return ((getConditionImmunities() & (uint32_t)type) == (uint32_t)type);
  1517. }
  1518.  
  1519. bool Creature::isSuppress(ConditionType_t type) const
  1520. {
  1521. return ((getConditionSuppressions() & (uint32_t)type) == (uint32_t)type);
  1522. }
  1523.  
  1524. std::string Creature::getDescription(int32_t) const
  1525. {
  1526. return "a creature";
  1527. }
  1528.  
  1529. int32_t Creature::getStepDuration(Direction dir) const
  1530. {
  1531. if(dir == NORTHWEST || dir == NORTHEAST || dir == SOUTHWEST || dir == SOUTHEAST)
  1532. return getStepDuration() * 2;
  1533.  
  1534. return getStepDuration();
  1535. }
  1536.  
  1537. int32_t Creature::getStepDuration() const
  1538. {
  1539. if(removed)
  1540. return 0;
  1541.  
  1542. uint32_t stepSpeed = getStepSpeed();
  1543. if(!stepSpeed)
  1544. return 0;
  1545.  
  1546. const Tile* tile = getTile();
  1547. if(!tile || !tile->ground)
  1548. return 0;
  1549.  
  1550. return ((1000 * Item::items[tile->ground->getID()].speed) / stepSpeed) * lastStepCost;
  1551. }
  1552.  
  1553. int64_t Creature::getEventStepTicks(bool onlyDelay/* = false*/) const
  1554. {
  1555. int64_t ret = getWalkDelay();
  1556. if(ret > 0)
  1557. return ret;
  1558.  
  1559. if(!onlyDelay)
  1560. return getStepDuration();
  1561.  
  1562. return 1;
  1563. }
  1564.  
  1565. void Creature::getCreatureLight(LightInfo& light) const
  1566. {
  1567. light = internalLight;
  1568. }
  1569.  
  1570. void Creature::resetLight()
  1571. {
  1572. internalLight.level = internalLight.color = 0;
  1573. }
  1574.  
  1575. bool Creature::registerCreatureEvent(const std::string& name)
  1576. {
  1577. CreatureEvent* event = g_creatureEvents->getEventByName(name);
  1578. if(!event || !event->isLoaded()) //check for existance
  1579. return false;
  1580.  
  1581. for(CreatureEventList::iterator it = eventsList.begin(); it != eventsList.end(); ++it)
  1582. {
  1583. if((*it) == event) //do not allow registration of same event more than once
  1584. return false;
  1585. }
  1586.  
  1587. eventsList.push_back(event);
  1588. return true;
  1589. }
  1590.  
  1591. bool Creature::unregisterCreatureEvent(const std::string& name)
  1592. {
  1593. CreatureEvent* event = g_creatureEvents->getEventByName(name);
  1594. if(!event || !event->isLoaded()) //check for existance
  1595. return false;
  1596.  
  1597. for(CreatureEventList::iterator it = eventsList.begin(); it != eventsList.end(); ++it)
  1598. {
  1599. if((*it) != event)
  1600. continue;
  1601.  
  1602. eventsList.erase(it);
  1603. return true; // we shouldn't have a duplicate
  1604. }
  1605.  
  1606. return false;
  1607. }
  1608.  
  1609. CreatureEventList Creature::getCreatureEvents(CreatureEventType_t type)
  1610. {
  1611. CreatureEventList retList;
  1612. for(CreatureEventList::iterator it = eventsList.begin(); it != eventsList.end(); ++it)
  1613. {
  1614. if((*it)->getEventType() == type && (*it)->isLoaded())
  1615. retList.push_back(*it);
  1616. }
  1617.  
  1618. return retList;
  1619. }
  1620.  
  1621. FrozenPathingConditionCall::FrozenPathingConditionCall(const Position& _targetPos)
  1622. {
  1623. targetPos = _targetPos;
  1624. }
  1625.  
  1626. bool FrozenPathingConditionCall::isInRange(const Position& startPos, const Position& testPos,
  1627. const FindPathParams& fpp) const
  1628. {
  1629. int32_t dxMin = ((fpp.fullPathSearch || (startPos.x - targetPos.x) <= 0) ? fpp.maxTargetDist : 0),
  1630. dxMax = ((fpp.fullPathSearch || (startPos.x - targetPos.x) >= 0) ? fpp.maxTargetDist : 0),
  1631. dyMin = ((fpp.fullPathSearch || (startPos.y - targetPos.y) <= 0) ? fpp.maxTargetDist : 0),
  1632. dyMax = ((fpp.fullPathSearch || (startPos.y - targetPos.y) >= 0) ? fpp.maxTargetDist : 0);
  1633. if(testPos.x > targetPos.x + dxMax || testPos.x < targetPos.x - dxMin)
  1634. return false;
  1635.  
  1636. if(testPos.y > targetPos.y + dyMax || testPos.y < targetPos.y - dyMin)
  1637. return false;
  1638.  
  1639. return true;
  1640. }
  1641.  
  1642. bool FrozenPathingConditionCall::operator()(const Position& startPos, const Position& testPos,
  1643. const FindPathParams& fpp, int32_t& bestMatchDist) const
  1644. {
  1645. if(!isInRange(startPos, testPos, fpp))
  1646. return false;
  1647.  
  1648. if(fpp.clearSight && !g_game.isSightClear(testPos, targetPos, true))
  1649. return false;
  1650.  
  1651. int32_t testDist = std::max(std::abs(targetPos.x - testPos.x), std::abs(targetPos.y - testPos.y));
  1652. if(fpp.maxTargetDist == 1)
  1653. return (testDist >= fpp.minTargetDist && testDist <= fpp.maxTargetDist);
  1654.  
  1655. if(testDist <= fpp.maxTargetDist)
  1656. {
  1657. if(testDist < fpp.minTargetDist)
  1658. return false;
  1659.  
  1660. if(testDist == fpp.maxTargetDist)
  1661. {
  1662. bestMatchDist = 0;
  1663. return true;
  1664. }
  1665. else if(testDist > bestMatchDist)
  1666. {
  1667. //not quite what we want, but the best so far
  1668. bestMatchDist = testDist;
  1669. return true;
  1670. }
  1671. }
  1672.  
  1673. return false;
  1674. }
Advertisement
Add Comment
Please, Sign In to add comment