Guest User

Untitled

a guest
Mar 28th, 2020
239
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 348.98 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(player && atype == ATTACK_PHYSICAL) {
  113. if(player->getVocation() == VOCATION_KNIGHT) {
  114. newDamage -= newDamage * (0.01 * (double)g_config.KNIGHT_LOOSE);
  115. } else if(player->getVocation() == VOCATION_PALADIN) {
  116. std::cout << "Before " << newDamage << std::endl;
  117. newDamage += newDamage * (0.01 * (double)g_config.PALADIN_RAISE);
  118. std::cout << "After " << newDamage << std::endl;
  119. }
  120. } else if(player) {
  121. std::cout << "atype " << atype << std::endl;
  122. }
  123.  
  124. if (necklace && necklace->getCharges() > 0)
  125. {
  126. if (necklace->getID() == ITEM_STONE_SKIN_AMULET)
  127. {
  128. newDamage *= 0.10;
  129. necklace->useCharge();
  130. }
  131.  
  132. else if (necklace->getID() == ITEM_PROTECTION_AMULET)
  133. {
  134. newDamage *= 0.80;
  135. necklace->useCharge();
  136. }
  137.  
  138. else if ((necklace->getID() == ITEM_DRAGON_NECKLACE && (atype & ATTACK_FIRE)) ||
  139. (necklace->getID() == ITEM_SILVER_AMULET && (atype & ATTACK_POISON)) ||
  140. (necklace->getID() == ITEM_STRANGE_TALISMAN && (atype & ATTACK_ENERGY)) ||
  141. (necklace->getID() == ITEM_ELVEN_AMULET))
  142. {
  143. newDamage *= 0.8;
  144. necklace->useCharge();
  145. }
  146.  
  147.  
  148. else if ((necklace->getID() == ITEM_MAGMA_AMULET && (atype & ATTACK_FIRE)))
  149. {
  150. newDamage *= 0.7;
  151. necklace->useCharge();
  152. }
  153.  
  154.  
  155. #ifdef YUR_DRAINS
  156. else if (necklace->getID() == ITEM_BRONZE_AMULET && (atype & ATTACK_MANADRAIN))
  157. {
  158. newDamage *= 0.5;
  159. necklace->useCharge();
  160. }
  161.  
  162. else if (necklace->getID() == ITEM_GARLIC_NECKLACE && (atype & ATTACK_LIFEDRAIN))
  163. {
  164. newDamage = 0.5;
  165. necklace->useCharge();
  166. }
  167.  
  168. #endif //YUR_DRAINS
  169.  
  170. if (necklace->getCharges() <= 0)
  171. player->removeItemInventory(SLOT_NECKLACE);
  172. }
  173.  
  174. if (ring && ring->getCharges() > 0)
  175. {
  176. if (ring->getID() == ITEM_MIGHT_RING)
  177. {
  178. newDamage *= 0.8;
  179. ring->useCharge();
  180. }
  181.  
  182. if (ring->getCharges() <= 0)
  183. player->removeItemInventory(SLOT_RING);
  184. }
  185. #ifdef HUCZU_FIX
  186. if(armor)
  187. {
  188. if(armor->getID() == ITEM_FIRE_ARMOR && (atype & ATTACK_FIRE))
  189. newDamage *= 0.8;
  190. }
  191. #endif //HUCZU_FIX
  192.  
  193. return (int32_t)newDamage;
  194. }
  195. #endif //YUR_RINGS_AMULETS
  196.  
  197. void GameState::onAttack(Creature* attacker, const Position& pos, const MagicEffectClass* me)
  198. {
  199. Tile *tile = game->map->getTile(pos);
  200.  
  201. if(!tile)
  202. return;
  203.  
  204. #ifdef YUR_PVP_ARENA
  205. CreatureVector arenaLosers;
  206. #endif //YUR_PVP_ARENA
  207.  
  208. CreatureVector::iterator cit;
  209. Player* attackPlayer = dynamic_cast<Player*>(attacker);
  210. Creature *targetCreature = NULL;
  211. Player *targetPlayer = NULL;
  212. for(cit = tile->creatures.begin(); cit != tile->creatures.end(); ++cit) {
  213. targetCreature = (*cit);
  214. targetPlayer = dynamic_cast<Player*>(targetCreature);
  215. bool pvpArena = false;
  216. #ifdef TR_SUMMONS
  217. bool targetIsSummon = (targetCreature && targetCreature->isPlayersSummon());
  218. bool summonVsPlayer = (attacker && attacker->isPlayersSummon() && targetPlayer);
  219. #endif //TR_SUMMONS
  220.  
  221. int32_t damage = me->getDamage(targetCreature, attacker);
  222. int32_t manaDamage = 0;
  223.  
  224. if(attackPlayer){
  225. if(!me->offensive && me->minDamage != 0 && g_config.getGlobalString("showHealingDamage") == "yes"){
  226. int32_t lecz = std::min(std::abs(damage), attackPlayer->healthmax - attackPlayer->health);
  227. std::stringstream anidamage;
  228. anidamage << "+" << lecz;
  229. if(lecz != 0)
  230. game->sendAnimatedTextExt(attackPlayer->pos, 96, anidamage.str().c_str());
  231. }
  232. }
  233.  
  234. #ifdef YUR_RINGS_AMULETS
  235. damage = applyAmulets(targetPlayer, damage, me->attackType);
  236. #endif //YUR_RINGS_AMULETS
  237.  
  238. if (damage > 0) {
  239. if(attackPlayer && attackPlayer->access < g_config.ACCESS_PROTECT) {
  240. if(targetPlayer && targetPlayer != attackPlayer && game->getWorldType() != WORLD_TYPE_NO_PVP)
  241. attackPlayer->pzLocked = true;
  242. }
  243.  
  244. if(targetCreature->access < g_config.ACCESS_PROTECT && targetPlayer && game->getWorldType() != WORLD_TYPE_NO_PVP)
  245. {
  246. #ifdef YUR_CVS_MODS
  247. targetPlayer->inFightTicks = std::max(g_config.PZ_LOCKED, targetPlayer->inFightTicks);
  248. #else
  249. targetPlayer->inFightTicks = g_config.PZ_LOCKED;
  250. #endif //YUR_CVS_MODS
  251. targetPlayer->sendIcons();
  252. }
  253. #ifdef SURVIVAL_BLACKSQUARE
  254. if(damage > 0 && attackPlayer && targetPlayer && attackPlayer != targetPlayer){
  255. NetworkMessage attackedpmsg;
  256. attackedpmsg.AddPlayerAttacked(attacker);
  257. targetPlayer->sendNetworkMessage(&attackedpmsg);
  258. }
  259. #endif //SURVIVAL_BLACKSQUARE
  260.  
  261. #ifdef YUR_PVP_ARENA
  262. pvpArena = isPvpArena(attacker) && isPvpArena(targetCreature);
  263. #endif //YUR_PVP_ARENA
  264.  
  265. #ifdef TR_SUMMONS
  266. if ((game->getWorldType() == WORLD_TYPE_NO_PVP && !pvpArena && summonVsPlayer) ||
  267. (game->getWorldType() == WORLD_TYPE_NO_PVP && !pvpArena && attackPlayer && (targetPlayer || targetIsSummon) && attackPlayer->access < g_config.ACCESS_PROTECT)) {
  268. #else
  269. if(game->getWorldType() == WORLD_TYPE_NO_PVP && !pvpArena && attackPlayer && targetPlayer && attackPlayer->access < ACCESS_PROTECT){
  270. #endif //TR_SUMMONS
  271. damage = 0;
  272. }
  273. }
  274.  
  275. if (damage != 0)
  276. {
  277. // Bedzie pro ustawione all
  278. #ifdef HUCZU_FIX
  279. if(attackPlayer){
  280. Item* armor = attackPlayer->getItem(SLOT_ARMOR);
  281. Item* legs = attackPlayer->getItem(SLOT_LEGS);
  282. Item* helmet = attackPlayer->getItem(SLOT_HEAD);
  283. Item* boots = attackPlayer->getItem(SLOT_FEET);
  284. Item* ring = attackPlayer->getItem(SLOT_RING);
  285. Item* amulet = attackPlayer->getItem(SLOT_NECKLACE);
  286.  
  287. if(attackPlayer->vocation == 1 || attackPlayer->vocation == 2){
  288. if(armor){
  289. if(armor->getID() == ITEM_GLACIER_ROBE){
  290. double newdamage = damage*2/100.0;
  291. damage += (int32_t)newdamage;
  292. }
  293. else if(armor->getID() == ITEM_ARCHMAGE_COAT){
  294. double newdamage = damage*5/100.0;
  295. damage += (int32_t)newdamage;
  296. }
  297. else if(armor->getID() == ITEM_BMC){
  298. double newdamage = damage*3/100.0;
  299. damage += (int32_t)newdamage;
  300. }
  301. }
  302. if(legs){
  303. if(legs->getID() == ITEM_GLACIER_KIT){
  304. double newdamage = damage*2/100.0;
  305. damage += (int32_t)newdamage;
  306. }
  307. }
  308. }
  309.  
  310. if(legs){
  311. if(legs->getID() == ITEM_ZS_LEGS){
  312. double newdamage = damage*10/100.0;
  313. damage += (int32_t)newdamage;
  314. }
  315. }
  316.  
  317. if(g_config.MGITEMS){
  318. if(helmet && helmet->getID() == g_config.MGITEMHELMET){
  319. double newdamage = damage*g_config.ITEM_MDOWNHELMET/100.0;
  320. damage += (int32_t)newdamage;
  321. }
  322. if(armor && armor->getID() == g_config.MGITEMARMOR){
  323. double newdamage = damage*g_config.ITEM_MDOWNARMOR/100.0;
  324. damage += (int32_t)newdamage;
  325. }
  326. if(legs && legs->getID() == g_config.MGITEMLEGS){
  327. double newdamage = damage*g_config.ITEM_MDOWNLEGS/100.0;
  328. damage += (int32_t)newdamage;
  329. }
  330. if(boots && boots->getID() == g_config.MGITEMBOOTS){
  331. double newdamage = damage*g_config.ITEM_MDOWNBOOTS/100.0;
  332. damage += (int32_t)newdamage;
  333. }
  334. if(ring && ring->getID() == g_config.MGITEMRINGS){
  335. double newdamage = damage*g_config.ITEM_MDOWNRING/100.0;
  336. damage += (int32_t)newdamage;
  337. }
  338. if(amulet && amulet->getID() == g_config.MGITEMAMU){
  339. double newdamage = damage*g_config.ITEM_MDOWNAMU/100.0;
  340. damage += (int32_t)newdamage;
  341. }
  342. }
  343. }
  344. #endif //HUCZU_FIX i git w chuj
  345.  
  346. #ifdef YUR_DRAINS
  347. if (me->attackType & ATTACK_MANADRAIN)
  348. {
  349. manaDamage = std::min(damage, targetCreature->mana);
  350. targetCreature->drainMana(manaDamage);
  351. damage = 0;
  352. }
  353. else
  354. #endif //YUR_DRAINS
  355. {
  356. game->creatureApplyDamage(targetCreature, damage, damage, manaDamage
  357. #ifdef YUR_PVP_ARENA
  358. , (pvpArena? &arenaLosers : NULL)
  359. #endif //YUR_PVP_ARENA
  360. );
  361. }
  362.  
  363. #ifdef YUR_DRAINS
  364. if (me->attackType & ATTACK_LIFEDRAIN)
  365. {
  366. attacker->health = std::min(attacker->healthmax, attacker->health + damage);
  367. addCreatureState(tile, attacker, 0, 0, false); // update attacker health
  368. }
  369. #endif //YUR_DRAINS
  370.  
  371. #ifdef YUR_INVISIBLE
  372. if (targetCreature && !targetPlayer)
  373. {
  374. targetCreature->setInvisible(0);
  375. game->creatureChangeOutfit(targetCreature);
  376. }
  377. #endif //YUR_INVISIBLE
  378. }
  379.  
  380. #ifdef HUCZU_SKULLS
  381. if (me->offensive && game->getWorldType() == WORLD_TYPE_PVP)
  382. game->onPvP(attacker, targetCreature, targetCreature->health <= 0);
  383. #endif
  384.  
  385. addCreatureState(tile, targetCreature, damage, manaDamage, me->drawblood);
  386. }
  387.  
  388. //Solid ground items/Magic items (fire/poison/energy)
  389. MagicEffectItem *newmagicItem = me->getMagicItem(attacker, tile->isPz(),
  390. (tile->isBlocking(BLOCK_SOLID, true) != RET_NOERROR));
  391.  
  392. if(newmagicItem) {
  393.  
  394. MagicEffectItem *magicItem = tile->getFieldItem();
  395.  
  396. if(magicItem) {
  397. //Replace existing magic field
  398. magicItem->transform(newmagicItem);
  399.  
  400. int32_t stackpos = tile->getThingStackPos(magicItem);
  401. if(tile->removeThing(magicItem)) {
  402.  
  403. SpectatorVec list;
  404. SpectatorVec::iterator it;
  405.  
  406. game->getSpectators(Range(pos, true), list);
  407.  
  408. //players
  409. for(it = list.begin(); it != list.end(); ++it) {
  410. if(dynamic_cast<Player*>(*it)) {
  411. (*it)->onThingDisappear(magicItem, stackpos);
  412. }
  413. }
  414.  
  415. //none-players
  416. for(it = list.begin(); it != list.end(); ++it) {
  417. if(!dynamic_cast<Player*>(*it)) {
  418. (*it)->onThingDisappear(magicItem, stackpos);
  419. }
  420. }
  421.  
  422. tile->addThing(magicItem);
  423.  
  424. //players
  425. for(it = list.begin(); it != list.end(); ++it) {
  426. if(dynamic_cast<Player*>(*it)) {
  427. (*it)->onThingAppear(magicItem);
  428. }
  429. }
  430.  
  431. //none-players
  432. for(it = list.begin(); it != list.end(); ++it) {
  433. if(!dynamic_cast<Player*>(*it)) {
  434. (*it)->onThingAppear(magicItem);
  435. }
  436. }
  437. }
  438. }
  439. else {
  440. magicItem = new MagicEffectItem(*newmagicItem);
  441. magicItem->useThing();
  442. magicItem->pos = pos;
  443.  
  444. tile->addThing(magicItem);
  445.  
  446. SpectatorVec list;
  447. SpectatorVec::iterator it;
  448.  
  449. game->getSpectators(Range(pos, true), list);
  450.  
  451. //players
  452. for(it = list.begin(); it != list.end(); ++it) {
  453. if(dynamic_cast<Player*>(*it)) {
  454. (*it)->onThingAppear(magicItem);
  455. }
  456. }
  457.  
  458. //none-players
  459. for(it = list.begin(); it != list.end(); ++it) {
  460. if(!dynamic_cast<Player*>(*it)) {
  461. (*it)->onThingAppear(magicItem);
  462. }
  463. }
  464.  
  465. magicItem->isRemoved = false;
  466. game->startDecay(magicItem);
  467. }
  468. }
  469.  
  470. //Clean up
  471. for(CreatureStateVec::const_iterator csIt = creaturestates[tile].begin(); csIt != creaturestates[tile].end(); ++csIt) {
  472. onAttackedCreature(tile, attacker, csIt->first, csIt->second.damage, csIt->second.drawBlood);
  473. }
  474.  
  475. if(attackPlayer && attackPlayer->access < g_config.ACCESS_PROTECT) {
  476. //Add exhaustion
  477. if(me->causeExhaustion(true) /*!areaTargetVec.empty())*/)
  478. {
  479. attackPlayer->exhaustedTicks = g_config.EXHAUSTED;
  480. }
  481.  
  482. //Fight symbol
  483. if(me->offensive /*&& !areaTargetVec.empty()*/)
  484. {
  485. #ifdef YUR_CVS_MODS
  486. attackPlayer->inFightTicks = std::max(g_config.PZ_LOCKED, attackPlayer->inFightTicks);
  487. #else
  488. attackPlayer->inFightTicks = g_config.PZ_LOCKED;
  489. #endif //YUR_CVS_MODS
  490. }
  491. }
  492.  
  493. #ifdef YUR_PVP_ARENA
  494. for (CreatureVector::iterator it = arenaLosers.begin(); it != arenaLosers.end(); ++it)
  495. {
  496. Tile* tile = game->getTile((*it)->pos);
  497.  
  498. if (tile)
  499. {
  500. game->teleport(*it, tile->getPvpArenaExit());
  501. }
  502.  
  503. if(Monster* monster = dynamic_cast<Monster*>(*it))
  504. {
  505. if(Tile *tile = game->map->getTile(monster->pos))
  506. {
  507. if(tile->isPvpArena())
  508. {
  509. game->removeCreature(monster);
  510. }
  511. }
  512. }
  513. }
  514. #endif //YUR_PVP_ARENA
  515. }
  516.  
  517. void GameState::onAttack(Creature* attacker, const Position& pos, Creature* attackedCreature)
  518. {
  519. bool pvpArena = false;
  520. #ifdef YUR_PVP_ARENA
  521. CreatureVector arenaLosers;
  522. pvpArena = isPvpArena(attacker) && isPvpArena(attackedCreature);
  523. #endif //YUR_PVP_ARENA
  524.  
  525. //TODO: Decent formulas and such...
  526. int32_t damage = attacker->getWeaponDamage();
  527. int32_t armor = attackedCreature->getArmor();
  528. int32_t defense = attackedCreature->getDefense();
  529.  
  530. Player* attackPlayer = dynamic_cast<Player*>(attacker);
  531. Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  532.  
  533. if(attackedPlayer)
  534. attackedPlayer->addSkillShieldTry(1);
  535.  
  536. int32_t probability = rand() % 10000;
  537.  
  538. #ifdef YUR_CVS_MODS
  539. if(probability * damage < defense * 3000)
  540. damage = 0;
  541. else
  542. damage -= (int32_t)((damage*(armor/50.0)*(rand()/(RAND_MAX+1.0))) + (armor*2) + defense/1.5);
  543. //damage -= (int32_t)((armor)*(rand()/(RAND_MAX+1.0))) + armor; // wik's
  544. #else
  545. if(probability * damage < defense * 10000)
  546. damage = 0;
  547. else
  548. {
  549. damage -= (armor * (10000 + rand() % 10000)) / 10000;
  550. }
  551. #endif //YUR_CVS_MODS
  552.  
  553. int32_t manaDamage = 0;
  554.  
  555. if(attackPlayer && attackedPlayer){
  556. damage -= (int32_t) damage / 2;
  557. }
  558.  
  559.  
  560. if (attacker->access >= g_config.ACCESS_PROTECT)
  561. damage += 1;
  562.  
  563.  
  564. Tile* tile = game->map->getTile(pos);
  565. bool blood;
  566. if(damage > 0)
  567. {
  568. // F-AXE,F-SWORD,P-DAGGER
  569. if(attackPlayer)
  570. {
  571. for (int32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++)
  572. {
  573. if(g_config.EFFECT_ATACK && attackPlayer->getItem(slot) && (attackPlayer->getItem(slot)->getID() == ITEM_FAXE || attackPlayer->getItem(slot)->getID() == ITEM_FSWORD))
  574. {
  575. game->CreateCondition(attackedCreature, attacker, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 5, 5, 2000, 1);
  576. }
  577. if(g_config.EFFECT_ATACK && attackPlayer->getItem(slot) && (attackPlayer->getItem(slot)->getID() == ITEM_PD))
  578. {
  579. game->CreateCondition(attackedCreature, attacker, 30, NM_ME_POISEN_RINGS, NM_ME_POISEN_RINGS, ATTACK_POISON, true, 5, 5, 2000, 3);
  580. }
  581. }
  582. }
  583.  
  584. // P-BOLT ENERGY
  585. if(attackPlayer)
  586. {
  587. int32_t slot = SLOT_AMMO;
  588. if(g_config.EFFECT_ATACK && attackPlayer->getItem(slot) && (attackPlayer->getItem(slot)->getID() == 5260))
  589. {
  590. game->CreateCondition(attackedCreature, attacker, 35, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 10, 10, 2000, 1);
  591. }
  592. }
  593.  
  594. #ifdef YUR_ICE_RAPIER
  595. if (attackPlayer)
  596. for (int32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++)
  597. if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->getID() == ITEM_ICE_RAPIER)
  598. attackPlayer->removeItemInventory(slot);
  599. #endif //YUR_ICE_RAPIER
  600.  
  601. #ifdef PALL_REQ_LVL
  602. if (attackPlayer){
  603. for (int32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++){
  604. if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->isWeapon() && attackPlayer->getItem(slot)->getReqLevel() > attackPlayer->getLevel())
  605. {
  606. int32_t newdamage = attackPlayer->getWeaponDamage() / random_range(4, 7);
  607. if (attackPlayer->getWeaponDamage() >= 7)
  608. damage = 0;
  609. else
  610. damage = newdamage;
  611. }
  612. if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->getAmuType() != 0 && attackPlayer->getItem(slot)->getReqLevel() > attackPlayer->getLevel())
  613. {
  614. int32_t newdamage = attackPlayer->getWeaponDamage() / random_range(4, 7);
  615. if (attackPlayer->getWeaponDamage() >= 7)
  616. damage = 0;
  617. else
  618. damage = newdamage;
  619. }
  620. if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->isWeapon() && attackPlayer->getItem(slot)->getReqVoc() != attackPlayer->getVocation() && attackPlayer->getItem(slot)->getReqVoc() > 0)
  621. {
  622. int32_t newdamage = attackPlayer->getWeaponDamage() / random_range(4, 9);
  623. if (attackPlayer->getWeaponDamage() >= 7)
  624. damage = 0;
  625. else
  626. damage = newdamage;
  627. }
  628. }
  629. }
  630. #endif //PALL_REQ_LVL
  631.  
  632. #ifdef YUR_RINGS_AMULETS
  633. damage = applyAmulets(attackedPlayer, damage, ATTACK_PHYSICAL);
  634. #endif //YUR_RINGS_AMULETS
  635.  
  636.  
  637. #ifdef CHRIS_CRIT_HIT
  638. if(attackPlayer){
  639. int32_t critcial_hit;
  640. int32_t rand_hit = random_range(0, 700);
  641. switch(rand_hit){
  642. case 75:
  643. critcial_hit = random_range(50, 100);
  644. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  645. break;
  646. case 87:
  647. critcial_hit = random_range(50, 100);
  648. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  649. break;
  650. case 95:
  651. critcial_hit = random_range(50, 100);
  652. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  653. break;
  654. case 113:
  655. critcial_hit = random_range(80, 130);
  656. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  657. break;
  658. case 128:
  659. critcial_hit = random_range(80, 130);
  660. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  661. break;
  662. case 133:
  663. critcial_hit = random_range(80, 130);
  664. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  665. break;
  666. case 145:
  667. critcial_hit = random_range(80, 130);
  668. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  669. break;
  670. case 157:
  671. critcial_hit = random_range(80, 130);
  672. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  673. break;
  674. case 167:
  675. critcial_hit = random_range(80, 130);
  676. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  677. break;
  678. case 187:
  679. critcial_hit = random_range(80, 130);
  680. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  681. break;
  682. case 195:
  683. critcial_hit = random_range(80, 130);
  684. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  685. break;
  686. case 202:
  687. critcial_hit = random_range(110, 160);
  688. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  689. break;
  690. case 225:
  691. critcial_hit = random_range(110, 160);
  692. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  693. break;
  694. case 238:
  695. critcial_hit = random_range(110, 160);
  696. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  697. break;
  698. case 245:
  699. critcial_hit = random_range(110, 160);
  700. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  701. break;
  702. case 268:
  703. critcial_hit = random_range(110, 160);
  704. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  705. break;
  706. case 287:
  707. critcial_hit = random_range(110, 160);
  708. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  709. break;
  710. case 298:
  711. critcial_hit = random_range(110, 160);
  712. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  713. break;
  714. case 324:
  715. critcial_hit = random_range(140, 400);
  716. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  717. break;
  718. case 356:
  719. critcial_hit = random_range(140, 190);
  720. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  721. break;
  722. case 371:
  723. critcial_hit = random_range(140, 190);
  724. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  725. break;
  726. case 380:
  727. critcial_hit = random_range(140, 190);
  728. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  729. break;
  730. case 397:
  731. critcial_hit = random_range(140, 190);
  732. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  733. break;
  734. case 399:
  735. critcial_hit = random_range(140, 190);
  736. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  737. break;
  738. case 400:
  739. critcial_hit = random_range(170, 210);
  740. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  741. break;
  742. case 428:
  743. critcial_hit = random_range(170, 210);
  744. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  745. break;
  746. case 432:
  747. critcial_hit = random_range(170, 210);
  748. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  749. break;
  750. case 444:
  751. critcial_hit = random_range(170, 210);
  752. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  753. break;
  754. case 474:
  755. critcial_hit = random_range(170, 210);
  756. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  757. break;
  758. default:
  759. critcial_hit = 0;
  760. break;
  761. }
  762.  
  763. if (attackPlayer->vocation == 4){
  764. if(critcial_hit != 0){
  765. if(attackPlayer->level >= 150){
  766. if(attackPlayer && attackPlayer->items[SLOT_RIGHT] && attackPlayer->items[SLOT_RIGHT]->getID() == ITEM_RAINBOW){
  767. if(attackPlayer->items[SLOT_LEFT]){
  768. if(attackPlayer->items[SLOT_LEFT]->getID() != ITEM_RAINBOW)
  769. critcial_hit += critcial_hit*(25/100);
  770. game->CreateCondition(attackedCreature, attacker, 35, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 25, 25, 1000, 1);
  771. }
  772. }
  773. }
  774. if(attackPlayer && attackPlayer->items[SLOT_LEFT] && attackPlayer->items[SLOT_LEFT]->getID() == ITEM_RAINBOW){
  775. if(attackPlayer->items[SLOT_RIGHT]){
  776. if(attackPlayer->items[SLOT_RIGHT]->getID() != ITEM_RAINBOW)
  777. critcial_hit += critcial_hit*(25/100);
  778. game->CreateCondition(attackedCreature, attacker, 35, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 25, 25, 1000, 1);
  779. }
  780. }
  781. }
  782. damage += critcial_hit;
  783. }
  784. }
  785.  
  786. #endif //CHRIS_CRIT_HIT
  787.  
  788. game->creatureApplyDamage(attackedCreature, damage, damage, manaDamage
  789.  
  790.  
  791. #ifdef YUR_PVP_ARENA
  792. , (pvpArena? &arenaLosers : NULL)
  793. #endif //YUR_PVP_ARENA
  794. );
  795.  
  796. #ifdef HUCZU_SKULLS
  797. if (game->getWorldType() == WORLD_TYPE_PVP)
  798. game->onPvP(attacker, attackedCreature, attackedCreature->health <= 0);
  799. #endif
  800.  
  801. blood = true;
  802.  
  803. if(attackPlayer && attackPlayer->maxDmg < damage) {
  804. attackPlayer->maxDmg = (int32_t) damage;
  805. std::stringstream MaxDmgMsg;
  806. MaxDmgMsg << "Your new best damage is " << attackPlayer->maxDmg << ".";
  807. attackPlayer->sendTextMessage(MSG_ADVANCE, MaxDmgMsg.str().c_str());
  808. }
  809. }
  810. else{//no draw blood
  811. blood = false;
  812. }
  813.  
  814. addCreatureState(tile, attackedCreature, damage, manaDamage, blood);
  815. onAttackedCreature(tile, attacker, attackedCreature, damage, true);
  816.  
  817. /*
  818. if (attackPlayer && attackPlayer->isUsingSpears() && random_range(1,100000) > g_config.SPEAR_LOSE_CHANCE)
  819. {
  820. Item* spear = Item::CreateItem(ITEM_SPEAR, 1);
  821. spear->pos = attackedCreature->pos;
  822. game->addThing(attackPlayer, spear->pos, spear);
  823. }
  824. */
  825.  
  826. #ifdef YUR_PVP_ARENA
  827. for (CreatureVector::iterator it = arenaLosers.begin(); it != arenaLosers.end(); ++it){
  828. Tile* tile = game->getTile((*it)->pos);
  829. if (tile){
  830. game->teleport(*it, tile->getPvpArenaExit());
  831. }
  832. if(Monster* monster = dynamic_cast<Monster*>(*it)){
  833. if(Tile *tile = game->map->getTile(monster->pos)){
  834. if(tile->isPvpArena()){
  835. game->removeCreature(monster);
  836. }
  837. }
  838. }
  839. }
  840. #endif //YUR_PVP_ARENA
  841. }
  842.  
  843. void GameState::addCreatureState(Tile* tile, Creature* attackedCreature, int32_t damage, int32_t manaDamage, bool drawBlood)
  844. {
  845. CreatureState cs;
  846. cs.damage = damage;
  847. cs.manaDamage = manaDamage;
  848. cs.drawBlood = drawBlood;
  849.  
  850. creaturestates[tile].push_back( make_pair(attackedCreature, cs) );
  851. }
  852.  
  853. void GameState::onAttackedCreature(Tile* tile, Creature *attacker, Creature* attackedCreature, int32_t damage, bool drawBlood)
  854. {
  855. Player *attackedplayer = dynamic_cast<Player*>(attackedCreature);
  856. Position CreaturePos = attackedCreature->pos;
  857.  
  858. #ifdef TJ_MONSTER_BLOOD
  859. bool dead = false;
  860. #endif //TJ_MONSTER_BLOOD
  861.  
  862. #ifdef TR_SUMMONS
  863. //Summon exp share by Yurez
  864. Player *player = dynamic_cast<Player*>(attacker);
  865. Creature* attackerMaster = attacker? attacker->getMaster() : NULL;
  866. if(attackerMaster && dynamic_cast<Player*>(attackerMaster)){//attacker is players summon
  867. attackedCreature->addInflictedDamage(attacker, damage/2);
  868. attackedCreature->addInflictedDamage(attackerMaster, damage/2);
  869. }// end summon exp share
  870. else if(player && player->party != 0){
  871. int32_t partySize = 0;
  872. SpectatorVec list;
  873. SpectatorVec::iterator it;
  874. game->getSpectators(Range(player->pos), list);
  875. /*Get all specatators around this player
  876. then check if they are in his party*/
  877. for(it = list.begin(); it != list.end(); ++it){//find number too div by
  878. Player* p = dynamic_cast<Player*>(*it);
  879. if(p && p->party == player->party)//huczu_fix
  880. partySize++;
  881. }
  882. for(it = list.begin(); it != list.end(); ++it){
  883. Player* p = dynamic_cast<Player*>(*it);
  884. if(p && p->party == player->party && partySize != 0/*dont div by 0*/)//same party add exp, huczu_fix
  885. attackedCreature->addInflictedDamage(p, damage/partySize);
  886. }
  887. }
  888. else
  889. attackedCreature->addInflictedDamage(attacker, damage);
  890. #endif //TR_SUMMONS
  891.  
  892. if(attackedplayer){
  893. attackedplayer->sendStats();
  894. }
  895. //Remove player?
  896. if(attackedCreature->health <= 0 && attackedCreature->isRemoved == false)
  897. {
  898. #ifdef TJ_MONSTER_BLOOD
  899. dead = true;
  900. #endif //TJ_MONSTER_BLOOD
  901. #ifdef JD_DEATH_LIST
  902. if (attackedplayer && attacker)
  903. attackedplayer->addDeath(attacker->getName(), attackedplayer->level, time(0));
  904. #endif //JD_DEATH_LIST
  905. unsigned char stackpos = tile->getThingStackPos(attackedCreature);
  906.  
  907.  
  908. //tasksys
  909. Player* attackingplayer = dynamic_cast<Player*>(attacker);
  910. if(attackingplayer && attackedCreature->getName() == attackingplayer->taskmonster && attackingplayer->taskcount < attackingplayer->taskmax)
  911. {
  912. // attackingplayer->taskcount++;
  913. std::stringstream info;
  914. std::string mons = attackingplayer->taskmonster;
  915. std::transform(mons.begin(), mons.end(), mons.begin(), (int(*)(int))tolower);
  916.  
  917. if(attackingplayer->taskcount < attackingplayer->taskmax)
  918. {
  919. info << "You have killed " << attackingplayer->taskcount << " out of " << attackingplayer->taskmax << " " << mons << "s.";
  920. }
  921. else
  922. {
  923. info << "You have finished task of killing " << mons << "s. ";
  924. }
  925.  
  926. // attackingplayer->sendTextMessage(MSG_ORANGE, info.str().c_str());
  927. }
  928. //tasksys
  929.  
  930. //Prepare body
  931. Item *corpseitem = Item::CreateItem(attackedCreature->getLookCorpse());
  932. corpseitem->pos = CreaturePos;
  933. tile->addThing(corpseitem);
  934.  
  935. #ifdef _DEATH_EVENTS
  936. if (!attackedplayer)
  937. {
  938. Monster* monster = dynamic_cast<Monster*>(attackedCreature);
  939. Player* killer = dynamic_cast<Player*>(attacker);
  940.  
  941. if (killer && monster && monster->getAction())
  942. {
  943. actions.onCreatureKill(killer, attackedCreature, corpseitem, monster->getAction());
  944. }
  945.  
  946. }
  947. #endif //_DEATH_EVENTS
  948.  
  949. #ifdef __MIZIAK_CREATURESCRIPTS__
  950. if(dynamic_cast<Player*>(attacker) && attackedCreature)
  951. actions.creatureEvent("kill", dynamic_cast<Player*>(attacker), attackedCreature, corpseitem, NULL);
  952. #endif //__MIZIAK_CREATURESCRIPTS__
  953.  
  954. //remove creature
  955. if(attackedplayer){
  956. actions.luaWalkOff(attackedplayer,attackedplayer->pos,tile->ground->getID(),tile->ground->getUniqueId(),tile->ground->getActionId()); //CHANGE onWalk
  957. attackedplayer->onThingDisappear(attackedplayer,stackpos);
  958.  
  959. #ifdef __MIZIAK_CREATURESCRIPTS__
  960. attackedplayer->dieorlogout = true;
  961. if(attacker)
  962. actions.creatureEvent("death", attackedplayer, attacker, corpseitem, NULL);
  963. #endif //__MIZIAK_CREATURESCRIPTS__
  964.  
  965.  
  966. attackedplayer->die(); //handles exp/skills/maglevel loss
  967. }
  968.  
  969. //Add eventual loot
  970. Container *lootcontainer = dynamic_cast<Container*>(corpseitem);
  971. if(lootcontainer) {
  972. attackedCreature->dropLoot(lootcontainer);
  973.  
  974. #ifdef HUCZU_LOOT_INFO
  975. Monster* monster = dynamic_cast<Monster*>(attackedCreature);
  976. Player* atakujacy = dynamic_cast<Player*>(attacker);
  977. if(monster && atakujacy){
  978. std::stringstream ss, info;
  979. //info << "Loot of " << monster->getName() << lootcontainer->getContentDescription() << ".";
  980. info << "Loot of " << monster->getName();
  981. ss << lootcontainer->getContentDescription() << ".";
  982. if(atakujacy->party != 0){
  983. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  984. if((*it).second->party == atakujacy->party){
  985. if((*it).second->getID() != atakujacy->getID()){
  986. (*it).second->sendToSpecialChannel(atakujacy, SPEAK_CHANNEL_O, ss.str().c_str(), 0x02, info.str().c_str());
  987. //(*it).second->sendTextMessage(MSG_INFO, info.str().c_str());
  988. }
  989. }
  990. }
  991. }else{
  992. //atakujacy->sendTextMessage(MSG_INFO, info.str().c_str());
  993. atakujacy->sendToSpecialChannel(atakujacy, SPEAK_CHANNEL_O, ss.str().c_str(), 0x02, info.str().c_str());
  994. }
  995. }
  996. #endif //HUCZU_LOOT_INFO
  997. }
  998.  
  999. #ifdef HUCZU_MONSTER_QUEST
  1000. Monster* monster = dynamic_cast<Monster*>(attackedCreature);
  1001. Player* atakujacy = dynamic_cast<Player*>(attacker);
  1002. int32_t value, kills;
  1003.  
  1004. if(monster && atakujacy && monster->getQuestId() != 0){
  1005.  
  1006. if(monster->getQuestId() == 2 && atakujacy->getStorageValue(100, value) == 1){
  1007. int32_t killsprzed = atakujacy->getQuestKills(2);
  1008. atakujacy->addQuestKills(2, killsprzed+1);
  1009. }
  1010.  
  1011. }
  1012. #endif //HUCZU_MONSTER_QUEST
  1013.  
  1014.  
  1015. game->removeCreature(attackedCreature);
  1016. // Update attackedCreature pos because contains
  1017. // temple position for players
  1018. attackedCreature->pos = CreaturePos;
  1019.  
  1020. //add body
  1021. game->sendAddThing(NULL,corpseitem->pos,corpseitem);
  1022.  
  1023. if(attackedplayer){
  1024. std::stringstream ss;
  1025. ss << corpseitem->getDescription(false);
  1026.  
  1027. ss << "You recognize " << attackedplayer->getName() << ". ";
  1028. if(attacker){
  1029. ss << (attackedplayer->getSex() == PLAYERSEX_FEMALE ? "She" : "He") << " was killed by ";
  1030.  
  1031. Player *attackerplayer = dynamic_cast<Player*>(attacker);
  1032. if(attackerplayer) {
  1033. ss << attacker->getName();
  1034. }
  1035. else {
  1036. std::string creaturename = attacker->getName();
  1037. std::transform(creaturename.begin(), creaturename.end(), creaturename.begin(), (int32_t(*)(int32_t))tolower);
  1038. ss << article(creaturename);
  1039. }
  1040. }
  1041.  
  1042. //set body special description
  1043. corpseitem->setSpecialDescription(ss.str());
  1044. //send corpse to the dead player. It is not in spectator list
  1045. // because was removed
  1046. attackedplayer->onThingAppear(corpseitem);
  1047. }
  1048. game->startDecay(corpseitem);
  1049.  
  1050. //Get all creatures that will gain xp from this kill..
  1051. CreatureState* attackedCreatureState = NULL;
  1052. std::vector<long> creaturelist;
  1053.  
  1054. if(!(dynamic_cast<Player*>(attackedCreature) && game->getWorldType() != WORLD_TYPE_PVP_ENFORCED)){
  1055. creaturelist = attackedCreature->getInflicatedDamageCreatureList();
  1056. CreatureStateVec& creatureStateVec = creaturestates[tile];
  1057. for(CreatureStateVec::iterator csIt = creatureStateVec.begin(); csIt != creatureStateVec.end(); ++csIt) {
  1058. if(csIt->first == attackedCreature) {
  1059. attackedCreatureState = &csIt->second;
  1060. break;
  1061. }
  1062. }
  1063. }
  1064.  
  1065. if(attackedCreatureState) { //should never be NULL..
  1066. //Add experience
  1067. for(std::vector<long>::const_iterator iit = creaturelist.begin(); iit != creaturelist.end(); ++iit) {
  1068. Creature* gainExpCreature = game->getCreatureByID(*iit);
  1069. if(gainExpCreature) {
  1070. exp_t gainedExperience = attackedCreature->getGainedExperience(gainExpCreature);
  1071. if(gainedExperience <= 0)
  1072. continue;
  1073.  
  1074. Player *gainExpPlayer = dynamic_cast<Player*>(gainExpCreature);
  1075.  
  1076. if(gainExpPlayer) {
  1077. gainExpPlayer->addExp(gainedExperience);
  1078. if(gainExpPlayer && attackedCreature->getName() == gainExpPlayer->taskmonster && gainExpPlayer->taskcount < gainExpPlayer->taskmax)
  1079. {
  1080. gainExpPlayer->taskcount++;
  1081. std::stringstream info;
  1082. std::string mons = gainExpPlayer->taskmonster;
  1083. std::transform(mons.begin(), mons.end(), mons.begin(), (int(*)(int))tolower);
  1084.  
  1085. if(gainExpPlayer->taskcount < gainExpPlayer->taskmax)
  1086. {
  1087. info << "You have killed " << gainExpPlayer->taskcount << " out of " << gainExpPlayer->taskmax << " " << mons << "s.";
  1088. }
  1089. else
  1090. {
  1091. info << "You have finished task of killing " << mons << "s. ";
  1092. }
  1093. gainExpPlayer->sendTextMessage(MSG_ORANGE, info.str().c_str());
  1094. }
  1095.  
  1096.  
  1097.  
  1098. }
  1099. //Need to add this creature and all that can see it to spectators, unless they already added
  1100. SpectatorVec creaturelist;
  1101. game->getSpectators(Range(gainExpCreature->pos, true), creaturelist);
  1102.  
  1103. for(SpectatorVec::const_iterator cit = creaturelist.begin(); cit != creaturelist.end(); ++cit) {
  1104. if(std::find(spectatorlist.begin(), spectatorlist.end(), *cit) == spectatorlist.end()) {
  1105. spectatorlist.push_back(*cit);
  1106. }
  1107. }
  1108.  
  1109. //Add creature to attackerlist
  1110. attackedCreatureState->attackerlist.push_back(gainExpCreature);
  1111. }
  1112. }
  1113. }
  1114.  
  1115. Player *player = dynamic_cast<Player*>(attacker);
  1116. if(player){
  1117. player->sendStats();
  1118. }
  1119.  
  1120. if(attackedCreature && attackedCreature->getMaster() != NULL) {
  1121. attackedCreature->getMaster()->removeSummon(attackedCreature);
  1122. }
  1123. }
  1124.  
  1125.  
  1126. //Add blood?
  1127. #ifdef TJ_MONSTER_BLOOD
  1128. if((drawBlood || attackedCreature->health <= 0) && damage > 0 && attackedCreature->bloodsplash != 255) {
  1129. Item* splash = Item::CreateItem(dead? ITEM_POOL : ITEM_SPLASH, attackedCreature->bloodsplash);
  1130. game->addThing(NULL, CreaturePos, splash);
  1131. game->startDecay(splash);
  1132. game->updateTile(CreaturePos);
  1133. }
  1134. #else
  1135. if((drawBlood || attackedCreature->health <= 0) && damage > 0) {
  1136. Item* splash = Item::CreateItem(ITEM_SPLASH, FLUID_BLOOD);
  1137. game->addThing(NULL, CreaturePos, splash);
  1138. game->startDecay(splash);
  1139. game->updateTile(CreaturePos);
  1140. }
  1141. #endif //TJ_MONSTER_BLOOD
  1142. }
  1143.  
  1144.  
  1145. Game::Game()
  1146. {
  1147. eventIdCount = 1000;
  1148. this->game_state = GAME_STATE_NORMAL;
  1149. this->map = NULL;
  1150. this->worldType = WORLD_TYPE_PVP;
  1151. OTSYS_THREAD_LOCKVARINIT(gameLock);
  1152. OTSYS_THREAD_LOCKVARINIT(eventLock);
  1153. OTSYS_THREAD_LOCKVARINIT(AutoID::autoIDLock);
  1154. #if defined __EXCEPTION_TRACER__
  1155. OTSYS_THREAD_LOCKVARINIT(maploadlock);
  1156. #endif
  1157. OTSYS_THREAD_SIGNALVARINIT(eventSignal);
  1158. BufferedPlayers.clear();
  1159. OTSYS_CREATE_THREAD(eventThread, this);
  1160.  
  1161. #ifdef __DEBUG_CRITICALSECTION__
  1162. OTSYS_CREATE_THREAD(monitorThread, this);
  1163. #endif
  1164.  
  1165. addEvent(makeTask(DECAY_INTERVAL, boost::bind(&Game::checkDecay,this,DECAY_INTERVAL)));
  1166.  
  1167. #ifdef CVS_DAY_CYCLE
  1168. int32_t daycycle = 3600;
  1169. light_hour_delta = 1440*10/daycycle;
  1170. light_hour = 0;
  1171. lightlevel = LIGHT_LEVEL_NIGHT;
  1172. light_state = LIGHT_STATE_NIGHT;
  1173. addEvent(makeTask(10000, boost::bind(&Game::checkLight, this, 10000)));
  1174. #endif //CVS_DAY_CYCLE
  1175. }
  1176.  
  1177.  
  1178. Game::~Game()
  1179. {
  1180. if(map) {
  1181. delete map;
  1182. }
  1183. }
  1184.  
  1185. void Game::setWorldType(enum_world_type type)
  1186. {
  1187. this->worldType = type;
  1188. }
  1189.  
  1190. enum_game_state Game::getGameState()
  1191. {
  1192. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::getGameState()");
  1193. return game_state;
  1194. }
  1195.  
  1196. int32_t Game::loadMap(std::string filename, std::string filekind) {
  1197. if(!map)
  1198. map = new Map;
  1199.  
  1200. max_players = atoi(g_config.getGlobalString("maxplayers").c_str());
  1201. distanceToKill = atoi(g_config.getGlobalString("dist", "50").c_str());
  1202. return map->loadMap(filename, filekind);
  1203. }
  1204.  
  1205.  
  1206.  
  1207. /*****************************************************************************/
  1208.  
  1209. #ifdef __DEBUG_CRITICALSECTION__
  1210.  
  1211. OTSYS_THREAD_RETURN Game::monitorThread(void *p)
  1212. {
  1213. Game* _this = (Game*)p;
  1214.  
  1215. while (true) {
  1216. OTSYS_SLEEP(6000);
  1217.  
  1218. int32_t ret = OTSYS_THREAD_LOCKEX(_this->gameLock, 60 * 2 * 1000);
  1219. if(ret != OTSYS_THREAD_TIMEOUT) {
  1220. OTSYS_THREAD_UNLOCK(_this->gameLock, NULL);
  1221. continue;
  1222. }
  1223.  
  1224. bool file = false;
  1225. std::ostream *outdriver;
  1226. std::cout << "Error: generating critical section file..." <<std::endl;
  1227. std::ofstream output("deadlock.txt",std::ios_base::app);
  1228. if(output.fail()){
  1229. outdriver = &std::cout;
  1230. file = false;
  1231. }
  1232. else{
  1233. file = true;
  1234. outdriver = &output;
  1235. }
  1236.  
  1237. time_t rawtime;
  1238. time(&rawtime);
  1239. *outdriver << "*****************************************************" << std::endl;
  1240. *outdriver << "Error report - " << std::ctime(&rawtime) << std::endl;
  1241.  
  1242. OTSYS_THREAD_LOCK_CLASS::LogList::iterator it;
  1243. for(it = OTSYS_THREAD_LOCK_CLASS::loglist.begin(); it != OTSYS_THREAD_LOCK_CLASS::loglist.end(); ++it) {
  1244. *outdriver << (it->lock ? "lock - " : "unlock - ") << it->str
  1245. << " threadid: " << it->threadid
  1246. << " time: " << it->time
  1247. << " ptr: " << it->mutexaddr
  1248. << std::endl;
  1249. }
  1250.  
  1251. *outdriver << "*****************************************************" << std::endl;
  1252. if(file)
  1253. ((std::ofstream*)outdriver)->close();
  1254.  
  1255. std::cout << "Error report generated. Killing server." <<std::endl;
  1256. exit(1); //force exit
  1257. }
  1258. }
  1259. #endif
  1260.  
  1261. OTSYS_THREAD_RETURN Game::eventThread(void *p)
  1262. {
  1263. #if defined __EXCEPTION_TRACER__
  1264. ExceptionHandler eventExceptionHandler;
  1265. eventExceptionHandler.InstallHandler();
  1266. #endif
  1267.  
  1268. Game* _this = (Game*)p;
  1269.  
  1270. // basically what we do is, look at the first scheduled item,
  1271. // and then sleep until it's due (or if there is none, sleep until we get an event)
  1272. // of course this means we need to get a notification if there are new events added
  1273. while (true)
  1274. {
  1275. #ifdef __DEBUG__EVENTSCHEDULER__
  1276. std::cout << "schedulercycle start..." << std::endl;
  1277. #endif
  1278.  
  1279. SchedulerTask* task = NULL;
  1280. bool runtask = false;
  1281.  
  1282. // check if there are events waiting...
  1283. OTSYS_THREAD_LOCK(_this->eventLock, "eventThread()")
  1284.  
  1285. int32_t ret;
  1286. if (_this->eventList.size() == 0) {
  1287. // unlock mutex and wait for signal
  1288. ret = OTSYS_THREAD_WAITSIGNAL(_this->eventSignal, _this->eventLock);
  1289. } else {
  1290. // unlock mutex and wait for signal or timeout
  1291. ret = OTSYS_THREAD_WAITSIGNAL_TIMED(_this->eventSignal, _this->eventLock, _this->eventList.top()->getCycle());
  1292. }
  1293. // the mutex is locked again now...
  1294. if (ret == OTSYS_THREAD_TIMEOUT) {
  1295. // ok we had a timeout, so there has to be an event we have to execute...
  1296. #ifdef __DEBUG__EVENTSCHEDULER__
  1297. std::cout << "event found at " << OTSYS_TIME() << " which is to be scheduled at: " << _this->eventList.top()->getCycle() << std::endl;
  1298. #endif
  1299. task = _this->eventList.top();
  1300. _this->eventList.pop();
  1301. }
  1302.  
  1303. if(task) {
  1304. std::map<uint32_t, SchedulerTask*>::iterator it = _this->eventIdMap.find(task->getEventId());
  1305. if(it != _this->eventIdMap.end()) {
  1306. _this->eventIdMap.erase(it);
  1307. runtask = true;
  1308. }
  1309. }
  1310.  
  1311. OTSYS_THREAD_UNLOCK(_this->eventLock, "eventThread()");
  1312. if (task) {
  1313. if(runtask) {
  1314. (*task)(_this);
  1315. }
  1316. delete task;
  1317. }
  1318. }
  1319. #if defined __EXCEPTION_TRACER__
  1320. eventExceptionHandler.RemoveHandler();
  1321. #endif
  1322.  
  1323. }
  1324.  
  1325. uint32_t Game::addEvent(SchedulerTask* event) {
  1326. bool do_signal = false;
  1327. OTSYS_THREAD_LOCK(eventLock, "addEvent()")
  1328.  
  1329. if(event->getEventId() == 0) {
  1330. ++eventIdCount;
  1331. event->setEventId(eventIdCount);
  1332. }
  1333.  
  1334. #ifdef __DEBUG__EVENTSCHEDULER__
  1335. std::cout << "addEvent - " << event->getEventId() << std::endl;
  1336. #endif
  1337.  
  1338. eventIdMap[event->getEventId()] = event;
  1339.  
  1340. /*
  1341. if (eventList.empty() || *event < *eventList.top())
  1342. do_signal = true;
  1343. */
  1344.  
  1345. bool isEmpty = eventList.empty();
  1346. eventList.push(event);
  1347.  
  1348. if(isEmpty || *event < *eventList.top())
  1349. do_signal = true;
  1350.  
  1351. /*
  1352. if (eventList.empty() || *event < *eventList.top())
  1353. do_signal = true;
  1354. */
  1355.  
  1356. OTSYS_THREAD_UNLOCK(eventLock, "addEvent()")
  1357.  
  1358. if (do_signal)
  1359. OTSYS_THREAD_SIGNAL_SEND(eventSignal);
  1360.  
  1361. return event->getEventId();
  1362. }
  1363.  
  1364. bool Game::stopEvent(uint32_t eventid) {
  1365. if(eventid == 0)
  1366. return false;
  1367.  
  1368. OTSYS_THREAD_LOCK(eventLock, "stopEvent()")
  1369.  
  1370. std::map<uint32_t, SchedulerTask*>::iterator it = eventIdMap.find(eventid);
  1371. if(it != eventIdMap.end()) {
  1372.  
  1373. #ifdef __DEBUG__EVENTSCHEDULER__
  1374. std::cout << "stopEvent - eventid: " << eventid << "/" << it->second->getEventId() << std::endl;
  1375. #endif
  1376.  
  1377. //it->second->setEventId(0); //invalidate the event
  1378. eventIdMap.erase(it);
  1379.  
  1380. OTSYS_THREAD_UNLOCK(eventLock, "stopEvent()")
  1381. return true;
  1382. }
  1383.  
  1384. OTSYS_THREAD_UNLOCK(eventLock, "stopEvent()")
  1385. return false;
  1386. }
  1387.  
  1388. /*****************************************************************************/
  1389.  
  1390. uint32_t Game::getPlayersOnline() {return (uint32_t)Player::listPlayer.list.size();};
  1391. uint32_t Game::getMonstersOnline() {return (uint32_t)Monster::listMonster.list.size();};
  1392. uint32_t Game::getNpcsOnline() {return (uint32_t)Npc::listNpc.list.size();};
  1393. uint32_t Game::getCreaturesOnline() {return (uint32_t)listCreature.list.size();};
  1394.  
  1395. Tile* Game::getTile(unsigned short _x, unsigned short _y, unsigned char _z)
  1396. {
  1397. return map->getTile(_x, _y, _z);
  1398. }
  1399.  
  1400. Tile* Game::getTile(const Position& pos)
  1401. {
  1402. return map->getTile(pos);
  1403. }
  1404.  
  1405. void Game::setTile(unsigned short _x, unsigned short _y, unsigned char _z, unsigned short groundId)
  1406. {
  1407. map->setTile(_x, _y, _z, groundId);
  1408. }
  1409.  
  1410. Creature* Game::getCreatureByID(uint32_t id)
  1411. {
  1412. if(id == 0)
  1413. return NULL;
  1414.  
  1415. AutoList<Creature>::listiterator it = listCreature.list.find(id);
  1416. if(it != listCreature.list.end()) {
  1417. return (*it).second;
  1418. }
  1419.  
  1420. return NULL; //just in case the player doesnt exist
  1421. }
  1422.  
  1423. Player* Game::getPlayerByID(uint32_t id)
  1424. {
  1425. if(id == 0)
  1426. return NULL;
  1427.  
  1428. AutoList<Player>::listiterator it = Player::listPlayer.list.find(id);
  1429. if(it != Player::listPlayer.list.end()) {
  1430. return (*it).second;
  1431. }
  1432.  
  1433. return NULL; //just in case the player doesnt exist
  1434. }
  1435.  
  1436. Creature* Game::getCreatureByName(const std::string &s)
  1437. {
  1438. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::getCreatureByName()");
  1439.  
  1440. std::string txt1 = s;
  1441. std::transform(txt1.begin(), txt1.end(), txt1.begin(), upchar);
  1442. for(AutoList<Creature>::listiterator it = listCreature.list.begin(); it != listCreature.list.end(); ++it){
  1443. std::string txt2 = (*it).second->getName();
  1444. std::transform(txt2.begin(), txt2.end(), txt2.begin(), upchar);
  1445. if(txt1 == txt2)
  1446. return it->second;
  1447. }
  1448.  
  1449. return NULL; //just in case the creature doesnt exist
  1450. }
  1451.  
  1452. Player* Game::getPlayerByName(const std::string &s)
  1453. {
  1454. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::getPlayerByName()");
  1455.  
  1456. std::string txt1 = s;
  1457. std::transform(txt1.begin(), txt1.end(), txt1.begin(), upchar);
  1458. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  1459. std::string txt2 = (*it).second->getName();
  1460. std::transform(txt2.begin(), txt2.end(), txt2.begin(), upchar);
  1461. if(txt1 == txt2)
  1462. return it->second;
  1463. }
  1464.  
  1465. return NULL; //just in case the player doesnt exist
  1466. }
  1467.  
  1468. bool Game::placeCreature(Position &pos, Creature* c
  1469. #ifdef YUR_LOGIN_QUEUE
  1470. , int32_t* placeInQueue
  1471. #endif //YUR_LOGIN_QUEUE
  1472. )
  1473. {
  1474. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::placeCreature()");
  1475. bool success = false;
  1476. Player *p = dynamic_cast<Player*>(c);
  1477. Monster *monsterzin = dynamic_cast<Monster*>(c);
  1478.  
  1479. #ifdef YUR_LOGIN_QUEUE
  1480. if (!p || c->access >= g_config.ACCESS_ENTER ||
  1481. #ifdef YUR_PREMIUM_PROMOTION
  1482. (p->isPremmium() && !g_config.QUEUE_PREMMY) ||
  1483. #endif //YUR_PREMIUM_PROMOTION
  1484. loginQueue.login(p->accountNumber, getPlayersOnline(), max_players, placeInQueue))
  1485. {
  1486. #else //YUR_LOGIN_QUEUE
  1487. if (!p || c->access >= g_config.ACCESS_ENTER || getPlayersOnline() < max_players)
  1488. {
  1489. #endif //YUR_LOGIN_QUEUE
  1490.  
  1491. success = map->placeCreature(pos, c);
  1492. if(success)
  1493. {
  1494. c->useThing();
  1495.  
  1496. c->setID();
  1497. //std::cout << "place: " << c << " " << c->getID() << std::endl;
  1498. listCreature.addList(c);
  1499. c->addList();
  1500. c->isRemoved = false;
  1501.  
  1502. sendAddThing(NULL,c->pos,c);
  1503.  
  1504. if(p)
  1505. {
  1506. checkRecord();
  1507. #ifdef __DEBUG_PLAYERS__
  1508. std::cout << (uint32_t)getPlayersOnline() << " players online." << std::endl;
  1509. #endif
  1510. #ifdef YUR_GUILD_SYSTEM
  1511. Guilds::ReloadGuildInfo(p);
  1512. #endif //YUR_GUILD_SYSTEM
  1513. /*#ifdef ELEM_VIP_LIST
  1514. vipLogin(p);
  1515. #endif //ELEM_VIP_LIST*/
  1516. }
  1517.  
  1518. if(p){
  1519. c->eventCheck = addEvent(makeTask(1000, std::bind2nd(std::mem_fun(&Game::checkCreature), c->getID())));
  1520. }
  1521. else{
  1522. c->eventCheck = addEvent(makeTask(1000, std::bind2nd(std::mem_fun(&Game::checkCreature), c->getID())));
  1523. }
  1524.  
  1525. //c->eventCheckAttacking = addEvent(makeTask(2000, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), c->getID())));
  1526. }
  1527. }
  1528. else {
  1529. //we cant add the player, server is full
  1530. success = false;
  1531. }
  1532.  
  1533. #ifdef __MIZIAK_CREATURESCRIPTS__
  1534. if(p)
  1535. actions.creatureEvent("login", p, NULL, NULL, NULL);
  1536. #endif //__MIZIAK_CREATURESCRIPTS__
  1537.  
  1538.  
  1539. if(monsterzin){
  1540. c->masterPos.x = c->pos.x;
  1541. c->masterPos.y = c->pos.y;
  1542. c->masterPos.z = c->pos.z;
  1543. }
  1544. return success;
  1545. }
  1546.  
  1547. bool Game::removeCreature(Creature* c)
  1548. {
  1549. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::removeCreature()");
  1550. if(c->isRemoved == true)
  1551. return false;
  1552. #ifdef __DEBUG__
  1553. std::cout << "removing creature "<< std::endl;
  1554. #endif
  1555.  
  1556. #ifdef __MIZIAK_CREATURESCRIPTS__
  1557. Player* pc = dynamic_cast<Player*>(c);
  1558. if(pc)
  1559. if(!pc->dieorlogout)
  1560. actions.creatureEvent("logout", pc, NULL, NULL, NULL);
  1561. #endif //__MIZIAK_CREATURESCRIPTS__
  1562.  
  1563. if(!removeThing(NULL,c->pos,c))
  1564. return false;
  1565.  
  1566. //std::cout << "remove: " << c << " " << c->getID() << std::endl;
  1567. listCreature.removeList(c->getID());
  1568. c->removeList();
  1569. c->isRemoved = true;
  1570.  
  1571. if(g_config.SUMMON_BODIES){
  1572. c->isRemoved = true;
  1573.  
  1574. Creature *summon = NULL;
  1575. for(std::list<Creature*>::iterator cit = c->summons.begin(); cit != c->summons.end(); ++cit) {
  1576. summon = (*cit);
  1577. Position CreaturePos = summon->pos;
  1578. Tile *tile = map->getTile(CreaturePos);
  1579. Item *corpseitem = Item::CreateItem(summon->getLookCorpse());
  1580. corpseitem->pos = CreaturePos; /*summoned bodies by Cayan*/
  1581. tile->addThing(corpseitem);
  1582. removeCreature(summon);
  1583. updateTile(CreaturePos);
  1584. }
  1585. }
  1586. else
  1587. {
  1588. c->isRemoved = true;
  1589.  
  1590. //for(std::list<Creature*>::iterator cit = c->summons.begin(); cit != c->summons.end(); ++cit) {
  1591. //removeCreature(*cit);
  1592. //}
  1593. }
  1594.  
  1595.  
  1596. stopEvent(c->eventCheck);
  1597. stopEvent(c->eventCheckAttacking);
  1598. stopEvent(c->eventCheckFollow);
  1599.  
  1600. Player* player = dynamic_cast<Player*>(c);
  1601. if(player){
  1602.  
  1603. #ifdef HUCZU_SKULLS
  1604. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  1605. Player *on = dynamic_cast<Player*>(it->second);
  1606. if(on && player->isYellowTo(on)){
  1607. on->removeFromYellowList(player);
  1608. }
  1609. if(on && on->hasAttacked(player)){
  1610. on->removeFromAttakedList(player);
  1611. }
  1612. player->clearAttakedList();
  1613. player->clearYellowList();
  1614. }
  1615.  
  1616. if(player->party != 0)
  1617. LeaveParty(player);
  1618. #endif //HUCZU_SKULLS
  1619.  
  1620. if(player->tradePartner != 0) {
  1621. playerCloseTrade(player);
  1622. }
  1623. if(player->eventAutoWalk)
  1624. stopEvent(player->eventAutoWalk);
  1625.  
  1626. Tile* fromT = getTile(player->pos);
  1627. if(fromT && fromT->ground)
  1628. actions.luaWalkOff(player,player->pos,fromT->ground->getID(),fromT->ground->getUniqueId(),fromT->ground->getActionId());
  1629.  
  1630. g_chat.removeUserFromAllChannels(player);
  1631. if(!IOPlayer::instance()->savePlayer(player)){
  1632. std::cout << "Error while saving player: " << player->getName() << std::endl;
  1633. }
  1634. std::cout << (uint32_t)getPlayersOnline() << " players online." << std::endl;
  1635.  
  1636.  
  1637. /*#ifdef ELEM_VIP_LIST
  1638. vipLogout(c->getName());
  1639. #endif //ELEM_VIP_LIST*/
  1640.  
  1641.  
  1642. }
  1643. this->FreeThing(c);
  1644. return true;
  1645. }
  1646.  
  1647. void Game::thingMove(Creature *creature, Thing *thing,
  1648. unsigned short to_x, unsigned short to_y, unsigned char to_z, unsigned char count)
  1649. {
  1650. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 1");
  1651.  
  1652. Tile *fromTile = map->getTile(thing->pos);
  1653.  
  1654. if (fromTile)
  1655. {
  1656. int32_t oldstackpos = fromTile->getThingStackPos(thing);
  1657. thingMoveInternal(creature, thing->pos.x, thing->pos.y, thing->pos.z, oldstackpos, 0, to_x, to_y, to_z, count);
  1658. }
  1659. }
  1660.  
  1661.  
  1662. void Game::thingMove(Creature *creature, unsigned short from_x, unsigned short from_y, unsigned char from_z,
  1663. unsigned char stackPos, unsigned short itemid, unsigned short to_x, unsigned short to_y, unsigned char to_z, unsigned char count)
  1664. {
  1665. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 2");
  1666.  
  1667. Tile *fromTile = getTile(from_x, from_y, from_z);
  1668. if(!fromTile)
  1669. return;
  1670.  
  1671. #ifdef FIXY
  1672. if(dynamic_cast<Player*>(creature) && fromTile && !fromTile->ground) {
  1673. dynamic_cast<Player*>(creature)->sendCancelWalk();
  1674. return;
  1675. }
  1676. #endif //FIXY
  1677.  
  1678. Tile *toTile = getTile(to_x, to_y, to_z);
  1679. if(!toTile)
  1680. return;
  1681.  
  1682. #ifdef FIXY
  1683. if (toTile->isHouse() && !fromTile->isHouse())
  1684. return;
  1685. #endif //FIXY
  1686.  
  1687. Thing* thing = fromTile->getThingByStackPos(stackPos);
  1688. if(!thing)
  1689. return;
  1690.  
  1691. Item* item = dynamic_cast<Item*>(thing);
  1692.  
  1693. if(item && (item->getID() != itemid || item != fromTile->getTopDownItem()))
  1694. return;
  1695.  
  1696. thingMoveInternal(creature, from_x, from_y, from_z, stackPos, itemid, to_x, to_y, to_z, count);
  1697. }
  1698.  
  1699. //container/inventory to container/inventory
  1700. void Game::thingMove(Player *player,
  1701. unsigned char from_cid, unsigned char from_slotid, unsigned short itemid, bool fromInventory,
  1702. unsigned char to_cid, unsigned char to_slotid, bool toInventory,
  1703. unsigned char count)
  1704. {
  1705. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 3");
  1706.  
  1707. thingMoveInternal(player, from_cid, from_slotid, itemid, fromInventory,
  1708. to_cid, to_slotid, toInventory, count);
  1709. }
  1710.  
  1711. //container/inventory to ground
  1712. void Game::thingMove(Player *player,
  1713. unsigned char from_cid, unsigned char from_slotid, unsigned short itemid, bool fromInventory,
  1714. const Position& toPos, unsigned char count)
  1715. {
  1716. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 4");
  1717. Container *fromContainer = player->getContainer(from_cid);
  1718. if(fromContainer && !fromContainer->shop.empty())
  1719. return;
  1720.  
  1721. #ifdef FIXY
  1722. Tile *toTile = getTile(toPos.x, toPos.y, toPos.z);
  1723. if(!toTile)
  1724. return;
  1725.  
  1726. if (player) {
  1727. Tile *fromTile = getTile(player->pos);
  1728. if(!fromTile->isHouse() && toTile->isHouse())
  1729. return;
  1730. }
  1731. #endif //FIXY
  1732.  
  1733. thingMoveInternal(player, from_cid, from_slotid, itemid, fromInventory, toPos, count);
  1734. }
  1735.  
  1736. //ground to container/inventory
  1737. void Game::thingMove(Player *player,
  1738. const Position& fromPos, unsigned char stackPos, unsigned short itemid,
  1739. unsigned char to_cid, unsigned char to_slotid, bool toInventory,
  1740. unsigned char count)
  1741. {
  1742. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 5");
  1743. thingMoveInternal(player, fromPos, stackPos, itemid, to_cid, to_slotid, toInventory, count);
  1744. }
  1745.  
  1746. #ifdef FIXY
  1747. bool Game::onPrepareMoveThing(Creature* player, /*const*/ Thing* thing,
  1748. const Position& fromPos, const Position& toPos, int32_t count)
  1749. {
  1750. const Creature* movingCreature = dynamic_cast<const Creature*>(thing);
  1751. Player *playa = dynamic_cast<Player*>(thing);
  1752.  
  1753. if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) &&
  1754. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  1755. {
  1756. player->sendCancel("Destination is out of reach.");
  1757. return false;
  1758. }
  1759. //RZUCANIE GM PO EKRANIE?
  1760. else if( ((abs(fromPos.x - toPos.x) > thing->throwRange) || (abs(fromPos.y - toPos.y) > thing->throwRange)
  1761. || (fromPos.z != toPos.z)) && player->access >= g_config.ACCESS_REMOTE) {
  1762. if(player == thing){
  1763. teleport(player,toPos);
  1764.  
  1765. if(!playa->gmInvisible){
  1766. globalMagicEffect(fromPos, NM_ME_PUFF);
  1767. globalMagicEffect(toPos, NM_ME_ENERGY_AREA);
  1768. }
  1769. else
  1770. {
  1771. playa->sendMagicEffect(fromPos, NM_ME_PUFF);
  1772. playa->sendMagicEffect(toPos, NM_ME_ENERGY_AREA);
  1773. }
  1774. }
  1775. else
  1776. teleport(thing,toPos);
  1777. }
  1778.  
  1779.  
  1780. 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)))) {
  1781. player->sendCancel("Destination is out of reach.");
  1782. return false;
  1783. }
  1784.  
  1785.  
  1786. else if(player->access < g_config.ACCESS_REMOTE && movingCreature && fromPos.z != toPos.z){
  1787. player->sendCancel("Destination is out of reach.");
  1788. return false;
  1789. }
  1790.  
  1791. else {
  1792. const Item* item = dynamic_cast<const Item*>(thing);
  1793. if(item) {
  1794. if(item->getID() == ITEM_FOOTBALL &&
  1795. player->access < g_config.getGlobalNumber("accessfootball", 3) && (
  1796. (abs(player->pos.x - toPos.x) > 2) ||
  1797. (abs(player->pos.y - toPos.y) > 2) ||
  1798. (player->pos.z != fromPos.z))
  1799. ){
  1800. player->sendCancel("Nie mozesz tak daleko kopnac.");
  1801. return false;
  1802. }
  1803. int32_t blockstate = 0;
  1804. if(item->isBlocking())
  1805. blockstate |= BLOCK_SOLID;
  1806.  
  1807. if(item->isPickupable() || !item->isNotMoveable())
  1808. blockstate |= BLOCK_PICKUPABLE;
  1809.  
  1810. if(blockstate != 0) {
  1811. switch(map->canThrowObjectTo(fromPos, toPos, blockstate)) {
  1812. case RET_NOERROR:
  1813. return true;
  1814. break;
  1815.  
  1816. case RET_CANNOTTHROW:
  1817. player->sendCancel("Nie mozesz tam rzucic.");
  1818. return false;
  1819. break;
  1820.  
  1821. case RET_CREATUREBLOCK:
  1822. case RET_NOTENOUGHROOM:
  1823. #ifdef KOSZ
  1824. if(item->getID() != ITEM_DUSTBIN){
  1825. player->sendCancel("Przykro mi, nie ma miejsca.");
  1826. return false;
  1827. }
  1828. #else
  1829. player->sendCancel("Przykro mi, nie ma miejsca.");
  1830. return false;
  1831. #endif //KOSZ
  1832. break;
  1833.  
  1834. default:
  1835. player->sendCancel("Sorry not possible.");
  1836. return false;
  1837. break;
  1838. }
  1839. }
  1840. }
  1841. }
  1842.  
  1843. return true;
  1844. }
  1845. #else //FIXY
  1846. bool Game::onPrepareMoveThing(Creature* player, const Thing* thing,
  1847. const Position& fromPos, const Position& toPos, int32_t count)
  1848. {
  1849. if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) &&
  1850. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  1851. {
  1852. player->sendCancel("Za daleko...");
  1853. return false;
  1854. }
  1855. else if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) &&
  1856. ((abs(fromPos.x - toPos.x) > thing->throwRange) || (abs(fromPos.y - toPos.y) > thing->throwRange)
  1857. || (fromPos.z != toPos.z) /*TODO: Make it possible to throw items to different floors ))*/
  1858. {
  1859. player->sendCancel("Destination is out of reach.");
  1860. return false;
  1861. }
  1862. else {
  1863. const Item* item = dynamic_cast<const Item*>(thing);
  1864. if(item) {
  1865. int32_t blockstate = 0;
  1866. if(item->isBlocking())
  1867. blockstate |= BLOCK_SOLID;
  1868.  
  1869. if(item->isPickupable() || !item->isNotMoveable())
  1870. blockstate |= BLOCK_PICKUPABLE;
  1871.  
  1872. if(blockstate != 0) {
  1873. switch(map->canThrowObjectTo(fromPos, toPos, blockstate)) {
  1874. case RET_NOERROR:
  1875. return true;
  1876. break;
  1877.  
  1878. case RET_CANNOTTHROW:
  1879. player->sendCancel("Nie mozesz tam rzucic.");
  1880. return false;
  1881. break;
  1882.  
  1883. case RET_CREATUREBLOCK:
  1884. case RET_NOTENOUGHROOM:
  1885. player->sendCancel("Przykro mi, nie ma miejsca.");
  1886. return false;
  1887. break;
  1888.  
  1889. default:
  1890. player->sendCancel("Sorry not possible.");
  1891. return false;
  1892. break;
  1893. }
  1894. }
  1895. }
  1896. }
  1897. return true;
  1898. }
  1899. #endif //FIXY
  1900. /*ground -> ground*/
  1901. bool Game::onPrepareMoveThing(Creature* creature, const Thing* thing,
  1902. const Tile* fromTile, const Tile *toTile, int32_t count)
  1903. {
  1904. const Player* player = dynamic_cast<const Player*>(creature);
  1905.  
  1906. const Item *item = dynamic_cast<const Item*>(thing);
  1907. const Creature* movingCreature = dynamic_cast<const Creature*>(thing);
  1908. const Player* movingPlayer = dynamic_cast<const Player*>(thing);
  1909.  
  1910. /* if(movingCreature){
  1911. addEvent(makeTask(2000, std::mem_fun(&Game::onPrepareMoveCreature, creature, movingCreature, fromTile, toTile))));
  1912. }*/
  1913. if(item && !item->canMovedTo(toTile)) {
  1914. creature->sendCancel("Sorry, not possible.");
  1915. return false;
  1916. }
  1917.  
  1918. else if(movingCreature && !movingCreature->canMovedTo(toTile)) {
  1919. if(player && player->eventCheckFollow == 0) {
  1920. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  1921. player->sendCancelWalk();
  1922. }
  1923.  
  1924. return false;
  1925. }
  1926. else if(!movingPlayer && toTile && toTile->floorChange()) {
  1927. creature->sendCancel("Sorry, not possible.");
  1928. return false;
  1929. }
  1930. else if(movingCreature && toTile && !toTile->ground) {
  1931. if(player) {
  1932. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  1933. player->sendCancelWalk();
  1934. }
  1935.  
  1936. return false;
  1937. }
  1938.  
  1939. if (fromTile && fromTile->splash == thing && fromTile->splash->isNotMoveable()) {
  1940. creature->sendCancel("You cannot move this object.");
  1941. #ifdef __DEBUG__
  1942. cout << creature->getName() << " is trying to move a splash item!" << std::endl;
  1943. #endif
  1944. return false;
  1945. }
  1946. else if (item && item->isNotMoveable()) {
  1947. creature->sendCancel("You cannot move this object.");
  1948. #ifdef __DEBUG__
  1949. cout << creature->getName() << " is trying to move an unmoveable item!" << std::endl;
  1950. #endif
  1951. return false;
  1952. }
  1953.  
  1954. #ifdef TLM_HOUSE_SYSTEM
  1955. if (item && toTile && toTile->isHouse())
  1956. {
  1957. const Container* container = dynamic_cast<const Container*>(item);
  1958. int32_t moving = container? container->getItemHoldingCount() : 1;
  1959.  
  1960. if (moving + toTile->getItemHoldingCount() > g_config.MAX_HOUSE_TILE_ITEMS)
  1961. {
  1962. creature->sendCancel("You cannot put more items on a house tile.");
  1963. return false;
  1964. }
  1965. }
  1966. #endif //TLM_HOUSE_SYSTEM
  1967.  
  1968. return true; //return thing->canMovedTo(toTile);
  1969. }
  1970. /*inventory -> container*/
  1971. bool Game::onPrepareMoveThing(Player* player, const Item* fromItem, slots_t fromSlot,
  1972. const Container* toContainer, const Item* toItem, int32_t count)
  1973. {
  1974. if(toContainer && !toContainer->shop.empty()){
  1975. creatureUseShop(player, fromItem->getID(), count, "toShop");
  1976. return false;
  1977. }
  1978. if(toContainer && toContainer->getParent() && !toContainer->getParent()->shop.empty())
  1979. return false;
  1980. if(!fromItem->isPickupable()) {
  1981. player->sendCancel("Sorry, not possible.");
  1982. return false;
  1983. }
  1984. else {
  1985. const Container *itemContainer = dynamic_cast<const Container*>(fromItem);
  1986. if(itemContainer) {
  1987. if(itemContainer->isHoldingItem(toContainer) || (toContainer == itemContainer)) {
  1988. player->sendCancel("To jest niemozliwe!");
  1989. return false;
  1990. }
  1991. }
  1992.  
  1993. if((!fromItem->isStackable() || !toItem || fromItem->getID() != toItem->getID() || toItem->getItemCountOrSubtype() >= 100) && toContainer->size() + 1 > toContainer->capacity()) {
  1994. player->sendCancel("Przykro mi, nie ma miejsca.");
  1995. return false;
  1996. }
  1997.  
  1998. Container const *topContainer = toContainer->getTopParent();
  1999. int32_t itemsToadd;
  2000. if(!topContainer)
  2001. topContainer = toContainer;
  2002.  
  2003. Container const *fromContainer = dynamic_cast<const Container*>(fromItem);
  2004. if(fromContainer)
  2005. itemsToadd = fromContainer->getItemHoldingCount() + 1;
  2006. else
  2007. itemsToadd = 1;
  2008.  
  2009. if(topContainer->depot != 0 && player->max_depot_items != 0 && topContainer->getItemHoldingCount() + itemsToadd >= player->max_depot_items){
  2010. player->sendCancel("Nie mozesz polozyc wiecej przedmiotow w depo.");
  2011. return false;
  2012. }
  2013. }
  2014. return true;
  2015. }
  2016.  
  2017. /*container -> container*/
  2018. /*ground -> container*/
  2019. bool Game::onPrepareMoveThing(Player* player,
  2020. const Position& fromPos, const Container* fromContainer, const Item* fromItem,
  2021. const Position& toPos, const Container* toContainer, const Item* toItem, int32_t count)
  2022. {
  2023. if(fromContainer && toContainer && (!fromContainer->shop.empty() || !toContainer->shop.empty())){
  2024. creatureUseShop(player, fromItem->getID(), count, (!fromContainer->shop.empty() ? "fromShop" : "toShop"));
  2025. return false;
  2026. }
  2027.  
  2028. if(!fromContainer && toContainer && !toContainer->shop.empty())
  2029. return false;
  2030. if(toContainer && toContainer->getParent() && !toContainer->getParent()->shop.empty())
  2031. return false;
  2032.  
  2033. if (player->access < g_config.ACCESS_REMOTE &&
  2034. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  2035. {
  2036. player->sendCancel("Za daleko...");
  2037. return false;
  2038. }
  2039. else if (player->access < g_config.ACCESS_REMOTE &&
  2040. ((abs(fromPos.x - toPos.x) > fromItem->throwRange) || (abs(fromPos.y - toPos.y) > fromItem->throwRange)
  2041. || (fromPos.z != toPos.z)))
  2042. {
  2043. player->sendCancel("Destination is out of reach.");
  2044. return false;
  2045. }
  2046.  
  2047. if(!fromItem->isPickupable()) {
  2048. player->sendCancel("You cannot move this object.");
  2049. return false;
  2050. }
  2051. else {
  2052. if((!fromItem->isStackable() || !toItem || fromItem->getID() != toItem->getID() || toItem->getItemCountOrSubtype() >= 100) && toContainer->size() + 1 > toContainer->capacity()) {
  2053. player->sendCancel("Przykro mi, nie ma miejsca.");
  2054. return false;
  2055. }
  2056.  
  2057. const Container *itemContainer = dynamic_cast<const Container*>(fromItem);
  2058. if(itemContainer) {
  2059. if(itemContainer->isHoldingItem(toContainer) || (toContainer == itemContainer) || (fromContainer && fromContainer == itemContainer)) {
  2060. player->sendCancel("To jest niemozliwe!");
  2061. return false;
  2062. }
  2063. }
  2064.  
  2065. double itemWeight = (fromItem->isStackable() ? Item::items[fromItem->getID()].weight * std::max(1, count) : fromItem->getWeight());
  2066. if((!fromContainer || !player->isHoldingContainer(fromContainer)) && player->isHoldingContainer(toContainer)) {
  2067. if(player->access < g_config.ACCESS_PROTECT && player->getFreeCapacity() < itemWeight) {
  2068. player->sendCancel("Ten przedmiot jest za ciezki.");
  2069. return false;
  2070. }
  2071. }
  2072.  
  2073. Container const *topContainer = toContainer->getTopParent();
  2074. int32_t itemsToadd;
  2075. if(!topContainer)
  2076. topContainer = toContainer;
  2077.  
  2078. Container const *fromContainer = dynamic_cast<const Container*>(fromItem);
  2079. if(fromContainer)
  2080. itemsToadd = fromContainer->getItemHoldingCount() + 1;
  2081. else
  2082. itemsToadd = 1;
  2083.  
  2084. if(topContainer->depot != 0 && player->max_depot_items != 0 && topContainer->getItemHoldingCount() >= player->max_depot_items){
  2085. player->sendCancel("Nie mozesz polozyc wiecej przedmiotow w depo.");
  2086. return false;
  2087. }
  2088. }
  2089. return true;
  2090. }
  2091.  
  2092. /*ground -> ground*/
  2093. bool Game::onPrepareMoveCreature(Creature *creature, const Creature* creatureMoving,
  2094. const Tile *fromTile, const Tile *toTile)
  2095. {
  2096. const Player* playerMoving = dynamic_cast<const Player*>(creatureMoving);
  2097. Player* player = dynamic_cast<Player*>(creature);
  2098.  
  2099. #ifdef _BBK_PUSH_DELAY
  2100. if(player && player != creatureMoving && player->pushDelay > 0)
  2101. {
  2102. player->sendCancel("Wait a moment.");
  2103. return false;
  2104. }
  2105. else if(player)
  2106. player->pushDelay = 2*1000; //2 sec
  2107.  
  2108. //wypychanie z depo
  2109. if(player && playerMoving && player != playerMoving && fromTile->isPz() && !toTile->isPz())
  2110. {
  2111. player->sendCancel("Sorry, not possible.");
  2112. return false;
  2113. }
  2114. //wepchanie do depo
  2115. if(player && playerMoving && playerMoving->pzLocked && toTile->isPz())
  2116. {
  2117. player->sendCancel("Sorry, not possible.");
  2118. player->sendCancelWalk();
  2119. return false;
  2120. }
  2121. //wchodzenie do depo
  2122. if(player && player->pzLocked && toTile->isPz())
  2123. {
  2124. player->sendCancel("You can not enter a protection zone after attacking another player.");
  2125. player->sendCancelWalk();
  2126. return false;
  2127. }
  2128. #endif //_BBK_PUSH_DELAY
  2129.  
  2130. if (creature->access < g_config.ACCESS_PROTECT && creature != creatureMoving && !creatureMoving->isPushable())
  2131. {
  2132. creature->sendCancel("Sorry, not possible.");
  2133. return false;
  2134. }
  2135. else if(creature != creatureMoving && toTile->floorChange()){
  2136. creature->sendCancel("Sorry, not possible.");
  2137. return false;
  2138. }
  2139. else if(creature != creatureMoving && toTile->getTeleportItem()){
  2140. creature->sendCancel("Sorry, not possible.");
  2141. return false;
  2142. }
  2143.  
  2144. return true;
  2145. }
  2146.  
  2147. /*ground -> inventory*/
  2148. bool Game::onPrepareMoveThing(Player *player, const Position& fromPos, const Item *item,
  2149. slots_t toSlot, int32_t count)
  2150. {
  2151. if (player->access < g_config.ACCESS_REMOTE &&
  2152. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  2153. {
  2154. player->sendCancel("It's too far.");
  2155. return false;
  2156. }
  2157. else if(!item->isPickupable()) {
  2158. player->sendCancel("You cannot move this object.");
  2159. return false;
  2160. }
  2161.  
  2162. double itemWeight = (item->isStackable() ? Item::items[item->getID()].weight * std::max(1, count) : item->getWeight());
  2163. if(player->access < g_config.ACCESS_PROTECT && player->getFreeCapacity() < itemWeight) {
  2164. player->sendCancel("This object is too heavy.");
  2165. return false;
  2166. }
  2167.  
  2168. return true;
  2169. }
  2170.  
  2171. /*inventory -> inventory*/
  2172. bool Game::onPrepareMoveThing(Player *player, slots_t fromSlot, const Item *fromItem,
  2173. slots_t toSlot, const Item *toItem, int32_t count)
  2174. {
  2175. if(toItem && (!toItem->isStackable() || toItem->getID() != fromItem->getID())) {
  2176. player->sendCancel("There is not enough room.");
  2177. return false;
  2178. }
  2179.  
  2180. return true;
  2181. }
  2182.  
  2183. /*container -> inventory*/
  2184. bool Game::onPrepareMoveThing(Player *player, const Container *fromContainer, const Item *fromItem,
  2185. slots_t toSlot, const Item *toItem, int32_t count)
  2186. {
  2187. if(fromContainer && !fromContainer->shop.empty()){
  2188. creatureUseShop(player, fromItem->getID(), count, "fromShop");
  2189. return false;
  2190. }
  2191. #ifdef _REX_FIGHT_MOD_
  2192. if (toItem && (toItem->getID() == fromItem->getID() && !toItem->isStackable())){
  2193. #else
  2194. if(toItem && (!toItem->isStackable() || toItem->getID() != fromItem->getID())) {
  2195. #endif //Segundo em container -> inventory
  2196. player->sendCancel("There is not enough room.");
  2197. return false;
  2198. }
  2199.  
  2200. double itemWeight = (fromItem->isStackable() ? Item::items[fromItem->getID()].weight * std::max(1, count) : fromItem->getWeight());
  2201. if(player->access < g_config.ACCESS_PROTECT && !player->isHoldingContainer(fromContainer) &&
  2202. player->getFreeCapacity() < itemWeight) {
  2203. player->sendCancel("This object is too heavy.");
  2204. return false;
  2205. }
  2206.  
  2207. return true;
  2208. }
  2209.  
  2210. /*->inventory*/
  2211. bool Game::onPrepareMoveThing(Player *player, const Item *item,
  2212. slots_t toSlot, int32_t count)
  2213. {
  2214. switch(toSlot)
  2215. {
  2216. case SLOT_HEAD:
  2217. if(item->getSlotPosition() & SLOTP_HEAD)
  2218. return true;
  2219. break;
  2220. case SLOT_NECKLACE:
  2221. if(item->getSlotPosition() & SLOTP_NECKLACE)
  2222. return true;
  2223. break;
  2224. case SLOT_BACKPACK:
  2225. if(item->getSlotPosition() & SLOTP_BACKPACK)
  2226. return true;
  2227. break;
  2228. case SLOT_ARMOR:
  2229. if(item->getSlotPosition() & SLOTP_ARMOR)
  2230. return true;
  2231. break;
  2232. case SLOT_RIGHT:
  2233. if(item->getSlotPosition() & SLOTP_RIGHT){
  2234. #ifdef _REX_CVS_MOD_
  2235. //One weapon for hand by ReX
  2236. if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_LEFT] != NULL && player->items[SLOT_LEFT]->isWeapon() && player->items[SLOT_LEFT]->getWeaponType() != SHIELD){
  2237. player->sendCancel("You may use only one weapon.");
  2238. return false;
  2239. }
  2240. #endif
  2241. else if(item->getSlotPosition() & SLOTP_TWO_HAND){
  2242. if(player->items[SLOT_LEFT] != NULL){
  2243. player->sendCancel("First remove the two-handed item.");
  2244. return false;
  2245. }
  2246. return true ;
  2247. }
  2248. else{
  2249. if(player->items[SLOT_LEFT]){
  2250. #ifdef _REX_CVS_MOD_
  2251. //One weapon for hand by ReX
  2252. if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_LEFT] != NULL && player->items[SLOT_LEFT]->isWeapon() && player->items[SLOT_LEFT]->getWeaponType() != SHIELD){
  2253. player->sendCancel("You may use only one weapon.");
  2254. return false;
  2255. }
  2256. #endif
  2257. else if(player->items[SLOT_LEFT]->getSlotPosition() & SLOTP_TWO_HAND){
  2258. player->sendCancel("First remove the two-handed item.");
  2259. return false;
  2260. }
  2261. return true;
  2262. }
  2263. return true;
  2264. }
  2265. }
  2266. break;
  2267. case SLOT_LEFT:
  2268. if(item->getSlotPosition() & SLOTP_LEFT){
  2269. #ifdef _REX_CVS_MOD_
  2270. //One weapon for hand by ReX
  2271. if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_RIGHT] != NULL && player->items[SLOT_RIGHT]->isWeapon() && player->items[SLOT_RIGHT]->getWeaponType() != SHIELD){
  2272. player->sendCancel("You may use only one weapon.");
  2273. return false;
  2274. }
  2275. #endif
  2276. else if(item->getSlotPosition() & SLOTP_TWO_HAND){
  2277. if(player->items[SLOT_RIGHT] != NULL){
  2278. player->sendCancel("First remove the two-handed item.");
  2279. return false;
  2280. }
  2281. return true ;
  2282. }
  2283. else{
  2284. if(player->items[SLOT_RIGHT]){
  2285. #ifdef _REX_CVS_MOD_
  2286. //One weapon for hand by ReX
  2287. if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_RIGHT] != NULL && player->items[SLOT_RIGHT]->isWeapon() && player->items[SLOT_RIGHT]->getWeaponType() != SHIELD){
  2288. player->sendCancel("You may use only one weapon.");
  2289. return false;
  2290. }
  2291. #endif
  2292. else if(player->items[SLOT_RIGHT]->getSlotPosition() & SLOTP_TWO_HAND){
  2293. player->sendCancel("First remove the two-handed item.");
  2294. return false;
  2295. }
  2296. return true;
  2297. }
  2298. return true;
  2299. }
  2300. }
  2301. break;
  2302. case SLOT_LEGS:
  2303. if(item->getSlotPosition() & SLOTP_LEGS)
  2304. return true;
  2305. break;
  2306. case SLOT_FEET:
  2307. if(item->getSlotPosition() & SLOTP_FEET)
  2308. return true;
  2309. break;
  2310. case SLOT_RING:
  2311. if(item->getSlotPosition() & SLOTP_RING
  2312. #ifdef _REX_CVS_MOD_
  2313. || item->getID() == 2208
  2314. #endif
  2315. )
  2316. return true;
  2317. break;
  2318. case SLOT_AMMO:
  2319. if(item->getSlotPosition() & SLOTP_AMMO)
  2320. return true;
  2321. break;
  2322. }
  2323.  
  2324. player->sendCancel("You cannot put that object in that place.");
  2325. return false;
  2326. }
  2327.  
  2328. //container/inventory to container/inventory
  2329. void Game::thingMoveInternal(Player *player,
  2330. unsigned short from_cid, unsigned short from_slotid, unsigned short itemid,
  2331. bool fromInventory,unsigned short to_cid, unsigned short to_slotid, bool toInventory,
  2332. unsigned short count)
  2333. {
  2334. Container *fromContainer = NULL;
  2335. Container *toContainer = NULL;
  2336. Item *fromItem = NULL;
  2337. Item *toItem = NULL;
  2338.  
  2339. if(fromInventory) {
  2340. fromItem = player->getItem(from_cid);
  2341. fromContainer = dynamic_cast<Container *>(fromItem);
  2342. }
  2343. else {
  2344. fromContainer = player->getContainer(from_cid);
  2345.  
  2346. if(fromContainer) {
  2347. if(from_slotid >= fromContainer->size())
  2348. return;
  2349.  
  2350. fromItem = fromContainer->getItem(from_slotid);
  2351. }
  2352. }
  2353.  
  2354. if(toInventory) {
  2355. toItem = player->getItem(to_cid);
  2356. toContainer = dynamic_cast<Container *>(toItem);
  2357. }
  2358. else {
  2359. toContainer = player->getContainer(to_cid);
  2360.  
  2361. if(toContainer) {
  2362. if(to_slotid >= toContainer->capacity())
  2363. return;
  2364.  
  2365. toItem = toContainer->getItem(to_slotid);
  2366. Container *toSlotContainer = dynamic_cast<Container*>(toItem);
  2367. if(toSlotContainer) {
  2368. toContainer = toSlotContainer;
  2369. toItem = NULL;
  2370. }
  2371. }
  2372. }
  2373.  
  2374. if(!fromItem || (toItem == fromItem) || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()) || fromItem->getID() != itemid)
  2375. return;
  2376.  
  2377. //Container to container
  2378. if(!fromInventory && fromContainer && toContainer) {
  2379. Position fromPos = (fromContainer->pos.x == 0xFFFF ? player->pos : fromContainer->pos);
  2380. Position toPos = (toContainer->pos.x == 0xFFFF ? player->pos : toContainer->pos);
  2381.  
  2382. if(onPrepareMoveThing(player, fromPos, fromContainer, fromItem, toPos, toContainer, toItem, count)) {
  2383.  
  2384. autoCloseTrade(fromItem, true);
  2385. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2386. int32_t oldToCount = 0;
  2387.  
  2388. //move around an item in a container
  2389. if(fromItem->isStackable()) {
  2390. if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2391. {
  2392. oldToCount = toItem->getItemCountOrSubtype();
  2393. int32_t newToCount = std::min(100, oldToCount + count);
  2394. toItem->setItemCountOrSubtype(newToCount);
  2395.  
  2396. if(oldToCount != newToCount) {
  2397. autoCloseTrade(toItem);
  2398. }
  2399.  
  2400. int32_t subcount = oldFromCount - count;
  2401. fromItem->setItemCountOrSubtype(subcount);
  2402.  
  2403. int32_t surplusCount = oldToCount + count - 100;
  2404. if(surplusCount > 0) {
  2405. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2406. if(onPrepareMoveThing(player, fromPos, fromContainer, surplusItem, toPos, toContainer, NULL, count)) {
  2407. autoCloseTrade(toContainer);
  2408. toContainer->addItem(surplusItem);
  2409. }
  2410. else {
  2411. delete surplusItem;
  2412. count -= surplusCount; //re-define the actual amount we move.
  2413. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2414. }
  2415. }
  2416. }
  2417. else if(count < oldFromCount) {
  2418. int32_t subcount = oldFromCount - count;
  2419. fromItem->setItemCountOrSubtype(subcount);
  2420.  
  2421. Item* moveItem = Item::CreateItem(fromItem->getID(), count);
  2422. toContainer->addItem(moveItem);
  2423. autoCloseTrade(toContainer);
  2424. }
  2425. else {
  2426. if(fromContainer == toContainer) {
  2427. fromContainer->moveItem(from_slotid, 0);
  2428. }
  2429. else if(fromContainer->removeItem(fromItem)) {
  2430. autoCloseTrade(toContainer);
  2431. toContainer->addItem(fromItem);
  2432. }
  2433. }
  2434.  
  2435. if(fromItem->getItemCountOrSubtype() == 0) {
  2436. fromContainer->removeItem(fromItem);
  2437. this->FreeThing(fromItem);
  2438. }
  2439. }
  2440. else {
  2441. if(fromContainer == toContainer) {
  2442. fromContainer->moveItem(from_slotid, 0);
  2443. }
  2444. else if(fromContainer->removeItem(fromItem)) {
  2445. autoCloseTrade(toContainer);
  2446. toContainer->addItem(fromItem);
  2447. }
  2448. }
  2449.  
  2450. if(player->isHoldingContainer(fromContainer) != player->isHoldingContainer(toContainer)) {
  2451. player->updateInventoryWeigth();
  2452. }
  2453.  
  2454. SpectatorVec list;
  2455. SpectatorVec::iterator it;
  2456.  
  2457. if(fromPos == toPos) {
  2458. getSpectators(Range(fromPos, false), list);
  2459. }
  2460. else {
  2461. getSpectators(Range(fromPos, toPos), list);
  2462. }
  2463.  
  2464. if(!list.empty()) {
  2465. //players
  2466. for(it = list.begin(); it != list.end(); ++it) {
  2467. if(dynamic_cast<Player*>(*it)) {
  2468. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2469. }
  2470. }
  2471.  
  2472. //none-players
  2473. for(it = list.begin(); it != list.end(); ++it) {
  2474. if(!dynamic_cast<Player*>(*it)) {
  2475. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2476. }
  2477. }
  2478. }
  2479. else
  2480. player->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2481. }
  2482. }
  2483. else {
  2484. //inventory to inventory
  2485. if(fromInventory && toInventory && !toContainer) {
  2486. Position fromPos = player->pos;
  2487. Position toPos = player->pos;
  2488. if(onPrepareMoveThing(player, fromItem, (slots_t)to_cid, count) && onPrepareMoveThing(player, (slots_t)from_cid, fromItem, (slots_t)to_cid, toItem, count)) {
  2489.  
  2490. autoCloseTrade(fromItem, true);
  2491. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2492. int32_t oldToCount = 0;
  2493.  
  2494. //bbk 2020
  2495. std::cout << "inventory to inventory" << std::endl;
  2496. if(fromItem && (slots_t)to_cid == SLOT_RING) fromItem->setGlimmer();
  2497. if(toItem && (slots_t)from_cid == SLOT_RING) toItem->removeGlimmer();
  2498.  
  2499. if(fromItem->isStackable()) {
  2500. if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2501. {
  2502. oldToCount = toItem->getItemCountOrSubtype();
  2503. int32_t newToCount = std::min(100, oldToCount + count);
  2504. toItem->setItemCountOrSubtype(newToCount);
  2505.  
  2506. if(oldToCount != newToCount) {
  2507. autoCloseTrade(toItem);
  2508. }
  2509.  
  2510. int32_t subcount = oldFromCount - count;
  2511. fromItem->setItemCountOrSubtype(subcount);
  2512.  
  2513. int32_t surplusCount = oldToCount + count - 100;
  2514. if(surplusCount > 0) {
  2515. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2516. player->sendCancel("There is not enough room.");
  2517. }
  2518.  
  2519. if(fromItem->getItemCountOrSubtype() == 0) {
  2520. player->removeItemInventory(from_cid, true);
  2521. this->FreeThing(fromItem);
  2522. }
  2523. }
  2524. else if(count < oldFromCount) {
  2525. int32_t subcount = oldFromCount - count;
  2526. fromItem->setItemCountOrSubtype(subcount);
  2527.  
  2528. autoCloseTrade(toItem);
  2529. player->removeItemInventory(to_cid, true);
  2530. player->addItemInventory(Item::CreateItem(fromItem->getID(), count), to_cid, true);
  2531.  
  2532. if(fromItem->getItemCountOrSubtype() == 0) {
  2533. player->removeItemInventory(from_cid, true);
  2534. this->FreeThing(fromItem);
  2535. }
  2536. }
  2537. else {
  2538. if(player->removeItemInventory(from_cid, true)) {
  2539. player->removeItemInventory(to_cid, true);
  2540. player->addItemInventory(fromItem, to_cid, true);
  2541. }
  2542. }
  2543. }
  2544. else if(player->removeItemInventory(from_cid, true)) {
  2545. player->removeItemInventory(to_cid, true);
  2546. player->addItemInventory(fromItem, to_cid, true);
  2547. }
  2548.  
  2549. player->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2550. }
  2551. }
  2552. //container to inventory
  2553. else if(!fromInventory && fromContainer && toInventory) {
  2554. if(onPrepareMoveThing(player, fromItem, (slots_t)to_cid, count) && onPrepareMoveThing(player, fromContainer, fromItem, (slots_t)to_cid, toItem, count)) {
  2555. autoCloseTrade(fromItem, true);
  2556. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2557. int32_t oldToCount = 0;
  2558.  
  2559. //bbk 2020
  2560. std::cout << "container to inventory" << std::endl;
  2561. if(fromItem) fromItem->removeGlimmer();
  2562. if(toItem ) toItem->removeGlimmer();
  2563.  
  2564. if(fromItem->isStackable()) {
  2565. if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2566. {
  2567. oldToCount = toItem->getItemCountOrSubtype();
  2568. int32_t newToCount = std::min(100, oldToCount + count);
  2569. toItem->setItemCountOrSubtype(newToCount);
  2570.  
  2571. if(oldToCount != newToCount) {
  2572. autoCloseTrade(toItem);
  2573. }
  2574.  
  2575. int32_t subcount = oldFromCount - count;
  2576. fromItem->setItemCountOrSubtype(subcount);
  2577.  
  2578. int32_t surplusCount = oldToCount + count - 100;
  2579. if(surplusCount > 0) {
  2580. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2581. player->sendCancel("There is not enough room.");
  2582. }
  2583.  
  2584. if(fromItem->getItemCountOrSubtype() == 0) {
  2585. fromContainer->removeItem(fromItem);
  2586. this->FreeThing(fromItem);
  2587. }
  2588. }
  2589. else if(count < oldFromCount) {
  2590. int32_t subcount = oldFromCount - count;
  2591. fromItem->setItemCountOrSubtype(subcount);
  2592.  
  2593. player->removeItemInventory(to_cid, true);
  2594. player->addItemInventory(Item::CreateItem(fromItem->getID(), count), to_cid, true);
  2595.  
  2596. if(toItem) {
  2597. fromContainer->addItem(toItem);
  2598. }
  2599.  
  2600. if(fromItem->getItemCountOrSubtype() == 0) {
  2601. fromContainer->removeItem(fromItem);
  2602. this->FreeThing(fromItem);
  2603. }
  2604. }
  2605. else {
  2606. if(fromContainer->removeItem(fromItem)) {
  2607. player->removeItemInventory(to_cid, true);
  2608. player->addItemInventory(fromItem, to_cid, true);
  2609.  
  2610. if(toItem) {
  2611. fromContainer->addItem(toItem);
  2612. }
  2613. }
  2614. }
  2615. }
  2616. else if(fromContainer->removeItem(fromItem)) {
  2617. player->removeItemInventory(to_cid, true);
  2618. player->addItemInventory(fromItem, to_cid, true);
  2619.  
  2620. if(toItem) {
  2621. fromContainer->addItem(toItem);
  2622. }
  2623. }
  2624.  
  2625. if(!player->isHoldingContainer(fromContainer)) {
  2626. player->updateInventoryWeigth();
  2627. }
  2628.  
  2629. //if(fromContainer->pos.x != 0xFFFF) {
  2630. if(fromContainer->getTopParent()->pos.x != 0xFFFF) {
  2631. SpectatorVec list;
  2632. SpectatorVec::iterator it;
  2633.  
  2634. getSpectators(Range(fromContainer->getTopParent()->pos, false), list);
  2635.  
  2636. //players
  2637. for(it = list.begin(); it != list.end(); ++it) {
  2638. if(dynamic_cast<Player*>(*it)) {
  2639. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2640. }
  2641. }
  2642.  
  2643. //none-players
  2644. for(it = list.begin(); it != list.end(); ++it) {
  2645. if(!dynamic_cast<Player*>(*it)) {
  2646. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2647. }
  2648. }
  2649. }
  2650. else
  2651. player->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2652. }
  2653. }
  2654. //inventory to container
  2655. else if(fromInventory && toContainer) {
  2656. Position fromPos = player->pos;
  2657. Position toPos = (toContainer->pos.x == 0xFFFF ? player->pos : toContainer->pos);
  2658.  
  2659. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2660. int32_t oldToCount = 0;
  2661.  
  2662. //bbk 2020
  2663. std::cout << "inventory to container" << std::endl;
  2664. if(fromItem) fromItem->removeGlimmer();
  2665. if(toItem) toItem->removeGlimmer();
  2666.  
  2667. if(onPrepareMoveThing(player, fromItem, (slots_t)from_cid, toContainer, toItem, count)) {
  2668. autoCloseTrade(fromItem, true);
  2669. if(fromItem->isStackable()) {
  2670. if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2671. {
  2672. oldToCount = toItem->getItemCountOrSubtype();
  2673. int32_t newToCount = std::min(100, oldToCount + count);
  2674. toItem->setItemCountOrSubtype(newToCount);
  2675.  
  2676. if(oldToCount != newToCount) {
  2677. autoCloseTrade(toItem);
  2678. }
  2679.  
  2680. int32_t subcount = oldFromCount - count;
  2681. fromItem->setItemCountOrSubtype(subcount);
  2682.  
  2683. int32_t surplusCount = oldToCount + count - 100;
  2684. if(surplusCount > 0) {
  2685. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2686.  
  2687. if(onPrepareMoveThing(player, fromPos, NULL, surplusItem, toPos, toContainer, NULL, count)) {
  2688. autoCloseTrade(toContainer);
  2689. toContainer->addItem(surplusItem);
  2690. }
  2691. else {
  2692. delete surplusItem;
  2693. count -= surplusCount; //re-define the actual amount we move.
  2694. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2695. }
  2696. }
  2697. }
  2698. else if(count < oldFromCount) {
  2699. int32_t subcount = oldFromCount - count;
  2700. fromItem->setItemCountOrSubtype(subcount);
  2701. autoCloseTrade(toContainer);
  2702. toContainer->addItem(Item::CreateItem(fromItem->getID(), count));
  2703. }
  2704. else {
  2705. if(player->removeItemInventory((slots_t)from_cid, true)) {
  2706. autoCloseTrade(toContainer);
  2707. toContainer->addItem(fromItem);
  2708.  
  2709. if(player->isHoldingContainer(toContainer)) {
  2710. player->updateInventoryWeigth();
  2711. }
  2712. }
  2713. }
  2714.  
  2715. if(fromItem->getItemCountOrSubtype() == 0) {
  2716. player->removeItemInventory(from_cid, true);
  2717. this->FreeThing(fromItem);
  2718. }
  2719. }
  2720. else if(player->removeItemInventory(from_cid, true)) {
  2721. autoCloseTrade(toContainer);
  2722. toContainer->addItem(fromItem);
  2723.  
  2724. if(player->isHoldingContainer(toContainer)) {
  2725. player->updateInventoryWeigth();
  2726. }
  2727. }
  2728.  
  2729. if(!player->isHoldingContainer(toContainer)) {
  2730. player->updateInventoryWeigth();
  2731. }
  2732.  
  2733. if(toContainer->getTopParent()->pos.x != 0xFFFF) {
  2734. SpectatorVec list;
  2735. SpectatorVec::iterator it;
  2736.  
  2737. getSpectators(Range(toContainer->getTopParent()->pos, false), list);
  2738.  
  2739. //players
  2740. for(it = list.begin(); it != list.end(); ++it) {
  2741. if(dynamic_cast<Player*>(*it)) {
  2742. (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2743. }
  2744. }
  2745.  
  2746. //none-players
  2747. for(it = list.begin(); it != list.end(); ++it) {
  2748. if(!dynamic_cast<Player*>(*it)) {
  2749. (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2750. }
  2751. }
  2752. }
  2753. else
  2754. player->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2755. }
  2756. }
  2757. }
  2758. }
  2759.  
  2760. //container/inventory to ground
  2761. void Game::thingMoveInternal(Player *player,
  2762. unsigned char from_cid, unsigned char from_slotid, unsigned short itemid, bool fromInventory,
  2763. const Position& toPos, unsigned char count)
  2764. {
  2765. Container *fromContainer = NULL;
  2766. Tile *toTile = map->getTile(toPos);
  2767. if(!toTile)
  2768. return;
  2769.  
  2770. /*container to ground*/
  2771. if(!fromInventory) {
  2772. fromContainer = player->getContainer(from_cid);
  2773. if(!fromContainer)
  2774. return;
  2775.  
  2776. Position fromPos = (fromContainer->pos.x == 0xFFFF ? player->pos : fromContainer->pos);
  2777. Item *fromItem = dynamic_cast<Item*>(fromContainer->getItem(from_slotid));
  2778. Item* toItem = dynamic_cast<Item*>(toTile->getTopDownItem());
  2779.  
  2780. if(!fromItem || (toItem == fromItem) || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()) || fromItem->getID() != itemid)
  2781. return;
  2782.  
  2783. if(onPrepareMoveThing(player, fromItem, fromPos, toPos, count) && onPrepareMoveThing(player, fromItem, NULL, toTile, count)) {
  2784. autoCloseTrade(fromItem, true);
  2785. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2786. int32_t oldToCount = 0;
  2787.  
  2788. //Do action...
  2789. #ifdef TP_TRASH_BINS
  2790. if (toItem && toItem->isDeleter())
  2791. {
  2792. fromContainer->removeItem(fromItem);
  2793. FreeThing(fromItem);
  2794. }
  2795. else if(fromItem->isStackable()) {
  2796. #else
  2797. if(fromItem->isStackable()) {
  2798. #endif //TP_TRASH_BINS
  2799. if(toItem && toItem->getID() == fromItem->getID())
  2800. {
  2801. oldToCount = toItem->getItemCountOrSubtype();
  2802. int32_t newToCount = std::min(100, oldToCount + count);
  2803. toItem->setItemCountOrSubtype(newToCount);
  2804.  
  2805. if(oldToCount != newToCount) {
  2806. autoCloseTrade(toItem);
  2807. }
  2808.  
  2809. int32_t subcount = oldFromCount - count;
  2810. fromItem->setItemCountOrSubtype(subcount);
  2811.  
  2812. int32_t surplusCount = oldToCount + count - 100;
  2813. if(surplusCount > 0) {
  2814. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2815. surplusItem->pos = toPos;
  2816.  
  2817. toTile->addThing(surplusItem);
  2818. }
  2819.  
  2820. if(fromItem->getItemCountOrSubtype() == 0) {
  2821. fromContainer->removeItem(fromItem);
  2822. this->FreeThing(fromItem);
  2823. }
  2824. }
  2825. else if(count < oldFromCount) {
  2826. int32_t subcount = oldFromCount - count;
  2827. fromItem->setItemCountOrSubtype(subcount);
  2828.  
  2829. Item *moveItem = Item::CreateItem(fromItem->getID(), count);
  2830. moveItem->pos = toPos;
  2831. toTile->addThing(moveItem);
  2832.  
  2833. if(fromItem->getItemCountOrSubtype() == 0) {
  2834. fromContainer->removeItem(fromItem);
  2835. this->FreeThing(fromItem);
  2836. }
  2837. }
  2838. else if(fromContainer->removeItem(fromItem)) {
  2839. fromItem->pos = toPos;
  2840. toTile->addThing(fromItem);
  2841. }
  2842. }
  2843. else if(fromContainer->removeItem(fromItem)) {
  2844. fromItem->pos = toPos;
  2845. toTile->addThing(fromItem);
  2846. }
  2847.  
  2848. if(player->isHoldingContainer(fromContainer)) {
  2849. player->updateInventoryWeigth();
  2850. }
  2851.  
  2852. SpectatorVec list;
  2853. SpectatorVec::iterator it;
  2854.  
  2855. getSpectators(Range(fromPos, false), list);
  2856.  
  2857. SpectatorVec tolist;
  2858. getSpectators(Range(toPos, true), tolist);
  2859.  
  2860. for(it = tolist.begin(); it != tolist.end(); ++it) {
  2861. if(std::find(list.begin(), list.end(), *it) == list.end()) {
  2862. list.push_back(*it);
  2863. }
  2864. }
  2865.  
  2866. //players
  2867. for(it = list.begin(); it != list.end(); ++it) {
  2868. if(dynamic_cast<Player*>(*it)) {
  2869. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2870. }
  2871. }
  2872.  
  2873. //none-players
  2874. for(it = list.begin(); it != list.end(); ++it) {
  2875. if(!dynamic_cast<Player*>(*it)) {
  2876. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2877. }
  2878. }
  2879. }
  2880. }
  2881. else /*inventory to ground*/{
  2882. Item *fromItem = player->getItem(from_cid);
  2883. if(!fromItem || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()) || fromItem->getID() != itemid)
  2884. return;
  2885.  
  2886. if(onPrepareMoveThing(player, fromItem, player->pos, toPos, count) && onPrepareMoveThing(player, fromItem, NULL, toTile, count)) {
  2887. autoCloseTrade(fromItem, true);
  2888. Item* toItem = dynamic_cast<Item*>(toTile->getTopDownItem());
  2889. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2890. int32_t oldToCount = 0;
  2891.  
  2892. //bbk 2020
  2893. std::cout << "inventory to ground" << std::endl;
  2894. if(fromItem) fromItem->removeGlimmer();
  2895.  
  2896. //Do action...
  2897. #ifdef TP_TRASH_BINS
  2898. if(toItem && toItem->isDeleter())
  2899. {
  2900. player->removeItemInventory(from_cid, true);
  2901. FreeThing(fromItem);
  2902. }
  2903. else if(fromItem->isStackable()) {
  2904. #else
  2905. if(fromItem->isStackable()) {
  2906. #endif //TP_TRASH_BINS
  2907. if(toItem && toItem->getID() == fromItem->getID())
  2908. {
  2909. oldToCount = toItem->getItemCountOrSubtype();
  2910. int32_t newToCount = std::min(100, oldToCount + count);
  2911. toItem->setItemCountOrSubtype(newToCount);
  2912.  
  2913. if(oldToCount != newToCount) {
  2914. autoCloseTrade(toItem);
  2915. }
  2916.  
  2917. int32_t subcount = oldFromCount - count;
  2918. fromItem->setItemCountOrSubtype(subcount);
  2919.  
  2920. int32_t surplusCount = oldToCount + count - 100;
  2921. if(surplusCount > 0) {
  2922. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2923. surplusItem->pos = toPos;
  2924.  
  2925. toTile->addThing(surplusItem);
  2926. }
  2927.  
  2928. if(fromItem->getItemCountOrSubtype() == 0) {
  2929. player->removeItemInventory(from_cid, true);
  2930. this->FreeThing(fromItem);
  2931. }
  2932. }
  2933. else if(count < oldFromCount) {
  2934. int32_t subcount = oldFromCount - count;
  2935. fromItem->setItemCountOrSubtype(subcount);
  2936.  
  2937. Item *moveItem = Item::CreateItem(fromItem->getID(), count);
  2938. moveItem->pos = toPos;
  2939. toTile->addThing(moveItem);
  2940.  
  2941. if(fromItem->getItemCountOrSubtype() == 0) {
  2942. player->removeItemInventory(from_cid, true);
  2943. this->FreeThing(fromItem);
  2944. }
  2945. }
  2946. else if(player->removeItemInventory(from_cid, true)) {
  2947. fromItem->pos = toPos;
  2948. toTile->addThing(fromItem);
  2949. }
  2950. }
  2951. else if(player->removeItemInventory(from_cid, true)) {
  2952. fromItem->pos = toPos;
  2953. toTile->addThing(fromItem);
  2954. }
  2955.  
  2956. player->updateInventoryWeigth();
  2957.  
  2958. SpectatorVec list;
  2959. SpectatorVec::iterator it;
  2960.  
  2961. getSpectators(Range(player->pos, false), list);
  2962.  
  2963. SpectatorVec tolist;
  2964. getSpectators(Range(toPos, true), tolist);
  2965.  
  2966. for(it = tolist.begin(); it != tolist.end(); ++it) {
  2967. if(std::find(list.begin(), list.end(), *it) == list.end()) {
  2968. list.push_back(*it);
  2969. }
  2970. }
  2971.  
  2972. //players
  2973. for(it = list.begin(); it != list.end(); ++it) {
  2974. if(dynamic_cast<Player*>(*it)) {
  2975. (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2976. }
  2977. }
  2978.  
  2979. //none-players
  2980. for(it = list.begin(); it != list.end(); ++it) {
  2981. if(!dynamic_cast<Player*>(*it)) {
  2982. (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2983. }
  2984. }
  2985. }
  2986. }
  2987.  
  2988. }
  2989.  
  2990. //ground to container/inventory
  2991. void Game::thingMoveInternal(Player *player, const Position& fromPos, unsigned char stackPos,
  2992. uint16_t itemid, unsigned char to_cid, unsigned char to_slotid, bool toInventory, unsigned char count)
  2993. {
  2994. Tile *fromTile = map->getTile(fromPos);
  2995. if(!fromTile)
  2996. return;
  2997.  
  2998. Container *toContainer = NULL;
  2999.  
  3000. Item* fromItem = dynamic_cast<Item*>(fromTile->getTopDownItem());
  3001. Item *toItem = NULL;
  3002.  
  3003. if(!fromItem || (fromItem->getID() != itemid) || (fromItem != fromTile->getTopDownItem()))
  3004. return;
  3005.  
  3006. if(toInventory)
  3007. {
  3008. toItem = player->getItem(to_cid);
  3009. toContainer = dynamic_cast<Container*>(toItem);
  3010. }
  3011. else
  3012. {
  3013. toContainer = player->getContainer(to_cid);
  3014. if(!toContainer)
  3015. return;
  3016.  
  3017. toItem = toContainer->getItem(to_slotid);
  3018. Container *toSlotContainer = dynamic_cast<Container*>(toItem);
  3019.  
  3020. if(toSlotContainer)
  3021. {
  3022. toContainer = toSlotContainer;
  3023. toItem = NULL;
  3024. }
  3025. }
  3026.  
  3027. if((toItem == fromItem) || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()))
  3028. return;
  3029.  
  3030. /*ground to container*/
  3031. if(toContainer)
  3032. {
  3033. /*if(onPrepareMoveThing(player, fromItem, fromPos, player->pos, count) &&
  3034. onPrepareMoveThing(player, fromItem, NULL, toContainer, toItem, count))*/
  3035.  
  3036. Position toPos = (toContainer->pos.x == 0xFFFF ? player->pos : toContainer->pos);
  3037. if(onPrepareMoveThing(player, fromPos, NULL, fromItem, toPos, toContainer, toItem, count))
  3038. {
  3039. autoCloseTrade(fromItem, true);
  3040. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  3041. int32_t oldToCount = 0;
  3042. int32_t stackpos = fromTile->getThingStackPos(fromItem);
  3043.  
  3044. if(fromItem->isStackable())
  3045. {
  3046. if(toItem && toItem->getID() == fromItem->getID())
  3047. {
  3048. oldToCount = toItem->getItemCountOrSubtype();
  3049. int32_t newToCount = std::min(100, oldToCount + count);
  3050. toItem->setItemCountOrSubtype(newToCount);
  3051.  
  3052. if(oldToCount != newToCount)
  3053. {
  3054. autoCloseTrade(toItem);
  3055. }
  3056.  
  3057. int32_t subcount = oldFromCount - count;
  3058. fromItem->setItemCountOrSubtype(subcount);
  3059.  
  3060. int32_t surplusCount = oldToCount + count - 100;
  3061. if(surplusCount > 0)
  3062. {
  3063. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  3064.  
  3065. if(onPrepareMoveThing(player, fromPos, NULL, surplusItem, toPos, toContainer, NULL, count))
  3066. {
  3067. autoCloseTrade(toContainer);
  3068. toContainer->addItem(surplusItem);
  3069. }
  3070. else
  3071. {
  3072. delete surplusItem;
  3073. count -= surplusCount; //re-define the actual amount we move.
  3074. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  3075. }
  3076. }
  3077.  
  3078. if(fromItem->getItemCountOrSubtype() == 0)
  3079. {
  3080. if(fromTile->removeThing(fromItem))
  3081. {
  3082. this->FreeThing(fromItem);
  3083. }
  3084. }
  3085. }
  3086. else if(count < oldFromCount)
  3087. {
  3088. int32_t subcount = oldFromCount - count;
  3089. fromItem->setItemCountOrSubtype(subcount);
  3090.  
  3091. autoCloseTrade(toContainer);
  3092. toContainer->addItem(Item::CreateItem(fromItem->getID(), count));
  3093.  
  3094. if(fromItem->getItemCountOrSubtype() == 0)
  3095. {
  3096. if(fromTile->removeThing(fromItem))
  3097. {
  3098. this->FreeThing(fromItem);
  3099. }
  3100. }
  3101. }
  3102. else if(fromTile->removeThing(fromItem))
  3103. {
  3104. autoCloseTrade(toContainer);
  3105. toContainer->addItem(fromItem);
  3106. }
  3107. }
  3108. else
  3109. {
  3110. if(fromTile->removeThing(fromItem))
  3111. {
  3112. autoCloseTrade(toContainer);
  3113. toContainer->addItem(fromItem);
  3114. }
  3115. }
  3116.  
  3117. if(player->isHoldingContainer(toContainer))
  3118. {
  3119. player->updateInventoryWeigth();
  3120. }
  3121.  
  3122. SpectatorVec list;
  3123. SpectatorVec::iterator it;
  3124.  
  3125. getSpectators(Range(fromPos, true), list);
  3126.  
  3127. //players
  3128. for(it = list.begin(); it != list.end(); ++it)
  3129. {
  3130. if(dynamic_cast<Player*>(*it))
  3131. {
  3132. (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  3133. }
  3134. }
  3135.  
  3136. //none-players
  3137. for(it = list.begin(); it != list.end(); ++it)
  3138. {
  3139. if(!dynamic_cast<Player*>(*it))
  3140. {
  3141. (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  3142. }
  3143. }
  3144. }
  3145. }
  3146. //ground to inventory
  3147. else if(toInventory)
  3148. {
  3149. if(onPrepareMoveThing(player, fromPos, fromItem, (slots_t)to_cid, count) && onPrepareMoveThing(player, fromItem, (slots_t)to_cid, count))
  3150. {
  3151. autoCloseTrade(fromItem, true);
  3152. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  3153. int32_t oldToCount = 0;
  3154. int32_t stackpos = fromTile->getThingStackPos(fromItem);
  3155.  
  3156. //bbk 2020
  3157. std::cout << "ground to inventory" << std::endl;
  3158. if(fromItem && (slots_t)to_cid == SLOT_RING) {
  3159. fromItem->setGlimmer();
  3160. if(toItem) toItem->removeGlimmer();
  3161. }
  3162.  
  3163. if(fromItem->isStackable())
  3164. {
  3165. if(toItem && toItem->getID() == fromItem->getID())
  3166. {
  3167. oldToCount = toItem->getItemCountOrSubtype();
  3168. int32_t newToCount = std::min(100, oldToCount + count);
  3169. toItem->setItemCountOrSubtype(newToCount);
  3170.  
  3171. if(oldToCount != newToCount)
  3172. {
  3173. autoCloseTrade(toItem);
  3174. }
  3175.  
  3176. int32_t subcount = oldFromCount - count;
  3177. fromItem->setItemCountOrSubtype(subcount);
  3178.  
  3179. int32_t surplusCount = oldToCount + count - 100;
  3180. if(surplusCount > 0)
  3181. {
  3182. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  3183. player->sendCancel("Sorry not enough room.");
  3184. }
  3185.  
  3186. if(fromItem->getItemCountOrSubtype() == 0)
  3187. {
  3188. if(fromTile->removeThing(fromItem))
  3189. {
  3190. this->FreeThing(fromItem);
  3191. }
  3192. }
  3193. }
  3194. else if(count < oldFromCount)
  3195. {
  3196. int32_t subcount = oldFromCount - count;
  3197. fromItem->setItemCountOrSubtype(subcount);
  3198.  
  3199. player->removeItemInventory(to_cid, true);
  3200. player->addItemInventory(Item::CreateItem(fromItem->getID(), count), to_cid, true);
  3201.  
  3202. if(toItem)
  3203. {
  3204. autoCloseTrade(toItem);
  3205. fromTile->addThing(toItem);
  3206. toItem->pos = fromPos;
  3207. }
  3208.  
  3209. if(fromItem->getItemCountOrSubtype() == 0)
  3210. {
  3211. if(fromTile->removeThing(fromItem))
  3212. {
  3213. this->FreeThing(fromItem);
  3214. }
  3215. }
  3216. }
  3217. else
  3218. {
  3219. if(fromTile->removeThing(fromItem))
  3220. {
  3221. player->removeItemInventory(to_cid, true);
  3222. player->addItemInventory(fromItem, to_cid, true);
  3223.  
  3224. if(toItem)
  3225. {
  3226. autoCloseTrade(toItem);
  3227. fromTile->addThing(toItem);
  3228. toItem->pos = fromPos;
  3229. }
  3230. }
  3231. }
  3232. }
  3233. else
  3234. {
  3235. if(fromTile->removeThing(fromItem))
  3236. {
  3237. player->removeItemInventory(to_cid, true);
  3238. player->addItemInventory(fromItem, to_cid, true);
  3239.  
  3240. if(toItem)
  3241. {
  3242. autoCloseTrade(toItem);
  3243. fromTile->addThing(toItem);
  3244. toItem->pos = fromPos;
  3245. }
  3246. }
  3247. }
  3248.  
  3249. player->updateInventoryWeigth();
  3250.  
  3251. SpectatorVec list;
  3252. SpectatorVec::iterator it;
  3253.  
  3254. getSpectators(Range(fromPos, true), list);
  3255.  
  3256. //players
  3257. for(it = list.begin(); it != list.end(); ++it)
  3258. {
  3259. if(dynamic_cast<Player*>(*it))
  3260. {
  3261. (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  3262. }
  3263. }
  3264.  
  3265. //none-players
  3266. for(it = list.begin(); it != list.end(); ++it)
  3267. {
  3268. if(!dynamic_cast<Player*>(*it))
  3269. {
  3270. (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  3271. }
  3272. }
  3273. }
  3274. }
  3275. }
  3276.  
  3277. //ground to ground
  3278. void Game::thingMoveInternal(Creature *creature, unsigned short from_x, unsigned short from_y, unsigned char from_z,
  3279. unsigned char stackPos, unsigned short itemid, unsigned short to_x, unsigned short to_y, unsigned char to_z, unsigned char count)
  3280. {
  3281. Tile *fromTile = getTile(from_x, from_y, from_z);
  3282. if(!fromTile)
  3283. return;
  3284.  
  3285. if(dynamic_cast<Player*>(creature) && fromTile && !fromTile->ground) {
  3286. dynamic_cast<Player*>(creature)->sendCancelWalk();
  3287. return;
  3288. }
  3289.  
  3290. Tile *toTile = getTile(to_x, to_y, to_z);
  3291. /*
  3292. if(!toTile){
  3293. if(dynamic_cast<Player*>(player))
  3294. dynamic_cast<Player*>(player)->sendCancelWalk("Sorry, not possible...");
  3295. return;
  3296. }
  3297. */
  3298.  
  3299. Thing *thing = fromTile->getThingByStackPos(stackPos);
  3300.  
  3301. if (!thing)
  3302. return;
  3303.  
  3304. Item* item = dynamic_cast<Item*>(thing);
  3305. Creature* creatureMoving = dynamic_cast<Creature*>(thing);
  3306. Player* playerMoving = dynamic_cast<Player*>(creatureMoving);
  3307. Player* player = dynamic_cast<Player*>(creature);
  3308.  
  3309. Position oldPos;
  3310. oldPos.x = from_x;
  3311. oldPos.y = from_y;
  3312. oldPos.z = from_z;
  3313.  
  3314. #ifdef TP_TRASH_BINS
  3315. if(toTile)
  3316. {
  3317. Thing *tothing = toTile->getThingByStackPos(stackPos);
  3318. Item *toItem = dynamic_cast<Item*>(tothing);
  3319.  
  3320. if(item && toItem && !playerMoving && !creature && toItem->isDeleter())
  3321. {
  3322. fromTile->removeThing(item);
  3323. this->FreeThing(item);
  3324. //creatureBroadcastTileUpdated(oldPos);
  3325. sendRemoveThing(player, item->pos, item, stackPos);
  3326. return;
  3327. }
  3328. }
  3329. #endif //TP_TRASH_BINS
  3330. /* if (toTile){
  3331. ItemVector::iterator brn;
  3332. for (brn = toTile->downItems.begin(); brn != toTile->downItems.end(); brn++)
  3333. {
  3334. 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)
  3335. */
  3336. if(toTile && player && playerMoving && playerMoving != player && toTile->getFieldItem())
  3337. {
  3338. player->sendCancel("Sorry, not possible.");
  3339. return;
  3340. }
  3341. // *** Creature moving itself to a non-tile
  3342. if(!toTile && creatureMoving && creatureMoving == creature){
  3343. //change level begin
  3344. Tile* downTile = getTile(to_x, to_y, to_z+1);
  3345. //diagonal begin
  3346. if(!downTile)
  3347. {
  3348. if(player) {
  3349. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  3350. player->sendCancelWalk();
  3351. }
  3352.  
  3353. return;
  3354. }
  3355.  
  3356. if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  3357. teleport(creatureMoving, Position(creatureMoving->pos.x-2, creatureMoving->pos.y+2, creatureMoving->pos.z+1));
  3358. }
  3359. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  3360. teleport(creatureMoving, Position(creatureMoving->pos.x+2, creatureMoving->pos.y+2, creatureMoving->pos.z+1));
  3361. }
  3362. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  3363. teleport(creatureMoving, Position(creatureMoving->pos.x-2, creatureMoving->pos.y-2, creatureMoving->pos.z+1));
  3364. }
  3365. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  3366. teleport(creatureMoving, Position(creatureMoving->pos.x+2, creatureMoving->pos.y-2, creatureMoving->pos.z+1));
  3367. }
  3368. //diagonal end
  3369. else if(downTile->floorChange(NORTH)){
  3370. teleport(creatureMoving, Position(to_x, to_y + 1, creatureMoving->pos.z+1));
  3371. }
  3372. else if(downTile->floorChange(SOUTH)){
  3373. teleport(creatureMoving, Position(to_x, to_y - 1, creatureMoving->pos.z+1));
  3374. }
  3375. else if(downTile->floorChange(EAST)){
  3376. teleport(creatureMoving, Position(to_x - 1, to_y, creatureMoving->pos.z+1));
  3377. }
  3378. else if(downTile->floorChange(WEST)){
  3379. teleport(creatureMoving, Position(to_x + 1, to_y, creatureMoving->pos.z+1));
  3380. }
  3381. else
  3382. if(player) {
  3383. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  3384. player->sendCancelWalk();
  3385. }
  3386.  
  3387. //change level end
  3388. return;
  3389. }
  3390.  
  3391. #ifdef DT_PREMMY
  3392. if(player && playerMoving && !player->premmium == true){
  3393. if(!premmytiles.empty()){
  3394. for(int32_t o = 0; o < premmytiles.size(); o++) {
  3395. if((premmytiles[o].second.x != 0) &&
  3396. (premmytiles[o].second.y != 0) && (premmytiles[o].second.z != 0)){
  3397. if(Position(to_x, to_y, to_z) == premmytiles[o].first) {
  3398. player->sendCancelWalk();
  3399. teleport(playerMoving,
  3400. Position(premmytiles[o].second.x, premmytiles[o].second.y,
  3401. premmytiles[o].second.z));
  3402. player->sendMagicEffect(player->pos,
  3403. NM_ME_MAGIC_ENERGIE);
  3404. return;
  3405. }
  3406. }
  3407. else{
  3408. if(Position(to_x, to_y, to_z) == premmytiles[o].first) {
  3409. player->sendCancelWalk();
  3410. break;
  3411. }
  3412. }
  3413. }
  3414. }
  3415. }
  3416.  
  3417. #endif //DT_PREMMY
  3418.  
  3419.  
  3420.  
  3421. // *** Checking if the thing can be moved around
  3422.  
  3423. if(!toTile)
  3424. return;
  3425.  
  3426. if(!onPrepareMoveThing(creature, thing, oldPos, Position(to_x, to_y, to_z), count))
  3427. return;
  3428.  
  3429. if(creatureMoving && !onPrepareMoveCreature(creature, creatureMoving, fromTile, toTile))
  3430. return;
  3431.  
  3432. if(!onPrepareMoveThing(creature, thing, fromTile, toTile, count))
  3433. return;
  3434.  
  3435. Position to_pos;
  3436. to_pos.x = to_x;
  3437. to_pos.y = to_y;
  3438. to_pos.z = to_z;
  3439.  
  3440. Item* fromItem = dynamic_cast<Item*>(getThing(oldPos, stackPos, player));
  3441. Item* toItem = dynamic_cast<Item*>(toTile->getTopDownItem());
  3442.  
  3443. if(fromItem && fromItem->isStackable()){
  3444. if(fromItem->getItemCountOrSubtype() < count)
  3445. {
  3446. player->sendCancel("Sorry, not possible.");
  3447. return;
  3448. }
  3449.  
  3450. if((abs(player->pos.x - oldPos.x) > 1) || (abs(player->pos.y - oldPos.y) > 1) || (player->pos.z != oldPos.z)){
  3451. player->sendCancel("It's far away.");
  3452. return;
  3453. }
  3454. if(toItem && fromItem->getID() == toItem->getID()){
  3455. int32_t oldToCount = toItem->getItemCountOrSubtype();
  3456. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  3457. int32_t newToCount = std::min(100, oldToCount + count);
  3458. toItem->setItemCountOrSubtype(newToCount);
  3459.  
  3460. if(oldToCount != newToCount) {
  3461. autoCloseTrade(toItem);
  3462. }
  3463.  
  3464. int32_t subcount = oldFromCount - count;
  3465. fromItem->setItemCountOrSubtype(subcount);
  3466.  
  3467. int32_t surplusCount = oldToCount + count - 100;
  3468. if(surplusCount > 0) {
  3469. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  3470. surplusItem->pos = to_pos;
  3471. toTile->addThing(surplusItem);
  3472. }
  3473.  
  3474. if(fromItem->getItemCountOrSubtype() == 0) {
  3475. if(removeThing(player, oldPos, fromItem))
  3476. player->updateInventoryWeigth();
  3477. }
  3478.  
  3479. creatureBroadcastTileUpdated(to_pos);
  3480. creatureBroadcastTileUpdated(oldPos);
  3481.  
  3482. return;
  3483. }
  3484. else if(count < fromItem->getItemCountOrSubtype()) {
  3485. int32_t subcount = fromItem->getItemCountOrSubtype() - count;
  3486. fromItem->setItemCountOrSubtype(subcount);
  3487.  
  3488. Item *moveItem = Item::CreateItem(fromItem->getID(), count);
  3489. moveItem->pos = to_pos;
  3490. toTile->addThing(moveItem);
  3491.  
  3492. if(fromItem->getItemCountOrSubtype() == 0) {
  3493. if(removeThing(player, oldPos, fromItem))
  3494. player->updateInventoryWeigth();
  3495. }
  3496.  
  3497. creatureBroadcastTileUpdated(to_pos);
  3498. creatureBroadcastTileUpdated(oldPos);
  3499. return;
  3500. }
  3501. else{
  3502. Item *moveItem = Item::CreateItem(fromItem->getID(), fromItem->getItemCountOrSubtype());
  3503. moveItem->pos = to_pos;
  3504. toTile->addThing(moveItem);
  3505.  
  3506. if(removeThing(player, oldPos, fromItem))
  3507. player->updateInventoryWeigth();
  3508.  
  3509. creatureBroadcastTileUpdated(to_pos);
  3510. creatureBroadcastTileUpdated(oldPos);
  3511. return;
  3512. }
  3513.  
  3514. return;
  3515. }
  3516.  
  3517. /*
  3518. if(item && (item->getID() != itemid || item != fromTile->getTopDownItem()))
  3519. return;
  3520. */
  3521.  
  3522. // *** If the destiny is a teleport item, teleport the thing
  3523.  
  3524. const Teleport *teleportitem = toTile->getTeleportItem();
  3525. if(teleportitem) {
  3526. Player *player = dynamic_cast<Player*>(thing);
  3527. teleport(thing, teleportitem->getDestPos());
  3528. if(player) {
  3529. globalMagicEffect(player->pos, NM_ME_ENERGY_AREA);
  3530. }
  3531. return;
  3532. }
  3533.  
  3534. Monster* monsterMoving = dynamic_cast<Monster*>(creatureMoving);
  3535. if (monsterMoving && toTile->isPz()){
  3536. return;
  3537. }
  3538.  
  3539. #ifdef TLM_HOUSE_SYSTEM
  3540. if (playerMoving && toTile->getHouse() &&
  3541. (fromTile->getHouse() != toTile->getHouse() || playerMoving->houseRightsChanged))
  3542. {
  3543. if (playerMoving->access < g_config.ACCESS_HOUSE &&
  3544. toTile->getHouse()->getPlayerRights(playerMoving->getName()) == HOUSE_NONE)
  3545. {
  3546. playerMoving->sendTextMessage(MSG_SMALLINFO, "You are not invited.");
  3547. playerMoving->sendCancelWalk();
  3548. return;
  3549. }
  3550. else
  3551. playerMoving->houseRightsChanged = false; // if we are invited stop checking rights
  3552. }
  3553. #endif //TLM_HOUSE_SYSTEM
  3554.  
  3555. // *** Normal moving
  3556.  
  3557. if(creatureMoving)
  3558. {
  3559. // we need to update the direction the player is facing to...
  3560. // otherwise we are facing some problems in turning into the
  3561. // direction we were facing before the movement
  3562. // check y first cuz after a diagonal move we lock to east or west
  3563. if (to_y < oldPos.y) creatureMoving->direction = NORTH;
  3564. if (to_y > oldPos.y) creatureMoving->direction = SOUTH;
  3565. if (to_x > oldPos.x) creatureMoving->direction = EAST;
  3566. if (to_x < oldPos.x) creatureMoving->direction = WEST;
  3567. }
  3568.  
  3569. int32_t oldstackpos = fromTile->getThingStackPos(thing);
  3570. if (fromTile->removeThing(thing))
  3571. {
  3572. toTile->addThing(thing);
  3573.  
  3574. thing->pos.x = to_x;
  3575. thing->pos.y = to_y;
  3576. thing->pos.z = to_z;
  3577.  
  3578. SpectatorVec list;
  3579. SpectatorVec::iterator it;
  3580.  
  3581. getSpectators(Range(oldPos, Position(to_x, to_y, to_z)), list);
  3582.  
  3583. #ifdef TRS_GM_INVISIBLE
  3584. if(playerMoving && playerMoving->gmInvisible)
  3585. {
  3586. for(it = list.begin(); it != list.end(); ++it)
  3587. {
  3588. if(playerMoving == (*it) || (*it)->access >= playerMoving->access)
  3589. {
  3590. if(Player* p = dynamic_cast<Player*>(*it))
  3591. {
  3592. if(p->attackedCreature == creature->getID())
  3593. {
  3594. autoCloseAttack(p, creature);
  3595. }
  3596. (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3597. }
  3598. }
  3599. }
  3600. }
  3601. else if(playerMoving && !playerMoving->gmInvisible)
  3602. {
  3603. for(it = list.begin(); it != list.end(); ++it)
  3604. {
  3605. if(Player* p = dynamic_cast<Player*>(*it))
  3606. {
  3607. if(p->attackedCreature == creature->getID())
  3608. {
  3609. autoCloseAttack(p, creature);
  3610. }
  3611. (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3612. }
  3613. }
  3614. }
  3615. else
  3616. {
  3617. for(it = list.begin(); it != list.end(); ++it)
  3618. {
  3619. if(Player* p = dynamic_cast<Player*>(*it))
  3620. {
  3621. if(p->attackedCreature == creature->getID())
  3622. {
  3623. autoCloseAttack(p, creature);
  3624. }
  3625. (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3626. }
  3627. }
  3628. }
  3629. #else //TRS_GM_INVISIBLE
  3630. //players
  3631. for(it = list.begin(); it != list.end(); ++it)
  3632. {
  3633. if(Player* p = dynamic_cast<Player*>(*it)) {
  3634. if(p->attackedCreature == creature->getID()) {
  3635. autoCloseAttack(p, creature);
  3636. }
  3637. (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3638. }
  3639. }
  3640. #endif //TRS_GM_INVISIBLE
  3641.  
  3642. //none-players
  3643. for(it = list.begin(); it != list.end(); ++it)
  3644. {
  3645. if(!dynamic_cast<Player*>(*it)) {
  3646. (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3647. }
  3648. }
  3649.  
  3650. autoCloseTrade(item, true);
  3651. //depot tiles
  3652.  
  3653. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 426))
  3654. {
  3655. int32_t e = 0;
  3656. Container* c = playerMoving->getDepot(1);
  3657. std::stringstream s;
  3658. e += getDepot(c, e);
  3659. s << "Your depot contains " << e;
  3660. if(e > 1)
  3661. s << " items.";
  3662. else
  3663. s << " item.";
  3664. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3665. }
  3666.  
  3667. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 416))
  3668. {
  3669. int32_t e = 0;
  3670. Container* c = playerMoving->getDepot(2);
  3671. std::stringstream s;
  3672. e += getDepot(c, e);
  3673. s << "Your depot contains " << e;
  3674. if(e > 1)
  3675. s << " items.";
  3676. else
  3677. s << " item.";
  3678. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3679. }
  3680.  
  3681. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 446))
  3682. {
  3683. int32_t e = 0;
  3684. Container* c = playerMoving->getDepot(3);
  3685. std::stringstream s;
  3686. e += getDepot(c, e);
  3687. s << "Your depot contains " << e;
  3688. if(e > 1)
  3689. s << " items.";
  3690. else
  3691. s << " item.";
  3692. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3693. }
  3694.  
  3695. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 3216))
  3696. {
  3697. int32_t e = 0;
  3698. Container* c = playerMoving->getDepot(4);
  3699. std::stringstream s;
  3700. e += getDepot(c, e);
  3701. s << "Your depot contains " << e;
  3702. if(e > 1)
  3703. s << " items.";
  3704. else
  3705. s << " item.";
  3706. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3707. }
  3708.  
  3709. if(playerMoving && toTile && fromTile)
  3710. {
  3711. actions.luaWalk(playerMoving,playerMoving->pos,toTile->ground->getID(),toTile->ground->getUniqueId(),toTile->ground->getActionId()); //CHANGE onWalk
  3712. }
  3713.  
  3714. if(playerMoving && toTile && fromTile)
  3715. {
  3716. actions.luaWalkOff(playerMoving,oldPos,fromTile->ground->getID(),fromTile->ground->getUniqueId(),fromTile->ground->getActionId()); //CHANGE onWalk
  3717. }
  3718.  
  3719. if(playerMoving && fromTile && toTile && player == playerMoving)
  3720. switch(toTile->ground->getID())
  3721. {
  3722. case 416:
  3723. {
  3724. toTile->removeThing(toTile->ground);
  3725. toTile->addThing(new Item(417));
  3726. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3727. }
  3728. break;
  3729.  
  3730. case 426:
  3731. {
  3732. toTile->removeThing(toTile->ground);
  3733. toTile->addThing(new Item(425));
  3734. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3735. }
  3736. break;
  3737. case 3216:
  3738. {
  3739. toTile->removeThing(toTile->ground);
  3740. toTile->addThing(new Item(3217));
  3741. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3742. }
  3743. break;
  3744. case 446:
  3745. {
  3746. toTile->removeThing(toTile->ground);
  3747. toTile->addThing(new Item(447));
  3748. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3749. }
  3750. break;
  3751. case 293:
  3752. {
  3753. toTile->removeThing(toTile->ground);
  3754. toTile->addThing(new Item(294));
  3755. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3756. }
  3757. break;
  3758. }
  3759. switch(fromTile->ground->getID())
  3760. {
  3761. case 3217:
  3762. {
  3763. fromTile->removeThing(fromTile->ground);
  3764. fromTile->addThing(new Item(3216));
  3765. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3766. break;
  3767. }
  3768. case 417:
  3769. {
  3770. fromTile->removeThing(fromTile->ground);
  3771. fromTile->addThing(new Item(416));
  3772. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3773. break;
  3774. }
  3775. case 425:
  3776. {
  3777. fromTile->removeThing(fromTile->ground);
  3778. fromTile->addThing(new Item(426));
  3779. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3780. break;
  3781. }
  3782. case 447:
  3783. {
  3784. fromTile->removeThing(fromTile->ground);
  3785. fromTile->addThing(new Item(446));
  3786. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3787. break;
  3788. }
  3789. }
  3790. //end depot tiles-+
  3791. if (playerMoving)
  3792. {
  3793. if(playerMoving->attackedCreature != 0) {
  3794. Creature* attackedCreature = getCreatureByID(creatureMoving->attackedCreature);
  3795. if(attackedCreature){
  3796. autoCloseAttack(playerMoving, attackedCreature);
  3797. }
  3798. }
  3799.  
  3800. if(playerMoving->tradePartner != 0) {
  3801. Player* tradePartner = getPlayerByID(playerMoving->tradePartner);
  3802. if(tradePartner) {
  3803. if((std::abs(playerMoving->pos.x - tradePartner->pos.x) > 2) ||
  3804. (std::abs(playerMoving->pos.y - tradePartner->pos.y) > 2) || (playerMoving->pos.z != tradePartner->pos.z)
  3805. #ifdef HUCZU_FIX
  3806. || (fromTile->isHouse() && !toTile->isHouse())
  3807. #endif //HUCZU_FIX
  3808. ){
  3809. playerCloseTrade(playerMoving);
  3810. }
  3811. }
  3812. }
  3813.  
  3814. //change level begin
  3815. if(toTile->floorChangeDown())
  3816. {
  3817. Tile* downTile = getTile(to_x, to_y, to_z+1);
  3818. if(downTile){
  3819. //diagonal begin
  3820. if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  3821. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y+1, playerMoving->pos.z+1));
  3822. }
  3823. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  3824. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y+1, playerMoving->pos.z+1));
  3825. }
  3826. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  3827. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y-1, playerMoving->pos.z+1));
  3828. }
  3829. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  3830. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y-1, playerMoving->pos.z+1));
  3831. }
  3832. //diagonal end
  3833. else if(downTile->floorChange(NORTH)){
  3834. teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y+1, playerMoving->pos.z+1));
  3835. }
  3836. else if(downTile->floorChange(SOUTH)){
  3837. teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y-1, playerMoving->pos.z+1));
  3838. }
  3839. else if(downTile->floorChange(EAST)){
  3840. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y, playerMoving->pos.z+1));
  3841. }
  3842. else if(downTile->floorChange(WEST)){
  3843. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y, playerMoving->pos.z+1));
  3844. }
  3845. else { //allow just real tiles to be hole'like
  3846. // TODO: later can be changed to check for piled items like chairs, boxes
  3847. teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y, playerMoving->pos.z+1));
  3848. }
  3849. }
  3850. }
  3851. //diagonal begin
  3852. else if(toTile->floorChange(NORTH) && toTile->floorChange(EAST)){
  3853. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y-1, playerMoving->pos.z-1));
  3854. }
  3855. else if(toTile->floorChange(NORTH) && toTile->floorChange(WEST)){
  3856. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y-1, playerMoving->pos.z-1));
  3857. }
  3858. else if(toTile->floorChange(SOUTH) && toTile->floorChange(EAST)){
  3859. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y+1, playerMoving->pos.z-1));
  3860. }
  3861. else if(toTile->floorChange(SOUTH) && toTile->floorChange(WEST)){
  3862. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y+1, playerMoving->pos.z-1));
  3863. }
  3864. //diagonal end
  3865. else if(toTile->floorChange(NORTH)){
  3866. teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y-1, playerMoving->pos.z-1));
  3867. }
  3868. else if(toTile->floorChange(SOUTH)){
  3869. teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y+1, playerMoving->pos.z-1));
  3870. }
  3871. else if(toTile->floorChange(EAST)){
  3872. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y, playerMoving->pos.z-1));
  3873. }
  3874. else if(toTile->floorChange(WEST)){
  3875. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y, playerMoving->pos.z-1));
  3876. }
  3877. //change level end
  3878. }
  3879.  
  3880. // Magic Field in destiny field
  3881. #ifdef HUCZU_FIX
  3882. if(toTile && playerMoving && playerMoving->access < g_config.ACCESS_PROTECT && !toTile->downItems.empty() && !toTile->isPvpArena())
  3883. #else
  3884. if(toTile && playerMoving && playerMoving->access < g_config.ACCESS_PROTECT && !toTile->downItems.empty() || toTile && creatureMoving && creatureMoving->access < g_config.ACCESS_PROTECT && !toTile->downItems.empty())
  3885. #endif //HUCZU_FIX
  3886. {
  3887. ItemVector::iterator iit;
  3888. for (iit = toTile->downItems.begin(); iit != toTile->downItems.end(); iit++)
  3889. {
  3890. if(toTile->isPvpArena()) break;
  3891. if(!(*iit)) continue;
  3892. Item *item = dynamic_cast<Item*>(*iit);
  3893. if(!item) continue;
  3894. if(!creatureMoving || creatureMoving->isRemoved || creatureMoving->health <= 0) break;
  3895. if (item->getID() == 1492 || item->getID() == 1423 || item->getID() == 1487 || item->getID() == 1500){//Fire - Big
  3896. doFieldDamage(creatureMoving, 199 , NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 20);
  3897. // creature DamageColor, damageEffect, hitEffect attackType, offensive, damage
  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() == 1493 || item->getID() == 1424 || item->getID() == 1488 || item->getID() == 1501){//Fire Medium
  3902. doFieldDamage(creatureMoving, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 10);
  3903. if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3904. CreateCondition(creatureMoving, NULL, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 10, 10, 2000, 10);
  3905. }
  3906. else if(item->getID() == 1495 || item->getID() == 1491 || item->getID() == 1504){//Energy
  3907. doFieldDamage(creatureMoving, 71, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 30);
  3908. if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3909. CreateCondition(creatureMoving, NULL, 71, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 30, 30, 2000, 3);
  3910. }
  3911. else if(item->getID() == 1496 || item->getID() == 1490 || item->getID() == 1503 || item->getID() == 1505){//Poison
  3912. doFieldDamage(creatureMoving, 30, NM_ME_POISEN, NM_ME_POISEN, ATTACK_POISON, true, 10);
  3913. if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3914. CreateCondition(creatureMoving, NULL, 30, NM_ME_POISEN, NM_ME_POISEN_RINGS, ATTACK_POISON, true, 10, 10, 2000, 10);
  3915. }
  3916. }
  3917. }
  3918. }
  3919.  
  3920. if(creatureMoving && !toTile->isPvpArena())
  3921. {
  3922. const MagicEffectItem* fieldItem = toTile->getFieldItem();
  3923.  
  3924. if(fieldItem) {
  3925. const MagicEffectTargetCreatureCondition *magicTargetCondition = fieldItem->getCondition();
  3926.  
  3927. if(!(getWorldType() == WORLD_TYPE_NO_PVP && playerMoving && magicTargetCondition && magicTargetCondition->getOwnerID() != 0)) {
  3928. fieldItem->getDamage(creatureMoving);
  3929. }
  3930.  
  3931. if(magicTargetCondition && ((magicTargetCondition->attackType == ATTACK_FIRE) ||
  3932. (magicTargetCondition->attackType == ATTACK_POISON) ||
  3933. (magicTargetCondition->attackType == ATTACK_ENERGY))) {
  3934. Creature *c = getCreatureByID(magicTargetCondition->getOwnerID());
  3935. creatureMakeMagic(c, thing->pos, magicTargetCondition);
  3936. }
  3937. }
  3938. }
  3939. }
  3940.  
  3941.  
  3942. void Game::getSpectators(const Range& range, SpectatorVec& list)
  3943. {
  3944. map->getSpectators(range, list);
  3945. }
  3946.  
  3947. void Game::creatureTurn(Creature *creature, Direction dir)
  3948. {
  3949. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureTurn()");
  3950.  
  3951. if (creature->direction != dir) {
  3952. creature->direction = dir;
  3953.  
  3954. int32_t stackpos = map->getTile(creature->pos)->getThingStackPos(creature);
  3955.  
  3956. SpectatorVec list;
  3957. SpectatorVec::iterator it;
  3958.  
  3959. map->getSpectators(Range(creature->pos, true), list);
  3960.  
  3961. //players
  3962. for(it = list.begin(); it != list.end(); ++it) {
  3963. if(dynamic_cast<Player*>(*it)) {
  3964. (*it)->onCreatureTurn(creature, stackpos);
  3965. }
  3966. }
  3967.  
  3968. //none-players
  3969. for(it = list.begin(); it != list.end(); ++it) {
  3970. if(!dynamic_cast<Player*>(*it)) {
  3971. (*it)->onCreatureTurn(creature, stackpos);
  3972. }
  3973. }
  3974. }
  3975. }
  3976.  
  3977. void Game::addCommandTag(std::string tag){
  3978. bool found = false;
  3979. for(size_t i=0;i< commandTags.size() ;i++){
  3980. if(commandTags[i] == tag){
  3981. found = true;
  3982. break;
  3983. }
  3984. }
  3985. if(!found){
  3986. commandTags.push_back(tag);
  3987. }
  3988. }
  3989.  
  3990. void Game::resetCommandTag(){
  3991. commandTags.clear();
  3992. }
  3993.  
  3994. void Game::creatureSay(Creature *creature, SpeakClasses type, const std::string &text)
  3995. {
  3996. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureSay()");
  3997. using std::string;
  3998. string spoken=text;
  3999. std::transform(spoken.begin(), spoken.end(), spoken.begin(), (int32_t(*)(int32_t))std::tolower);
  4000. bool GMcommand = false;
  4001. // First, check if this was a GM command
  4002. for(size_t i=0;i< commandTags.size() ;i++){
  4003. if(commandTags[i] == text.substr(0,1)){
  4004. if(commands.exeCommand(creature,text)){
  4005. GMcommand = true;
  4006. }
  4007. break;
  4008. }
  4009. }
  4010. Player* p = dynamic_cast<Player*>(creature);
  4011. Player* player = dynamic_cast<Player*>(creature);
  4012.  
  4013. #ifdef HUCZU_FIX
  4014. if (player && spoken == "exevo grav vita" && (!g_config.LEARN_SPELLS || player->knowsSpell("exevo grav vita")))
  4015. {
  4016. Tile *tile = NULL;
  4017. Position wgpos;
  4018. wgpos.z = player->pos.z;
  4019. switch(player->direction)
  4020. {
  4021. case NORTH:
  4022. wgpos.x = player->pos.x;
  4023. wgpos.y = player->pos.y-1;
  4024. break;
  4025. case SOUTH:
  4026. wgpos.x = player->pos.x;
  4027. wgpos.y = player->pos.y+1;
  4028. break;
  4029. case EAST:
  4030. wgpos.x = player->pos.x+1;
  4031. wgpos.y = player->pos.y;
  4032. break;
  4033. case WEST:
  4034. wgpos.x = player->pos.x-1;
  4035. wgpos.y = player->pos.y;
  4036. break;
  4037. default:
  4038. break;
  4039. }
  4040. tile = getTile(wgpos.x, wgpos.y, wgpos.z);
  4041. if(!tile || tile->isBlocking(BLOCK_SOLID,false,false) || tile->isPz())
  4042. {
  4043. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4044. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  4045. return;
  4046. }
  4047. if(player->access < 2)
  4048. {
  4049. if(player->mana < 220)
  4050. {
  4051. player->sendCancel("You do not have enough mana.");
  4052. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4053. return;
  4054. }
  4055. if(!player->premmium)
  4056. {
  4057. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4058. player->sendCancel("You need buy a premmium account for use this spell");
  4059. return;
  4060. }
  4061. if(player->maglevel < 26){
  4062. player->sendCancel("You do not have the magic level.");
  4063. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4064. return;
  4065. }
  4066. if(player->vocation != 2)
  4067. {
  4068. player->sendTextMessage(MSG_SMALLINFO, "You do not have the required vocation.");
  4069. player->sendMagicEffect(player->pos, 2);
  4070. return;
  4071. }
  4072. if (player->exhaustedTicks >= 1000)
  4073. {
  4074. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4075. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  4076. return;
  4077. }
  4078. }
  4079. player->mana -= 220;
  4080. player->addManaSpent(220);
  4081. player->exhaustedTicks = g_config.EXHAUSTED;
  4082. Item* Tree = Item::CreateItem(ITEM_WILDGROWTH, 1);
  4083. addThing(NULL, wgpos, Tree);
  4084. startDecay(Tree);
  4085. SpectatorVec list;
  4086. SpectatorVec::iterator it;
  4087. getSpectators(Range(player->pos), list);
  4088. for(it = list.begin(); it != list.end(); ++it) {
  4089. Player* playerek = dynamic_cast<Player*>(*it);
  4090. if(playerek)
  4091. playerek->sendMagicEffect(playerek->pos, NM_ME_MAGIC_POISEN);
  4092. }
  4093. player->sendMagicEffect(player->pos, NM_ME_MAGIC_ENERGIE);
  4094. }
  4095. #endif //HUCZU_FIX
  4096.  
  4097. if(spoken=="exana pox"){
  4098. MagicEffectClass pox;
  4099. pox.animationColor = 0;
  4100. pox.damageEffect = NM_ME_MAGIC_ENERGIE;
  4101. pox.hitEffect = 255;
  4102. pox.attackType = ATTACK_NONE;
  4103. pox.maxDamage = 0;
  4104. pox.minDamage = 0;
  4105. pox.offensive = false;
  4106. pox.manaCost = 30;
  4107. if(creatureMakeMagic(creature, creature->pos, &pox)){
  4108. creature->removeCondition(ATTACK_POISON);
  4109.  
  4110. if(player)
  4111. player->sendIcons();
  4112. }
  4113. }
  4114.  
  4115. if(!GMcommand){
  4116. Player* player = dynamic_cast<Player*>(creature);
  4117.  
  4118. if(text=="!besthit")
  4119. {
  4120. std::stringstream info;
  4121. if(player->maxDmg>0){
  4122. info << "Your best hit: " << player->maxDmg;}
  4123. else{
  4124. info << "You didn't any damage.";}
  4125. player->sendTextMessage(MSG_EVENT,info.str().c_str());
  4126. }
  4127.  
  4128. 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')) {
  4129.  
  4130. if(player->mana < 200) {
  4131. player->sendCancel("You do not have enough mana.");
  4132. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4133. return;
  4134. }
  4135. if(player->maglevel < 15) {
  4136. player->sendCancel("You do not have the magic level.");
  4137. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4138. return;
  4139. }
  4140. if(player->vocation != 1)
  4141. {
  4142. player->sendTextMessage(MSG_SMALLINFO, "You do not have the required vocation.");
  4143. player->sendMagicEffect(player->pos, 2);
  4144. return;
  4145. }
  4146. player->mana -= 200;
  4147. player->addManaSpent(200);
  4148. SpectatorVec list;
  4149. SpectatorVec::iterator it;
  4150. getSpectators(Range(creature->pos), list);
  4151. for(it = list.begin(); it != list.end(); ++it) {
  4152. if(Creature *c = dynamic_cast<Creature*>(*it)) {
  4153. if(c)
  4154. {
  4155. c->setInvisible(0);
  4156. creatureChangeOutfit(c);
  4157. }
  4158. }
  4159. player->sendMagicEffect(player->pos, NM_ME_MAGIC_ENERGIE);
  4160. }
  4161. }
  4162. if (player)
  4163. checkSpell(player, type, text);
  4164. // It was no command, or it was just a player
  4165. SpectatorVec list;
  4166. SpectatorVec::iterator it;
  4167. getSpectators(Range(creature->pos), list);
  4168. //players
  4169. for(it = list.begin(); it != list.end(); ++it) {
  4170. if(dynamic_cast<Player*>(*it)) {
  4171. (*it)->onCreatureSay(creature, type, text);
  4172. }
  4173. }
  4174.  
  4175. //none-players
  4176. for(it = list.begin(); it != list.end(); ++it) {
  4177. if(!dynamic_cast<Player*>(*it)) {
  4178. (*it)->onCreatureSay(creature, type, text);
  4179. }
  4180. }
  4181. }
  4182. }
  4183.  
  4184. void Game::teleport(Thing *thing, const Position& newPos)
  4185. {
  4186.  
  4187. if (newPos == thing->pos)
  4188. return;
  4189.  
  4190. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::teleport()");
  4191.  
  4192. //Tile *toTile = getTile( newPos.x, newPos.y, newPos.z );
  4193. Tile *toTile = map->getTile(newPos);
  4194. if (toTile)
  4195. {
  4196. Creature *creature = dynamic_cast<Creature*>(thing);
  4197. if (creature)
  4198. {
  4199. //Tile *fromTile = getTile( thing->pos.x, thing->pos.y, thing->pos.z );
  4200. Tile *fromTile = map->getTile(thing->pos);
  4201. if (!fromTile)
  4202. return;
  4203.  
  4204. int osp = fromTile->getThingStackPos(thing);
  4205. if (!fromTile->removeThing(thing))
  4206. return;
  4207.  
  4208. toTile->addThing(thing);
  4209. Position oldPos = thing->pos;
  4210.  
  4211. SpectatorVec list;
  4212. SpectatorVec::iterator it;
  4213.  
  4214. getSpectators(Range(thing->pos, true), list);
  4215.  
  4216. //players
  4217. for (it = list.begin(); it != list.end(); ++it)
  4218. {
  4219. if (Player* p = dynamic_cast<Player*>(*it))
  4220. {
  4221. if (p->attackedCreature == creature->getID())
  4222. {
  4223. autoCloseAttack(p, creature);
  4224. }
  4225.  
  4226. (*it)->onCreatureDisappear(creature, osp, true);
  4227. }
  4228. }
  4229.  
  4230. //none-players
  4231. for (it = list.begin(); it != list.end(); ++it)
  4232. {
  4233. if (!dynamic_cast<Player*>(*it))
  4234. {
  4235. (*it)->onCreatureDisappear(creature, osp, true);
  4236. }
  4237. }
  4238.  
  4239. if (newPos.y < oldPos.y)
  4240. creature->direction = NORTH;
  4241. if (newPos.y > oldPos.y)
  4242. creature->direction = SOUTH;
  4243. if (newPos.x > oldPos.x && (std::abs(newPos.x - oldPos.x) >= std::abs(newPos.y - oldPos.y)))
  4244. creature->direction = EAST;
  4245. if (newPos.x < oldPos.x && (std::abs(newPos.x - oldPos.x) >= std::abs(newPos.y - oldPos.y)))
  4246. creature->direction = WEST;
  4247.  
  4248. thing->pos = newPos;
  4249.  
  4250. Player *player = dynamic_cast<Player*>(creature);
  4251. if (player && player->attackedCreature != 0)
  4252. {
  4253. Creature* attackedCreature = getCreatureByID(player->attackedCreature);
  4254. if (attackedCreature)
  4255. {
  4256. autoCloseAttack(player, attackedCreature);
  4257. }
  4258. }
  4259.  
  4260. list.clear();
  4261. getSpectators(Range(thing->pos, true), list);
  4262.  
  4263. #ifdef TRS_GM_INVISIBLE
  4264. //players
  4265. for (it = list.begin(); it != list.end(); ++it)
  4266. {
  4267. if (player)
  4268. {
  4269. if (player->gmInvisible && player == (*it))
  4270. {
  4271. if (Player* p = dynamic_cast<Player*>(*it))
  4272. {
  4273. if (p->attackedCreature == creature->getID())
  4274. {
  4275. autoCloseAttack(p, creature);
  4276. }
  4277. (*it)->onTeleport(creature, &oldPos, osp);
  4278. }
  4279. }
  4280. else if (player->gmInvisible && player != (*it) && (*it)->access < player->access)
  4281. {
  4282. // Nothing Because he is invisible...
  4283. }
  4284. else
  4285. {
  4286. if (Player* p = dynamic_cast<Player*>(*it))
  4287. {
  4288. if (p->attackedCreature == creature->getID())
  4289. {
  4290. autoCloseAttack(p, creature);
  4291. }
  4292. (*it)->onTeleport(creature, &oldPos, osp);
  4293. }
  4294. }
  4295. }
  4296. else
  4297. creatureBroadcastTileUpdated(newPos);
  4298. }
  4299. #else //TRS_GM_INVISIBLE
  4300. //players
  4301. for (it = list.begin(); it != list.end(); ++it)
  4302. {
  4303. if (Player* p = dynamic_cast<Player*>(*it))
  4304. {
  4305. if (p->attackedCreature == creature->getID())
  4306. {
  4307. autoCloseAttack(p, creature);
  4308. }
  4309. (*it)->onTeleport(creature, &oldPos, osp);
  4310. }
  4311. }
  4312. #endif //TRS_GM_INVISIBLE
  4313.  
  4314. //none-players
  4315. for (it = list.begin(); it != list.end(); ++it)
  4316. {
  4317. if (!dynamic_cast<Player*>(*it))
  4318. {
  4319. (*it)->onTeleport(creature, &oldPos, osp);
  4320. }
  4321. }
  4322. }
  4323. else
  4324. {
  4325. if (removeThing(NULL, thing->pos, thing, false))
  4326. {
  4327. addThing(NULL, newPos, thing);
  4328. }
  4329. }
  4330. }//if(toTile)
  4331.  
  4332. }
  4333.  
  4334.  
  4335. void Game::creatureChangeOutfit(Creature *creature)
  4336. {
  4337. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureChangeOutfit()");
  4338.  
  4339. SpectatorVec list;
  4340. SpectatorVec::iterator it;
  4341.  
  4342. getSpectators(Range(creature->pos, true), list);
  4343.  
  4344. //players
  4345. for(it = list.begin(); it != list.end(); ++it) {
  4346. if(dynamic_cast<Player*>(*it)) {
  4347. (*it)->onCreatureChangeOutfit(creature);
  4348. }
  4349. }
  4350.  
  4351. //none-players
  4352. for(it = list.begin(); it != list.end(); ++it) {
  4353. if(!dynamic_cast<Player*>(*it)) {
  4354. (*it)->onCreatureChangeOutfit(creature);
  4355. }
  4356. }
  4357. }
  4358.  
  4359. void Game::creatureWhisper(Creature *creature, const std::string &text)
  4360. {
  4361. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureWhisper()");
  4362.  
  4363. SpectatorVec list;
  4364. SpectatorVec::iterator it;
  4365.  
  4366. getSpectators(Range(creature->pos), list);
  4367.  
  4368. //players
  4369. for(it = list.begin(); it != list.end(); ++it) {
  4370. if(dynamic_cast<Player*>(*it)) {
  4371. if(abs(creature->pos.x - (*it)->pos.x) > 1 || abs(creature->pos.y - (*it)->pos.y) > 1)
  4372. (*it)->onCreatureSay(creature, SPEAK_WHISPER, std::string("pspsps"));
  4373. else
  4374. (*it)->onCreatureSay(creature, SPEAK_WHISPER, text);
  4375. }
  4376. }
  4377.  
  4378. //none-players
  4379. for(it = list.begin(); it != list.end(); ++it) {
  4380. if(!dynamic_cast<Player*>(*it)) {
  4381. if(abs(creature->pos.x - (*it)->pos.x) > 1 || abs(creature->pos.y - (*it)->pos.y) > 1)
  4382. (*it)->onCreatureSay(creature, SPEAK_WHISPER, std::string("pspsps"));
  4383. else
  4384. (*it)->onCreatureSay(creature, SPEAK_WHISPER, text);
  4385. }
  4386. }
  4387. }
  4388.  
  4389. void Game::creatureYell(Creature *creature, std::string &text)
  4390. {
  4391. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureYell()");
  4392. if(!creature)
  4393. return;
  4394. #ifdef HUCZU_FIX
  4395. if(creature->level < 2 && creature->access < 2){
  4396. return;
  4397. }
  4398. #endif //HUCZU_FIX
  4399. std::transform(text.begin(), text.end(), text.begin(), upchar);
  4400.  
  4401. SpectatorVec list;
  4402. SpectatorVec::iterator it;
  4403. getSpectators(Range(creature->pos, 18, 18, 14, 14), list);
  4404.  
  4405. for(it = list.begin(); it != list.end(); ++it){
  4406. if(*it)
  4407. (*it)->onCreatureSay(creature, SPEAK_YELL, text);
  4408. }
  4409. }
  4410.  
  4411. //ZBÊ„NE
  4412. /*void Game::creatureYell(Creature *creature, std::string &text)
  4413. {
  4414. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureYell()");
  4415. Player* player = dynamic_cast<Player*>(creature);
  4416. #ifdef HUCZU_FIX
  4417. if(player && player->level < 2 && player->access < 2){
  4418. player->sendTextMessage(MSG_SMALLINFO, "You cannot yell.");
  4419. return;
  4420. }
  4421. #endif //HUCZU_FIX
  4422. if (player && player->access < g_config.ACCESS_PROTECT && player->exhaustedTicks >= 1000)
  4423. {
  4424. player->exhaustedTicks += g_config.EXHAUSTED_ADD;
  4425. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  4426. }
  4427. else {
  4428. creature->exhaustedTicks = g_config.EXHAUSTED;
  4429. std::transform(text.begin(), text.end(), text.begin(), upchar);
  4430.  
  4431. SpectatorVec list;
  4432. SpectatorVec::iterator it;
  4433.  
  4434. getSpectators(Range(creature->pos, 18, 18, 14, 14), list);
  4435.  
  4436. //players
  4437. for(it = list.begin(); it != list.end(); ++it) {
  4438. if(dynamic_cast<Player*>(*it)) {
  4439. (*it)->onCreatureSay(creature, SPEAK_YELL, text);
  4440. }
  4441. }
  4442. }
  4443. }*/
  4444.  
  4445. void Game::creatureSpeakTo(Creature *creature, SpeakClasses type,const std::string &receiver, const std::string &text)
  4446. {
  4447. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureSpeakTo");
  4448.  
  4449. Player* player = dynamic_cast<Player*>(creature);
  4450. if(!player)
  4451. return;
  4452.  
  4453. Player* toPlayer = getPlayerByName(receiver);
  4454. if(!toPlayer) {
  4455. player->sendTextMessage(MSG_SMALLINFO, "A player with this name is not online.");
  4456. return;
  4457. }
  4458. if(creature->access < g_config.ACCESS_TALK){
  4459. type = SPEAK_PRIVATE;
  4460. }
  4461.  
  4462. if(!toPlayer){
  4463. player->onCreatureSay(player, type, text);
  4464. }
  4465. time_t ticks = time(0);
  4466. tm* now = localtime(&ticks);
  4467. char buf[32];
  4468. strftime(buf, sizeof(buf), "%d/%m/%Y %H:%M", now);
  4469. std::ofstream out2("data/logs/private.log", std::ios::app);
  4470. out2 << '[' << buf << "] " << toPlayer->getName() << " from " << player->getName() << ": " << text << std::endl;
  4471. out2.close();
  4472.  
  4473. toPlayer->onCreatureSay(player, type, text);
  4474. std::stringstream ss;
  4475. ss << "Message sent to " << toPlayer->getName() << ".";
  4476. player->sendTextMessage(MSG_SMALLINFO, ss.str().c_str());
  4477. }
  4478.  
  4479. void Game::creatureTalkToChannel(Player *player, SpeakClasses type, std::string &text, uint16_t channelId)
  4480. {
  4481. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureTalkToChannel");
  4482.  
  4483. if(player->access < g_config.ACCESS_TALK){
  4484. type = SPEAK_CHANNEL_Y;
  4485. }
  4486.  
  4487. if(player->guildStatus == GUILD_LEADER && channelId == 0x00)
  4488. type = SPEAK_CHANNEL_R1;
  4489. if(player->guildStatus == GUILD_VICE && channelId == 0x00)
  4490. type = SPEAK_CHANNEL_O;
  4491.  
  4492. g_chat.talkToChannel(player, type, text, channelId);
  4493. }
  4494.  
  4495. void Game::creatureMonsterYell(Monster* monster, const std::string& text)
  4496. {
  4497. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureMonsterYell()");
  4498.  
  4499. SpectatorVec list;
  4500. SpectatorVec::iterator it;
  4501.  
  4502. map->getSpectators(Range(monster->pos, 18, 18, 14, 14), list);
  4503.  
  4504. //players
  4505. for(it = list.begin(); it != list.end(); ++it) {
  4506. if(dynamic_cast<Player*>(*it)) {
  4507. (*it)->onCreatureSay(monster, SPEAK_MONSTER1, text);
  4508. }
  4509. }
  4510. }
  4511.  
  4512. void Game::creatureBroadcastMessage(Creature *creature, const std::string &text)
  4513. {
  4514. if(creature->access < g_config.ACCESS_TALK)
  4515. return;
  4516.  
  4517. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureBroadcastMessage()");
  4518.  
  4519. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  4520. {
  4521. (*it).second->onCreatureSay(creature, SPEAK_BROADCAST, text);
  4522. }
  4523. }
  4524.  
  4525. /** \todo Someone _PLEASE_ clean up this mess */
  4526. bool Game::creatureMakeMagic(Creature *creature, const Position& centerpos, const MagicEffectClass* me)
  4527. {
  4528.  
  4529. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureMakeMagic()");
  4530.  
  4531. #ifdef __DEBUG__
  4532. cout << "creatureMakeMagic: " << (creature ? creature->getName() : "No name") << ", x: " << centerpos.x << ", y: " << centerpos.y << ", z: " << centerpos.z << std::endl;
  4533. #endif
  4534.  
  4535. Position frompos;
  4536.  
  4537. if(creature) {
  4538. frompos = creature->pos;
  4539.  
  4540. if(!creatureOnPrepareMagicAttack(creature, centerpos, me))
  4541. {
  4542.  
  4543. return false;
  4544. }
  4545. }
  4546. else {
  4547. frompos = centerpos;
  4548. }
  4549.  
  4550. MagicAreaVec tmpMagicAreaVec;
  4551. me->getArea(centerpos, tmpMagicAreaVec);
  4552.  
  4553. std::vector<Position> poslist;
  4554.  
  4555. Position topLeft(0xFFFF, 0xFFFF, frompos.z), bottomRight(0, 0, frompos.z);
  4556.  
  4557. //Filter out the tiles we actually can work on
  4558. for(MagicAreaVec::iterator maIt = tmpMagicAreaVec.begin(); maIt != tmpMagicAreaVec.end(); ++maIt) {
  4559. Tile *t = map->getTile(maIt->x, maIt->y, maIt->z);
  4560. if(t && (!creature || (creature->access >= g_config.ACCESS_PROTECT || !me->offensive || !t->isPz()) ) ) {
  4561. if((t->isBlocking(BLOCK_PROJECTILE) == RET_NOERROR) && (me->isIndirect() ||
  4562. //(map->canThrowItemTo(frompos, (*maIt), false, true) && !t->floorChange()))) {
  4563. ((map->canThrowObjectTo(centerpos, (*maIt), BLOCK_PROJECTILE) == RET_NOERROR) && !t->floorChange()))) {
  4564.  
  4565. if(maIt->x < topLeft.x)
  4566. topLeft.x = maIt->x;
  4567.  
  4568. if(maIt->y < topLeft.y)
  4569. topLeft.y = maIt->y;
  4570.  
  4571. if(maIt->x > bottomRight.x)
  4572. bottomRight.x = maIt->x;
  4573.  
  4574. if(maIt->y > bottomRight.y)
  4575. bottomRight.y = maIt->y;
  4576.  
  4577. poslist.push_back(*maIt);
  4578. }
  4579. }
  4580. }
  4581.  
  4582. topLeft.z = frompos.z;
  4583. bottomRight.z = frompos.z;
  4584.  
  4585. if(topLeft.x == 0xFFFF || topLeft.y == 0xFFFF || bottomRight.x == 0 || bottomRight.y == 0){
  4586.  
  4587. return false;
  4588. }
  4589.  
  4590. #ifdef __DEBUG__
  4591. printf("top left %d %d %d\n", topLeft.x, topLeft.y, topLeft.z);
  4592. printf("bottom right %d %d %d\n", bottomRight.x, bottomRight.y, bottomRight.z);
  4593. #endif
  4594.  
  4595. //We do all changes against a GameState to keep track of the changes,
  4596. //need some more work to work for all situations...
  4597. GameState gamestate(this, Range(topLeft, bottomRight));
  4598.  
  4599. //Tile *targettile = getTile(centerpos.x, centerpos.y, centerpos.z);
  4600. Tile *targettile = map->getTile(centerpos);
  4601. bool bSuccess = false;
  4602. bool hasTarget = false;
  4603. bool isBlocking = true;
  4604. if(targettile){
  4605. hasTarget = !targettile->creatures.empty();
  4606. isBlocking = (targettile->isBlocking(BLOCK_SOLID, true) != RET_NOERROR);
  4607. }
  4608.  
  4609. if(targettile && me->canCast(isBlocking, !targettile->creatures.empty())) {
  4610. bSuccess = true;
  4611.  
  4612. //Apply the permanent effect to the map
  4613. std::vector<Position>::const_iterator tlIt;
  4614. for(tlIt = poslist.begin(); tlIt != poslist.end(); ++tlIt) {
  4615. gamestate.onAttack(creature, Position(*tlIt), me);
  4616. }
  4617. }
  4618.  
  4619. SpectatorVec spectatorlist = gamestate.getSpectators();
  4620. SpectatorVec::iterator it;
  4621.  
  4622. for(it = spectatorlist.begin(); it != spectatorlist.end(); ++it) {
  4623. Player* spectator = dynamic_cast<Player*>(*it);
  4624.  
  4625. if(!spectator)
  4626. continue;
  4627.  
  4628. if(bSuccess) {
  4629. me->getDistanceShoot(spectator, creature, centerpos, hasTarget);
  4630.  
  4631. std::vector<Position>::const_iterator tlIt;
  4632. for(tlIt = poslist.begin(); tlIt != poslist.end(); ++tlIt) {
  4633. Position pos = *tlIt;
  4634. //Tile *tile = getTile(pos.x, pos.y, pos.z);
  4635. Tile *tile = map->getTile(pos);
  4636. const CreatureStateVec& creatureStateVec = gamestate.getCreatureStateList(tile);
  4637.  
  4638. if(creatureStateVec.empty()) { //no targets
  4639. me->getMagicEffect(spectator, creature, NULL, pos, 0, targettile->isPz(), isBlocking);
  4640. }
  4641. else {
  4642. for(CreatureStateVec::const_iterator csIt = creatureStateVec.begin(); csIt != creatureStateVec.end(); ++csIt) {
  4643. Creature *target = csIt->first;
  4644. const CreatureState& creatureState = csIt->second;
  4645.  
  4646. me->getMagicEffect(spectator, creature, target, target->pos, creatureState.damage, tile->isPz(), false);
  4647.  
  4648. //could be death due to a magic damage with no owner (fire/poison/energy)
  4649. if(creature && target->isRemoved == true) {
  4650.  
  4651. for(std::vector<Creature*>::const_iterator cit = creatureState.attackerlist.begin(); cit != creatureState.attackerlist.end(); ++cit) {
  4652. Creature* gainExpCreature = *cit;
  4653. if(dynamic_cast<Player*>(gainExpCreature))
  4654. dynamic_cast<Player*>(gainExpCreature)->sendStats();
  4655.  
  4656. if(spectator->CanSee(gainExpCreature->pos.x, gainExpCreature->pos.y, gainExpCreature->pos.z)){
  4657. std::stringstream exp;
  4658. exp << target->getGainedExperience(gainExpCreature);
  4659. spectator->sendAnimatedText(gainExpCreature->pos, 0xD7, exp.str());
  4660. }
  4661. }
  4662.  
  4663. }
  4664.  
  4665. if(spectator->CanSee(target->pos.x, target->pos.y, target->pos.z))
  4666. {
  4667. if(creatureState.damage != 0) {
  4668. std::stringstream dmg;
  4669. dmg << std::abs(creatureState.damage);
  4670. #ifdef TJ_MONSTER_BLOOD
  4671. if (me->attackType & ATTACK_PHYSICAL)
  4672. spectator->sendAnimatedText(target->pos, target->bloodcolor, dmg.str());
  4673. else
  4674. #endif //TJ_MONSTER_BLOOD
  4675. spectator->sendAnimatedText(target->pos, me->animationColor, dmg.str());
  4676. }
  4677.  
  4678. if(creatureState.manaDamage > 0){
  4679. spectator->sendMagicEffect(target->pos, NM_ME_LOOSE_ENERGY);
  4680. std::stringstream manaDmg;
  4681. manaDmg << std::abs(creatureState.manaDamage);
  4682. spectator->sendAnimatedText(target->pos, 2, manaDmg.str());
  4683. }
  4684.  
  4685. if (target->health > 0)
  4686. spectator->sendCreatureHealth(target);
  4687.  
  4688. if (spectator == target){
  4689. CreateManaDamageUpdate(target, creature, creatureState.manaDamage);
  4690. CreateDamageUpdate(target, creature, creatureState.damage);
  4691. }
  4692. }
  4693. }
  4694. }
  4695. }
  4696. }
  4697. else {
  4698. me->FailedToCast(spectator, creature, isBlocking, hasTarget);
  4699. }
  4700.  
  4701. }
  4702.  
  4703. return bSuccess;
  4704. }
  4705.  
  4706. void Game::creatureApplyDamage(Creature *creature, int32_t damage, int32_t &outDamage, int32_t &outManaDamage
  4707. #ifdef YUR_PVP_ARENA
  4708. , CreatureVector* arenaLosers
  4709. #endif //YUR_PVP_ARENA
  4710. )
  4711. {
  4712. outDamage = damage;
  4713. outManaDamage = 0;
  4714.  
  4715. if (damage > 0)
  4716. {
  4717. if (creature->manaShieldTicks >= 1000 && (damage < creature->mana) ) {
  4718. outManaDamage = damage;
  4719. outDamage = 0;
  4720. }
  4721. else if (creature->manaShieldTicks >= 1000 && (damage > creature->mana) ) {
  4722. outManaDamage = creature->mana;
  4723. outDamage -= outManaDamage;
  4724. }
  4725. else if((creature->manaShieldTicks < 1000) && (damage > creature->health))
  4726. outDamage = creature->health;
  4727. else if (creature->manaShieldTicks >= 1000 && (damage > (creature->health + creature->mana))) {
  4728. outDamage = creature->health;
  4729. outManaDamage = creature->mana;
  4730. }
  4731.  
  4732. if(creature->manaShieldTicks < 1000 || (creature->mana == 0))
  4733. #ifdef YUR_PVP_ARENA
  4734. creature->drainHealth(outDamage, arenaLosers);
  4735. #else
  4736. creature->drainHealth(outDamage);
  4737. #endif //YUR_PVP_ARENA
  4738. else if(outManaDamage > 0)
  4739. {
  4740. #ifdef YUR_PVP_ARENA
  4741. creature->drainHealth(outDamage, arenaLosers);
  4742. #else
  4743. creature->drainHealth(outDamage);
  4744. #endif //YUR_PVP_ARENA
  4745. creature->drainMana(outManaDamage);
  4746. }
  4747. else
  4748. creature->drainMana(outDamage);
  4749. }
  4750. else {
  4751. int32_t newhealth = creature->health - damage;
  4752. if(newhealth > creature->healthmax)
  4753. newhealth = creature->healthmax;
  4754.  
  4755. creature->health = newhealth;
  4756.  
  4757. outDamage = creature->health - newhealth;
  4758. outManaDamage = 0;
  4759. }
  4760. }
  4761.  
  4762. bool Game::creatureCastSpell(Creature *creature, const Position& centerpos, const MagicEffectClass& me)
  4763. {
  4764.  
  4765. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureCastSpell()");
  4766. std::cout << "Game::creatureCastSpell " << creature->getName() << std::endl;
  4767. // if(me.offensive == false && me.damageEffect > 0 && creature->conditions.hasCondition(ATTACK_PARALYZE))
  4768. if(me.damageEffect <= 0 && creature->conditions.hasCondition(ATTACK_PARALYZE))
  4769. {
  4770. creature->removeCondition(ATTACK_PARALYZE);
  4771. changeSpeed(creature->getID(), creature->getNormalSpeed()+creature->hasteSpeed);
  4772. Player *player = dynamic_cast<Player*>(creature);
  4773. if(player)
  4774. player->sendIcons();
  4775. }
  4776.  
  4777. return creatureMakeMagic(creature, centerpos, &me);
  4778. }
  4779.  
  4780.  
  4781. bool Game::creatureThrowRune(Creature *creature, const Position& centerpos, const MagicEffectClass& me) {
  4782.  
  4783.  
  4784. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureThrowRune()");
  4785. bool ret = false;
  4786. #ifdef HUCZU_FIX
  4787. int32_t dist_x = std::abs(creature->pos.x - centerpos.x);
  4788. int32_t dist_y = std::abs(creature->pos.y - centerpos.y);
  4789. #endif //HUCZU_FIX
  4790. if(creature->pos.z != centerpos.z) {
  4791. creature->sendCancel("You need to be on the same floor.");
  4792. }
  4793. #ifdef HUCZU_FIX
  4794. else if(dist_x > 7 || dist_y > 6)
  4795. return TOO_FAR;
  4796. #endif //HUCZU_FIX
  4797. //else if(!map->canThrowItemTo(creature->pos, centerpos, false, true)) {
  4798. else if(map->canThrowObjectTo(creature->pos, centerpos, BLOCK_PROJECTILE) != RET_NOERROR) {
  4799. creature->sendCancel("You cannot throw there.");
  4800. }
  4801. else
  4802. ret = creatureMakeMagic(creature, centerpos, &me);
  4803.  
  4804.  
  4805.  
  4806. return ret;
  4807. }
  4808.  
  4809. bool Game::creatureOnPrepareAttack(Creature *creature, Position pos)
  4810. {
  4811. if(creature){
  4812. Player* player = dynamic_cast<Player*>(creature);
  4813.  
  4814. //Tile* tile = (Tile*)getTile(creature->pos.x, creature->pos.y, creature->pos.z);
  4815. Tile* tile = map->getTile(creature->pos);
  4816. //Tile* targettile = getTile(pos.x, pos.y, pos.z);
  4817. Tile* targettile = map->getTile(pos);
  4818.  
  4819. if(creature->access < g_config.ACCESS_PROTECT) {
  4820. if(tile && tile->isPz()) {
  4821. if(player) {
  4822. player->sendTextMessage(MSG_SMALLINFO, "You may not attack a person while you are in a protection zone.");
  4823. playerSetAttackedCreature(player, 0);
  4824. }
  4825.  
  4826. return false;
  4827. }
  4828. else if(targettile && targettile->isPz()) {
  4829. if(player) {
  4830. player->sendTextMessage(MSG_SMALLINFO, "You may not attack a person in a protection zone.");
  4831. playerSetAttackedCreature(player, 0);
  4832. }
  4833.  
  4834. return false;
  4835. }
  4836. }
  4837.  
  4838. return true;
  4839. }
  4840.  
  4841. return false;
  4842. }
  4843.  
  4844. bool Game::creatureOnPrepareMagicAttack(Creature *creature, Position pos, const MagicEffectClass* me)
  4845. {
  4846. if(!me->offensive || me->isIndirect() || creatureOnPrepareAttack(creature, pos)) {
  4847. /*
  4848. if(creature->access < ACCESS_PROTECT) {
  4849. if(!((std::abs(creature->pos.x-centerpos.x) <= 8) && (std::abs(creature->pos.y-centerpos.y) <= 6) &&
  4850. (creature->pos.z == centerpos.z)))
  4851. return false;
  4852. }
  4853. */
  4854.  
  4855. Player* player = dynamic_cast<Player*>(creature);
  4856. if(player) {
  4857. if(player->access < g_config.ACCESS_PROTECT) {
  4858. if(player->exhaustedTicks >= 1000 && me->causeExhaustion(true)) {
  4859. if(me->offensive) {
  4860. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.",player->pos, NM_ME_PUFF);
  4861. player->exhaustedTicks += g_config.EXHAUSTED_ADD;
  4862. }
  4863.  
  4864. return false;
  4865. }
  4866. else if(player->mana < me->manaCost) {
  4867. player->sendTextMessage(MSG_SMALLINFO, "You do not have enough mana.",player->pos, NM_ME_PUFF);
  4868. return false;
  4869. }
  4870. else
  4871. player->mana -= me->manaCost;
  4872. //player->manaspent += me->manaCost;
  4873. player->addManaSpent(me->manaCost);
  4874. }
  4875. }
  4876.  
  4877. return true;
  4878. }
  4879.  
  4880. return false;
  4881. }
  4882.  
  4883. void Game::creatureMakeDamage(Creature *creature, Creature *attackedCreature, fight_t damagetype)
  4884. {
  4885. if(!creatureOnPrepareAttack(creature, attackedCreature->pos))
  4886. return;
  4887.  
  4888.  
  4889. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureMakeDamage()");
  4890.  
  4891. Player* player = dynamic_cast<Player*>(creature);
  4892. Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  4893.  
  4894. #ifdef ANTI_MISS
  4895. if(player && player->atkMode == 1 && player->access <= g_config.ACCESS_PROTECT && attackedPlayer && attackedPlayer->skullType == 0) {
  4896. player->sendCancelAttacking();
  4897. player->sendTextMessage(MSG_SMALLINFO, "Turn secure mode off if you really want to attack unmarked players.");
  4898. return;
  4899. }
  4900. #endif //ANTI_MISS
  4901.  
  4902. //Tile* targettile = getTile(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z);
  4903. Tile* targettile = map->getTile(attackedCreature->pos);
  4904.  
  4905. //can the attacker reach the attacked?
  4906. bool inReach = false;
  4907.  
  4908. switch(damagetype){
  4909. case FIGHT_MELEE:
  4910. if((std::abs(creature->pos.x-attackedCreature->pos.x) <= 1) &&
  4911. (std::abs(creature->pos.y-attackedCreature->pos.y) <= 1) &&
  4912. (creature->pos.z == attackedCreature->pos.z))
  4913. inReach = true;
  4914. break;
  4915. case FIGHT_DIST:
  4916. if((std::abs(creature->pos.x-attackedCreature->pos.x) <= 8) &&
  4917. (std::abs(creature->pos.y-attackedCreature->pos.y) <= 5) &&
  4918. (creature->pos.z == attackedCreature->pos.z)) {
  4919.  
  4920. //if(map->canThrowItemTo(creature->pos, attackedCreature->pos, false, true))
  4921. if(map->canThrowObjectTo(creature->pos, attackedCreature->pos, BLOCK_PROJECTILE) == RET_NOERROR)
  4922. inReach = true;
  4923. }
  4924. break;
  4925. case FIGHT_MAGICDIST:
  4926. if((std::abs(creature->pos.x-attackedCreature->pos.x) <= 8) &&
  4927. (std::abs(creature->pos.y-attackedCreature->pos.y) <= 5) &&
  4928. (creature->pos.z == attackedCreature->pos.z)) {
  4929.  
  4930. //if(map->canThrowItemTo(creature->pos, attackedCreature->pos, false, true))
  4931. if(map->canThrowObjectTo(creature->pos, attackedCreature->pos, BLOCK_PROJECTILE) == RET_NOERROR)
  4932. inReach = true;
  4933. }
  4934. break;
  4935.  
  4936. }
  4937.  
  4938. if (player && player->access < g_config.ACCESS_PROTECT)
  4939. {
  4940. #ifdef YUR_CVS_MODS
  4941. player->inFightTicks = std::max(g_config.PZ_LOCKED, player->inFightTicks);
  4942. #else
  4943. player->inFightTicks = g_config.PZ_LOCKED;
  4944. #endif //YUR_CVS_MODS
  4945.  
  4946. player->sendIcons();
  4947. if(attackedPlayer)
  4948. player->pzLocked = true;
  4949. }
  4950.  
  4951. if(attackedPlayer && attackedPlayer->access < g_config.ACCESS_PROTECT)
  4952. {
  4953. #ifdef YUR_CVS_MODS
  4954. attackedPlayer->inFightTicks = std::max(g_config.PZ_LOCKED, attackedPlayer->inFightTicks);
  4955. #else
  4956. attackedPlayer->inFightTicks = g_config.PZ_LOCKED;
  4957. #endif //YUR_CVS_MODS
  4958. attackedPlayer->sendIcons();
  4959. }
  4960.  
  4961. if(!inReach){
  4962. return;
  4963. }
  4964.  
  4965. //We do all changes against a GameState to keep track of the changes,
  4966. //need some more work to work for all situations...
  4967. GameState gamestate(this, Range(creature->pos, attackedCreature->pos));
  4968.  
  4969. gamestate.onAttack(creature, attackedCreature->pos, attackedCreature);
  4970.  
  4971. const CreatureStateVec& creatureStateVec = gamestate.getCreatureStateList(targettile);
  4972. const CreatureState& creatureState = creatureStateVec[0].second;
  4973.  
  4974. if(player && (creatureState.damage > 0 || creatureState.manaDamage > 0)) {
  4975. #ifdef WANDS_JIDDO
  4976. 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()))))
  4977. player->addSkillTry(2);
  4978. #else
  4979. player->addSkillTry(2);
  4980. #endif
  4981. }
  4982. else if(player){
  4983. #ifdef WANDS_JIDDO
  4984. 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()))))
  4985. player->addSkillTry(1);
  4986. #else
  4987. player->addSkillTry(1);
  4988. #endif
  4989. }
  4990. if(attackedPlayer){
  4991. NetworkMessage msg;
  4992. msg.AddByte(0x86);
  4993. msg.AddU32(creature->getID());
  4994. msg.AddByte(0x00);
  4995. attackedPlayer->sendNetworkMessage(&msg);
  4996. }
  4997.  
  4998. SpectatorVec spectatorlist = gamestate.getSpectators();
  4999. SpectatorVec::iterator it;
  5000.  
  5001. for(it = spectatorlist.begin(); it != spectatorlist.end(); ++it) {
  5002. Player* spectator = dynamic_cast<Player*>(*it);
  5003. if(!spectator)
  5004. continue;
  5005.  
  5006. if(damagetype != FIGHT_MELEE){
  5007. spectator->sendDistanceShoot(creature->pos, attackedCreature->pos, creature->getSubFightType());
  5008. }
  5009.  
  5010. if (attackedCreature->manaShieldTicks < 1000 && (creatureState.damage == 0) &&
  5011. (spectator->CanSee(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z))) {
  5012. spectator->sendMagicEffect(attackedCreature->pos, NM_ME_PUFF);
  5013. }
  5014. else if (attackedCreature->manaShieldTicks < 1000 && (creatureState.damage < 0) &&
  5015. (spectator->CanSee(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z))) {
  5016. spectator->sendMagicEffect(attackedCreature->pos, NM_ME_BLOCKHIT);
  5017. }
  5018. else {
  5019. for(std::vector<Creature*>::const_iterator cit = creatureState.attackerlist.begin(); cit != creatureState.attackerlist.end(); ++cit) {
  5020. Creature* gainexpCreature = *cit;
  5021. if(dynamic_cast<Player*>(gainexpCreature))
  5022. dynamic_cast<Player*>(gainexpCreature)->sendStats();
  5023.  
  5024. if(spectator->CanSee(gainexpCreature->pos.x, gainexpCreature->pos.y, gainexpCreature->pos.z)) {
  5025. char exp[128];
  5026. #ifdef YUR_HIGH_LEVELS // TODO: format like this: 1,000,000
  5027. sprintf(exp,"%lld",attackedCreature->getGainedExperience(gainexpCreature));
  5028. spectator->sendAnimatedText(gainexpCreature->pos, 0xD7, exp);
  5029. #else
  5030. itoa(attackedCreature->getGainedExperience(gainexpCreature), exp, 10);
  5031. #endif //YUR_HIGH_LEVLES
  5032. spectator->sendAnimatedText(gainexpCreature->pos, 0xD7, exp);
  5033. }
  5034. }
  5035.  
  5036. if (spectator->CanSee(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z))
  5037. {
  5038. if(creatureState.damage > 0) {
  5039. std::stringstream dmg;
  5040. dmg << std::abs(creatureState.damage);
  5041. #ifdef TJ_MONSTER_BLOOD
  5042. spectator->sendAnimatedText(attackedCreature->pos, attackedCreature->bloodcolor, dmg.str());
  5043. spectator->sendMagicEffect(attackedCreature->pos, attackedCreature->bloodeffect);
  5044. #else
  5045. spectator->sendAnimatedText(attackedCreature->pos, 0xB4, dmg.str());
  5046. spectator->sendMagicEffect(attackedCreature->pos, NM_ME_DRAW_BLOOD);
  5047. #endif //TJ_MONSTER_BLOOD
  5048. }
  5049.  
  5050. if(creatureState.manaDamage >0) {
  5051. std::stringstream manaDmg;
  5052. manaDmg << std::abs(creatureState.manaDamage);
  5053. spectator->sendMagicEffect(attackedCreature->pos, NM_ME_LOOSE_ENERGY);
  5054. spectator->sendAnimatedText(attackedCreature->pos, 2, manaDmg.str());
  5055. }
  5056.  
  5057. if (attackedCreature->health > 0)
  5058. spectator->sendCreatureHealth(attackedCreature);
  5059.  
  5060. if (spectator == attackedCreature) {
  5061. CreateManaDamageUpdate(attackedCreature, creature, creatureState.manaDamage);
  5062. CreateDamageUpdate(attackedCreature, creature, creatureState.damage);
  5063. }
  5064. }
  5065. }
  5066. }
  5067.  
  5068. if(damagetype != FIGHT_MELEE && player) {
  5069. player->removeDistItem();
  5070. }
  5071.  
  5072.  
  5073. }
  5074.  
  5075. std::list<Position> Game::getPathTo(Creature *creature, Position start, Position to, bool creaturesBlock){
  5076. return map->getPathTo(creature, start, to, creaturesBlock);
  5077. }
  5078.  
  5079. std::list<Position> Game::getPathToEx(Creature *creature, Position start, Position to, bool creaturesBlock){
  5080. return map->getPathToEx(creature, start, to, creaturesBlock);
  5081. }
  5082.  
  5083.  
  5084. void Game::checkPlayerWalk(uint32_t id)
  5085. {
  5086. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkPlayerWalk");
  5087.  
  5088. Player *player = getPlayerByID(id);
  5089.  
  5090. if(!player)
  5091. return;
  5092. if(player->pathlist.empty()){
  5093. stopEvent(player->eventAutoWalk);
  5094. player->eventAutoWalk = 0;
  5095. return;
  5096. }
  5097.  
  5098. Position pos = player->pos;
  5099. Direction dir = player->pathlist.front();
  5100. player->pathlist.pop_front();
  5101.  
  5102. switch (dir) {
  5103. case NORTH:
  5104. pos.y--;
  5105. break;
  5106. case EAST:
  5107. pos.x++;
  5108. break;
  5109. case SOUTH:
  5110. pos.y++;
  5111. break;
  5112. case WEST:
  5113. pos.x--;
  5114. break;
  5115. case NORTHEAST:
  5116. pos.x++;
  5117. pos.y--;
  5118. break;
  5119. case NORTHWEST:
  5120. pos.x--;
  5121. pos.y--;
  5122. break;
  5123. case SOUTHWEST:
  5124. pos.x--;
  5125. pos.y++;
  5126. break;
  5127. case SOUTHEAST:
  5128. pos.x++;
  5129. pos.y++;
  5130. break;
  5131. }
  5132.  
  5133. /*
  5134. #ifdef __DEBUG__
  5135. std::cout << "move to: " << dir << std::endl;
  5136. #endif
  5137. */
  5138.  
  5139. player->lastmove = OTSYS_TIME();
  5140. thingMove(player, player, pos.x, pos.y, pos.z, 1);
  5141. flushSendBuffers();
  5142. if(!player->pathlist.empty()){
  5143. int ticks = (int)player->getSleepTicks();
  5144. player->eventAutoWalk = addEvent(makeTask(ticks, std::bind2nd(std::mem_fun(&Game::checkPlayerWalk), id)));
  5145. }
  5146. else
  5147. {
  5148. stopEvent(player->eventAutoWalk);//?
  5149. player->eventAutoWalk = 0;
  5150. }
  5151. }
  5152. void Game::checkCreature(uint32_t id)
  5153. {
  5154. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreature()");
  5155.  
  5156. Creature *creature = getCreatureByID(id);
  5157.  
  5158. if (creature && creature->isRemoved == false)
  5159. {
  5160. int32_t thinkTicks = 0;
  5161. int32_t oldThinkTicks = creature->onThink(thinkTicks);
  5162.  
  5163. if(thinkTicks > 0) {
  5164. creature->eventCheck = addEvent(makeTask(thinkTicks, std::bind2nd(std::mem_fun(&Game::checkCreature), id)));
  5165. }
  5166. else
  5167. creature->eventCheck = 0;
  5168.  
  5169. Player* player = dynamic_cast<Player*>(creature);
  5170. if(player)
  5171. {
  5172. //Tile *tile = getTile(player->pos.x, player->pos.y, player->pos.z);
  5173. Tile *tile = map->getTile(player->pos);
  5174. if(tile == NULL){
  5175. std::cout << "CheckPlayer NULL tile: " << player->getName() << std::endl;
  5176. return;
  5177. }
  5178.  
  5179.  
  5180.  
  5181. #ifdef _REX_CVS_MOD_
  5182. if(player->tradeTicks >= 1000)
  5183. player->tradeTicks -= thinkTicks;
  5184. #endif
  5185.  
  5186.  
  5187. #ifdef CVS_DAY_CYCLE
  5188. player->sendWorldLightLevel(lightlevel, 0xD7);
  5189. #endif //CVS_DAY_CYCLE
  5190. #ifdef REX_MUTED
  5191.  
  5192. #endif //REX_MUTED
  5193. #ifdef TR_ANTI_AFK
  5194. player->checkAfk(thinkTicks);
  5195. #endif //TR_ANTI_AF
  5196. #ifdef YUR_BOH
  5197. player->checkBoh();
  5198. #endif //YUR_BOH
  5199. #ifdef YUR_WH
  5200. player->checkWh();
  5201. #endif //YUR_WH
  5202.  
  5203. #ifdef YUR_RINGS_AMULETS
  5204. player->checkRing(thinkTicks);
  5205. #endif //YUR_RINGS_AMULETS
  5206.  
  5207. //SOFT BOOTS
  5208. if(player->softTicks >= 2) {
  5209. if(player->items[SLOT_FEET] && player->items[SLOT_FEET]->getID() == ITEM_SOFT_BOOTS && !tile->isPz()){
  5210. player->mana += min(g_config.SOFT_MANA, player->manamax - player->mana);
  5211. player->health += min(g_config.SOFT_HEALTH, player->healthmax - player->health);
  5212. }
  5213. player->softTicks = 0;
  5214. } else {
  5215. player->softTicks++;
  5216. }
  5217. // LIFE RING
  5218. if(player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_LIFE_RING_IN_USE && !tile->isPz()){
  5219. player->mana += min(g_config.LR_MANA, player->manamax - player->mana);
  5220. player->health += min(g_config.LR_HEALTH, player->healthmax - player->health);
  5221. }
  5222. // ROH
  5223. if(player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_RING_OF_HEALING_IN_USE && !tile->isPz()){
  5224. player->mana += min(g_config.ROH_MANA, player->manamax - player->mana);
  5225. player->health += min(g_config.ROH_HEALTH, player->healthmax - player->health);
  5226. }
  5227. // ROAH
  5228. // ROH 240
  5229. if(player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_STEALTH_RING_IN_USE && !tile->isPz()){
  5230. player->mana += min(g_config.ROAH_MANA, player->manamax - player->mana);
  5231. player->health += min(g_config.ROAH_HEALTH, player->healthmax - player->health);
  5232. }
  5233. // RAINBOW SHIELD
  5234. if(player->level >= 150){
  5235. if(player->items[SLOT_RIGHT] && player->items[SLOT_RIGHT]->getID() == ITEM_RAINBOW && !tile->isPz()){
  5236. if(player->items[SLOT_LEFT]){
  5237. if(player->items[SLOT_LEFT]->getID() != ITEM_RAINBOW)
  5238. if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5239. player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5240. player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5241. player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5242. }
  5243. }else{
  5244. if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5245. player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5246. player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5247. player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5248. }
  5249. }
  5250. }
  5251. if(player->items[SLOT_LEFT] && player->items[SLOT_LEFT]->getID() == ITEM_RAINBOW && !tile->isPz()){
  5252. if(player->items[SLOT_RIGHT]){
  5253. if(player->items[SLOT_RIGHT]->getID() != ITEM_RAINBOW)
  5254. if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5255. player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5256. player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5257. player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5258. }
  5259. }else{
  5260. if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5261. player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5262. player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5263. player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5264. }
  5265. }
  5266. }
  5267. }
  5268.  
  5269. // RING OF THE SKY
  5270. if(player->level >= 30 && player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_ROTS && !tile->isPz())
  5271. player->mana += min(1, player->manamax - player->mana);
  5272.  
  5273. // ORSHABAAL HEART
  5274. if(player->name == "Ekudron" || player->name == "Agecik" && player->items[SLOT_AMMO] && player->items[SLOT_AMMO]->getID() == ITEM_ORSHABAAL_HEARTH && !tile->isPz())
  5275. player->mana += min(4, player->manamax - player->mana);
  5276.  
  5277. #ifdef HUCZU_FIX
  5278. if(player->items[SLOT_FEET] && player->items[SLOT_FEET]->getID() == ITEM_SPECTRE_BOOTS)
  5279. player->immunities = ATTACK_PARALYZE;
  5280. else
  5281. player->immunities -= ATTACK_PARALYZE;
  5282. #endif //HUCZU_FIX
  5283.  
  5284. #ifdef YUR_LIGHT_ITEM
  5285. player->checkLightItem(thinkTicks);
  5286. #endif //YUR_LIGHT_ITEM
  5287. #ifdef HUCZU_EXHAUSTED
  5288. if(player->mmo > 0)
  5289. player->mmo -= 1;
  5290. else
  5291. player->mmo = 0;
  5292.  
  5293. if(player->lookex > 0)
  5294. player->lookex -= 1;
  5295. else
  5296. player->lookex = 0;
  5297.  
  5298. if(player->antyrainbow > 0)
  5299. player->antyrainbow -= 1;
  5300. else
  5301. player->antyrainbow = 0;
  5302.  
  5303. if(player->antyrainbow2 > 0)
  5304. player->antyrainbow2 -= 1;
  5305. else
  5306. player->antyrainbow2 = 0;
  5307.  
  5308. if(player->clin > 0)
  5309. player->clin -= 1;
  5310. else
  5311. player->clin = 0;
  5312.  
  5313. if(player->shut_d > 0)
  5314. player->shut_d -= 1;
  5315. else
  5316. player->shut_d = 0;
  5317.  
  5318. if(player->houseTicks > 0)
  5319. player->houseTicks -= 1;
  5320. else
  5321. player->houseTicks = 0;
  5322. #endif //HUCZU_EXHAUSTED
  5323.  
  5324. if(player->flamTicks >= 1000){
  5325. player->flamTicks -= thinkTicks;
  5326. if(player->flamTicks == 0){
  5327. player->flamBool = false;
  5328. }
  5329. }
  5330.  
  5331.  
  5332. if(player->items[SLOT_RIGHT] && player->items[SLOT_LEFT]){
  5333. 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)){
  5334. player->removeItemInventory(SLOT_RIGHT);
  5335. }
  5336. 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)){
  5337. player->removeItemInventory(SLOT_LEFT);
  5338. }
  5339. }
  5340.  
  5341. if(player->items[SLOT_RIGHT] && player->items[SLOT_LEFT]){
  5342. 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)){
  5343. player->removeItemInventory(SLOT_RIGHT);
  5344. }
  5345. 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)){
  5346. player->removeItemInventory(SLOT_LEFT);
  5347. }
  5348. }
  5349.  
  5350. #ifdef HUCZU_SKULLS
  5351. if (player->checkSkull(thinkTicks))
  5352. Skull(player);
  5353. #endif //HUCZU_SKULLS
  5354.  
  5355. #ifdef YUR_INVISIBLE
  5356. if (player->checkInvisible(thinkTicks))
  5357. creatureChangeOutfit(player);
  5358. #endif //YUR_INVISIBLE
  5359.  
  5360. #ifdef _BBK_PUSH_DELAY
  5361. if(player->pushDelay >= 1000)
  5362. {
  5363. player->pushDelay -= thinkTicks;
  5364. if(player->pushDelay < 0)
  5365. player->pushDelay = 0;
  5366. }
  5367. #endif //_BBK_PUSH_DELAY
  5368.  
  5369. if(player->training == true){
  5370. if(player->trainingTicks >= 1000){
  5371. player->trainingTicks -= thinkTicks;
  5372.  
  5373. if(player->trainingTicks < 0)
  5374. player->trainingTicks = 0;
  5375. }
  5376. if(player->trainingTicks == 0 && player->rewriteTicks == 0){
  5377. int code = random_range(47,99) * random_range(47,99);
  5378. player->rewriteCode = code;
  5379. player->needrewrite = true;
  5380. player->rewriteTicks = g_config.REWRITE_TICKS;
  5381. std::ostringstream info;
  5382. player->sendTextMessage(MSG_BLUE_TEXT,"You are training here pretty long.Are you using bot?");
  5383. info << "Please rewrite code: " << player->rewriteCode << std::ends;
  5384. player->sendTextMessage(MSG_BLUE_TEXT, info.str().c_str());
  5385. std::ostringstream info2;
  5386. info2 << "Use this command !train 1234. You have " << player->rewriteTicks/1000 << " seconds!" << std::ends;
  5387. player->sendTextMessage(MSG_BLUE_TEXT, info2.str().c_str());
  5388. }
  5389.  
  5390. if(player->needrewrite != false){
  5391. if(player->rewriteTicks >= 1000){
  5392. player->rewriteTicks -= thinkTicks;
  5393. }
  5394.  
  5395. if(player->rewriteTicks == 0){
  5396. this->teleport(player, player->masterPos);
  5397. player->training = false;
  5398. player->trainingTicks = 0;
  5399. player->needrewrite = false;
  5400. player->rewriteCode = 0;
  5401. player->rewriteTicks = 0;
  5402. player->kickPlayer();
  5403. //player->sendLogout();
  5404. }
  5405. }
  5406. }
  5407.  
  5408.  
  5409.  
  5410. #ifdef HUCZU_FIX
  5411. if(player->gainHealthTick()){
  5412. SpectatorVec list;
  5413. SpectatorVec::iterator it;
  5414. getSpectators(Range(creature->pos), list);
  5415. for(it = list.begin(); it != list.end(); ++it) {
  5416. Player* p = dynamic_cast<Player*>(*it);
  5417. if(p)
  5418. p->sendCreatureHealth(player);
  5419. }
  5420. }
  5421. #endif //HUCZU_FIX
  5422.  
  5423. if(player->lightTicks >= 1000){
  5424. player->lightTicks -= thinkTicks;
  5425. if(player->lightTicks <= 1000){
  5426. player->lightTicks = 1;
  5427. }
  5428. }
  5429. else if(player->lightTicks == 1){
  5430. if(player->lightlevel > 0){
  5431. creatureChangeLight(player, 0, player->lightlevel-1, 0xD7);
  5432. }
  5433. else{
  5434. creatureChangeLight(player, 0, 0, 0xD7);
  5435. player->lightTicks = 0;
  5436. player->lightItem = 0;
  5437. }
  5438. if(player->lightTries > 0){
  5439. player->lightTicks = 3*60*1000;
  5440. player->lightTries -= 1;
  5441. }
  5442. }
  5443.  
  5444. #ifdef HUCZU_SKULLS
  5445. checkSkullTime(player);
  5446. #endif //HUCZU_SKULLS
  5447.  
  5448.  
  5449. if(!tile->isPz()){
  5450. if(player->food > 1000){
  5451. player->gainManaTick();
  5452. player->food -= thinkTicks;
  5453. if(player->healthmax - player->health > 0){
  5454. if(player->gainHealthTick()){
  5455. SpectatorVec list;
  5456. SpectatorVec::iterator it;
  5457. getSpectators(Range(creature->pos), list);
  5458. for(it = list.begin(); it != list.end(); ++it) {
  5459. Player* p = dynamic_cast<Player*>(*it);
  5460. if(p)
  5461. p->sendCreatureHealth(player);
  5462. }
  5463. }
  5464. }
  5465. }
  5466. }
  5467.  
  5468. //send stast only if have changed
  5469. if(player->NeedUpdateStats()){
  5470. player->sendStats();
  5471. }
  5472.  
  5473. player->sendPing(thinkTicks);
  5474.  
  5475. if(player->inFightTicks >= 1000) {
  5476. player->inFightTicks -= thinkTicks;
  5477.  
  5478. if(player->inFightTicks < 1000)
  5479. player->pzLocked = false;
  5480. player->sendIcons();
  5481. }
  5482.  
  5483. if(player->drunkTicks >= 1000) {
  5484. int32_t random = random_range(1,100);
  5485. if(random <= 25){
  5486. creatureSay(creature, SPEAK_SAY, "Hicks!");
  5487. Position pos;
  5488. int32_t randomwalk = random_range(1,4);
  5489. switch(randomwalk){
  5490. case 1:pos.x++;break;
  5491. case 2:pos.x--;break;
  5492. case 3:pos.y++;break;
  5493. case 4:pos.y--;break;
  5494. }
  5495. Tile* toTile = getTile(pos.x, pos.y, pos.z);
  5496. //make sure they don't get teleported into a place they shouldn't
  5497. if(toTile &&
  5498. !toTile->isBlocking(1, false, false) &&
  5499. !toTile->isBlocking(2, false, false) &&
  5500. !toTile->isBlocking(4, false, false) &&
  5501. !toTile->isBlocking(8, false, false) &&
  5502. !toTile->isBlocking(16, false, false))
  5503. teleport(player,pos);
  5504. }
  5505. player->drunkTicks -= thinkTicks;
  5506. player->sendIcons();
  5507. }
  5508.  
  5509. if(player->exhaustedTicks >= 1000){
  5510. player->exhaustedTicks -= thinkTicks;
  5511.  
  5512. if(player->exhaustedTicks < 0)
  5513. player->exhaustedTicks = 0;
  5514. }
  5515.  
  5516. if(player->manaShieldTicks >=1000){
  5517. player->manaShieldTicks -= thinkTicks;
  5518.  
  5519. if(player->manaShieldTicks < 1000)
  5520. player->sendIcons();
  5521. }
  5522. if(player->dwarvenTicks > 0){
  5523. player->drunkTicks = 0;
  5524. player->sendIcons();
  5525. }
  5526. if(player->dwarvenTicks = 0){
  5527. player->drunkTicks = 4000;
  5528. player->sendIcons();
  5529. }
  5530.  
  5531. if(player->hasteTicks >=1000)
  5532. player->hasteTicks -= thinkTicks;
  5533. }else{
  5534.  
  5535. if(creature->manaShieldTicks >=1000){
  5536. creature->manaShieldTicks -= thinkTicks;
  5537. }
  5538.  
  5539. if(creature->hasteTicks >=1000){
  5540. creature->hasteTicks -= thinkTicks;
  5541. }
  5542.  
  5543. #ifdef YUR_INVISIBLE
  5544. if (creature->checkInvisible(thinkTicks))
  5545. creatureChangeOutfit(creature);
  5546. #endif //YUR_INVISIBLE
  5547. }
  5548.  
  5549. Conditions& conditions = creature->getConditions();
  5550. for(Conditions::iterator condIt = conditions.begin(); condIt != conditions.end(); ++condIt) {
  5551. if(condIt->first == ATTACK_FIRE || condIt->first == ATTACK_ENERGY || condIt->first == ATTACK_POISON) {
  5552. ConditionVec &condVec = condIt->second;
  5553.  
  5554. if(condVec.empty())
  5555. continue;
  5556.  
  5557. CreatureCondition& condition = condVec[0];
  5558.  
  5559. if(condition.onTick(oldThinkTicks)) {
  5560. const MagicEffectTargetCreatureCondition* magicTargetCondition = condition.getCondition();
  5561. Creature* c = getCreatureByID(magicTargetCondition->getOwnerID());
  5562. creatureMakeMagic(c, creature->pos, magicTargetCondition);
  5563.  
  5564. if(condition.getCount() <= 0) {
  5565. condVec.erase(condVec.begin());
  5566. if(dynamic_cast<Player*>(creature))
  5567. player->sendIcons();
  5568. }
  5569. }
  5570. }
  5571. if(condIt->first == ATTACK_PARALYZE)
  5572. {
  5573. ConditionVec &condVec = condIt->second;
  5574. if(condVec.empty())
  5575. continue;
  5576.  
  5577. CreatureCondition& condition = condVec[0];
  5578. if(condition.onTick(oldThinkTicks))
  5579. {
  5580. //Player* player = dynamic_cast<Player*>(creature);
  5581. if(creature->getImmunities() != ATTACK_PARALYZE)
  5582. {
  5583. changeSpeed(creature->getID(), 100);
  5584. if(player)
  5585. {
  5586. player->sendTextMessage(MSG_SMALLINFO, "You are paralyzed.");
  5587. player->sendIcons();
  5588. }
  5589. }
  5590.  
  5591. if(condition.getCount() <= 0)
  5592. {
  5593. condVec.erase(condVec.begin());
  5594. changeSpeed(creature->getID(), creature->getNormalSpeed()+creature->hasteSpeed);
  5595. if(player)
  5596. {
  5597. player->sendIcons();
  5598. }
  5599. }
  5600. }
  5601. }
  5602. }
  5603. flushSendBuffers();
  5604. }
  5605. }
  5606.  
  5607. void Game::changeOutfit(uint32_t id, int32_t looktype){
  5608.  
  5609. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::changeOutfit()");
  5610.  
  5611. Creature *creature = getCreatureByID(id);
  5612. if(creature){
  5613. creature->looktype = looktype;
  5614. if(creature->lookfeet_master != 0 || creature->lookhead_master != 0 ||
  5615. creature->looklegs_master != 0 || creature->lookbody_master != 0 ){
  5616. creature->lookhead = creature->lookhead_master;
  5617. creature->lookbody = creature->lookbody_master;
  5618. creature->looklegs = creature->looklegs_master;
  5619. creature->lookfeet = creature->lookfeet_master;
  5620.  
  5621. creature->lookhead_master = 0;
  5622. creature->lookbody_master = 0;
  5623. creature->looklegs_master = 0;
  5624. creature->lookfeet_master = 0;
  5625. }
  5626. creatureChangeOutfit(creature);
  5627. }
  5628. }
  5629.  
  5630. void Game::changeOutfitAfter(uint32_t id, int32_t looktype, long time)
  5631. {
  5632. addEvent(makeTask(time, boost::bind(&Game::changeOutfit, this,id, looktype)));
  5633. }
  5634.  
  5635. void Game::changeSpeed(uint32_t id, unsigned short speed)
  5636. {
  5637. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::changeSpeed()");
  5638. Creature *creature = getCreatureByID(id);
  5639. if(creature && /*creature->hasteTicks < 1000 && */creature->speed != speed)
  5640. {
  5641. creature->speed = speed;
  5642. Player* player = dynamic_cast<Player*>(creature);
  5643. if(player){
  5644. player->sendChangeSpeed(creature);
  5645. player->sendIcons();
  5646. }
  5647. SpectatorVec list;
  5648. SpectatorVec::iterator it;
  5649. getSpectators(Range(creature->pos), list);
  5650. //for(uint32_t i = 0; i < list.size(); i++)
  5651. for(it = list.begin(); it != list.end(); ++it) {
  5652. Player* p = dynamic_cast<Player*>(*it);
  5653. if(p)
  5654. p->sendChangeSpeed(creature);
  5655. }
  5656. }
  5657. }
  5658.  
  5659. void Game::checkCreatureAttacking(uint32_t id)
  5660. {
  5661. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreatureAttacking()");
  5662.  
  5663. Creature *creature = getCreatureByID(id);
  5664. if (creature != NULL && creature->isRemoved == false)
  5665. {
  5666.  
  5667. creature->eventCheckAttacking = 0;
  5668. Player *player = dynamic_cast<Player*>(creature);
  5669. Monster *monster = dynamic_cast<Monster*>(creature);
  5670. if (monster) {
  5671. monster->onAttack();
  5672. }
  5673. else {
  5674. if (creature->attackedCreature != 0)
  5675. {
  5676. Creature *attackedCreature = getCreatureByID(creature->attackedCreature);
  5677. if (attackedCreature)
  5678. {
  5679. // canAttack system BRY
  5680.  
  5681. Player *attacker = dynamic_cast<Player*>(creature);
  5682. Player *attacked = dynamic_cast<Player*>(attackedCreature);
  5683. bool canAttack = false;
  5684. if(attacker && attacked)
  5685. {
  5686. Tile* tile = getTile(attacker->pos.x,attacker->pos.y, attacker->pos.z);
  5687. if(attacked->level >= 1 && attacked->level < 30 && attacker->level >= 1 && attacker->level < 30)
  5688. canAttack = false;
  5689.  
  5690. else if(attacked->level >= 30 && attacked->level < 80 && attacker->level >= 30 && attacker->level < 80)
  5691. canAttack = true;
  5692.  
  5693. else if(attacked->level >= 81 && attacked->level < 999 && attacker->level >= 81 && attacker->level < 999)
  5694. canAttack = true;
  5695.  
  5696.  
  5697. else if(tile && tile->isPvpArena())
  5698. canAttack = true;
  5699. }
  5700.  
  5701.  
  5702.  
  5703. if(attacker && attacked && !canAttack)
  5704. {
  5705. attacker->sendCancelAttacking();
  5706. attacker->sendCancel("You may not attack this player yet.");
  5707. playerSetAttackedCreature(attacker, 0);
  5708. return;
  5709. }
  5710. //Tile* fromtile = getTile(creature->pos.x, creature->pos.y, creature->pos.z);
  5711. Tile* fromtile = map->getTile(creature->pos);
  5712. if(fromtile == NULL) {
  5713. std::cout << "checkCreatureAttacking NULL tile: " << creature->getName() << std::endl;
  5714. //return;
  5715. }
  5716. Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  5717. if (!attackedCreature->isAttackable() == 0 && fromtile && fromtile->isPz() && creature->access < g_config.ACCESS_PROTECT)
  5718. {
  5719. Player* player = dynamic_cast<Player*>(creature);
  5720. if (player) {
  5721. player->sendTextMessage(MSG_SMALLINFO, "You may not attack a person in a protection zone.");
  5722. //player->sendCancelAttacking();
  5723. playerSetAttackedCreature(player, 0);
  5724. return;
  5725. }
  5726. }
  5727. #ifdef YUR_INVISIBLE
  5728. if (attackedCreature->isInvisible())
  5729. {
  5730. Player* player = dynamic_cast<Player*>(creature);
  5731. Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  5732.  
  5733. if (player && !attackedPlayer) {
  5734. player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  5735. playerSetAttackedCreature(player, 0);
  5736. return;
  5737. }
  5738. }
  5739. #endif //YUR_INVISIBLE
  5740. else
  5741. {
  5742. if (attackedCreature != NULL && attackedCreature->isRemoved == false)
  5743. {
  5744.  
  5745. #ifdef ZS_SWORDS
  5746. int32_t swordid = player->getSwordId();
  5747. if (swordid > 0)
  5748. useSword(player, attackedCreature, swordid);
  5749. #endif //ZS_SWORDS
  5750.  
  5751. if(player && player->followMode == 0x01) {
  5752. player->followCreature = attackedCreature->getID();
  5753. playerAttackSetFollowCreature(player, attackedCreature->getID());
  5754. playerFollowAttacking(player, attackedCreature);
  5755. long long delay = player->getSleepTicks();
  5756. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollowAttack), player->getID())));
  5757. }
  5758.  
  5759.  
  5760. #ifdef WANDS_JIDDO
  5761. Player* player = dynamic_cast<Player*>(creature);
  5762. int32_t wandid = 0;
  5763. if(player && ((player->items[SLOT_RIGHT] && (wandid = player->items[SLOT_RIGHT]->getWand())) || (player->items[SLOT_LEFT] && (wandid = player->items[SLOT_LEFT]->getWand())))) {
  5764. useWand(creature, attackedCreature, wandid);
  5765. } else {
  5766. #endif
  5767. Player* player = dynamic_cast<Player*>(creature);
  5768. if (player)
  5769. {
  5770. #ifdef SD_BURST_ARROW
  5771. if (player->isUsingBurstArrows())
  5772. burstArrow(player, attackedCreature->pos);
  5773. #endif //SD_BURST_ARROW
  5774. if(player->flamBool == true){
  5775. Blasting(player, attackedCreature, attackedCreature->pos);
  5776. player->flamBool = false;
  5777. }
  5778. }
  5779. this->creatureMakeDamage(creature, attackedCreature, creature->getFightType());
  5780. #ifdef WANDS_JIDDO
  5781. }
  5782. #endif
  5783. }
  5784. }
  5785.  
  5786. if (player->vocation == 0) {
  5787. int32_t speed = int32_t(g_config.NO_VOC_SPEED * 1000);
  5788. creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5789. }
  5790. else if (player->vocation == 1) {
  5791. int32_t speed = int32_t(g_config.SORC_SPEED * 1000);
  5792. creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5793. }
  5794. else if (player->vocation == 2) {
  5795. int32_t speed = int32_t(g_config.DRUID_SPEED * 1000);
  5796. creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5797. }
  5798. else if (player->vocation == 3) {
  5799. int32_t speed = int32_t(g_config.PALLY_SPEED * 1000);
  5800. creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5801. }
  5802. else if (player->vocation == 4) {
  5803. int32_t speed = int32_t(g_config.KNIGHT_SPEED * 1000);
  5804. creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5805. }
  5806. else { //change the 2000 to whatever you want; 2000 = 2 seconds per attack
  5807. creature->eventCheckAttacking = addEvent(makeTask(1000, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5808. }
  5809. }
  5810. }
  5811. }
  5812. flushSendBuffers();
  5813. }
  5814. }
  5815. void Game::checkDecay(int32_t t)
  5816. {
  5817. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkDecay()");
  5818.  
  5819. addEvent(makeTask(DECAY_INTERVAL, boost::bind(&Game::checkDecay,this,DECAY_INTERVAL)));
  5820.  
  5821. list<decayBlock*>::iterator it;
  5822. for(it = decayVector.begin();it != decayVector.end();){
  5823. (*it)->decayTime -= t;
  5824. if((*it)->decayTime <= 0){
  5825. list<Item*>::iterator it2;
  5826. for(it2 = (*it)->decayItems.begin(); it2 != (*it)->decayItems.end(); it2++){
  5827. /*todo: Decaying item could be in a container carried by a player,
  5828. should all items have a pointer to their parent (like containers)?*/
  5829. Item* item = *it2;
  5830. item->isDecaying = false;
  5831. if(item->canDecay()){
  5832. if(item->pos.x != 0xFFFF){
  5833. Tile *tile = map->getTile(item->pos);
  5834. if(tile){
  5835. Position pos = item->pos;
  5836. Item* newitem = item->decay();
  5837.  
  5838. if(newitem){
  5839. int32_t stackpos = tile->getThingStackPos(item);
  5840. if(newitem == item){
  5841. sendUpdateThing(NULL,pos,newitem,stackpos);
  5842. }
  5843. else{
  5844. if(tile->removeThing(item)){
  5845. //autoclose containers
  5846. if(dynamic_cast<Container*>(item)){
  5847. SpectatorVec list;
  5848. SpectatorVec::iterator it;
  5849.  
  5850. getSpectators(Range(pos, true), list);
  5851.  
  5852. for(it = list.begin(); it != list.end(); ++it) {
  5853. Player* spectator = dynamic_cast<Player*>(*it);
  5854. if(spectator)
  5855. spectator->onThingRemove(item);
  5856. }
  5857. }
  5858.  
  5859. tile->insertThing(newitem, stackpos);
  5860. sendUpdateThing(NULL,pos,newitem,stackpos);
  5861. FreeThing(item);
  5862. }
  5863. }
  5864. startDecay(newitem);
  5865. }
  5866. else{
  5867. if(removeThing(NULL,pos,item)){
  5868. FreeThing(item);
  5869. }
  5870. }//newitem
  5871. }//tile
  5872. }//pos != 0xFFFF
  5873. }//item->canDecay()
  5874. FreeThing(item);
  5875. }//for it2
  5876. delete *it;
  5877. it = decayVector.erase(it);
  5878. }//(*it)->decayTime <= 0
  5879. else{
  5880. it++;
  5881. }
  5882. }//for it
  5883.  
  5884. flushSendBuffers();
  5885. }
  5886.  
  5887. void Game::startDecay(Item* item){
  5888. if(item->isDecaying)
  5889. return;//dont add 2 times the same item
  5890. //get decay time
  5891. item->isDecaying = true;
  5892. uint32_t dtime = item->getDecayTime();
  5893. if(dtime == 0)
  5894. return;
  5895. //round time
  5896. if(dtime < DECAY_INTERVAL)
  5897. dtime = DECAY_INTERVAL;
  5898. dtime = (dtime/DECAY_INTERVAL)*DECAY_INTERVAL;
  5899. item->useThing();
  5900. //search if there are any block with this time
  5901. list<decayBlock*>::iterator it;
  5902. for(it = decayVector.begin();it != decayVector.end();it++){
  5903. if((*it)->decayTime == dtime){
  5904. (*it)->decayItems.push_back(item);
  5905. return;
  5906. }
  5907. }
  5908. //we need a new decayBlock
  5909. decayBlock* db = new decayBlock;
  5910. db->decayTime = dtime;
  5911. db->decayItems.clear();
  5912. db->decayItems.push_back(item);
  5913. decayVector.push_back(db);
  5914. }
  5915.  
  5916. void Game::checkSpawns(int32_t t)
  5917. {
  5918. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkSpawns()");
  5919.  
  5920. SpawnManager::instance()->checkSpawns(t);
  5921. this->addEvent(makeTask(t, std::bind2nd(std::mem_fun(&Game::checkSpawns), t)));
  5922. }
  5923.  
  5924. void Game::CreateDamageUpdate(Creature* creature, Creature* attackCreature, int32_t damage)
  5925. {
  5926. Player* player = dynamic_cast<Player*>(creature);
  5927. Player* attackPlayer = dynamic_cast<Player*>(attackCreature);
  5928. if(!player)
  5929. return;
  5930. //player->sendStats();
  5931. //msg.AddPlayerStats(player);
  5932. if (damage > 0) {
  5933. std::stringstream dmgmesg, info;
  5934.  
  5935. if(damage == 1) {
  5936. dmgmesg << "You lose 1 hitpoint";
  5937. }
  5938. else
  5939. dmgmesg << "You lose " << damage << " hitpoints";
  5940.  
  5941. if(attackPlayer) {
  5942. dmgmesg << " due to an attack by " << attackCreature->getName();
  5943. }
  5944. else if(attackCreature) {
  5945. std::string strname = attackCreature->getName();
  5946. std::transform(strname.begin(), strname.end(), strname.begin(), (int32_t(*)(int32_t))tolower);
  5947. dmgmesg << " due to an attack by a " << strname;
  5948. }
  5949. dmgmesg <<".";
  5950.  
  5951. player->sendTextMessage(MSG_EVENT, dmgmesg.str().c_str());
  5952. //msg.AddTextMessage(MSG_EVENT, dmgmesg.str().c_str());
  5953. }
  5954. if (player->isRemoved == true){
  5955. player->sendTextMessage(MSG_ADVANCE, "You are dead.");
  5956. }
  5957. }
  5958.  
  5959.  
  5960. void Game::CreateManaDamageUpdate(Creature* creature, Creature* attackCreature, int32_t damage)
  5961. {
  5962. Player* player = dynamic_cast<Player*>(creature);
  5963. if(!player)
  5964. return;
  5965.  
  5966. if (damage > 0) {
  5967. std::stringstream dmgmesg;
  5968. dmgmesg << "You lose " << damage << " mana";
  5969. if(attackCreature) {
  5970. dmgmesg << " blocking an attack by " << attackCreature->getName();
  5971. }
  5972. dmgmesg <<".";
  5973.  
  5974. player->sendTextMessage(MSG_EVENT, dmgmesg.str().c_str());
  5975. }
  5976. }
  5977.  
  5978. bool Game::creatureSaySpell(Creature *creature, const std::string &text, bool say)
  5979. {
  5980. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureSaySpell()");
  5981.  
  5982. bool ret = false;
  5983.  
  5984. Player* player = dynamic_cast<Player*>(creature);
  5985. std::string temp, var;
  5986. uint32_t loc = (uint32_t)text.find( "\"", 0 );
  5987. if( loc != string::npos && loc >= 0){
  5988. temp = std::string(text, 0, loc-1);
  5989. var = std::string(text, (loc+1), text.size()-loc-1);
  5990. }
  5991. else {
  5992. temp = text;
  5993. var = std::string("");
  5994. }
  5995.  
  5996. std::transform(temp.begin(), temp.end(), temp.begin(), (int32_t(*)(int32_t))tolower);
  5997.  
  5998. if(creature->access >= g_config.ACCESS_PROTECT || !player){
  5999. std::map<std::string, Spell*>::iterator sit = spells.getAllSpells()->find(temp);
  6000. if (sit != spells.getAllSpells()->end()){
  6001. sit->second->getSpellScript()->castSpell(creature, creature->pos, var);
  6002. if (creature->access >= g_config.ACCESS_PROTECT && say == true)
  6003. this->creatureSay(creature, SPEAK_MONSTER1, text);
  6004. ret = true;
  6005. }
  6006. }
  6007. else if(player){
  6008. std::map<std::string, Spell*>* tmp = spells.getVocSpells(player->vocation);
  6009. if(tmp){
  6010. std::map<std::string, Spell*>::iterator sit = tmp->find(temp);
  6011. if(sit != tmp->end()){
  6012. if(player->maglevel >= sit->second->getMagLv()){
  6013. #ifdef YUR_LEARN_SPELLS
  6014. if (g_config.LEARN_SPELLS && !player->knowsSpell(temp))
  6015. ret = false;
  6016. else
  6017. #endif //YUR_LEARN_SPELLS
  6018. {
  6019. if(sit->second->getSpellScript()->castSpell(creature, creature->pos, var) && say == true)
  6020. this->creatureSay(player, SPEAK_MONSTER1, text);
  6021. ret = true;
  6022. }
  6023. }
  6024. }
  6025. }
  6026. }
  6027.  
  6028.  
  6029.  
  6030. return ret;
  6031. }
  6032.  
  6033. void Game::playerAutoWalk(Player* player, std::list<Direction>& path)
  6034. {
  6035. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerAutoWalk()");
  6036.  
  6037. stopEvent(player->eventAutoWalk);
  6038. player->eventAutoWalk = 0;
  6039.  
  6040. if(player->isRemoved)
  6041. return;
  6042.  
  6043. player->pathlist = path;
  6044. int32_t ticks = (int32_t)player->getSleepTicks();
  6045. /*
  6046. #ifdef __DEBUG__
  6047. std::cout << "playerAutoWalk - " << ticks << std::endl;
  6048. #endif
  6049. */
  6050. if(!player->pathlist.empty())
  6051. player->eventAutoWalk = addEvent(makeTask(ticks, std::bind2nd(std::mem_fun(&Game::checkPlayerWalk), player->getID())));
  6052.  
  6053. // then we schedule the movement...
  6054. // the interval seems to depend on the speed of the char?
  6055. //player->eventAutoWalk = addEvent(makeTask<Direction>(0, MovePlayer(player->getID()), path, 400, StopMovePlayer(player->getID())));
  6056. //player->pathlist = path;
  6057. }
  6058.  
  6059. bool Game::playerUseItemEx(Player *player, const Position& posFrom,const unsigned char stack_from,
  6060. const Position &posTo,const unsigned char stack_to, const unsigned short itemid)
  6061. {
  6062. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerUseItemEx()");
  6063.  
  6064. if(player->isRemoved)
  6065. return false;
  6066.  
  6067. bool ret = false;
  6068.  
  6069. Position thingpos = getThingMapPos(player, posFrom);
  6070. Item *item = dynamic_cast<Item*>(getThing(posFrom, stack_from, player));
  6071. Container* container = player->getContainer(player->shop_index);
  6072. if(container && item && !container->shop.empty() && container->isHoldingItem(item))
  6073. return false;
  6074.  
  6075. if(item) {
  6076. //Runes
  6077. std::map<unsigned short, Spell*>::iterator sit = spells.getAllRuneSpells()->find(item->getID());
  6078. if(sit != spells.getAllRuneSpells()->end()) {
  6079. #ifdef PALL_REQ_LVL
  6080. std::stringstream ss;
  6081. if(item->getReqLevel() > player->getLevel()){
  6082. ss << "\n Musisz miec " << item->getReqLevel() << " poziom aby tego uzyc.";
  6083. ret = false;
  6084. }
  6085. if(item->isWeapon() && item->getReqVoc() != player->getVocation()){
  6086. switch(item->getReqVoc()){
  6087. case 1:
  6088. ss << "\n You must be a sorcerer to use this weapon.";
  6089. ret = false;
  6090. break;
  6091. case 2:
  6092. ss << "\n You must be a druid to use this weapon.";
  6093. ret = false;
  6094. break;
  6095. case 3:
  6096. ss << "\n You must be a paladin to use this weapon.";
  6097. ret = false;
  6098. break;
  6099. case 4:
  6100. ss << "\n You must be a knight to use this weapon.";
  6101. ret = false;
  6102. break;
  6103. }
  6104. }
  6105. player->sendTextMessage(MSG_SMALLINFO, ss.str().c_str());
  6106. #endif //PALL_REQ_LVL
  6107. if( (abs(thingpos.x - player->pos.x) > 1) || (abs(thingpos.y - player->pos.y) > 1) ) {
  6108. player->sendCancel("Too far away.");
  6109. ret = false;
  6110. }
  6111. else {
  6112. std::string var = std::string("");
  6113. if(player->access >= g_config.ACCESS_PROTECT || sit->second->getMagLv() <= player->maglevel)
  6114. {
  6115. bool success = sit->second->getSpellScript()->castSpell(player, posTo, var);
  6116. ret = success;
  6117. if(success) {
  6118. autoCloseTrade(item);
  6119. item->setItemCharge(std::max((int32_t)item->getItemCharge() - 1, 0) );
  6120. if(item->getItemCharge() == 0) {
  6121. if(removeThing(player,posFrom,item)){
  6122. FreeThing(item);
  6123. }
  6124. }
  6125. }
  6126. }
  6127. else
  6128. {
  6129. player->sendCancel("You don't have the required magic level to use that rune.");
  6130. }
  6131. }
  6132. }
  6133. else{
  6134. actions.UseItemEx(player,posFrom,stack_from,posTo,stack_to,itemid);
  6135. ret = true;
  6136. }
  6137. }
  6138.  
  6139.  
  6140. return ret;
  6141. }
  6142.  
  6143.  
  6144. bool Game::playerUseItem(Player *player, const Position& pos, const unsigned char stackpos, const unsigned short itemid, unsigned char index)
  6145. {
  6146. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerUseItem()");
  6147. if(itemid == 2273 || itemid == 2275 ){
  6148.  
  6149. MagicEffectClass pox;
  6150. pox.animationColor = 0;
  6151. pox.damageEffect = NM_ME_MAGIC_ENERGIE;
  6152. pox.hitEffect = 255;
  6153. pox.attackType = ATTACK_NONE;
  6154. pox.maxDamage = 0;
  6155. pox.minDamage = 0;
  6156. pox.offensive = false;
  6157. pox.manaCost = 0;
  6158. if(creatureMakeMagic(player, player->pos, &pox)){
  6159. player->removeCondition(ATTACK_PARALYZE);
  6160. int32_t newspeed = player->getNormalSpeed()+player->hasteSpeed;
  6161. changeSpeed(player->getID(), (unsigned short)newspeed);
  6162.  
  6163. if(player)
  6164. player->sendIcons();
  6165. }
  6166. else{
  6167. player->sendCancel("Sorry, not possible.");
  6168. return false;
  6169. }
  6170. }
  6171. if(player->isRemoved)
  6172. return false;
  6173.  
  6174. actions.UseItem(player,pos,stackpos,itemid,index);
  6175. return true;
  6176. }
  6177.  
  6178. bool Game::playerUseBattleWindow(Player *player, Position &posFrom, unsigned char stackpos, unsigned short itemid, uint32_t creatureid)
  6179. {
  6180. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerUseBattleWindow");
  6181.  
  6182. if(player->isRemoved)
  6183. return false;
  6184.  
  6185. Creature *creature = getCreatureByID(creatureid);
  6186. if(!creature || dynamic_cast<Player*>(creature))
  6187. return false;
  6188.  
  6189. 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)
  6190. return false;
  6191.  
  6192. bool ret = false;
  6193.  
  6194. Position thingpos = getThingMapPos(player, posFrom);
  6195. Item *item = dynamic_cast<Item*>(getThing(posFrom, stackpos, player));
  6196. Container* container = player->getContainer(player->shop_index);
  6197. if(container && item && !container->shop.empty() && container->isHoldingItem(item))
  6198. return false;
  6199. if(item) {
  6200. //Runes
  6201. std::map<unsigned short, Spell*>::iterator sit = spells.getAllRuneSpells()->find(item->getID());
  6202. if(sit != spells.getAllRuneSpells()->end()) {
  6203. if( (abs(thingpos.x - player->pos.x) > 1) || (abs(thingpos.y - player->pos.y) > 1) ) {
  6204. player->sendCancel("Too far away.");
  6205. }
  6206. else {
  6207. std::string var = std::string("");
  6208. if(player->access >= g_config.ACCESS_PROTECT || sit->second->getMagLv() <= player->maglevel)
  6209. {
  6210. bool success = sit->second->getSpellScript()->castSpell(player, creature->pos, var);
  6211. ret = success;
  6212. if(success){
  6213. autoCloseTrade(item);
  6214. item->setItemCharge(std::max((int32_t)item->getItemCharge() - 1, 0) );
  6215. if(item->getItemCharge() == 0){
  6216. if(removeThing(player,posFrom,item)){
  6217. FreeThing(item);
  6218. }
  6219. }
  6220. }
  6221. }
  6222. else
  6223. {
  6224. player->sendCancel("You don't have the required magic level to use that rune.");
  6225. }
  6226. }
  6227. }
  6228. }
  6229. return ret;
  6230. }
  6231.  
  6232. bool Game::playerRotateItem(Player *player, const Position& pos, const unsigned char stackpos, const unsigned short itemid)
  6233. {
  6234. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerRotateItem()");
  6235.  
  6236. if(player->isRemoved)
  6237. return false;
  6238.  
  6239. if(std::abs(player->pos.x - pos.x) > 1 || std::abs(player->pos.y - pos.y) > 1 || player->pos.z != pos.z){
  6240. player->sendCancel("Too far away.");
  6241. return false;
  6242. }
  6243.  
  6244. Item *item = dynamic_cast<Item*>(getThing(pos, stackpos, player));
  6245. if(item && item->rotate()){
  6246. sendUpdateThing(player, pos, item, stackpos);
  6247. }
  6248.  
  6249. return false;
  6250. }
  6251.  
  6252. void Game::playerRequestTrade(Player* player, const Position& pos,
  6253. const unsigned char stackpos, const unsigned short itemid, uint32_t playerid)
  6254. {
  6255. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerRequestTrade()");
  6256.  
  6257. if(player->isRemoved)
  6258. return;
  6259.  
  6260. Player *tradePartner = getPlayerByID(playerid);
  6261. if(!tradePartner || tradePartner == player) {
  6262. player->sendTextMessage(MSG_INFO, "Sorry, not possible.");
  6263. return;
  6264. }
  6265.  
  6266. if(player->tradeState != TRADE_NONE && !(player->tradeState == TRADE_ACKNOWLEDGE && player->tradePartner == playerid)) {
  6267. player->sendCancel("You are already trading.");
  6268. return;
  6269. }
  6270. else if(tradePartner->tradeState != TRADE_NONE && tradePartner->tradePartner != player->getID()) {
  6271. player->sendCancel("This player is already trading.");
  6272. return;
  6273. }
  6274.  
  6275. Item *tradeItem = dynamic_cast<Item*>(getThing(pos, stackpos, player));
  6276. if(!tradeItem || tradeItem->getID() != itemid || !tradeItem->isPickupable()) {
  6277. player->sendCancel("Sorry, not possible.");
  6278. return;
  6279. }
  6280.  
  6281. #ifdef __KIRO_AKT__
  6282. if(tradeItem->getID() == ITEM_AKT)
  6283. {
  6284. Tile* tile = getTile(player->pos);
  6285. House* house = tile? tile->getHouse() : NULL;
  6286.  
  6287. if(!house)
  6288. {
  6289. player->sendCancel("You must stay in house!");
  6290. return;
  6291. }
  6292. if(house->getOwner() != player->getName())
  6293. {
  6294. player->sendCancel("You must stay in your house!");
  6295. return;
  6296. }
  6297. }
  6298.  
  6299. #endif
  6300.  
  6301. if(!player->removeItem(tradeItem, true)) {
  6302. /*if( (abs(player->pos.x - pos.x) > 1) || (abs(player->pos.y - pos.y) > 1) ) {
  6303. player->sendCancel("To far away...");
  6304. return;
  6305. }*/
  6306. player->sendCancel("Sorry, not possible.");
  6307. return;
  6308. }
  6309.  
  6310. std::map<Item*, uint32_t>::const_iterator it;
  6311. const Container* container = NULL;
  6312. for(it = tradeItems.begin(); it != tradeItems.end(); it++) {
  6313. if(tradeItem == it->first ||
  6314. ((container = dynamic_cast<const Container*>(tradeItem)) && container->isHoldingItem(it->first)) ||
  6315. ((container = dynamic_cast<const Container*>(it->first)) && container->isHoldingItem(tradeItem)))
  6316. {
  6317. player->sendTextMessage(MSG_INFO, "This item is already beeing traded.");
  6318. return;
  6319. }
  6320. }
  6321.  
  6322. Container* tradeContainer = dynamic_cast<Container*>(tradeItem);
  6323. if(tradeContainer && tradeContainer->getItemHoldingCount() + 1 > 100){
  6324. player->sendTextMessage(MSG_INFO, "You cannot trade more than 100 items.");
  6325. return;
  6326. }
  6327.  
  6328. player->tradePartner = playerid;
  6329. player->tradeItem = tradeItem;
  6330. player->tradeState = TRADE_INITIATED;
  6331. tradeItem->useThing();
  6332. tradeItems[tradeItem] = player->getID();
  6333.  
  6334. player->sendTradeItemRequest(player, tradeItem, true);
  6335.  
  6336. if(tradePartner->tradeState == TRADE_NONE){
  6337. std::stringstream trademsg;
  6338. trademsg << player->getName() <<" wants to trade with you.";
  6339. tradePartner->sendTextMessage(MSG_INFO, trademsg.str().c_str());
  6340. tradePartner->tradeState = TRADE_ACKNOWLEDGE;
  6341. tradePartner->tradePartner = player->getID();
  6342. }
  6343. else {
  6344. Item* counterOfferItem = tradePartner->tradeItem;
  6345. player->sendTradeItemRequest(tradePartner, counterOfferItem, false);
  6346. tradePartner->sendTradeItemRequest(player, tradeItem, false);
  6347. }
  6348. }
  6349.  
  6350. void Game::playerAcceptTrade(Player* player)
  6351. {
  6352. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerAcceptTrade()");
  6353.  
  6354. if(player->isRemoved)
  6355. return;
  6356.  
  6357. player->setAcceptTrade(true);
  6358. Player *tradePartner = getPlayerByID(player->tradePartner);
  6359. if(tradePartner && tradePartner->getAcceptTrade()) {
  6360. Item *tradeItem1 = player->tradeItem;
  6361. Item *tradeItem2 = tradePartner->tradeItem;
  6362.  
  6363. player->sendCloseTrade();
  6364. tradePartner->sendCloseTrade();
  6365.  
  6366. #ifdef __KIRO_AKT__
  6367. if(tradeItem1->getID() == ITEM_AKT)
  6368. {
  6369. Tile* tile = getTile(player->pos);
  6370. House* house = tile? tile->getHouse() : NULL;
  6371. Tile* tile2 = getTile(tradePartner->pos);
  6372. Creature* creature = getCreatureByName(house->getOwner());
  6373. Player* prevOwner = creature? dynamic_cast<Player*>(creature) : NULL;
  6374. if(!house || !tile->isHouse())
  6375. {
  6376. player->sendCancel("You must stay in house!");
  6377. return;
  6378. }
  6379. if(!tile->isHouse() && !tile2->isHouse() && player->tradeState != TRADE_INITIATED){
  6380. player->sendCancel("You can only sell act if you are in house and you are the owner!");
  6381. return;
  6382. }
  6383. if(house->getOwner() != player->getName())
  6384. {
  6385. player->sendCancel("You must stay in your house!");
  6386. return;
  6387. }
  6388.  
  6389. if(house && house->checkHouseCount(tradePartner) >= g_config.getGlobalNumber("maxhouses", 0)){
  6390. std::stringstream textmsg;
  6391. textmsg << "You cannot have more than " << g_config.getGlobalNumber("maxhouses", 1) << " house.";
  6392. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6393. return;
  6394. }
  6395.  
  6396. if (house && tradePartner->level < g_config.getGlobalNumber("buyhouselvlrook",1) && tradePartner->vocation == 0)
  6397. {
  6398. player->sendCancel("This player have too low level to buy house!");
  6399. std::stringstream textmsg;
  6400. textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("buyhouselvlrook",2) << " level.";
  6401. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6402. return;
  6403. }
  6404.  
  6405. if (house && tradePartner->level < g_config.getGlobalNumber("houselevel", 0) && tradePartner->vocation != 0)
  6406. {
  6407. player->sendCancel("This player have too low level to buy house!");
  6408. std::stringstream textmsg;
  6409. textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("houselevel", 0) << " level.";
  6410. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6411. return;
  6412. }
  6413.  
  6414. if(tradePartner->getFreeCapacity() < tradeItem1->getWeight())
  6415. {
  6416. return;
  6417. }
  6418.  
  6419. if(player->addItem(tradeItem2, true) && tradePartner->addItem(tradeItem1, true) &&
  6420. player->removeItem(tradeItem1, true) && tradePartner->removeItem(tradeItem2, true)){
  6421.  
  6422. player->removeItem(tradeItem1);
  6423. tradePartner->removeItem(tradeItem2);
  6424.  
  6425. player->onThingRemove(tradeItem1);
  6426. tradePartner->onThingRemove(tradeItem2);
  6427.  
  6428. player->addItem(tradeItem2);
  6429. tradePartner->addItem(tradeItem1);
  6430. }
  6431. else{
  6432. player->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6433. tradePartner->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6434. return;
  6435. }
  6436. player->removeItem(tradeItem1, true);
  6437. tradePartner->addItem(tradeItem1, true);
  6438. player->addItem(tradeItem2, true);
  6439. house->setOwner(tradePartner->getName());
  6440. teleport(player,tradePartner->pos);
  6441. if (prevOwner)
  6442. prevOwner->houseRightsChanged = true;
  6443. tradePartner->houseRightsChanged = true;
  6444. }
  6445. else if(tradeItem2->getID() == ITEM_AKT)
  6446. {
  6447. Tile* tile = getTile(tradePartner->pos);
  6448. House* house = tile? tile->getHouse() : NULL;
  6449. Tile* tile2 = getTile(player->pos);
  6450. Creature* creature = getCreatureByName(house->getOwner());
  6451. Player* prevOwner = creature? dynamic_cast<Player*>(creature) : NULL;
  6452. if(!house || !tile->isHouse())
  6453. {
  6454. tradePartner->sendCancel("You must stay in house!");
  6455. return;
  6456. }
  6457. if(!tile->isHouse() && !tile2->isHouse() && player->tradeState != TRADE_INITIATED){
  6458. player->sendCancel("You can only sell act if you are in house and you are the owner!");
  6459. return;
  6460. }
  6461. if(house->getOwner() != tradePartner->getName())
  6462. {
  6463. tradePartner->sendCancel("You must stay in your house!");
  6464. return;
  6465. }
  6466.  
  6467. if(house && house->checkHouseCount(player) >= g_config.getGlobalNumber("maxhouses", 0)){
  6468. std::stringstream textmsg;
  6469. textmsg << " You cannot have more than " << g_config.getGlobalNumber("maxhouses", 1) << " house.";
  6470. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6471. return;
  6472. }
  6473.  
  6474. if (house && tradePartner->level < g_config.getGlobalNumber("buyhouselvlrook",1) && tradePartner->vocation == 0)
  6475. {
  6476. player->sendCancel("This player have too low level to buy house!");
  6477. std::stringstream textmsg;
  6478. textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("buyhouselvlrook",2) << " level.";
  6479. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6480. return;
  6481. }
  6482.  
  6483. if (house && tradePartner->level < g_config.getGlobalNumber("houselevel", 0) && tradePartner->vocation != 0)
  6484. {
  6485. player->sendCancel("This player have too low level to buy house!");
  6486. std::stringstream textmsg;
  6487. textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("houselevel", 0) << " level.";
  6488. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6489. return;
  6490. }
  6491.  
  6492. if(tradePartner->getFreeCapacity() < tradeItem1->getWeight())
  6493. {
  6494. return;
  6495. }
  6496.  
  6497. if(player->addItem(tradeItem2, true) && tradePartner->addItem(tradeItem1, true) &&
  6498. player->removeItem(tradeItem1, true) && tradePartner->removeItem(tradeItem2, true)){
  6499.  
  6500. player->removeItem(tradeItem1);
  6501. tradePartner->removeItem(tradeItem2);
  6502.  
  6503. player->onThingRemove(tradeItem1);
  6504. tradePartner->onThingRemove(tradeItem2);
  6505.  
  6506. player->addItem(tradeItem2);
  6507. tradePartner->addItem(tradeItem1);
  6508. }
  6509. else{
  6510. player->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6511. tradePartner->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6512. return;
  6513. }
  6514. tradePartner->removeItem(tradeItem1, true);
  6515. player->addItem(tradeItem1, true);
  6516. tradePartner->addItem(tradeItem2, true);
  6517. house->setOwner(player->getName());
  6518. teleport(tradePartner,player->pos);
  6519. if (prevOwner)
  6520. prevOwner->houseRightsChanged = true;
  6521. player->houseRightsChanged = true;
  6522. }
  6523. #endif
  6524.  
  6525. if(player->addItem(tradeItem2, true) && tradePartner->addItem(tradeItem1, true) &&
  6526. player->removeItem(tradeItem1, true) && tradePartner->removeItem(tradeItem2, true)){
  6527.  
  6528. player->removeItem(tradeItem1);
  6529. tradePartner->removeItem(tradeItem2);
  6530.  
  6531. player->onThingRemove(tradeItem1);
  6532. tradePartner->onThingRemove(tradeItem2);
  6533.  
  6534. player->addItem(tradeItem2);
  6535. tradePartner->addItem(tradeItem1);
  6536. }
  6537. else{
  6538. player->sendTextMessage(MSG_SMALLINFO, "Sorry not possible.");
  6539. tradePartner->sendTextMessage(MSG_SMALLINFO, "Sorry not possible.");
  6540. }
  6541.  
  6542. std::map<Item*, uint32_t>::iterator it;
  6543.  
  6544. it = tradeItems.find(tradeItem1);
  6545. if(it != tradeItems.end()) {
  6546. FreeThing(it->first);
  6547. tradeItems.erase(it);
  6548. }
  6549.  
  6550. it = tradeItems.find(tradeItem2);
  6551. if(it != tradeItems.end()) {
  6552. FreeThing(it->first);
  6553. tradeItems.erase(it);
  6554. }
  6555.  
  6556. player->setAcceptTrade(false);
  6557. tradePartner->setAcceptTrade(false);
  6558. }
  6559. }
  6560.  
  6561. void Game::playerLookInTrade(Player* player, bool lookAtCounterOffer, int32_t index)
  6562. {
  6563. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerLookInTrade()");
  6564.  
  6565. Player *tradePartner = getPlayerByID(player->tradePartner);
  6566. if(!tradePartner)
  6567. return;
  6568.  
  6569. Item *tradeItem = NULL;
  6570.  
  6571. if(lookAtCounterOffer)
  6572. tradeItem = tradePartner->getTradeItem();
  6573. else
  6574. tradeItem = player->getTradeItem();
  6575.  
  6576. if(!tradeItem)
  6577. return;
  6578.  
  6579. #ifdef __KIRO_AKT__
  6580. if(tradeItem->getID() == ITEM_AKT)
  6581. {
  6582. Tile* tile = getTile(tradePartner->pos);
  6583. House* house = tile? tile->getHouse() : NULL;
  6584.  
  6585.  
  6586. if(house && house->getOwner() == tradePartner->getName())
  6587. {
  6588. stringstream ss;
  6589. ss << "You see " << tradeItem->getDescription(true) << " applies to: " << house->getName() << ".";
  6590. player->sendTextMessage(MSG_INFO, ss.str().c_str());
  6591. return;
  6592. }
  6593.  
  6594. }
  6595. #endif
  6596.  
  6597. if(index == 0) {
  6598. stringstream ss;
  6599. ss << "You see " << tradeItem->getDescription(true);
  6600. player->sendTextMessage(MSG_INFO, ss.str().c_str());
  6601. return;
  6602. }
  6603.  
  6604. Container *tradeContainer = dynamic_cast<Container*>(tradeItem);
  6605. if(!tradeContainer || index > tradeContainer->getItemHoldingCount())
  6606. return;
  6607.  
  6608. bool foundItem = false;
  6609. std::list<const Container*> stack;
  6610. stack.push_back(tradeContainer);
  6611.  
  6612. ContainerList::const_iterator it;
  6613.  
  6614. while(!foundItem && stack.size() > 0) {
  6615. const Container *container = stack.front();
  6616. stack.pop_front();
  6617.  
  6618. for (it = container->getItems(); it != container->getEnd(); ++it) {
  6619. Container *container = dynamic_cast<Container*>(*it);
  6620. if(container) {
  6621. stack.push_back(container);
  6622. }
  6623.  
  6624. --index;
  6625. if(index == 0) {
  6626. tradeItem = *it;
  6627. foundItem = true;
  6628. break;
  6629. }
  6630. }
  6631. }
  6632.  
  6633. if(foundItem) {
  6634. stringstream ss;
  6635. ss << "You see " << tradeItem->getDescription(true);
  6636. player->sendTextMessage(MSG_INFO, ss.str().c_str());
  6637. }
  6638. }
  6639.  
  6640. void Game::playerCloseTrade(Player* player)
  6641. {
  6642. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerCloseTrade()");
  6643.  
  6644. Player* tradePartner = getPlayerByID(player->tradePartner);
  6645.  
  6646. std::vector<Item*>::iterator it;
  6647. if(player->getTradeItem()) {
  6648. std::map<Item*, uint32_t>::iterator it = tradeItems.find(player->getTradeItem());
  6649. if(it != tradeItems.end()) {
  6650. FreeThing(it->first);
  6651. tradeItems.erase(it);
  6652. }
  6653. }
  6654.  
  6655. player->setAcceptTrade(false);
  6656. player->sendTextMessage(MSG_SMALLINFO, "Trade cancelled.");
  6657. player->sendCloseTrade();
  6658.  
  6659. if(tradePartner) {
  6660. if(tradePartner->getTradeItem()) {
  6661. std::map<Item*, uint32_t>::iterator it = tradeItems.find(tradePartner->getTradeItem());
  6662. if(it != tradeItems.end()) {
  6663. FreeThing(it->first);
  6664. tradeItems.erase(it);
  6665. }
  6666. }
  6667.  
  6668. tradePartner->setAcceptTrade(false);
  6669. tradePartner->sendTextMessage(MSG_SMALLINFO, "Trade cancelled.");
  6670. tradePartner->sendCloseTrade();
  6671. }
  6672. }
  6673.  
  6674. void Game::autoCloseTrade(const Item* item, bool itemMoved /*= false*/)
  6675. {
  6676. if(!item)
  6677. return;
  6678.  
  6679. std::map<Item*, uint32_t>::const_iterator it;
  6680. const Container* container = NULL;
  6681. for(it = tradeItems.begin(); it != tradeItems.end(); it++) {
  6682. if(item == it->first ||
  6683. (itemMoved && (container = dynamic_cast<const Container*>(item)) && container->isHoldingItem(it->first)) ||
  6684. ((container = dynamic_cast<const Container*>(it->first)) && container->isHoldingItem(item)))
  6685. {
  6686. Player* player = getPlayerByID(it->second);
  6687. if(player){
  6688. playerCloseTrade(player);
  6689. }
  6690.  
  6691. break;
  6692. }
  6693. }
  6694. }
  6695.  
  6696. void Game::autoCloseAttack(Player* player, Creature* target)
  6697. {
  6698. if((std::abs(player->pos.x - target->pos.x) > 7) ||
  6699. (std::abs(player->pos.y - target->pos.y) > 5) || (player->pos.z != target->pos.z)){
  6700. player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  6701. playerSetAttackedCreature(player, 0);
  6702. }
  6703. }
  6704.  
  6705. void Game::playerSetAttackedCreature(Player* player, uint32_t creatureid)
  6706. {
  6707. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerSetAttackedCreature()");
  6708.  
  6709. if(player->isRemoved)
  6710. return;
  6711.  
  6712. if(player->attackedCreature != 0 && creatureid == 0) {
  6713. player->sendCancelAttacking();
  6714. }
  6715.  
  6716.  
  6717. Creature* attackedCreature = NULL;
  6718. if(creatureid != 0) {
  6719. attackedCreature = getCreatureByID(creatureid);
  6720. }
  6721.  
  6722. Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  6723. bool pvpArena = false, rook = false, attackedIsSummon = false;
  6724.  
  6725. #ifdef YUR_PVP_ARENA
  6726. if (player && attackedCreature)
  6727. {
  6728. Tile *t1 = map->getTile(player->pos), *t2 = map->getTile(attackedCreature->pos);
  6729. pvpArena = t1 && t2 && t1->isPvpArena() && t2->isPvpArena();
  6730. }
  6731. #endif //YUR_PVP_ARENA
  6732.  
  6733. #ifdef YUR_ROOKGARD
  6734. rook = player && player->isRookie() && attackedPlayer && attackedPlayer->isRookie();
  6735. #endif //YUR_ROOKGARD
  6736.  
  6737. #ifdef TR_SUMMONS
  6738. attackedIsSummon = (attackedCreature && attackedCreature->isPlayersSummon() && attackedCreature->getMaster() != player);
  6739. #endif //TR_SUMMONS
  6740.  
  6741. if(!attackedCreature || (attackedCreature->access >= g_config.ACCESS_PROTECT || ((getWorldType() == WORLD_TYPE_NO_PVP || rook) &&
  6742. !pvpArena && player->access < g_config.ACCESS_PROTECT && (dynamic_cast<Player*>(attackedCreature) || attackedIsSummon)))) {
  6743. if(attackedCreature) {
  6744. player->sendTextMessage(MSG_SMALLINFO, "You may not attack this player.");
  6745. }
  6746. player->sendCancelAttacking();
  6747. player->setAttackedCreature(NULL);
  6748. stopEvent(player->eventCheckAttacking);
  6749. player->eventCheckAttacking = 0;
  6750. }
  6751. else if(attackedCreature) {
  6752. player->setAttackedCreature(attackedCreature);
  6753. stopEvent(player->eventCheckAttacking);
  6754. player->eventCheckAttacking = addEvent(makeTask(g_config.getGlobalNumber("firstattack", 2000), std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), player->getID())));
  6755. }
  6756.  
  6757. }
  6758.  
  6759.  
  6760. void Game::flushSendBuffers()
  6761. {
  6762. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::flushSendBuffers()");
  6763.  
  6764. for(std::vector<Player*>::iterator it = BufferedPlayers.begin(); it != BufferedPlayers.end(); ++it) {
  6765. (*it)->flushMsg();
  6766. (*it)->SendBuffer = false;
  6767. (*it)->releaseThing();
  6768. /*
  6769. #ifdef __DEBUG__
  6770. std::cout << "flushSendBuffers() - releaseThing()" << std::endl;
  6771. #endif
  6772. */
  6773. }
  6774. BufferedPlayers.clear();
  6775.  
  6776. //free memory
  6777. for(std::vector<Thing*>::iterator it = ToReleaseThings.begin(); it != ToReleaseThings.end(); ++it){
  6778. (*it)->releaseThing();
  6779. }
  6780. ToReleaseThings.clear();
  6781.  
  6782.  
  6783. return;
  6784. }
  6785.  
  6786. void Game::addPlayerBuffer(Player* p)
  6787. {
  6788. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::addPlayerBuffer()");
  6789.  
  6790. /*
  6791. #ifdef __DEBUG__
  6792. std::cout << "addPlayerBuffer() - useThing()" << std::endl;
  6793. #endif
  6794. */
  6795. if(p->SendBuffer == false){
  6796. p->useThing();
  6797. BufferedPlayers.push_back(p);
  6798. p->SendBuffer = true;
  6799. }
  6800.  
  6801. return;
  6802. }
  6803.  
  6804. void Game::FreeThing(Thing* thing){
  6805.  
  6806. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::FreeThing()");
  6807. //std::cout << "freeThing() " << thing <<std::endl;
  6808. ToReleaseThings.push_back(thing);
  6809.  
  6810. return;
  6811. }
  6812. /*
  6813. ADD
  6814. container(player,pos-cid,thing)
  6815. inventory(player,pos-i,[ignored])
  6816. ground([ignored],postion,thing)
  6817.  
  6818. REMOVE
  6819. container(player,pos-cid,thing,autoclose?)
  6820. inventory(player,pos-i,thing,autoclose?)
  6821. ground([ignored],postion,thing,autoclose?,stackpos)
  6822.  
  6823. UPDATE
  6824. container(player,pos-cid,thing)
  6825. inventory(player,pos-i,[ignored])
  6826. ground([ignored],postion,thing,stackpos)
  6827. */
  6828. void Game::sendAddThing(Player* player,const Position &pos,const Thing* thing){
  6829. if(pos.x == 0xFFFF) {
  6830. if(!player)
  6831. return;
  6832. if(pos.y & 0x40) { //container
  6833. if(!thing)
  6834. return;
  6835.  
  6836. const Item *item = dynamic_cast<const Item*>(thing);
  6837. if(!item)
  6838. return;
  6839.  
  6840. unsigned char containerid = pos.y & 0x0F;
  6841. Container* container = player->getContainer(containerid);
  6842. if(!container)
  6843. return;
  6844.  
  6845. SpectatorVec list;
  6846. SpectatorVec::iterator it;
  6847.  
  6848. Position centerpos = (container->pos.x == 0xFFFF ? player->pos : container->pos);
  6849. getSpectators(Range(centerpos,2,2,2,2,false), list);
  6850.  
  6851. if(!list.empty()) {
  6852. for(it = list.begin(); it != list.end(); ++it) {
  6853. Player *spectator = dynamic_cast<Player*>(*it);
  6854. if(spectator)
  6855. spectator->onItemAddContainer(container,item);
  6856. }
  6857. }
  6858. else
  6859. player->onItemAddContainer(container,item);
  6860.  
  6861. }
  6862. else //inventory
  6863. {
  6864. player->sendInventory(pos.y);
  6865. }
  6866. }
  6867. else //ground
  6868. {
  6869. if(!thing)
  6870. return;
  6871.  
  6872. #ifdef SM_SUMMON_ATTACK
  6873. Monster* monster = dynamic_cast<Monster*>(const_cast<Thing*>(thing));
  6874. #endif //SM_SUMMON_ATTACK
  6875.  
  6876. SpectatorVec list;
  6877. SpectatorVec::iterator it;
  6878.  
  6879. getSpectators(Range(pos,true), list);
  6880.  
  6881. //players
  6882. for(it = list.begin(); it != list.end(); ++it) {
  6883. if(dynamic_cast<Player*>(*it)) {
  6884. (*it)->onThingAppear(thing);
  6885. #ifdef SM_SUMMON_ATTACK
  6886. if (monster && !monster->isSummon())
  6887. monster->onThingAppear(*it);
  6888. #endif //SM_SUMMON_ATTACK
  6889. }
  6890. }
  6891.  
  6892. //none-players
  6893. for(it = list.begin(); it != list.end(); ++it) {
  6894. if(!dynamic_cast<Player*>(*it)) {
  6895. (*it)->onThingAppear(thing);
  6896. }
  6897. }
  6898. }
  6899. }
  6900.  
  6901. void Game::sendRemoveThing(Player* player,const Position &pos,const Thing* thing,const unsigned char stackpos /*=1*/ ,const bool autoclose/* =false*/){
  6902. if(!thing)
  6903. return;
  6904.  
  6905. const Item *item = dynamic_cast<const Item*>(thing);
  6906. bool perform_autoclose = false;
  6907. if(autoclose && item){
  6908. const Container *container = dynamic_cast<const Container*>(item);
  6909. if(container)
  6910. perform_autoclose = true;
  6911. }
  6912.  
  6913. if(pos.x == 0xFFFF) {
  6914. if(!player)
  6915. return;
  6916. if(pos.y & 0x40) { //container
  6917. if(!item)
  6918. return;
  6919.  
  6920. unsigned char containerid = pos.y & 0x0F;
  6921. Container* container = player->getContainer(containerid);
  6922. if(!container)
  6923. return;
  6924.  
  6925. //check that item is in the container
  6926. unsigned char slot = container->getSlotNumberByItem(item);
  6927.  
  6928. SpectatorVec list;
  6929. SpectatorVec::iterator it;
  6930.  
  6931. Position centerpos = (container->pos.x == 0xFFFF ? player->pos : container->pos);
  6932. getSpectators(Range(centerpos,2,2,2,2,false), list);
  6933.  
  6934. if(!list.empty()) {
  6935. for(it = list.begin(); it != list.end(); ++it) {
  6936. Player *spectator = dynamic_cast<Player*>(*it);
  6937. if(spectator){
  6938. spectator->onItemRemoveContainer(container,slot);
  6939. if(perform_autoclose){
  6940. spectator->onThingRemove(thing);
  6941. }
  6942. }
  6943. }
  6944. }
  6945. else{
  6946. player->onItemRemoveContainer(container,slot);
  6947. if(perform_autoclose){
  6948. player->onThingRemove(thing);
  6949. }
  6950. }
  6951.  
  6952. }
  6953. else //inventory
  6954. {
  6955. player->removeItemInventory(pos.y);
  6956. if(perform_autoclose){
  6957. player->onThingRemove(thing);
  6958. }
  6959. }
  6960. }
  6961. else //ground
  6962. {
  6963. SpectatorVec list;
  6964. SpectatorVec::iterator it;
  6965.  
  6966. getSpectators(Range(pos,true), list);
  6967.  
  6968. //players
  6969. for(it = list.begin(); it != list.end(); ++it) {
  6970. Player *spectator = dynamic_cast<Player*>(*it);
  6971. if(spectator) {
  6972. spectator->onThingDisappear(thing,stackpos);
  6973.  
  6974. if(perform_autoclose){
  6975. spectator->onThingRemove(thing);
  6976. }
  6977. }
  6978. }
  6979.  
  6980. //none-players
  6981. for(it = list.begin(); it != list.end(); ++it) {
  6982. if(!dynamic_cast<Player*>(*it)) {
  6983. (*it)->onThingDisappear(thing,stackpos);
  6984. }
  6985. }
  6986. }
  6987. }
  6988.  
  6989. void Game::sendUpdateThing(Player* player,const Position &pos,const Thing* thing,const unsigned char stackpos/*=1*/){
  6990.  
  6991. if(pos.x == 0xFFFF) {
  6992. if(!player)
  6993. return;
  6994. if(pos.y & 0x40) { //container
  6995. if(!thing)
  6996. return;
  6997.  
  6998. const Item *item = dynamic_cast<const Item*>(thing);
  6999. if(!item)
  7000. return;
  7001.  
  7002. unsigned char containerid = pos.y & 0x0F;
  7003. Container* container = player->getContainer(containerid);
  7004. if(!container)
  7005. return;
  7006. //check that item is in the container
  7007. unsigned char slot = container->getSlotNumberByItem(item);
  7008.  
  7009. SpectatorVec list;
  7010. SpectatorVec::iterator it;
  7011.  
  7012. Position centerpos = (container->pos.x == 0xFFFF ? player->pos : container->pos);
  7013. getSpectators(Range(centerpos,2,2,2,2,false), list);
  7014.  
  7015. if(!list.empty()) {
  7016. for(it = list.begin(); it != list.end(); ++it) {
  7017. Player *spectator = dynamic_cast<Player*>(*it);
  7018. if(spectator)
  7019. spectator->onItemUpdateContainer(container,item,slot);
  7020. }
  7021. }
  7022. else{
  7023. //never should be here
  7024. std::cout << "Error: sendUpdateThing" << std::endl;
  7025. //player->onItemUpdateContainer(container,item,slot);
  7026. }
  7027.  
  7028. }
  7029. else //inventory
  7030. {
  7031. player->sendInventory(pos.y);
  7032. }
  7033. }
  7034. else //ground
  7035. {
  7036. if(!thing)
  7037. return;
  7038.  
  7039. SpectatorVec list;
  7040. SpectatorVec::iterator it;
  7041.  
  7042. getSpectators(Range(pos,true), list);
  7043.  
  7044. //players
  7045. for(it = list.begin(); it != list.end(); ++it) {
  7046. if(dynamic_cast<Player*>(*it)) {
  7047. (*it)->onThingTransform(thing,stackpos);
  7048. }
  7049. }
  7050.  
  7051. //none-players
  7052. for(it = list.begin(); it != list.end(); ++it) {
  7053. if(!dynamic_cast<Player*>(*it)) {
  7054. (*it)->onThingTransform(thing,stackpos);
  7055. }
  7056. }
  7057. }
  7058. }
  7059.  
  7060. void Game::addThing(Player* player,const Position &pos,Thing* thing)
  7061. {
  7062. if(!thing)
  7063. return;
  7064. Item *item = dynamic_cast<Item*>(thing);
  7065.  
  7066. if(pos.x == 0xFFFF) {
  7067. if(!player || !item)
  7068. return;
  7069.  
  7070. if(pos.y & 0x40) { //container
  7071. unsigned char containerid = pos.y & 0x0F;
  7072. Container* container = player->getContainer(containerid);
  7073. if(!container)
  7074. return;
  7075.  
  7076. container->addItem(item);
  7077. sendAddThing(player,pos,thing);
  7078. }
  7079. else //inventory
  7080. {
  7081. player->addItemInventory(item,pos.y,true);
  7082. sendAddThing(player,pos,thing);
  7083. }
  7084. }
  7085. else //ground
  7086. {
  7087. if(!thing)
  7088. return;
  7089. //Tile *tile = map->getTile(pos.x, pos.y, pos.z);
  7090. Tile *tile = map->getTile(pos);
  7091. if(tile){
  7092. thing->pos = pos;
  7093. if(item && item->isSplash()){
  7094. if(tile->splash){
  7095. int32_t oldstackpos = tile->getThingStackPos(tile->splash);
  7096. Item *oldsplash = tile->splash;
  7097.  
  7098. oldsplash->isRemoved = true;
  7099. FreeThing(oldsplash);
  7100.  
  7101. tile->splash = item;
  7102.  
  7103. sendUpdateThing(NULL, pos, item, oldstackpos);
  7104. }
  7105. else{
  7106. tile->splash = item;
  7107. sendAddThing(NULL,pos,tile->splash);
  7108. }
  7109. }
  7110. else if(item && item->isGroundTile()){
  7111. tile->ground = item;
  7112.  
  7113. SpectatorVec list;
  7114. SpectatorVec::iterator it;
  7115.  
  7116. getSpectators(Range(thing->pos, true), list);
  7117.  
  7118. //players
  7119. for(it = list.begin(); it != list.end(); ++it) {
  7120. if(dynamic_cast<Player*>(*it)) {
  7121. (*it)->onTileUpdated(pos);
  7122. }
  7123. }
  7124.  
  7125. //none-players
  7126. for(it = list.begin(); it != list.end(); ++it) {
  7127. if(!dynamic_cast<Player*>(*it)) {
  7128. (*it)->onTileUpdated(pos);
  7129. }
  7130. }
  7131.  
  7132. //Game::creatureBroadcastTileUpdated(thing->pos);
  7133. }
  7134. else if(item && item->isStackable()){
  7135. Item *topitem = tile->getTopDownItem();
  7136. if(topitem && topitem->getID() == item->getID() &&
  7137. topitem->getItemCountOrSubtype() + item->getItemCountOrSubtype() <= 100){
  7138. topitem->setItemCountOrSubtype(topitem->getItemCountOrSubtype() + item->getItemCountOrSubtype());
  7139. int32_t stackpos = tile->getThingStackPos(topitem);
  7140. sendUpdateThing(NULL,topitem->pos,topitem,stackpos);
  7141. item->pos.x = 0xFFFF;
  7142. FreeThing(item);
  7143. }
  7144. else{
  7145. tile->addThing(thing);
  7146. sendAddThing(player,pos,thing);
  7147. }
  7148. }
  7149. else{
  7150. tile->addThing(thing);
  7151. sendAddThing(player,pos,thing);
  7152. }
  7153. }
  7154. }
  7155. }
  7156.  
  7157. bool Game::removeThing(Player* player,const Position &pos,Thing* thing, bool setRemoved /*= true*/)
  7158. {
  7159. if(!thing)
  7160. return false;
  7161. Item *item = dynamic_cast<Item*>(thing);
  7162.  
  7163. if(pos.x == 0xFFFF) {
  7164. if(!player || !item)
  7165. return false;
  7166.  
  7167. if(pos.y & 0x40) { //container
  7168. unsigned char containerid = pos.y & 0x0F;
  7169. Container* container = player->getContainer(containerid);
  7170. if(!container)
  7171. return false;
  7172.  
  7173. sendRemoveThing(player,pos,thing,0,true);
  7174. if(!container->removeItem(item))
  7175. return false;
  7176.  
  7177. if(player && player->isHoldingContainer(container)) {
  7178. player->updateInventoryWeigth();
  7179. player->sendStats();
  7180. }
  7181. }
  7182. else //inventory
  7183. {
  7184. //sendRemoveThing(player,pos,thing,0,true);
  7185. if(!player->removeItemInventory(pos.y))
  7186. return false;
  7187. player->onThingRemove(thing);
  7188. //player->removeItemInventory(pos.y,true);
  7189. }
  7190. if(setRemoved)
  7191. item->isRemoved = true;
  7192. return true;
  7193. }
  7194. else //ground
  7195. {
  7196. //Tile *tile = map->getTile(pos.x, pos.y, pos.z);
  7197. Tile *tile = map->getTile(pos);
  7198. if(tile){
  7199. unsigned char stackpos = tile->getThingStackPos(thing);
  7200. if(!tile->removeThing(thing))
  7201. return false;
  7202. sendRemoveThing(NULL,pos,thing,stackpos,true);
  7203. }
  7204. else{
  7205. return false;
  7206. }
  7207. if(item && setRemoved){
  7208. item->isRemoved = true;
  7209. }
  7210. return true;
  7211. }
  7212. }
  7213.  
  7214. Position Game::getThingMapPos(Player *player, const Position &pos)
  7215. {
  7216. if(pos.x == 0xFFFF){
  7217. Position dummyPos(0,0,0);
  7218. if(!player)
  7219. return dummyPos;
  7220. if(pos.y & 0x40) { //from container
  7221. unsigned char containerid = pos.y & 0x0F;
  7222. const Container* container = player->getContainer(containerid);
  7223. if(!container){
  7224. return dummyPos;
  7225. }
  7226. while(container->getParent() != NULL) {
  7227. container = container->getParent();
  7228. }
  7229. if(container->pos.x == 0xFFFF)
  7230. return player->pos;
  7231. else
  7232. return container->pos;
  7233. }
  7234. else //from inventory
  7235. {
  7236. return player->pos;
  7237. }
  7238. }
  7239. else{
  7240. return pos;
  7241. }
  7242. }
  7243.  
  7244. Thing* Game::getThing(const Position &pos,unsigned char stack, Player* player /*=NULL*/)
  7245. {
  7246. if(pos.x == 0xFFFF) {
  7247. if(!player)
  7248. return NULL;
  7249. if(pos.y & 0x40) { //from container
  7250. unsigned char containerid = pos.y & 0x0F;
  7251. Container* container = player->getContainer(containerid);
  7252. if(!container)
  7253. return NULL;
  7254.  
  7255. return container->getItem(pos.z);
  7256. }
  7257. else //from inventory
  7258. {
  7259. return player->getItem(pos.y);
  7260. }
  7261. }
  7262. else //from ground
  7263. {
  7264. //Tile *t = getTile(pos.x, pos.y, pos.z);
  7265. Tile *t = map->getTile(pos);
  7266. if(!t)
  7267. return NULL;
  7268.  
  7269. return t->getThingByStackPos(stack);
  7270. }
  7271. }
  7272. int32_t Game::getDepot(Container* c, int32_t e)
  7273. {
  7274. for(int32_t a = 0; a < c->size(); a++)
  7275. {
  7276. Container* x = dynamic_cast<Container*>(dynamic_cast<Item*>(c->getItem(a)));
  7277. Item* i = dynamic_cast<Item*>(c->getItem(a));
  7278. if(i)
  7279. e++;
  7280. if(x)
  7281. e = getDepot(x, e);
  7282. }
  7283. return e;
  7284. }
  7285.  
  7286.  
  7287. #ifdef WOLV_LOAD_NPC
  7288. bool Game::loadNpcs()
  7289. {
  7290. xmlDocPtr doc;
  7291. doc = xmlParseFile((g_config.DATA_DIR + "world/npc.xml").c_str());
  7292. if (!doc)
  7293. return false;
  7294.  
  7295. xmlNodePtr root, npcNode;
  7296. root = xmlDocGetRootElement(doc);
  7297.  
  7298. if (xmlStrcmp(root->name, (const xmlChar*)"npclist"))
  7299. {
  7300. xmlFreeDoc(doc);
  7301. return false;
  7302. }
  7303.  
  7304. npcNode = root->children;
  7305. while (npcNode)
  7306. {
  7307. if (strcmp((const char*) npcNode->name, "npc") == 0)
  7308. {
  7309. std::string name = (const char*)xmlGetProp(npcNode, (const xmlChar *) "name");
  7310. int32_t x = atoi((const char*) xmlGetProp(npcNode, (const xmlChar*) "x"));
  7311. int32_t y = atoi((const char*) xmlGetProp(npcNode, (const xmlChar*) "y"));
  7312. int32_t z = atoi((const char*) xmlGetProp(npcNode, (const xmlChar*) "z"));
  7313.  
  7314. Npc* mynpc = new Npc(name, this);
  7315. mynpc->pos = Position(x, y, z);
  7316.  
  7317. if (!placeCreature(mynpc->pos, mynpc))
  7318. {
  7319. std::cout << "Could not place " << name << "!" << std::endl;
  7320. xmlFreeDoc(doc);
  7321. return false;
  7322. }
  7323.  
  7324. const char* tmp = (const char*)xmlGetProp(npcNode, (const xmlChar*) "dir");
  7325. if (tmp)
  7326. mynpc->setDirection((Direction)atoi(tmp));
  7327. }
  7328. npcNode = npcNode->next;
  7329. }
  7330.  
  7331. xmlFreeDoc(doc);
  7332. return true;
  7333. }
  7334. #endif //WOLV_LOAD_NPC
  7335.  
  7336. #ifdef TLM_SERVER_SAVE
  7337. void Game::serverSave()
  7338. {
  7339. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::serverSave()");
  7340. std::cout << ":: zapis serwera :: " << std::endl;
  7341. timer();
  7342.  
  7343. AutoList<Player>::listiterator it = Player::listPlayer.list.begin();
  7344. while (it != Player::listPlayer.list.end())
  7345. {
  7346. IOPlayer::instance()->savePlayer(it->second);
  7347. ++it;
  7348. }
  7349. std::cout << ":: Gracze [" << timer() << " s]" << std::endl;
  7350. Guilds::Save();
  7351. std::cout << "Gildie [" << timer() << " s]" << std::endl;
  7352. Houses::Save(this);
  7353. std::cout << ":: Domki [" << timer() << " s]" << std::endl;
  7354. loginQueue.save();
  7355. std::cout << ":: Kolejki [" << timer() << " s]" << std::endl;
  7356.  
  7357. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it);
  7358. }
  7359.  
  7360. void Game::autoServerSave()
  7361. {
  7362. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::autoServerSave()");
  7363. serverSave();
  7364. addEvent(makeTask(g_config.getGlobalNumber("autosave", 1)*60000, std::mem_fun(&Game::autoServerSave)));
  7365. }
  7366. #endif //TLM_SERVER_SAVE
  7367.  
  7368.  
  7369. #ifdef ELEM_VIP_LIST
  7370. /*void Game::vipLogin(Player* player)
  7371. {
  7372. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::vipLogin()");
  7373. std::string vipname = player->getName();
  7374.  
  7375. #ifdef _NG_BBK_VIP_SYSTEM__
  7376. std::transform(vipname.begin(), vipname.end(), vipname.begin(), (int32_t(*)(int32_t)) std::tolower);
  7377. #endif //_NG_BBK_VIP_SYSTEM__
  7378.  
  7379. for(AutoList<Creature>::listiterator cit = listCreature.list.begin(); cit != listCreature.list.end(); ++cit)
  7380. {
  7381. Player* player = dynamic_cast<Player*>((*cit).second);
  7382. if (player)
  7383. player->sendVipLogin(vipname);
  7384. }
  7385. }
  7386.  
  7387. void Game::vipLogout(std::string vipname)
  7388. {
  7389. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::vipLogout()");
  7390.  
  7391. #ifdef _NG_BBK_VIP_SYSTEM__
  7392. std::transform(vipname.begin(), vipname.end(), vipname.begin(), (int32_t(*)(int32_t)) std::tolower);
  7393. #endif //_NG_BBK_VIP_SYSTEM__
  7394.  
  7395. for(AutoList<Creature>::listiterator cit = listCreature.list.begin(); cit != listCreature.list.end(); ++cit)
  7396. {
  7397. Player* player = dynamic_cast<Player*>((*cit).second);
  7398. if (player)
  7399. player->sendVipLogout(vipname);
  7400. }
  7401. }*/
  7402.  
  7403. bool Game::isPlayer(std::string name)
  7404. {
  7405. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::isPlayer()");
  7406. extern xmlMutexPtr xmlmutex;
  7407.  
  7408. std::string datadir = g_config.getGlobalString("datadir");
  7409. std::string filenamecheck = datadir + "players/" + name + ".xml";
  7410. std::transform(filenamecheck.begin(),filenamecheck.end(), filenamecheck.begin(), (int32_t(*)(int32_t))tolower);
  7411.  
  7412. xmlDocPtr doc;
  7413. xmlMutexLock(xmlmutex);
  7414. doc = xmlParseFile(filenamecheck.c_str());
  7415.  
  7416. if (doc)
  7417. {
  7418. xmlMutexUnlock(xmlmutex);
  7419. xmlFreeDoc(doc);
  7420. return true;
  7421. }
  7422. else
  7423. {
  7424. xmlMutexUnlock(xmlmutex);
  7425. xmlFreeDoc(doc);
  7426. return false;
  7427. }
  7428. }
  7429. #endif //ELEM_VIP_LIST
  7430.  
  7431. void Game::checkSpell(Player* player, SpeakClasses type, std::string text)
  7432. {
  7433. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkSpell()");
  7434.  
  7435. if (player->isRookie())
  7436. return;
  7437.  
  7438. #ifdef TLM_HOUSE_SYSTEM
  7439. else if (text == "aleta gom") // edit owner
  7440. {
  7441. Tile* tile = getTile(player->pos);
  7442. House* house = tile? tile->getHouse() : NULL;
  7443.  
  7444. if (house && house->getPlayerRights(player->getName()) == HOUSE_OWNER)
  7445. {
  7446. player->sendHouseWindow(house, player->pos, HOUSE_OWNER);
  7447. }
  7448. else
  7449. {
  7450. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7451. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7452. }
  7453. }
  7454. else if (text == "aleta grav") // edit door owners
  7455. {
  7456. bool last = false;
  7457. for (int32_t x = player->pos.x-1; x <= player->pos.x+1 && !last; x++)
  7458. {
  7459. for(int32_t y = player->pos.y-1; y <= player->pos.y+1 && !last; y++)
  7460. {
  7461. Position doorPos(x, y, player->pos.z);
  7462. Tile* tile = getTile(doorPos);
  7463. House* house = tile? tile->getHouse() : NULL;
  7464.  
  7465. if (house && house->getPlayerRights(doorPos, player->getName()) == HOUSE_OWNER)
  7466. {
  7467. Item *item = dynamic_cast<Item*>(tile->getThingByStackPos(tile->getThingCount()-1));
  7468. if (item && Item::items[item->getID()].isDoor)
  7469. {
  7470. player->sendHouseWindow(house, doorPos, HOUSE_DOOROWNER);
  7471. last = true;
  7472. }
  7473. }
  7474. }
  7475. }
  7476. }
  7477. else if (text == "!buyhouse" || text == "!buyhome")
  7478. {
  7479. uint32_t money = player->getMoney();
  7480. bool last = false;
  7481. #ifdef HUCZU_EXHAUSTED
  7482. if(player->houseTicks > 0){
  7483. player->sendCancel("You're exhausted.");
  7484. return;
  7485. }
  7486. else
  7487. player->houseTicks += 5;
  7488. #endif //HUCZU_EXHAUSTED
  7489. int32_t houselevel = g_config.getGlobalNumber("houselevel", 0);
  7490. if(!player->premmium){
  7491. player->sendCancel("You must have a premium to buy house!");
  7492. return;
  7493. }
  7494. if( player->getLevel() < houselevel ){
  7495. std::stringstream textmsg2;
  7496. textmsg2 << " You need level " << houselevel << "+ to buy a house! ";
  7497. player->sendTextMessage(MSG_ADVANCE, textmsg2.str().c_str());
  7498. }
  7499. else{
  7500.  
  7501. for (int32_t x = player->pos.x-1; x <= player->pos.x+1 && !last; x++)
  7502. {
  7503. for(int32_t y = player->pos.y-1; y <= player->pos.y+1 && !last; y++)
  7504. {
  7505. Position doorPos(x, y, player->pos.z);
  7506. Tile* tile = getTile(doorPos);
  7507. House* house = tile? tile->getHouse() : NULL;
  7508. if(house){
  7509. if(house->getPlayerRights(player->getName()) == HOUSE_OWNER){
  7510. player->sendTextMessage(MSG_ADVANCE, "You own this house.");
  7511. return;
  7512. }
  7513. if(house->isBought()){
  7514. player->sendTextMessage(MSG_ADVANCE, "This house already has an owner.");
  7515. return;
  7516. }
  7517. if(house->checkHouseCount(player) >= g_config.getGlobalNumber("maxhouses", 0)){
  7518. std::stringstream textmsg;
  7519. textmsg << " You cant have more than " << g_config.getGlobalNumber("maxhouses", 1) << " houses ";
  7520. player->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  7521. return;
  7522. }
  7523. if(house->getPlayerRights(doorPos, player->getName()) == HOUSE_NONE && !house->isBought() && house->checkHouseCount(player) < g_config.getGlobalNumber("maxhouses", 1))
  7524. {
  7525. Item *item = dynamic_cast<Item*>(tile->getThingByStackPos(tile->getThingCount()-1));
  7526. long price = g_config.getGlobalNumber("priceforsqm", 0) * house->getHouseSQM(house->getName());
  7527.  
  7528. if (item && Item::items[item->getID()].isDoor && price <= money)
  7529. {
  7530. player->substractMoney(price);
  7531. house->setOwner(player->getName());
  7532. house->save();
  7533. player->sendTextMessage(MSG_ADVANCE, "You bought a house.");
  7534. last = true;
  7535. }
  7536. else{
  7537. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7538. player->sendTextMessage(MSG_SMALLINFO, "You dont have enough money to buy this house.");
  7539. }
  7540. }
  7541. }
  7542. }
  7543. }
  7544. }
  7545. }
  7546. else if (text == "aleta sio") // edit guests
  7547. {
  7548. Tile* tile = getTile(player->pos);
  7549. House* house = tile? tile->getHouse() : NULL;
  7550.  
  7551. if (house && house->getPlayerRights(player->getName()) >= HOUSE_SUBOWNER)
  7552. {
  7553. player->sendHouseWindow(house, player->pos, HOUSE_GUEST);
  7554. }
  7555. else
  7556. {
  7557. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7558. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7559. }
  7560. }
  7561. else if (text == "aleta som") // edit subowners
  7562. {
  7563. Tile* tile = getTile(player->pos);
  7564. House* house = tile? tile->getHouse() : NULL;
  7565.  
  7566. if (house && house->getPlayerRights(player->getName()) == HOUSE_OWNER)
  7567. {
  7568. player->sendHouseWindow(house, player->pos, HOUSE_SUBOWNER);
  7569. }
  7570. else
  7571. {
  7572. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7573. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7574. }
  7575. }
  7576. else if (text == "alana sio") // kick me
  7577. {
  7578. Tile* tile = getTile(player->pos);
  7579. House* house = tile? tile->getHouse() : NULL;
  7580.  
  7581. if (house)
  7582. {
  7583. teleport(player, house->getFrontDoor());
  7584. player->sendMagicEffect(player->pos, NM_ME_ENERGY_AREA);
  7585. }
  7586. else
  7587. {
  7588. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7589. player->sendTextMessage(MSG_SMALLINFO, "You are not in a house.");
  7590. }
  7591. }
  7592. else if (text.substr(0, 11) == "alana sio \"") // kick someone
  7593. {
  7594. Creature* c = getCreatureByName(text.substr(11).c_str());
  7595. Player *target = c? dynamic_cast<Player*>(c) : NULL;
  7596.  
  7597. if (target)
  7598. {
  7599. Tile* tile = getTile(player->pos);
  7600. Tile* targetTile = getTile(target->pos);
  7601. House* house = tile? tile->getHouse() : NULL;
  7602. House* targetHouse = targetTile? targetTile->getHouse() : NULL;
  7603.  
  7604. if (house && targetHouse && house == targetHouse &&
  7605. house->getPlayerRights(player->getName()) >= HOUSE_SUBOWNER)
  7606. {
  7607. Position pos = house->getFrontDoor();
  7608. if (pos.x != 0xFFFF && pos.y != 0xFFFF && pos.z != 0xFF)
  7609. {
  7610. teleport(target, pos);
  7611. player->sendMagicEffect(target->pos, NM_ME_ENERGY_AREA);
  7612. }
  7613. else
  7614. {
  7615. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7616. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7617. }
  7618. }
  7619. else
  7620. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7621. }
  7622. else
  7623. {
  7624. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7625. player->sendTextMessage(MSG_SMALLINFO, "This player does not exist.");
  7626. }
  7627. }
  7628. #endif //TLM_HOUSE_SYSTEM
  7629.  
  7630. #ifdef TR_SUMMONS
  7631. else if (text.substr(0, 11) == "utevo res \"" &&
  7632. (!g_config.LEARN_SPELLS || player->knowsSpell("utevo res")))
  7633. {
  7634. if (player->vocation == VOCATION_DRUID || player->vocation == VOCATION_SORCERER ||
  7635. (g_config.SUMMONS_ALL_VOC && player->vocation != VOCATION_NONE))
  7636. {
  7637. std::string name = text.substr(11);
  7638. int32_t reqMana = Summons::getRequiredMana(name);
  7639. Tile* tile = getTile(player->pos);
  7640.  
  7641. if (!tile)
  7642. {
  7643. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7644. player->sendCancel("Sorry, not possible.");
  7645. }
  7646. else if (reqMana < 0)
  7647. {
  7648. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7649. player->sendCancel("You cannot summon this creature.");
  7650. }
  7651. else if (tile->isPz())
  7652. {
  7653. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7654. player->sendCancel("You cannot summon creatures in protection zone.");
  7655. }
  7656. #ifdef YUR_PVP_ARENA
  7657. else if (tile->isPvpArena())
  7658. {
  7659. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7660. player->sendCancel("You cannot summon creatures on arena.");
  7661. }
  7662. #endif //YUR_PVP_ARENA
  7663. else if (player->getSummonCount() >= g_config.MAX_SUMMONS)
  7664. {
  7665. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7666. player->sendCancel("You cannot have more summons.");
  7667. }
  7668. else if (player->getMana() < reqMana)
  7669. {
  7670. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7671. player->sendCancel("Not enough mana.");
  7672. }
  7673. else if (!placeSummon(player, name))
  7674. {
  7675. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7676. player->sendCancel("Not enough room");
  7677. }
  7678. else
  7679. {
  7680. player->mana -= reqMana;
  7681. player->addManaSpent(reqMana);
  7682. }
  7683. }
  7684. }
  7685. #endif //TR_SUMMONS
  7686.  
  7687. /*
  7688. #ifdef HUCZU_FIX
  7689. else if (text == "exevo flam sio" &&
  7690. (!g_config.LEARN_SPELLS || player->knowsSpell("exevo flam sio")))
  7691. {
  7692. const int32_t REQ_MANA = 200;
  7693.  
  7694. if (player->mana < REQ_MANA)
  7695. {
  7696. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7697. player->sendTextMessage(MSG_SMALLINFO, "Not enough mana.");
  7698. }
  7699.  
  7700. else if (player->maglevel < 15)
  7701. {
  7702. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7703. player->sendTextMessage(MSG_SMALLINFO, "You don't have the required magic level.");
  7704. }
  7705.  
  7706. else if (player->exhaustedTicks >= 1000 && player->access < g_config.ACCESS_PROTECT)
  7707. {
  7708. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7709. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  7710. }
  7711.  
  7712. else if (player->flamTicks != 0 && player->access < g_config.ACCESS_PROTECT)
  7713. {
  7714. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7715. player->sendTextMessage(MSG_SMALLINFO, "Not ready yet.");
  7716. }
  7717.  
  7718. else
  7719. {
  7720. player->flamBool = true;
  7721. player->exhaustedTicks = 2*1000;
  7722. player->sendMagicEffect(player->pos, NM_ME_MAGIC_BLOOD);
  7723. }
  7724. }
  7725. #endif //HUCZU_FIX
  7726. */
  7727.  
  7728. else if (text.substr(0,7) == "exiva \"" &&
  7729. (!g_config.LEARN_SPELLS || player->knowsSpell("exiva")))
  7730. {
  7731. std::string name = text.substr(7);
  7732. Creature *c = getCreatureByName(name);
  7733. if (dynamic_cast<Player*>(c))
  7734. {
  7735. if(player->mana >= 20)
  7736. {
  7737. player->mana -= 20;
  7738. player->addManaSpent(20);
  7739. }
  7740. else if (player->exhaustedTicks >= 1000 && player->access < g_config.ACCESS_PROTECT)
  7741. {
  7742. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7743. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  7744. }
  7745. else
  7746. {
  7747. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7748. player->sendTextMessage(MSG_SMALLINFO, "Not enough mana.");
  7749. return;
  7750. }
  7751.  
  7752.  
  7753. int32_t x = c->pos.x - player->pos.x;
  7754. int32_t y = c->pos.y - player->pos.y;
  7755. int32_t z = c->pos.z - player->pos.z;
  7756. std::stringstream position;
  7757. position << name;
  7758.  
  7759. if(c->access < 3) {
  7760. if((x > 96 && y > 48) || (x > 48 && y > 94) || (x > 74 && y > 74))
  7761. position << " is very far to the south-east.";
  7762. else if((x > 96 && y < -48) || (x > 48 && y < -96) || (x > 74 && y < -74))
  7763. position << " is very far to the north-east.";
  7764. else if((x < -96 && y > 48) || (x < -48 && y > 96) || (x < -74 && y > 74))
  7765. position << " is very far to the south-west.";
  7766. else if((x < -96 && y < -48) || (x < -48 && y < -96) || (x < -74 && y < -74))
  7767. position << " is very far to the north-west.";
  7768.  
  7769. else if((x > 48 && y > 24) || (x > 24 && y > 48) || (x > 36 && y > 36))
  7770. position << " is far to the south-east.";
  7771. else if((x > 48 && y < -24) || (x > 24 && y < -48) || (x > 36 && y < -36))
  7772. position << " is far to the north-east.";
  7773. else if((x < -48 && y > 24) || (x < -24 && y > 48) || (x < -36 && y > 36))
  7774. position << " is far to the south-west.";
  7775. else if((x < -48 && y < -24) || (x < -24 && y < -48) || (x < -36 && y < -36))
  7776. position << " is far to the north-west.";
  7777.  
  7778. else if((x > 6 && y > 12 && z > 0) || (x > 12 && y > 6 && z > 0) || (x > 9 && y > 9 && z > 0))
  7779. position << " is on a lower lvl to the south-east.";
  7780. else if((x > 6 && y < -12 && z > 0) || (x > 12 && y < -6 && z > 0) || (x > 9 && y < -9 && z > 0))
  7781. position << " is on a lower lvl to the north-east.";
  7782. else if((x < -6 && y > 12 && z > 0) || (x < -12 && y > 6 && z > 0) || (x < -9 && y > 9 && z > 0))
  7783. position << " is on a lower lvl to the south-west.";
  7784. else if((x < -6 && y < -12 && z > 0) || (x < -12 && y < -6 && z > 0) || (x < -9 && y < -9 && z > 0))
  7785. position << " is on a lower lvl to the north-west.";
  7786.  
  7787. else if((x > 6 && y > 12 && z < 0) || (x > 12 && y > 6 && z < 0) || (x > 9 && y > 9 && z < 0))
  7788. position << " is on a higher lvl to the south-east.";
  7789. else if((x > 6 && y < -12 && z < 0) || (x > 12 && y < -6 && z < 0) || (x > 9 && y < -9 && z < 0))
  7790. position << " is on a higher lvl to the north-east.";
  7791. else if((x < -6 && y > 12 && z < 0) || (x < -12 && y > 6 && z < 0) || (x < -9 && y > 9 && z < 0))
  7792. position << " is on a higher lvl to the south-west.";
  7793. else if((x < -6 && y < -12 && z < 0) || (x < -12 && y < -6 && z < 0) || (x < -9 && y < -9 && z < 0))
  7794. position << " is on a higher lvl to the north-west.";
  7795.  
  7796. else if((x > 6 && y > 12 && z == 0) || (x > 12 && y > 6 && z == 0) || (x > 9 && y > 9 && z == 0))
  7797. position << " is to the south-east.";
  7798. else if((x > 6 && y < -12 && z == 0) || (x > 12 && y < -6 && z == 0) || (x > 9 && y < -9 && z == 0))
  7799. position << " is to the north-east.";
  7800. else if((x < -6 && y > 12 && z == 0) || (x < -12 && y > 6 && z == 0) || (x < -9 && y > 9 && z == 0))
  7801. position << " is to the south-west.";
  7802. else if((x < -6 && y < -12 && z == 0) || (x < -12 && y < -6 && z == 0) || (x < -9 && y < -9 && z == 0))
  7803. position << " is to the north-west.";
  7804.  
  7805. else if(x > 74)
  7806. position << " is very far to the east.";
  7807. else if(x < -74)
  7808. position << " is very far to the west.";
  7809. else if(y > 74)
  7810. position << " is very far to the south.";
  7811. else if(y < -74)
  7812. position << " is very far to the north.";
  7813.  
  7814. else if(x > 36)
  7815. position << " is far to the east.";
  7816. else if(x < -36)
  7817. position << " is far to the west.";
  7818. else if(y > 36)
  7819. position << " is far to the south.";
  7820. else if(y < -36)
  7821. position << " is far to the north.";
  7822.  
  7823. else if(x > 3 && z < 0)
  7824. position << " is on a higher lvl to the east.";
  7825. else if(x < -3 && z < 0)
  7826. position << " is on a higher lvl to the west.";
  7827. else if(y > 3 && z < 0)
  7828. position << " is on a higher lvl to the south.";
  7829. else if(y < -3 && z < 0)
  7830. position << " is on a higher lvl to the north.";
  7831.  
  7832. else if(x > 3 && z > 0)
  7833. position << " is on a lower lvl to the east.";
  7834. else if(x < -3 && z > 0)
  7835. position << " is on a lower lvl to the west.";
  7836. else if(y > 3 && z > 0)
  7837. position << " is on a lower lvl to the south.";
  7838. else if(y < -3 && z > 0)
  7839. position << " is on a lower lvl to the north.";
  7840.  
  7841. else if(x > 3 && z == 0)
  7842. position << " is to the east.";
  7843. else if(x < -3 && z == 0)
  7844. position << " is to the west.";
  7845. else if(y > 3 && z == 0)
  7846. position << " is to the south.";
  7847. else if(y < -3 && z == 0)
  7848. position << " is to the north.";
  7849.  
  7850. else if(x < 4 && y < 4 && z > 0)
  7851. position << " is below you.";
  7852. else if(x < 4 && y < 4 && z < 0)
  7853. position << " is above you.";
  7854. else
  7855. position << " is just beside you.";
  7856.  
  7857. player->sendTextMessage(MSG_INFO, position.str().c_str());
  7858. player->sendMagicEffect(player->pos, NM_ME_MAGIC_ENERGIE);
  7859. }else{
  7860. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7861. player->sendTextMessage(MSG_SMALLINFO, "Srry, you cant exiva GM's");
  7862. }
  7863. }else
  7864. player->sendTextMessage(MSG_SMALLINFO, "This player is not online.");
  7865. }
  7866.  
  7867. else if (text == "exani tera" &&
  7868. (!g_config.LEARN_SPELLS || player->knowsSpell("exani tera")))
  7869. {
  7870. const int32_t REQ_MANA = 20;
  7871. Tile* tile = getTile(player->pos);
  7872.  
  7873. if (!(tile && (tile->ground->getID() == ITEM_ROPE_SPOT1 || tile->ground->getID() == ITEM_ROPE_SPOT2)))
  7874. {
  7875. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7876. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7877. }
  7878. else if (player->mana < REQ_MANA)
  7879. {
  7880. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7881. player->sendTextMessage(MSG_SMALLINFO, "Not enough mana.");
  7882. }
  7883. else if (player->maglevel < 0)
  7884. {
  7885. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7886. player->sendTextMessage(MSG_SMALLINFO, "You don't have the required magic level.");
  7887. }
  7888. else if (player->exhaustedTicks >= 1000 && player->access < g_config.ACCESS_PROTECT)
  7889. {
  7890. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7891. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  7892. }
  7893. else
  7894. {
  7895. teleport(player, Position(player->pos.x, player->pos.y+1, player->pos.z-1));
  7896. player->sendMagicEffect(player->pos, NM_ME_ENERGY_AREA);
  7897.  
  7898. if (player->access < g_config.ACCESS_PROTECT)
  7899. {
  7900. player->mana -= REQ_MANA;
  7901. player->addManaSpent(REQ_MANA);
  7902. }
  7903. }
  7904. }
  7905. }
  7906.  
  7907. #ifdef TR_SUMMONS
  7908. bool Game::placeSummon(Player* p, const std::string& name)
  7909. {
  7910. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::placeSummon()");
  7911. Monster* monster = Monster::createMonster(name, this);
  7912.  
  7913. if(!monster)
  7914. return false;
  7915.  
  7916. Position pos = p->pos;
  7917. switch (p->direction)
  7918. {
  7919. case NORTH: pos.y--; break;
  7920. case SOUTH: pos.y++; break;
  7921. case EAST: pos.x++; break;
  7922. case WEST: pos.x--; break;
  7923. }
  7924.  
  7925. Tile* tile = getTile(pos);
  7926. #ifdef YUR_PVP_ARENA
  7927. if (!tile || tile->isPz() || tile->isPvpArena() || !placeCreature(pos, monster))
  7928. #else
  7929. if (!tile || tile->isPz() || !placeCreature(pos, monster))
  7930. #endif //YUR_PVP_ARENA
  7931. {
  7932. delete monster;
  7933. return false;
  7934. }
  7935. else
  7936. {
  7937. p->addSummon(monster);
  7938. return true;
  7939. }
  7940. }
  7941. #endif //TR_SUMMONS
  7942.  
  7943.  
  7944. #ifdef TRS_GM_INVISIBLE
  7945. void Game::creatureBroadcastTileUpdated(const Position& pos)
  7946. {
  7947. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureBroadcastTileUpdated()");
  7948. SpectatorVec list;
  7949. SpectatorVec::iterator it;
  7950. getSpectators(Range(pos, true), list);
  7951.  
  7952. //players
  7953. for(it = list.begin(); it != list.end(); ++it) {
  7954. if(dynamic_cast<Player*>(*it)) {
  7955. (*it)->onTileUpdated(pos);
  7956. }
  7957. }
  7958.  
  7959. //none-players
  7960. for(it = list.begin(); it != list.end(); ++it) {
  7961. if(!dynamic_cast<Player*>(*it)) {
  7962. (*it)->onTileUpdated(pos);
  7963. }
  7964. }
  7965. }
  7966. #endif //TRS_GM_INVISIBLE
  7967.  
  7968.  
  7969. #ifdef HUCZU_SKULLS
  7970. void Game::Skull(Player* player)
  7971. {
  7972. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::Skull()");
  7973. if (player)
  7974. {
  7975. SpectatorVec list;
  7976. SpectatorVec::iterator it;
  7977. getSpectators(Range(player->pos, true), list);
  7978.  
  7979. for(it = list.begin(); it != list.end(); ++it)
  7980. {
  7981. Player* spectator = dynamic_cast<Player*>(*it);
  7982. if(spectator)
  7983. if(player->skullType == SKULL_NONE ||
  7984. player->skullType == SKULL_WHITE ||
  7985. player->skullType == SKULL_RED ||
  7986. player->skullType == SKULL_YELLOW && player->isYellowTo(spectator))
  7987. spectator->onSkull(player);
  7988. }
  7989. }
  7990. }
  7991.  
  7992. void Game::onPvP(Creature* creature, Creature* attacked, bool murder)
  7993. {
  7994. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::onPvP()");
  7995. if (creature && creature->getMaster())
  7996. creature = creature->getMaster(); // pk-ing with summons fix
  7997.  
  7998. Player* player = dynamic_cast<Player*>(creature);
  7999. Player* attackedPlayer = dynamic_cast<Player*>(attacked);
  8000.  
  8001. if (player == attackedPlayer)
  8002. return;
  8003. if(!player || !attackedPlayer)
  8004. return;
  8005. if (player && player->access >= g_config.ACCESS_PROTECT || attackedPlayer && attackedPlayer->access >= g_config.ACCESS_PROTECT)
  8006. return;
  8007. if (player->party != 0 && attackedPlayer->party != 0 && player->party == attackedPlayer->party)
  8008. return;
  8009.  
  8010. Tile *p1 = map->getTile(player->pos), *p2 = map->getTile(attackedPlayer->pos);
  8011. if (p1->isPvpArena() && p2->isPvpArena()){
  8012. player->pzLocked = false;
  8013. attackedPlayer->pzLocked = false;
  8014. return;
  8015. }
  8016.  
  8017.  
  8018. player->pzLocked = true;
  8019.  
  8020. if (!murder)
  8021. {
  8022. if(!player->hasAttacked(attackedPlayer)){
  8023. player->attackedPlayers.push_back(attackedPlayer);
  8024. }
  8025.  
  8026. if (attackedPlayer->skullType == SKULL_NONE || attackedPlayer->skullType == SKULL_YELLOW && !attackedPlayer->isYellowTo(player))
  8027. {
  8028. if (player->skullType != SKULL_RED && player->skullType != SKULL_WHITE)
  8029. {
  8030. player->skullType = SKULL_WHITE;
  8031. Skull(player);
  8032. }
  8033. }
  8034.  
  8035. else if(attackedPlayer->skullType == SKULL_WHITE || attackedPlayer->skullType == SKULL_RED)
  8036. {
  8037. if(player->skullType == SKULL_NONE && !player->isYellowTo(attackedPlayer))//si no tiene skull y no es yellow, tenemos que ponerle yellow.
  8038. {
  8039. if(!attackedPlayer->hasAttacked(player))
  8040. {
  8041. player->skullType = SKULL_YELLOW;
  8042. attackedPlayer->hasAsYellow.push_back(player);
  8043. attackedPlayer->onSkull(player);
  8044. }
  8045. }
  8046. }
  8047. if(player->inFightTicks < (int32_t)g_config.PZ_LOCKED)
  8048. player->inFightTicks = (int32_t)g_config.PZ_LOCKED;
  8049. if(player->skullTicks < (int32_t)g_config.PZ_LOCKED)
  8050. player->skullTicks = (int32_t)g_config.PZ_LOCKED;
  8051.  
  8052. }
  8053. else // murder
  8054. {
  8055. 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.
  8056. {
  8057. player->skullKills++;
  8058. std::string justice(std::string("Warning! The murder of ") + attackedPlayer->getName() + " was not justified!");
  8059. player->sendTextMessage(MSG_RED_INFO, justice.c_str());
  8060.  
  8061. if (player->skullKills >= g_config.BAN_UNJUST)
  8062. {
  8063. banPlayer(player, "Excessive unjustifed player killing", "AccountBan", "Zagan Square 2.3 2011 (Braviera)", false);
  8064. }
  8065.  
  8066. if (player->skullKills >= g_config.RED_UNJUST)
  8067. {
  8068. player->skullType = SKULL_RED;
  8069. if(player->skullTicks < g_config.RED_TIME)
  8070. player->skullTicks = g_config.RED_TIME;
  8071. if(player->inFightTicks < g_config.WHITE_TIME)
  8072. player->inFightTicks = g_config.WHITE_TIME;
  8073. Skull(player);
  8074. }
  8075. else
  8076. {
  8077. player->skullType = SKULL_WHITE;
  8078. if(player->skullTicks < g_config.WHITE_TIME)
  8079. player->skullTicks = g_config.WHITE_TIME;
  8080. if(player->inFightTicks < g_config.WHITE_TIME)
  8081. player->inFightTicks = g_config.WHITE_TIME;
  8082. Skull(player);
  8083. }
  8084. }
  8085.  
  8086. else if (attackedPlayer->skullType == SKULL_RED)//victim had red skull..(fair kill)
  8087. {
  8088. if(player->inFightTicks < g_config.WHITE_TIME)
  8089. player->inFightTicks = g_config.WHITE_TIME;//not giving him a skull.. just setting the murder time.
  8090. }
  8091.  
  8092. else if (attackedPlayer->skullType == SKULL_WHITE) //victim had white skull.. (fair kill)
  8093. {
  8094. attackedPlayer->skullType = SKULL_NONE;
  8095. attackedPlayer->skullTicks = 0;
  8096. Skull(attackedPlayer);
  8097. if(player->inFightTicks < g_config.WHITE_TIME)
  8098. player->inFightTicks = g_config.WHITE_TIME;//not giving him a skull.. just setting the murder time.
  8099. }
  8100.  
  8101. else if (attackedPlayer->skullType == SKULL_YELLOW /*&& attackedPlayer->isYellowTo(player)*/)//el que murio era yellow skull para el que lo mato.
  8102. {
  8103. attackedPlayer->skullType = SKULL_NONE;
  8104. attackedPlayer->skullTicks = 0;
  8105. attackedPlayer->inFightTicks = 0;
  8106. Skull(attackedPlayer);
  8107. if(player->inFightTicks < g_config.WHITE_TIME)
  8108. player->inFightTicks = g_config.WHITE_TIME;
  8109. }
  8110. //attackedPlayer->clearAttacked();//czyszczenie listy zaatakowanych
  8111. //player->removeFromYellowList(attackedPlayer);//usuwanie gracza z Yellow skull z listy atakowanych z ys
  8112. //attackedPlayer->removeFromYellowList(player);
  8113. }
  8114. }
  8115.  
  8116. void Game::LeaveParty(Player *player)
  8117. {
  8118. int32_t members = 0;
  8119. std::stringstream bericht1;
  8120. bericht1 << player->getName() << " has left the party";
  8121. if(player->getID() == player->party)
  8122. {
  8123. disbandParty(player->party);
  8124. return;
  8125. }
  8126. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  8127. {
  8128. if((*it).second->party == player->party)
  8129. {
  8130. members++;
  8131. if((*it).second->getID() != player->getID())
  8132. (*it).second->sendTextMessage(MSG_INFO, bericht1.str().c_str());
  8133. (*it).second->onPartyIcons(player, 0, false, true);
  8134. player->onPartyIcons((*it).second, 0, false, true);
  8135. }
  8136. }
  8137. if(members <= 2)
  8138. {
  8139. disbandParty(player->party);
  8140. return;
  8141. }
  8142. player->sendTextMessage(MSG_INFO, "You have left the party.");
  8143. player->party = 0;
  8144. }
  8145.  
  8146. void Game::disbandParty(uint32_t partyID)
  8147. {
  8148. for(AutoList<Player>::listiterator cit = Player::listPlayer.list.begin(); cit != Player::listPlayer.list.end(); ++cit)
  8149. {
  8150. if((*cit).second->party == partyID)
  8151. {
  8152. (*cit).second->party = 0;
  8153. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  8154. {
  8155. (*cit).second->onPartyIcons((*it).second, 0, false, true);
  8156. if((*it).second->skullType == SKULL_NONE ||
  8157. (*it).second->skullType == SKULL_WHITE ||
  8158. (*it).second->skullType == SKULL_RED ||
  8159. (*it).second->skullType == SKULL_YELLOW &&
  8160. (*it).second->isYellowTo((*cit).second))
  8161. (*cit).second->onSkull((*it).second);
  8162. }
  8163. (*cit).second->sendTextMessage(MSG_INFO, "Your party has been disbanded.");
  8164. }
  8165. }
  8166. }
  8167. void Game::checkSkullTime(Player* player)
  8168. {
  8169. if(player->skullType == SKULL_NONE)//just in case
  8170. return;
  8171.  
  8172. if(player->skullTicks < player->inFightTicks)
  8173. player->skullTicks = player->inFightTicks;
  8174.  
  8175. if(player->skullType != SKULL_RED && player->skullTicks > player->inFightTicks) //we don't want to do that if the player has a red skull...
  8176. player->inFightTicks = player->skullTicks;
  8177.  
  8178. }
  8179. #endif //HUCZU_SKULLS
  8180.  
  8181.  
  8182.  
  8183. #ifdef SD_BURST_ARROW
  8184. class MagicEffectAreaNoExhaustionClass: public MagicEffectAreaClass {
  8185. public:
  8186. bool causeExhaustion(bool hasTarget) const { return false; }
  8187. };
  8188.  
  8189. void Game::burstArrow(Creature* c, const Position& pos)
  8190. {
  8191. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::burstArrow()");
  8192. std::vector<unsigned char> col;
  8193. MagicEffectAreaNoExhaustionClass runeAreaSpell;
  8194.  
  8195. Player* player = dynamic_cast<Player*>(c);
  8196.  
  8197. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8198. runeAreaSpell.animationEffect = NM_ANI_BURSTARROW;
  8199. runeAreaSpell.hitEffect = NM_ME_EXPLOSION_DAMAGE;
  8200. runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8201. runeAreaSpell.animationColor = 198; //DAMAGE_FIRE;
  8202. runeAreaSpell.drawblood = true;
  8203. runeAreaSpell.offensive = true;
  8204.  
  8205. /* Area of Spell */
  8206. col.push_back(1);
  8207. col.push_back(1);
  8208. col.push_back(1);
  8209. runeAreaSpell.areaVec.push_back(col);
  8210. col.clear();
  8211. col.push_back(1);
  8212. col.push_back(1);
  8213. col.push_back(1);
  8214. runeAreaSpell.areaVec.push_back(col);
  8215. col.clear();
  8216. col.push_back(1);
  8217. col.push_back(1);
  8218. col.push_back(1);
  8219. runeAreaSpell.areaVec.push_back(col);
  8220.  
  8221. /* hard no ? */
  8222. runeAreaSpell.direction = 1;
  8223.  
  8224. if (player->vocation == VOCATION_KNIGHT) {
  8225. 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);
  8226. 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);
  8227. }
  8228.  
  8229. if (player->vocation == VOCATION_PALADIN) {
  8230. 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);
  8231. 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);
  8232. }
  8233.  
  8234. if (player->vocation == VOCATION_DRUID) {
  8235. 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);
  8236. 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);
  8237. }
  8238.  
  8239. if (player->vocation == VOCATION_SORCERER) {
  8240. 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);
  8241. 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);
  8242. }
  8243.  
  8244. creatureThrowRune(c, pos, runeAreaSpell);
  8245. }
  8246. #endif //SD_BURST_ARROW
  8247.  
  8248.  
  8249. #ifdef YUR_SHUTDOWN
  8250. void Game::sheduleShutdown(int32_t minutes)
  8251. {
  8252. if (minutes > 0)
  8253. checkShutdown(minutes);
  8254. }
  8255.  
  8256. void Game::checkShutdown(int32_t minutes)
  8257. {
  8258. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkShutdown()");
  8259. if (minutes == 0)
  8260. {
  8261. setGameState(GAME_STATE_CLOSED);
  8262. while (!Player::listPlayer.list.empty())
  8263. Player::listPlayer.list.begin()->second->kickPlayer();
  8264.  
  8265. serverSave();
  8266. std::cout << "==| shutdown..." << std::endl;
  8267. //setGameState(GAME_STATE_SHUTDOWN);
  8268. OTSYS_SLEEP(1000);
  8269. exit(1);
  8270. }
  8271. else
  8272. {
  8273. std::stringstream msg;
  8274. msg << "Server going to shutdown in " << minutes << (minutes>1? " minutes. \n Please logout." : " minute. \n Please logout.") << std::ends;
  8275.  
  8276. AutoList<Player>::listiterator it = Player::listPlayer.list.begin();
  8277. while (it != Player::listPlayer.list.end())
  8278. {
  8279. (*it).second->sendTextMessage(MSG_RED_INFO, msg.str().c_str());
  8280. ++it;
  8281. }
  8282.  
  8283. addEvent(makeTask(60000, boost::bind(&Game::checkShutdown, this, minutes - 1)));
  8284. }
  8285. }
  8286. #endif //YUR_SHUTDOWN
  8287.  
  8288.  
  8289. #ifdef YUR_CMD_EXT
  8290. void Game::setMaxPlayers(uint32_t newmax)
  8291. {
  8292. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::setMaxPlayers()");
  8293. max_players = newmax;
  8294. Status::instance()->playersmax = newmax;
  8295. }
  8296. #endif //YUR_CMD_EXT
  8297.  
  8298. long Game::cleanMap()
  8299. {
  8300. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::cleanMap()");
  8301. return map->clean();
  8302. }
  8303.  
  8304. long Game::beforeClean()
  8305. {
  8306. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it) {
  8307. it->second->sendTextMessage(MSG_RED_INFO, "1 minute to clean. Get your things from floor now!");
  8308. }
  8309. addEvent(makeTask(60000, std::mem_fun(&Game::secondsToClean)));
  8310. }
  8311. long Game::beforeCleanTrzy()
  8312. {
  8313. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it) {
  8314. it->second->sendTextMessage(MSG_RED_INFO, "Warning! Clean in 3 minutes.");
  8315. }
  8316. addEvent(makeTask(60000, std::mem_fun(&Game::beforeCleanDwa)));
  8317. }
  8318. long Game::beforeCleanDwa()
  8319. {
  8320. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it) {
  8321. it->second->sendTextMessage(MSG_RED_INFO, "Warning! Clean in 2 minutes.");
  8322. }
  8323. addEvent(makeTask(60000, std::mem_fun(&Game::beforeClean)));
  8324. }
  8325. void Game::secondsToClean()
  8326. {
  8327. autocleanMap(5);
  8328. }
  8329. void Game::autocleanMap(int32_t seconds)
  8330. {
  8331. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::autocleanMap()");
  8332. if (seconds == 0)
  8333. {
  8334. std::cout << ":: auto clean... ";
  8335. timer();
  8336. long count = cleanMap();
  8337. double sec = timer();
  8338.  
  8339. std::stringstream msg;
  8340. msg << "Clean completed. Collected " << count << (count==1? " item." : " items.") << std::ends;
  8341. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  8342. if(dynamic_cast<Player*>(it->second))
  8343. (*it).second->sendTextMessage(MSG_RED_INFO, msg.str().c_str());
  8344. }
  8345.  
  8346. std::cout << "ok (" << timer() << "s)" << std::endl;
  8347. addEvent(makeTask((g_config.getGlobalNumber("autoclean", 2))*60000, std::mem_fun(&Game::beforeCleanTrzy)));
  8348. }
  8349. else
  8350. {
  8351. std::stringstream msg;
  8352. msg << "Clean in " << seconds << std::ends;
  8353.  
  8354. AutoList<Player>::listiterator it = Player::listPlayer.list.begin();
  8355. while (it != Player::listPlayer.list.end())
  8356. {
  8357. (*it).second->sendTextMessage(MSG_RED_INFO, msg.str().c_str());
  8358. ++it;
  8359. }
  8360.  
  8361. addEvent(makeTask(8000, boost::bind(&Game::autocleanMap, this, seconds - 1)));
  8362. }
  8363. }
  8364.  
  8365.  
  8366. #ifdef CVS_DAY_CYCLE
  8367. void Game::creatureChangeLight(Player* player, int32_t time, unsigned char lightlevel, unsigned char lightcolor)
  8368. {
  8369. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureChangeLight()");
  8370.  
  8371. player->setLightLevel(lightlevel, lightcolor);
  8372. SpectatorVec list;
  8373. getSpectators(Range(player->pos), list);
  8374.  
  8375. for (SpectatorVec::iterator iter = list.begin(); iter != list.end(); ++iter)
  8376. {
  8377. Player* spectator = dynamic_cast<Player*>(*iter);
  8378. if (spectator)
  8379. spectator->sendPlayerLightLevel(player);
  8380. }
  8381. }
  8382.  
  8383. void Game::checkLight(int32_t t)
  8384. {
  8385. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkLight()");
  8386. addEvent(makeTask(10000, boost::bind(&Game::checkLight, this, 10000)));
  8387.  
  8388. light_hour = light_hour + light_hour_delta;
  8389. if(light_hour > 1440)
  8390. light_hour = light_hour - 1440;
  8391.  
  8392. if(std::abs(light_hour - SUNRISE) < 2*light_hour_delta){
  8393. light_state = LIGHT_STATE_SUNRISE;
  8394. }
  8395. else if(std::abs(light_hour - SUNSET) < 2*light_hour_delta){
  8396. light_state = LIGHT_STATE_SUNSET;
  8397. }
  8398.  
  8399. int32_t newlightlevel = lightlevel;
  8400. switch(light_state){
  8401. case LIGHT_STATE_SUNRISE:
  8402. newlightlevel += (LIGHT_LEVEL_DAY - LIGHT_LEVEL_NIGHT)/30;
  8403. break;
  8404. case LIGHT_STATE_SUNSET:
  8405. newlightlevel -= (LIGHT_LEVEL_DAY - LIGHT_LEVEL_NIGHT)/30;
  8406. break;
  8407. }
  8408.  
  8409. if(newlightlevel <= LIGHT_LEVEL_NIGHT){
  8410. lightlevel = LIGHT_LEVEL_NIGHT;
  8411. light_state = LIGHT_STATE_NIGHT;
  8412. }
  8413. else if(newlightlevel >= LIGHT_LEVEL_DAY){
  8414. lightlevel = LIGHT_LEVEL_DAY;
  8415. light_state = LIGHT_STATE_DAY;
  8416. }
  8417. else{
  8418. lightlevel = newlightlevel;
  8419. }
  8420.  
  8421.  
  8422. // status, ten kod i tak jest brzydki
  8423. uint64_t time = OTSYS_TIME();
  8424. ofstream file;
  8425. file.open ("status");
  8426. file << time << " " << (time - Status::instance()->start)/1000 << " " << Status::instance()->playersonline << " " << Status::instance()->playersmax;
  8427. file.close();
  8428.  
  8429. file.open("online");
  8430. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  8431. std::string txt = (*it).second->getName();
  8432. file << (*it).second->getName() << ";" << (*it).second->getLevel() << "\n";
  8433. }
  8434. file.close();
  8435.  
  8436.  
  8437. }
  8438.  
  8439. unsigned char Game::getLightLevel(){
  8440. return lightlevel;
  8441. }
  8442. #endif //CVS_DAY_CYCLE
  8443.  
  8444.  
  8445. #ifdef WANDS_JIDDO
  8446. void Game::useWand(Creature *creature, Creature *attackedCreature, int32_t wandid) {
  8447.  
  8448. Player *player = dynamic_cast<Player*>(creature);
  8449. if(!player) return;
  8450.  
  8451. if((wandid == 5318 && (player->vocation == VOCATION_DRUID) && player->mana >= 15 && player->getLevel() >= 65)) { //Quagmire rod
  8452. int32_t dist = 6;
  8453. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8454. std::vector<unsigned char> col;
  8455. MagicEffectAreaClass runeAreaSpell;
  8456. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8457. runeAreaSpell.animationEffect = NM_ANI_SNOWBALL;
  8458. runeAreaSpell.hitEffect = NM_ME_LOOSE_ENERGY;
  8459. runeAreaSpell.areaEffect = NM_ME_DRAW_BLOOD;
  8460. runeAreaSpell.animationColor = 0x47;
  8461. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8462. col.push_back(0);
  8463. col.push_back(0);
  8464. col.push_back(0);
  8465. runeAreaSpell.areaVec.push_back(col);
  8466. col.clear();
  8467. col.push_back(0);
  8468. col.push_back(1);
  8469. col.push_back(0);
  8470. runeAreaSpell.areaVec.push_back(col);
  8471. col.clear();
  8472. col.push_back(0);
  8473. col.push_back(0);
  8474. col.push_back(0);
  8475. runeAreaSpell.areaVec.push_back(col);
  8476. col.clear();
  8477. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 70; runeAreaSpell.maxDamage = 150;
  8478. long tempExhaust = player->exhaustedTicks;
  8479. player->exhaustedTicks = 0;
  8480. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8481. player->exhaustedTicks = tempExhaust;
  8482. int32_t mana = 15;
  8483. player->addManaSpent(mana);
  8484. player->mana -= mana;
  8485. return;
  8486. }
  8487.  
  8488.  
  8489. if((wandid == 5319 && (player->vocation == VOCATION_SORCERER) && player->mana >= 15 && player->getLevel() >= 65)) { //Wand of cosmic energy
  8490. int32_t dist = 6;
  8491. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8492. std::vector<unsigned char> col;
  8493. MagicEffectAreaClass runeAreaSpell;
  8494. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8495. runeAreaSpell.animationEffect = NM_ANI_LARGEROCK;
  8496. runeAreaSpell.hitEffect = NM_ME_SOUND_WHITE;
  8497. runeAreaSpell.areaEffect = NM_ME_SOUND_WHITE;
  8498. runeAreaSpell.animationColor = 0xAC;
  8499. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8500. col.push_back(0);
  8501. col.push_back(0);
  8502. col.push_back(0);
  8503. runeAreaSpell.areaVec.push_back(col);
  8504. col.clear();
  8505. col.push_back(0);
  8506. col.push_back(1);
  8507. col.push_back(0);
  8508. runeAreaSpell.areaVec.push_back(col);
  8509. col.clear();
  8510. col.push_back(0);
  8511. col.push_back(0);
  8512. col.push_back(0);
  8513. runeAreaSpell.areaVec.push_back(col);
  8514. col.clear();
  8515. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 70; runeAreaSpell.maxDamage = 150;
  8516. long tempExhaust = player->exhaustedTicks;
  8517. player->exhaustedTicks = 0;
  8518. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8519. player->exhaustedTicks = tempExhaust;
  8520. int32_t mana = 15;
  8521. player->addManaSpent(mana);
  8522. player->mana -= mana;
  8523. return;
  8524. }
  8525.  
  8526. //SCEPTRE OF THE LOST SOULS
  8527. if((wandid == 5326 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_DRUID) && player->mana >= 50 && player->getLevel() >= 300)) {
  8528. int32_t dist = 4;
  8529. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8530. std::vector<unsigned char> col;
  8531. MagicEffectAreaClass runeAreaSpell;
  8532. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8533. runeAreaSpell.animationEffect = NM_ANI_ENERGY2;
  8534. runeAreaSpell.hitEffect = NM_ME_ENERGY_AREA;
  8535. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8536. runeAreaSpell.animationColor = 0x65;
  8537. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8538. col.push_back(0);
  8539. col.push_back(0);
  8540. col.push_back(0);
  8541. runeAreaSpell.areaVec.push_back(col);
  8542. col.clear();
  8543. col.push_back(0);
  8544. col.push_back(1);
  8545. col.push_back(0);
  8546. runeAreaSpell.areaVec.push_back(col);
  8547. col.clear();
  8548. col.push_back(0);
  8549. col.push_back(0);
  8550. col.push_back(0);
  8551. runeAreaSpell.areaVec.push_back(col);
  8552. col.clear();
  8553. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 350; runeAreaSpell.maxDamage = 450;
  8554. long tempExhaust = player->exhaustedTicks;
  8555. player->exhaustedTicks = 0;
  8556. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8557. player->exhaustedTicks = tempExhaust;
  8558. int32_t mana = 50;
  8559. player->addManaSpent(mana);
  8560. player->mana -= mana;
  8561. return;
  8562. }
  8563.  
  8564. //NATURE WAND
  8565. if((wandid == 2544 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_DRUID) && player->mana >= 35 && player->getLevel() >= 200)) {
  8566. int32_t dist = 5;
  8567. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8568. std::vector<unsigned char> col;
  8569. MagicEffectAreaClass runeAreaSpell;
  8570. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8571. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8572. runeAreaSpell.hitEffect = 20;
  8573. runeAreaSpell.areaEffect = 20;
  8574. runeAreaSpell.animationColor = 0x60;
  8575. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8576. col.push_back(0);
  8577. col.push_back(0);
  8578. col.push_back(0);
  8579. runeAreaSpell.areaVec.push_back(col);
  8580. col.clear();
  8581. col.push_back(0);
  8582. col.push_back(1);
  8583. col.push_back(0);
  8584. runeAreaSpell.areaVec.push_back(col);
  8585. col.clear();
  8586. col.push_back(0);
  8587. col.push_back(0);
  8588. col.push_back(0);
  8589. runeAreaSpell.areaVec.push_back(col);
  8590. col.clear();
  8591. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 200; runeAreaSpell.maxDamage = 350;
  8592. long tempExhaust = player->exhaustedTicks;
  8593. player->exhaustedTicks = 0;
  8594. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8595. player->exhaustedTicks = tempExhaust;
  8596. int32_t mana = 35;
  8597. player->addManaSpent(mana);
  8598. player->mana -= mana;
  8599. return;
  8600. }
  8601.  
  8602. //SPRITE WAND
  8603. if((wandid == 2453 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_DRUID) && player->mana >= 25 && player->getLevel() >= 150)) {
  8604. int32_t dist = 5;
  8605. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8606. std::vector<unsigned char> col;
  8607. MagicEffectAreaClass runeAreaSpell;
  8608. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8609. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8610. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8611. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8612. runeAreaSpell.animationColor = 0x11;
  8613. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8614. col.push_back(0);
  8615. col.push_back(0);
  8616. col.push_back(0);
  8617. runeAreaSpell.areaVec.push_back(col);
  8618. col.clear();
  8619. col.push_back(0);
  8620. col.push_back(1);
  8621. col.push_back(0);
  8622. runeAreaSpell.areaVec.push_back(col);
  8623. col.clear();
  8624. col.push_back(0);
  8625. col.push_back(0);
  8626. col.push_back(0);
  8627. runeAreaSpell.areaVec.push_back(col);
  8628. col.clear();
  8629. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 150; runeAreaSpell.maxDamage = 250;
  8630. long tempExhaust = player->exhaustedTicks;
  8631. player->exhaustedTicks = 0;
  8632. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8633. player->exhaustedTicks = tempExhaust;
  8634. int32_t mana = 25;
  8635. player->addManaSpent(mana);
  8636. player->mana -= mana;
  8637. return;
  8638. }
  8639.  
  8640.  
  8641. if((wandid == 2181 && (player->vocation == VOCATION_DRUID) && player->mana >= 8 && player->getLevel() >= 26)) { //Quagmire rod
  8642. int32_t dist = 2;
  8643. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8644. std::vector<unsigned char> col;
  8645. MagicEffectAreaClass runeAreaSpell;
  8646. runeAreaSpell.attackType = ATTACK_POISON;
  8647. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8648. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  8649. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  8650. runeAreaSpell.animationColor = 0x60;
  8651. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8652. col.push_back(0);
  8653. col.push_back(0);
  8654. col.push_back(0);
  8655. runeAreaSpell.areaVec.push_back(col);
  8656. col.clear();
  8657. col.push_back(0);
  8658. col.push_back(1);
  8659. col.push_back(0);
  8660. runeAreaSpell.areaVec.push_back(col);
  8661. col.clear();
  8662. col.push_back(0);
  8663. col.push_back(0);
  8664. col.push_back(0);
  8665. runeAreaSpell.areaVec.push_back(col);
  8666. col.clear();
  8667. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 40; runeAreaSpell.maxDamage = 50;
  8668. long tempExhaust = player->exhaustedTicks;
  8669. player->exhaustedTicks = 0;
  8670. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8671. player->exhaustedTicks = tempExhaust;
  8672. int32_t mana = 8;
  8673. player->addManaSpent(mana);
  8674. player->mana -= mana;
  8675. return;
  8676. }
  8677.  
  8678. if((wandid == 2182 && (player->vocation == VOCATION_DRUID) && player->mana >= 2 && player->getLevel() >= 7)) { //Snakebite rod
  8679. int32_t dist = 4;
  8680. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8681. std::vector<unsigned char> col;
  8682. MagicEffectAreaClass runeAreaSpell;
  8683. runeAreaSpell.attackType = ATTACK_POISON;
  8684. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8685. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  8686. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  8687. runeAreaSpell.animationColor = 0x60;
  8688. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8689. col.push_back(0);
  8690. col.push_back(0);
  8691. col.push_back(0);
  8692. runeAreaSpell.areaVec.push_back(col);
  8693. col.clear();
  8694. col.push_back(0);
  8695. col.push_back(1);
  8696. col.push_back(0);
  8697. runeAreaSpell.areaVec.push_back(col);
  8698. col.clear();
  8699. col.push_back(0);
  8700. col.push_back(0);
  8701. col.push_back(0);
  8702. runeAreaSpell.areaVec.push_back(col);
  8703. col.clear();
  8704. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 8; runeAreaSpell.maxDamage = 18;
  8705. long tempExhaust = player->exhaustedTicks;
  8706. player->exhaustedTicks = 0;
  8707. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8708. player->exhaustedTicks = tempExhaust;
  8709. int32_t mana = 2;
  8710. player->addManaSpent(mana);
  8711. player->mana -= mana;
  8712. return;
  8713. }
  8714.  
  8715.  
  8716.  
  8717. if((wandid == 2183 && (player->vocation == VOCATION_DRUID) && player->mana >= 13 && player->getLevel() >= 33)) { //Tempest rod
  8718. int32_t dist = 2;
  8719. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8720. std::vector<unsigned char> col;
  8721. MagicEffectAreaClass runeAreaSpell;
  8722. runeAreaSpell.attackType = ATTACK_ENERGY;
  8723. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8724. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8725. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8726. runeAreaSpell.animationColor = 0x11;
  8727. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8728. col.push_back(0);
  8729. col.push_back(0);
  8730. col.push_back(0);
  8731. runeAreaSpell.areaVec.push_back(col);
  8732. col.clear();
  8733. col.push_back(0);
  8734. col.push_back(1);
  8735. col.push_back(0);
  8736. runeAreaSpell.areaVec.push_back(col);
  8737. col.clear();
  8738. col.push_back(0);
  8739. col.push_back(0);
  8740. col.push_back(0);
  8741. runeAreaSpell.areaVec.push_back(col);
  8742. col.clear();
  8743. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 60; runeAreaSpell.maxDamage = 70;
  8744. long tempExhaust = player->exhaustedTicks;
  8745. player->exhaustedTicks = 0;
  8746. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8747. player->exhaustedTicks = tempExhaust;
  8748. int32_t mana = 13;
  8749. player->addManaSpent(mana);
  8750. player->mana -= mana;
  8751. return;
  8752. }
  8753.  
  8754.  
  8755. if((wandid == 2185 && (player->vocation == VOCATION_DRUID) && player->mana >= 5 && player->getLevel() >= 19)) { //Volcanic rod
  8756. int32_t dist = 2;
  8757. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8758. std::vector<unsigned char> col;
  8759. MagicEffectAreaClass runeAreaSpell;
  8760. runeAreaSpell.attackType = ATTACK_FIRE;
  8761. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  8762. runeAreaSpell.hitEffect = NM_ME_FIRE_AREA;
  8763. runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8764. runeAreaSpell.animationColor = 0xC7;
  8765. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8766. col.push_back(0);
  8767. col.push_back(0);
  8768. col.push_back(0);
  8769. runeAreaSpell.areaVec.push_back(col);
  8770. col.clear();
  8771. col.push_back(0);
  8772. col.push_back(1);
  8773. col.push_back(0);
  8774. runeAreaSpell.areaVec.push_back(col);
  8775. col.clear();
  8776. col.push_back(0);
  8777. col.push_back(0);
  8778. col.push_back(0);
  8779. runeAreaSpell.areaVec.push_back(col);
  8780. col.clear();
  8781. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 25; runeAreaSpell.maxDamage = 35;
  8782. long tempExhaust = player->exhaustedTicks;
  8783. player->exhaustedTicks = 0;
  8784. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8785. player->exhaustedTicks = tempExhaust;
  8786. int32_t mana = 5;
  8787. player->addManaSpent(mana);
  8788. player->mana -= mana;
  8789. return;
  8790. }
  8791.  
  8792.  
  8793. if((wandid == 2186 && (player->vocation == VOCATION_DRUID) && player->mana >= 3 && player->getLevel() >= 13)) { //Moonlight rod
  8794. int32_t dist = 3;
  8795. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8796. std::vector<unsigned char> col;
  8797. MagicEffectAreaClass runeAreaSpell;
  8798. runeAreaSpell.attackType = ATTACK_ENERGY;
  8799. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8800. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8801. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8802. runeAreaSpell.animationColor = 0x47;
  8803. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8804. col.push_back(0);
  8805. col.push_back(0);
  8806. col.push_back(0);
  8807. runeAreaSpell.areaVec.push_back(col);
  8808. col.clear();
  8809. col.push_back(0);
  8810. col.push_back(1);
  8811. col.push_back(0);
  8812. runeAreaSpell.areaVec.push_back(col);
  8813. col.clear();
  8814. col.push_back(0);
  8815. col.push_back(0);
  8816. col.push_back(0);
  8817. runeAreaSpell.areaVec.push_back(col);
  8818. col.clear();
  8819. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 14; runeAreaSpell.maxDamage = 24;
  8820. long tempExhaust = player->exhaustedTicks;
  8821. player->exhaustedTicks = 0;
  8822. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8823. player->exhaustedTicks = tempExhaust;
  8824. int32_t mana = 3;
  8825. player->addManaSpent(mana);
  8826. player->mana -= mana;
  8827. return;
  8828. }
  8829.  
  8830.  
  8831. if((wandid == 2187 && (player->vocation == VOCATION_SORCERER) && player->mana >= 13 && player->getLevel() >= 33)) { //Wand of inferno
  8832. int32_t dist = 2;
  8833. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8834. std::vector<unsigned char> col;
  8835. MagicEffectAreaClass runeAreaSpell;
  8836. runeAreaSpell.attackType = ATTACK_FIRE;
  8837. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  8838. runeAreaSpell.hitEffect = NM_ME_FIRE_AREA;
  8839. runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8840. runeAreaSpell.animationColor = 0xC7;
  8841. runeAreaSpell.drawblood = true;
  8842. runeAreaSpell.offensive = true;
  8843. col.push_back(0);
  8844. col.push_back(0);
  8845. col.push_back(0);
  8846. runeAreaSpell.areaVec.push_back(col);
  8847. col.clear();
  8848. col.push_back(0);
  8849. col.push_back(1);
  8850. col.push_back(0);
  8851. runeAreaSpell.areaVec.push_back(col);
  8852. col.clear();
  8853. col.push_back(0);
  8854. col.push_back(0);
  8855. col.push_back(0);
  8856. runeAreaSpell.areaVec.push_back(col);
  8857. col.clear();
  8858. runeAreaSpell.direction = 1;
  8859. runeAreaSpell.minDamage = 60;
  8860. runeAreaSpell.maxDamage = 70;
  8861. long tempExhaust = player->exhaustedTicks;
  8862. player->exhaustedTicks = 0;
  8863. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8864. player->exhaustedTicks = tempExhaust;
  8865. int32_t mana = 13;
  8866. player->addManaSpent(mana);
  8867. player->mana -= mana;
  8868.  
  8869. return;
  8870. }
  8871.  
  8872.  
  8873. if((wandid == 2188 && (player->vocation == VOCATION_SORCERER) && player->mana >= 5 && player->getLevel() >= 19)) { //Wand of plague
  8874. int32_t dist = 2;
  8875. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8876. std::vector<unsigned char> col;
  8877. MagicEffectAreaClass runeAreaSpell;
  8878. runeAreaSpell.attackType = ATTACK_POISON;
  8879. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8880. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  8881. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  8882. runeAreaSpell.animationColor = 0x60;
  8883. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8884. col.push_back(0);
  8885. col.push_back(0);
  8886. col.push_back(0);
  8887. runeAreaSpell.areaVec.push_back(col);
  8888. col.clear();
  8889. col.push_back(0);
  8890. col.push_back(1);
  8891. col.push_back(0);
  8892. runeAreaSpell.areaVec.push_back(col);
  8893. col.clear();
  8894. col.push_back(0);
  8895. col.push_back(0);
  8896. col.push_back(0);
  8897. runeAreaSpell.areaVec.push_back(col);
  8898. col.clear();
  8899. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 25; runeAreaSpell.maxDamage = 35;
  8900. long tempExhaust = player->exhaustedTicks;
  8901. player->exhaustedTicks = 0;
  8902. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8903. player->exhaustedTicks = tempExhaust;
  8904. int32_t mana = 5;
  8905. player->addManaSpent(mana);
  8906. player->mana -= mana;
  8907. return;
  8908. }
  8909.  
  8910.  
  8911. if((wandid == 2189 && (player->vocation == VOCATION_SORCERER) && player->mana >= 8 && player->getLevel() >= 26)) { //Wand of cosmic energy
  8912. int32_t dist = 2;
  8913. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8914. std::vector<unsigned char> col;
  8915. MagicEffectAreaClass runeAreaSpell;
  8916. runeAreaSpell.attackType = ATTACK_ENERGY;
  8917. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8918. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8919. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8920. runeAreaSpell.animationColor = 0x47;
  8921. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8922. col.push_back(0);
  8923. col.push_back(0);
  8924. col.push_back(0);
  8925. runeAreaSpell.areaVec.push_back(col);
  8926. col.clear();
  8927. col.push_back(0);
  8928. col.push_back(1);
  8929. col.push_back(0);
  8930. runeAreaSpell.areaVec.push_back(col);
  8931. col.clear();
  8932. col.push_back(0);
  8933. col.push_back(0);
  8934. col.push_back(0);
  8935. runeAreaSpell.areaVec.push_back(col);
  8936. col.clear();
  8937. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 40; runeAreaSpell.maxDamage = 50;
  8938. long tempExhaust = player->exhaustedTicks;
  8939. player->exhaustedTicks = 0;
  8940. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8941. player->exhaustedTicks = tempExhaust;
  8942. int32_t mana = 8;
  8943. player->addManaSpent(mana);
  8944. player->mana -= mana;
  8945. return;
  8946. }
  8947.  
  8948.  
  8949. if((wandid == 2190 && (player->vocation == VOCATION_SORCERER) && player->mana >= 2 && player->getLevel() >= 7)) { //Wand of vortex
  8950. int32_t dist = 3;
  8951. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8952. std::vector<unsigned char> col;
  8953. MagicEffectAreaClass runeAreaSpell;
  8954. runeAreaSpell.attackType = ATTACK_ENERGY;
  8955. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8956. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8957. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8958. runeAreaSpell.animationColor = 0x47;
  8959. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8960. col.push_back(0);
  8961. col.push_back(0);
  8962. col.push_back(0);
  8963. runeAreaSpell.areaVec.push_back(col);
  8964. col.clear();
  8965. col.push_back(0);
  8966. col.push_back(1);
  8967. col.push_back(0);
  8968. runeAreaSpell.areaVec.push_back(col);
  8969. col.clear();
  8970. col.push_back(0);
  8971. col.push_back(0);
  8972. col.push_back(0);
  8973. runeAreaSpell.areaVec.push_back(col);
  8974. col.clear();
  8975. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 8; runeAreaSpell.maxDamage = 18;
  8976. long tempExhaust = player->exhaustedTicks;
  8977. player->exhaustedTicks = 0;
  8978. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8979. player->exhaustedTicks = tempExhaust;
  8980. int32_t mana = 2;
  8981. player->addManaSpent(mana);
  8982. player->mana -= mana;
  8983. return;
  8984. }
  8985.  
  8986. if((wandid == 2191 && (player->vocation == VOCATION_SORCERER) && player->mana >= 3 && player->getLevel() >= 13)) { //Wand of dragonbreath
  8987. int32_t dist = 3;
  8988. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8989. std::vector<unsigned char> col;
  8990. MagicEffectAreaClass runeAreaSpell;
  8991. runeAreaSpell.attackType = ATTACK_FIRE;
  8992. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  8993. runeAreaSpell.hitEffect = NM_ME_FIRE_AREA;
  8994. runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8995. runeAreaSpell.animationColor = 0xC7;
  8996. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8997. col.push_back(0);
  8998. col.push_back(0);
  8999. col.push_back(0);
  9000. runeAreaSpell.areaVec.push_back(col);
  9001. col.clear();
  9002. col.push_back(0);
  9003. col.push_back(1);
  9004. col.push_back(0);
  9005. runeAreaSpell.areaVec.push_back(col);
  9006. col.clear();
  9007. col.push_back(0);
  9008. col.push_back(0);
  9009. col.push_back(0);
  9010. runeAreaSpell.areaVec.push_back(col);
  9011. col.clear();
  9012. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 14; runeAreaSpell.maxDamage = 24;
  9013. long tempExhaust = player->exhaustedTicks;
  9014. player->exhaustedTicks = 0;
  9015. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  9016. player->exhaustedTicks = tempExhaust;
  9017. int32_t mana = 3;
  9018. player->addManaSpent(mana);
  9019. player->mana -= mana;
  9020. return;
  9021. }
  9022. //messages by Subarmy
  9023.  
  9024.  
  9025.  
  9026. 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
  9027. player->sendTextMessage(MSG_SMALLINFO, "This wand can only be wielded by sorcerers.");
  9028. }
  9029. 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
  9030. player->sendTextMessage(MSG_SMALLINFO, "This wand can only be wielded by druids.");
  9031. }
  9032. if((wandid == 2181 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 26)) {
  9033. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 26 level to wield this wand.");
  9034. }
  9035. if((wandid == 2544 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 200)) {
  9036. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 200 level to wield this wand.");
  9037. }
  9038. if((wandid == 5326 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 300)) {
  9039. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 300 level to wield this wand.");
  9040. }
  9041. if((wandid == 2453 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 150)) {
  9042. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 150 level to wield this wand.");
  9043. }
  9044. if((wandid == 2182 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 7)) {
  9045. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 7 level to wield this wand.");
  9046. }
  9047. if((wandid == 2183 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 33)) {
  9048. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 33 to wield this wand.");
  9049. }
  9050. if((wandid == 2185 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 19)) {
  9051. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 19 level to wield this wand.");
  9052. }
  9053. if((wandid == 2186 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 13)) {
  9054. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 13 level to wield this wand.");
  9055. }
  9056. if((wandid == 5318 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 65)) {
  9057. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 65 level to wield this wand.");
  9058. }
  9059. if((wandid == 2187 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 33)) {
  9060. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 33 level to wield this wand.");
  9061. }
  9062. if((wandid == 5319 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 65)) {
  9063. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 65 level to wield this wand.");
  9064. }
  9065. if((wandid == 2453 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 150)) {
  9066. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 150 level to wield this wand.");
  9067. }
  9068. if((wandid == 2544 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 200)) {
  9069. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 200 level to wield this wand.");
  9070. }
  9071. if((wandid == 5326 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 300)) {
  9072. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 300 level to wield this wand.");
  9073. }
  9074. if((wandid == 2188 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 19)) {
  9075. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 19 level to wield this wand.");
  9076. }
  9077. if((wandid == 2189 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 26)) {
  9078. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 26 level to wield this wand.");
  9079. }
  9080. if((wandid == 2190 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 7)) {
  9081. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 7 level to wield this wand.");
  9082. }
  9083.  
  9084. if((wandid == 2191 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 13)) {
  9085. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 13 level to wield this wand.");
  9086. }//end messages by Subarmy
  9087. }
  9088. #endif
  9089. // ONLINE RECORD
  9090. void Game::checkRecord()
  9091. {
  9092. if(record < getPlayersOnline()){
  9093. record = getPlayersOnline();
  9094. saveRecord();
  9095.  
  9096. std::stringstream record;
  9097. record << "New record: " << getPlayersOnline() << " players are logged in." << std::endl;
  9098. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  9099. (*it).second->sendTextMessage(MSG_ADVANCE, record.str().c_str());
  9100. }
  9101.  
  9102. }
  9103.  
  9104. bool Game::loadRecord()
  9105. {
  9106. std::string filename = g_config.getGlobalString("datadir") + "record.xml";
  9107. xmlDocPtr doc;
  9108. xmlMutexLock(xmlmutex);
  9109. doc = xmlParseFile(filename.c_str());
  9110.  
  9111. if (doc)
  9112. {
  9113. xmlNodePtr root, tmp;
  9114. root = xmlDocGetRootElement(doc);
  9115.  
  9116. if (xmlStrcmp(root->name, (const xmlChar*)"record"))
  9117. {
  9118. xmlFreeDoc(doc);
  9119. xmlMutexUnlock(xmlmutex);
  9120. return false;
  9121. }
  9122.  
  9123. record = atoi((const char*)xmlGetProp(root, (const xmlChar *)"record"));
  9124.  
  9125. xmlFreeDoc(doc);
  9126. xmlMutexUnlock(xmlmutex);
  9127. return true;
  9128. }
  9129.  
  9130. xmlMutexUnlock(xmlmutex);
  9131. return false;
  9132. }
  9133.  
  9134. bool Game::saveRecord()
  9135. {
  9136. std::string filename = g_config.getGlobalString("datadir") + "record.xml";
  9137. xmlDocPtr doc;
  9138. xmlNodePtr root, tmp;
  9139. xmlMutexLock(xmlmutex);
  9140. time_t time = std::time(NULL);
  9141.  
  9142. doc = xmlNewDoc((const xmlChar*)"1.0");
  9143. doc->children = xmlNewDocNode(doc, NULL, (const xmlChar*)"record", NULL);
  9144. root = doc->children;
  9145.  
  9146. std::stringstream sb;
  9147. sb << record; xmlSetProp(root, (const xmlChar*) "record", (const xmlChar*)sb.str().c_str()); sb.str("");
  9148. sb << time; xmlSetProp(root, (const xmlChar*) "time", (const xmlChar*)sb.str().c_str()); sb.str("");
  9149.  
  9150. xmlSaveFile(filename.c_str(), doc);
  9151. xmlFreeDoc(doc);
  9152. xmlMutexUnlock(xmlmutex);
  9153. return true;
  9154. }
  9155. // ANIMATED TEXT WHEN ADVANCE
  9156. void Game::sendAnimatedTextExt(const Position pos,int32_t aniColor,const std::string &text)
  9157. {
  9158. SpectatorVec list;
  9159. SpectatorVec::iterator it;
  9160. getSpectators(Range(pos), list);
  9161. for(it = list.begin(); it != list.end(); ++it){
  9162. Player* spec = dynamic_cast<Player*>(*it);
  9163. if(spec)
  9164. spec->sendAnimatedText(pos, aniColor, text);
  9165. }
  9166. }
  9167. // CREATUREBYPOSITION
  9168. Creature* Game::getCreatureByPosition(int32_t x, int32_t y, int32_t z)
  9169. {
  9170. for(AutoList<Creature>::listiterator it = listCreature.list.begin(); it != listCreature.list.end(); ++it){
  9171. if(it->second->pos.x == x && it->second->pos.y == y && it->second->pos.z == z)
  9172. return it->second;
  9173. }
  9174.  
  9175. return NULL;
  9176. }
  9177. // CREATE CONDITION
  9178. 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)
  9179. {
  9180. uint32_t targetID;
  9181. if(target)
  9182. targetID = target->getID();
  9183. else
  9184. targetID = 0;
  9185.  
  9186. MagicEffectTargetCreatureCondition magicCondition = MagicEffectTargetCreatureCondition(targetID);
  9187. magicCondition.animationColor = animationColor;
  9188. magicCondition.damageEffect = damageEffect;
  9189. magicCondition.hitEffect = hitEffect;
  9190. magicCondition.attackType = attackType;
  9191. magicCondition.maxDamage = maxDamage;
  9192. magicCondition.minDamage = minDamage;
  9193. magicCondition.offensive = offensive;
  9194. CreatureCondition condition = CreatureCondition(ticks, count, magicCondition);
  9195. creature->addCondition(condition, true);
  9196.  
  9197. Player *player = dynamic_cast<Player*>(creature);
  9198. if(player)
  9199. player->sendIcons();
  9200. }
  9201. // Fields loaded from map - The Chaos
  9202. void Game::doFieldDamage(Creature* creature, unsigned char animationColor, unsigned char damageEffect,
  9203. unsigned char hitEffect, attacktype_t attackType, bool offensive, int32_t damage)
  9204. {
  9205. MagicEffectClass cd;
  9206. cd.animationColor = animationColor;
  9207. cd.damageEffect = damageEffect;
  9208. cd.hitEffect = hitEffect;
  9209. cd.attackType = attackType;
  9210. cd.offensive = offensive;
  9211. Player* itsHim = dynamic_cast<Player*>(getCreatureByID(creature->getID()));
  9212. if(itsHim){ //Since that was causing damage/2 against player, here its my solution =)
  9213. cd.maxDamage = damage*2;
  9214. cd.minDamage = damage*2;
  9215. }
  9216. else{
  9217. cd.maxDamage = damage;
  9218. cd.minDamage = damage;
  9219. }
  9220. creatureMakeMagic(NULL, creature->pos, &cd);
  9221. }
  9222. void Game::updateTile(const Position& pos)
  9223. {
  9224. SpectatorVec list;
  9225. SpectatorVec::iterator i;
  9226. getSpectators(Range(pos), list);
  9227. for(i = list.begin(); i != list.end(); ++i)
  9228. (*i)->onTileUpdated(pos);
  9229. }
  9230.  
  9231. void Game::banPlayer(Player *player, std::string reason, std::string action, std::string comment, bool IPban)
  9232. {
  9233. int32_t bantime = 0;
  9234.  
  9235. if(player){
  9236.  
  9237. if(comment=="deletion")
  9238. player->deleted = 1; // make player deleted
  9239. else
  9240. bantime = atoi(comment.c_str()) * 86400; // else make players banned for "comment" days (86400 = 1 day)
  9241.  
  9242. if(player->finalwarning == 1 || player->times == 4)
  9243. player->deleted = 1; // if player was already warned let delete thy char
  9244.  
  9245. if(action=="AccountBan+FinalWarning" || player->times == 3)
  9246. player->finalwarning = 1; // if player has warned set variable
  9247.  
  9248. if(reason=="Excessive unjustifed player killing")
  9249. bantime = g_config.getGlobalNumber("pkbandays",3) * 86400; // baannnnn pekaayssss (from config.lua)
  9250.  
  9251. player->banned = 1;
  9252. player->times++;
  9253. player->comment = comment;
  9254. player->reason = reason;
  9255. player->action = action;
  9256. player->banstart = std::time(NULL);
  9257. player->banend = player->banstart + bantime;
  9258. time_t endBan = player->banend;
  9259. player->banrealtime = ctime(&endBan); // this variable stores REAL ban date in string, so you wont see 11105220952 in accmaker ;)
  9260. if(IPban){
  9261. std::pair<uint32_t, uint32_t> IpNetMask;
  9262. IpNetMask.first = player->lastip;
  9263. IpNetMask.second = 0xFFFFFFFF;
  9264. if(IpNetMask.first > 0)
  9265. bannedIPs.push_back(IpNetMask);
  9266. }
  9267. std::stringstream ban;
  9268. ban << "You just have been banned for " << reason << "!";
  9269. player->sendTextMessage(MSG_INFO, ban.str().c_str());
  9270. player->kickPlayer();
  9271. }
  9272. }
  9273.  
  9274. #ifdef REX_MUTED
  9275.  
  9276. #endif //REX_MUTED
  9277. #ifdef HUCZU_FIX
  9278. bool Game::loadCities(Player* player, std::string name)
  9279. {
  9280. xmlDocPtr doc;
  9281. std::string file = "data/miasta.xml";
  9282. doc = xmlParseFile(file.c_str());
  9283. if(doc){
  9284. xmlNodePtr root, miasto;
  9285. root = xmlDocGetRootElement(doc);
  9286. if(xmlStrcmp(root->name, (const xmlChar*)"miasta")) {
  9287. xmlFreeDoc(doc);
  9288. return -1;
  9289. }
  9290. miasto = root->children;
  9291. while(miasto){
  9292. if(strcmp((char*) miasto->name, "miasto")==0){
  9293.  
  9294. std::string nameIN = (const char*)xmlGetProp(miasto, (const xmlChar *) "nazwa");
  9295. int32_t x = atoi((const char*)xmlGetProp(miasto, (const xmlChar *) "x"));
  9296. int32_t y = atoi((const char*)xmlGetProp(miasto, (const xmlChar *) "y"));
  9297. int32_t z = atoi((const char*)xmlGetProp(miasto, (const xmlChar *) "z"));
  9298. Position pos(x,y,z);
  9299. if(nameIN == name)
  9300. teleport(player,pos);
  9301. }
  9302. miasto = miasto->next;
  9303. }
  9304. xmlFreeDoc(doc);
  9305. return 0;
  9306. }
  9307. return -1;
  9308. }
  9309. #endif //HUCZU_FIX
  9310. // RAID SYSTEM
  9311. bool Game::loadRaid(std::string name)
  9312. {
  9313. xmlDocPtr doc;
  9314. std::cout << "Executing raid named " << name << "." << std::endl;
  9315. std::string file = "data/world/raids.xml";
  9316. doc = xmlParseFile(file.c_str());
  9317. if(doc){
  9318. xmlNodePtr root, raid, command;
  9319. root = xmlDocGetRootElement(doc);
  9320. if(xmlStrcmp(root->name, (const xmlChar*)"raids")) {
  9321. xmlFreeDoc(doc);
  9322. return -1;
  9323. }
  9324. raid = root->children;
  9325. while(raid){
  9326. if(strcmp((char*) raid->name, "raid")==0){
  9327.  
  9328. std::string nameIN = (const char*)xmlGetProp(raid, (const xmlChar *) "name");
  9329. if(nameIN == name) {
  9330. std::string messageIN = (const char*)xmlGetProp(raid, (const xmlChar *) "message");
  9331. std::string brodcasterIN = (const char*)xmlGetProp(raid, (const xmlChar *) "brodcaster");
  9332.  
  9333. Creature *c = getCreatureByName(brodcasterIN);
  9334. if(c) {
  9335. creatureBroadcastMessage(c,messageIN);
  9336. } else {
  9337. std::cout << "Could not send news msg! Brodcaster does not exist" << std::endl;
  9338. }
  9339.  
  9340. if(nameIN == name) {
  9341. command = raid->children;
  9342.  
  9343. while(command) {
  9344.  
  9345. if(strcmp((char*) command->name, "monster")==0){
  9346. std::string monstername = (const char*)xmlGetProp(command, (const xmlChar *) "name");
  9347. int32_t x = atoi((const char*)xmlGetProp(command, (const xmlChar *) "x"));
  9348. int32_t y = atoi((const char*)xmlGetProp(command, (const xmlChar *) "y"));
  9349. int32_t z = atoi((const char*)xmlGetProp(command, (const xmlChar *) "z"));
  9350.  
  9351. int32_t loot = atoi((const char*)xmlGetProp(command, (const xmlChar *) "lootid")); //Not yet implemented!
  9352. int32_t chance = atoi((const char*)xmlGetProp(command, (const xmlChar *) "chance")); //Not yet implemented!
  9353. placeRaidMonster(monstername, x, y, z);
  9354. }
  9355.  
  9356. if(strcmp((char*) command->name, "area")==0){
  9357. std::string monstername = (const char*)xmlGetProp(command, (const xmlChar *) "monster");
  9358. int32_t count = atoi((const char*)xmlGetProp(command, (const xmlChar *) "count"));
  9359. int32_t xf = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posxfrom"));
  9360. int32_t yf = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posyfrom"));
  9361. int32_t zf = atoi((const char*)xmlGetProp(command, (const xmlChar *) "poszfrom"));
  9362.  
  9363. int32_t xt = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posxto"));
  9364. int32_t yt = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posyto"));
  9365. int32_t zt = atoi((const char*)xmlGetProp(command, (const xmlChar *) "poszto"));
  9366.  
  9367. int32_t i = 0;
  9368. int32_t tries = 0;
  9369. while (i<=count && tries<=(count*10)) {
  9370. int32_t x = (int32_t)((xt-xf) * (rand()/(RAND_MAX+1.0)) + xf);
  9371. int32_t y = (int32_t)((yt-yf) * (rand()/(RAND_MAX+1.0)) + yf);
  9372. int32_t z = (int32_t)((zt-zf) * (rand()/(RAND_MAX+1.0)) + zf);
  9373. Tile* t = map->getTile(x,y,z);
  9374. if(t && t->isPz() == false) {
  9375. placeRaidMonster(monstername, x, y, z);
  9376. i++;
  9377. }
  9378. tries++;
  9379. }
  9380. }
  9381. if(strcmp((char*) command->name, "message")==0){
  9382. std::string msg = (const char*)xmlGetProp(command, (const xmlChar *) "text");
  9383. std::string brodcaster = (const char*)xmlGetProp(command, (const xmlChar *) "brodcaster");
  9384. Creature *c = getCreatureByName(brodcaster);
  9385. if(c) {
  9386. creatureBroadcastMessage(c,msg);
  9387. } else {
  9388. std::cout << "Could not send news msg! Brodcaster does not exist." << std::endl;
  9389. }
  9390. }
  9391. command = command->next;
  9392. }
  9393. }
  9394. }
  9395. }
  9396. raid = raid->next;
  9397. }
  9398. xmlFreeDoc(doc);
  9399. return 0;
  9400. }
  9401. return -1;
  9402. }
  9403. bool Game::placeRaidMonster(std::string name, int32_t x, int32_t y, int32_t z)
  9404. {
  9405. Monster* monster = Monster::createMonster(name, this);
  9406. //For new CVS use the following line:
  9407. //Monster* monster = Monster::createMonster(name, this);
  9408. if(!monster){
  9409. delete monster;
  9410. return false;
  9411. }
  9412. Position pos;
  9413. pos.x = x;
  9414. pos.y = y;
  9415. pos.z = z;
  9416.  
  9417. // Place the monster
  9418. if(!placeCreature(pos, monster)) {
  9419. delete monster;
  9420. return false;
  9421. }
  9422.  
  9423. return true;
  9424. }
  9425.  
  9426. void Game::spectatorText(Position pos, unsigned char color, std::string text)
  9427. {
  9428. SpectatorVec list;
  9429. SpectatorVec::iterator it;
  9430. getSpectators(Range(pos, true), list);
  9431.  
  9432. for(it = list.begin(); it != list.end(); ++it) {
  9433. if(Player* p = dynamic_cast<Player*>(*it)) {
  9434. p->sendAnimatedText(pos, color, text);
  9435. }
  9436. }
  9437. }
  9438.  
  9439. #ifdef DT_PREMMY
  9440. bool Game::countPremmy(Player *player)
  9441. {
  9442. Account acc = IOAccount::instance()->loadAccount(player->accountNumber);
  9443. int32_t cont;
  9444. if(acc.lastsaveday == 0)
  9445. cont = 0;
  9446. else
  9447. cont = acc.lastsaveday2 - acc.lastsaveday;
  9448. //std::cout << "Last Login in Acc: " << acc.lastsaveday << " - Today: " << acc.lastsaveday2 << " - Days removed from acc: " << cont << std::endl;
  9449. if(cont < 0){
  9450. cont =+ 365; //dodajemy caly rok
  9451. }
  9452. if((acc.premDays - cont) <= 0)
  9453. {
  9454. acc.premDays = 0;
  9455. player->premmium = false;
  9456. }
  9457. else
  9458. {
  9459. acc.premDays = acc.premDays - cont;
  9460. player->premmium = true;
  9461. }
  9462. if(g_config.FREE_PREMMY)
  9463. player->premmium = true;
  9464.  
  9465. IOAccount::instance()->saveAccount(acc);
  9466.  
  9467. }
  9468.  
  9469. #endif //DT_PREMMY
  9470.  
  9471.  
  9472. #ifdef ZS_SWORDS
  9473. void Game::useSword(Creature *creature, Creature *attackedCreature, int32_t swordid)
  9474. {
  9475. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::useSword()");
  9476.  
  9477. Player *player = dynamic_cast<Player*>(creature);
  9478. if(!player || !attackedCreature || player->pos.z != attackedCreature->pos.z)
  9479. return;
  9480.  
  9481. int32_t dist, mana = 0;
  9482. MagicEffectAreaNoExhaustionClass runeAreaSpell;
  9483. runeAreaSpell.drawblood = true;
  9484. runeAreaSpell.offensive = true;
  9485. runeAreaSpell.direction = 1;
  9486.  
  9487.  
  9488. // P O I S O N //
  9489.  
  9490. if (swordid == ITEM_P_MB && player->vocation == VOCATION_KNIGHT &&
  9491. player->mana >= g_config.MANA_P_MB && player->getLevel() >= 220)
  9492. {
  9493. dist = g_config.RANGE_P_MB;
  9494. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9495. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9496. return;
  9497.  
  9498. runeAreaSpell.attackType = ATTACK_SWORD;
  9499. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  9500. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  9501. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  9502. runeAreaSpell.animationColor = 0x60;
  9503.  
  9504. runeAreaSpell.minDamage = 10;
  9505. runeAreaSpell.maxDamage = 60;
  9506. mana = g_config.MANA_P_MB;
  9507. }
  9508.  
  9509. else if (swordid == ITEM_P_MAUL && player->vocation == VOCATION_KNIGHT &&
  9510. player->mana >= g_config.MANA_P_MAUL && player->getLevel() >= 220)
  9511. {
  9512. dist = g_config.RANGE_P_MAUL;
  9513. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9514. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9515. return;
  9516.  
  9517. runeAreaSpell.attackType = ATTACK_SWORD;
  9518. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  9519. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  9520. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  9521. runeAreaSpell.animationColor = 0x60;
  9522.  
  9523. runeAreaSpell.minDamage = 10;
  9524. runeAreaSpell.maxDamage = 60;
  9525. mana = g_config.MANA_P_MAUL;
  9526. }
  9527.  
  9528. else if (swordid == ITEM_P_HEAD && player->vocation == VOCATION_KNIGHT &&
  9529. player->mana >= g_config.MANA_P_HEAD && player->getLevel() >= 220)
  9530. {
  9531. dist = g_config.RANGE_P_HEAD;
  9532. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9533. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9534. return;
  9535.  
  9536. runeAreaSpell.attackType = ATTACK_SWORD;
  9537. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  9538. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  9539. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  9540. runeAreaSpell.animationColor = 0x60;
  9541.  
  9542. runeAreaSpell.minDamage = 10;
  9543. runeAreaSpell.maxDamage = 60;
  9544. mana = g_config.MANA_P_HEAD;
  9545. }
  9546.  
  9547. // F I R E //
  9548.  
  9549. else if (swordid == ITEM_F_MB && player->vocation == VOCATION_KNIGHT &&
  9550. player->mana >= g_config.MANA_F_MB && player->getLevel() >= 320)
  9551. {
  9552. dist = g_config.RANGE_F_MB;
  9553. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9554. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9555. return;
  9556.  
  9557. runeAreaSpell.attackType = ATTACK_SWORD;
  9558. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  9559. runeAreaSpell.hitEffect = NM_ME_EXPLOSION_AREA;
  9560. runeAreaSpell.areaEffect = NM_ME_EXPLOSION_AREA;
  9561. runeAreaSpell.animationColor = 0xC6;
  9562.  
  9563. runeAreaSpell.minDamage = 60;
  9564. runeAreaSpell.maxDamage = 110;
  9565. mana = g_config.MANA_F_MB;
  9566. }
  9567.  
  9568. else if (swordid == ITEM_F_MAUL && player->vocation == VOCATION_KNIGHT &&
  9569. player->mana >= g_config.MANA_F_MAUL && player->getLevel() >= 320)
  9570. {
  9571. dist = g_config.RANGE_F_MAUL;
  9572. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9573. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9574. return;
  9575.  
  9576. runeAreaSpell.attackType = ATTACK_SWORD;
  9577. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  9578. runeAreaSpell.hitEffect = NM_ME_EXPLOSION_AREA;
  9579. runeAreaSpell.areaEffect = NM_ME_EXPLOSION_AREA;
  9580. runeAreaSpell.animationColor = 0xC6;
  9581.  
  9582. runeAreaSpell.minDamage = 60;
  9583. runeAreaSpell.maxDamage = 110;
  9584. mana = g_config.MANA_F_MAUL;
  9585. }
  9586.  
  9587. else if (swordid == ITEM_F_HEAD && player->vocation == VOCATION_KNIGHT &&
  9588. player->mana >= g_config.MANA_F_HEAD && player->getLevel() >= 320)
  9589. {
  9590. dist = g_config.RANGE_F_HEAD;
  9591. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9592. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9593. return;
  9594.  
  9595. runeAreaSpell.attackType = ATTACK_SWORD;
  9596. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  9597. runeAreaSpell.hitEffect = NM_ME_EXPLOSION_AREA;
  9598. runeAreaSpell.areaEffect = NM_ME_EXPLOSION_AREA;
  9599. runeAreaSpell.animationColor = 0xC6;
  9600.  
  9601. runeAreaSpell.minDamage = 60;
  9602. runeAreaSpell.maxDamage = 110;
  9603. mana = g_config.MANA_F_HEAD;
  9604. }
  9605.  
  9606. // E N E R G Y //
  9607.  
  9608. else if (swordid == ITEM_E_MB && player->vocation == VOCATION_KNIGHT &&
  9609. player->mana >= g_config.MANA_E_MB && player->getLevel() >= 420)
  9610. {
  9611. dist = g_config.RANGE_E_MB;
  9612. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9613. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9614. return;
  9615.  
  9616. runeAreaSpell.attackType = ATTACK_SWORD;
  9617. runeAreaSpell.animationEffect = NM_ANI_SUDDENDEATH;
  9618. runeAreaSpell.hitEffect = NM_ME_MORT_AREA;
  9619. runeAreaSpell.areaEffect = NM_ME_MORT_AREA;
  9620. runeAreaSpell.animationColor = 0xB9;
  9621.  
  9622. runeAreaSpell.minDamage = 110;
  9623. runeAreaSpell.maxDamage = 160;
  9624. mana = g_config.MANA_E_MB;
  9625. }
  9626.  
  9627. else if (swordid == ITEM_E_MAUL && player->vocation == VOCATION_KNIGHT &&
  9628. player->mana >= g_config.MANA_E_MAUL && player->getLevel() >= 420)
  9629. {
  9630. dist = g_config.RANGE_E_MAUL;
  9631. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9632. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9633. return;
  9634.  
  9635. runeAreaSpell.attackType = ATTACK_SWORD;
  9636. runeAreaSpell.animationEffect = NM_ANI_SUDDENDEATH;
  9637. runeAreaSpell.hitEffect = NM_ME_MORT_AREA;
  9638. runeAreaSpell.areaEffect = NM_ME_MORT_AREA;
  9639. runeAreaSpell.animationColor = 0xB9;
  9640.  
  9641. runeAreaSpell.minDamage = 110;
  9642. runeAreaSpell.maxDamage = 160;
  9643. mana = g_config.MANA_E_MAUL;
  9644. }
  9645.  
  9646. else if (swordid == ITEM_E_HEAD && player->vocation == VOCATION_KNIGHT &&
  9647. player->mana >= g_config.MANA_E_HEAD && player->getLevel() >= 420)
  9648. {
  9649. dist = g_config.RANGE_E_HEAD;
  9650. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9651. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9652. return;
  9653.  
  9654. runeAreaSpell.attackType = ATTACK_SWORD;
  9655. runeAreaSpell.animationEffect = NM_ANI_SUDDENDEATH;
  9656. runeAreaSpell.hitEffect = NM_ME_MORT_AREA;
  9657. runeAreaSpell.areaEffect = NM_ME_MORT_AREA;
  9658. runeAreaSpell.animationColor = 0xB9;
  9659.  
  9660. runeAreaSpell.minDamage = 110;
  9661. runeAreaSpell.maxDamage = 160;
  9662. mana = g_config.MANA_E_HEAD;
  9663. }
  9664.  
  9665. // P L A Y E R W E A P O N S //
  9666.  
  9667. else if (swordid == ITEM_HAIK_AXE && player->vocation == VOCATION_KNIGHT &&
  9668. player->mana >= g_config.MANA_HAIK_AXE && player->getLevel() >= 500)
  9669. {
  9670. dist = g_config.RANGE_HAIK_AXE;
  9671. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9672. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9673. return;
  9674.  
  9675. runeAreaSpell.attackType = ATTACK_SWORD;
  9676. runeAreaSpell.animationEffect = NM_ANI_STAR;
  9677. runeAreaSpell.hitEffect = NM_ME_STAR;
  9678. runeAreaSpell.areaEffect = NM_ME_STAR;
  9679. runeAreaSpell.animationColor = 0xD2;
  9680.  
  9681. runeAreaSpell.minDamage = 300;
  9682. runeAreaSpell.maxDamage = 350;
  9683. mana = g_config.MANA_HAIK_AXE;
  9684. }
  9685.  
  9686. else if (swordid == ITEM_BLETKA_AXE && player->vocation == VOCATION_KNIGHT &&
  9687. player->mana >= g_config.MANA_BLETKA_AXE)
  9688. {
  9689. dist = g_config.RANGE_BLETKA_AXE;
  9690. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9691. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9692. return;
  9693.  
  9694. runeAreaSpell.attackType = ATTACK_SWORD;
  9695. runeAreaSpell.animationEffect = NM_ANI_STAR;
  9696. runeAreaSpell.hitEffect = NM_ME_STAR;
  9697. runeAreaSpell.areaEffect = NM_ME_STAR;
  9698. runeAreaSpell.animationColor = 0xD2;
  9699.  
  9700. runeAreaSpell.minDamage = 150;
  9701. runeAreaSpell.maxDamage = 200;
  9702. mana = g_config.MANA_BLETKA_AXE;
  9703. }
  9704.  
  9705. // K U N I E C //
  9706.  
  9707. if (mana > 0)
  9708. {
  9709. std::vector<unsigned char> col;
  9710.  
  9711. col.push_back(0);
  9712. col.push_back(0);
  9713. col.push_back(0);
  9714. runeAreaSpell.areaVec.push_back(col);
  9715. col.clear();
  9716. col.push_back(0);
  9717. col.push_back(1);
  9718. col.push_back(0);
  9719. runeAreaSpell.areaVec.push_back(col);
  9720. col.clear();
  9721. col.push_back(0);
  9722. col.push_back(0);
  9723. col.push_back(0);
  9724. runeAreaSpell.areaVec.push_back(col);
  9725.  
  9726. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  9727. player->addManaSpent(mana);
  9728. player->mana -= mana;
  9729. }
  9730. }
  9731. #endif //ZS_SWORDS
  9732.  
  9733. #ifdef YUR_READABLES
  9734. bool Game::LoadReadables()
  9735. {
  9736. std::string file = g_config.getGlobalString("datadir") + "readables.xml";
  9737. xmlDocPtr doc;
  9738. xmlMutexLock(xmlmutex);
  9739.  
  9740. doc = xmlParseFile(file.c_str());
  9741. if (!doc)
  9742. return false;
  9743.  
  9744. xmlNodePtr root, readableNode;
  9745. root = xmlDocGetRootElement(doc);
  9746. if (xmlStrcmp(root->name, (const xmlChar*)"readables"))
  9747. {
  9748. xmlFreeDoc(doc);
  9749. xmlMutexUnlock(xmlmutex);
  9750. return false;
  9751. }
  9752.  
  9753. readableNode = root->children;
  9754. while (readableNode)
  9755. {
  9756. if (strcmp((char*) readableNode->name, "readable") == 0)
  9757. {
  9758. int32_t x = atoi((const char*)xmlGetProp(readableNode, (const xmlChar *) "x"));
  9759. int32_t y = atoi((const char*)xmlGetProp(readableNode, (const xmlChar *) "y"));
  9760. int32_t z = atoi((const char*)xmlGetProp(readableNode, (const xmlChar *) "z"));
  9761. std::string text = (const char*)xmlGetProp(readableNode, (const xmlChar *) "text");
  9762.  
  9763. for (size_t i = 0; i < text.length()-1; i++) // make real newlines
  9764. if (text.at(i) == '\\' && text.at(i+1) == 'n')
  9765. {
  9766. text[i] = ' ';
  9767. text[i+1] = '\n';
  9768. }
  9769.  
  9770. Tile* tile = getTile(x, y, z);
  9771. if (tile)
  9772. {
  9773. Thing* thing = tile->getTopThing();
  9774. Item* item = thing? dynamic_cast<Item*>(thing) : NULL;
  9775.  
  9776. if (item)
  9777. item->setReadable(text);
  9778. else
  9779. {
  9780. std::cout << "\nTop thing at " << Position(x,y,z) << " is not an item!";
  9781. return false;
  9782. }
  9783. }
  9784. else
  9785. {
  9786. std::cout << "\nTile " << Position(x,y,z) << " is not valid!";
  9787. return false;
  9788. }
  9789. }
  9790. readableNode = readableNode->next;
  9791. }
  9792.  
  9793. xmlFreeDoc(doc);
  9794. xmlMutexUnlock(xmlmutex);
  9795. return true;
  9796. }
  9797. #endif //YUR_READABLES
  9798.  
  9799. void Game::Blasting(Creature* c, Creature *attackedCreature, const Position& pos)
  9800. {
  9801. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::Blasting()");
  9802. Player* player = dynamic_cast<Player*>(c);
  9803. unsigned short dist = 6;
  9804. unsigned short REQ_MANA = 200;
  9805. uint32_t poziom = player->level;
  9806. uint32_t magpoziom = player->maglevel;
  9807.  
  9808. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9809. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9810. return;
  9811.  
  9812. MagicEffectAreaNoExhaustionClass runeAreaSpell;
  9813. runeAreaSpell.drawblood = true;
  9814. runeAreaSpell.offensive = true;
  9815. runeAreaSpell.direction = 1;
  9816. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  9817. runeAreaSpell.animationEffect = NM_ANI_REMOTE;
  9818. runeAreaSpell.hitEffect = NM_ME_EXPLO;
  9819. runeAreaSpell.areaEffect = NM_ME_EXPLO;
  9820. runeAreaSpell.animationColor = 0x60;
  9821.  
  9822. if((poziom * 2 + magpoziom * 3) >= 100){
  9823. runeAreaSpell.minDamage = int32_t((poziom * 2 + magpoziom * 3) * 1.6 );
  9824. runeAreaSpell.maxDamage = int32_t((poziom * 2 + magpoziom * 3) * 1.9 );
  9825. }else{
  9826. runeAreaSpell.minDamage = int32_t(100 * 1.5 );
  9827. runeAreaSpell.maxDamage = int32_t(100 * 1.8 );
  9828. }
  9829.  
  9830. std::vector<unsigned char> col;
  9831. col.push_back(0);
  9832. col.push_back(0);
  9833. col.push_back(0);
  9834. runeAreaSpell.areaVec.push_back(col);
  9835. col.clear();
  9836. col.push_back(0);
  9837. col.push_back(1);
  9838. col.push_back(0);
  9839. runeAreaSpell.areaVec.push_back(col);
  9840. col.clear();
  9841. col.push_back(0);
  9842. col.push_back(0);
  9843. col.push_back(0);
  9844. runeAreaSpell.areaVec.push_back(col);
  9845.  
  9846. creatureThrowRune(c, pos, runeAreaSpell);
  9847. player->flamTicks = 2*1000;
  9848. if (player->access < g_config.ACCESS_PROTECT)
  9849. {
  9850. player->mana -= REQ_MANA;
  9851. player->addManaSpent(REQ_MANA);
  9852. }
  9853. }
  9854. #ifdef KOSZ
  9855. bool Game::canDelete(Player *player, unsigned short itemid, Position toPos, Position fromPos, int32_t from_stack, unsigned char count)
  9856. {
  9857. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::canDelete()");
  9858.  
  9859. if(itemid == 99 || (itemid >= 4329 && itemid <= 4555))
  9860. return false;
  9861. else if(fromPos.x != 0xFFFF && ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  9862. return false;
  9863. else if(map->canThrowObjectTo(player->pos, toPos, BLOCK_PROJECTILE) != RET_NOERROR)
  9864. return false;
  9865. else if(toPos.x == 0xFFFF)
  9866. return false;
  9867. else if((player->access < g_config.ACCESS_REMOTE) &&
  9868. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  9869. return false;
  9870.  
  9871. Item* trash = dynamic_cast<Item*>(getThing(fromPos, from_stack, player));
  9872. if(trash){
  9873. trash->pos = fromPos;
  9874. if((abs(player->pos.x - toPos.x) > trash->throwRange) || (abs(player->pos.y - toPos.y) > trash->throwRange)) {
  9875. return false;
  9876. }
  9877.  
  9878. Tile *toTile = map->getTile(toPos);
  9879. if(toTile){
  9880. 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)){
  9881. if(!trash->isNotMoveable() && trash->isBlocking())
  9882. return false;
  9883. else if(trashObjects(player, toTile, trash, toPos, fromPos, from_stack, count))
  9884. return true;
  9885. }
  9886. Item *toItem = dynamic_cast<Item*>(toTile->getTopTopItem());
  9887.  
  9888. if(toItem && toItem->getID() == ITEM_DUSTBIN){
  9889. if(!trash->isNotMoveable() && trash->isBlocking())
  9890. return false;
  9891. else if(trashObjects(player, toTile, trash, toPos, fromPos, from_stack, count))
  9892. return true;
  9893. }
  9894. }
  9895. }
  9896.  
  9897. return false;
  9898. }
  9899.  
  9900. bool Game::trashObjects(Player *player, Tile *toTile, Item *trash, Position toPos, Position fromPos, int32_t from_stack, unsigned char count)
  9901. {
  9902. //OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::trashObjects()");
  9903.  
  9904. if(!player || !toTile || !trash || !from_stack || !count){
  9905. return false;}
  9906.  
  9907. if(toTile){
  9908. switch(toTile->ground->getID()){
  9909. case GROUND_WATER1:
  9910. case GROUND_WATER2:
  9911. case GROUND_WATER3:
  9912. case GROUND_WATER4:
  9913. case GROUND_WATER5:
  9914. case GROUND_WATER6:
  9915. case GROUND_WATER7:
  9916. case GROUND_WATER8:
  9917. case GROUND_WATER9:
  9918. case GROUND_WATER10:
  9919. case GROUND_WATER11:
  9920. case GROUND_WATER12:
  9921. case GROUND_WATER13:
  9922. case GROUND_WATER14:
  9923. case GROUND_WATER15:
  9924. case GROUND_WATER16:
  9925. case GROUND_WATER17:
  9926. case GROUND_WATER18:
  9927. case GROUND_WATER19:
  9928. case GROUND_WATER20:
  9929. case GROUND_WATER21:
  9930. case GROUND_WATER22:
  9931. case GROUND_WATER23:
  9932. case GROUND_WATER24:
  9933. case GROUND_WATER25:
  9934. case GROUND_WATER26:
  9935. case GROUND_WATER27:
  9936. case GROUND_WATER28:
  9937. case GROUND_WATER29:
  9938. case GROUND_WATER30:
  9939. case GROUND_WATER31:
  9940. case GROUND_WATER32:
  9941. case GROUND_WATER33:
  9942. case GROUND_WATER34:
  9943. case GROUND_WATER35:
  9944. case GROUND_WATER36:
  9945. case GROUND_WATER37:
  9946. case GROUND_WATER38:
  9947. case GROUND_WATER39:
  9948. case GROUND_WATER40:
  9949. case GROUND_WATER41:
  9950. case GROUND_WATER42:
  9951. case GROUND_WATER43:
  9952. case GROUND_WATER44:
  9953. spectatorEffect(toPos, NM_ME_LOOSE_ENERGY);
  9954. if(trashItems(player, trash, fromPos, from_stack, count))
  9955. return true;
  9956. break;
  9957. case GROUND_LAVA1:
  9958. case GROUND_LAVA2:
  9959. case GROUND_LAVA3:
  9960. case GROUND_LAVA4:
  9961. spectatorEffect(toPos, NM_ME_HITBY_FIRE);
  9962. if(trashItems(player, trash, fromPos, from_stack, count))
  9963. return true;
  9964. break;
  9965. case GROUND_SWAMP1:
  9966. case GROUND_SWAMP2:
  9967. case GROUND_SWAMP3:
  9968. case GROUND_SWAMP4:
  9969. spectatorEffect(toPos, NM_ME_POISEN_RINGS);
  9970. if(trashItems(player, trash, fromPos, from_stack, count))
  9971. return true;
  9972. break;
  9973. case GROUND_BLACK_SWAMP1:
  9974. case GROUND_BLACK_SWAMP2:
  9975. case GROUND_BLACK_SWAMP3:
  9976. case GROUND_BLACK_SWAMP4:
  9977. spectatorEffect(toPos, NM_ME_MORT_AREA);
  9978. if(trashItems(player, trash, fromPos, from_stack, count))
  9979. return true;
  9980. break;
  9981. }
  9982. }
  9983.  
  9984. return false;
  9985. }
  9986.  
  9987. bool Game::trashItems(Player *player, Item *trash, Position fromPos, int32_t from_stack, unsigned char count)
  9988. {
  9989. //OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::trashItems()");
  9990. if(!trash){return false;}
  9991. if(trash->getID() == 99 || (trash->getID() >= 4329 && trash->getID() <= 4555))
  9992. return false;
  9993. else if(fromPos.x != 0xFFFF && ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  9994. return false;
  9995. else if((player->access < g_config.ACCESS_REMOTE) &&
  9996. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  9997. return false;
  9998.  
  9999. if(trash && player){
  10000. if(trash->isStackable()){
  10001. if(trash->getItemCountOrSubtype() > count){
  10002. trash->setItemCountOrSubtype(trash->getItemCountOrSubtype() - count);
  10003. sendUpdateThing(player,fromPos,trash,from_stack);
  10004. player->updateInventoryWeigth();
  10005. return true;
  10006. }
  10007. else{
  10008. if(removeThing(player, fromPos, trash)){
  10009. player->updateInventoryWeigth();
  10010. return true;
  10011. }
  10012. }
  10013. }
  10014. else{
  10015. if(removeThing(player, fromPos, trash)){
  10016. player->updateInventoryWeigth();
  10017. return true;
  10018. }
  10019. }
  10020. }
  10021. return false;
  10022. }
  10023.  
  10024. bool Game::canTeleportItem(Player *player, unsigned short itemid, Position toPos, Position fromPos, int32_t from_stack, unsigned char count)
  10025. {
  10026. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::canTeleportItem()");
  10027.  
  10028. if(itemid == 99 || (itemid >= 4329 && itemid <= 4555))
  10029. return false;
  10030. else if(fromPos.x != 0xFFFF && ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  10031. return false;
  10032. else if(map->canThrowObjectTo(player->pos, toPos, BLOCK_PROJECTILE) != RET_NOERROR)
  10033. return false;
  10034. else if(toPos.x == 0xFFFF)
  10035. return false;
  10036. else if(!checkChangeFloor(map->getTile(toPos), getTile(toPos.x,toPos.y,toPos.z+1)))
  10037. return false;
  10038. else if((player->access < g_config.ACCESS_REMOTE) &&
  10039. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  10040. return false;
  10041.  
  10042. Item* tpItem = dynamic_cast<Item*>(getThing(fromPos, from_stack, player));
  10043. if(tpItem){
  10044. tpItem->pos = fromPos;
  10045. if((abs(player->pos.x - toPos.x) > tpItem->throwRange) || (abs(player->pos.y - toPos.y) > tpItem->throwRange)) {
  10046. return false;
  10047. }
  10048.  
  10049. if(tpItem->isStackable()){
  10050. if(tpItem->getItemCountOrSubtype() > count){
  10051. tpItem->setItemCountOrSubtype(tpItem->getItemCountOrSubtype() - count);
  10052. Item *newitem = Item::CreateItem(tpItem->getID(), count);
  10053. addThing(player,getTeleportPos(toPos),newitem);
  10054. sendUpdateThing(player,fromPos,tpItem,from_stack);
  10055. player->updateInventoryWeigth();
  10056. return true;
  10057. }
  10058. else{
  10059. if(removeThing(player, fromPos, tpItem)){
  10060. addThing(player,getTeleportPos(toPos),tpItem);
  10061. player->updateInventoryWeigth();
  10062. return true;
  10063. }
  10064. }
  10065. }
  10066. else{
  10067. if(removeThing(player, fromPos, tpItem)){
  10068. addThing(player,getTeleportPos(toPos),tpItem);
  10069. player->updateInventoryWeigth();
  10070. return true;
  10071. }
  10072. }
  10073. }
  10074. return false;
  10075. }
  10076.  
  10077. void Game::spectatorEffect(Position pos, unsigned char type)
  10078. {
  10079. SpectatorVec list;
  10080. SpectatorVec::iterator it;
  10081. getSpectators(Range(pos, true), list);
  10082.  
  10083. for(it = list.begin(); it != list.end(); ++it) {
  10084. if(Player* p = dynamic_cast<Player*>(*it)) {
  10085. p->sendMagicEffect(pos, type);
  10086. }
  10087. }
  10088. }
  10089.  
  10090. bool Game::checkChangeFloor(Tile *toTile, Tile* downTile)
  10091. {
  10092. if(toTile->ground && toTile->ground->floorChangeDown())
  10093. {
  10094. if(downTile){
  10095. if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  10096. return true;
  10097. }
  10098. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  10099. return true;
  10100. }
  10101. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  10102. return true;
  10103. }
  10104. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  10105. return true;
  10106. }
  10107. else if(downTile->floorChange(NORTH)){
  10108. return true;
  10109. }
  10110. else if(downTile->floorChange(SOUTH)){
  10111. return true;
  10112. }
  10113. else if(downTile->floorChange(EAST)){
  10114. return true;
  10115. }
  10116. else if(downTile->floorChange(WEST)){
  10117. return true;
  10118. }
  10119. else if(Item::items[toTile->ground->getID()].floorChangeDown){
  10120. return true;
  10121. }
  10122. else {
  10123. return true;
  10124. }
  10125. }
  10126. }
  10127. else if(toTile->floorChange(NORTH) && toTile->floorChange(EAST)){
  10128. return true;
  10129. }
  10130. else if(toTile->floorChange(NORTH) && toTile->floorChange(WEST)){
  10131. return true;
  10132. }
  10133. else if(toTile->floorChange(SOUTH) && toTile->floorChange(EAST)){
  10134. return true;
  10135. }
  10136. else if(toTile->floorChange(SOUTH) && toTile->floorChange(WEST)){
  10137. return true;
  10138. }
  10139. else if(toTile->floorChange(NORTH)){
  10140. return true;
  10141. }
  10142. else if(toTile->floorChange(SOUTH)){
  10143. return true;
  10144. }
  10145. else if(toTile->floorChange(EAST)){
  10146. return true;
  10147. }
  10148. else if(toTile->floorChange(WEST)){
  10149. return true;
  10150. }
  10151. if(!toTile){
  10152. if(!downTile)
  10153. {
  10154. return false;
  10155. }
  10156. else if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  10157. return true;
  10158. }
  10159. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  10160. return true;
  10161. }
  10162. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  10163. return true;
  10164. }
  10165. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  10166. return true;
  10167. }
  10168. else if(downTile->floorChange(NORTH)){
  10169. return true;
  10170. }
  10171. else if(downTile->floorChange(SOUTH)){
  10172. return true;
  10173. }
  10174. else if(downTile->floorChange(EAST)){
  10175. return true;
  10176. }
  10177. else if(downTile->floorChange(WEST)){
  10178. return true;
  10179. }
  10180. }
  10181. return false;
  10182. }
  10183.  
  10184. Position Game::getTeleportPos(Position to)
  10185. {
  10186. Tile *toTile = map->getTile(to);
  10187.  
  10188. if(toTile->ground && toTile->ground->floorChangeDown())
  10189. {
  10190. Tile* downTile = getTile(to.x, to.y, to.z+1);
  10191. if(downTile){
  10192. //diagonal begin
  10193. if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  10194. return Position(to.x-1, to.y+1, to.z+1);
  10195. }
  10196. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  10197. return Position(to.x+1, to.y+1, to.z+1);
  10198. }
  10199. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  10200. return Position(to.x-1, to.y-1, to.z+1);
  10201. }
  10202. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  10203. return Position(to.x+1, to.y-1, to.z+1);
  10204. }
  10205. //diagonal end
  10206. else if(downTile->floorChange(NORTH)){
  10207. return Position(to.x, to.y+1, to.z+1);
  10208. }
  10209. else if(downTile->floorChange(SOUTH)){
  10210. return Position(to.x, to.y-1, to.z+1);
  10211. }
  10212. else if(downTile->floorChange(EAST)){
  10213. return Position(to.x-1, to.y, to.z+1);
  10214. }
  10215. else if(downTile->floorChange(WEST)){
  10216. return Position(to.x+1, to.y, to.z+1);
  10217. }
  10218. //floor change down
  10219. else if(Item::items[toTile->ground->getID()].floorChangeDown){
  10220. return Position(to.x, to.y, to.z+1);
  10221. }
  10222. else {
  10223. return Position(to.x, to.y, to.z+1);
  10224. }
  10225. }
  10226. }
  10227. //diagonal begin
  10228. else if(toTile->floorChange(NORTH) && toTile->floorChange(EAST)){
  10229. return Position(to.x+1, to.y-1, to.z-1);
  10230. }
  10231. else if(toTile->floorChange(NORTH) && toTile->floorChange(WEST)){
  10232. return Position(to.x-1, to.y-1, to.z-1);
  10233. }
  10234. else if(toTile->floorChange(SOUTH) && toTile->floorChange(EAST)){
  10235. return Position(to.x+1, to.y+1, to.z-1);
  10236. }
  10237. else if(toTile->floorChange(SOUTH) && toTile->floorChange(WEST)){
  10238. return Position(to.x-1, to.y+1, to.z-1);
  10239. }
  10240. else if(toTile->floorChange(NORTH)){
  10241. return Position(to.x, to.y-1, to.z-1);
  10242. }
  10243. else if(toTile->floorChange(SOUTH)){
  10244. return Position(to.x, to.y+1, to.z-1);
  10245. }
  10246. else if(toTile->floorChange(EAST)){
  10247. return Position(to.x+1, to.y, to.z-1);
  10248. }
  10249. else if(toTile->floorChange(WEST)){
  10250. return Position(to.x-1, to.y, to.z-1);
  10251. }
  10252. if(!toTile){
  10253. Tile* downTile = getTile(to.x, to.y, to.z+1);
  10254. if(!downTile)
  10255. {
  10256. return Position(0,0,0);
  10257. }
  10258. else if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  10259. return Position(to.x-2, to.y+2, to.z+1);
  10260. }
  10261. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  10262. return Position(to.x+2, to.y+2, to.z+1);
  10263. }
  10264. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  10265. return Position(to.x-2, to.y-2, to.z+1);
  10266. }
  10267. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  10268. return Position(to.x+2, to.y-2, to.z+1);
  10269. }
  10270. else if(downTile->floorChange(NORTH)){
  10271. return Position(to.x, to.y + 1, to.z+1);
  10272. }
  10273. else if(downTile->floorChange(SOUTH)){
  10274. return Position(to.x, to.y - 1, to.z+1);
  10275. }
  10276. else if(downTile->floorChange(EAST)){
  10277. return Position(to.x - 1, to.y, to.z+1);
  10278. }
  10279. else if(downTile->floorChange(WEST)){
  10280. return Position(to.x + 1, to.y, to.z+1);
  10281. }
  10282. }
  10283. }
  10284. #endif //KOSZ
  10285.  
  10286. void Game::globalMagicEffect(const Position pos, unsigned char type)
  10287. {
  10288. SpectatorVec list;
  10289. SpectatorVec::iterator it;
  10290. getSpectators(Range(pos), list);
  10291. for(it = list.begin(); it != list.end(); ++it){
  10292. Player* p = dynamic_cast<Player*>(*it);
  10293. if(p)
  10294. p->sendMagicEffect(pos, type);
  10295. }
  10296. }
  10297.  
  10298. void Game::checkCreatureFollow(uint32_t id)
  10299. {
  10300. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreatureFollow");
  10301. Player *player = getPlayerByID(id);
  10302. if(!player)
  10303. return;
  10304. if(!player->pathList.empty()) {
  10305. Creature *followCreature = getCreatureByID(player->followCreature);
  10306. if(followCreature == 0)
  10307. return;
  10308. if((std::abs(player->pos.x - followCreature->pos.x) > 7) ||
  10309. (std::abs(player->pos.y - followCreature->pos.y) > 5) || (player->pos.z != followCreature->pos.z)){
  10310. player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  10311. player->eventCheckFollow = 0;
  10312. player->followCreature = 0;
  10313. playerSetAttackedCreature(player, 0);
  10314. return;
  10315. }
  10316. if(followCreature && abs(followCreature->pos.x - player->pos.x) <= 1 && abs(followCreature->pos.y - player->pos.y) <= 1) player->pathList.clear();
  10317. else {
  10318. Position toPos = player->pathList.front();
  10319. player->pathList.pop_front();
  10320. player->lastmove = OTSYS_TIME();
  10321. this->thingMove(player, player, toPos.x, toPos.y, player->pos.z, 1);
  10322. flushSendBuffers();
  10323. }
  10324. }
  10325. if(!player->pathList.empty()) {
  10326. long long delay = player->getSleepTicks();
  10327. stopEvent(player->eventCheckFollow);
  10328. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollow), id)));
  10329. } else {
  10330. player->eventCheckFollow = 0;
  10331. }
  10332. }
  10333. void Game::checkCreatureFollowAttack(uint32_t id)
  10334. {
  10335. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreatureFollowAttack");
  10336. Player *player = getPlayerByID(id);
  10337. if(!player)
  10338. return;
  10339. if(!player->pathList.empty()) {
  10340. Creature *followCreature = getCreatureByID(player->followCreature);
  10341. if(followCreature == 0)
  10342. return;
  10343. if(player->followMode == 0x00) {
  10344. stopEvent(player->eventCheckFollow);
  10345. player->eventCheckFollow = 0;
  10346. player->followCreature = 0;
  10347. return;
  10348. }
  10349. if((std::abs(player->pos.x - followCreature->pos.x) > 7) ||
  10350. (std::abs(player->pos.y - followCreature->pos.y) > 5) || (player->pos.z != followCreature->pos.z)){
  10351. player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  10352. player->eventCheckFollow = 0;
  10353. player->followCreature = 0;
  10354. playerSetAttackedCreature(player, 0);
  10355. return;
  10356. }
  10357. if(followCreature && abs(followCreature->pos.x - player->pos.x) <= 1 && abs(followCreature->pos.y - player->pos.y) <= 1) player->pathList.clear();
  10358. else {
  10359. Position toPos = player->pathList.front();
  10360. player->pathList.pop_front();
  10361. player->lastmove = OTSYS_TIME();
  10362. this->thingMove(player, player, toPos.x, toPos.y, player->pos.z, 1);
  10363. flushSendBuffers();
  10364. }
  10365. }
  10366. if(!player->pathList.empty()) {
  10367. long long delay = player->getSleepTicks();
  10368. stopEvent(player->eventCheckFollow);
  10369. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollowAttack), id)));
  10370. } else {
  10371. player->eventCheckFollow = 0;
  10372. }
  10373. }
  10374. void Game::playerFollow(Player* player, Creature *followCreature)
  10375. {
  10376. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerFollow()");
  10377. if(followCreature->isRemoved || player->isRemoved || !player || !followCreature){
  10378. player->eventCheckFollow = 0;
  10379. player->followCreature = 0;
  10380. return;
  10381. }
  10382. player->pathList = getPathToEx(player, player->pos, followCreature->pos, false);
  10383. long long delay = player->getSleepTicks();
  10384. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollow), player->getID())));
  10385. }
  10386. void Game::playerFollowAttacking(Player* player, Creature *followCreature)
  10387. {
  10388. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerFollow()");
  10389. if(followCreature->isRemoved || player->isRemoved || !player || !followCreature){
  10390. player->eventCheckFollow = 0;
  10391. player->followCreature = 0;
  10392. return;
  10393. }
  10394. if(player->followMode == 0x00) {
  10395. stopEvent(player->eventCheckFollow);
  10396. player->eventCheckFollow = 0;
  10397. player->followCreature = 0;
  10398. return;
  10399. }
  10400. player->pathList = getPathToEx(player, player->pos, followCreature->pos, false);
  10401. long long delay = player->getSleepTicks();
  10402. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollowAttack), player->getID())));
  10403. }
  10404. void Game::playerSetFollowCreature(Player* player, uint32_t creatureid)
  10405. {
  10406. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerSetFollowCreature()");
  10407. if(player->isRemoved || !player)
  10408. return;
  10409. if(creatureid == 0) {
  10410. stopEvent(player->eventCheckFollow);
  10411. player->eventCheckFollow = 0;
  10412. player->followCreature = 0;
  10413. }
  10414. Creature* followCreature = NULL;
  10415. if(creatureid != 0) {
  10416. followCreature = getCreatureByID(creatureid);
  10417. }
  10418. if(followCreature) {
  10419. player->followCreature = followCreature->getID();
  10420. stopEvent(player->eventCheckFollow);
  10421. playerFollow(player, followCreature);
  10422. }
  10423. }
  10424. void Game::playerAttackSetFollowCreature(Player* player, uint32_t creatureid)
  10425. {
  10426. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerAttackSetFollowCreature()");
  10427. if(player->isRemoved || !player)
  10428. return;
  10429. if(player->followMode == 0x00) {
  10430. return;
  10431. }
  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. playerFollowAttacking(player, followCreature);
  10445. }
  10446. }
  10447.  
  10448. #ifdef HUCZU_AUTORESTART
  10449. void Game::beforeRestart()
  10450. {
  10451. sheduleShutdown(5);
  10452. }
  10453. #endif
  10454.  
  10455. void Game::creatureUseShop(Creature *creature, int id, int count, std::string way){
  10456. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureUseShop()");
  10457.  
  10458. int stackpos = map->getTile(creature->pos)->getThingStackPos(creature);
  10459.  
  10460. SpectatorVec list;
  10461. SpectatorVec::iterator it;
  10462.  
  10463. map->getSpectators(Range(creature->pos, true), list);
  10464.  
  10465. for(it = list.begin(); it != list.end(); ++it) {
  10466. if(dynamic_cast<Npc*>(*it)) {
  10467. (*it)->onCreatureUseShop(creature, id, count, way);
  10468. }
  10469. }atype
  10470. }
Add Comment
Please, Sign In to add comment