Guest User

Untitled

a guest
Apr 2nd, 2020
222
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 349.76 KB | None | 0 0
  1. //////////////////////////////////////////////////////////////////////
  2. // OpenTibia - an opensource roleplaying game
  3. //////////////////////////////////////////////////////////////////////
  4. // class representing the gamestate
  5. //////////////////////////////////////////////////////////////////////
  6. // This program is free software; you can redistribute it and/or
  7. // modify it under the terms of the GNU General Public License
  8. // as published by the Free Software Foundation; either version 2
  9. // of the License, or (at your option) any later version.
  10. //
  11. // This program is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU General Public License
  17. // along with this program; if not, write to the Free Software Foundation,
  18. // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. //////////////////////////////////////////////////////////////////////
  20.  
  21.  
  22. #include "patch.h"
  23. #include "definitions.h"
  24. #include <string>
  25. #include <sstream>
  26. #include <fstream>
  27. #include <ctime> //You may need to use ctime.h or time.h if this doesn't work.
  28.  
  29. #include <map>
  30. //#include <algorithm>
  31.  
  32. #ifdef __DEBUG_CRITICALSECTION__
  33. #include <iostream>
  34. #include <fstream>
  35. #endif
  36.  
  37. #include <boost/config.hpp>
  38. #include <boost/bind.hpp>
  39.  
  40. using namespace std;
  41.  
  42. #include <stdio.h>
  43. #include "otsystem.h"
  44. #include "items.h"
  45. #include "commands.h"
  46. #include "creature.h"
  47. #include "player.h"
  48. #include "monster.h"
  49. #include "npc.h"
  50. #include "game.h"
  51. #include "tile.h"
  52.  
  53. #include "spells.h"
  54. #include "actions.h"
  55. #include "ioplayer.h"
  56. #include "ioaccount.h"
  57. #include "chat.h"
  58. #include "status.h"
  59.  
  60. #include "luascript.h"
  61. #include "templates.h"
  62. #include "houses.h"
  63. #include "summons.h"
  64. #include "pvparena.h"
  65. #include <ctype.h>
  66. #if defined __EXCEPTION_TRACER__
  67. #include "exception.h"
  68. extern OTSYS_THREAD_LOCKVAR maploadlock;
  69. #endif
  70.  
  71. #define EVENT_CHECKCREATURE 123
  72. #define EVENT_CHECKCREATUREATTACKING 124
  73.  
  74. extern LuaScript g_config;
  75. extern Spells spells;
  76. extern Actions actions;
  77. extern Commands commands;
  78. extern Chat g_chat;
  79. extern xmlMutexPtr xmlmutex;
  80.  
  81. extern std::vector< std::pair<uint32_t, uint32_t> > bannedIPs;
  82.  
  83. GameState::GameState(Game *game, const Range &range)
  84. {
  85. this->game = game;
  86. game->getSpectators(range, spectatorlist);
  87. }
  88.  
  89. bool is_poof;
  90.  
  91. #ifdef YUR_PVP_ARENA
  92. bool GameState::isPvpArena(Creature* c)
  93. {
  94. if (!c)
  95. return false;
  96. Tile *tile = game->map->getTile(c->pos);
  97. return tile && tile->isPvpArena();
  98. }
  99. #endif //YUR_PVP_ARENA
  100.  
  101. #ifdef YUR_RINGS_AMULETS
  102. int32_t GameState::applyAmulets(Player* player, int32_t damage, attacktype_t atype)
  103. {
  104. if (!player || atype == ATTACK_NONE)
  105. return damage;
  106.  
  107. double newDamage = (double)damage;
  108. Item* necklace = player->getItem(SLOT_NECKLACE);
  109. Item* ring = player->getItem(SLOT_RING);
  110. Item* armor = player->getItem(SLOT_ARMOR);
  111.  
  112. if (necklace && necklace->getCharges() > 0)
  113. {
  114. if (necklace->getID() == ITEM_STONE_SKIN_AMULET)
  115. {
  116. newDamage *= 0.10;
  117. necklace->useCharge();
  118. }
  119.  
  120. else if (necklace->getID() == ITEM_PROTECTION_AMULET)
  121. {
  122. newDamage *= 0.80;
  123. necklace->useCharge();
  124. }
  125.  
  126. else if ((necklace->getID() == ITEM_DRAGON_NECKLACE && (atype & ATTACK_FIRE)) ||
  127. (necklace->getID() == ITEM_SILVER_AMULET && (atype & ATTACK_POISON)) ||
  128. (necklace->getID() == ITEM_STRANGE_TALISMAN && (atype & ATTACK_ENERGY)) ||
  129. (necklace->getID() == ITEM_ELVEN_AMULET))
  130. {
  131. newDamage *= 0.8;
  132. necklace->useCharge();
  133. }
  134.  
  135.  
  136. else if ((necklace->getID() == ITEM_MAGMA_AMULET && (atype & ATTACK_FIRE)))
  137. {
  138. newDamage *= 0.7;
  139. necklace->useCharge();
  140. }
  141.  
  142.  
  143. #ifdef YUR_DRAINS
  144. else if (necklace->getID() == ITEM_BRONZE_AMULET && (atype & ATTACK_MANADRAIN))
  145. {
  146. newDamage *= 0.5;
  147. necklace->useCharge();
  148. }
  149.  
  150. else if (necklace->getID() == ITEM_GARLIC_NECKLACE && (atype & ATTACK_LIFEDRAIN))
  151. {
  152. newDamage = 0.5;
  153. necklace->useCharge();
  154. }
  155.  
  156. #endif //YUR_DRAINS
  157.  
  158. if (necklace->getCharges() <= 0)
  159. player->removeItemInventory(SLOT_NECKLACE);
  160. }
  161.  
  162. if (ring && ring->getCharges() > 0)
  163. {
  164. if (ring->getID() == ITEM_MIGHT_RING)
  165. {
  166. newDamage *= 0.8;
  167. ring->useCharge();
  168. }
  169.  
  170. if (ring->getCharges() <= 0)
  171. player->removeItemInventory(SLOT_RING);
  172. }
  173. #ifdef HUCZU_FIX
  174. if(armor)
  175. {
  176. if(armor->getID() == ITEM_FIRE_ARMOR && (atype & ATTACK_FIRE))
  177. newDamage *= 0.8;
  178. }
  179. #endif //HUCZU_FIX
  180.  
  181. return (int32_t)newDamage;
  182. }
  183. #endif //YUR_RINGS_AMULETS
  184.  
  185. void GameState::onAttack(Creature* attacker, const Position& pos, const MagicEffectClass* me)
  186. {
  187. Tile *tile = game->map->getTile(pos);
  188.  
  189. if(!tile)
  190. return;
  191.  
  192. #ifdef YUR_PVP_ARENA
  193. CreatureVector arenaLosers;
  194. #endif //YUR_PVP_ARENA
  195.  
  196. CreatureVector::iterator cit;
  197. Player* attackPlayer = dynamic_cast<Player*>(attacker);
  198. Creature *targetCreature = NULL;
  199. Player *targetPlayer = NULL;
  200. for(cit = tile->creatures.begin(); cit != tile->creatures.end(); ++cit) {
  201. targetCreature = (*cit);
  202. targetPlayer = dynamic_cast<Player*>(targetCreature);
  203. bool pvpArena = false;
  204. #ifdef TR_SUMMONS
  205. bool targetIsSummon = (targetCreature && targetCreature->isPlayersSummon());
  206. bool summonVsPlayer = (attacker && attacker->isPlayersSummon() && targetPlayer);
  207. #endif //TR_SUMMONS
  208.  
  209. int32_t damage = me->getDamage(targetCreature, attacker);
  210. int32_t manaDamage = 0;
  211.  
  212. if(attackPlayer){
  213. if(!me->offensive && me->minDamage != 0 && g_config.getGlobalString("showHealingDamage") == "yes"){
  214. int32_t lecz = std::min(std::abs(damage), attackPlayer->healthmax - attackPlayer->health);
  215. std::stringstream anidamage;
  216. anidamage << "+" << lecz;
  217. if(lecz != 0)
  218. game->sendAnimatedTextExt(attackPlayer->pos, 96, anidamage.str().c_str());
  219. }
  220. }
  221.  
  222. #ifdef YUR_RINGS_AMULETS
  223. damage = applyAmulets(targetPlayer, damage, me->attackType);
  224. #endif //YUR_RINGS_AMULETS
  225.  
  226. if (damage > 0) {
  227. if(attackPlayer && attackPlayer->access < g_config.ACCESS_PROTECT) {
  228. if(targetPlayer && targetPlayer != attackPlayer && game->getWorldType() != WORLD_TYPE_NO_PVP)
  229. attackPlayer->pzLocked = true;
  230. }
  231.  
  232. if(targetCreature->access < g_config.ACCESS_PROTECT && targetPlayer && game->getWorldType() != WORLD_TYPE_NO_PVP)
  233. {
  234. #ifdef YUR_CVS_MODS
  235. targetPlayer->inFightTicks = std::max(g_config.PZ_LOCKED, targetPlayer->inFightTicks);
  236. #else
  237. targetPlayer->inFightTicks = g_config.PZ_LOCKED;
  238. #endif //YUR_CVS_MODS
  239. targetPlayer->sendIcons();
  240. }
  241. #ifdef SURVIVAL_BLACKSQUARE
  242. if(damage > 0 && attackPlayer && targetPlayer && attackPlayer != targetPlayer){
  243. NetworkMessage attackedpmsg;
  244. attackedpmsg.AddPlayerAttacked(attacker);
  245. targetPlayer->sendNetworkMessage(&attackedpmsg);
  246. }
  247. #endif //SURVIVAL_BLACKSQUARE
  248.  
  249. #ifdef YUR_PVP_ARENA
  250. pvpArena = isPvpArena(attacker) && isPvpArena(targetCreature);
  251. #endif //YUR_PVP_ARENA
  252.  
  253. #ifdef TR_SUMMONS
  254. if ((game->getWorldType() == WORLD_TYPE_NO_PVP && !pvpArena && summonVsPlayer) ||
  255. (game->getWorldType() == WORLD_TYPE_NO_PVP && !pvpArena && attackPlayer && (targetPlayer || targetIsSummon) && attackPlayer->access < g_config.ACCESS_PROTECT)) {
  256. #else
  257. if(game->getWorldType() == WORLD_TYPE_NO_PVP && !pvpArena && attackPlayer && targetPlayer && attackPlayer->access < ACCESS_PROTECT){
  258. #endif //TR_SUMMONS
  259. damage = 0;
  260. }
  261. }
  262.  
  263. if (damage != 0)
  264. {
  265. // Bedzie pro ustawione all
  266. #ifdef HUCZU_FIX
  267. if(attackPlayer){
  268. Item* armor = attackPlayer->getItem(SLOT_ARMOR);
  269. Item* legs = attackPlayer->getItem(SLOT_LEGS);
  270. Item* helmet = attackPlayer->getItem(SLOT_HEAD);
  271. Item* boots = attackPlayer->getItem(SLOT_FEET);
  272. Item* ring = attackPlayer->getItem(SLOT_RING);
  273. Item* amulet = attackPlayer->getItem(SLOT_NECKLACE);
  274.  
  275. if(attackPlayer->vocation == 1 || attackPlayer->vocation == 2){
  276. if(armor){
  277. if(armor->getID() == ITEM_GLACIER_ROBE){
  278. double newdamage = damage*2/100.0;
  279. damage += (int32_t)newdamage;
  280. }
  281. else if(armor->getID() == ITEM_ARCHMAGE_COAT){
  282. double newdamage = damage*5/100.0;
  283. damage += (int32_t)newdamage;
  284. }
  285. else if(armor->getID() == ITEM_BMC){
  286. double newdamage = damage*3/100.0;
  287. damage += (int32_t)newdamage;
  288. }
  289. }
  290. if(legs){
  291. if(legs->getID() == ITEM_GLACIER_KIT){
  292. double newdamage = damage*2/100.0;
  293. damage += (int32_t)newdamage;
  294. }
  295. }
  296. }
  297.  
  298. if(legs){
  299. if(legs->getID() == ITEM_ZS_LEGS){
  300. double newdamage = damage*10/100.0;
  301. damage += (int32_t)newdamage;
  302. }
  303. }
  304.  
  305. if(g_config.MGITEMS){
  306. if(helmet && helmet->getID() == g_config.MGITEMHELMET){
  307. double newdamage = damage*g_config.ITEM_MDOWNHELMET/100.0;
  308. damage += (int32_t)newdamage;
  309. }
  310. if(armor && armor->getID() == g_config.MGITEMARMOR){
  311. double newdamage = damage*g_config.ITEM_MDOWNARMOR/100.0;
  312. damage += (int32_t)newdamage;
  313. }
  314. if(legs && legs->getID() == g_config.MGITEMLEGS){
  315. double newdamage = damage*g_config.ITEM_MDOWNLEGS/100.0;
  316. damage += (int32_t)newdamage;
  317. }
  318. if(boots && boots->getID() == g_config.MGITEMBOOTS){
  319. double newdamage = damage*g_config.ITEM_MDOWNBOOTS/100.0;
  320. damage += (int32_t)newdamage;
  321. }
  322. if(ring && ring->getID() == g_config.MGITEMRINGS){
  323. double newdamage = damage*g_config.ITEM_MDOWNRING/100.0;
  324. damage += (int32_t)newdamage;
  325. }
  326. if(amulet && amulet->getID() == g_config.MGITEMAMU){
  327. double newdamage = damage*g_config.ITEM_MDOWNAMU/100.0;
  328. damage += (int32_t)newdamage;
  329. }
  330. }
  331. }
  332. #endif //HUCZU_FIX i git w chuj
  333.  
  334. #ifdef YUR_DRAINS
  335. if (me->attackType & ATTACK_MANADRAIN)
  336. {
  337. manaDamage = std::min(damage, targetCreature->mana);
  338. targetCreature->drainMana(manaDamage);
  339. damage = 0;
  340. }
  341. else
  342. #endif //YUR_DRAINS
  343. {
  344. game->creatureApplyDamage(targetCreature, damage, damage, manaDamage
  345. #ifdef YUR_PVP_ARENA
  346. , (pvpArena? &arenaLosers : NULL)
  347. #endif //YUR_PVP_ARENA
  348. );
  349. }
  350.  
  351. #ifdef YUR_DRAINS
  352. if (me->attackType & ATTACK_LIFEDRAIN)
  353. {
  354. attacker->health = std::min(attacker->healthmax, attacker->health + damage);
  355. addCreatureState(tile, attacker, 0, 0, false); // update attacker health
  356. }
  357. #endif //YUR_DRAINS
  358.  
  359. #ifdef YUR_INVISIBLE
  360. if (targetCreature && !targetPlayer)
  361. {
  362. targetCreature->setInvisible(0);
  363. game->creatureChangeOutfit(targetCreature);
  364. }
  365. #endif //YUR_INVISIBLE
  366. }
  367.  
  368. #ifdef HUCZU_SKULLS
  369. if (me->offensive && game->getWorldType() == WORLD_TYPE_PVP)
  370. game->onPvP(attacker, targetCreature, targetCreature->health <= 0);
  371. #endif
  372.  
  373. addCreatureState(tile, targetCreature, damage, manaDamage, me->drawblood);
  374. }
  375.  
  376. //Solid ground items/Magic items (fire/poison/energy)
  377. MagicEffectItem *newmagicItem = me->getMagicItem(attacker, tile->isPz(),
  378. (tile->isBlocking(BLOCK_SOLID, true) != RET_NOERROR));
  379.  
  380. if(newmagicItem) {
  381.  
  382. MagicEffectItem *magicItem = tile->getFieldItem();
  383.  
  384. if(magicItem) {
  385. //Replace existing magic field
  386. magicItem->transform(newmagicItem);
  387.  
  388. int32_t stackpos = tile->getThingStackPos(magicItem);
  389. if(tile->removeThing(magicItem)) {
  390.  
  391. SpectatorVec list;
  392. SpectatorVec::iterator it;
  393.  
  394. game->getSpectators(Range(pos, true), list);
  395.  
  396. //players
  397. for(it = list.begin(); it != list.end(); ++it) {
  398. if(dynamic_cast<Player*>(*it)) {
  399. (*it)->onThingDisappear(magicItem, stackpos);
  400. }
  401. }
  402.  
  403. //none-players
  404. for(it = list.begin(); it != list.end(); ++it) {
  405. if(!dynamic_cast<Player*>(*it)) {
  406. (*it)->onThingDisappear(magicItem, stackpos);
  407. }
  408. }
  409.  
  410. tile->addThing(magicItem);
  411.  
  412. //players
  413. for(it = list.begin(); it != list.end(); ++it) {
  414. if(dynamic_cast<Player*>(*it)) {
  415. (*it)->onThingAppear(magicItem);
  416. }
  417. }
  418.  
  419. //none-players
  420. for(it = list.begin(); it != list.end(); ++it) {
  421. if(!dynamic_cast<Player*>(*it)) {
  422. (*it)->onThingAppear(magicItem);
  423. }
  424. }
  425. }
  426. }
  427. else {
  428. magicItem = new MagicEffectItem(*newmagicItem);
  429. magicItem->useThing();
  430. magicItem->pos = pos;
  431.  
  432. tile->addThing(magicItem);
  433.  
  434. SpectatorVec list;
  435. SpectatorVec::iterator it;
  436.  
  437. game->getSpectators(Range(pos, true), list);
  438.  
  439. //players
  440. for(it = list.begin(); it != list.end(); ++it) {
  441. if(dynamic_cast<Player*>(*it)) {
  442. (*it)->onThingAppear(magicItem);
  443. }
  444. }
  445.  
  446. //none-players
  447. for(it = list.begin(); it != list.end(); ++it) {
  448. if(!dynamic_cast<Player*>(*it)) {
  449. (*it)->onThingAppear(magicItem);
  450. }
  451. }
  452.  
  453. magicItem->isRemoved = false;
  454. game->startDecay(magicItem);
  455. }
  456. }
  457.  
  458. //Clean up
  459. for(CreatureStateVec::const_iterator csIt = creaturestates[tile].begin(); csIt != creaturestates[tile].end(); ++csIt) {
  460. onAttackedCreature(tile, attacker, csIt->first, csIt->second.damage, csIt->second.drawBlood);
  461. }
  462.  
  463. if(attackPlayer && attackPlayer->access < g_config.ACCESS_PROTECT) {
  464. //Add exhaustion
  465. if(me->causeExhaustion(true) /*!areaTargetVec.empty())*/)
  466. {
  467. attackPlayer->exhaustedTicks = g_config.EXHAUSTED;
  468. }
  469.  
  470. //Fight symbol
  471. if(me->offensive /*&& !areaTargetVec.empty()*/)
  472. {
  473. #ifdef YUR_CVS_MODS
  474. attackPlayer->inFightTicks = std::max(g_config.PZ_LOCKED, attackPlayer->inFightTicks);
  475. #else
  476. attackPlayer->inFightTicks = g_config.PZ_LOCKED;
  477. #endif //YUR_CVS_MODS
  478. }
  479. }
  480.  
  481. #ifdef YUR_PVP_ARENA
  482. for (CreatureVector::iterator it = arenaLosers.begin(); it != arenaLosers.end(); ++it)
  483. {
  484. Tile* tile = game->getTile((*it)->pos);
  485.  
  486. if (tile)
  487. {
  488. game->teleport(*it, tile->getPvpArenaExit());
  489. }
  490.  
  491. if(Monster* monster = dynamic_cast<Monster*>(*it))
  492. {
  493. if(Tile *tile = game->map->getTile(monster->pos))
  494. {
  495. if(tile->isPvpArena())
  496. {
  497. game->removeCreature(monster);
  498. }
  499. }
  500. }
  501. }
  502. #endif //YUR_PVP_ARENA
  503. }
  504.  
  505. void GameState::onAttack(Creature* attacker, const Position& pos, Creature* attackedCreature)
  506. {
  507. bool pvpArena = false;
  508. #ifdef YUR_PVP_ARENA
  509. CreatureVector arenaLosers;
  510. pvpArena = isPvpArena(attacker) && isPvpArena(attackedCreature);
  511. #endif //YUR_PVP_ARENA
  512.  
  513. //TODO: Decent formulas and such...
  514. int32_t damage = attacker->getWeaponDamage();
  515. int32_t armor = attackedCreature->getArmor();
  516. int32_t defense = attackedCreature->getDefense();
  517.  
  518. Player* attackPlayer = dynamic_cast<Player*>(attacker);
  519. Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  520.  
  521. if(attackedPlayer)
  522. attackedPlayer->addSkillShieldTry(1);
  523.  
  524. int32_t probability = rand() % 10000;
  525.  
  526. #ifdef YUR_CVS_MODS
  527. if(probability * damage < defense * 3000)
  528. damage = 0;
  529. else
  530. damage -= (int32_t)((damage*(armor/50.0)*(rand()/(RAND_MAX+1.0))) + (armor*2) + defense/1.5);
  531. //damage -= (int32_t)((armor)*(rand()/(RAND_MAX+1.0))) + armor; // wik's
  532. #else
  533. if(probability * damage < defense * 10000)
  534. damage = 0;
  535. else
  536. {
  537. damage -= (armor * (10000 + rand() % 10000)) / 10000;
  538. }
  539. #endif //YUR_CVS_MODS
  540.  
  541. int32_t manaDamage = 0;
  542.  
  543. if(attackPlayer && attackedPlayer){
  544. damage -= (int32_t) damage / 2;
  545. }
  546.  
  547.  
  548. if (attacker->access >= g_config.ACCESS_PROTECT)
  549. damage += 1;
  550.  
  551.  
  552. Tile* tile = game->map->getTile(pos);
  553. bool blood;
  554. if(damage > 0)
  555. {
  556. // F-AXE,F-SWORD,P-DAGGER
  557. if(attackPlayer)
  558. {
  559. for (int32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++)
  560. {
  561. if(g_config.EFFECT_ATACK && attackPlayer->getItem(slot) && (attackPlayer->getItem(slot)->getID() == ITEM_FAXE || attackPlayer->getItem(slot)->getID() == ITEM_FSWORD))
  562. {
  563. game->CreateCondition(attackedCreature, attacker, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 5, 5, 2000, 1);
  564. }
  565. if(g_config.EFFECT_ATACK && attackPlayer->getItem(slot) && (attackPlayer->getItem(slot)->getID() == ITEM_PD))
  566. {
  567. game->CreateCondition(attackedCreature, attacker, 30, NM_ME_POISEN_RINGS, NM_ME_POISEN_RINGS, ATTACK_POISON, true, 5, 5, 2000, 3);
  568. }
  569. }
  570. }
  571.  
  572. // P-BOLT ENERGY
  573. if(attackPlayer)
  574. {
  575. int32_t slot = SLOT_AMMO;
  576. if(g_config.EFFECT_ATACK && attackPlayer->getItem(slot) && (attackPlayer->getItem(slot)->getID() == 5260))
  577. {
  578. game->CreateCondition(attackedCreature, attacker, 35, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 10, 10, 2000, 1);
  579. }
  580. }
  581.  
  582. #ifdef YUR_ICE_RAPIER
  583. if (attackPlayer)
  584. for (int32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++)
  585. if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->getID() == ITEM_ICE_RAPIER)
  586. attackPlayer->removeItemInventory(slot);
  587. #endif //YUR_ICE_RAPIER
  588.  
  589. #ifdef PALL_REQ_LVL
  590. if (attackPlayer){
  591. for (int32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++){
  592. if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->isWeapon() && attackPlayer->getItem(slot)->getReqLevel() > attackPlayer->getLevel())
  593. {
  594. int32_t newdamage = attackPlayer->getWeaponDamage() / random_range(4, 7);
  595. if (attackPlayer->getWeaponDamage() >= 7)
  596. damage = 0;
  597. else
  598. damage = newdamage;
  599. }
  600. if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->getAmuType() != 0 && attackPlayer->getItem(slot)->getReqLevel() > attackPlayer->getLevel())
  601. {
  602. int32_t newdamage = attackPlayer->getWeaponDamage() / random_range(4, 7);
  603. if (attackPlayer->getWeaponDamage() >= 7)
  604. damage = 0;
  605. else
  606. damage = newdamage;
  607. }
  608. if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->isWeapon() && attackPlayer->getItem(slot)->getReqVoc() != attackPlayer->getVocation() && attackPlayer->getItem(slot)->getReqVoc() > 0)
  609. {
  610. int32_t newdamage = attackPlayer->getWeaponDamage() / random_range(4, 9);
  611. if (attackPlayer->getWeaponDamage() >= 7)
  612. damage = 0;
  613. else
  614. damage = newdamage;
  615. }
  616. }
  617. }
  618. #endif //PALL_REQ_LVL
  619.  
  620. if(attackPlayer && attackPlayer->getVocation() == VOCATION_PALADIN) {
  621. damage += damage * (0.01 * (double)g_config.PALADIN_RAISE);
  622.  
  623. }
  624. if(attackPlayer && attackPlayer->getVocation() == VOCATION_KNIGHT) {
  625. damage = damage * (uint32_t)g_config.KNIGHT_LOOSE / 100;
  626. }
  627. #ifdef YUR_RINGS_AMULETS
  628. damage = applyAmulets(attackedPlayer, damage, ATTACK_PHYSICAL);
  629. #endif //YUR_RINGS_AMULETS
  630.  
  631.  
  632. #ifdef CHRIS_CRIT_HIT
  633. if(attackPlayer){
  634. int32_t critcial_hit;
  635. int32_t rand_hit = random_range(0, 700);
  636. switch(rand_hit){
  637. case 75:
  638. critcial_hit = random_range(50, 100);
  639. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  640. break;
  641. case 87:
  642. critcial_hit = random_range(50, 100);
  643. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  644. break;
  645. case 95:
  646. critcial_hit = random_range(50, 100);
  647. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  648. break;
  649. case 113:
  650. critcial_hit = random_range(80, 130);
  651. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  652. break;
  653. case 128:
  654. critcial_hit = random_range(80, 130);
  655. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  656. break;
  657. case 133:
  658. critcial_hit = random_range(80, 130);
  659. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  660. break;
  661. case 145:
  662. critcial_hit = random_range(80, 130);
  663. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  664. break;
  665. case 157:
  666. critcial_hit = random_range(80, 130);
  667. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  668. break;
  669. case 167:
  670. critcial_hit = random_range(80, 130);
  671. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  672. break;
  673. case 187:
  674. critcial_hit = random_range(80, 130);
  675. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  676. break;
  677. case 195:
  678. critcial_hit = random_range(80, 130);
  679. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  680. break;
  681. case 202:
  682. critcial_hit = random_range(110, 160);
  683. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  684. break;
  685. case 225:
  686. critcial_hit = random_range(110, 160);
  687. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  688. break;
  689. case 238:
  690. critcial_hit = random_range(110, 160);
  691. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  692. break;
  693. case 245:
  694. critcial_hit = random_range(110, 160);
  695. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  696. break;
  697. case 268:
  698. critcial_hit = random_range(110, 160);
  699. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  700. break;
  701. case 287:
  702. critcial_hit = random_range(110, 160);
  703. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  704. break;
  705. case 298:
  706. critcial_hit = random_range(110, 160);
  707. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  708. break;
  709. case 324:
  710. critcial_hit = random_range(140, 400);
  711. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  712. break;
  713. case 356:
  714. critcial_hit = random_range(140, 190);
  715. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  716. break;
  717. case 371:
  718. critcial_hit = random_range(140, 190);
  719. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  720. break;
  721. case 380:
  722. critcial_hit = random_range(140, 190);
  723. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  724. break;
  725. case 397:
  726. critcial_hit = random_range(140, 190);
  727. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  728. break;
  729. case 399:
  730. critcial_hit = random_range(140, 190);
  731. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  732. break;
  733. case 400:
  734. critcial_hit = random_range(170, 210);
  735. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  736. break;
  737. case 428:
  738. critcial_hit = random_range(170, 210);
  739. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  740. break;
  741. case 432:
  742. critcial_hit = random_range(170, 210);
  743. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  744. break;
  745. case 444:
  746. critcial_hit = random_range(170, 210);
  747. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  748. break;
  749. case 474:
  750. critcial_hit = random_range(170, 210);
  751. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  752. break;
  753. default:
  754. critcial_hit = 0;
  755. break;
  756. }
  757.  
  758. if (attackPlayer->vocation == 4){
  759. if(critcial_hit != 0){
  760. if(attackPlayer->level >= 150){
  761. if(attackPlayer && attackPlayer->items[SLOT_RIGHT] && attackPlayer->items[SLOT_RIGHT]->getID() == ITEM_RAINBOW){
  762. if(attackPlayer->items[SLOT_LEFT]){
  763. if(attackPlayer->items[SLOT_LEFT]->getID() != ITEM_RAINBOW)
  764. critcial_hit += critcial_hit*(25/100);
  765. game->CreateCondition(attackedCreature, attacker, 35, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 25, 25, 1000, 1);
  766. }
  767. }
  768. }
  769. if(attackPlayer && attackPlayer->items[SLOT_LEFT] && attackPlayer->items[SLOT_LEFT]->getID() == ITEM_RAINBOW){
  770. if(attackPlayer->items[SLOT_RIGHT]){
  771. if(attackPlayer->items[SLOT_RIGHT]->getID() != ITEM_RAINBOW)
  772. critcial_hit += critcial_hit*(25/100);
  773. game->CreateCondition(attackedCreature, attacker, 35, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 25, 25, 1000, 1);
  774. }
  775. }
  776. }
  777. damage += critcial_hit;
  778. }
  779. }
  780.  
  781. #endif //CHRIS_CRIT_HIT
  782.  
  783. game->creatureApplyDamage(attackedCreature, damage, damage, manaDamage
  784.  
  785.  
  786. #ifdef YUR_PVP_ARENA
  787. , (pvpArena? &arenaLosers : NULL)
  788. #endif //YUR_PVP_ARENA
  789. );
  790.  
  791. #ifdef HUCZU_SKULLS
  792. if (game->getWorldType() == WORLD_TYPE_PVP)
  793. game->onPvP(attacker, attackedCreature, attackedCreature->health <= 0);
  794. #endif
  795.  
  796. blood = true;
  797.  
  798. if(attackPlayer && attackPlayer->maxDmg < damage) {
  799. attackPlayer->maxDmg = (int32_t) damage;
  800. std::stringstream MaxDmgMsg;
  801. MaxDmgMsg << "Your new best damage is " << attackPlayer->maxDmg << ".";
  802. attackPlayer->sendTextMessage(MSG_ADVANCE, MaxDmgMsg.str().c_str());
  803. }
  804. }
  805. else{//no draw blood
  806. blood = false;
  807. }
  808.  
  809. addCreatureState(tile, attackedCreature, damage, manaDamage, blood);
  810. onAttackedCreature(tile, attacker, attackedCreature, damage, true);
  811.  
  812. /*
  813. if (attackPlayer && attackPlayer->isUsingSpears() && random_range(1,100000) > g_config.SPEAR_LOSE_CHANCE)
  814. {
  815. Item* spear = Item::CreateItem(ITEM_SPEAR, 1);
  816. spear->pos = attackedCreature->pos;
  817. game->addThing(attackPlayer, spear->pos, spear);
  818. }
  819. */
  820.  
  821. #ifdef YUR_PVP_ARENA
  822. for (CreatureVector::iterator it = arenaLosers.begin(); it != arenaLosers.end(); ++it){
  823. Tile* tile = game->getTile((*it)->pos);
  824. if (tile){
  825. game->teleport(*it, tile->getPvpArenaExit());
  826. }
  827. if(Monster* monster = dynamic_cast<Monster*>(*it)){
  828. if(Tile *tile = game->map->getTile(monster->pos)){
  829. if(tile->isPvpArena()){
  830. game->removeCreature(monster);
  831. }
  832. }
  833. }
  834. }
  835. #endif //YUR_PVP_ARENA
  836. }
  837.  
  838. void GameState::addCreatureState(Tile* tile, Creature* attackedCreature, int32_t damage, int32_t manaDamage, bool drawBlood)
  839. {
  840. CreatureState cs;
  841. cs.damage = damage;
  842. cs.manaDamage = manaDamage;
  843. cs.drawBlood = drawBlood;
  844.  
  845. creaturestates[tile].push_back( make_pair(attackedCreature, cs) );
  846. }
  847.  
  848. void GameState::onAttackedCreature(Tile* tile, Creature *attacker, Creature* attackedCreature, int32_t damage, bool drawBlood)
  849. {
  850. Player *attackedplayer = dynamic_cast<Player*>(attackedCreature);
  851. Position CreaturePos = attackedCreature->pos;
  852.  
  853. #ifdef TJ_MONSTER_BLOOD
  854. bool dead = false;
  855. #endif //TJ_MONSTER_BLOOD
  856.  
  857. #ifdef TR_SUMMONS
  858. //Summon exp share by Yurez
  859. Player *player = dynamic_cast<Player*>(attacker);
  860. Creature* attackerMaster = attacker? attacker->getMaster() : NULL;
  861. if(attackerMaster && dynamic_cast<Player*>(attackerMaster)){//attacker is players summon
  862. attackedCreature->addInflictedDamage(attacker, damage/2);
  863. attackedCreature->addInflictedDamage(attackerMaster, damage/2);
  864. }// end summon exp share
  865. else if(player && player->party != 0){
  866. int32_t partySize = 0;
  867. SpectatorVec list;
  868. SpectatorVec::iterator it;
  869. game->getSpectators(Range(player->pos), list);
  870. /*Get all specatators around this player
  871. then check if they are in his party*/
  872. for(it = list.begin(); it != list.end(); ++it){//find number too div by
  873. Player* p = dynamic_cast<Player*>(*it);
  874. if(p && p->party == player->party)//huczu_fix
  875. partySize++;
  876. }
  877. for(it = list.begin(); it != list.end(); ++it){
  878. Player* p = dynamic_cast<Player*>(*it);
  879. if(p && p->party == player->party && partySize != 0/*dont div by 0*/)//same party add exp, huczu_fix
  880. attackedCreature->addInflictedDamage(p, damage/partySize);
  881. }
  882. }
  883. else
  884. attackedCreature->addInflictedDamage(attacker, damage);
  885. #endif //TR_SUMMONS
  886.  
  887. if(attackedplayer){
  888. attackedplayer->sendStats();
  889. }
  890. //Remove player?
  891. if(attackedCreature->health <= 0 && attackedCreature->isRemoved == false)
  892. {
  893. #ifdef TJ_MONSTER_BLOOD
  894. dead = true;
  895. #endif //TJ_MONSTER_BLOOD
  896. #ifdef JD_DEATH_LIST
  897. if (attackedplayer && attacker)
  898. attackedplayer->addDeath(attacker->getName(), attackedplayer->level, time(0));
  899. #endif //JD_DEATH_LIST
  900. unsigned char stackpos = tile->getThingStackPos(attackedCreature);
  901.  
  902.  
  903. //tasksys
  904. Player* attackingplayer = dynamic_cast<Player*>(attacker);
  905. if(attackingplayer && attackedCreature->getName() == attackingplayer->taskmonster && attackingplayer->taskcount < attackingplayer->taskmax)
  906. {
  907. // attackingplayer->taskcount++;
  908. std::stringstream info;
  909. std::string mons = attackingplayer->taskmonster;
  910. std::transform(mons.begin(), mons.end(), mons.begin(), (int(*)(int))tolower);
  911.  
  912. if(attackingplayer->taskcount < attackingplayer->taskmax)
  913. {
  914. info << "You have killed " << attackingplayer->taskcount << " out of " << attackingplayer->taskmax << " " << mons << "s.";
  915. }
  916. else
  917. {
  918. info << "You have finished task of killing " << mons << "s. ";
  919. }
  920.  
  921. // attackingplayer->sendTextMessage(MSG_ORANGE, info.str().c_str());
  922. }
  923. //tasksys
  924.  
  925. //Prepare body
  926. Item *corpseitem = Item::CreateItem(attackedCreature->getLookCorpse());
  927. corpseitem->pos = CreaturePos;
  928. tile->addThing(corpseitem);
  929.  
  930. #ifdef _DEATH_EVENTS
  931. if (!attackedplayer)
  932. {
  933. Monster* monster = dynamic_cast<Monster*>(attackedCreature);
  934. Player* killer = dynamic_cast<Player*>(attacker);
  935.  
  936. if (killer && monster && monster->getAction())
  937. {
  938. actions.onCreatureKill(killer, attackedCreature, corpseitem, monster->getAction());
  939. }
  940.  
  941. }
  942. #endif //_DEATH_EVENTS
  943.  
  944. #ifdef __MIZIAK_CREATURESCRIPTS__
  945. if(dynamic_cast<Player*>(attacker) && attackedCreature)
  946. actions.creatureEvent("kill", dynamic_cast<Player*>(attacker), attackedCreature, corpseitem, NULL);
  947. #endif //__MIZIAK_CREATURESCRIPTS__
  948.  
  949. //remove creature
  950. if(attackedplayer){
  951. actions.luaWalkOff(attackedplayer,attackedplayer->pos,tile->ground->getID(),tile->ground->getUniqueId(),tile->ground->getActionId()); //CHANGE onWalk
  952. attackedplayer->onThingDisappear(attackedplayer,stackpos);
  953.  
  954. #ifdef __MIZIAK_CREATURESCRIPTS__
  955. attackedplayer->dieorlogout = true;
  956. if(attacker)
  957. actions.creatureEvent("death", attackedplayer, attacker, corpseitem, NULL);
  958. #endif //__MIZIAK_CREATURESCRIPTS__
  959.  
  960.  
  961. attackedplayer->die(); //handles exp/skills/maglevel loss
  962. }
  963.  
  964. //Add eventual loot
  965. Container *lootcontainer = dynamic_cast<Container*>(corpseitem);
  966. if(lootcontainer) {
  967. attackedCreature->dropLoot(lootcontainer);
  968.  
  969. #ifdef HUCZU_LOOT_INFO
  970. Monster* monster = dynamic_cast<Monster*>(attackedCreature);
  971. Player* atakujacy = dynamic_cast<Player*>(attacker);
  972. if(monster && atakujacy){
  973. std::stringstream ss, info;
  974. //info << "Loot of " << monster->getName() << lootcontainer->getContentDescription() << ".";
  975. info << "Loot of " << monster->getName();
  976. ss << lootcontainer->getContentDescription() << ".";
  977. if(atakujacy->party != 0){
  978. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  979. if((*it).second->party == atakujacy->party){
  980. if((*it).second->getID() != atakujacy->getID()){
  981. (*it).second->sendToSpecialChannel(atakujacy, SPEAK_CHANNEL_O, ss.str().c_str(), 0x02, info.str().c_str());
  982. //(*it).second->sendTextMessage(MSG_INFO, info.str().c_str());
  983. }
  984. }
  985. }
  986. }else{
  987. //atakujacy->sendTextMessage(MSG_INFO, info.str().c_str());
  988. atakujacy->sendToSpecialChannel(atakujacy, SPEAK_CHANNEL_O, ss.str().c_str(), 0x02, info.str().c_str());
  989. }
  990. }
  991. #endif //HUCZU_LOOT_INFO
  992. }
  993.  
  994. #ifdef HUCZU_MONSTER_QUEST
  995. Monster* monster = dynamic_cast<Monster*>(attackedCreature);
  996. Player* atakujacy = dynamic_cast<Player*>(attacker);
  997. int32_t value, kills;
  998.  
  999. if(monster && atakujacy && monster->getQuestId() != 0){
  1000.  
  1001. if(monster->getQuestId() == 2 && atakujacy->getStorageValue(100, value) == 1){
  1002. int32_t killsprzed = atakujacy->getQuestKills(2);
  1003. atakujacy->addQuestKills(2, killsprzed+1);
  1004. }
  1005.  
  1006. }
  1007. #endif //HUCZU_MONSTER_QUEST
  1008.  
  1009.  
  1010. game->removeCreature(attackedCreature);
  1011. // Update attackedCreature pos because contains
  1012. // temple position for players
  1013. attackedCreature->pos = CreaturePos;
  1014.  
  1015. //add body
  1016. game->sendAddThing(NULL,corpseitem->pos,corpseitem);
  1017.  
  1018. if(attackedplayer){
  1019. std::stringstream ss;
  1020. ss << corpseitem->getDescription(false);
  1021.  
  1022. ss << "You recognize " << attackedplayer->getName() << ". ";
  1023. if(attacker){
  1024. ss << (attackedplayer->getSex() == PLAYERSEX_FEMALE ? "She" : "He") << " was killed by ";
  1025.  
  1026. Player *attackerplayer = dynamic_cast<Player*>(attacker);
  1027. if(attackerplayer) {
  1028. ss << attacker->getName();
  1029. }
  1030. else {
  1031. std::string creaturename = attacker->getName();
  1032. std::transform(creaturename.begin(), creaturename.end(), creaturename.begin(), (int32_t(*)(int32_t))tolower);
  1033. ss << article(creaturename);
  1034. }
  1035. }
  1036.  
  1037. //set body special description
  1038. corpseitem->setSpecialDescription(ss.str());
  1039. //send corpse to the dead player. It is not in spectator list
  1040. // because was removed
  1041. attackedplayer->onThingAppear(corpseitem);
  1042. }
  1043. game->startDecay(corpseitem);
  1044.  
  1045. //Get all creatures that will gain xp from this kill..
  1046. CreatureState* attackedCreatureState = NULL;
  1047. std::vector<long> creaturelist;
  1048.  
  1049. if(!(dynamic_cast<Player*>(attackedCreature) && game->getWorldType() != WORLD_TYPE_PVP_ENFORCED)){
  1050. creaturelist = attackedCreature->getInflicatedDamageCreatureList();
  1051. CreatureStateVec& creatureStateVec = creaturestates[tile];
  1052. for(CreatureStateVec::iterator csIt = creatureStateVec.begin(); csIt != creatureStateVec.end(); ++csIt) {
  1053. if(csIt->first == attackedCreature) {
  1054. attackedCreatureState = &csIt->second;
  1055. break;
  1056. }
  1057. }
  1058. }
  1059.  
  1060. if(attackedCreatureState) { //should never be NULL..
  1061. //Add experience
  1062. for(std::vector<long>::const_iterator iit = creaturelist.begin(); iit != creaturelist.end(); ++iit) {
  1063. Creature* gainExpCreature = game->getCreatureByID(*iit);
  1064. if(gainExpCreature) {
  1065. exp_t gainedExperience = attackedCreature->getGainedExperience(gainExpCreature);
  1066. if(gainedExperience <= 0)
  1067. continue;
  1068.  
  1069. Player *gainExpPlayer = dynamic_cast<Player*>(gainExpCreature);
  1070.  
  1071. if(gainExpPlayer) {
  1072. gainExpPlayer->addExp(gainedExperience);
  1073. if(gainExpPlayer && attackedCreature->getName() == gainExpPlayer->taskmonster && gainExpPlayer->taskcount < gainExpPlayer->taskmax)
  1074. {
  1075. gainExpPlayer->taskcount++;
  1076. std::stringstream info;
  1077. std::string mons = gainExpPlayer->taskmonster;
  1078. std::transform(mons.begin(), mons.end(), mons.begin(), (int(*)(int))tolower);
  1079.  
  1080. if(gainExpPlayer->taskcount < gainExpPlayer->taskmax)
  1081. {
  1082. info << "You have killed " << gainExpPlayer->taskcount << " out of " << gainExpPlayer->taskmax << " " << mons << "s.";
  1083. }
  1084. else
  1085. {
  1086. info << "You have finished task of killing " << mons << "s. ";
  1087. }
  1088. gainExpPlayer->sendTextMessage(MSG_ORANGE, info.str().c_str());
  1089. }
  1090.  
  1091.  
  1092.  
  1093. }
  1094. //Need to add this creature and all that can see it to spectators, unless they already added
  1095. SpectatorVec creaturelist;
  1096. game->getSpectators(Range(gainExpCreature->pos, true), creaturelist);
  1097.  
  1098. for(SpectatorVec::const_iterator cit = creaturelist.begin(); cit != creaturelist.end(); ++cit) {
  1099. if(std::find(spectatorlist.begin(), spectatorlist.end(), *cit) == spectatorlist.end()) {
  1100. spectatorlist.push_back(*cit);
  1101. }
  1102. }
  1103.  
  1104. //Add creature to attackerlist
  1105. attackedCreatureState->attackerlist.push_back(gainExpCreature);
  1106. }
  1107. }
  1108. }
  1109.  
  1110. Player *player = dynamic_cast<Player*>(attacker);
  1111. if(player){
  1112. player->sendStats();
  1113. }
  1114.  
  1115. if(attackedCreature && attackedCreature->getMaster() != NULL) {
  1116. attackedCreature->getMaster()->removeSummon(attackedCreature);
  1117. }
  1118. }
  1119.  
  1120.  
  1121. //Add blood?
  1122. #ifdef TJ_MONSTER_BLOOD
  1123. if((drawBlood || attackedCreature->health <= 0) && damage > 0 && attackedCreature->bloodsplash != 255) {
  1124. Item* splash = Item::CreateItem(dead? ITEM_POOL : ITEM_SPLASH, attackedCreature->bloodsplash);
  1125. game->addThing(NULL, CreaturePos, splash);
  1126. game->startDecay(splash);
  1127. game->updateTile(CreaturePos);
  1128. }
  1129. #else
  1130. if((drawBlood || attackedCreature->health <= 0) && damage > 0) {
  1131. Item* splash = Item::CreateItem(ITEM_SPLASH, FLUID_BLOOD);
  1132. game->addThing(NULL, CreaturePos, splash);
  1133. game->startDecay(splash);
  1134. game->updateTile(CreaturePos);
  1135. }
  1136. #endif //TJ_MONSTER_BLOOD
  1137. }
  1138.  
  1139.  
  1140. Game::Game()
  1141. {
  1142. eventIdCount = 1000;
  1143. this->game_state = GAME_STATE_NORMAL;
  1144. this->map = NULL;
  1145. this->worldType = WORLD_TYPE_PVP;
  1146. OTSYS_THREAD_LOCKVARINIT(gameLock);
  1147. OTSYS_THREAD_LOCKVARINIT(eventLock);
  1148. OTSYS_THREAD_LOCKVARINIT(AutoID::autoIDLock);
  1149. #if defined __EXCEPTION_TRACER__
  1150. OTSYS_THREAD_LOCKVARINIT(maploadlock);
  1151. #endif
  1152. OTSYS_THREAD_SIGNALVARINIT(eventSignal);
  1153. BufferedPlayers.clear();
  1154. OTSYS_CREATE_THREAD(eventThread, this);
  1155.  
  1156. #ifdef __DEBUG_CRITICALSECTION__
  1157. OTSYS_CREATE_THREAD(monitorThread, this);
  1158. #endif
  1159.  
  1160. addEvent(makeTask(DECAY_INTERVAL, boost::bind(&Game::checkDecay,this,DECAY_INTERVAL)));
  1161.  
  1162. #ifdef CVS_DAY_CYCLE
  1163. int32_t daycycle = 3600;
  1164. light_hour_delta = 1440*10/daycycle;
  1165. light_hour = 0;
  1166. lightlevel = LIGHT_LEVEL_NIGHT;
  1167. light_state = LIGHT_STATE_NIGHT;
  1168. addEvent(makeTask(10000, boost::bind(&Game::checkLight, this, 10000)));
  1169. #endif //CVS_DAY_CYCLE
  1170. }
  1171.  
  1172.  
  1173. Game::~Game()
  1174. {
  1175. if(map) {
  1176. delete map;
  1177. }
  1178. }
  1179.  
  1180. void Game::setWorldType(enum_world_type type)
  1181. {
  1182. this->worldType = type;
  1183. }
  1184.  
  1185. enum_game_state Game::getGameState()
  1186. {
  1187. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::getGameState()");
  1188. return game_state;
  1189. }
  1190.  
  1191. int32_t Game::loadMap(std::string filename, std::string filekind) {
  1192. if(!map)
  1193. map = new Map;
  1194.  
  1195. max_players = atoi(g_config.getGlobalString("maxplayers").c_str());
  1196. distanceToKill = atoi(g_config.getGlobalString("dist", "50").c_str());
  1197. return map->loadMap(filename, filekind);
  1198. }
  1199.  
  1200.  
  1201.  
  1202. /*****************************************************************************/
  1203.  
  1204. #ifdef __DEBUG_CRITICALSECTION__
  1205.  
  1206. OTSYS_THREAD_RETURN Game::monitorThread(void *p)
  1207. {
  1208. Game* _this = (Game*)p;
  1209.  
  1210. while (true) {
  1211. OTSYS_SLEEP(6000);
  1212.  
  1213. int32_t ret = OTSYS_THREAD_LOCKEX(_this->gameLock, 60 * 2 * 1000);
  1214. if(ret != OTSYS_THREAD_TIMEOUT) {
  1215. OTSYS_THREAD_UNLOCK(_this->gameLock, NULL);
  1216. continue;
  1217. }
  1218.  
  1219. bool file = false;
  1220. std::ostream *outdriver;
  1221. std::cout << "Error: generating critical section file..." <<std::endl;
  1222. std::ofstream output("deadlock.txt",std::ios_base::app);
  1223. if(output.fail()){
  1224. outdriver = &std::cout;
  1225. file = false;
  1226. }
  1227. else{
  1228. file = true;
  1229. outdriver = &output;
  1230. }
  1231.  
  1232. time_t rawtime;
  1233. time(&rawtime);
  1234. *outdriver << "*****************************************************" << std::endl;
  1235. *outdriver << "Error report - " << std::ctime(&rawtime) << std::endl;
  1236.  
  1237. OTSYS_THREAD_LOCK_CLASS::LogList::iterator it;
  1238. for(it = OTSYS_THREAD_LOCK_CLASS::loglist.begin(); it != OTSYS_THREAD_LOCK_CLASS::loglist.end(); ++it) {
  1239. *outdriver << (it->lock ? "lock - " : "unlock - ") << it->str
  1240. << " threadid: " << it->threadid
  1241. << " time: " << it->time
  1242. << " ptr: " << it->mutexaddr
  1243. << std::endl;
  1244. }
  1245.  
  1246. *outdriver << "*****************************************************" << std::endl;
  1247. if(file)
  1248. ((std::ofstream*)outdriver)->close();
  1249.  
  1250. std::cout << "Error report generated. Killing server." <<std::endl;
  1251. exit(1); //force exit
  1252. }
  1253. }
  1254. #endif
  1255.  
  1256. OTSYS_THREAD_RETURN Game::eventThread(void *p)
  1257. {
  1258. #if defined __EXCEPTION_TRACER__
  1259. ExceptionHandler eventExceptionHandler;
  1260. eventExceptionHandler.InstallHandler();
  1261. #endif
  1262.  
  1263. Game* _this = (Game*)p;
  1264.  
  1265. // basically what we do is, look at the first scheduled item,
  1266. // and then sleep until it's due (or if there is none, sleep until we get an event)
  1267. // of course this means we need to get a notification if there are new events added
  1268. while (true)
  1269. {
  1270. #ifdef __DEBUG__EVENTSCHEDULER__
  1271. std::cout << "schedulercycle start..." << std::endl;
  1272. #endif
  1273.  
  1274. SchedulerTask* task = NULL;
  1275. bool runtask = false;
  1276.  
  1277. // check if there are events waiting...
  1278. OTSYS_THREAD_LOCK(_this->eventLock, "eventThread()")
  1279.  
  1280. int32_t ret;
  1281. if (_this->eventList.size() == 0) {
  1282. // unlock mutex and wait for signal
  1283. ret = OTSYS_THREAD_WAITSIGNAL(_this->eventSignal, _this->eventLock);
  1284. } else {
  1285. // unlock mutex and wait for signal or timeout
  1286. ret = OTSYS_THREAD_WAITSIGNAL_TIMED(_this->eventSignal, _this->eventLock, _this->eventList.top()->getCycle());
  1287. }
  1288. // the mutex is locked again now...
  1289. if (ret == OTSYS_THREAD_TIMEOUT) {
  1290. // ok we had a timeout, so there has to be an event we have to execute...
  1291. #ifdef __DEBUG__EVENTSCHEDULER__
  1292. std::cout << "event found at " << OTSYS_TIME() << " which is to be scheduled at: " << _this->eventList.top()->getCycle() << std::endl;
  1293. #endif
  1294. task = _this->eventList.top();
  1295. _this->eventList.pop();
  1296. }
  1297.  
  1298. if(task) {
  1299. std::map<uint32_t, SchedulerTask*>::iterator it = _this->eventIdMap.find(task->getEventId());
  1300. if(it != _this->eventIdMap.end()) {
  1301. _this->eventIdMap.erase(it);
  1302. runtask = true;
  1303. }
  1304. }
  1305.  
  1306. OTSYS_THREAD_UNLOCK(_this->eventLock, "eventThread()");
  1307. if (task) {
  1308. if(runtask) {
  1309. (*task)(_this);
  1310. }
  1311. delete task;
  1312. }
  1313. }
  1314. #if defined __EXCEPTION_TRACER__
  1315. eventExceptionHandler.RemoveHandler();
  1316. #endif
  1317.  
  1318. }
  1319.  
  1320. uint32_t Game::addEvent(SchedulerTask* event) {
  1321. bool do_signal = false;
  1322. OTSYS_THREAD_LOCK(eventLock, "addEvent()")
  1323.  
  1324. if(event->getEventId() == 0) {
  1325. ++eventIdCount;
  1326. event->setEventId(eventIdCount);
  1327. }
  1328.  
  1329. #ifdef __DEBUG__EVENTSCHEDULER__
  1330. std::cout << "addEvent - " << event->getEventId() << std::endl;
  1331. #endif
  1332.  
  1333. eventIdMap[event->getEventId()] = event;
  1334.  
  1335. /*
  1336. if (eventList.empty() || *event < *eventList.top())
  1337. do_signal = true;
  1338. */
  1339.  
  1340. bool isEmpty = eventList.empty();
  1341. eventList.push(event);
  1342.  
  1343. if(isEmpty || *event < *eventList.top())
  1344. do_signal = true;
  1345.  
  1346. /*
  1347. if (eventList.empty() || *event < *eventList.top())
  1348. do_signal = true;
  1349. */
  1350.  
  1351. OTSYS_THREAD_UNLOCK(eventLock, "addEvent()")
  1352.  
  1353. if (do_signal)
  1354. OTSYS_THREAD_SIGNAL_SEND(eventSignal);
  1355.  
  1356. return event->getEventId();
  1357. }
  1358.  
  1359. bool Game::stopEvent(uint32_t eventid) {
  1360. if(eventid == 0)
  1361. return false;
  1362.  
  1363. OTSYS_THREAD_LOCK(eventLock, "stopEvent()")
  1364.  
  1365. std::map<uint32_t, SchedulerTask*>::iterator it = eventIdMap.find(eventid);
  1366. if(it != eventIdMap.end()) {
  1367.  
  1368. #ifdef __DEBUG__EVENTSCHEDULER__
  1369. std::cout << "stopEvent - eventid: " << eventid << "/" << it->second->getEventId() << std::endl;
  1370. #endif
  1371.  
  1372. //it->second->setEventId(0); //invalidate the event
  1373. eventIdMap.erase(it);
  1374.  
  1375. OTSYS_THREAD_UNLOCK(eventLock, "stopEvent()")
  1376. return true;
  1377. }
  1378.  
  1379. OTSYS_THREAD_UNLOCK(eventLock, "stopEvent()")
  1380. return false;
  1381. }
  1382.  
  1383. /*****************************************************************************/
  1384.  
  1385. uint32_t Game::getPlayersOnline() {return (uint32_t)Player::listPlayer.list.size();};
  1386. uint32_t Game::getMonstersOnline() {return (uint32_t)Monster::listMonster.list.size();};
  1387. uint32_t Game::getNpcsOnline() {return (uint32_t)Npc::listNpc.list.size();};
  1388. uint32_t Game::getCreaturesOnline() {return (uint32_t)listCreature.list.size();};
  1389.  
  1390. Tile* Game::getTile(unsigned short _x, unsigned short _y, unsigned char _z)
  1391. {
  1392. return map->getTile(_x, _y, _z);
  1393. }
  1394.  
  1395. Tile* Game::getTile(const Position& pos)
  1396. {
  1397. return map->getTile(pos);
  1398. }
  1399.  
  1400. void Game::setTile(unsigned short _x, unsigned short _y, unsigned char _z, unsigned short groundId)
  1401. {
  1402. map->setTile(_x, _y, _z, groundId);
  1403. }
  1404.  
  1405. Creature* Game::getCreatureByID(uint32_t id)
  1406. {
  1407. if(id == 0)
  1408. return NULL;
  1409.  
  1410. AutoList<Creature>::listiterator it = listCreature.list.find(id);
  1411. if(it != listCreature.list.end()) {
  1412. return (*it).second;
  1413. }
  1414.  
  1415. return NULL; //just in case the player doesnt exist
  1416. }
  1417.  
  1418. Player* Game::getPlayerByID(uint32_t id)
  1419. {
  1420. if(id == 0)
  1421. return NULL;
  1422.  
  1423. AutoList<Player>::listiterator it = Player::listPlayer.list.find(id);
  1424. if(it != Player::listPlayer.list.end()) {
  1425. return (*it).second;
  1426. }
  1427.  
  1428. return NULL; //just in case the player doesnt exist
  1429. }
  1430.  
  1431. Creature* Game::getCreatureByName(const std::string &s)
  1432. {
  1433. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::getCreatureByName()");
  1434.  
  1435. std::string txt1 = s;
  1436. std::transform(txt1.begin(), txt1.end(), txt1.begin(), upchar);
  1437. for(AutoList<Creature>::listiterator it = listCreature.list.begin(); it != listCreature.list.end(); ++it){
  1438. std::string txt2 = (*it).second->getName();
  1439. std::transform(txt2.begin(), txt2.end(), txt2.begin(), upchar);
  1440. if(txt1 == txt2)
  1441. return it->second;
  1442. }
  1443.  
  1444. return NULL; //just in case the creature doesnt exist
  1445. }
  1446.  
  1447. Player* Game::getPlayerByName(const std::string &s)
  1448. {
  1449. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::getPlayerByName()");
  1450.  
  1451. std::string txt1 = s;
  1452. std::transform(txt1.begin(), txt1.end(), txt1.begin(), upchar);
  1453. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  1454. std::string txt2 = (*it).second->getName();
  1455. std::transform(txt2.begin(), txt2.end(), txt2.begin(), upchar);
  1456. if(txt1 == txt2)
  1457. return it->second;
  1458. }
  1459.  
  1460. return NULL; //just in case the player doesnt exist
  1461. }
  1462.  
  1463. bool Game::placeCreature(Position &pos, Creature* c
  1464. #ifdef YUR_LOGIN_QUEUE
  1465. , int32_t* placeInQueue
  1466. #endif //YUR_LOGIN_QUEUE
  1467. )
  1468. {
  1469. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::placeCreature()");
  1470. bool success = false;
  1471. Player *p = dynamic_cast<Player*>(c);
  1472. Monster *monsterzin = dynamic_cast<Monster*>(c);
  1473.  
  1474. #ifdef YUR_LOGIN_QUEUE
  1475. if (!p || c->access >= g_config.ACCESS_ENTER ||
  1476. #ifdef YUR_PREMIUM_PROMOTION
  1477. (p->isPremmium() && !g_config.QUEUE_PREMMY) ||
  1478. #endif //YUR_PREMIUM_PROMOTION
  1479. loginQueue.login(p->accountNumber, getPlayersOnline(), max_players, placeInQueue))
  1480. {
  1481. #else //YUR_LOGIN_QUEUE
  1482. if (!p || c->access >= g_config.ACCESS_ENTER || getPlayersOnline() < max_players)
  1483. {
  1484. #endif //YUR_LOGIN_QUEUE
  1485.  
  1486. success = map->placeCreature(pos, c);
  1487. if(success)
  1488. {
  1489. c->useThing();
  1490.  
  1491. c->setID();
  1492. //std::cout << "place: " << c << " " << c->getID() << std::endl;
  1493. listCreature.addList(c);
  1494. c->addList();
  1495. c->isRemoved = false;
  1496.  
  1497. sendAddThing(NULL,c->pos,c);
  1498.  
  1499. if(p)
  1500. {
  1501. checkRecord();
  1502. #ifdef __DEBUG_PLAYERS__
  1503. std::cout << (uint32_t)getPlayersOnline() << " players online." << std::endl;
  1504. #endif
  1505. #ifdef YUR_GUILD_SYSTEM
  1506. Guilds::ReloadGuildInfo(p);
  1507. #endif //YUR_GUILD_SYSTEM
  1508. /*#ifdef ELEM_VIP_LIST
  1509. vipLogin(p);
  1510. #endif //ELEM_VIP_LIST*/
  1511. }
  1512.  
  1513. if(p){
  1514. c->eventCheck = addEvent(makeTask(1000, std::bind2nd(std::mem_fun(&Game::checkCreature), c->getID())));
  1515. }
  1516. else{
  1517. c->eventCheck = addEvent(makeTask(1000, std::bind2nd(std::mem_fun(&Game::checkCreature), c->getID())));
  1518. }
  1519.  
  1520. //c->eventCheckAttacking = addEvent(makeTask(2000, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), c->getID())));
  1521. }
  1522. }
  1523. else {
  1524. //we cant add the player, server is full
  1525. success = false;
  1526. }
  1527.  
  1528. #ifdef __MIZIAK_CREATURESCRIPTS__
  1529. if(p)
  1530. actions.creatureEvent("login", p, NULL, NULL, NULL);
  1531. #endif //__MIZIAK_CREATURESCRIPTS__
  1532.  
  1533.  
  1534. if(monsterzin){
  1535. c->masterPos.x = c->pos.x;
  1536. c->masterPos.y = c->pos.y;
  1537. c->masterPos.z = c->pos.z;
  1538. }
  1539. return success;
  1540. }
  1541.  
  1542. bool Game::removeCreature(Creature* c)
  1543. {
  1544. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::removeCreature()");
  1545. if(c->isRemoved == true)
  1546. return false;
  1547. #ifdef __DEBUG__
  1548. std::cout << "removing creature "<< std::endl;
  1549. #endif
  1550.  
  1551. #ifdef __MIZIAK_CREATURESCRIPTS__
  1552. Player* pc = dynamic_cast<Player*>(c);
  1553. if(pc)
  1554. if(!pc->dieorlogout)
  1555. actions.creatureEvent("logout", pc, NULL, NULL, NULL);
  1556. #endif //__MIZIAK_CREATURESCRIPTS__
  1557.  
  1558. if(!removeThing(NULL,c->pos,c))
  1559. return false;
  1560.  
  1561. //std::cout << "remove: " << c << " " << c->getID() << std::endl;
  1562. listCreature.removeList(c->getID());
  1563. c->removeList();
  1564. c->isRemoved = true;
  1565.  
  1566. if(g_config.SUMMON_BODIES){
  1567. c->isRemoved = true;
  1568.  
  1569. Creature *summon = NULL;
  1570. for(std::list<Creature*>::iterator cit = c->summons.begin(); cit != c->summons.end(); ++cit) {
  1571. summon = (*cit);
  1572. Position CreaturePos = summon->pos;
  1573. Tile *tile = map->getTile(CreaturePos);
  1574. Item *corpseitem = Item::CreateItem(summon->getLookCorpse());
  1575. corpseitem->pos = CreaturePos; /*summoned bodies by Cayan*/
  1576. tile->addThing(corpseitem);
  1577. removeCreature(summon);
  1578. updateTile(CreaturePos);
  1579. }
  1580. }
  1581. else
  1582. {
  1583. c->isRemoved = true;
  1584.  
  1585. //for(std::list<Creature*>::iterator cit = c->summons.begin(); cit != c->summons.end(); ++cit) {
  1586. //removeCreature(*cit);
  1587. //}
  1588. }
  1589.  
  1590.  
  1591. stopEvent(c->eventCheck);
  1592. stopEvent(c->eventCheckAttacking);
  1593. stopEvent(c->eventCheckFollow);
  1594.  
  1595. Player* player = dynamic_cast<Player*>(c);
  1596. if(player){
  1597.  
  1598. #ifdef HUCZU_SKULLS
  1599. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  1600. Player *on = dynamic_cast<Player*>(it->second);
  1601. if(on && player->isYellowTo(on)){
  1602. on->removeFromYellowList(player);
  1603. }
  1604. if(on && on->hasAttacked(player)){
  1605. on->removeFromAttakedList(player);
  1606. }
  1607. player->clearAttakedList();
  1608. player->clearYellowList();
  1609. }
  1610.  
  1611. if(player->party != 0)
  1612. LeaveParty(player);
  1613. #endif //HUCZU_SKULLS
  1614.  
  1615. if(player->tradePartner != 0) {
  1616. playerCloseTrade(player);
  1617. }
  1618. if(player->eventAutoWalk)
  1619. stopEvent(player->eventAutoWalk);
  1620.  
  1621. Tile* fromT = getTile(player->pos);
  1622. if(fromT && fromT->ground)
  1623. actions.luaWalkOff(player,player->pos,fromT->ground->getID(),fromT->ground->getUniqueId(),fromT->ground->getActionId());
  1624.  
  1625. g_chat.removeUserFromAllChannels(player);
  1626. if(!IOPlayer::instance()->savePlayer(player)){
  1627. std::cout << "Error while saving player: " << player->getName() << std::endl;
  1628. }
  1629. std::cout << (uint32_t)getPlayersOnline() << " players online." << std::endl;
  1630.  
  1631.  
  1632. /*#ifdef ELEM_VIP_LIST
  1633. vipLogout(c->getName());
  1634. #endif //ELEM_VIP_LIST*/
  1635.  
  1636.  
  1637. }
  1638. this->FreeThing(c);
  1639. return true;
  1640. }
  1641.  
  1642. void Game::thingMove(Creature *creature, Thing *thing,
  1643. unsigned short to_x, unsigned short to_y, unsigned char to_z, unsigned char count)
  1644. {
  1645. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 1");
  1646.  
  1647. Tile *fromTile = map->getTile(thing->pos);
  1648.  
  1649. if (fromTile)
  1650. {
  1651. int32_t oldstackpos = fromTile->getThingStackPos(thing);
  1652. thingMoveInternal(creature, thing->pos.x, thing->pos.y, thing->pos.z, oldstackpos, 0, to_x, to_y, to_z, count);
  1653. }
  1654. }
  1655.  
  1656.  
  1657. void Game::thingMove(Creature *creature, unsigned short from_x, unsigned short from_y, unsigned char from_z,
  1658. unsigned char stackPos, unsigned short itemid, unsigned short to_x, unsigned short to_y, unsigned char to_z, unsigned char count)
  1659. {
  1660. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 2");
  1661.  
  1662. Tile *fromTile = getTile(from_x, from_y, from_z);
  1663. if(!fromTile)
  1664. return;
  1665.  
  1666. #ifdef FIXY
  1667. if(dynamic_cast<Player*>(creature) && fromTile && !fromTile->ground) {
  1668. dynamic_cast<Player*>(creature)->sendCancelWalk();
  1669. return;
  1670. }
  1671. #endif //FIXY
  1672.  
  1673. Tile *toTile = getTile(to_x, to_y, to_z);
  1674. if(!toTile)
  1675. return;
  1676.  
  1677. #ifdef FIXY
  1678. if (toTile->isHouse() && !fromTile->isHouse())
  1679. return;
  1680. #endif //FIXY
  1681.  
  1682. Thing* thing = fromTile->getThingByStackPos(stackPos);
  1683. if(!thing)
  1684. return;
  1685.  
  1686. Item* item = dynamic_cast<Item*>(thing);
  1687.  
  1688. if(item && (item->getID() != itemid || item != fromTile->getTopDownItem()))
  1689. return;
  1690.  
  1691. thingMoveInternal(creature, from_x, from_y, from_z, stackPos, itemid, to_x, to_y, to_z, count);
  1692. }
  1693.  
  1694. //container/inventory to container/inventory
  1695. void Game::thingMove(Player *player,
  1696. unsigned char from_cid, unsigned char from_slotid, unsigned short itemid, bool fromInventory,
  1697. unsigned char to_cid, unsigned char to_slotid, bool toInventory,
  1698. unsigned char count)
  1699. {
  1700. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 3");
  1701.  
  1702. thingMoveInternal(player, from_cid, from_slotid, itemid, fromInventory,
  1703. to_cid, to_slotid, toInventory, count);
  1704. }
  1705.  
  1706. //container/inventory to ground
  1707. void Game::thingMove(Player *player,
  1708. unsigned char from_cid, unsigned char from_slotid, unsigned short itemid, bool fromInventory,
  1709. const Position& toPos, unsigned char count)
  1710. {
  1711. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 4");
  1712. Container *fromContainer = player->getContainer(from_cid);
  1713. if(fromContainer && !fromContainer->shop.empty())
  1714. return;
  1715.  
  1716. #ifdef FIXY
  1717. Tile *toTile = getTile(toPos.x, toPos.y, toPos.z);
  1718. if(!toTile)
  1719. return;
  1720.  
  1721. if (player) {
  1722. Tile *fromTile = getTile(player->pos);
  1723. if(!fromTile->isHouse() && toTile->isHouse())
  1724. return;
  1725. }
  1726. #endif //FIXY
  1727.  
  1728. thingMoveInternal(player, from_cid, from_slotid, itemid, fromInventory, toPos, count);
  1729. }
  1730.  
  1731. //ground to container/inventory
  1732. void Game::thingMove(Player *player,
  1733. const Position& fromPos, unsigned char stackPos, unsigned short itemid,
  1734. unsigned char to_cid, unsigned char to_slotid, bool toInventory,
  1735. unsigned char count)
  1736. {
  1737. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 5");
  1738. thingMoveInternal(player, fromPos, stackPos, itemid, to_cid, to_slotid, toInventory, count);
  1739. }
  1740.  
  1741. #ifdef FIXY
  1742. bool Game::onPrepareMoveThing(Creature* player, /*const*/ Thing* thing,
  1743. const Position& fromPos, const Position& toPos, int32_t count)
  1744. {
  1745. const Creature* movingCreature = dynamic_cast<const Creature*>(thing);
  1746. Player *playa = dynamic_cast<Player*>(thing);
  1747.  
  1748. if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) &&
  1749. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  1750. {
  1751. player->sendCancel("Destination is out of reach.");
  1752. return false;
  1753. }
  1754. //RZUCANIE GM PO EKRANIE?
  1755. else if( ((abs(fromPos.x - toPos.x) > thing->throwRange) || (abs(fromPos.y - toPos.y) > thing->throwRange)
  1756. || (fromPos.z != toPos.z)) && player->access >= g_config.ACCESS_REMOTE) {
  1757. if(player == thing){
  1758. teleport(player,toPos);
  1759.  
  1760. if(!playa->gmInvisible){
  1761. globalMagicEffect(fromPos, NM_ME_PUFF);
  1762. globalMagicEffect(toPos, NM_ME_ENERGY_AREA);
  1763. }
  1764. else
  1765. {
  1766. playa->sendMagicEffect(fromPos, NM_ME_PUFF);
  1767. playa->sendMagicEffect(toPos, NM_ME_ENERGY_AREA);
  1768. }
  1769. }
  1770. else
  1771. teleport(thing,toPos);
  1772. }
  1773.  
  1774.  
  1775. else if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) && ((abs(fromPos.x - toPos.x) > thing->throwRange || abs(fromPos.y - toPos.y) > thing->throwRange || (abs(fromPos.z - toPos.z+1) > thing->throwRange)))) {
  1776. player->sendCancel("Destination is out of reach.");
  1777. return false;
  1778. }
  1779.  
  1780.  
  1781. else if(player->access < g_config.ACCESS_REMOTE && movingCreature && fromPos.z != toPos.z){
  1782. player->sendCancel("Destination is out of reach.");
  1783. return false;
  1784. }
  1785.  
  1786. else {
  1787. const Item* item = dynamic_cast<const Item*>(thing);
  1788. if(item) {
  1789. if(item->getID() == ITEM_FOOTBALL &&
  1790. player->access < g_config.getGlobalNumber("accessfootball", 3) && (
  1791. (abs(player->pos.x - toPos.x) > 2) ||
  1792. (abs(player->pos.y - toPos.y) > 2) ||
  1793. (player->pos.z != fromPos.z))
  1794. ){
  1795. player->sendCancel("Nie mozesz tak daleko kopnac.");
  1796. return false;
  1797. }
  1798. int32_t blockstate = 0;
  1799. if(item->isBlocking())
  1800. blockstate |= BLOCK_SOLID;
  1801.  
  1802. if(item->isPickupable() || !item->isNotMoveable())
  1803. blockstate |= BLOCK_PICKUPABLE;
  1804.  
  1805. if(blockstate != 0) {
  1806. switch(map->canThrowObjectTo(fromPos, toPos, blockstate)) {
  1807. case RET_NOERROR:
  1808. return true;
  1809. break;
  1810.  
  1811. case RET_CANNOTTHROW:
  1812. player->sendCancel("Nie mozesz tam rzucic.");
  1813. return false;
  1814. break;
  1815.  
  1816. case RET_CREATUREBLOCK:
  1817. case RET_NOTENOUGHROOM:
  1818. #ifdef KOSZ
  1819. if(item->getID() != ITEM_DUSTBIN){
  1820. player->sendCancel("Przykro mi, nie ma miejsca.");
  1821. return false;
  1822. }
  1823. #else
  1824. player->sendCancel("Przykro mi, nie ma miejsca.");
  1825. return false;
  1826. #endif //KOSZ
  1827. break;
  1828.  
  1829. default:
  1830. player->sendCancel("Sorry not possible.");
  1831. return false;
  1832. break;
  1833. }
  1834. }
  1835. }
  1836. }
  1837.  
  1838. return true;
  1839. }
  1840. #else //FIXY
  1841. bool Game::onPrepareMoveThing(Creature* player, const Thing* thing,
  1842. const Position& fromPos, const Position& toPos, int32_t count)
  1843. {
  1844. if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) &&
  1845. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  1846. {
  1847. player->sendCancel("Za daleko...");
  1848. return false;
  1849. }
  1850. else if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) &&
  1851. ((abs(fromPos.x - toPos.x) > thing->throwRange) || (abs(fromPos.y - toPos.y) > thing->throwRange)
  1852. || (fromPos.z != toPos.z) /*TODO: Make it possible to throw items to different floors ))*/
  1853. {
  1854. player->sendCancel("Destination is out of reach.");
  1855. return false;
  1856. }
  1857. else {
  1858. const Item* item = dynamic_cast<const Item*>(thing);
  1859. if(item) {
  1860. int32_t blockstate = 0;
  1861. if(item->isBlocking())
  1862. blockstate |= BLOCK_SOLID;
  1863.  
  1864. if(item->isPickupable() || !item->isNotMoveable())
  1865. blockstate |= BLOCK_PICKUPABLE;
  1866.  
  1867. if(blockstate != 0) {
  1868. switch(map->canThrowObjectTo(fromPos, toPos, blockstate)) {
  1869. case RET_NOERROR:
  1870. return true;
  1871. break;
  1872.  
  1873. case RET_CANNOTTHROW:
  1874. player->sendCancel("Nie mozesz tam rzucic.");
  1875. return false;
  1876. break;
  1877.  
  1878. case RET_CREATUREBLOCK:
  1879. case RET_NOTENOUGHROOM:
  1880. player->sendCancel("Przykro mi, nie ma miejsca.");
  1881. return false;
  1882. break;
  1883.  
  1884. default:
  1885. player->sendCancel("Sorry not possible.");
  1886. return false;
  1887. break;
  1888. }
  1889. }
  1890. }
  1891. }
  1892. return true;
  1893. }
  1894. #endif //FIXY
  1895. /*ground -> ground*/
  1896. bool Game::onPrepareMoveThing(Creature* creature, const Thing* thing,
  1897. const Tile* fromTile, const Tile *toTile, int32_t count)
  1898. {
  1899. const Player* player = dynamic_cast<const Player*>(creature);
  1900.  
  1901. const Item *item = dynamic_cast<const Item*>(thing);
  1902. const Creature* movingCreature = dynamic_cast<const Creature*>(thing);
  1903. const Player* movingPlayer = dynamic_cast<const Player*>(thing);
  1904.  
  1905. /* if(movingCreature){
  1906. addEvent(makeTask(2000, std::mem_fun(&Game::onPrepareMoveCreature, creature, movingCreature, fromTile, toTile))));
  1907. }*/
  1908. if(item && !item->canMovedTo(toTile)) {
  1909. creature->sendCancel("Sorry, not possible.");
  1910. return false;
  1911. }
  1912.  
  1913. else if(movingCreature && !movingCreature->canMovedTo(toTile)) {
  1914. if(player && player->eventCheckFollow == 0) {
  1915. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  1916. player->sendCancelWalk();
  1917. }
  1918.  
  1919. return false;
  1920. }
  1921. else if(!movingPlayer && toTile && toTile->floorChange()) {
  1922. creature->sendCancel("Sorry, not possible.");
  1923. return false;
  1924. }
  1925. else if(movingCreature && toTile && !toTile->ground) {
  1926. if(player) {
  1927. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  1928. player->sendCancelWalk();
  1929. }
  1930.  
  1931. return false;
  1932. }
  1933.  
  1934. if (fromTile && fromTile->splash == thing && fromTile->splash->isNotMoveable()) {
  1935. creature->sendCancel("You cannot move this object.");
  1936. #ifdef __DEBUG__
  1937. cout << creature->getName() << " is trying to move a splash item!" << std::endl;
  1938. #endif
  1939. return false;
  1940. }
  1941. else if (item && item->isNotMoveable()) {
  1942. creature->sendCancel("You cannot move this object.");
  1943. #ifdef __DEBUG__
  1944. cout << creature->getName() << " is trying to move an unmoveable item!" << std::endl;
  1945. #endif
  1946. return false;
  1947. }
  1948.  
  1949. #ifdef TLM_HOUSE_SYSTEM
  1950. if (item && toTile && toTile->isHouse())
  1951. {
  1952. const Container* container = dynamic_cast<const Container*>(item);
  1953. int32_t moving = container? container->getItemHoldingCount() : 1;
  1954.  
  1955. if (moving + toTile->getItemHoldingCount() > g_config.MAX_HOUSE_TILE_ITEMS)
  1956. {
  1957. creature->sendCancel("You cannot put more items on a house tile.");
  1958. return false;
  1959. }
  1960. }
  1961. #endif //TLM_HOUSE_SYSTEM
  1962.  
  1963. return true; //return thing->canMovedTo(toTile);
  1964. }
  1965. /*inventory -> container*/
  1966. bool Game::onPrepareMoveThing(Player* player, const Item* fromItem, slots_t fromSlot,
  1967. const Container* toContainer, const Item* toItem, int32_t count)
  1968. {
  1969. if(toContainer && !toContainer->shop.empty()){
  1970. creatureUseShop(player, fromItem->getID(), count, "toShop");
  1971. return false;
  1972. }
  1973. if(toContainer && toContainer->getParent() && !toContainer->getParent()->shop.empty())
  1974. return false;
  1975. if(!fromItem->isPickupable()) {
  1976. player->sendCancel("Sorry, not possible.");
  1977. return false;
  1978. }
  1979. else {
  1980. const Container *itemContainer = dynamic_cast<const Container*>(fromItem);
  1981. if(itemContainer) {
  1982. if(itemContainer->isHoldingItem(toContainer) || (toContainer == itemContainer)) {
  1983. player->sendCancel("To jest niemozliwe!");
  1984. return false;
  1985. }
  1986. }
  1987.  
  1988. if((!fromItem->isStackable() || !toItem || fromItem->getID() != toItem->getID() || toItem->getItemCountOrSubtype() >= 100) && toContainer->size() + 1 > toContainer->capacity()) {
  1989. player->sendCancel("Przykro mi, nie ma miejsca.");
  1990. return false;
  1991. }
  1992.  
  1993. Container const *topContainer = toContainer->getTopParent();
  1994. int32_t itemsToadd;
  1995. if(!topContainer)
  1996. topContainer = toContainer;
  1997.  
  1998. Container const *fromContainer = dynamic_cast<const Container*>(fromItem);
  1999. if(fromContainer)
  2000. itemsToadd = fromContainer->getItemHoldingCount() + 1;
  2001. else
  2002. itemsToadd = 1;
  2003.  
  2004. if(topContainer->depot != 0 && player->max_depot_items != 0 && topContainer->getItemHoldingCount() + itemsToadd >= player->max_depot_items){
  2005. player->sendCancel("Nie mozesz polozyc wiecej przedmiotow w depo.");
  2006. return false;
  2007. }
  2008. }
  2009. return true;
  2010. }
  2011.  
  2012. /*container -> container*/
  2013. /*ground -> container*/
  2014. bool Game::onPrepareMoveThing(Player* player,
  2015. const Position& fromPos, const Container* fromContainer, const Item* fromItem,
  2016. const Position& toPos, const Container* toContainer, const Item* toItem, int32_t count)
  2017. {
  2018. if(fromContainer && toContainer && (!fromContainer->shop.empty() || !toContainer->shop.empty())){
  2019. creatureUseShop(player, fromItem->getID(), count, (!fromContainer->shop.empty() ? "fromShop" : "toShop"));
  2020. return false;
  2021. }
  2022.  
  2023. if(!fromContainer && toContainer && !toContainer->shop.empty())
  2024. return false;
  2025. if(toContainer && toContainer->getParent() && !toContainer->getParent()->shop.empty())
  2026. return false;
  2027.  
  2028. if (player->access < g_config.ACCESS_REMOTE &&
  2029. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  2030. {
  2031. player->sendCancel("Za daleko...");
  2032. return false;
  2033. }
  2034. else if (player->access < g_config.ACCESS_REMOTE &&
  2035. ((abs(fromPos.x - toPos.x) > fromItem->throwRange) || (abs(fromPos.y - toPos.y) > fromItem->throwRange)
  2036. || (fromPos.z != toPos.z)))
  2037. {
  2038. player->sendCancel("Destination is out of reach.");
  2039. return false;
  2040. }
  2041.  
  2042. if(!fromItem->isPickupable()) {
  2043. player->sendCancel("You cannot move this object.");
  2044. return false;
  2045. }
  2046. else {
  2047. if((!fromItem->isStackable() || !toItem || fromItem->getID() != toItem->getID() || toItem->getItemCountOrSubtype() >= 100) && toContainer->size() + 1 > toContainer->capacity()) {
  2048. player->sendCancel("Przykro mi, nie ma miejsca.");
  2049. return false;
  2050. }
  2051.  
  2052. const Container *itemContainer = dynamic_cast<const Container*>(fromItem);
  2053. if(itemContainer) {
  2054. if(itemContainer->isHoldingItem(toContainer) || (toContainer == itemContainer) || (fromContainer && fromContainer == itemContainer)) {
  2055. player->sendCancel("To jest niemozliwe!");
  2056. return false;
  2057. }
  2058. }
  2059.  
  2060. double itemWeight = (fromItem->isStackable() ? Item::items[fromItem->getID()].weight * std::max(1, count) : fromItem->getWeight());
  2061. if((!fromContainer || !player->isHoldingContainer(fromContainer)) && player->isHoldingContainer(toContainer)) {
  2062. if(player->access < g_config.ACCESS_PROTECT && player->getFreeCapacity() < itemWeight) {
  2063. player->sendCancel("Ten przedmiot jest za ciezki.");
  2064. return false;
  2065. }
  2066. }
  2067.  
  2068. Container const *topContainer = toContainer->getTopParent();
  2069. int32_t itemsToadd;
  2070. if(!topContainer)
  2071. topContainer = toContainer;
  2072.  
  2073. Container const *fromContainer = dynamic_cast<const Container*>(fromItem);
  2074. if(fromContainer)
  2075. itemsToadd = fromContainer->getItemHoldingCount() + 1;
  2076. else
  2077. itemsToadd = 1;
  2078.  
  2079. if(topContainer->depot != 0 && player->max_depot_items != 0 && topContainer->getItemHoldingCount() >= player->max_depot_items){
  2080. player->sendCancel("Nie mozesz polozyc wiecej przedmiotow w depo.");
  2081. return false;
  2082. }
  2083. }
  2084. return true;
  2085. }
  2086.  
  2087. /*ground -> ground*/
  2088. bool Game::onPrepareMoveCreature(Creature *creature, const Creature* creatureMoving,
  2089. const Tile *fromTile, const Tile *toTile)
  2090. {
  2091. const Player* playerMoving = dynamic_cast<const Player*>(creatureMoving);
  2092. Player* player = dynamic_cast<Player*>(creature);
  2093.  
  2094. #ifdef _BBK_PUSH_DELAY
  2095. if(player && player != creatureMoving && player->pushDelay > 0)
  2096. {
  2097. player->sendCancel("Wait a moment.");
  2098. return false;
  2099. }
  2100. else if(player)
  2101. player->pushDelay = 2*1000; //2 sec
  2102.  
  2103. //wypychanie z depo
  2104. if(player && playerMoving && player != playerMoving && fromTile->isPz() && !toTile->isPz())
  2105. {
  2106. player->sendCancel("Sorry, not possible.");
  2107. return false;
  2108. }
  2109. //wepchanie do depo
  2110. if(player && playerMoving && playerMoving->pzLocked && toTile->isPz())
  2111. {
  2112. player->sendCancel("Sorry, not possible.");
  2113. player->sendCancelWalk();
  2114. return false;
  2115. }
  2116. //wchodzenie do depo
  2117. if(player && player->pzLocked && toTile->isPz())
  2118. {
  2119. player->sendCancel("You can not enter a protection zone after attacking another player.");
  2120. player->sendCancelWalk();
  2121. return false;
  2122. }
  2123. #endif //_BBK_PUSH_DELAY
  2124.  
  2125. if (creature->access < g_config.ACCESS_PROTECT && creature != creatureMoving && !creatureMoving->isPushable())
  2126. {
  2127. creature->sendCancel("Sorry, not possible.");
  2128. return false;
  2129. }
  2130. else if(creature != creatureMoving && toTile->floorChange()){
  2131. creature->sendCancel("Sorry, not possible.");
  2132. return false;
  2133. }
  2134. else if(creature != creatureMoving && toTile->getTeleportItem()){
  2135. creature->sendCancel("Sorry, not possible.");
  2136. return false;
  2137. }
  2138.  
  2139. return true;
  2140. }
  2141.  
  2142. /*ground -> inventory*/
  2143. bool Game::onPrepareMoveThing(Player *player, const Position& fromPos, const Item *item,
  2144. slots_t toSlot, int32_t count)
  2145. {
  2146. if (player->access < g_config.ACCESS_REMOTE &&
  2147. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  2148. {
  2149. player->sendCancel("It's too far.");
  2150. return false;
  2151. }
  2152. else if(!item->isPickupable()) {
  2153. player->sendCancel("You cannot move this object.");
  2154. return false;
  2155. }
  2156.  
  2157. double itemWeight = (item->isStackable() ? Item::items[item->getID()].weight * std::max(1, count) : item->getWeight());
  2158. if(player->access < g_config.ACCESS_PROTECT && player->getFreeCapacity() < itemWeight) {
  2159. player->sendCancel("This object is too heavy.");
  2160. return false;
  2161. }
  2162.  
  2163. return true;
  2164. }
  2165.  
  2166. /*inventory -> inventory*/
  2167. bool Game::onPrepareMoveThing(Player *player, slots_t fromSlot, const Item *fromItem,
  2168. slots_t toSlot, const Item *toItem, int32_t count)
  2169. {
  2170. if(toItem && (!toItem->isStackable() || toItem->getID() != fromItem->getID())) {
  2171. player->sendCancel("There is not enough room.");
  2172. return false;
  2173. }
  2174.  
  2175. return true;
  2176. }
  2177.  
  2178. /*container -> inventory*/
  2179. bool Game::onPrepareMoveThing(Player *player, const Container *fromContainer, const Item *fromItem,
  2180. slots_t toSlot, const Item *toItem, int32_t count)
  2181. {
  2182. if(fromContainer && !fromContainer->shop.empty()){
  2183. creatureUseShop(player, fromItem->getID(), count, "fromShop");
  2184. return false;
  2185. }
  2186. #ifdef _REX_FIGHT_MOD_
  2187. if (toItem && (toItem->getID() == fromItem->getID() && !toItem->isStackable())){
  2188. #else
  2189. if(toItem && (!toItem->isStackable() || toItem->getID() != fromItem->getID())) {
  2190. #endif //Segundo em container -> inventory
  2191. player->sendCancel("There is not enough room.");
  2192. return false;
  2193. }
  2194.  
  2195. double itemWeight = (fromItem->isStackable() ? Item::items[fromItem->getID()].weight * std::max(1, count) : fromItem->getWeight());
  2196. if(player->access < g_config.ACCESS_PROTECT && !player->isHoldingContainer(fromContainer) &&
  2197. player->getFreeCapacity() < itemWeight) {
  2198. player->sendCancel("This object is too heavy.");
  2199. return false;
  2200. }
  2201.  
  2202. return true;
  2203. }
  2204.  
  2205. /*->inventory*/
  2206. bool Game::onPrepareMoveThing(Player *player, const Item *item,
  2207. slots_t toSlot, int32_t count)
  2208. {
  2209. switch(toSlot)
  2210. {
  2211. case SLOT_HEAD:
  2212. if(item->getSlotPosition() & SLOTP_HEAD)
  2213. return true;
  2214. break;
  2215. case SLOT_NECKLACE:
  2216. if(item->getSlotPosition() & SLOTP_NECKLACE)
  2217. return true;
  2218. break;
  2219. case SLOT_BACKPACK:
  2220. if(item->getSlotPosition() & SLOTP_BACKPACK)
  2221. return true;
  2222. break;
  2223. case SLOT_ARMOR:
  2224. if(item->getSlotPosition() & SLOTP_ARMOR)
  2225. return true;
  2226. break;
  2227. case SLOT_RIGHT:
  2228. if(item->getSlotPosition() & SLOTP_RIGHT){
  2229. #ifdef _REX_CVS_MOD_
  2230. //One weapon for hand by ReX
  2231. if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_LEFT] != NULL && player->items[SLOT_LEFT]->isWeapon() && player->items[SLOT_LEFT]->getWeaponType() != SHIELD){
  2232. player->sendCancel("You may use only one weapon.");
  2233. return false;
  2234. }
  2235. #endif
  2236. else if(item->getSlotPosition() & SLOTP_TWO_HAND){
  2237. if(player->items[SLOT_LEFT] != NULL){
  2238. player->sendCancel("First remove the two-handed item.");
  2239. return false;
  2240. }
  2241. return true ;
  2242. }
  2243. else{
  2244. if(player->items[SLOT_LEFT]){
  2245. #ifdef _REX_CVS_MOD_
  2246. //One weapon for hand by ReX
  2247. if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_LEFT] != NULL && player->items[SLOT_LEFT]->isWeapon() && player->items[SLOT_LEFT]->getWeaponType() != SHIELD){
  2248. player->sendCancel("You may use only one weapon.");
  2249. return false;
  2250. }
  2251. #endif
  2252. else if(player->items[SLOT_LEFT]->getSlotPosition() & SLOTP_TWO_HAND){
  2253. player->sendCancel("First remove the two-handed item.");
  2254. return false;
  2255. }
  2256. return true;
  2257. }
  2258. return true;
  2259. }
  2260. }
  2261. break;
  2262. case SLOT_LEFT:
  2263. if(item->getSlotPosition() & SLOTP_LEFT){
  2264. #ifdef _REX_CVS_MOD_
  2265. //One weapon for hand by ReX
  2266. if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_RIGHT] != NULL && player->items[SLOT_RIGHT]->isWeapon() && player->items[SLOT_RIGHT]->getWeaponType() != SHIELD){
  2267. player->sendCancel("You may use only one weapon.");
  2268. return false;
  2269. }
  2270. #endif
  2271. else if(item->getSlotPosition() & SLOTP_TWO_HAND){
  2272. if(player->items[SLOT_RIGHT] != NULL){
  2273. player->sendCancel("First remove the two-handed item.");
  2274. return false;
  2275. }
  2276. return true ;
  2277. }
  2278. else{
  2279. if(player->items[SLOT_RIGHT]){
  2280. #ifdef _REX_CVS_MOD_
  2281. //One weapon for hand by ReX
  2282. if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_RIGHT] != NULL && player->items[SLOT_RIGHT]->isWeapon() && player->items[SLOT_RIGHT]->getWeaponType() != SHIELD){
  2283. player->sendCancel("You may use only one weapon.");
  2284. return false;
  2285. }
  2286. #endif
  2287. else if(player->items[SLOT_RIGHT]->getSlotPosition() & SLOTP_TWO_HAND){
  2288. player->sendCancel("First remove the two-handed item.");
  2289. return false;
  2290. }
  2291. return true;
  2292. }
  2293. return true;
  2294. }
  2295. }
  2296. break;
  2297. case SLOT_LEGS:
  2298. if(item->getSlotPosition() & SLOTP_LEGS)
  2299. return true;
  2300. break;
  2301. case SLOT_FEET:
  2302. if(item->getSlotPosition() & SLOTP_FEET)
  2303. return true;
  2304. break;
  2305. case SLOT_RING:
  2306. if(item->getSlotPosition() & SLOTP_RING
  2307. #ifdef _REX_CVS_MOD_
  2308. || item->getID() == 2208
  2309. #endif
  2310. )
  2311. return true;
  2312. break;
  2313. case SLOT_AMMO:
  2314. if(item->getSlotPosition() & SLOTP_AMMO)
  2315. return true;
  2316. break;
  2317. }
  2318.  
  2319. player->sendCancel("You cannot put that object in that place.");
  2320. return false;
  2321. }
  2322.  
  2323. //container/inventory to container/inventory
  2324. void Game::thingMoveInternal(Player *player,
  2325. unsigned short from_cid, unsigned short from_slotid, unsigned short itemid,
  2326. bool fromInventory,unsigned short to_cid, unsigned short to_slotid, bool toInventory,
  2327. unsigned short count)
  2328. {
  2329. Container *fromContainer = NULL;
  2330. Container *toContainer = NULL;
  2331. Item *fromItem = NULL;
  2332. Item *toItem = NULL;
  2333.  
  2334. if(fromInventory) {
  2335. fromItem = player->getItem(from_cid);
  2336. fromContainer = dynamic_cast<Container *>(fromItem);
  2337. }
  2338. else {
  2339. fromContainer = player->getContainer(from_cid);
  2340.  
  2341. if(fromContainer) {
  2342. if(from_slotid >= fromContainer->size())
  2343. return;
  2344.  
  2345. fromItem = fromContainer->getItem(from_slotid);
  2346. }
  2347. }
  2348.  
  2349. if(toInventory) {
  2350. toItem = player->getItem(to_cid);
  2351. toContainer = dynamic_cast<Container *>(toItem);
  2352. }
  2353. else {
  2354. toContainer = player->getContainer(to_cid);
  2355.  
  2356. if(toContainer) {
  2357. if(to_slotid >= toContainer->capacity())
  2358. return;
  2359.  
  2360. toItem = toContainer->getItem(to_slotid);
  2361. Container *toSlotContainer = dynamic_cast<Container*>(toItem);
  2362. if(toSlotContainer) {
  2363. toContainer = toSlotContainer;
  2364. toItem = NULL;
  2365. }
  2366. }
  2367. }
  2368.  
  2369. if(!fromItem || (toItem == fromItem) || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()) || fromItem->getID() != itemid)
  2370. return;
  2371.  
  2372. //Container to container
  2373. if(!fromInventory && fromContainer && toContainer) {
  2374. Position fromPos = (fromContainer->pos.x == 0xFFFF ? player->pos : fromContainer->pos);
  2375. Position toPos = (toContainer->pos.x == 0xFFFF ? player->pos : toContainer->pos);
  2376.  
  2377. if(onPrepareMoveThing(player, fromPos, fromContainer, fromItem, toPos, toContainer, toItem, count)) {
  2378.  
  2379. autoCloseTrade(fromItem, true);
  2380. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2381. int32_t oldToCount = 0;
  2382.  
  2383. //move around an item in a container
  2384. if(fromItem->isStackable()) {
  2385. if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2386. {
  2387. oldToCount = toItem->getItemCountOrSubtype();
  2388. int32_t newToCount = std::min(100, oldToCount + count);
  2389. toItem->setItemCountOrSubtype(newToCount);
  2390.  
  2391. if(oldToCount != newToCount) {
  2392. autoCloseTrade(toItem);
  2393. }
  2394.  
  2395. int32_t subcount = oldFromCount - count;
  2396. fromItem->setItemCountOrSubtype(subcount);
  2397.  
  2398. int32_t surplusCount = oldToCount + count - 100;
  2399. if(surplusCount > 0) {
  2400. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2401. if(onPrepareMoveThing(player, fromPos, fromContainer, surplusItem, toPos, toContainer, NULL, count)) {
  2402. autoCloseTrade(toContainer);
  2403. toContainer->addItem(surplusItem);
  2404. }
  2405. else {
  2406. delete surplusItem;
  2407. count -= surplusCount; //re-define the actual amount we move.
  2408. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2409. }
  2410. }
  2411. }
  2412. else if(count < oldFromCount) {
  2413. int32_t subcount = oldFromCount - count;
  2414. fromItem->setItemCountOrSubtype(subcount);
  2415.  
  2416. Item* moveItem = Item::CreateItem(fromItem->getID(), count);
  2417. toContainer->addItem(moveItem);
  2418. autoCloseTrade(toContainer);
  2419. }
  2420. else {
  2421. if(fromContainer == toContainer) {
  2422. fromContainer->moveItem(from_slotid, 0);
  2423. }
  2424. else if(fromContainer->removeItem(fromItem)) {
  2425. autoCloseTrade(toContainer);
  2426. toContainer->addItem(fromItem);
  2427. }
  2428. }
  2429.  
  2430. if(fromItem->getItemCountOrSubtype() == 0) {
  2431. fromContainer->removeItem(fromItem);
  2432. this->FreeThing(fromItem);
  2433. }
  2434. }
  2435. else {
  2436. if(fromContainer == toContainer) {
  2437. fromContainer->moveItem(from_slotid, 0);
  2438. }
  2439. else if(fromContainer->removeItem(fromItem)) {
  2440. autoCloseTrade(toContainer);
  2441. toContainer->addItem(fromItem);
  2442. }
  2443. }
  2444.  
  2445. if(player->isHoldingContainer(fromContainer) != player->isHoldingContainer(toContainer)) {
  2446. player->updateInventoryWeigth();
  2447. }
  2448.  
  2449. SpectatorVec list;
  2450. SpectatorVec::iterator it;
  2451.  
  2452. if(fromPos == toPos) {
  2453. getSpectators(Range(fromPos, false), list);
  2454. }
  2455. else {
  2456. getSpectators(Range(fromPos, toPos), list);
  2457. }
  2458.  
  2459. if(!list.empty()) {
  2460. //players
  2461. for(it = list.begin(); it != list.end(); ++it) {
  2462. if(dynamic_cast<Player*>(*it)) {
  2463. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2464. }
  2465. }
  2466.  
  2467. //none-players
  2468. for(it = list.begin(); it != list.end(); ++it) {
  2469. if(!dynamic_cast<Player*>(*it)) {
  2470. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2471. }
  2472. }
  2473. }
  2474. else
  2475. player->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2476. }
  2477. }
  2478. else {
  2479. //inventory to inventory
  2480. if(fromInventory && toInventory && !toContainer) {
  2481. Position fromPos = player->pos;
  2482. Position toPos = player->pos;
  2483. if(onPrepareMoveThing(player, fromItem, (slots_t)to_cid, count) && onPrepareMoveThing(player, (slots_t)from_cid, fromItem, (slots_t)to_cid, toItem, count)) {
  2484.  
  2485. autoCloseTrade(fromItem, true);
  2486. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2487. int32_t oldToCount = 0;
  2488.  
  2489. //bbk 2020
  2490. std::cout << "inventory to inventory" << std::endl;
  2491. if(fromItem && (slots_t)to_cid == SLOT_RING) fromItem->setGlimmer();
  2492. if(toItem && (slots_t)from_cid == SLOT_RING) toItem->removeGlimmer();
  2493.  
  2494. if(fromItem->isStackable()) {
  2495. if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2496. {
  2497. oldToCount = toItem->getItemCountOrSubtype();
  2498. int32_t newToCount = std::min(100, oldToCount + count);
  2499. toItem->setItemCountOrSubtype(newToCount);
  2500.  
  2501. if(oldToCount != newToCount) {
  2502. autoCloseTrade(toItem);
  2503. }
  2504.  
  2505. int32_t subcount = oldFromCount - count;
  2506. fromItem->setItemCountOrSubtype(subcount);
  2507.  
  2508. int32_t surplusCount = oldToCount + count - 100;
  2509. if(surplusCount > 0) {
  2510. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2511. player->sendCancel("There is not enough room.");
  2512. }
  2513.  
  2514. if(fromItem->getItemCountOrSubtype() == 0) {
  2515. player->removeItemInventory(from_cid, true);
  2516. this->FreeThing(fromItem);
  2517. }
  2518. }
  2519. else if(count < oldFromCount) {
  2520. int32_t subcount = oldFromCount - count;
  2521. fromItem->setItemCountOrSubtype(subcount);
  2522.  
  2523. autoCloseTrade(toItem);
  2524. player->removeItemInventory(to_cid, true);
  2525. player->addItemInventory(Item::CreateItem(fromItem->getID(), count), to_cid, true);
  2526.  
  2527. if(fromItem->getItemCountOrSubtype() == 0) {
  2528. player->removeItemInventory(from_cid, true);
  2529. this->FreeThing(fromItem);
  2530. }
  2531. }
  2532. else {
  2533. if(player->removeItemInventory(from_cid, true)) {
  2534. player->removeItemInventory(to_cid, true);
  2535. player->addItemInventory(fromItem, to_cid, true);
  2536. }
  2537. }
  2538. }
  2539. else if(player->removeItemInventory(from_cid, true)) {
  2540. player->removeItemInventory(to_cid, true);
  2541. player->addItemInventory(fromItem, to_cid, true);
  2542. }
  2543.  
  2544. player->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2545. }
  2546. }
  2547. //container to inventory
  2548. else if(!fromInventory && fromContainer && toInventory) {
  2549. if(onPrepareMoveThing(player, fromItem, (slots_t)to_cid, count) && onPrepareMoveThing(player, fromContainer, fromItem, (slots_t)to_cid, toItem, count)) {
  2550. autoCloseTrade(fromItem, true);
  2551. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2552. int32_t oldToCount = 0;
  2553.  
  2554. //bbk 2020
  2555. std::cout << "container to inventory" << std::endl;
  2556. if(fromItem) fromItem->removeGlimmer();
  2557. if(toItem ) toItem->removeGlimmer();
  2558.  
  2559. if(fromItem->isStackable()) {
  2560. if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2561. {
  2562. oldToCount = toItem->getItemCountOrSubtype();
  2563. int32_t newToCount = std::min(100, oldToCount + count);
  2564. toItem->setItemCountOrSubtype(newToCount);
  2565.  
  2566. if(oldToCount != newToCount) {
  2567. autoCloseTrade(toItem);
  2568. }
  2569.  
  2570. int32_t subcount = oldFromCount - count;
  2571. fromItem->setItemCountOrSubtype(subcount);
  2572.  
  2573. int32_t surplusCount = oldToCount + count - 100;
  2574. if(surplusCount > 0) {
  2575. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2576. player->sendCancel("There is not enough room.");
  2577. }
  2578.  
  2579. if(fromItem->getItemCountOrSubtype() == 0) {
  2580. fromContainer->removeItem(fromItem);
  2581. this->FreeThing(fromItem);
  2582. }
  2583. }
  2584. else if(count < oldFromCount) {
  2585. int32_t subcount = oldFromCount - count;
  2586. fromItem->setItemCountOrSubtype(subcount);
  2587.  
  2588. player->removeItemInventory(to_cid, true);
  2589. player->addItemInventory(Item::CreateItem(fromItem->getID(), count), to_cid, true);
  2590.  
  2591. if(toItem) {
  2592. fromContainer->addItem(toItem);
  2593. }
  2594.  
  2595. if(fromItem->getItemCountOrSubtype() == 0) {
  2596. fromContainer->removeItem(fromItem);
  2597. this->FreeThing(fromItem);
  2598. }
  2599. }
  2600. else {
  2601. if(fromContainer->removeItem(fromItem)) {
  2602. player->removeItemInventory(to_cid, true);
  2603. player->addItemInventory(fromItem, to_cid, true);
  2604.  
  2605. if(toItem) {
  2606. fromContainer->addItem(toItem);
  2607. }
  2608. }
  2609. }
  2610. }
  2611. else if(fromContainer->removeItem(fromItem)) {
  2612. player->removeItemInventory(to_cid, true);
  2613. player->addItemInventory(fromItem, to_cid, true);
  2614.  
  2615. if(toItem) {
  2616. fromContainer->addItem(toItem);
  2617. }
  2618. }
  2619.  
  2620. if(!player->isHoldingContainer(fromContainer)) {
  2621. player->updateInventoryWeigth();
  2622. }
  2623.  
  2624. //if(fromContainer->pos.x != 0xFFFF) {
  2625. if(fromContainer->getTopParent()->pos.x != 0xFFFF) {
  2626. SpectatorVec list;
  2627. SpectatorVec::iterator it;
  2628.  
  2629. getSpectators(Range(fromContainer->getTopParent()->pos, false), list);
  2630.  
  2631. //players
  2632. for(it = list.begin(); it != list.end(); ++it) {
  2633. if(dynamic_cast<Player*>(*it)) {
  2634. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2635. }
  2636. }
  2637.  
  2638. //none-players
  2639. for(it = list.begin(); it != list.end(); ++it) {
  2640. if(!dynamic_cast<Player*>(*it)) {
  2641. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2642. }
  2643. }
  2644. }
  2645. else
  2646. player->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2647. }
  2648. }
  2649. //inventory to container
  2650. else if(fromInventory && toContainer) {
  2651. Position fromPos = player->pos;
  2652. Position toPos = (toContainer->pos.x == 0xFFFF ? player->pos : toContainer->pos);
  2653.  
  2654. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2655. int32_t oldToCount = 0;
  2656.  
  2657. //bbk 2020
  2658. std::cout << "inventory to container" << std::endl;
  2659. if(fromItem) fromItem->removeGlimmer();
  2660. if(toItem) toItem->removeGlimmer();
  2661.  
  2662. if(onPrepareMoveThing(player, fromItem, (slots_t)from_cid, toContainer, toItem, count)) {
  2663. autoCloseTrade(fromItem, true);
  2664. if(fromItem->isStackable()) {
  2665. if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2666. {
  2667. oldToCount = toItem->getItemCountOrSubtype();
  2668. int32_t newToCount = std::min(100, oldToCount + count);
  2669. toItem->setItemCountOrSubtype(newToCount);
  2670.  
  2671. if(oldToCount != newToCount) {
  2672. autoCloseTrade(toItem);
  2673. }
  2674.  
  2675. int32_t subcount = oldFromCount - count;
  2676. fromItem->setItemCountOrSubtype(subcount);
  2677.  
  2678. int32_t surplusCount = oldToCount + count - 100;
  2679. if(surplusCount > 0) {
  2680. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2681.  
  2682. if(onPrepareMoveThing(player, fromPos, NULL, surplusItem, toPos, toContainer, NULL, count)) {
  2683. autoCloseTrade(toContainer);
  2684. toContainer->addItem(surplusItem);
  2685. }
  2686. else {
  2687. delete surplusItem;
  2688. count -= surplusCount; //re-define the actual amount we move.
  2689. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2690. }
  2691. }
  2692. }
  2693. else if(count < oldFromCount) {
  2694. int32_t subcount = oldFromCount - count;
  2695. fromItem->setItemCountOrSubtype(subcount);
  2696. autoCloseTrade(toContainer);
  2697. toContainer->addItem(Item::CreateItem(fromItem->getID(), count));
  2698. }
  2699. else {
  2700. if(player->removeItemInventory((slots_t)from_cid, true)) {
  2701. autoCloseTrade(toContainer);
  2702. toContainer->addItem(fromItem);
  2703.  
  2704. if(player->isHoldingContainer(toContainer)) {
  2705. player->updateInventoryWeigth();
  2706. }
  2707. }
  2708. }
  2709.  
  2710. if(fromItem->getItemCountOrSubtype() == 0) {
  2711. player->removeItemInventory(from_cid, true);
  2712. this->FreeThing(fromItem);
  2713. }
  2714. }
  2715. else if(player->removeItemInventory(from_cid, true)) {
  2716. autoCloseTrade(toContainer);
  2717. toContainer->addItem(fromItem);
  2718.  
  2719. if(player->isHoldingContainer(toContainer)) {
  2720. player->updateInventoryWeigth();
  2721. }
  2722. }
  2723.  
  2724. if(!player->isHoldingContainer(toContainer)) {
  2725. player->updateInventoryWeigth();
  2726. }
  2727.  
  2728. if(toContainer->getTopParent()->pos.x != 0xFFFF) {
  2729. SpectatorVec list;
  2730. SpectatorVec::iterator it;
  2731.  
  2732. getSpectators(Range(toContainer->getTopParent()->pos, false), list);
  2733.  
  2734. //players
  2735. for(it = list.begin(); it != list.end(); ++it) {
  2736. if(dynamic_cast<Player*>(*it)) {
  2737. (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2738. }
  2739. }
  2740.  
  2741. //none-players
  2742. for(it = list.begin(); it != list.end(); ++it) {
  2743. if(!dynamic_cast<Player*>(*it)) {
  2744. (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2745. }
  2746. }
  2747. }
  2748. else
  2749. player->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2750. }
  2751. }
  2752. }
  2753. }
  2754.  
  2755. //container/inventory to ground
  2756. void Game::thingMoveInternal(Player *player,
  2757. unsigned char from_cid, unsigned char from_slotid, unsigned short itemid, bool fromInventory,
  2758. const Position& toPos, unsigned char count)
  2759. {
  2760. Container *fromContainer = NULL;
  2761. Tile *toTile = map->getTile(toPos);
  2762. if(!toTile)
  2763. return;
  2764.  
  2765. /*container to ground*/
  2766. if(!fromInventory) {
  2767. fromContainer = player->getContainer(from_cid);
  2768. if(!fromContainer)
  2769. return;
  2770.  
  2771. Position fromPos = (fromContainer->pos.x == 0xFFFF ? player->pos : fromContainer->pos);
  2772. Item *fromItem = dynamic_cast<Item*>(fromContainer->getItem(from_slotid));
  2773. Item* toItem = dynamic_cast<Item*>(toTile->getTopDownItem());
  2774.  
  2775. if(!fromItem || (toItem == fromItem) || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()) || fromItem->getID() != itemid)
  2776. return;
  2777.  
  2778. if(onPrepareMoveThing(player, fromItem, fromPos, toPos, count) && onPrepareMoveThing(player, fromItem, NULL, toTile, count)) {
  2779. autoCloseTrade(fromItem, true);
  2780. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2781. int32_t oldToCount = 0;
  2782.  
  2783. //Do action...
  2784. #ifdef TP_TRASH_BINS
  2785. if (toItem && toItem->isDeleter())
  2786. {
  2787. fromContainer->removeItem(fromItem);
  2788. FreeThing(fromItem);
  2789. }
  2790. else if(fromItem->isStackable()) {
  2791. #else
  2792. if(fromItem->isStackable()) {
  2793. #endif //TP_TRASH_BINS
  2794. if(toItem && toItem->getID() == fromItem->getID())
  2795. {
  2796. oldToCount = toItem->getItemCountOrSubtype();
  2797. int32_t newToCount = std::min(100, oldToCount + count);
  2798. toItem->setItemCountOrSubtype(newToCount);
  2799.  
  2800. if(oldToCount != newToCount) {
  2801. autoCloseTrade(toItem);
  2802. }
  2803.  
  2804. int32_t subcount = oldFromCount - count;
  2805. fromItem->setItemCountOrSubtype(subcount);
  2806.  
  2807. int32_t surplusCount = oldToCount + count - 100;
  2808. if(surplusCount > 0) {
  2809. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2810. surplusItem->pos = toPos;
  2811.  
  2812. toTile->addThing(surplusItem);
  2813. }
  2814.  
  2815. if(fromItem->getItemCountOrSubtype() == 0) {
  2816. fromContainer->removeItem(fromItem);
  2817. this->FreeThing(fromItem);
  2818. }
  2819. }
  2820. else if(count < oldFromCount) {
  2821. int32_t subcount = oldFromCount - count;
  2822. fromItem->setItemCountOrSubtype(subcount);
  2823.  
  2824. Item *moveItem = Item::CreateItem(fromItem->getID(), count);
  2825. moveItem->pos = toPos;
  2826. toTile->addThing(moveItem);
  2827.  
  2828. if(fromItem->getItemCountOrSubtype() == 0) {
  2829. fromContainer->removeItem(fromItem);
  2830. this->FreeThing(fromItem);
  2831. }
  2832. }
  2833. else if(fromContainer->removeItem(fromItem)) {
  2834. fromItem->pos = toPos;
  2835. toTile->addThing(fromItem);
  2836. }
  2837. }
  2838. else if(fromContainer->removeItem(fromItem)) {
  2839. fromItem->pos = toPos;
  2840. toTile->addThing(fromItem);
  2841. }
  2842.  
  2843. if(player->isHoldingContainer(fromContainer)) {
  2844. player->updateInventoryWeigth();
  2845. }
  2846.  
  2847. SpectatorVec list;
  2848. SpectatorVec::iterator it;
  2849.  
  2850. getSpectators(Range(fromPos, false), list);
  2851.  
  2852. SpectatorVec tolist;
  2853. getSpectators(Range(toPos, true), tolist);
  2854.  
  2855. for(it = tolist.begin(); it != tolist.end(); ++it) {
  2856. if(std::find(list.begin(), list.end(), *it) == list.end()) {
  2857. list.push_back(*it);
  2858. }
  2859. }
  2860.  
  2861. //players
  2862. for(it = list.begin(); it != list.end(); ++it) {
  2863. if(dynamic_cast<Player*>(*it)) {
  2864. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2865. }
  2866. }
  2867.  
  2868. //none-players
  2869. for(it = list.begin(); it != list.end(); ++it) {
  2870. if(!dynamic_cast<Player*>(*it)) {
  2871. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2872. }
  2873. }
  2874. }
  2875. }
  2876. else /*inventory to ground*/{
  2877. Item *fromItem = player->getItem(from_cid);
  2878. if(!fromItem || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()) || fromItem->getID() != itemid)
  2879. return;
  2880.  
  2881. if(onPrepareMoveThing(player, fromItem, player->pos, toPos, count) && onPrepareMoveThing(player, fromItem, NULL, toTile, count)) {
  2882. autoCloseTrade(fromItem, true);
  2883. Item* toItem = dynamic_cast<Item*>(toTile->getTopDownItem());
  2884. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2885. int32_t oldToCount = 0;
  2886.  
  2887. //bbk 2020
  2888. std::cout << "inventory to ground" << std::endl;
  2889. if(fromItem) fromItem->removeGlimmer();
  2890.  
  2891. //Do action...
  2892. #ifdef TP_TRASH_BINS
  2893. if(toItem && toItem->isDeleter())
  2894. {
  2895. player->removeItemInventory(from_cid, true);
  2896. FreeThing(fromItem);
  2897. }
  2898. else if(fromItem->isStackable()) {
  2899. #else
  2900. if(fromItem->isStackable()) {
  2901. #endif //TP_TRASH_BINS
  2902. if(toItem && toItem->getID() == fromItem->getID())
  2903. {
  2904. oldToCount = toItem->getItemCountOrSubtype();
  2905. int32_t newToCount = std::min(100, oldToCount + count);
  2906. toItem->setItemCountOrSubtype(newToCount);
  2907.  
  2908. if(oldToCount != newToCount) {
  2909. autoCloseTrade(toItem);
  2910. }
  2911.  
  2912. int32_t subcount = oldFromCount - count;
  2913. fromItem->setItemCountOrSubtype(subcount);
  2914.  
  2915. int32_t surplusCount = oldToCount + count - 100;
  2916. if(surplusCount > 0) {
  2917. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2918. surplusItem->pos = toPos;
  2919.  
  2920. toTile->addThing(surplusItem);
  2921. }
  2922.  
  2923. if(fromItem->getItemCountOrSubtype() == 0) {
  2924. player->removeItemInventory(from_cid, true);
  2925. this->FreeThing(fromItem);
  2926. }
  2927. }
  2928. else if(count < oldFromCount) {
  2929. int32_t subcount = oldFromCount - count;
  2930. fromItem->setItemCountOrSubtype(subcount);
  2931.  
  2932. Item *moveItem = Item::CreateItem(fromItem->getID(), count);
  2933. moveItem->pos = toPos;
  2934. toTile->addThing(moveItem);
  2935.  
  2936. if(fromItem->getItemCountOrSubtype() == 0) {
  2937. player->removeItemInventory(from_cid, true);
  2938. this->FreeThing(fromItem);
  2939. }
  2940. }
  2941. else if(player->removeItemInventory(from_cid, true)) {
  2942. fromItem->pos = toPos;
  2943. toTile->addThing(fromItem);
  2944. }
  2945. }
  2946. else if(player->removeItemInventory(from_cid, true)) {
  2947. fromItem->pos = toPos;
  2948. toTile->addThing(fromItem);
  2949. }
  2950.  
  2951. player->updateInventoryWeigth();
  2952.  
  2953. SpectatorVec list;
  2954. SpectatorVec::iterator it;
  2955.  
  2956. getSpectators(Range(player->pos, false), list);
  2957.  
  2958. SpectatorVec tolist;
  2959. getSpectators(Range(toPos, true), tolist);
  2960.  
  2961. for(it = tolist.begin(); it != tolist.end(); ++it) {
  2962. if(std::find(list.begin(), list.end(), *it) == list.end()) {
  2963. list.push_back(*it);
  2964. }
  2965. }
  2966.  
  2967. //players
  2968. for(it = list.begin(); it != list.end(); ++it) {
  2969. if(dynamic_cast<Player*>(*it)) {
  2970. (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2971. }
  2972. }
  2973.  
  2974. //none-players
  2975. for(it = list.begin(); it != list.end(); ++it) {
  2976. if(!dynamic_cast<Player*>(*it)) {
  2977. (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2978. }
  2979. }
  2980. }
  2981. }
  2982.  
  2983. }
  2984.  
  2985. //ground to container/inventory
  2986. void Game::thingMoveInternal(Player *player, const Position& fromPos, unsigned char stackPos,
  2987. uint16_t itemid, unsigned char to_cid, unsigned char to_slotid, bool toInventory, unsigned char count)
  2988. {
  2989. Tile *fromTile = map->getTile(fromPos);
  2990. if(!fromTile)
  2991. return;
  2992.  
  2993. Container *toContainer = NULL;
  2994.  
  2995. Item* fromItem = dynamic_cast<Item*>(fromTile->getTopDownItem());
  2996. Item *toItem = NULL;
  2997.  
  2998. if(!fromItem || (fromItem->getID() != itemid) || (fromItem != fromTile->getTopDownItem()))
  2999. return;
  3000.  
  3001. if(toInventory)
  3002. {
  3003. toItem = player->getItem(to_cid);
  3004. toContainer = dynamic_cast<Container*>(toItem);
  3005. }
  3006. else
  3007. {
  3008. toContainer = player->getContainer(to_cid);
  3009. if(!toContainer)
  3010. return;
  3011.  
  3012. toItem = toContainer->getItem(to_slotid);
  3013. Container *toSlotContainer = dynamic_cast<Container*>(toItem);
  3014.  
  3015. if(toSlotContainer)
  3016. {
  3017. toContainer = toSlotContainer;
  3018. toItem = NULL;
  3019. }
  3020. }
  3021.  
  3022. if((toItem == fromItem) || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()))
  3023. return;
  3024.  
  3025. /*ground to container*/
  3026. if(toContainer)
  3027. {
  3028. /*if(onPrepareMoveThing(player, fromItem, fromPos, player->pos, count) &&
  3029. onPrepareMoveThing(player, fromItem, NULL, toContainer, toItem, count))*/
  3030.  
  3031. Position toPos = (toContainer->pos.x == 0xFFFF ? player->pos : toContainer->pos);
  3032. if(onPrepareMoveThing(player, fromPos, NULL, fromItem, toPos, toContainer, toItem, count))
  3033. {
  3034. autoCloseTrade(fromItem, true);
  3035. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  3036. int32_t oldToCount = 0;
  3037. int32_t stackpos = fromTile->getThingStackPos(fromItem);
  3038.  
  3039. if(fromItem->isStackable())
  3040. {
  3041. if(toItem && toItem->getID() == fromItem->getID())
  3042. {
  3043. oldToCount = toItem->getItemCountOrSubtype();
  3044. int32_t newToCount = std::min(100, oldToCount + count);
  3045. toItem->setItemCountOrSubtype(newToCount);
  3046.  
  3047. if(oldToCount != newToCount)
  3048. {
  3049. autoCloseTrade(toItem);
  3050. }
  3051.  
  3052. int32_t subcount = oldFromCount - count;
  3053. fromItem->setItemCountOrSubtype(subcount);
  3054.  
  3055. int32_t surplusCount = oldToCount + count - 100;
  3056. if(surplusCount > 0)
  3057. {
  3058. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  3059.  
  3060. if(onPrepareMoveThing(player, fromPos, NULL, surplusItem, toPos, toContainer, NULL, count))
  3061. {
  3062. autoCloseTrade(toContainer);
  3063. toContainer->addItem(surplusItem);
  3064. }
  3065. else
  3066. {
  3067. delete surplusItem;
  3068. count -= surplusCount; //re-define the actual amount we move.
  3069. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  3070. }
  3071. }
  3072.  
  3073. if(fromItem->getItemCountOrSubtype() == 0)
  3074. {
  3075. if(fromTile->removeThing(fromItem))
  3076. {
  3077. this->FreeThing(fromItem);
  3078. }
  3079. }
  3080. }
  3081. else if(count < oldFromCount)
  3082. {
  3083. int32_t subcount = oldFromCount - count;
  3084. fromItem->setItemCountOrSubtype(subcount);
  3085.  
  3086. autoCloseTrade(toContainer);
  3087. toContainer->addItem(Item::CreateItem(fromItem->getID(), count));
  3088.  
  3089. if(fromItem->getItemCountOrSubtype() == 0)
  3090. {
  3091. if(fromTile->removeThing(fromItem))
  3092. {
  3093. this->FreeThing(fromItem);
  3094. }
  3095. }
  3096. }
  3097. else if(fromTile->removeThing(fromItem))
  3098. {
  3099. autoCloseTrade(toContainer);
  3100. toContainer->addItem(fromItem);
  3101. }
  3102. }
  3103. else
  3104. {
  3105. if(fromTile->removeThing(fromItem))
  3106. {
  3107. autoCloseTrade(toContainer);
  3108. toContainer->addItem(fromItem);
  3109. }
  3110. }
  3111.  
  3112. if(player->isHoldingContainer(toContainer))
  3113. {
  3114. player->updateInventoryWeigth();
  3115. }
  3116.  
  3117. SpectatorVec list;
  3118. SpectatorVec::iterator it;
  3119.  
  3120. getSpectators(Range(fromPos, true), list);
  3121.  
  3122. //players
  3123. for(it = list.begin(); it != list.end(); ++it)
  3124. {
  3125. if(dynamic_cast<Player*>(*it))
  3126. {
  3127. (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  3128. }
  3129. }
  3130.  
  3131. //none-players
  3132. for(it = list.begin(); it != list.end(); ++it)
  3133. {
  3134. if(!dynamic_cast<Player*>(*it))
  3135. {
  3136. (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  3137. }
  3138. }
  3139. }
  3140. }
  3141. //ground to inventory
  3142. else if(toInventory)
  3143. {
  3144. if(onPrepareMoveThing(player, fromPos, fromItem, (slots_t)to_cid, count) && onPrepareMoveThing(player, fromItem, (slots_t)to_cid, count))
  3145. {
  3146. autoCloseTrade(fromItem, true);
  3147. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  3148. int32_t oldToCount = 0;
  3149. int32_t stackpos = fromTile->getThingStackPos(fromItem);
  3150.  
  3151. //bbk 2020
  3152. std::cout << "ground to inventory" << std::endl;
  3153. if(fromItem && (slots_t)to_cid == SLOT_RING) {
  3154. fromItem->setGlimmer();
  3155. if(toItem) toItem->removeGlimmer();
  3156. }
  3157.  
  3158. if(fromItem->isStackable())
  3159. {
  3160. if(toItem && toItem->getID() == fromItem->getID())
  3161. {
  3162. oldToCount = toItem->getItemCountOrSubtype();
  3163. int32_t newToCount = std::min(100, oldToCount + count);
  3164. toItem->setItemCountOrSubtype(newToCount);
  3165.  
  3166. if(oldToCount != newToCount)
  3167. {
  3168. autoCloseTrade(toItem);
  3169. }
  3170.  
  3171. int32_t subcount = oldFromCount - count;
  3172. fromItem->setItemCountOrSubtype(subcount);
  3173.  
  3174. int32_t surplusCount = oldToCount + count - 100;
  3175. if(surplusCount > 0)
  3176. {
  3177. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  3178. player->sendCancel("Sorry not enough room.");
  3179. }
  3180.  
  3181. if(fromItem->getItemCountOrSubtype() == 0)
  3182. {
  3183. if(fromTile->removeThing(fromItem))
  3184. {
  3185. this->FreeThing(fromItem);
  3186. }
  3187. }
  3188. }
  3189. else if(count < oldFromCount)
  3190. {
  3191. int32_t subcount = oldFromCount - count;
  3192. fromItem->setItemCountOrSubtype(subcount);
  3193.  
  3194. player->removeItemInventory(to_cid, true);
  3195. player->addItemInventory(Item::CreateItem(fromItem->getID(), count), to_cid, true);
  3196.  
  3197. if(toItem)
  3198. {
  3199. autoCloseTrade(toItem);
  3200. fromTile->addThing(toItem);
  3201. toItem->pos = fromPos;
  3202. }
  3203.  
  3204. if(fromItem->getItemCountOrSubtype() == 0)
  3205. {
  3206. if(fromTile->removeThing(fromItem))
  3207. {
  3208. this->FreeThing(fromItem);
  3209. }
  3210. }
  3211. }
  3212. else
  3213. {
  3214. if(fromTile->removeThing(fromItem))
  3215. {
  3216. player->removeItemInventory(to_cid, true);
  3217. player->addItemInventory(fromItem, to_cid, true);
  3218.  
  3219. if(toItem)
  3220. {
  3221. autoCloseTrade(toItem);
  3222. fromTile->addThing(toItem);
  3223. toItem->pos = fromPos;
  3224. }
  3225. }
  3226. }
  3227. }
  3228. else
  3229. {
  3230. if(fromTile->removeThing(fromItem))
  3231. {
  3232. player->removeItemInventory(to_cid, true);
  3233. player->addItemInventory(fromItem, to_cid, true);
  3234.  
  3235. if(toItem)
  3236. {
  3237. autoCloseTrade(toItem);
  3238. fromTile->addThing(toItem);
  3239. toItem->pos = fromPos;
  3240. }
  3241. }
  3242. }
  3243.  
  3244. player->updateInventoryWeigth();
  3245.  
  3246. SpectatorVec list;
  3247. SpectatorVec::iterator it;
  3248.  
  3249. getSpectators(Range(fromPos, true), list);
  3250.  
  3251. //players
  3252. for(it = list.begin(); it != list.end(); ++it)
  3253. {
  3254. if(dynamic_cast<Player*>(*it))
  3255. {
  3256. (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  3257. }
  3258. }
  3259.  
  3260. //none-players
  3261. for(it = list.begin(); it != list.end(); ++it)
  3262. {
  3263. if(!dynamic_cast<Player*>(*it))
  3264. {
  3265. (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  3266. }
  3267. }
  3268. }
  3269. }
  3270. }
  3271.  
  3272. //ground to ground
  3273. void Game::thingMoveInternal(Creature *creature, unsigned short from_x, unsigned short from_y, unsigned char from_z,
  3274. unsigned char stackPos, unsigned short itemid, unsigned short to_x, unsigned short to_y, unsigned char to_z, unsigned char count)
  3275. {
  3276. Tile *fromTile = getTile(from_x, from_y, from_z);
  3277. if(!fromTile)
  3278. return;
  3279.  
  3280. if(dynamic_cast<Player*>(creature) && fromTile && !fromTile->ground) {
  3281. dynamic_cast<Player*>(creature)->sendCancelWalk();
  3282. return;
  3283. }
  3284.  
  3285. Tile *toTile = getTile(to_x, to_y, to_z);
  3286. /*
  3287. if(!toTile){
  3288. if(dynamic_cast<Player*>(player))
  3289. dynamic_cast<Player*>(player)->sendCancelWalk("Sorry, not possible...");
  3290. return;
  3291. }
  3292. */
  3293.  
  3294. Thing *thing = fromTile->getThingByStackPos(stackPos);
  3295.  
  3296. if (!thing)
  3297. return;
  3298.  
  3299. Item* item = dynamic_cast<Item*>(thing);
  3300. Creature* creatureMoving = dynamic_cast<Creature*>(thing);
  3301. Player* playerMoving = dynamic_cast<Player*>(creatureMoving);
  3302. Player* player = dynamic_cast<Player*>(creature);
  3303.  
  3304. Position oldPos;
  3305. oldPos.x = from_x;
  3306. oldPos.y = from_y;
  3307. oldPos.z = from_z;
  3308.  
  3309. #ifdef TP_TRASH_BINS
  3310. if(toTile)
  3311. {
  3312. Thing *tothing = toTile->getThingByStackPos(stackPos);
  3313. Item *toItem = dynamic_cast<Item*>(tothing);
  3314.  
  3315. if(item && toItem && !playerMoving && !creature && toItem->isDeleter())
  3316. {
  3317. fromTile->removeThing(item);
  3318. this->FreeThing(item);
  3319. //creatureBroadcastTileUpdated(oldPos);
  3320. sendRemoveThing(player, item->pos, item, stackPos);
  3321. return;
  3322. }
  3323. }
  3324. #endif //TP_TRASH_BINS
  3325. /* if (toTile){
  3326. ItemVector::iterator brn;
  3327. for (brn = toTile->downItems.begin(); brn != toTile->downItems.end(); brn++)
  3328. {
  3329. if (playerMoving && (*brn)->getID() == 1397 && player != thing || playerMoving && (*brn)->getID() == 1487 && player != thing || playerMoving && (*brn)->getID() == 1488 && player != thing || playerMoving && (*brn)->getID() == 1490 && player != thing || playerMoving && (*brn)->getID() == 1491 && player != thing || playerMoving && (*brn)->getID() == 1492 && player != thing || playerMoving && (*brn)->getID() == 1493 && player != thing || playerMoving && (*brn)->getID() == 1495 && player != thing || playerMoving && (*brn)->getID() == 1496 && player != thing || playerMoving && (*brn)->getID() == 1500 && player != thing || playerMoving && (*brn)->getID() == 1501 && player != thing || playerMoving && (*brn)->getID() == 1503 && player != thing || playerMoving && (*brn)->getID() == 1504 && player != thing || playerMoving && (*brn)->getID() == 1505 && player != thing || playerMoving && (*brn)->getID() == 1506 && player != thing || playerMoving && (*brn)->getID() == 1507 && player != thing || playerMoving && (*brn)->getID() == 1423 && player != thing || playerMoving && (*brn)->getID() == 1424 && player != thing || playerMoving && (*brn)->getID() == 1425 && player != thing)
  3330. */
  3331. if(toTile && player && playerMoving && playerMoving != player && toTile->getFieldItem())
  3332. {
  3333. player->sendCancel("Sorry, not possible.");
  3334. return;
  3335. }
  3336. // *** Creature moving itself to a non-tile
  3337. if(!toTile && creatureMoving && creatureMoving == creature){
  3338. //change level begin
  3339. Tile* downTile = getTile(to_x, to_y, to_z+1);
  3340. //diagonal begin
  3341. if(!downTile)
  3342. {
  3343. if(player) {
  3344. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  3345. player->sendCancelWalk();
  3346. }
  3347.  
  3348. return;
  3349. }
  3350.  
  3351. if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  3352. teleport(creatureMoving, Position(creatureMoving->pos.x-2, creatureMoving->pos.y+2, creatureMoving->pos.z+1));
  3353. }
  3354. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  3355. teleport(creatureMoving, Position(creatureMoving->pos.x+2, creatureMoving->pos.y+2, creatureMoving->pos.z+1));
  3356. }
  3357. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  3358. teleport(creatureMoving, Position(creatureMoving->pos.x-2, creatureMoving->pos.y-2, creatureMoving->pos.z+1));
  3359. }
  3360. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  3361. teleport(creatureMoving, Position(creatureMoving->pos.x+2, creatureMoving->pos.y-2, creatureMoving->pos.z+1));
  3362. }
  3363. //diagonal end
  3364. else if(downTile->floorChange(NORTH)){
  3365. teleport(creatureMoving, Position(to_x, to_y + 1, creatureMoving->pos.z+1));
  3366. }
  3367. else if(downTile->floorChange(SOUTH)){
  3368. teleport(creatureMoving, Position(to_x, to_y - 1, creatureMoving->pos.z+1));
  3369. }
  3370. else if(downTile->floorChange(EAST)){
  3371. teleport(creatureMoving, Position(to_x - 1, to_y, creatureMoving->pos.z+1));
  3372. }
  3373. else if(downTile->floorChange(WEST)){
  3374. teleport(creatureMoving, Position(to_x + 1, to_y, creatureMoving->pos.z+1));
  3375. }
  3376. else
  3377. if(player) {
  3378. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  3379. player->sendCancelWalk();
  3380. }
  3381.  
  3382. //change level end
  3383. return;
  3384. }
  3385.  
  3386. #ifdef DT_PREMMY
  3387. if(player && playerMoving && !player->premmium == true){
  3388. if(!premmytiles.empty()){
  3389. for(int32_t o = 0; o < premmytiles.size(); o++) {
  3390. if((premmytiles[o].second.x != 0) &&
  3391. (premmytiles[o].second.y != 0) && (premmytiles[o].second.z != 0)){
  3392. if(Position(to_x, to_y, to_z) == premmytiles[o].first) {
  3393. player->sendCancelWalk();
  3394. teleport(playerMoving,
  3395. Position(premmytiles[o].second.x, premmytiles[o].second.y,
  3396. premmytiles[o].second.z));
  3397. player->sendMagicEffect(player->pos,
  3398. NM_ME_MAGIC_ENERGIE);
  3399. return;
  3400. }
  3401. }
  3402. else{
  3403. if(Position(to_x, to_y, to_z) == premmytiles[o].first) {
  3404. player->sendCancelWalk();
  3405. break;
  3406. }
  3407. }
  3408. }
  3409. }
  3410. }
  3411.  
  3412. #endif //DT_PREMMY
  3413.  
  3414.  
  3415.  
  3416. // *** Checking if the thing can be moved around
  3417.  
  3418. if(!toTile)
  3419. return;
  3420.  
  3421. if(!onPrepareMoveThing(creature, thing, oldPos, Position(to_x, to_y, to_z), count))
  3422. return;
  3423.  
  3424. if(creatureMoving && !onPrepareMoveCreature(creature, creatureMoving, fromTile, toTile))
  3425. return;
  3426.  
  3427. if(!onPrepareMoveThing(creature, thing, fromTile, toTile, count))
  3428. return;
  3429.  
  3430. Position to_pos;
  3431. to_pos.x = to_x;
  3432. to_pos.y = to_y;
  3433. to_pos.z = to_z;
  3434.  
  3435. Item* fromItem = dynamic_cast<Item*>(getThing(oldPos, stackPos, player));
  3436. Item* toItem = dynamic_cast<Item*>(toTile->getTopDownItem());
  3437.  
  3438. if(fromItem && fromItem->isStackable()){
  3439. if(fromItem->getItemCountOrSubtype() < count)
  3440. {
  3441. player->sendCancel("Sorry, not possible.");
  3442. return;
  3443. }
  3444.  
  3445. if((abs(player->pos.x - oldPos.x) > 1) || (abs(player->pos.y - oldPos.y) > 1) || (player->pos.z != oldPos.z)){
  3446. player->sendCancel("It's far away.");
  3447. return;
  3448. }
  3449. if(toItem && fromItem->getID() == toItem->getID()){
  3450. int32_t oldToCount = toItem->getItemCountOrSubtype();
  3451. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  3452. int32_t newToCount = std::min(100, oldToCount + count);
  3453. toItem->setItemCountOrSubtype(newToCount);
  3454.  
  3455. if(oldToCount != newToCount) {
  3456. autoCloseTrade(toItem);
  3457. }
  3458.  
  3459. int32_t subcount = oldFromCount - count;
  3460. fromItem->setItemCountOrSubtype(subcount);
  3461.  
  3462. int32_t surplusCount = oldToCount + count - 100;
  3463. if(surplusCount > 0) {
  3464. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  3465. surplusItem->pos = to_pos;
  3466. toTile->addThing(surplusItem);
  3467. }
  3468.  
  3469. if(fromItem->getItemCountOrSubtype() == 0) {
  3470. if(removeThing(player, oldPos, fromItem))
  3471. player->updateInventoryWeigth();
  3472. }
  3473.  
  3474. creatureBroadcastTileUpdated(to_pos);
  3475. creatureBroadcastTileUpdated(oldPos);
  3476.  
  3477. return;
  3478. }
  3479. else if(count < fromItem->getItemCountOrSubtype()) {
  3480. int32_t subcount = fromItem->getItemCountOrSubtype() - count;
  3481. fromItem->setItemCountOrSubtype(subcount);
  3482.  
  3483. Item *moveItem = Item::CreateItem(fromItem->getID(), count);
  3484. moveItem->pos = to_pos;
  3485. toTile->addThing(moveItem);
  3486.  
  3487. if(fromItem->getItemCountOrSubtype() == 0) {
  3488. if(removeThing(player, oldPos, fromItem))
  3489. player->updateInventoryWeigth();
  3490. }
  3491.  
  3492. creatureBroadcastTileUpdated(to_pos);
  3493. creatureBroadcastTileUpdated(oldPos);
  3494. return;
  3495. }
  3496. else{
  3497. Item *moveItem = Item::CreateItem(fromItem->getID(), fromItem->getItemCountOrSubtype());
  3498. moveItem->pos = to_pos;
  3499. toTile->addThing(moveItem);
  3500.  
  3501. if(removeThing(player, oldPos, fromItem))
  3502. player->updateInventoryWeigth();
  3503.  
  3504. creatureBroadcastTileUpdated(to_pos);
  3505. creatureBroadcastTileUpdated(oldPos);
  3506. return;
  3507. }
  3508.  
  3509. return;
  3510. }
  3511.  
  3512. /*
  3513. if(item && (item->getID() != itemid || item != fromTile->getTopDownItem()))
  3514. return;
  3515. */
  3516.  
  3517. // *** If the destiny is a teleport item, teleport the thing
  3518.  
  3519. const Teleport *teleportitem = toTile->getTeleportItem();
  3520. if(teleportitem) {
  3521. Player *player = dynamic_cast<Player*>(thing);
  3522. teleport(thing, teleportitem->getDestPos());
  3523. if(player) {
  3524. globalMagicEffect(player->pos, NM_ME_ENERGY_AREA);
  3525. }
  3526. return;
  3527. }
  3528.  
  3529. Monster* monsterMoving = dynamic_cast<Monster*>(creatureMoving);
  3530. if (monsterMoving && toTile->isPz()){
  3531. return;
  3532. }
  3533.  
  3534. #ifdef TLM_HOUSE_SYSTEM
  3535. if (playerMoving && toTile->getHouse() &&
  3536. (fromTile->getHouse() != toTile->getHouse() || playerMoving->houseRightsChanged))
  3537. {
  3538. if (playerMoving->access < g_config.ACCESS_HOUSE &&
  3539. toTile->getHouse()->getPlayerRights(playerMoving->getName()) == HOUSE_NONE)
  3540. {
  3541. playerMoving->sendTextMessage(MSG_SMALLINFO, "You are not invited.");
  3542. playerMoving->sendCancelWalk();
  3543. return;
  3544. }
  3545. else
  3546. playerMoving->houseRightsChanged = false; // if we are invited stop checking rights
  3547. }
  3548. #endif //TLM_HOUSE_SYSTEM
  3549.  
  3550. // *** Normal moving
  3551.  
  3552. if(creatureMoving)
  3553. {
  3554. // we need to update the direction the player is facing to...
  3555. // otherwise we are facing some problems in turning into the
  3556. // direction we were facing before the movement
  3557. // check y first cuz after a diagonal move we lock to east or west
  3558. if (to_y < oldPos.y) creatureMoving->direction = NORTH;
  3559. if (to_y > oldPos.y) creatureMoving->direction = SOUTH;
  3560. if (to_x > oldPos.x) creatureMoving->direction = EAST;
  3561. if (to_x < oldPos.x) creatureMoving->direction = WEST;
  3562. }
  3563.  
  3564. int32_t oldstackpos = fromTile->getThingStackPos(thing);
  3565. if (fromTile->removeThing(thing))
  3566. {
  3567. toTile->addThing(thing);
  3568.  
  3569. thing->pos.x = to_x;
  3570. thing->pos.y = to_y;
  3571. thing->pos.z = to_z;
  3572.  
  3573. SpectatorVec list;
  3574. SpectatorVec::iterator it;
  3575.  
  3576. getSpectators(Range(oldPos, Position(to_x, to_y, to_z)), list);
  3577.  
  3578. #ifdef TRS_GM_INVISIBLE
  3579. if(playerMoving && playerMoving->gmInvisible)
  3580. {
  3581. for(it = list.begin(); it != list.end(); ++it)
  3582. {
  3583. if(playerMoving == (*it) || (*it)->access >= playerMoving->access)
  3584. {
  3585. if(Player* p = dynamic_cast<Player*>(*it))
  3586. {
  3587. if(p->attackedCreature == creature->getID())
  3588. {
  3589. autoCloseAttack(p, creature);
  3590. }
  3591. (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3592. }
  3593. }
  3594. }
  3595. }
  3596. else if(playerMoving && !playerMoving->gmInvisible)
  3597. {
  3598. for(it = list.begin(); it != list.end(); ++it)
  3599. {
  3600. if(Player* p = dynamic_cast<Player*>(*it))
  3601. {
  3602. if(p->attackedCreature == creature->getID())
  3603. {
  3604. autoCloseAttack(p, creature);
  3605. }
  3606. (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3607. }
  3608. }
  3609. }
  3610. else
  3611. {
  3612. for(it = list.begin(); it != list.end(); ++it)
  3613. {
  3614. if(Player* p = dynamic_cast<Player*>(*it))
  3615. {
  3616. if(p->attackedCreature == creature->getID())
  3617. {
  3618. autoCloseAttack(p, creature);
  3619. }
  3620. (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3621. }
  3622. }
  3623. }
  3624. #else //TRS_GM_INVISIBLE
  3625. //players
  3626. for(it = list.begin(); it != list.end(); ++it)
  3627. {
  3628. if(Player* p = dynamic_cast<Player*>(*it)) {
  3629. if(p->attackedCreature == creature->getID()) {
  3630. autoCloseAttack(p, creature);
  3631. }
  3632. (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3633. }
  3634. }
  3635. #endif //TRS_GM_INVISIBLE
  3636.  
  3637. //none-players
  3638. for(it = list.begin(); it != list.end(); ++it)
  3639. {
  3640. if(!dynamic_cast<Player*>(*it)) {
  3641. (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3642. }
  3643. }
  3644.  
  3645. autoCloseTrade(item, true);
  3646. //depot tiles
  3647.  
  3648. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 426))
  3649. {
  3650. int32_t e = 0;
  3651. Container* c = playerMoving->getDepot(1);
  3652. std::stringstream s;
  3653. e += getDepot(c, e);
  3654. s << "Your depot contains " << e;
  3655. if(e > 1)
  3656. s << " items.";
  3657. else
  3658. s << " item.";
  3659. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3660. }
  3661.  
  3662. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 416))
  3663. {
  3664. int32_t e = 0;
  3665. Container* c = playerMoving->getDepot(2);
  3666. std::stringstream s;
  3667. e += getDepot(c, e);
  3668. s << "Your depot contains " << e;
  3669. if(e > 1)
  3670. s << " items.";
  3671. else
  3672. s << " item.";
  3673. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3674. }
  3675.  
  3676. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 446))
  3677. {
  3678. int32_t e = 0;
  3679. Container* c = playerMoving->getDepot(3);
  3680. std::stringstream s;
  3681. e += getDepot(c, e);
  3682. s << "Your depot contains " << e;
  3683. if(e > 1)
  3684. s << " items.";
  3685. else
  3686. s << " item.";
  3687. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3688. }
  3689.  
  3690. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 3216))
  3691. {
  3692. int32_t e = 0;
  3693. Container* c = playerMoving->getDepot(4);
  3694. std::stringstream s;
  3695. e += getDepot(c, e);
  3696. s << "Your depot contains " << e;
  3697. if(e > 1)
  3698. s << " items.";
  3699. else
  3700. s << " item.";
  3701. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3702. }
  3703.  
  3704. if(playerMoving && toTile && fromTile)
  3705. {
  3706. actions.luaWalk(playerMoving,playerMoving->pos,toTile->ground->getID(),toTile->ground->getUniqueId(),toTile->ground->getActionId()); //CHANGE onWalk
  3707. }
  3708.  
  3709. if(playerMoving && toTile && fromTile)
  3710. {
  3711. actions.luaWalkOff(playerMoving,oldPos,fromTile->ground->getID(),fromTile->ground->getUniqueId(),fromTile->ground->getActionId()); //CHANGE onWalk
  3712. }
  3713.  
  3714. if(playerMoving && fromTile && toTile && player == playerMoving)
  3715. switch(toTile->ground->getID())
  3716. {
  3717. case 416:
  3718. {
  3719. toTile->removeThing(toTile->ground);
  3720. toTile->addThing(new Item(417));
  3721. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3722. }
  3723. break;
  3724.  
  3725. case 426:
  3726. {
  3727. toTile->removeThing(toTile->ground);
  3728. toTile->addThing(new Item(425));
  3729. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3730. }
  3731. break;
  3732. case 3216:
  3733. {
  3734. toTile->removeThing(toTile->ground);
  3735. toTile->addThing(new Item(3217));
  3736. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3737. }
  3738. break;
  3739. case 446:
  3740. {
  3741. toTile->removeThing(toTile->ground);
  3742. toTile->addThing(new Item(447));
  3743. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3744. }
  3745. break;
  3746. case 293:
  3747. {
  3748. toTile->removeThing(toTile->ground);
  3749. toTile->addThing(new Item(294));
  3750. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3751. }
  3752. break;
  3753. }
  3754. switch(fromTile->ground->getID())
  3755. {
  3756. case 3217:
  3757. {
  3758. fromTile->removeThing(fromTile->ground);
  3759. fromTile->addThing(new Item(3216));
  3760. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3761. break;
  3762. }
  3763. case 417:
  3764. {
  3765. fromTile->removeThing(fromTile->ground);
  3766. fromTile->addThing(new Item(416));
  3767. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3768. break;
  3769. }
  3770. case 425:
  3771. {
  3772. fromTile->removeThing(fromTile->ground);
  3773. fromTile->addThing(new Item(426));
  3774. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3775. break;
  3776. }
  3777. case 447:
  3778. {
  3779. fromTile->removeThing(fromTile->ground);
  3780. fromTile->addThing(new Item(446));
  3781. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3782. break;
  3783. }
  3784. }
  3785. //end depot tiles-+
  3786. if (playerMoving)
  3787. {
  3788. if(playerMoving->attackedCreature != 0) {
  3789. Creature* attackedCreature = getCreatureByID(creatureMoving->attackedCreature);
  3790. if(attackedCreature){
  3791. autoCloseAttack(playerMoving, attackedCreature);
  3792. }
  3793. }
  3794.  
  3795. if(playerMoving->tradePartner != 0) {
  3796. Player* tradePartner = getPlayerByID(playerMoving->tradePartner);
  3797. if(tradePartner) {
  3798. if((std::abs(playerMoving->pos.x - tradePartner->pos.x) > 2) ||
  3799. (std::abs(playerMoving->pos.y - tradePartner->pos.y) > 2) || (playerMoving->pos.z != tradePartner->pos.z)
  3800. #ifdef HUCZU_FIX
  3801. || (fromTile->isHouse() && !toTile->isHouse())
  3802. #endif //HUCZU_FIX
  3803. ){
  3804. playerCloseTrade(playerMoving);
  3805. }
  3806. }
  3807. }
  3808.  
  3809. //change level begin
  3810. if(toTile->floorChangeDown())
  3811. {
  3812. Tile* downTile = getTile(to_x, to_y, to_z+1);
  3813. if(downTile){
  3814. //diagonal begin
  3815. if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  3816. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y+1, playerMoving->pos.z+1));
  3817. }
  3818. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  3819. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y+1, playerMoving->pos.z+1));
  3820. }
  3821. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  3822. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y-1, playerMoving->pos.z+1));
  3823. }
  3824. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  3825. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y-1, playerMoving->pos.z+1));
  3826. }
  3827. //diagonal end
  3828. else if(downTile->floorChange(NORTH)){
  3829. teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y+1, playerMoving->pos.z+1));
  3830. }
  3831. else if(downTile->floorChange(SOUTH)){
  3832. teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y-1, playerMoving->pos.z+1));
  3833. }
  3834. else if(downTile->floorChange(EAST)){
  3835. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y, playerMoving->pos.z+1));
  3836. }
  3837. else if(downTile->floorChange(WEST)){
  3838. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y, playerMoving->pos.z+1));
  3839. }
  3840. else { //allow just real tiles to be hole'like
  3841. // TODO: later can be changed to check for piled items like chairs, boxes
  3842. teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y, playerMoving->pos.z+1));
  3843. }
  3844. }
  3845. }
  3846. //diagonal begin
  3847. else if(toTile->floorChange(NORTH) && toTile->floorChange(EAST)){
  3848. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y-1, playerMoving->pos.z-1));
  3849. }
  3850. else if(toTile->floorChange(NORTH) && toTile->floorChange(WEST)){
  3851. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y-1, playerMoving->pos.z-1));
  3852. }
  3853. else if(toTile->floorChange(SOUTH) && toTile->floorChange(EAST)){
  3854. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y+1, playerMoving->pos.z-1));
  3855. }
  3856. else if(toTile->floorChange(SOUTH) && toTile->floorChange(WEST)){
  3857. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y+1, playerMoving->pos.z-1));
  3858. }
  3859. //diagonal end
  3860. else if(toTile->floorChange(NORTH)){
  3861. teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y-1, playerMoving->pos.z-1));
  3862. }
  3863. else if(toTile->floorChange(SOUTH)){
  3864. teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y+1, playerMoving->pos.z-1));
  3865. }
  3866. else if(toTile->floorChange(EAST)){
  3867. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y, playerMoving->pos.z-1));
  3868. }
  3869. else if(toTile->floorChange(WEST)){
  3870. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y, playerMoving->pos.z-1));
  3871. }
  3872. //change level end
  3873. }
  3874.  
  3875. // Magic Field in destiny field
  3876. #ifdef HUCZU_FIX
  3877. if(toTile && playerMoving && playerMoving->access < g_config.ACCESS_PROTECT && !toTile->downItems.empty() && !toTile->isPvpArena())
  3878. #else
  3879. if(toTile && playerMoving && playerMoving->access < g_config.ACCESS_PROTECT && !toTile->downItems.empty() || toTile && creatureMoving && creatureMoving->access < g_config.ACCESS_PROTECT && !toTile->downItems.empty())
  3880. #endif //HUCZU_FIX
  3881. {
  3882. ItemVector::iterator iit;
  3883. for (iit = toTile->downItems.begin(); iit != toTile->downItems.end(); iit++)
  3884. {
  3885. if(toTile->isPvpArena()) break;
  3886. if(!(*iit)) continue;
  3887. Item *item = dynamic_cast<Item*>(*iit);
  3888. if(!item) continue;
  3889. if(!creatureMoving || creatureMoving->isRemoved || creatureMoving->health <= 0) break;
  3890. if (item->getID() == 1492 || item->getID() == 1423 || item->getID() == 1487 || item->getID() == 1500){//Fire - Big
  3891. doFieldDamage(creatureMoving, 199 , NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 20);
  3892. // creature DamageColor, damageEffect, hitEffect attackType, offensive, damage
  3893. if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3894. CreateCondition(creatureMoving, NULL, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 10, 10, 2000, 10);
  3895. }
  3896. else if(item->getID() == 1493 || item->getID() == 1424 || item->getID() == 1488 || item->getID() == 1501){//Fire Medium
  3897. doFieldDamage(creatureMoving, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 10);
  3898. if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3899. CreateCondition(creatureMoving, NULL, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 10, 10, 2000, 10);
  3900. }
  3901. else if(item->getID() == 1495 || item->getID() == 1491 || item->getID() == 1504){//Energy
  3902. doFieldDamage(creatureMoving, 71, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 30);
  3903. if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3904. CreateCondition(creatureMoving, NULL, 71, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 30, 30, 2000, 3);
  3905. }
  3906. else if(item->getID() == 1496 || item->getID() == 1490 || item->getID() == 1503 || item->getID() == 1505){//Poison
  3907. doFieldDamage(creatureMoving, 30, NM_ME_POISEN, NM_ME_POISEN, ATTACK_POISON, true, 10);
  3908. if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3909. CreateCondition(creatureMoving, NULL, 30, NM_ME_POISEN, NM_ME_POISEN_RINGS, ATTACK_POISON, true, 10, 10, 2000, 10);
  3910. }
  3911. }
  3912. }
  3913. }
  3914.  
  3915. if(creatureMoving && !toTile->isPvpArena())
  3916. {
  3917. const MagicEffectItem* fieldItem = toTile->getFieldItem();
  3918.  
  3919. if(fieldItem) {
  3920. const MagicEffectTargetCreatureCondition *magicTargetCondition = fieldItem->getCondition();
  3921.  
  3922. if(!(getWorldType() == WORLD_TYPE_NO_PVP && playerMoving && magicTargetCondition && magicTargetCondition->getOwnerID() != 0)) {
  3923. fieldItem->getDamage(creatureMoving);
  3924. }
  3925.  
  3926. if(magicTargetCondition && ((magicTargetCondition->attackType == ATTACK_FIRE) ||
  3927. (magicTargetCondition->attackType == ATTACK_POISON) ||
  3928. (magicTargetCondition->attackType == ATTACK_ENERGY))) {
  3929. Creature *c = getCreatureByID(magicTargetCondition->getOwnerID());
  3930. creatureMakeMagic(c, thing->pos, magicTargetCondition);
  3931. }
  3932. }
  3933. }
  3934. }
  3935.  
  3936.  
  3937. void Game::getSpectators(const Range& range, SpectatorVec& list)
  3938. {
  3939. map->getSpectators(range, list);
  3940. }
  3941.  
  3942. void Game::creatureTurn(Creature *creature, Direction dir)
  3943. {
  3944. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureTurn()");
  3945.  
  3946. if (creature->direction != dir) {
  3947. creature->direction = dir;
  3948.  
  3949. int32_t stackpos = map->getTile(creature->pos)->getThingStackPos(creature);
  3950.  
  3951. SpectatorVec list;
  3952. SpectatorVec::iterator it;
  3953.  
  3954. map->getSpectators(Range(creature->pos, true), list);
  3955.  
  3956. //players
  3957. for(it = list.begin(); it != list.end(); ++it) {
  3958. if(dynamic_cast<Player*>(*it)) {
  3959. (*it)->onCreatureTurn(creature, stackpos);
  3960. }
  3961. }
  3962.  
  3963. //none-players
  3964. for(it = list.begin(); it != list.end(); ++it) {
  3965. if(!dynamic_cast<Player*>(*it)) {
  3966. (*it)->onCreatureTurn(creature, stackpos);
  3967. }
  3968. }
  3969. }
  3970. }
  3971.  
  3972. void Game::addCommandTag(std::string tag){
  3973. bool found = false;
  3974. for(size_t i=0;i< commandTags.size() ;i++){
  3975. if(commandTags[i] == tag){
  3976. found = true;
  3977. break;
  3978. }
  3979. }
  3980. if(!found){
  3981. commandTags.push_back(tag);
  3982. }
  3983. }
  3984.  
  3985. void Game::resetCommandTag(){
  3986. commandTags.clear();
  3987. }
  3988.  
  3989. void Game::creatureSay(Creature *creature, SpeakClasses type, const std::string &text)
  3990. {
  3991. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureSay()");
  3992. using std::string;
  3993. string spoken=text;
  3994. std::transform(spoken.begin(), spoken.end(), spoken.begin(), (int32_t(*)(int32_t))std::tolower);
  3995. bool GMcommand = false;
  3996. // First, check if this was a GM command
  3997. for(size_t i=0;i< commandTags.size() ;i++){
  3998. if(commandTags[i] == text.substr(0,1)){
  3999. if(commands.exeCommand(creature,text)){
  4000. GMcommand = true;
  4001. }
  4002. break;
  4003. }
  4004. }
  4005. Player* p = dynamic_cast<Player*>(creature);
  4006. Player* player = dynamic_cast<Player*>(creature);
  4007.  
  4008. #ifdef HUCZU_FIX
  4009. if (player && spoken == "exevo grav vita" && (!g_config.LEARN_SPELLS || player->knowsSpell("exevo grav vita")))
  4010. {
  4011. Tile *tile = NULL;
  4012. Position wgpos;
  4013. wgpos.z = player->pos.z;
  4014. switch(player->direction)
  4015. {
  4016. case NORTH:
  4017. wgpos.x = player->pos.x;
  4018. wgpos.y = player->pos.y-1;
  4019. break;
  4020. case SOUTH:
  4021. wgpos.x = player->pos.x;
  4022. wgpos.y = player->pos.y+1;
  4023. break;
  4024. case EAST:
  4025. wgpos.x = player->pos.x+1;
  4026. wgpos.y = player->pos.y;
  4027. break;
  4028. case WEST:
  4029. wgpos.x = player->pos.x-1;
  4030. wgpos.y = player->pos.y;
  4031. break;
  4032. default:
  4033. break;
  4034. }
  4035. tile = getTile(wgpos.x, wgpos.y, wgpos.z);
  4036. if(!tile || tile->isBlocking(BLOCK_SOLID,false,false) || tile->isPz())
  4037. {
  4038. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4039. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  4040. return;
  4041. }
  4042. if(player->access < 2)
  4043. {
  4044. if(player->mana < 220)
  4045. {
  4046. player->sendCancel("You do not have enough mana.");
  4047. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4048. return;
  4049. }
  4050. if(!player->premmium)
  4051. {
  4052. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4053. player->sendCancel("You need buy a premmium account for use this spell");
  4054. return;
  4055. }
  4056. if(player->maglevel < 26){
  4057. player->sendCancel("You do not have the magic level.");
  4058. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4059. return;
  4060. }
  4061. if(player->vocation != 2)
  4062. {
  4063. player->sendTextMessage(MSG_SMALLINFO, "You do not have the required vocation.");
  4064. player->sendMagicEffect(player->pos, 2);
  4065. return;
  4066. }
  4067. if (player->exhaustedTicks >= 1000)
  4068. {
  4069. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4070. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  4071. return;
  4072. }
  4073. }
  4074. player->mana -= 220;
  4075. player->addManaSpent(220);
  4076. player->exhaustedTicks = g_config.EXHAUSTED;
  4077. Item* Tree = Item::CreateItem(ITEM_WILDGROWTH, 1);
  4078. addThing(NULL, wgpos, Tree);
  4079. startDecay(Tree);
  4080. SpectatorVec list;
  4081. SpectatorVec::iterator it;
  4082. getSpectators(Range(player->pos), list);
  4083. for(it = list.begin(); it != list.end(); ++it) {
  4084. Player* playerek = dynamic_cast<Player*>(*it);
  4085. if(playerek)
  4086. playerek->sendMagicEffect(playerek->pos, NM_ME_MAGIC_POISEN);
  4087. }
  4088. player->sendMagicEffect(player->pos, NM_ME_MAGIC_ENERGIE);
  4089. }
  4090. #endif //HUCZU_FIX
  4091.  
  4092. if(spoken=="exana pox"){
  4093. MagicEffectClass pox;
  4094. pox.animationColor = 0;
  4095. pox.damageEffect = NM_ME_MAGIC_ENERGIE;
  4096. pox.hitEffect = 255;
  4097. pox.attackType = ATTACK_NONE;
  4098. pox.maxDamage = 0;
  4099. pox.minDamage = 0;
  4100. pox.offensive = false;
  4101. pox.manaCost = 30;
  4102. if(creatureMakeMagic(creature, creature->pos, &pox)){
  4103. creature->removeCondition(ATTACK_POISON);
  4104.  
  4105. if(player)
  4106. player->sendIcons();
  4107. }
  4108. }
  4109.  
  4110. if(!GMcommand){
  4111. Player* player = dynamic_cast<Player*>(creature);
  4112.  
  4113. if(text=="!besthit")
  4114. {
  4115. std::stringstream info;
  4116. if(player->maxDmg>0){
  4117. info << "Your best hit: " << player->maxDmg;}
  4118. else{
  4119. info << "You didn't any damage.";}
  4120. player->sendTextMessage(MSG_EVENT,info.str().c_str());
  4121. }
  4122.  
  4123. if(player && (text[0] == 'e' || text[0] == 'E') && (text[1] == 'x' || text[1] == 'X') && (text[2] == 'a' || text[2] == 'A') && (text[3] == 'n' || text[3] == 'N') && (text[4] == 'a' || text[4] == 'A') && (text[5] == ' ') && (text[6] == 'a' || text[6] == 'A') && (text[7] == 'n' || text[7] == 'N') && (text[8] == 'i' || text[8] == 'i')) {
  4124.  
  4125. if(player->mana < 200) {
  4126. player->sendCancel("You do not have enough mana.");
  4127. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4128. return;
  4129. }
  4130. if(player->maglevel < 15) {
  4131. player->sendCancel("You do not have the magic level.");
  4132. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4133. return;
  4134. }
  4135. if(player->vocation != 1)
  4136. {
  4137. player->sendTextMessage(MSG_SMALLINFO, "You do not have the required vocation.");
  4138. player->sendMagicEffect(player->pos, 2);
  4139. return;
  4140. }
  4141. player->mana -= 200;
  4142. player->addManaSpent(200);
  4143. SpectatorVec list;
  4144. SpectatorVec::iterator it;
  4145. getSpectators(Range(creature->pos), list);
  4146. for(it = list.begin(); it != list.end(); ++it) {
  4147. if(Creature *c = dynamic_cast<Creature*>(*it)) {
  4148. if(c)
  4149. {
  4150. c->setInvisible(0);
  4151. creatureChangeOutfit(c);
  4152. }
  4153. }
  4154. player->sendMagicEffect(player->pos, NM_ME_MAGIC_ENERGIE);
  4155. }
  4156. }
  4157. if (player)
  4158. checkSpell(player, type, text);
  4159. // It was no command, or it was just a player
  4160. SpectatorVec list;
  4161. SpectatorVec::iterator it;
  4162. getSpectators(Range(creature->pos), list);
  4163. //players
  4164. for(it = list.begin(); it != list.end(); ++it) {
  4165. if(dynamic_cast<Player*>(*it)) {
  4166. (*it)->onCreatureSay(creature, type, text);
  4167. }
  4168. }
  4169.  
  4170. //none-players
  4171. for(it = list.begin(); it != list.end(); ++it) {
  4172. if(!dynamic_cast<Player*>(*it)) {
  4173. (*it)->onCreatureSay(creature, type, text);
  4174. }
  4175. }
  4176. }
  4177. }
  4178.  
  4179. void Game::teleport(Thing *thing, const Position& newPos)
  4180. {
  4181.  
  4182. if (newPos == thing->pos)
  4183. return;
  4184.  
  4185. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::teleport()");
  4186.  
  4187. //Tile *toTile = getTile( newPos.x, newPos.y, newPos.z );
  4188. Tile *toTile = map->getTile(newPos);
  4189. if (toTile)
  4190. {
  4191. Creature *creature = dynamic_cast<Creature*>(thing);
  4192. if (creature)
  4193. {
  4194. //Tile *fromTile = getTile( thing->pos.x, thing->pos.y, thing->pos.z );
  4195. Tile *fromTile = map->getTile(thing->pos);
  4196. if (!fromTile)
  4197. return;
  4198.  
  4199. int osp = fromTile->getThingStackPos(thing);
  4200. if (!fromTile->removeThing(thing))
  4201. return;
  4202.  
  4203. toTile->addThing(thing);
  4204. Position oldPos = thing->pos;
  4205.  
  4206. SpectatorVec list;
  4207. SpectatorVec::iterator it;
  4208.  
  4209. getSpectators(Range(thing->pos, true), list);
  4210.  
  4211. //players
  4212. for (it = list.begin(); it != list.end(); ++it)
  4213. {
  4214. if (Player* p = dynamic_cast<Player*>(*it))
  4215. {
  4216. if (p->attackedCreature == creature->getID())
  4217. {
  4218. autoCloseAttack(p, creature);
  4219. }
  4220.  
  4221. (*it)->onCreatureDisappear(creature, osp, true);
  4222. }
  4223. }
  4224.  
  4225. //none-players
  4226. for (it = list.begin(); it != list.end(); ++it)
  4227. {
  4228. if (!dynamic_cast<Player*>(*it))
  4229. {
  4230. (*it)->onCreatureDisappear(creature, osp, true);
  4231. }
  4232. }
  4233.  
  4234. if (newPos.y < oldPos.y)
  4235. creature->direction = NORTH;
  4236. if (newPos.y > oldPos.y)
  4237. creature->direction = SOUTH;
  4238. if (newPos.x > oldPos.x && (std::abs(newPos.x - oldPos.x) >= std::abs(newPos.y - oldPos.y)))
  4239. creature->direction = EAST;
  4240. if (newPos.x < oldPos.x && (std::abs(newPos.x - oldPos.x) >= std::abs(newPos.y - oldPos.y)))
  4241. creature->direction = WEST;
  4242.  
  4243. thing->pos = newPos;
  4244.  
  4245. Player *player = dynamic_cast<Player*>(creature);
  4246. if (player && player->attackedCreature != 0)
  4247. {
  4248. Creature* attackedCreature = getCreatureByID(player->attackedCreature);
  4249. if (attackedCreature)
  4250. {
  4251. autoCloseAttack(player, attackedCreature);
  4252. }
  4253. }
  4254.  
  4255. list.clear();
  4256. getSpectators(Range(thing->pos, true), list);
  4257.  
  4258. #ifdef TRS_GM_INVISIBLE
  4259. //players
  4260. for (it = list.begin(); it != list.end(); ++it)
  4261. {
  4262. if (player)
  4263. {
  4264. if (player->gmInvisible && player == (*it))
  4265. {
  4266. if (Player* p = dynamic_cast<Player*>(*it))
  4267. {
  4268. if (p->attackedCreature == creature->getID())
  4269. {
  4270. autoCloseAttack(p, creature);
  4271. }
  4272. (*it)->onTeleport(creature, &oldPos, osp);
  4273. }
  4274. }
  4275. else if (player->gmInvisible && player != (*it) && (*it)->access < player->access)
  4276. {
  4277. // Nothing Because he is invisible...
  4278. }
  4279. else
  4280. {
  4281. if (Player* p = dynamic_cast<Player*>(*it))
  4282. {
  4283. if (p->attackedCreature == creature->getID())
  4284. {
  4285. autoCloseAttack(p, creature);
  4286. }
  4287. (*it)->onTeleport(creature, &oldPos, osp);
  4288. }
  4289. }
  4290. }
  4291. else
  4292. creatureBroadcastTileUpdated(newPos);
  4293. }
  4294. #else //TRS_GM_INVISIBLE
  4295. //players
  4296. for (it = list.begin(); it != list.end(); ++it)
  4297. {
  4298. if (Player* p = dynamic_cast<Player*>(*it))
  4299. {
  4300. if (p->attackedCreature == creature->getID())
  4301. {
  4302. autoCloseAttack(p, creature);
  4303. }
  4304. (*it)->onTeleport(creature, &oldPos, osp);
  4305. }
  4306. }
  4307. #endif //TRS_GM_INVISIBLE
  4308.  
  4309. //none-players
  4310. for (it = list.begin(); it != list.end(); ++it)
  4311. {
  4312. if (!dynamic_cast<Player*>(*it))
  4313. {
  4314. (*it)->onTeleport(creature, &oldPos, osp);
  4315. }
  4316. }
  4317. }
  4318. else
  4319. {
  4320. if (removeThing(NULL, thing->pos, thing, false))
  4321. {
  4322. addThing(NULL, newPos, thing);
  4323. }
  4324. }
  4325. }//if(toTile)
  4326.  
  4327. }
  4328.  
  4329.  
  4330. void Game::creatureChangeOutfit(Creature *creature)
  4331. {
  4332. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureChangeOutfit()");
  4333.  
  4334. SpectatorVec list;
  4335. SpectatorVec::iterator it;
  4336.  
  4337. getSpectators(Range(creature->pos, true), list);
  4338.  
  4339. //players
  4340. for(it = list.begin(); it != list.end(); ++it) {
  4341. if(dynamic_cast<Player*>(*it)) {
  4342. (*it)->onCreatureChangeOutfit(creature);
  4343. }
  4344. }
  4345.  
  4346. //none-players
  4347. for(it = list.begin(); it != list.end(); ++it) {
  4348. if(!dynamic_cast<Player*>(*it)) {
  4349. (*it)->onCreatureChangeOutfit(creature);
  4350. }
  4351. }
  4352. }
  4353.  
  4354. void Game::creatureWhisper(Creature *creature, const std::string &text)
  4355. {
  4356. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureWhisper()");
  4357.  
  4358. SpectatorVec list;
  4359. SpectatorVec::iterator it;
  4360.  
  4361. getSpectators(Range(creature->pos), list);
  4362.  
  4363. //players
  4364. for(it = list.begin(); it != list.end(); ++it) {
  4365. if(dynamic_cast<Player*>(*it)) {
  4366. if(abs(creature->pos.x - (*it)->pos.x) > 1 || abs(creature->pos.y - (*it)->pos.y) > 1)
  4367. (*it)->onCreatureSay(creature, SPEAK_WHISPER, std::string("pspsps"));
  4368. else
  4369. (*it)->onCreatureSay(creature, SPEAK_WHISPER, text);
  4370. }
  4371. }
  4372.  
  4373. //none-players
  4374. for(it = list.begin(); it != list.end(); ++it) {
  4375. if(!dynamic_cast<Player*>(*it)) {
  4376. if(abs(creature->pos.x - (*it)->pos.x) > 1 || abs(creature->pos.y - (*it)->pos.y) > 1)
  4377. (*it)->onCreatureSay(creature, SPEAK_WHISPER, std::string("pspsps"));
  4378. else
  4379. (*it)->onCreatureSay(creature, SPEAK_WHISPER, text);
  4380. }
  4381. }
  4382. }
  4383.  
  4384. void Game::creatureYell(Creature *creature, std::string &text)
  4385. {
  4386. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureYell()");
  4387. if(!creature)
  4388. return;
  4389. #ifdef HUCZU_FIX
  4390. if(creature->level < 2 && creature->access < 2){
  4391. return;
  4392. }
  4393. #endif //HUCZU_FIX
  4394. std::transform(text.begin(), text.end(), text.begin(), upchar);
  4395.  
  4396. SpectatorVec list;
  4397. SpectatorVec::iterator it;
  4398. getSpectators(Range(creature->pos, 18, 18, 14, 14), list);
  4399.  
  4400. for(it = list.begin(); it != list.end(); ++it){
  4401. if(*it)
  4402. (*it)->onCreatureSay(creature, SPEAK_YELL, text);
  4403. }
  4404. }
  4405.  
  4406. //ZBÊ„NE
  4407. /*void Game::creatureYell(Creature *creature, std::string &text)
  4408. {
  4409. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureYell()");
  4410. Player* player = dynamic_cast<Player*>(creature);
  4411. #ifdef HUCZU_FIX
  4412. if(player && player->level < 2 && player->access < 2){
  4413. player->sendTextMessage(MSG_SMALLINFO, "You cannot yell.");
  4414. return;
  4415. }
  4416. #endif //HUCZU_FIX
  4417. if (player && player->access < g_config.ACCESS_PROTECT && player->exhaustedTicks >= 1000)
  4418. {
  4419. player->exhaustedTicks += g_config.EXHAUSTED_ADD;
  4420. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  4421. }
  4422. else {
  4423. creature->exhaustedTicks = g_config.EXHAUSTED;
  4424. std::transform(text.begin(), text.end(), text.begin(), upchar);
  4425.  
  4426. SpectatorVec list;
  4427. SpectatorVec::iterator it;
  4428.  
  4429. getSpectators(Range(creature->pos, 18, 18, 14, 14), list);
  4430.  
  4431. //players
  4432. for(it = list.begin(); it != list.end(); ++it) {
  4433. if(dynamic_cast<Player*>(*it)) {
  4434. (*it)->onCreatureSay(creature, SPEAK_YELL, text);
  4435. }
  4436. }
  4437. }
  4438. }*/
  4439.  
  4440. void Game::creatureSpeakTo(Creature *creature, SpeakClasses type,const std::string &receiver, const std::string &text)
  4441. {
  4442. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureSpeakTo");
  4443.  
  4444. Player* player = dynamic_cast<Player*>(creature);
  4445. if(!player)
  4446. return;
  4447.  
  4448. Player* toPlayer = getPlayerByName(receiver);
  4449. if(!toPlayer) {
  4450. player->sendTextMessage(MSG_SMALLINFO, "A player with this name is not online.");
  4451. return;
  4452. }
  4453. if(creature->access < g_config.ACCESS_TALK){
  4454. type = SPEAK_PRIVATE;
  4455. }
  4456.  
  4457. if(!toPlayer){
  4458. player->onCreatureSay(player, type, text);
  4459. }
  4460. time_t ticks = time(0);
  4461. tm* now = localtime(&ticks);
  4462. char buf[32];
  4463. strftime(buf, sizeof(buf), "%d/%m/%Y %H:%M", now);
  4464. std::ofstream out2("data/logs/private.log", std::ios::app);
  4465. out2 << '[' << buf << "] " << toPlayer->getName() << " from " << player->getName() << ": " << text << std::endl;
  4466. out2.close();
  4467.  
  4468. toPlayer->onCreatureSay(player, type, text);
  4469. std::stringstream ss;
  4470. ss << "Message sent to " << toPlayer->getName() << ".";
  4471. player->sendTextMessage(MSG_SMALLINFO, ss.str().c_str());
  4472. }
  4473.  
  4474. void Game::creatureTalkToChannel(Player *player, SpeakClasses type, std::string &text, uint16_t channelId)
  4475. {
  4476. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureTalkToChannel");
  4477.  
  4478. if(player->access < g_config.ACCESS_TALK){
  4479. type = SPEAK_CHANNEL_Y;
  4480. }
  4481.  
  4482. if(player->guildStatus == GUILD_LEADER && channelId == 0x00)
  4483. type = SPEAK_CHANNEL_R1;
  4484. if(player->guildStatus == GUILD_VICE && channelId == 0x00)
  4485. type = SPEAK_CHANNEL_O;
  4486.  
  4487. g_chat.talkToChannel(player, type, text, channelId);
  4488. }
  4489.  
  4490. void Game::creatureMonsterYell(Monster* monster, const std::string& text)
  4491. {
  4492. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureMonsterYell()");
  4493.  
  4494. SpectatorVec list;
  4495. SpectatorVec::iterator it;
  4496.  
  4497. map->getSpectators(Range(monster->pos, 18, 18, 14, 14), list);
  4498.  
  4499. //players
  4500. for(it = list.begin(); it != list.end(); ++it) {
  4501. if(dynamic_cast<Player*>(*it)) {
  4502. (*it)->onCreatureSay(monster, SPEAK_MONSTER1, text);
  4503. }
  4504. }
  4505. }
  4506.  
  4507. void Game::creatureBroadcastMessage(Creature *creature, const std::string &text)
  4508. {
  4509. if(creature->access < g_config.ACCESS_TALK)
  4510. return;
  4511.  
  4512. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureBroadcastMessage()");
  4513.  
  4514. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  4515. {
  4516. (*it).second->onCreatureSay(creature, SPEAK_BROADCAST, text);
  4517. }
  4518. }
  4519.  
  4520. /** \todo Someone _PLEASE_ clean up this mess */
  4521. bool Game::creatureMakeMagic(Creature *creature, const Position& centerpos, const MagicEffectClass* me, bool isparal = false)
  4522. {
  4523.  
  4524. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureMakeMagic()");
  4525.  
  4526. #ifdef __DEBUG__
  4527. cout << "creatureMakeMagic: " << (creature ? creature->getName() : "No name") << ", x: " << centerpos.x << ", y: " << centerpos.y << ", z: " << centerpos.z << std::endl;
  4528. #endif
  4529.  
  4530. Position frompos;
  4531.  
  4532. if(creature) {
  4533. frompos = creature->pos;
  4534.  
  4535. if(!creatureOnPrepareMagicAttack(creature, centerpos, me, isparal))
  4536. {
  4537.  
  4538. return false;
  4539. }
  4540. }
  4541. else {
  4542. frompos = centerpos;
  4543. }
  4544.  
  4545. MagicAreaVec tmpMagicAreaVec;
  4546. me->getArea(centerpos, tmpMagicAreaVec);
  4547.  
  4548. std::vector<Position> poslist;
  4549.  
  4550. Position topLeft(0xFFFF, 0xFFFF, frompos.z), bottomRight(0, 0, frompos.z);
  4551.  
  4552. //Filter out the tiles we actually can work on
  4553. for(MagicAreaVec::iterator maIt = tmpMagicAreaVec.begin(); maIt != tmpMagicAreaVec.end(); ++maIt) {
  4554. Tile *t = map->getTile(maIt->x, maIt->y, maIt->z);
  4555. if(t && (!creature || (creature->access >= g_config.ACCESS_PROTECT || !me->offensive || !t->isPz()) ) ) {
  4556. if((t->isBlocking(BLOCK_PROJECTILE) == RET_NOERROR) && (me->isIndirect() ||
  4557. //(map->canThrowItemTo(frompos, (*maIt), false, true) && !t->floorChange()))) {
  4558. ((map->canThrowObjectTo(centerpos, (*maIt), BLOCK_PROJECTILE) == RET_NOERROR) && !t->floorChange()))) {
  4559.  
  4560. if(maIt->x < topLeft.x)
  4561. topLeft.x = maIt->x;
  4562.  
  4563. if(maIt->y < topLeft.y)
  4564. topLeft.y = maIt->y;
  4565.  
  4566. if(maIt->x > bottomRight.x)
  4567. bottomRight.x = maIt->x;
  4568.  
  4569. if(maIt->y > bottomRight.y)
  4570. bottomRight.y = maIt->y;
  4571.  
  4572. poslist.push_back(*maIt);
  4573. }
  4574. }
  4575. }
  4576.  
  4577. topLeft.z = frompos.z;
  4578. bottomRight.z = frompos.z;
  4579.  
  4580. if(topLeft.x == 0xFFFF || topLeft.y == 0xFFFF || bottomRight.x == 0 || bottomRight.y == 0){
  4581.  
  4582. return false;
  4583. }
  4584.  
  4585. #ifdef __DEBUG__
  4586. printf("top left %d %d %d\n", topLeft.x, topLeft.y, topLeft.z);
  4587. printf("bottom right %d %d %d\n", bottomRight.x, bottomRight.y, bottomRight.z);
  4588. #endif
  4589.  
  4590. //We do all changes against a GameState to keep track of the changes,
  4591. //need some more work to work for all situations...
  4592. GameState gamestate(this, Range(topLeft, bottomRight));
  4593.  
  4594. //Tile *targettile = getTile(centerpos.x, centerpos.y, centerpos.z);
  4595. Tile *targettile = map->getTile(centerpos);
  4596. bool bSuccess = false;
  4597. bool hasTarget = false;
  4598. bool isBlocking = true;
  4599. if(targettile){
  4600. hasTarget = !targettile->creatures.empty();
  4601. isBlocking = (targettile->isBlocking(BLOCK_SOLID, true) != RET_NOERROR);
  4602. }
  4603.  
  4604. if(targettile && me->canCast(isBlocking, !targettile->creatures.empty())) {
  4605. bSuccess = true;
  4606.  
  4607. //Apply the permanent effect to the map
  4608. std::vector<Position>::const_iterator tlIt;
  4609. for(tlIt = poslist.begin(); tlIt != poslist.end(); ++tlIt) {
  4610. gamestate.onAttack(creature, Position(*tlIt), me);
  4611. }
  4612. }
  4613. if(bSuccess) {
  4614. if(isparal == true) {
  4615. Player* player = dynamic_cast<Player*>(creature);
  4616. if(player) {
  4617. player->mana -= me->manaCost;
  4618. std::cout << "isparal, creatureMakeMagic: " << isparal << std::endl;
  4619. //player->manaspent += me->manaCost;
  4620. player->addManaSpent(me->manaCost);
  4621. }
  4622. }
  4623. }
  4624. SpectatorVec spectatorlist = gamestate.getSpectators();
  4625. SpectatorVec::iterator it;
  4626.  
  4627. for(it = spectatorlist.begin(); it != spectatorlist.end(); ++it) {
  4628. Player* spectator = dynamic_cast<Player*>(*it);
  4629.  
  4630. if(!spectator)
  4631. continue;
  4632.  
  4633. if(bSuccess) {
  4634.  
  4635. me->getDistanceShoot(spectator, creature, centerpos, hasTarget);
  4636.  
  4637. std::vector<Position>::const_iterator tlIt;
  4638. for(tlIt = poslist.begin(); tlIt != poslist.end(); ++tlIt) {
  4639. Position pos = *tlIt;
  4640. //Tile *tile = getTile(pos.x, pos.y, pos.z);
  4641. Tile *tile = map->getTile(pos);
  4642. const CreatureStateVec& creatureStateVec = gamestate.getCreatureStateList(tile);
  4643.  
  4644. if(creatureStateVec.empty()) { //no targets
  4645. me->getMagicEffect(spectator, creature, NULL, pos, 0, targettile->isPz(), isBlocking);
  4646. }
  4647. else {
  4648. for(CreatureStateVec::const_iterator csIt = creatureStateVec.begin(); csIt != creatureStateVec.end(); ++csIt) {
  4649. Creature *target = csIt->first;
  4650. const CreatureState& creatureState = csIt->second;
  4651.  
  4652. me->getMagicEffect(spectator, creature, target, target->pos, creatureState.damage, tile->isPz(), false);
  4653.  
  4654. //could be death due to a magic damage with no owner (fire/poison/energy)
  4655. if(creature && target->isRemoved == true) {
  4656.  
  4657. for(std::vector<Creature*>::const_iterator cit = creatureState.attackerlist.begin(); cit != creatureState.attackerlist.end(); ++cit) {
  4658. Creature* gainExpCreature = *cit;
  4659. if(dynamic_cast<Player*>(gainExpCreature))
  4660. dynamic_cast<Player*>(gainExpCreature)->sendStats();
  4661.  
  4662. if(spectator->CanSee(gainExpCreature->pos.x, gainExpCreature->pos.y, gainExpCreature->pos.z)){
  4663. std::stringstream exp;
  4664. exp << target->getGainedExperience(gainExpCreature);
  4665. spectator->sendAnimatedText(gainExpCreature->pos, 0xD7, exp.str());
  4666. }
  4667. }
  4668.  
  4669. }
  4670.  
  4671. if(spectator->CanSee(target->pos.x, target->pos.y, target->pos.z))
  4672. {
  4673. if(creatureState.damage != 0) {
  4674. std::stringstream dmg;
  4675. dmg << std::abs(creatureState.damage);
  4676. #ifdef TJ_MONSTER_BLOOD
  4677. if (me->attackType & ATTACK_PHYSICAL)
  4678. spectator->sendAnimatedText(target->pos, target->bloodcolor, dmg.str());
  4679. else
  4680. #endif //TJ_MONSTER_BLOOD
  4681. spectator->sendAnimatedText(target->pos, me->animationColor, dmg.str());
  4682. }
  4683.  
  4684. if(creatureState.manaDamage > 0){
  4685. spectator->sendMagicEffect(target->pos, NM_ME_LOOSE_ENERGY);
  4686. std::stringstream manaDmg;
  4687. manaDmg << std::abs(creatureState.manaDamage);
  4688. spectator->sendAnimatedText(target->pos, 2, manaDmg.str());
  4689. }
  4690.  
  4691. if (target->health > 0)
  4692. spectator->sendCreatureHealth(target);
  4693.  
  4694. if (spectator == target){
  4695. CreateManaDamageUpdate(target, creature, creatureState.manaDamage);
  4696. CreateDamageUpdate(target, creature, creatureState.damage);
  4697. }
  4698. }
  4699. }
  4700. }
  4701. }
  4702. }
  4703. else {
  4704. me->FailedToCast(spectator, creature, isBlocking, hasTarget);
  4705. }
  4706.  
  4707. }
  4708.  
  4709. return bSuccess;
  4710. }
  4711.  
  4712. void Game::creatureApplyDamage(Creature *creature, int32_t damage, int32_t &outDamage, int32_t &outManaDamage
  4713. #ifdef YUR_PVP_ARENA
  4714. , CreatureVector* arenaLosers
  4715. #endif //YUR_PVP_ARENA
  4716. )
  4717. {
  4718. outDamage = damage;
  4719. outManaDamage = 0;
  4720.  
  4721. if (damage > 0)
  4722. {
  4723. if (creature->manaShieldTicks >= 1000 && (damage < creature->mana) ) {
  4724. outManaDamage = damage;
  4725. outDamage = 0;
  4726. }
  4727. else if (creature->manaShieldTicks >= 1000 && (damage > creature->mana) ) {
  4728. outManaDamage = creature->mana;
  4729. outDamage -= outManaDamage;
  4730. }
  4731. else if((creature->manaShieldTicks < 1000) && (damage > creature->health))
  4732. outDamage = creature->health;
  4733. else if (creature->manaShieldTicks >= 1000 && (damage > (creature->health + creature->mana))) {
  4734. outDamage = creature->health;
  4735. outManaDamage = creature->mana;
  4736. }
  4737.  
  4738. if(creature->manaShieldTicks < 1000 || (creature->mana == 0))
  4739. #ifdef YUR_PVP_ARENA
  4740. creature->drainHealth(outDamage, arenaLosers);
  4741. #else
  4742. creature->drainHealth(outDamage);
  4743. #endif //YUR_PVP_ARENA
  4744. else if(outManaDamage > 0)
  4745. {
  4746. #ifdef YUR_PVP_ARENA
  4747. creature->drainHealth(outDamage, arenaLosers);
  4748. #else
  4749. creature->drainHealth(outDamage);
  4750. #endif //YUR_PVP_ARENA
  4751. creature->drainMana(outManaDamage);
  4752. }
  4753. else
  4754. creature->drainMana(outDamage);
  4755. }
  4756. else {
  4757. int32_t newhealth = creature->health - damage;
  4758. if(newhealth > creature->healthmax)
  4759. newhealth = creature->healthmax;
  4760.  
  4761. creature->health = newhealth;
  4762.  
  4763. outDamage = creature->health - newhealth;
  4764. outManaDamage = 0;
  4765. }
  4766. }
  4767.  
  4768. bool Game::creatureCastSpell(Creature *creature, const Position& centerpos, const MagicEffectClass& me)
  4769. {
  4770.  
  4771. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureCastSpell()");
  4772. std::cout << "Game::creatureCastSpell " << creature->getName() << std::endl;
  4773. // if(me.offensive == false && me.damageEffect > 0 && creature->conditions.hasCondition(ATTACK_PARALYZE))
  4774. if(/*(*/me.damageEffect <= 0 /* || me.damageEffect == NM_ME_MAGIC_ENERGIE)*/ && creature->conditions.hasCondition(ATTACK_PARALYZE))
  4775. {
  4776. creature->removeCondition(ATTACK_PARALYZE);
  4777. changeSpeed(creature->getID(), creature->getNormalSpeed()+creature->hasteSpeed);
  4778. Player *player = dynamic_cast<Player*>(creature);
  4779. if(player)
  4780. player->sendIcons();
  4781. }
  4782.  
  4783. return creatureMakeMagic(creature, centerpos, &me);
  4784. }
  4785.  
  4786.  
  4787. bool Game::creatureThrowRune(Creature *creature, const Position& centerpos, const MagicEffectClass& me, bool isparal = false) {
  4788.  
  4789.  
  4790. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureThrowRune()");
  4791. bool ret = false;
  4792. #ifdef HUCZU_FIX
  4793. int32_t dist_x = std::abs(creature->pos.x - centerpos.x);
  4794. int32_t dist_y = std::abs(creature->pos.y - centerpos.y);
  4795. #endif //HUCZU_FIX
  4796. if(creature->pos.z != centerpos.z) {
  4797. creature->sendCancel("You need to be on the same floor.");
  4798. }
  4799. #ifdef HUCZU_FIX
  4800. else if(dist_x > 7 || dist_y > 6)
  4801. return TOO_FAR;
  4802. #endif //HUCZU_FIX
  4803. //else if(!map->canThrowItemTo(creature->pos, centerpos, false, true)) {
  4804. else if(map->canThrowObjectTo(creature->pos, centerpos, BLOCK_PROJECTILE) != RET_NOERROR) {
  4805. creature->sendCancel("You cannot throw there.");
  4806. }
  4807. else
  4808. ret = creatureMakeMagic(creature, centerpos, &me, isparal);
  4809.  
  4810.  
  4811.  
  4812. return ret;
  4813. }
  4814.  
  4815. bool Game::creatureOnPrepareAttack(Creature *creature, Position pos)
  4816. {
  4817. if(creature){
  4818. Player* player = dynamic_cast<Player*>(creature);
  4819.  
  4820. //Tile* tile = (Tile*)getTile(creature->pos.x, creature->pos.y, creature->pos.z);
  4821. Tile* tile = map->getTile(creature->pos);
  4822. //Tile* targettile = getTile(pos.x, pos.y, pos.z);
  4823. Tile* targettile = map->getTile(pos);
  4824.  
  4825. if(creature->access < g_config.ACCESS_PROTECT) {
  4826. if(tile && tile->isPz()) {
  4827. if(player) {
  4828. player->sendTextMessage(MSG_SMALLINFO, "You may not attack a person while you are in a protection zone.");
  4829. playerSetAttackedCreature(player, 0);
  4830. }
  4831.  
  4832. return false;
  4833. }
  4834. else if(targettile && targettile->isPz()) {
  4835. if(player) {
  4836. player->sendTextMessage(MSG_SMALLINFO, "You may not attack a person in a protection zone.");
  4837. playerSetAttackedCreature(player, 0);
  4838. }
  4839.  
  4840. return false;
  4841. }
  4842. }
  4843.  
  4844. return true;
  4845. }
  4846.  
  4847. return false;
  4848. }
  4849.  
  4850. bool Game::creatureOnPrepareMagicAttack(Creature *creature, Position pos, const MagicEffectClass* me, bool isparal = false)
  4851. {
  4852. if(!me->offensive || me->isIndirect() || creatureOnPrepareAttack(creature, pos)) {
  4853. /*
  4854. if(creature->access < ACCESS_PROTECT) {
  4855. if(!((std::abs(creature->pos.x-centerpos.x) <= 8) && (std::abs(creature->pos.y-centerpos.y) <= 6) &&
  4856. (creature->pos.z == centerpos.z)))
  4857. return false;
  4858. }
  4859. */
  4860.  
  4861. Player* player = dynamic_cast<Player*>(creature);
  4862. if(player) {
  4863. if(player->access < g_config.ACCESS_PROTECT) {
  4864. if(player->exhaustedTicks >= 1000 && me->causeExhaustion(true)) {
  4865. if(me->offensive) {
  4866. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.",player->pos, NM_ME_PUFF);
  4867. player->exhaustedTicks += g_config.EXHAUSTED_ADD;
  4868. }
  4869.  
  4870. return false;
  4871. }
  4872. else if(player->mana < me->manaCost) {
  4873. player->sendTextMessage(MSG_SMALLINFO, "You do not have enough mana.",player->pos, NM_ME_PUFF);
  4874. return false;
  4875. }
  4876. else {
  4877. if(isparal != true) {
  4878. player->mana -= me->manaCost;
  4879. //player->manaspent += me->manaCost;
  4880. std::cout << "isparal, creatureOnPrepareMagicAttack: " << isparal << std::endl;
  4881. player->addManaSpent(me->manaCost);
  4882. }
  4883. }
  4884. }
  4885. }
  4886.  
  4887. return true;
  4888. }
  4889.  
  4890. return false;
  4891. }
  4892.  
  4893. void Game::creatureMakeDamage(Creature *creature, Creature *attackedCreature, fight_t damagetype)
  4894. {
  4895. if(!creatureOnPrepareAttack(creature, attackedCreature->pos))
  4896. return;
  4897.  
  4898.  
  4899. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureMakeDamage()");
  4900.  
  4901. Player* player = dynamic_cast<Player*>(creature);
  4902. Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  4903. //Attack limiter
  4904. if(player) {
  4905. if (player->lastAttack == 0) {
  4906. player->lastAttack = OTSYS_TIME() - 1000 - 1;
  4907. }
  4908. if ((OTSYS_TIME() - player->lastAttack) < 1000) {
  4909. return;
  4910. }
  4911. }
  4912. #ifdef ANTI_MISS
  4913. if(player && player->atkMode == 1 && player->access <= g_config.ACCESS_PROTECT && attackedPlayer && attackedPlayer->skullType == 0) {
  4914. player->sendCancelAttacking();
  4915. player->sendTextMessage(MSG_SMALLINFO, "Turn secure mode off if you really want to attack unmarked players.");
  4916. return;
  4917. }
  4918. #endif //ANTI_MISS
  4919.  
  4920. //Tile* targettile = getTile(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z);
  4921. Tile* targettile = map->getTile(attackedCreature->pos);
  4922.  
  4923. //can the attacker reach the attacked?
  4924. bool inReach = false;
  4925.  
  4926. switch(damagetype){
  4927. case FIGHT_MELEE:
  4928. if((std::abs(creature->pos.x-attackedCreature->pos.x) <= 1) &&
  4929. (std::abs(creature->pos.y-attackedCreature->pos.y) <= 1) &&
  4930. (creature->pos.z == attackedCreature->pos.z))
  4931. inReach = true;
  4932. break;
  4933. case FIGHT_DIST:
  4934. if((std::abs(creature->pos.x-attackedCreature->pos.x) <= 8) &&
  4935. (std::abs(creature->pos.y-attackedCreature->pos.y) <= 5) &&
  4936. (creature->pos.z == attackedCreature->pos.z)) {
  4937.  
  4938. //if(map->canThrowItemTo(creature->pos, attackedCreature->pos, false, true))
  4939. if(map->canThrowObjectTo(creature->pos, attackedCreature->pos, BLOCK_PROJECTILE) == RET_NOERROR)
  4940. inReach = true;
  4941. }
  4942. break;
  4943. case FIGHT_MAGICDIST:
  4944. if((std::abs(creature->pos.x-attackedCreature->pos.x) <= 8) &&
  4945. (std::abs(creature->pos.y-attackedCreature->pos.y) <= 5) &&
  4946. (creature->pos.z == attackedCreature->pos.z)) {
  4947.  
  4948. //if(map->canThrowItemTo(creature->pos, attackedCreature->pos, false, true))
  4949. if(map->canThrowObjectTo(creature->pos, attackedCreature->pos, BLOCK_PROJECTILE) == RET_NOERROR)
  4950. inReach = true;
  4951. }
  4952. break;
  4953.  
  4954. }
  4955.  
  4956. if (player && player->access < g_config.ACCESS_PROTECT)
  4957. {
  4958. #ifdef YUR_CVS_MODS
  4959. player->inFightTicks = std::max(g_config.PZ_LOCKED, player->inFightTicks);
  4960. #else
  4961. player->inFightTicks = g_config.PZ_LOCKED;
  4962. #endif //YUR_CVS_MODS
  4963.  
  4964. player->sendIcons();
  4965. if(attackedPlayer)
  4966. player->pzLocked = true;
  4967. }
  4968.  
  4969. if(attackedPlayer && attackedPlayer->access < g_config.ACCESS_PROTECT)
  4970. {
  4971. #ifdef YUR_CVS_MODS
  4972. attackedPlayer->inFightTicks = std::max(g_config.PZ_LOCKED, attackedPlayer->inFightTicks);
  4973. #else
  4974. attackedPlayer->inFightTicks = g_config.PZ_LOCKED;
  4975. #endif //YUR_CVS_MODS
  4976. attackedPlayer->sendIcons();
  4977. }
  4978.  
  4979. if(!inReach){
  4980. return;
  4981. }
  4982.  
  4983. //We do all changes against a GameState to keep track of the changes,
  4984. //need some more work to work for all situations...
  4985. GameState gamestate(this, Range(creature->pos, attackedCreature->pos));
  4986.  
  4987. gamestate.onAttack(creature, attackedCreature->pos, attackedCreature);
  4988.  
  4989. const CreatureStateVec& creatureStateVec = gamestate.getCreatureStateList(targettile);
  4990. const CreatureState& creatureState = creatureStateVec[0].second;
  4991.  
  4992. if(player && (creatureState.damage > 0 || creatureState.manaDamage > 0)) {
  4993. #ifdef WANDS_JIDDO
  4994. if(player && ((player->items[SLOT_RIGHT] && (!player->items[SLOT_RIGHT]->getWand())) || (!player->items[SLOT_RIGHT] && !player->items[SLOT_LEFT]) || (player->items[SLOT_LEFT] && (!player->items[SLOT_LEFT]->getWand()))))
  4995. player->addSkillTry(2);
  4996. #else
  4997. player->addSkillTry(2);
  4998. #endif
  4999. }
  5000. else if(player){
  5001. #ifdef WANDS_JIDDO
  5002. if(player && ((player->items[SLOT_RIGHT] && (!player->items[SLOT_RIGHT]->getWand())) || (!player->items[SLOT_RIGHT] && !player->items[SLOT_LEFT]) || (player->items[SLOT_LEFT] && (!player->items[SLOT_LEFT]->getWand()))))
  5003. player->addSkillTry(1);
  5004. #else
  5005. player->addSkillTry(1);
  5006. #endif
  5007. }
  5008. if(attackedPlayer){
  5009. NetworkMessage msg;
  5010. msg.AddByte(0x86);
  5011. msg.AddU32(creature->getID());
  5012. msg.AddByte(0x00);
  5013. attackedPlayer->sendNetworkMessage(&msg);
  5014. }
  5015.  
  5016. SpectatorVec spectatorlist = gamestate.getSpectators();
  5017. SpectatorVec::iterator it;
  5018.  
  5019. for(it = spectatorlist.begin(); it != spectatorlist.end(); ++it) {
  5020. Player* spectator = dynamic_cast<Player*>(*it);
  5021. if(!spectator)
  5022. continue;
  5023.  
  5024. if(damagetype != FIGHT_MELEE){
  5025. spectator->sendDistanceShoot(creature->pos, attackedCreature->pos, creature->getSubFightType());
  5026. }
  5027.  
  5028. if (attackedCreature->manaShieldTicks < 1000 && (creatureState.damage == 0) &&
  5029. (spectator->CanSee(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z))) {
  5030. spectator->sendMagicEffect(attackedCreature->pos, NM_ME_PUFF);
  5031. }
  5032. else if (attackedCreature->manaShieldTicks < 1000 && (creatureState.damage < 0) &&
  5033. (spectator->CanSee(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z))) {
  5034. spectator->sendMagicEffect(attackedCreature->pos, NM_ME_BLOCKHIT);
  5035. }
  5036. else {
  5037. for(std::vector<Creature*>::const_iterator cit = creatureState.attackerlist.begin(); cit != creatureState.attackerlist.end(); ++cit) {
  5038. Creature* gainexpCreature = *cit;
  5039. if(dynamic_cast<Player*>(gainexpCreature))
  5040. dynamic_cast<Player*>(gainexpCreature)->sendStats();
  5041.  
  5042. if(spectator->CanSee(gainexpCreature->pos.x, gainexpCreature->pos.y, gainexpCreature->pos.z)) {
  5043. char exp[128];
  5044. #ifdef YUR_HIGH_LEVELS // TODO: format like this: 1,000,000
  5045. sprintf(exp,"%lld",attackedCreature->getGainedExperience(gainexpCreature));
  5046. spectator->sendAnimatedText(gainexpCreature->pos, 0xD7, exp);
  5047. #else
  5048. itoa(attackedCreature->getGainedExperience(gainexpCreature), exp, 10);
  5049. #endif //YUR_HIGH_LEVLES
  5050. spectator->sendAnimatedText(gainexpCreature->pos, 0xD7, exp);
  5051. }
  5052. }
  5053.  
  5054. if (spectator->CanSee(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z))
  5055. {
  5056. if(creatureState.damage > 0) {
  5057. std::stringstream dmg;
  5058. dmg << std::abs(creatureState.damage);
  5059. #ifdef TJ_MONSTER_BLOOD
  5060. spectator->sendAnimatedText(attackedCreature->pos, attackedCreature->bloodcolor, dmg.str());
  5061. spectator->sendMagicEffect(attackedCreature->pos, attackedCreature->bloodeffect);
  5062. #else
  5063. spectator->sendAnimatedText(attackedCreature->pos, 0xB4, dmg.str());
  5064. spectator->sendMagicEffect(attackedCreature->pos, NM_ME_DRAW_BLOOD);
  5065. #endif //TJ_MONSTER_BLOOD
  5066. }
  5067.  
  5068. if(creatureState.manaDamage >0) {
  5069. std::stringstream manaDmg;
  5070. manaDmg << std::abs(creatureState.manaDamage);
  5071. spectator->sendMagicEffect(attackedCreature->pos, NM_ME_LOOSE_ENERGY);
  5072. spectator->sendAnimatedText(attackedCreature->pos, 2, manaDmg.str());
  5073. }
  5074.  
  5075. if (attackedCreature->health > 0)
  5076. spectator->sendCreatureHealth(attackedCreature);
  5077.  
  5078. if (spectator == attackedCreature) {
  5079. CreateManaDamageUpdate(attackedCreature, creature, creatureState.manaDamage);
  5080. CreateDamageUpdate(attackedCreature, creature, creatureState.damage);
  5081. }
  5082. if(player)
  5083. player->lastAttack = OTSYS_TIME();
  5084. }
  5085. }
  5086. }
  5087.  
  5088. if(damagetype != FIGHT_MELEE && player) {
  5089. player->removeDistItem();
  5090. }
  5091.  
  5092.  
  5093. }
  5094.  
  5095. std::list<Position> Game::getPathTo(Creature *creature, Position start, Position to, bool creaturesBlock){
  5096. return map->getPathTo(creature, start, to, creaturesBlock);
  5097. }
  5098.  
  5099. std::list<Position> Game::getPathToEx(Creature *creature, Position start, Position to, bool creaturesBlock){
  5100. return map->getPathToEx(creature, start, to, creaturesBlock);
  5101. }
  5102.  
  5103.  
  5104. void Game::checkPlayerWalk(uint32_t id)
  5105. {
  5106. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkPlayerWalk");
  5107.  
  5108. Player *player = getPlayerByID(id);
  5109.  
  5110. if(!player)
  5111. return;
  5112. if(player->pathlist.empty()){
  5113. stopEvent(player->eventAutoWalk);
  5114. player->eventAutoWalk = 0;
  5115. return;
  5116. }
  5117.  
  5118. Position pos = player->pos;
  5119. Direction dir = player->pathlist.front();
  5120. player->pathlist.pop_front();
  5121.  
  5122. switch (dir) {
  5123. case NORTH:
  5124. pos.y--;
  5125. break;
  5126. case EAST:
  5127. pos.x++;
  5128. break;
  5129. case SOUTH:
  5130. pos.y++;
  5131. break;
  5132. case WEST:
  5133. pos.x--;
  5134. break;
  5135. case NORTHEAST:
  5136. pos.x++;
  5137. pos.y--;
  5138. break;
  5139. case NORTHWEST:
  5140. pos.x--;
  5141. pos.y--;
  5142. break;
  5143. case SOUTHWEST:
  5144. pos.x--;
  5145. pos.y++;
  5146. break;
  5147. case SOUTHEAST:
  5148. pos.x++;
  5149. pos.y++;
  5150. break;
  5151. }
  5152.  
  5153. /*
  5154. #ifdef __DEBUG__
  5155. std::cout << "move to: " << dir << std::endl;
  5156. #endif
  5157. */
  5158.  
  5159. player->lastmove = OTSYS_TIME();
  5160. thingMove(player, player, pos.x, pos.y, pos.z, 1);
  5161. flushSendBuffers();
  5162. if(!player->pathlist.empty()){
  5163. int ticks = (int)player->getSleepTicks();
  5164. player->eventAutoWalk = addEvent(makeTask(ticks, std::bind2nd(std::mem_fun(&Game::checkPlayerWalk), id)));
  5165. }
  5166. else
  5167. {
  5168. stopEvent(player->eventAutoWalk);//?
  5169. player->eventAutoWalk = 0;
  5170. }
  5171. }
  5172. void Game::checkCreature(uint32_t id)
  5173. {
  5174. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreature()");
  5175.  
  5176. Creature *creature = getCreatureByID(id);
  5177.  
  5178. if (creature && creature->isRemoved == false)
  5179. {
  5180. int32_t thinkTicks = 0;
  5181. int32_t oldThinkTicks = creature->onThink(thinkTicks);
  5182.  
  5183. if(thinkTicks > 0) {
  5184. creature->eventCheck = addEvent(makeTask(thinkTicks, std::bind2nd(std::mem_fun(&Game::checkCreature), id)));
  5185. }
  5186. else
  5187. creature->eventCheck = 0;
  5188.  
  5189. Player* player = dynamic_cast<Player*>(creature);
  5190. if(player)
  5191. {
  5192. //Tile *tile = getTile(player->pos.x, player->pos.y, player->pos.z);
  5193. Tile *tile = map->getTile(player->pos);
  5194. if(tile == NULL){
  5195. std::cout << "CheckPlayer NULL tile: " << player->getName() << std::endl;
  5196. return;
  5197. }
  5198.  
  5199.  
  5200.  
  5201. #ifdef _REX_CVS_MOD_
  5202. if(player->tradeTicks >= 1000)
  5203. player->tradeTicks -= thinkTicks;
  5204. #endif
  5205.  
  5206.  
  5207. #ifdef CVS_DAY_CYCLE
  5208. player->sendWorldLightLevel(lightlevel, 0xD7);
  5209. #endif //CVS_DAY_CYCLE
  5210. #ifdef REX_MUTED
  5211.  
  5212. #endif //REX_MUTED
  5213. #ifdef TR_ANTI_AFK
  5214. player->checkAfk(thinkTicks);
  5215. #endif //TR_ANTI_AF
  5216. #ifdef YUR_BOH
  5217. player->checkBoh();
  5218. #endif //YUR_BOH
  5219. #ifdef YUR_WH
  5220. player->checkWh();
  5221. #endif //YUR_WH
  5222.  
  5223. #ifdef YUR_RINGS_AMULETS
  5224. player->checkRing(thinkTicks);
  5225. #endif //YUR_RINGS_AMULETS
  5226.  
  5227. //SOFT BOOTS
  5228. if(player->softTicks >= 2) {
  5229. if(player->items[SLOT_FEET] && player->items[SLOT_FEET]->getID() == ITEM_SOFT_BOOTS && !tile->isPz()){
  5230. player->mana += min(g_config.SOFT_MANA, player->manamax - player->mana);
  5231. player->health += min(g_config.SOFT_HEALTH, player->healthmax - player->health);
  5232. }
  5233. player->softTicks = 0;
  5234. } else {
  5235. player->softTicks++;
  5236. }
  5237. // LIFE RING
  5238. if(player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_LIFE_RING_IN_USE && !tile->isPz()){
  5239. player->mana += min(g_config.LR_MANA, player->manamax - player->mana);
  5240. player->health += min(g_config.LR_HEALTH, player->healthmax - player->health);
  5241. }
  5242. // ROH
  5243. if(player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_RING_OF_HEALING_IN_USE && !tile->isPz()){
  5244. player->mana += min(g_config.ROH_MANA, player->manamax - player->mana);
  5245. player->health += min(g_config.ROH_HEALTH, player->healthmax - player->health);
  5246. }
  5247. // ROAH
  5248. // ROH 240
  5249. if(player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_STEALTH_RING_IN_USE && !tile->isPz()){
  5250. player->mana += min(g_config.ROAH_MANA, player->manamax - player->mana);
  5251. player->health += min(g_config.ROAH_HEALTH, player->healthmax - player->health);
  5252. }
  5253. // RAINBOW SHIELD
  5254. if(player->level >= 150){
  5255. if(player->items[SLOT_RIGHT] && player->items[SLOT_RIGHT]->getID() == ITEM_RAINBOW && !tile->isPz()){
  5256. if(player->items[SLOT_LEFT]){
  5257. if(player->items[SLOT_LEFT]->getID() != ITEM_RAINBOW)
  5258. if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5259. player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5260. player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5261. player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5262. }
  5263. }else{
  5264. if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5265. player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5266. player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5267. player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5268. }
  5269. }
  5270. }
  5271. if(player->items[SLOT_LEFT] && player->items[SLOT_LEFT]->getID() == ITEM_RAINBOW && !tile->isPz()){
  5272. if(player->items[SLOT_RIGHT]){
  5273. if(player->items[SLOT_RIGHT]->getID() != ITEM_RAINBOW)
  5274. if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5275. player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5276. player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5277. player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5278. }
  5279. }else{
  5280. if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5281. player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5282. player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5283. player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5284. }
  5285. }
  5286. }
  5287. }
  5288.  
  5289. // RING OF THE SKY
  5290. if(player->level >= 30 && player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_ROTS && !tile->isPz())
  5291. player->mana += min(1, player->manamax - player->mana);
  5292.  
  5293. // ORSHABAAL HEART
  5294. if(player->name == "Ekudron" || player->name == "Agecik" && player->items[SLOT_AMMO] && player->items[SLOT_AMMO]->getID() == ITEM_ORSHABAAL_HEARTH && !tile->isPz())
  5295. player->mana += min(4, player->manamax - player->mana);
  5296.  
  5297. #ifdef HUCZU_FIX
  5298. if(player->items[SLOT_FEET] && player->items[SLOT_FEET]->getID() == ITEM_SPECTRE_BOOTS)
  5299. player->immunities = ATTACK_PARALYZE;
  5300. else
  5301. player->immunities -= ATTACK_PARALYZE;
  5302. #endif //HUCZU_FIX
  5303.  
  5304. #ifdef YUR_LIGHT_ITEM
  5305. player->checkLightItem(thinkTicks);
  5306. #endif //YUR_LIGHT_ITEM
  5307. #ifdef HUCZU_EXHAUSTED
  5308. if(player->mmo > 0)
  5309. player->mmo -= 1;
  5310. else
  5311. player->mmo = 0;
  5312.  
  5313. if(player->lookex > 0)
  5314. player->lookex -= 1;
  5315. else
  5316. player->lookex = 0;
  5317.  
  5318. if(player->antyrainbow > 0)
  5319. player->antyrainbow -= 1;
  5320. else
  5321. player->antyrainbow = 0;
  5322.  
  5323. if(player->antyrainbow2 > 0)
  5324. player->antyrainbow2 -= 1;
  5325. else
  5326. player->antyrainbow2 = 0;
  5327.  
  5328. if(player->clin > 0)
  5329. player->clin -= 1;
  5330. else
  5331. player->clin = 0;
  5332.  
  5333. if(player->shut_d > 0)
  5334. player->shut_d -= 1;
  5335. else
  5336. player->shut_d = 0;
  5337.  
  5338. if(player->houseTicks > 0)
  5339. player->houseTicks -= 1;
  5340. else
  5341. player->houseTicks = 0;
  5342. #endif //HUCZU_EXHAUSTED
  5343.  
  5344. if(player->flamTicks >= 1000){
  5345. player->flamTicks -= thinkTicks;
  5346. if(player->flamTicks == 0){
  5347. player->flamBool = false;
  5348. }
  5349. }
  5350.  
  5351.  
  5352. if(player->items[SLOT_RIGHT] && player->items[SLOT_LEFT]){
  5353. if((player->items[SLOT_RIGHT]->getID() == ITEM_BOW || player->items[SLOT_RIGHT]->getID() == ITEM_XBOW) && (player->items[SLOT_LEFT]->getWeaponType() == SHIELD || player->items[SLOT_LEFT]->getWeaponType() == SWORD || player->items[SLOT_LEFT]->getWeaponType() == AXE || player->items[SLOT_LEFT]->getWeaponType() == CLUB)){
  5354. player->removeItemInventory(SLOT_RIGHT);
  5355. }
  5356. if((player->items[SLOT_LEFT]->getID() == ITEM_BOW || player->items[SLOT_LEFT]->getID() == ITEM_XBOW) && (player->items[SLOT_RIGHT]->getWeaponType() == SHIELD || player->items[SLOT_RIGHT]->getWeaponType() == SWORD || player->items[SLOT_RIGHT]->getWeaponType() == AXE || player->items[SLOT_RIGHT]->getWeaponType() == CLUB)){
  5357. player->removeItemInventory(SLOT_LEFT);
  5358. }
  5359. }
  5360.  
  5361. if(player->items[SLOT_RIGHT] && player->items[SLOT_LEFT]){
  5362. if((player->items[SLOT_RIGHT]->getID() == ITEM_SPEAR || player->items[SLOT_RIGHT]->getID() == ITEM_KNIFE || player->items[SLOT_RIGHT]->getID() == ITEM_STONE || player->items[SLOT_RIGHT]->getID() == ITEM_SNOWBALL || player->items[SLOT_RIGHT]->getID() == ITEM_STAR) && (player->items[SLOT_LEFT]->getWeaponType() == SWORD || player->items[SLOT_LEFT]->getWeaponType() == AXE || player->items[SLOT_LEFT]->getWeaponType() == CLUB)){
  5363. player->removeItemInventory(SLOT_RIGHT);
  5364. }
  5365. if((player->items[SLOT_LEFT]->getID() == ITEM_SPEAR || player->items[SLOT_LEFT]->getID() == ITEM_KNIFE || player->items[SLOT_LEFT]->getID() == ITEM_STONE || player->items[SLOT_LEFT]->getID() == ITEM_SNOWBALL || player->items[SLOT_LEFT]->getID() == ITEM_STAR) && (player->items[SLOT_RIGHT]->getWeaponType() == SWORD || player->items[SLOT_RIGHT]->getWeaponType() == AXE || player->items[SLOT_RIGHT]->getWeaponType() == CLUB)){
  5366. player->removeItemInventory(SLOT_LEFT);
  5367. }
  5368. }
  5369.  
  5370. #ifdef HUCZU_SKULLS
  5371. if (player->checkSkull(thinkTicks))
  5372. Skull(player);
  5373. #endif //HUCZU_SKULLS
  5374.  
  5375. #ifdef YUR_INVISIBLE
  5376. if (player->checkInvisible(thinkTicks))
  5377. creatureChangeOutfit(player);
  5378. #endif //YUR_INVISIBLE
  5379.  
  5380. #ifdef _BBK_PUSH_DELAY
  5381. if(player->pushDelay >= 1000)
  5382. {
  5383. player->pushDelay -= thinkTicks;
  5384. if(player->pushDelay < 0)
  5385. player->pushDelay = 0;
  5386. }
  5387. #endif //_BBK_PUSH_DELAY
  5388.  
  5389. if(player->training == true){
  5390. if(player->trainingTicks >= 1000){
  5391. player->trainingTicks -= thinkTicks;
  5392.  
  5393. if(player->trainingTicks < 0)
  5394. player->trainingTicks = 0;
  5395. }
  5396. if(player->trainingTicks == 0 && player->rewriteTicks == 0){
  5397. int code = random_range(47,99) * random_range(47,99);
  5398. player->rewriteCode = code;
  5399. player->needrewrite = true;
  5400. player->rewriteTicks = g_config.REWRITE_TICKS;
  5401. std::ostringstream info;
  5402. player->sendTextMessage(MSG_BLUE_TEXT,"You are training here pretty long.Are you using bot?");
  5403. info << "Please rewrite code: " << player->rewriteCode << std::ends;
  5404. player->sendTextMessage(MSG_BLUE_TEXT, info.str().c_str());
  5405. std::ostringstream info2;
  5406. info2 << "Use this command !train 1234. You have " << player->rewriteTicks/1000 << " seconds!" << std::ends;
  5407. player->sendTextMessage(MSG_BLUE_TEXT, info2.str().c_str());
  5408. }
  5409.  
  5410. if(player->needrewrite != false){
  5411. if(player->rewriteTicks >= 1000){
  5412. player->rewriteTicks -= thinkTicks;
  5413. }
  5414.  
  5415. if(player->rewriteTicks == 0){
  5416. this->teleport(player, player->masterPos);
  5417. player->training = false;
  5418. player->trainingTicks = 0;
  5419. player->needrewrite = false;
  5420. player->rewriteCode = 0;
  5421. player->rewriteTicks = 0;
  5422. player->kickPlayer();
  5423. //player->sendLogout();
  5424. }
  5425. }
  5426. }
  5427.  
  5428.  
  5429.  
  5430. #ifdef HUCZU_FIX
  5431. if(player->gainHealthTick()){
  5432. SpectatorVec list;
  5433. SpectatorVec::iterator it;
  5434. getSpectators(Range(creature->pos), list);
  5435. for(it = list.begin(); it != list.end(); ++it) {
  5436. Player* p = dynamic_cast<Player*>(*it);
  5437. if(p)
  5438. p->sendCreatureHealth(player);
  5439. }
  5440. }
  5441. #endif //HUCZU_FIX
  5442.  
  5443. if(player->lightTicks >= 1000){
  5444. player->lightTicks -= thinkTicks;
  5445. if(player->lightTicks <= 1000){
  5446. player->lightTicks = 1;
  5447. }
  5448. }
  5449. else if(player->lightTicks == 1){
  5450. if(player->lightlevel > 0){
  5451. creatureChangeLight(player, 0, player->lightlevel-1, 0xD7);
  5452. }
  5453. else{
  5454. creatureChangeLight(player, 0, 0, 0xD7);
  5455. player->lightTicks = 0;
  5456. player->lightItem = 0;
  5457. }
  5458. if(player->lightTries > 0){
  5459. player->lightTicks = 3*60*1000;
  5460. player->lightTries -= 1;
  5461. }
  5462. }
  5463.  
  5464. #ifdef HUCZU_SKULLS
  5465. checkSkullTime(player);
  5466. #endif //HUCZU_SKULLS
  5467.  
  5468.  
  5469. if(!tile->isPz()){
  5470. if(player->food > 1000){
  5471. player->gainManaTick();
  5472. player->food -= thinkTicks;
  5473. if(player->healthmax - player->health > 0){
  5474. if(player->gainHealthTick()){
  5475. SpectatorVec list;
  5476. SpectatorVec::iterator it;
  5477. getSpectators(Range(creature->pos), list);
  5478. for(it = list.begin(); it != list.end(); ++it) {
  5479. Player* p = dynamic_cast<Player*>(*it);
  5480. if(p)
  5481. p->sendCreatureHealth(player);
  5482. }
  5483. }
  5484. }
  5485. }
  5486. }
  5487.  
  5488. //send stast only if have changed
  5489. if(player->NeedUpdateStats()){
  5490. player->sendStats();
  5491. }
  5492.  
  5493. player->sendPing(thinkTicks);
  5494.  
  5495. if(player->inFightTicks >= 1000) {
  5496. player->inFightTicks -= thinkTicks;
  5497.  
  5498. if(player->inFightTicks < 1000)
  5499. player->pzLocked = false;
  5500. player->sendIcons();
  5501. }
  5502.  
  5503. if(player->drunkTicks >= 1000) {
  5504. int32_t random = random_range(1,100);
  5505. if(random <= 25){
  5506. creatureSay(creature, SPEAK_SAY, "Hicks!");
  5507. Position pos;
  5508. int32_t randomwalk = random_range(1,4);
  5509. switch(randomwalk){
  5510. case 1:pos.x++;break;
  5511. case 2:pos.x--;break;
  5512. case 3:pos.y++;break;
  5513. case 4:pos.y--;break;
  5514. }
  5515. Tile* toTile = getTile(pos.x, pos.y, pos.z);
  5516. //make sure they don't get teleported into a place they shouldn't
  5517. if(toTile &&
  5518. !toTile->isBlocking(1, false, false) &&
  5519. !toTile->isBlocking(2, false, false) &&
  5520. !toTile->isBlocking(4, false, false) &&
  5521. !toTile->isBlocking(8, false, false) &&
  5522. !toTile->isBlocking(16, false, false))
  5523. teleport(player,pos);
  5524. }
  5525. player->drunkTicks -= thinkTicks;
  5526. player->sendIcons();
  5527. }
  5528.  
  5529. if(player->exhaustedTicks >= 1000){
  5530. player->exhaustedTicks -= thinkTicks;
  5531.  
  5532. if(player->exhaustedTicks < 0)
  5533. player->exhaustedTicks = 0;
  5534. }
  5535.  
  5536. if(player->manaShieldTicks >=1000){
  5537. player->manaShieldTicks -= thinkTicks;
  5538.  
  5539. if(player->manaShieldTicks < 1000)
  5540. player->sendIcons();
  5541. }
  5542. if(player->dwarvenTicks > 0){
  5543. player->drunkTicks = 0;
  5544. player->sendIcons();
  5545. }
  5546. if(player->dwarvenTicks = 0){
  5547. player->drunkTicks = 4000;
  5548. player->sendIcons();
  5549. }
  5550.  
  5551. if(player->hasteTicks >=1000)
  5552. player->hasteTicks -= thinkTicks;
  5553. }else{
  5554.  
  5555. if(creature->manaShieldTicks >=1000){
  5556. creature->manaShieldTicks -= thinkTicks;
  5557. }
  5558.  
  5559. if(creature->hasteTicks >=1000){
  5560. creature->hasteTicks -= thinkTicks;
  5561. }
  5562.  
  5563. #ifdef YUR_INVISIBLE
  5564. if (creature->checkInvisible(thinkTicks))
  5565. creatureChangeOutfit(creature);
  5566. #endif //YUR_INVISIBLE
  5567. }
  5568.  
  5569. Conditions& conditions = creature->getConditions();
  5570. for(Conditions::iterator condIt = conditions.begin(); condIt != conditions.end(); ++condIt) {
  5571. if(condIt->first == ATTACK_FIRE || condIt->first == ATTACK_ENERGY || condIt->first == ATTACK_POISON) {
  5572. ConditionVec &condVec = condIt->second;
  5573.  
  5574. if(condVec.empty())
  5575. continue;
  5576.  
  5577. CreatureCondition& condition = condVec[0];
  5578.  
  5579. if(condition.onTick(oldThinkTicks)) {
  5580. const MagicEffectTargetCreatureCondition* magicTargetCondition = condition.getCondition();
  5581. Creature* c = getCreatureByID(magicTargetCondition->getOwnerID());
  5582. creatureMakeMagic(c, creature->pos, magicTargetCondition);
  5583.  
  5584. if(condition.getCount() <= 0) {
  5585. condVec.erase(condVec.begin());
  5586. if(dynamic_cast<Player*>(creature))
  5587. player->sendIcons();
  5588. }
  5589. }
  5590. }
  5591. if(condIt->first == ATTACK_PARALYZE)
  5592. {
  5593. ConditionVec &condVec = condIt->second;
  5594. if(condVec.empty())
  5595. continue;
  5596.  
  5597. CreatureCondition& condition = condVec[0];
  5598. if(condition.onTick(oldThinkTicks))
  5599. {
  5600. //Player* player = dynamic_cast<Player*>(creature);
  5601. if(creature->getImmunities() != ATTACK_PARALYZE)
  5602. {
  5603. changeSpeed(creature->getID(), 100);
  5604. if(player)
  5605. {
  5606. player->sendTextMessage(MSG_SMALLINFO, "You are paralyzed.");
  5607. player->sendIcons();
  5608. }
  5609. }
  5610.  
  5611. if(condition.getCount() <= 0)
  5612. {
  5613. condVec.erase(condVec.begin());
  5614. changeSpeed(creature->getID(), creature->getNormalSpeed()+creature->hasteSpeed);
  5615. if(player)
  5616. {
  5617. player->sendIcons();
  5618. }
  5619. }
  5620. }
  5621. }
  5622. }
  5623. flushSendBuffers();
  5624. }
  5625. }
  5626.  
  5627. void Game::changeOutfit(uint32_t id, int32_t looktype){
  5628.  
  5629. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::changeOutfit()");
  5630.  
  5631. Creature *creature = getCreatureByID(id);
  5632. if(creature){
  5633. creature->looktype = looktype;
  5634. if(creature->lookfeet_master != 0 || creature->lookhead_master != 0 ||
  5635. creature->looklegs_master != 0 || creature->lookbody_master != 0 ){
  5636. creature->lookhead = creature->lookhead_master;
  5637. creature->lookbody = creature->lookbody_master;
  5638. creature->looklegs = creature->looklegs_master;
  5639. creature->lookfeet = creature->lookfeet_master;
  5640.  
  5641. creature->lookhead_master = 0;
  5642. creature->lookbody_master = 0;
  5643. creature->looklegs_master = 0;
  5644. creature->lookfeet_master = 0;
  5645. }
  5646. creatureChangeOutfit(creature);
  5647. }
  5648. }
  5649.  
  5650. void Game::changeOutfitAfter(uint32_t id, int32_t looktype, long time)
  5651. {
  5652. addEvent(makeTask(time, boost::bind(&Game::changeOutfit, this,id, looktype)));
  5653. }
  5654.  
  5655. void Game::changeSpeed(uint32_t id, unsigned short speed)
  5656. {
  5657. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::changeSpeed()");
  5658. Creature *creature = getCreatureByID(id);
  5659. if(creature && /*creature->hasteTicks < 1000 && */creature->speed != speed)
  5660. {
  5661. creature->speed = speed;
  5662. Player* player = dynamic_cast<Player*>(creature);
  5663. if(player){
  5664. player->sendChangeSpeed(creature);
  5665. player->sendIcons();
  5666. }
  5667. SpectatorVec list;
  5668. SpectatorVec::iterator it;
  5669. getSpectators(Range(creature->pos), list);
  5670. //for(uint32_t i = 0; i < list.size(); i++)
  5671. for(it = list.begin(); it != list.end(); ++it) {
  5672. Player* p = dynamic_cast<Player*>(*it);
  5673. if(p)
  5674. p->sendChangeSpeed(creature);
  5675. }
  5676. }
  5677. }
  5678.  
  5679. void Game::checkCreatureAttacking(uint32_t id)
  5680. {
  5681. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreatureAttacking()");
  5682.  
  5683. Creature *creature = getCreatureByID(id);
  5684. if (creature != NULL && creature->isRemoved == false)
  5685. {
  5686.  
  5687. creature->eventCheckAttacking = 0;
  5688. Player *player = dynamic_cast<Player*>(creature);
  5689. Monster *monster = dynamic_cast<Monster*>(creature);
  5690. if (monster) {
  5691. monster->onAttack();
  5692. }
  5693. else {
  5694. if (creature->attackedCreature != 0)
  5695. {
  5696. Creature *attackedCreature = getCreatureByID(creature->attackedCreature);
  5697. if (attackedCreature)
  5698. {
  5699. // canAttack system BRY
  5700.  
  5701. Player *attacker = dynamic_cast<Player*>(creature);
  5702. Player *attacked = dynamic_cast<Player*>(attackedCreature);
  5703. bool canAttack = false;
  5704. if(attacker && attacked)
  5705. {
  5706. Tile* tile = getTile(attacker->pos.x,attacker->pos.y, attacker->pos.z);
  5707. if(attacked->level >= 1 && attacked->level < 30 && attacker->level >= 1 && attacker->level < 30)
  5708. canAttack = false;
  5709.  
  5710. else if(attacked->level >= 30 && attacked->level < 80 && attacker->level >= 30 && attacker->level < 80)
  5711. canAttack = true;
  5712.  
  5713. else if(attacked->level >= 80 && attacked->level < 999 && attacker->level >= 80 && attacker->level < 999)
  5714. canAttack = true;
  5715.  
  5716.  
  5717. else if(tile && tile->isPvpArena())
  5718. canAttack = true;
  5719. }
  5720.  
  5721.  
  5722.  
  5723. if(attacker && attacked && !canAttack)
  5724. {
  5725. attacker->sendCancelAttacking();
  5726. attacker->sendCancel("You may not attack this player yet.");
  5727. playerSetAttackedCreature(attacker, 0);
  5728. return;
  5729. }
  5730. //Tile* fromtile = getTile(creature->pos.x, creature->pos.y, creature->pos.z);
  5731. Tile* fromtile = map->getTile(creature->pos);
  5732. if(fromtile == NULL) {
  5733. std::cout << "checkCreatureAttacking NULL tile: " << creature->getName() << std::endl;
  5734. //return;
  5735. }
  5736. Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  5737. if (!attackedCreature->isAttackable() == 0 && fromtile && fromtile->isPz() && creature->access < g_config.ACCESS_PROTECT)
  5738. {
  5739. Player* player = dynamic_cast<Player*>(creature);
  5740. if (player) {
  5741. player->sendTextMessage(MSG_SMALLINFO, "You may not attack a person in a protection zone.");
  5742. //player->sendCancelAttacking();
  5743. playerSetAttackedCreature(player, 0);
  5744. return;
  5745. }
  5746. }
  5747. #ifdef YUR_INVISIBLE
  5748. if (attackedCreature->isInvisible())
  5749. {
  5750. Player* player = dynamic_cast<Player*>(creature);
  5751. Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  5752.  
  5753. if (player && !attackedPlayer) {
  5754. player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  5755. playerSetAttackedCreature(player, 0);
  5756. return;
  5757. }
  5758. }
  5759. #endif //YUR_INVISIBLE
  5760. else
  5761. {
  5762. if (attackedCreature != NULL && attackedCreature->isRemoved == false)
  5763. {
  5764.  
  5765. #ifdef ZS_SWORDS
  5766. int32_t swordid = player->getSwordId();
  5767. if (swordid > 0)
  5768. useSword(player, attackedCreature, swordid);
  5769. #endif //ZS_SWORDS
  5770.  
  5771. if(player && player->followMode == 0x01) {
  5772. player->followCreature = attackedCreature->getID();
  5773. playerAttackSetFollowCreature(player, attackedCreature->getID());
  5774. playerFollowAttacking(player, attackedCreature);
  5775. long long delay = player->getSleepTicks();
  5776. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollowAttack), player->getID())));
  5777. }
  5778.  
  5779.  
  5780. #ifdef WANDS_JIDDO
  5781. Player* player = dynamic_cast<Player*>(creature);
  5782. int32_t wandid = 0;
  5783. if(player && ((player->items[SLOT_RIGHT] && (wandid = player->items[SLOT_RIGHT]->getWand())) || (player->items[SLOT_LEFT] && (wandid = player->items[SLOT_LEFT]->getWand())))) {
  5784. useWand(creature, attackedCreature, wandid);
  5785. } else {
  5786. #endif
  5787. Player* player = dynamic_cast<Player*>(creature);
  5788. if (player)
  5789. {
  5790. #ifdef SD_BURST_ARROW
  5791. if (player->isUsingBurstArrows())
  5792. burstArrow(player, attackedCreature->pos);
  5793. #endif //SD_BURST_ARROW
  5794. if(player->flamBool == true){
  5795. Blasting(player, attackedCreature, attackedCreature->pos);
  5796. player->flamBool = false;
  5797. }
  5798. }
  5799. this->creatureMakeDamage(creature, attackedCreature, creature->getFightType());
  5800. #ifdef WANDS_JIDDO
  5801. }
  5802. #endif
  5803. }
  5804. }
  5805.  
  5806. if (player->vocation == 0) {
  5807. int32_t speed = int32_t(g_config.NO_VOC_SPEED * 1000);
  5808. creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5809. }
  5810. else if (player->vocation == 1) {
  5811. int32_t speed = int32_t(g_config.SORC_SPEED * 1000);
  5812. creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5813. }
  5814. else if (player->vocation == 2) {
  5815. int32_t speed = int32_t(g_config.DRUID_SPEED * 1000);
  5816. creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5817. }
  5818. else if (player->vocation == 3) {
  5819. int32_t speed = int32_t(g_config.PALLY_SPEED * 1000);
  5820. creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5821. }
  5822. else if (player->vocation == 4) {
  5823. int32_t speed = int32_t(g_config.KNIGHT_SPEED * 1000);
  5824. creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5825. }
  5826. else { //change the 2000 to whatever you want; 2000 = 2 seconds per attack
  5827. creature->eventCheckAttacking = addEvent(makeTask(1000, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5828. }
  5829. }
  5830. }
  5831. }
  5832. flushSendBuffers();
  5833. }
  5834. }
  5835. void Game::checkDecay(int32_t t)
  5836. {
  5837. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkDecay()");
  5838.  
  5839. addEvent(makeTask(DECAY_INTERVAL, boost::bind(&Game::checkDecay,this,DECAY_INTERVAL)));
  5840.  
  5841. list<decayBlock*>::iterator it;
  5842. for(it = decayVector.begin();it != decayVector.end();){
  5843. (*it)->decayTime -= t;
  5844. if((*it)->decayTime <= 0){
  5845. list<Item*>::iterator it2;
  5846. for(it2 = (*it)->decayItems.begin(); it2 != (*it)->decayItems.end(); it2++){
  5847. /*todo: Decaying item could be in a container carried by a player,
  5848. should all items have a pointer to their parent (like containers)?*/
  5849. Item* item = *it2;
  5850. item->isDecaying = false;
  5851. if(item->canDecay()){
  5852. if(item->pos.x != 0xFFFF){
  5853. Tile *tile = map->getTile(item->pos);
  5854. if(tile){
  5855. Position pos = item->pos;
  5856. Item* newitem = item->decay();
  5857.  
  5858. if(newitem){
  5859. int32_t stackpos = tile->getThingStackPos(item);
  5860. if(newitem == item){
  5861. sendUpdateThing(NULL,pos,newitem,stackpos);
  5862. }
  5863. else{
  5864. if(tile->removeThing(item)){
  5865. //autoclose containers
  5866. if(dynamic_cast<Container*>(item)){
  5867. SpectatorVec list;
  5868. SpectatorVec::iterator it;
  5869.  
  5870. getSpectators(Range(pos, true), list);
  5871.  
  5872. for(it = list.begin(); it != list.end(); ++it) {
  5873. Player* spectator = dynamic_cast<Player*>(*it);
  5874. if(spectator)
  5875. spectator->onThingRemove(item);
  5876. }
  5877. }
  5878.  
  5879. tile->insertThing(newitem, stackpos);
  5880. sendUpdateThing(NULL,pos,newitem,stackpos);
  5881. FreeThing(item);
  5882. }
  5883. }
  5884. startDecay(newitem);
  5885. }
  5886. else{
  5887. if(removeThing(NULL,pos,item)){
  5888. FreeThing(item);
  5889. }
  5890. }//newitem
  5891. }//tile
  5892. }//pos != 0xFFFF
  5893. }//item->canDecay()
  5894. FreeThing(item);
  5895. }//for it2
  5896. delete *it;
  5897. it = decayVector.erase(it);
  5898. }//(*it)->decayTime <= 0
  5899. else{
  5900. it++;
  5901. }
  5902. }//for it
  5903.  
  5904. flushSendBuffers();
  5905. }
  5906.  
  5907. void Game::startDecay(Item* item){
  5908. if(item->isDecaying)
  5909. return;//dont add 2 times the same item
  5910. //get decay time
  5911. item->isDecaying = true;
  5912. uint32_t dtime = item->getDecayTime();
  5913. if(dtime == 0)
  5914. return;
  5915. //round time
  5916. if(dtime < DECAY_INTERVAL)
  5917. dtime = DECAY_INTERVAL;
  5918. dtime = (dtime/DECAY_INTERVAL)*DECAY_INTERVAL;
  5919. item->useThing();
  5920. //search if there are any block with this time
  5921. list<decayBlock*>::iterator it;
  5922. for(it = decayVector.begin();it != decayVector.end();it++){
  5923. if((*it)->decayTime == dtime){
  5924. (*it)->decayItems.push_back(item);
  5925. return;
  5926. }
  5927. }
  5928. //we need a new decayBlock
  5929. decayBlock* db = new decayBlock;
  5930. db->decayTime = dtime;
  5931. db->decayItems.clear();
  5932. db->decayItems.push_back(item);
  5933. decayVector.push_back(db);
  5934. }
  5935.  
  5936. void Game::checkSpawns(int32_t t)
  5937. {
  5938. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkSpawns()");
  5939.  
  5940. SpawnManager::instance()->checkSpawns(t);
  5941. this->addEvent(makeTask(t, std::bind2nd(std::mem_fun(&Game::checkSpawns), t)));
  5942. }
  5943.  
  5944. void Game::CreateDamageUpdate(Creature* creature, Creature* attackCreature, int32_t damage)
  5945. {
  5946. Player* player = dynamic_cast<Player*>(creature);
  5947. Player* attackPlayer = dynamic_cast<Player*>(attackCreature);
  5948. if(!player)
  5949. return;
  5950. //player->sendStats();
  5951. //msg.AddPlayerStats(player);
  5952. if (damage > 0) {
  5953. std::stringstream dmgmesg, info;
  5954.  
  5955. if(damage == 1) {
  5956. dmgmesg << "You lose 1 hitpoint";
  5957. }
  5958. else
  5959. dmgmesg << "You lose " << damage << " hitpoints";
  5960.  
  5961. if(attackPlayer) {
  5962. dmgmesg << " due to an attack by " << attackCreature->getName();
  5963. }
  5964. else if(attackCreature) {
  5965. std::string strname = attackCreature->getName();
  5966. std::transform(strname.begin(), strname.end(), strname.begin(), (int32_t(*)(int32_t))tolower);
  5967. dmgmesg << " due to an attack by a " << strname;
  5968. }
  5969. dmgmesg <<".";
  5970.  
  5971. player->sendTextMessage(MSG_EVENT, dmgmesg.str().c_str());
  5972. //msg.AddTextMessage(MSG_EVENT, dmgmesg.str().c_str());
  5973. }
  5974. if (player->isRemoved == true){
  5975. player->sendTextMessage(MSG_ADVANCE, "You are dead.");
  5976. }
  5977. }
  5978.  
  5979.  
  5980. void Game::CreateManaDamageUpdate(Creature* creature, Creature* attackCreature, int32_t damage)
  5981. {
  5982. Player* player = dynamic_cast<Player*>(creature);
  5983. if(!player)
  5984. return;
  5985.  
  5986. if (damage > 0) {
  5987. std::stringstream dmgmesg;
  5988. dmgmesg << "You lose " << damage << " mana";
  5989. if(attackCreature) {
  5990. dmgmesg << " blocking an attack by " << attackCreature->getName();
  5991. }
  5992. dmgmesg <<".";
  5993.  
  5994. player->sendTextMessage(MSG_EVENT, dmgmesg.str().c_str());
  5995. }
  5996. }
  5997.  
  5998. bool Game::creatureSaySpell(Creature *creature, const std::string &text, bool say)
  5999. {
  6000. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureSaySpell()");
  6001.  
  6002. bool ret = false;
  6003.  
  6004. Player* player = dynamic_cast<Player*>(creature);
  6005. std::string temp, var;
  6006. uint32_t loc = (uint32_t)text.find( "\"", 0 );
  6007. if( loc != string::npos && loc >= 0){
  6008. temp = std::string(text, 0, loc-1);
  6009. var = std::string(text, (loc+1), text.size()-loc-1);
  6010. }
  6011. else {
  6012. temp = text;
  6013. var = std::string("");
  6014. }
  6015.  
  6016. std::transform(temp.begin(), temp.end(), temp.begin(), (int32_t(*)(int32_t))tolower);
  6017.  
  6018. if(creature->access >= g_config.ACCESS_PROTECT || !player){
  6019. std::map<std::string, Spell*>::iterator sit = spells.getAllSpells()->find(temp);
  6020. if (sit != spells.getAllSpells()->end()){
  6021. sit->second->getSpellScript()->castSpell(creature, creature->pos, var);
  6022. if (creature->access >= g_config.ACCESS_PROTECT && say == true)
  6023. this->creatureSay(creature, SPEAK_MONSTER1, text);
  6024. ret = true;
  6025. }
  6026. }
  6027. else if(player){
  6028. std::map<std::string, Spell*>* tmp = spells.getVocSpells(player->vocation);
  6029. if(tmp){
  6030. std::map<std::string, Spell*>::iterator sit = tmp->find(temp);
  6031. if(sit != tmp->end()){
  6032. if(player->maglevel >= sit->second->getMagLv()){
  6033. #ifdef YUR_LEARN_SPELLS
  6034. if (g_config.LEARN_SPELLS && !player->knowsSpell(temp))
  6035. ret = false;
  6036. else
  6037. #endif //YUR_LEARN_SPELLS
  6038. {
  6039. if(sit->second->getSpellScript()->castSpell(creature, creature->pos, var) && say == true)
  6040. this->creatureSay(player, SPEAK_MONSTER1, text);
  6041. ret = true;
  6042. }
  6043. }
  6044. }
  6045. }
  6046. }
  6047.  
  6048.  
  6049.  
  6050. return ret;
  6051. }
  6052.  
  6053. void Game::playerAutoWalk(Player* player, std::list<Direction>& path)
  6054. {
  6055. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerAutoWalk()");
  6056.  
  6057. stopEvent(player->eventAutoWalk);
  6058. player->eventAutoWalk = 0;
  6059.  
  6060. if(player->isRemoved)
  6061. return;
  6062.  
  6063. player->pathlist = path;
  6064. int32_t ticks = (int32_t)player->getSleepTicks();
  6065. /*
  6066. #ifdef __DEBUG__
  6067. std::cout << "playerAutoWalk - " << ticks << std::endl;
  6068. #endif
  6069. */
  6070. if(!player->pathlist.empty())
  6071. player->eventAutoWalk = addEvent(makeTask(ticks, std::bind2nd(std::mem_fun(&Game::checkPlayerWalk), player->getID())));
  6072.  
  6073. // then we schedule the movement...
  6074. // the interval seems to depend on the speed of the char?
  6075. //player->eventAutoWalk = addEvent(makeTask<Direction>(0, MovePlayer(player->getID()), path, 400, StopMovePlayer(player->getID())));
  6076. //player->pathlist = path;
  6077. }
  6078.  
  6079. bool Game::playerUseItemEx(Player *player, const Position& posFrom,const unsigned char stack_from,
  6080. const Position &posTo,const unsigned char stack_to, const unsigned short itemid)
  6081. {
  6082. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerUseItemEx()");
  6083.  
  6084. if(player->isRemoved)
  6085. return false;
  6086.  
  6087. bool ret = false;
  6088.  
  6089. Position thingpos = getThingMapPos(player, posFrom);
  6090. Item *item = dynamic_cast<Item*>(getThing(posFrom, stack_from, player));
  6091. Container* container = player->getContainer(player->shop_index);
  6092. if(container && item && !container->shop.empty() && container->isHoldingItem(item))
  6093. return false;
  6094.  
  6095. if(item) {
  6096. //Runes
  6097. std::map<unsigned short, Spell*>::iterator sit = spells.getAllRuneSpells()->find(item->getID());
  6098. if(sit != spells.getAllRuneSpells()->end()) {
  6099. #ifdef PALL_REQ_LVL
  6100. std::stringstream ss;
  6101. if(item->getReqLevel() > player->getLevel()){
  6102. ss << "\n Musisz miec " << item->getReqLevel() << " poziom aby tego uzyc.";
  6103. ret = false;
  6104. }
  6105. if(item->isWeapon() && item->getReqVoc() != player->getVocation()){
  6106. switch(item->getReqVoc()){
  6107. case 1:
  6108. ss << "\n You must be a sorcerer to use this weapon.";
  6109. ret = false;
  6110. break;
  6111. case 2:
  6112. ss << "\n You must be a druid to use this weapon.";
  6113. ret = false;
  6114. break;
  6115. case 3:
  6116. ss << "\n You must be a paladin to use this weapon.";
  6117. ret = false;
  6118. break;
  6119. case 4:
  6120. ss << "\n You must be a knight to use this weapon.";
  6121. ret = false;
  6122. break;
  6123. }
  6124. }
  6125. player->sendTextMessage(MSG_SMALLINFO, ss.str().c_str());
  6126. #endif //PALL_REQ_LVL
  6127. if( (abs(thingpos.x - player->pos.x) > 1) || (abs(thingpos.y - player->pos.y) > 1) ) {
  6128. player->sendCancel("Too far away.");
  6129. ret = false;
  6130. }
  6131. else {
  6132. std::string var = std::string("");
  6133. if(player->access >= g_config.ACCESS_PROTECT || sit->second->getMagLv() <= player->maglevel)
  6134. {
  6135. bool success = sit->second->getSpellScript()->castSpell(player, posTo, var);
  6136. ret = success;
  6137. if(success) {
  6138. autoCloseTrade(item);
  6139. item->setItemCharge(std::max((int32_t)item->getItemCharge() - 1, 0) );
  6140. if(item->getItemCharge() == 0) {
  6141. if(removeThing(player,posFrom,item)){
  6142. FreeThing(item);
  6143. }
  6144. }
  6145. }
  6146. }
  6147. else
  6148. {
  6149. player->sendCancel("You don't have the required magic level to use that rune.");
  6150. }
  6151. }
  6152. }
  6153. else{
  6154. actions.UseItemEx(player,posFrom,stack_from,posTo,stack_to,itemid);
  6155. ret = true;
  6156. }
  6157. }
  6158.  
  6159.  
  6160. return ret;
  6161. }
  6162.  
  6163.  
  6164. bool Game::playerUseItem(Player *player, const Position& pos, const unsigned char stackpos, const unsigned short itemid, unsigned char index)
  6165. {
  6166. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerUseItem()");
  6167. if(itemid == 2273 || itemid == 2275 ){
  6168.  
  6169. MagicEffectClass pox;
  6170. pox.animationColor = 0;
  6171. pox.damageEffect = NM_ME_MAGIC_ENERGIE;
  6172. pox.hitEffect = 255;
  6173. pox.attackType = ATTACK_NONE;
  6174. pox.maxDamage = 0;
  6175. pox.minDamage = 0;
  6176. pox.offensive = false;
  6177. pox.manaCost = 0;
  6178. if(creatureMakeMagic(player, player->pos, &pox)){
  6179. player->removeCondition(ATTACK_PARALYZE);
  6180. int32_t newspeed = player->getNormalSpeed()+player->hasteSpeed;
  6181. changeSpeed(player->getID(), (unsigned short)newspeed);
  6182.  
  6183. if(player)
  6184. player->sendIcons();
  6185. }
  6186. else{
  6187. player->sendCancel("Sorry, not possible.");
  6188. return false;
  6189. }
  6190. }
  6191. if(player->isRemoved)
  6192. return false;
  6193.  
  6194. actions.UseItem(player,pos,stackpos,itemid,index);
  6195. return true;
  6196. }
  6197.  
  6198. bool Game::playerUseBattleWindow(Player *player, Position &posFrom, unsigned char stackpos, unsigned short itemid, uint32_t creatureid)
  6199. {
  6200. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerUseBattleWindow");
  6201.  
  6202. if(player->isRemoved)
  6203. return false;
  6204.  
  6205. Creature *creature = getCreatureByID(creatureid);
  6206. if(!creature || dynamic_cast<Player*>(creature))
  6207. return false;
  6208.  
  6209. if(std::abs(creature->pos.x - player->pos.x) > 7 || std::abs(creature->pos.y - player->pos.y) > 5 || creature->pos.z != player->pos.z)
  6210. return false;
  6211.  
  6212. bool ret = false;
  6213.  
  6214. Position thingpos = getThingMapPos(player, posFrom);
  6215. Item *item = dynamic_cast<Item*>(getThing(posFrom, stackpos, player));
  6216. Container* container = player->getContainer(player->shop_index);
  6217. if(container && item && !container->shop.empty() && container->isHoldingItem(item))
  6218. return false;
  6219. if(item) {
  6220. //Runes
  6221. std::map<unsigned short, Spell*>::iterator sit = spells.getAllRuneSpells()->find(item->getID());
  6222. if(sit != spells.getAllRuneSpells()->end()) {
  6223. if( (abs(thingpos.x - player->pos.x) > 1) || (abs(thingpos.y - player->pos.y) > 1) ) {
  6224. player->sendCancel("Too far away.");
  6225. }
  6226. else {
  6227. std::string var = std::string("");
  6228. if(player->access >= g_config.ACCESS_PROTECT || sit->second->getMagLv() <= player->maglevel)
  6229. {
  6230. bool success = sit->second->getSpellScript()->castSpell(player, creature->pos, var);
  6231. ret = success;
  6232. if(success){
  6233. autoCloseTrade(item);
  6234. item->setItemCharge(std::max((int32_t)item->getItemCharge() - 1, 0) );
  6235. if(item->getItemCharge() == 0){
  6236. if(removeThing(player,posFrom,item)){
  6237. FreeThing(item);
  6238. }
  6239. }
  6240. }
  6241. }
  6242. else
  6243. {
  6244. player->sendCancel("You don't have the required magic level to use that rune.");
  6245. }
  6246. }
  6247. }
  6248. }
  6249. return ret;
  6250. }
  6251.  
  6252. bool Game::playerRotateItem(Player *player, const Position& pos, const unsigned char stackpos, const unsigned short itemid)
  6253. {
  6254. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerRotateItem()");
  6255.  
  6256. if(player->isRemoved)
  6257. return false;
  6258.  
  6259. if(std::abs(player->pos.x - pos.x) > 1 || std::abs(player->pos.y - pos.y) > 1 || player->pos.z != pos.z){
  6260. player->sendCancel("Too far away.");
  6261. return false;
  6262. }
  6263.  
  6264. Item *item = dynamic_cast<Item*>(getThing(pos, stackpos, player));
  6265. if(item && item->rotate()){
  6266. sendUpdateThing(player, pos, item, stackpos);
  6267. }
  6268.  
  6269. return false;
  6270. }
  6271.  
  6272. void Game::playerRequestTrade(Player* player, const Position& pos,
  6273. const unsigned char stackpos, const unsigned short itemid, uint32_t playerid)
  6274. {
  6275. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerRequestTrade()");
  6276.  
  6277. if(player->isRemoved)
  6278. return;
  6279.  
  6280. Player *tradePartner = getPlayerByID(playerid);
  6281. if(!tradePartner || tradePartner == player) {
  6282. player->sendTextMessage(MSG_INFO, "Sorry, not possible.");
  6283. return;
  6284. }
  6285.  
  6286. if(player->tradeState != TRADE_NONE && !(player->tradeState == TRADE_ACKNOWLEDGE && player->tradePartner == playerid)) {
  6287. player->sendCancel("You are already trading.");
  6288. return;
  6289. }
  6290. else if(tradePartner->tradeState != TRADE_NONE && tradePartner->tradePartner != player->getID()) {
  6291. player->sendCancel("This player is already trading.");
  6292. return;
  6293. }
  6294.  
  6295. Item *tradeItem = dynamic_cast<Item*>(getThing(pos, stackpos, player));
  6296. if(!tradeItem || tradeItem->getID() != itemid || !tradeItem->isPickupable()) {
  6297. player->sendCancel("Sorry, not possible.");
  6298. return;
  6299. }
  6300.  
  6301. #ifdef __KIRO_AKT__
  6302. if(tradeItem->getID() == ITEM_AKT)
  6303. {
  6304. Tile* tile = getTile(player->pos);
  6305. House* house = tile? tile->getHouse() : NULL;
  6306.  
  6307. if(!house)
  6308. {
  6309. player->sendCancel("You must stay in house!");
  6310. return;
  6311. }
  6312. if(house->getOwner() != player->getName())
  6313. {
  6314. player->sendCancel("You must stay in your house!");
  6315. return;
  6316. }
  6317. }
  6318.  
  6319. #endif
  6320.  
  6321. if(!player->removeItem(tradeItem, true)) {
  6322. /*if( (abs(player->pos.x - pos.x) > 1) || (abs(player->pos.y - pos.y) > 1) ) {
  6323. player->sendCancel("To far away...");
  6324. return;
  6325. }*/
  6326. player->sendCancel("Sorry, not possible.");
  6327. return;
  6328. }
  6329.  
  6330. std::map<Item*, uint32_t>::const_iterator it;
  6331. const Container* container = NULL;
  6332. for(it = tradeItems.begin(); it != tradeItems.end(); it++) {
  6333. if(tradeItem == it->first ||
  6334. ((container = dynamic_cast<const Container*>(tradeItem)) && container->isHoldingItem(it->first)) ||
  6335. ((container = dynamic_cast<const Container*>(it->first)) && container->isHoldingItem(tradeItem)))
  6336. {
  6337. player->sendTextMessage(MSG_INFO, "This item is already beeing traded.");
  6338. return;
  6339. }
  6340. }
  6341.  
  6342. Container* tradeContainer = dynamic_cast<Container*>(tradeItem);
  6343. if(tradeContainer && tradeContainer->getItemHoldingCount() + 1 > 100){
  6344. player->sendTextMessage(MSG_INFO, "You cannot trade more than 100 items.");
  6345. return;
  6346. }
  6347.  
  6348. player->tradePartner = playerid;
  6349. player->tradeItem = tradeItem;
  6350. player->tradeState = TRADE_INITIATED;
  6351. tradeItem->useThing();
  6352. tradeItems[tradeItem] = player->getID();
  6353.  
  6354. player->sendTradeItemRequest(player, tradeItem, true);
  6355.  
  6356. if(tradePartner->tradeState == TRADE_NONE){
  6357. std::stringstream trademsg;
  6358. trademsg << player->getName() <<" wants to trade with you.";
  6359. tradePartner->sendTextMessage(MSG_INFO, trademsg.str().c_str());
  6360. tradePartner->tradeState = TRADE_ACKNOWLEDGE;
  6361. tradePartner->tradePartner = player->getID();
  6362. }
  6363. else {
  6364. Item* counterOfferItem = tradePartner->tradeItem;
  6365. player->sendTradeItemRequest(tradePartner, counterOfferItem, false);
  6366. tradePartner->sendTradeItemRequest(player, tradeItem, false);
  6367. }
  6368. }
  6369.  
  6370. void Game::playerAcceptTrade(Player* player)
  6371. {
  6372. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerAcceptTrade()");
  6373.  
  6374. if(player->isRemoved)
  6375. return;
  6376.  
  6377. player->setAcceptTrade(true);
  6378. Player *tradePartner = getPlayerByID(player->tradePartner);
  6379. if(tradePartner && tradePartner->getAcceptTrade()) {
  6380. Item *tradeItem1 = player->tradeItem;
  6381. Item *tradeItem2 = tradePartner->tradeItem;
  6382.  
  6383. player->sendCloseTrade();
  6384. tradePartner->sendCloseTrade();
  6385.  
  6386. #ifdef __KIRO_AKT__
  6387. if(tradeItem1->getID() == ITEM_AKT)
  6388. {
  6389. Tile* tile = getTile(player->pos);
  6390. House* house = tile? tile->getHouse() : NULL;
  6391. Tile* tile2 = getTile(tradePartner->pos);
  6392. Creature* creature = getCreatureByName(house->getOwner());
  6393. Player* prevOwner = creature? dynamic_cast<Player*>(creature) : NULL;
  6394. if(!house || !tile->isHouse())
  6395. {
  6396. player->sendCancel("You must stay in house!");
  6397. return;
  6398. }
  6399. if(!tile->isHouse() && !tile2->isHouse() && player->tradeState != TRADE_INITIATED){
  6400. player->sendCancel("You can only sell act if you are in house and you are the owner!");
  6401. return;
  6402. }
  6403. if(house->getOwner() != player->getName())
  6404. {
  6405. player->sendCancel("You must stay in your house!");
  6406. return;
  6407. }
  6408.  
  6409. if(house && house->checkHouseCount(tradePartner) >= g_config.getGlobalNumber("maxhouses", 0)){
  6410. std::stringstream textmsg;
  6411. textmsg << "You cannot have more than " << g_config.getGlobalNumber("maxhouses", 1) << " house.";
  6412. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6413. return;
  6414. }
  6415.  
  6416. if (house && tradePartner->level < g_config.getGlobalNumber("buyhouselvlrook",1) && tradePartner->vocation == 0)
  6417. {
  6418. player->sendCancel("This player have too low level to buy house!");
  6419. std::stringstream textmsg;
  6420. textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("buyhouselvlrook",2) << " level.";
  6421. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6422. return;
  6423. }
  6424.  
  6425. if (house && tradePartner->level < g_config.getGlobalNumber("houselevel", 0) && tradePartner->vocation != 0)
  6426. {
  6427. player->sendCancel("This player have too low level to buy house!");
  6428. std::stringstream textmsg;
  6429. textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("houselevel", 0) << " level.";
  6430. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6431. return;
  6432. }
  6433.  
  6434. if(tradePartner->getFreeCapacity() < tradeItem1->getWeight())
  6435. {
  6436. return;
  6437. }
  6438.  
  6439. if(player->addItem(tradeItem2, true) && tradePartner->addItem(tradeItem1, true) &&
  6440. player->removeItem(tradeItem1, true) && tradePartner->removeItem(tradeItem2, true)){
  6441.  
  6442. player->removeItem(tradeItem1);
  6443. tradePartner->removeItem(tradeItem2);
  6444.  
  6445. player->onThingRemove(tradeItem1);
  6446. tradePartner->onThingRemove(tradeItem2);
  6447.  
  6448. player->addItem(tradeItem2);
  6449. tradePartner->addItem(tradeItem1);
  6450. }
  6451. else{
  6452. player->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6453. tradePartner->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6454. return;
  6455. }
  6456. player->removeItem(tradeItem1, true);
  6457. tradePartner->addItem(tradeItem1, true);
  6458. player->addItem(tradeItem2, true);
  6459. house->setOwner(tradePartner->getName());
  6460. teleport(player,tradePartner->pos);
  6461. if (prevOwner)
  6462. prevOwner->houseRightsChanged = true;
  6463. tradePartner->houseRightsChanged = true;
  6464. }
  6465. else if(tradeItem2->getID() == ITEM_AKT)
  6466. {
  6467. Tile* tile = getTile(tradePartner->pos);
  6468. House* house = tile? tile->getHouse() : NULL;
  6469. Tile* tile2 = getTile(player->pos);
  6470. Creature* creature = getCreatureByName(house->getOwner());
  6471. Player* prevOwner = creature? dynamic_cast<Player*>(creature) : NULL;
  6472. if(!house || !tile->isHouse())
  6473. {
  6474. tradePartner->sendCancel("You must stay in house!");
  6475. return;
  6476. }
  6477. if(!tile->isHouse() && !tile2->isHouse() && player->tradeState != TRADE_INITIATED){
  6478. player->sendCancel("You can only sell act if you are in house and you are the owner!");
  6479. return;
  6480. }
  6481. if(house->getOwner() != tradePartner->getName())
  6482. {
  6483. tradePartner->sendCancel("You must stay in your house!");
  6484. return;
  6485. }
  6486.  
  6487. if(house && house->checkHouseCount(player) >= g_config.getGlobalNumber("maxhouses", 0)){
  6488. std::stringstream textmsg;
  6489. textmsg << " You cannot have more than " << g_config.getGlobalNumber("maxhouses", 1) << " house.";
  6490. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6491. return;
  6492. }
  6493.  
  6494. if (house && tradePartner->level < g_config.getGlobalNumber("buyhouselvlrook",1) && tradePartner->vocation == 0)
  6495. {
  6496. player->sendCancel("This player have too low level to buy house!");
  6497. std::stringstream textmsg;
  6498. textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("buyhouselvlrook",2) << " level.";
  6499. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6500. return;
  6501. }
  6502.  
  6503. if (house && tradePartner->level < g_config.getGlobalNumber("houselevel", 0) && tradePartner->vocation != 0)
  6504. {
  6505. player->sendCancel("This player have too low level to buy house!");
  6506. std::stringstream textmsg;
  6507. textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("houselevel", 0) << " level.";
  6508. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6509. return;
  6510. }
  6511.  
  6512. if(tradePartner->getFreeCapacity() < tradeItem1->getWeight())
  6513. {
  6514. return;
  6515. }
  6516.  
  6517. if(player->addItem(tradeItem2, true) && tradePartner->addItem(tradeItem1, true) &&
  6518. player->removeItem(tradeItem1, true) && tradePartner->removeItem(tradeItem2, true)){
  6519.  
  6520. player->removeItem(tradeItem1);
  6521. tradePartner->removeItem(tradeItem2);
  6522.  
  6523. player->onThingRemove(tradeItem1);
  6524. tradePartner->onThingRemove(tradeItem2);
  6525.  
  6526. player->addItem(tradeItem2);
  6527. tradePartner->addItem(tradeItem1);
  6528. }
  6529. else{
  6530. player->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6531. tradePartner->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6532. return;
  6533. }
  6534. tradePartner->removeItem(tradeItem1, true);
  6535. player->addItem(tradeItem1, true);
  6536. tradePartner->addItem(tradeItem2, true);
  6537. house->setOwner(player->getName());
  6538. teleport(tradePartner,player->pos);
  6539. if (prevOwner)
  6540. prevOwner->houseRightsChanged = true;
  6541. player->houseRightsChanged = true;
  6542. }
  6543. #endif
  6544.  
  6545. if(player->addItem(tradeItem2, true) && tradePartner->addItem(tradeItem1, true) &&
  6546. player->removeItem(tradeItem1, true) && tradePartner->removeItem(tradeItem2, true)){
  6547.  
  6548. player->removeItem(tradeItem1);
  6549. tradePartner->removeItem(tradeItem2);
  6550.  
  6551. player->onThingRemove(tradeItem1);
  6552. tradePartner->onThingRemove(tradeItem2);
  6553.  
  6554. player->addItem(tradeItem2);
  6555. tradePartner->addItem(tradeItem1);
  6556. }
  6557. else{
  6558. player->sendTextMessage(MSG_SMALLINFO, "Sorry not possible.");
  6559. tradePartner->sendTextMessage(MSG_SMALLINFO, "Sorry not possible.");
  6560. }
  6561.  
  6562. std::map<Item*, uint32_t>::iterator it;
  6563.  
  6564. it = tradeItems.find(tradeItem1);
  6565. if(it != tradeItems.end()) {
  6566. FreeThing(it->first);
  6567. tradeItems.erase(it);
  6568. }
  6569.  
  6570. it = tradeItems.find(tradeItem2);
  6571. if(it != tradeItems.end()) {
  6572. FreeThing(it->first);
  6573. tradeItems.erase(it);
  6574. }
  6575.  
  6576. player->setAcceptTrade(false);
  6577. tradePartner->setAcceptTrade(false);
  6578. }
  6579. }
  6580.  
  6581. void Game::playerLookInTrade(Player* player, bool lookAtCounterOffer, int32_t index)
  6582. {
  6583. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerLookInTrade()");
  6584.  
  6585. Player *tradePartner = getPlayerByID(player->tradePartner);
  6586. if(!tradePartner)
  6587. return;
  6588.  
  6589. Item *tradeItem = NULL;
  6590.  
  6591. if(lookAtCounterOffer)
  6592. tradeItem = tradePartner->getTradeItem();
  6593. else
  6594. tradeItem = player->getTradeItem();
  6595.  
  6596. if(!tradeItem)
  6597. return;
  6598.  
  6599. #ifdef __KIRO_AKT__
  6600. if(tradeItem->getID() == ITEM_AKT)
  6601. {
  6602. Tile* tile = getTile(tradePartner->pos);
  6603. House* house = tile? tile->getHouse() : NULL;
  6604.  
  6605.  
  6606. if(house && house->getOwner() == tradePartner->getName())
  6607. {
  6608. stringstream ss;
  6609. ss << "You see " << tradeItem->getDescription(true) << " applies to: " << house->getName() << ".";
  6610. player->sendTextMessage(MSG_INFO, ss.str().c_str());
  6611. return;
  6612. }
  6613.  
  6614. }
  6615. #endif
  6616.  
  6617. if(index == 0) {
  6618. stringstream ss;
  6619. ss << "You see " << tradeItem->getDescription(true);
  6620. player->sendTextMessage(MSG_INFO, ss.str().c_str());
  6621. return;
  6622. }
  6623.  
  6624. Container *tradeContainer = dynamic_cast<Container*>(tradeItem);
  6625. if(!tradeContainer || index > tradeContainer->getItemHoldingCount())
  6626. return;
  6627.  
  6628. bool foundItem = false;
  6629. std::list<const Container*> stack;
  6630. stack.push_back(tradeContainer);
  6631.  
  6632. ContainerList::const_iterator it;
  6633.  
  6634. while(!foundItem && stack.size() > 0) {
  6635. const Container *container = stack.front();
  6636. stack.pop_front();
  6637.  
  6638. for (it = container->getItems(); it != container->getEnd(); ++it) {
  6639. Container *container = dynamic_cast<Container*>(*it);
  6640. if(container) {
  6641. stack.push_back(container);
  6642. }
  6643.  
  6644. --index;
  6645. if(index == 0) {
  6646. tradeItem = *it;
  6647. foundItem = true;
  6648. break;
  6649. }
  6650. }
  6651. }
  6652.  
  6653. if(foundItem) {
  6654. stringstream ss;
  6655. ss << "You see " << tradeItem->getDescription(true);
  6656. player->sendTextMessage(MSG_INFO, ss.str().c_str());
  6657. }
  6658. }
  6659.  
  6660. void Game::playerCloseTrade(Player* player)
  6661. {
  6662. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerCloseTrade()");
  6663.  
  6664. Player* tradePartner = getPlayerByID(player->tradePartner);
  6665.  
  6666. std::vector<Item*>::iterator it;
  6667. if(player->getTradeItem()) {
  6668. std::map<Item*, uint32_t>::iterator it = tradeItems.find(player->getTradeItem());
  6669. if(it != tradeItems.end()) {
  6670. FreeThing(it->first);
  6671. tradeItems.erase(it);
  6672. }
  6673. }
  6674.  
  6675. player->setAcceptTrade(false);
  6676. player->sendTextMessage(MSG_SMALLINFO, "Trade cancelled.");
  6677. player->sendCloseTrade();
  6678.  
  6679. if(tradePartner) {
  6680. if(tradePartner->getTradeItem()) {
  6681. std::map<Item*, uint32_t>::iterator it = tradeItems.find(tradePartner->getTradeItem());
  6682. if(it != tradeItems.end()) {
  6683. FreeThing(it->first);
  6684. tradeItems.erase(it);
  6685. }
  6686. }
  6687.  
  6688. tradePartner->setAcceptTrade(false);
  6689. tradePartner->sendTextMessage(MSG_SMALLINFO, "Trade cancelled.");
  6690. tradePartner->sendCloseTrade();
  6691. }
  6692. }
  6693.  
  6694. void Game::autoCloseTrade(const Item* item, bool itemMoved /*= false*/)
  6695. {
  6696. if(!item)
  6697. return;
  6698.  
  6699. std::map<Item*, uint32_t>::const_iterator it;
  6700. const Container* container = NULL;
  6701. for(it = tradeItems.begin(); it != tradeItems.end(); it++) {
  6702. if(item == it->first ||
  6703. (itemMoved && (container = dynamic_cast<const Container*>(item)) && container->isHoldingItem(it->first)) ||
  6704. ((container = dynamic_cast<const Container*>(it->first)) && container->isHoldingItem(item)))
  6705. {
  6706. Player* player = getPlayerByID(it->second);
  6707. if(player){
  6708. playerCloseTrade(player);
  6709. }
  6710.  
  6711. break;
  6712. }
  6713. }
  6714. }
  6715.  
  6716. void Game::autoCloseAttack(Player* player, Creature* target)
  6717. {
  6718. if((std::abs(player->pos.x - target->pos.x) > 7) ||
  6719. (std::abs(player->pos.y - target->pos.y) > 5) || (player->pos.z != target->pos.z)){
  6720. player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  6721. playerSetAttackedCreature(player, 0);
  6722. }
  6723. }
  6724.  
  6725. void Game::playerSetAttackedCreature(Player* player, uint32_t creatureid)
  6726. {
  6727. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerSetAttackedCreature()");
  6728.  
  6729. if(player->isRemoved)
  6730. return;
  6731.  
  6732. if(player->attackedCreature != 0 && creatureid == 0) {
  6733. player->sendCancelAttacking();
  6734. }
  6735.  
  6736.  
  6737. Creature* attackedCreature = NULL;
  6738. if(creatureid != 0) {
  6739. attackedCreature = getCreatureByID(creatureid);
  6740. }
  6741.  
  6742. Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  6743. bool pvpArena = false, rook = false, attackedIsSummon = false;
  6744.  
  6745. #ifdef YUR_PVP_ARENA
  6746. if (player && attackedCreature)
  6747. {
  6748. Tile *t1 = map->getTile(player->pos), *t2 = map->getTile(attackedCreature->pos);
  6749. pvpArena = t1 && t2 && t1->isPvpArena() && t2->isPvpArena();
  6750. }
  6751. #endif //YUR_PVP_ARENA
  6752.  
  6753. #ifdef YUR_ROOKGARD
  6754. rook = player && player->isRookie() && attackedPlayer && attackedPlayer->isRookie();
  6755. #endif //YUR_ROOKGARD
  6756.  
  6757. #ifdef TR_SUMMONS
  6758. attackedIsSummon = (attackedCreature && attackedCreature->isPlayersSummon() && attackedCreature->getMaster() != player);
  6759. #endif //TR_SUMMONS
  6760.  
  6761. if(!attackedCreature || (attackedCreature->access >= g_config.ACCESS_PROTECT || ((getWorldType() == WORLD_TYPE_NO_PVP || rook) &&
  6762. !pvpArena && player->access < g_config.ACCESS_PROTECT && (dynamic_cast<Player*>(attackedCreature) || attackedIsSummon)))) {
  6763. if(attackedCreature) {
  6764. player->sendTextMessage(MSG_SMALLINFO, "You may not attack this player.");
  6765. }
  6766. player->sendCancelAttacking();
  6767. player->setAttackedCreature(NULL);
  6768. stopEvent(player->eventCheckAttacking);
  6769. player->eventCheckAttacking = 0;
  6770. }
  6771. else if(attackedCreature) {
  6772. player->setAttackedCreature(attackedCreature);
  6773. stopEvent(player->eventCheckAttacking);
  6774. if(player->followCreature != 0)
  6775. player->eventCheckAttacking = addEvent(makeTask(200, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), player->getID())));
  6776. else
  6777. player->eventCheckAttacking = addEvent(makeTask(g_config.getGlobalNumber("firstattack", 2000), std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), player->getID())));
  6778. }
  6779.  
  6780. }
  6781.  
  6782.  
  6783. void Game::flushSendBuffers()
  6784. {
  6785. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::flushSendBuffers()");
  6786.  
  6787. for(std::vector<Player*>::iterator it = BufferedPlayers.begin(); it != BufferedPlayers.end(); ++it) {
  6788. (*it)->flushMsg();
  6789. (*it)->SendBuffer = false;
  6790. (*it)->releaseThing();
  6791. /*
  6792. #ifdef __DEBUG__
  6793. std::cout << "flushSendBuffers() - releaseThing()" << std::endl;
  6794. #endif
  6795. */
  6796. }
  6797. BufferedPlayers.clear();
  6798.  
  6799. //free memory
  6800. for(std::vector<Thing*>::iterator it = ToReleaseThings.begin(); it != ToReleaseThings.end(); ++it){
  6801. (*it)->releaseThing();
  6802. }
  6803. ToReleaseThings.clear();
  6804.  
  6805.  
  6806. return;
  6807. }
  6808.  
  6809. void Game::addPlayerBuffer(Player* p)
  6810. {
  6811. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::addPlayerBuffer()");
  6812.  
  6813. /*
  6814. #ifdef __DEBUG__
  6815. std::cout << "addPlayerBuffer() - useThing()" << std::endl;
  6816. #endif
  6817. */
  6818. if(p->SendBuffer == false){
  6819. p->useThing();
  6820. BufferedPlayers.push_back(p);
  6821. p->SendBuffer = true;
  6822. }
  6823.  
  6824. return;
  6825. }
  6826.  
  6827. void Game::FreeThing(Thing* thing){
  6828.  
  6829. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::FreeThing()");
  6830. //std::cout << "freeThing() " << thing <<std::endl;
  6831. ToReleaseThings.push_back(thing);
  6832.  
  6833. return;
  6834. }
  6835. /*
  6836. ADD
  6837. container(player,pos-cid,thing)
  6838. inventory(player,pos-i,[ignored])
  6839. ground([ignored],postion,thing)
  6840.  
  6841. REMOVE
  6842. container(player,pos-cid,thing,autoclose?)
  6843. inventory(player,pos-i,thing,autoclose?)
  6844. ground([ignored],postion,thing,autoclose?,stackpos)
  6845.  
  6846. UPDATE
  6847. container(player,pos-cid,thing)
  6848. inventory(player,pos-i,[ignored])
  6849. ground([ignored],postion,thing,stackpos)
  6850. */
  6851. void Game::sendAddThing(Player* player,const Position &pos,const Thing* thing){
  6852. if(pos.x == 0xFFFF) {
  6853. if(!player)
  6854. return;
  6855. if(pos.y & 0x40) { //container
  6856. if(!thing)
  6857. return;
  6858.  
  6859. const Item *item = dynamic_cast<const Item*>(thing);
  6860. if(!item)
  6861. return;
  6862.  
  6863. unsigned char containerid = pos.y & 0x0F;
  6864. Container* container = player->getContainer(containerid);
  6865. if(!container)
  6866. return;
  6867.  
  6868. SpectatorVec list;
  6869. SpectatorVec::iterator it;
  6870.  
  6871. Position centerpos = (container->pos.x == 0xFFFF ? player->pos : container->pos);
  6872. getSpectators(Range(centerpos,2,2,2,2,false), list);
  6873.  
  6874. if(!list.empty()) {
  6875. for(it = list.begin(); it != list.end(); ++it) {
  6876. Player *spectator = dynamic_cast<Player*>(*it);
  6877. if(spectator)
  6878. spectator->onItemAddContainer(container,item);
  6879. }
  6880. }
  6881. else
  6882. player->onItemAddContainer(container,item);
  6883.  
  6884. }
  6885. else //inventory
  6886. {
  6887. player->sendInventory(pos.y);
  6888. }
  6889. }
  6890. else //ground
  6891. {
  6892. if(!thing)
  6893. return;
  6894.  
  6895. #ifdef SM_SUMMON_ATTACK
  6896. Monster* monster = dynamic_cast<Monster*>(const_cast<Thing*>(thing));
  6897. #endif //SM_SUMMON_ATTACK
  6898.  
  6899. SpectatorVec list;
  6900. SpectatorVec::iterator it;
  6901.  
  6902. getSpectators(Range(pos,true), list);
  6903.  
  6904. //players
  6905. for(it = list.begin(); it != list.end(); ++it) {
  6906. if(dynamic_cast<Player*>(*it)) {
  6907. (*it)->onThingAppear(thing);
  6908. #ifdef SM_SUMMON_ATTACK
  6909. if (monster && !monster->isSummon())
  6910. monster->onThingAppear(*it);
  6911. #endif //SM_SUMMON_ATTACK
  6912. }
  6913. }
  6914.  
  6915. //none-players
  6916. for(it = list.begin(); it != list.end(); ++it) {
  6917. if(!dynamic_cast<Player*>(*it)) {
  6918. (*it)->onThingAppear(thing);
  6919. }
  6920. }
  6921. }
  6922. }
  6923.  
  6924. void Game::sendRemoveThing(Player* player,const Position &pos,const Thing* thing,const unsigned char stackpos /*=1*/ ,const bool autoclose/* =false*/){
  6925. if(!thing)
  6926. return;
  6927.  
  6928. const Item *item = dynamic_cast<const Item*>(thing);
  6929. bool perform_autoclose = false;
  6930. if(autoclose && item){
  6931. const Container *container = dynamic_cast<const Container*>(item);
  6932. if(container)
  6933. perform_autoclose = true;
  6934. }
  6935.  
  6936. if(pos.x == 0xFFFF) {
  6937. if(!player)
  6938. return;
  6939. if(pos.y & 0x40) { //container
  6940. if(!item)
  6941. return;
  6942.  
  6943. unsigned char containerid = pos.y & 0x0F;
  6944. Container* container = player->getContainer(containerid);
  6945. if(!container)
  6946. return;
  6947.  
  6948. //check that item is in the container
  6949. unsigned char slot = container->getSlotNumberByItem(item);
  6950.  
  6951. SpectatorVec list;
  6952. SpectatorVec::iterator it;
  6953.  
  6954. Position centerpos = (container->pos.x == 0xFFFF ? player->pos : container->pos);
  6955. getSpectators(Range(centerpos,2,2,2,2,false), list);
  6956.  
  6957. if(!list.empty()) {
  6958. for(it = list.begin(); it != list.end(); ++it) {
  6959. Player *spectator = dynamic_cast<Player*>(*it);
  6960. if(spectator){
  6961. spectator->onItemRemoveContainer(container,slot);
  6962. if(perform_autoclose){
  6963. spectator->onThingRemove(thing);
  6964. }
  6965. }
  6966. }
  6967. }
  6968. else{
  6969. player->onItemRemoveContainer(container,slot);
  6970. if(perform_autoclose){
  6971. player->onThingRemove(thing);
  6972. }
  6973. }
  6974.  
  6975. }
  6976. else //inventory
  6977. {
  6978. player->removeItemInventory(pos.y);
  6979. if(perform_autoclose){
  6980. player->onThingRemove(thing);
  6981. }
  6982. }
  6983. }
  6984. else //ground
  6985. {
  6986. SpectatorVec list;
  6987. SpectatorVec::iterator it;
  6988.  
  6989. getSpectators(Range(pos,true), list);
  6990.  
  6991. //players
  6992. for(it = list.begin(); it != list.end(); ++it) {
  6993. Player *spectator = dynamic_cast<Player*>(*it);
  6994. if(spectator) {
  6995. spectator->onThingDisappear(thing,stackpos);
  6996.  
  6997. if(perform_autoclose){
  6998. spectator->onThingRemove(thing);
  6999. }
  7000. }
  7001. }
  7002.  
  7003. //none-players
  7004. for(it = list.begin(); it != list.end(); ++it) {
  7005. if(!dynamic_cast<Player*>(*it)) {
  7006. (*it)->onThingDisappear(thing,stackpos);
  7007. }
  7008. }
  7009. }
  7010. }
  7011.  
  7012. void Game::sendUpdateThing(Player* player,const Position &pos,const Thing* thing,const unsigned char stackpos/*=1*/){
  7013.  
  7014. if(pos.x == 0xFFFF) {
  7015. if(!player)
  7016. return;
  7017. if(pos.y & 0x40) { //container
  7018. if(!thing)
  7019. return;
  7020.  
  7021. const Item *item = dynamic_cast<const Item*>(thing);
  7022. if(!item)
  7023. return;
  7024.  
  7025. unsigned char containerid = pos.y & 0x0F;
  7026. Container* container = player->getContainer(containerid);
  7027. if(!container)
  7028. return;
  7029. //check that item is in the container
  7030. unsigned char slot = container->getSlotNumberByItem(item);
  7031.  
  7032. SpectatorVec list;
  7033. SpectatorVec::iterator it;
  7034.  
  7035. Position centerpos = (container->pos.x == 0xFFFF ? player->pos : container->pos);
  7036. getSpectators(Range(centerpos,2,2,2,2,false), list);
  7037.  
  7038. if(!list.empty()) {
  7039. for(it = list.begin(); it != list.end(); ++it) {
  7040. Player *spectator = dynamic_cast<Player*>(*it);
  7041. if(spectator)
  7042. spectator->onItemUpdateContainer(container,item,slot);
  7043. }
  7044. }
  7045. else{
  7046. //never should be here
  7047. std::cout << "Error: sendUpdateThing" << std::endl;
  7048. //player->onItemUpdateContainer(container,item,slot);
  7049. }
  7050.  
  7051. }
  7052. else //inventory
  7053. {
  7054. player->sendInventory(pos.y);
  7055. }
  7056. }
  7057. else //ground
  7058. {
  7059. if(!thing)
  7060. return;
  7061.  
  7062. SpectatorVec list;
  7063. SpectatorVec::iterator it;
  7064.  
  7065. getSpectators(Range(pos,true), list);
  7066.  
  7067. //players
  7068. for(it = list.begin(); it != list.end(); ++it) {
  7069. if(dynamic_cast<Player*>(*it)) {
  7070. (*it)->onThingTransform(thing,stackpos);
  7071. }
  7072. }
  7073.  
  7074. //none-players
  7075. for(it = list.begin(); it != list.end(); ++it) {
  7076. if(!dynamic_cast<Player*>(*it)) {
  7077. (*it)->onThingTransform(thing,stackpos);
  7078. }
  7079. }
  7080. }
  7081. }
  7082.  
  7083. void Game::addThing(Player* player,const Position &pos,Thing* thing)
  7084. {
  7085. if(!thing)
  7086. return;
  7087. Item *item = dynamic_cast<Item*>(thing);
  7088.  
  7089. if(pos.x == 0xFFFF) {
  7090. if(!player || !item)
  7091. return;
  7092.  
  7093. if(pos.y & 0x40) { //container
  7094. unsigned char containerid = pos.y & 0x0F;
  7095. Container* container = player->getContainer(containerid);
  7096. if(!container)
  7097. return;
  7098.  
  7099. container->addItem(item);
  7100. sendAddThing(player,pos,thing);
  7101. }
  7102. else //inventory
  7103. {
  7104. player->addItemInventory(item,pos.y,true);
  7105. sendAddThing(player,pos,thing);
  7106. }
  7107. }
  7108. else //ground
  7109. {
  7110. if(!thing)
  7111. return;
  7112. //Tile *tile = map->getTile(pos.x, pos.y, pos.z);
  7113. Tile *tile = map->getTile(pos);
  7114. if(tile){
  7115. thing->pos = pos;
  7116. if(item && item->isSplash()){
  7117. if(tile->splash){
  7118. int32_t oldstackpos = tile->getThingStackPos(tile->splash);
  7119. Item *oldsplash = tile->splash;
  7120.  
  7121. oldsplash->isRemoved = true;
  7122. FreeThing(oldsplash);
  7123.  
  7124. tile->splash = item;
  7125.  
  7126. sendUpdateThing(NULL, pos, item, oldstackpos);
  7127. }
  7128. else{
  7129. tile->splash = item;
  7130. sendAddThing(NULL,pos,tile->splash);
  7131. }
  7132. }
  7133. else if(item && item->isGroundTile()){
  7134. tile->ground = item;
  7135.  
  7136. SpectatorVec list;
  7137. SpectatorVec::iterator it;
  7138.  
  7139. getSpectators(Range(thing->pos, true), list);
  7140.  
  7141. //players
  7142. for(it = list.begin(); it != list.end(); ++it) {
  7143. if(dynamic_cast<Player*>(*it)) {
  7144. (*it)->onTileUpdated(pos);
  7145. }
  7146. }
  7147.  
  7148. //none-players
  7149. for(it = list.begin(); it != list.end(); ++it) {
  7150. if(!dynamic_cast<Player*>(*it)) {
  7151. (*it)->onTileUpdated(pos);
  7152. }
  7153. }
  7154.  
  7155. //Game::creatureBroadcastTileUpdated(thing->pos);
  7156. }
  7157. else if(item && item->isStackable()){
  7158. Item *topitem = tile->getTopDownItem();
  7159. if(topitem && topitem->getID() == item->getID() &&
  7160. topitem->getItemCountOrSubtype() + item->getItemCountOrSubtype() <= 100){
  7161. topitem->setItemCountOrSubtype(topitem->getItemCountOrSubtype() + item->getItemCountOrSubtype());
  7162. int32_t stackpos = tile->getThingStackPos(topitem);
  7163. sendUpdateThing(NULL,topitem->pos,topitem,stackpos);
  7164. item->pos.x = 0xFFFF;
  7165. FreeThing(item);
  7166. }
  7167. else{
  7168. tile->addThing(thing);
  7169. sendAddThing(player,pos,thing);
  7170. }
  7171. }
  7172. else{
  7173. tile->addThing(thing);
  7174. sendAddThing(player,pos,thing);
  7175. }
  7176. }
  7177. }
  7178. }
  7179.  
  7180. bool Game::removeThing(Player* player,const Position &pos,Thing* thing, bool setRemoved /*= true*/)
  7181. {
  7182. if(!thing)
  7183. return false;
  7184. Item *item = dynamic_cast<Item*>(thing);
  7185.  
  7186. if(pos.x == 0xFFFF) {
  7187. if(!player || !item)
  7188. return false;
  7189.  
  7190. if(pos.y & 0x40) { //container
  7191. unsigned char containerid = pos.y & 0x0F;
  7192. Container* container = player->getContainer(containerid);
  7193. if(!container)
  7194. return false;
  7195.  
  7196. sendRemoveThing(player,pos,thing,0,true);
  7197. if(!container->removeItem(item))
  7198. return false;
  7199.  
  7200. if(player && player->isHoldingContainer(container)) {
  7201. player->updateInventoryWeigth();
  7202. player->sendStats();
  7203. }
  7204. }
  7205. else //inventory
  7206. {
  7207. //sendRemoveThing(player,pos,thing,0,true);
  7208. if(!player->removeItemInventory(pos.y))
  7209. return false;
  7210. player->onThingRemove(thing);
  7211. //player->removeItemInventory(pos.y,true);
  7212. }
  7213. if(setRemoved)
  7214. item->isRemoved = true;
  7215. return true;
  7216. }
  7217. else //ground
  7218. {
  7219. //Tile *tile = map->getTile(pos.x, pos.y, pos.z);
  7220. Tile *tile = map->getTile(pos);
  7221. if(tile){
  7222. unsigned char stackpos = tile->getThingStackPos(thing);
  7223. if(!tile->removeThing(thing))
  7224. return false;
  7225. sendRemoveThing(NULL,pos,thing,stackpos,true);
  7226. }
  7227. else{
  7228. return false;
  7229. }
  7230. if(item && setRemoved){
  7231. item->isRemoved = true;
  7232. }
  7233. return true;
  7234. }
  7235. }
  7236.  
  7237. Position Game::getThingMapPos(Player *player, const Position &pos)
  7238. {
  7239. if(pos.x == 0xFFFF){
  7240. Position dummyPos(0,0,0);
  7241. if(!player)
  7242. return dummyPos;
  7243. if(pos.y & 0x40) { //from container
  7244. unsigned char containerid = pos.y & 0x0F;
  7245. const Container* container = player->getContainer(containerid);
  7246. if(!container){
  7247. return dummyPos;
  7248. }
  7249. while(container->getParent() != NULL) {
  7250. container = container->getParent();
  7251. }
  7252. if(container->pos.x == 0xFFFF)
  7253. return player->pos;
  7254. else
  7255. return container->pos;
  7256. }
  7257. else //from inventory
  7258. {
  7259. return player->pos;
  7260. }
  7261. }
  7262. else{
  7263. return pos;
  7264. }
  7265. }
  7266.  
  7267. Thing* Game::getThing(const Position &pos,unsigned char stack, Player* player /*=NULL*/)
  7268. {
  7269. if(pos.x == 0xFFFF) {
  7270. if(!player)
  7271. return NULL;
  7272. if(pos.y & 0x40) { //from container
  7273. unsigned char containerid = pos.y & 0x0F;
  7274. Container* container = player->getContainer(containerid);
  7275. if(!container)
  7276. return NULL;
  7277.  
  7278. return container->getItem(pos.z);
  7279. }
  7280. else //from inventory
  7281. {
  7282. return player->getItem(pos.y);
  7283. }
  7284. }
  7285. else //from ground
  7286. {
  7287. //Tile *t = getTile(pos.x, pos.y, pos.z);
  7288. Tile *t = map->getTile(pos);
  7289. if(!t)
  7290. return NULL;
  7291.  
  7292. return t->getThingByStackPos(stack);
  7293. }
  7294. }
  7295. int32_t Game::getDepot(Container* c, int32_t e)
  7296. {
  7297. for(int32_t a = 0; a < c->size(); a++)
  7298. {
  7299. Container* x = dynamic_cast<Container*>(dynamic_cast<Item*>(c->getItem(a)));
  7300. Item* i = dynamic_cast<Item*>(c->getItem(a));
  7301. if(i)
  7302. e++;
  7303. if(x)
  7304. e = getDepot(x, e);
  7305. }
  7306. return e;
  7307. }
  7308.  
  7309.  
  7310. #ifdef WOLV_LOAD_NPC
  7311. bool Game::loadNpcs()
  7312. {
  7313. xmlDocPtr doc;
  7314. doc = xmlParseFile((g_config.DATA_DIR + "world/npc.xml").c_str());
  7315. if (!doc)
  7316. return false;
  7317.  
  7318. xmlNodePtr root, npcNode;
  7319. root = xmlDocGetRootElement(doc);
  7320.  
  7321. if (xmlStrcmp(root->name, (const xmlChar*)"npclist"))
  7322. {
  7323. xmlFreeDoc(doc);
  7324. return false;
  7325. }
  7326.  
  7327. npcNode = root->children;
  7328. while (npcNode)
  7329. {
  7330. if (strcmp((const char*) npcNode->name, "npc") == 0)
  7331. {
  7332. std::string name = (const char*)xmlGetProp(npcNode, (const xmlChar *) "name");
  7333. int32_t x = atoi((const char*) xmlGetProp(npcNode, (const xmlChar*) "x"));
  7334. int32_t y = atoi((const char*) xmlGetProp(npcNode, (const xmlChar*) "y"));
  7335. int32_t z = atoi((const char*) xmlGetProp(npcNode, (const xmlChar*) "z"));
  7336.  
  7337. Npc* mynpc = new Npc(name, this);
  7338. mynpc->pos = Position(x, y, z);
  7339.  
  7340. if (!placeCreature(mynpc->pos, mynpc))
  7341. {
  7342. std::cout << "Could not place " << name << "!" << std::endl;
  7343. xmlFreeDoc(doc);
  7344. return false;
  7345. }
  7346.  
  7347. const char* tmp = (const char*)xmlGetProp(npcNode, (const xmlChar*) "dir");
  7348. if (tmp)
  7349. mynpc->setDirection((Direction)atoi(tmp));
  7350. }
  7351. npcNode = npcNode->next;
  7352. }
  7353.  
  7354. xmlFreeDoc(doc);
  7355. return true;
  7356. }
  7357. #endif //WOLV_LOAD_NPC
  7358.  
  7359. #ifdef TLM_SERVER_SAVE
  7360. void Game::serverSave()
  7361. {
  7362. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::serverSave()");
  7363. std::cout << ":: zapis serwera :: " << std::endl;
  7364. timer();
  7365.  
  7366. AutoList<Player>::listiterator it = Player::listPlayer.list.begin();
  7367. while (it != Player::listPlayer.list.end())
  7368. {
  7369. IOPlayer::instance()->savePlayer(it->second);
  7370. ++it;
  7371. }
  7372. std::cout << ":: Gracze [" << timer() << " s]" << std::endl;
  7373. Guilds::Save();
  7374. std::cout << "Gildie [" << timer() << " s]" << std::endl;
  7375. Houses::Save(this);
  7376. std::cout << ":: Domki [" << timer() << " s]" << std::endl;
  7377. loginQueue.save();
  7378. std::cout << ":: Kolejki [" << timer() << " s]" << std::endl;
  7379.  
  7380. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it);
  7381. }
  7382.  
  7383. void Game::autoServerSave()
  7384. {
  7385. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::autoServerSave()");
  7386. serverSave();
  7387. addEvent(makeTask(g_config.getGlobalNumber("autosave", 1)*60000, std::mem_fun(&Game::autoServerSave)));
  7388. }
  7389. #endif //TLM_SERVER_SAVE
  7390.  
  7391.  
  7392. #ifdef ELEM_VIP_LIST
  7393. /*void Game::vipLogin(Player* player)
  7394. {
  7395. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::vipLogin()");
  7396. std::string vipname = player->getName();
  7397.  
  7398. #ifdef _NG_BBK_VIP_SYSTEM__
  7399. std::transform(vipname.begin(), vipname.end(), vipname.begin(), (int32_t(*)(int32_t)) std::tolower);
  7400. #endif //_NG_BBK_VIP_SYSTEM__
  7401.  
  7402. for(AutoList<Creature>::listiterator cit = listCreature.list.begin(); cit != listCreature.list.end(); ++cit)
  7403. {
  7404. Player* player = dynamic_cast<Player*>((*cit).second);
  7405. if (player)
  7406. player->sendVipLogin(vipname);
  7407. }
  7408. }
  7409.  
  7410. void Game::vipLogout(std::string vipname)
  7411. {
  7412. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::vipLogout()");
  7413.  
  7414. #ifdef _NG_BBK_VIP_SYSTEM__
  7415. std::transform(vipname.begin(), vipname.end(), vipname.begin(), (int32_t(*)(int32_t)) std::tolower);
  7416. #endif //_NG_BBK_VIP_SYSTEM__
  7417.  
  7418. for(AutoList<Creature>::listiterator cit = listCreature.list.begin(); cit != listCreature.list.end(); ++cit)
  7419. {
  7420. Player* player = dynamic_cast<Player*>((*cit).second);
  7421. if (player)
  7422. player->sendVipLogout(vipname);
  7423. }
  7424. }*/
  7425.  
  7426. bool Game::isPlayer(std::string name)
  7427. {
  7428. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::isPlayer()");
  7429. extern xmlMutexPtr xmlmutex;
  7430.  
  7431. std::string datadir = g_config.getGlobalString("datadir");
  7432. std::string filenamecheck = datadir + "players/" + name + ".xml";
  7433. std::transform(filenamecheck.begin(),filenamecheck.end(), filenamecheck.begin(), (int32_t(*)(int32_t))tolower);
  7434.  
  7435. xmlDocPtr doc;
  7436. xmlMutexLock(xmlmutex);
  7437. doc = xmlParseFile(filenamecheck.c_str());
  7438.  
  7439. if (doc)
  7440. {
  7441. xmlMutexUnlock(xmlmutex);
  7442. xmlFreeDoc(doc);
  7443. return true;
  7444. }
  7445. else
  7446. {
  7447. xmlMutexUnlock(xmlmutex);
  7448. xmlFreeDoc(doc);
  7449. return false;
  7450. }
  7451. }
  7452. #endif //ELEM_VIP_LIST
  7453.  
  7454. void Game::checkSpell(Player* player, SpeakClasses type, std::string text)
  7455. {
  7456. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkSpell()");
  7457.  
  7458. if (player->isRookie())
  7459. return;
  7460.  
  7461. #ifdef TLM_HOUSE_SYSTEM
  7462. else if (text == "aleta gom") // edit owner
  7463. {
  7464. Tile* tile = getTile(player->pos);
  7465. House* house = tile? tile->getHouse() : NULL;
  7466.  
  7467. if (house && house->getPlayerRights(player->getName()) == HOUSE_OWNER)
  7468. {
  7469. player->sendHouseWindow(house, player->pos, HOUSE_OWNER);
  7470. }
  7471. else
  7472. {
  7473. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7474. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7475. }
  7476. }
  7477. else if (text == "aleta grav") // edit door owners
  7478. {
  7479. bool last = false;
  7480. for (int32_t x = player->pos.x-1; x <= player->pos.x+1 && !last; x++)
  7481. {
  7482. for(int32_t y = player->pos.y-1; y <= player->pos.y+1 && !last; y++)
  7483. {
  7484. Position doorPos(x, y, player->pos.z);
  7485. Tile* tile = getTile(doorPos);
  7486. House* house = tile? tile->getHouse() : NULL;
  7487.  
  7488. if (house && house->getPlayerRights(doorPos, player->getName()) == HOUSE_OWNER)
  7489. {
  7490. Item *item = dynamic_cast<Item*>(tile->getThingByStackPos(tile->getThingCount()-1));
  7491. if (item && Item::items[item->getID()].isDoor)
  7492. {
  7493. player->sendHouseWindow(house, doorPos, HOUSE_DOOROWNER);
  7494. last = true;
  7495. }
  7496. }
  7497. }
  7498. }
  7499. }
  7500. else if (text == "!buyhouse" || text == "!buyhome")
  7501. {
  7502. uint32_t money = player->getMoney();
  7503. bool last = false;
  7504. #ifdef HUCZU_EXHAUSTED
  7505. if(player->houseTicks > 0){
  7506. player->sendCancel("You're exhausted.");
  7507. return;
  7508. }
  7509. else
  7510. player->houseTicks += 5;
  7511. #endif //HUCZU_EXHAUSTED
  7512. int32_t houselevel = g_config.getGlobalNumber("houselevel", 0);
  7513. if(!player->premmium){
  7514. player->sendCancel("You must have a premium to buy house!");
  7515. return;
  7516. }
  7517. if( player->getLevel() < houselevel ){
  7518. std::stringstream textmsg2;
  7519. textmsg2 << " You need level " << houselevel << "+ to buy a house! ";
  7520. player->sendTextMessage(MSG_ADVANCE, textmsg2.str().c_str());
  7521. }
  7522. else{
  7523.  
  7524. for (int32_t x = player->pos.x-1; x <= player->pos.x+1 && !last; x++)
  7525. {
  7526. for(int32_t y = player->pos.y-1; y <= player->pos.y+1 && !last; y++)
  7527. {
  7528. Position doorPos(x, y, player->pos.z);
  7529. Tile* tile = getTile(doorPos);
  7530. House* house = tile? tile->getHouse() : NULL;
  7531. if(house){
  7532. if(house->getPlayerRights(player->getName()) == HOUSE_OWNER){
  7533. player->sendTextMessage(MSG_ADVANCE, "You own this house.");
  7534. return;
  7535. }
  7536. if(house->isBought()){
  7537. player->sendTextMessage(MSG_ADVANCE, "This house already has an owner.");
  7538. return;
  7539. }
  7540. if(house->checkHouseCount(player) >= g_config.getGlobalNumber("maxhouses", 0)){
  7541. std::stringstream textmsg;
  7542. textmsg << " You cant have more than " << g_config.getGlobalNumber("maxhouses", 1) << " houses ";
  7543. player->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  7544. return;
  7545. }
  7546. if(house->getPlayerRights(doorPos, player->getName()) == HOUSE_NONE && !house->isBought() && house->checkHouseCount(player) < g_config.getGlobalNumber("maxhouses", 1))
  7547. {
  7548. Item *item = dynamic_cast<Item*>(tile->getThingByStackPos(tile->getThingCount()-1));
  7549. long price = g_config.getGlobalNumber("priceforsqm", 0) * house->getHouseSQM(house->getName());
  7550.  
  7551. if (item && Item::items[item->getID()].isDoor && price <= money)
  7552. {
  7553. player->substractMoney(price);
  7554. house->setOwner(player->getName());
  7555. house->save();
  7556. player->sendTextMessage(MSG_ADVANCE, "You bought a house.");
  7557. last = true;
  7558. }
  7559. else{
  7560. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7561. player->sendTextMessage(MSG_SMALLINFO, "You dont have enough money to buy this house.");
  7562. }
  7563. }
  7564. }
  7565. }
  7566. }
  7567. }
  7568. }
  7569. else if (text == "aleta sio") // edit guests
  7570. {
  7571. Tile* tile = getTile(player->pos);
  7572. House* house = tile? tile->getHouse() : NULL;
  7573.  
  7574. if (house && house->getPlayerRights(player->getName()) >= HOUSE_SUBOWNER)
  7575. {
  7576. player->sendHouseWindow(house, player->pos, HOUSE_GUEST);
  7577. }
  7578. else
  7579. {
  7580. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7581. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7582. }
  7583. }
  7584. else if (text == "aleta som") // edit subowners
  7585. {
  7586. Tile* tile = getTile(player->pos);
  7587. House* house = tile? tile->getHouse() : NULL;
  7588.  
  7589. if (house && house->getPlayerRights(player->getName()) == HOUSE_OWNER)
  7590. {
  7591. player->sendHouseWindow(house, player->pos, HOUSE_SUBOWNER);
  7592. }
  7593. else
  7594. {
  7595. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7596. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7597. }
  7598. }
  7599. else if (text == "alana sio") // kick me
  7600. {
  7601. Tile* tile = getTile(player->pos);
  7602. House* house = tile? tile->getHouse() : NULL;
  7603.  
  7604. if (house)
  7605. {
  7606. teleport(player, house->getFrontDoor());
  7607. player->sendMagicEffect(player->pos, NM_ME_ENERGY_AREA);
  7608. }
  7609. else
  7610. {
  7611. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7612. player->sendTextMessage(MSG_SMALLINFO, "You are not in a house.");
  7613. }
  7614. }
  7615. else if (text.substr(0, 11) == "alana sio \"") // kick someone
  7616. {
  7617. Creature* c = getCreatureByName(text.substr(11).c_str());
  7618. Player *target = c? dynamic_cast<Player*>(c) : NULL;
  7619.  
  7620. if (target)
  7621. {
  7622. Tile* tile = getTile(player->pos);
  7623. Tile* targetTile = getTile(target->pos);
  7624. House* house = tile? tile->getHouse() : NULL;
  7625. House* targetHouse = targetTile? targetTile->getHouse() : NULL;
  7626.  
  7627. if (house && targetHouse && house == targetHouse &&
  7628. house->getPlayerRights(player->getName()) >= HOUSE_SUBOWNER)
  7629. {
  7630. Position pos = house->getFrontDoor();
  7631. if (pos.x != 0xFFFF && pos.y != 0xFFFF && pos.z != 0xFF)
  7632. {
  7633. teleport(target, pos);
  7634. player->sendMagicEffect(target->pos, NM_ME_ENERGY_AREA);
  7635. }
  7636. else
  7637. {
  7638. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7639. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7640. }
  7641. }
  7642. else
  7643. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7644. }
  7645. else
  7646. {
  7647. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7648. player->sendTextMessage(MSG_SMALLINFO, "This player does not exist.");
  7649. }
  7650. }
  7651. #endif //TLM_HOUSE_SYSTEM
  7652.  
  7653. #ifdef TR_SUMMONS
  7654. else if (text.substr(0, 11) == "utevo res \"" &&
  7655. (!g_config.LEARN_SPELLS || player->knowsSpell("utevo res")))
  7656. {
  7657. if (player->vocation == VOCATION_DRUID || player->vocation == VOCATION_SORCERER ||
  7658. (g_config.SUMMONS_ALL_VOC && player->vocation != VOCATION_NONE))
  7659. {
  7660. std::string name = text.substr(11);
  7661. int32_t reqMana = Summons::getRequiredMana(name);
  7662. Tile* tile = getTile(player->pos);
  7663.  
  7664. if (!tile)
  7665. {
  7666. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7667. player->sendCancel("Sorry, not possible.");
  7668. }
  7669. else if (reqMana < 0)
  7670. {
  7671. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7672. player->sendCancel("You cannot summon this creature.");
  7673. }
  7674. else if (tile->isPz())
  7675. {
  7676. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7677. player->sendCancel("You cannot summon creatures in protection zone.");
  7678. }
  7679. #ifdef YUR_PVP_ARENA
  7680. else if (tile->isPvpArena())
  7681. {
  7682. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7683. player->sendCancel("You cannot summon creatures on arena.");
  7684. }
  7685. #endif //YUR_PVP_ARENA
  7686. else if (player->getSummonCount() >= g_config.MAX_SUMMONS)
  7687. {
  7688. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7689. player->sendCancel("You cannot have more summons.");
  7690. }
  7691. else if (player->getMana() < reqMana)
  7692. {
  7693. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7694. player->sendCancel("Not enough mana.");
  7695. }
  7696. else if (!placeSummon(player, name))
  7697. {
  7698. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7699. player->sendCancel("Not enough room");
  7700. }
  7701. else
  7702. {
  7703. player->mana -= reqMana;
  7704. player->addManaSpent(reqMana);
  7705. }
  7706. }
  7707. }
  7708. #endif //TR_SUMMONS
  7709.  
  7710. /*
  7711. #ifdef HUCZU_FIX
  7712. else if (text == "exevo flam sio" &&
  7713. (!g_config.LEARN_SPELLS || player->knowsSpell("exevo flam sio")))
  7714. {
  7715. const int32_t REQ_MANA = 200;
  7716.  
  7717. if (player->mana < REQ_MANA)
  7718. {
  7719. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7720. player->sendTextMessage(MSG_SMALLINFO, "Not enough mana.");
  7721. }
  7722.  
  7723. else if (player->maglevel < 15)
  7724. {
  7725. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7726. player->sendTextMessage(MSG_SMALLINFO, "You don't have the required magic level.");
  7727. }
  7728.  
  7729. else if (player->exhaustedTicks >= 1000 && player->access < g_config.ACCESS_PROTECT)
  7730. {
  7731. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7732. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  7733. }
  7734.  
  7735. else if (player->flamTicks != 0 && player->access < g_config.ACCESS_PROTECT)
  7736. {
  7737. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7738. player->sendTextMessage(MSG_SMALLINFO, "Not ready yet.");
  7739. }
  7740.  
  7741. else
  7742. {
  7743. player->flamBool = true;
  7744. player->exhaustedTicks = 2*1000;
  7745. player->sendMagicEffect(player->pos, NM_ME_MAGIC_BLOOD);
  7746. }
  7747. }
  7748. #endif //HUCZU_FIX
  7749. */
  7750.  
  7751. else if (text.substr(0,7) == "exiva \"" &&
  7752. (!g_config.LEARN_SPELLS || player->knowsSpell("exiva")))
  7753. {
  7754. std::string name = text.substr(7);
  7755. Creature *c = getCreatureByName(name);
  7756. if (dynamic_cast<Player*>(c))
  7757. {
  7758. if(player->mana >= 20)
  7759. {
  7760. player->mana -= 20;
  7761. player->addManaSpent(20);
  7762. }
  7763. else if (player->exhaustedTicks >= 1000 && player->access < g_config.ACCESS_PROTECT)
  7764. {
  7765. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7766. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  7767. }
  7768. else
  7769. {
  7770. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7771. player->sendTextMessage(MSG_SMALLINFO, "Not enough mana.");
  7772. return;
  7773. }
  7774.  
  7775.  
  7776. int32_t x = c->pos.x - player->pos.x;
  7777. int32_t y = c->pos.y - player->pos.y;
  7778. int32_t z = c->pos.z - player->pos.z;
  7779. std::stringstream position;
  7780. position << name;
  7781.  
  7782. if(c->access < 3) {
  7783. if((x > 96 && y > 48) || (x > 48 && y > 94) || (x > 74 && y > 74))
  7784. position << " is very far to the south-east.";
  7785. else if((x > 96 && y < -48) || (x > 48 && y < -96) || (x > 74 && y < -74))
  7786. position << " is very far to the north-east.";
  7787. else if((x < -96 && y > 48) || (x < -48 && y > 96) || (x < -74 && y > 74))
  7788. position << " is very far to the south-west.";
  7789. else if((x < -96 && y < -48) || (x < -48 && y < -96) || (x < -74 && y < -74))
  7790. position << " is very far to the north-west.";
  7791.  
  7792. else if((x > 48 && y > 24) || (x > 24 && y > 48) || (x > 36 && y > 36))
  7793. position << " is far to the south-east.";
  7794. else if((x > 48 && y < -24) || (x > 24 && y < -48) || (x > 36 && y < -36))
  7795. position << " is far to the north-east.";
  7796. else if((x < -48 && y > 24) || (x < -24 && y > 48) || (x < -36 && y > 36))
  7797. position << " is far to the south-west.";
  7798. else if((x < -48 && y < -24) || (x < -24 && y < -48) || (x < -36 && y < -36))
  7799. position << " is far to the north-west.";
  7800.  
  7801. else if((x > 6 && y > 12 && z > 0) || (x > 12 && y > 6 && z > 0) || (x > 9 && y > 9 && z > 0))
  7802. position << " is on a lower lvl to the south-east.";
  7803. else if((x > 6 && y < -12 && z > 0) || (x > 12 && y < -6 && z > 0) || (x > 9 && y < -9 && z > 0))
  7804. position << " is on a lower lvl to the north-east.";
  7805. else if((x < -6 && y > 12 && z > 0) || (x < -12 && y > 6 && z > 0) || (x < -9 && y > 9 && z > 0))
  7806. position << " is on a lower lvl to the south-west.";
  7807. else if((x < -6 && y < -12 && z > 0) || (x < -12 && y < -6 && z > 0) || (x < -9 && y < -9 && z > 0))
  7808. position << " is on a lower lvl to the north-west.";
  7809.  
  7810. else if((x > 6 && y > 12 && z < 0) || (x > 12 && y > 6 && z < 0) || (x > 9 && y > 9 && z < 0))
  7811. position << " is on a higher lvl to the south-east.";
  7812. else if((x > 6 && y < -12 && z < 0) || (x > 12 && y < -6 && z < 0) || (x > 9 && y < -9 && z < 0))
  7813. position << " is on a higher lvl to the north-east.";
  7814. else if((x < -6 && y > 12 && z < 0) || (x < -12 && y > 6 && z < 0) || (x < -9 && y > 9 && z < 0))
  7815. position << " is on a higher lvl to the south-west.";
  7816. else if((x < -6 && y < -12 && z < 0) || (x < -12 && y < -6 && z < 0) || (x < -9 && y < -9 && z < 0))
  7817. position << " is on a higher lvl to the north-west.";
  7818.  
  7819. else if((x > 6 && y > 12 && z == 0) || (x > 12 && y > 6 && z == 0) || (x > 9 && y > 9 && z == 0))
  7820. position << " is to the south-east.";
  7821. else if((x > 6 && y < -12 && z == 0) || (x > 12 && y < -6 && z == 0) || (x > 9 && y < -9 && z == 0))
  7822. position << " is to the north-east.";
  7823. else if((x < -6 && y > 12 && z == 0) || (x < -12 && y > 6 && z == 0) || (x < -9 && y > 9 && z == 0))
  7824. position << " is to the south-west.";
  7825. else if((x < -6 && y < -12 && z == 0) || (x < -12 && y < -6 && z == 0) || (x < -9 && y < -9 && z == 0))
  7826. position << " is to the north-west.";
  7827.  
  7828. else if(x > 74)
  7829. position << " is very far to the east.";
  7830. else if(x < -74)
  7831. position << " is very far to the west.";
  7832. else if(y > 74)
  7833. position << " is very far to the south.";
  7834. else if(y < -74)
  7835. position << " is very far to the north.";
  7836.  
  7837. else if(x > 36)
  7838. position << " is far to the east.";
  7839. else if(x < -36)
  7840. position << " is far to the west.";
  7841. else if(y > 36)
  7842. position << " is far to the south.";
  7843. else if(y < -36)
  7844. position << " is far to the north.";
  7845.  
  7846. else if(x > 3 && z < 0)
  7847. position << " is on a higher lvl to the east.";
  7848. else if(x < -3 && z < 0)
  7849. position << " is on a higher lvl to the west.";
  7850. else if(y > 3 && z < 0)
  7851. position << " is on a higher lvl to the south.";
  7852. else if(y < -3 && z < 0)
  7853. position << " is on a higher lvl to the north.";
  7854.  
  7855. else if(x > 3 && z > 0)
  7856. position << " is on a lower lvl to the east.";
  7857. else if(x < -3 && z > 0)
  7858. position << " is on a lower lvl to the west.";
  7859. else if(y > 3 && z > 0)
  7860. position << " is on a lower lvl to the south.";
  7861. else if(y < -3 && z > 0)
  7862. position << " is on a lower lvl to the north.";
  7863.  
  7864. else if(x > 3 && z == 0)
  7865. position << " is to the east.";
  7866. else if(x < -3 && z == 0)
  7867. position << " is to the west.";
  7868. else if(y > 3 && z == 0)
  7869. position << " is to the south.";
  7870. else if(y < -3 && z == 0)
  7871. position << " is to the north.";
  7872.  
  7873. else if(x < 4 && y < 4 && z > 0)
  7874. position << " is below you.";
  7875. else if(x < 4 && y < 4 && z < 0)
  7876. position << " is above you.";
  7877. else
  7878. position << " is just beside you.";
  7879.  
  7880. player->sendTextMessage(MSG_INFO, position.str().c_str());
  7881. player->sendMagicEffect(player->pos, NM_ME_MAGIC_ENERGIE);
  7882. }else{
  7883. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7884. player->sendTextMessage(MSG_SMALLINFO, "Srry, you cant exiva GM's");
  7885. }
  7886. }else
  7887. player->sendTextMessage(MSG_SMALLINFO, "This player is not online.");
  7888. }
  7889.  
  7890. else if (text == "exani tera" &&
  7891. (!g_config.LEARN_SPELLS || player->knowsSpell("exani tera")))
  7892. {
  7893. const int32_t REQ_MANA = 20;
  7894. Tile* tile = getTile(player->pos);
  7895.  
  7896. if (!(tile && (tile->ground->getID() == ITEM_ROPE_SPOT1 || tile->ground->getID() == ITEM_ROPE_SPOT2)))
  7897. {
  7898. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7899. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7900. }
  7901. else if (player->mana < REQ_MANA)
  7902. {
  7903. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7904. player->sendTextMessage(MSG_SMALLINFO, "Not enough mana.");
  7905. }
  7906. else if (player->maglevel < 0)
  7907. {
  7908. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7909. player->sendTextMessage(MSG_SMALLINFO, "You don't have the required magic level.");
  7910. }
  7911. else if (player->exhaustedTicks >= 1000 && player->access < g_config.ACCESS_PROTECT)
  7912. {
  7913. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7914. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  7915. }
  7916. else
  7917. {
  7918. teleport(player, Position(player->pos.x, player->pos.y+1, player->pos.z-1));
  7919. player->sendMagicEffect(player->pos, NM_ME_ENERGY_AREA);
  7920.  
  7921. if (player->access < g_config.ACCESS_PROTECT)
  7922. {
  7923. player->mana -= REQ_MANA;
  7924. player->addManaSpent(REQ_MANA);
  7925. }
  7926. }
  7927. }
  7928. }
  7929.  
  7930. #ifdef TR_SUMMONS
  7931. bool Game::placeSummon(Player* p, const std::string& name)
  7932. {
  7933. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::placeSummon()");
  7934. Monster* monster = Monster::createMonster(name, this);
  7935.  
  7936. if(!monster)
  7937. return false;
  7938.  
  7939. Position pos = p->pos;
  7940. switch (p->direction)
  7941. {
  7942. case NORTH: pos.y--; break;
  7943. case SOUTH: pos.y++; break;
  7944. case EAST: pos.x++; break;
  7945. case WEST: pos.x--; break;
  7946. }
  7947.  
  7948. Tile* tile = getTile(pos);
  7949. #ifdef YUR_PVP_ARENA
  7950. if (!tile || tile->isPz() || tile->isPvpArena() || !placeCreature(pos, monster))
  7951. #else
  7952. if (!tile || tile->isPz() || !placeCreature(pos, monster))
  7953. #endif //YUR_PVP_ARENA
  7954. {
  7955. delete monster;
  7956. return false;
  7957. }
  7958. else
  7959. {
  7960. p->addSummon(monster);
  7961. return true;
  7962. }
  7963. }
  7964. #endif //TR_SUMMONS
  7965.  
  7966.  
  7967. #ifdef TRS_GM_INVISIBLE
  7968. void Game::creatureBroadcastTileUpdated(const Position& pos)
  7969. {
  7970. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureBroadcastTileUpdated()");
  7971. SpectatorVec list;
  7972. SpectatorVec::iterator it;
  7973. getSpectators(Range(pos, true), list);
  7974.  
  7975. //players
  7976. for(it = list.begin(); it != list.end(); ++it) {
  7977. if(dynamic_cast<Player*>(*it)) {
  7978. (*it)->onTileUpdated(pos);
  7979. }
  7980. }
  7981.  
  7982. //none-players
  7983. for(it = list.begin(); it != list.end(); ++it) {
  7984. if(!dynamic_cast<Player*>(*it)) {
  7985. (*it)->onTileUpdated(pos);
  7986. }
  7987. }
  7988. }
  7989. #endif //TRS_GM_INVISIBLE
  7990.  
  7991.  
  7992. #ifdef HUCZU_SKULLS
  7993. void Game::Skull(Player* player)
  7994. {
  7995. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::Skull()");
  7996. if (player)
  7997. {
  7998. SpectatorVec list;
  7999. SpectatorVec::iterator it;
  8000. getSpectators(Range(player->pos, true), list);
  8001.  
  8002. for(it = list.begin(); it != list.end(); ++it)
  8003. {
  8004. Player* spectator = dynamic_cast<Player*>(*it);
  8005. if(spectator)
  8006. if(player->skullType == SKULL_NONE ||
  8007. player->skullType == SKULL_WHITE ||
  8008. player->skullType == SKULL_RED ||
  8009. player->skullType == SKULL_YELLOW && player->isYellowTo(spectator))
  8010. spectator->onSkull(player);
  8011. }
  8012. }
  8013. }
  8014.  
  8015. void Game::onPvP(Creature* creature, Creature* attacked, bool murder)
  8016. {
  8017. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::onPvP()");
  8018. if (creature && creature->getMaster())
  8019. creature = creature->getMaster(); // pk-ing with summons fix
  8020.  
  8021. Player* player = dynamic_cast<Player*>(creature);
  8022. Player* attackedPlayer = dynamic_cast<Player*>(attacked);
  8023.  
  8024. if (player == attackedPlayer)
  8025. return;
  8026. if(!player || !attackedPlayer)
  8027. return;
  8028. if (player && player->access >= g_config.ACCESS_PROTECT || attackedPlayer && attackedPlayer->access >= g_config.ACCESS_PROTECT)
  8029. return;
  8030. if (player->party != 0 && attackedPlayer->party != 0 && player->party == attackedPlayer->party)
  8031. return;
  8032.  
  8033. Tile *p1 = map->getTile(player->pos), *p2 = map->getTile(attackedPlayer->pos);
  8034. if (p1->isPvpArena() && p2->isPvpArena()){
  8035. player->pzLocked = false;
  8036. attackedPlayer->pzLocked = false;
  8037. return;
  8038. }
  8039.  
  8040.  
  8041. player->pzLocked = true;
  8042.  
  8043. if (!murder)
  8044. {
  8045. if(!player->hasAttacked(attackedPlayer)){
  8046. player->attackedPlayers.push_back(attackedPlayer);
  8047. }
  8048.  
  8049. if (attackedPlayer->skullType == SKULL_NONE || attackedPlayer->skullType == SKULL_YELLOW && !attackedPlayer->isYellowTo(player))
  8050. {
  8051. if (player->skullType != SKULL_RED && player->skullType != SKULL_WHITE)
  8052. {
  8053. player->skullType = SKULL_WHITE;
  8054. Skull(player);
  8055. }
  8056. }
  8057.  
  8058. else if(attackedPlayer->skullType == SKULL_WHITE || attackedPlayer->skullType == SKULL_RED)
  8059. {
  8060. if(player->skullType == SKULL_NONE && !player->isYellowTo(attackedPlayer))//si no tiene skull y no es yellow, tenemos que ponerle yellow.
  8061. {
  8062. if(!attackedPlayer->hasAttacked(player))
  8063. {
  8064. player->skullType = SKULL_YELLOW;
  8065. attackedPlayer->hasAsYellow.push_back(player);
  8066. attackedPlayer->onSkull(player);
  8067. }
  8068. }
  8069. }
  8070. if(player->inFightTicks < (int32_t)g_config.PZ_LOCKED)
  8071. player->inFightTicks = (int32_t)g_config.PZ_LOCKED;
  8072. if(player->skullTicks < (int32_t)g_config.PZ_LOCKED)
  8073. player->skullTicks = (int32_t)g_config.PZ_LOCKED;
  8074.  
  8075. }
  8076. else // murder
  8077. {
  8078. if (attackedPlayer->skullType == SKULL_NONE || (attackedPlayer->skullType == SKULL_YELLOW && !player->isYellowTo(attackedPlayer))) //Ofiara nie miala skulla oraz miala yellow ale nie na graczu ktora go zabil.
  8079. {
  8080. player->skullKills++;
  8081. std::string justice(std::string("Warning! The murder of ") + attackedPlayer->getName() + " was not justified!");
  8082. player->sendTextMessage(MSG_RED_INFO, justice.c_str());
  8083.  
  8084. if (player->skullKills >= g_config.BAN_UNJUST)
  8085. {
  8086. banPlayer(player, "Excessive unjustifed player killing", "AccountBan", "Zagan Square 2.3 2011 (Braviera)", false);
  8087. }
  8088.  
  8089. if (player->skullKills >= g_config.RED_UNJUST)
  8090. {
  8091. player->skullType = SKULL_RED;
  8092. if(player->skullTicks < g_config.RED_TIME)
  8093. player->skullTicks = g_config.RED_TIME;
  8094. if(player->inFightTicks < g_config.WHITE_TIME)
  8095. player->inFightTicks = g_config.WHITE_TIME;
  8096. Skull(player);
  8097. }
  8098. else
  8099. {
  8100. player->skullType = SKULL_WHITE;
  8101. if(player->skullTicks < g_config.WHITE_TIME)
  8102. player->skullTicks = g_config.WHITE_TIME;
  8103. if(player->inFightTicks < g_config.WHITE_TIME)
  8104. player->inFightTicks = g_config.WHITE_TIME;
  8105. Skull(player);
  8106. }
  8107. }
  8108.  
  8109. else if (attackedPlayer->skullType == SKULL_RED)//victim had red skull..(fair kill)
  8110. {
  8111. if(player->inFightTicks < g_config.WHITE_TIME)
  8112. player->inFightTicks = g_config.WHITE_TIME;//not giving him a skull.. just setting the murder time.
  8113. }
  8114.  
  8115. else if (attackedPlayer->skullType == SKULL_WHITE) //victim had white skull.. (fair kill)
  8116. {
  8117. attackedPlayer->skullType = SKULL_NONE;
  8118. attackedPlayer->skullTicks = 0;
  8119. Skull(attackedPlayer);
  8120. if(player->inFightTicks < g_config.WHITE_TIME)
  8121. player->inFightTicks = g_config.WHITE_TIME;//not giving him a skull.. just setting the murder time.
  8122. }
  8123.  
  8124. else if (attackedPlayer->skullType == SKULL_YELLOW /*&& attackedPlayer->isYellowTo(player)*/)//el que murio era yellow skull para el que lo mato.
  8125. {
  8126. attackedPlayer->skullType = SKULL_NONE;
  8127. attackedPlayer->skullTicks = 0;
  8128. attackedPlayer->inFightTicks = 0;
  8129. Skull(attackedPlayer);
  8130. if(player->inFightTicks < g_config.WHITE_TIME)
  8131. player->inFightTicks = g_config.WHITE_TIME;
  8132. }
  8133. //attackedPlayer->clearAttacked();//czyszczenie listy zaatakowanych
  8134. //player->removeFromYellowList(attackedPlayer);//usuwanie gracza z Yellow skull z listy atakowanych z ys
  8135. //attackedPlayer->removeFromYellowList(player);
  8136. }
  8137. }
  8138.  
  8139. void Game::LeaveParty(Player *player)
  8140. {
  8141. int32_t members = 0;
  8142. std::stringstream bericht1;
  8143. bericht1 << player->getName() << " has left the party";
  8144. if(player->getID() == player->party)
  8145. {
  8146. disbandParty(player->party);
  8147. return;
  8148. }
  8149. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  8150. {
  8151. if((*it).second->party == player->party)
  8152. {
  8153. members++;
  8154. if((*it).second->getID() != player->getID())
  8155. (*it).second->sendTextMessage(MSG_INFO, bericht1.str().c_str());
  8156. (*it).second->onPartyIcons(player, 0, false, true);
  8157. player->onPartyIcons((*it).second, 0, false, true);
  8158. }
  8159. }
  8160. if(members <= 2)
  8161. {
  8162. disbandParty(player->party);
  8163. return;
  8164. }
  8165. player->sendTextMessage(MSG_INFO, "You have left the party.");
  8166. player->party = 0;
  8167. }
  8168.  
  8169. void Game::disbandParty(uint32_t partyID)
  8170. {
  8171. for(AutoList<Player>::listiterator cit = Player::listPlayer.list.begin(); cit != Player::listPlayer.list.end(); ++cit)
  8172. {
  8173. if((*cit).second->party == partyID)
  8174. {
  8175. (*cit).second->party = 0;
  8176. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  8177. {
  8178. (*cit).second->onPartyIcons((*it).second, 0, false, true);
  8179. if((*it).second->skullType == SKULL_NONE ||
  8180. (*it).second->skullType == SKULL_WHITE ||
  8181. (*it).second->skullType == SKULL_RED ||
  8182. (*it).second->skullType == SKULL_YELLOW &&
  8183. (*it).second->isYellowTo((*cit).second))
  8184. (*cit).second->onSkull((*it).second);
  8185. }
  8186. (*cit).second->sendTextMessage(MSG_INFO, "Your party has been disbanded.");
  8187. }
  8188. }
  8189. }
  8190. void Game::checkSkullTime(Player* player)
  8191. {
  8192. if(player->skullType == SKULL_NONE)//just in case
  8193. return;
  8194.  
  8195. if(player->skullTicks < player->inFightTicks)
  8196. player->skullTicks = player->inFightTicks;
  8197.  
  8198. if(player->skullType != SKULL_RED && player->skullTicks > player->inFightTicks) //we don't want to do that if the player has a red skull...
  8199. player->inFightTicks = player->skullTicks;
  8200.  
  8201. }
  8202. #endif //HUCZU_SKULLS
  8203.  
  8204.  
  8205.  
  8206. #ifdef SD_BURST_ARROW
  8207. class MagicEffectAreaNoExhaustionClass: public MagicEffectAreaClass {
  8208. public:
  8209. bool causeExhaustion(bool hasTarget) const { return false; }
  8210. };
  8211.  
  8212. void Game::burstArrow(Creature* c, const Position& pos)
  8213. {
  8214. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::burstArrow()");
  8215. std::vector<unsigned char> col;
  8216. MagicEffectAreaNoExhaustionClass runeAreaSpell;
  8217.  
  8218. Player* player = dynamic_cast<Player*>(c);
  8219.  
  8220. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8221. runeAreaSpell.animationEffect = NM_ANI_BURSTARROW;
  8222. runeAreaSpell.hitEffect = NM_ME_EXPLOSION_DAMAGE;
  8223. runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8224. runeAreaSpell.animationColor = 198; //DAMAGE_FIRE;
  8225. runeAreaSpell.drawblood = true;
  8226. runeAreaSpell.offensive = true;
  8227.  
  8228. /* Area of Spell */
  8229. col.push_back(1);
  8230. col.push_back(1);
  8231. col.push_back(1);
  8232. runeAreaSpell.areaVec.push_back(col);
  8233. col.clear();
  8234. col.push_back(1);
  8235. col.push_back(1);
  8236. col.push_back(1);
  8237. runeAreaSpell.areaVec.push_back(col);
  8238. col.clear();
  8239. col.push_back(1);
  8240. col.push_back(1);
  8241. col.push_back(1);
  8242. runeAreaSpell.areaVec.push_back(col);
  8243.  
  8244. /* hard no ? */
  8245. runeAreaSpell.direction = 1;
  8246.  
  8247. if (player->vocation == VOCATION_KNIGHT) {
  8248. runeAreaSpell.minDamage = int32_t(((c->level*g_config.KNIGHT_BURST_DMG_LVL)+(c->maglevel*g_config.KNIGHT_BURST_DMG_MLVL))*g_config.KNIGHT_BURST_DMG_LO);
  8249. runeAreaSpell.maxDamage = int32_t(((c->level*g_config.KNIGHT_BURST_DMG_LVL)+(c->maglevel*g_config.KNIGHT_BURST_DMG_MLVL))*g_config.KNIGHT_BURST_DMG_HI);
  8250. }
  8251.  
  8252. if (player->vocation == VOCATION_PALADIN) {
  8253. runeAreaSpell.minDamage = int32_t(((c->level*g_config.PALADIN_BURST_DMG_LVL)+(c->maglevel*g_config.PALADIN_BURST_DMG_MLVL))*g_config.PALADIN_BURST_DMG_LO);
  8254. runeAreaSpell.maxDamage = int32_t(((c->level*g_config.PALADIN_BURST_DMG_LVL)+(c->maglevel*g_config.PALADIN_BURST_DMG_MLVL))*g_config.PALADIN_BURST_DMG_HI);
  8255. }
  8256.  
  8257. if (player->vocation == VOCATION_DRUID) {
  8258. runeAreaSpell.minDamage = int32_t(((c->level*g_config.DRUID_BURST_DMG_LVL)+(c->maglevel*g_config.DRUID_BURST_DMG_MLVL))*g_config.DRUID_BURST_DMG_LO);
  8259. runeAreaSpell.maxDamage = int32_t(((c->level*g_config.DRUID_BURST_DMG_LVL)+(c->maglevel*g_config.DRUID_BURST_DMG_MLVL))*g_config.DRUID_BURST_DMG_HI);
  8260. }
  8261.  
  8262. if (player->vocation == VOCATION_SORCERER) {
  8263. runeAreaSpell.minDamage = int32_t(((c->level*g_config.SORCERER_BURST_DMG_LVL)+(c->maglevel*g_config.SORCERER_BURST_DMG_MLVL))*g_config.SORCERER_BURST_DMG_LO);
  8264. runeAreaSpell.maxDamage = int32_t(((c->level*g_config.SORCERER_BURST_DMG_LVL)+(c->maglevel*g_config.SORCERER_BURST_DMG_MLVL))*g_config.SORCERER_BURST_DMG_HI);
  8265. }
  8266.  
  8267. creatureThrowRune(c, pos, runeAreaSpell);
  8268. }
  8269. #endif //SD_BURST_ARROW
  8270.  
  8271.  
  8272. #ifdef YUR_SHUTDOWN
  8273. void Game::sheduleShutdown(int32_t minutes)
  8274. {
  8275. if (minutes > 0)
  8276. checkShutdown(minutes);
  8277. }
  8278.  
  8279. void Game::checkShutdown(int32_t minutes)
  8280. {
  8281. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkShutdown()");
  8282. if (minutes == 0)
  8283. {
  8284. setGameState(GAME_STATE_CLOSED);
  8285. while (!Player::listPlayer.list.empty())
  8286. Player::listPlayer.list.begin()->second->kickPlayer();
  8287.  
  8288. serverSave();
  8289. std::cout << "==| shutdown..." << std::endl;
  8290. //setGameState(GAME_STATE_SHUTDOWN);
  8291. OTSYS_SLEEP(1000);
  8292. exit(1);
  8293. }
  8294. else
  8295. {
  8296. std::stringstream msg;
  8297. msg << "Server going to shutdown in " << minutes << (minutes>1? " minutes. \n Please logout." : " minute. \n Please logout.") << std::ends;
  8298.  
  8299. AutoList<Player>::listiterator it = Player::listPlayer.list.begin();
  8300. while (it != Player::listPlayer.list.end())
  8301. {
  8302. (*it).second->sendTextMessage(MSG_RED_INFO, msg.str().c_str());
  8303. ++it;
  8304. }
  8305.  
  8306. addEvent(makeTask(60000, boost::bind(&Game::checkShutdown, this, minutes - 1)));
  8307. }
  8308. }
  8309. #endif //YUR_SHUTDOWN
  8310.  
  8311.  
  8312. #ifdef YUR_CMD_EXT
  8313. void Game::setMaxPlayers(uint32_t newmax)
  8314. {
  8315. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::setMaxPlayers()");
  8316. max_players = newmax;
  8317. Status::instance()->playersmax = newmax;
  8318. }
  8319. #endif //YUR_CMD_EXT
  8320.  
  8321. long Game::cleanMap()
  8322. {
  8323. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::cleanMap()");
  8324. return map->clean();
  8325. }
  8326.  
  8327. long Game::beforeClean()
  8328. {
  8329. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it) {
  8330. it->second->sendTextMessage(MSG_RED_INFO, "1 minute to clean. Get your things from floor now!");
  8331. }
  8332. addEvent(makeTask(60000, std::mem_fun(&Game::secondsToClean)));
  8333. }
  8334. long Game::beforeCleanTrzy()
  8335. {
  8336. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it) {
  8337. it->second->sendTextMessage(MSG_RED_INFO, "Warning! Clean in 3 minutes.");
  8338. }
  8339. addEvent(makeTask(60000, std::mem_fun(&Game::beforeCleanDwa)));
  8340. }
  8341. long Game::beforeCleanDwa()
  8342. {
  8343. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it) {
  8344. it->second->sendTextMessage(MSG_RED_INFO, "Warning! Clean in 2 minutes.");
  8345. }
  8346. addEvent(makeTask(60000, std::mem_fun(&Game::beforeClean)));
  8347. }
  8348. void Game::secondsToClean()
  8349. {
  8350. autocleanMap(5);
  8351. }
  8352. void Game::autocleanMap(int32_t seconds)
  8353. {
  8354. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::autocleanMap()");
  8355. if (seconds == 0)
  8356. {
  8357. std::cout << ":: auto clean... ";
  8358. timer();
  8359. long count = cleanMap();
  8360. double sec = timer();
  8361.  
  8362. std::stringstream msg;
  8363. msg << "Clean completed. Collected " << count << (count==1? " item." : " items.") << std::ends;
  8364. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  8365. if(dynamic_cast<Player*>(it->second))
  8366. (*it).second->sendTextMessage(MSG_RED_INFO, msg.str().c_str());
  8367. }
  8368.  
  8369. std::cout << "ok (" << timer() << "s)" << std::endl;
  8370. addEvent(makeTask((g_config.getGlobalNumber("autoclean", 2))*60000, std::mem_fun(&Game::beforeCleanTrzy)));
  8371. }
  8372. else
  8373. {
  8374. std::stringstream msg;
  8375. msg << "Clean in " << seconds << std::ends;
  8376.  
  8377. AutoList<Player>::listiterator it = Player::listPlayer.list.begin();
  8378. while (it != Player::listPlayer.list.end())
  8379. {
  8380. (*it).second->sendTextMessage(MSG_RED_INFO, msg.str().c_str());
  8381. ++it;
  8382. }
  8383.  
  8384. addEvent(makeTask(8000, boost::bind(&Game::autocleanMap, this, seconds - 1)));
  8385. }
  8386. }
  8387.  
  8388.  
  8389. #ifdef CVS_DAY_CYCLE
  8390. void Game::creatureChangeLight(Player* player, int32_t time, unsigned char lightlevel, unsigned char lightcolor)
  8391. {
  8392. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureChangeLight()");
  8393.  
  8394. player->setLightLevel(lightlevel, lightcolor);
  8395. SpectatorVec list;
  8396. getSpectators(Range(player->pos), list);
  8397.  
  8398. for (SpectatorVec::iterator iter = list.begin(); iter != list.end(); ++iter)
  8399. {
  8400. Player* spectator = dynamic_cast<Player*>(*iter);
  8401. if (spectator)
  8402. spectator->sendPlayerLightLevel(player);
  8403. }
  8404. }
  8405.  
  8406. void Game::checkLight(int32_t t)
  8407. {
  8408. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkLight()");
  8409. addEvent(makeTask(10000, boost::bind(&Game::checkLight, this, 10000)));
  8410.  
  8411. light_hour = light_hour + light_hour_delta;
  8412. if(light_hour > 1440)
  8413. light_hour = light_hour - 1440;
  8414.  
  8415. if(std::abs(light_hour - SUNRISE) < 2*light_hour_delta){
  8416. light_state = LIGHT_STATE_SUNRISE;
  8417. }
  8418. else if(std::abs(light_hour - SUNSET) < 2*light_hour_delta){
  8419. light_state = LIGHT_STATE_SUNSET;
  8420. }
  8421.  
  8422. int32_t newlightlevel = lightlevel;
  8423. switch(light_state){
  8424. case LIGHT_STATE_SUNRISE:
  8425. newlightlevel += (LIGHT_LEVEL_DAY - LIGHT_LEVEL_NIGHT)/30;
  8426. break;
  8427. case LIGHT_STATE_SUNSET:
  8428. newlightlevel -= (LIGHT_LEVEL_DAY - LIGHT_LEVEL_NIGHT)/30;
  8429. break;
  8430. }
  8431.  
  8432. if(newlightlevel <= LIGHT_LEVEL_NIGHT){
  8433. lightlevel = LIGHT_LEVEL_NIGHT;
  8434. light_state = LIGHT_STATE_NIGHT;
  8435. }
  8436. else if(newlightlevel >= LIGHT_LEVEL_DAY){
  8437. lightlevel = LIGHT_LEVEL_DAY;
  8438. light_state = LIGHT_STATE_DAY;
  8439. }
  8440. else{
  8441. lightlevel = newlightlevel;
  8442. }
  8443.  
  8444.  
  8445. // status, ten kod i tak jest brzydki
  8446. uint64_t time = OTSYS_TIME();
  8447. ofstream file;
  8448. file.open ("status");
  8449. file << time << " " << (time - Status::instance()->start)/1000 << " " << Status::instance()->playersonline << " " << Status::instance()->playersmax;
  8450. file.close();
  8451.  
  8452. file.open("online");
  8453. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  8454. std::string txt = (*it).second->getName();
  8455. file << (*it).second->getName() << ";" << (*it).second->getLevel() << "\n";
  8456. }
  8457. file.close();
  8458.  
  8459.  
  8460. }
  8461.  
  8462. unsigned char Game::getLightLevel(){
  8463. return lightlevel;
  8464. }
  8465. #endif //CVS_DAY_CYCLE
  8466.  
  8467.  
  8468. #ifdef WANDS_JIDDO
  8469. void Game::useWand(Creature *creature, Creature *attackedCreature, int32_t wandid) {
  8470.  
  8471. Player *player = dynamic_cast<Player*>(creature);
  8472. if(!player) return;
  8473.  
  8474. if((wandid == 5318 && (player->vocation == VOCATION_DRUID) && player->mana >= 10 && player->getLevel() >= 65)) { //Quagmire rod
  8475. int32_t dist = 6;
  8476. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8477. std::vector<unsigned char> col;
  8478. MagicEffectAreaClass runeAreaSpell;
  8479. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8480. runeAreaSpell.animationEffect = NM_ANI_SNOWBALL;
  8481. runeAreaSpell.hitEffect = NM_ME_LOOSE_ENERGY;
  8482. runeAreaSpell.areaEffect = NM_ME_DRAW_BLOOD;
  8483. runeAreaSpell.animationColor = 0x47;
  8484. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8485. col.push_back(0);
  8486. col.push_back(0);
  8487. col.push_back(0);
  8488. runeAreaSpell.areaVec.push_back(col);
  8489. col.clear();
  8490. col.push_back(0);
  8491. col.push_back(1);
  8492. col.push_back(0);
  8493. runeAreaSpell.areaVec.push_back(col);
  8494. col.clear();
  8495. col.push_back(0);
  8496. col.push_back(0);
  8497. col.push_back(0);
  8498. runeAreaSpell.areaVec.push_back(col);
  8499. col.clear();
  8500. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 70; runeAreaSpell.maxDamage = 150;
  8501. long tempExhaust = player->exhaustedTicks;
  8502. player->exhaustedTicks = 0;
  8503. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8504. player->exhaustedTicks = tempExhaust;
  8505. int32_t mana = 10;
  8506. player->addManaSpent(mana);
  8507. player->mana -= mana;
  8508. return;
  8509. }
  8510.  
  8511.  
  8512. if((wandid == 5319 && (player->vocation == VOCATION_SORCERER) && player->mana >= 10 && player->getLevel() >= 65)) { //Wand of cosmic energy
  8513. int32_t dist = 6;
  8514. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8515. std::vector<unsigned char> col;
  8516. MagicEffectAreaClass runeAreaSpell;
  8517. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8518. runeAreaSpell.animationEffect = NM_ANI_LARGEROCK;
  8519. runeAreaSpell.hitEffect = NM_ME_SOUND_WHITE;
  8520. runeAreaSpell.areaEffect = NM_ME_SOUND_WHITE;
  8521. runeAreaSpell.animationColor = 0xAC;
  8522. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8523. col.push_back(0);
  8524. col.push_back(0);
  8525. col.push_back(0);
  8526. runeAreaSpell.areaVec.push_back(col);
  8527. col.clear();
  8528. col.push_back(0);
  8529. col.push_back(1);
  8530. col.push_back(0);
  8531. runeAreaSpell.areaVec.push_back(col);
  8532. col.clear();
  8533. col.push_back(0);
  8534. col.push_back(0);
  8535. col.push_back(0);
  8536. runeAreaSpell.areaVec.push_back(col);
  8537. col.clear();
  8538. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 70; runeAreaSpell.maxDamage = 150;
  8539. long tempExhaust = player->exhaustedTicks;
  8540. player->exhaustedTicks = 0;
  8541. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8542. player->exhaustedTicks = tempExhaust;
  8543. int32_t mana = 10;
  8544. player->addManaSpent(mana);
  8545. player->mana -= mana;
  8546. return;
  8547. }
  8548.  
  8549. //SCEPTRE OF THE LOST SOULS
  8550. if((wandid == 5326 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_DRUID) && player->mana >= 50 && player->getLevel() >= 300)) {
  8551. int32_t dist = 4;
  8552. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8553. std::vector<unsigned char> col;
  8554. MagicEffectAreaClass runeAreaSpell;
  8555. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8556. runeAreaSpell.animationEffect = NM_ANI_ENERGY2;
  8557. runeAreaSpell.hitEffect = NM_ME_ENERGY_AREA;
  8558. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8559. runeAreaSpell.animationColor = 0x65;
  8560. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8561. col.push_back(0);
  8562. col.push_back(0);
  8563. col.push_back(0);
  8564. runeAreaSpell.areaVec.push_back(col);
  8565. col.clear();
  8566. col.push_back(0);
  8567. col.push_back(1);
  8568. col.push_back(0);
  8569. runeAreaSpell.areaVec.push_back(col);
  8570. col.clear();
  8571. col.push_back(0);
  8572. col.push_back(0);
  8573. col.push_back(0);
  8574. runeAreaSpell.areaVec.push_back(col);
  8575. col.clear();
  8576. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 350; runeAreaSpell.maxDamage = 450;
  8577. long tempExhaust = player->exhaustedTicks;
  8578. player->exhaustedTicks = 0;
  8579. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8580. player->exhaustedTicks = tempExhaust;
  8581. int32_t mana = 50;
  8582. player->addManaSpent(mana);
  8583. player->mana -= mana;
  8584. return;
  8585. }
  8586.  
  8587. //NATURE WAND
  8588. if((wandid == 2544 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_DRUID) && player->mana >= 35 && player->getLevel() >= 200)) {
  8589. int32_t dist = 5;
  8590. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8591. std::vector<unsigned char> col;
  8592. MagicEffectAreaClass runeAreaSpell;
  8593. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8594. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8595. runeAreaSpell.hitEffect = 20;
  8596. runeAreaSpell.areaEffect = 20;
  8597. runeAreaSpell.animationColor = 0x60;
  8598. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8599. col.push_back(0);
  8600. col.push_back(0);
  8601. col.push_back(0);
  8602. runeAreaSpell.areaVec.push_back(col);
  8603. col.clear();
  8604. col.push_back(0);
  8605. col.push_back(1);
  8606. col.push_back(0);
  8607. runeAreaSpell.areaVec.push_back(col);
  8608. col.clear();
  8609. col.push_back(0);
  8610. col.push_back(0);
  8611. col.push_back(0);
  8612. runeAreaSpell.areaVec.push_back(col);
  8613. col.clear();
  8614. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 200; runeAreaSpell.maxDamage = 350;
  8615. long tempExhaust = player->exhaustedTicks;
  8616. player->exhaustedTicks = 0;
  8617. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8618. player->exhaustedTicks = tempExhaust;
  8619. int32_t mana = 35;
  8620. player->addManaSpent(mana);
  8621. player->mana -= mana;
  8622. return;
  8623. }
  8624.  
  8625. //SPRITE WAND
  8626. if((wandid == 2453 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_DRUID) && player->mana >= 25 && player->getLevel() >= 150)) {
  8627. int32_t dist = 5;
  8628. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8629. std::vector<unsigned char> col;
  8630. MagicEffectAreaClass runeAreaSpell;
  8631. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8632. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8633. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8634. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8635. runeAreaSpell.animationColor = 0x11;
  8636. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8637. col.push_back(0);
  8638. col.push_back(0);
  8639. col.push_back(0);
  8640. runeAreaSpell.areaVec.push_back(col);
  8641. col.clear();
  8642. col.push_back(0);
  8643. col.push_back(1);
  8644. col.push_back(0);
  8645. runeAreaSpell.areaVec.push_back(col);
  8646. col.clear();
  8647. col.push_back(0);
  8648. col.push_back(0);
  8649. col.push_back(0);
  8650. runeAreaSpell.areaVec.push_back(col);
  8651. col.clear();
  8652. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 150; runeAreaSpell.maxDamage = 250;
  8653. long tempExhaust = player->exhaustedTicks;
  8654. player->exhaustedTicks = 0;
  8655. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8656. player->exhaustedTicks = tempExhaust;
  8657. int32_t mana = 25;
  8658. player->addManaSpent(mana);
  8659. player->mana -= mana;
  8660. return;
  8661. }
  8662.  
  8663.  
  8664. if((wandid == 2181 && (player->vocation == VOCATION_DRUID) && player->mana >= 8 && player->getLevel() >= 26)) { //Quagmire rod
  8665. int32_t dist = 2;
  8666. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8667. std::vector<unsigned char> col;
  8668. MagicEffectAreaClass runeAreaSpell;
  8669. runeAreaSpell.attackType = ATTACK_POISON;
  8670. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8671. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  8672. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  8673. runeAreaSpell.animationColor = 0x60;
  8674. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8675. col.push_back(0);
  8676. col.push_back(0);
  8677. col.push_back(0);
  8678. runeAreaSpell.areaVec.push_back(col);
  8679. col.clear();
  8680. col.push_back(0);
  8681. col.push_back(1);
  8682. col.push_back(0);
  8683. runeAreaSpell.areaVec.push_back(col);
  8684. col.clear();
  8685. col.push_back(0);
  8686. col.push_back(0);
  8687. col.push_back(0);
  8688. runeAreaSpell.areaVec.push_back(col);
  8689. col.clear();
  8690. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 40; runeAreaSpell.maxDamage = 50;
  8691. long tempExhaust = player->exhaustedTicks;
  8692. player->exhaustedTicks = 0;
  8693. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8694. player->exhaustedTicks = tempExhaust;
  8695. int32_t mana = 8;
  8696. player->addManaSpent(mana);
  8697. player->mana -= mana;
  8698. return;
  8699. }
  8700.  
  8701. if((wandid == 2182 && (player->vocation == VOCATION_DRUID) && player->mana >= 2 && player->getLevel() >= 7)) { //Snakebite rod
  8702. int32_t dist = 4;
  8703. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8704. std::vector<unsigned char> col;
  8705. MagicEffectAreaClass runeAreaSpell;
  8706. runeAreaSpell.attackType = ATTACK_POISON;
  8707. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8708. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  8709. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  8710. runeAreaSpell.animationColor = 0x60;
  8711. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8712. col.push_back(0);
  8713. col.push_back(0);
  8714. col.push_back(0);
  8715. runeAreaSpell.areaVec.push_back(col);
  8716. col.clear();
  8717. col.push_back(0);
  8718. col.push_back(1);
  8719. col.push_back(0);
  8720. runeAreaSpell.areaVec.push_back(col);
  8721. col.clear();
  8722. col.push_back(0);
  8723. col.push_back(0);
  8724. col.push_back(0);
  8725. runeAreaSpell.areaVec.push_back(col);
  8726. col.clear();
  8727. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 8; runeAreaSpell.maxDamage = 18;
  8728. long tempExhaust = player->exhaustedTicks;
  8729. player->exhaustedTicks = 0;
  8730. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8731. player->exhaustedTicks = tempExhaust;
  8732. int32_t mana = 2;
  8733. player->addManaSpent(mana);
  8734. player->mana -= mana;
  8735. return;
  8736. }
  8737.  
  8738.  
  8739.  
  8740. if((wandid == 2183 && (player->vocation == VOCATION_DRUID) && player->mana >= 13 && player->getLevel() >= 33)) { //Tempest rod
  8741. int32_t dist = 2;
  8742. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8743. std::vector<unsigned char> col;
  8744. MagicEffectAreaClass runeAreaSpell;
  8745. runeAreaSpell.attackType = ATTACK_ENERGY;
  8746. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8747. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8748. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8749. runeAreaSpell.animationColor = 0x11;
  8750. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8751. col.push_back(0);
  8752. col.push_back(0);
  8753. col.push_back(0);
  8754. runeAreaSpell.areaVec.push_back(col);
  8755. col.clear();
  8756. col.push_back(0);
  8757. col.push_back(1);
  8758. col.push_back(0);
  8759. runeAreaSpell.areaVec.push_back(col);
  8760. col.clear();
  8761. col.push_back(0);
  8762. col.push_back(0);
  8763. col.push_back(0);
  8764. runeAreaSpell.areaVec.push_back(col);
  8765. col.clear();
  8766. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 60; runeAreaSpell.maxDamage = 70;
  8767. long tempExhaust = player->exhaustedTicks;
  8768. player->exhaustedTicks = 0;
  8769. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8770. player->exhaustedTicks = tempExhaust;
  8771. int32_t mana = 13;
  8772. player->addManaSpent(mana);
  8773. player->mana -= mana;
  8774. return;
  8775. }
  8776.  
  8777.  
  8778. if((wandid == 2185 && (player->vocation == VOCATION_DRUID) && player->mana >= 5 && player->getLevel() >= 19)) { //Volcanic rod
  8779. int32_t dist = 2;
  8780. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8781. std::vector<unsigned char> col;
  8782. MagicEffectAreaClass runeAreaSpell;
  8783. runeAreaSpell.attackType = ATTACK_FIRE;
  8784. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  8785. runeAreaSpell.hitEffect = NM_ME_FIRE_AREA;
  8786. runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8787. runeAreaSpell.animationColor = 0xC7;
  8788. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8789. col.push_back(0);
  8790. col.push_back(0);
  8791. col.push_back(0);
  8792. runeAreaSpell.areaVec.push_back(col);
  8793. col.clear();
  8794. col.push_back(0);
  8795. col.push_back(1);
  8796. col.push_back(0);
  8797. runeAreaSpell.areaVec.push_back(col);
  8798. col.clear();
  8799. col.push_back(0);
  8800. col.push_back(0);
  8801. col.push_back(0);
  8802. runeAreaSpell.areaVec.push_back(col);
  8803. col.clear();
  8804. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 25; runeAreaSpell.maxDamage = 35;
  8805. long tempExhaust = player->exhaustedTicks;
  8806. player->exhaustedTicks = 0;
  8807. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8808. player->exhaustedTicks = tempExhaust;
  8809. int32_t mana = 5;
  8810. player->addManaSpent(mana);
  8811. player->mana -= mana;
  8812. return;
  8813. }
  8814.  
  8815.  
  8816. if((wandid == 2186 && (player->vocation == VOCATION_DRUID) && player->mana >= 3 && player->getLevel() >= 13)) { //Moonlight rod
  8817. int32_t dist = 3;
  8818. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8819. std::vector<unsigned char> col;
  8820. MagicEffectAreaClass runeAreaSpell;
  8821. runeAreaSpell.attackType = ATTACK_ENERGY;
  8822. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8823. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8824. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8825. runeAreaSpell.animationColor = 0x47;
  8826. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8827. col.push_back(0);
  8828. col.push_back(0);
  8829. col.push_back(0);
  8830. runeAreaSpell.areaVec.push_back(col);
  8831. col.clear();
  8832. col.push_back(0);
  8833. col.push_back(1);
  8834. col.push_back(0);
  8835. runeAreaSpell.areaVec.push_back(col);
  8836. col.clear();
  8837. col.push_back(0);
  8838. col.push_back(0);
  8839. col.push_back(0);
  8840. runeAreaSpell.areaVec.push_back(col);
  8841. col.clear();
  8842. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 14; runeAreaSpell.maxDamage = 24;
  8843. long tempExhaust = player->exhaustedTicks;
  8844. player->exhaustedTicks = 0;
  8845. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8846. player->exhaustedTicks = tempExhaust;
  8847. int32_t mana = 3;
  8848. player->addManaSpent(mana);
  8849. player->mana -= mana;
  8850. return;
  8851. }
  8852.  
  8853.  
  8854. if((wandid == 2187 && (player->vocation == VOCATION_SORCERER) && player->mana >= 13 && player->getLevel() >= 33)) { //Wand of inferno
  8855. int32_t dist = 2;
  8856. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8857. std::vector<unsigned char> col;
  8858. MagicEffectAreaClass runeAreaSpell;
  8859. runeAreaSpell.attackType = ATTACK_FIRE;
  8860. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  8861. runeAreaSpell.hitEffect = NM_ME_FIRE_AREA;
  8862. runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8863. runeAreaSpell.animationColor = 0xC7;
  8864. runeAreaSpell.drawblood = true;
  8865. runeAreaSpell.offensive = true;
  8866. col.push_back(0);
  8867. col.push_back(0);
  8868. col.push_back(0);
  8869. runeAreaSpell.areaVec.push_back(col);
  8870. col.clear();
  8871. col.push_back(0);
  8872. col.push_back(1);
  8873. col.push_back(0);
  8874. runeAreaSpell.areaVec.push_back(col);
  8875. col.clear();
  8876. col.push_back(0);
  8877. col.push_back(0);
  8878. col.push_back(0);
  8879. runeAreaSpell.areaVec.push_back(col);
  8880. col.clear();
  8881. runeAreaSpell.direction = 1;
  8882. runeAreaSpell.minDamage = 60;
  8883. runeAreaSpell.maxDamage = 70;
  8884. long tempExhaust = player->exhaustedTicks;
  8885. player->exhaustedTicks = 0;
  8886. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8887. player->exhaustedTicks = tempExhaust;
  8888. int32_t mana = 13;
  8889. player->addManaSpent(mana);
  8890. player->mana -= mana;
  8891.  
  8892. return;
  8893. }
  8894.  
  8895.  
  8896. if((wandid == 2188 && (player->vocation == VOCATION_SORCERER) && player->mana >= 5 && player->getLevel() >= 19)) { //Wand of plague
  8897. int32_t dist = 2;
  8898. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8899. std::vector<unsigned char> col;
  8900. MagicEffectAreaClass runeAreaSpell;
  8901. runeAreaSpell.attackType = ATTACK_POISON;
  8902. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8903. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  8904. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  8905. runeAreaSpell.animationColor = 0x60;
  8906. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8907. col.push_back(0);
  8908. col.push_back(0);
  8909. col.push_back(0);
  8910. runeAreaSpell.areaVec.push_back(col);
  8911. col.clear();
  8912. col.push_back(0);
  8913. col.push_back(1);
  8914. col.push_back(0);
  8915. runeAreaSpell.areaVec.push_back(col);
  8916. col.clear();
  8917. col.push_back(0);
  8918. col.push_back(0);
  8919. col.push_back(0);
  8920. runeAreaSpell.areaVec.push_back(col);
  8921. col.clear();
  8922. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 25; runeAreaSpell.maxDamage = 35;
  8923. long tempExhaust = player->exhaustedTicks;
  8924. player->exhaustedTicks = 0;
  8925. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8926. player->exhaustedTicks = tempExhaust;
  8927. int32_t mana = 5;
  8928. player->addManaSpent(mana);
  8929. player->mana -= mana;
  8930. return;
  8931. }
  8932.  
  8933.  
  8934. if((wandid == 2189 && (player->vocation == VOCATION_SORCERER) && player->mana >= 8 && player->getLevel() >= 26)) { //Wand of cosmic energy
  8935. int32_t dist = 2;
  8936. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8937. std::vector<unsigned char> col;
  8938. MagicEffectAreaClass runeAreaSpell;
  8939. runeAreaSpell.attackType = ATTACK_ENERGY;
  8940. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8941. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8942. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8943. runeAreaSpell.animationColor = 0x47;
  8944. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8945. col.push_back(0);
  8946. col.push_back(0);
  8947. col.push_back(0);
  8948. runeAreaSpell.areaVec.push_back(col);
  8949. col.clear();
  8950. col.push_back(0);
  8951. col.push_back(1);
  8952. col.push_back(0);
  8953. runeAreaSpell.areaVec.push_back(col);
  8954. col.clear();
  8955. col.push_back(0);
  8956. col.push_back(0);
  8957. col.push_back(0);
  8958. runeAreaSpell.areaVec.push_back(col);
  8959. col.clear();
  8960. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 40; runeAreaSpell.maxDamage = 50;
  8961. long tempExhaust = player->exhaustedTicks;
  8962. player->exhaustedTicks = 0;
  8963. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8964. player->exhaustedTicks = tempExhaust;
  8965. int32_t mana = 8;
  8966. player->addManaSpent(mana);
  8967. player->mana -= mana;
  8968. return;
  8969. }
  8970.  
  8971.  
  8972. if((wandid == 2190 && (player->vocation == VOCATION_SORCERER) && player->mana >= 2 && player->getLevel() >= 7)) { //Wand of vortex
  8973. int32_t dist = 3;
  8974. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8975. std::vector<unsigned char> col;
  8976. MagicEffectAreaClass runeAreaSpell;
  8977. runeAreaSpell.attackType = ATTACK_ENERGY;
  8978. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8979. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8980. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8981. runeAreaSpell.animationColor = 0x47;
  8982. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8983. col.push_back(0);
  8984. col.push_back(0);
  8985. col.push_back(0);
  8986. runeAreaSpell.areaVec.push_back(col);
  8987. col.clear();
  8988. col.push_back(0);
  8989. col.push_back(1);
  8990. col.push_back(0);
  8991. runeAreaSpell.areaVec.push_back(col);
  8992. col.clear();
  8993. col.push_back(0);
  8994. col.push_back(0);
  8995. col.push_back(0);
  8996. runeAreaSpell.areaVec.push_back(col);
  8997. col.clear();
  8998. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 8; runeAreaSpell.maxDamage = 18;
  8999. long tempExhaust = player->exhaustedTicks;
  9000. player->exhaustedTicks = 0;
  9001. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  9002. player->exhaustedTicks = tempExhaust;
  9003. int32_t mana = 2;
  9004. player->addManaSpent(mana);
  9005. player->mana -= mana;
  9006. return;
  9007. }
  9008.  
  9009. if((wandid == 2191 && (player->vocation == VOCATION_SORCERER) && player->mana >= 3 && player->getLevel() >= 13)) { //Wand of dragonbreath
  9010. int32_t dist = 3;
  9011. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  9012. std::vector<unsigned char> col;
  9013. MagicEffectAreaClass runeAreaSpell;
  9014. runeAreaSpell.attackType = ATTACK_FIRE;
  9015. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  9016. runeAreaSpell.hitEffect = NM_ME_FIRE_AREA;
  9017. runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  9018. runeAreaSpell.animationColor = 0xC7;
  9019. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  9020. col.push_back(0);
  9021. col.push_back(0);
  9022. col.push_back(0);
  9023. runeAreaSpell.areaVec.push_back(col);
  9024. col.clear();
  9025. col.push_back(0);
  9026. col.push_back(1);
  9027. col.push_back(0);
  9028. runeAreaSpell.areaVec.push_back(col);
  9029. col.clear();
  9030. col.push_back(0);
  9031. col.push_back(0);
  9032. col.push_back(0);
  9033. runeAreaSpell.areaVec.push_back(col);
  9034. col.clear();
  9035. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 14; runeAreaSpell.maxDamage = 24;
  9036. long tempExhaust = player->exhaustedTicks;
  9037. player->exhaustedTicks = 0;
  9038. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  9039. player->exhaustedTicks = tempExhaust;
  9040. int32_t mana = 3;
  9041. player->addManaSpent(mana);
  9042. player->mana -= mana;
  9043. return;
  9044. }
  9045. //messages by Subarmy
  9046.  
  9047.  
  9048.  
  9049. if((wandid == 2191 || wandid == 2190 || wandid == 5319 || wandid == 2189 || wandid == 2188 || wandid == 2187 || wandid == 2453 || wandid == 2544 && (player->vocation == VOCATION_DRUID || player->vocation == VOCATION_KNIGHT || player->vocation == VOCATION_PALADIN || (player->vocation >= 0 && player->access > 0)))) { //msg when wrong voc
  9050. player->sendTextMessage(MSG_SMALLINFO, "This wand can only be wielded by sorcerers.");
  9051. }
  9052. if((wandid == 2186 || wandid == 2185 || wandid == 5318 || wandid == 2183 || wandid == 2182 || wandid == 2181 || wandid == 2453 || wandid == 2544 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_KNIGHT || player->vocation == VOCATION_PALADIN || (player->vocation >= 0 && player->access > 0)))) { //msg when wrong voc
  9053. player->sendTextMessage(MSG_SMALLINFO, "This wand can only be wielded by druids.");
  9054. }
  9055. if((wandid == 2181 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 26)) {
  9056. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 26 level to wield this wand.");
  9057. }
  9058. if((wandid == 2544 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 200)) {
  9059. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 200 level to wield this wand.");
  9060. }
  9061. if((wandid == 5326 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 300)) {
  9062. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 300 level to wield this wand.");
  9063. }
  9064. if((wandid == 2453 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 150)) {
  9065. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 150 level to wield this wand.");
  9066. }
  9067. if((wandid == 2182 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 7)) {
  9068. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 7 level to wield this wand.");
  9069. }
  9070. if((wandid == 2183 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 33)) {
  9071. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 33 to wield this wand.");
  9072. }
  9073. if((wandid == 2185 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 19)) {
  9074. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 19 level to wield this wand.");
  9075. }
  9076. if((wandid == 2186 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 13)) {
  9077. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 13 level to wield this wand.");
  9078. }
  9079. if((wandid == 5318 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 65)) {
  9080. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 65 level to wield this wand.");
  9081. }
  9082. if((wandid == 2187 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 33)) {
  9083. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 33 level to wield this wand.");
  9084. }
  9085. if((wandid == 5319 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 65)) {
  9086. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 65 level to wield this wand.");
  9087. }
  9088. if((wandid == 2453 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 150)) {
  9089. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 150 level to wield this wand.");
  9090. }
  9091. if((wandid == 2544 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 200)) {
  9092. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 200 level to wield this wand.");
  9093. }
  9094. if((wandid == 5326 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 300)) {
  9095. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 300 level to wield this wand.");
  9096. }
  9097. if((wandid == 2188 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 19)) {
  9098. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 19 level to wield this wand.");
  9099. }
  9100. if((wandid == 2189 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 26)) {
  9101. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 26 level to wield this wand.");
  9102. }
  9103. if((wandid == 2190 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 7)) {
  9104. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 7 level to wield this wand.");
  9105. }
  9106.  
  9107. if((wandid == 2191 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 13)) {
  9108. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 13 level to wield this wand.");
  9109. }//end messages by Subarmy
  9110. }
  9111. #endif
  9112. // ONLINE RECORD
  9113. void Game::checkRecord()
  9114. {
  9115. if(record < getPlayersOnline()){
  9116. record = getPlayersOnline();
  9117. saveRecord();
  9118.  
  9119. std::stringstream record;
  9120. record << "New record: " << getPlayersOnline() << " players are logged in." << std::endl;
  9121. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  9122. (*it).second->sendTextMessage(MSG_ADVANCE, record.str().c_str());
  9123. }
  9124.  
  9125. }
  9126.  
  9127. bool Game::loadRecord()
  9128. {
  9129. std::string filename = g_config.getGlobalString("datadir") + "record.xml";
  9130. xmlDocPtr doc;
  9131. xmlMutexLock(xmlmutex);
  9132. doc = xmlParseFile(filename.c_str());
  9133.  
  9134. if (doc)
  9135. {
  9136. xmlNodePtr root, tmp;
  9137. root = xmlDocGetRootElement(doc);
  9138.  
  9139. if (xmlStrcmp(root->name, (const xmlChar*)"record"))
  9140. {
  9141. xmlFreeDoc(doc);
  9142. xmlMutexUnlock(xmlmutex);
  9143. return false;
  9144. }
  9145.  
  9146. record = atoi((const char*)xmlGetProp(root, (const xmlChar *)"record"));
  9147.  
  9148. xmlFreeDoc(doc);
  9149. xmlMutexUnlock(xmlmutex);
  9150. return true;
  9151. }
  9152.  
  9153. xmlMutexUnlock(xmlmutex);
  9154. return false;
  9155. }
  9156.  
  9157. bool Game::saveRecord()
  9158. {
  9159. std::string filename = g_config.getGlobalString("datadir") + "record.xml";
  9160. xmlDocPtr doc;
  9161. xmlNodePtr root, tmp;
  9162. xmlMutexLock(xmlmutex);
  9163. time_t time = std::time(NULL);
  9164.  
  9165. doc = xmlNewDoc((const xmlChar*)"1.0");
  9166. doc->children = xmlNewDocNode(doc, NULL, (const xmlChar*)"record", NULL);
  9167. root = doc->children;
  9168.  
  9169. std::stringstream sb;
  9170. sb << record; xmlSetProp(root, (const xmlChar*) "record", (const xmlChar*)sb.str().c_str()); sb.str("");
  9171. sb << time; xmlSetProp(root, (const xmlChar*) "time", (const xmlChar*)sb.str().c_str()); sb.str("");
  9172.  
  9173. xmlSaveFile(filename.c_str(), doc);
  9174. xmlFreeDoc(doc);
  9175. xmlMutexUnlock(xmlmutex);
  9176. return true;
  9177. }
  9178. // ANIMATED TEXT WHEN ADVANCE
  9179. void Game::sendAnimatedTextExt(const Position pos,int32_t aniColor,const std::string &text)
  9180. {
  9181. SpectatorVec list;
  9182. SpectatorVec::iterator it;
  9183. getSpectators(Range(pos), list);
  9184. for(it = list.begin(); it != list.end(); ++it){
  9185. Player* spec = dynamic_cast<Player*>(*it);
  9186. if(spec)
  9187. spec->sendAnimatedText(pos, aniColor, text);
  9188. }
  9189. }
  9190. // CREATUREBYPOSITION
  9191. Creature* Game::getCreatureByPosition(int32_t x, int32_t y, int32_t z)
  9192. {
  9193. for(AutoList<Creature>::listiterator it = listCreature.list.begin(); it != listCreature.list.end(); ++it){
  9194. if(it->second->pos.x == x && it->second->pos.y == y && it->second->pos.z == z)
  9195. return it->second;
  9196. }
  9197.  
  9198. return NULL;
  9199. }
  9200. // CREATE CONDITION
  9201. void Game::CreateCondition(Creature* creature, Creature* target, unsigned char animationColor, unsigned char damageEffect, unsigned char hitEffect, attacktype_t attackType, bool offensive, int32_t maxDamage, int32_t minDamage, long ticks, long count)
  9202. {
  9203. uint32_t targetID;
  9204. if(target)
  9205. targetID = target->getID();
  9206. else
  9207. targetID = 0;
  9208.  
  9209. MagicEffectTargetCreatureCondition magicCondition = MagicEffectTargetCreatureCondition(targetID);
  9210. magicCondition.animationColor = animationColor;
  9211. magicCondition.damageEffect = damageEffect;
  9212. magicCondition.hitEffect = hitEffect;
  9213. magicCondition.attackType = attackType;
  9214. magicCondition.maxDamage = maxDamage;
  9215. magicCondition.minDamage = minDamage;
  9216. magicCondition.offensive = offensive;
  9217. CreatureCondition condition = CreatureCondition(ticks, count, magicCondition);
  9218. creature->addCondition(condition, true);
  9219.  
  9220. Player *player = dynamic_cast<Player*>(creature);
  9221. if(player)
  9222. player->sendIcons();
  9223. }
  9224. // Fields loaded from map - The Chaos
  9225. void Game::doFieldDamage(Creature* creature, unsigned char animationColor, unsigned char damageEffect,
  9226. unsigned char hitEffect, attacktype_t attackType, bool offensive, int32_t damage)
  9227. {
  9228. MagicEffectClass cd;
  9229. cd.animationColor = animationColor;
  9230. cd.damageEffect = damageEffect;
  9231. cd.hitEffect = hitEffect;
  9232. cd.attackType = attackType;
  9233. cd.offensive = offensive;
  9234. Player* itsHim = dynamic_cast<Player*>(getCreatureByID(creature->getID()));
  9235. if(itsHim){ //Since that was causing damage/2 against player, here its my solution =)
  9236. cd.maxDamage = damage*2;
  9237. cd.minDamage = damage*2;
  9238. }
  9239. else{
  9240. cd.maxDamage = damage;
  9241. cd.minDamage = damage;
  9242. }
  9243. creatureMakeMagic(NULL, creature->pos, &cd);
  9244. }
  9245. void Game::updateTile(const Position& pos)
  9246. {
  9247. SpectatorVec list;
  9248. SpectatorVec::iterator i;
  9249. getSpectators(Range(pos), list);
  9250. for(i = list.begin(); i != list.end(); ++i)
  9251. (*i)->onTileUpdated(pos);
  9252. }
  9253.  
  9254. void Game::banPlayer(Player *player, std::string reason, std::string action, std::string comment, bool IPban)
  9255. {
  9256. int32_t bantime = 0;
  9257.  
  9258. if(player){
  9259.  
  9260. if(comment=="deletion")
  9261. player->deleted = 1; // make player deleted
  9262. else
  9263. bantime = atoi(comment.c_str()) * 86400; // else make players banned for "comment" days (86400 = 1 day)
  9264.  
  9265. if(player->finalwarning == 1 || player->times == 4)
  9266. player->deleted = 1; // if player was already warned let delete thy char
  9267.  
  9268. if(action=="AccountBan+FinalWarning" || player->times == 3)
  9269. player->finalwarning = 1; // if player has warned set variable
  9270.  
  9271. if(reason=="Excessive unjustifed player killing")
  9272. bantime = g_config.getGlobalNumber("pkbandays",3) * 86400; // baannnnn pekaayssss (from config.lua)
  9273.  
  9274. player->banned = 1;
  9275. player->times++;
  9276. player->comment = comment;
  9277. player->reason = reason;
  9278. player->action = action;
  9279. player->banstart = std::time(NULL);
  9280. player->banend = player->banstart + bantime;
  9281. time_t endBan = player->banend;
  9282. player->banrealtime = ctime(&endBan); // this variable stores REAL ban date in string, so you wont see 11105220952 in accmaker ;)
  9283. if(IPban){
  9284. std::pair<uint32_t, uint32_t> IpNetMask;
  9285. IpNetMask.first = player->lastip;
  9286. IpNetMask.second = 0xFFFFFFFF;
  9287. if(IpNetMask.first > 0)
  9288. bannedIPs.push_back(IpNetMask);
  9289. }
  9290. std::stringstream ban;
  9291. ban << "You just have been banned for " << reason << "!";
  9292. player->sendTextMessage(MSG_INFO, ban.str().c_str());
  9293. player->kickPlayer();
  9294. }
  9295. }
  9296.  
  9297. #ifdef REX_MUTED
  9298.  
  9299. #endif //REX_MUTED
  9300. #ifdef HUCZU_FIX
  9301. bool Game::loadCities(Player* player, std::string name)
  9302. {
  9303. xmlDocPtr doc;
  9304. std::string file = "data/miasta.xml";
  9305. doc = xmlParseFile(file.c_str());
  9306. if(doc){
  9307. xmlNodePtr root, miasto;
  9308. root = xmlDocGetRootElement(doc);
  9309. if(xmlStrcmp(root->name, (const xmlChar*)"miasta")) {
  9310. xmlFreeDoc(doc);
  9311. return -1;
  9312. }
  9313. miasto = root->children;
  9314. while(miasto){
  9315. if(strcmp((char*) miasto->name, "miasto")==0){
  9316.  
  9317. std::string nameIN = (const char*)xmlGetProp(miasto, (const xmlChar *) "nazwa");
  9318. int32_t x = atoi((const char*)xmlGetProp(miasto, (const xmlChar *) "x"));
  9319. int32_t y = atoi((const char*)xmlGetProp(miasto, (const xmlChar *) "y"));
  9320. int32_t z = atoi((const char*)xmlGetProp(miasto, (const xmlChar *) "z"));
  9321. Position pos(x,y,z);
  9322. if(nameIN == name)
  9323. teleport(player,pos);
  9324. }
  9325. miasto = miasto->next;
  9326. }
  9327. xmlFreeDoc(doc);
  9328. return 0;
  9329. }
  9330. return -1;
  9331. }
  9332. #endif //HUCZU_FIX
  9333. // RAID SYSTEM
  9334. bool Game::loadRaid(std::string name)
  9335. {
  9336. xmlDocPtr doc;
  9337. std::cout << "Executing raid named " << name << "." << std::endl;
  9338. std::string file = "data/world/raids.xml";
  9339. doc = xmlParseFile(file.c_str());
  9340. if(doc){
  9341. xmlNodePtr root, raid, command;
  9342. root = xmlDocGetRootElement(doc);
  9343. if(xmlStrcmp(root->name, (const xmlChar*)"raids")) {
  9344. xmlFreeDoc(doc);
  9345. return -1;
  9346. }
  9347. raid = root->children;
  9348. while(raid){
  9349. if(strcmp((char*) raid->name, "raid")==0){
  9350.  
  9351. std::string nameIN = (const char*)xmlGetProp(raid, (const xmlChar *) "name");
  9352. if(nameIN == name) {
  9353. std::string messageIN = (const char*)xmlGetProp(raid, (const xmlChar *) "message");
  9354. std::string brodcasterIN = (const char*)xmlGetProp(raid, (const xmlChar *) "brodcaster");
  9355.  
  9356. Creature *c = getCreatureByName(brodcasterIN);
  9357. if(c) {
  9358. creatureBroadcastMessage(c,messageIN);
  9359. } else {
  9360. std::cout << "Could not send news msg! Brodcaster does not exist" << std::endl;
  9361. }
  9362.  
  9363. if(nameIN == name) {
  9364. command = raid->children;
  9365.  
  9366. while(command) {
  9367.  
  9368. if(strcmp((char*) command->name, "monster")==0){
  9369. std::string monstername = (const char*)xmlGetProp(command, (const xmlChar *) "name");
  9370. int32_t x = atoi((const char*)xmlGetProp(command, (const xmlChar *) "x"));
  9371. int32_t y = atoi((const char*)xmlGetProp(command, (const xmlChar *) "y"));
  9372. int32_t z = atoi((const char*)xmlGetProp(command, (const xmlChar *) "z"));
  9373.  
  9374. int32_t loot = atoi((const char*)xmlGetProp(command, (const xmlChar *) "lootid")); //Not yet implemented!
  9375. int32_t chance = atoi((const char*)xmlGetProp(command, (const xmlChar *) "chance")); //Not yet implemented!
  9376. placeRaidMonster(monstername, x, y, z);
  9377. }
  9378.  
  9379. if(strcmp((char*) command->name, "area")==0){
  9380. std::string monstername = (const char*)xmlGetProp(command, (const xmlChar *) "monster");
  9381. int32_t count = atoi((const char*)xmlGetProp(command, (const xmlChar *) "count"));
  9382. int32_t xf = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posxfrom"));
  9383. int32_t yf = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posyfrom"));
  9384. int32_t zf = atoi((const char*)xmlGetProp(command, (const xmlChar *) "poszfrom"));
  9385.  
  9386. int32_t xt = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posxto"));
  9387. int32_t yt = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posyto"));
  9388. int32_t zt = atoi((const char*)xmlGetProp(command, (const xmlChar *) "poszto"));
  9389.  
  9390. int32_t i = 0;
  9391. int32_t tries = 0;
  9392. while (i<=count && tries<=(count*10)) {
  9393. int32_t x = (int32_t)((xt-xf) * (rand()/(RAND_MAX+1.0)) + xf);
  9394. int32_t y = (int32_t)((yt-yf) * (rand()/(RAND_MAX+1.0)) + yf);
  9395. int32_t z = (int32_t)((zt-zf) * (rand()/(RAND_MAX+1.0)) + zf);
  9396. Tile* t = map->getTile(x,y,z);
  9397. if(t && t->isPz() == false) {
  9398. placeRaidMonster(monstername, x, y, z);
  9399. i++;
  9400. }
  9401. tries++;
  9402. }
  9403. }
  9404. if(strcmp((char*) command->name, "message")==0){
  9405. std::string msg = (const char*)xmlGetProp(command, (const xmlChar *) "text");
  9406. std::string brodcaster = (const char*)xmlGetProp(command, (const xmlChar *) "brodcaster");
  9407. Creature *c = getCreatureByName(brodcaster);
  9408. if(c) {
  9409. creatureBroadcastMessage(c,msg);
  9410. } else {
  9411. std::cout << "Could not send news msg! Brodcaster does not exist." << std::endl;
  9412. }
  9413. }
  9414. command = command->next;
  9415. }
  9416. }
  9417. }
  9418. }
  9419. raid = raid->next;
  9420. }
  9421. xmlFreeDoc(doc);
  9422. return 0;
  9423. }
  9424. return -1;
  9425. }
  9426. bool Game::placeRaidMonster(std::string name, int32_t x, int32_t y, int32_t z)
  9427. {
  9428. Monster* monster = Monster::createMonster(name, this);
  9429. //For new CVS use the following line:
  9430. //Monster* monster = Monster::createMonster(name, this);
  9431. if(!monster){
  9432. delete monster;
  9433. return false;
  9434. }
  9435. Position pos;
  9436. pos.x = x;
  9437. pos.y = y;
  9438. pos.z = z;
  9439.  
  9440. // Place the monster
  9441. if(!placeCreature(pos, monster)) {
  9442. delete monster;
  9443. return false;
  9444. }
  9445.  
  9446. return true;
  9447. }
  9448.  
  9449. void Game::spectatorText(Position pos, unsigned char color, std::string text)
  9450. {
  9451. SpectatorVec list;
  9452. SpectatorVec::iterator it;
  9453. getSpectators(Range(pos, true), list);
  9454.  
  9455. for(it = list.begin(); it != list.end(); ++it) {
  9456. if(Player* p = dynamic_cast<Player*>(*it)) {
  9457. p->sendAnimatedText(pos, color, text);
  9458. }
  9459. }
  9460. }
  9461.  
  9462. #ifdef DT_PREMMY
  9463. bool Game::countPremmy(Player *player)
  9464. {
  9465. Account acc = IOAccount::instance()->loadAccount(player->accountNumber);
  9466. int32_t cont;
  9467. if(acc.lastsaveday == 0)
  9468. cont = 0;
  9469. else
  9470. cont = acc.lastsaveday2 - acc.lastsaveday;
  9471. //std::cout << "Last Login in Acc: " << acc.lastsaveday << " - Today: " << acc.lastsaveday2 << " - Days removed from acc: " << cont << std::endl;
  9472. if(cont < 0){
  9473. cont =+ 365; //dodajemy caly rok
  9474. }
  9475. if((acc.premDays - cont) <= 0)
  9476. {
  9477. acc.premDays = 0;
  9478. player->premmium = false;
  9479. }
  9480. else
  9481. {
  9482. acc.premDays = acc.premDays - cont;
  9483. player->premmium = true;
  9484. }
  9485. if(g_config.FREE_PREMMY)
  9486. player->premmium = true;
  9487.  
  9488. IOAccount::instance()->saveAccount(acc);
  9489.  
  9490. }
  9491.  
  9492. #endif //DT_PREMMY
  9493.  
  9494.  
  9495. #ifdef ZS_SWORDS
  9496. void Game::useSword(Creature *creature, Creature *attackedCreature, int32_t swordid)
  9497. {
  9498. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::useSword()");
  9499.  
  9500. Player *player = dynamic_cast<Player*>(creature);
  9501. if(!player || !attackedCreature || player->pos.z != attackedCreature->pos.z)
  9502. return;
  9503.  
  9504. int32_t dist, mana = 0;
  9505. MagicEffectAreaNoExhaustionClass runeAreaSpell;
  9506. runeAreaSpell.drawblood = true;
  9507. runeAreaSpell.offensive = true;
  9508. runeAreaSpell.direction = 1;
  9509.  
  9510.  
  9511. // P O I S O N //
  9512.  
  9513. if (swordid == ITEM_P_MB && player->vocation == VOCATION_KNIGHT &&
  9514. player->mana >= g_config.MANA_P_MB && player->getLevel() >= 220)
  9515. {
  9516. dist = g_config.RANGE_P_MB;
  9517. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9518. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9519. return;
  9520.  
  9521. runeAreaSpell.attackType = ATTACK_SWORD;
  9522. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  9523. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  9524. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  9525. runeAreaSpell.animationColor = 0x60;
  9526.  
  9527. runeAreaSpell.minDamage = 10;
  9528. runeAreaSpell.maxDamage = 60;
  9529. mana = g_config.MANA_P_MB;
  9530. }
  9531.  
  9532. else if (swordid == ITEM_P_MAUL && player->vocation == VOCATION_KNIGHT &&
  9533. player->mana >= g_config.MANA_P_MAUL && player->getLevel() >= 220)
  9534. {
  9535. dist = g_config.RANGE_P_MAUL;
  9536. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9537. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9538. return;
  9539.  
  9540. runeAreaSpell.attackType = ATTACK_SWORD;
  9541. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  9542. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  9543. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  9544. runeAreaSpell.animationColor = 0x60;
  9545.  
  9546. runeAreaSpell.minDamage = 10;
  9547. runeAreaSpell.maxDamage = 60;
  9548. mana = g_config.MANA_P_MAUL;
  9549. }
  9550.  
  9551. else if (swordid == ITEM_P_HEAD && player->vocation == VOCATION_KNIGHT &&
  9552. player->mana >= g_config.MANA_P_HEAD && player->getLevel() >= 220)
  9553. {
  9554. dist = g_config.RANGE_P_HEAD;
  9555. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9556. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9557. return;
  9558.  
  9559. runeAreaSpell.attackType = ATTACK_SWORD;
  9560. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  9561. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  9562. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  9563. runeAreaSpell.animationColor = 0x60;
  9564.  
  9565. runeAreaSpell.minDamage = 10;
  9566. runeAreaSpell.maxDamage = 60;
  9567. mana = g_config.MANA_P_HEAD;
  9568. }
  9569.  
  9570. // F I R E //
  9571.  
  9572. else if (swordid == ITEM_F_MB && player->vocation == VOCATION_KNIGHT &&
  9573. player->mana >= g_config.MANA_F_MB && player->getLevel() >= 320)
  9574. {
  9575. dist = g_config.RANGE_F_MB;
  9576. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9577. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9578. return;
  9579.  
  9580. runeAreaSpell.attackType = ATTACK_SWORD;
  9581. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  9582. runeAreaSpell.hitEffect = NM_ME_EXPLOSION_AREA;
  9583. runeAreaSpell.areaEffect = NM_ME_EXPLOSION_AREA;
  9584. runeAreaSpell.animationColor = 0xC6;
  9585.  
  9586. runeAreaSpell.minDamage = 60;
  9587. runeAreaSpell.maxDamage = 110;
  9588. mana = g_config.MANA_F_MB;
  9589. }
  9590.  
  9591. else if (swordid == ITEM_F_MAUL && player->vocation == VOCATION_KNIGHT &&
  9592. player->mana >= g_config.MANA_F_MAUL && player->getLevel() >= 320)
  9593. {
  9594. dist = g_config.RANGE_F_MAUL;
  9595. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9596. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9597. return;
  9598.  
  9599. runeAreaSpell.attackType = ATTACK_SWORD;
  9600. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  9601. runeAreaSpell.hitEffect = NM_ME_EXPLOSION_AREA;
  9602. runeAreaSpell.areaEffect = NM_ME_EXPLOSION_AREA;
  9603. runeAreaSpell.animationColor = 0xC6;
  9604.  
  9605. runeAreaSpell.minDamage = 60;
  9606. runeAreaSpell.maxDamage = 110;
  9607. mana = g_config.MANA_F_MAUL;
  9608. }
  9609.  
  9610. else if (swordid == ITEM_F_HEAD && player->vocation == VOCATION_KNIGHT &&
  9611. player->mana >= g_config.MANA_F_HEAD && player->getLevel() >= 320)
  9612. {
  9613. dist = g_config.RANGE_F_HEAD;
  9614. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9615. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9616. return;
  9617.  
  9618. runeAreaSpell.attackType = ATTACK_SWORD;
  9619. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  9620. runeAreaSpell.hitEffect = NM_ME_EXPLOSION_AREA;
  9621. runeAreaSpell.areaEffect = NM_ME_EXPLOSION_AREA;
  9622. runeAreaSpell.animationColor = 0xC6;
  9623.  
  9624. runeAreaSpell.minDamage = 60;
  9625. runeAreaSpell.maxDamage = 110;
  9626. mana = g_config.MANA_F_HEAD;
  9627. }
  9628.  
  9629. // E N E R G Y //
  9630.  
  9631. else if (swordid == ITEM_E_MB && player->vocation == VOCATION_KNIGHT &&
  9632. player->mana >= g_config.MANA_E_MB && player->getLevel() >= 420)
  9633. {
  9634. dist = g_config.RANGE_E_MB;
  9635. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9636. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9637. return;
  9638.  
  9639. runeAreaSpell.attackType = ATTACK_SWORD;
  9640. runeAreaSpell.animationEffect = NM_ANI_SUDDENDEATH;
  9641. runeAreaSpell.hitEffect = NM_ME_MORT_AREA;
  9642. runeAreaSpell.areaEffect = NM_ME_MORT_AREA;
  9643. runeAreaSpell.animationColor = 0xB9;
  9644.  
  9645. runeAreaSpell.minDamage = 110;
  9646. runeAreaSpell.maxDamage = 160;
  9647. mana = g_config.MANA_E_MB;
  9648. }
  9649.  
  9650. else if (swordid == ITEM_E_MAUL && player->vocation == VOCATION_KNIGHT &&
  9651. player->mana >= g_config.MANA_E_MAUL && player->getLevel() >= 420)
  9652. {
  9653. dist = g_config.RANGE_E_MAUL;
  9654. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9655. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9656. return;
  9657.  
  9658. runeAreaSpell.attackType = ATTACK_SWORD;
  9659. runeAreaSpell.animationEffect = NM_ANI_SUDDENDEATH;
  9660. runeAreaSpell.hitEffect = NM_ME_MORT_AREA;
  9661. runeAreaSpell.areaEffect = NM_ME_MORT_AREA;
  9662. runeAreaSpell.animationColor = 0xB9;
  9663.  
  9664. runeAreaSpell.minDamage = 110;
  9665. runeAreaSpell.maxDamage = 160;
  9666. mana = g_config.MANA_E_MAUL;
  9667. }
  9668.  
  9669. else if (swordid == ITEM_E_HEAD && player->vocation == VOCATION_KNIGHT &&
  9670. player->mana >= g_config.MANA_E_HEAD && player->getLevel() >= 420)
  9671. {
  9672. dist = g_config.RANGE_E_HEAD;
  9673. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9674. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9675. return;
  9676.  
  9677. runeAreaSpell.attackType = ATTACK_SWORD;
  9678. runeAreaSpell.animationEffect = NM_ANI_SUDDENDEATH;
  9679. runeAreaSpell.hitEffect = NM_ME_MORT_AREA;
  9680. runeAreaSpell.areaEffect = NM_ME_MORT_AREA;
  9681. runeAreaSpell.animationColor = 0xB9;
  9682.  
  9683. runeAreaSpell.minDamage = 110;
  9684. runeAreaSpell.maxDamage = 160;
  9685. mana = g_config.MANA_E_HEAD;
  9686. }
  9687.  
  9688. // P L A Y E R W E A P O N S //
  9689.  
  9690. else if (swordid == ITEM_HAIK_AXE && player->vocation == VOCATION_KNIGHT &&
  9691. player->mana >= g_config.MANA_HAIK_AXE && player->getLevel() >= 500)
  9692. {
  9693. dist = g_config.RANGE_HAIK_AXE;
  9694. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9695. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9696. return;
  9697.  
  9698. runeAreaSpell.attackType = ATTACK_SWORD;
  9699. runeAreaSpell.animationEffect = NM_ANI_STAR;
  9700. runeAreaSpell.hitEffect = NM_ME_STAR;
  9701. runeAreaSpell.areaEffect = NM_ME_STAR;
  9702. runeAreaSpell.animationColor = 0xD2;
  9703.  
  9704. runeAreaSpell.minDamage = 300;
  9705. runeAreaSpell.maxDamage = 350;
  9706. mana = g_config.MANA_HAIK_AXE;
  9707. }
  9708.  
  9709. else if (swordid == ITEM_BLETKA_AXE && player->vocation == VOCATION_KNIGHT &&
  9710. player->mana >= g_config.MANA_BLETKA_AXE)
  9711. {
  9712. dist = g_config.RANGE_BLETKA_AXE;
  9713. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9714. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9715. return;
  9716.  
  9717. runeAreaSpell.attackType = ATTACK_SWORD;
  9718. runeAreaSpell.animationEffect = NM_ANI_STAR;
  9719. runeAreaSpell.hitEffect = NM_ME_STAR;
  9720. runeAreaSpell.areaEffect = NM_ME_STAR;
  9721. runeAreaSpell.animationColor = 0xD2;
  9722.  
  9723. runeAreaSpell.minDamage = 150;
  9724. runeAreaSpell.maxDamage = 200;
  9725. mana = g_config.MANA_BLETKA_AXE;
  9726. }
  9727.  
  9728. // K U N I E C //
  9729.  
  9730. if (mana > 0)
  9731. {
  9732. std::vector<unsigned char> col;
  9733.  
  9734. col.push_back(0);
  9735. col.push_back(0);
  9736. col.push_back(0);
  9737. runeAreaSpell.areaVec.push_back(col);
  9738. col.clear();
  9739. col.push_back(0);
  9740. col.push_back(1);
  9741. col.push_back(0);
  9742. runeAreaSpell.areaVec.push_back(col);
  9743. col.clear();
  9744. col.push_back(0);
  9745. col.push_back(0);
  9746. col.push_back(0);
  9747. runeAreaSpell.areaVec.push_back(col);
  9748.  
  9749. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  9750. player->addManaSpent(mana);
  9751. player->mana -= mana;
  9752. }
  9753. }
  9754. #endif //ZS_SWORDS
  9755.  
  9756. #ifdef YUR_READABLES
  9757. bool Game::LoadReadables()
  9758. {
  9759. std::string file = g_config.getGlobalString("datadir") + "readables.xml";
  9760. xmlDocPtr doc;
  9761. xmlMutexLock(xmlmutex);
  9762.  
  9763. doc = xmlParseFile(file.c_str());
  9764. if (!doc)
  9765. return false;
  9766.  
  9767. xmlNodePtr root, readableNode;
  9768. root = xmlDocGetRootElement(doc);
  9769. if (xmlStrcmp(root->name, (const xmlChar*)"readables"))
  9770. {
  9771. xmlFreeDoc(doc);
  9772. xmlMutexUnlock(xmlmutex);
  9773. return false;
  9774. }
  9775.  
  9776. readableNode = root->children;
  9777. while (readableNode)
  9778. {
  9779. if (strcmp((char*) readableNode->name, "readable") == 0)
  9780. {
  9781. int32_t x = atoi((const char*)xmlGetProp(readableNode, (const xmlChar *) "x"));
  9782. int32_t y = atoi((const char*)xmlGetProp(readableNode, (const xmlChar *) "y"));
  9783. int32_t z = atoi((const char*)xmlGetProp(readableNode, (const xmlChar *) "z"));
  9784. std::string text = (const char*)xmlGetProp(readableNode, (const xmlChar *) "text");
  9785.  
  9786. for (size_t i = 0; i < text.length()-1; i++) // make real newlines
  9787. if (text.at(i) == '\\' && text.at(i+1) == 'n')
  9788. {
  9789. text[i] = ' ';
  9790. text[i+1] = '\n';
  9791. }
  9792.  
  9793. Tile* tile = getTile(x, y, z);
  9794. if (tile)
  9795. {
  9796. Thing* thing = tile->getTopThing();
  9797. Item* item = thing? dynamic_cast<Item*>(thing) : NULL;
  9798.  
  9799. if (item)
  9800. item->setReadable(text);
  9801. else
  9802. {
  9803. std::cout << "\nTop thing at " << Position(x,y,z) << " is not an item!";
  9804. return false;
  9805. }
  9806. }
  9807. else
  9808. {
  9809. std::cout << "\nTile " << Position(x,y,z) << " is not valid!";
  9810. return false;
  9811. }
  9812. }
  9813. readableNode = readableNode->next;
  9814. }
  9815.  
  9816. xmlFreeDoc(doc);
  9817. xmlMutexUnlock(xmlmutex);
  9818. return true;
  9819. }
  9820. #endif //YUR_READABLES
  9821.  
  9822. void Game::Blasting(Creature* c, Creature *attackedCreature, const Position& pos)
  9823. {
  9824. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::Blasting()");
  9825. Player* player = dynamic_cast<Player*>(c);
  9826. unsigned short dist = 6;
  9827. unsigned short REQ_MANA = 200;
  9828. uint32_t poziom = player->level;
  9829. uint32_t magpoziom = player->maglevel;
  9830.  
  9831. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9832. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9833. return;
  9834.  
  9835. MagicEffectAreaNoExhaustionClass runeAreaSpell;
  9836. runeAreaSpell.drawblood = true;
  9837. runeAreaSpell.offensive = true;
  9838. runeAreaSpell.direction = 1;
  9839. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  9840. runeAreaSpell.animationEffect = NM_ANI_REMOTE;
  9841. runeAreaSpell.hitEffect = NM_ME_EXPLO;
  9842. runeAreaSpell.areaEffect = NM_ME_EXPLO;
  9843. runeAreaSpell.animationColor = 0x60;
  9844.  
  9845. if((poziom * 2 + magpoziom * 3) >= 100){
  9846. runeAreaSpell.minDamage = int32_t((poziom * 2 + magpoziom * 3) * 1.6 );
  9847. runeAreaSpell.maxDamage = int32_t((poziom * 2 + magpoziom * 3) * 1.9 );
  9848. }else{
  9849. runeAreaSpell.minDamage = int32_t(100 * 1.5 );
  9850. runeAreaSpell.maxDamage = int32_t(100 * 1.8 );
  9851. }
  9852.  
  9853. std::vector<unsigned char> col;
  9854. col.push_back(0);
  9855. col.push_back(0);
  9856. col.push_back(0);
  9857. runeAreaSpell.areaVec.push_back(col);
  9858. col.clear();
  9859. col.push_back(0);
  9860. col.push_back(1);
  9861. col.push_back(0);
  9862. runeAreaSpell.areaVec.push_back(col);
  9863. col.clear();
  9864. col.push_back(0);
  9865. col.push_back(0);
  9866. col.push_back(0);
  9867. runeAreaSpell.areaVec.push_back(col);
  9868.  
  9869. creatureThrowRune(c, pos, runeAreaSpell);
  9870. player->flamTicks = 2*1000;
  9871. if (player->access < g_config.ACCESS_PROTECT)
  9872. {
  9873. player->mana -= REQ_MANA;
  9874. player->addManaSpent(REQ_MANA);
  9875. }
  9876. }
  9877. #ifdef KOSZ
  9878. bool Game::canDelete(Player *player, unsigned short itemid, Position toPos, Position fromPos, int32_t from_stack, unsigned char count)
  9879. {
  9880. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::canDelete()");
  9881.  
  9882. if(itemid == 99 || (itemid >= 4329 && itemid <= 4555))
  9883. return false;
  9884. else if(fromPos.x != 0xFFFF && ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  9885. return false;
  9886. else if(map->canThrowObjectTo(player->pos, toPos, BLOCK_PROJECTILE) != RET_NOERROR)
  9887. return false;
  9888. else if(toPos.x == 0xFFFF)
  9889. return false;
  9890. else if((player->access < g_config.ACCESS_REMOTE) &&
  9891. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  9892. return false;
  9893.  
  9894. Item* trash = dynamic_cast<Item*>(getThing(fromPos, from_stack, player));
  9895. if(trash){
  9896. trash->pos = fromPos;
  9897. if((abs(player->pos.x - toPos.x) > trash->throwRange) || (abs(player->pos.y - toPos.y) > trash->throwRange)) {
  9898. return false;
  9899. }
  9900.  
  9901. Tile *toTile = map->getTile(toPos);
  9902. if(toTile){
  9903. if((toTile->ground->getID() >= GROUND_WATER1 && toTile->ground->getID() <= GROUND_WATER4) || (toTile->ground->getID() >= GROUND_WATER5 && toTile->ground->getID() <= GROUND_WATER16) || (toTile->ground->getID() == GROUND_WATER17) || (toTile->ground->getID() >= GROUND_WATER18 && toTile->ground->getID() <= GROUND_WATER35) || (toTile->ground->getID() >= GROUND_WATER36 && toTile->ground->getID() <= GROUND_WATER38) || (toTile->ground->getID() >= GROUND_WATER39 && toTile->ground->getID() <= GROUND_WATER44) || (toTile->ground->getID() >= GROUND_LAVA1 && toTile->ground->getID() <= GROUND_SWAMP4) || (toTile->ground->getID() >= GROUND_BLACK_SWAMP1 && toTile->ground->getID() <= GROUND_BLACK_SWAMP4)){
  9904. if(!trash->isNotMoveable() && trash->isBlocking())
  9905. return false;
  9906. else if(trashObjects(player, toTile, trash, toPos, fromPos, from_stack, count))
  9907. return true;
  9908. }
  9909. Item *toItem = dynamic_cast<Item*>(toTile->getTopTopItem());
  9910.  
  9911. if(toItem && toItem->getID() == ITEM_DUSTBIN){
  9912. if(!trash->isNotMoveable() && trash->isBlocking())
  9913. return false;
  9914. else if(trashObjects(player, toTile, trash, toPos, fromPos, from_stack, count))
  9915. return true;
  9916. }
  9917. }
  9918. }
  9919.  
  9920. return false;
  9921. }
  9922.  
  9923. bool Game::trashObjects(Player *player, Tile *toTile, Item *trash, Position toPos, Position fromPos, int32_t from_stack, unsigned char count)
  9924. {
  9925. //OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::trashObjects()");
  9926.  
  9927. if(!player || !toTile || !trash || !from_stack || !count){
  9928. return false;}
  9929.  
  9930. if(toTile){
  9931. switch(toTile->ground->getID()){
  9932. case GROUND_WATER1:
  9933. case GROUND_WATER2:
  9934. case GROUND_WATER3:
  9935. case GROUND_WATER4:
  9936. case GROUND_WATER5:
  9937. case GROUND_WATER6:
  9938. case GROUND_WATER7:
  9939. case GROUND_WATER8:
  9940. case GROUND_WATER9:
  9941. case GROUND_WATER10:
  9942. case GROUND_WATER11:
  9943. case GROUND_WATER12:
  9944. case GROUND_WATER13:
  9945. case GROUND_WATER14:
  9946. case GROUND_WATER15:
  9947. case GROUND_WATER16:
  9948. case GROUND_WATER17:
  9949. case GROUND_WATER18:
  9950. case GROUND_WATER19:
  9951. case GROUND_WATER20:
  9952. case GROUND_WATER21:
  9953. case GROUND_WATER22:
  9954. case GROUND_WATER23:
  9955. case GROUND_WATER24:
  9956. case GROUND_WATER25:
  9957. case GROUND_WATER26:
  9958. case GROUND_WATER27:
  9959. case GROUND_WATER28:
  9960. case GROUND_WATER29:
  9961. case GROUND_WATER30:
  9962. case GROUND_WATER31:
  9963. case GROUND_WATER32:
  9964. case GROUND_WATER33:
  9965. case GROUND_WATER34:
  9966. case GROUND_WATER35:
  9967. case GROUND_WATER36:
  9968. case GROUND_WATER37:
  9969. case GROUND_WATER38:
  9970. case GROUND_WATER39:
  9971. case GROUND_WATER40:
  9972. case GROUND_WATER41:
  9973. case GROUND_WATER42:
  9974. case GROUND_WATER43:
  9975. case GROUND_WATER44:
  9976. spectatorEffect(toPos, NM_ME_LOOSE_ENERGY);
  9977. if(trashItems(player, trash, fromPos, from_stack, count))
  9978. return true;
  9979. break;
  9980. case GROUND_LAVA1:
  9981. case GROUND_LAVA2:
  9982. case GROUND_LAVA3:
  9983. case GROUND_LAVA4:
  9984. spectatorEffect(toPos, NM_ME_HITBY_FIRE);
  9985. if(trashItems(player, trash, fromPos, from_stack, count))
  9986. return true;
  9987. break;
  9988. case GROUND_SWAMP1:
  9989. case GROUND_SWAMP2:
  9990. case GROUND_SWAMP3:
  9991. case GROUND_SWAMP4:
  9992. spectatorEffect(toPos, NM_ME_POISEN_RINGS);
  9993. if(trashItems(player, trash, fromPos, from_stack, count))
  9994. return true;
  9995. break;
  9996. case GROUND_BLACK_SWAMP1:
  9997. case GROUND_BLACK_SWAMP2:
  9998. case GROUND_BLACK_SWAMP3:
  9999. case GROUND_BLACK_SWAMP4:
  10000. spectatorEffect(toPos, NM_ME_MORT_AREA);
  10001. if(trashItems(player, trash, fromPos, from_stack, count))
  10002. return true;
  10003. break;
  10004. }
  10005. }
  10006.  
  10007. return false;
  10008. }
  10009.  
  10010. bool Game::trashItems(Player *player, Item *trash, Position fromPos, int32_t from_stack, unsigned char count)
  10011. {
  10012. //OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::trashItems()");
  10013. if(!trash){return false;}
  10014. if(trash->getID() == 99 || (trash->getID() >= 4329 && trash->getID() <= 4555))
  10015. return false;
  10016. else if(fromPos.x != 0xFFFF && ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  10017. return false;
  10018. else if((player->access < g_config.ACCESS_REMOTE) &&
  10019. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  10020. return false;
  10021.  
  10022. if(trash && player){
  10023. if(trash->isStackable()){
  10024. if(trash->getItemCountOrSubtype() > count){
  10025. trash->setItemCountOrSubtype(trash->getItemCountOrSubtype() - count);
  10026. sendUpdateThing(player,fromPos,trash,from_stack);
  10027. player->updateInventoryWeigth();
  10028. return true;
  10029. }
  10030. else{
  10031. if(removeThing(player, fromPos, trash)){
  10032. player->updateInventoryWeigth();
  10033. return true;
  10034. }
  10035. }
  10036. }
  10037. else{
  10038. if(removeThing(player, fromPos, trash)){
  10039. player->updateInventoryWeigth();
  10040. return true;
  10041. }
  10042. }
  10043. }
  10044. return false;
  10045. }
  10046.  
  10047. bool Game::canTeleportItem(Player *player, unsigned short itemid, Position toPos, Position fromPos, int32_t from_stack, unsigned char count)
  10048. {
  10049. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::canTeleportItem()");
  10050.  
  10051. if(itemid == 99 || (itemid >= 4329 && itemid <= 4555))
  10052. return false;
  10053. else if(fromPos.x != 0xFFFF && ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  10054. return false;
  10055. else if(map->canThrowObjectTo(player->pos, toPos, BLOCK_PROJECTILE) != RET_NOERROR)
  10056. return false;
  10057. else if(toPos.x == 0xFFFF)
  10058. return false;
  10059. else if(!checkChangeFloor(map->getTile(toPos), getTile(toPos.x,toPos.y,toPos.z+1)))
  10060. return false;
  10061. else if((player->access < g_config.ACCESS_REMOTE) &&
  10062. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  10063. return false;
  10064.  
  10065. Item* tpItem = dynamic_cast<Item*>(getThing(fromPos, from_stack, player));
  10066. if(tpItem){
  10067. tpItem->pos = fromPos;
  10068. if((abs(player->pos.x - toPos.x) > tpItem->throwRange) || (abs(player->pos.y - toPos.y) > tpItem->throwRange)) {
  10069. return false;
  10070. }
  10071.  
  10072. if(tpItem->isStackable()){
  10073. if(tpItem->getItemCountOrSubtype() > count){
  10074. tpItem->setItemCountOrSubtype(tpItem->getItemCountOrSubtype() - count);
  10075. Item *newitem = Item::CreateItem(tpItem->getID(), count);
  10076. addThing(player,getTeleportPos(toPos),newitem);
  10077. sendUpdateThing(player,fromPos,tpItem,from_stack);
  10078. player->updateInventoryWeigth();
  10079. return true;
  10080. }
  10081. else{
  10082. if(removeThing(player, fromPos, tpItem)){
  10083. addThing(player,getTeleportPos(toPos),tpItem);
  10084. player->updateInventoryWeigth();
  10085. return true;
  10086. }
  10087. }
  10088. }
  10089. else{
  10090. if(removeThing(player, fromPos, tpItem)){
  10091. addThing(player,getTeleportPos(toPos),tpItem);
  10092. player->updateInventoryWeigth();
  10093. return true;
  10094. }
  10095. }
  10096. }
  10097. return false;
  10098. }
  10099.  
  10100. void Game::spectatorEffect(Position pos, unsigned char type)
  10101. {
  10102. SpectatorVec list;
  10103. SpectatorVec::iterator it;
  10104. getSpectators(Range(pos, true), list);
  10105.  
  10106. for(it = list.begin(); it != list.end(); ++it) {
  10107. if(Player* p = dynamic_cast<Player*>(*it)) {
  10108. p->sendMagicEffect(pos, type);
  10109. }
  10110. }
  10111. }
  10112.  
  10113. bool Game::checkChangeFloor(Tile *toTile, Tile* downTile)
  10114. {
  10115. if(toTile->ground && toTile->ground->floorChangeDown())
  10116. {
  10117. if(downTile){
  10118. if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  10119. return true;
  10120. }
  10121. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  10122. return true;
  10123. }
  10124. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  10125. return true;
  10126. }
  10127. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  10128. return true;
  10129. }
  10130. else if(downTile->floorChange(NORTH)){
  10131. return true;
  10132. }
  10133. else if(downTile->floorChange(SOUTH)){
  10134. return true;
  10135. }
  10136. else if(downTile->floorChange(EAST)){
  10137. return true;
  10138. }
  10139. else if(downTile->floorChange(WEST)){
  10140. return true;
  10141. }
  10142. else if(Item::items[toTile->ground->getID()].floorChangeDown){
  10143. return true;
  10144. }
  10145. else {
  10146. return true;
  10147. }
  10148. }
  10149. }
  10150. else if(toTile->floorChange(NORTH) && toTile->floorChange(EAST)){
  10151. return true;
  10152. }
  10153. else if(toTile->floorChange(NORTH) && toTile->floorChange(WEST)){
  10154. return true;
  10155. }
  10156. else if(toTile->floorChange(SOUTH) && toTile->floorChange(EAST)){
  10157. return true;
  10158. }
  10159. else if(toTile->floorChange(SOUTH) && toTile->floorChange(WEST)){
  10160. return true;
  10161. }
  10162. else if(toTile->floorChange(NORTH)){
  10163. return true;
  10164. }
  10165. else if(toTile->floorChange(SOUTH)){
  10166. return true;
  10167. }
  10168. else if(toTile->floorChange(EAST)){
  10169. return true;
  10170. }
  10171. else if(toTile->floorChange(WEST)){
  10172. return true;
  10173. }
  10174. if(!toTile){
  10175. if(!downTile)
  10176. {
  10177. return false;
  10178. }
  10179. else if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  10180. return true;
  10181. }
  10182. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  10183. return true;
  10184. }
  10185. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  10186. return true;
  10187. }
  10188. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  10189. return true;
  10190. }
  10191. else if(downTile->floorChange(NORTH)){
  10192. return true;
  10193. }
  10194. else if(downTile->floorChange(SOUTH)){
  10195. return true;
  10196. }
  10197. else if(downTile->floorChange(EAST)){
  10198. return true;
  10199. }
  10200. else if(downTile->floorChange(WEST)){
  10201. return true;
  10202. }
  10203. }
  10204. return false;
  10205. }
  10206.  
  10207. Position Game::getTeleportPos(Position to)
  10208. {
  10209. Tile *toTile = map->getTile(to);
  10210.  
  10211. if(toTile->ground && toTile->ground->floorChangeDown())
  10212. {
  10213. Tile* downTile = getTile(to.x, to.y, to.z+1);
  10214. if(downTile){
  10215. //diagonal begin
  10216. if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  10217. return Position(to.x-1, to.y+1, to.z+1);
  10218. }
  10219. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  10220. return Position(to.x+1, to.y+1, to.z+1);
  10221. }
  10222. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  10223. return Position(to.x-1, to.y-1, to.z+1);
  10224. }
  10225. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  10226. return Position(to.x+1, to.y-1, to.z+1);
  10227. }
  10228. //diagonal end
  10229. else if(downTile->floorChange(NORTH)){
  10230. return Position(to.x, to.y+1, to.z+1);
  10231. }
  10232. else if(downTile->floorChange(SOUTH)){
  10233. return Position(to.x, to.y-1, to.z+1);
  10234. }
  10235. else if(downTile->floorChange(EAST)){
  10236. return Position(to.x-1, to.y, to.z+1);
  10237. }
  10238. else if(downTile->floorChange(WEST)){
  10239. return Position(to.x+1, to.y, to.z+1);
  10240. }
  10241. //floor change down
  10242. else if(Item::items[toTile->ground->getID()].floorChangeDown){
  10243. return Position(to.x, to.y, to.z+1);
  10244. }
  10245. else {
  10246. return Position(to.x, to.y, to.z+1);
  10247. }
  10248. }
  10249. }
  10250. //diagonal begin
  10251. else if(toTile->floorChange(NORTH) && toTile->floorChange(EAST)){
  10252. return Position(to.x+1, to.y-1, to.z-1);
  10253. }
  10254. else if(toTile->floorChange(NORTH) && toTile->floorChange(WEST)){
  10255. return Position(to.x-1, to.y-1, to.z-1);
  10256. }
  10257. else if(toTile->floorChange(SOUTH) && toTile->floorChange(EAST)){
  10258. return Position(to.x+1, to.y+1, to.z-1);
  10259. }
  10260. else if(toTile->floorChange(SOUTH) && toTile->floorChange(WEST)){
  10261. return Position(to.x-1, to.y+1, to.z-1);
  10262. }
  10263. else if(toTile->floorChange(NORTH)){
  10264. return Position(to.x, to.y-1, to.z-1);
  10265. }
  10266. else if(toTile->floorChange(SOUTH)){
  10267. return Position(to.x, to.y+1, to.z-1);
  10268. }
  10269. else if(toTile->floorChange(EAST)){
  10270. return Position(to.x+1, to.y, to.z-1);
  10271. }
  10272. else if(toTile->floorChange(WEST)){
  10273. return Position(to.x-1, to.y, to.z-1);
  10274. }
  10275. if(!toTile){
  10276. Tile* downTile = getTile(to.x, to.y, to.z+1);
  10277. if(!downTile)
  10278. {
  10279. return Position(0,0,0);
  10280. }
  10281. else if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  10282. return Position(to.x-2, to.y+2, to.z+1);
  10283. }
  10284. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  10285. return Position(to.x+2, to.y+2, to.z+1);
  10286. }
  10287. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  10288. return Position(to.x-2, to.y-2, to.z+1);
  10289. }
  10290. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  10291. return Position(to.x+2, to.y-2, to.z+1);
  10292. }
  10293. else if(downTile->floorChange(NORTH)){
  10294. return Position(to.x, to.y + 1, to.z+1);
  10295. }
  10296. else if(downTile->floorChange(SOUTH)){
  10297. return Position(to.x, to.y - 1, to.z+1);
  10298. }
  10299. else if(downTile->floorChange(EAST)){
  10300. return Position(to.x - 1, to.y, to.z+1);
  10301. }
  10302. else if(downTile->floorChange(WEST)){
  10303. return Position(to.x + 1, to.y, to.z+1);
  10304. }
  10305. }
  10306. }
  10307. #endif //KOSZ
  10308.  
  10309. void Game::globalMagicEffect(const Position pos, unsigned char type)
  10310. {
  10311. SpectatorVec list;
  10312. SpectatorVec::iterator it;
  10313. getSpectators(Range(pos), list);
  10314. for(it = list.begin(); it != list.end(); ++it){
  10315. Player* p = dynamic_cast<Player*>(*it);
  10316. if(p)
  10317. p->sendMagicEffect(pos, type);
  10318. }
  10319. }
  10320.  
  10321. void Game::checkCreatureFollow(uint32_t id)
  10322. {
  10323. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreatureFollow");
  10324. Player *player = getPlayerByID(id);
  10325. if(!player)
  10326. return;
  10327. if(!player->pathList.empty()) {
  10328. Creature *followCreature = getCreatureByID(player->followCreature);
  10329. if(followCreature == 0)
  10330. return;
  10331. if((std::abs(player->pos.x - followCreature->pos.x) > 7) ||
  10332. (std::abs(player->pos.y - followCreature->pos.y) > 5) || (player->pos.z != followCreature->pos.z)){
  10333. player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  10334. player->eventCheckFollow = 0;
  10335. player->followCreature = 0;
  10336. playerSetAttackedCreature(player, 0);
  10337. return;
  10338. }
  10339. if(followCreature && abs(followCreature->pos.x - player->pos.x) <= 1 && abs(followCreature->pos.y - player->pos.y) <= 1) player->pathList.clear();
  10340. else {
  10341. Position toPos = player->pathList.front();
  10342. player->pathList.pop_front();
  10343. player->lastmove = OTSYS_TIME();
  10344. this->thingMove(player, player, toPos.x, toPos.y, player->pos.z, 1);
  10345. flushSendBuffers();
  10346. }
  10347. }
  10348. if(!player->pathList.empty()) {
  10349. long long delay = player->getSleepTicks();
  10350. stopEvent(player->eventCheckFollow);
  10351. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollow), id)));
  10352. } else {
  10353. player->eventCheckFollow = 0;
  10354. }
  10355. }
  10356. void Game::checkCreatureFollowAttack(uint32_t id)
  10357. {
  10358. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreatureFollowAttack");
  10359. Player *player = getPlayerByID(id);
  10360. if(!player)
  10361. return;
  10362. if(!player->pathList.empty()) {
  10363. Creature *followCreature = getCreatureByID(player->followCreature);
  10364. if(followCreature == 0)
  10365. return;
  10366. if(player->followMode == 0x00) {
  10367. stopEvent(player->eventCheckFollow);
  10368. player->eventCheckFollow = 0;
  10369. player->followCreature = 0;
  10370. return;
  10371. }
  10372. if((std::abs(player->pos.x - followCreature->pos.x) > 7) ||
  10373. (std::abs(player->pos.y - followCreature->pos.y) > 5) || (player->pos.z != followCreature->pos.z)){
  10374. player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  10375. player->eventCheckFollow = 0;
  10376. player->followCreature = 0;
  10377. playerSetAttackedCreature(player, 0);
  10378. return;
  10379. }
  10380. if(followCreature && abs(followCreature->pos.x - player->pos.x) <= 1 && abs(followCreature->pos.y - player->pos.y) <= 1) player->pathList.clear();
  10381. else {
  10382. Position toPos = player->pathList.front();
  10383. player->pathList.pop_front();
  10384. player->lastmove = OTSYS_TIME();
  10385. this->thingMove(player, player, toPos.x, toPos.y, player->pos.z, 1);
  10386. flushSendBuffers();
  10387. }
  10388. }
  10389. if(!player->pathList.empty()) {
  10390. long long delay = player->getSleepTicks();
  10391. stopEvent(player->eventCheckFollow);
  10392. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollowAttack), id)));
  10393. } else {
  10394. player->eventCheckFollow = 0;
  10395. }
  10396. }
  10397. void Game::playerFollow(Player* player, Creature *followCreature)
  10398. {
  10399. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerFollow()");
  10400. if(followCreature->isRemoved || player->isRemoved || !player || !followCreature){
  10401. player->eventCheckFollow = 0;
  10402. player->followCreature = 0;
  10403. return;
  10404. }
  10405. player->pathList = getPathToEx(player, player->pos, followCreature->pos, false);
  10406. long long delay = player->getSleepTicks();
  10407. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollow), player->getID())));
  10408. }
  10409. void Game::playerFollowAttacking(Player* player, Creature *followCreature)
  10410. {
  10411. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerFollow()");
  10412. if(followCreature->isRemoved || player->isRemoved || !player || !followCreature){
  10413. player->eventCheckFollow = 0;
  10414. player->followCreature = 0;
  10415. return;
  10416. }
  10417. if(player->followMode == 0x00) {
  10418. stopEvent(player->eventCheckFollow);
  10419. player->eventCheckFollow = 0;
  10420. player->followCreature = 0;
  10421. return;
  10422. }
  10423. player->pathList = getPathToEx(player, player->pos, followCreature->pos, false);
  10424. long long delay = player->getSleepTicks();
  10425. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollowAttack), player->getID())));
  10426. }
  10427. void Game::playerSetFollowCreature(Player* player, uint32_t creatureid)
  10428. {
  10429. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerSetFollowCreature()");
  10430. if(player->isRemoved || !player)
  10431. return;
  10432. if(creatureid == 0) {
  10433. stopEvent(player->eventCheckFollow);
  10434. player->eventCheckFollow = 0;
  10435. player->followCreature = 0;
  10436. }
  10437. Creature* followCreature = NULL;
  10438. if(creatureid != 0) {
  10439. followCreature = getCreatureByID(creatureid);
  10440. }
  10441. if(followCreature) {
  10442. player->followCreature = followCreature->getID();
  10443. stopEvent(player->eventCheckFollow);
  10444. playerFollow(player, followCreature);
  10445. }
  10446. }
  10447. void Game::playerAttackSetFollowCreature(Player* player, uint32_t creatureid)
  10448. {
  10449. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerAttackSetFollowCreature()");
  10450. if(player->isRemoved || !player)
  10451. return;
  10452. if(player->followMode == 0x00) {
  10453. return;
  10454. }
  10455. if(creatureid == 0) {
  10456. stopEvent(player->eventCheckFollow);
  10457. player->eventCheckFollow = 0;
  10458. player->followCreature = 0;
  10459. }
  10460. Creature* followCreature = NULL;
  10461. if(creatureid != 0) {
  10462. followCreature = getCreatureByID(creatureid);
  10463. }
  10464. if(followCreature) {
  10465. player->followCreature = followCreature->getID();
  10466. stopEvent(player->eventCheckFollow);
  10467. playerFollowAttacking(player, followCreature);
  10468. }
  10469. }
  10470.  
  10471. #ifdef HUCZU_AUTORESTART
  10472. void Game::beforeRestart()
  10473. {
  10474. sheduleShutdown(5);
  10475. }
  10476. #endif
  10477.  
  10478. void Game::creatureUseShop(Creature *creature, int id, int count, std::string way){
  10479. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureUseShop()");
  10480.  
  10481. int stackpos = map->getTile(creature->pos)->getThingStackPos(creature);
  10482.  
  10483. SpectatorVec list;
  10484. SpectatorVec::iterator it;
  10485.  
  10486. map->getSpectators(Range(creature->pos, true), list);
  10487.  
  10488. for(it = list.begin(); it != list.end(); ++it) {
  10489. if(dynamic_cast<Npc*>(*it)) {
  10490. (*it)->onCreatureUseShop(creature, id, count, way);
  10491. }
  10492. }
  10493. }
Add Comment
Please, Sign In to add comment