Guest User

Untitled

a guest
Mar 28th, 2020
222
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 348.90 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. }
  121.  
  122. if (necklace && necklace->getCharges() > 0)
  123. {
  124. if (necklace->getID() == ITEM_STONE_SKIN_AMULET)
  125. {
  126. newDamage *= 0.10;
  127. necklace->useCharge();
  128. }
  129.  
  130. else if (necklace->getID() == ITEM_PROTECTION_AMULET)
  131. {
  132. newDamage *= 0.80;
  133. necklace->useCharge();
  134. }
  135.  
  136. else if ((necklace->getID() == ITEM_DRAGON_NECKLACE && (atype & ATTACK_FIRE)) ||
  137. (necklace->getID() == ITEM_SILVER_AMULET && (atype & ATTACK_POISON)) ||
  138. (necklace->getID() == ITEM_STRANGE_TALISMAN && (atype & ATTACK_ENERGY)) ||
  139. (necklace->getID() == ITEM_ELVEN_AMULET))
  140. {
  141. newDamage *= 0.8;
  142. necklace->useCharge();
  143. }
  144.  
  145.  
  146. else if ((necklace->getID() == ITEM_MAGMA_AMULET && (atype & ATTACK_FIRE)))
  147. {
  148. newDamage *= 0.7;
  149. necklace->useCharge();
  150. }
  151.  
  152.  
  153. #ifdef YUR_DRAINS
  154. else if (necklace->getID() == ITEM_BRONZE_AMULET && (atype & ATTACK_MANADRAIN))
  155. {
  156. newDamage *= 0.5;
  157. necklace->useCharge();
  158. }
  159.  
  160. else if (necklace->getID() == ITEM_GARLIC_NECKLACE && (atype & ATTACK_LIFEDRAIN))
  161. {
  162. newDamage = 0.5;
  163. necklace->useCharge();
  164. }
  165.  
  166. #endif //YUR_DRAINS
  167.  
  168. if (necklace->getCharges() <= 0)
  169. player->removeItemInventory(SLOT_NECKLACE);
  170. }
  171.  
  172. if (ring && ring->getCharges() > 0)
  173. {
  174. if (ring->getID() == ITEM_MIGHT_RING)
  175. {
  176. newDamage *= 0.8;
  177. ring->useCharge();
  178. }
  179.  
  180. if (ring->getCharges() <= 0)
  181. player->removeItemInventory(SLOT_RING);
  182. }
  183. #ifdef HUCZU_FIX
  184. if(armor)
  185. {
  186. if(armor->getID() == ITEM_FIRE_ARMOR && (atype & ATTACK_FIRE))
  187. newDamage *= 0.8;
  188. }
  189. #endif //HUCZU_FIX
  190.  
  191. return (int32_t)newDamage;
  192. }
  193. #endif //YUR_RINGS_AMULETS
  194.  
  195. void GameState::onAttack(Creature* attacker, const Position& pos, const MagicEffectClass* me)
  196. {
  197. Tile *tile = game->map->getTile(pos);
  198.  
  199. if(!tile)
  200. return;
  201.  
  202. #ifdef YUR_PVP_ARENA
  203. CreatureVector arenaLosers;
  204. #endif //YUR_PVP_ARENA
  205.  
  206. CreatureVector::iterator cit;
  207. Player* attackPlayer = dynamic_cast<Player*>(attacker);
  208. Creature *targetCreature = NULL;
  209. Player *targetPlayer = NULL;
  210. for(cit = tile->creatures.begin(); cit != tile->creatures.end(); ++cit) {
  211. targetCreature = (*cit);
  212. targetPlayer = dynamic_cast<Player*>(targetCreature);
  213. bool pvpArena = false;
  214. #ifdef TR_SUMMONS
  215. bool targetIsSummon = (targetCreature && targetCreature->isPlayersSummon());
  216. bool summonVsPlayer = (attacker && attacker->isPlayersSummon() && targetPlayer);
  217. #endif //TR_SUMMONS
  218.  
  219. int32_t damage = me->getDamage(targetCreature, attacker);
  220. int32_t manaDamage = 0;
  221.  
  222. if(attackPlayer){
  223. if(!me->offensive && me->minDamage != 0 && g_config.getGlobalString("showHealingDamage") == "yes"){
  224. int32_t lecz = std::min(std::abs(damage), attackPlayer->healthmax - attackPlayer->health);
  225. std::stringstream anidamage;
  226. anidamage << "+" << lecz;
  227. if(lecz != 0)
  228. game->sendAnimatedTextExt(attackPlayer->pos, 96, anidamage.str().c_str());
  229. }
  230. }
  231.  
  232. #ifdef YUR_RINGS_AMULETS
  233. damage = applyAmulets(targetPlayer, damage, me->attackType);
  234. #endif //YUR_RINGS_AMULETS
  235.  
  236. if (damage > 0) {
  237. if(attackPlayer && attackPlayer->access < g_config.ACCESS_PROTECT) {
  238. if(targetPlayer && targetPlayer != attackPlayer && game->getWorldType() != WORLD_TYPE_NO_PVP)
  239. attackPlayer->pzLocked = true;
  240. }
  241.  
  242. if(targetCreature->access < g_config.ACCESS_PROTECT && targetPlayer && game->getWorldType() != WORLD_TYPE_NO_PVP)
  243. {
  244. #ifdef YUR_CVS_MODS
  245. targetPlayer->inFightTicks = std::max(g_config.PZ_LOCKED, targetPlayer->inFightTicks);
  246. #else
  247. targetPlayer->inFightTicks = g_config.PZ_LOCKED;
  248. #endif //YUR_CVS_MODS
  249. targetPlayer->sendIcons();
  250. }
  251. #ifdef SURVIVAL_BLACKSQUARE
  252. if(damage > 0 && attackPlayer && targetPlayer && attackPlayer != targetPlayer){
  253. NetworkMessage attackedpmsg;
  254. attackedpmsg.AddPlayerAttacked(attacker);
  255. targetPlayer->sendNetworkMessage(&attackedpmsg);
  256. }
  257. #endif //SURVIVAL_BLACKSQUARE
  258.  
  259. #ifdef YUR_PVP_ARENA
  260. pvpArena = isPvpArena(attacker) && isPvpArena(targetCreature);
  261. #endif //YUR_PVP_ARENA
  262.  
  263. #ifdef TR_SUMMONS
  264. if ((game->getWorldType() == WORLD_TYPE_NO_PVP && !pvpArena && summonVsPlayer) ||
  265. (game->getWorldType() == WORLD_TYPE_NO_PVP && !pvpArena && attackPlayer && (targetPlayer || targetIsSummon) && attackPlayer->access < g_config.ACCESS_PROTECT)) {
  266. #else
  267. if(game->getWorldType() == WORLD_TYPE_NO_PVP && !pvpArena && attackPlayer && targetPlayer && attackPlayer->access < ACCESS_PROTECT){
  268. #endif //TR_SUMMONS
  269. damage = 0;
  270. }
  271. }
  272.  
  273. if (damage != 0)
  274. {
  275. // Bedzie pro ustawione all
  276. #ifdef HUCZU_FIX
  277. if(attackPlayer){
  278. Item* armor = attackPlayer->getItem(SLOT_ARMOR);
  279. Item* legs = attackPlayer->getItem(SLOT_LEGS);
  280. Item* helmet = attackPlayer->getItem(SLOT_HEAD);
  281. Item* boots = attackPlayer->getItem(SLOT_FEET);
  282. Item* ring = attackPlayer->getItem(SLOT_RING);
  283. Item* amulet = attackPlayer->getItem(SLOT_NECKLACE);
  284.  
  285. if(attackPlayer->vocation == 1 || attackPlayer->vocation == 2){
  286. if(armor){
  287. if(armor->getID() == ITEM_GLACIER_ROBE){
  288. double newdamage = damage*2/100.0;
  289. damage += (int32_t)newdamage;
  290. }
  291. else if(armor->getID() == ITEM_ARCHMAGE_COAT){
  292. double newdamage = damage*5/100.0;
  293. damage += (int32_t)newdamage;
  294. }
  295. else if(armor->getID() == ITEM_BMC){
  296. double newdamage = damage*3/100.0;
  297. damage += (int32_t)newdamage;
  298. }
  299. }
  300. if(legs){
  301. if(legs->getID() == ITEM_GLACIER_KIT){
  302. double newdamage = damage*2/100.0;
  303. damage += (int32_t)newdamage;
  304. }
  305. }
  306. }
  307.  
  308. if(legs){
  309. if(legs->getID() == ITEM_ZS_LEGS){
  310. double newdamage = damage*10/100.0;
  311. damage += (int32_t)newdamage;
  312. }
  313. }
  314.  
  315. if(g_config.MGITEMS){
  316. if(helmet && helmet->getID() == g_config.MGITEMHELMET){
  317. double newdamage = damage*g_config.ITEM_MDOWNHELMET/100.0;
  318. damage += (int32_t)newdamage;
  319. }
  320. if(armor && armor->getID() == g_config.MGITEMARMOR){
  321. double newdamage = damage*g_config.ITEM_MDOWNARMOR/100.0;
  322. damage += (int32_t)newdamage;
  323. }
  324. if(legs && legs->getID() == g_config.MGITEMLEGS){
  325. double newdamage = damage*g_config.ITEM_MDOWNLEGS/100.0;
  326. damage += (int32_t)newdamage;
  327. }
  328. if(boots && boots->getID() == g_config.MGITEMBOOTS){
  329. double newdamage = damage*g_config.ITEM_MDOWNBOOTS/100.0;
  330. damage += (int32_t)newdamage;
  331. }
  332. if(ring && ring->getID() == g_config.MGITEMRINGS){
  333. double newdamage = damage*g_config.ITEM_MDOWNRING/100.0;
  334. damage += (int32_t)newdamage;
  335. }
  336. if(amulet && amulet->getID() == g_config.MGITEMAMU){
  337. double newdamage = damage*g_config.ITEM_MDOWNAMU/100.0;
  338. damage += (int32_t)newdamage;
  339. }
  340. }
  341. }
  342. #endif //HUCZU_FIX i git w chuj
  343.  
  344. #ifdef YUR_DRAINS
  345. if (me->attackType & ATTACK_MANADRAIN)
  346. {
  347. manaDamage = std::min(damage, targetCreature->mana);
  348. targetCreature->drainMana(manaDamage);
  349. damage = 0;
  350. }
  351. else
  352. #endif //YUR_DRAINS
  353. {
  354. game->creatureApplyDamage(targetCreature, damage, damage, manaDamage
  355. #ifdef YUR_PVP_ARENA
  356. , (pvpArena? &arenaLosers : NULL)
  357. #endif //YUR_PVP_ARENA
  358. );
  359. }
  360.  
  361. #ifdef YUR_DRAINS
  362. if (me->attackType & ATTACK_LIFEDRAIN)
  363. {
  364. attacker->health = std::min(attacker->healthmax, attacker->health + damage);
  365. addCreatureState(tile, attacker, 0, 0, false); // update attacker health
  366. }
  367. #endif //YUR_DRAINS
  368.  
  369. #ifdef YUR_INVISIBLE
  370. if (targetCreature && !targetPlayer)
  371. {
  372. targetCreature->setInvisible(0);
  373. game->creatureChangeOutfit(targetCreature);
  374. }
  375. #endif //YUR_INVISIBLE
  376. }
  377.  
  378. #ifdef HUCZU_SKULLS
  379. if (me->offensive && game->getWorldType() == WORLD_TYPE_PVP)
  380. game->onPvP(attacker, targetCreature, targetCreature->health <= 0);
  381. #endif
  382.  
  383. addCreatureState(tile, targetCreature, damage, manaDamage, me->drawblood);
  384. }
  385.  
  386. //Solid ground items/Magic items (fire/poison/energy)
  387. MagicEffectItem *newmagicItem = me->getMagicItem(attacker, tile->isPz(),
  388. (tile->isBlocking(BLOCK_SOLID, true) != RET_NOERROR));
  389.  
  390. if(newmagicItem) {
  391.  
  392. MagicEffectItem *magicItem = tile->getFieldItem();
  393.  
  394. if(magicItem) {
  395. //Replace existing magic field
  396. magicItem->transform(newmagicItem);
  397.  
  398. int32_t stackpos = tile->getThingStackPos(magicItem);
  399. if(tile->removeThing(magicItem)) {
  400.  
  401. SpectatorVec list;
  402. SpectatorVec::iterator it;
  403.  
  404. game->getSpectators(Range(pos, true), list);
  405.  
  406. //players
  407. for(it = list.begin(); it != list.end(); ++it) {
  408. if(dynamic_cast<Player*>(*it)) {
  409. (*it)->onThingDisappear(magicItem, stackpos);
  410. }
  411. }
  412.  
  413. //none-players
  414. for(it = list.begin(); it != list.end(); ++it) {
  415. if(!dynamic_cast<Player*>(*it)) {
  416. (*it)->onThingDisappear(magicItem, stackpos);
  417. }
  418. }
  419.  
  420. tile->addThing(magicItem);
  421.  
  422. //players
  423. for(it = list.begin(); it != list.end(); ++it) {
  424. if(dynamic_cast<Player*>(*it)) {
  425. (*it)->onThingAppear(magicItem);
  426. }
  427. }
  428.  
  429. //none-players
  430. for(it = list.begin(); it != list.end(); ++it) {
  431. if(!dynamic_cast<Player*>(*it)) {
  432. (*it)->onThingAppear(magicItem);
  433. }
  434. }
  435. }
  436. }
  437. else {
  438. magicItem = new MagicEffectItem(*newmagicItem);
  439. magicItem->useThing();
  440. magicItem->pos = pos;
  441.  
  442. tile->addThing(magicItem);
  443.  
  444. SpectatorVec list;
  445. SpectatorVec::iterator it;
  446.  
  447. game->getSpectators(Range(pos, true), list);
  448.  
  449. //players
  450. for(it = list.begin(); it != list.end(); ++it) {
  451. if(dynamic_cast<Player*>(*it)) {
  452. (*it)->onThingAppear(magicItem);
  453. }
  454. }
  455.  
  456. //none-players
  457. for(it = list.begin(); it != list.end(); ++it) {
  458. if(!dynamic_cast<Player*>(*it)) {
  459. (*it)->onThingAppear(magicItem);
  460. }
  461. }
  462.  
  463. magicItem->isRemoved = false;
  464. game->startDecay(magicItem);
  465. }
  466. }
  467.  
  468. //Clean up
  469. for(CreatureStateVec::const_iterator csIt = creaturestates[tile].begin(); csIt != creaturestates[tile].end(); ++csIt) {
  470. onAttackedCreature(tile, attacker, csIt->first, csIt->second.damage, csIt->second.drawBlood);
  471. }
  472.  
  473. if(attackPlayer && attackPlayer->access < g_config.ACCESS_PROTECT) {
  474. //Add exhaustion
  475. if(me->causeExhaustion(true) /*!areaTargetVec.empty())*/)
  476. {
  477. attackPlayer->exhaustedTicks = g_config.EXHAUSTED;
  478. }
  479.  
  480. //Fight symbol
  481. if(me->offensive /*&& !areaTargetVec.empty()*/)
  482. {
  483. #ifdef YUR_CVS_MODS
  484. attackPlayer->inFightTicks = std::max(g_config.PZ_LOCKED, attackPlayer->inFightTicks);
  485. #else
  486. attackPlayer->inFightTicks = g_config.PZ_LOCKED;
  487. #endif //YUR_CVS_MODS
  488. }
  489. }
  490.  
  491. #ifdef YUR_PVP_ARENA
  492. for (CreatureVector::iterator it = arenaLosers.begin(); it != arenaLosers.end(); ++it)
  493. {
  494. Tile* tile = game->getTile((*it)->pos);
  495.  
  496. if (tile)
  497. {
  498. game->teleport(*it, tile->getPvpArenaExit());
  499. }
  500.  
  501. if(Monster* monster = dynamic_cast<Monster*>(*it))
  502. {
  503. if(Tile *tile = game->map->getTile(monster->pos))
  504. {
  505. if(tile->isPvpArena())
  506. {
  507. game->removeCreature(monster);
  508. }
  509. }
  510. }
  511. }
  512. #endif //YUR_PVP_ARENA
  513. }
  514.  
  515. void GameState::onAttack(Creature* attacker, const Position& pos, Creature* attackedCreature)
  516. {
  517. bool pvpArena = false;
  518. #ifdef YUR_PVP_ARENA
  519. CreatureVector arenaLosers;
  520. pvpArena = isPvpArena(attacker) && isPvpArena(attackedCreature);
  521. #endif //YUR_PVP_ARENA
  522.  
  523. //TODO: Decent formulas and such...
  524. int32_t damage = attacker->getWeaponDamage();
  525. int32_t armor = attackedCreature->getArmor();
  526. int32_t defense = attackedCreature->getDefense();
  527.  
  528. Player* attackPlayer = dynamic_cast<Player*>(attacker);
  529. Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  530.  
  531. if(attackedPlayer)
  532. attackedPlayer->addSkillShieldTry(1);
  533.  
  534. int32_t probability = rand() % 10000;
  535.  
  536. #ifdef YUR_CVS_MODS
  537. if(probability * damage < defense * 3000)
  538. damage = 0;
  539. else
  540. damage -= (int32_t)((damage*(armor/50.0)*(rand()/(RAND_MAX+1.0))) + (armor*2) + defense/1.5);
  541. //damage -= (int32_t)((armor)*(rand()/(RAND_MAX+1.0))) + armor; // wik's
  542. #else
  543. if(probability * damage < defense * 10000)
  544. damage = 0;
  545. else
  546. {
  547. damage -= (armor * (10000 + rand() % 10000)) / 10000;
  548. }
  549. #endif //YUR_CVS_MODS
  550.  
  551. int32_t manaDamage = 0;
  552.  
  553. if(attackPlayer && attackedPlayer){
  554. damage -= (int32_t) damage / 2;
  555. }
  556.  
  557.  
  558. if (attacker->access >= g_config.ACCESS_PROTECT)
  559. damage += 1;
  560.  
  561.  
  562. Tile* tile = game->map->getTile(pos);
  563. bool blood;
  564. if(damage > 0)
  565. {
  566. // F-AXE,F-SWORD,P-DAGGER
  567. if(attackPlayer)
  568. {
  569. for (int32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++)
  570. {
  571. if(g_config.EFFECT_ATACK && attackPlayer->getItem(slot) && (attackPlayer->getItem(slot)->getID() == ITEM_FAXE || attackPlayer->getItem(slot)->getID() == ITEM_FSWORD))
  572. {
  573. game->CreateCondition(attackedCreature, attacker, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 5, 5, 2000, 1);
  574. }
  575. if(g_config.EFFECT_ATACK && attackPlayer->getItem(slot) && (attackPlayer->getItem(slot)->getID() == ITEM_PD))
  576. {
  577. game->CreateCondition(attackedCreature, attacker, 30, NM_ME_POISEN_RINGS, NM_ME_POISEN_RINGS, ATTACK_POISON, true, 5, 5, 2000, 3);
  578. }
  579. }
  580. }
  581.  
  582. // P-BOLT ENERGY
  583. if(attackPlayer)
  584. {
  585. int32_t slot = SLOT_AMMO;
  586. if(g_config.EFFECT_ATACK && attackPlayer->getItem(slot) && (attackPlayer->getItem(slot)->getID() == 5260))
  587. {
  588. game->CreateCondition(attackedCreature, attacker, 35, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 10, 10, 2000, 1);
  589. }
  590. }
  591.  
  592. #ifdef YUR_ICE_RAPIER
  593. if (attackPlayer)
  594. for (int32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++)
  595. if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->getID() == ITEM_ICE_RAPIER)
  596. attackPlayer->removeItemInventory(slot);
  597. #endif //YUR_ICE_RAPIER
  598.  
  599. #ifdef PALL_REQ_LVL
  600. if (attackPlayer){
  601. for (int32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++){
  602. if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->isWeapon() && attackPlayer->getItem(slot)->getReqLevel() > attackPlayer->getLevel())
  603. {
  604. int32_t newdamage = attackPlayer->getWeaponDamage() / random_range(4, 7);
  605. if (attackPlayer->getWeaponDamage() >= 7)
  606. damage = 0;
  607. else
  608. damage = newdamage;
  609. }
  610. if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->getAmuType() != 0 && attackPlayer->getItem(slot)->getReqLevel() > attackPlayer->getLevel())
  611. {
  612. int32_t newdamage = attackPlayer->getWeaponDamage() / random_range(4, 7);
  613. if (attackPlayer->getWeaponDamage() >= 7)
  614. damage = 0;
  615. else
  616. damage = newdamage;
  617. }
  618. if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->isWeapon() && attackPlayer->getItem(slot)->getReqVoc() != attackPlayer->getVocation() && attackPlayer->getItem(slot)->getReqVoc() > 0)
  619. {
  620. int32_t newdamage = attackPlayer->getWeaponDamage() / random_range(4, 9);
  621. if (attackPlayer->getWeaponDamage() >= 7)
  622. damage = 0;
  623. else
  624. damage = newdamage;
  625. }
  626. }
  627. }
  628. #endif //PALL_REQ_LVL
  629.  
  630. #ifdef YUR_RINGS_AMULETS
  631. damage = applyAmulets(attackedPlayer, damage, ATTACK_PHYSICAL);
  632. #endif //YUR_RINGS_AMULETS
  633.  
  634.  
  635. #ifdef CHRIS_CRIT_HIT
  636. if(attackPlayer){
  637. int32_t critcial_hit;
  638. int32_t rand_hit = random_range(0, 700);
  639. switch(rand_hit){
  640. case 75:
  641. critcial_hit = random_range(50, 100);
  642. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  643. break;
  644. case 87:
  645. critcial_hit = random_range(50, 100);
  646. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  647. break;
  648. case 95:
  649. critcial_hit = random_range(50, 100);
  650. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  651. break;
  652. case 113:
  653. critcial_hit = random_range(80, 130);
  654. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  655. break;
  656. case 128:
  657. critcial_hit = random_range(80, 130);
  658. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  659. break;
  660. case 133:
  661. critcial_hit = random_range(80, 130);
  662. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  663. break;
  664. case 145:
  665. critcial_hit = random_range(80, 130);
  666. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  667. break;
  668. case 157:
  669. critcial_hit = random_range(80, 130);
  670. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  671. break;
  672. case 167:
  673. critcial_hit = random_range(80, 130);
  674. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  675. break;
  676. case 187:
  677. critcial_hit = random_range(80, 130);
  678. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  679. break;
  680. case 195:
  681. critcial_hit = random_range(80, 130);
  682. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  683. break;
  684. case 202:
  685. critcial_hit = random_range(110, 160);
  686. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  687. break;
  688. case 225:
  689. critcial_hit = random_range(110, 160);
  690. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  691. break;
  692. case 238:
  693. critcial_hit = random_range(110, 160);
  694. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  695. break;
  696. case 245:
  697. critcial_hit = random_range(110, 160);
  698. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  699. break;
  700. case 268:
  701. critcial_hit = random_range(110, 160);
  702. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  703. break;
  704. case 287:
  705. critcial_hit = random_range(110, 160);
  706. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  707. break;
  708. case 298:
  709. critcial_hit = random_range(110, 160);
  710. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  711. break;
  712. case 324:
  713. critcial_hit = random_range(140, 400);
  714. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  715. break;
  716. case 356:
  717. critcial_hit = random_range(140, 190);
  718. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  719. break;
  720. case 371:
  721. critcial_hit = random_range(140, 190);
  722. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  723. break;
  724. case 380:
  725. critcial_hit = random_range(140, 190);
  726. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  727. break;
  728. case 397:
  729. critcial_hit = random_range(140, 190);
  730. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  731. break;
  732. case 399:
  733. critcial_hit = random_range(140, 190);
  734. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  735. break;
  736. case 400:
  737. critcial_hit = random_range(170, 210);
  738. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  739. break;
  740. case 428:
  741. critcial_hit = random_range(170, 210);
  742. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  743. break;
  744. case 432:
  745. critcial_hit = random_range(170, 210);
  746. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  747. break;
  748. case 444:
  749. critcial_hit = random_range(170, 210);
  750. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  751. break;
  752. case 474:
  753. critcial_hit = random_range(170, 210);
  754. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  755. break;
  756. default:
  757. critcial_hit = 0;
  758. break;
  759. }
  760.  
  761. if (attackPlayer->vocation == 4){
  762. if(critcial_hit != 0){
  763. if(attackPlayer->level >= 150){
  764. if(attackPlayer && attackPlayer->items[SLOT_RIGHT] && attackPlayer->items[SLOT_RIGHT]->getID() == ITEM_RAINBOW){
  765. if(attackPlayer->items[SLOT_LEFT]){
  766. if(attackPlayer->items[SLOT_LEFT]->getID() != ITEM_RAINBOW)
  767. critcial_hit += critcial_hit*(25/100);
  768. game->CreateCondition(attackedCreature, attacker, 35, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 25, 25, 1000, 1);
  769. }
  770. }
  771. }
  772. if(attackPlayer && attackPlayer->items[SLOT_LEFT] && attackPlayer->items[SLOT_LEFT]->getID() == ITEM_RAINBOW){
  773. if(attackPlayer->items[SLOT_RIGHT]){
  774. if(attackPlayer->items[SLOT_RIGHT]->getID() != ITEM_RAINBOW)
  775. critcial_hit += critcial_hit*(25/100);
  776. game->CreateCondition(attackedCreature, attacker, 35, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 25, 25, 1000, 1);
  777. }
  778. }
  779. }
  780. damage += critcial_hit;
  781. }
  782. }
  783.  
  784. #endif //CHRIS_CRIT_HIT
  785.  
  786. game->creatureApplyDamage(attackedCreature, damage, damage, manaDamage
  787.  
  788.  
  789. #ifdef YUR_PVP_ARENA
  790. , (pvpArena? &arenaLosers : NULL)
  791. #endif //YUR_PVP_ARENA
  792. );
  793.  
  794. #ifdef HUCZU_SKULLS
  795. if (game->getWorldType() == WORLD_TYPE_PVP)
  796. game->onPvP(attacker, attackedCreature, attackedCreature->health <= 0);
  797. #endif
  798.  
  799. blood = true;
  800.  
  801. if(attackPlayer && attackPlayer->maxDmg < damage) {
  802. attackPlayer->maxDmg = (int32_t) damage;
  803. std::stringstream MaxDmgMsg;
  804. MaxDmgMsg << "Your new best damage is " << attackPlayer->maxDmg << ".";
  805. attackPlayer->sendTextMessage(MSG_ADVANCE, MaxDmgMsg.str().c_str());
  806. }
  807. }
  808. else{//no draw blood
  809. blood = false;
  810. }
  811.  
  812. addCreatureState(tile, attackedCreature, damage, manaDamage, blood);
  813. onAttackedCreature(tile, attacker, attackedCreature, damage, true);
  814.  
  815. /*
  816. if (attackPlayer && attackPlayer->isUsingSpears() && random_range(1,100000) > g_config.SPEAR_LOSE_CHANCE)
  817. {
  818. Item* spear = Item::CreateItem(ITEM_SPEAR, 1);
  819. spear->pos = attackedCreature->pos;
  820. game->addThing(attackPlayer, spear->pos, spear);
  821. }
  822. */
  823.  
  824. #ifdef YUR_PVP_ARENA
  825. for (CreatureVector::iterator it = arenaLosers.begin(); it != arenaLosers.end(); ++it){
  826. Tile* tile = game->getTile((*it)->pos);
  827. if (tile){
  828. game->teleport(*it, tile->getPvpArenaExit());
  829. }
  830. if(Monster* monster = dynamic_cast<Monster*>(*it)){
  831. if(Tile *tile = game->map->getTile(monster->pos)){
  832. if(tile->isPvpArena()){
  833. game->removeCreature(monster);
  834. }
  835. }
  836. }
  837. }
  838. #endif //YUR_PVP_ARENA
  839. }
  840.  
  841. void GameState::addCreatureState(Tile* tile, Creature* attackedCreature, int32_t damage, int32_t manaDamage, bool drawBlood)
  842. {
  843. CreatureState cs;
  844. cs.damage = damage;
  845. cs.manaDamage = manaDamage;
  846. cs.drawBlood = drawBlood;
  847.  
  848. creaturestates[tile].push_back( make_pair(attackedCreature, cs) );
  849. }
  850.  
  851. void GameState::onAttackedCreature(Tile* tile, Creature *attacker, Creature* attackedCreature, int32_t damage, bool drawBlood)
  852. {
  853. Player *attackedplayer = dynamic_cast<Player*>(attackedCreature);
  854. Position CreaturePos = attackedCreature->pos;
  855.  
  856. #ifdef TJ_MONSTER_BLOOD
  857. bool dead = false;
  858. #endif //TJ_MONSTER_BLOOD
  859.  
  860. #ifdef TR_SUMMONS
  861. //Summon exp share by Yurez
  862. Player *player = dynamic_cast<Player*>(attacker);
  863. Creature* attackerMaster = attacker? attacker->getMaster() : NULL;
  864. if(attackerMaster && dynamic_cast<Player*>(attackerMaster)){//attacker is players summon
  865. attackedCreature->addInflictedDamage(attacker, damage/2);
  866. attackedCreature->addInflictedDamage(attackerMaster, damage/2);
  867. }// end summon exp share
  868. else if(player && player->party != 0){
  869. int32_t partySize = 0;
  870. SpectatorVec list;
  871. SpectatorVec::iterator it;
  872. game->getSpectators(Range(player->pos), list);
  873. /*Get all specatators around this player
  874. then check if they are in his party*/
  875. for(it = list.begin(); it != list.end(); ++it){//find number too div by
  876. Player* p = dynamic_cast<Player*>(*it);
  877. if(p && p->party == player->party)//huczu_fix
  878. partySize++;
  879. }
  880. for(it = list.begin(); it != list.end(); ++it){
  881. Player* p = dynamic_cast<Player*>(*it);
  882. if(p && p->party == player->party && partySize != 0/*dont div by 0*/)//same party add exp, huczu_fix
  883. attackedCreature->addInflictedDamage(p, damage/partySize);
  884. }
  885. }
  886. else
  887. attackedCreature->addInflictedDamage(attacker, damage);
  888. #endif //TR_SUMMONS
  889.  
  890. if(attackedplayer){
  891. attackedplayer->sendStats();
  892. }
  893. //Remove player?
  894. if(attackedCreature->health <= 0 && attackedCreature->isRemoved == false)
  895. {
  896. #ifdef TJ_MONSTER_BLOOD
  897. dead = true;
  898. #endif //TJ_MONSTER_BLOOD
  899. #ifdef JD_DEATH_LIST
  900. if (attackedplayer && attacker)
  901. attackedplayer->addDeath(attacker->getName(), attackedplayer->level, time(0));
  902. #endif //JD_DEATH_LIST
  903. unsigned char stackpos = tile->getThingStackPos(attackedCreature);
  904.  
  905.  
  906. //tasksys
  907. Player* attackingplayer = dynamic_cast<Player*>(attacker);
  908. if(attackingplayer && attackedCreature->getName() == attackingplayer->taskmonster && attackingplayer->taskcount < attackingplayer->taskmax)
  909. {
  910. // attackingplayer->taskcount++;
  911. std::stringstream info;
  912. std::string mons = attackingplayer->taskmonster;
  913. std::transform(mons.begin(), mons.end(), mons.begin(), (int(*)(int))tolower);
  914.  
  915. if(attackingplayer->taskcount < attackingplayer->taskmax)
  916. {
  917. info << "You have killed " << attackingplayer->taskcount << " out of " << attackingplayer->taskmax << " " << mons << "s.";
  918. }
  919. else
  920. {
  921. info << "You have finished task of killing " << mons << "s. ";
  922. }
  923.  
  924. // attackingplayer->sendTextMessage(MSG_ORANGE, info.str().c_str());
  925. }
  926. //tasksys
  927.  
  928. //Prepare body
  929. Item *corpseitem = Item::CreateItem(attackedCreature->getLookCorpse());
  930. corpseitem->pos = CreaturePos;
  931. tile->addThing(corpseitem);
  932.  
  933. #ifdef _DEATH_EVENTS
  934. if (!attackedplayer)
  935. {
  936. Monster* monster = dynamic_cast<Monster*>(attackedCreature);
  937. Player* killer = dynamic_cast<Player*>(attacker);
  938.  
  939. if (killer && monster && monster->getAction())
  940. {
  941. actions.onCreatureKill(killer, attackedCreature, corpseitem, monster->getAction());
  942. }
  943.  
  944. }
  945. #endif //_DEATH_EVENTS
  946.  
  947. #ifdef __MIZIAK_CREATURESCRIPTS__
  948. if(dynamic_cast<Player*>(attacker) && attackedCreature)
  949. actions.creatureEvent("kill", dynamic_cast<Player*>(attacker), attackedCreature, corpseitem, NULL);
  950. #endif //__MIZIAK_CREATURESCRIPTS__
  951.  
  952. //remove creature
  953. if(attackedplayer){
  954. actions.luaWalkOff(attackedplayer,attackedplayer->pos,tile->ground->getID(),tile->ground->getUniqueId(),tile->ground->getActionId()); //CHANGE onWalk
  955. attackedplayer->onThingDisappear(attackedplayer,stackpos);
  956.  
  957. #ifdef __MIZIAK_CREATURESCRIPTS__
  958. attackedplayer->dieorlogout = true;
  959. if(attacker)
  960. actions.creatureEvent("death", attackedplayer, attacker, corpseitem, NULL);
  961. #endif //__MIZIAK_CREATURESCRIPTS__
  962.  
  963.  
  964. attackedplayer->die(); //handles exp/skills/maglevel loss
  965. }
  966.  
  967. //Add eventual loot
  968. Container *lootcontainer = dynamic_cast<Container*>(corpseitem);
  969. if(lootcontainer) {
  970. attackedCreature->dropLoot(lootcontainer);
  971.  
  972. #ifdef HUCZU_LOOT_INFO
  973. Monster* monster = dynamic_cast<Monster*>(attackedCreature);
  974. Player* atakujacy = dynamic_cast<Player*>(attacker);
  975. if(monster && atakujacy){
  976. std::stringstream ss, info;
  977. //info << "Loot of " << monster->getName() << lootcontainer->getContentDescription() << ".";
  978. info << "Loot of " << monster->getName();
  979. ss << lootcontainer->getContentDescription() << ".";
  980. if(atakujacy->party != 0){
  981. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  982. if((*it).second->party == atakujacy->party){
  983. if((*it).second->getID() != atakujacy->getID()){
  984. (*it).second->sendToSpecialChannel(atakujacy, SPEAK_CHANNEL_O, ss.str().c_str(), 0x02, info.str().c_str());
  985. //(*it).second->sendTextMessage(MSG_INFO, info.str().c_str());
  986. }
  987. }
  988. }
  989. }else{
  990. //atakujacy->sendTextMessage(MSG_INFO, info.str().c_str());
  991. atakujacy->sendToSpecialChannel(atakujacy, SPEAK_CHANNEL_O, ss.str().c_str(), 0x02, info.str().c_str());
  992. }
  993. }
  994. #endif //HUCZU_LOOT_INFO
  995. }
  996.  
  997. #ifdef HUCZU_MONSTER_QUEST
  998. Monster* monster = dynamic_cast<Monster*>(attackedCreature);
  999. Player* atakujacy = dynamic_cast<Player*>(attacker);
  1000. int32_t value, kills;
  1001.  
  1002. if(monster && atakujacy && monster->getQuestId() != 0){
  1003.  
  1004. if(monster->getQuestId() == 2 && atakujacy->getStorageValue(100, value) == 1){
  1005. int32_t killsprzed = atakujacy->getQuestKills(2);
  1006. atakujacy->addQuestKills(2, killsprzed+1);
  1007. }
  1008.  
  1009. }
  1010. #endif //HUCZU_MONSTER_QUEST
  1011.  
  1012.  
  1013. game->removeCreature(attackedCreature);
  1014. // Update attackedCreature pos because contains
  1015. // temple position for players
  1016. attackedCreature->pos = CreaturePos;
  1017.  
  1018. //add body
  1019. game->sendAddThing(NULL,corpseitem->pos,corpseitem);
  1020.  
  1021. if(attackedplayer){
  1022. std::stringstream ss;
  1023. ss << corpseitem->getDescription(false);
  1024.  
  1025. ss << "You recognize " << attackedplayer->getName() << ". ";
  1026. if(attacker){
  1027. ss << (attackedplayer->getSex() == PLAYERSEX_FEMALE ? "She" : "He") << " was killed by ";
  1028.  
  1029. Player *attackerplayer = dynamic_cast<Player*>(attacker);
  1030. if(attackerplayer) {
  1031. ss << attacker->getName();
  1032. }
  1033. else {
  1034. std::string creaturename = attacker->getName();
  1035. std::transform(creaturename.begin(), creaturename.end(), creaturename.begin(), (int32_t(*)(int32_t))tolower);
  1036. ss << article(creaturename);
  1037. }
  1038. }
  1039.  
  1040. //set body special description
  1041. corpseitem->setSpecialDescription(ss.str());
  1042. //send corpse to the dead player. It is not in spectator list
  1043. // because was removed
  1044. attackedplayer->onThingAppear(corpseitem);
  1045. }
  1046. game->startDecay(corpseitem);
  1047.  
  1048. //Get all creatures that will gain xp from this kill..
  1049. CreatureState* attackedCreatureState = NULL;
  1050. std::vector<long> creaturelist;
  1051.  
  1052. if(!(dynamic_cast<Player*>(attackedCreature) && game->getWorldType() != WORLD_TYPE_PVP_ENFORCED)){
  1053. creaturelist = attackedCreature->getInflicatedDamageCreatureList();
  1054. CreatureStateVec& creatureStateVec = creaturestates[tile];
  1055. for(CreatureStateVec::iterator csIt = creatureStateVec.begin(); csIt != creatureStateVec.end(); ++csIt) {
  1056. if(csIt->first == attackedCreature) {
  1057. attackedCreatureState = &csIt->second;
  1058. break;
  1059. }
  1060. }
  1061. }
  1062.  
  1063. if(attackedCreatureState) { //should never be NULL..
  1064. //Add experience
  1065. for(std::vector<long>::const_iterator iit = creaturelist.begin(); iit != creaturelist.end(); ++iit) {
  1066. Creature* gainExpCreature = game->getCreatureByID(*iit);
  1067. if(gainExpCreature) {
  1068. exp_t gainedExperience = attackedCreature->getGainedExperience(gainExpCreature);
  1069. if(gainedExperience <= 0)
  1070. continue;
  1071.  
  1072. Player *gainExpPlayer = dynamic_cast<Player*>(gainExpCreature);
  1073.  
  1074. if(gainExpPlayer) {
  1075. gainExpPlayer->addExp(gainedExperience);
  1076. if(gainExpPlayer && attackedCreature->getName() == gainExpPlayer->taskmonster && gainExpPlayer->taskcount < gainExpPlayer->taskmax)
  1077. {
  1078. gainExpPlayer->taskcount++;
  1079. std::stringstream info;
  1080. std::string mons = gainExpPlayer->taskmonster;
  1081. std::transform(mons.begin(), mons.end(), mons.begin(), (int(*)(int))tolower);
  1082.  
  1083. if(gainExpPlayer->taskcount < gainExpPlayer->taskmax)
  1084. {
  1085. info << "You have killed " << gainExpPlayer->taskcount << " out of " << gainExpPlayer->taskmax << " " << mons << "s.";
  1086. }
  1087. else
  1088. {
  1089. info << "You have finished task of killing " << mons << "s. ";
  1090. }
  1091. gainExpPlayer->sendTextMessage(MSG_ORANGE, info.str().c_str());
  1092. }
  1093.  
  1094.  
  1095.  
  1096. }
  1097. //Need to add this creature and all that can see it to spectators, unless they already added
  1098. SpectatorVec creaturelist;
  1099. game->getSpectators(Range(gainExpCreature->pos, true), creaturelist);
  1100.  
  1101. for(SpectatorVec::const_iterator cit = creaturelist.begin(); cit != creaturelist.end(); ++cit) {
  1102. if(std::find(spectatorlist.begin(), spectatorlist.end(), *cit) == spectatorlist.end()) {
  1103. spectatorlist.push_back(*cit);
  1104. }
  1105. }
  1106.  
  1107. //Add creature to attackerlist
  1108. attackedCreatureState->attackerlist.push_back(gainExpCreature);
  1109. }
  1110. }
  1111. }
  1112.  
  1113. Player *player = dynamic_cast<Player*>(attacker);
  1114. if(player){
  1115. player->sendStats();
  1116. }
  1117.  
  1118. if(attackedCreature && attackedCreature->getMaster() != NULL) {
  1119. attackedCreature->getMaster()->removeSummon(attackedCreature);
  1120. }
  1121. }
  1122.  
  1123.  
  1124. //Add blood?
  1125. #ifdef TJ_MONSTER_BLOOD
  1126. if((drawBlood || attackedCreature->health <= 0) && damage > 0 && attackedCreature->bloodsplash != 255) {
  1127. Item* splash = Item::CreateItem(dead? ITEM_POOL : ITEM_SPLASH, attackedCreature->bloodsplash);
  1128. game->addThing(NULL, CreaturePos, splash);
  1129. game->startDecay(splash);
  1130. game->updateTile(CreaturePos);
  1131. }
  1132. #else
  1133. if((drawBlood || attackedCreature->health <= 0) && damage > 0) {
  1134. Item* splash = Item::CreateItem(ITEM_SPLASH, FLUID_BLOOD);
  1135. game->addThing(NULL, CreaturePos, splash);
  1136. game->startDecay(splash);
  1137. game->updateTile(CreaturePos);
  1138. }
  1139. #endif //TJ_MONSTER_BLOOD
  1140. }
  1141.  
  1142.  
  1143. Game::Game()
  1144. {
  1145. eventIdCount = 1000;
  1146. this->game_state = GAME_STATE_NORMAL;
  1147. this->map = NULL;
  1148. this->worldType = WORLD_TYPE_PVP;
  1149. OTSYS_THREAD_LOCKVARINIT(gameLock);
  1150. OTSYS_THREAD_LOCKVARINIT(eventLock);
  1151. OTSYS_THREAD_LOCKVARINIT(AutoID::autoIDLock);
  1152. #if defined __EXCEPTION_TRACER__
  1153. OTSYS_THREAD_LOCKVARINIT(maploadlock);
  1154. #endif
  1155. OTSYS_THREAD_SIGNALVARINIT(eventSignal);
  1156. BufferedPlayers.clear();
  1157. OTSYS_CREATE_THREAD(eventThread, this);
  1158.  
  1159. #ifdef __DEBUG_CRITICALSECTION__
  1160. OTSYS_CREATE_THREAD(monitorThread, this);
  1161. #endif
  1162.  
  1163. addEvent(makeTask(DECAY_INTERVAL, boost::bind(&Game::checkDecay,this,DECAY_INTERVAL)));
  1164.  
  1165. #ifdef CVS_DAY_CYCLE
  1166. int32_t daycycle = 3600;
  1167. light_hour_delta = 1440*10/daycycle;
  1168. light_hour = 0;
  1169. lightlevel = LIGHT_LEVEL_NIGHT;
  1170. light_state = LIGHT_STATE_NIGHT;
  1171. addEvent(makeTask(10000, boost::bind(&Game::checkLight, this, 10000)));
  1172. #endif //CVS_DAY_CYCLE
  1173. }
  1174.  
  1175.  
  1176. Game::~Game()
  1177. {
  1178. if(map) {
  1179. delete map;
  1180. }
  1181. }
  1182.  
  1183. void Game::setWorldType(enum_world_type type)
  1184. {
  1185. this->worldType = type;
  1186. }
  1187.  
  1188. enum_game_state Game::getGameState()
  1189. {
  1190. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::getGameState()");
  1191. return game_state;
  1192. }
  1193.  
  1194. int32_t Game::loadMap(std::string filename, std::string filekind) {
  1195. if(!map)
  1196. map = new Map;
  1197.  
  1198. max_players = atoi(g_config.getGlobalString("maxplayers").c_str());
  1199. distanceToKill = atoi(g_config.getGlobalString("dist", "50").c_str());
  1200. return map->loadMap(filename, filekind);
  1201. }
  1202.  
  1203.  
  1204.  
  1205. /*****************************************************************************/
  1206.  
  1207. #ifdef __DEBUG_CRITICALSECTION__
  1208.  
  1209. OTSYS_THREAD_RETURN Game::monitorThread(void *p)
  1210. {
  1211. Game* _this = (Game*)p;
  1212.  
  1213. while (true) {
  1214. OTSYS_SLEEP(6000);
  1215.  
  1216. int32_t ret = OTSYS_THREAD_LOCKEX(_this->gameLock, 60 * 2 * 1000);
  1217. if(ret != OTSYS_THREAD_TIMEOUT) {
  1218. OTSYS_THREAD_UNLOCK(_this->gameLock, NULL);
  1219. continue;
  1220. }
  1221.  
  1222. bool file = false;
  1223. std::ostream *outdriver;
  1224. std::cout << "Error: generating critical section file..." <<std::endl;
  1225. std::ofstream output("deadlock.txt",std::ios_base::app);
  1226. if(output.fail()){
  1227. outdriver = &std::cout;
  1228. file = false;
  1229. }
  1230. else{
  1231. file = true;
  1232. outdriver = &output;
  1233. }
  1234.  
  1235. time_t rawtime;
  1236. time(&rawtime);
  1237. *outdriver << "*****************************************************" << std::endl;
  1238. *outdriver << "Error report - " << std::ctime(&rawtime) << std::endl;
  1239.  
  1240. OTSYS_THREAD_LOCK_CLASS::LogList::iterator it;
  1241. for(it = OTSYS_THREAD_LOCK_CLASS::loglist.begin(); it != OTSYS_THREAD_LOCK_CLASS::loglist.end(); ++it) {
  1242. *outdriver << (it->lock ? "lock - " : "unlock - ") << it->str
  1243. << " threadid: " << it->threadid
  1244. << " time: " << it->time
  1245. << " ptr: " << it->mutexaddr
  1246. << std::endl;
  1247. }
  1248.  
  1249. *outdriver << "*****************************************************" << std::endl;
  1250. if(file)
  1251. ((std::ofstream*)outdriver)->close();
  1252.  
  1253. std::cout << "Error report generated. Killing server." <<std::endl;
  1254. exit(1); //force exit
  1255. }
  1256. }
  1257. #endif
  1258.  
  1259. OTSYS_THREAD_RETURN Game::eventThread(void *p)
  1260. {
  1261. #if defined __EXCEPTION_TRACER__
  1262. ExceptionHandler eventExceptionHandler;
  1263. eventExceptionHandler.InstallHandler();
  1264. #endif
  1265.  
  1266. Game* _this = (Game*)p;
  1267.  
  1268. // basically what we do is, look at the first scheduled item,
  1269. // and then sleep until it's due (or if there is none, sleep until we get an event)
  1270. // of course this means we need to get a notification if there are new events added
  1271. while (true)
  1272. {
  1273. #ifdef __DEBUG__EVENTSCHEDULER__
  1274. std::cout << "schedulercycle start..." << std::endl;
  1275. #endif
  1276.  
  1277. SchedulerTask* task = NULL;
  1278. bool runtask = false;
  1279.  
  1280. // check if there are events waiting...
  1281. OTSYS_THREAD_LOCK(_this->eventLock, "eventThread()")
  1282.  
  1283. int32_t ret;
  1284. if (_this->eventList.size() == 0) {
  1285. // unlock mutex and wait for signal
  1286. ret = OTSYS_THREAD_WAITSIGNAL(_this->eventSignal, _this->eventLock);
  1287. } else {
  1288. // unlock mutex and wait for signal or timeout
  1289. ret = OTSYS_THREAD_WAITSIGNAL_TIMED(_this->eventSignal, _this->eventLock, _this->eventList.top()->getCycle());
  1290. }
  1291. // the mutex is locked again now...
  1292. if (ret == OTSYS_THREAD_TIMEOUT) {
  1293. // ok we had a timeout, so there has to be an event we have to execute...
  1294. #ifdef __DEBUG__EVENTSCHEDULER__
  1295. std::cout << "event found at " << OTSYS_TIME() << " which is to be scheduled at: " << _this->eventList.top()->getCycle() << std::endl;
  1296. #endif
  1297. task = _this->eventList.top();
  1298. _this->eventList.pop();
  1299. }
  1300.  
  1301. if(task) {
  1302. std::map<uint32_t, SchedulerTask*>::iterator it = _this->eventIdMap.find(task->getEventId());
  1303. if(it != _this->eventIdMap.end()) {
  1304. _this->eventIdMap.erase(it);
  1305. runtask = true;
  1306. }
  1307. }
  1308.  
  1309. OTSYS_THREAD_UNLOCK(_this->eventLock, "eventThread()");
  1310. if (task) {
  1311. if(runtask) {
  1312. (*task)(_this);
  1313. }
  1314. delete task;
  1315. }
  1316. }
  1317. #if defined __EXCEPTION_TRACER__
  1318. eventExceptionHandler.RemoveHandler();
  1319. #endif
  1320.  
  1321. }
  1322.  
  1323. uint32_t Game::addEvent(SchedulerTask* event) {
  1324. bool do_signal = false;
  1325. OTSYS_THREAD_LOCK(eventLock, "addEvent()")
  1326.  
  1327. if(event->getEventId() == 0) {
  1328. ++eventIdCount;
  1329. event->setEventId(eventIdCount);
  1330. }
  1331.  
  1332. #ifdef __DEBUG__EVENTSCHEDULER__
  1333. std::cout << "addEvent - " << event->getEventId() << std::endl;
  1334. #endif
  1335.  
  1336. eventIdMap[event->getEventId()] = event;
  1337.  
  1338. /*
  1339. if (eventList.empty() || *event < *eventList.top())
  1340. do_signal = true;
  1341. */
  1342.  
  1343. bool isEmpty = eventList.empty();
  1344. eventList.push(event);
  1345.  
  1346. if(isEmpty || *event < *eventList.top())
  1347. do_signal = true;
  1348.  
  1349. /*
  1350. if (eventList.empty() || *event < *eventList.top())
  1351. do_signal = true;
  1352. */
  1353.  
  1354. OTSYS_THREAD_UNLOCK(eventLock, "addEvent()")
  1355.  
  1356. if (do_signal)
  1357. OTSYS_THREAD_SIGNAL_SEND(eventSignal);
  1358.  
  1359. return event->getEventId();
  1360. }
  1361.  
  1362. bool Game::stopEvent(uint32_t eventid) {
  1363. if(eventid == 0)
  1364. return false;
  1365.  
  1366. OTSYS_THREAD_LOCK(eventLock, "stopEvent()")
  1367.  
  1368. std::map<uint32_t, SchedulerTask*>::iterator it = eventIdMap.find(eventid);
  1369. if(it != eventIdMap.end()) {
  1370.  
  1371. #ifdef __DEBUG__EVENTSCHEDULER__
  1372. std::cout << "stopEvent - eventid: " << eventid << "/" << it->second->getEventId() << std::endl;
  1373. #endif
  1374.  
  1375. //it->second->setEventId(0); //invalidate the event
  1376. eventIdMap.erase(it);
  1377.  
  1378. OTSYS_THREAD_UNLOCK(eventLock, "stopEvent()")
  1379. return true;
  1380. }
  1381.  
  1382. OTSYS_THREAD_UNLOCK(eventLock, "stopEvent()")
  1383. return false;
  1384. }
  1385.  
  1386. /*****************************************************************************/
  1387.  
  1388. uint32_t Game::getPlayersOnline() {return (uint32_t)Player::listPlayer.list.size();};
  1389. uint32_t Game::getMonstersOnline() {return (uint32_t)Monster::listMonster.list.size();};
  1390. uint32_t Game::getNpcsOnline() {return (uint32_t)Npc::listNpc.list.size();};
  1391. uint32_t Game::getCreaturesOnline() {return (uint32_t)listCreature.list.size();};
  1392.  
  1393. Tile* Game::getTile(unsigned short _x, unsigned short _y, unsigned char _z)
  1394. {
  1395. return map->getTile(_x, _y, _z);
  1396. }
  1397.  
  1398. Tile* Game::getTile(const Position& pos)
  1399. {
  1400. return map->getTile(pos);
  1401. }
  1402.  
  1403. void Game::setTile(unsigned short _x, unsigned short _y, unsigned char _z, unsigned short groundId)
  1404. {
  1405. map->setTile(_x, _y, _z, groundId);
  1406. }
  1407.  
  1408. Creature* Game::getCreatureByID(uint32_t id)
  1409. {
  1410. if(id == 0)
  1411. return NULL;
  1412.  
  1413. AutoList<Creature>::listiterator it = listCreature.list.find(id);
  1414. if(it != listCreature.list.end()) {
  1415. return (*it).second;
  1416. }
  1417.  
  1418. return NULL; //just in case the player doesnt exist
  1419. }
  1420.  
  1421. Player* Game::getPlayerByID(uint32_t id)
  1422. {
  1423. if(id == 0)
  1424. return NULL;
  1425.  
  1426. AutoList<Player>::listiterator it = Player::listPlayer.list.find(id);
  1427. if(it != Player::listPlayer.list.end()) {
  1428. return (*it).second;
  1429. }
  1430.  
  1431. return NULL; //just in case the player doesnt exist
  1432. }
  1433.  
  1434. Creature* Game::getCreatureByName(const std::string &s)
  1435. {
  1436. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::getCreatureByName()");
  1437.  
  1438. std::string txt1 = s;
  1439. std::transform(txt1.begin(), txt1.end(), txt1.begin(), upchar);
  1440. for(AutoList<Creature>::listiterator it = listCreature.list.begin(); it != listCreature.list.end(); ++it){
  1441. std::string txt2 = (*it).second->getName();
  1442. std::transform(txt2.begin(), txt2.end(), txt2.begin(), upchar);
  1443. if(txt1 == txt2)
  1444. return it->second;
  1445. }
  1446.  
  1447. return NULL; //just in case the creature doesnt exist
  1448. }
  1449.  
  1450. Player* Game::getPlayerByName(const std::string &s)
  1451. {
  1452. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::getPlayerByName()");
  1453.  
  1454. std::string txt1 = s;
  1455. std::transform(txt1.begin(), txt1.end(), txt1.begin(), upchar);
  1456. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  1457. std::string txt2 = (*it).second->getName();
  1458. std::transform(txt2.begin(), txt2.end(), txt2.begin(), upchar);
  1459. if(txt1 == txt2)
  1460. return it->second;
  1461. }
  1462.  
  1463. return NULL; //just in case the player doesnt exist
  1464. }
  1465.  
  1466. bool Game::placeCreature(Position &pos, Creature* c
  1467. #ifdef YUR_LOGIN_QUEUE
  1468. , int32_t* placeInQueue
  1469. #endif //YUR_LOGIN_QUEUE
  1470. )
  1471. {
  1472. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::placeCreature()");
  1473. bool success = false;
  1474. Player *p = dynamic_cast<Player*>(c);
  1475. Monster *monsterzin = dynamic_cast<Monster*>(c);
  1476.  
  1477. #ifdef YUR_LOGIN_QUEUE
  1478. if (!p || c->access >= g_config.ACCESS_ENTER ||
  1479. #ifdef YUR_PREMIUM_PROMOTION
  1480. (p->isPremmium() && !g_config.QUEUE_PREMMY) ||
  1481. #endif //YUR_PREMIUM_PROMOTION
  1482. loginQueue.login(p->accountNumber, getPlayersOnline(), max_players, placeInQueue))
  1483. {
  1484. #else //YUR_LOGIN_QUEUE
  1485. if (!p || c->access >= g_config.ACCESS_ENTER || getPlayersOnline() < max_players)
  1486. {
  1487. #endif //YUR_LOGIN_QUEUE
  1488.  
  1489. success = map->placeCreature(pos, c);
  1490. if(success)
  1491. {
  1492. c->useThing();
  1493.  
  1494. c->setID();
  1495. //std::cout << "place: " << c << " " << c->getID() << std::endl;
  1496. listCreature.addList(c);
  1497. c->addList();
  1498. c->isRemoved = false;
  1499.  
  1500. sendAddThing(NULL,c->pos,c);
  1501.  
  1502. if(p)
  1503. {
  1504. checkRecord();
  1505. #ifdef __DEBUG_PLAYERS__
  1506. std::cout << (uint32_t)getPlayersOnline() << " players online." << std::endl;
  1507. #endif
  1508. #ifdef YUR_GUILD_SYSTEM
  1509. Guilds::ReloadGuildInfo(p);
  1510. #endif //YUR_GUILD_SYSTEM
  1511. /*#ifdef ELEM_VIP_LIST
  1512. vipLogin(p);
  1513. #endif //ELEM_VIP_LIST*/
  1514. }
  1515.  
  1516. if(p){
  1517. c->eventCheck = addEvent(makeTask(1000, std::bind2nd(std::mem_fun(&Game::checkCreature), c->getID())));
  1518. }
  1519. else{
  1520. c->eventCheck = addEvent(makeTask(1000, std::bind2nd(std::mem_fun(&Game::checkCreature), c->getID())));
  1521. }
  1522.  
  1523. //c->eventCheckAttacking = addEvent(makeTask(2000, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), c->getID())));
  1524. }
  1525. }
  1526. else {
  1527. //we cant add the player, server is full
  1528. success = false;
  1529. }
  1530.  
  1531. #ifdef __MIZIAK_CREATURESCRIPTS__
  1532. if(p)
  1533. actions.creatureEvent("login", p, NULL, NULL, NULL);
  1534. #endif //__MIZIAK_CREATURESCRIPTS__
  1535.  
  1536.  
  1537. if(monsterzin){
  1538. c->masterPos.x = c->pos.x;
  1539. c->masterPos.y = c->pos.y;
  1540. c->masterPos.z = c->pos.z;
  1541. }
  1542. return success;
  1543. }
  1544.  
  1545. bool Game::removeCreature(Creature* c)
  1546. {
  1547. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::removeCreature()");
  1548. if(c->isRemoved == true)
  1549. return false;
  1550. #ifdef __DEBUG__
  1551. std::cout << "removing creature "<< std::endl;
  1552. #endif
  1553.  
  1554. #ifdef __MIZIAK_CREATURESCRIPTS__
  1555. Player* pc = dynamic_cast<Player*>(c);
  1556. if(pc)
  1557. if(!pc->dieorlogout)
  1558. actions.creatureEvent("logout", pc, NULL, NULL, NULL);
  1559. #endif //__MIZIAK_CREATURESCRIPTS__
  1560.  
  1561. if(!removeThing(NULL,c->pos,c))
  1562. return false;
  1563.  
  1564. //std::cout << "remove: " << c << " " << c->getID() << std::endl;
  1565. listCreature.removeList(c->getID());
  1566. c->removeList();
  1567. c->isRemoved = true;
  1568.  
  1569. if(g_config.SUMMON_BODIES){
  1570. c->isRemoved = true;
  1571.  
  1572. Creature *summon = NULL;
  1573. for(std::list<Creature*>::iterator cit = c->summons.begin(); cit != c->summons.end(); ++cit) {
  1574. summon = (*cit);
  1575. Position CreaturePos = summon->pos;
  1576. Tile *tile = map->getTile(CreaturePos);
  1577. Item *corpseitem = Item::CreateItem(summon->getLookCorpse());
  1578. corpseitem->pos = CreaturePos; /*summoned bodies by Cayan*/
  1579. tile->addThing(corpseitem);
  1580. removeCreature(summon);
  1581. updateTile(CreaturePos);
  1582. }
  1583. }
  1584. else
  1585. {
  1586. c->isRemoved = true;
  1587.  
  1588. //for(std::list<Creature*>::iterator cit = c->summons.begin(); cit != c->summons.end(); ++cit) {
  1589. //removeCreature(*cit);
  1590. //}
  1591. }
  1592.  
  1593.  
  1594. stopEvent(c->eventCheck);
  1595. stopEvent(c->eventCheckAttacking);
  1596. stopEvent(c->eventCheckFollow);
  1597.  
  1598. Player* player = dynamic_cast<Player*>(c);
  1599. if(player){
  1600.  
  1601. #ifdef HUCZU_SKULLS
  1602. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  1603. Player *on = dynamic_cast<Player*>(it->second);
  1604. if(on && player->isYellowTo(on)){
  1605. on->removeFromYellowList(player);
  1606. }
  1607. if(on && on->hasAttacked(player)){
  1608. on->removeFromAttakedList(player);
  1609. }
  1610. player->clearAttakedList();
  1611. player->clearYellowList();
  1612. }
  1613.  
  1614. if(player->party != 0)
  1615. LeaveParty(player);
  1616. #endif //HUCZU_SKULLS
  1617.  
  1618. if(player->tradePartner != 0) {
  1619. playerCloseTrade(player);
  1620. }
  1621. if(player->eventAutoWalk)
  1622. stopEvent(player->eventAutoWalk);
  1623.  
  1624. Tile* fromT = getTile(player->pos);
  1625. if(fromT && fromT->ground)
  1626. actions.luaWalkOff(player,player->pos,fromT->ground->getID(),fromT->ground->getUniqueId(),fromT->ground->getActionId());
  1627.  
  1628. g_chat.removeUserFromAllChannels(player);
  1629. if(!IOPlayer::instance()->savePlayer(player)){
  1630. std::cout << "Error while saving player: " << player->getName() << std::endl;
  1631. }
  1632. std::cout << (uint32_t)getPlayersOnline() << " players online." << std::endl;
  1633.  
  1634.  
  1635. /*#ifdef ELEM_VIP_LIST
  1636. vipLogout(c->getName());
  1637. #endif //ELEM_VIP_LIST*/
  1638.  
  1639.  
  1640. }
  1641. this->FreeThing(c);
  1642. return true;
  1643. }
  1644.  
  1645. void Game::thingMove(Creature *creature, Thing *thing,
  1646. unsigned short to_x, unsigned short to_y, unsigned char to_z, unsigned char count)
  1647. {
  1648. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 1");
  1649.  
  1650. Tile *fromTile = map->getTile(thing->pos);
  1651.  
  1652. if (fromTile)
  1653. {
  1654. int32_t oldstackpos = fromTile->getThingStackPos(thing);
  1655. thingMoveInternal(creature, thing->pos.x, thing->pos.y, thing->pos.z, oldstackpos, 0, to_x, to_y, to_z, count);
  1656. }
  1657. }
  1658.  
  1659.  
  1660. void Game::thingMove(Creature *creature, unsigned short from_x, unsigned short from_y, unsigned char from_z,
  1661. unsigned char stackPos, unsigned short itemid, unsigned short to_x, unsigned short to_y, unsigned char to_z, unsigned char count)
  1662. {
  1663. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 2");
  1664.  
  1665. Tile *fromTile = getTile(from_x, from_y, from_z);
  1666. if(!fromTile)
  1667. return;
  1668.  
  1669. #ifdef FIXY
  1670. if(dynamic_cast<Player*>(creature) && fromTile && !fromTile->ground) {
  1671. dynamic_cast<Player*>(creature)->sendCancelWalk();
  1672. return;
  1673. }
  1674. #endif //FIXY
  1675.  
  1676. Tile *toTile = getTile(to_x, to_y, to_z);
  1677. if(!toTile)
  1678. return;
  1679.  
  1680. #ifdef FIXY
  1681. if (toTile->isHouse() && !fromTile->isHouse())
  1682. return;
  1683. #endif //FIXY
  1684.  
  1685. Thing* thing = fromTile->getThingByStackPos(stackPos);
  1686. if(!thing)
  1687. return;
  1688.  
  1689. Item* item = dynamic_cast<Item*>(thing);
  1690.  
  1691. if(item && (item->getID() != itemid || item != fromTile->getTopDownItem()))
  1692. return;
  1693.  
  1694. thingMoveInternal(creature, from_x, from_y, from_z, stackPos, itemid, to_x, to_y, to_z, count);
  1695. }
  1696.  
  1697. //container/inventory to container/inventory
  1698. void Game::thingMove(Player *player,
  1699. unsigned char from_cid, unsigned char from_slotid, unsigned short itemid, bool fromInventory,
  1700. unsigned char to_cid, unsigned char to_slotid, bool toInventory,
  1701. unsigned char count)
  1702. {
  1703. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 3");
  1704.  
  1705. thingMoveInternal(player, from_cid, from_slotid, itemid, fromInventory,
  1706. to_cid, to_slotid, toInventory, count);
  1707. }
  1708.  
  1709. //container/inventory to ground
  1710. void Game::thingMove(Player *player,
  1711. unsigned char from_cid, unsigned char from_slotid, unsigned short itemid, bool fromInventory,
  1712. const Position& toPos, unsigned char count)
  1713. {
  1714. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 4");
  1715. Container *fromContainer = player->getContainer(from_cid);
  1716. if(fromContainer && !fromContainer->shop.empty())
  1717. return;
  1718.  
  1719. #ifdef FIXY
  1720. Tile *toTile = getTile(toPos.x, toPos.y, toPos.z);
  1721. if(!toTile)
  1722. return;
  1723.  
  1724. if (player) {
  1725. Tile *fromTile = getTile(player->pos);
  1726. if(!fromTile->isHouse() && toTile->isHouse())
  1727. return;
  1728. }
  1729. #endif //FIXY
  1730.  
  1731. thingMoveInternal(player, from_cid, from_slotid, itemid, fromInventory, toPos, count);
  1732. }
  1733.  
  1734. //ground to container/inventory
  1735. void Game::thingMove(Player *player,
  1736. const Position& fromPos, unsigned char stackPos, unsigned short itemid,
  1737. unsigned char to_cid, unsigned char to_slotid, bool toInventory,
  1738. unsigned char count)
  1739. {
  1740. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 5");
  1741. thingMoveInternal(player, fromPos, stackPos, itemid, to_cid, to_slotid, toInventory, count);
  1742. }
  1743.  
  1744. #ifdef FIXY
  1745. bool Game::onPrepareMoveThing(Creature* player, /*const*/ Thing* thing,
  1746. const Position& fromPos, const Position& toPos, int32_t count)
  1747. {
  1748. const Creature* movingCreature = dynamic_cast<const Creature*>(thing);
  1749. Player *playa = dynamic_cast<Player*>(thing);
  1750.  
  1751. if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) &&
  1752. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  1753. {
  1754. player->sendCancel("Destination is out of reach.");
  1755. return false;
  1756. }
  1757. //RZUCANIE GM PO EKRANIE?
  1758. else if( ((abs(fromPos.x - toPos.x) > thing->throwRange) || (abs(fromPos.y - toPos.y) > thing->throwRange)
  1759. || (fromPos.z != toPos.z)) && player->access >= g_config.ACCESS_REMOTE) {
  1760. if(player == thing){
  1761. teleport(player,toPos);
  1762.  
  1763. if(!playa->gmInvisible){
  1764. globalMagicEffect(fromPos, NM_ME_PUFF);
  1765. globalMagicEffect(toPos, NM_ME_ENERGY_AREA);
  1766. }
  1767. else
  1768. {
  1769. playa->sendMagicEffect(fromPos, NM_ME_PUFF);
  1770. playa->sendMagicEffect(toPos, NM_ME_ENERGY_AREA);
  1771. }
  1772. }
  1773. else
  1774. teleport(thing,toPos);
  1775. }
  1776.  
  1777.  
  1778. 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)))) {
  1779. player->sendCancel("Destination is out of reach.");
  1780. return false;
  1781. }
  1782.  
  1783.  
  1784. else if(player->access < g_config.ACCESS_REMOTE && movingCreature && fromPos.z != toPos.z){
  1785. player->sendCancel("Destination is out of reach.");
  1786. return false;
  1787. }
  1788.  
  1789. else {
  1790. const Item* item = dynamic_cast<const Item*>(thing);
  1791. if(item) {
  1792. if(item->getID() == ITEM_FOOTBALL &&
  1793. player->access < g_config.getGlobalNumber("accessfootball", 3) && (
  1794. (abs(player->pos.x - toPos.x) > 2) ||
  1795. (abs(player->pos.y - toPos.y) > 2) ||
  1796. (player->pos.z != fromPos.z))
  1797. ){
  1798. player->sendCancel("Nie mozesz tak daleko kopnac.");
  1799. return false;
  1800. }
  1801. int32_t blockstate = 0;
  1802. if(item->isBlocking())
  1803. blockstate |= BLOCK_SOLID;
  1804.  
  1805. if(item->isPickupable() || !item->isNotMoveable())
  1806. blockstate |= BLOCK_PICKUPABLE;
  1807.  
  1808. if(blockstate != 0) {
  1809. switch(map->canThrowObjectTo(fromPos, toPos, blockstate)) {
  1810. case RET_NOERROR:
  1811. return true;
  1812. break;
  1813.  
  1814. case RET_CANNOTTHROW:
  1815. player->sendCancel("Nie mozesz tam rzucic.");
  1816. return false;
  1817. break;
  1818.  
  1819. case RET_CREATUREBLOCK:
  1820. case RET_NOTENOUGHROOM:
  1821. #ifdef KOSZ
  1822. if(item->getID() != ITEM_DUSTBIN){
  1823. player->sendCancel("Przykro mi, nie ma miejsca.");
  1824. return false;
  1825. }
  1826. #else
  1827. player->sendCancel("Przykro mi, nie ma miejsca.");
  1828. return false;
  1829. #endif //KOSZ
  1830. break;
  1831.  
  1832. default:
  1833. player->sendCancel("Sorry not possible.");
  1834. return false;
  1835. break;
  1836. }
  1837. }
  1838. }
  1839. }
  1840.  
  1841. return true;
  1842. }
  1843. #else //FIXY
  1844. bool Game::onPrepareMoveThing(Creature* player, const Thing* thing,
  1845. const Position& fromPos, const Position& toPos, int32_t count)
  1846. {
  1847. if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) &&
  1848. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  1849. {
  1850. player->sendCancel("Za daleko...");
  1851. return false;
  1852. }
  1853. else if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) &&
  1854. ((abs(fromPos.x - toPos.x) > thing->throwRange) || (abs(fromPos.y - toPos.y) > thing->throwRange)
  1855. || (fromPos.z != toPos.z) /*TODO: Make it possible to throw items to different floors ))*/
  1856. {
  1857. player->sendCancel("Destination is out of reach.");
  1858. return false;
  1859. }
  1860. else {
  1861. const Item* item = dynamic_cast<const Item*>(thing);
  1862. if(item) {
  1863. int32_t blockstate = 0;
  1864. if(item->isBlocking())
  1865. blockstate |= BLOCK_SOLID;
  1866.  
  1867. if(item->isPickupable() || !item->isNotMoveable())
  1868. blockstate |= BLOCK_PICKUPABLE;
  1869.  
  1870. if(blockstate != 0) {
  1871. switch(map->canThrowObjectTo(fromPos, toPos, blockstate)) {
  1872. case RET_NOERROR:
  1873. return true;
  1874. break;
  1875.  
  1876. case RET_CANNOTTHROW:
  1877. player->sendCancel("Nie mozesz tam rzucic.");
  1878. return false;
  1879. break;
  1880.  
  1881. case RET_CREATUREBLOCK:
  1882. case RET_NOTENOUGHROOM:
  1883. player->sendCancel("Przykro mi, nie ma miejsca.");
  1884. return false;
  1885. break;
  1886.  
  1887. default:
  1888. player->sendCancel("Sorry not possible.");
  1889. return false;
  1890. break;
  1891. }
  1892. }
  1893. }
  1894. }
  1895. return true;
  1896. }
  1897. #endif //FIXY
  1898. /*ground -> ground*/
  1899. bool Game::onPrepareMoveThing(Creature* creature, const Thing* thing,
  1900. const Tile* fromTile, const Tile *toTile, int32_t count)
  1901. {
  1902. const Player* player = dynamic_cast<const Player*>(creature);
  1903.  
  1904. const Item *item = dynamic_cast<const Item*>(thing);
  1905. const Creature* movingCreature = dynamic_cast<const Creature*>(thing);
  1906. const Player* movingPlayer = dynamic_cast<const Player*>(thing);
  1907.  
  1908. /* if(movingCreature){
  1909. addEvent(makeTask(2000, std::mem_fun(&Game::onPrepareMoveCreature, creature, movingCreature, fromTile, toTile))));
  1910. }*/
  1911. if(item && !item->canMovedTo(toTile)) {
  1912. creature->sendCancel("Sorry, not possible.");
  1913. return false;
  1914. }
  1915.  
  1916. else if(movingCreature && !movingCreature->canMovedTo(toTile)) {
  1917. if(player && player->eventCheckFollow == 0) {
  1918. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  1919. player->sendCancelWalk();
  1920. }
  1921.  
  1922. return false;
  1923. }
  1924. else if(!movingPlayer && toTile && toTile->floorChange()) {
  1925. creature->sendCancel("Sorry, not possible.");
  1926. return false;
  1927. }
  1928. else if(movingCreature && toTile && !toTile->ground) {
  1929. if(player) {
  1930. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  1931. player->sendCancelWalk();
  1932. }
  1933.  
  1934. return false;
  1935. }
  1936.  
  1937. if (fromTile && fromTile->splash == thing && fromTile->splash->isNotMoveable()) {
  1938. creature->sendCancel("You cannot move this object.");
  1939. #ifdef __DEBUG__
  1940. cout << creature->getName() << " is trying to move a splash item!" << std::endl;
  1941. #endif
  1942. return false;
  1943. }
  1944. else if (item && item->isNotMoveable()) {
  1945. creature->sendCancel("You cannot move this object.");
  1946. #ifdef __DEBUG__
  1947. cout << creature->getName() << " is trying to move an unmoveable item!" << std::endl;
  1948. #endif
  1949. return false;
  1950. }
  1951.  
  1952. #ifdef TLM_HOUSE_SYSTEM
  1953. if (item && toTile && toTile->isHouse())
  1954. {
  1955. const Container* container = dynamic_cast<const Container*>(item);
  1956. int32_t moving = container? container->getItemHoldingCount() : 1;
  1957.  
  1958. if (moving + toTile->getItemHoldingCount() > g_config.MAX_HOUSE_TILE_ITEMS)
  1959. {
  1960. creature->sendCancel("You cannot put more items on a house tile.");
  1961. return false;
  1962. }
  1963. }
  1964. #endif //TLM_HOUSE_SYSTEM
  1965.  
  1966. return true; //return thing->canMovedTo(toTile);
  1967. }
  1968. /*inventory -> container*/
  1969. bool Game::onPrepareMoveThing(Player* player, const Item* fromItem, slots_t fromSlot,
  1970. const Container* toContainer, const Item* toItem, int32_t count)
  1971. {
  1972. if(toContainer && !toContainer->shop.empty()){
  1973. creatureUseShop(player, fromItem->getID(), count, "toShop");
  1974. return false;
  1975. }
  1976. if(toContainer && toContainer->getParent() && !toContainer->getParent()->shop.empty())
  1977. return false;
  1978. if(!fromItem->isPickupable()) {
  1979. player->sendCancel("Sorry, not possible.");
  1980. return false;
  1981. }
  1982. else {
  1983. const Container *itemContainer = dynamic_cast<const Container*>(fromItem);
  1984. if(itemContainer) {
  1985. if(itemContainer->isHoldingItem(toContainer) || (toContainer == itemContainer)) {
  1986. player->sendCancel("To jest niemozliwe!");
  1987. return false;
  1988. }
  1989. }
  1990.  
  1991. if((!fromItem->isStackable() || !toItem || fromItem->getID() != toItem->getID() || toItem->getItemCountOrSubtype() >= 100) && toContainer->size() + 1 > toContainer->capacity()) {
  1992. player->sendCancel("Przykro mi, nie ma miejsca.");
  1993. return false;
  1994. }
  1995.  
  1996. Container const *topContainer = toContainer->getTopParent();
  1997. int32_t itemsToadd;
  1998. if(!topContainer)
  1999. topContainer = toContainer;
  2000.  
  2001. Container const *fromContainer = dynamic_cast<const Container*>(fromItem);
  2002. if(fromContainer)
  2003. itemsToadd = fromContainer->getItemHoldingCount() + 1;
  2004. else
  2005. itemsToadd = 1;
  2006.  
  2007. if(topContainer->depot != 0 && player->max_depot_items != 0 && topContainer->getItemHoldingCount() + itemsToadd >= player->max_depot_items){
  2008. player->sendCancel("Nie mozesz polozyc wiecej przedmiotow w depo.");
  2009. return false;
  2010. }
  2011. }
  2012. return true;
  2013. }
  2014.  
  2015. /*container -> container*/
  2016. /*ground -> container*/
  2017. bool Game::onPrepareMoveThing(Player* player,
  2018. const Position& fromPos, const Container* fromContainer, const Item* fromItem,
  2019. const Position& toPos, const Container* toContainer, const Item* toItem, int32_t count)
  2020. {
  2021. if(fromContainer && toContainer && (!fromContainer->shop.empty() || !toContainer->shop.empty())){
  2022. creatureUseShop(player, fromItem->getID(), count, (!fromContainer->shop.empty() ? "fromShop" : "toShop"));
  2023. return false;
  2024. }
  2025.  
  2026. if(!fromContainer && toContainer && !toContainer->shop.empty())
  2027. return false;
  2028. if(toContainer && toContainer->getParent() && !toContainer->getParent()->shop.empty())
  2029. return false;
  2030.  
  2031. if (player->access < g_config.ACCESS_REMOTE &&
  2032. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  2033. {
  2034. player->sendCancel("Za daleko...");
  2035. return false;
  2036. }
  2037. else if (player->access < g_config.ACCESS_REMOTE &&
  2038. ((abs(fromPos.x - toPos.x) > fromItem->throwRange) || (abs(fromPos.y - toPos.y) > fromItem->throwRange)
  2039. || (fromPos.z != toPos.z)))
  2040. {
  2041. player->sendCancel("Destination is out of reach.");
  2042. return false;
  2043. }
  2044.  
  2045. if(!fromItem->isPickupable()) {
  2046. player->sendCancel("You cannot move this object.");
  2047. return false;
  2048. }
  2049. else {
  2050. if((!fromItem->isStackable() || !toItem || fromItem->getID() != toItem->getID() || toItem->getItemCountOrSubtype() >= 100) && toContainer->size() + 1 > toContainer->capacity()) {
  2051. player->sendCancel("Przykro mi, nie ma miejsca.");
  2052. return false;
  2053. }
  2054.  
  2055. const Container *itemContainer = dynamic_cast<const Container*>(fromItem);
  2056. if(itemContainer) {
  2057. if(itemContainer->isHoldingItem(toContainer) || (toContainer == itemContainer) || (fromContainer && fromContainer == itemContainer)) {
  2058. player->sendCancel("To jest niemozliwe!");
  2059. return false;
  2060. }
  2061. }
  2062.  
  2063. double itemWeight = (fromItem->isStackable() ? Item::items[fromItem->getID()].weight * std::max(1, count) : fromItem->getWeight());
  2064. if((!fromContainer || !player->isHoldingContainer(fromContainer)) && player->isHoldingContainer(toContainer)) {
  2065. if(player->access < g_config.ACCESS_PROTECT && player->getFreeCapacity() < itemWeight) {
  2066. player->sendCancel("Ten przedmiot jest za ciezki.");
  2067. return false;
  2068. }
  2069. }
  2070.  
  2071. Container const *topContainer = toContainer->getTopParent();
  2072. int32_t itemsToadd;
  2073. if(!topContainer)
  2074. topContainer = toContainer;
  2075.  
  2076. Container const *fromContainer = dynamic_cast<const Container*>(fromItem);
  2077. if(fromContainer)
  2078. itemsToadd = fromContainer->getItemHoldingCount() + 1;
  2079. else
  2080. itemsToadd = 1;
  2081.  
  2082. if(topContainer->depot != 0 && player->max_depot_items != 0 && topContainer->getItemHoldingCount() >= player->max_depot_items){
  2083. player->sendCancel("Nie mozesz polozyc wiecej przedmiotow w depo.");
  2084. return false;
  2085. }
  2086. }
  2087. return true;
  2088. }
  2089.  
  2090. /*ground -> ground*/
  2091. bool Game::onPrepareMoveCreature(Creature *creature, const Creature* creatureMoving,
  2092. const Tile *fromTile, const Tile *toTile)
  2093. {
  2094. const Player* playerMoving = dynamic_cast<const Player*>(creatureMoving);
  2095. Player* player = dynamic_cast<Player*>(creature);
  2096.  
  2097. #ifdef _BBK_PUSH_DELAY
  2098. if(player && player != creatureMoving && player->pushDelay > 0)
  2099. {
  2100. player->sendCancel("Wait a moment.");
  2101. return false;
  2102. }
  2103. else if(player)
  2104. player->pushDelay = 2*1000; //2 sec
  2105.  
  2106. //wypychanie z depo
  2107. if(player && playerMoving && player != playerMoving && fromTile->isPz() && !toTile->isPz())
  2108. {
  2109. player->sendCancel("Sorry, not possible.");
  2110. return false;
  2111. }
  2112. //wepchanie do depo
  2113. if(player && playerMoving && playerMoving->pzLocked && toTile->isPz())
  2114. {
  2115. player->sendCancel("Sorry, not possible.");
  2116. player->sendCancelWalk();
  2117. return false;
  2118. }
  2119. //wchodzenie do depo
  2120. if(player && player->pzLocked && toTile->isPz())
  2121. {
  2122. player->sendCancel("You can not enter a protection zone after attacking another player.");
  2123. player->sendCancelWalk();
  2124. return false;
  2125. }
  2126. #endif //_BBK_PUSH_DELAY
  2127.  
  2128. if (creature->access < g_config.ACCESS_PROTECT && creature != creatureMoving && !creatureMoving->isPushable())
  2129. {
  2130. creature->sendCancel("Sorry, not possible.");
  2131. return false;
  2132. }
  2133. else if(creature != creatureMoving && toTile->floorChange()){
  2134. creature->sendCancel("Sorry, not possible.");
  2135. return false;
  2136. }
  2137. else if(creature != creatureMoving && toTile->getTeleportItem()){
  2138. creature->sendCancel("Sorry, not possible.");
  2139. return false;
  2140. }
  2141.  
  2142. return true;
  2143. }
  2144.  
  2145. /*ground -> inventory*/
  2146. bool Game::onPrepareMoveThing(Player *player, const Position& fromPos, const Item *item,
  2147. slots_t toSlot, int32_t count)
  2148. {
  2149. if (player->access < g_config.ACCESS_REMOTE &&
  2150. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  2151. {
  2152. player->sendCancel("It's too far.");
  2153. return false;
  2154. }
  2155. else if(!item->isPickupable()) {
  2156. player->sendCancel("You cannot move this object.");
  2157. return false;
  2158. }
  2159.  
  2160. double itemWeight = (item->isStackable() ? Item::items[item->getID()].weight * std::max(1, count) : item->getWeight());
  2161. if(player->access < g_config.ACCESS_PROTECT && player->getFreeCapacity() < itemWeight) {
  2162. player->sendCancel("This object is too heavy.");
  2163. return false;
  2164. }
  2165.  
  2166. return true;
  2167. }
  2168.  
  2169. /*inventory -> inventory*/
  2170. bool Game::onPrepareMoveThing(Player *player, slots_t fromSlot, const Item *fromItem,
  2171. slots_t toSlot, const Item *toItem, int32_t count)
  2172. {
  2173. if(toItem && (!toItem->isStackable() || toItem->getID() != fromItem->getID())) {
  2174. player->sendCancel("There is not enough room.");
  2175. return false;
  2176. }
  2177.  
  2178. return true;
  2179. }
  2180.  
  2181. /*container -> inventory*/
  2182. bool Game::onPrepareMoveThing(Player *player, const Container *fromContainer, const Item *fromItem,
  2183. slots_t toSlot, const Item *toItem, int32_t count)
  2184. {
  2185. if(fromContainer && !fromContainer->shop.empty()){
  2186. creatureUseShop(player, fromItem->getID(), count, "fromShop");
  2187. return false;
  2188. }
  2189. #ifdef _REX_FIGHT_MOD_
  2190. if (toItem && (toItem->getID() == fromItem->getID() && !toItem->isStackable())){
  2191. #else
  2192. if(toItem && (!toItem->isStackable() || toItem->getID() != fromItem->getID())) {
  2193. #endif //Segundo em container -> inventory
  2194. player->sendCancel("There is not enough room.");
  2195. return false;
  2196. }
  2197.  
  2198. double itemWeight = (fromItem->isStackable() ? Item::items[fromItem->getID()].weight * std::max(1, count) : fromItem->getWeight());
  2199. if(player->access < g_config.ACCESS_PROTECT && !player->isHoldingContainer(fromContainer) &&
  2200. player->getFreeCapacity() < itemWeight) {
  2201. player->sendCancel("This object is too heavy.");
  2202. return false;
  2203. }
  2204.  
  2205. return true;
  2206. }
  2207.  
  2208. /*->inventory*/
  2209. bool Game::onPrepareMoveThing(Player *player, const Item *item,
  2210. slots_t toSlot, int32_t count)
  2211. {
  2212. switch(toSlot)
  2213. {
  2214. case SLOT_HEAD:
  2215. if(item->getSlotPosition() & SLOTP_HEAD)
  2216. return true;
  2217. break;
  2218. case SLOT_NECKLACE:
  2219. if(item->getSlotPosition() & SLOTP_NECKLACE)
  2220. return true;
  2221. break;
  2222. case SLOT_BACKPACK:
  2223. if(item->getSlotPosition() & SLOTP_BACKPACK)
  2224. return true;
  2225. break;
  2226. case SLOT_ARMOR:
  2227. if(item->getSlotPosition() & SLOTP_ARMOR)
  2228. return true;
  2229. break;
  2230. case SLOT_RIGHT:
  2231. if(item->getSlotPosition() & SLOTP_RIGHT){
  2232. #ifdef _REX_CVS_MOD_
  2233. //One weapon for hand by ReX
  2234. if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_LEFT] != NULL && player->items[SLOT_LEFT]->isWeapon() && player->items[SLOT_LEFT]->getWeaponType() != SHIELD){
  2235. player->sendCancel("You may use only one weapon.");
  2236. return false;
  2237. }
  2238. #endif
  2239. else if(item->getSlotPosition() & SLOTP_TWO_HAND){
  2240. if(player->items[SLOT_LEFT] != NULL){
  2241. player->sendCancel("First remove the two-handed item.");
  2242. return false;
  2243. }
  2244. return true ;
  2245. }
  2246. else{
  2247. if(player->items[SLOT_LEFT]){
  2248. #ifdef _REX_CVS_MOD_
  2249. //One weapon for hand by ReX
  2250. if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_LEFT] != NULL && player->items[SLOT_LEFT]->isWeapon() && player->items[SLOT_LEFT]->getWeaponType() != SHIELD){
  2251. player->sendCancel("You may use only one weapon.");
  2252. return false;
  2253. }
  2254. #endif
  2255. else if(player->items[SLOT_LEFT]->getSlotPosition() & SLOTP_TWO_HAND){
  2256. player->sendCancel("First remove the two-handed item.");
  2257. return false;
  2258. }
  2259. return true;
  2260. }
  2261. return true;
  2262. }
  2263. }
  2264. break;
  2265. case SLOT_LEFT:
  2266. if(item->getSlotPosition() & SLOTP_LEFT){
  2267. #ifdef _REX_CVS_MOD_
  2268. //One weapon for hand by ReX
  2269. if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_RIGHT] != NULL && player->items[SLOT_RIGHT]->isWeapon() && player->items[SLOT_RIGHT]->getWeaponType() != SHIELD){
  2270. player->sendCancel("You may use only one weapon.");
  2271. return false;
  2272. }
  2273. #endif
  2274. else if(item->getSlotPosition() & SLOTP_TWO_HAND){
  2275. if(player->items[SLOT_RIGHT] != NULL){
  2276. player->sendCancel("First remove the two-handed item.");
  2277. return false;
  2278. }
  2279. return true ;
  2280. }
  2281. else{
  2282. if(player->items[SLOT_RIGHT]){
  2283. #ifdef _REX_CVS_MOD_
  2284. //One weapon for hand by ReX
  2285. if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_RIGHT] != NULL && player->items[SLOT_RIGHT]->isWeapon() && player->items[SLOT_RIGHT]->getWeaponType() != SHIELD){
  2286. player->sendCancel("You may use only one weapon.");
  2287. return false;
  2288. }
  2289. #endif
  2290. else if(player->items[SLOT_RIGHT]->getSlotPosition() & SLOTP_TWO_HAND){
  2291. player->sendCancel("First remove the two-handed item.");
  2292. return false;
  2293. }
  2294. return true;
  2295. }
  2296. return true;
  2297. }
  2298. }
  2299. break;
  2300. case SLOT_LEGS:
  2301. if(item->getSlotPosition() & SLOTP_LEGS)
  2302. return true;
  2303. break;
  2304. case SLOT_FEET:
  2305. if(item->getSlotPosition() & SLOTP_FEET)
  2306. return true;
  2307. break;
  2308. case SLOT_RING:
  2309. if(item->getSlotPosition() & SLOTP_RING
  2310. #ifdef _REX_CVS_MOD_
  2311. || item->getID() == 2208
  2312. #endif
  2313. )
  2314. return true;
  2315. break;
  2316. case SLOT_AMMO:
  2317. if(item->getSlotPosition() & SLOTP_AMMO)
  2318. return true;
  2319. break;
  2320. }
  2321.  
  2322. player->sendCancel("You cannot put that object in that place.");
  2323. return false;
  2324. }
  2325.  
  2326. //container/inventory to container/inventory
  2327. void Game::thingMoveInternal(Player *player,
  2328. unsigned short from_cid, unsigned short from_slotid, unsigned short itemid,
  2329. bool fromInventory,unsigned short to_cid, unsigned short to_slotid, bool toInventory,
  2330. unsigned short count)
  2331. {
  2332. Container *fromContainer = NULL;
  2333. Container *toContainer = NULL;
  2334. Item *fromItem = NULL;
  2335. Item *toItem = NULL;
  2336.  
  2337. if(fromInventory) {
  2338. fromItem = player->getItem(from_cid);
  2339. fromContainer = dynamic_cast<Container *>(fromItem);
  2340. }
  2341. else {
  2342. fromContainer = player->getContainer(from_cid);
  2343.  
  2344. if(fromContainer) {
  2345. if(from_slotid >= fromContainer->size())
  2346. return;
  2347.  
  2348. fromItem = fromContainer->getItem(from_slotid);
  2349. }
  2350. }
  2351.  
  2352. if(toInventory) {
  2353. toItem = player->getItem(to_cid);
  2354. toContainer = dynamic_cast<Container *>(toItem);
  2355. }
  2356. else {
  2357. toContainer = player->getContainer(to_cid);
  2358.  
  2359. if(toContainer) {
  2360. if(to_slotid >= toContainer->capacity())
  2361. return;
  2362.  
  2363. toItem = toContainer->getItem(to_slotid);
  2364. Container *toSlotContainer = dynamic_cast<Container*>(toItem);
  2365. if(toSlotContainer) {
  2366. toContainer = toSlotContainer;
  2367. toItem = NULL;
  2368. }
  2369. }
  2370. }
  2371.  
  2372. if(!fromItem || (toItem == fromItem) || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()) || fromItem->getID() != itemid)
  2373. return;
  2374.  
  2375. //Container to container
  2376. if(!fromInventory && fromContainer && toContainer) {
  2377. Position fromPos = (fromContainer->pos.x == 0xFFFF ? player->pos : fromContainer->pos);
  2378. Position toPos = (toContainer->pos.x == 0xFFFF ? player->pos : toContainer->pos);
  2379.  
  2380. if(onPrepareMoveThing(player, fromPos, fromContainer, fromItem, toPos, toContainer, toItem, count)) {
  2381.  
  2382. autoCloseTrade(fromItem, true);
  2383. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2384. int32_t oldToCount = 0;
  2385.  
  2386. //move around an item in a container
  2387. if(fromItem->isStackable()) {
  2388. if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2389. {
  2390. oldToCount = toItem->getItemCountOrSubtype();
  2391. int32_t newToCount = std::min(100, oldToCount + count);
  2392. toItem->setItemCountOrSubtype(newToCount);
  2393.  
  2394. if(oldToCount != newToCount) {
  2395. autoCloseTrade(toItem);
  2396. }
  2397.  
  2398. int32_t subcount = oldFromCount - count;
  2399. fromItem->setItemCountOrSubtype(subcount);
  2400.  
  2401. int32_t surplusCount = oldToCount + count - 100;
  2402. if(surplusCount > 0) {
  2403. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2404. if(onPrepareMoveThing(player, fromPos, fromContainer, surplusItem, toPos, toContainer, NULL, count)) {
  2405. autoCloseTrade(toContainer);
  2406. toContainer->addItem(surplusItem);
  2407. }
  2408. else {
  2409. delete surplusItem;
  2410. count -= surplusCount; //re-define the actual amount we move.
  2411. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2412. }
  2413. }
  2414. }
  2415. else if(count < oldFromCount) {
  2416. int32_t subcount = oldFromCount - count;
  2417. fromItem->setItemCountOrSubtype(subcount);
  2418.  
  2419. Item* moveItem = Item::CreateItem(fromItem->getID(), count);
  2420. toContainer->addItem(moveItem);
  2421. autoCloseTrade(toContainer);
  2422. }
  2423. else {
  2424. if(fromContainer == toContainer) {
  2425. fromContainer->moveItem(from_slotid, 0);
  2426. }
  2427. else if(fromContainer->removeItem(fromItem)) {
  2428. autoCloseTrade(toContainer);
  2429. toContainer->addItem(fromItem);
  2430. }
  2431. }
  2432.  
  2433. if(fromItem->getItemCountOrSubtype() == 0) {
  2434. fromContainer->removeItem(fromItem);
  2435. this->FreeThing(fromItem);
  2436. }
  2437. }
  2438. else {
  2439. if(fromContainer == toContainer) {
  2440. fromContainer->moveItem(from_slotid, 0);
  2441. }
  2442. else if(fromContainer->removeItem(fromItem)) {
  2443. autoCloseTrade(toContainer);
  2444. toContainer->addItem(fromItem);
  2445. }
  2446. }
  2447.  
  2448. if(player->isHoldingContainer(fromContainer) != player->isHoldingContainer(toContainer)) {
  2449. player->updateInventoryWeigth();
  2450. }
  2451.  
  2452. SpectatorVec list;
  2453. SpectatorVec::iterator it;
  2454.  
  2455. if(fromPos == toPos) {
  2456. getSpectators(Range(fromPos, false), list);
  2457. }
  2458. else {
  2459. getSpectators(Range(fromPos, toPos), list);
  2460. }
  2461.  
  2462. if(!list.empty()) {
  2463. //players
  2464. for(it = list.begin(); it != list.end(); ++it) {
  2465. if(dynamic_cast<Player*>(*it)) {
  2466. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2467. }
  2468. }
  2469.  
  2470. //none-players
  2471. for(it = list.begin(); it != list.end(); ++it) {
  2472. if(!dynamic_cast<Player*>(*it)) {
  2473. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2474. }
  2475. }
  2476. }
  2477. else
  2478. player->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2479. }
  2480. }
  2481. else {
  2482. //inventory to inventory
  2483. if(fromInventory && toInventory && !toContainer) {
  2484. Position fromPos = player->pos;
  2485. Position toPos = player->pos;
  2486. if(onPrepareMoveThing(player, fromItem, (slots_t)to_cid, count) && onPrepareMoveThing(player, (slots_t)from_cid, fromItem, (slots_t)to_cid, toItem, count)) {
  2487.  
  2488. autoCloseTrade(fromItem, true);
  2489. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2490. int32_t oldToCount = 0;
  2491.  
  2492. //bbk 2020
  2493. std::cout << "inventory to inventory" << std::endl;
  2494. if(fromItem && (slots_t)to_cid == SLOT_RING) fromItem->setGlimmer();
  2495. if(toItem && (slots_t)from_cid == SLOT_RING) toItem->removeGlimmer();
  2496.  
  2497. if(fromItem->isStackable()) {
  2498. if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2499. {
  2500. oldToCount = toItem->getItemCountOrSubtype();
  2501. int32_t newToCount = std::min(100, oldToCount + count);
  2502. toItem->setItemCountOrSubtype(newToCount);
  2503.  
  2504. if(oldToCount != newToCount) {
  2505. autoCloseTrade(toItem);
  2506. }
  2507.  
  2508. int32_t subcount = oldFromCount - count;
  2509. fromItem->setItemCountOrSubtype(subcount);
  2510.  
  2511. int32_t surplusCount = oldToCount + count - 100;
  2512. if(surplusCount > 0) {
  2513. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2514. player->sendCancel("There is not enough room.");
  2515. }
  2516.  
  2517. if(fromItem->getItemCountOrSubtype() == 0) {
  2518. player->removeItemInventory(from_cid, true);
  2519. this->FreeThing(fromItem);
  2520. }
  2521. }
  2522. else if(count < oldFromCount) {
  2523. int32_t subcount = oldFromCount - count;
  2524. fromItem->setItemCountOrSubtype(subcount);
  2525.  
  2526. autoCloseTrade(toItem);
  2527. player->removeItemInventory(to_cid, true);
  2528. player->addItemInventory(Item::CreateItem(fromItem->getID(), count), to_cid, true);
  2529.  
  2530. if(fromItem->getItemCountOrSubtype() == 0) {
  2531. player->removeItemInventory(from_cid, true);
  2532. this->FreeThing(fromItem);
  2533. }
  2534. }
  2535. else {
  2536. if(player->removeItemInventory(from_cid, true)) {
  2537. player->removeItemInventory(to_cid, true);
  2538. player->addItemInventory(fromItem, to_cid, true);
  2539. }
  2540. }
  2541. }
  2542. else if(player->removeItemInventory(from_cid, true)) {
  2543. player->removeItemInventory(to_cid, true);
  2544. player->addItemInventory(fromItem, to_cid, true);
  2545. }
  2546.  
  2547. player->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2548. }
  2549. }
  2550. //container to inventory
  2551. else if(!fromInventory && fromContainer && toInventory) {
  2552. if(onPrepareMoveThing(player, fromItem, (slots_t)to_cid, count) && onPrepareMoveThing(player, fromContainer, fromItem, (slots_t)to_cid, toItem, count)) {
  2553. autoCloseTrade(fromItem, true);
  2554. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2555. int32_t oldToCount = 0;
  2556.  
  2557. //bbk 2020
  2558. std::cout << "container to inventory" << std::endl;
  2559. if(fromItem) fromItem->removeGlimmer();
  2560. if(toItem ) toItem->removeGlimmer();
  2561.  
  2562. if(fromItem->isStackable()) {
  2563. if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2564. {
  2565. oldToCount = toItem->getItemCountOrSubtype();
  2566. int32_t newToCount = std::min(100, oldToCount + count);
  2567. toItem->setItemCountOrSubtype(newToCount);
  2568.  
  2569. if(oldToCount != newToCount) {
  2570. autoCloseTrade(toItem);
  2571. }
  2572.  
  2573. int32_t subcount = oldFromCount - count;
  2574. fromItem->setItemCountOrSubtype(subcount);
  2575.  
  2576. int32_t surplusCount = oldToCount + count - 100;
  2577. if(surplusCount > 0) {
  2578. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2579. player->sendCancel("There is not enough room.");
  2580. }
  2581.  
  2582. if(fromItem->getItemCountOrSubtype() == 0) {
  2583. fromContainer->removeItem(fromItem);
  2584. this->FreeThing(fromItem);
  2585. }
  2586. }
  2587. else if(count < oldFromCount) {
  2588. int32_t subcount = oldFromCount - count;
  2589. fromItem->setItemCountOrSubtype(subcount);
  2590.  
  2591. player->removeItemInventory(to_cid, true);
  2592. player->addItemInventory(Item::CreateItem(fromItem->getID(), count), to_cid, true);
  2593.  
  2594. if(toItem) {
  2595. fromContainer->addItem(toItem);
  2596. }
  2597.  
  2598. if(fromItem->getItemCountOrSubtype() == 0) {
  2599. fromContainer->removeItem(fromItem);
  2600. this->FreeThing(fromItem);
  2601. }
  2602. }
  2603. else {
  2604. if(fromContainer->removeItem(fromItem)) {
  2605. player->removeItemInventory(to_cid, true);
  2606. player->addItemInventory(fromItem, to_cid, true);
  2607.  
  2608. if(toItem) {
  2609. fromContainer->addItem(toItem);
  2610. }
  2611. }
  2612. }
  2613. }
  2614. else if(fromContainer->removeItem(fromItem)) {
  2615. player->removeItemInventory(to_cid, true);
  2616. player->addItemInventory(fromItem, to_cid, true);
  2617.  
  2618. if(toItem) {
  2619. fromContainer->addItem(toItem);
  2620. }
  2621. }
  2622.  
  2623. if(!player->isHoldingContainer(fromContainer)) {
  2624. player->updateInventoryWeigth();
  2625. }
  2626.  
  2627. //if(fromContainer->pos.x != 0xFFFF) {
  2628. if(fromContainer->getTopParent()->pos.x != 0xFFFF) {
  2629. SpectatorVec list;
  2630. SpectatorVec::iterator it;
  2631.  
  2632. getSpectators(Range(fromContainer->getTopParent()->pos, false), list);
  2633.  
  2634. //players
  2635. for(it = list.begin(); it != list.end(); ++it) {
  2636. if(dynamic_cast<Player*>(*it)) {
  2637. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2638. }
  2639. }
  2640.  
  2641. //none-players
  2642. for(it = list.begin(); it != list.end(); ++it) {
  2643. if(!dynamic_cast<Player*>(*it)) {
  2644. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2645. }
  2646. }
  2647. }
  2648. else
  2649. player->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2650. }
  2651. }
  2652. //inventory to container
  2653. else if(fromInventory && toContainer) {
  2654. Position fromPos = player->pos;
  2655. Position toPos = (toContainer->pos.x == 0xFFFF ? player->pos : toContainer->pos);
  2656.  
  2657. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2658. int32_t oldToCount = 0;
  2659.  
  2660. //bbk 2020
  2661. std::cout << "inventory to container" << std::endl;
  2662. if(fromItem) fromItem->removeGlimmer();
  2663. if(toItem) toItem->removeGlimmer();
  2664.  
  2665. if(onPrepareMoveThing(player, fromItem, (slots_t)from_cid, toContainer, toItem, count)) {
  2666. autoCloseTrade(fromItem, true);
  2667. if(fromItem->isStackable()) {
  2668. if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2669. {
  2670. oldToCount = toItem->getItemCountOrSubtype();
  2671. int32_t newToCount = std::min(100, oldToCount + count);
  2672. toItem->setItemCountOrSubtype(newToCount);
  2673.  
  2674. if(oldToCount != newToCount) {
  2675. autoCloseTrade(toItem);
  2676. }
  2677.  
  2678. int32_t subcount = oldFromCount - count;
  2679. fromItem->setItemCountOrSubtype(subcount);
  2680.  
  2681. int32_t surplusCount = oldToCount + count - 100;
  2682. if(surplusCount > 0) {
  2683. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2684.  
  2685. if(onPrepareMoveThing(player, fromPos, NULL, surplusItem, toPos, toContainer, NULL, count)) {
  2686. autoCloseTrade(toContainer);
  2687. toContainer->addItem(surplusItem);
  2688. }
  2689. else {
  2690. delete surplusItem;
  2691. count -= surplusCount; //re-define the actual amount we move.
  2692. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2693. }
  2694. }
  2695. }
  2696. else if(count < oldFromCount) {
  2697. int32_t subcount = oldFromCount - count;
  2698. fromItem->setItemCountOrSubtype(subcount);
  2699. autoCloseTrade(toContainer);
  2700. toContainer->addItem(Item::CreateItem(fromItem->getID(), count));
  2701. }
  2702. else {
  2703. if(player->removeItemInventory((slots_t)from_cid, true)) {
  2704. autoCloseTrade(toContainer);
  2705. toContainer->addItem(fromItem);
  2706.  
  2707. if(player->isHoldingContainer(toContainer)) {
  2708. player->updateInventoryWeigth();
  2709. }
  2710. }
  2711. }
  2712.  
  2713. if(fromItem->getItemCountOrSubtype() == 0) {
  2714. player->removeItemInventory(from_cid, true);
  2715. this->FreeThing(fromItem);
  2716. }
  2717. }
  2718. else if(player->removeItemInventory(from_cid, true)) {
  2719. autoCloseTrade(toContainer);
  2720. toContainer->addItem(fromItem);
  2721.  
  2722. if(player->isHoldingContainer(toContainer)) {
  2723. player->updateInventoryWeigth();
  2724. }
  2725. }
  2726.  
  2727. if(!player->isHoldingContainer(toContainer)) {
  2728. player->updateInventoryWeigth();
  2729. }
  2730.  
  2731. if(toContainer->getTopParent()->pos.x != 0xFFFF) {
  2732. SpectatorVec list;
  2733. SpectatorVec::iterator it;
  2734.  
  2735. getSpectators(Range(toContainer->getTopParent()->pos, false), list);
  2736.  
  2737. //players
  2738. for(it = list.begin(); it != list.end(); ++it) {
  2739. if(dynamic_cast<Player*>(*it)) {
  2740. (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2741. }
  2742. }
  2743.  
  2744. //none-players
  2745. for(it = list.begin(); it != list.end(); ++it) {
  2746. if(!dynamic_cast<Player*>(*it)) {
  2747. (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2748. }
  2749. }
  2750. }
  2751. else
  2752. player->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2753. }
  2754. }
  2755. }
  2756. }
  2757.  
  2758. //container/inventory to ground
  2759. void Game::thingMoveInternal(Player *player,
  2760. unsigned char from_cid, unsigned char from_slotid, unsigned short itemid, bool fromInventory,
  2761. const Position& toPos, unsigned char count)
  2762. {
  2763. Container *fromContainer = NULL;
  2764. Tile *toTile = map->getTile(toPos);
  2765. if(!toTile)
  2766. return;
  2767.  
  2768. /*container to ground*/
  2769. if(!fromInventory) {
  2770. fromContainer = player->getContainer(from_cid);
  2771. if(!fromContainer)
  2772. return;
  2773.  
  2774. Position fromPos = (fromContainer->pos.x == 0xFFFF ? player->pos : fromContainer->pos);
  2775. Item *fromItem = dynamic_cast<Item*>(fromContainer->getItem(from_slotid));
  2776. Item* toItem = dynamic_cast<Item*>(toTile->getTopDownItem());
  2777.  
  2778. if(!fromItem || (toItem == fromItem) || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()) || fromItem->getID() != itemid)
  2779. return;
  2780.  
  2781. if(onPrepareMoveThing(player, fromItem, fromPos, toPos, count) && onPrepareMoveThing(player, fromItem, NULL, toTile, count)) {
  2782. autoCloseTrade(fromItem, true);
  2783. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2784. int32_t oldToCount = 0;
  2785.  
  2786. //Do action...
  2787. #ifdef TP_TRASH_BINS
  2788. if (toItem && toItem->isDeleter())
  2789. {
  2790. fromContainer->removeItem(fromItem);
  2791. FreeThing(fromItem);
  2792. }
  2793. else if(fromItem->isStackable()) {
  2794. #else
  2795. if(fromItem->isStackable()) {
  2796. #endif //TP_TRASH_BINS
  2797. if(toItem && toItem->getID() == fromItem->getID())
  2798. {
  2799. oldToCount = toItem->getItemCountOrSubtype();
  2800. int32_t newToCount = std::min(100, oldToCount + count);
  2801. toItem->setItemCountOrSubtype(newToCount);
  2802.  
  2803. if(oldToCount != newToCount) {
  2804. autoCloseTrade(toItem);
  2805. }
  2806.  
  2807. int32_t subcount = oldFromCount - count;
  2808. fromItem->setItemCountOrSubtype(subcount);
  2809.  
  2810. int32_t surplusCount = oldToCount + count - 100;
  2811. if(surplusCount > 0) {
  2812. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2813. surplusItem->pos = toPos;
  2814.  
  2815. toTile->addThing(surplusItem);
  2816. }
  2817.  
  2818. if(fromItem->getItemCountOrSubtype() == 0) {
  2819. fromContainer->removeItem(fromItem);
  2820. this->FreeThing(fromItem);
  2821. }
  2822. }
  2823. else if(count < oldFromCount) {
  2824. int32_t subcount = oldFromCount - count;
  2825. fromItem->setItemCountOrSubtype(subcount);
  2826.  
  2827. Item *moveItem = Item::CreateItem(fromItem->getID(), count);
  2828. moveItem->pos = toPos;
  2829. toTile->addThing(moveItem);
  2830.  
  2831. if(fromItem->getItemCountOrSubtype() == 0) {
  2832. fromContainer->removeItem(fromItem);
  2833. this->FreeThing(fromItem);
  2834. }
  2835. }
  2836. else if(fromContainer->removeItem(fromItem)) {
  2837. fromItem->pos = toPos;
  2838. toTile->addThing(fromItem);
  2839. }
  2840. }
  2841. else if(fromContainer->removeItem(fromItem)) {
  2842. fromItem->pos = toPos;
  2843. toTile->addThing(fromItem);
  2844. }
  2845.  
  2846. if(player->isHoldingContainer(fromContainer)) {
  2847. player->updateInventoryWeigth();
  2848. }
  2849.  
  2850. SpectatorVec list;
  2851. SpectatorVec::iterator it;
  2852.  
  2853. getSpectators(Range(fromPos, false), list);
  2854.  
  2855. SpectatorVec tolist;
  2856. getSpectators(Range(toPos, true), tolist);
  2857.  
  2858. for(it = tolist.begin(); it != tolist.end(); ++it) {
  2859. if(std::find(list.begin(), list.end(), *it) == list.end()) {
  2860. list.push_back(*it);
  2861. }
  2862. }
  2863.  
  2864. //players
  2865. for(it = list.begin(); it != list.end(); ++it) {
  2866. if(dynamic_cast<Player*>(*it)) {
  2867. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2868. }
  2869. }
  2870.  
  2871. //none-players
  2872. for(it = list.begin(); it != list.end(); ++it) {
  2873. if(!dynamic_cast<Player*>(*it)) {
  2874. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2875. }
  2876. }
  2877. }
  2878. }
  2879. else /*inventory to ground*/{
  2880. Item *fromItem = player->getItem(from_cid);
  2881. if(!fromItem || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()) || fromItem->getID() != itemid)
  2882. return;
  2883.  
  2884. if(onPrepareMoveThing(player, fromItem, player->pos, toPos, count) && onPrepareMoveThing(player, fromItem, NULL, toTile, count)) {
  2885. autoCloseTrade(fromItem, true);
  2886. Item* toItem = dynamic_cast<Item*>(toTile->getTopDownItem());
  2887. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2888. int32_t oldToCount = 0;
  2889.  
  2890. //bbk 2020
  2891. std::cout << "inventory to ground" << std::endl;
  2892. if(fromItem) fromItem->removeGlimmer();
  2893.  
  2894. //Do action...
  2895. #ifdef TP_TRASH_BINS
  2896. if(toItem && toItem->isDeleter())
  2897. {
  2898. player->removeItemInventory(from_cid, true);
  2899. FreeThing(fromItem);
  2900. }
  2901. else if(fromItem->isStackable()) {
  2902. #else
  2903. if(fromItem->isStackable()) {
  2904. #endif //TP_TRASH_BINS
  2905. if(toItem && toItem->getID() == fromItem->getID())
  2906. {
  2907. oldToCount = toItem->getItemCountOrSubtype();
  2908. int32_t newToCount = std::min(100, oldToCount + count);
  2909. toItem->setItemCountOrSubtype(newToCount);
  2910.  
  2911. if(oldToCount != newToCount) {
  2912. autoCloseTrade(toItem);
  2913. }
  2914.  
  2915. int32_t subcount = oldFromCount - count;
  2916. fromItem->setItemCountOrSubtype(subcount);
  2917.  
  2918. int32_t surplusCount = oldToCount + count - 100;
  2919. if(surplusCount > 0) {
  2920. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2921. surplusItem->pos = toPos;
  2922.  
  2923. toTile->addThing(surplusItem);
  2924. }
  2925.  
  2926. if(fromItem->getItemCountOrSubtype() == 0) {
  2927. player->removeItemInventory(from_cid, true);
  2928. this->FreeThing(fromItem);
  2929. }
  2930. }
  2931. else if(count < oldFromCount) {
  2932. int32_t subcount = oldFromCount - count;
  2933. fromItem->setItemCountOrSubtype(subcount);
  2934.  
  2935. Item *moveItem = Item::CreateItem(fromItem->getID(), count);
  2936. moveItem->pos = toPos;
  2937. toTile->addThing(moveItem);
  2938.  
  2939. if(fromItem->getItemCountOrSubtype() == 0) {
  2940. player->removeItemInventory(from_cid, true);
  2941. this->FreeThing(fromItem);
  2942. }
  2943. }
  2944. else if(player->removeItemInventory(from_cid, true)) {
  2945. fromItem->pos = toPos;
  2946. toTile->addThing(fromItem);
  2947. }
  2948. }
  2949. else if(player->removeItemInventory(from_cid, true)) {
  2950. fromItem->pos = toPos;
  2951. toTile->addThing(fromItem);
  2952. }
  2953.  
  2954. player->updateInventoryWeigth();
  2955.  
  2956. SpectatorVec list;
  2957. SpectatorVec::iterator it;
  2958.  
  2959. getSpectators(Range(player->pos, false), list);
  2960.  
  2961. SpectatorVec tolist;
  2962. getSpectators(Range(toPos, true), tolist);
  2963.  
  2964. for(it = tolist.begin(); it != tolist.end(); ++it) {
  2965. if(std::find(list.begin(), list.end(), *it) == list.end()) {
  2966. list.push_back(*it);
  2967. }
  2968. }
  2969.  
  2970. //players
  2971. for(it = list.begin(); it != list.end(); ++it) {
  2972. if(dynamic_cast<Player*>(*it)) {
  2973. (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2974. }
  2975. }
  2976.  
  2977. //none-players
  2978. for(it = list.begin(); it != list.end(); ++it) {
  2979. if(!dynamic_cast<Player*>(*it)) {
  2980. (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2981. }
  2982. }
  2983. }
  2984. }
  2985.  
  2986. }
  2987.  
  2988. //ground to container/inventory
  2989. void Game::thingMoveInternal(Player *player, const Position& fromPos, unsigned char stackPos,
  2990. uint16_t itemid, unsigned char to_cid, unsigned char to_slotid, bool toInventory, unsigned char count)
  2991. {
  2992. Tile *fromTile = map->getTile(fromPos);
  2993. if(!fromTile)
  2994. return;
  2995.  
  2996. Container *toContainer = NULL;
  2997.  
  2998. Item* fromItem = dynamic_cast<Item*>(fromTile->getTopDownItem());
  2999. Item *toItem = NULL;
  3000.  
  3001. if(!fromItem || (fromItem->getID() != itemid) || (fromItem != fromTile->getTopDownItem()))
  3002. return;
  3003.  
  3004. if(toInventory)
  3005. {
  3006. toItem = player->getItem(to_cid);
  3007. toContainer = dynamic_cast<Container*>(toItem);
  3008. }
  3009. else
  3010. {
  3011. toContainer = player->getContainer(to_cid);
  3012. if(!toContainer)
  3013. return;
  3014.  
  3015. toItem = toContainer->getItem(to_slotid);
  3016. Container *toSlotContainer = dynamic_cast<Container*>(toItem);
  3017.  
  3018. if(toSlotContainer)
  3019. {
  3020. toContainer = toSlotContainer;
  3021. toItem = NULL;
  3022. }
  3023. }
  3024.  
  3025. if((toItem == fromItem) || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()))
  3026. return;
  3027.  
  3028. /*ground to container*/
  3029. if(toContainer)
  3030. {
  3031. /*if(onPrepareMoveThing(player, fromItem, fromPos, player->pos, count) &&
  3032. onPrepareMoveThing(player, fromItem, NULL, toContainer, toItem, count))*/
  3033.  
  3034. Position toPos = (toContainer->pos.x == 0xFFFF ? player->pos : toContainer->pos);
  3035. if(onPrepareMoveThing(player, fromPos, NULL, fromItem, toPos, toContainer, toItem, count))
  3036. {
  3037. autoCloseTrade(fromItem, true);
  3038. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  3039. int32_t oldToCount = 0;
  3040. int32_t stackpos = fromTile->getThingStackPos(fromItem);
  3041.  
  3042. if(fromItem->isStackable())
  3043. {
  3044. if(toItem && toItem->getID() == fromItem->getID())
  3045. {
  3046. oldToCount = toItem->getItemCountOrSubtype();
  3047. int32_t newToCount = std::min(100, oldToCount + count);
  3048. toItem->setItemCountOrSubtype(newToCount);
  3049.  
  3050. if(oldToCount != newToCount)
  3051. {
  3052. autoCloseTrade(toItem);
  3053. }
  3054.  
  3055. int32_t subcount = oldFromCount - count;
  3056. fromItem->setItemCountOrSubtype(subcount);
  3057.  
  3058. int32_t surplusCount = oldToCount + count - 100;
  3059. if(surplusCount > 0)
  3060. {
  3061. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  3062.  
  3063. if(onPrepareMoveThing(player, fromPos, NULL, surplusItem, toPos, toContainer, NULL, count))
  3064. {
  3065. autoCloseTrade(toContainer);
  3066. toContainer->addItem(surplusItem);
  3067. }
  3068. else
  3069. {
  3070. delete surplusItem;
  3071. count -= surplusCount; //re-define the actual amount we move.
  3072. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  3073. }
  3074. }
  3075.  
  3076. if(fromItem->getItemCountOrSubtype() == 0)
  3077. {
  3078. if(fromTile->removeThing(fromItem))
  3079. {
  3080. this->FreeThing(fromItem);
  3081. }
  3082. }
  3083. }
  3084. else if(count < oldFromCount)
  3085. {
  3086. int32_t subcount = oldFromCount - count;
  3087. fromItem->setItemCountOrSubtype(subcount);
  3088.  
  3089. autoCloseTrade(toContainer);
  3090. toContainer->addItem(Item::CreateItem(fromItem->getID(), count));
  3091.  
  3092. if(fromItem->getItemCountOrSubtype() == 0)
  3093. {
  3094. if(fromTile->removeThing(fromItem))
  3095. {
  3096. this->FreeThing(fromItem);
  3097. }
  3098. }
  3099. }
  3100. else if(fromTile->removeThing(fromItem))
  3101. {
  3102. autoCloseTrade(toContainer);
  3103. toContainer->addItem(fromItem);
  3104. }
  3105. }
  3106. else
  3107. {
  3108. if(fromTile->removeThing(fromItem))
  3109. {
  3110. autoCloseTrade(toContainer);
  3111. toContainer->addItem(fromItem);
  3112. }
  3113. }
  3114.  
  3115. if(player->isHoldingContainer(toContainer))
  3116. {
  3117. player->updateInventoryWeigth();
  3118. }
  3119.  
  3120. SpectatorVec list;
  3121. SpectatorVec::iterator it;
  3122.  
  3123. getSpectators(Range(fromPos, true), list);
  3124.  
  3125. //players
  3126. for(it = list.begin(); it != list.end(); ++it)
  3127. {
  3128. if(dynamic_cast<Player*>(*it))
  3129. {
  3130. (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  3131. }
  3132. }
  3133.  
  3134. //none-players
  3135. for(it = list.begin(); it != list.end(); ++it)
  3136. {
  3137. if(!dynamic_cast<Player*>(*it))
  3138. {
  3139. (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  3140. }
  3141. }
  3142. }
  3143. }
  3144. //ground to inventory
  3145. else if(toInventory)
  3146. {
  3147. if(onPrepareMoveThing(player, fromPos, fromItem, (slots_t)to_cid, count) && onPrepareMoveThing(player, fromItem, (slots_t)to_cid, count))
  3148. {
  3149. autoCloseTrade(fromItem, true);
  3150. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  3151. int32_t oldToCount = 0;
  3152. int32_t stackpos = fromTile->getThingStackPos(fromItem);
  3153.  
  3154. //bbk 2020
  3155. std::cout << "ground to inventory" << std::endl;
  3156. if(fromItem && (slots_t)to_cid == SLOT_RING) {
  3157. fromItem->setGlimmer();
  3158. if(toItem) toItem->removeGlimmer();
  3159. }
  3160.  
  3161. if(fromItem->isStackable())
  3162. {
  3163. if(toItem && toItem->getID() == fromItem->getID())
  3164. {
  3165. oldToCount = toItem->getItemCountOrSubtype();
  3166. int32_t newToCount = std::min(100, oldToCount + count);
  3167. toItem->setItemCountOrSubtype(newToCount);
  3168.  
  3169. if(oldToCount != newToCount)
  3170. {
  3171. autoCloseTrade(toItem);
  3172. }
  3173.  
  3174. int32_t subcount = oldFromCount - count;
  3175. fromItem->setItemCountOrSubtype(subcount);
  3176.  
  3177. int32_t surplusCount = oldToCount + count - 100;
  3178. if(surplusCount > 0)
  3179. {
  3180. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  3181. player->sendCancel("Sorry not enough room.");
  3182. }
  3183.  
  3184. if(fromItem->getItemCountOrSubtype() == 0)
  3185. {
  3186. if(fromTile->removeThing(fromItem))
  3187. {
  3188. this->FreeThing(fromItem);
  3189. }
  3190. }
  3191. }
  3192. else if(count < oldFromCount)
  3193. {
  3194. int32_t subcount = oldFromCount - count;
  3195. fromItem->setItemCountOrSubtype(subcount);
  3196.  
  3197. player->removeItemInventory(to_cid, true);
  3198. player->addItemInventory(Item::CreateItem(fromItem->getID(), count), to_cid, true);
  3199.  
  3200. if(toItem)
  3201. {
  3202. autoCloseTrade(toItem);
  3203. fromTile->addThing(toItem);
  3204. toItem->pos = fromPos;
  3205. }
  3206.  
  3207. if(fromItem->getItemCountOrSubtype() == 0)
  3208. {
  3209. if(fromTile->removeThing(fromItem))
  3210. {
  3211. this->FreeThing(fromItem);
  3212. }
  3213. }
  3214. }
  3215. else
  3216. {
  3217. if(fromTile->removeThing(fromItem))
  3218. {
  3219. player->removeItemInventory(to_cid, true);
  3220. player->addItemInventory(fromItem, to_cid, true);
  3221.  
  3222. if(toItem)
  3223. {
  3224. autoCloseTrade(toItem);
  3225. fromTile->addThing(toItem);
  3226. toItem->pos = fromPos;
  3227. }
  3228. }
  3229. }
  3230. }
  3231. else
  3232. {
  3233. if(fromTile->removeThing(fromItem))
  3234. {
  3235. player->removeItemInventory(to_cid, true);
  3236. player->addItemInventory(fromItem, to_cid, true);
  3237.  
  3238. if(toItem)
  3239. {
  3240. autoCloseTrade(toItem);
  3241. fromTile->addThing(toItem);
  3242. toItem->pos = fromPos;
  3243. }
  3244. }
  3245. }
  3246.  
  3247. player->updateInventoryWeigth();
  3248.  
  3249. SpectatorVec list;
  3250. SpectatorVec::iterator it;
  3251.  
  3252. getSpectators(Range(fromPos, true), list);
  3253.  
  3254. //players
  3255. for(it = list.begin(); it != list.end(); ++it)
  3256. {
  3257. if(dynamic_cast<Player*>(*it))
  3258. {
  3259. (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  3260. }
  3261. }
  3262.  
  3263. //none-players
  3264. for(it = list.begin(); it != list.end(); ++it)
  3265. {
  3266. if(!dynamic_cast<Player*>(*it))
  3267. {
  3268. (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  3269. }
  3270. }
  3271. }
  3272. }
  3273. }
  3274.  
  3275. //ground to ground
  3276. void Game::thingMoveInternal(Creature *creature, unsigned short from_x, unsigned short from_y, unsigned char from_z,
  3277. unsigned char stackPos, unsigned short itemid, unsigned short to_x, unsigned short to_y, unsigned char to_z, unsigned char count)
  3278. {
  3279. Tile *fromTile = getTile(from_x, from_y, from_z);
  3280. if(!fromTile)
  3281. return;
  3282.  
  3283. if(dynamic_cast<Player*>(creature) && fromTile && !fromTile->ground) {
  3284. dynamic_cast<Player*>(creature)->sendCancelWalk();
  3285. return;
  3286. }
  3287.  
  3288. Tile *toTile = getTile(to_x, to_y, to_z);
  3289. /*
  3290. if(!toTile){
  3291. if(dynamic_cast<Player*>(player))
  3292. dynamic_cast<Player*>(player)->sendCancelWalk("Sorry, not possible...");
  3293. return;
  3294. }
  3295. */
  3296.  
  3297. Thing *thing = fromTile->getThingByStackPos(stackPos);
  3298.  
  3299. if (!thing)
  3300. return;
  3301.  
  3302. Item* item = dynamic_cast<Item*>(thing);
  3303. Creature* creatureMoving = dynamic_cast<Creature*>(thing);
  3304. Player* playerMoving = dynamic_cast<Player*>(creatureMoving);
  3305. Player* player = dynamic_cast<Player*>(creature);
  3306.  
  3307. Position oldPos;
  3308. oldPos.x = from_x;
  3309. oldPos.y = from_y;
  3310. oldPos.z = from_z;
  3311.  
  3312. #ifdef TP_TRASH_BINS
  3313. if(toTile)
  3314. {
  3315. Thing *tothing = toTile->getThingByStackPos(stackPos);
  3316. Item *toItem = dynamic_cast<Item*>(tothing);
  3317.  
  3318. if(item && toItem && !playerMoving && !creature && toItem->isDeleter())
  3319. {
  3320. fromTile->removeThing(item);
  3321. this->FreeThing(item);
  3322. //creatureBroadcastTileUpdated(oldPos);
  3323. sendRemoveThing(player, item->pos, item, stackPos);
  3324. return;
  3325. }
  3326. }
  3327. #endif //TP_TRASH_BINS
  3328. /* if (toTile){
  3329. ItemVector::iterator brn;
  3330. for (brn = toTile->downItems.begin(); brn != toTile->downItems.end(); brn++)
  3331. {
  3332. 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)
  3333. */
  3334. if(toTile && player && playerMoving && playerMoving != player && toTile->getFieldItem())
  3335. {
  3336. player->sendCancel("Sorry, not possible.");
  3337. return;
  3338. }
  3339. // *** Creature moving itself to a non-tile
  3340. if(!toTile && creatureMoving && creatureMoving == creature){
  3341. //change level begin
  3342. Tile* downTile = getTile(to_x, to_y, to_z+1);
  3343. //diagonal begin
  3344. if(!downTile)
  3345. {
  3346. if(player) {
  3347. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  3348. player->sendCancelWalk();
  3349. }
  3350.  
  3351. return;
  3352. }
  3353.  
  3354. if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  3355. teleport(creatureMoving, Position(creatureMoving->pos.x-2, creatureMoving->pos.y+2, creatureMoving->pos.z+1));
  3356. }
  3357. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  3358. teleport(creatureMoving, Position(creatureMoving->pos.x+2, creatureMoving->pos.y+2, creatureMoving->pos.z+1));
  3359. }
  3360. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  3361. teleport(creatureMoving, Position(creatureMoving->pos.x-2, creatureMoving->pos.y-2, creatureMoving->pos.z+1));
  3362. }
  3363. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  3364. teleport(creatureMoving, Position(creatureMoving->pos.x+2, creatureMoving->pos.y-2, creatureMoving->pos.z+1));
  3365. }
  3366. //diagonal end
  3367. else if(downTile->floorChange(NORTH)){
  3368. teleport(creatureMoving, Position(to_x, to_y + 1, creatureMoving->pos.z+1));
  3369. }
  3370. else if(downTile->floorChange(SOUTH)){
  3371. teleport(creatureMoving, Position(to_x, to_y - 1, creatureMoving->pos.z+1));
  3372. }
  3373. else if(downTile->floorChange(EAST)){
  3374. teleport(creatureMoving, Position(to_x - 1, to_y, creatureMoving->pos.z+1));
  3375. }
  3376. else if(downTile->floorChange(WEST)){
  3377. teleport(creatureMoving, Position(to_x + 1, to_y, creatureMoving->pos.z+1));
  3378. }
  3379. else
  3380. if(player) {
  3381. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  3382. player->sendCancelWalk();
  3383. }
  3384.  
  3385. //change level end
  3386. return;
  3387. }
  3388.  
  3389. #ifdef DT_PREMMY
  3390. if(player && playerMoving && !player->premmium == true){
  3391. if(!premmytiles.empty()){
  3392. for(int32_t o = 0; o < premmytiles.size(); o++) {
  3393. if((premmytiles[o].second.x != 0) &&
  3394. (premmytiles[o].second.y != 0) && (premmytiles[o].second.z != 0)){
  3395. if(Position(to_x, to_y, to_z) == premmytiles[o].first) {
  3396. player->sendCancelWalk();
  3397. teleport(playerMoving,
  3398. Position(premmytiles[o].second.x, premmytiles[o].second.y,
  3399. premmytiles[o].second.z));
  3400. player->sendMagicEffect(player->pos,
  3401. NM_ME_MAGIC_ENERGIE);
  3402. return;
  3403. }
  3404. }
  3405. else{
  3406. if(Position(to_x, to_y, to_z) == premmytiles[o].first) {
  3407. player->sendCancelWalk();
  3408. break;
  3409. }
  3410. }
  3411. }
  3412. }
  3413. }
  3414.  
  3415. #endif //DT_PREMMY
  3416.  
  3417.  
  3418.  
  3419. // *** Checking if the thing can be moved around
  3420.  
  3421. if(!toTile)
  3422. return;
  3423.  
  3424. if(!onPrepareMoveThing(creature, thing, oldPos, Position(to_x, to_y, to_z), count))
  3425. return;
  3426.  
  3427. if(creatureMoving && !onPrepareMoveCreature(creature, creatureMoving, fromTile, toTile))
  3428. return;
  3429.  
  3430. if(!onPrepareMoveThing(creature, thing, fromTile, toTile, count))
  3431. return;
  3432.  
  3433. Position to_pos;
  3434. to_pos.x = to_x;
  3435. to_pos.y = to_y;
  3436. to_pos.z = to_z;
  3437.  
  3438. Item* fromItem = dynamic_cast<Item*>(getThing(oldPos, stackPos, player));
  3439. Item* toItem = dynamic_cast<Item*>(toTile->getTopDownItem());
  3440.  
  3441. if(fromItem && fromItem->isStackable()){
  3442. if(fromItem->getItemCountOrSubtype() < count)
  3443. {
  3444. player->sendCancel("Sorry, not possible.");
  3445. return;
  3446. }
  3447.  
  3448. if((abs(player->pos.x - oldPos.x) > 1) || (abs(player->pos.y - oldPos.y) > 1) || (player->pos.z != oldPos.z)){
  3449. player->sendCancel("It's far away.");
  3450. return;
  3451. }
  3452. if(toItem && fromItem->getID() == toItem->getID()){
  3453. int32_t oldToCount = toItem->getItemCountOrSubtype();
  3454. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  3455. int32_t newToCount = std::min(100, oldToCount + count);
  3456. toItem->setItemCountOrSubtype(newToCount);
  3457.  
  3458. if(oldToCount != newToCount) {
  3459. autoCloseTrade(toItem);
  3460. }
  3461.  
  3462. int32_t subcount = oldFromCount - count;
  3463. fromItem->setItemCountOrSubtype(subcount);
  3464.  
  3465. int32_t surplusCount = oldToCount + count - 100;
  3466. if(surplusCount > 0) {
  3467. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  3468. surplusItem->pos = to_pos;
  3469. toTile->addThing(surplusItem);
  3470. }
  3471.  
  3472. if(fromItem->getItemCountOrSubtype() == 0) {
  3473. if(removeThing(player, oldPos, fromItem))
  3474. player->updateInventoryWeigth();
  3475. }
  3476.  
  3477. creatureBroadcastTileUpdated(to_pos);
  3478. creatureBroadcastTileUpdated(oldPos);
  3479.  
  3480. return;
  3481. }
  3482. else if(count < fromItem->getItemCountOrSubtype()) {
  3483. int32_t subcount = fromItem->getItemCountOrSubtype() - count;
  3484. fromItem->setItemCountOrSubtype(subcount);
  3485.  
  3486. Item *moveItem = Item::CreateItem(fromItem->getID(), count);
  3487. moveItem->pos = to_pos;
  3488. toTile->addThing(moveItem);
  3489.  
  3490. if(fromItem->getItemCountOrSubtype() == 0) {
  3491. if(removeThing(player, oldPos, fromItem))
  3492. player->updateInventoryWeigth();
  3493. }
  3494.  
  3495. creatureBroadcastTileUpdated(to_pos);
  3496. creatureBroadcastTileUpdated(oldPos);
  3497. return;
  3498. }
  3499. else{
  3500. Item *moveItem = Item::CreateItem(fromItem->getID(), fromItem->getItemCountOrSubtype());
  3501. moveItem->pos = to_pos;
  3502. toTile->addThing(moveItem);
  3503.  
  3504. if(removeThing(player, oldPos, fromItem))
  3505. player->updateInventoryWeigth();
  3506.  
  3507. creatureBroadcastTileUpdated(to_pos);
  3508. creatureBroadcastTileUpdated(oldPos);
  3509. return;
  3510. }
  3511.  
  3512. return;
  3513. }
  3514.  
  3515. /*
  3516. if(item && (item->getID() != itemid || item != fromTile->getTopDownItem()))
  3517. return;
  3518. */
  3519.  
  3520. // *** If the destiny is a teleport item, teleport the thing
  3521.  
  3522. const Teleport *teleportitem = toTile->getTeleportItem();
  3523. if(teleportitem) {
  3524. Player *player = dynamic_cast<Player*>(thing);
  3525. teleport(thing, teleportitem->getDestPos());
  3526. if(player) {
  3527. globalMagicEffect(player->pos, NM_ME_ENERGY_AREA);
  3528. }
  3529. return;
  3530. }
  3531.  
  3532. Monster* monsterMoving = dynamic_cast<Monster*>(creatureMoving);
  3533. if (monsterMoving && toTile->isPz()){
  3534. return;
  3535. }
  3536.  
  3537. #ifdef TLM_HOUSE_SYSTEM
  3538. if (playerMoving && toTile->getHouse() &&
  3539. (fromTile->getHouse() != toTile->getHouse() || playerMoving->houseRightsChanged))
  3540. {
  3541. if (playerMoving->access < g_config.ACCESS_HOUSE &&
  3542. toTile->getHouse()->getPlayerRights(playerMoving->getName()) == HOUSE_NONE)
  3543. {
  3544. playerMoving->sendTextMessage(MSG_SMALLINFO, "You are not invited.");
  3545. playerMoving->sendCancelWalk();
  3546. return;
  3547. }
  3548. else
  3549. playerMoving->houseRightsChanged = false; // if we are invited stop checking rights
  3550. }
  3551. #endif //TLM_HOUSE_SYSTEM
  3552.  
  3553. // *** Normal moving
  3554.  
  3555. if(creatureMoving)
  3556. {
  3557. // we need to update the direction the player is facing to...
  3558. // otherwise we are facing some problems in turning into the
  3559. // direction we were facing before the movement
  3560. // check y first cuz after a diagonal move we lock to east or west
  3561. if (to_y < oldPos.y) creatureMoving->direction = NORTH;
  3562. if (to_y > oldPos.y) creatureMoving->direction = SOUTH;
  3563. if (to_x > oldPos.x) creatureMoving->direction = EAST;
  3564. if (to_x < oldPos.x) creatureMoving->direction = WEST;
  3565. }
  3566.  
  3567. int32_t oldstackpos = fromTile->getThingStackPos(thing);
  3568. if (fromTile->removeThing(thing))
  3569. {
  3570. toTile->addThing(thing);
  3571.  
  3572. thing->pos.x = to_x;
  3573. thing->pos.y = to_y;
  3574. thing->pos.z = to_z;
  3575.  
  3576. SpectatorVec list;
  3577. SpectatorVec::iterator it;
  3578.  
  3579. getSpectators(Range(oldPos, Position(to_x, to_y, to_z)), list);
  3580.  
  3581. #ifdef TRS_GM_INVISIBLE
  3582. if(playerMoving && playerMoving->gmInvisible)
  3583. {
  3584. for(it = list.begin(); it != list.end(); ++it)
  3585. {
  3586. if(playerMoving == (*it) || (*it)->access >= playerMoving->access)
  3587. {
  3588. if(Player* p = dynamic_cast<Player*>(*it))
  3589. {
  3590. if(p->attackedCreature == creature->getID())
  3591. {
  3592. autoCloseAttack(p, creature);
  3593. }
  3594. (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3595. }
  3596. }
  3597. }
  3598. }
  3599. else if(playerMoving && !playerMoving->gmInvisible)
  3600. {
  3601. for(it = list.begin(); it != list.end(); ++it)
  3602. {
  3603. if(Player* p = dynamic_cast<Player*>(*it))
  3604. {
  3605. if(p->attackedCreature == creature->getID())
  3606. {
  3607. autoCloseAttack(p, creature);
  3608. }
  3609. (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3610. }
  3611. }
  3612. }
  3613. else
  3614. {
  3615. for(it = list.begin(); it != list.end(); ++it)
  3616. {
  3617. if(Player* p = dynamic_cast<Player*>(*it))
  3618. {
  3619. if(p->attackedCreature == creature->getID())
  3620. {
  3621. autoCloseAttack(p, creature);
  3622. }
  3623. (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3624. }
  3625. }
  3626. }
  3627. #else //TRS_GM_INVISIBLE
  3628. //players
  3629. for(it = list.begin(); it != list.end(); ++it)
  3630. {
  3631. if(Player* p = dynamic_cast<Player*>(*it)) {
  3632. if(p->attackedCreature == creature->getID()) {
  3633. autoCloseAttack(p, creature);
  3634. }
  3635. (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3636. }
  3637. }
  3638. #endif //TRS_GM_INVISIBLE
  3639.  
  3640. //none-players
  3641. for(it = list.begin(); it != list.end(); ++it)
  3642. {
  3643. if(!dynamic_cast<Player*>(*it)) {
  3644. (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3645. }
  3646. }
  3647.  
  3648. autoCloseTrade(item, true);
  3649. //depot tiles
  3650.  
  3651. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 426))
  3652. {
  3653. int32_t e = 0;
  3654. Container* c = playerMoving->getDepot(1);
  3655. std::stringstream s;
  3656. e += getDepot(c, e);
  3657. s << "Your depot contains " << e;
  3658. if(e > 1)
  3659. s << " items.";
  3660. else
  3661. s << " item.";
  3662. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3663. }
  3664.  
  3665. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 416))
  3666. {
  3667. int32_t e = 0;
  3668. Container* c = playerMoving->getDepot(2);
  3669. std::stringstream s;
  3670. e += getDepot(c, e);
  3671. s << "Your depot contains " << e;
  3672. if(e > 1)
  3673. s << " items.";
  3674. else
  3675. s << " item.";
  3676. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3677. }
  3678.  
  3679. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 446))
  3680. {
  3681. int32_t e = 0;
  3682. Container* c = playerMoving->getDepot(3);
  3683. std::stringstream s;
  3684. e += getDepot(c, e);
  3685. s << "Your depot contains " << e;
  3686. if(e > 1)
  3687. s << " items.";
  3688. else
  3689. s << " item.";
  3690. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3691. }
  3692.  
  3693. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 3216))
  3694. {
  3695. int32_t e = 0;
  3696. Container* c = playerMoving->getDepot(4);
  3697. std::stringstream s;
  3698. e += getDepot(c, e);
  3699. s << "Your depot contains " << e;
  3700. if(e > 1)
  3701. s << " items.";
  3702. else
  3703. s << " item.";
  3704. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3705. }
  3706.  
  3707. if(playerMoving && toTile && fromTile)
  3708. {
  3709. actions.luaWalk(playerMoving,playerMoving->pos,toTile->ground->getID(),toTile->ground->getUniqueId(),toTile->ground->getActionId()); //CHANGE onWalk
  3710. }
  3711.  
  3712. if(playerMoving && toTile && fromTile)
  3713. {
  3714. actions.luaWalkOff(playerMoving,oldPos,fromTile->ground->getID(),fromTile->ground->getUniqueId(),fromTile->ground->getActionId()); //CHANGE onWalk
  3715. }
  3716.  
  3717. if(playerMoving && fromTile && toTile && player == playerMoving)
  3718. switch(toTile->ground->getID())
  3719. {
  3720. case 416:
  3721. {
  3722. toTile->removeThing(toTile->ground);
  3723. toTile->addThing(new Item(417));
  3724. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3725. }
  3726. break;
  3727.  
  3728. case 426:
  3729. {
  3730. toTile->removeThing(toTile->ground);
  3731. toTile->addThing(new Item(425));
  3732. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3733. }
  3734. break;
  3735. case 3216:
  3736. {
  3737. toTile->removeThing(toTile->ground);
  3738. toTile->addThing(new Item(3217));
  3739. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3740. }
  3741. break;
  3742. case 446:
  3743. {
  3744. toTile->removeThing(toTile->ground);
  3745. toTile->addThing(new Item(447));
  3746. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3747. }
  3748. break;
  3749. case 293:
  3750. {
  3751. toTile->removeThing(toTile->ground);
  3752. toTile->addThing(new Item(294));
  3753. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3754. }
  3755. break;
  3756. }
  3757. switch(fromTile->ground->getID())
  3758. {
  3759. case 3217:
  3760. {
  3761. fromTile->removeThing(fromTile->ground);
  3762. fromTile->addThing(new Item(3216));
  3763. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3764. break;
  3765. }
  3766. case 417:
  3767. {
  3768. fromTile->removeThing(fromTile->ground);
  3769. fromTile->addThing(new Item(416));
  3770. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3771. break;
  3772. }
  3773. case 425:
  3774. {
  3775. fromTile->removeThing(fromTile->ground);
  3776. fromTile->addThing(new Item(426));
  3777. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3778. break;
  3779. }
  3780. case 447:
  3781. {
  3782. fromTile->removeThing(fromTile->ground);
  3783. fromTile->addThing(new Item(446));
  3784. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3785. break;
  3786. }
  3787. }
  3788. //end depot tiles-+
  3789. if (playerMoving)
  3790. {
  3791. if(playerMoving->attackedCreature != 0) {
  3792. Creature* attackedCreature = getCreatureByID(creatureMoving->attackedCreature);
  3793. if(attackedCreature){
  3794. autoCloseAttack(playerMoving, attackedCreature);
  3795. }
  3796. }
  3797.  
  3798. if(playerMoving->tradePartner != 0) {
  3799. Player* tradePartner = getPlayerByID(playerMoving->tradePartner);
  3800. if(tradePartner) {
  3801. if((std::abs(playerMoving->pos.x - tradePartner->pos.x) > 2) ||
  3802. (std::abs(playerMoving->pos.y - tradePartner->pos.y) > 2) || (playerMoving->pos.z != tradePartner->pos.z)
  3803. #ifdef HUCZU_FIX
  3804. || (fromTile->isHouse() && !toTile->isHouse())
  3805. #endif //HUCZU_FIX
  3806. ){
  3807. playerCloseTrade(playerMoving);
  3808. }
  3809. }
  3810. }
  3811.  
  3812. //change level begin
  3813. if(toTile->floorChangeDown())
  3814. {
  3815. Tile* downTile = getTile(to_x, to_y, to_z+1);
  3816. if(downTile){
  3817. //diagonal begin
  3818. if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  3819. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y+1, playerMoving->pos.z+1));
  3820. }
  3821. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  3822. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y+1, playerMoving->pos.z+1));
  3823. }
  3824. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  3825. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y-1, playerMoving->pos.z+1));
  3826. }
  3827. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  3828. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y-1, playerMoving->pos.z+1));
  3829. }
  3830. //diagonal end
  3831. else if(downTile->floorChange(NORTH)){
  3832. teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y+1, playerMoving->pos.z+1));
  3833. }
  3834. else if(downTile->floorChange(SOUTH)){
  3835. teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y-1, playerMoving->pos.z+1));
  3836. }
  3837. else if(downTile->floorChange(EAST)){
  3838. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y, playerMoving->pos.z+1));
  3839. }
  3840. else if(downTile->floorChange(WEST)){
  3841. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y, playerMoving->pos.z+1));
  3842. }
  3843. else { //allow just real tiles to be hole'like
  3844. // TODO: later can be changed to check for piled items like chairs, boxes
  3845. teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y, playerMoving->pos.z+1));
  3846. }
  3847. }
  3848. }
  3849. //diagonal begin
  3850. else if(toTile->floorChange(NORTH) && toTile->floorChange(EAST)){
  3851. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y-1, playerMoving->pos.z-1));
  3852. }
  3853. else if(toTile->floorChange(NORTH) && toTile->floorChange(WEST)){
  3854. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y-1, playerMoving->pos.z-1));
  3855. }
  3856. else if(toTile->floorChange(SOUTH) && toTile->floorChange(EAST)){
  3857. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y+1, playerMoving->pos.z-1));
  3858. }
  3859. else if(toTile->floorChange(SOUTH) && toTile->floorChange(WEST)){
  3860. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y+1, playerMoving->pos.z-1));
  3861. }
  3862. //diagonal end
  3863. else if(toTile->floorChange(NORTH)){
  3864. teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y-1, playerMoving->pos.z-1));
  3865. }
  3866. else if(toTile->floorChange(SOUTH)){
  3867. teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y+1, playerMoving->pos.z-1));
  3868. }
  3869. else if(toTile->floorChange(EAST)){
  3870. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y, playerMoving->pos.z-1));
  3871. }
  3872. else if(toTile->floorChange(WEST)){
  3873. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y, playerMoving->pos.z-1));
  3874. }
  3875. //change level end
  3876. }
  3877.  
  3878. // Magic Field in destiny field
  3879. #ifdef HUCZU_FIX
  3880. if(toTile && playerMoving && playerMoving->access < g_config.ACCESS_PROTECT && !toTile->downItems.empty() && !toTile->isPvpArena())
  3881. #else
  3882. if(toTile && playerMoving && playerMoving->access < g_config.ACCESS_PROTECT && !toTile->downItems.empty() || toTile && creatureMoving && creatureMoving->access < g_config.ACCESS_PROTECT && !toTile->downItems.empty())
  3883. #endif //HUCZU_FIX
  3884. {
  3885. ItemVector::iterator iit;
  3886. for (iit = toTile->downItems.begin(); iit != toTile->downItems.end(); iit++)
  3887. {
  3888. if(toTile->isPvpArena()) break;
  3889. if(!(*iit)) continue;
  3890. Item *item = dynamic_cast<Item*>(*iit);
  3891. if(!item) continue;
  3892. if(!creatureMoving || creatureMoving->isRemoved || creatureMoving->health <= 0) break;
  3893. if (item->getID() == 1492 || item->getID() == 1423 || item->getID() == 1487 || item->getID() == 1500){//Fire - Big
  3894. doFieldDamage(creatureMoving, 199 , NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 20);
  3895. // creature DamageColor, damageEffect, hitEffect attackType, offensive, damage
  3896. if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3897. CreateCondition(creatureMoving, NULL, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 10, 10, 2000, 10);
  3898. }
  3899. else if(item->getID() == 1493 || item->getID() == 1424 || item->getID() == 1488 || item->getID() == 1501){//Fire Medium
  3900. doFieldDamage(creatureMoving, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 10);
  3901. if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3902. CreateCondition(creatureMoving, NULL, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 10, 10, 2000, 10);
  3903. }
  3904. else if(item->getID() == 1495 || item->getID() == 1491 || item->getID() == 1504){//Energy
  3905. doFieldDamage(creatureMoving, 71, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 30);
  3906. if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3907. CreateCondition(creatureMoving, NULL, 71, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 30, 30, 2000, 3);
  3908. }
  3909. else if(item->getID() == 1496 || item->getID() == 1490 || item->getID() == 1503 || item->getID() == 1505){//Poison
  3910. doFieldDamage(creatureMoving, 30, NM_ME_POISEN, NM_ME_POISEN, ATTACK_POISON, true, 10);
  3911. if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3912. CreateCondition(creatureMoving, NULL, 30, NM_ME_POISEN, NM_ME_POISEN_RINGS, ATTACK_POISON, true, 10, 10, 2000, 10);
  3913. }
  3914. }
  3915. }
  3916. }
  3917.  
  3918. if(creatureMoving && !toTile->isPvpArena())
  3919. {
  3920. const MagicEffectItem* fieldItem = toTile->getFieldItem();
  3921.  
  3922. if(fieldItem) {
  3923. const MagicEffectTargetCreatureCondition *magicTargetCondition = fieldItem->getCondition();
  3924.  
  3925. if(!(getWorldType() == WORLD_TYPE_NO_PVP && playerMoving && magicTargetCondition && magicTargetCondition->getOwnerID() != 0)) {
  3926. fieldItem->getDamage(creatureMoving);
  3927. }
  3928.  
  3929. if(magicTargetCondition && ((magicTargetCondition->attackType == ATTACK_FIRE) ||
  3930. (magicTargetCondition->attackType == ATTACK_POISON) ||
  3931. (magicTargetCondition->attackType == ATTACK_ENERGY))) {
  3932. Creature *c = getCreatureByID(magicTargetCondition->getOwnerID());
  3933. creatureMakeMagic(c, thing->pos, magicTargetCondition);
  3934. }
  3935. }
  3936. }
  3937. }
  3938.  
  3939.  
  3940. void Game::getSpectators(const Range& range, SpectatorVec& list)
  3941. {
  3942. map->getSpectators(range, list);
  3943. }
  3944.  
  3945. void Game::creatureTurn(Creature *creature, Direction dir)
  3946. {
  3947. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureTurn()");
  3948.  
  3949. if (creature->direction != dir) {
  3950. creature->direction = dir;
  3951.  
  3952. int32_t stackpos = map->getTile(creature->pos)->getThingStackPos(creature);
  3953.  
  3954. SpectatorVec list;
  3955. SpectatorVec::iterator it;
  3956.  
  3957. map->getSpectators(Range(creature->pos, true), list);
  3958.  
  3959. //players
  3960. for(it = list.begin(); it != list.end(); ++it) {
  3961. if(dynamic_cast<Player*>(*it)) {
  3962. (*it)->onCreatureTurn(creature, stackpos);
  3963. }
  3964. }
  3965.  
  3966. //none-players
  3967. for(it = list.begin(); it != list.end(); ++it) {
  3968. if(!dynamic_cast<Player*>(*it)) {
  3969. (*it)->onCreatureTurn(creature, stackpos);
  3970. }
  3971. }
  3972. }
  3973. }
  3974.  
  3975. void Game::addCommandTag(std::string tag){
  3976. bool found = false;
  3977. for(size_t i=0;i< commandTags.size() ;i++){
  3978. if(commandTags[i] == tag){
  3979. found = true;
  3980. break;
  3981. }
  3982. }
  3983. if(!found){
  3984. commandTags.push_back(tag);
  3985. }
  3986. }
  3987.  
  3988. void Game::resetCommandTag(){
  3989. commandTags.clear();
  3990. }
  3991.  
  3992. void Game::creatureSay(Creature *creature, SpeakClasses type, const std::string &text)
  3993. {
  3994. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureSay()");
  3995. using std::string;
  3996. string spoken=text;
  3997. std::transform(spoken.begin(), spoken.end(), spoken.begin(), (int32_t(*)(int32_t))std::tolower);
  3998. bool GMcommand = false;
  3999. // First, check if this was a GM command
  4000. for(size_t i=0;i< commandTags.size() ;i++){
  4001. if(commandTags[i] == text.substr(0,1)){
  4002. if(commands.exeCommand(creature,text)){
  4003. GMcommand = true;
  4004. }
  4005. break;
  4006. }
  4007. }
  4008. Player* p = dynamic_cast<Player*>(creature);
  4009. Player* player = dynamic_cast<Player*>(creature);
  4010.  
  4011. #ifdef HUCZU_FIX
  4012. if (player && spoken == "exevo grav vita" && (!g_config.LEARN_SPELLS || player->knowsSpell("exevo grav vita")))
  4013. {
  4014. Tile *tile = NULL;
  4015. Position wgpos;
  4016. wgpos.z = player->pos.z;
  4017. switch(player->direction)
  4018. {
  4019. case NORTH:
  4020. wgpos.x = player->pos.x;
  4021. wgpos.y = player->pos.y-1;
  4022. break;
  4023. case SOUTH:
  4024. wgpos.x = player->pos.x;
  4025. wgpos.y = player->pos.y+1;
  4026. break;
  4027. case EAST:
  4028. wgpos.x = player->pos.x+1;
  4029. wgpos.y = player->pos.y;
  4030. break;
  4031. case WEST:
  4032. wgpos.x = player->pos.x-1;
  4033. wgpos.y = player->pos.y;
  4034. break;
  4035. default:
  4036. break;
  4037. }
  4038. tile = getTile(wgpos.x, wgpos.y, wgpos.z);
  4039. if(!tile || tile->isBlocking(BLOCK_SOLID,false,false) || tile->isPz())
  4040. {
  4041. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4042. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  4043. return;
  4044. }
  4045. if(player->access < 2)
  4046. {
  4047. if(player->mana < 220)
  4048. {
  4049. player->sendCancel("You do not have enough mana.");
  4050. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4051. return;
  4052. }
  4053. if(!player->premmium)
  4054. {
  4055. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4056. player->sendCancel("You need buy a premmium account for use this spell");
  4057. return;
  4058. }
  4059. if(player->maglevel < 26){
  4060. player->sendCancel("You do not have the magic level.");
  4061. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4062. return;
  4063. }
  4064. if(player->vocation != 2)
  4065. {
  4066. player->sendTextMessage(MSG_SMALLINFO, "You do not have the required vocation.");
  4067. player->sendMagicEffect(player->pos, 2);
  4068. return;
  4069. }
  4070. if (player->exhaustedTicks >= 1000)
  4071. {
  4072. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4073. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  4074. return;
  4075. }
  4076. }
  4077. player->mana -= 220;
  4078. player->addManaSpent(220);
  4079. player->exhaustedTicks = g_config.EXHAUSTED;
  4080. Item* Tree = Item::CreateItem(ITEM_WILDGROWTH, 1);
  4081. addThing(NULL, wgpos, Tree);
  4082. startDecay(Tree);
  4083. SpectatorVec list;
  4084. SpectatorVec::iterator it;
  4085. getSpectators(Range(player->pos), list);
  4086. for(it = list.begin(); it != list.end(); ++it) {
  4087. Player* playerek = dynamic_cast<Player*>(*it);
  4088. if(playerek)
  4089. playerek->sendMagicEffect(playerek->pos, NM_ME_MAGIC_POISEN);
  4090. }
  4091. player->sendMagicEffect(player->pos, NM_ME_MAGIC_ENERGIE);
  4092. }
  4093. #endif //HUCZU_FIX
  4094.  
  4095. if(spoken=="exana pox"){
  4096. MagicEffectClass pox;
  4097. pox.animationColor = 0;
  4098. pox.damageEffect = NM_ME_MAGIC_ENERGIE;
  4099. pox.hitEffect = 255;
  4100. pox.attackType = ATTACK_NONE;
  4101. pox.maxDamage = 0;
  4102. pox.minDamage = 0;
  4103. pox.offensive = false;
  4104. pox.manaCost = 30;
  4105. if(creatureMakeMagic(creature, creature->pos, &pox)){
  4106. creature->removeCondition(ATTACK_POISON);
  4107.  
  4108. if(player)
  4109. player->sendIcons();
  4110. }
  4111. }
  4112.  
  4113. if(!GMcommand){
  4114. Player* player = dynamic_cast<Player*>(creature);
  4115.  
  4116. if(text=="!besthit")
  4117. {
  4118. std::stringstream info;
  4119. if(player->maxDmg>0){
  4120. info << "Your best hit: " << player->maxDmg;}
  4121. else{
  4122. info << "You didn't any damage.";}
  4123. player->sendTextMessage(MSG_EVENT,info.str().c_str());
  4124. }
  4125.  
  4126. 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')) {
  4127.  
  4128. if(player->mana < 200) {
  4129. player->sendCancel("You do not have enough mana.");
  4130. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4131. return;
  4132. }
  4133. if(player->maglevel < 15) {
  4134. player->sendCancel("You do not have the magic level.");
  4135. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4136. return;
  4137. }
  4138. if(player->vocation != 1)
  4139. {
  4140. player->sendTextMessage(MSG_SMALLINFO, "You do not have the required vocation.");
  4141. player->sendMagicEffect(player->pos, 2);
  4142. return;
  4143. }
  4144. player->mana -= 200;
  4145. player->addManaSpent(200);
  4146. SpectatorVec list;
  4147. SpectatorVec::iterator it;
  4148. getSpectators(Range(creature->pos), list);
  4149. for(it = list.begin(); it != list.end(); ++it) {
  4150. if(Creature *c = dynamic_cast<Creature*>(*it)) {
  4151. if(c)
  4152. {
  4153. c->setInvisible(0);
  4154. creatureChangeOutfit(c);
  4155. }
  4156. }
  4157. player->sendMagicEffect(player->pos, NM_ME_MAGIC_ENERGIE);
  4158. }
  4159. }
  4160. if (player)
  4161. checkSpell(player, type, text);
  4162. // It was no command, or it was just a player
  4163. SpectatorVec list;
  4164. SpectatorVec::iterator it;
  4165. getSpectators(Range(creature->pos), list);
  4166. //players
  4167. for(it = list.begin(); it != list.end(); ++it) {
  4168. if(dynamic_cast<Player*>(*it)) {
  4169. (*it)->onCreatureSay(creature, type, text);
  4170. }
  4171. }
  4172.  
  4173. //none-players
  4174. for(it = list.begin(); it != list.end(); ++it) {
  4175. if(!dynamic_cast<Player*>(*it)) {
  4176. (*it)->onCreatureSay(creature, type, text);
  4177. }
  4178. }
  4179. }
  4180. }
  4181.  
  4182. void Game::teleport(Thing *thing, const Position& newPos)
  4183. {
  4184.  
  4185. if (newPos == thing->pos)
  4186. return;
  4187.  
  4188. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::teleport()");
  4189.  
  4190. //Tile *toTile = getTile( newPos.x, newPos.y, newPos.z );
  4191. Tile *toTile = map->getTile(newPos);
  4192. if (toTile)
  4193. {
  4194. Creature *creature = dynamic_cast<Creature*>(thing);
  4195. if (creature)
  4196. {
  4197. //Tile *fromTile = getTile( thing->pos.x, thing->pos.y, thing->pos.z );
  4198. Tile *fromTile = map->getTile(thing->pos);
  4199. if (!fromTile)
  4200. return;
  4201.  
  4202. int osp = fromTile->getThingStackPos(thing);
  4203. if (!fromTile->removeThing(thing))
  4204. return;
  4205.  
  4206. toTile->addThing(thing);
  4207. Position oldPos = thing->pos;
  4208.  
  4209. SpectatorVec list;
  4210. SpectatorVec::iterator it;
  4211.  
  4212. getSpectators(Range(thing->pos, true), list);
  4213.  
  4214. //players
  4215. for (it = list.begin(); it != list.end(); ++it)
  4216. {
  4217. if (Player* p = dynamic_cast<Player*>(*it))
  4218. {
  4219. if (p->attackedCreature == creature->getID())
  4220. {
  4221. autoCloseAttack(p, creature);
  4222. }
  4223.  
  4224. (*it)->onCreatureDisappear(creature, osp, true);
  4225. }
  4226. }
  4227.  
  4228. //none-players
  4229. for (it = list.begin(); it != list.end(); ++it)
  4230. {
  4231. if (!dynamic_cast<Player*>(*it))
  4232. {
  4233. (*it)->onCreatureDisappear(creature, osp, true);
  4234. }
  4235. }
  4236.  
  4237. if (newPos.y < oldPos.y)
  4238. creature->direction = NORTH;
  4239. if (newPos.y > oldPos.y)
  4240. creature->direction = SOUTH;
  4241. if (newPos.x > oldPos.x && (std::abs(newPos.x - oldPos.x) >= std::abs(newPos.y - oldPos.y)))
  4242. creature->direction = EAST;
  4243. if (newPos.x < oldPos.x && (std::abs(newPos.x - oldPos.x) >= std::abs(newPos.y - oldPos.y)))
  4244. creature->direction = WEST;
  4245.  
  4246. thing->pos = newPos;
  4247.  
  4248. Player *player = dynamic_cast<Player*>(creature);
  4249. if (player && player->attackedCreature != 0)
  4250. {
  4251. Creature* attackedCreature = getCreatureByID(player->attackedCreature);
  4252. if (attackedCreature)
  4253. {
  4254. autoCloseAttack(player, attackedCreature);
  4255. }
  4256. }
  4257.  
  4258. list.clear();
  4259. getSpectators(Range(thing->pos, true), list);
  4260.  
  4261. #ifdef TRS_GM_INVISIBLE
  4262. //players
  4263. for (it = list.begin(); it != list.end(); ++it)
  4264. {
  4265. if (player)
  4266. {
  4267. if (player->gmInvisible && player == (*it))
  4268. {
  4269. if (Player* p = dynamic_cast<Player*>(*it))
  4270. {
  4271. if (p->attackedCreature == creature->getID())
  4272. {
  4273. autoCloseAttack(p, creature);
  4274. }
  4275. (*it)->onTeleport(creature, &oldPos, osp);
  4276. }
  4277. }
  4278. else if (player->gmInvisible && player != (*it) && (*it)->access < player->access)
  4279. {
  4280. // Nothing Because he is invisible...
  4281. }
  4282. else
  4283. {
  4284. if (Player* p = dynamic_cast<Player*>(*it))
  4285. {
  4286. if (p->attackedCreature == creature->getID())
  4287. {
  4288. autoCloseAttack(p, creature);
  4289. }
  4290. (*it)->onTeleport(creature, &oldPos, osp);
  4291. }
  4292. }
  4293. }
  4294. else
  4295. creatureBroadcastTileUpdated(newPos);
  4296. }
  4297. #else //TRS_GM_INVISIBLE
  4298. //players
  4299. for (it = list.begin(); it != list.end(); ++it)
  4300. {
  4301. if (Player* p = dynamic_cast<Player*>(*it))
  4302. {
  4303. if (p->attackedCreature == creature->getID())
  4304. {
  4305. autoCloseAttack(p, creature);
  4306. }
  4307. (*it)->onTeleport(creature, &oldPos, osp);
  4308. }
  4309. }
  4310. #endif //TRS_GM_INVISIBLE
  4311.  
  4312. //none-players
  4313. for (it = list.begin(); it != list.end(); ++it)
  4314. {
  4315. if (!dynamic_cast<Player*>(*it))
  4316. {
  4317. (*it)->onTeleport(creature, &oldPos, osp);
  4318. }
  4319. }
  4320. }
  4321. else
  4322. {
  4323. if (removeThing(NULL, thing->pos, thing, false))
  4324. {
  4325. addThing(NULL, newPos, thing);
  4326. }
  4327. }
  4328. }//if(toTile)
  4329.  
  4330. }
  4331.  
  4332.  
  4333. void Game::creatureChangeOutfit(Creature *creature)
  4334. {
  4335. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureChangeOutfit()");
  4336.  
  4337. SpectatorVec list;
  4338. SpectatorVec::iterator it;
  4339.  
  4340. getSpectators(Range(creature->pos, true), list);
  4341.  
  4342. //players
  4343. for(it = list.begin(); it != list.end(); ++it) {
  4344. if(dynamic_cast<Player*>(*it)) {
  4345. (*it)->onCreatureChangeOutfit(creature);
  4346. }
  4347. }
  4348.  
  4349. //none-players
  4350. for(it = list.begin(); it != list.end(); ++it) {
  4351. if(!dynamic_cast<Player*>(*it)) {
  4352. (*it)->onCreatureChangeOutfit(creature);
  4353. }
  4354. }
  4355. }
  4356.  
  4357. void Game::creatureWhisper(Creature *creature, const std::string &text)
  4358. {
  4359. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureWhisper()");
  4360.  
  4361. SpectatorVec list;
  4362. SpectatorVec::iterator it;
  4363.  
  4364. getSpectators(Range(creature->pos), list);
  4365.  
  4366. //players
  4367. for(it = list.begin(); it != list.end(); ++it) {
  4368. if(dynamic_cast<Player*>(*it)) {
  4369. if(abs(creature->pos.x - (*it)->pos.x) > 1 || abs(creature->pos.y - (*it)->pos.y) > 1)
  4370. (*it)->onCreatureSay(creature, SPEAK_WHISPER, std::string("pspsps"));
  4371. else
  4372. (*it)->onCreatureSay(creature, SPEAK_WHISPER, text);
  4373. }
  4374. }
  4375.  
  4376. //none-players
  4377. for(it = list.begin(); it != list.end(); ++it) {
  4378. if(!dynamic_cast<Player*>(*it)) {
  4379. if(abs(creature->pos.x - (*it)->pos.x) > 1 || abs(creature->pos.y - (*it)->pos.y) > 1)
  4380. (*it)->onCreatureSay(creature, SPEAK_WHISPER, std::string("pspsps"));
  4381. else
  4382. (*it)->onCreatureSay(creature, SPEAK_WHISPER, text);
  4383. }
  4384. }
  4385. }
  4386.  
  4387. void Game::creatureYell(Creature *creature, std::string &text)
  4388. {
  4389. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureYell()");
  4390. if(!creature)
  4391. return;
  4392. #ifdef HUCZU_FIX
  4393. if(creature->level < 2 && creature->access < 2){
  4394. return;
  4395. }
  4396. #endif //HUCZU_FIX
  4397. std::transform(text.begin(), text.end(), text.begin(), upchar);
  4398.  
  4399. SpectatorVec list;
  4400. SpectatorVec::iterator it;
  4401. getSpectators(Range(creature->pos, 18, 18, 14, 14), list);
  4402.  
  4403. for(it = list.begin(); it != list.end(); ++it){
  4404. if(*it)
  4405. (*it)->onCreatureSay(creature, SPEAK_YELL, text);
  4406. }
  4407. }
  4408.  
  4409. //ZBÊ„NE
  4410. /*void Game::creatureYell(Creature *creature, std::string &text)
  4411. {
  4412. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureYell()");
  4413. Player* player = dynamic_cast<Player*>(creature);
  4414. #ifdef HUCZU_FIX
  4415. if(player && player->level < 2 && player->access < 2){
  4416. player->sendTextMessage(MSG_SMALLINFO, "You cannot yell.");
  4417. return;
  4418. }
  4419. #endif //HUCZU_FIX
  4420. if (player && player->access < g_config.ACCESS_PROTECT && player->exhaustedTicks >= 1000)
  4421. {
  4422. player->exhaustedTicks += g_config.EXHAUSTED_ADD;
  4423. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  4424. }
  4425. else {
  4426. creature->exhaustedTicks = g_config.EXHAUSTED;
  4427. std::transform(text.begin(), text.end(), text.begin(), upchar);
  4428.  
  4429. SpectatorVec list;
  4430. SpectatorVec::iterator it;
  4431.  
  4432. getSpectators(Range(creature->pos, 18, 18, 14, 14), list);
  4433.  
  4434. //players
  4435. for(it = list.begin(); it != list.end(); ++it) {
  4436. if(dynamic_cast<Player*>(*it)) {
  4437. (*it)->onCreatureSay(creature, SPEAK_YELL, text);
  4438. }
  4439. }
  4440. }
  4441. }*/
  4442.  
  4443. void Game::creatureSpeakTo(Creature *creature, SpeakClasses type,const std::string &receiver, const std::string &text)
  4444. {
  4445. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureSpeakTo");
  4446.  
  4447. Player* player = dynamic_cast<Player*>(creature);
  4448. if(!player)
  4449. return;
  4450.  
  4451. Player* toPlayer = getPlayerByName(receiver);
  4452. if(!toPlayer) {
  4453. player->sendTextMessage(MSG_SMALLINFO, "A player with this name is not online.");
  4454. return;
  4455. }
  4456. if(creature->access < g_config.ACCESS_TALK){
  4457. type = SPEAK_PRIVATE;
  4458. }
  4459.  
  4460. if(!toPlayer){
  4461. player->onCreatureSay(player, type, text);
  4462. }
  4463. time_t ticks = time(0);
  4464. tm* now = localtime(&ticks);
  4465. char buf[32];
  4466. strftime(buf, sizeof(buf), "%d/%m/%Y %H:%M", now);
  4467. std::ofstream out2("data/logs/private.log", std::ios::app);
  4468. out2 << '[' << buf << "] " << toPlayer->getName() << " from " << player->getName() << ": " << text << std::endl;
  4469. out2.close();
  4470.  
  4471. toPlayer->onCreatureSay(player, type, text);
  4472. std::stringstream ss;
  4473. ss << "Message sent to " << toPlayer->getName() << ".";
  4474. player->sendTextMessage(MSG_SMALLINFO, ss.str().c_str());
  4475. }
  4476.  
  4477. void Game::creatureTalkToChannel(Player *player, SpeakClasses type, std::string &text, uint16_t channelId)
  4478. {
  4479. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureTalkToChannel");
  4480.  
  4481. if(player->access < g_config.ACCESS_TALK){
  4482. type = SPEAK_CHANNEL_Y;
  4483. }
  4484.  
  4485. if(player->guildStatus == GUILD_LEADER && channelId == 0x00)
  4486. type = SPEAK_CHANNEL_R1;
  4487. if(player->guildStatus == GUILD_VICE && channelId == 0x00)
  4488. type = SPEAK_CHANNEL_O;
  4489.  
  4490. g_chat.talkToChannel(player, type, text, channelId);
  4491. }
  4492.  
  4493. void Game::creatureMonsterYell(Monster* monster, const std::string& text)
  4494. {
  4495. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureMonsterYell()");
  4496.  
  4497. SpectatorVec list;
  4498. SpectatorVec::iterator it;
  4499.  
  4500. map->getSpectators(Range(monster->pos, 18, 18, 14, 14), list);
  4501.  
  4502. //players
  4503. for(it = list.begin(); it != list.end(); ++it) {
  4504. if(dynamic_cast<Player*>(*it)) {
  4505. (*it)->onCreatureSay(monster, SPEAK_MONSTER1, text);
  4506. }
  4507. }
  4508. }
  4509.  
  4510. void Game::creatureBroadcastMessage(Creature *creature, const std::string &text)
  4511. {
  4512. if(creature->access < g_config.ACCESS_TALK)
  4513. return;
  4514.  
  4515. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureBroadcastMessage()");
  4516.  
  4517. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  4518. {
  4519. (*it).second->onCreatureSay(creature, SPEAK_BROADCAST, text);
  4520. }
  4521. }
  4522.  
  4523. /** \todo Someone _PLEASE_ clean up this mess */
  4524. bool Game::creatureMakeMagic(Creature *creature, const Position& centerpos, const MagicEffectClass* me)
  4525. {
  4526.  
  4527. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureMakeMagic()");
  4528.  
  4529. #ifdef __DEBUG__
  4530. cout << "creatureMakeMagic: " << (creature ? creature->getName() : "No name") << ", x: " << centerpos.x << ", y: " << centerpos.y << ", z: " << centerpos.z << std::endl;
  4531. #endif
  4532.  
  4533. Position frompos;
  4534.  
  4535. if(creature) {
  4536. frompos = creature->pos;
  4537.  
  4538. if(!creatureOnPrepareMagicAttack(creature, centerpos, me))
  4539. {
  4540.  
  4541. return false;
  4542. }
  4543. }
  4544. else {
  4545. frompos = centerpos;
  4546. }
  4547.  
  4548. MagicAreaVec tmpMagicAreaVec;
  4549. me->getArea(centerpos, tmpMagicAreaVec);
  4550.  
  4551. std::vector<Position> poslist;
  4552.  
  4553. Position topLeft(0xFFFF, 0xFFFF, frompos.z), bottomRight(0, 0, frompos.z);
  4554.  
  4555. //Filter out the tiles we actually can work on
  4556. for(MagicAreaVec::iterator maIt = tmpMagicAreaVec.begin(); maIt != tmpMagicAreaVec.end(); ++maIt) {
  4557. Tile *t = map->getTile(maIt->x, maIt->y, maIt->z);
  4558. if(t && (!creature || (creature->access >= g_config.ACCESS_PROTECT || !me->offensive || !t->isPz()) ) ) {
  4559. if((t->isBlocking(BLOCK_PROJECTILE) == RET_NOERROR) && (me->isIndirect() ||
  4560. //(map->canThrowItemTo(frompos, (*maIt), false, true) && !t->floorChange()))) {
  4561. ((map->canThrowObjectTo(centerpos, (*maIt), BLOCK_PROJECTILE) == RET_NOERROR) && !t->floorChange()))) {
  4562.  
  4563. if(maIt->x < topLeft.x)
  4564. topLeft.x = maIt->x;
  4565.  
  4566. if(maIt->y < topLeft.y)
  4567. topLeft.y = maIt->y;
  4568.  
  4569. if(maIt->x > bottomRight.x)
  4570. bottomRight.x = maIt->x;
  4571.  
  4572. if(maIt->y > bottomRight.y)
  4573. bottomRight.y = maIt->y;
  4574.  
  4575. poslist.push_back(*maIt);
  4576. }
  4577. }
  4578. }
  4579.  
  4580. topLeft.z = frompos.z;
  4581. bottomRight.z = frompos.z;
  4582.  
  4583. if(topLeft.x == 0xFFFF || topLeft.y == 0xFFFF || bottomRight.x == 0 || bottomRight.y == 0){
  4584.  
  4585. return false;
  4586. }
  4587.  
  4588. #ifdef __DEBUG__
  4589. printf("top left %d %d %d\n", topLeft.x, topLeft.y, topLeft.z);
  4590. printf("bottom right %d %d %d\n", bottomRight.x, bottomRight.y, bottomRight.z);
  4591. #endif
  4592.  
  4593. //We do all changes against a GameState to keep track of the changes,
  4594. //need some more work to work for all situations...
  4595. GameState gamestate(this, Range(topLeft, bottomRight));
  4596.  
  4597. //Tile *targettile = getTile(centerpos.x, centerpos.y, centerpos.z);
  4598. Tile *targettile = map->getTile(centerpos);
  4599. bool bSuccess = false;
  4600. bool hasTarget = false;
  4601. bool isBlocking = true;
  4602. if(targettile){
  4603. hasTarget = !targettile->creatures.empty();
  4604. isBlocking = (targettile->isBlocking(BLOCK_SOLID, true) != RET_NOERROR);
  4605. }
  4606.  
  4607. if(targettile && me->canCast(isBlocking, !targettile->creatures.empty())) {
  4608. bSuccess = true;
  4609.  
  4610. //Apply the permanent effect to the map
  4611. std::vector<Position>::const_iterator tlIt;
  4612. for(tlIt = poslist.begin(); tlIt != poslist.end(); ++tlIt) {
  4613. gamestate.onAttack(creature, Position(*tlIt), me);
  4614. }
  4615. }
  4616.  
  4617. SpectatorVec spectatorlist = gamestate.getSpectators();
  4618. SpectatorVec::iterator it;
  4619.  
  4620. for(it = spectatorlist.begin(); it != spectatorlist.end(); ++it) {
  4621. Player* spectator = dynamic_cast<Player*>(*it);
  4622.  
  4623. if(!spectator)
  4624. continue;
  4625.  
  4626. if(bSuccess) {
  4627. me->getDistanceShoot(spectator, creature, centerpos, hasTarget);
  4628.  
  4629. std::vector<Position>::const_iterator tlIt;
  4630. for(tlIt = poslist.begin(); tlIt != poslist.end(); ++tlIt) {
  4631. Position pos = *tlIt;
  4632. //Tile *tile = getTile(pos.x, pos.y, pos.z);
  4633. Tile *tile = map->getTile(pos);
  4634. const CreatureStateVec& creatureStateVec = gamestate.getCreatureStateList(tile);
  4635.  
  4636. if(creatureStateVec.empty()) { //no targets
  4637. me->getMagicEffect(spectator, creature, NULL, pos, 0, targettile->isPz(), isBlocking);
  4638. }
  4639. else {
  4640. for(CreatureStateVec::const_iterator csIt = creatureStateVec.begin(); csIt != creatureStateVec.end(); ++csIt) {
  4641. Creature *target = csIt->first;
  4642. const CreatureState& creatureState = csIt->second;
  4643.  
  4644. me->getMagicEffect(spectator, creature, target, target->pos, creatureState.damage, tile->isPz(), false);
  4645.  
  4646. //could be death due to a magic damage with no owner (fire/poison/energy)
  4647. if(creature && target->isRemoved == true) {
  4648.  
  4649. for(std::vector<Creature*>::const_iterator cit = creatureState.attackerlist.begin(); cit != creatureState.attackerlist.end(); ++cit) {
  4650. Creature* gainExpCreature = *cit;
  4651. if(dynamic_cast<Player*>(gainExpCreature))
  4652. dynamic_cast<Player*>(gainExpCreature)->sendStats();
  4653.  
  4654. if(spectator->CanSee(gainExpCreature->pos.x, gainExpCreature->pos.y, gainExpCreature->pos.z)){
  4655. std::stringstream exp;
  4656. exp << target->getGainedExperience(gainExpCreature);
  4657. spectator->sendAnimatedText(gainExpCreature->pos, 0xD7, exp.str());
  4658. }
  4659. }
  4660.  
  4661. }
  4662.  
  4663. if(spectator->CanSee(target->pos.x, target->pos.y, target->pos.z))
  4664. {
  4665. if(creatureState.damage != 0) {
  4666. std::stringstream dmg;
  4667. dmg << std::abs(creatureState.damage);
  4668. #ifdef TJ_MONSTER_BLOOD
  4669. if (me->attackType & ATTACK_PHYSICAL)
  4670. spectator->sendAnimatedText(target->pos, target->bloodcolor, dmg.str());
  4671. else
  4672. #endif //TJ_MONSTER_BLOOD
  4673. spectator->sendAnimatedText(target->pos, me->animationColor, dmg.str());
  4674. }
  4675.  
  4676. if(creatureState.manaDamage > 0){
  4677. spectator->sendMagicEffect(target->pos, NM_ME_LOOSE_ENERGY);
  4678. std::stringstream manaDmg;
  4679. manaDmg << std::abs(creatureState.manaDamage);
  4680. spectator->sendAnimatedText(target->pos, 2, manaDmg.str());
  4681. }
  4682.  
  4683. if (target->health > 0)
  4684. spectator->sendCreatureHealth(target);
  4685.  
  4686. if (spectator == target){
  4687. CreateManaDamageUpdate(target, creature, creatureState.manaDamage);
  4688. CreateDamageUpdate(target, creature, creatureState.damage);
  4689. }
  4690. }
  4691. }
  4692. }
  4693. }
  4694. }
  4695. else {
  4696. me->FailedToCast(spectator, creature, isBlocking, hasTarget);
  4697. }
  4698.  
  4699. }
  4700.  
  4701. return bSuccess;
  4702. }
  4703.  
  4704. void Game::creatureApplyDamage(Creature *creature, int32_t damage, int32_t &outDamage, int32_t &outManaDamage
  4705. #ifdef YUR_PVP_ARENA
  4706. , CreatureVector* arenaLosers
  4707. #endif //YUR_PVP_ARENA
  4708. )
  4709. {
  4710. outDamage = damage;
  4711. outManaDamage = 0;
  4712.  
  4713. if (damage > 0)
  4714. {
  4715. if (creature->manaShieldTicks >= 1000 && (damage < creature->mana) ) {
  4716. outManaDamage = damage;
  4717. outDamage = 0;
  4718. }
  4719. else if (creature->manaShieldTicks >= 1000 && (damage > creature->mana) ) {
  4720. outManaDamage = creature->mana;
  4721. outDamage -= outManaDamage;
  4722. }
  4723. else if((creature->manaShieldTicks < 1000) && (damage > creature->health))
  4724. outDamage = creature->health;
  4725. else if (creature->manaShieldTicks >= 1000 && (damage > (creature->health + creature->mana))) {
  4726. outDamage = creature->health;
  4727. outManaDamage = creature->mana;
  4728. }
  4729.  
  4730. if(creature->manaShieldTicks < 1000 || (creature->mana == 0))
  4731. #ifdef YUR_PVP_ARENA
  4732. creature->drainHealth(outDamage, arenaLosers);
  4733. #else
  4734. creature->drainHealth(outDamage);
  4735. #endif //YUR_PVP_ARENA
  4736. else if(outManaDamage > 0)
  4737. {
  4738. #ifdef YUR_PVP_ARENA
  4739. creature->drainHealth(outDamage, arenaLosers);
  4740. #else
  4741. creature->drainHealth(outDamage);
  4742. #endif //YUR_PVP_ARENA
  4743. creature->drainMana(outManaDamage);
  4744. }
  4745. else
  4746. creature->drainMana(outDamage);
  4747. }
  4748. else {
  4749. int32_t newhealth = creature->health - damage;
  4750. if(newhealth > creature->healthmax)
  4751. newhealth = creature->healthmax;
  4752.  
  4753. creature->health = newhealth;
  4754.  
  4755. outDamage = creature->health - newhealth;
  4756. outManaDamage = 0;
  4757. }
  4758. }
  4759.  
  4760. bool Game::creatureCastSpell(Creature *creature, const Position& centerpos, const MagicEffectClass& me)
  4761. {
  4762.  
  4763. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureCastSpell()");
  4764. std::cout << "Game::creatureCastSpell " << creature->getName() << std::endl;
  4765. // if(me.offensive == false && me.damageEffect > 0 && creature->conditions.hasCondition(ATTACK_PARALYZE))
  4766. if(me.damageEffect <= 0 && creature->conditions.hasCondition(ATTACK_PARALYZE))
  4767. {
  4768. creature->removeCondition(ATTACK_PARALYZE);
  4769. changeSpeed(creature->getID(), creature->getNormalSpeed()+creature->hasteSpeed);
  4770. Player *player = dynamic_cast<Player*>(creature);
  4771. if(player)
  4772. player->sendIcons();
  4773. }
  4774.  
  4775. return creatureMakeMagic(creature, centerpos, &me);
  4776. }
  4777.  
  4778.  
  4779. bool Game::creatureThrowRune(Creature *creature, const Position& centerpos, const MagicEffectClass& me) {
  4780.  
  4781.  
  4782. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureThrowRune()");
  4783. bool ret = false;
  4784. #ifdef HUCZU_FIX
  4785. int32_t dist_x = std::abs(creature->pos.x - centerpos.x);
  4786. int32_t dist_y = std::abs(creature->pos.y - centerpos.y);
  4787. #endif //HUCZU_FIX
  4788. if(creature->pos.z != centerpos.z) {
  4789. creature->sendCancel("You need to be on the same floor.");
  4790. }
  4791. #ifdef HUCZU_FIX
  4792. else if(dist_x > 7 || dist_y > 6)
  4793. return TOO_FAR;
  4794. #endif //HUCZU_FIX
  4795. //else if(!map->canThrowItemTo(creature->pos, centerpos, false, true)) {
  4796. else if(map->canThrowObjectTo(creature->pos, centerpos, BLOCK_PROJECTILE) != RET_NOERROR) {
  4797. creature->sendCancel("You cannot throw there.");
  4798. }
  4799. else
  4800. ret = creatureMakeMagic(creature, centerpos, &me);
  4801.  
  4802.  
  4803.  
  4804. return ret;
  4805. }
  4806.  
  4807. bool Game::creatureOnPrepareAttack(Creature *creature, Position pos)
  4808. {
  4809. if(creature){
  4810. Player* player = dynamic_cast<Player*>(creature);
  4811.  
  4812. //Tile* tile = (Tile*)getTile(creature->pos.x, creature->pos.y, creature->pos.z);
  4813. Tile* tile = map->getTile(creature->pos);
  4814. //Tile* targettile = getTile(pos.x, pos.y, pos.z);
  4815. Tile* targettile = map->getTile(pos);
  4816.  
  4817. if(creature->access < g_config.ACCESS_PROTECT) {
  4818. if(tile && tile->isPz()) {
  4819. if(player) {
  4820. player->sendTextMessage(MSG_SMALLINFO, "You may not attack a person while you are in a protection zone.");
  4821. playerSetAttackedCreature(player, 0);
  4822. }
  4823.  
  4824. return false;
  4825. }
  4826. else if(targettile && targettile->isPz()) {
  4827. if(player) {
  4828. player->sendTextMessage(MSG_SMALLINFO, "You may not attack a person in a protection zone.");
  4829. playerSetAttackedCreature(player, 0);
  4830. }
  4831.  
  4832. return false;
  4833. }
  4834. }
  4835.  
  4836. return true;
  4837. }
  4838.  
  4839. return false;
  4840. }
  4841.  
  4842. bool Game::creatureOnPrepareMagicAttack(Creature *creature, Position pos, const MagicEffectClass* me)
  4843. {
  4844. if(!me->offensive || me->isIndirect() || creatureOnPrepareAttack(creature, pos)) {
  4845. /*
  4846. if(creature->access < ACCESS_PROTECT) {
  4847. if(!((std::abs(creature->pos.x-centerpos.x) <= 8) && (std::abs(creature->pos.y-centerpos.y) <= 6) &&
  4848. (creature->pos.z == centerpos.z)))
  4849. return false;
  4850. }
  4851. */
  4852.  
  4853. Player* player = dynamic_cast<Player*>(creature);
  4854. if(player) {
  4855. if(player->access < g_config.ACCESS_PROTECT) {
  4856. if(player->exhaustedTicks >= 1000 && me->causeExhaustion(true)) {
  4857. if(me->offensive) {
  4858. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.",player->pos, NM_ME_PUFF);
  4859. player->exhaustedTicks += g_config.EXHAUSTED_ADD;
  4860. }
  4861.  
  4862. return false;
  4863. }
  4864. else if(player->mana < me->manaCost) {
  4865. player->sendTextMessage(MSG_SMALLINFO, "You do not have enough mana.",player->pos, NM_ME_PUFF);
  4866. return false;
  4867. }
  4868. else
  4869. player->mana -= me->manaCost;
  4870. //player->manaspent += me->manaCost;
  4871. player->addManaSpent(me->manaCost);
  4872. }
  4873. }
  4874.  
  4875. return true;
  4876. }
  4877.  
  4878. return false;
  4879. }
  4880.  
  4881. void Game::creatureMakeDamage(Creature *creature, Creature *attackedCreature, fight_t damagetype)
  4882. {
  4883. if(!creatureOnPrepareAttack(creature, attackedCreature->pos))
  4884. return;
  4885.  
  4886.  
  4887. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureMakeDamage()");
  4888.  
  4889. Player* player = dynamic_cast<Player*>(creature);
  4890. Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  4891.  
  4892. #ifdef ANTI_MISS
  4893. if(player && player->atkMode == 1 && player->access <= g_config.ACCESS_PROTECT && attackedPlayer && attackedPlayer->skullType == 0) {
  4894. player->sendCancelAttacking();
  4895. player->sendTextMessage(MSG_SMALLINFO, "Turn secure mode off if you really want to attack unmarked players.");
  4896. return;
  4897. }
  4898. #endif //ANTI_MISS
  4899.  
  4900. //Tile* targettile = getTile(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z);
  4901. Tile* targettile = map->getTile(attackedCreature->pos);
  4902.  
  4903. //can the attacker reach the attacked?
  4904. bool inReach = false;
  4905.  
  4906. switch(damagetype){
  4907. case FIGHT_MELEE:
  4908. if((std::abs(creature->pos.x-attackedCreature->pos.x) <= 1) &&
  4909. (std::abs(creature->pos.y-attackedCreature->pos.y) <= 1) &&
  4910. (creature->pos.z == attackedCreature->pos.z))
  4911. inReach = true;
  4912. break;
  4913. case FIGHT_DIST:
  4914. if((std::abs(creature->pos.x-attackedCreature->pos.x) <= 8) &&
  4915. (std::abs(creature->pos.y-attackedCreature->pos.y) <= 5) &&
  4916. (creature->pos.z == attackedCreature->pos.z)) {
  4917.  
  4918. //if(map->canThrowItemTo(creature->pos, attackedCreature->pos, false, true))
  4919. if(map->canThrowObjectTo(creature->pos, attackedCreature->pos, BLOCK_PROJECTILE) == RET_NOERROR)
  4920. inReach = true;
  4921. }
  4922. break;
  4923. case FIGHT_MAGICDIST:
  4924. if((std::abs(creature->pos.x-attackedCreature->pos.x) <= 8) &&
  4925. (std::abs(creature->pos.y-attackedCreature->pos.y) <= 5) &&
  4926. (creature->pos.z == attackedCreature->pos.z)) {
  4927.  
  4928. //if(map->canThrowItemTo(creature->pos, attackedCreature->pos, false, true))
  4929. if(map->canThrowObjectTo(creature->pos, attackedCreature->pos, BLOCK_PROJECTILE) == RET_NOERROR)
  4930. inReach = true;
  4931. }
  4932. break;
  4933.  
  4934. }
  4935.  
  4936. if (player && player->access < g_config.ACCESS_PROTECT)
  4937. {
  4938. #ifdef YUR_CVS_MODS
  4939. player->inFightTicks = std::max(g_config.PZ_LOCKED, player->inFightTicks);
  4940. #else
  4941. player->inFightTicks = g_config.PZ_LOCKED;
  4942. #endif //YUR_CVS_MODS
  4943.  
  4944. player->sendIcons();
  4945. if(attackedPlayer)
  4946. player->pzLocked = true;
  4947. }
  4948.  
  4949. if(attackedPlayer && attackedPlayer->access < g_config.ACCESS_PROTECT)
  4950. {
  4951. #ifdef YUR_CVS_MODS
  4952. attackedPlayer->inFightTicks = std::max(g_config.PZ_LOCKED, attackedPlayer->inFightTicks);
  4953. #else
  4954. attackedPlayer->inFightTicks = g_config.PZ_LOCKED;
  4955. #endif //YUR_CVS_MODS
  4956. attackedPlayer->sendIcons();
  4957. }
  4958.  
  4959. if(!inReach){
  4960. return;
  4961. }
  4962.  
  4963. //We do all changes against a GameState to keep track of the changes,
  4964. //need some more work to work for all situations...
  4965. GameState gamestate(this, Range(creature->pos, attackedCreature->pos));
  4966.  
  4967. gamestate.onAttack(creature, attackedCreature->pos, attackedCreature);
  4968.  
  4969. const CreatureStateVec& creatureStateVec = gamestate.getCreatureStateList(targettile);
  4970. const CreatureState& creatureState = creatureStateVec[0].second;
  4971.  
  4972. if(player && (creatureState.damage > 0 || creatureState.manaDamage > 0)) {
  4973. #ifdef WANDS_JIDDO
  4974. 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()))))
  4975. player->addSkillTry(2);
  4976. #else
  4977. player->addSkillTry(2);
  4978. #endif
  4979. }
  4980. else if(player){
  4981. #ifdef WANDS_JIDDO
  4982. 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()))))
  4983. player->addSkillTry(1);
  4984. #else
  4985. player->addSkillTry(1);
  4986. #endif
  4987. }
  4988. if(attackedPlayer){
  4989. NetworkMessage msg;
  4990. msg.AddByte(0x86);
  4991. msg.AddU32(creature->getID());
  4992. msg.AddByte(0x00);
  4993. attackedPlayer->sendNetworkMessage(&msg);
  4994. }
  4995.  
  4996. SpectatorVec spectatorlist = gamestate.getSpectators();
  4997. SpectatorVec::iterator it;
  4998.  
  4999. for(it = spectatorlist.begin(); it != spectatorlist.end(); ++it) {
  5000. Player* spectator = dynamic_cast<Player*>(*it);
  5001. if(!spectator)
  5002. continue;
  5003.  
  5004. if(damagetype != FIGHT_MELEE){
  5005. spectator->sendDistanceShoot(creature->pos, attackedCreature->pos, creature->getSubFightType());
  5006. }
  5007.  
  5008. if (attackedCreature->manaShieldTicks < 1000 && (creatureState.damage == 0) &&
  5009. (spectator->CanSee(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z))) {
  5010. spectator->sendMagicEffect(attackedCreature->pos, NM_ME_PUFF);
  5011. }
  5012. else if (attackedCreature->manaShieldTicks < 1000 && (creatureState.damage < 0) &&
  5013. (spectator->CanSee(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z))) {
  5014. spectator->sendMagicEffect(attackedCreature->pos, NM_ME_BLOCKHIT);
  5015. }
  5016. else {
  5017. for(std::vector<Creature*>::const_iterator cit = creatureState.attackerlist.begin(); cit != creatureState.attackerlist.end(); ++cit) {
  5018. Creature* gainexpCreature = *cit;
  5019. if(dynamic_cast<Player*>(gainexpCreature))
  5020. dynamic_cast<Player*>(gainexpCreature)->sendStats();
  5021.  
  5022. if(spectator->CanSee(gainexpCreature->pos.x, gainexpCreature->pos.y, gainexpCreature->pos.z)) {
  5023. char exp[128];
  5024. #ifdef YUR_HIGH_LEVELS // TODO: format like this: 1,000,000
  5025. sprintf(exp,"%lld",attackedCreature->getGainedExperience(gainexpCreature));
  5026. spectator->sendAnimatedText(gainexpCreature->pos, 0xD7, exp);
  5027. #else
  5028. itoa(attackedCreature->getGainedExperience(gainexpCreature), exp, 10);
  5029. #endif //YUR_HIGH_LEVLES
  5030. spectator->sendAnimatedText(gainexpCreature->pos, 0xD7, exp);
  5031. }
  5032. }
  5033.  
  5034. if (spectator->CanSee(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z))
  5035. {
  5036. if(creatureState.damage > 0) {
  5037. std::stringstream dmg;
  5038. dmg << std::abs(creatureState.damage);
  5039. #ifdef TJ_MONSTER_BLOOD
  5040. spectator->sendAnimatedText(attackedCreature->pos, attackedCreature->bloodcolor, dmg.str());
  5041. spectator->sendMagicEffect(attackedCreature->pos, attackedCreature->bloodeffect);
  5042. #else
  5043. spectator->sendAnimatedText(attackedCreature->pos, 0xB4, dmg.str());
  5044. spectator->sendMagicEffect(attackedCreature->pos, NM_ME_DRAW_BLOOD);
  5045. #endif //TJ_MONSTER_BLOOD
  5046. }
  5047.  
  5048. if(creatureState.manaDamage >0) {
  5049. std::stringstream manaDmg;
  5050. manaDmg << std::abs(creatureState.manaDamage);
  5051. spectator->sendMagicEffect(attackedCreature->pos, NM_ME_LOOSE_ENERGY);
  5052. spectator->sendAnimatedText(attackedCreature->pos, 2, manaDmg.str());
  5053. }
  5054.  
  5055. if (attackedCreature->health > 0)
  5056. spectator->sendCreatureHealth(attackedCreature);
  5057.  
  5058. if (spectator == attackedCreature) {
  5059. CreateManaDamageUpdate(attackedCreature, creature, creatureState.manaDamage);
  5060. CreateDamageUpdate(attackedCreature, creature, creatureState.damage);
  5061. }
  5062. }
  5063. }
  5064. }
  5065.  
  5066. if(damagetype != FIGHT_MELEE && player) {
  5067. player->removeDistItem();
  5068. }
  5069.  
  5070.  
  5071. }
  5072.  
  5073. std::list<Position> Game::getPathTo(Creature *creature, Position start, Position to, bool creaturesBlock){
  5074. return map->getPathTo(creature, start, to, creaturesBlock);
  5075. }
  5076.  
  5077. std::list<Position> Game::getPathToEx(Creature *creature, Position start, Position to, bool creaturesBlock){
  5078. return map->getPathToEx(creature, start, to, creaturesBlock);
  5079. }
  5080.  
  5081.  
  5082. void Game::checkPlayerWalk(uint32_t id)
  5083. {
  5084. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkPlayerWalk");
  5085.  
  5086. Player *player = getPlayerByID(id);
  5087.  
  5088. if(!player)
  5089. return;
  5090. if(player->pathlist.empty()){
  5091. stopEvent(player->eventAutoWalk);
  5092. player->eventAutoWalk = 0;
  5093. return;
  5094. }
  5095.  
  5096. Position pos = player->pos;
  5097. Direction dir = player->pathlist.front();
  5098. player->pathlist.pop_front();
  5099.  
  5100. switch (dir) {
  5101. case NORTH:
  5102. pos.y--;
  5103. break;
  5104. case EAST:
  5105. pos.x++;
  5106. break;
  5107. case SOUTH:
  5108. pos.y++;
  5109. break;
  5110. case WEST:
  5111. pos.x--;
  5112. break;
  5113. case NORTHEAST:
  5114. pos.x++;
  5115. pos.y--;
  5116. break;
  5117. case NORTHWEST:
  5118. pos.x--;
  5119. pos.y--;
  5120. break;
  5121. case SOUTHWEST:
  5122. pos.x--;
  5123. pos.y++;
  5124. break;
  5125. case SOUTHEAST:
  5126. pos.x++;
  5127. pos.y++;
  5128. break;
  5129. }
  5130.  
  5131. /*
  5132. #ifdef __DEBUG__
  5133. std::cout << "move to: " << dir << std::endl;
  5134. #endif
  5135. */
  5136.  
  5137. player->lastmove = OTSYS_TIME();
  5138. thingMove(player, player, pos.x, pos.y, pos.z, 1);
  5139. flushSendBuffers();
  5140. if(!player->pathlist.empty()){
  5141. int ticks = (int)player->getSleepTicks();
  5142. player->eventAutoWalk = addEvent(makeTask(ticks, std::bind2nd(std::mem_fun(&Game::checkPlayerWalk), id)));
  5143. }
  5144. else
  5145. {
  5146. stopEvent(player->eventAutoWalk);//?
  5147. player->eventAutoWalk = 0;
  5148. }
  5149. }
  5150. void Game::checkCreature(uint32_t id)
  5151. {
  5152. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreature()");
  5153.  
  5154. Creature *creature = getCreatureByID(id);
  5155.  
  5156. if (creature && creature->isRemoved == false)
  5157. {
  5158. int32_t thinkTicks = 0;
  5159. int32_t oldThinkTicks = creature->onThink(thinkTicks);
  5160.  
  5161. if(thinkTicks > 0) {
  5162. creature->eventCheck = addEvent(makeTask(thinkTicks, std::bind2nd(std::mem_fun(&Game::checkCreature), id)));
  5163. }
  5164. else
  5165. creature->eventCheck = 0;
  5166.  
  5167. Player* player = dynamic_cast<Player*>(creature);
  5168. if(player)
  5169. {
  5170. //Tile *tile = getTile(player->pos.x, player->pos.y, player->pos.z);
  5171. Tile *tile = map->getTile(player->pos);
  5172. if(tile == NULL){
  5173. std::cout << "CheckPlayer NULL tile: " << player->getName() << std::endl;
  5174. return;
  5175. }
  5176.  
  5177.  
  5178.  
  5179. #ifdef _REX_CVS_MOD_
  5180. if(player->tradeTicks >= 1000)
  5181. player->tradeTicks -= thinkTicks;
  5182. #endif
  5183.  
  5184.  
  5185. #ifdef CVS_DAY_CYCLE
  5186. player->sendWorldLightLevel(lightlevel, 0xD7);
  5187. #endif //CVS_DAY_CYCLE
  5188. #ifdef REX_MUTED
  5189.  
  5190. #endif //REX_MUTED
  5191. #ifdef TR_ANTI_AFK
  5192. player->checkAfk(thinkTicks);
  5193. #endif //TR_ANTI_AF
  5194. #ifdef YUR_BOH
  5195. player->checkBoh();
  5196. #endif //YUR_BOH
  5197. #ifdef YUR_WH
  5198. player->checkWh();
  5199. #endif //YUR_WH
  5200.  
  5201. #ifdef YUR_RINGS_AMULETS
  5202. player->checkRing(thinkTicks);
  5203. #endif //YUR_RINGS_AMULETS
  5204.  
  5205. //SOFT BOOTS
  5206. if(player->softTicks >= 2) {
  5207. if(player->items[SLOT_FEET] && player->items[SLOT_FEET]->getID() == ITEM_SOFT_BOOTS && !tile->isPz()){
  5208. player->mana += min(g_config.SOFT_MANA, player->manamax - player->mana);
  5209. player->health += min(g_config.SOFT_HEALTH, player->healthmax - player->health);
  5210. }
  5211. player->softTicks = 0;
  5212. } else {
  5213. player->softTicks++;
  5214. }
  5215. // LIFE RING
  5216. if(player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_LIFE_RING_IN_USE && !tile->isPz()){
  5217. player->mana += min(g_config.LR_MANA, player->manamax - player->mana);
  5218. player->health += min(g_config.LR_HEALTH, player->healthmax - player->health);
  5219. }
  5220. // ROH
  5221. if(player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_RING_OF_HEALING_IN_USE && !tile->isPz()){
  5222. player->mana += min(g_config.ROH_MANA, player->manamax - player->mana);
  5223. player->health += min(g_config.ROH_HEALTH, player->healthmax - player->health);
  5224. }
  5225. // ROAH
  5226. // ROH 240
  5227. if(player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_STEALTH_RING_IN_USE && !tile->isPz()){
  5228. player->mana += min(g_config.ROAH_MANA, player->manamax - player->mana);
  5229. player->health += min(g_config.ROAH_HEALTH, player->healthmax - player->health);
  5230. }
  5231. // RAINBOW SHIELD
  5232. if(player->level >= 150){
  5233. if(player->items[SLOT_RIGHT] && player->items[SLOT_RIGHT]->getID() == ITEM_RAINBOW && !tile->isPz()){
  5234. if(player->items[SLOT_LEFT]){
  5235. if(player->items[SLOT_LEFT]->getID() != ITEM_RAINBOW)
  5236. if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5237. player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5238. player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5239. player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5240. }
  5241. }else{
  5242. if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5243. player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5244. player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5245. player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5246. }
  5247. }
  5248. }
  5249. if(player->items[SLOT_LEFT] && player->items[SLOT_LEFT]->getID() == ITEM_RAINBOW && !tile->isPz()){
  5250. if(player->items[SLOT_RIGHT]){
  5251. if(player->items[SLOT_RIGHT]->getID() != ITEM_RAINBOW)
  5252. if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5253. player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5254. player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5255. player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5256. }
  5257. }else{
  5258. if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5259. player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5260. player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5261. player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5262. }
  5263. }
  5264. }
  5265. }
  5266.  
  5267. // RING OF THE SKY
  5268. if(player->level >= 30 && player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_ROTS && !tile->isPz())
  5269. player->mana += min(1, player->manamax - player->mana);
  5270.  
  5271. // ORSHABAAL HEART
  5272. if(player->name == "Ekudron" || player->name == "Agecik" && player->items[SLOT_AMMO] && player->items[SLOT_AMMO]->getID() == ITEM_ORSHABAAL_HEARTH && !tile->isPz())
  5273. player->mana += min(4, player->manamax - player->mana);
  5274.  
  5275. #ifdef HUCZU_FIX
  5276. if(player->items[SLOT_FEET] && player->items[SLOT_FEET]->getID() == ITEM_SPECTRE_BOOTS)
  5277. player->immunities = ATTACK_PARALYZE;
  5278. else
  5279. player->immunities -= ATTACK_PARALYZE;
  5280. #endif //HUCZU_FIX
  5281.  
  5282. #ifdef YUR_LIGHT_ITEM
  5283. player->checkLightItem(thinkTicks);
  5284. #endif //YUR_LIGHT_ITEM
  5285. #ifdef HUCZU_EXHAUSTED
  5286. if(player->mmo > 0)
  5287. player->mmo -= 1;
  5288. else
  5289. player->mmo = 0;
  5290.  
  5291. if(player->lookex > 0)
  5292. player->lookex -= 1;
  5293. else
  5294. player->lookex = 0;
  5295.  
  5296. if(player->antyrainbow > 0)
  5297. player->antyrainbow -= 1;
  5298. else
  5299. player->antyrainbow = 0;
  5300.  
  5301. if(player->antyrainbow2 > 0)
  5302. player->antyrainbow2 -= 1;
  5303. else
  5304. player->antyrainbow2 = 0;
  5305.  
  5306. if(player->clin > 0)
  5307. player->clin -= 1;
  5308. else
  5309. player->clin = 0;
  5310.  
  5311. if(player->shut_d > 0)
  5312. player->shut_d -= 1;
  5313. else
  5314. player->shut_d = 0;
  5315.  
  5316. if(player->houseTicks > 0)
  5317. player->houseTicks -= 1;
  5318. else
  5319. player->houseTicks = 0;
  5320. #endif //HUCZU_EXHAUSTED
  5321.  
  5322. if(player->flamTicks >= 1000){
  5323. player->flamTicks -= thinkTicks;
  5324. if(player->flamTicks == 0){
  5325. player->flamBool = false;
  5326. }
  5327. }
  5328.  
  5329.  
  5330. if(player->items[SLOT_RIGHT] && player->items[SLOT_LEFT]){
  5331. 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)){
  5332. player->removeItemInventory(SLOT_RIGHT);
  5333. }
  5334. 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)){
  5335. player->removeItemInventory(SLOT_LEFT);
  5336. }
  5337. }
  5338.  
  5339. if(player->items[SLOT_RIGHT] && player->items[SLOT_LEFT]){
  5340. 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)){
  5341. player->removeItemInventory(SLOT_RIGHT);
  5342. }
  5343. 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)){
  5344. player->removeItemInventory(SLOT_LEFT);
  5345. }
  5346. }
  5347.  
  5348. #ifdef HUCZU_SKULLS
  5349. if (player->checkSkull(thinkTicks))
  5350. Skull(player);
  5351. #endif //HUCZU_SKULLS
  5352.  
  5353. #ifdef YUR_INVISIBLE
  5354. if (player->checkInvisible(thinkTicks))
  5355. creatureChangeOutfit(player);
  5356. #endif //YUR_INVISIBLE
  5357.  
  5358. #ifdef _BBK_PUSH_DELAY
  5359. if(player->pushDelay >= 1000)
  5360. {
  5361. player->pushDelay -= thinkTicks;
  5362. if(player->pushDelay < 0)
  5363. player->pushDelay = 0;
  5364. }
  5365. #endif //_BBK_PUSH_DELAY
  5366.  
  5367. if(player->training == true){
  5368. if(player->trainingTicks >= 1000){
  5369. player->trainingTicks -= thinkTicks;
  5370.  
  5371. if(player->trainingTicks < 0)
  5372. player->trainingTicks = 0;
  5373. }
  5374. if(player->trainingTicks == 0 && player->rewriteTicks == 0){
  5375. int code = random_range(47,99) * random_range(47,99);
  5376. player->rewriteCode = code;
  5377. player->needrewrite = true;
  5378. player->rewriteTicks = g_config.REWRITE_TICKS;
  5379. std::ostringstream info;
  5380. player->sendTextMessage(MSG_BLUE_TEXT,"You are training here pretty long.Are you using bot?");
  5381. info << "Please rewrite code: " << player->rewriteCode << std::ends;
  5382. player->sendTextMessage(MSG_BLUE_TEXT, info.str().c_str());
  5383. std::ostringstream info2;
  5384. info2 << "Use this command !train 1234. You have " << player->rewriteTicks/1000 << " seconds!" << std::ends;
  5385. player->sendTextMessage(MSG_BLUE_TEXT, info2.str().c_str());
  5386. }
  5387.  
  5388. if(player->needrewrite != false){
  5389. if(player->rewriteTicks >= 1000){
  5390. player->rewriteTicks -= thinkTicks;
  5391. }
  5392.  
  5393. if(player->rewriteTicks == 0){
  5394. this->teleport(player, player->masterPos);
  5395. player->training = false;
  5396. player->trainingTicks = 0;
  5397. player->needrewrite = false;
  5398. player->rewriteCode = 0;
  5399. player->rewriteTicks = 0;
  5400. player->kickPlayer();
  5401. //player->sendLogout();
  5402. }
  5403. }
  5404. }
  5405.  
  5406.  
  5407.  
  5408. #ifdef HUCZU_FIX
  5409. if(player->gainHealthTick()){
  5410. SpectatorVec list;
  5411. SpectatorVec::iterator it;
  5412. getSpectators(Range(creature->pos), list);
  5413. for(it = list.begin(); it != list.end(); ++it) {
  5414. Player* p = dynamic_cast<Player*>(*it);
  5415. if(p)
  5416. p->sendCreatureHealth(player);
  5417. }
  5418. }
  5419. #endif //HUCZU_FIX
  5420.  
  5421. if(player->lightTicks >= 1000){
  5422. player->lightTicks -= thinkTicks;
  5423. if(player->lightTicks <= 1000){
  5424. player->lightTicks = 1;
  5425. }
  5426. }
  5427. else if(player->lightTicks == 1){
  5428. if(player->lightlevel > 0){
  5429. creatureChangeLight(player, 0, player->lightlevel-1, 0xD7);
  5430. }
  5431. else{
  5432. creatureChangeLight(player, 0, 0, 0xD7);
  5433. player->lightTicks = 0;
  5434. player->lightItem = 0;
  5435. }
  5436. if(player->lightTries > 0){
  5437. player->lightTicks = 3*60*1000;
  5438. player->lightTries -= 1;
  5439. }
  5440. }
  5441.  
  5442. #ifdef HUCZU_SKULLS
  5443. checkSkullTime(player);
  5444. #endif //HUCZU_SKULLS
  5445.  
  5446.  
  5447. if(!tile->isPz()){
  5448. if(player->food > 1000){
  5449. player->gainManaTick();
  5450. player->food -= thinkTicks;
  5451. if(player->healthmax - player->health > 0){
  5452. if(player->gainHealthTick()){
  5453. SpectatorVec list;
  5454. SpectatorVec::iterator it;
  5455. getSpectators(Range(creature->pos), list);
  5456. for(it = list.begin(); it != list.end(); ++it) {
  5457. Player* p = dynamic_cast<Player*>(*it);
  5458. if(p)
  5459. p->sendCreatureHealth(player);
  5460. }
  5461. }
  5462. }
  5463. }
  5464. }
  5465.  
  5466. //send stast only if have changed
  5467. if(player->NeedUpdateStats()){
  5468. player->sendStats();
  5469. }
  5470.  
  5471. player->sendPing(thinkTicks);
  5472.  
  5473. if(player->inFightTicks >= 1000) {
  5474. player->inFightTicks -= thinkTicks;
  5475.  
  5476. if(player->inFightTicks < 1000)
  5477. player->pzLocked = false;
  5478. player->sendIcons();
  5479. }
  5480.  
  5481. if(player->drunkTicks >= 1000) {
  5482. int32_t random = random_range(1,100);
  5483. if(random <= 25){
  5484. creatureSay(creature, SPEAK_SAY, "Hicks!");
  5485. Position pos;
  5486. int32_t randomwalk = random_range(1,4);
  5487. switch(randomwalk){
  5488. case 1:pos.x++;break;
  5489. case 2:pos.x--;break;
  5490. case 3:pos.y++;break;
  5491. case 4:pos.y--;break;
  5492. }
  5493. Tile* toTile = getTile(pos.x, pos.y, pos.z);
  5494. //make sure they don't get teleported into a place they shouldn't
  5495. if(toTile &&
  5496. !toTile->isBlocking(1, false, false) &&
  5497. !toTile->isBlocking(2, false, false) &&
  5498. !toTile->isBlocking(4, false, false) &&
  5499. !toTile->isBlocking(8, false, false) &&
  5500. !toTile->isBlocking(16, false, false))
  5501. teleport(player,pos);
  5502. }
  5503. player->drunkTicks -= thinkTicks;
  5504. player->sendIcons();
  5505. }
  5506.  
  5507. if(player->exhaustedTicks >= 1000){
  5508. player->exhaustedTicks -= thinkTicks;
  5509.  
  5510. if(player->exhaustedTicks < 0)
  5511. player->exhaustedTicks = 0;
  5512. }
  5513.  
  5514. if(player->manaShieldTicks >=1000){
  5515. player->manaShieldTicks -= thinkTicks;
  5516.  
  5517. if(player->manaShieldTicks < 1000)
  5518. player->sendIcons();
  5519. }
  5520. if(player->dwarvenTicks > 0){
  5521. player->drunkTicks = 0;
  5522. player->sendIcons();
  5523. }
  5524. if(player->dwarvenTicks = 0){
  5525. player->drunkTicks = 4000;
  5526. player->sendIcons();
  5527. }
  5528.  
  5529. if(player->hasteTicks >=1000)
  5530. player->hasteTicks -= thinkTicks;
  5531. }else{
  5532.  
  5533. if(creature->manaShieldTicks >=1000){
  5534. creature->manaShieldTicks -= thinkTicks;
  5535. }
  5536.  
  5537. if(creature->hasteTicks >=1000){
  5538. creature->hasteTicks -= thinkTicks;
  5539. }
  5540.  
  5541. #ifdef YUR_INVISIBLE
  5542. if (creature->checkInvisible(thinkTicks))
  5543. creatureChangeOutfit(creature);
  5544. #endif //YUR_INVISIBLE
  5545. }
  5546.  
  5547. Conditions& conditions = creature->getConditions();
  5548. for(Conditions::iterator condIt = conditions.begin(); condIt != conditions.end(); ++condIt) {
  5549. if(condIt->first == ATTACK_FIRE || condIt->first == ATTACK_ENERGY || condIt->first == ATTACK_POISON) {
  5550. ConditionVec &condVec = condIt->second;
  5551.  
  5552. if(condVec.empty())
  5553. continue;
  5554.  
  5555. CreatureCondition& condition = condVec[0];
  5556.  
  5557. if(condition.onTick(oldThinkTicks)) {
  5558. const MagicEffectTargetCreatureCondition* magicTargetCondition = condition.getCondition();
  5559. Creature* c = getCreatureByID(magicTargetCondition->getOwnerID());
  5560. creatureMakeMagic(c, creature->pos, magicTargetCondition);
  5561.  
  5562. if(condition.getCount() <= 0) {
  5563. condVec.erase(condVec.begin());
  5564. if(dynamic_cast<Player*>(creature))
  5565. player->sendIcons();
  5566. }
  5567. }
  5568. }
  5569. if(condIt->first == ATTACK_PARALYZE)
  5570. {
  5571. ConditionVec &condVec = condIt->second;
  5572. if(condVec.empty())
  5573. continue;
  5574.  
  5575. CreatureCondition& condition = condVec[0];
  5576. if(condition.onTick(oldThinkTicks))
  5577. {
  5578. //Player* player = dynamic_cast<Player*>(creature);
  5579. if(creature->getImmunities() != ATTACK_PARALYZE)
  5580. {
  5581. changeSpeed(creature->getID(), 100);
  5582. if(player)
  5583. {
  5584. player->sendTextMessage(MSG_SMALLINFO, "You are paralyzed.");
  5585. player->sendIcons();
  5586. }
  5587. }
  5588.  
  5589. if(condition.getCount() <= 0)
  5590. {
  5591. condVec.erase(condVec.begin());
  5592. changeSpeed(creature->getID(), creature->getNormalSpeed()+creature->hasteSpeed);
  5593. if(player)
  5594. {
  5595. player->sendIcons();
  5596. }
  5597. }
  5598. }
  5599. }
  5600. }
  5601. flushSendBuffers();
  5602. }
  5603. }
  5604.  
  5605. void Game::changeOutfit(uint32_t id, int32_t looktype){
  5606.  
  5607. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::changeOutfit()");
  5608.  
  5609. Creature *creature = getCreatureByID(id);
  5610. if(creature){
  5611. creature->looktype = looktype;
  5612. if(creature->lookfeet_master != 0 || creature->lookhead_master != 0 ||
  5613. creature->looklegs_master != 0 || creature->lookbody_master != 0 ){
  5614. creature->lookhead = creature->lookhead_master;
  5615. creature->lookbody = creature->lookbody_master;
  5616. creature->looklegs = creature->looklegs_master;
  5617. creature->lookfeet = creature->lookfeet_master;
  5618.  
  5619. creature->lookhead_master = 0;
  5620. creature->lookbody_master = 0;
  5621. creature->looklegs_master = 0;
  5622. creature->lookfeet_master = 0;
  5623. }
  5624. creatureChangeOutfit(creature);
  5625. }
  5626. }
  5627.  
  5628. void Game::changeOutfitAfter(uint32_t id, int32_t looktype, long time)
  5629. {
  5630. addEvent(makeTask(time, boost::bind(&Game::changeOutfit, this,id, looktype)));
  5631. }
  5632.  
  5633. void Game::changeSpeed(uint32_t id, unsigned short speed)
  5634. {
  5635. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::changeSpeed()");
  5636. Creature *creature = getCreatureByID(id);
  5637. if(creature && /*creature->hasteTicks < 1000 && */creature->speed != speed)
  5638. {
  5639. creature->speed = speed;
  5640. Player* player = dynamic_cast<Player*>(creature);
  5641. if(player){
  5642. player->sendChangeSpeed(creature);
  5643. player->sendIcons();
  5644. }
  5645. SpectatorVec list;
  5646. SpectatorVec::iterator it;
  5647. getSpectators(Range(creature->pos), list);
  5648. //for(uint32_t i = 0; i < list.size(); i++)
  5649. for(it = list.begin(); it != list.end(); ++it) {
  5650. Player* p = dynamic_cast<Player*>(*it);
  5651. if(p)
  5652. p->sendChangeSpeed(creature);
  5653. }
  5654. }
  5655. }
  5656.  
  5657. void Game::checkCreatureAttacking(uint32_t id)
  5658. {
  5659. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreatureAttacking()");
  5660.  
  5661. Creature *creature = getCreatureByID(id);
  5662. if (creature != NULL && creature->isRemoved == false)
  5663. {
  5664.  
  5665. creature->eventCheckAttacking = 0;
  5666. Player *player = dynamic_cast<Player*>(creature);
  5667. Monster *monster = dynamic_cast<Monster*>(creature);
  5668. if (monster) {
  5669. monster->onAttack();
  5670. }
  5671. else {
  5672. if (creature->attackedCreature != 0)
  5673. {
  5674. Creature *attackedCreature = getCreatureByID(creature->attackedCreature);
  5675. if (attackedCreature)
  5676. {
  5677. // canAttack system BRY
  5678.  
  5679. Player *attacker = dynamic_cast<Player*>(creature);
  5680. Player *attacked = dynamic_cast<Player*>(attackedCreature);
  5681. bool canAttack = false;
  5682. if(attacker && attacked)
  5683. {
  5684. Tile* tile = getTile(attacker->pos.x,attacker->pos.y, attacker->pos.z);
  5685. if(attacked->level >= 1 && attacked->level < 30 && attacker->level >= 1 && attacker->level < 30)
  5686. canAttack = false;
  5687.  
  5688. else if(attacked->level >= 30 && attacked->level < 80 && attacker->level >= 30 && attacker->level < 80)
  5689. canAttack = true;
  5690.  
  5691. else if(attacked->level >= 81 && attacked->level < 999 && attacker->level >= 81 && attacker->level < 999)
  5692. canAttack = true;
  5693.  
  5694.  
  5695. else if(tile && tile->isPvpArena())
  5696. canAttack = true;
  5697. }
  5698.  
  5699.  
  5700.  
  5701. if(attacker && attacked && !canAttack)
  5702. {
  5703. attacker->sendCancelAttacking();
  5704. attacker->sendCancel("You may not attack this player yet.");
  5705. playerSetAttackedCreature(attacker, 0);
  5706. return;
  5707. }
  5708. //Tile* fromtile = getTile(creature->pos.x, creature->pos.y, creature->pos.z);
  5709. Tile* fromtile = map->getTile(creature->pos);
  5710. if(fromtile == NULL) {
  5711. std::cout << "checkCreatureAttacking NULL tile: " << creature->getName() << std::endl;
  5712. //return;
  5713. }
  5714. Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  5715. if (!attackedCreature->isAttackable() == 0 && fromtile && fromtile->isPz() && creature->access < g_config.ACCESS_PROTECT)
  5716. {
  5717. Player* player = dynamic_cast<Player*>(creature);
  5718. if (player) {
  5719. player->sendTextMessage(MSG_SMALLINFO, "You may not attack a person in a protection zone.");
  5720. //player->sendCancelAttacking();
  5721. playerSetAttackedCreature(player, 0);
  5722. return;
  5723. }
  5724. }
  5725. #ifdef YUR_INVISIBLE
  5726. if (attackedCreature->isInvisible())
  5727. {
  5728. Player* player = dynamic_cast<Player*>(creature);
  5729. Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  5730.  
  5731. if (player && !attackedPlayer) {
  5732. player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  5733. playerSetAttackedCreature(player, 0);
  5734. return;
  5735. }
  5736. }
  5737. #endif //YUR_INVISIBLE
  5738. else
  5739. {
  5740. if (attackedCreature != NULL && attackedCreature->isRemoved == false)
  5741. {
  5742.  
  5743. #ifdef ZS_SWORDS
  5744. int32_t swordid = player->getSwordId();
  5745. if (swordid > 0)
  5746. useSword(player, attackedCreature, swordid);
  5747. #endif //ZS_SWORDS
  5748.  
  5749. if(player && player->followMode == 0x01) {
  5750. player->followCreature = attackedCreature->getID();
  5751. playerAttackSetFollowCreature(player, attackedCreature->getID());
  5752. playerFollowAttacking(player, attackedCreature);
  5753. long long delay = player->getSleepTicks();
  5754. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollowAttack), player->getID())));
  5755. }
  5756.  
  5757.  
  5758. #ifdef WANDS_JIDDO
  5759. Player* player = dynamic_cast<Player*>(creature);
  5760. int32_t wandid = 0;
  5761. if(player && ((player->items[SLOT_RIGHT] && (wandid = player->items[SLOT_RIGHT]->getWand())) || (player->items[SLOT_LEFT] && (wandid = player->items[SLOT_LEFT]->getWand())))) {
  5762. useWand(creature, attackedCreature, wandid);
  5763. } else {
  5764. #endif
  5765. Player* player = dynamic_cast<Player*>(creature);
  5766. if (player)
  5767. {
  5768. #ifdef SD_BURST_ARROW
  5769. if (player->isUsingBurstArrows())
  5770. burstArrow(player, attackedCreature->pos);
  5771. #endif //SD_BURST_ARROW
  5772. if(player->flamBool == true){
  5773. Blasting(player, attackedCreature, attackedCreature->pos);
  5774. player->flamBool = false;
  5775. }
  5776. }
  5777. this->creatureMakeDamage(creature, attackedCreature, creature->getFightType());
  5778. #ifdef WANDS_JIDDO
  5779. }
  5780. #endif
  5781. }
  5782. }
  5783.  
  5784. if (player->vocation == 0) {
  5785. int32_t speed = int32_t(g_config.NO_VOC_SPEED * 1000);
  5786. creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5787. }
  5788. else if (player->vocation == 1) {
  5789. int32_t speed = int32_t(g_config.SORC_SPEED * 1000);
  5790. creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5791. }
  5792. else if (player->vocation == 2) {
  5793. int32_t speed = int32_t(g_config.DRUID_SPEED * 1000);
  5794. creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5795. }
  5796. else if (player->vocation == 3) {
  5797. int32_t speed = int32_t(g_config.PALLY_SPEED * 1000);
  5798. creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5799. }
  5800. else if (player->vocation == 4) {
  5801. int32_t speed = int32_t(g_config.KNIGHT_SPEED * 1000);
  5802. creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5803. }
  5804. else { //change the 2000 to whatever you want; 2000 = 2 seconds per attack
  5805. creature->eventCheckAttacking = addEvent(makeTask(1000, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5806. }
  5807. }
  5808. }
  5809. }
  5810. flushSendBuffers();
  5811. }
  5812. }
  5813. void Game::checkDecay(int32_t t)
  5814. {
  5815. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkDecay()");
  5816.  
  5817. addEvent(makeTask(DECAY_INTERVAL, boost::bind(&Game::checkDecay,this,DECAY_INTERVAL)));
  5818.  
  5819. list<decayBlock*>::iterator it;
  5820. for(it = decayVector.begin();it != decayVector.end();){
  5821. (*it)->decayTime -= t;
  5822. if((*it)->decayTime <= 0){
  5823. list<Item*>::iterator it2;
  5824. for(it2 = (*it)->decayItems.begin(); it2 != (*it)->decayItems.end(); it2++){
  5825. /*todo: Decaying item could be in a container carried by a player,
  5826. should all items have a pointer to their parent (like containers)?*/
  5827. Item* item = *it2;
  5828. item->isDecaying = false;
  5829. if(item->canDecay()){
  5830. if(item->pos.x != 0xFFFF){
  5831. Tile *tile = map->getTile(item->pos);
  5832. if(tile){
  5833. Position pos = item->pos;
  5834. Item* newitem = item->decay();
  5835.  
  5836. if(newitem){
  5837. int32_t stackpos = tile->getThingStackPos(item);
  5838. if(newitem == item){
  5839. sendUpdateThing(NULL,pos,newitem,stackpos);
  5840. }
  5841. else{
  5842. if(tile->removeThing(item)){
  5843. //autoclose containers
  5844. if(dynamic_cast<Container*>(item)){
  5845. SpectatorVec list;
  5846. SpectatorVec::iterator it;
  5847.  
  5848. getSpectators(Range(pos, true), list);
  5849.  
  5850. for(it = list.begin(); it != list.end(); ++it) {
  5851. Player* spectator = dynamic_cast<Player*>(*it);
  5852. if(spectator)
  5853. spectator->onThingRemove(item);
  5854. }
  5855. }
  5856.  
  5857. tile->insertThing(newitem, stackpos);
  5858. sendUpdateThing(NULL,pos,newitem,stackpos);
  5859. FreeThing(item);
  5860. }
  5861. }
  5862. startDecay(newitem);
  5863. }
  5864. else{
  5865. if(removeThing(NULL,pos,item)){
  5866. FreeThing(item);
  5867. }
  5868. }//newitem
  5869. }//tile
  5870. }//pos != 0xFFFF
  5871. }//item->canDecay()
  5872. FreeThing(item);
  5873. }//for it2
  5874. delete *it;
  5875. it = decayVector.erase(it);
  5876. }//(*it)->decayTime <= 0
  5877. else{
  5878. it++;
  5879. }
  5880. }//for it
  5881.  
  5882. flushSendBuffers();
  5883. }
  5884.  
  5885. void Game::startDecay(Item* item){
  5886. if(item->isDecaying)
  5887. return;//dont add 2 times the same item
  5888. //get decay time
  5889. item->isDecaying = true;
  5890. uint32_t dtime = item->getDecayTime();
  5891. if(dtime == 0)
  5892. return;
  5893. //round time
  5894. if(dtime < DECAY_INTERVAL)
  5895. dtime = DECAY_INTERVAL;
  5896. dtime = (dtime/DECAY_INTERVAL)*DECAY_INTERVAL;
  5897. item->useThing();
  5898. //search if there are any block with this time
  5899. list<decayBlock*>::iterator it;
  5900. for(it = decayVector.begin();it != decayVector.end();it++){
  5901. if((*it)->decayTime == dtime){
  5902. (*it)->decayItems.push_back(item);
  5903. return;
  5904. }
  5905. }
  5906. //we need a new decayBlock
  5907. decayBlock* db = new decayBlock;
  5908. db->decayTime = dtime;
  5909. db->decayItems.clear();
  5910. db->decayItems.push_back(item);
  5911. decayVector.push_back(db);
  5912. }
  5913.  
  5914. void Game::checkSpawns(int32_t t)
  5915. {
  5916. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkSpawns()");
  5917.  
  5918. SpawnManager::instance()->checkSpawns(t);
  5919. this->addEvent(makeTask(t, std::bind2nd(std::mem_fun(&Game::checkSpawns), t)));
  5920. }
  5921.  
  5922. void Game::CreateDamageUpdate(Creature* creature, Creature* attackCreature, int32_t damage)
  5923. {
  5924. Player* player = dynamic_cast<Player*>(creature);
  5925. Player* attackPlayer = dynamic_cast<Player*>(attackCreature);
  5926. if(!player)
  5927. return;
  5928. //player->sendStats();
  5929. //msg.AddPlayerStats(player);
  5930. if (damage > 0) {
  5931. std::stringstream dmgmesg, info;
  5932.  
  5933. if(damage == 1) {
  5934. dmgmesg << "You lose 1 hitpoint";
  5935. }
  5936. else
  5937. dmgmesg << "You lose " << damage << " hitpoints";
  5938.  
  5939. if(attackPlayer) {
  5940. dmgmesg << " due to an attack by " << attackCreature->getName();
  5941. }
  5942. else if(attackCreature) {
  5943. std::string strname = attackCreature->getName();
  5944. std::transform(strname.begin(), strname.end(), strname.begin(), (int32_t(*)(int32_t))tolower);
  5945. dmgmesg << " due to an attack by a " << strname;
  5946. }
  5947. dmgmesg <<".";
  5948.  
  5949. player->sendTextMessage(MSG_EVENT, dmgmesg.str().c_str());
  5950. //msg.AddTextMessage(MSG_EVENT, dmgmesg.str().c_str());
  5951. }
  5952. if (player->isRemoved == true){
  5953. player->sendTextMessage(MSG_ADVANCE, "You are dead.");
  5954. }
  5955. }
  5956.  
  5957.  
  5958. void Game::CreateManaDamageUpdate(Creature* creature, Creature* attackCreature, int32_t damage)
  5959. {
  5960. Player* player = dynamic_cast<Player*>(creature);
  5961. if(!player)
  5962. return;
  5963.  
  5964. if (damage > 0) {
  5965. std::stringstream dmgmesg;
  5966. dmgmesg << "You lose " << damage << " mana";
  5967. if(attackCreature) {
  5968. dmgmesg << " blocking an attack by " << attackCreature->getName();
  5969. }
  5970. dmgmesg <<".";
  5971.  
  5972. player->sendTextMessage(MSG_EVENT, dmgmesg.str().c_str());
  5973. }
  5974. }
  5975.  
  5976. bool Game::creatureSaySpell(Creature *creature, const std::string &text, bool say)
  5977. {
  5978. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureSaySpell()");
  5979.  
  5980. bool ret = false;
  5981.  
  5982. Player* player = dynamic_cast<Player*>(creature);
  5983. std::string temp, var;
  5984. uint32_t loc = (uint32_t)text.find( "\"", 0 );
  5985. if( loc != string::npos && loc >= 0){
  5986. temp = std::string(text, 0, loc-1);
  5987. var = std::string(text, (loc+1), text.size()-loc-1);
  5988. }
  5989. else {
  5990. temp = text;
  5991. var = std::string("");
  5992. }
  5993.  
  5994. std::transform(temp.begin(), temp.end(), temp.begin(), (int32_t(*)(int32_t))tolower);
  5995.  
  5996. if(creature->access >= g_config.ACCESS_PROTECT || !player){
  5997. std::map<std::string, Spell*>::iterator sit = spells.getAllSpells()->find(temp);
  5998. if (sit != spells.getAllSpells()->end()){
  5999. sit->second->getSpellScript()->castSpell(creature, creature->pos, var);
  6000. if (creature->access >= g_config.ACCESS_PROTECT && say == true)
  6001. this->creatureSay(creature, SPEAK_MONSTER1, text);
  6002. ret = true;
  6003. }
  6004. }
  6005. else if(player){
  6006. std::map<std::string, Spell*>* tmp = spells.getVocSpells(player->vocation);
  6007. if(tmp){
  6008. std::map<std::string, Spell*>::iterator sit = tmp->find(temp);
  6009. if(sit != tmp->end()){
  6010. if(player->maglevel >= sit->second->getMagLv()){
  6011. #ifdef YUR_LEARN_SPELLS
  6012. if (g_config.LEARN_SPELLS && !player->knowsSpell(temp))
  6013. ret = false;
  6014. else
  6015. #endif //YUR_LEARN_SPELLS
  6016. {
  6017. if(sit->second->getSpellScript()->castSpell(creature, creature->pos, var) && say == true)
  6018. this->creatureSay(player, SPEAK_MONSTER1, text);
  6019. ret = true;
  6020. }
  6021. }
  6022. }
  6023. }
  6024. }
  6025.  
  6026.  
  6027.  
  6028. return ret;
  6029. }
  6030.  
  6031. void Game::playerAutoWalk(Player* player, std::list<Direction>& path)
  6032. {
  6033. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerAutoWalk()");
  6034.  
  6035. stopEvent(player->eventAutoWalk);
  6036. player->eventAutoWalk = 0;
  6037.  
  6038. if(player->isRemoved)
  6039. return;
  6040.  
  6041. player->pathlist = path;
  6042. int32_t ticks = (int32_t)player->getSleepTicks();
  6043. /*
  6044. #ifdef __DEBUG__
  6045. std::cout << "playerAutoWalk - " << ticks << std::endl;
  6046. #endif
  6047. */
  6048. if(!player->pathlist.empty())
  6049. player->eventAutoWalk = addEvent(makeTask(ticks, std::bind2nd(std::mem_fun(&Game::checkPlayerWalk), player->getID())));
  6050.  
  6051. // then we schedule the movement...
  6052. // the interval seems to depend on the speed of the char?
  6053. //player->eventAutoWalk = addEvent(makeTask<Direction>(0, MovePlayer(player->getID()), path, 400, StopMovePlayer(player->getID())));
  6054. //player->pathlist = path;
  6055. }
  6056.  
  6057. bool Game::playerUseItemEx(Player *player, const Position& posFrom,const unsigned char stack_from,
  6058. const Position &posTo,const unsigned char stack_to, const unsigned short itemid)
  6059. {
  6060. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerUseItemEx()");
  6061.  
  6062. if(player->isRemoved)
  6063. return false;
  6064.  
  6065. bool ret = false;
  6066.  
  6067. Position thingpos = getThingMapPos(player, posFrom);
  6068. Item *item = dynamic_cast<Item*>(getThing(posFrom, stack_from, player));
  6069. Container* container = player->getContainer(player->shop_index);
  6070. if(container && item && !container->shop.empty() && container->isHoldingItem(item))
  6071. return false;
  6072.  
  6073. if(item) {
  6074. //Runes
  6075. std::map<unsigned short, Spell*>::iterator sit = spells.getAllRuneSpells()->find(item->getID());
  6076. if(sit != spells.getAllRuneSpells()->end()) {
  6077. #ifdef PALL_REQ_LVL
  6078. std::stringstream ss;
  6079. if(item->getReqLevel() > player->getLevel()){
  6080. ss << "\n Musisz miec " << item->getReqLevel() << " poziom aby tego uzyc.";
  6081. ret = false;
  6082. }
  6083. if(item->isWeapon() && item->getReqVoc() != player->getVocation()){
  6084. switch(item->getReqVoc()){
  6085. case 1:
  6086. ss << "\n You must be a sorcerer to use this weapon.";
  6087. ret = false;
  6088. break;
  6089. case 2:
  6090. ss << "\n You must be a druid to use this weapon.";
  6091. ret = false;
  6092. break;
  6093. case 3:
  6094. ss << "\n You must be a paladin to use this weapon.";
  6095. ret = false;
  6096. break;
  6097. case 4:
  6098. ss << "\n You must be a knight to use this weapon.";
  6099. ret = false;
  6100. break;
  6101. }
  6102. }
  6103. player->sendTextMessage(MSG_SMALLINFO, ss.str().c_str());
  6104. #endif //PALL_REQ_LVL
  6105. if( (abs(thingpos.x - player->pos.x) > 1) || (abs(thingpos.y - player->pos.y) > 1) ) {
  6106. player->sendCancel("Too far away.");
  6107. ret = false;
  6108. }
  6109. else {
  6110. std::string var = std::string("");
  6111. if(player->access >= g_config.ACCESS_PROTECT || sit->second->getMagLv() <= player->maglevel)
  6112. {
  6113. bool success = sit->second->getSpellScript()->castSpell(player, posTo, var);
  6114. ret = success;
  6115. if(success) {
  6116. autoCloseTrade(item);
  6117. item->setItemCharge(std::max((int32_t)item->getItemCharge() - 1, 0) );
  6118. if(item->getItemCharge() == 0) {
  6119. if(removeThing(player,posFrom,item)){
  6120. FreeThing(item);
  6121. }
  6122. }
  6123. }
  6124. }
  6125. else
  6126. {
  6127. player->sendCancel("You don't have the required magic level to use that rune.");
  6128. }
  6129. }
  6130. }
  6131. else{
  6132. actions.UseItemEx(player,posFrom,stack_from,posTo,stack_to,itemid);
  6133. ret = true;
  6134. }
  6135. }
  6136.  
  6137.  
  6138. return ret;
  6139. }
  6140.  
  6141.  
  6142. bool Game::playerUseItem(Player *player, const Position& pos, const unsigned char stackpos, const unsigned short itemid, unsigned char index)
  6143. {
  6144. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerUseItem()");
  6145. if(itemid == 2273 || itemid == 2275 ){
  6146.  
  6147. MagicEffectClass pox;
  6148. pox.animationColor = 0;
  6149. pox.damageEffect = NM_ME_MAGIC_ENERGIE;
  6150. pox.hitEffect = 255;
  6151. pox.attackType = ATTACK_NONE;
  6152. pox.maxDamage = 0;
  6153. pox.minDamage = 0;
  6154. pox.offensive = false;
  6155. pox.manaCost = 0;
  6156. if(creatureMakeMagic(player, player->pos, &pox)){
  6157. player->removeCondition(ATTACK_PARALYZE);
  6158. int32_t newspeed = player->getNormalSpeed()+player->hasteSpeed;
  6159. changeSpeed(player->getID(), (unsigned short)newspeed);
  6160.  
  6161. if(player)
  6162. player->sendIcons();
  6163. }
  6164. else{
  6165. player->sendCancel("Sorry, not possible.");
  6166. return false;
  6167. }
  6168. }
  6169. if(player->isRemoved)
  6170. return false;
  6171.  
  6172. actions.UseItem(player,pos,stackpos,itemid,index);
  6173. return true;
  6174. }
  6175.  
  6176. bool Game::playerUseBattleWindow(Player *player, Position &posFrom, unsigned char stackpos, unsigned short itemid, uint32_t creatureid)
  6177. {
  6178. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerUseBattleWindow");
  6179.  
  6180. if(player->isRemoved)
  6181. return false;
  6182.  
  6183. Creature *creature = getCreatureByID(creatureid);
  6184. if(!creature || dynamic_cast<Player*>(creature))
  6185. return false;
  6186.  
  6187. 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)
  6188. return false;
  6189.  
  6190. bool ret = false;
  6191.  
  6192. Position thingpos = getThingMapPos(player, posFrom);
  6193. Item *item = dynamic_cast<Item*>(getThing(posFrom, stackpos, player));
  6194. Container* container = player->getContainer(player->shop_index);
  6195. if(container && item && !container->shop.empty() && container->isHoldingItem(item))
  6196. return false;
  6197. if(item) {
  6198. //Runes
  6199. std::map<unsigned short, Spell*>::iterator sit = spells.getAllRuneSpells()->find(item->getID());
  6200. if(sit != spells.getAllRuneSpells()->end()) {
  6201. if( (abs(thingpos.x - player->pos.x) > 1) || (abs(thingpos.y - player->pos.y) > 1) ) {
  6202. player->sendCancel("Too far away.");
  6203. }
  6204. else {
  6205. std::string var = std::string("");
  6206. if(player->access >= g_config.ACCESS_PROTECT || sit->second->getMagLv() <= player->maglevel)
  6207. {
  6208. bool success = sit->second->getSpellScript()->castSpell(player, creature->pos, var);
  6209. ret = success;
  6210. if(success){
  6211. autoCloseTrade(item);
  6212. item->setItemCharge(std::max((int32_t)item->getItemCharge() - 1, 0) );
  6213. if(item->getItemCharge() == 0){
  6214. if(removeThing(player,posFrom,item)){
  6215. FreeThing(item);
  6216. }
  6217. }
  6218. }
  6219. }
  6220. else
  6221. {
  6222. player->sendCancel("You don't have the required magic level to use that rune.");
  6223. }
  6224. }
  6225. }
  6226. }
  6227. return ret;
  6228. }
  6229.  
  6230. bool Game::playerRotateItem(Player *player, const Position& pos, const unsigned char stackpos, const unsigned short itemid)
  6231. {
  6232. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerRotateItem()");
  6233.  
  6234. if(player->isRemoved)
  6235. return false;
  6236.  
  6237. if(std::abs(player->pos.x - pos.x) > 1 || std::abs(player->pos.y - pos.y) > 1 || player->pos.z != pos.z){
  6238. player->sendCancel("Too far away.");
  6239. return false;
  6240. }
  6241.  
  6242. Item *item = dynamic_cast<Item*>(getThing(pos, stackpos, player));
  6243. if(item && item->rotate()){
  6244. sendUpdateThing(player, pos, item, stackpos);
  6245. }
  6246.  
  6247. return false;
  6248. }
  6249.  
  6250. void Game::playerRequestTrade(Player* player, const Position& pos,
  6251. const unsigned char stackpos, const unsigned short itemid, uint32_t playerid)
  6252. {
  6253. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerRequestTrade()");
  6254.  
  6255. if(player->isRemoved)
  6256. return;
  6257.  
  6258. Player *tradePartner = getPlayerByID(playerid);
  6259. if(!tradePartner || tradePartner == player) {
  6260. player->sendTextMessage(MSG_INFO, "Sorry, not possible.");
  6261. return;
  6262. }
  6263.  
  6264. if(player->tradeState != TRADE_NONE && !(player->tradeState == TRADE_ACKNOWLEDGE && player->tradePartner == playerid)) {
  6265. player->sendCancel("You are already trading.");
  6266. return;
  6267. }
  6268. else if(tradePartner->tradeState != TRADE_NONE && tradePartner->tradePartner != player->getID()) {
  6269. player->sendCancel("This player is already trading.");
  6270. return;
  6271. }
  6272.  
  6273. Item *tradeItem = dynamic_cast<Item*>(getThing(pos, stackpos, player));
  6274. if(!tradeItem || tradeItem->getID() != itemid || !tradeItem->isPickupable()) {
  6275. player->sendCancel("Sorry, not possible.");
  6276. return;
  6277. }
  6278.  
  6279. #ifdef __KIRO_AKT__
  6280. if(tradeItem->getID() == ITEM_AKT)
  6281. {
  6282. Tile* tile = getTile(player->pos);
  6283. House* house = tile? tile->getHouse() : NULL;
  6284.  
  6285. if(!house)
  6286. {
  6287. player->sendCancel("You must stay in house!");
  6288. return;
  6289. }
  6290. if(house->getOwner() != player->getName())
  6291. {
  6292. player->sendCancel("You must stay in your house!");
  6293. return;
  6294. }
  6295. }
  6296.  
  6297. #endif
  6298.  
  6299. if(!player->removeItem(tradeItem, true)) {
  6300. /*if( (abs(player->pos.x - pos.x) > 1) || (abs(player->pos.y - pos.y) > 1) ) {
  6301. player->sendCancel("To far away...");
  6302. return;
  6303. }*/
  6304. player->sendCancel("Sorry, not possible.");
  6305. return;
  6306. }
  6307.  
  6308. std::map<Item*, uint32_t>::const_iterator it;
  6309. const Container* container = NULL;
  6310. for(it = tradeItems.begin(); it != tradeItems.end(); it++) {
  6311. if(tradeItem == it->first ||
  6312. ((container = dynamic_cast<const Container*>(tradeItem)) && container->isHoldingItem(it->first)) ||
  6313. ((container = dynamic_cast<const Container*>(it->first)) && container->isHoldingItem(tradeItem)))
  6314. {
  6315. player->sendTextMessage(MSG_INFO, "This item is already beeing traded.");
  6316. return;
  6317. }
  6318. }
  6319.  
  6320. Container* tradeContainer = dynamic_cast<Container*>(tradeItem);
  6321. if(tradeContainer && tradeContainer->getItemHoldingCount() + 1 > 100){
  6322. player->sendTextMessage(MSG_INFO, "You cannot trade more than 100 items.");
  6323. return;
  6324. }
  6325.  
  6326. player->tradePartner = playerid;
  6327. player->tradeItem = tradeItem;
  6328. player->tradeState = TRADE_INITIATED;
  6329. tradeItem->useThing();
  6330. tradeItems[tradeItem] = player->getID();
  6331.  
  6332. player->sendTradeItemRequest(player, tradeItem, true);
  6333.  
  6334. if(tradePartner->tradeState == TRADE_NONE){
  6335. std::stringstream trademsg;
  6336. trademsg << player->getName() <<" wants to trade with you.";
  6337. tradePartner->sendTextMessage(MSG_INFO, trademsg.str().c_str());
  6338. tradePartner->tradeState = TRADE_ACKNOWLEDGE;
  6339. tradePartner->tradePartner = player->getID();
  6340. }
  6341. else {
  6342. Item* counterOfferItem = tradePartner->tradeItem;
  6343. player->sendTradeItemRequest(tradePartner, counterOfferItem, false);
  6344. tradePartner->sendTradeItemRequest(player, tradeItem, false);
  6345. }
  6346. }
  6347.  
  6348. void Game::playerAcceptTrade(Player* player)
  6349. {
  6350. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerAcceptTrade()");
  6351.  
  6352. if(player->isRemoved)
  6353. return;
  6354.  
  6355. player->setAcceptTrade(true);
  6356. Player *tradePartner = getPlayerByID(player->tradePartner);
  6357. if(tradePartner && tradePartner->getAcceptTrade()) {
  6358. Item *tradeItem1 = player->tradeItem;
  6359. Item *tradeItem2 = tradePartner->tradeItem;
  6360.  
  6361. player->sendCloseTrade();
  6362. tradePartner->sendCloseTrade();
  6363.  
  6364. #ifdef __KIRO_AKT__
  6365. if(tradeItem1->getID() == ITEM_AKT)
  6366. {
  6367. Tile* tile = getTile(player->pos);
  6368. House* house = tile? tile->getHouse() : NULL;
  6369. Tile* tile2 = getTile(tradePartner->pos);
  6370. Creature* creature = getCreatureByName(house->getOwner());
  6371. Player* prevOwner = creature? dynamic_cast<Player*>(creature) : NULL;
  6372. if(!house || !tile->isHouse())
  6373. {
  6374. player->sendCancel("You must stay in house!");
  6375. return;
  6376. }
  6377. if(!tile->isHouse() && !tile2->isHouse() && player->tradeState != TRADE_INITIATED){
  6378. player->sendCancel("You can only sell act if you are in house and you are the owner!");
  6379. return;
  6380. }
  6381. if(house->getOwner() != player->getName())
  6382. {
  6383. player->sendCancel("You must stay in your house!");
  6384. return;
  6385. }
  6386.  
  6387. if(house && house->checkHouseCount(tradePartner) >= g_config.getGlobalNumber("maxhouses", 0)){
  6388. std::stringstream textmsg;
  6389. textmsg << "You cannot have more than " << g_config.getGlobalNumber("maxhouses", 1) << " house.";
  6390. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6391. return;
  6392. }
  6393.  
  6394. if (house && tradePartner->level < g_config.getGlobalNumber("buyhouselvlrook",1) && tradePartner->vocation == 0)
  6395. {
  6396. player->sendCancel("This player have too low level to buy house!");
  6397. std::stringstream textmsg;
  6398. textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("buyhouselvlrook",2) << " level.";
  6399. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6400. return;
  6401. }
  6402.  
  6403. if (house && tradePartner->level < g_config.getGlobalNumber("houselevel", 0) && tradePartner->vocation != 0)
  6404. {
  6405. player->sendCancel("This player have too low level to buy house!");
  6406. std::stringstream textmsg;
  6407. textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("houselevel", 0) << " level.";
  6408. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6409. return;
  6410. }
  6411.  
  6412. if(tradePartner->getFreeCapacity() < tradeItem1->getWeight())
  6413. {
  6414. return;
  6415. }
  6416.  
  6417. if(player->addItem(tradeItem2, true) && tradePartner->addItem(tradeItem1, true) &&
  6418. player->removeItem(tradeItem1, true) && tradePartner->removeItem(tradeItem2, true)){
  6419.  
  6420. player->removeItem(tradeItem1);
  6421. tradePartner->removeItem(tradeItem2);
  6422.  
  6423. player->onThingRemove(tradeItem1);
  6424. tradePartner->onThingRemove(tradeItem2);
  6425.  
  6426. player->addItem(tradeItem2);
  6427. tradePartner->addItem(tradeItem1);
  6428. }
  6429. else{
  6430. player->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6431. tradePartner->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6432. return;
  6433. }
  6434. player->removeItem(tradeItem1, true);
  6435. tradePartner->addItem(tradeItem1, true);
  6436. player->addItem(tradeItem2, true);
  6437. house->setOwner(tradePartner->getName());
  6438. teleport(player,tradePartner->pos);
  6439. if (prevOwner)
  6440. prevOwner->houseRightsChanged = true;
  6441. tradePartner->houseRightsChanged = true;
  6442. }
  6443. else if(tradeItem2->getID() == ITEM_AKT)
  6444. {
  6445. Tile* tile = getTile(tradePartner->pos);
  6446. House* house = tile? tile->getHouse() : NULL;
  6447. Tile* tile2 = getTile(player->pos);
  6448. Creature* creature = getCreatureByName(house->getOwner());
  6449. Player* prevOwner = creature? dynamic_cast<Player*>(creature) : NULL;
  6450. if(!house || !tile->isHouse())
  6451. {
  6452. tradePartner->sendCancel("You must stay in house!");
  6453. return;
  6454. }
  6455. if(!tile->isHouse() && !tile2->isHouse() && player->tradeState != TRADE_INITIATED){
  6456. player->sendCancel("You can only sell act if you are in house and you are the owner!");
  6457. return;
  6458. }
  6459. if(house->getOwner() != tradePartner->getName())
  6460. {
  6461. tradePartner->sendCancel("You must stay in your house!");
  6462. return;
  6463. }
  6464.  
  6465. if(house && house->checkHouseCount(player) >= g_config.getGlobalNumber("maxhouses", 0)){
  6466. std::stringstream textmsg;
  6467. textmsg << " You cannot have more than " << g_config.getGlobalNumber("maxhouses", 1) << " house.";
  6468. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6469. return;
  6470. }
  6471.  
  6472. if (house && tradePartner->level < g_config.getGlobalNumber("buyhouselvlrook",1) && tradePartner->vocation == 0)
  6473. {
  6474. player->sendCancel("This player have too low level to buy house!");
  6475. std::stringstream textmsg;
  6476. textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("buyhouselvlrook",2) << " level.";
  6477. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6478. return;
  6479. }
  6480.  
  6481. if (house && tradePartner->level < g_config.getGlobalNumber("houselevel", 0) && tradePartner->vocation != 0)
  6482. {
  6483. player->sendCancel("This player have too low level to buy house!");
  6484. std::stringstream textmsg;
  6485. textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("houselevel", 0) << " level.";
  6486. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6487. return;
  6488. }
  6489.  
  6490. if(tradePartner->getFreeCapacity() < tradeItem1->getWeight())
  6491. {
  6492. return;
  6493. }
  6494.  
  6495. if(player->addItem(tradeItem2, true) && tradePartner->addItem(tradeItem1, true) &&
  6496. player->removeItem(tradeItem1, true) && tradePartner->removeItem(tradeItem2, true)){
  6497.  
  6498. player->removeItem(tradeItem1);
  6499. tradePartner->removeItem(tradeItem2);
  6500.  
  6501. player->onThingRemove(tradeItem1);
  6502. tradePartner->onThingRemove(tradeItem2);
  6503.  
  6504. player->addItem(tradeItem2);
  6505. tradePartner->addItem(tradeItem1);
  6506. }
  6507. else{
  6508. player->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6509. tradePartner->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6510. return;
  6511. }
  6512. tradePartner->removeItem(tradeItem1, true);
  6513. player->addItem(tradeItem1, true);
  6514. tradePartner->addItem(tradeItem2, true);
  6515. house->setOwner(player->getName());
  6516. teleport(tradePartner,player->pos);
  6517. if (prevOwner)
  6518. prevOwner->houseRightsChanged = true;
  6519. player->houseRightsChanged = true;
  6520. }
  6521. #endif
  6522.  
  6523. if(player->addItem(tradeItem2, true) && tradePartner->addItem(tradeItem1, true) &&
  6524. player->removeItem(tradeItem1, true) && tradePartner->removeItem(tradeItem2, true)){
  6525.  
  6526. player->removeItem(tradeItem1);
  6527. tradePartner->removeItem(tradeItem2);
  6528.  
  6529. player->onThingRemove(tradeItem1);
  6530. tradePartner->onThingRemove(tradeItem2);
  6531.  
  6532. player->addItem(tradeItem2);
  6533. tradePartner->addItem(tradeItem1);
  6534. }
  6535. else{
  6536. player->sendTextMessage(MSG_SMALLINFO, "Sorry not possible.");
  6537. tradePartner->sendTextMessage(MSG_SMALLINFO, "Sorry not possible.");
  6538. }
  6539.  
  6540. std::map<Item*, uint32_t>::iterator it;
  6541.  
  6542. it = tradeItems.find(tradeItem1);
  6543. if(it != tradeItems.end()) {
  6544. FreeThing(it->first);
  6545. tradeItems.erase(it);
  6546. }
  6547.  
  6548. it = tradeItems.find(tradeItem2);
  6549. if(it != tradeItems.end()) {
  6550. FreeThing(it->first);
  6551. tradeItems.erase(it);
  6552. }
  6553.  
  6554. player->setAcceptTrade(false);
  6555. tradePartner->setAcceptTrade(false);
  6556. }
  6557. }
  6558.  
  6559. void Game::playerLookInTrade(Player* player, bool lookAtCounterOffer, int32_t index)
  6560. {
  6561. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerLookInTrade()");
  6562.  
  6563. Player *tradePartner = getPlayerByID(player->tradePartner);
  6564. if(!tradePartner)
  6565. return;
  6566.  
  6567. Item *tradeItem = NULL;
  6568.  
  6569. if(lookAtCounterOffer)
  6570. tradeItem = tradePartner->getTradeItem();
  6571. else
  6572. tradeItem = player->getTradeItem();
  6573.  
  6574. if(!tradeItem)
  6575. return;
  6576.  
  6577. #ifdef __KIRO_AKT__
  6578. if(tradeItem->getID() == ITEM_AKT)
  6579. {
  6580. Tile* tile = getTile(tradePartner->pos);
  6581. House* house = tile? tile->getHouse() : NULL;
  6582.  
  6583.  
  6584. if(house && house->getOwner() == tradePartner->getName())
  6585. {
  6586. stringstream ss;
  6587. ss << "You see " << tradeItem->getDescription(true) << " applies to: " << house->getName() << ".";
  6588. player->sendTextMessage(MSG_INFO, ss.str().c_str());
  6589. return;
  6590. }
  6591.  
  6592. }
  6593. #endif
  6594.  
  6595. if(index == 0) {
  6596. stringstream ss;
  6597. ss << "You see " << tradeItem->getDescription(true);
  6598. player->sendTextMessage(MSG_INFO, ss.str().c_str());
  6599. return;
  6600. }
  6601.  
  6602. Container *tradeContainer = dynamic_cast<Container*>(tradeItem);
  6603. if(!tradeContainer || index > tradeContainer->getItemHoldingCount())
  6604. return;
  6605.  
  6606. bool foundItem = false;
  6607. std::list<const Container*> stack;
  6608. stack.push_back(tradeContainer);
  6609.  
  6610. ContainerList::const_iterator it;
  6611.  
  6612. while(!foundItem && stack.size() > 0) {
  6613. const Container *container = stack.front();
  6614. stack.pop_front();
  6615.  
  6616. for (it = container->getItems(); it != container->getEnd(); ++it) {
  6617. Container *container = dynamic_cast<Container*>(*it);
  6618. if(container) {
  6619. stack.push_back(container);
  6620. }
  6621.  
  6622. --index;
  6623. if(index == 0) {
  6624. tradeItem = *it;
  6625. foundItem = true;
  6626. break;
  6627. }
  6628. }
  6629. }
  6630.  
  6631. if(foundItem) {
  6632. stringstream ss;
  6633. ss << "You see " << tradeItem->getDescription(true);
  6634. player->sendTextMessage(MSG_INFO, ss.str().c_str());
  6635. }
  6636. }
  6637.  
  6638. void Game::playerCloseTrade(Player* player)
  6639. {
  6640. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerCloseTrade()");
  6641.  
  6642. Player* tradePartner = getPlayerByID(player->tradePartner);
  6643.  
  6644. std::vector<Item*>::iterator it;
  6645. if(player->getTradeItem()) {
  6646. std::map<Item*, uint32_t>::iterator it = tradeItems.find(player->getTradeItem());
  6647. if(it != tradeItems.end()) {
  6648. FreeThing(it->first);
  6649. tradeItems.erase(it);
  6650. }
  6651. }
  6652.  
  6653. player->setAcceptTrade(false);
  6654. player->sendTextMessage(MSG_SMALLINFO, "Trade cancelled.");
  6655. player->sendCloseTrade();
  6656.  
  6657. if(tradePartner) {
  6658. if(tradePartner->getTradeItem()) {
  6659. std::map<Item*, uint32_t>::iterator it = tradeItems.find(tradePartner->getTradeItem());
  6660. if(it != tradeItems.end()) {
  6661. FreeThing(it->first);
  6662. tradeItems.erase(it);
  6663. }
  6664. }
  6665.  
  6666. tradePartner->setAcceptTrade(false);
  6667. tradePartner->sendTextMessage(MSG_SMALLINFO, "Trade cancelled.");
  6668. tradePartner->sendCloseTrade();
  6669. }
  6670. }
  6671.  
  6672. void Game::autoCloseTrade(const Item* item, bool itemMoved /*= false*/)
  6673. {
  6674. if(!item)
  6675. return;
  6676.  
  6677. std::map<Item*, uint32_t>::const_iterator it;
  6678. const Container* container = NULL;
  6679. for(it = tradeItems.begin(); it != tradeItems.end(); it++) {
  6680. if(item == it->first ||
  6681. (itemMoved && (container = dynamic_cast<const Container*>(item)) && container->isHoldingItem(it->first)) ||
  6682. ((container = dynamic_cast<const Container*>(it->first)) && container->isHoldingItem(item)))
  6683. {
  6684. Player* player = getPlayerByID(it->second);
  6685. if(player){
  6686. playerCloseTrade(player);
  6687. }
  6688.  
  6689. break;
  6690. }
  6691. }
  6692. }
  6693.  
  6694. void Game::autoCloseAttack(Player* player, Creature* target)
  6695. {
  6696. if((std::abs(player->pos.x - target->pos.x) > 7) ||
  6697. (std::abs(player->pos.y - target->pos.y) > 5) || (player->pos.z != target->pos.z)){
  6698. player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  6699. playerSetAttackedCreature(player, 0);
  6700. }
  6701. }
  6702.  
  6703. void Game::playerSetAttackedCreature(Player* player, uint32_t creatureid)
  6704. {
  6705. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerSetAttackedCreature()");
  6706.  
  6707. if(player->isRemoved)
  6708. return;
  6709.  
  6710. if(player->attackedCreature != 0 && creatureid == 0) {
  6711. player->sendCancelAttacking();
  6712. }
  6713.  
  6714.  
  6715. Creature* attackedCreature = NULL;
  6716. if(creatureid != 0) {
  6717. attackedCreature = getCreatureByID(creatureid);
  6718. }
  6719.  
  6720. Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  6721. bool pvpArena = false, rook = false, attackedIsSummon = false;
  6722.  
  6723. #ifdef YUR_PVP_ARENA
  6724. if (player && attackedCreature)
  6725. {
  6726. Tile *t1 = map->getTile(player->pos), *t2 = map->getTile(attackedCreature->pos);
  6727. pvpArena = t1 && t2 && t1->isPvpArena() && t2->isPvpArena();
  6728. }
  6729. #endif //YUR_PVP_ARENA
  6730.  
  6731. #ifdef YUR_ROOKGARD
  6732. rook = player && player->isRookie() && attackedPlayer && attackedPlayer->isRookie();
  6733. #endif //YUR_ROOKGARD
  6734.  
  6735. #ifdef TR_SUMMONS
  6736. attackedIsSummon = (attackedCreature && attackedCreature->isPlayersSummon() && attackedCreature->getMaster() != player);
  6737. #endif //TR_SUMMONS
  6738.  
  6739. if(!attackedCreature || (attackedCreature->access >= g_config.ACCESS_PROTECT || ((getWorldType() == WORLD_TYPE_NO_PVP || rook) &&
  6740. !pvpArena && player->access < g_config.ACCESS_PROTECT && (dynamic_cast<Player*>(attackedCreature) || attackedIsSummon)))) {
  6741. if(attackedCreature) {
  6742. player->sendTextMessage(MSG_SMALLINFO, "You may not attack this player.");
  6743. }
  6744. player->sendCancelAttacking();
  6745. player->setAttackedCreature(NULL);
  6746. stopEvent(player->eventCheckAttacking);
  6747. player->eventCheckAttacking = 0;
  6748. }
  6749. else if(attackedCreature) {
  6750. player->setAttackedCreature(attackedCreature);
  6751. stopEvent(player->eventCheckAttacking);
  6752. player->eventCheckAttacking = addEvent(makeTask(g_config.getGlobalNumber("firstattack", 2000), std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), player->getID())));
  6753. }
  6754.  
  6755. }
  6756.  
  6757.  
  6758. void Game::flushSendBuffers()
  6759. {
  6760. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::flushSendBuffers()");
  6761.  
  6762. for(std::vector<Player*>::iterator it = BufferedPlayers.begin(); it != BufferedPlayers.end(); ++it) {
  6763. (*it)->flushMsg();
  6764. (*it)->SendBuffer = false;
  6765. (*it)->releaseThing();
  6766. /*
  6767. #ifdef __DEBUG__
  6768. std::cout << "flushSendBuffers() - releaseThing()" << std::endl;
  6769. #endif
  6770. */
  6771. }
  6772. BufferedPlayers.clear();
  6773.  
  6774. //free memory
  6775. for(std::vector<Thing*>::iterator it = ToReleaseThings.begin(); it != ToReleaseThings.end(); ++it){
  6776. (*it)->releaseThing();
  6777. }
  6778. ToReleaseThings.clear();
  6779.  
  6780.  
  6781. return;
  6782. }
  6783.  
  6784. void Game::addPlayerBuffer(Player* p)
  6785. {
  6786. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::addPlayerBuffer()");
  6787.  
  6788. /*
  6789. #ifdef __DEBUG__
  6790. std::cout << "addPlayerBuffer() - useThing()" << std::endl;
  6791. #endif
  6792. */
  6793. if(p->SendBuffer == false){
  6794. p->useThing();
  6795. BufferedPlayers.push_back(p);
  6796. p->SendBuffer = true;
  6797. }
  6798.  
  6799. return;
  6800. }
  6801.  
  6802. void Game::FreeThing(Thing* thing){
  6803.  
  6804. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::FreeThing()");
  6805. //std::cout << "freeThing() " << thing <<std::endl;
  6806. ToReleaseThings.push_back(thing);
  6807.  
  6808. return;
  6809. }
  6810. /*
  6811. ADD
  6812. container(player,pos-cid,thing)
  6813. inventory(player,pos-i,[ignored])
  6814. ground([ignored],postion,thing)
  6815.  
  6816. REMOVE
  6817. container(player,pos-cid,thing,autoclose?)
  6818. inventory(player,pos-i,thing,autoclose?)
  6819. ground([ignored],postion,thing,autoclose?,stackpos)
  6820.  
  6821. UPDATE
  6822. container(player,pos-cid,thing)
  6823. inventory(player,pos-i,[ignored])
  6824. ground([ignored],postion,thing,stackpos)
  6825. */
  6826. void Game::sendAddThing(Player* player,const Position &pos,const Thing* thing){
  6827. if(pos.x == 0xFFFF) {
  6828. if(!player)
  6829. return;
  6830. if(pos.y & 0x40) { //container
  6831. if(!thing)
  6832. return;
  6833.  
  6834. const Item *item = dynamic_cast<const Item*>(thing);
  6835. if(!item)
  6836. return;
  6837.  
  6838. unsigned char containerid = pos.y & 0x0F;
  6839. Container* container = player->getContainer(containerid);
  6840. if(!container)
  6841. return;
  6842.  
  6843. SpectatorVec list;
  6844. SpectatorVec::iterator it;
  6845.  
  6846. Position centerpos = (container->pos.x == 0xFFFF ? player->pos : container->pos);
  6847. getSpectators(Range(centerpos,2,2,2,2,false), list);
  6848.  
  6849. if(!list.empty()) {
  6850. for(it = list.begin(); it != list.end(); ++it) {
  6851. Player *spectator = dynamic_cast<Player*>(*it);
  6852. if(spectator)
  6853. spectator->onItemAddContainer(container,item);
  6854. }
  6855. }
  6856. else
  6857. player->onItemAddContainer(container,item);
  6858.  
  6859. }
  6860. else //inventory
  6861. {
  6862. player->sendInventory(pos.y);
  6863. }
  6864. }
  6865. else //ground
  6866. {
  6867. if(!thing)
  6868. return;
  6869.  
  6870. #ifdef SM_SUMMON_ATTACK
  6871. Monster* monster = dynamic_cast<Monster*>(const_cast<Thing*>(thing));
  6872. #endif //SM_SUMMON_ATTACK
  6873.  
  6874. SpectatorVec list;
  6875. SpectatorVec::iterator it;
  6876.  
  6877. getSpectators(Range(pos,true), list);
  6878.  
  6879. //players
  6880. for(it = list.begin(); it != list.end(); ++it) {
  6881. if(dynamic_cast<Player*>(*it)) {
  6882. (*it)->onThingAppear(thing);
  6883. #ifdef SM_SUMMON_ATTACK
  6884. if (monster && !monster->isSummon())
  6885. monster->onThingAppear(*it);
  6886. #endif //SM_SUMMON_ATTACK
  6887. }
  6888. }
  6889.  
  6890. //none-players
  6891. for(it = list.begin(); it != list.end(); ++it) {
  6892. if(!dynamic_cast<Player*>(*it)) {
  6893. (*it)->onThingAppear(thing);
  6894. }
  6895. }
  6896. }
  6897. }
  6898.  
  6899. void Game::sendRemoveThing(Player* player,const Position &pos,const Thing* thing,const unsigned char stackpos /*=1*/ ,const bool autoclose/* =false*/){
  6900. if(!thing)
  6901. return;
  6902.  
  6903. const Item *item = dynamic_cast<const Item*>(thing);
  6904. bool perform_autoclose = false;
  6905. if(autoclose && item){
  6906. const Container *container = dynamic_cast<const Container*>(item);
  6907. if(container)
  6908. perform_autoclose = true;
  6909. }
  6910.  
  6911. if(pos.x == 0xFFFF) {
  6912. if(!player)
  6913. return;
  6914. if(pos.y & 0x40) { //container
  6915. if(!item)
  6916. return;
  6917.  
  6918. unsigned char containerid = pos.y & 0x0F;
  6919. Container* container = player->getContainer(containerid);
  6920. if(!container)
  6921. return;
  6922.  
  6923. //check that item is in the container
  6924. unsigned char slot = container->getSlotNumberByItem(item);
  6925.  
  6926. SpectatorVec list;
  6927. SpectatorVec::iterator it;
  6928.  
  6929. Position centerpos = (container->pos.x == 0xFFFF ? player->pos : container->pos);
  6930. getSpectators(Range(centerpos,2,2,2,2,false), list);
  6931.  
  6932. if(!list.empty()) {
  6933. for(it = list.begin(); it != list.end(); ++it) {
  6934. Player *spectator = dynamic_cast<Player*>(*it);
  6935. if(spectator){
  6936. spectator->onItemRemoveContainer(container,slot);
  6937. if(perform_autoclose){
  6938. spectator->onThingRemove(thing);
  6939. }
  6940. }
  6941. }
  6942. }
  6943. else{
  6944. player->onItemRemoveContainer(container,slot);
  6945. if(perform_autoclose){
  6946. player->onThingRemove(thing);
  6947. }
  6948. }
  6949.  
  6950. }
  6951. else //inventory
  6952. {
  6953. player->removeItemInventory(pos.y);
  6954. if(perform_autoclose){
  6955. player->onThingRemove(thing);
  6956. }
  6957. }
  6958. }
  6959. else //ground
  6960. {
  6961. SpectatorVec list;
  6962. SpectatorVec::iterator it;
  6963.  
  6964. getSpectators(Range(pos,true), list);
  6965.  
  6966. //players
  6967. for(it = list.begin(); it != list.end(); ++it) {
  6968. Player *spectator = dynamic_cast<Player*>(*it);
  6969. if(spectator) {
  6970. spectator->onThingDisappear(thing,stackpos);
  6971.  
  6972. if(perform_autoclose){
  6973. spectator->onThingRemove(thing);
  6974. }
  6975. }
  6976. }
  6977.  
  6978. //none-players
  6979. for(it = list.begin(); it != list.end(); ++it) {
  6980. if(!dynamic_cast<Player*>(*it)) {
  6981. (*it)->onThingDisappear(thing,stackpos);
  6982. }
  6983. }
  6984. }
  6985. }
  6986.  
  6987. void Game::sendUpdateThing(Player* player,const Position &pos,const Thing* thing,const unsigned char stackpos/*=1*/){
  6988.  
  6989. if(pos.x == 0xFFFF) {
  6990. if(!player)
  6991. return;
  6992. if(pos.y & 0x40) { //container
  6993. if(!thing)
  6994. return;
  6995.  
  6996. const Item *item = dynamic_cast<const Item*>(thing);
  6997. if(!item)
  6998. return;
  6999.  
  7000. unsigned char containerid = pos.y & 0x0F;
  7001. Container* container = player->getContainer(containerid);
  7002. if(!container)
  7003. return;
  7004. //check that item is in the container
  7005. unsigned char slot = container->getSlotNumberByItem(item);
  7006.  
  7007. SpectatorVec list;
  7008. SpectatorVec::iterator it;
  7009.  
  7010. Position centerpos = (container->pos.x == 0xFFFF ? player->pos : container->pos);
  7011. getSpectators(Range(centerpos,2,2,2,2,false), list);
  7012.  
  7013. if(!list.empty()) {
  7014. for(it = list.begin(); it != list.end(); ++it) {
  7015. Player *spectator = dynamic_cast<Player*>(*it);
  7016. if(spectator)
  7017. spectator->onItemUpdateContainer(container,item,slot);
  7018. }
  7019. }
  7020. else{
  7021. //never should be here
  7022. std::cout << "Error: sendUpdateThing" << std::endl;
  7023. //player->onItemUpdateContainer(container,item,slot);
  7024. }
  7025.  
  7026. }
  7027. else //inventory
  7028. {
  7029. player->sendInventory(pos.y);
  7030. }
  7031. }
  7032. else //ground
  7033. {
  7034. if(!thing)
  7035. return;
  7036.  
  7037. SpectatorVec list;
  7038. SpectatorVec::iterator it;
  7039.  
  7040. getSpectators(Range(pos,true), list);
  7041.  
  7042. //players
  7043. for(it = list.begin(); it != list.end(); ++it) {
  7044. if(dynamic_cast<Player*>(*it)) {
  7045. (*it)->onThingTransform(thing,stackpos);
  7046. }
  7047. }
  7048.  
  7049. //none-players
  7050. for(it = list.begin(); it != list.end(); ++it) {
  7051. if(!dynamic_cast<Player*>(*it)) {
  7052. (*it)->onThingTransform(thing,stackpos);
  7053. }
  7054. }
  7055. }
  7056. }
  7057.  
  7058. void Game::addThing(Player* player,const Position &pos,Thing* thing)
  7059. {
  7060. if(!thing)
  7061. return;
  7062. Item *item = dynamic_cast<Item*>(thing);
  7063.  
  7064. if(pos.x == 0xFFFF) {
  7065. if(!player || !item)
  7066. return;
  7067.  
  7068. if(pos.y & 0x40) { //container
  7069. unsigned char containerid = pos.y & 0x0F;
  7070. Container* container = player->getContainer(containerid);
  7071. if(!container)
  7072. return;
  7073.  
  7074. container->addItem(item);
  7075. sendAddThing(player,pos,thing);
  7076. }
  7077. else //inventory
  7078. {
  7079. player->addItemInventory(item,pos.y,true);
  7080. sendAddThing(player,pos,thing);
  7081. }
  7082. }
  7083. else //ground
  7084. {
  7085. if(!thing)
  7086. return;
  7087. //Tile *tile = map->getTile(pos.x, pos.y, pos.z);
  7088. Tile *tile = map->getTile(pos);
  7089. if(tile){
  7090. thing->pos = pos;
  7091. if(item && item->isSplash()){
  7092. if(tile->splash){
  7093. int32_t oldstackpos = tile->getThingStackPos(tile->splash);
  7094. Item *oldsplash = tile->splash;
  7095.  
  7096. oldsplash->isRemoved = true;
  7097. FreeThing(oldsplash);
  7098.  
  7099. tile->splash = item;
  7100.  
  7101. sendUpdateThing(NULL, pos, item, oldstackpos);
  7102. }
  7103. else{
  7104. tile->splash = item;
  7105. sendAddThing(NULL,pos,tile->splash);
  7106. }
  7107. }
  7108. else if(item && item->isGroundTile()){
  7109. tile->ground = item;
  7110.  
  7111. SpectatorVec list;
  7112. SpectatorVec::iterator it;
  7113.  
  7114. getSpectators(Range(thing->pos, true), list);
  7115.  
  7116. //players
  7117. for(it = list.begin(); it != list.end(); ++it) {
  7118. if(dynamic_cast<Player*>(*it)) {
  7119. (*it)->onTileUpdated(pos);
  7120. }
  7121. }
  7122.  
  7123. //none-players
  7124. for(it = list.begin(); it != list.end(); ++it) {
  7125. if(!dynamic_cast<Player*>(*it)) {
  7126. (*it)->onTileUpdated(pos);
  7127. }
  7128. }
  7129.  
  7130. //Game::creatureBroadcastTileUpdated(thing->pos);
  7131. }
  7132. else if(item && item->isStackable()){
  7133. Item *topitem = tile->getTopDownItem();
  7134. if(topitem && topitem->getID() == item->getID() &&
  7135. topitem->getItemCountOrSubtype() + item->getItemCountOrSubtype() <= 100){
  7136. topitem->setItemCountOrSubtype(topitem->getItemCountOrSubtype() + item->getItemCountOrSubtype());
  7137. int32_t stackpos = tile->getThingStackPos(topitem);
  7138. sendUpdateThing(NULL,topitem->pos,topitem,stackpos);
  7139. item->pos.x = 0xFFFF;
  7140. FreeThing(item);
  7141. }
  7142. else{
  7143. tile->addThing(thing);
  7144. sendAddThing(player,pos,thing);
  7145. }
  7146. }
  7147. else{
  7148. tile->addThing(thing);
  7149. sendAddThing(player,pos,thing);
  7150. }
  7151. }
  7152. }
  7153. }
  7154.  
  7155. bool Game::removeThing(Player* player,const Position &pos,Thing* thing, bool setRemoved /*= true*/)
  7156. {
  7157. if(!thing)
  7158. return false;
  7159. Item *item = dynamic_cast<Item*>(thing);
  7160.  
  7161. if(pos.x == 0xFFFF) {
  7162. if(!player || !item)
  7163. return false;
  7164.  
  7165. if(pos.y & 0x40) { //container
  7166. unsigned char containerid = pos.y & 0x0F;
  7167. Container* container = player->getContainer(containerid);
  7168. if(!container)
  7169. return false;
  7170.  
  7171. sendRemoveThing(player,pos,thing,0,true);
  7172. if(!container->removeItem(item))
  7173. return false;
  7174.  
  7175. if(player && player->isHoldingContainer(container)) {
  7176. player->updateInventoryWeigth();
  7177. player->sendStats();
  7178. }
  7179. }
  7180. else //inventory
  7181. {
  7182. //sendRemoveThing(player,pos,thing,0,true);
  7183. if(!player->removeItemInventory(pos.y))
  7184. return false;
  7185. player->onThingRemove(thing);
  7186. //player->removeItemInventory(pos.y,true);
  7187. }
  7188. if(setRemoved)
  7189. item->isRemoved = true;
  7190. return true;
  7191. }
  7192. else //ground
  7193. {
  7194. //Tile *tile = map->getTile(pos.x, pos.y, pos.z);
  7195. Tile *tile = map->getTile(pos);
  7196. if(tile){
  7197. unsigned char stackpos = tile->getThingStackPos(thing);
  7198. if(!tile->removeThing(thing))
  7199. return false;
  7200. sendRemoveThing(NULL,pos,thing,stackpos,true);
  7201. }
  7202. else{
  7203. return false;
  7204. }
  7205. if(item && setRemoved){
  7206. item->isRemoved = true;
  7207. }
  7208. return true;
  7209. }
  7210. }
  7211.  
  7212. Position Game::getThingMapPos(Player *player, const Position &pos)
  7213. {
  7214. if(pos.x == 0xFFFF){
  7215. Position dummyPos(0,0,0);
  7216. if(!player)
  7217. return dummyPos;
  7218. if(pos.y & 0x40) { //from container
  7219. unsigned char containerid = pos.y & 0x0F;
  7220. const Container* container = player->getContainer(containerid);
  7221. if(!container){
  7222. return dummyPos;
  7223. }
  7224. while(container->getParent() != NULL) {
  7225. container = container->getParent();
  7226. }
  7227. if(container->pos.x == 0xFFFF)
  7228. return player->pos;
  7229. else
  7230. return container->pos;
  7231. }
  7232. else //from inventory
  7233. {
  7234. return player->pos;
  7235. }
  7236. }
  7237. else{
  7238. return pos;
  7239. }
  7240. }
  7241.  
  7242. Thing* Game::getThing(const Position &pos,unsigned char stack, Player* player /*=NULL*/)
  7243. {
  7244. if(pos.x == 0xFFFF) {
  7245. if(!player)
  7246. return NULL;
  7247. if(pos.y & 0x40) { //from container
  7248. unsigned char containerid = pos.y & 0x0F;
  7249. Container* container = player->getContainer(containerid);
  7250. if(!container)
  7251. return NULL;
  7252.  
  7253. return container->getItem(pos.z);
  7254. }
  7255. else //from inventory
  7256. {
  7257. return player->getItem(pos.y);
  7258. }
  7259. }
  7260. else //from ground
  7261. {
  7262. //Tile *t = getTile(pos.x, pos.y, pos.z);
  7263. Tile *t = map->getTile(pos);
  7264. if(!t)
  7265. return NULL;
  7266.  
  7267. return t->getThingByStackPos(stack);
  7268. }
  7269. }
  7270. int32_t Game::getDepot(Container* c, int32_t e)
  7271. {
  7272. for(int32_t a = 0; a < c->size(); a++)
  7273. {
  7274. Container* x = dynamic_cast<Container*>(dynamic_cast<Item*>(c->getItem(a)));
  7275. Item* i = dynamic_cast<Item*>(c->getItem(a));
  7276. if(i)
  7277. e++;
  7278. if(x)
  7279. e = getDepot(x, e);
  7280. }
  7281. return e;
  7282. }
  7283.  
  7284.  
  7285. #ifdef WOLV_LOAD_NPC
  7286. bool Game::loadNpcs()
  7287. {
  7288. xmlDocPtr doc;
  7289. doc = xmlParseFile((g_config.DATA_DIR + "world/npc.xml").c_str());
  7290. if (!doc)
  7291. return false;
  7292.  
  7293. xmlNodePtr root, npcNode;
  7294. root = xmlDocGetRootElement(doc);
  7295.  
  7296. if (xmlStrcmp(root->name, (const xmlChar*)"npclist"))
  7297. {
  7298. xmlFreeDoc(doc);
  7299. return false;
  7300. }
  7301.  
  7302. npcNode = root->children;
  7303. while (npcNode)
  7304. {
  7305. if (strcmp((const char*) npcNode->name, "npc") == 0)
  7306. {
  7307. std::string name = (const char*)xmlGetProp(npcNode, (const xmlChar *) "name");
  7308. int32_t x = atoi((const char*) xmlGetProp(npcNode, (const xmlChar*) "x"));
  7309. int32_t y = atoi((const char*) xmlGetProp(npcNode, (const xmlChar*) "y"));
  7310. int32_t z = atoi((const char*) xmlGetProp(npcNode, (const xmlChar*) "z"));
  7311.  
  7312. Npc* mynpc = new Npc(name, this);
  7313. mynpc->pos = Position(x, y, z);
  7314.  
  7315. if (!placeCreature(mynpc->pos, mynpc))
  7316. {
  7317. std::cout << "Could not place " << name << "!" << std::endl;
  7318. xmlFreeDoc(doc);
  7319. return false;
  7320. }
  7321.  
  7322. const char* tmp = (const char*)xmlGetProp(npcNode, (const xmlChar*) "dir");
  7323. if (tmp)
  7324. mynpc->setDirection((Direction)atoi(tmp));
  7325. }
  7326. npcNode = npcNode->next;
  7327. }
  7328.  
  7329. xmlFreeDoc(doc);
  7330. return true;
  7331. }
  7332. #endif //WOLV_LOAD_NPC
  7333.  
  7334. #ifdef TLM_SERVER_SAVE
  7335. void Game::serverSave()
  7336. {
  7337. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::serverSave()");
  7338. std::cout << ":: zapis serwera :: " << std::endl;
  7339. timer();
  7340.  
  7341. AutoList<Player>::listiterator it = Player::listPlayer.list.begin();
  7342. while (it != Player::listPlayer.list.end())
  7343. {
  7344. IOPlayer::instance()->savePlayer(it->second);
  7345. ++it;
  7346. }
  7347. std::cout << ":: Gracze [" << timer() << " s]" << std::endl;
  7348. Guilds::Save();
  7349. std::cout << "Gildie [" << timer() << " s]" << std::endl;
  7350. Houses::Save(this);
  7351. std::cout << ":: Domki [" << timer() << " s]" << std::endl;
  7352. loginQueue.save();
  7353. std::cout << ":: Kolejki [" << timer() << " s]" << std::endl;
  7354.  
  7355. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it);
  7356. }
  7357.  
  7358. void Game::autoServerSave()
  7359. {
  7360. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::autoServerSave()");
  7361. serverSave();
  7362. addEvent(makeTask(g_config.getGlobalNumber("autosave", 1)*60000, std::mem_fun(&Game::autoServerSave)));
  7363. }
  7364. #endif //TLM_SERVER_SAVE
  7365.  
  7366.  
  7367. #ifdef ELEM_VIP_LIST
  7368. /*void Game::vipLogin(Player* player)
  7369. {
  7370. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::vipLogin()");
  7371. std::string vipname = player->getName();
  7372.  
  7373. #ifdef _NG_BBK_VIP_SYSTEM__
  7374. std::transform(vipname.begin(), vipname.end(), vipname.begin(), (int32_t(*)(int32_t)) std::tolower);
  7375. #endif //_NG_BBK_VIP_SYSTEM__
  7376.  
  7377. for(AutoList<Creature>::listiterator cit = listCreature.list.begin(); cit != listCreature.list.end(); ++cit)
  7378. {
  7379. Player* player = dynamic_cast<Player*>((*cit).second);
  7380. if (player)
  7381. player->sendVipLogin(vipname);
  7382. }
  7383. }
  7384.  
  7385. void Game::vipLogout(std::string vipname)
  7386. {
  7387. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::vipLogout()");
  7388.  
  7389. #ifdef _NG_BBK_VIP_SYSTEM__
  7390. std::transform(vipname.begin(), vipname.end(), vipname.begin(), (int32_t(*)(int32_t)) std::tolower);
  7391. #endif //_NG_BBK_VIP_SYSTEM__
  7392.  
  7393. for(AutoList<Creature>::listiterator cit = listCreature.list.begin(); cit != listCreature.list.end(); ++cit)
  7394. {
  7395. Player* player = dynamic_cast<Player*>((*cit).second);
  7396. if (player)
  7397. player->sendVipLogout(vipname);
  7398. }
  7399. }*/
  7400.  
  7401. bool Game::isPlayer(std::string name)
  7402. {
  7403. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::isPlayer()");
  7404. extern xmlMutexPtr xmlmutex;
  7405.  
  7406. std::string datadir = g_config.getGlobalString("datadir");
  7407. std::string filenamecheck = datadir + "players/" + name + ".xml";
  7408. std::transform(filenamecheck.begin(),filenamecheck.end(), filenamecheck.begin(), (int32_t(*)(int32_t))tolower);
  7409.  
  7410. xmlDocPtr doc;
  7411. xmlMutexLock(xmlmutex);
  7412. doc = xmlParseFile(filenamecheck.c_str());
  7413.  
  7414. if (doc)
  7415. {
  7416. xmlMutexUnlock(xmlmutex);
  7417. xmlFreeDoc(doc);
  7418. return true;
  7419. }
  7420. else
  7421. {
  7422. xmlMutexUnlock(xmlmutex);
  7423. xmlFreeDoc(doc);
  7424. return false;
  7425. }
  7426. }
  7427. #endif //ELEM_VIP_LIST
  7428.  
  7429. void Game::checkSpell(Player* player, SpeakClasses type, std::string text)
  7430. {
  7431. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkSpell()");
  7432.  
  7433. if (player->isRookie())
  7434. return;
  7435.  
  7436. #ifdef TLM_HOUSE_SYSTEM
  7437. else if (text == "aleta gom") // edit owner
  7438. {
  7439. Tile* tile = getTile(player->pos);
  7440. House* house = tile? tile->getHouse() : NULL;
  7441.  
  7442. if (house && house->getPlayerRights(player->getName()) == HOUSE_OWNER)
  7443. {
  7444. player->sendHouseWindow(house, player->pos, HOUSE_OWNER);
  7445. }
  7446. else
  7447. {
  7448. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7449. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7450. }
  7451. }
  7452. else if (text == "aleta grav") // edit door owners
  7453. {
  7454. bool last = false;
  7455. for (int32_t x = player->pos.x-1; x <= player->pos.x+1 && !last; x++)
  7456. {
  7457. for(int32_t y = player->pos.y-1; y <= player->pos.y+1 && !last; y++)
  7458. {
  7459. Position doorPos(x, y, player->pos.z);
  7460. Tile* tile = getTile(doorPos);
  7461. House* house = tile? tile->getHouse() : NULL;
  7462.  
  7463. if (house && house->getPlayerRights(doorPos, player->getName()) == HOUSE_OWNER)
  7464. {
  7465. Item *item = dynamic_cast<Item*>(tile->getThingByStackPos(tile->getThingCount()-1));
  7466. if (item && Item::items[item->getID()].isDoor)
  7467. {
  7468. player->sendHouseWindow(house, doorPos, HOUSE_DOOROWNER);
  7469. last = true;
  7470. }
  7471. }
  7472. }
  7473. }
  7474. }
  7475. else if (text == "!buyhouse" || text == "!buyhome")
  7476. {
  7477. uint32_t money = player->getMoney();
  7478. bool last = false;
  7479. #ifdef HUCZU_EXHAUSTED
  7480. if(player->houseTicks > 0){
  7481. player->sendCancel("You're exhausted.");
  7482. return;
  7483. }
  7484. else
  7485. player->houseTicks += 5;
  7486. #endif //HUCZU_EXHAUSTED
  7487. int32_t houselevel = g_config.getGlobalNumber("houselevel", 0);
  7488. if(!player->premmium){
  7489. player->sendCancel("You must have a premium to buy house!");
  7490. return;
  7491. }
  7492. if( player->getLevel() < houselevel ){
  7493. std::stringstream textmsg2;
  7494. textmsg2 << " You need level " << houselevel << "+ to buy a house! ";
  7495. player->sendTextMessage(MSG_ADVANCE, textmsg2.str().c_str());
  7496. }
  7497. else{
  7498.  
  7499. for (int32_t x = player->pos.x-1; x <= player->pos.x+1 && !last; x++)
  7500. {
  7501. for(int32_t y = player->pos.y-1; y <= player->pos.y+1 && !last; y++)
  7502. {
  7503. Position doorPos(x, y, player->pos.z);
  7504. Tile* tile = getTile(doorPos);
  7505. House* house = tile? tile->getHouse() : NULL;
  7506. if(house){
  7507. if(house->getPlayerRights(player->getName()) == HOUSE_OWNER){
  7508. player->sendTextMessage(MSG_ADVANCE, "You own this house.");
  7509. return;
  7510. }
  7511. if(house->isBought()){
  7512. player->sendTextMessage(MSG_ADVANCE, "This house already has an owner.");
  7513. return;
  7514. }
  7515. if(house->checkHouseCount(player) >= g_config.getGlobalNumber("maxhouses", 0)){
  7516. std::stringstream textmsg;
  7517. textmsg << " You cant have more than " << g_config.getGlobalNumber("maxhouses", 1) << " houses ";
  7518. player->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  7519. return;
  7520. }
  7521. if(house->getPlayerRights(doorPos, player->getName()) == HOUSE_NONE && !house->isBought() && house->checkHouseCount(player) < g_config.getGlobalNumber("maxhouses", 1))
  7522. {
  7523. Item *item = dynamic_cast<Item*>(tile->getThingByStackPos(tile->getThingCount()-1));
  7524. long price = g_config.getGlobalNumber("priceforsqm", 0) * house->getHouseSQM(house->getName());
  7525.  
  7526. if (item && Item::items[item->getID()].isDoor && price <= money)
  7527. {
  7528. player->substractMoney(price);
  7529. house->setOwner(player->getName());
  7530. house->save();
  7531. player->sendTextMessage(MSG_ADVANCE, "You bought a house.");
  7532. last = true;
  7533. }
  7534. else{
  7535. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7536. player->sendTextMessage(MSG_SMALLINFO, "You dont have enough money to buy this house.");
  7537. }
  7538. }
  7539. }
  7540. }
  7541. }
  7542. }
  7543. }
  7544. else if (text == "aleta sio") // edit guests
  7545. {
  7546. Tile* tile = getTile(player->pos);
  7547. House* house = tile? tile->getHouse() : NULL;
  7548.  
  7549. if (house && house->getPlayerRights(player->getName()) >= HOUSE_SUBOWNER)
  7550. {
  7551. player->sendHouseWindow(house, player->pos, HOUSE_GUEST);
  7552. }
  7553. else
  7554. {
  7555. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7556. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7557. }
  7558. }
  7559. else if (text == "aleta som") // edit subowners
  7560. {
  7561. Tile* tile = getTile(player->pos);
  7562. House* house = tile? tile->getHouse() : NULL;
  7563.  
  7564. if (house && house->getPlayerRights(player->getName()) == HOUSE_OWNER)
  7565. {
  7566. player->sendHouseWindow(house, player->pos, HOUSE_SUBOWNER);
  7567. }
  7568. else
  7569. {
  7570. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7571. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7572. }
  7573. }
  7574. else if (text == "alana sio") // kick me
  7575. {
  7576. Tile* tile = getTile(player->pos);
  7577. House* house = tile? tile->getHouse() : NULL;
  7578.  
  7579. if (house)
  7580. {
  7581. teleport(player, house->getFrontDoor());
  7582. player->sendMagicEffect(player->pos, NM_ME_ENERGY_AREA);
  7583. }
  7584. else
  7585. {
  7586. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7587. player->sendTextMessage(MSG_SMALLINFO, "You are not in a house.");
  7588. }
  7589. }
  7590. else if (text.substr(0, 11) == "alana sio \"") // kick someone
  7591. {
  7592. Creature* c = getCreatureByName(text.substr(11).c_str());
  7593. Player *target = c? dynamic_cast<Player*>(c) : NULL;
  7594.  
  7595. if (target)
  7596. {
  7597. Tile* tile = getTile(player->pos);
  7598. Tile* targetTile = getTile(target->pos);
  7599. House* house = tile? tile->getHouse() : NULL;
  7600. House* targetHouse = targetTile? targetTile->getHouse() : NULL;
  7601.  
  7602. if (house && targetHouse && house == targetHouse &&
  7603. house->getPlayerRights(player->getName()) >= HOUSE_SUBOWNER)
  7604. {
  7605. Position pos = house->getFrontDoor();
  7606. if (pos.x != 0xFFFF && pos.y != 0xFFFF && pos.z != 0xFF)
  7607. {
  7608. teleport(target, pos);
  7609. player->sendMagicEffect(target->pos, NM_ME_ENERGY_AREA);
  7610. }
  7611. else
  7612. {
  7613. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7614. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7615. }
  7616. }
  7617. else
  7618. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7619. }
  7620. else
  7621. {
  7622. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7623. player->sendTextMessage(MSG_SMALLINFO, "This player does not exist.");
  7624. }
  7625. }
  7626. #endif //TLM_HOUSE_SYSTEM
  7627.  
  7628. #ifdef TR_SUMMONS
  7629. else if (text.substr(0, 11) == "utevo res \"" &&
  7630. (!g_config.LEARN_SPELLS || player->knowsSpell("utevo res")))
  7631. {
  7632. if (player->vocation == VOCATION_DRUID || player->vocation == VOCATION_SORCERER ||
  7633. (g_config.SUMMONS_ALL_VOC && player->vocation != VOCATION_NONE))
  7634. {
  7635. std::string name = text.substr(11);
  7636. int32_t reqMana = Summons::getRequiredMana(name);
  7637. Tile* tile = getTile(player->pos);
  7638.  
  7639. if (!tile)
  7640. {
  7641. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7642. player->sendCancel("Sorry, not possible.");
  7643. }
  7644. else if (reqMana < 0)
  7645. {
  7646. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7647. player->sendCancel("You cannot summon this creature.");
  7648. }
  7649. else if (tile->isPz())
  7650. {
  7651. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7652. player->sendCancel("You cannot summon creatures in protection zone.");
  7653. }
  7654. #ifdef YUR_PVP_ARENA
  7655. else if (tile->isPvpArena())
  7656. {
  7657. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7658. player->sendCancel("You cannot summon creatures on arena.");
  7659. }
  7660. #endif //YUR_PVP_ARENA
  7661. else if (player->getSummonCount() >= g_config.MAX_SUMMONS)
  7662. {
  7663. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7664. player->sendCancel("You cannot have more summons.");
  7665. }
  7666. else if (player->getMana() < reqMana)
  7667. {
  7668. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7669. player->sendCancel("Not enough mana.");
  7670. }
  7671. else if (!placeSummon(player, name))
  7672. {
  7673. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7674. player->sendCancel("Not enough room");
  7675. }
  7676. else
  7677. {
  7678. player->mana -= reqMana;
  7679. player->addManaSpent(reqMana);
  7680. }
  7681. }
  7682. }
  7683. #endif //TR_SUMMONS
  7684.  
  7685. /*
  7686. #ifdef HUCZU_FIX
  7687. else if (text == "exevo flam sio" &&
  7688. (!g_config.LEARN_SPELLS || player->knowsSpell("exevo flam sio")))
  7689. {
  7690. const int32_t REQ_MANA = 200;
  7691.  
  7692. if (player->mana < REQ_MANA)
  7693. {
  7694. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7695. player->sendTextMessage(MSG_SMALLINFO, "Not enough mana.");
  7696. }
  7697.  
  7698. else if (player->maglevel < 15)
  7699. {
  7700. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7701. player->sendTextMessage(MSG_SMALLINFO, "You don't have the required magic level.");
  7702. }
  7703.  
  7704. else if (player->exhaustedTicks >= 1000 && player->access < g_config.ACCESS_PROTECT)
  7705. {
  7706. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7707. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  7708. }
  7709.  
  7710. else if (player->flamTicks != 0 && player->access < g_config.ACCESS_PROTECT)
  7711. {
  7712. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7713. player->sendTextMessage(MSG_SMALLINFO, "Not ready yet.");
  7714. }
  7715.  
  7716. else
  7717. {
  7718. player->flamBool = true;
  7719. player->exhaustedTicks = 2*1000;
  7720. player->sendMagicEffect(player->pos, NM_ME_MAGIC_BLOOD);
  7721. }
  7722. }
  7723. #endif //HUCZU_FIX
  7724. */
  7725.  
  7726. else if (text.substr(0,7) == "exiva \"" &&
  7727. (!g_config.LEARN_SPELLS || player->knowsSpell("exiva")))
  7728. {
  7729. std::string name = text.substr(7);
  7730. Creature *c = getCreatureByName(name);
  7731. if (dynamic_cast<Player*>(c))
  7732. {
  7733. if(player->mana >= 20)
  7734. {
  7735. player->mana -= 20;
  7736. player->addManaSpent(20);
  7737. }
  7738. else if (player->exhaustedTicks >= 1000 && player->access < g_config.ACCESS_PROTECT)
  7739. {
  7740. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7741. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  7742. }
  7743. else
  7744. {
  7745. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7746. player->sendTextMessage(MSG_SMALLINFO, "Not enough mana.");
  7747. return;
  7748. }
  7749.  
  7750.  
  7751. int32_t x = c->pos.x - player->pos.x;
  7752. int32_t y = c->pos.y - player->pos.y;
  7753. int32_t z = c->pos.z - player->pos.z;
  7754. std::stringstream position;
  7755. position << name;
  7756.  
  7757. if(c->access < 3) {
  7758. if((x > 96 && y > 48) || (x > 48 && y > 94) || (x > 74 && y > 74))
  7759. position << " is very far to the south-east.";
  7760. else if((x > 96 && y < -48) || (x > 48 && y < -96) || (x > 74 && y < -74))
  7761. position << " is very far to the north-east.";
  7762. else if((x < -96 && y > 48) || (x < -48 && y > 96) || (x < -74 && y > 74))
  7763. position << " is very far to the south-west.";
  7764. else if((x < -96 && y < -48) || (x < -48 && y < -96) || (x < -74 && y < -74))
  7765. position << " is very far to the north-west.";
  7766.  
  7767. else if((x > 48 && y > 24) || (x > 24 && y > 48) || (x > 36 && y > 36))
  7768. position << " is far to the south-east.";
  7769. else if((x > 48 && y < -24) || (x > 24 && y < -48) || (x > 36 && y < -36))
  7770. position << " is far to the north-east.";
  7771. else if((x < -48 && y > 24) || (x < -24 && y > 48) || (x < -36 && y > 36))
  7772. position << " is far to the south-west.";
  7773. else if((x < -48 && y < -24) || (x < -24 && y < -48) || (x < -36 && y < -36))
  7774. position << " is far to the north-west.";
  7775.  
  7776. else if((x > 6 && y > 12 && z > 0) || (x > 12 && y > 6 && z > 0) || (x > 9 && y > 9 && z > 0))
  7777. position << " is on a lower lvl to the south-east.";
  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 north-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 south-west.";
  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 north-west.";
  7784.  
  7785. else if((x > 6 && y > 12 && z < 0) || (x > 12 && y > 6 && z < 0) || (x > 9 && y > 9 && z < 0))
  7786. position << " is on a higher lvl to the south-east.";
  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 north-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 south-west.";
  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 north-west.";
  7793.  
  7794. else if((x > 6 && y > 12 && z == 0) || (x > 12 && y > 6 && z == 0) || (x > 9 && y > 9 && z == 0))
  7795. position << " is to the south-east.";
  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 north-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 south-west.";
  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 north-west.";
  7802.  
  7803. else if(x > 74)
  7804. position << " is very far to the east.";
  7805. else if(x < -74)
  7806. position << " is very far to the west.";
  7807. else if(y > 74)
  7808. position << " is very far to the south.";
  7809. else if(y < -74)
  7810. position << " is very far to the north.";
  7811.  
  7812. else if(x > 36)
  7813. position << " is far to the east.";
  7814. else if(x < -36)
  7815. position << " is far to the west.";
  7816. else if(y > 36)
  7817. position << " is far to the south.";
  7818. else if(y < -36)
  7819. position << " is far to the north.";
  7820.  
  7821. else if(x > 3 && z < 0)
  7822. position << " is on a higher lvl to the east.";
  7823. else if(x < -3 && z < 0)
  7824. position << " is on a higher lvl to the west.";
  7825. else if(y > 3 && z < 0)
  7826. position << " is on a higher lvl to the south.";
  7827. else if(y < -3 && z < 0)
  7828. position << " is on a higher lvl to the north.";
  7829.  
  7830. else if(x > 3 && z > 0)
  7831. position << " is on a lower lvl to the east.";
  7832. else if(x < -3 && z > 0)
  7833. position << " is on a lower lvl to the west.";
  7834. else if(y > 3 && z > 0)
  7835. position << " is on a lower lvl to the south.";
  7836. else if(y < -3 && z > 0)
  7837. position << " is on a lower lvl to the north.";
  7838.  
  7839. else if(x > 3 && z == 0)
  7840. position << " is to the east.";
  7841. else if(x < -3 && z == 0)
  7842. position << " is to the west.";
  7843. else if(y > 3 && z == 0)
  7844. position << " is to the south.";
  7845. else if(y < -3 && z == 0)
  7846. position << " is to the north.";
  7847.  
  7848. else if(x < 4 && y < 4 && z > 0)
  7849. position << " is below you.";
  7850. else if(x < 4 && y < 4 && z < 0)
  7851. position << " is above you.";
  7852. else
  7853. position << " is just beside you.";
  7854.  
  7855. player->sendTextMessage(MSG_INFO, position.str().c_str());
  7856. player->sendMagicEffect(player->pos, NM_ME_MAGIC_ENERGIE);
  7857. }else{
  7858. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7859. player->sendTextMessage(MSG_SMALLINFO, "Srry, you cant exiva GM's");
  7860. }
  7861. }else
  7862. player->sendTextMessage(MSG_SMALLINFO, "This player is not online.");
  7863. }
  7864.  
  7865. else if (text == "exani tera" &&
  7866. (!g_config.LEARN_SPELLS || player->knowsSpell("exani tera")))
  7867. {
  7868. const int32_t REQ_MANA = 20;
  7869. Tile* tile = getTile(player->pos);
  7870.  
  7871. if (!(tile && (tile->ground->getID() == ITEM_ROPE_SPOT1 || tile->ground->getID() == ITEM_ROPE_SPOT2)))
  7872. {
  7873. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7874. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7875. }
  7876. else if (player->mana < REQ_MANA)
  7877. {
  7878. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7879. player->sendTextMessage(MSG_SMALLINFO, "Not enough mana.");
  7880. }
  7881. else if (player->maglevel < 0)
  7882. {
  7883. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7884. player->sendTextMessage(MSG_SMALLINFO, "You don't have the required magic level.");
  7885. }
  7886. else if (player->exhaustedTicks >= 1000 && player->access < g_config.ACCESS_PROTECT)
  7887. {
  7888. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7889. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  7890. }
  7891. else
  7892. {
  7893. teleport(player, Position(player->pos.x, player->pos.y+1, player->pos.z-1));
  7894. player->sendMagicEffect(player->pos, NM_ME_ENERGY_AREA);
  7895.  
  7896. if (player->access < g_config.ACCESS_PROTECT)
  7897. {
  7898. player->mana -= REQ_MANA;
  7899. player->addManaSpent(REQ_MANA);
  7900. }
  7901. }
  7902. }
  7903. }
  7904.  
  7905. #ifdef TR_SUMMONS
  7906. bool Game::placeSummon(Player* p, const std::string& name)
  7907. {
  7908. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::placeSummon()");
  7909. Monster* monster = Monster::createMonster(name, this);
  7910.  
  7911. if(!monster)
  7912. return false;
  7913.  
  7914. Position pos = p->pos;
  7915. switch (p->direction)
  7916. {
  7917. case NORTH: pos.y--; break;
  7918. case SOUTH: pos.y++; break;
  7919. case EAST: pos.x++; break;
  7920. case WEST: pos.x--; break;
  7921. }
  7922.  
  7923. Tile* tile = getTile(pos);
  7924. #ifdef YUR_PVP_ARENA
  7925. if (!tile || tile->isPz() || tile->isPvpArena() || !placeCreature(pos, monster))
  7926. #else
  7927. if (!tile || tile->isPz() || !placeCreature(pos, monster))
  7928. #endif //YUR_PVP_ARENA
  7929. {
  7930. delete monster;
  7931. return false;
  7932. }
  7933. else
  7934. {
  7935. p->addSummon(monster);
  7936. return true;
  7937. }
  7938. }
  7939. #endif //TR_SUMMONS
  7940.  
  7941.  
  7942. #ifdef TRS_GM_INVISIBLE
  7943. void Game::creatureBroadcastTileUpdated(const Position& pos)
  7944. {
  7945. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureBroadcastTileUpdated()");
  7946. SpectatorVec list;
  7947. SpectatorVec::iterator it;
  7948. getSpectators(Range(pos, true), list);
  7949.  
  7950. //players
  7951. for(it = list.begin(); it != list.end(); ++it) {
  7952. if(dynamic_cast<Player*>(*it)) {
  7953. (*it)->onTileUpdated(pos);
  7954. }
  7955. }
  7956.  
  7957. //none-players
  7958. for(it = list.begin(); it != list.end(); ++it) {
  7959. if(!dynamic_cast<Player*>(*it)) {
  7960. (*it)->onTileUpdated(pos);
  7961. }
  7962. }
  7963. }
  7964. #endif //TRS_GM_INVISIBLE
  7965.  
  7966.  
  7967. #ifdef HUCZU_SKULLS
  7968. void Game::Skull(Player* player)
  7969. {
  7970. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::Skull()");
  7971. if (player)
  7972. {
  7973. SpectatorVec list;
  7974. SpectatorVec::iterator it;
  7975. getSpectators(Range(player->pos, true), list);
  7976.  
  7977. for(it = list.begin(); it != list.end(); ++it)
  7978. {
  7979. Player* spectator = dynamic_cast<Player*>(*it);
  7980. if(spectator)
  7981. if(player->skullType == SKULL_NONE ||
  7982. player->skullType == SKULL_WHITE ||
  7983. player->skullType == SKULL_RED ||
  7984. player->skullType == SKULL_YELLOW && player->isYellowTo(spectator))
  7985. spectator->onSkull(player);
  7986. }
  7987. }
  7988. }
  7989.  
  7990. void Game::onPvP(Creature* creature, Creature* attacked, bool murder)
  7991. {
  7992. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::onPvP()");
  7993. if (creature && creature->getMaster())
  7994. creature = creature->getMaster(); // pk-ing with summons fix
  7995.  
  7996. Player* player = dynamic_cast<Player*>(creature);
  7997. Player* attackedPlayer = dynamic_cast<Player*>(attacked);
  7998.  
  7999. if (player == attackedPlayer)
  8000. return;
  8001. if(!player || !attackedPlayer)
  8002. return;
  8003. if (player && player->access >= g_config.ACCESS_PROTECT || attackedPlayer && attackedPlayer->access >= g_config.ACCESS_PROTECT)
  8004. return;
  8005. if (player->party != 0 && attackedPlayer->party != 0 && player->party == attackedPlayer->party)
  8006. return;
  8007.  
  8008. Tile *p1 = map->getTile(player->pos), *p2 = map->getTile(attackedPlayer->pos);
  8009. if (p1->isPvpArena() && p2->isPvpArena()){
  8010. player->pzLocked = false;
  8011. attackedPlayer->pzLocked = false;
  8012. return;
  8013. }
  8014.  
  8015.  
  8016. player->pzLocked = true;
  8017.  
  8018. if (!murder)
  8019. {
  8020. if(!player->hasAttacked(attackedPlayer)){
  8021. player->attackedPlayers.push_back(attackedPlayer);
  8022. }
  8023.  
  8024. if (attackedPlayer->skullType == SKULL_NONE || attackedPlayer->skullType == SKULL_YELLOW && !attackedPlayer->isYellowTo(player))
  8025. {
  8026. if (player->skullType != SKULL_RED && player->skullType != SKULL_WHITE)
  8027. {
  8028. player->skullType = SKULL_WHITE;
  8029. Skull(player);
  8030. }
  8031. }
  8032.  
  8033. else if(attackedPlayer->skullType == SKULL_WHITE || attackedPlayer->skullType == SKULL_RED)
  8034. {
  8035. if(player->skullType == SKULL_NONE && !player->isYellowTo(attackedPlayer))//si no tiene skull y no es yellow, tenemos que ponerle yellow.
  8036. {
  8037. if(!attackedPlayer->hasAttacked(player))
  8038. {
  8039. player->skullType = SKULL_YELLOW;
  8040. attackedPlayer->hasAsYellow.push_back(player);
  8041. attackedPlayer->onSkull(player);
  8042. }
  8043. }
  8044. }
  8045. if(player->inFightTicks < (int32_t)g_config.PZ_LOCKED)
  8046. player->inFightTicks = (int32_t)g_config.PZ_LOCKED;
  8047. if(player->skullTicks < (int32_t)g_config.PZ_LOCKED)
  8048. player->skullTicks = (int32_t)g_config.PZ_LOCKED;
  8049.  
  8050. }
  8051. else // murder
  8052. {
  8053. 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.
  8054. {
  8055. player->skullKills++;
  8056. std::string justice(std::string("Warning! The murder of ") + attackedPlayer->getName() + " was not justified!");
  8057. player->sendTextMessage(MSG_RED_INFO, justice.c_str());
  8058.  
  8059. if (player->skullKills >= g_config.BAN_UNJUST)
  8060. {
  8061. banPlayer(player, "Excessive unjustifed player killing", "AccountBan", "Zagan Square 2.3 2011 (Braviera)", false);
  8062. }
  8063.  
  8064. if (player->skullKills >= g_config.RED_UNJUST)
  8065. {
  8066. player->skullType = SKULL_RED;
  8067. if(player->skullTicks < g_config.RED_TIME)
  8068. player->skullTicks = g_config.RED_TIME;
  8069. if(player->inFightTicks < g_config.WHITE_TIME)
  8070. player->inFightTicks = g_config.WHITE_TIME;
  8071. Skull(player);
  8072. }
  8073. else
  8074. {
  8075. player->skullType = SKULL_WHITE;
  8076. if(player->skullTicks < g_config.WHITE_TIME)
  8077. player->skullTicks = g_config.WHITE_TIME;
  8078. if(player->inFightTicks < g_config.WHITE_TIME)
  8079. player->inFightTicks = g_config.WHITE_TIME;
  8080. Skull(player);
  8081. }
  8082. }
  8083.  
  8084. else if (attackedPlayer->skullType == SKULL_RED)//victim had red skull..(fair kill)
  8085. {
  8086. if(player->inFightTicks < g_config.WHITE_TIME)
  8087. player->inFightTicks = g_config.WHITE_TIME;//not giving him a skull.. just setting the murder time.
  8088. }
  8089.  
  8090. else if (attackedPlayer->skullType == SKULL_WHITE) //victim had white skull.. (fair kill)
  8091. {
  8092. attackedPlayer->skullType = SKULL_NONE;
  8093. attackedPlayer->skullTicks = 0;
  8094. Skull(attackedPlayer);
  8095. if(player->inFightTicks < g_config.WHITE_TIME)
  8096. player->inFightTicks = g_config.WHITE_TIME;//not giving him a skull.. just setting the murder time.
  8097. }
  8098.  
  8099. else if (attackedPlayer->skullType == SKULL_YELLOW /*&& attackedPlayer->isYellowTo(player)*/)//el que murio era yellow skull para el que lo mato.
  8100. {
  8101. attackedPlayer->skullType = SKULL_NONE;
  8102. attackedPlayer->skullTicks = 0;
  8103. attackedPlayer->inFightTicks = 0;
  8104. Skull(attackedPlayer);
  8105. if(player->inFightTicks < g_config.WHITE_TIME)
  8106. player->inFightTicks = g_config.WHITE_TIME;
  8107. }
  8108. //attackedPlayer->clearAttacked();//czyszczenie listy zaatakowanych
  8109. //player->removeFromYellowList(attackedPlayer);//usuwanie gracza z Yellow skull z listy atakowanych z ys
  8110. //attackedPlayer->removeFromYellowList(player);
  8111. }
  8112. }
  8113.  
  8114. void Game::LeaveParty(Player *player)
  8115. {
  8116. int32_t members = 0;
  8117. std::stringstream bericht1;
  8118. bericht1 << player->getName() << " has left the party";
  8119. if(player->getID() == player->party)
  8120. {
  8121. disbandParty(player->party);
  8122. return;
  8123. }
  8124. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  8125. {
  8126. if((*it).second->party == player->party)
  8127. {
  8128. members++;
  8129. if((*it).second->getID() != player->getID())
  8130. (*it).second->sendTextMessage(MSG_INFO, bericht1.str().c_str());
  8131. (*it).second->onPartyIcons(player, 0, false, true);
  8132. player->onPartyIcons((*it).second, 0, false, true);
  8133. }
  8134. }
  8135. if(members <= 2)
  8136. {
  8137. disbandParty(player->party);
  8138. return;
  8139. }
  8140. player->sendTextMessage(MSG_INFO, "You have left the party.");
  8141. player->party = 0;
  8142. }
  8143.  
  8144. void Game::disbandParty(uint32_t partyID)
  8145. {
  8146. for(AutoList<Player>::listiterator cit = Player::listPlayer.list.begin(); cit != Player::listPlayer.list.end(); ++cit)
  8147. {
  8148. if((*cit).second->party == partyID)
  8149. {
  8150. (*cit).second->party = 0;
  8151. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  8152. {
  8153. (*cit).second->onPartyIcons((*it).second, 0, false, true);
  8154. if((*it).second->skullType == SKULL_NONE ||
  8155. (*it).second->skullType == SKULL_WHITE ||
  8156. (*it).second->skullType == SKULL_RED ||
  8157. (*it).second->skullType == SKULL_YELLOW &&
  8158. (*it).second->isYellowTo((*cit).second))
  8159. (*cit).second->onSkull((*it).second);
  8160. }
  8161. (*cit).second->sendTextMessage(MSG_INFO, "Your party has been disbanded.");
  8162. }
  8163. }
  8164. }
  8165. void Game::checkSkullTime(Player* player)
  8166. {
  8167. if(player->skullType == SKULL_NONE)//just in case
  8168. return;
  8169.  
  8170. if(player->skullTicks < player->inFightTicks)
  8171. player->skullTicks = player->inFightTicks;
  8172.  
  8173. if(player->skullType != SKULL_RED && player->skullTicks > player->inFightTicks) //we don't want to do that if the player has a red skull...
  8174. player->inFightTicks = player->skullTicks;
  8175.  
  8176. }
  8177. #endif //HUCZU_SKULLS
  8178.  
  8179.  
  8180.  
  8181. #ifdef SD_BURST_ARROW
  8182. class MagicEffectAreaNoExhaustionClass: public MagicEffectAreaClass {
  8183. public:
  8184. bool causeExhaustion(bool hasTarget) const { return false; }
  8185. };
  8186.  
  8187. void Game::burstArrow(Creature* c, const Position& pos)
  8188. {
  8189. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::burstArrow()");
  8190. std::vector<unsigned char> col;
  8191. MagicEffectAreaNoExhaustionClass runeAreaSpell;
  8192.  
  8193. Player* player = dynamic_cast<Player*>(c);
  8194.  
  8195. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8196. runeAreaSpell.animationEffect = NM_ANI_BURSTARROW;
  8197. runeAreaSpell.hitEffect = NM_ME_EXPLOSION_DAMAGE;
  8198. runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8199. runeAreaSpell.animationColor = 198; //DAMAGE_FIRE;
  8200. runeAreaSpell.drawblood = true;
  8201. runeAreaSpell.offensive = true;
  8202.  
  8203. /* Area of Spell */
  8204. col.push_back(1);
  8205. col.push_back(1);
  8206. col.push_back(1);
  8207. runeAreaSpell.areaVec.push_back(col);
  8208. col.clear();
  8209. col.push_back(1);
  8210. col.push_back(1);
  8211. col.push_back(1);
  8212. runeAreaSpell.areaVec.push_back(col);
  8213. col.clear();
  8214. col.push_back(1);
  8215. col.push_back(1);
  8216. col.push_back(1);
  8217. runeAreaSpell.areaVec.push_back(col);
  8218.  
  8219. /* hard no ? */
  8220. runeAreaSpell.direction = 1;
  8221.  
  8222. if (player->vocation == VOCATION_KNIGHT) {
  8223. 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);
  8224. 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);
  8225. }
  8226.  
  8227. if (player->vocation == VOCATION_PALADIN) {
  8228. 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);
  8229. 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);
  8230. }
  8231.  
  8232. if (player->vocation == VOCATION_DRUID) {
  8233. 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);
  8234. 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);
  8235. }
  8236.  
  8237. if (player->vocation == VOCATION_SORCERER) {
  8238. 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);
  8239. 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);
  8240. }
  8241.  
  8242. creatureThrowRune(c, pos, runeAreaSpell);
  8243. }
  8244. #endif //SD_BURST_ARROW
  8245.  
  8246.  
  8247. #ifdef YUR_SHUTDOWN
  8248. void Game::sheduleShutdown(int32_t minutes)
  8249. {
  8250. if (minutes > 0)
  8251. checkShutdown(minutes);
  8252. }
  8253.  
  8254. void Game::checkShutdown(int32_t minutes)
  8255. {
  8256. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkShutdown()");
  8257. if (minutes == 0)
  8258. {
  8259. setGameState(GAME_STATE_CLOSED);
  8260. while (!Player::listPlayer.list.empty())
  8261. Player::listPlayer.list.begin()->second->kickPlayer();
  8262.  
  8263. serverSave();
  8264. std::cout << "==| shutdown..." << std::endl;
  8265. //setGameState(GAME_STATE_SHUTDOWN);
  8266. OTSYS_SLEEP(1000);
  8267. exit(1);
  8268. }
  8269. else
  8270. {
  8271. std::stringstream msg;
  8272. msg << "Server going to shutdown in " << minutes << (minutes>1? " minutes. \n Please logout." : " minute. \n Please logout.") << std::ends;
  8273.  
  8274. AutoList<Player>::listiterator it = Player::listPlayer.list.begin();
  8275. while (it != Player::listPlayer.list.end())
  8276. {
  8277. (*it).second->sendTextMessage(MSG_RED_INFO, msg.str().c_str());
  8278. ++it;
  8279. }
  8280.  
  8281. addEvent(makeTask(60000, boost::bind(&Game::checkShutdown, this, minutes - 1)));
  8282. }
  8283. }
  8284. #endif //YUR_SHUTDOWN
  8285.  
  8286.  
  8287. #ifdef YUR_CMD_EXT
  8288. void Game::setMaxPlayers(uint32_t newmax)
  8289. {
  8290. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::setMaxPlayers()");
  8291. max_players = newmax;
  8292. Status::instance()->playersmax = newmax;
  8293. }
  8294. #endif //YUR_CMD_EXT
  8295.  
  8296. long Game::cleanMap()
  8297. {
  8298. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::cleanMap()");
  8299. return map->clean();
  8300. }
  8301.  
  8302. long Game::beforeClean()
  8303. {
  8304. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it) {
  8305. it->second->sendTextMessage(MSG_RED_INFO, "1 minute to clean. Get your things from floor now!");
  8306. }
  8307. addEvent(makeTask(60000, std::mem_fun(&Game::secondsToClean)));
  8308. }
  8309. long Game::beforeCleanTrzy()
  8310. {
  8311. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it) {
  8312. it->second->sendTextMessage(MSG_RED_INFO, "Warning! Clean in 3 minutes.");
  8313. }
  8314. addEvent(makeTask(60000, std::mem_fun(&Game::beforeCleanDwa)));
  8315. }
  8316. long Game::beforeCleanDwa()
  8317. {
  8318. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it) {
  8319. it->second->sendTextMessage(MSG_RED_INFO, "Warning! Clean in 2 minutes.");
  8320. }
  8321. addEvent(makeTask(60000, std::mem_fun(&Game::beforeClean)));
  8322. }
  8323. void Game::secondsToClean()
  8324. {
  8325. autocleanMap(5);
  8326. }
  8327. void Game::autocleanMap(int32_t seconds)
  8328. {
  8329. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::autocleanMap()");
  8330. if (seconds == 0)
  8331. {
  8332. std::cout << ":: auto clean... ";
  8333. timer();
  8334. long count = cleanMap();
  8335. double sec = timer();
  8336.  
  8337. std::stringstream msg;
  8338. msg << "Clean completed. Collected " << count << (count==1? " item." : " items.") << std::ends;
  8339. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  8340. if(dynamic_cast<Player*>(it->second))
  8341. (*it).second->sendTextMessage(MSG_RED_INFO, msg.str().c_str());
  8342. }
  8343.  
  8344. std::cout << "ok (" << timer() << "s)" << std::endl;
  8345. addEvent(makeTask((g_config.getGlobalNumber("autoclean", 2))*60000, std::mem_fun(&Game::beforeCleanTrzy)));
  8346. }
  8347. else
  8348. {
  8349. std::stringstream msg;
  8350. msg << "Clean in " << seconds << std::ends;
  8351.  
  8352. AutoList<Player>::listiterator it = Player::listPlayer.list.begin();
  8353. while (it != Player::listPlayer.list.end())
  8354. {
  8355. (*it).second->sendTextMessage(MSG_RED_INFO, msg.str().c_str());
  8356. ++it;
  8357. }
  8358.  
  8359. addEvent(makeTask(8000, boost::bind(&Game::autocleanMap, this, seconds - 1)));
  8360. }
  8361. }
  8362.  
  8363.  
  8364. #ifdef CVS_DAY_CYCLE
  8365. void Game::creatureChangeLight(Player* player, int32_t time, unsigned char lightlevel, unsigned char lightcolor)
  8366. {
  8367. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureChangeLight()");
  8368.  
  8369. player->setLightLevel(lightlevel, lightcolor);
  8370. SpectatorVec list;
  8371. getSpectators(Range(player->pos), list);
  8372.  
  8373. for (SpectatorVec::iterator iter = list.begin(); iter != list.end(); ++iter)
  8374. {
  8375. Player* spectator = dynamic_cast<Player*>(*iter);
  8376. if (spectator)
  8377. spectator->sendPlayerLightLevel(player);
  8378. }
  8379. }
  8380.  
  8381. void Game::checkLight(int32_t t)
  8382. {
  8383. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkLight()");
  8384. addEvent(makeTask(10000, boost::bind(&Game::checkLight, this, 10000)));
  8385.  
  8386. light_hour = light_hour + light_hour_delta;
  8387. if(light_hour > 1440)
  8388. light_hour = light_hour - 1440;
  8389.  
  8390. if(std::abs(light_hour - SUNRISE) < 2*light_hour_delta){
  8391. light_state = LIGHT_STATE_SUNRISE;
  8392. }
  8393. else if(std::abs(light_hour - SUNSET) < 2*light_hour_delta){
  8394. light_state = LIGHT_STATE_SUNSET;
  8395. }
  8396.  
  8397. int32_t newlightlevel = lightlevel;
  8398. switch(light_state){
  8399. case LIGHT_STATE_SUNRISE:
  8400. newlightlevel += (LIGHT_LEVEL_DAY - LIGHT_LEVEL_NIGHT)/30;
  8401. break;
  8402. case LIGHT_STATE_SUNSET:
  8403. newlightlevel -= (LIGHT_LEVEL_DAY - LIGHT_LEVEL_NIGHT)/30;
  8404. break;
  8405. }
  8406.  
  8407. if(newlightlevel <= LIGHT_LEVEL_NIGHT){
  8408. lightlevel = LIGHT_LEVEL_NIGHT;
  8409. light_state = LIGHT_STATE_NIGHT;
  8410. }
  8411. else if(newlightlevel >= LIGHT_LEVEL_DAY){
  8412. lightlevel = LIGHT_LEVEL_DAY;
  8413. light_state = LIGHT_STATE_DAY;
  8414. }
  8415. else{
  8416. lightlevel = newlightlevel;
  8417. }
  8418.  
  8419.  
  8420. // status, ten kod i tak jest brzydki
  8421. uint64_t time = OTSYS_TIME();
  8422. ofstream file;
  8423. file.open ("status");
  8424. file << time << " " << (time - Status::instance()->start)/1000 << " " << Status::instance()->playersonline << " " << Status::instance()->playersmax;
  8425. file.close();
  8426.  
  8427. file.open("online");
  8428. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  8429. std::string txt = (*it).second->getName();
  8430. file << (*it).second->getName() << ";" << (*it).second->getLevel() << "\n";
  8431. }
  8432. file.close();
  8433.  
  8434.  
  8435. }
  8436.  
  8437. unsigned char Game::getLightLevel(){
  8438. return lightlevel;
  8439. }
  8440. #endif //CVS_DAY_CYCLE
  8441.  
  8442.  
  8443. #ifdef WANDS_JIDDO
  8444. void Game::useWand(Creature *creature, Creature *attackedCreature, int32_t wandid) {
  8445.  
  8446. Player *player = dynamic_cast<Player*>(creature);
  8447. if(!player) return;
  8448.  
  8449. if((wandid == 5318 && (player->vocation == VOCATION_DRUID) && player->mana >= 15 && player->getLevel() >= 65)) { //Quagmire rod
  8450. int32_t dist = 6;
  8451. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8452. std::vector<unsigned char> col;
  8453. MagicEffectAreaClass runeAreaSpell;
  8454. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8455. runeAreaSpell.animationEffect = NM_ANI_SNOWBALL;
  8456. runeAreaSpell.hitEffect = NM_ME_LOOSE_ENERGY;
  8457. runeAreaSpell.areaEffect = NM_ME_DRAW_BLOOD;
  8458. runeAreaSpell.animationColor = 0x47;
  8459. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8460. col.push_back(0);
  8461. col.push_back(0);
  8462. col.push_back(0);
  8463. runeAreaSpell.areaVec.push_back(col);
  8464. col.clear();
  8465. col.push_back(0);
  8466. col.push_back(1);
  8467. col.push_back(0);
  8468. runeAreaSpell.areaVec.push_back(col);
  8469. col.clear();
  8470. col.push_back(0);
  8471. col.push_back(0);
  8472. col.push_back(0);
  8473. runeAreaSpell.areaVec.push_back(col);
  8474. col.clear();
  8475. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 70; runeAreaSpell.maxDamage = 150;
  8476. long tempExhaust = player->exhaustedTicks;
  8477. player->exhaustedTicks = 0;
  8478. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8479. player->exhaustedTicks = tempExhaust;
  8480. int32_t mana = 15;
  8481. player->addManaSpent(mana);
  8482. player->mana -= mana;
  8483. return;
  8484. }
  8485.  
  8486.  
  8487. if((wandid == 5319 && (player->vocation == VOCATION_SORCERER) && player->mana >= 15 && player->getLevel() >= 65)) { //Wand of cosmic energy
  8488. int32_t dist = 6;
  8489. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8490. std::vector<unsigned char> col;
  8491. MagicEffectAreaClass runeAreaSpell;
  8492. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8493. runeAreaSpell.animationEffect = NM_ANI_LARGEROCK;
  8494. runeAreaSpell.hitEffect = NM_ME_SOUND_WHITE;
  8495. runeAreaSpell.areaEffect = NM_ME_SOUND_WHITE;
  8496. runeAreaSpell.animationColor = 0xAC;
  8497. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8498. col.push_back(0);
  8499. col.push_back(0);
  8500. col.push_back(0);
  8501. runeAreaSpell.areaVec.push_back(col);
  8502. col.clear();
  8503. col.push_back(0);
  8504. col.push_back(1);
  8505. col.push_back(0);
  8506. runeAreaSpell.areaVec.push_back(col);
  8507. col.clear();
  8508. col.push_back(0);
  8509. col.push_back(0);
  8510. col.push_back(0);
  8511. runeAreaSpell.areaVec.push_back(col);
  8512. col.clear();
  8513. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 70; runeAreaSpell.maxDamage = 150;
  8514. long tempExhaust = player->exhaustedTicks;
  8515. player->exhaustedTicks = 0;
  8516. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8517. player->exhaustedTicks = tempExhaust;
  8518. int32_t mana = 15;
  8519. player->addManaSpent(mana);
  8520. player->mana -= mana;
  8521. return;
  8522. }
  8523.  
  8524. //SCEPTRE OF THE LOST SOULS
  8525. if((wandid == 5326 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_DRUID) && player->mana >= 50 && player->getLevel() >= 300)) {
  8526. int32_t dist = 4;
  8527. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8528. std::vector<unsigned char> col;
  8529. MagicEffectAreaClass runeAreaSpell;
  8530. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8531. runeAreaSpell.animationEffect = NM_ANI_ENERGY2;
  8532. runeAreaSpell.hitEffect = NM_ME_ENERGY_AREA;
  8533. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8534. runeAreaSpell.animationColor = 0x65;
  8535. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8536. col.push_back(0);
  8537. col.push_back(0);
  8538. col.push_back(0);
  8539. runeAreaSpell.areaVec.push_back(col);
  8540. col.clear();
  8541. col.push_back(0);
  8542. col.push_back(1);
  8543. col.push_back(0);
  8544. runeAreaSpell.areaVec.push_back(col);
  8545. col.clear();
  8546. col.push_back(0);
  8547. col.push_back(0);
  8548. col.push_back(0);
  8549. runeAreaSpell.areaVec.push_back(col);
  8550. col.clear();
  8551. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 350; runeAreaSpell.maxDamage = 450;
  8552. long tempExhaust = player->exhaustedTicks;
  8553. player->exhaustedTicks = 0;
  8554. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8555. player->exhaustedTicks = tempExhaust;
  8556. int32_t mana = 50;
  8557. player->addManaSpent(mana);
  8558. player->mana -= mana;
  8559. return;
  8560. }
  8561.  
  8562. //NATURE WAND
  8563. if((wandid == 2544 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_DRUID) && player->mana >= 35 && player->getLevel() >= 200)) {
  8564. int32_t dist = 5;
  8565. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8566. std::vector<unsigned char> col;
  8567. MagicEffectAreaClass runeAreaSpell;
  8568. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8569. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8570. runeAreaSpell.hitEffect = 20;
  8571. runeAreaSpell.areaEffect = 20;
  8572. runeAreaSpell.animationColor = 0x60;
  8573. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8574. col.push_back(0);
  8575. col.push_back(0);
  8576. col.push_back(0);
  8577. runeAreaSpell.areaVec.push_back(col);
  8578. col.clear();
  8579. col.push_back(0);
  8580. col.push_back(1);
  8581. col.push_back(0);
  8582. runeAreaSpell.areaVec.push_back(col);
  8583. col.clear();
  8584. col.push_back(0);
  8585. col.push_back(0);
  8586. col.push_back(0);
  8587. runeAreaSpell.areaVec.push_back(col);
  8588. col.clear();
  8589. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 200; runeAreaSpell.maxDamage = 350;
  8590. long tempExhaust = player->exhaustedTicks;
  8591. player->exhaustedTicks = 0;
  8592. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8593. player->exhaustedTicks = tempExhaust;
  8594. int32_t mana = 35;
  8595. player->addManaSpent(mana);
  8596. player->mana -= mana;
  8597. return;
  8598. }
  8599.  
  8600. //SPRITE WAND
  8601. if((wandid == 2453 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_DRUID) && player->mana >= 25 && player->getLevel() >= 150)) {
  8602. int32_t dist = 5;
  8603. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8604. std::vector<unsigned char> col;
  8605. MagicEffectAreaClass runeAreaSpell;
  8606. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8607. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8608. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8609. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8610. runeAreaSpell.animationColor = 0x11;
  8611. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8612. col.push_back(0);
  8613. col.push_back(0);
  8614. col.push_back(0);
  8615. runeAreaSpell.areaVec.push_back(col);
  8616. col.clear();
  8617. col.push_back(0);
  8618. col.push_back(1);
  8619. col.push_back(0);
  8620. runeAreaSpell.areaVec.push_back(col);
  8621. col.clear();
  8622. col.push_back(0);
  8623. col.push_back(0);
  8624. col.push_back(0);
  8625. runeAreaSpell.areaVec.push_back(col);
  8626. col.clear();
  8627. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 150; runeAreaSpell.maxDamage = 250;
  8628. long tempExhaust = player->exhaustedTicks;
  8629. player->exhaustedTicks = 0;
  8630. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8631. player->exhaustedTicks = tempExhaust;
  8632. int32_t mana = 25;
  8633. player->addManaSpent(mana);
  8634. player->mana -= mana;
  8635. return;
  8636. }
  8637.  
  8638.  
  8639. if((wandid == 2181 && (player->vocation == VOCATION_DRUID) && player->mana >= 8 && player->getLevel() >= 26)) { //Quagmire rod
  8640. int32_t dist = 2;
  8641. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8642. std::vector<unsigned char> col;
  8643. MagicEffectAreaClass runeAreaSpell;
  8644. runeAreaSpell.attackType = ATTACK_POISON;
  8645. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8646. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  8647. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  8648. runeAreaSpell.animationColor = 0x60;
  8649. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8650. col.push_back(0);
  8651. col.push_back(0);
  8652. col.push_back(0);
  8653. runeAreaSpell.areaVec.push_back(col);
  8654. col.clear();
  8655. col.push_back(0);
  8656. col.push_back(1);
  8657. col.push_back(0);
  8658. runeAreaSpell.areaVec.push_back(col);
  8659. col.clear();
  8660. col.push_back(0);
  8661. col.push_back(0);
  8662. col.push_back(0);
  8663. runeAreaSpell.areaVec.push_back(col);
  8664. col.clear();
  8665. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 40; runeAreaSpell.maxDamage = 50;
  8666. long tempExhaust = player->exhaustedTicks;
  8667. player->exhaustedTicks = 0;
  8668. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8669. player->exhaustedTicks = tempExhaust;
  8670. int32_t mana = 8;
  8671. player->addManaSpent(mana);
  8672. player->mana -= mana;
  8673. return;
  8674. }
  8675.  
  8676. if((wandid == 2182 && (player->vocation == VOCATION_DRUID) && player->mana >= 2 && player->getLevel() >= 7)) { //Snakebite rod
  8677. int32_t dist = 4;
  8678. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8679. std::vector<unsigned char> col;
  8680. MagicEffectAreaClass runeAreaSpell;
  8681. runeAreaSpell.attackType = ATTACK_POISON;
  8682. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8683. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  8684. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  8685. runeAreaSpell.animationColor = 0x60;
  8686. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8687. col.push_back(0);
  8688. col.push_back(0);
  8689. col.push_back(0);
  8690. runeAreaSpell.areaVec.push_back(col);
  8691. col.clear();
  8692. col.push_back(0);
  8693. col.push_back(1);
  8694. col.push_back(0);
  8695. runeAreaSpell.areaVec.push_back(col);
  8696. col.clear();
  8697. col.push_back(0);
  8698. col.push_back(0);
  8699. col.push_back(0);
  8700. runeAreaSpell.areaVec.push_back(col);
  8701. col.clear();
  8702. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 8; runeAreaSpell.maxDamage = 18;
  8703. long tempExhaust = player->exhaustedTicks;
  8704. player->exhaustedTicks = 0;
  8705. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8706. player->exhaustedTicks = tempExhaust;
  8707. int32_t mana = 2;
  8708. player->addManaSpent(mana);
  8709. player->mana -= mana;
  8710. return;
  8711. }
  8712.  
  8713.  
  8714.  
  8715. if((wandid == 2183 && (player->vocation == VOCATION_DRUID) && player->mana >= 13 && player->getLevel() >= 33)) { //Tempest rod
  8716. int32_t dist = 2;
  8717. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8718. std::vector<unsigned char> col;
  8719. MagicEffectAreaClass runeAreaSpell;
  8720. runeAreaSpell.attackType = ATTACK_ENERGY;
  8721. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8722. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8723. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8724. runeAreaSpell.animationColor = 0x11;
  8725. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8726. col.push_back(0);
  8727. col.push_back(0);
  8728. col.push_back(0);
  8729. runeAreaSpell.areaVec.push_back(col);
  8730. col.clear();
  8731. col.push_back(0);
  8732. col.push_back(1);
  8733. col.push_back(0);
  8734. runeAreaSpell.areaVec.push_back(col);
  8735. col.clear();
  8736. col.push_back(0);
  8737. col.push_back(0);
  8738. col.push_back(0);
  8739. runeAreaSpell.areaVec.push_back(col);
  8740. col.clear();
  8741. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 60; runeAreaSpell.maxDamage = 70;
  8742. long tempExhaust = player->exhaustedTicks;
  8743. player->exhaustedTicks = 0;
  8744. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8745. player->exhaustedTicks = tempExhaust;
  8746. int32_t mana = 13;
  8747. player->addManaSpent(mana);
  8748. player->mana -= mana;
  8749. return;
  8750. }
  8751.  
  8752.  
  8753. if((wandid == 2185 && (player->vocation == VOCATION_DRUID) && player->mana >= 5 && player->getLevel() >= 19)) { //Volcanic rod
  8754. int32_t dist = 2;
  8755. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8756. std::vector<unsigned char> col;
  8757. MagicEffectAreaClass runeAreaSpell;
  8758. runeAreaSpell.attackType = ATTACK_FIRE;
  8759. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  8760. runeAreaSpell.hitEffect = NM_ME_FIRE_AREA;
  8761. runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8762. runeAreaSpell.animationColor = 0xC7;
  8763. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8764. col.push_back(0);
  8765. col.push_back(0);
  8766. col.push_back(0);
  8767. runeAreaSpell.areaVec.push_back(col);
  8768. col.clear();
  8769. col.push_back(0);
  8770. col.push_back(1);
  8771. col.push_back(0);
  8772. runeAreaSpell.areaVec.push_back(col);
  8773. col.clear();
  8774. col.push_back(0);
  8775. col.push_back(0);
  8776. col.push_back(0);
  8777. runeAreaSpell.areaVec.push_back(col);
  8778. col.clear();
  8779. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 25; runeAreaSpell.maxDamage = 35;
  8780. long tempExhaust = player->exhaustedTicks;
  8781. player->exhaustedTicks = 0;
  8782. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8783. player->exhaustedTicks = tempExhaust;
  8784. int32_t mana = 5;
  8785. player->addManaSpent(mana);
  8786. player->mana -= mana;
  8787. return;
  8788. }
  8789.  
  8790.  
  8791. if((wandid == 2186 && (player->vocation == VOCATION_DRUID) && player->mana >= 3 && player->getLevel() >= 13)) { //Moonlight rod
  8792. int32_t dist = 3;
  8793. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8794. std::vector<unsigned char> col;
  8795. MagicEffectAreaClass runeAreaSpell;
  8796. runeAreaSpell.attackType = ATTACK_ENERGY;
  8797. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8798. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8799. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8800. runeAreaSpell.animationColor = 0x47;
  8801. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8802. col.push_back(0);
  8803. col.push_back(0);
  8804. col.push_back(0);
  8805. runeAreaSpell.areaVec.push_back(col);
  8806. col.clear();
  8807. col.push_back(0);
  8808. col.push_back(1);
  8809. col.push_back(0);
  8810. runeAreaSpell.areaVec.push_back(col);
  8811. col.clear();
  8812. col.push_back(0);
  8813. col.push_back(0);
  8814. col.push_back(0);
  8815. runeAreaSpell.areaVec.push_back(col);
  8816. col.clear();
  8817. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 14; runeAreaSpell.maxDamage = 24;
  8818. long tempExhaust = player->exhaustedTicks;
  8819. player->exhaustedTicks = 0;
  8820. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8821. player->exhaustedTicks = tempExhaust;
  8822. int32_t mana = 3;
  8823. player->addManaSpent(mana);
  8824. player->mana -= mana;
  8825. return;
  8826. }
  8827.  
  8828.  
  8829. if((wandid == 2187 && (player->vocation == VOCATION_SORCERER) && player->mana >= 13 && player->getLevel() >= 33)) { //Wand of inferno
  8830. int32_t dist = 2;
  8831. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8832. std::vector<unsigned char> col;
  8833. MagicEffectAreaClass runeAreaSpell;
  8834. runeAreaSpell.attackType = ATTACK_FIRE;
  8835. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  8836. runeAreaSpell.hitEffect = NM_ME_FIRE_AREA;
  8837. runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8838. runeAreaSpell.animationColor = 0xC7;
  8839. runeAreaSpell.drawblood = true;
  8840. runeAreaSpell.offensive = true;
  8841. col.push_back(0);
  8842. col.push_back(0);
  8843. col.push_back(0);
  8844. runeAreaSpell.areaVec.push_back(col);
  8845. col.clear();
  8846. col.push_back(0);
  8847. col.push_back(1);
  8848. col.push_back(0);
  8849. runeAreaSpell.areaVec.push_back(col);
  8850. col.clear();
  8851. col.push_back(0);
  8852. col.push_back(0);
  8853. col.push_back(0);
  8854. runeAreaSpell.areaVec.push_back(col);
  8855. col.clear();
  8856. runeAreaSpell.direction = 1;
  8857. runeAreaSpell.minDamage = 60;
  8858. runeAreaSpell.maxDamage = 70;
  8859. long tempExhaust = player->exhaustedTicks;
  8860. player->exhaustedTicks = 0;
  8861. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8862. player->exhaustedTicks = tempExhaust;
  8863. int32_t mana = 13;
  8864. player->addManaSpent(mana);
  8865. player->mana -= mana;
  8866.  
  8867. return;
  8868. }
  8869.  
  8870.  
  8871. if((wandid == 2188 && (player->vocation == VOCATION_SORCERER) && player->mana >= 5 && player->getLevel() >= 19)) { //Wand of plague
  8872. int32_t dist = 2;
  8873. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8874. std::vector<unsigned char> col;
  8875. MagicEffectAreaClass runeAreaSpell;
  8876. runeAreaSpell.attackType = ATTACK_POISON;
  8877. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8878. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  8879. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  8880. runeAreaSpell.animationColor = 0x60;
  8881. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8882. col.push_back(0);
  8883. col.push_back(0);
  8884. col.push_back(0);
  8885. runeAreaSpell.areaVec.push_back(col);
  8886. col.clear();
  8887. col.push_back(0);
  8888. col.push_back(1);
  8889. col.push_back(0);
  8890. runeAreaSpell.areaVec.push_back(col);
  8891. col.clear();
  8892. col.push_back(0);
  8893. col.push_back(0);
  8894. col.push_back(0);
  8895. runeAreaSpell.areaVec.push_back(col);
  8896. col.clear();
  8897. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 25; runeAreaSpell.maxDamage = 35;
  8898. long tempExhaust = player->exhaustedTicks;
  8899. player->exhaustedTicks = 0;
  8900. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8901. player->exhaustedTicks = tempExhaust;
  8902. int32_t mana = 5;
  8903. player->addManaSpent(mana);
  8904. player->mana -= mana;
  8905. return;
  8906. }
  8907.  
  8908.  
  8909. if((wandid == 2189 && (player->vocation == VOCATION_SORCERER) && player->mana >= 8 && player->getLevel() >= 26)) { //Wand of cosmic energy
  8910. int32_t dist = 2;
  8911. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8912. std::vector<unsigned char> col;
  8913. MagicEffectAreaClass runeAreaSpell;
  8914. runeAreaSpell.attackType = ATTACK_ENERGY;
  8915. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8916. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8917. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8918. runeAreaSpell.animationColor = 0x47;
  8919. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8920. col.push_back(0);
  8921. col.push_back(0);
  8922. col.push_back(0);
  8923. runeAreaSpell.areaVec.push_back(col);
  8924. col.clear();
  8925. col.push_back(0);
  8926. col.push_back(1);
  8927. col.push_back(0);
  8928. runeAreaSpell.areaVec.push_back(col);
  8929. col.clear();
  8930. col.push_back(0);
  8931. col.push_back(0);
  8932. col.push_back(0);
  8933. runeAreaSpell.areaVec.push_back(col);
  8934. col.clear();
  8935. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 40; runeAreaSpell.maxDamage = 50;
  8936. long tempExhaust = player->exhaustedTicks;
  8937. player->exhaustedTicks = 0;
  8938. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8939. player->exhaustedTicks = tempExhaust;
  8940. int32_t mana = 8;
  8941. player->addManaSpent(mana);
  8942. player->mana -= mana;
  8943. return;
  8944. }
  8945.  
  8946.  
  8947. if((wandid == 2190 && (player->vocation == VOCATION_SORCERER) && player->mana >= 2 && player->getLevel() >= 7)) { //Wand of vortex
  8948. int32_t dist = 3;
  8949. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8950. std::vector<unsigned char> col;
  8951. MagicEffectAreaClass runeAreaSpell;
  8952. runeAreaSpell.attackType = ATTACK_ENERGY;
  8953. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8954. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8955. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8956. runeAreaSpell.animationColor = 0x47;
  8957. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8958. col.push_back(0);
  8959. col.push_back(0);
  8960. col.push_back(0);
  8961. runeAreaSpell.areaVec.push_back(col);
  8962. col.clear();
  8963. col.push_back(0);
  8964. col.push_back(1);
  8965. col.push_back(0);
  8966. runeAreaSpell.areaVec.push_back(col);
  8967. col.clear();
  8968. col.push_back(0);
  8969. col.push_back(0);
  8970. col.push_back(0);
  8971. runeAreaSpell.areaVec.push_back(col);
  8972. col.clear();
  8973. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 8; runeAreaSpell.maxDamage = 18;
  8974. long tempExhaust = player->exhaustedTicks;
  8975. player->exhaustedTicks = 0;
  8976. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8977. player->exhaustedTicks = tempExhaust;
  8978. int32_t mana = 2;
  8979. player->addManaSpent(mana);
  8980. player->mana -= mana;
  8981. return;
  8982. }
  8983.  
  8984. if((wandid == 2191 && (player->vocation == VOCATION_SORCERER) && player->mana >= 3 && player->getLevel() >= 13)) { //Wand of dragonbreath
  8985. int32_t dist = 3;
  8986. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8987. std::vector<unsigned char> col;
  8988. MagicEffectAreaClass runeAreaSpell;
  8989. runeAreaSpell.attackType = ATTACK_FIRE;
  8990. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  8991. runeAreaSpell.hitEffect = NM_ME_FIRE_AREA;
  8992. runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8993. runeAreaSpell.animationColor = 0xC7;
  8994. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8995. col.push_back(0);
  8996. col.push_back(0);
  8997. col.push_back(0);
  8998. runeAreaSpell.areaVec.push_back(col);
  8999. col.clear();
  9000. col.push_back(0);
  9001. col.push_back(1);
  9002. col.push_back(0);
  9003. runeAreaSpell.areaVec.push_back(col);
  9004. col.clear();
  9005. col.push_back(0);
  9006. col.push_back(0);
  9007. col.push_back(0);
  9008. runeAreaSpell.areaVec.push_back(col);
  9009. col.clear();
  9010. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 14; runeAreaSpell.maxDamage = 24;
  9011. long tempExhaust = player->exhaustedTicks;
  9012. player->exhaustedTicks = 0;
  9013. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  9014. player->exhaustedTicks = tempExhaust;
  9015. int32_t mana = 3;
  9016. player->addManaSpent(mana);
  9017. player->mana -= mana;
  9018. return;
  9019. }
  9020. //messages by Subarmy
  9021.  
  9022.  
  9023.  
  9024. 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
  9025. player->sendTextMessage(MSG_SMALLINFO, "This wand can only be wielded by sorcerers.");
  9026. }
  9027. 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
  9028. player->sendTextMessage(MSG_SMALLINFO, "This wand can only be wielded by druids.");
  9029. }
  9030. if((wandid == 2181 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 26)) {
  9031. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 26 level to wield this wand.");
  9032. }
  9033. if((wandid == 2544 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 200)) {
  9034. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 200 level to wield this wand.");
  9035. }
  9036. if((wandid == 5326 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 300)) {
  9037. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 300 level to wield this wand.");
  9038. }
  9039. if((wandid == 2453 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 150)) {
  9040. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 150 level to wield this wand.");
  9041. }
  9042. if((wandid == 2182 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 7)) {
  9043. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 7 level to wield this wand.");
  9044. }
  9045. if((wandid == 2183 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 33)) {
  9046. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 33 to wield this wand.");
  9047. }
  9048. if((wandid == 2185 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 19)) {
  9049. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 19 level to wield this wand.");
  9050. }
  9051. if((wandid == 2186 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 13)) {
  9052. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 13 level to wield this wand.");
  9053. }
  9054. if((wandid == 5318 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 65)) {
  9055. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 65 level to wield this wand.");
  9056. }
  9057. if((wandid == 2187 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 33)) {
  9058. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 33 level to wield this wand.");
  9059. }
  9060. if((wandid == 5319 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 65)) {
  9061. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 65 level to wield this wand.");
  9062. }
  9063. if((wandid == 2453 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 150)) {
  9064. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 150 level to wield this wand.");
  9065. }
  9066. if((wandid == 2544 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 200)) {
  9067. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 200 level to wield this wand.");
  9068. }
  9069. if((wandid == 5326 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 300)) {
  9070. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 300 level to wield this wand.");
  9071. }
  9072. if((wandid == 2188 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 19)) {
  9073. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 19 level to wield this wand.");
  9074. }
  9075. if((wandid == 2189 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 26)) {
  9076. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 26 level to wield this wand.");
  9077. }
  9078. if((wandid == 2190 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 7)) {
  9079. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 7 level to wield this wand.");
  9080. }
  9081.  
  9082. if((wandid == 2191 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 13)) {
  9083. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 13 level to wield this wand.");
  9084. }//end messages by Subarmy
  9085. }
  9086. #endif
  9087. // ONLINE RECORD
  9088. void Game::checkRecord()
  9089. {
  9090. if(record < getPlayersOnline()){
  9091. record = getPlayersOnline();
  9092. saveRecord();
  9093.  
  9094. std::stringstream record;
  9095. record << "New record: " << getPlayersOnline() << " players are logged in." << std::endl;
  9096. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  9097. (*it).second->sendTextMessage(MSG_ADVANCE, record.str().c_str());
  9098. }
  9099.  
  9100. }
  9101.  
  9102. bool Game::loadRecord()
  9103. {
  9104. std::string filename = g_config.getGlobalString("datadir") + "record.xml";
  9105. xmlDocPtr doc;
  9106. xmlMutexLock(xmlmutex);
  9107. doc = xmlParseFile(filename.c_str());
  9108.  
  9109. if (doc)
  9110. {
  9111. xmlNodePtr root, tmp;
  9112. root = xmlDocGetRootElement(doc);
  9113.  
  9114. if (xmlStrcmp(root->name, (const xmlChar*)"record"))
  9115. {
  9116. xmlFreeDoc(doc);
  9117. xmlMutexUnlock(xmlmutex);
  9118. return false;
  9119. }
  9120.  
  9121. record = atoi((const char*)xmlGetProp(root, (const xmlChar *)"record"));
  9122.  
  9123. xmlFreeDoc(doc);
  9124. xmlMutexUnlock(xmlmutex);
  9125. return true;
  9126. }
  9127.  
  9128. xmlMutexUnlock(xmlmutex);
  9129. return false;
  9130. }
  9131.  
  9132. bool Game::saveRecord()
  9133. {
  9134. std::string filename = g_config.getGlobalString("datadir") + "record.xml";
  9135. xmlDocPtr doc;
  9136. xmlNodePtr root, tmp;
  9137. xmlMutexLock(xmlmutex);
  9138. time_t time = std::time(NULL);
  9139.  
  9140. doc = xmlNewDoc((const xmlChar*)"1.0");
  9141. doc->children = xmlNewDocNode(doc, NULL, (const xmlChar*)"record", NULL);
  9142. root = doc->children;
  9143.  
  9144. std::stringstream sb;
  9145. sb << record; xmlSetProp(root, (const xmlChar*) "record", (const xmlChar*)sb.str().c_str()); sb.str("");
  9146. sb << time; xmlSetProp(root, (const xmlChar*) "time", (const xmlChar*)sb.str().c_str()); sb.str("");
  9147.  
  9148. xmlSaveFile(filename.c_str(), doc);
  9149. xmlFreeDoc(doc);
  9150. xmlMutexUnlock(xmlmutex);
  9151. return true;
  9152. }
  9153. // ANIMATED TEXT WHEN ADVANCE
  9154. void Game::sendAnimatedTextExt(const Position pos,int32_t aniColor,const std::string &text)
  9155. {
  9156. SpectatorVec list;
  9157. SpectatorVec::iterator it;
  9158. getSpectators(Range(pos), list);
  9159. for(it = list.begin(); it != list.end(); ++it){
  9160. Player* spec = dynamic_cast<Player*>(*it);
  9161. if(spec)
  9162. spec->sendAnimatedText(pos, aniColor, text);
  9163. }
  9164. }
  9165. // CREATUREBYPOSITION
  9166. Creature* Game::getCreatureByPosition(int32_t x, int32_t y, int32_t z)
  9167. {
  9168. for(AutoList<Creature>::listiterator it = listCreature.list.begin(); it != listCreature.list.end(); ++it){
  9169. if(it->second->pos.x == x && it->second->pos.y == y && it->second->pos.z == z)
  9170. return it->second;
  9171. }
  9172.  
  9173. return NULL;
  9174. }
  9175. // CREATE CONDITION
  9176. 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)
  9177. {
  9178. uint32_t targetID;
  9179. if(target)
  9180. targetID = target->getID();
  9181. else
  9182. targetID = 0;
  9183.  
  9184. MagicEffectTargetCreatureCondition magicCondition = MagicEffectTargetCreatureCondition(targetID);
  9185. magicCondition.animationColor = animationColor;
  9186. magicCondition.damageEffect = damageEffect;
  9187. magicCondition.hitEffect = hitEffect;
  9188. magicCondition.attackType = attackType;
  9189. magicCondition.maxDamage = maxDamage;
  9190. magicCondition.minDamage = minDamage;
  9191. magicCondition.offensive = offensive;
  9192. CreatureCondition condition = CreatureCondition(ticks, count, magicCondition);
  9193. creature->addCondition(condition, true);
  9194.  
  9195. Player *player = dynamic_cast<Player*>(creature);
  9196. if(player)
  9197. player->sendIcons();
  9198. }
  9199. // Fields loaded from map - The Chaos
  9200. void Game::doFieldDamage(Creature* creature, unsigned char animationColor, unsigned char damageEffect,
  9201. unsigned char hitEffect, attacktype_t attackType, bool offensive, int32_t damage)
  9202. {
  9203. MagicEffectClass cd;
  9204. cd.animationColor = animationColor;
  9205. cd.damageEffect = damageEffect;
  9206. cd.hitEffect = hitEffect;
  9207. cd.attackType = attackType;
  9208. cd.offensive = offensive;
  9209. Player* itsHim = dynamic_cast<Player*>(getCreatureByID(creature->getID()));
  9210. if(itsHim){ //Since that was causing damage/2 against player, here its my solution =)
  9211. cd.maxDamage = damage*2;
  9212. cd.minDamage = damage*2;
  9213. }
  9214. else{
  9215. cd.maxDamage = damage;
  9216. cd.minDamage = damage;
  9217. }
  9218. creatureMakeMagic(NULL, creature->pos, &cd);
  9219. }
  9220. void Game::updateTile(const Position& pos)
  9221. {
  9222. SpectatorVec list;
  9223. SpectatorVec::iterator i;
  9224. getSpectators(Range(pos), list);
  9225. for(i = list.begin(); i != list.end(); ++i)
  9226. (*i)->onTileUpdated(pos);
  9227. }
  9228.  
  9229. void Game::banPlayer(Player *player, std::string reason, std::string action, std::string comment, bool IPban)
  9230. {
  9231. int32_t bantime = 0;
  9232.  
  9233. if(player){
  9234.  
  9235. if(comment=="deletion")
  9236. player->deleted = 1; // make player deleted
  9237. else
  9238. bantime = atoi(comment.c_str()) * 86400; // else make players banned for "comment" days (86400 = 1 day)
  9239.  
  9240. if(player->finalwarning == 1 || player->times == 4)
  9241. player->deleted = 1; // if player was already warned let delete thy char
  9242.  
  9243. if(action=="AccountBan+FinalWarning" || player->times == 3)
  9244. player->finalwarning = 1; // if player has warned set variable
  9245.  
  9246. if(reason=="Excessive unjustifed player killing")
  9247. bantime = g_config.getGlobalNumber("pkbandays",3) * 86400; // baannnnn pekaayssss (from config.lua)
  9248.  
  9249. player->banned = 1;
  9250. player->times++;
  9251. player->comment = comment;
  9252. player->reason = reason;
  9253. player->action = action;
  9254. player->banstart = std::time(NULL);
  9255. player->banend = player->banstart + bantime;
  9256. time_t endBan = player->banend;
  9257. player->banrealtime = ctime(&endBan); // this variable stores REAL ban date in string, so you wont see 11105220952 in accmaker ;)
  9258. if(IPban){
  9259. std::pair<uint32_t, uint32_t> IpNetMask;
  9260. IpNetMask.first = player->lastip;
  9261. IpNetMask.second = 0xFFFFFFFF;
  9262. if(IpNetMask.first > 0)
  9263. bannedIPs.push_back(IpNetMask);
  9264. }
  9265. std::stringstream ban;
  9266. ban << "You just have been banned for " << reason << "!";
  9267. player->sendTextMessage(MSG_INFO, ban.str().c_str());
  9268. player->kickPlayer();
  9269. }
  9270. }
  9271.  
  9272. #ifdef REX_MUTED
  9273.  
  9274. #endif //REX_MUTED
  9275. #ifdef HUCZU_FIX
  9276. bool Game::loadCities(Player* player, std::string name)
  9277. {
  9278. xmlDocPtr doc;
  9279. std::string file = "data/miasta.xml";
  9280. doc = xmlParseFile(file.c_str());
  9281. if(doc){
  9282. xmlNodePtr root, miasto;
  9283. root = xmlDocGetRootElement(doc);
  9284. if(xmlStrcmp(root->name, (const xmlChar*)"miasta")) {
  9285. xmlFreeDoc(doc);
  9286. return -1;
  9287. }
  9288. miasto = root->children;
  9289. while(miasto){
  9290. if(strcmp((char*) miasto->name, "miasto")==0){
  9291.  
  9292. std::string nameIN = (const char*)xmlGetProp(miasto, (const xmlChar *) "nazwa");
  9293. int32_t x = atoi((const char*)xmlGetProp(miasto, (const xmlChar *) "x"));
  9294. int32_t y = atoi((const char*)xmlGetProp(miasto, (const xmlChar *) "y"));
  9295. int32_t z = atoi((const char*)xmlGetProp(miasto, (const xmlChar *) "z"));
  9296. Position pos(x,y,z);
  9297. if(nameIN == name)
  9298. teleport(player,pos);
  9299. }
  9300. miasto = miasto->next;
  9301. }
  9302. xmlFreeDoc(doc);
  9303. return 0;
  9304. }
  9305. return -1;
  9306. }
  9307. #endif //HUCZU_FIX
  9308. // RAID SYSTEM
  9309. bool Game::loadRaid(std::string name)
  9310. {
  9311. xmlDocPtr doc;
  9312. std::cout << "Executing raid named " << name << "." << std::endl;
  9313. std::string file = "data/world/raids.xml";
  9314. doc = xmlParseFile(file.c_str());
  9315. if(doc){
  9316. xmlNodePtr root, raid, command;
  9317. root = xmlDocGetRootElement(doc);
  9318. if(xmlStrcmp(root->name, (const xmlChar*)"raids")) {
  9319. xmlFreeDoc(doc);
  9320. return -1;
  9321. }
  9322. raid = root->children;
  9323. while(raid){
  9324. if(strcmp((char*) raid->name, "raid")==0){
  9325.  
  9326. std::string nameIN = (const char*)xmlGetProp(raid, (const xmlChar *) "name");
  9327. if(nameIN == name) {
  9328. std::string messageIN = (const char*)xmlGetProp(raid, (const xmlChar *) "message");
  9329. std::string brodcasterIN = (const char*)xmlGetProp(raid, (const xmlChar *) "brodcaster");
  9330.  
  9331. Creature *c = getCreatureByName(brodcasterIN);
  9332. if(c) {
  9333. creatureBroadcastMessage(c,messageIN);
  9334. } else {
  9335. std::cout << "Could not send news msg! Brodcaster does not exist" << std::endl;
  9336. }
  9337.  
  9338. if(nameIN == name) {
  9339. command = raid->children;
  9340.  
  9341. while(command) {
  9342.  
  9343. if(strcmp((char*) command->name, "monster")==0){
  9344. std::string monstername = (const char*)xmlGetProp(command, (const xmlChar *) "name");
  9345. int32_t x = atoi((const char*)xmlGetProp(command, (const xmlChar *) "x"));
  9346. int32_t y = atoi((const char*)xmlGetProp(command, (const xmlChar *) "y"));
  9347. int32_t z = atoi((const char*)xmlGetProp(command, (const xmlChar *) "z"));
  9348.  
  9349. int32_t loot = atoi((const char*)xmlGetProp(command, (const xmlChar *) "lootid")); //Not yet implemented!
  9350. int32_t chance = atoi((const char*)xmlGetProp(command, (const xmlChar *) "chance")); //Not yet implemented!
  9351. placeRaidMonster(monstername, x, y, z);
  9352. }
  9353.  
  9354. if(strcmp((char*) command->name, "area")==0){
  9355. std::string monstername = (const char*)xmlGetProp(command, (const xmlChar *) "monster");
  9356. int32_t count = atoi((const char*)xmlGetProp(command, (const xmlChar *) "count"));
  9357. int32_t xf = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posxfrom"));
  9358. int32_t yf = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posyfrom"));
  9359. int32_t zf = atoi((const char*)xmlGetProp(command, (const xmlChar *) "poszfrom"));
  9360.  
  9361. int32_t xt = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posxto"));
  9362. int32_t yt = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posyto"));
  9363. int32_t zt = atoi((const char*)xmlGetProp(command, (const xmlChar *) "poszto"));
  9364.  
  9365. int32_t i = 0;
  9366. int32_t tries = 0;
  9367. while (i<=count && tries<=(count*10)) {
  9368. int32_t x = (int32_t)((xt-xf) * (rand()/(RAND_MAX+1.0)) + xf);
  9369. int32_t y = (int32_t)((yt-yf) * (rand()/(RAND_MAX+1.0)) + yf);
  9370. int32_t z = (int32_t)((zt-zf) * (rand()/(RAND_MAX+1.0)) + zf);
  9371. Tile* t = map->getTile(x,y,z);
  9372. if(t && t->isPz() == false) {
  9373. placeRaidMonster(monstername, x, y, z);
  9374. i++;
  9375. }
  9376. tries++;
  9377. }
  9378. }
  9379. if(strcmp((char*) command->name, "message")==0){
  9380. std::string msg = (const char*)xmlGetProp(command, (const xmlChar *) "text");
  9381. std::string brodcaster = (const char*)xmlGetProp(command, (const xmlChar *) "brodcaster");
  9382. Creature *c = getCreatureByName(brodcaster);
  9383. if(c) {
  9384. creatureBroadcastMessage(c,msg);
  9385. } else {
  9386. std::cout << "Could not send news msg! Brodcaster does not exist." << std::endl;
  9387. }
  9388. }
  9389. command = command->next;
  9390. }
  9391. }
  9392. }
  9393. }
  9394. raid = raid->next;
  9395. }
  9396. xmlFreeDoc(doc);
  9397. return 0;
  9398. }
  9399. return -1;
  9400. }
  9401. bool Game::placeRaidMonster(std::string name, int32_t x, int32_t y, int32_t z)
  9402. {
  9403. Monster* monster = Monster::createMonster(name, this);
  9404. //For new CVS use the following line:
  9405. //Monster* monster = Monster::createMonster(name, this);
  9406. if(!monster){
  9407. delete monster;
  9408. return false;
  9409. }
  9410. Position pos;
  9411. pos.x = x;
  9412. pos.y = y;
  9413. pos.z = z;
  9414.  
  9415. // Place the monster
  9416. if(!placeCreature(pos, monster)) {
  9417. delete monster;
  9418. return false;
  9419. }
  9420.  
  9421. return true;
  9422. }
  9423.  
  9424. void Game::spectatorText(Position pos, unsigned char color, std::string text)
  9425. {
  9426. SpectatorVec list;
  9427. SpectatorVec::iterator it;
  9428. getSpectators(Range(pos, true), list);
  9429.  
  9430. for(it = list.begin(); it != list.end(); ++it) {
  9431. if(Player* p = dynamic_cast<Player*>(*it)) {
  9432. p->sendAnimatedText(pos, color, text);
  9433. }
  9434. }
  9435. }
  9436.  
  9437. #ifdef DT_PREMMY
  9438. bool Game::countPremmy(Player *player)
  9439. {
  9440. Account acc = IOAccount::instance()->loadAccount(player->accountNumber);
  9441. int32_t cont;
  9442. if(acc.lastsaveday == 0)
  9443. cont = 0;
  9444. else
  9445. cont = acc.lastsaveday2 - acc.lastsaveday;
  9446. //std::cout << "Last Login in Acc: " << acc.lastsaveday << " - Today: " << acc.lastsaveday2 << " - Days removed from acc: " << cont << std::endl;
  9447. if(cont < 0){
  9448. cont =+ 365; //dodajemy caly rok
  9449. }
  9450. if((acc.premDays - cont) <= 0)
  9451. {
  9452. acc.premDays = 0;
  9453. player->premmium = false;
  9454. }
  9455. else
  9456. {
  9457. acc.premDays = acc.premDays - cont;
  9458. player->premmium = true;
  9459. }
  9460. if(g_config.FREE_PREMMY)
  9461. player->premmium = true;
  9462.  
  9463. IOAccount::instance()->saveAccount(acc);
  9464.  
  9465. }
  9466.  
  9467. #endif //DT_PREMMY
  9468.  
  9469.  
  9470. #ifdef ZS_SWORDS
  9471. void Game::useSword(Creature *creature, Creature *attackedCreature, int32_t swordid)
  9472. {
  9473. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::useSword()");
  9474.  
  9475. Player *player = dynamic_cast<Player*>(creature);
  9476. if(!player || !attackedCreature || player->pos.z != attackedCreature->pos.z)
  9477. return;
  9478.  
  9479. int32_t dist, mana = 0;
  9480. MagicEffectAreaNoExhaustionClass runeAreaSpell;
  9481. runeAreaSpell.drawblood = true;
  9482. runeAreaSpell.offensive = true;
  9483. runeAreaSpell.direction = 1;
  9484.  
  9485.  
  9486. // P O I S O N //
  9487.  
  9488. if (swordid == ITEM_P_MB && player->vocation == VOCATION_KNIGHT &&
  9489. player->mana >= g_config.MANA_P_MB && player->getLevel() >= 220)
  9490. {
  9491. dist = g_config.RANGE_P_MB;
  9492. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9493. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9494. return;
  9495.  
  9496. runeAreaSpell.attackType = ATTACK_SWORD;
  9497. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  9498. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  9499. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  9500. runeAreaSpell.animationColor = 0x60;
  9501.  
  9502. runeAreaSpell.minDamage = 10;
  9503. runeAreaSpell.maxDamage = 60;
  9504. mana = g_config.MANA_P_MB;
  9505. }
  9506.  
  9507. else if (swordid == ITEM_P_MAUL && player->vocation == VOCATION_KNIGHT &&
  9508. player->mana >= g_config.MANA_P_MAUL && player->getLevel() >= 220)
  9509. {
  9510. dist = g_config.RANGE_P_MAUL;
  9511. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9512. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9513. return;
  9514.  
  9515. runeAreaSpell.attackType = ATTACK_SWORD;
  9516. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  9517. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  9518. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  9519. runeAreaSpell.animationColor = 0x60;
  9520.  
  9521. runeAreaSpell.minDamage = 10;
  9522. runeAreaSpell.maxDamage = 60;
  9523. mana = g_config.MANA_P_MAUL;
  9524. }
  9525.  
  9526. else if (swordid == ITEM_P_HEAD && player->vocation == VOCATION_KNIGHT &&
  9527. player->mana >= g_config.MANA_P_HEAD && player->getLevel() >= 220)
  9528. {
  9529. dist = g_config.RANGE_P_HEAD;
  9530. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9531. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9532. return;
  9533.  
  9534. runeAreaSpell.attackType = ATTACK_SWORD;
  9535. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  9536. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  9537. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  9538. runeAreaSpell.animationColor = 0x60;
  9539.  
  9540. runeAreaSpell.minDamage = 10;
  9541. runeAreaSpell.maxDamage = 60;
  9542. mana = g_config.MANA_P_HEAD;
  9543. }
  9544.  
  9545. // F I R E //
  9546.  
  9547. else if (swordid == ITEM_F_MB && player->vocation == VOCATION_KNIGHT &&
  9548. player->mana >= g_config.MANA_F_MB && player->getLevel() >= 320)
  9549. {
  9550. dist = g_config.RANGE_F_MB;
  9551. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9552. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9553. return;
  9554.  
  9555. runeAreaSpell.attackType = ATTACK_SWORD;
  9556. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  9557. runeAreaSpell.hitEffect = NM_ME_EXPLOSION_AREA;
  9558. runeAreaSpell.areaEffect = NM_ME_EXPLOSION_AREA;
  9559. runeAreaSpell.animationColor = 0xC6;
  9560.  
  9561. runeAreaSpell.minDamage = 60;
  9562. runeAreaSpell.maxDamage = 110;
  9563. mana = g_config.MANA_F_MB;
  9564. }
  9565.  
  9566. else if (swordid == ITEM_F_MAUL && player->vocation == VOCATION_KNIGHT &&
  9567. player->mana >= g_config.MANA_F_MAUL && player->getLevel() >= 320)
  9568. {
  9569. dist = g_config.RANGE_F_MAUL;
  9570. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9571. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9572. return;
  9573.  
  9574. runeAreaSpell.attackType = ATTACK_SWORD;
  9575. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  9576. runeAreaSpell.hitEffect = NM_ME_EXPLOSION_AREA;
  9577. runeAreaSpell.areaEffect = NM_ME_EXPLOSION_AREA;
  9578. runeAreaSpell.animationColor = 0xC6;
  9579.  
  9580. runeAreaSpell.minDamage = 60;
  9581. runeAreaSpell.maxDamage = 110;
  9582. mana = g_config.MANA_F_MAUL;
  9583. }
  9584.  
  9585. else if (swordid == ITEM_F_HEAD && player->vocation == VOCATION_KNIGHT &&
  9586. player->mana >= g_config.MANA_F_HEAD && player->getLevel() >= 320)
  9587. {
  9588. dist = g_config.RANGE_F_HEAD;
  9589. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9590. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9591. return;
  9592.  
  9593. runeAreaSpell.attackType = ATTACK_SWORD;
  9594. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  9595. runeAreaSpell.hitEffect = NM_ME_EXPLOSION_AREA;
  9596. runeAreaSpell.areaEffect = NM_ME_EXPLOSION_AREA;
  9597. runeAreaSpell.animationColor = 0xC6;
  9598.  
  9599. runeAreaSpell.minDamage = 60;
  9600. runeAreaSpell.maxDamage = 110;
  9601. mana = g_config.MANA_F_HEAD;
  9602. }
  9603.  
  9604. // E N E R G Y //
  9605.  
  9606. else if (swordid == ITEM_E_MB && player->vocation == VOCATION_KNIGHT &&
  9607. player->mana >= g_config.MANA_E_MB && player->getLevel() >= 420)
  9608. {
  9609. dist = g_config.RANGE_E_MB;
  9610. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9611. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9612. return;
  9613.  
  9614. runeAreaSpell.attackType = ATTACK_SWORD;
  9615. runeAreaSpell.animationEffect = NM_ANI_SUDDENDEATH;
  9616. runeAreaSpell.hitEffect = NM_ME_MORT_AREA;
  9617. runeAreaSpell.areaEffect = NM_ME_MORT_AREA;
  9618. runeAreaSpell.animationColor = 0xB9;
  9619.  
  9620. runeAreaSpell.minDamage = 110;
  9621. runeAreaSpell.maxDamage = 160;
  9622. mana = g_config.MANA_E_MB;
  9623. }
  9624.  
  9625. else if (swordid == ITEM_E_MAUL && player->vocation == VOCATION_KNIGHT &&
  9626. player->mana >= g_config.MANA_E_MAUL && player->getLevel() >= 420)
  9627. {
  9628. dist = g_config.RANGE_E_MAUL;
  9629. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9630. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9631. return;
  9632.  
  9633. runeAreaSpell.attackType = ATTACK_SWORD;
  9634. runeAreaSpell.animationEffect = NM_ANI_SUDDENDEATH;
  9635. runeAreaSpell.hitEffect = NM_ME_MORT_AREA;
  9636. runeAreaSpell.areaEffect = NM_ME_MORT_AREA;
  9637. runeAreaSpell.animationColor = 0xB9;
  9638.  
  9639. runeAreaSpell.minDamage = 110;
  9640. runeAreaSpell.maxDamage = 160;
  9641. mana = g_config.MANA_E_MAUL;
  9642. }
  9643.  
  9644. else if (swordid == ITEM_E_HEAD && player->vocation == VOCATION_KNIGHT &&
  9645. player->mana >= g_config.MANA_E_HEAD && player->getLevel() >= 420)
  9646. {
  9647. dist = g_config.RANGE_E_HEAD;
  9648. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9649. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9650. return;
  9651.  
  9652. runeAreaSpell.attackType = ATTACK_SWORD;
  9653. runeAreaSpell.animationEffect = NM_ANI_SUDDENDEATH;
  9654. runeAreaSpell.hitEffect = NM_ME_MORT_AREA;
  9655. runeAreaSpell.areaEffect = NM_ME_MORT_AREA;
  9656. runeAreaSpell.animationColor = 0xB9;
  9657.  
  9658. runeAreaSpell.minDamage = 110;
  9659. runeAreaSpell.maxDamage = 160;
  9660. mana = g_config.MANA_E_HEAD;
  9661. }
  9662.  
  9663. // P L A Y E R W E A P O N S //
  9664.  
  9665. else if (swordid == ITEM_HAIK_AXE && player->vocation == VOCATION_KNIGHT &&
  9666. player->mana >= g_config.MANA_HAIK_AXE && player->getLevel() >= 500)
  9667. {
  9668. dist = g_config.RANGE_HAIK_AXE;
  9669. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9670. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9671. return;
  9672.  
  9673. runeAreaSpell.attackType = ATTACK_SWORD;
  9674. runeAreaSpell.animationEffect = NM_ANI_STAR;
  9675. runeAreaSpell.hitEffect = NM_ME_STAR;
  9676. runeAreaSpell.areaEffect = NM_ME_STAR;
  9677. runeAreaSpell.animationColor = 0xD2;
  9678.  
  9679. runeAreaSpell.minDamage = 300;
  9680. runeAreaSpell.maxDamage = 350;
  9681. mana = g_config.MANA_HAIK_AXE;
  9682. }
  9683.  
  9684. else if (swordid == ITEM_BLETKA_AXE && player->vocation == VOCATION_KNIGHT &&
  9685. player->mana >= g_config.MANA_BLETKA_AXE)
  9686. {
  9687. dist = g_config.RANGE_BLETKA_AXE;
  9688. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9689. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9690. return;
  9691.  
  9692. runeAreaSpell.attackType = ATTACK_SWORD;
  9693. runeAreaSpell.animationEffect = NM_ANI_STAR;
  9694. runeAreaSpell.hitEffect = NM_ME_STAR;
  9695. runeAreaSpell.areaEffect = NM_ME_STAR;
  9696. runeAreaSpell.animationColor = 0xD2;
  9697.  
  9698. runeAreaSpell.minDamage = 150;
  9699. runeAreaSpell.maxDamage = 200;
  9700. mana = g_config.MANA_BLETKA_AXE;
  9701. }
  9702.  
  9703. // K U N I E C //
  9704.  
  9705. if (mana > 0)
  9706. {
  9707. std::vector<unsigned char> col;
  9708.  
  9709. col.push_back(0);
  9710. col.push_back(0);
  9711. col.push_back(0);
  9712. runeAreaSpell.areaVec.push_back(col);
  9713. col.clear();
  9714. col.push_back(0);
  9715. col.push_back(1);
  9716. col.push_back(0);
  9717. runeAreaSpell.areaVec.push_back(col);
  9718. col.clear();
  9719. col.push_back(0);
  9720. col.push_back(0);
  9721. col.push_back(0);
  9722. runeAreaSpell.areaVec.push_back(col);
  9723.  
  9724. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  9725. player->addManaSpent(mana);
  9726. player->mana -= mana;
  9727. }
  9728. }
  9729. #endif //ZS_SWORDS
  9730.  
  9731. #ifdef YUR_READABLES
  9732. bool Game::LoadReadables()
  9733. {
  9734. std::string file = g_config.getGlobalString("datadir") + "readables.xml";
  9735. xmlDocPtr doc;
  9736. xmlMutexLock(xmlmutex);
  9737.  
  9738. doc = xmlParseFile(file.c_str());
  9739. if (!doc)
  9740. return false;
  9741.  
  9742. xmlNodePtr root, readableNode;
  9743. root = xmlDocGetRootElement(doc);
  9744. if (xmlStrcmp(root->name, (const xmlChar*)"readables"))
  9745. {
  9746. xmlFreeDoc(doc);
  9747. xmlMutexUnlock(xmlmutex);
  9748. return false;
  9749. }
  9750.  
  9751. readableNode = root->children;
  9752. while (readableNode)
  9753. {
  9754. if (strcmp((char*) readableNode->name, "readable") == 0)
  9755. {
  9756. int32_t x = atoi((const char*)xmlGetProp(readableNode, (const xmlChar *) "x"));
  9757. int32_t y = atoi((const char*)xmlGetProp(readableNode, (const xmlChar *) "y"));
  9758. int32_t z = atoi((const char*)xmlGetProp(readableNode, (const xmlChar *) "z"));
  9759. std::string text = (const char*)xmlGetProp(readableNode, (const xmlChar *) "text");
  9760.  
  9761. for (size_t i = 0; i < text.length()-1; i++) // make real newlines
  9762. if (text.at(i) == '\\' && text.at(i+1) == 'n')
  9763. {
  9764. text[i] = ' ';
  9765. text[i+1] = '\n';
  9766. }
  9767.  
  9768. Tile* tile = getTile(x, y, z);
  9769. if (tile)
  9770. {
  9771. Thing* thing = tile->getTopThing();
  9772. Item* item = thing? dynamic_cast<Item*>(thing) : NULL;
  9773.  
  9774. if (item)
  9775. item->setReadable(text);
  9776. else
  9777. {
  9778. std::cout << "\nTop thing at " << Position(x,y,z) << " is not an item!";
  9779. return false;
  9780. }
  9781. }
  9782. else
  9783. {
  9784. std::cout << "\nTile " << Position(x,y,z) << " is not valid!";
  9785. return false;
  9786. }
  9787. }
  9788. readableNode = readableNode->next;
  9789. }
  9790.  
  9791. xmlFreeDoc(doc);
  9792. xmlMutexUnlock(xmlmutex);
  9793. return true;
  9794. }
  9795. #endif //YUR_READABLES
  9796.  
  9797. void Game::Blasting(Creature* c, Creature *attackedCreature, const Position& pos)
  9798. {
  9799. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::Blasting()");
  9800. Player* player = dynamic_cast<Player*>(c);
  9801. unsigned short dist = 6;
  9802. unsigned short REQ_MANA = 200;
  9803. uint32_t poziom = player->level;
  9804. uint32_t magpoziom = player->maglevel;
  9805.  
  9806. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9807. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9808. return;
  9809.  
  9810. MagicEffectAreaNoExhaustionClass runeAreaSpell;
  9811. runeAreaSpell.drawblood = true;
  9812. runeAreaSpell.offensive = true;
  9813. runeAreaSpell.direction = 1;
  9814. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  9815. runeAreaSpell.animationEffect = NM_ANI_REMOTE;
  9816. runeAreaSpell.hitEffect = NM_ME_EXPLO;
  9817. runeAreaSpell.areaEffect = NM_ME_EXPLO;
  9818. runeAreaSpell.animationColor = 0x60;
  9819.  
  9820. if((poziom * 2 + magpoziom * 3) >= 100){
  9821. runeAreaSpell.minDamage = int32_t((poziom * 2 + magpoziom * 3) * 1.6 );
  9822. runeAreaSpell.maxDamage = int32_t((poziom * 2 + magpoziom * 3) * 1.9 );
  9823. }else{
  9824. runeAreaSpell.minDamage = int32_t(100 * 1.5 );
  9825. runeAreaSpell.maxDamage = int32_t(100 * 1.8 );
  9826. }
  9827.  
  9828. std::vector<unsigned char> col;
  9829. col.push_back(0);
  9830. col.push_back(0);
  9831. col.push_back(0);
  9832. runeAreaSpell.areaVec.push_back(col);
  9833. col.clear();
  9834. col.push_back(0);
  9835. col.push_back(1);
  9836. col.push_back(0);
  9837. runeAreaSpell.areaVec.push_back(col);
  9838. col.clear();
  9839. col.push_back(0);
  9840. col.push_back(0);
  9841. col.push_back(0);
  9842. runeAreaSpell.areaVec.push_back(col);
  9843.  
  9844. creatureThrowRune(c, pos, runeAreaSpell);
  9845. player->flamTicks = 2*1000;
  9846. if (player->access < g_config.ACCESS_PROTECT)
  9847. {
  9848. player->mana -= REQ_MANA;
  9849. player->addManaSpent(REQ_MANA);
  9850. }
  9851. }
  9852. #ifdef KOSZ
  9853. bool Game::canDelete(Player *player, unsigned short itemid, Position toPos, Position fromPos, int32_t from_stack, unsigned char count)
  9854. {
  9855. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::canDelete()");
  9856.  
  9857. if(itemid == 99 || (itemid >= 4329 && itemid <= 4555))
  9858. return false;
  9859. else if(fromPos.x != 0xFFFF && ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  9860. return false;
  9861. else if(map->canThrowObjectTo(player->pos, toPos, BLOCK_PROJECTILE) != RET_NOERROR)
  9862. return false;
  9863. else if(toPos.x == 0xFFFF)
  9864. return false;
  9865. else if((player->access < g_config.ACCESS_REMOTE) &&
  9866. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  9867. return false;
  9868.  
  9869. Item* trash = dynamic_cast<Item*>(getThing(fromPos, from_stack, player));
  9870. if(trash){
  9871. trash->pos = fromPos;
  9872. if((abs(player->pos.x - toPos.x) > trash->throwRange) || (abs(player->pos.y - toPos.y) > trash->throwRange)) {
  9873. return false;
  9874. }
  9875.  
  9876. Tile *toTile = map->getTile(toPos);
  9877. if(toTile){
  9878. 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)){
  9879. if(!trash->isNotMoveable() && trash->isBlocking())
  9880. return false;
  9881. else if(trashObjects(player, toTile, trash, toPos, fromPos, from_stack, count))
  9882. return true;
  9883. }
  9884. Item *toItem = dynamic_cast<Item*>(toTile->getTopTopItem());
  9885.  
  9886. if(toItem && toItem->getID() == ITEM_DUSTBIN){
  9887. if(!trash->isNotMoveable() && trash->isBlocking())
  9888. return false;
  9889. else if(trashObjects(player, toTile, trash, toPos, fromPos, from_stack, count))
  9890. return true;
  9891. }
  9892. }
  9893. }
  9894.  
  9895. return false;
  9896. }
  9897.  
  9898. bool Game::trashObjects(Player *player, Tile *toTile, Item *trash, Position toPos, Position fromPos, int32_t from_stack, unsigned char count)
  9899. {
  9900. //OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::trashObjects()");
  9901.  
  9902. if(!player || !toTile || !trash || !from_stack || !count){
  9903. return false;}
  9904.  
  9905. if(toTile){
  9906. switch(toTile->ground->getID()){
  9907. case GROUND_WATER1:
  9908. case GROUND_WATER2:
  9909. case GROUND_WATER3:
  9910. case GROUND_WATER4:
  9911. case GROUND_WATER5:
  9912. case GROUND_WATER6:
  9913. case GROUND_WATER7:
  9914. case GROUND_WATER8:
  9915. case GROUND_WATER9:
  9916. case GROUND_WATER10:
  9917. case GROUND_WATER11:
  9918. case GROUND_WATER12:
  9919. case GROUND_WATER13:
  9920. case GROUND_WATER14:
  9921. case GROUND_WATER15:
  9922. case GROUND_WATER16:
  9923. case GROUND_WATER17:
  9924. case GROUND_WATER18:
  9925. case GROUND_WATER19:
  9926. case GROUND_WATER20:
  9927. case GROUND_WATER21:
  9928. case GROUND_WATER22:
  9929. case GROUND_WATER23:
  9930. case GROUND_WATER24:
  9931. case GROUND_WATER25:
  9932. case GROUND_WATER26:
  9933. case GROUND_WATER27:
  9934. case GROUND_WATER28:
  9935. case GROUND_WATER29:
  9936. case GROUND_WATER30:
  9937. case GROUND_WATER31:
  9938. case GROUND_WATER32:
  9939. case GROUND_WATER33:
  9940. case GROUND_WATER34:
  9941. case GROUND_WATER35:
  9942. case GROUND_WATER36:
  9943. case GROUND_WATER37:
  9944. case GROUND_WATER38:
  9945. case GROUND_WATER39:
  9946. case GROUND_WATER40:
  9947. case GROUND_WATER41:
  9948. case GROUND_WATER42:
  9949. case GROUND_WATER43:
  9950. case GROUND_WATER44:
  9951. spectatorEffect(toPos, NM_ME_LOOSE_ENERGY);
  9952. if(trashItems(player, trash, fromPos, from_stack, count))
  9953. return true;
  9954. break;
  9955. case GROUND_LAVA1:
  9956. case GROUND_LAVA2:
  9957. case GROUND_LAVA3:
  9958. case GROUND_LAVA4:
  9959. spectatorEffect(toPos, NM_ME_HITBY_FIRE);
  9960. if(trashItems(player, trash, fromPos, from_stack, count))
  9961. return true;
  9962. break;
  9963. case GROUND_SWAMP1:
  9964. case GROUND_SWAMP2:
  9965. case GROUND_SWAMP3:
  9966. case GROUND_SWAMP4:
  9967. spectatorEffect(toPos, NM_ME_POISEN_RINGS);
  9968. if(trashItems(player, trash, fromPos, from_stack, count))
  9969. return true;
  9970. break;
  9971. case GROUND_BLACK_SWAMP1:
  9972. case GROUND_BLACK_SWAMP2:
  9973. case GROUND_BLACK_SWAMP3:
  9974. case GROUND_BLACK_SWAMP4:
  9975. spectatorEffect(toPos, NM_ME_MORT_AREA);
  9976. if(trashItems(player, trash, fromPos, from_stack, count))
  9977. return true;
  9978. break;
  9979. }
  9980. }
  9981.  
  9982. return false;
  9983. }
  9984.  
  9985. bool Game::trashItems(Player *player, Item *trash, Position fromPos, int32_t from_stack, unsigned char count)
  9986. {
  9987. //OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::trashItems()");
  9988. if(!trash){return false;}
  9989. if(trash->getID() == 99 || (trash->getID() >= 4329 && trash->getID() <= 4555))
  9990. return false;
  9991. else if(fromPos.x != 0xFFFF && ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  9992. return false;
  9993. else if((player->access < g_config.ACCESS_REMOTE) &&
  9994. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  9995. return false;
  9996.  
  9997. if(trash && player){
  9998. if(trash->isStackable()){
  9999. if(trash->getItemCountOrSubtype() > count){
  10000. trash->setItemCountOrSubtype(trash->getItemCountOrSubtype() - count);
  10001. sendUpdateThing(player,fromPos,trash,from_stack);
  10002. player->updateInventoryWeigth();
  10003. return true;
  10004. }
  10005. else{
  10006. if(removeThing(player, fromPos, trash)){
  10007. player->updateInventoryWeigth();
  10008. return true;
  10009. }
  10010. }
  10011. }
  10012. else{
  10013. if(removeThing(player, fromPos, trash)){
  10014. player->updateInventoryWeigth();
  10015. return true;
  10016. }
  10017. }
  10018. }
  10019. return false;
  10020. }
  10021.  
  10022. bool Game::canTeleportItem(Player *player, unsigned short itemid, Position toPos, Position fromPos, int32_t from_stack, unsigned char count)
  10023. {
  10024. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::canTeleportItem()");
  10025.  
  10026. if(itemid == 99 || (itemid >= 4329 && itemid <= 4555))
  10027. return false;
  10028. else if(fromPos.x != 0xFFFF && ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  10029. return false;
  10030. else if(map->canThrowObjectTo(player->pos, toPos, BLOCK_PROJECTILE) != RET_NOERROR)
  10031. return false;
  10032. else if(toPos.x == 0xFFFF)
  10033. return false;
  10034. else if(!checkChangeFloor(map->getTile(toPos), getTile(toPos.x,toPos.y,toPos.z+1)))
  10035. return false;
  10036. else if((player->access < g_config.ACCESS_REMOTE) &&
  10037. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  10038. return false;
  10039.  
  10040. Item* tpItem = dynamic_cast<Item*>(getThing(fromPos, from_stack, player));
  10041. if(tpItem){
  10042. tpItem->pos = fromPos;
  10043. if((abs(player->pos.x - toPos.x) > tpItem->throwRange) || (abs(player->pos.y - toPos.y) > tpItem->throwRange)) {
  10044. return false;
  10045. }
  10046.  
  10047. if(tpItem->isStackable()){
  10048. if(tpItem->getItemCountOrSubtype() > count){
  10049. tpItem->setItemCountOrSubtype(tpItem->getItemCountOrSubtype() - count);
  10050. Item *newitem = Item::CreateItem(tpItem->getID(), count);
  10051. addThing(player,getTeleportPos(toPos),newitem);
  10052. sendUpdateThing(player,fromPos,tpItem,from_stack);
  10053. player->updateInventoryWeigth();
  10054. return true;
  10055. }
  10056. else{
  10057. if(removeThing(player, fromPos, tpItem)){
  10058. addThing(player,getTeleportPos(toPos),tpItem);
  10059. player->updateInventoryWeigth();
  10060. return true;
  10061. }
  10062. }
  10063. }
  10064. else{
  10065. if(removeThing(player, fromPos, tpItem)){
  10066. addThing(player,getTeleportPos(toPos),tpItem);
  10067. player->updateInventoryWeigth();
  10068. return true;
  10069. }
  10070. }
  10071. }
  10072. return false;
  10073. }
  10074.  
  10075. void Game::spectatorEffect(Position pos, unsigned char type)
  10076. {
  10077. SpectatorVec list;
  10078. SpectatorVec::iterator it;
  10079. getSpectators(Range(pos, true), list);
  10080.  
  10081. for(it = list.begin(); it != list.end(); ++it) {
  10082. if(Player* p = dynamic_cast<Player*>(*it)) {
  10083. p->sendMagicEffect(pos, type);
  10084. }
  10085. }
  10086. }
  10087.  
  10088. bool Game::checkChangeFloor(Tile *toTile, Tile* downTile)
  10089. {
  10090. if(toTile->ground && toTile->ground->floorChangeDown())
  10091. {
  10092. if(downTile){
  10093. if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  10094. return true;
  10095. }
  10096. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  10097. return true;
  10098. }
  10099. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  10100. return true;
  10101. }
  10102. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  10103. return true;
  10104. }
  10105. else if(downTile->floorChange(NORTH)){
  10106. return true;
  10107. }
  10108. else if(downTile->floorChange(SOUTH)){
  10109. return true;
  10110. }
  10111. else if(downTile->floorChange(EAST)){
  10112. return true;
  10113. }
  10114. else if(downTile->floorChange(WEST)){
  10115. return true;
  10116. }
  10117. else if(Item::items[toTile->ground->getID()].floorChangeDown){
  10118. return true;
  10119. }
  10120. else {
  10121. return true;
  10122. }
  10123. }
  10124. }
  10125. else if(toTile->floorChange(NORTH) && toTile->floorChange(EAST)){
  10126. return true;
  10127. }
  10128. else if(toTile->floorChange(NORTH) && toTile->floorChange(WEST)){
  10129. return true;
  10130. }
  10131. else if(toTile->floorChange(SOUTH) && toTile->floorChange(EAST)){
  10132. return true;
  10133. }
  10134. else if(toTile->floorChange(SOUTH) && toTile->floorChange(WEST)){
  10135. return true;
  10136. }
  10137. else if(toTile->floorChange(NORTH)){
  10138. return true;
  10139. }
  10140. else if(toTile->floorChange(SOUTH)){
  10141. return true;
  10142. }
  10143. else if(toTile->floorChange(EAST)){
  10144. return true;
  10145. }
  10146. else if(toTile->floorChange(WEST)){
  10147. return true;
  10148. }
  10149. if(!toTile){
  10150. if(!downTile)
  10151. {
  10152. return false;
  10153. }
  10154. else if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  10155. return true;
  10156. }
  10157. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  10158. return true;
  10159. }
  10160. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  10161. return true;
  10162. }
  10163. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  10164. return true;
  10165. }
  10166. else if(downTile->floorChange(NORTH)){
  10167. return true;
  10168. }
  10169. else if(downTile->floorChange(SOUTH)){
  10170. return true;
  10171. }
  10172. else if(downTile->floorChange(EAST)){
  10173. return true;
  10174. }
  10175. else if(downTile->floorChange(WEST)){
  10176. return true;
  10177. }
  10178. }
  10179. return false;
  10180. }
  10181.  
  10182. Position Game::getTeleportPos(Position to)
  10183. {
  10184. Tile *toTile = map->getTile(to);
  10185.  
  10186. if(toTile->ground && toTile->ground->floorChangeDown())
  10187. {
  10188. Tile* downTile = getTile(to.x, to.y, to.z+1);
  10189. if(downTile){
  10190. //diagonal begin
  10191. if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  10192. return Position(to.x-1, to.y+1, to.z+1);
  10193. }
  10194. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  10195. return Position(to.x+1, to.y+1, to.z+1);
  10196. }
  10197. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  10198. return Position(to.x-1, to.y-1, to.z+1);
  10199. }
  10200. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  10201. return Position(to.x+1, to.y-1, to.z+1);
  10202. }
  10203. //diagonal end
  10204. else if(downTile->floorChange(NORTH)){
  10205. return Position(to.x, to.y+1, to.z+1);
  10206. }
  10207. else if(downTile->floorChange(SOUTH)){
  10208. return Position(to.x, to.y-1, to.z+1);
  10209. }
  10210. else if(downTile->floorChange(EAST)){
  10211. return Position(to.x-1, to.y, to.z+1);
  10212. }
  10213. else if(downTile->floorChange(WEST)){
  10214. return Position(to.x+1, to.y, to.z+1);
  10215. }
  10216. //floor change down
  10217. else if(Item::items[toTile->ground->getID()].floorChangeDown){
  10218. return Position(to.x, to.y, to.z+1);
  10219. }
  10220. else {
  10221. return Position(to.x, to.y, to.z+1);
  10222. }
  10223. }
  10224. }
  10225. //diagonal begin
  10226. else if(toTile->floorChange(NORTH) && toTile->floorChange(EAST)){
  10227. return Position(to.x+1, to.y-1, to.z-1);
  10228. }
  10229. else if(toTile->floorChange(NORTH) && toTile->floorChange(WEST)){
  10230. return Position(to.x-1, to.y-1, to.z-1);
  10231. }
  10232. else if(toTile->floorChange(SOUTH) && toTile->floorChange(EAST)){
  10233. return Position(to.x+1, to.y+1, to.z-1);
  10234. }
  10235. else if(toTile->floorChange(SOUTH) && toTile->floorChange(WEST)){
  10236. return Position(to.x-1, to.y+1, to.z-1);
  10237. }
  10238. else if(toTile->floorChange(NORTH)){
  10239. return Position(to.x, to.y-1, to.z-1);
  10240. }
  10241. else if(toTile->floorChange(SOUTH)){
  10242. return Position(to.x, to.y+1, to.z-1);
  10243. }
  10244. else if(toTile->floorChange(EAST)){
  10245. return Position(to.x+1, to.y, to.z-1);
  10246. }
  10247. else if(toTile->floorChange(WEST)){
  10248. return Position(to.x-1, to.y, to.z-1);
  10249. }
  10250. if(!toTile){
  10251. Tile* downTile = getTile(to.x, to.y, to.z+1);
  10252. if(!downTile)
  10253. {
  10254. return Position(0,0,0);
  10255. }
  10256. else if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  10257. return Position(to.x-2, to.y+2, to.z+1);
  10258. }
  10259. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  10260. return Position(to.x+2, to.y+2, to.z+1);
  10261. }
  10262. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  10263. return Position(to.x-2, to.y-2, to.z+1);
  10264. }
  10265. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  10266. return Position(to.x+2, to.y-2, to.z+1);
  10267. }
  10268. else if(downTile->floorChange(NORTH)){
  10269. return Position(to.x, to.y + 1, to.z+1);
  10270. }
  10271. else if(downTile->floorChange(SOUTH)){
  10272. return Position(to.x, to.y - 1, to.z+1);
  10273. }
  10274. else if(downTile->floorChange(EAST)){
  10275. return Position(to.x - 1, to.y, to.z+1);
  10276. }
  10277. else if(downTile->floorChange(WEST)){
  10278. return Position(to.x + 1, to.y, to.z+1);
  10279. }
  10280. }
  10281. }
  10282. #endif //KOSZ
  10283.  
  10284. void Game::globalMagicEffect(const Position pos, unsigned char type)
  10285. {
  10286. SpectatorVec list;
  10287. SpectatorVec::iterator it;
  10288. getSpectators(Range(pos), list);
  10289. for(it = list.begin(); it != list.end(); ++it){
  10290. Player* p = dynamic_cast<Player*>(*it);
  10291. if(p)
  10292. p->sendMagicEffect(pos, type);
  10293. }
  10294. }
  10295.  
  10296. void Game::checkCreatureFollow(uint32_t id)
  10297. {
  10298. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreatureFollow");
  10299. Player *player = getPlayerByID(id);
  10300. if(!player)
  10301. return;
  10302. if(!player->pathList.empty()) {
  10303. Creature *followCreature = getCreatureByID(player->followCreature);
  10304. if(followCreature == 0)
  10305. return;
  10306. if((std::abs(player->pos.x - followCreature->pos.x) > 7) ||
  10307. (std::abs(player->pos.y - followCreature->pos.y) > 5) || (player->pos.z != followCreature->pos.z)){
  10308. player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  10309. player->eventCheckFollow = 0;
  10310. player->followCreature = 0;
  10311. playerSetAttackedCreature(player, 0);
  10312. return;
  10313. }
  10314. if(followCreature && abs(followCreature->pos.x - player->pos.x) <= 1 && abs(followCreature->pos.y - player->pos.y) <= 1) player->pathList.clear();
  10315. else {
  10316. Position toPos = player->pathList.front();
  10317. player->pathList.pop_front();
  10318. player->lastmove = OTSYS_TIME();
  10319. this->thingMove(player, player, toPos.x, toPos.y, player->pos.z, 1);
  10320. flushSendBuffers();
  10321. }
  10322. }
  10323. if(!player->pathList.empty()) {
  10324. long long delay = player->getSleepTicks();
  10325. stopEvent(player->eventCheckFollow);
  10326. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollow), id)));
  10327. } else {
  10328. player->eventCheckFollow = 0;
  10329. }
  10330. }
  10331. void Game::checkCreatureFollowAttack(uint32_t id)
  10332. {
  10333. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreatureFollowAttack");
  10334. Player *player = getPlayerByID(id);
  10335. if(!player)
  10336. return;
  10337. if(!player->pathList.empty()) {
  10338. Creature *followCreature = getCreatureByID(player->followCreature);
  10339. if(followCreature == 0)
  10340. return;
  10341. if(player->followMode == 0x00) {
  10342. stopEvent(player->eventCheckFollow);
  10343. player->eventCheckFollow = 0;
  10344. player->followCreature = 0;
  10345. return;
  10346. }
  10347. if((std::abs(player->pos.x - followCreature->pos.x) > 7) ||
  10348. (std::abs(player->pos.y - followCreature->pos.y) > 5) || (player->pos.z != followCreature->pos.z)){
  10349. player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  10350. player->eventCheckFollow = 0;
  10351. player->followCreature = 0;
  10352. playerSetAttackedCreature(player, 0);
  10353. return;
  10354. }
  10355. if(followCreature && abs(followCreature->pos.x - player->pos.x) <= 1 && abs(followCreature->pos.y - player->pos.y) <= 1) player->pathList.clear();
  10356. else {
  10357. Position toPos = player->pathList.front();
  10358. player->pathList.pop_front();
  10359. player->lastmove = OTSYS_TIME();
  10360. this->thingMove(player, player, toPos.x, toPos.y, player->pos.z, 1);
  10361. flushSendBuffers();
  10362. }
  10363. }
  10364. if(!player->pathList.empty()) {
  10365. long long delay = player->getSleepTicks();
  10366. stopEvent(player->eventCheckFollow);
  10367. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollowAttack), id)));
  10368. } else {
  10369. player->eventCheckFollow = 0;
  10370. }
  10371. }
  10372. void Game::playerFollow(Player* player, Creature *followCreature)
  10373. {
  10374. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerFollow()");
  10375. if(followCreature->isRemoved || player->isRemoved || !player || !followCreature){
  10376. player->eventCheckFollow = 0;
  10377. player->followCreature = 0;
  10378. return;
  10379. }
  10380. player->pathList = getPathToEx(player, player->pos, followCreature->pos, false);
  10381. long long delay = player->getSleepTicks();
  10382. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollow), player->getID())));
  10383. }
  10384. void Game::playerFollowAttacking(Player* player, Creature *followCreature)
  10385. {
  10386. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerFollow()");
  10387. if(followCreature->isRemoved || player->isRemoved || !player || !followCreature){
  10388. player->eventCheckFollow = 0;
  10389. player->followCreature = 0;
  10390. return;
  10391. }
  10392. if(player->followMode == 0x00) {
  10393. stopEvent(player->eventCheckFollow);
  10394. player->eventCheckFollow = 0;
  10395. player->followCreature = 0;
  10396. return;
  10397. }
  10398. player->pathList = getPathToEx(player, player->pos, followCreature->pos, false);
  10399. long long delay = player->getSleepTicks();
  10400. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollowAttack), player->getID())));
  10401. }
  10402. void Game::playerSetFollowCreature(Player* player, uint32_t creatureid)
  10403. {
  10404. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerSetFollowCreature()");
  10405. if(player->isRemoved || !player)
  10406. return;
  10407. if(creatureid == 0) {
  10408. stopEvent(player->eventCheckFollow);
  10409. player->eventCheckFollow = 0;
  10410. player->followCreature = 0;
  10411. }
  10412. Creature* followCreature = NULL;
  10413. if(creatureid != 0) {
  10414. followCreature = getCreatureByID(creatureid);
  10415. }
  10416. if(followCreature) {
  10417. player->followCreature = followCreature->getID();
  10418. stopEvent(player->eventCheckFollow);
  10419. playerFollow(player, followCreature);
  10420. }
  10421. }
  10422. void Game::playerAttackSetFollowCreature(Player* player, uint32_t creatureid)
  10423. {
  10424. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerAttackSetFollowCreature()");
  10425. if(player->isRemoved || !player)
  10426. return;
  10427. if(player->followMode == 0x00) {
  10428. return;
  10429. }
  10430. if(creatureid == 0) {
  10431. stopEvent(player->eventCheckFollow);
  10432. player->eventCheckFollow = 0;
  10433. player->followCreature = 0;
  10434. }
  10435. Creature* followCreature = NULL;
  10436. if(creatureid != 0) {
  10437. followCreature = getCreatureByID(creatureid);
  10438. }
  10439. if(followCreature) {
  10440. player->followCreature = followCreature->getID();
  10441. stopEvent(player->eventCheckFollow);
  10442. playerFollowAttacking(player, followCreature);
  10443. }
  10444. }
  10445.  
  10446. #ifdef HUCZU_AUTORESTART
  10447. void Game::beforeRestart()
  10448. {
  10449. sheduleShutdown(5);
  10450. }
  10451. #endif
  10452.  
  10453. void Game::creatureUseShop(Creature *creature, int id, int count, std::string way){
  10454. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureUseShop()");
  10455.  
  10456. int stackpos = map->getTile(creature->pos)->getThingStackPos(creature);
  10457.  
  10458. SpectatorVec list;
  10459. SpectatorVec::iterator it;
  10460.  
  10461. map->getSpectators(Range(creature->pos, true), list);
  10462.  
  10463. for(it = list.begin(); it != list.end(); ++it) {
  10464. if(dynamic_cast<Npc*>(*it)) {
  10465. (*it)->onCreatureUseShop(creature, id, count, way);
  10466. }
  10467. }
  10468. }
Add Comment
Please, Sign In to add comment