Guest User

Untitled

a guest
Mar 28th, 2020
179
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 348.59 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 && player->getVocation() == VOCATION_KNIGHT && atype == ATTACK_PHYSICAL) {
  113. newDamage *= 0.01*(double)g_config.KNIGHT_LOOSE;
  114. }
  115.  
  116. if (necklace && necklace->getCharges() > 0)
  117. {
  118. if (necklace->getID() == ITEM_STONE_SKIN_AMULET)
  119. {
  120. newDamage *= 0.10;
  121. necklace->useCharge();
  122. }
  123.  
  124. else if (necklace->getID() == ITEM_PROTECTION_AMULET)
  125. {
  126. newDamage *= 0.80;
  127. necklace->useCharge();
  128. }
  129.  
  130. else if ((necklace->getID() == ITEM_DRAGON_NECKLACE && (atype & ATTACK_FIRE)) ||
  131. (necklace->getID() == ITEM_SILVER_AMULET && (atype & ATTACK_POISON)) ||
  132. (necklace->getID() == ITEM_STRANGE_TALISMAN && (atype & ATTACK_ENERGY)) ||
  133. (necklace->getID() == ITEM_ELVEN_AMULET))
  134. {
  135. newDamage *= 0.8;
  136. necklace->useCharge();
  137. }
  138.  
  139.  
  140. else if ((necklace->getID() == ITEM_MAGMA_AMULET && (atype & ATTACK_FIRE)))
  141. {
  142. newDamage *= 0.7;
  143. necklace->useCharge();
  144. }
  145.  
  146.  
  147. #ifdef YUR_DRAINS
  148. else if (necklace->getID() == ITEM_BRONZE_AMULET && (atype & ATTACK_MANADRAIN))
  149. {
  150. newDamage *= 0.5;
  151. necklace->useCharge();
  152. }
  153.  
  154. else if (necklace->getID() == ITEM_GARLIC_NECKLACE && (atype & ATTACK_LIFEDRAIN))
  155. {
  156. newDamage = 0.5;
  157. necklace->useCharge();
  158. }
  159.  
  160. #endif //YUR_DRAINS
  161.  
  162. if (necklace->getCharges() <= 0)
  163. player->removeItemInventory(SLOT_NECKLACE);
  164. }
  165.  
  166. if (ring && ring->getCharges() > 0)
  167. {
  168. if (ring->getID() == ITEM_MIGHT_RING)
  169. {
  170. newDamage *= 0.8;
  171. ring->useCharge();
  172. }
  173.  
  174. if (ring->getCharges() <= 0)
  175. player->removeItemInventory(SLOT_RING);
  176. }
  177. #ifdef HUCZU_FIX
  178. if(armor)
  179. {
  180. if(armor->getID() == ITEM_FIRE_ARMOR && (atype & ATTACK_FIRE))
  181. newDamage *= 0.8;
  182. }
  183. #endif //HUCZU_FIX
  184.  
  185. return (int32_t)newDamage;
  186. }
  187. #endif //YUR_RINGS_AMULETS
  188.  
  189. void GameState::onAttack(Creature* attacker, const Position& pos, const MagicEffectClass* me)
  190. {
  191. Tile *tile = game->map->getTile(pos);
  192.  
  193. if(!tile)
  194. return;
  195.  
  196. #ifdef YUR_PVP_ARENA
  197. CreatureVector arenaLosers;
  198. #endif //YUR_PVP_ARENA
  199.  
  200. CreatureVector::iterator cit;
  201. Player* attackPlayer = dynamic_cast<Player*>(attacker);
  202. Creature *targetCreature = NULL;
  203. Player *targetPlayer = NULL;
  204. for(cit = tile->creatures.begin(); cit != tile->creatures.end(); ++cit) {
  205. targetCreature = (*cit);
  206. targetPlayer = dynamic_cast<Player*>(targetCreature);
  207. bool pvpArena = false;
  208. #ifdef TR_SUMMONS
  209. bool targetIsSummon = (targetCreature && targetCreature->isPlayersSummon());
  210. bool summonVsPlayer = (attacker && attacker->isPlayersSummon() && targetPlayer);
  211. #endif //TR_SUMMONS
  212.  
  213. int32_t damage = me->getDamage(targetCreature, attacker);
  214. int32_t manaDamage = 0;
  215.  
  216. if(attackPlayer){
  217. if(!me->offensive && me->minDamage != 0 && g_config.getGlobalString("showHealingDamage") == "yes"){
  218. int32_t lecz = std::min(std::abs(damage), attackPlayer->healthmax - attackPlayer->health);
  219. std::stringstream anidamage;
  220. anidamage << "+" << lecz;
  221. if(lecz != 0)
  222. game->sendAnimatedTextExt(attackPlayer->pos, 96, anidamage.str().c_str());
  223. }
  224. }
  225.  
  226. #ifdef YUR_RINGS_AMULETS
  227. damage = applyAmulets(targetPlayer, damage, me->attackType);
  228. #endif //YUR_RINGS_AMULETS
  229.  
  230. if (damage > 0) {
  231. if(attackPlayer && attackPlayer->access < g_config.ACCESS_PROTECT) {
  232. if(targetPlayer && targetPlayer != attackPlayer && game->getWorldType() != WORLD_TYPE_NO_PVP)
  233. attackPlayer->pzLocked = true;
  234. }
  235.  
  236. if(targetCreature->access < g_config.ACCESS_PROTECT && targetPlayer && game->getWorldType() != WORLD_TYPE_NO_PVP)
  237. {
  238. #ifdef YUR_CVS_MODS
  239. targetPlayer->inFightTicks = std::max(g_config.PZ_LOCKED, targetPlayer->inFightTicks);
  240. #else
  241. targetPlayer->inFightTicks = g_config.PZ_LOCKED;
  242. #endif //YUR_CVS_MODS
  243. targetPlayer->sendIcons();
  244. }
  245. #ifdef SURVIVAL_BLACKSQUARE
  246. if(damage > 0 && attackPlayer && targetPlayer && attackPlayer != targetPlayer){
  247. NetworkMessage attackedpmsg;
  248. attackedpmsg.AddPlayerAttacked(attacker);
  249. targetPlayer->sendNetworkMessage(&attackedpmsg);
  250. }
  251. #endif //SURVIVAL_BLACKSQUARE
  252.  
  253. #ifdef YUR_PVP_ARENA
  254. pvpArena = isPvpArena(attacker) && isPvpArena(targetCreature);
  255. #endif //YUR_PVP_ARENA
  256.  
  257. #ifdef TR_SUMMONS
  258. if ((game->getWorldType() == WORLD_TYPE_NO_PVP && !pvpArena && summonVsPlayer) ||
  259. (game->getWorldType() == WORLD_TYPE_NO_PVP && !pvpArena && attackPlayer && (targetPlayer || targetIsSummon) && attackPlayer->access < g_config.ACCESS_PROTECT)) {
  260. #else
  261. if(game->getWorldType() == WORLD_TYPE_NO_PVP && !pvpArena && attackPlayer && targetPlayer && attackPlayer->access < ACCESS_PROTECT){
  262. #endif //TR_SUMMONS
  263. damage = 0;
  264. }
  265. }
  266.  
  267. if (damage != 0)
  268. {
  269. // Bedzie pro ustawione all
  270. #ifdef HUCZU_FIX
  271. if(attackPlayer){
  272. Item* armor = attackPlayer->getItem(SLOT_ARMOR);
  273. Item* legs = attackPlayer->getItem(SLOT_LEGS);
  274. Item* helmet = attackPlayer->getItem(SLOT_HEAD);
  275. Item* boots = attackPlayer->getItem(SLOT_FEET);
  276. Item* ring = attackPlayer->getItem(SLOT_RING);
  277. Item* amulet = attackPlayer->getItem(SLOT_NECKLACE);
  278.  
  279. if(attackPlayer->vocation == 1 || attackPlayer->vocation == 2){
  280. if(armor){
  281. if(armor->getID() == ITEM_GLACIER_ROBE){
  282. double newdamage = damage*2/100.0;
  283. damage += (int32_t)newdamage;
  284. }
  285. else if(armor->getID() == ITEM_ARCHMAGE_COAT){
  286. double newdamage = damage*5/100.0;
  287. damage += (int32_t)newdamage;
  288. }
  289. else if(armor->getID() == ITEM_BMC){
  290. double newdamage = damage*3/100.0;
  291. damage += (int32_t)newdamage;
  292. }
  293. }
  294. if(legs){
  295. if(legs->getID() == ITEM_GLACIER_KIT){
  296. double newdamage = damage*2/100.0;
  297. damage += (int32_t)newdamage;
  298. }
  299. }
  300. }
  301.  
  302. if(legs){
  303. if(legs->getID() == ITEM_ZS_LEGS){
  304. double newdamage = damage*10/100.0;
  305. damage += (int32_t)newdamage;
  306. }
  307. }
  308.  
  309. if(g_config.MGITEMS){
  310. if(helmet && helmet->getID() == g_config.MGITEMHELMET){
  311. double newdamage = damage*g_config.ITEM_MDOWNHELMET/100.0;
  312. damage += (int32_t)newdamage;
  313. }
  314. if(armor && armor->getID() == g_config.MGITEMARMOR){
  315. double newdamage = damage*g_config.ITEM_MDOWNARMOR/100.0;
  316. damage += (int32_t)newdamage;
  317. }
  318. if(legs && legs->getID() == g_config.MGITEMLEGS){
  319. double newdamage = damage*g_config.ITEM_MDOWNLEGS/100.0;
  320. damage += (int32_t)newdamage;
  321. }
  322. if(boots && boots->getID() == g_config.MGITEMBOOTS){
  323. double newdamage = damage*g_config.ITEM_MDOWNBOOTS/100.0;
  324. damage += (int32_t)newdamage;
  325. }
  326. if(ring && ring->getID() == g_config.MGITEMRINGS){
  327. double newdamage = damage*g_config.ITEM_MDOWNRING/100.0;
  328. damage += (int32_t)newdamage;
  329. }
  330. if(amulet && amulet->getID() == g_config.MGITEMAMU){
  331. double newdamage = damage*g_config.ITEM_MDOWNAMU/100.0;
  332. damage += (int32_t)newdamage;
  333. }
  334. }
  335. }
  336. #endif //HUCZU_FIX i git w chuj
  337.  
  338. #ifdef YUR_DRAINS
  339. if (me->attackType & ATTACK_MANADRAIN)
  340. {
  341. manaDamage = std::min(damage, targetCreature->mana);
  342. targetCreature->drainMana(manaDamage);
  343. damage = 0;
  344. }
  345. else
  346. #endif //YUR_DRAINS
  347. {
  348. game->creatureApplyDamage(targetCreature, damage, damage, manaDamage
  349. #ifdef YUR_PVP_ARENA
  350. , (pvpArena? &arenaLosers : NULL)
  351. #endif //YUR_PVP_ARENA
  352. );
  353. }
  354.  
  355. #ifdef YUR_DRAINS
  356. if (me->attackType & ATTACK_LIFEDRAIN)
  357. {
  358. attacker->health = std::min(attacker->healthmax, attacker->health + damage);
  359. addCreatureState(tile, attacker, 0, 0, false); // update attacker health
  360. }
  361. #endif //YUR_DRAINS
  362.  
  363. #ifdef YUR_INVISIBLE
  364. if (targetCreature && !targetPlayer)
  365. {
  366. targetCreature->setInvisible(0);
  367. game->creatureChangeOutfit(targetCreature);
  368. }
  369. #endif //YUR_INVISIBLE
  370. }
  371.  
  372. #ifdef HUCZU_SKULLS
  373. if (me->offensive && game->getWorldType() == WORLD_TYPE_PVP)
  374. game->onPvP(attacker, targetCreature, targetCreature->health <= 0);
  375. #endif
  376.  
  377. addCreatureState(tile, targetCreature, damage, manaDamage, me->drawblood);
  378. }
  379.  
  380. //Solid ground items/Magic items (fire/poison/energy)
  381. MagicEffectItem *newmagicItem = me->getMagicItem(attacker, tile->isPz(),
  382. (tile->isBlocking(BLOCK_SOLID, true) != RET_NOERROR));
  383.  
  384. if(newmagicItem) {
  385.  
  386. MagicEffectItem *magicItem = tile->getFieldItem();
  387.  
  388. if(magicItem) {
  389. //Replace existing magic field
  390. magicItem->transform(newmagicItem);
  391.  
  392. int32_t stackpos = tile->getThingStackPos(magicItem);
  393. if(tile->removeThing(magicItem)) {
  394.  
  395. SpectatorVec list;
  396. SpectatorVec::iterator it;
  397.  
  398. game->getSpectators(Range(pos, true), list);
  399.  
  400. //players
  401. for(it = list.begin(); it != list.end(); ++it) {
  402. if(dynamic_cast<Player*>(*it)) {
  403. (*it)->onThingDisappear(magicItem, stackpos);
  404. }
  405. }
  406.  
  407. //none-players
  408. for(it = list.begin(); it != list.end(); ++it) {
  409. if(!dynamic_cast<Player*>(*it)) {
  410. (*it)->onThingDisappear(magicItem, stackpos);
  411. }
  412. }
  413.  
  414. tile->addThing(magicItem);
  415.  
  416. //players
  417. for(it = list.begin(); it != list.end(); ++it) {
  418. if(dynamic_cast<Player*>(*it)) {
  419. (*it)->onThingAppear(magicItem);
  420. }
  421. }
  422.  
  423. //none-players
  424. for(it = list.begin(); it != list.end(); ++it) {
  425. if(!dynamic_cast<Player*>(*it)) {
  426. (*it)->onThingAppear(magicItem);
  427. }
  428. }
  429. }
  430. }
  431. else {
  432. magicItem = new MagicEffectItem(*newmagicItem);
  433. magicItem->useThing();
  434. magicItem->pos = pos;
  435.  
  436. tile->addThing(magicItem);
  437.  
  438. SpectatorVec list;
  439. SpectatorVec::iterator it;
  440.  
  441. game->getSpectators(Range(pos, true), list);
  442.  
  443. //players
  444. for(it = list.begin(); it != list.end(); ++it) {
  445. if(dynamic_cast<Player*>(*it)) {
  446. (*it)->onThingAppear(magicItem);
  447. }
  448. }
  449.  
  450. //none-players
  451. for(it = list.begin(); it != list.end(); ++it) {
  452. if(!dynamic_cast<Player*>(*it)) {
  453. (*it)->onThingAppear(magicItem);
  454. }
  455. }
  456.  
  457. magicItem->isRemoved = false;
  458. game->startDecay(magicItem);
  459. }
  460. }
  461.  
  462. //Clean up
  463. for(CreatureStateVec::const_iterator csIt = creaturestates[tile].begin(); csIt != creaturestates[tile].end(); ++csIt) {
  464. onAttackedCreature(tile, attacker, csIt->first, csIt->second.damage, csIt->second.drawBlood);
  465. }
  466.  
  467. if(attackPlayer && attackPlayer->access < g_config.ACCESS_PROTECT) {
  468. //Add exhaustion
  469. if(me->causeExhaustion(true) /*!areaTargetVec.empty())*/)
  470. {
  471. attackPlayer->exhaustedTicks = g_config.EXHAUSTED;
  472. }
  473.  
  474. //Fight symbol
  475. if(me->offensive /*&& !areaTargetVec.empty()*/)
  476. {
  477. #ifdef YUR_CVS_MODS
  478. attackPlayer->inFightTicks = std::max(g_config.PZ_LOCKED, attackPlayer->inFightTicks);
  479. #else
  480. attackPlayer->inFightTicks = g_config.PZ_LOCKED;
  481. #endif //YUR_CVS_MODS
  482. }
  483. }
  484.  
  485. #ifdef YUR_PVP_ARENA
  486. for (CreatureVector::iterator it = arenaLosers.begin(); it != arenaLosers.end(); ++it)
  487. {
  488. Tile* tile = game->getTile((*it)->pos);
  489.  
  490. if (tile)
  491. {
  492. game->teleport(*it, tile->getPvpArenaExit());
  493. }
  494.  
  495. if(Monster* monster = dynamic_cast<Monster*>(*it))
  496. {
  497. if(Tile *tile = game->map->getTile(monster->pos))
  498. {
  499. if(tile->isPvpArena())
  500. {
  501. game->removeCreature(monster);
  502. }
  503. }
  504. }
  505. }
  506. #endif //YUR_PVP_ARENA
  507. }
  508.  
  509. void GameState::onAttack(Creature* attacker, const Position& pos, Creature* attackedCreature)
  510. {
  511. bool pvpArena = false;
  512. #ifdef YUR_PVP_ARENA
  513. CreatureVector arenaLosers;
  514. pvpArena = isPvpArena(attacker) && isPvpArena(attackedCreature);
  515. #endif //YUR_PVP_ARENA
  516.  
  517. //TODO: Decent formulas and such...
  518. int32_t damage = attacker->getWeaponDamage();
  519. int32_t armor = attackedCreature->getArmor();
  520. int32_t defense = attackedCreature->getDefense();
  521.  
  522. Player* attackPlayer = dynamic_cast<Player*>(attacker);
  523. Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  524.  
  525. if(attackedPlayer)
  526. attackedPlayer->addSkillShieldTry(1);
  527.  
  528. int32_t probability = rand() % 10000;
  529.  
  530. #ifdef YUR_CVS_MODS
  531. if(probability * damage < defense * 3000)
  532. damage = 0;
  533. else
  534. damage -= (int32_t)((damage*(armor/50.0)*(rand()/(RAND_MAX+1.0))) + (armor*2) + defense/1.5);
  535. //damage -= (int32_t)((armor)*(rand()/(RAND_MAX+1.0))) + armor; // wik's
  536. #else
  537. if(probability * damage < defense * 10000)
  538. damage = 0;
  539. else
  540. {
  541. damage -= (armor * (10000 + rand() % 10000)) / 10000;
  542. }
  543. #endif //YUR_CVS_MODS
  544.  
  545. int32_t manaDamage = 0;
  546.  
  547. if(attackPlayer && attackedPlayer){
  548. damage -= (int32_t) damage / 2;
  549. }
  550.  
  551.  
  552. if (attacker->access >= g_config.ACCESS_PROTECT)
  553. damage += 1;
  554.  
  555.  
  556. Tile* tile = game->map->getTile(pos);
  557. bool blood;
  558. if(damage > 0)
  559. {
  560. // F-AXE,F-SWORD,P-DAGGER
  561. if(attackPlayer)
  562. {
  563. for (int32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++)
  564. {
  565. if(g_config.EFFECT_ATACK && attackPlayer->getItem(slot) && (attackPlayer->getItem(slot)->getID() == ITEM_FAXE || attackPlayer->getItem(slot)->getID() == ITEM_FSWORD))
  566. {
  567. game->CreateCondition(attackedCreature, attacker, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 5, 5, 2000, 1);
  568. }
  569. if(g_config.EFFECT_ATACK && attackPlayer->getItem(slot) && (attackPlayer->getItem(slot)->getID() == ITEM_PD))
  570. {
  571. game->CreateCondition(attackedCreature, attacker, 30, NM_ME_POISEN_RINGS, NM_ME_POISEN_RINGS, ATTACK_POISON, true, 5, 5, 2000, 3);
  572. }
  573. }
  574. }
  575.  
  576. // P-BOLT ENERGY
  577. if(attackPlayer)
  578. {
  579. int32_t slot = SLOT_AMMO;
  580. if(g_config.EFFECT_ATACK && attackPlayer->getItem(slot) && (attackPlayer->getItem(slot)->getID() == 5260))
  581. {
  582. game->CreateCondition(attackedCreature, attacker, 35, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 10, 10, 2000, 1);
  583. }
  584. }
  585.  
  586. #ifdef YUR_ICE_RAPIER
  587. if (attackPlayer)
  588. for (int32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++)
  589. if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->getID() == ITEM_ICE_RAPIER)
  590. attackPlayer->removeItemInventory(slot);
  591. #endif //YUR_ICE_RAPIER
  592.  
  593. #ifdef PALL_REQ_LVL
  594. if (attackPlayer){
  595. for (int32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++){
  596. if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->isWeapon() && attackPlayer->getItem(slot)->getReqLevel() > attackPlayer->getLevel())
  597. {
  598. int32_t newdamage = attackPlayer->getWeaponDamage() / random_range(4, 7);
  599. if (attackPlayer->getWeaponDamage() >= 7)
  600. damage = 0;
  601. else
  602. damage = newdamage;
  603. }
  604. if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->getAmuType() != 0 && attackPlayer->getItem(slot)->getReqLevel() > attackPlayer->getLevel())
  605. {
  606. int32_t newdamage = attackPlayer->getWeaponDamage() / random_range(4, 7);
  607. if (attackPlayer->getWeaponDamage() >= 7)
  608. damage = 0;
  609. else
  610. damage = newdamage;
  611. }
  612. if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->isWeapon() && attackPlayer->getItem(slot)->getReqVoc() != attackPlayer->getVocation() && attackPlayer->getItem(slot)->getReqVoc() > 0)
  613. {
  614. int32_t newdamage = attackPlayer->getWeaponDamage() / random_range(4, 9);
  615. if (attackPlayer->getWeaponDamage() >= 7)
  616. damage = 0;
  617. else
  618. damage = newdamage;
  619. }
  620. }
  621. }
  622. #endif //PALL_REQ_LVL
  623.  
  624. #ifdef YUR_RINGS_AMULETS
  625. damage = applyAmulets(attackedPlayer, damage, ATTACK_PHYSICAL);
  626. #endif //YUR_RINGS_AMULETS
  627.  
  628.  
  629. #ifdef CHRIS_CRIT_HIT
  630. if(attackPlayer){
  631. int32_t critcial_hit;
  632. int32_t rand_hit = random_range(0, 700);
  633. switch(rand_hit){
  634. case 75:
  635. critcial_hit = random_range(50, 100);
  636. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  637. break;
  638. case 87:
  639. critcial_hit = random_range(50, 100);
  640. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  641. break;
  642. case 95:
  643. critcial_hit = random_range(50, 100);
  644. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  645. break;
  646. case 113:
  647. critcial_hit = random_range(80, 130);
  648. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  649. break;
  650. case 128:
  651. critcial_hit = random_range(80, 130);
  652. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  653. break;
  654. case 133:
  655. critcial_hit = random_range(80, 130);
  656. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  657. break;
  658. case 145:
  659. critcial_hit = random_range(80, 130);
  660. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  661. break;
  662. case 157:
  663. critcial_hit = random_range(80, 130);
  664. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  665. break;
  666. case 167:
  667. critcial_hit = random_range(80, 130);
  668. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  669. break;
  670. case 187:
  671. critcial_hit = random_range(80, 130);
  672. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  673. break;
  674. case 195:
  675. critcial_hit = random_range(80, 130);
  676. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  677. break;
  678. case 202:
  679. critcial_hit = random_range(110, 160);
  680. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  681. break;
  682. case 225:
  683. critcial_hit = random_range(110, 160);
  684. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  685. break;
  686. case 238:
  687. critcial_hit = random_range(110, 160);
  688. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  689. break;
  690. case 245:
  691. critcial_hit = random_range(110, 160);
  692. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  693. break;
  694. case 268:
  695. critcial_hit = random_range(110, 160);
  696. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  697. break;
  698. case 287:
  699. critcial_hit = random_range(110, 160);
  700. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  701. break;
  702. case 298:
  703. critcial_hit = random_range(110, 160);
  704. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  705. break;
  706. case 324:
  707. critcial_hit = random_range(140, 400);
  708. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  709. break;
  710. case 356:
  711. critcial_hit = random_range(140, 190);
  712. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  713. break;
  714. case 371:
  715. critcial_hit = random_range(140, 190);
  716. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  717. break;
  718. case 380:
  719. critcial_hit = random_range(140, 190);
  720. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  721. break;
  722. case 397:
  723. critcial_hit = random_range(140, 190);
  724. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  725. break;
  726. case 399:
  727. critcial_hit = random_range(140, 190);
  728. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  729. break;
  730. case 400:
  731. critcial_hit = random_range(170, 210);
  732. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  733. break;
  734. case 428:
  735. critcial_hit = random_range(170, 210);
  736. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  737. break;
  738. case 432:
  739. critcial_hit = random_range(170, 210);
  740. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  741. break;
  742. case 444:
  743. critcial_hit = random_range(170, 210);
  744. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  745. break;
  746. case 474:
  747. critcial_hit = random_range(170, 210);
  748. if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  749. break;
  750. default:
  751. critcial_hit = 0;
  752. break;
  753. }
  754.  
  755. if (attackPlayer->vocation == 4){
  756. if(critcial_hit != 0){
  757. if(attackPlayer->level >= 150){
  758. if(attackPlayer && attackPlayer->items[SLOT_RIGHT] && attackPlayer->items[SLOT_RIGHT]->getID() == ITEM_RAINBOW){
  759. if(attackPlayer->items[SLOT_LEFT]){
  760. if(attackPlayer->items[SLOT_LEFT]->getID() != ITEM_RAINBOW)
  761. critcial_hit += critcial_hit*(25/100);
  762. game->CreateCondition(attackedCreature, attacker, 35, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 25, 25, 1000, 1);
  763. }
  764. }
  765. }
  766. if(attackPlayer && attackPlayer->items[SLOT_LEFT] && attackPlayer->items[SLOT_LEFT]->getID() == ITEM_RAINBOW){
  767. if(attackPlayer->items[SLOT_RIGHT]){
  768. if(attackPlayer->items[SLOT_RIGHT]->getID() != ITEM_RAINBOW)
  769. critcial_hit += critcial_hit*(25/100);
  770. game->CreateCondition(attackedCreature, attacker, 35, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 25, 25, 1000, 1);
  771. }
  772. }
  773. }
  774. damage += critcial_hit;
  775. }
  776. }
  777.  
  778. #endif //CHRIS_CRIT_HIT
  779.  
  780. game->creatureApplyDamage(attackedCreature, damage, damage, manaDamage
  781.  
  782.  
  783. #ifdef YUR_PVP_ARENA
  784. , (pvpArena? &arenaLosers : NULL)
  785. #endif //YUR_PVP_ARENA
  786. );
  787.  
  788. #ifdef HUCZU_SKULLS
  789. if (game->getWorldType() == WORLD_TYPE_PVP)
  790. game->onPvP(attacker, attackedCreature, attackedCreature->health <= 0);
  791. #endif
  792.  
  793. blood = true;
  794.  
  795. if(attackPlayer && attackPlayer->maxDmg < damage) {
  796. attackPlayer->maxDmg = (int32_t) damage;
  797. std::stringstream MaxDmgMsg;
  798. MaxDmgMsg << "Your new best damage is " << attackPlayer->maxDmg << ".";
  799. attackPlayer->sendTextMessage(MSG_ADVANCE, MaxDmgMsg.str().c_str());
  800. }
  801. }
  802. else{//no draw blood
  803. blood = false;
  804. }
  805.  
  806. addCreatureState(tile, attackedCreature, damage, manaDamage, blood);
  807. onAttackedCreature(tile, attacker, attackedCreature, damage, true);
  808.  
  809. /*
  810. if (attackPlayer && attackPlayer->isUsingSpears() && random_range(1,100000) > g_config.SPEAR_LOSE_CHANCE)
  811. {
  812. Item* spear = Item::CreateItem(ITEM_SPEAR, 1);
  813. spear->pos = attackedCreature->pos;
  814. game->addThing(attackPlayer, spear->pos, spear);
  815. }
  816. */
  817.  
  818. #ifdef YUR_PVP_ARENA
  819. for (CreatureVector::iterator it = arenaLosers.begin(); it != arenaLosers.end(); ++it){
  820. Tile* tile = game->getTile((*it)->pos);
  821. if (tile){
  822. game->teleport(*it, tile->getPvpArenaExit());
  823. }
  824. if(Monster* monster = dynamic_cast<Monster*>(*it)){
  825. if(Tile *tile = game->map->getTile(monster->pos)){
  826. if(tile->isPvpArena()){
  827. game->removeCreature(monster);
  828. }
  829. }
  830. }
  831. }
  832. #endif //YUR_PVP_ARENA
  833. }
  834.  
  835. void GameState::addCreatureState(Tile* tile, Creature* attackedCreature, int32_t damage, int32_t manaDamage, bool drawBlood)
  836. {
  837. CreatureState cs;
  838. cs.damage = damage;
  839. cs.manaDamage = manaDamage;
  840. cs.drawBlood = drawBlood;
  841.  
  842. creaturestates[tile].push_back( make_pair(attackedCreature, cs) );
  843. }
  844.  
  845. void GameState::onAttackedCreature(Tile* tile, Creature *attacker, Creature* attackedCreature, int32_t damage, bool drawBlood)
  846. {
  847. Player *attackedplayer = dynamic_cast<Player*>(attackedCreature);
  848. Position CreaturePos = attackedCreature->pos;
  849.  
  850. #ifdef TJ_MONSTER_BLOOD
  851. bool dead = false;
  852. #endif //TJ_MONSTER_BLOOD
  853.  
  854. #ifdef TR_SUMMONS
  855. //Summon exp share by Yurez
  856. Player *player = dynamic_cast<Player*>(attacker);
  857. Creature* attackerMaster = attacker? attacker->getMaster() : NULL;
  858. if(attackerMaster && dynamic_cast<Player*>(attackerMaster)){//attacker is players summon
  859. attackedCreature->addInflictedDamage(attacker, damage/2);
  860. attackedCreature->addInflictedDamage(attackerMaster, damage/2);
  861. }// end summon exp share
  862. else if(player && player->party != 0){
  863. int32_t partySize = 0;
  864. SpectatorVec list;
  865. SpectatorVec::iterator it;
  866. game->getSpectators(Range(player->pos), list);
  867. /*Get all specatators around this player
  868. then check if they are in his party*/
  869. for(it = list.begin(); it != list.end(); ++it){//find number too div by
  870. Player* p = dynamic_cast<Player*>(*it);
  871. if(p && p->party == player->party)//huczu_fix
  872. partySize++;
  873. }
  874. for(it = list.begin(); it != list.end(); ++it){
  875. Player* p = dynamic_cast<Player*>(*it);
  876. if(p && p->party == player->party && partySize != 0/*dont div by 0*/)//same party add exp, huczu_fix
  877. attackedCreature->addInflictedDamage(p, damage/partySize);
  878. }
  879. }
  880. else
  881. attackedCreature->addInflictedDamage(attacker, damage);
  882. #endif //TR_SUMMONS
  883.  
  884. if(attackedplayer){
  885. attackedplayer->sendStats();
  886. }
  887. //Remove player?
  888. if(attackedCreature->health <= 0 && attackedCreature->isRemoved == false)
  889. {
  890. #ifdef TJ_MONSTER_BLOOD
  891. dead = true;
  892. #endif //TJ_MONSTER_BLOOD
  893. #ifdef JD_DEATH_LIST
  894. if (attackedplayer && attacker)
  895. attackedplayer->addDeath(attacker->getName(), attackedplayer->level, time(0));
  896. #endif //JD_DEATH_LIST
  897. unsigned char stackpos = tile->getThingStackPos(attackedCreature);
  898.  
  899.  
  900. //tasksys
  901. Player* attackingplayer = dynamic_cast<Player*>(attacker);
  902. if(attackingplayer && attackedCreature->getName() == attackingplayer->taskmonster && attackingplayer->taskcount < attackingplayer->taskmax)
  903. {
  904. // attackingplayer->taskcount++;
  905. std::stringstream info;
  906. std::string mons = attackingplayer->taskmonster;
  907. std::transform(mons.begin(), mons.end(), mons.begin(), (int(*)(int))tolower);
  908.  
  909. if(attackingplayer->taskcount < attackingplayer->taskmax)
  910. {
  911. info << "You have killed " << attackingplayer->taskcount << " out of " << attackingplayer->taskmax << " " << mons << "s.";
  912. }
  913. else
  914. {
  915. info << "You have finished task of killing " << mons << "s. ";
  916. }
  917.  
  918. // attackingplayer->sendTextMessage(MSG_ORANGE, info.str().c_str());
  919. }
  920. //tasksys
  921.  
  922. //Prepare body
  923. Item *corpseitem = Item::CreateItem(attackedCreature->getLookCorpse());
  924. corpseitem->pos = CreaturePos;
  925. tile->addThing(corpseitem);
  926.  
  927. #ifdef _DEATH_EVENTS
  928. if (!attackedplayer)
  929. {
  930. Monster* monster = dynamic_cast<Monster*>(attackedCreature);
  931. Player* killer = dynamic_cast<Player*>(attacker);
  932.  
  933. if (killer && monster && monster->getAction())
  934. {
  935. actions.onCreatureKill(killer, attackedCreature, corpseitem, monster->getAction());
  936. }
  937.  
  938. }
  939. #endif //_DEATH_EVENTS
  940.  
  941. #ifdef __MIZIAK_CREATURESCRIPTS__
  942. if(dynamic_cast<Player*>(attacker) && attackedCreature)
  943. actions.creatureEvent("kill", dynamic_cast<Player*>(attacker), attackedCreature, corpseitem, NULL);
  944. #endif //__MIZIAK_CREATURESCRIPTS__
  945.  
  946. //remove creature
  947. if(attackedplayer){
  948. actions.luaWalkOff(attackedplayer,attackedplayer->pos,tile->ground->getID(),tile->ground->getUniqueId(),tile->ground->getActionId()); //CHANGE onWalk
  949. attackedplayer->onThingDisappear(attackedplayer,stackpos);
  950.  
  951. #ifdef __MIZIAK_CREATURESCRIPTS__
  952. attackedplayer->dieorlogout = true;
  953. if(attacker)
  954. actions.creatureEvent("death", attackedplayer, attacker, corpseitem, NULL);
  955. #endif //__MIZIAK_CREATURESCRIPTS__
  956.  
  957.  
  958. attackedplayer->die(); //handles exp/skills/maglevel loss
  959. }
  960.  
  961. //Add eventual loot
  962. Container *lootcontainer = dynamic_cast<Container*>(corpseitem);
  963. if(lootcontainer) {
  964. attackedCreature->dropLoot(lootcontainer);
  965.  
  966. #ifdef HUCZU_LOOT_INFO
  967. Monster* monster = dynamic_cast<Monster*>(attackedCreature);
  968. Player* atakujacy = dynamic_cast<Player*>(attacker);
  969. if(monster && atakujacy){
  970. std::stringstream ss, info;
  971. //info << "Loot of " << monster->getName() << lootcontainer->getContentDescription() << ".";
  972. info << "Loot of " << monster->getName();
  973. ss << lootcontainer->getContentDescription() << ".";
  974. if(atakujacy->party != 0){
  975. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  976. if((*it).second->party == atakujacy->party){
  977. if((*it).second->getID() != atakujacy->getID()){
  978. (*it).second->sendToSpecialChannel(atakujacy, SPEAK_CHANNEL_O, ss.str().c_str(), 0x02, info.str().c_str());
  979. //(*it).second->sendTextMessage(MSG_INFO, info.str().c_str());
  980. }
  981. }
  982. }
  983. }else{
  984. //atakujacy->sendTextMessage(MSG_INFO, info.str().c_str());
  985. atakujacy->sendToSpecialChannel(atakujacy, SPEAK_CHANNEL_O, ss.str().c_str(), 0x02, info.str().c_str());
  986. }
  987. }
  988. #endif //HUCZU_LOOT_INFO
  989. }
  990.  
  991. #ifdef HUCZU_MONSTER_QUEST
  992. Monster* monster = dynamic_cast<Monster*>(attackedCreature);
  993. Player* atakujacy = dynamic_cast<Player*>(attacker);
  994. int32_t value, kills;
  995.  
  996. if(monster && atakujacy && monster->getQuestId() != 0){
  997.  
  998. if(monster->getQuestId() == 2 && atakujacy->getStorageValue(100, value) == 1){
  999. int32_t killsprzed = atakujacy->getQuestKills(2);
  1000. atakujacy->addQuestKills(2, killsprzed+1);
  1001. }
  1002.  
  1003. }
  1004. #endif //HUCZU_MONSTER_QUEST
  1005.  
  1006.  
  1007. game->removeCreature(attackedCreature);
  1008. // Update attackedCreature pos because contains
  1009. // temple position for players
  1010. attackedCreature->pos = CreaturePos;
  1011.  
  1012. //add body
  1013. game->sendAddThing(NULL,corpseitem->pos,corpseitem);
  1014.  
  1015. if(attackedplayer){
  1016. std::stringstream ss;
  1017. ss << corpseitem->getDescription(false);
  1018.  
  1019. ss << "You recognize " << attackedplayer->getName() << ". ";
  1020. if(attacker){
  1021. ss << (attackedplayer->getSex() == PLAYERSEX_FEMALE ? "She" : "He") << " was killed by ";
  1022.  
  1023. Player *attackerplayer = dynamic_cast<Player*>(attacker);
  1024. if(attackerplayer) {
  1025. ss << attacker->getName();
  1026. }
  1027. else {
  1028. std::string creaturename = attacker->getName();
  1029. std::transform(creaturename.begin(), creaturename.end(), creaturename.begin(), (int32_t(*)(int32_t))tolower);
  1030. ss << article(creaturename);
  1031. }
  1032. }
  1033.  
  1034. //set body special description
  1035. corpseitem->setSpecialDescription(ss.str());
  1036. //send corpse to the dead player. It is not in spectator list
  1037. // because was removed
  1038. attackedplayer->onThingAppear(corpseitem);
  1039. }
  1040. game->startDecay(corpseitem);
  1041.  
  1042. //Get all creatures that will gain xp from this kill..
  1043. CreatureState* attackedCreatureState = NULL;
  1044. std::vector<long> creaturelist;
  1045.  
  1046. if(!(dynamic_cast<Player*>(attackedCreature) && game->getWorldType() != WORLD_TYPE_PVP_ENFORCED)){
  1047. creaturelist = attackedCreature->getInflicatedDamageCreatureList();
  1048. CreatureStateVec& creatureStateVec = creaturestates[tile];
  1049. for(CreatureStateVec::iterator csIt = creatureStateVec.begin(); csIt != creatureStateVec.end(); ++csIt) {
  1050. if(csIt->first == attackedCreature) {
  1051. attackedCreatureState = &csIt->second;
  1052. break;
  1053. }
  1054. }
  1055. }
  1056.  
  1057. if(attackedCreatureState) { //should never be NULL..
  1058. //Add experience
  1059. for(std::vector<long>::const_iterator iit = creaturelist.begin(); iit != creaturelist.end(); ++iit) {
  1060. Creature* gainExpCreature = game->getCreatureByID(*iit);
  1061. if(gainExpCreature) {
  1062. exp_t gainedExperience = attackedCreature->getGainedExperience(gainExpCreature);
  1063. if(gainedExperience <= 0)
  1064. continue;
  1065.  
  1066. Player *gainExpPlayer = dynamic_cast<Player*>(gainExpCreature);
  1067.  
  1068. if(gainExpPlayer) {
  1069. gainExpPlayer->addExp(gainedExperience);
  1070. if(gainExpPlayer && attackedCreature->getName() == gainExpPlayer->taskmonster && gainExpPlayer->taskcount < gainExpPlayer->taskmax)
  1071. {
  1072. gainExpPlayer->taskcount++;
  1073. std::stringstream info;
  1074. std::string mons = gainExpPlayer->taskmonster;
  1075. std::transform(mons.begin(), mons.end(), mons.begin(), (int(*)(int))tolower);
  1076.  
  1077. if(gainExpPlayer->taskcount < gainExpPlayer->taskmax)
  1078. {
  1079. info << "You have killed " << gainExpPlayer->taskcount << " out of " << gainExpPlayer->taskmax << " " << mons << "s.";
  1080. }
  1081. else
  1082. {
  1083. info << "You have finished task of killing " << mons << "s. ";
  1084. }
  1085. gainExpPlayer->sendTextMessage(MSG_ORANGE, info.str().c_str());
  1086. }
  1087.  
  1088.  
  1089.  
  1090. }
  1091. //Need to add this creature and all that can see it to spectators, unless they already added
  1092. SpectatorVec creaturelist;
  1093. game->getSpectators(Range(gainExpCreature->pos, true), creaturelist);
  1094.  
  1095. for(SpectatorVec::const_iterator cit = creaturelist.begin(); cit != creaturelist.end(); ++cit) {
  1096. if(std::find(spectatorlist.begin(), spectatorlist.end(), *cit) == spectatorlist.end()) {
  1097. spectatorlist.push_back(*cit);
  1098. }
  1099. }
  1100.  
  1101. //Add creature to attackerlist
  1102. attackedCreatureState->attackerlist.push_back(gainExpCreature);
  1103. }
  1104. }
  1105. }
  1106.  
  1107. Player *player = dynamic_cast<Player*>(attacker);
  1108. if(player){
  1109. player->sendStats();
  1110. }
  1111.  
  1112. if(attackedCreature && attackedCreature->getMaster() != NULL) {
  1113. attackedCreature->getMaster()->removeSummon(attackedCreature);
  1114. }
  1115. }
  1116.  
  1117.  
  1118. //Add blood?
  1119. #ifdef TJ_MONSTER_BLOOD
  1120. if((drawBlood || attackedCreature->health <= 0) && damage > 0 && attackedCreature->bloodsplash != 255) {
  1121. Item* splash = Item::CreateItem(dead? ITEM_POOL : ITEM_SPLASH, attackedCreature->bloodsplash);
  1122. game->addThing(NULL, CreaturePos, splash);
  1123. game->startDecay(splash);
  1124. game->updateTile(CreaturePos);
  1125. }
  1126. #else
  1127. if((drawBlood || attackedCreature->health <= 0) && damage > 0) {
  1128. Item* splash = Item::CreateItem(ITEM_SPLASH, FLUID_BLOOD);
  1129. game->addThing(NULL, CreaturePos, splash);
  1130. game->startDecay(splash);
  1131. game->updateTile(CreaturePos);
  1132. }
  1133. #endif //TJ_MONSTER_BLOOD
  1134. }
  1135.  
  1136.  
  1137. Game::Game()
  1138. {
  1139. eventIdCount = 1000;
  1140. this->game_state = GAME_STATE_NORMAL;
  1141. this->map = NULL;
  1142. this->worldType = WORLD_TYPE_PVP;
  1143. OTSYS_THREAD_LOCKVARINIT(gameLock);
  1144. OTSYS_THREAD_LOCKVARINIT(eventLock);
  1145. OTSYS_THREAD_LOCKVARINIT(AutoID::autoIDLock);
  1146. #if defined __EXCEPTION_TRACER__
  1147. OTSYS_THREAD_LOCKVARINIT(maploadlock);
  1148. #endif
  1149. OTSYS_THREAD_SIGNALVARINIT(eventSignal);
  1150. BufferedPlayers.clear();
  1151. OTSYS_CREATE_THREAD(eventThread, this);
  1152.  
  1153. #ifdef __DEBUG_CRITICALSECTION__
  1154. OTSYS_CREATE_THREAD(monitorThread, this);
  1155. #endif
  1156.  
  1157. addEvent(makeTask(DECAY_INTERVAL, boost::bind(&Game::checkDecay,this,DECAY_INTERVAL)));
  1158.  
  1159. #ifdef CVS_DAY_CYCLE
  1160. int32_t daycycle = 3600;
  1161. light_hour_delta = 1440*10/daycycle;
  1162. light_hour = 0;
  1163. lightlevel = LIGHT_LEVEL_NIGHT;
  1164. light_state = LIGHT_STATE_NIGHT;
  1165. addEvent(makeTask(10000, boost::bind(&Game::checkLight, this, 10000)));
  1166. #endif //CVS_DAY_CYCLE
  1167. }
  1168.  
  1169.  
  1170. Game::~Game()
  1171. {
  1172. if(map) {
  1173. delete map;
  1174. }
  1175. }
  1176.  
  1177. void Game::setWorldType(enum_world_type type)
  1178. {
  1179. this->worldType = type;
  1180. }
  1181.  
  1182. enum_game_state Game::getGameState()
  1183. {
  1184. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::getGameState()");
  1185. return game_state;
  1186. }
  1187.  
  1188. int32_t Game::loadMap(std::string filename, std::string filekind) {
  1189. if(!map)
  1190. map = new Map;
  1191.  
  1192. max_players = atoi(g_config.getGlobalString("maxplayers").c_str());
  1193. distanceToKill = atoi(g_config.getGlobalString("dist", "50").c_str());
  1194. return map->loadMap(filename, filekind);
  1195. }
  1196.  
  1197.  
  1198.  
  1199. /*****************************************************************************/
  1200.  
  1201. #ifdef __DEBUG_CRITICALSECTION__
  1202.  
  1203. OTSYS_THREAD_RETURN Game::monitorThread(void *p)
  1204. {
  1205. Game* _this = (Game*)p;
  1206.  
  1207. while (true) {
  1208. OTSYS_SLEEP(6000);
  1209.  
  1210. int32_t ret = OTSYS_THREAD_LOCKEX(_this->gameLock, 60 * 2 * 1000);
  1211. if(ret != OTSYS_THREAD_TIMEOUT) {
  1212. OTSYS_THREAD_UNLOCK(_this->gameLock, NULL);
  1213. continue;
  1214. }
  1215.  
  1216. bool file = false;
  1217. std::ostream *outdriver;
  1218. std::cout << "Error: generating critical section file..." <<std::endl;
  1219. std::ofstream output("deadlock.txt",std::ios_base::app);
  1220. if(output.fail()){
  1221. outdriver = &std::cout;
  1222. file = false;
  1223. }
  1224. else{
  1225. file = true;
  1226. outdriver = &output;
  1227. }
  1228.  
  1229. time_t rawtime;
  1230. time(&rawtime);
  1231. *outdriver << "*****************************************************" << std::endl;
  1232. *outdriver << "Error report - " << std::ctime(&rawtime) << std::endl;
  1233.  
  1234. OTSYS_THREAD_LOCK_CLASS::LogList::iterator it;
  1235. for(it = OTSYS_THREAD_LOCK_CLASS::loglist.begin(); it != OTSYS_THREAD_LOCK_CLASS::loglist.end(); ++it) {
  1236. *outdriver << (it->lock ? "lock - " : "unlock - ") << it->str
  1237. << " threadid: " << it->threadid
  1238. << " time: " << it->time
  1239. << " ptr: " << it->mutexaddr
  1240. << std::endl;
  1241. }
  1242.  
  1243. *outdriver << "*****************************************************" << std::endl;
  1244. if(file)
  1245. ((std::ofstream*)outdriver)->close();
  1246.  
  1247. std::cout << "Error report generated. Killing server." <<std::endl;
  1248. exit(1); //force exit
  1249. }
  1250. }
  1251. #endif
  1252.  
  1253. OTSYS_THREAD_RETURN Game::eventThread(void *p)
  1254. {
  1255. #if defined __EXCEPTION_TRACER__
  1256. ExceptionHandler eventExceptionHandler;
  1257. eventExceptionHandler.InstallHandler();
  1258. #endif
  1259.  
  1260. Game* _this = (Game*)p;
  1261.  
  1262. // basically what we do is, look at the first scheduled item,
  1263. // and then sleep until it's due (or if there is none, sleep until we get an event)
  1264. // of course this means we need to get a notification if there are new events added
  1265. while (true)
  1266. {
  1267. #ifdef __DEBUG__EVENTSCHEDULER__
  1268. std::cout << "schedulercycle start..." << std::endl;
  1269. #endif
  1270.  
  1271. SchedulerTask* task = NULL;
  1272. bool runtask = false;
  1273.  
  1274. // check if there are events waiting...
  1275. OTSYS_THREAD_LOCK(_this->eventLock, "eventThread()")
  1276.  
  1277. int32_t ret;
  1278. if (_this->eventList.size() == 0) {
  1279. // unlock mutex and wait for signal
  1280. ret = OTSYS_THREAD_WAITSIGNAL(_this->eventSignal, _this->eventLock);
  1281. } else {
  1282. // unlock mutex and wait for signal or timeout
  1283. ret = OTSYS_THREAD_WAITSIGNAL_TIMED(_this->eventSignal, _this->eventLock, _this->eventList.top()->getCycle());
  1284. }
  1285. // the mutex is locked again now...
  1286. if (ret == OTSYS_THREAD_TIMEOUT) {
  1287. // ok we had a timeout, so there has to be an event we have to execute...
  1288. #ifdef __DEBUG__EVENTSCHEDULER__
  1289. std::cout << "event found at " << OTSYS_TIME() << " which is to be scheduled at: " << _this->eventList.top()->getCycle() << std::endl;
  1290. #endif
  1291. task = _this->eventList.top();
  1292. _this->eventList.pop();
  1293. }
  1294.  
  1295. if(task) {
  1296. std::map<uint32_t, SchedulerTask*>::iterator it = _this->eventIdMap.find(task->getEventId());
  1297. if(it != _this->eventIdMap.end()) {
  1298. _this->eventIdMap.erase(it);
  1299. runtask = true;
  1300. }
  1301. }
  1302.  
  1303. OTSYS_THREAD_UNLOCK(_this->eventLock, "eventThread()");
  1304. if (task) {
  1305. if(runtask) {
  1306. (*task)(_this);
  1307. }
  1308. delete task;
  1309. }
  1310. }
  1311. #if defined __EXCEPTION_TRACER__
  1312. eventExceptionHandler.RemoveHandler();
  1313. #endif
  1314.  
  1315. }
  1316.  
  1317. uint32_t Game::addEvent(SchedulerTask* event) {
  1318. bool do_signal = false;
  1319. OTSYS_THREAD_LOCK(eventLock, "addEvent()")
  1320.  
  1321. if(event->getEventId() == 0) {
  1322. ++eventIdCount;
  1323. event->setEventId(eventIdCount);
  1324. }
  1325.  
  1326. #ifdef __DEBUG__EVENTSCHEDULER__
  1327. std::cout << "addEvent - " << event->getEventId() << std::endl;
  1328. #endif
  1329.  
  1330. eventIdMap[event->getEventId()] = event;
  1331.  
  1332. /*
  1333. if (eventList.empty() || *event < *eventList.top())
  1334. do_signal = true;
  1335. */
  1336.  
  1337. bool isEmpty = eventList.empty();
  1338. eventList.push(event);
  1339.  
  1340. if(isEmpty || *event < *eventList.top())
  1341. do_signal = true;
  1342.  
  1343. /*
  1344. if (eventList.empty() || *event < *eventList.top())
  1345. do_signal = true;
  1346. */
  1347.  
  1348. OTSYS_THREAD_UNLOCK(eventLock, "addEvent()")
  1349.  
  1350. if (do_signal)
  1351. OTSYS_THREAD_SIGNAL_SEND(eventSignal);
  1352.  
  1353. return event->getEventId();
  1354. }
  1355.  
  1356. bool Game::stopEvent(uint32_t eventid) {
  1357. if(eventid == 0)
  1358. return false;
  1359.  
  1360. OTSYS_THREAD_LOCK(eventLock, "stopEvent()")
  1361.  
  1362. std::map<uint32_t, SchedulerTask*>::iterator it = eventIdMap.find(eventid);
  1363. if(it != eventIdMap.end()) {
  1364.  
  1365. #ifdef __DEBUG__EVENTSCHEDULER__
  1366. std::cout << "stopEvent - eventid: " << eventid << "/" << it->second->getEventId() << std::endl;
  1367. #endif
  1368.  
  1369. //it->second->setEventId(0); //invalidate the event
  1370. eventIdMap.erase(it);
  1371.  
  1372. OTSYS_THREAD_UNLOCK(eventLock, "stopEvent()")
  1373. return true;
  1374. }
  1375.  
  1376. OTSYS_THREAD_UNLOCK(eventLock, "stopEvent()")
  1377. return false;
  1378. }
  1379.  
  1380. /*****************************************************************************/
  1381.  
  1382. uint32_t Game::getPlayersOnline() {return (uint32_t)Player::listPlayer.list.size();};
  1383. uint32_t Game::getMonstersOnline() {return (uint32_t)Monster::listMonster.list.size();};
  1384. uint32_t Game::getNpcsOnline() {return (uint32_t)Npc::listNpc.list.size();};
  1385. uint32_t Game::getCreaturesOnline() {return (uint32_t)listCreature.list.size();};
  1386.  
  1387. Tile* Game::getTile(unsigned short _x, unsigned short _y, unsigned char _z)
  1388. {
  1389. return map->getTile(_x, _y, _z);
  1390. }
  1391.  
  1392. Tile* Game::getTile(const Position& pos)
  1393. {
  1394. return map->getTile(pos);
  1395. }
  1396.  
  1397. void Game::setTile(unsigned short _x, unsigned short _y, unsigned char _z, unsigned short groundId)
  1398. {
  1399. map->setTile(_x, _y, _z, groundId);
  1400. }
  1401.  
  1402. Creature* Game::getCreatureByID(uint32_t id)
  1403. {
  1404. if(id == 0)
  1405. return NULL;
  1406.  
  1407. AutoList<Creature>::listiterator it = listCreature.list.find(id);
  1408. if(it != listCreature.list.end()) {
  1409. return (*it).second;
  1410. }
  1411.  
  1412. return NULL; //just in case the player doesnt exist
  1413. }
  1414.  
  1415. Player* Game::getPlayerByID(uint32_t id)
  1416. {
  1417. if(id == 0)
  1418. return NULL;
  1419.  
  1420. AutoList<Player>::listiterator it = Player::listPlayer.list.find(id);
  1421. if(it != Player::listPlayer.list.end()) {
  1422. return (*it).second;
  1423. }
  1424.  
  1425. return NULL; //just in case the player doesnt exist
  1426. }
  1427.  
  1428. Creature* Game::getCreatureByName(const std::string &s)
  1429. {
  1430. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::getCreatureByName()");
  1431.  
  1432. std::string txt1 = s;
  1433. std::transform(txt1.begin(), txt1.end(), txt1.begin(), upchar);
  1434. for(AutoList<Creature>::listiterator it = listCreature.list.begin(); it != listCreature.list.end(); ++it){
  1435. std::string txt2 = (*it).second->getName();
  1436. std::transform(txt2.begin(), txt2.end(), txt2.begin(), upchar);
  1437. if(txt1 == txt2)
  1438. return it->second;
  1439. }
  1440.  
  1441. return NULL; //just in case the creature doesnt exist
  1442. }
  1443.  
  1444. Player* Game::getPlayerByName(const std::string &s)
  1445. {
  1446. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::getPlayerByName()");
  1447.  
  1448. std::string txt1 = s;
  1449. std::transform(txt1.begin(), txt1.end(), txt1.begin(), upchar);
  1450. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  1451. std::string txt2 = (*it).second->getName();
  1452. std::transform(txt2.begin(), txt2.end(), txt2.begin(), upchar);
  1453. if(txt1 == txt2)
  1454. return it->second;
  1455. }
  1456.  
  1457. return NULL; //just in case the player doesnt exist
  1458. }
  1459.  
  1460. bool Game::placeCreature(Position &pos, Creature* c
  1461. #ifdef YUR_LOGIN_QUEUE
  1462. , int32_t* placeInQueue
  1463. #endif //YUR_LOGIN_QUEUE
  1464. )
  1465. {
  1466. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::placeCreature()");
  1467. bool success = false;
  1468. Player *p = dynamic_cast<Player*>(c);
  1469. Monster *monsterzin = dynamic_cast<Monster*>(c);
  1470.  
  1471. #ifdef YUR_LOGIN_QUEUE
  1472. if (!p || c->access >= g_config.ACCESS_ENTER ||
  1473. #ifdef YUR_PREMIUM_PROMOTION
  1474. (p->isPremmium() && !g_config.QUEUE_PREMMY) ||
  1475. #endif //YUR_PREMIUM_PROMOTION
  1476. loginQueue.login(p->accountNumber, getPlayersOnline(), max_players, placeInQueue))
  1477. {
  1478. #else //YUR_LOGIN_QUEUE
  1479. if (!p || c->access >= g_config.ACCESS_ENTER || getPlayersOnline() < max_players)
  1480. {
  1481. #endif //YUR_LOGIN_QUEUE
  1482.  
  1483. success = map->placeCreature(pos, c);
  1484. if(success)
  1485. {
  1486. c->useThing();
  1487.  
  1488. c->setID();
  1489. //std::cout << "place: " << c << " " << c->getID() << std::endl;
  1490. listCreature.addList(c);
  1491. c->addList();
  1492. c->isRemoved = false;
  1493.  
  1494. sendAddThing(NULL,c->pos,c);
  1495.  
  1496. if(p)
  1497. {
  1498. checkRecord();
  1499. #ifdef __DEBUG_PLAYERS__
  1500. std::cout << (uint32_t)getPlayersOnline() << " players online." << std::endl;
  1501. #endif
  1502. #ifdef YUR_GUILD_SYSTEM
  1503. Guilds::ReloadGuildInfo(p);
  1504. #endif //YUR_GUILD_SYSTEM
  1505. /*#ifdef ELEM_VIP_LIST
  1506. vipLogin(p);
  1507. #endif //ELEM_VIP_LIST*/
  1508. }
  1509.  
  1510. if(p){
  1511. c->eventCheck = addEvent(makeTask(1000, std::bind2nd(std::mem_fun(&Game::checkCreature), c->getID())));
  1512. }
  1513. else{
  1514. c->eventCheck = addEvent(makeTask(1000, std::bind2nd(std::mem_fun(&Game::checkCreature), c->getID())));
  1515. }
  1516.  
  1517. //c->eventCheckAttacking = addEvent(makeTask(2000, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), c->getID())));
  1518. }
  1519. }
  1520. else {
  1521. //we cant add the player, server is full
  1522. success = false;
  1523. }
  1524.  
  1525. #ifdef __MIZIAK_CREATURESCRIPTS__
  1526. if(p)
  1527. actions.creatureEvent("login", p, NULL, NULL, NULL);
  1528. #endif //__MIZIAK_CREATURESCRIPTS__
  1529.  
  1530.  
  1531. if(monsterzin){
  1532. c->masterPos.x = c->pos.x;
  1533. c->masterPos.y = c->pos.y;
  1534. c->masterPos.z = c->pos.z;
  1535. }
  1536. return success;
  1537. }
  1538.  
  1539. bool Game::removeCreature(Creature* c)
  1540. {
  1541. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::removeCreature()");
  1542. if(c->isRemoved == true)
  1543. return false;
  1544. #ifdef __DEBUG__
  1545. std::cout << "removing creature "<< std::endl;
  1546. #endif
  1547.  
  1548. #ifdef __MIZIAK_CREATURESCRIPTS__
  1549. Player* pc = dynamic_cast<Player*>(c);
  1550. if(pc)
  1551. if(!pc->dieorlogout)
  1552. actions.creatureEvent("logout", pc, NULL, NULL, NULL);
  1553. #endif //__MIZIAK_CREATURESCRIPTS__
  1554.  
  1555. if(!removeThing(NULL,c->pos,c))
  1556. return false;
  1557.  
  1558. //std::cout << "remove: " << c << " " << c->getID() << std::endl;
  1559. listCreature.removeList(c->getID());
  1560. c->removeList();
  1561. c->isRemoved = true;
  1562.  
  1563. if(g_config.SUMMON_BODIES){
  1564. c->isRemoved = true;
  1565.  
  1566. Creature *summon = NULL;
  1567. for(std::list<Creature*>::iterator cit = c->summons.begin(); cit != c->summons.end(); ++cit) {
  1568. summon = (*cit);
  1569. Position CreaturePos = summon->pos;
  1570. Tile *tile = map->getTile(CreaturePos);
  1571. Item *corpseitem = Item::CreateItem(summon->getLookCorpse());
  1572. corpseitem->pos = CreaturePos; /*summoned bodies by Cayan*/
  1573. tile->addThing(corpseitem);
  1574. removeCreature(summon);
  1575. updateTile(CreaturePos);
  1576. }
  1577. }
  1578. else
  1579. {
  1580. c->isRemoved = true;
  1581.  
  1582. //for(std::list<Creature*>::iterator cit = c->summons.begin(); cit != c->summons.end(); ++cit) {
  1583. //removeCreature(*cit);
  1584. //}
  1585. }
  1586.  
  1587.  
  1588. stopEvent(c->eventCheck);
  1589. stopEvent(c->eventCheckAttacking);
  1590. stopEvent(c->eventCheckFollow);
  1591.  
  1592. Player* player = dynamic_cast<Player*>(c);
  1593. if(player){
  1594.  
  1595. #ifdef HUCZU_SKULLS
  1596. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  1597. Player *on = dynamic_cast<Player*>(it->second);
  1598. if(on && player->isYellowTo(on)){
  1599. on->removeFromYellowList(player);
  1600. }
  1601. if(on && on->hasAttacked(player)){
  1602. on->removeFromAttakedList(player);
  1603. }
  1604. player->clearAttakedList();
  1605. player->clearYellowList();
  1606. }
  1607.  
  1608. if(player->party != 0)
  1609. LeaveParty(player);
  1610. #endif //HUCZU_SKULLS
  1611.  
  1612. if(player->tradePartner != 0) {
  1613. playerCloseTrade(player);
  1614. }
  1615. if(player->eventAutoWalk)
  1616. stopEvent(player->eventAutoWalk);
  1617.  
  1618. Tile* fromT = getTile(player->pos);
  1619. if(fromT && fromT->ground)
  1620. actions.luaWalkOff(player,player->pos,fromT->ground->getID(),fromT->ground->getUniqueId(),fromT->ground->getActionId());
  1621.  
  1622. g_chat.removeUserFromAllChannels(player);
  1623. if(!IOPlayer::instance()->savePlayer(player)){
  1624. std::cout << "Error while saving player: " << player->getName() << std::endl;
  1625. }
  1626. std::cout << (uint32_t)getPlayersOnline() << " players online." << std::endl;
  1627.  
  1628.  
  1629. /*#ifdef ELEM_VIP_LIST
  1630. vipLogout(c->getName());
  1631. #endif //ELEM_VIP_LIST*/
  1632.  
  1633.  
  1634. }
  1635. this->FreeThing(c);
  1636. return true;
  1637. }
  1638.  
  1639. void Game::thingMove(Creature *creature, Thing *thing,
  1640. unsigned short to_x, unsigned short to_y, unsigned char to_z, unsigned char count)
  1641. {
  1642. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 1");
  1643.  
  1644. Tile *fromTile = map->getTile(thing->pos);
  1645.  
  1646. if (fromTile)
  1647. {
  1648. int32_t oldstackpos = fromTile->getThingStackPos(thing);
  1649. thingMoveInternal(creature, thing->pos.x, thing->pos.y, thing->pos.z, oldstackpos, 0, to_x, to_y, to_z, count);
  1650. }
  1651. }
  1652.  
  1653.  
  1654. void Game::thingMove(Creature *creature, unsigned short from_x, unsigned short from_y, unsigned char from_z,
  1655. unsigned char stackPos, unsigned short itemid, unsigned short to_x, unsigned short to_y, unsigned char to_z, unsigned char count)
  1656. {
  1657. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 2");
  1658.  
  1659. Tile *fromTile = getTile(from_x, from_y, from_z);
  1660. if(!fromTile)
  1661. return;
  1662.  
  1663. #ifdef FIXY
  1664. if(dynamic_cast<Player*>(creature) && fromTile && !fromTile->ground) {
  1665. dynamic_cast<Player*>(creature)->sendCancelWalk();
  1666. return;
  1667. }
  1668. #endif //FIXY
  1669.  
  1670. Tile *toTile = getTile(to_x, to_y, to_z);
  1671. if(!toTile)
  1672. return;
  1673.  
  1674. #ifdef FIXY
  1675. if (toTile->isHouse() && !fromTile->isHouse())
  1676. return;
  1677. #endif //FIXY
  1678.  
  1679. Thing* thing = fromTile->getThingByStackPos(stackPos);
  1680. if(!thing)
  1681. return;
  1682.  
  1683. Item* item = dynamic_cast<Item*>(thing);
  1684.  
  1685. if(item && (item->getID() != itemid || item != fromTile->getTopDownItem()))
  1686. return;
  1687.  
  1688. thingMoveInternal(creature, from_x, from_y, from_z, stackPos, itemid, to_x, to_y, to_z, count);
  1689. }
  1690.  
  1691. //container/inventory to container/inventory
  1692. void Game::thingMove(Player *player,
  1693. unsigned char from_cid, unsigned char from_slotid, unsigned short itemid, bool fromInventory,
  1694. unsigned char to_cid, unsigned char to_slotid, bool toInventory,
  1695. unsigned char count)
  1696. {
  1697. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 3");
  1698.  
  1699. thingMoveInternal(player, from_cid, from_slotid, itemid, fromInventory,
  1700. to_cid, to_slotid, toInventory, count);
  1701. }
  1702.  
  1703. //container/inventory to ground
  1704. void Game::thingMove(Player *player,
  1705. unsigned char from_cid, unsigned char from_slotid, unsigned short itemid, bool fromInventory,
  1706. const Position& toPos, unsigned char count)
  1707. {
  1708. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 4");
  1709. Container *fromContainer = player->getContainer(from_cid);
  1710. if(fromContainer && !fromContainer->shop.empty())
  1711. return;
  1712.  
  1713. #ifdef FIXY
  1714. Tile *toTile = getTile(toPos.x, toPos.y, toPos.z);
  1715. if(!toTile)
  1716. return;
  1717.  
  1718. if (player) {
  1719. Tile *fromTile = getTile(player->pos);
  1720. if(!fromTile->isHouse() && toTile->isHouse())
  1721. return;
  1722. }
  1723. #endif //FIXY
  1724.  
  1725. thingMoveInternal(player, from_cid, from_slotid, itemid, fromInventory, toPos, count);
  1726. }
  1727.  
  1728. //ground to container/inventory
  1729. void Game::thingMove(Player *player,
  1730. const Position& fromPos, unsigned char stackPos, unsigned short itemid,
  1731. unsigned char to_cid, unsigned char to_slotid, bool toInventory,
  1732. unsigned char count)
  1733. {
  1734. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 5");
  1735. thingMoveInternal(player, fromPos, stackPos, itemid, to_cid, to_slotid, toInventory, count);
  1736. }
  1737.  
  1738. #ifdef FIXY
  1739. bool Game::onPrepareMoveThing(Creature* player, /*const*/ Thing* thing,
  1740. const Position& fromPos, const Position& toPos, int32_t count)
  1741. {
  1742. const Creature* movingCreature = dynamic_cast<const Creature*>(thing);
  1743. Player *playa = dynamic_cast<Player*>(thing);
  1744.  
  1745. if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) &&
  1746. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  1747. {
  1748. player->sendCancel("Destination is out of reach.");
  1749. return false;
  1750. }
  1751. //RZUCANIE GM PO EKRANIE?
  1752. else if( ((abs(fromPos.x - toPos.x) > thing->throwRange) || (abs(fromPos.y - toPos.y) > thing->throwRange)
  1753. || (fromPos.z != toPos.z)) && player->access >= g_config.ACCESS_REMOTE) {
  1754. if(player == thing){
  1755. teleport(player,toPos);
  1756.  
  1757. if(!playa->gmInvisible){
  1758. globalMagicEffect(fromPos, NM_ME_PUFF);
  1759. globalMagicEffect(toPos, NM_ME_ENERGY_AREA);
  1760. }
  1761. else
  1762. {
  1763. playa->sendMagicEffect(fromPos, NM_ME_PUFF);
  1764. playa->sendMagicEffect(toPos, NM_ME_ENERGY_AREA);
  1765. }
  1766. }
  1767. else
  1768. teleport(thing,toPos);
  1769. }
  1770.  
  1771.  
  1772. 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)))) {
  1773. player->sendCancel("Destination is out of reach.");
  1774. return false;
  1775. }
  1776.  
  1777.  
  1778. else if(player->access < g_config.ACCESS_REMOTE && movingCreature && fromPos.z != toPos.z){
  1779. player->sendCancel("Destination is out of reach.");
  1780. return false;
  1781. }
  1782.  
  1783. else {
  1784. const Item* item = dynamic_cast<const Item*>(thing);
  1785. if(item) {
  1786. if(item->getID() == ITEM_FOOTBALL &&
  1787. player->access < g_config.getGlobalNumber("accessfootball", 3) && (
  1788. (abs(player->pos.x - toPos.x) > 2) ||
  1789. (abs(player->pos.y - toPos.y) > 2) ||
  1790. (player->pos.z != fromPos.z))
  1791. ){
  1792. player->sendCancel("Nie mozesz tak daleko kopnac.");
  1793. return false;
  1794. }
  1795. int32_t blockstate = 0;
  1796. if(item->isBlocking())
  1797. blockstate |= BLOCK_SOLID;
  1798.  
  1799. if(item->isPickupable() || !item->isNotMoveable())
  1800. blockstate |= BLOCK_PICKUPABLE;
  1801.  
  1802. if(blockstate != 0) {
  1803. switch(map->canThrowObjectTo(fromPos, toPos, blockstate)) {
  1804. case RET_NOERROR:
  1805. return true;
  1806. break;
  1807.  
  1808. case RET_CANNOTTHROW:
  1809. player->sendCancel("Nie mozesz tam rzucic.");
  1810. return false;
  1811. break;
  1812.  
  1813. case RET_CREATUREBLOCK:
  1814. case RET_NOTENOUGHROOM:
  1815. #ifdef KOSZ
  1816. if(item->getID() != ITEM_DUSTBIN){
  1817. player->sendCancel("Przykro mi, nie ma miejsca.");
  1818. return false;
  1819. }
  1820. #else
  1821. player->sendCancel("Przykro mi, nie ma miejsca.");
  1822. return false;
  1823. #endif //KOSZ
  1824. break;
  1825.  
  1826. default:
  1827. player->sendCancel("Sorry not possible.");
  1828. return false;
  1829. break;
  1830. }
  1831. }
  1832. }
  1833. }
  1834.  
  1835. return true;
  1836. }
  1837. #else //FIXY
  1838. bool Game::onPrepareMoveThing(Creature* player, const Thing* thing,
  1839. const Position& fromPos, const Position& toPos, int32_t count)
  1840. {
  1841. if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) &&
  1842. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  1843. {
  1844. player->sendCancel("Za daleko...");
  1845. return false;
  1846. }
  1847. else if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) &&
  1848. ((abs(fromPos.x - toPos.x) > thing->throwRange) || (abs(fromPos.y - toPos.y) > thing->throwRange)
  1849. || (fromPos.z != toPos.z) /*TODO: Make it possible to throw items to different floors ))*/
  1850. {
  1851. player->sendCancel("Destination is out of reach.");
  1852. return false;
  1853. }
  1854. else {
  1855. const Item* item = dynamic_cast<const Item*>(thing);
  1856. if(item) {
  1857. int32_t blockstate = 0;
  1858. if(item->isBlocking())
  1859. blockstate |= BLOCK_SOLID;
  1860.  
  1861. if(item->isPickupable() || !item->isNotMoveable())
  1862. blockstate |= BLOCK_PICKUPABLE;
  1863.  
  1864. if(blockstate != 0) {
  1865. switch(map->canThrowObjectTo(fromPos, toPos, blockstate)) {
  1866. case RET_NOERROR:
  1867. return true;
  1868. break;
  1869.  
  1870. case RET_CANNOTTHROW:
  1871. player->sendCancel("Nie mozesz tam rzucic.");
  1872. return false;
  1873. break;
  1874.  
  1875. case RET_CREATUREBLOCK:
  1876. case RET_NOTENOUGHROOM:
  1877. player->sendCancel("Przykro mi, nie ma miejsca.");
  1878. return false;
  1879. break;
  1880.  
  1881. default:
  1882. player->sendCancel("Sorry not possible.");
  1883. return false;
  1884. break;
  1885. }
  1886. }
  1887. }
  1888. }
  1889. return true;
  1890. }
  1891. #endif //FIXY
  1892. /*ground -> ground*/
  1893. bool Game::onPrepareMoveThing(Creature* creature, const Thing* thing,
  1894. const Tile* fromTile, const Tile *toTile, int32_t count)
  1895. {
  1896. const Player* player = dynamic_cast<const Player*>(creature);
  1897.  
  1898. const Item *item = dynamic_cast<const Item*>(thing);
  1899. const Creature* movingCreature = dynamic_cast<const Creature*>(thing);
  1900. const Player* movingPlayer = dynamic_cast<const Player*>(thing);
  1901.  
  1902. /* if(movingCreature){
  1903. addEvent(makeTask(2000, std::mem_fun(&Game::onPrepareMoveCreature, creature, movingCreature, fromTile, toTile))));
  1904. }*/
  1905. if(item && !item->canMovedTo(toTile)) {
  1906. creature->sendCancel("Sorry, not possible.");
  1907. return false;
  1908. }
  1909.  
  1910. else if(movingCreature && !movingCreature->canMovedTo(toTile)) {
  1911. if(player && player->eventCheckFollow == 0) {
  1912. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  1913. player->sendCancelWalk();
  1914. }
  1915.  
  1916. return false;
  1917. }
  1918. else if(!movingPlayer && toTile && toTile->floorChange()) {
  1919. creature->sendCancel("Sorry, not possible.");
  1920. return false;
  1921. }
  1922. else if(movingCreature && toTile && !toTile->ground) {
  1923. if(player) {
  1924. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  1925. player->sendCancelWalk();
  1926. }
  1927.  
  1928. return false;
  1929. }
  1930.  
  1931. if (fromTile && fromTile->splash == thing && fromTile->splash->isNotMoveable()) {
  1932. creature->sendCancel("You cannot move this object.");
  1933. #ifdef __DEBUG__
  1934. cout << creature->getName() << " is trying to move a splash item!" << std::endl;
  1935. #endif
  1936. return false;
  1937. }
  1938. else if (item && item->isNotMoveable()) {
  1939. creature->sendCancel("You cannot move this object.");
  1940. #ifdef __DEBUG__
  1941. cout << creature->getName() << " is trying to move an unmoveable item!" << std::endl;
  1942. #endif
  1943. return false;
  1944. }
  1945.  
  1946. #ifdef TLM_HOUSE_SYSTEM
  1947. if (item && toTile && toTile->isHouse())
  1948. {
  1949. const Container* container = dynamic_cast<const Container*>(item);
  1950. int32_t moving = container? container->getItemHoldingCount() : 1;
  1951.  
  1952. if (moving + toTile->getItemHoldingCount() > g_config.MAX_HOUSE_TILE_ITEMS)
  1953. {
  1954. creature->sendCancel("You cannot put more items on a house tile.");
  1955. return false;
  1956. }
  1957. }
  1958. #endif //TLM_HOUSE_SYSTEM
  1959.  
  1960. return true; //return thing->canMovedTo(toTile);
  1961. }
  1962. /*inventory -> container*/
  1963. bool Game::onPrepareMoveThing(Player* player, const Item* fromItem, slots_t fromSlot,
  1964. const Container* toContainer, const Item* toItem, int32_t count)
  1965. {
  1966. if(toContainer && !toContainer->shop.empty()){
  1967. creatureUseShop(player, fromItem->getID(), count, "toShop");
  1968. return false;
  1969. }
  1970. if(toContainer && toContainer->getParent() && !toContainer->getParent()->shop.empty())
  1971. return false;
  1972. if(!fromItem->isPickupable()) {
  1973. player->sendCancel("Sorry, not possible.");
  1974. return false;
  1975. }
  1976. else {
  1977. const Container *itemContainer = dynamic_cast<const Container*>(fromItem);
  1978. if(itemContainer) {
  1979. if(itemContainer->isHoldingItem(toContainer) || (toContainer == itemContainer)) {
  1980. player->sendCancel("To jest niemozliwe!");
  1981. return false;
  1982. }
  1983. }
  1984.  
  1985. if((!fromItem->isStackable() || !toItem || fromItem->getID() != toItem->getID() || toItem->getItemCountOrSubtype() >= 100) && toContainer->size() + 1 > toContainer->capacity()) {
  1986. player->sendCancel("Przykro mi, nie ma miejsca.");
  1987. return false;
  1988. }
  1989.  
  1990. Container const *topContainer = toContainer->getTopParent();
  1991. int32_t itemsToadd;
  1992. if(!topContainer)
  1993. topContainer = toContainer;
  1994.  
  1995. Container const *fromContainer = dynamic_cast<const Container*>(fromItem);
  1996. if(fromContainer)
  1997. itemsToadd = fromContainer->getItemHoldingCount() + 1;
  1998. else
  1999. itemsToadd = 1;
  2000.  
  2001. if(topContainer->depot != 0 && player->max_depot_items != 0 && topContainer->getItemHoldingCount() + itemsToadd >= player->max_depot_items){
  2002. player->sendCancel("Nie mozesz polozyc wiecej przedmiotow w depo.");
  2003. return false;
  2004. }
  2005. }
  2006. return true;
  2007. }
  2008.  
  2009. /*container -> container*/
  2010. /*ground -> container*/
  2011. bool Game::onPrepareMoveThing(Player* player,
  2012. const Position& fromPos, const Container* fromContainer, const Item* fromItem,
  2013. const Position& toPos, const Container* toContainer, const Item* toItem, int32_t count)
  2014. {
  2015. if(fromContainer && toContainer && (!fromContainer->shop.empty() || !toContainer->shop.empty())){
  2016. creatureUseShop(player, fromItem->getID(), count, (!fromContainer->shop.empty() ? "fromShop" : "toShop"));
  2017. return false;
  2018. }
  2019.  
  2020. if(!fromContainer && toContainer && !toContainer->shop.empty())
  2021. return false;
  2022. if(toContainer && toContainer->getParent() && !toContainer->getParent()->shop.empty())
  2023. return false;
  2024.  
  2025. if (player->access < g_config.ACCESS_REMOTE &&
  2026. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  2027. {
  2028. player->sendCancel("Za daleko...");
  2029. return false;
  2030. }
  2031. else if (player->access < g_config.ACCESS_REMOTE &&
  2032. ((abs(fromPos.x - toPos.x) > fromItem->throwRange) || (abs(fromPos.y - toPos.y) > fromItem->throwRange)
  2033. || (fromPos.z != toPos.z)))
  2034. {
  2035. player->sendCancel("Destination is out of reach.");
  2036. return false;
  2037. }
  2038.  
  2039. if(!fromItem->isPickupable()) {
  2040. player->sendCancel("You cannot move this object.");
  2041. return false;
  2042. }
  2043. else {
  2044. if((!fromItem->isStackable() || !toItem || fromItem->getID() != toItem->getID() || toItem->getItemCountOrSubtype() >= 100) && toContainer->size() + 1 > toContainer->capacity()) {
  2045. player->sendCancel("Przykro mi, nie ma miejsca.");
  2046. return false;
  2047. }
  2048.  
  2049. const Container *itemContainer = dynamic_cast<const Container*>(fromItem);
  2050. if(itemContainer) {
  2051. if(itemContainer->isHoldingItem(toContainer) || (toContainer == itemContainer) || (fromContainer && fromContainer == itemContainer)) {
  2052. player->sendCancel("To jest niemozliwe!");
  2053. return false;
  2054. }
  2055. }
  2056.  
  2057. double itemWeight = (fromItem->isStackable() ? Item::items[fromItem->getID()].weight * std::max(1, count) : fromItem->getWeight());
  2058. if((!fromContainer || !player->isHoldingContainer(fromContainer)) && player->isHoldingContainer(toContainer)) {
  2059. if(player->access < g_config.ACCESS_PROTECT && player->getFreeCapacity() < itemWeight) {
  2060. player->sendCancel("Ten przedmiot jest za ciezki.");
  2061. return false;
  2062. }
  2063. }
  2064.  
  2065. Container const *topContainer = toContainer->getTopParent();
  2066. int32_t itemsToadd;
  2067. if(!topContainer)
  2068. topContainer = toContainer;
  2069.  
  2070. Container const *fromContainer = dynamic_cast<const Container*>(fromItem);
  2071. if(fromContainer)
  2072. itemsToadd = fromContainer->getItemHoldingCount() + 1;
  2073. else
  2074. itemsToadd = 1;
  2075.  
  2076. if(topContainer->depot != 0 && player->max_depot_items != 0 && topContainer->getItemHoldingCount() >= player->max_depot_items){
  2077. player->sendCancel("Nie mozesz polozyc wiecej przedmiotow w depo.");
  2078. return false;
  2079. }
  2080. }
  2081. return true;
  2082. }
  2083.  
  2084. /*ground -> ground*/
  2085. bool Game::onPrepareMoveCreature(Creature *creature, const Creature* creatureMoving,
  2086. const Tile *fromTile, const Tile *toTile)
  2087. {
  2088. const Player* playerMoving = dynamic_cast<const Player*>(creatureMoving);
  2089. Player* player = dynamic_cast<Player*>(creature);
  2090.  
  2091. #ifdef _BBK_PUSH_DELAY
  2092. if(player && player != creatureMoving && player->pushDelay > 0)
  2093. {
  2094. player->sendCancel("Wait a moment.");
  2095. return false;
  2096. }
  2097. else if(player)
  2098. player->pushDelay = 2*1000; //2 sec
  2099.  
  2100. //wypychanie z depo
  2101. if(player && playerMoving && player != playerMoving && fromTile->isPz() && !toTile->isPz())
  2102. {
  2103. player->sendCancel("Sorry, not possible.");
  2104. return false;
  2105. }
  2106. //wepchanie do depo
  2107. if(player && playerMoving && playerMoving->pzLocked && toTile->isPz())
  2108. {
  2109. player->sendCancel("Sorry, not possible.");
  2110. player->sendCancelWalk();
  2111. return false;
  2112. }
  2113. //wchodzenie do depo
  2114. if(player && player->pzLocked && toTile->isPz())
  2115. {
  2116. player->sendCancel("You can not enter a protection zone after attacking another player.");
  2117. player->sendCancelWalk();
  2118. return false;
  2119. }
  2120. #endif //_BBK_PUSH_DELAY
  2121.  
  2122. if (creature->access < g_config.ACCESS_PROTECT && creature != creatureMoving && !creatureMoving->isPushable())
  2123. {
  2124. creature->sendCancel("Sorry, not possible.");
  2125. return false;
  2126. }
  2127. else if(creature != creatureMoving && toTile->floorChange()){
  2128. creature->sendCancel("Sorry, not possible.");
  2129. return false;
  2130. }
  2131. else if(creature != creatureMoving && toTile->getTeleportItem()){
  2132. creature->sendCancel("Sorry, not possible.");
  2133. return false;
  2134. }
  2135.  
  2136. return true;
  2137. }
  2138.  
  2139. /*ground -> inventory*/
  2140. bool Game::onPrepareMoveThing(Player *player, const Position& fromPos, const Item *item,
  2141. slots_t toSlot, int32_t count)
  2142. {
  2143. if (player->access < g_config.ACCESS_REMOTE &&
  2144. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  2145. {
  2146. player->sendCancel("It's too far.");
  2147. return false;
  2148. }
  2149. else if(!item->isPickupable()) {
  2150. player->sendCancel("You cannot move this object.");
  2151. return false;
  2152. }
  2153.  
  2154. double itemWeight = (item->isStackable() ? Item::items[item->getID()].weight * std::max(1, count) : item->getWeight());
  2155. if(player->access < g_config.ACCESS_PROTECT && player->getFreeCapacity() < itemWeight) {
  2156. player->sendCancel("This object is too heavy.");
  2157. return false;
  2158. }
  2159.  
  2160. return true;
  2161. }
  2162.  
  2163. /*inventory -> inventory*/
  2164. bool Game::onPrepareMoveThing(Player *player, slots_t fromSlot, const Item *fromItem,
  2165. slots_t toSlot, const Item *toItem, int32_t count)
  2166. {
  2167. if(toItem && (!toItem->isStackable() || toItem->getID() != fromItem->getID())) {
  2168. player->sendCancel("There is not enough room.");
  2169. return false;
  2170. }
  2171.  
  2172. return true;
  2173. }
  2174.  
  2175. /*container -> inventory*/
  2176. bool Game::onPrepareMoveThing(Player *player, const Container *fromContainer, const Item *fromItem,
  2177. slots_t toSlot, const Item *toItem, int32_t count)
  2178. {
  2179. if(fromContainer && !fromContainer->shop.empty()){
  2180. creatureUseShop(player, fromItem->getID(), count, "fromShop");
  2181. return false;
  2182. }
  2183. #ifdef _REX_FIGHT_MOD_
  2184. if (toItem && (toItem->getID() == fromItem->getID() && !toItem->isStackable())){
  2185. #else
  2186. if(toItem && (!toItem->isStackable() || toItem->getID() != fromItem->getID())) {
  2187. #endif //Segundo em container -> inventory
  2188. player->sendCancel("There is not enough room.");
  2189. return false;
  2190. }
  2191.  
  2192. double itemWeight = (fromItem->isStackable() ? Item::items[fromItem->getID()].weight * std::max(1, count) : fromItem->getWeight());
  2193. if(player->access < g_config.ACCESS_PROTECT && !player->isHoldingContainer(fromContainer) &&
  2194. player->getFreeCapacity() < itemWeight) {
  2195. player->sendCancel("This object is too heavy.");
  2196. return false;
  2197. }
  2198.  
  2199. return true;
  2200. }
  2201.  
  2202. /*->inventory*/
  2203. bool Game::onPrepareMoveThing(Player *player, const Item *item,
  2204. slots_t toSlot, int32_t count)
  2205. {
  2206. switch(toSlot)
  2207. {
  2208. case SLOT_HEAD:
  2209. if(item->getSlotPosition() & SLOTP_HEAD)
  2210. return true;
  2211. break;
  2212. case SLOT_NECKLACE:
  2213. if(item->getSlotPosition() & SLOTP_NECKLACE)
  2214. return true;
  2215. break;
  2216. case SLOT_BACKPACK:
  2217. if(item->getSlotPosition() & SLOTP_BACKPACK)
  2218. return true;
  2219. break;
  2220. case SLOT_ARMOR:
  2221. if(item->getSlotPosition() & SLOTP_ARMOR)
  2222. return true;
  2223. break;
  2224. case SLOT_RIGHT:
  2225. if(item->getSlotPosition() & SLOTP_RIGHT){
  2226. #ifdef _REX_CVS_MOD_
  2227. //One weapon for hand by ReX
  2228. if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_LEFT] != NULL && player->items[SLOT_LEFT]->isWeapon() && player->items[SLOT_LEFT]->getWeaponType() != SHIELD){
  2229. player->sendCancel("You may use only one weapon.");
  2230. return false;
  2231. }
  2232. #endif
  2233. else if(item->getSlotPosition() & SLOTP_TWO_HAND){
  2234. if(player->items[SLOT_LEFT] != NULL){
  2235. player->sendCancel("First remove the two-handed item.");
  2236. return false;
  2237. }
  2238. return true ;
  2239. }
  2240. else{
  2241. if(player->items[SLOT_LEFT]){
  2242. #ifdef _REX_CVS_MOD_
  2243. //One weapon for hand by ReX
  2244. if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_LEFT] != NULL && player->items[SLOT_LEFT]->isWeapon() && player->items[SLOT_LEFT]->getWeaponType() != SHIELD){
  2245. player->sendCancel("You may use only one weapon.");
  2246. return false;
  2247. }
  2248. #endif
  2249. else if(player->items[SLOT_LEFT]->getSlotPosition() & SLOTP_TWO_HAND){
  2250. player->sendCancel("First remove the two-handed item.");
  2251. return false;
  2252. }
  2253. return true;
  2254. }
  2255. return true;
  2256. }
  2257. }
  2258. break;
  2259. case SLOT_LEFT:
  2260. if(item->getSlotPosition() & SLOTP_LEFT){
  2261. #ifdef _REX_CVS_MOD_
  2262. //One weapon for hand by ReX
  2263. if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_RIGHT] != NULL && player->items[SLOT_RIGHT]->isWeapon() && player->items[SLOT_RIGHT]->getWeaponType() != SHIELD){
  2264. player->sendCancel("You may use only one weapon.");
  2265. return false;
  2266. }
  2267. #endif
  2268. else if(item->getSlotPosition() & SLOTP_TWO_HAND){
  2269. if(player->items[SLOT_RIGHT] != NULL){
  2270. player->sendCancel("First remove the two-handed item.");
  2271. return false;
  2272. }
  2273. return true ;
  2274. }
  2275. else{
  2276. if(player->items[SLOT_RIGHT]){
  2277. #ifdef _REX_CVS_MOD_
  2278. //One weapon for hand by ReX
  2279. if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_RIGHT] != NULL && player->items[SLOT_RIGHT]->isWeapon() && player->items[SLOT_RIGHT]->getWeaponType() != SHIELD){
  2280. player->sendCancel("You may use only one weapon.");
  2281. return false;
  2282. }
  2283. #endif
  2284. else if(player->items[SLOT_RIGHT]->getSlotPosition() & SLOTP_TWO_HAND){
  2285. player->sendCancel("First remove the two-handed item.");
  2286. return false;
  2287. }
  2288. return true;
  2289. }
  2290. return true;
  2291. }
  2292. }
  2293. break;
  2294. case SLOT_LEGS:
  2295. if(item->getSlotPosition() & SLOTP_LEGS)
  2296. return true;
  2297. break;
  2298. case SLOT_FEET:
  2299. if(item->getSlotPosition() & SLOTP_FEET)
  2300. return true;
  2301. break;
  2302. case SLOT_RING:
  2303. if(item->getSlotPosition() & SLOTP_RING
  2304. #ifdef _REX_CVS_MOD_
  2305. || item->getID() == 2208
  2306. #endif
  2307. )
  2308. return true;
  2309. break;
  2310. case SLOT_AMMO:
  2311. if(item->getSlotPosition() & SLOTP_AMMO)
  2312. return true;
  2313. break;
  2314. }
  2315.  
  2316. player->sendCancel("You cannot put that object in that place.");
  2317. return false;
  2318. }
  2319.  
  2320. //container/inventory to container/inventory
  2321. void Game::thingMoveInternal(Player *player,
  2322. unsigned short from_cid, unsigned short from_slotid, unsigned short itemid,
  2323. bool fromInventory,unsigned short to_cid, unsigned short to_slotid, bool toInventory,
  2324. unsigned short count)
  2325. {
  2326. Container *fromContainer = NULL;
  2327. Container *toContainer = NULL;
  2328. Item *fromItem = NULL;
  2329. Item *toItem = NULL;
  2330.  
  2331. if(fromInventory) {
  2332. fromItem = player->getItem(from_cid);
  2333. fromContainer = dynamic_cast<Container *>(fromItem);
  2334. }
  2335. else {
  2336. fromContainer = player->getContainer(from_cid);
  2337.  
  2338. if(fromContainer) {
  2339. if(from_slotid >= fromContainer->size())
  2340. return;
  2341.  
  2342. fromItem = fromContainer->getItem(from_slotid);
  2343. }
  2344. }
  2345.  
  2346. if(toInventory) {
  2347. toItem = player->getItem(to_cid);
  2348. toContainer = dynamic_cast<Container *>(toItem);
  2349. }
  2350. else {
  2351. toContainer = player->getContainer(to_cid);
  2352.  
  2353. if(toContainer) {
  2354. if(to_slotid >= toContainer->capacity())
  2355. return;
  2356.  
  2357. toItem = toContainer->getItem(to_slotid);
  2358. Container *toSlotContainer = dynamic_cast<Container*>(toItem);
  2359. if(toSlotContainer) {
  2360. toContainer = toSlotContainer;
  2361. toItem = NULL;
  2362. }
  2363. }
  2364. }
  2365.  
  2366. if(!fromItem || (toItem == fromItem) || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()) || fromItem->getID() != itemid)
  2367. return;
  2368.  
  2369. //Container to container
  2370. if(!fromInventory && fromContainer && toContainer) {
  2371. Position fromPos = (fromContainer->pos.x == 0xFFFF ? player->pos : fromContainer->pos);
  2372. Position toPos = (toContainer->pos.x == 0xFFFF ? player->pos : toContainer->pos);
  2373.  
  2374. if(onPrepareMoveThing(player, fromPos, fromContainer, fromItem, toPos, toContainer, toItem, count)) {
  2375.  
  2376. autoCloseTrade(fromItem, true);
  2377. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2378. int32_t oldToCount = 0;
  2379.  
  2380. //move around an item in a container
  2381. if(fromItem->isStackable()) {
  2382. if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2383. {
  2384. oldToCount = toItem->getItemCountOrSubtype();
  2385. int32_t newToCount = std::min(100, oldToCount + count);
  2386. toItem->setItemCountOrSubtype(newToCount);
  2387.  
  2388. if(oldToCount != newToCount) {
  2389. autoCloseTrade(toItem);
  2390. }
  2391.  
  2392. int32_t subcount = oldFromCount - count;
  2393. fromItem->setItemCountOrSubtype(subcount);
  2394.  
  2395. int32_t surplusCount = oldToCount + count - 100;
  2396. if(surplusCount > 0) {
  2397. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2398. if(onPrepareMoveThing(player, fromPos, fromContainer, surplusItem, toPos, toContainer, NULL, count)) {
  2399. autoCloseTrade(toContainer);
  2400. toContainer->addItem(surplusItem);
  2401. }
  2402. else {
  2403. delete surplusItem;
  2404. count -= surplusCount; //re-define the actual amount we move.
  2405. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2406. }
  2407. }
  2408. }
  2409. else if(count < oldFromCount) {
  2410. int32_t subcount = oldFromCount - count;
  2411. fromItem->setItemCountOrSubtype(subcount);
  2412.  
  2413. Item* moveItem = Item::CreateItem(fromItem->getID(), count);
  2414. toContainer->addItem(moveItem);
  2415. autoCloseTrade(toContainer);
  2416. }
  2417. else {
  2418. if(fromContainer == toContainer) {
  2419. fromContainer->moveItem(from_slotid, 0);
  2420. }
  2421. else if(fromContainer->removeItem(fromItem)) {
  2422. autoCloseTrade(toContainer);
  2423. toContainer->addItem(fromItem);
  2424. }
  2425. }
  2426.  
  2427. if(fromItem->getItemCountOrSubtype() == 0) {
  2428. fromContainer->removeItem(fromItem);
  2429. this->FreeThing(fromItem);
  2430. }
  2431. }
  2432. else {
  2433. if(fromContainer == toContainer) {
  2434. fromContainer->moveItem(from_slotid, 0);
  2435. }
  2436. else if(fromContainer->removeItem(fromItem)) {
  2437. autoCloseTrade(toContainer);
  2438. toContainer->addItem(fromItem);
  2439. }
  2440. }
  2441.  
  2442. if(player->isHoldingContainer(fromContainer) != player->isHoldingContainer(toContainer)) {
  2443. player->updateInventoryWeigth();
  2444. }
  2445.  
  2446. SpectatorVec list;
  2447. SpectatorVec::iterator it;
  2448.  
  2449. if(fromPos == toPos) {
  2450. getSpectators(Range(fromPos, false), list);
  2451. }
  2452. else {
  2453. getSpectators(Range(fromPos, toPos), list);
  2454. }
  2455.  
  2456. if(!list.empty()) {
  2457. //players
  2458. for(it = list.begin(); it != list.end(); ++it) {
  2459. if(dynamic_cast<Player*>(*it)) {
  2460. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2461. }
  2462. }
  2463.  
  2464. //none-players
  2465. for(it = list.begin(); it != list.end(); ++it) {
  2466. if(!dynamic_cast<Player*>(*it)) {
  2467. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2468. }
  2469. }
  2470. }
  2471. else
  2472. player->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2473. }
  2474. }
  2475. else {
  2476. //inventory to inventory
  2477. if(fromInventory && toInventory && !toContainer) {
  2478. Position fromPos = player->pos;
  2479. Position toPos = player->pos;
  2480. if(onPrepareMoveThing(player, fromItem, (slots_t)to_cid, count) && onPrepareMoveThing(player, (slots_t)from_cid, fromItem, (slots_t)to_cid, toItem, count)) {
  2481.  
  2482. autoCloseTrade(fromItem, true);
  2483. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2484. int32_t oldToCount = 0;
  2485.  
  2486. //bbk 2020
  2487. std::cout << "inventory to inventory" << std::endl;
  2488. if(fromItem && (slots_t)to_cid == SLOT_RING) fromItem->setGlimmer();
  2489. if(toItem && (slots_t)from_cid == SLOT_RING) toItem->removeGlimmer();
  2490.  
  2491. if(fromItem->isStackable()) {
  2492. if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2493. {
  2494. oldToCount = toItem->getItemCountOrSubtype();
  2495. int32_t newToCount = std::min(100, oldToCount + count);
  2496. toItem->setItemCountOrSubtype(newToCount);
  2497.  
  2498. if(oldToCount != newToCount) {
  2499. autoCloseTrade(toItem);
  2500. }
  2501.  
  2502. int32_t subcount = oldFromCount - count;
  2503. fromItem->setItemCountOrSubtype(subcount);
  2504.  
  2505. int32_t surplusCount = oldToCount + count - 100;
  2506. if(surplusCount > 0) {
  2507. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2508. player->sendCancel("There is not enough room.");
  2509. }
  2510.  
  2511. if(fromItem->getItemCountOrSubtype() == 0) {
  2512. player->removeItemInventory(from_cid, true);
  2513. this->FreeThing(fromItem);
  2514. }
  2515. }
  2516. else if(count < oldFromCount) {
  2517. int32_t subcount = oldFromCount - count;
  2518. fromItem->setItemCountOrSubtype(subcount);
  2519.  
  2520. autoCloseTrade(toItem);
  2521. player->removeItemInventory(to_cid, true);
  2522. player->addItemInventory(Item::CreateItem(fromItem->getID(), count), to_cid, true);
  2523.  
  2524. if(fromItem->getItemCountOrSubtype() == 0) {
  2525. player->removeItemInventory(from_cid, true);
  2526. this->FreeThing(fromItem);
  2527. }
  2528. }
  2529. else {
  2530. if(player->removeItemInventory(from_cid, true)) {
  2531. player->removeItemInventory(to_cid, true);
  2532. player->addItemInventory(fromItem, to_cid, true);
  2533. }
  2534. }
  2535. }
  2536. else if(player->removeItemInventory(from_cid, true)) {
  2537. player->removeItemInventory(to_cid, true);
  2538. player->addItemInventory(fromItem, to_cid, true);
  2539. }
  2540.  
  2541. player->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2542. }
  2543. }
  2544. //container to inventory
  2545. else if(!fromInventory && fromContainer && toInventory) {
  2546. if(onPrepareMoveThing(player, fromItem, (slots_t)to_cid, count) && onPrepareMoveThing(player, fromContainer, fromItem, (slots_t)to_cid, toItem, count)) {
  2547. autoCloseTrade(fromItem, true);
  2548. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2549. int32_t oldToCount = 0;
  2550.  
  2551. //bbk 2020
  2552. std::cout << "container to inventory" << std::endl;
  2553. if(fromItem) fromItem->removeGlimmer();
  2554. if(toItem ) toItem->removeGlimmer();
  2555.  
  2556. if(fromItem->isStackable()) {
  2557. if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2558. {
  2559. oldToCount = toItem->getItemCountOrSubtype();
  2560. int32_t newToCount = std::min(100, oldToCount + count);
  2561. toItem->setItemCountOrSubtype(newToCount);
  2562.  
  2563. if(oldToCount != newToCount) {
  2564. autoCloseTrade(toItem);
  2565. }
  2566.  
  2567. int32_t subcount = oldFromCount - count;
  2568. fromItem->setItemCountOrSubtype(subcount);
  2569.  
  2570. int32_t surplusCount = oldToCount + count - 100;
  2571. if(surplusCount > 0) {
  2572. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2573. player->sendCancel("There is not enough room.");
  2574. }
  2575.  
  2576. if(fromItem->getItemCountOrSubtype() == 0) {
  2577. fromContainer->removeItem(fromItem);
  2578. this->FreeThing(fromItem);
  2579. }
  2580. }
  2581. else if(count < oldFromCount) {
  2582. int32_t subcount = oldFromCount - count;
  2583. fromItem->setItemCountOrSubtype(subcount);
  2584.  
  2585. player->removeItemInventory(to_cid, true);
  2586. player->addItemInventory(Item::CreateItem(fromItem->getID(), count), to_cid, true);
  2587.  
  2588. if(toItem) {
  2589. fromContainer->addItem(toItem);
  2590. }
  2591.  
  2592. if(fromItem->getItemCountOrSubtype() == 0) {
  2593. fromContainer->removeItem(fromItem);
  2594. this->FreeThing(fromItem);
  2595. }
  2596. }
  2597. else {
  2598. if(fromContainer->removeItem(fromItem)) {
  2599. player->removeItemInventory(to_cid, true);
  2600. player->addItemInventory(fromItem, to_cid, true);
  2601.  
  2602. if(toItem) {
  2603. fromContainer->addItem(toItem);
  2604. }
  2605. }
  2606. }
  2607. }
  2608. else if(fromContainer->removeItem(fromItem)) {
  2609. player->removeItemInventory(to_cid, true);
  2610. player->addItemInventory(fromItem, to_cid, true);
  2611.  
  2612. if(toItem) {
  2613. fromContainer->addItem(toItem);
  2614. }
  2615. }
  2616.  
  2617. if(!player->isHoldingContainer(fromContainer)) {
  2618. player->updateInventoryWeigth();
  2619. }
  2620.  
  2621. //if(fromContainer->pos.x != 0xFFFF) {
  2622. if(fromContainer->getTopParent()->pos.x != 0xFFFF) {
  2623. SpectatorVec list;
  2624. SpectatorVec::iterator it;
  2625.  
  2626. getSpectators(Range(fromContainer->getTopParent()->pos, false), list);
  2627.  
  2628. //players
  2629. for(it = list.begin(); it != list.end(); ++it) {
  2630. if(dynamic_cast<Player*>(*it)) {
  2631. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2632. }
  2633. }
  2634.  
  2635. //none-players
  2636. for(it = list.begin(); it != list.end(); ++it) {
  2637. if(!dynamic_cast<Player*>(*it)) {
  2638. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2639. }
  2640. }
  2641. }
  2642. else
  2643. player->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2644. }
  2645. }
  2646. //inventory to container
  2647. else if(fromInventory && toContainer) {
  2648. Position fromPos = player->pos;
  2649. Position toPos = (toContainer->pos.x == 0xFFFF ? player->pos : toContainer->pos);
  2650.  
  2651. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2652. int32_t oldToCount = 0;
  2653.  
  2654. //bbk 2020
  2655. std::cout << "inventory to container" << std::endl;
  2656. if(fromItem) fromItem->removeGlimmer();
  2657. if(toItem) toItem->removeGlimmer();
  2658.  
  2659. if(onPrepareMoveThing(player, fromItem, (slots_t)from_cid, toContainer, toItem, count)) {
  2660. autoCloseTrade(fromItem, true);
  2661. if(fromItem->isStackable()) {
  2662. if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2663. {
  2664. oldToCount = toItem->getItemCountOrSubtype();
  2665. int32_t newToCount = std::min(100, oldToCount + count);
  2666. toItem->setItemCountOrSubtype(newToCount);
  2667.  
  2668. if(oldToCount != newToCount) {
  2669. autoCloseTrade(toItem);
  2670. }
  2671.  
  2672. int32_t subcount = oldFromCount - count;
  2673. fromItem->setItemCountOrSubtype(subcount);
  2674.  
  2675. int32_t surplusCount = oldToCount + count - 100;
  2676. if(surplusCount > 0) {
  2677. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2678.  
  2679. if(onPrepareMoveThing(player, fromPos, NULL, surplusItem, toPos, toContainer, NULL, count)) {
  2680. autoCloseTrade(toContainer);
  2681. toContainer->addItem(surplusItem);
  2682. }
  2683. else {
  2684. delete surplusItem;
  2685. count -= surplusCount; //re-define the actual amount we move.
  2686. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2687. }
  2688. }
  2689. }
  2690. else if(count < oldFromCount) {
  2691. int32_t subcount = oldFromCount - count;
  2692. fromItem->setItemCountOrSubtype(subcount);
  2693. autoCloseTrade(toContainer);
  2694. toContainer->addItem(Item::CreateItem(fromItem->getID(), count));
  2695. }
  2696. else {
  2697. if(player->removeItemInventory((slots_t)from_cid, true)) {
  2698. autoCloseTrade(toContainer);
  2699. toContainer->addItem(fromItem);
  2700.  
  2701. if(player->isHoldingContainer(toContainer)) {
  2702. player->updateInventoryWeigth();
  2703. }
  2704. }
  2705. }
  2706.  
  2707. if(fromItem->getItemCountOrSubtype() == 0) {
  2708. player->removeItemInventory(from_cid, true);
  2709. this->FreeThing(fromItem);
  2710. }
  2711. }
  2712. else if(player->removeItemInventory(from_cid, true)) {
  2713. autoCloseTrade(toContainer);
  2714. toContainer->addItem(fromItem);
  2715.  
  2716. if(player->isHoldingContainer(toContainer)) {
  2717. player->updateInventoryWeigth();
  2718. }
  2719. }
  2720.  
  2721. if(!player->isHoldingContainer(toContainer)) {
  2722. player->updateInventoryWeigth();
  2723. }
  2724.  
  2725. if(toContainer->getTopParent()->pos.x != 0xFFFF) {
  2726. SpectatorVec list;
  2727. SpectatorVec::iterator it;
  2728.  
  2729. getSpectators(Range(toContainer->getTopParent()->pos, false), list);
  2730.  
  2731. //players
  2732. for(it = list.begin(); it != list.end(); ++it) {
  2733. if(dynamic_cast<Player*>(*it)) {
  2734. (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2735. }
  2736. }
  2737.  
  2738. //none-players
  2739. for(it = list.begin(); it != list.end(); ++it) {
  2740. if(!dynamic_cast<Player*>(*it)) {
  2741. (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2742. }
  2743. }
  2744. }
  2745. else
  2746. player->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2747. }
  2748. }
  2749. }
  2750. }
  2751.  
  2752. //container/inventory to ground
  2753. void Game::thingMoveInternal(Player *player,
  2754. unsigned char from_cid, unsigned char from_slotid, unsigned short itemid, bool fromInventory,
  2755. const Position& toPos, unsigned char count)
  2756. {
  2757. Container *fromContainer = NULL;
  2758. Tile *toTile = map->getTile(toPos);
  2759. if(!toTile)
  2760. return;
  2761.  
  2762. /*container to ground*/
  2763. if(!fromInventory) {
  2764. fromContainer = player->getContainer(from_cid);
  2765. if(!fromContainer)
  2766. return;
  2767.  
  2768. Position fromPos = (fromContainer->pos.x == 0xFFFF ? player->pos : fromContainer->pos);
  2769. Item *fromItem = dynamic_cast<Item*>(fromContainer->getItem(from_slotid));
  2770. Item* toItem = dynamic_cast<Item*>(toTile->getTopDownItem());
  2771.  
  2772. if(!fromItem || (toItem == fromItem) || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()) || fromItem->getID() != itemid)
  2773. return;
  2774.  
  2775. if(onPrepareMoveThing(player, fromItem, fromPos, toPos, count) && onPrepareMoveThing(player, fromItem, NULL, toTile, count)) {
  2776. autoCloseTrade(fromItem, true);
  2777. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2778. int32_t oldToCount = 0;
  2779.  
  2780. //Do action...
  2781. #ifdef TP_TRASH_BINS
  2782. if (toItem && toItem->isDeleter())
  2783. {
  2784. fromContainer->removeItem(fromItem);
  2785. FreeThing(fromItem);
  2786. }
  2787. else if(fromItem->isStackable()) {
  2788. #else
  2789. if(fromItem->isStackable()) {
  2790. #endif //TP_TRASH_BINS
  2791. if(toItem && toItem->getID() == fromItem->getID())
  2792. {
  2793. oldToCount = toItem->getItemCountOrSubtype();
  2794. int32_t newToCount = std::min(100, oldToCount + count);
  2795. toItem->setItemCountOrSubtype(newToCount);
  2796.  
  2797. if(oldToCount != newToCount) {
  2798. autoCloseTrade(toItem);
  2799. }
  2800.  
  2801. int32_t subcount = oldFromCount - count;
  2802. fromItem->setItemCountOrSubtype(subcount);
  2803.  
  2804. int32_t surplusCount = oldToCount + count - 100;
  2805. if(surplusCount > 0) {
  2806. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2807. surplusItem->pos = toPos;
  2808.  
  2809. toTile->addThing(surplusItem);
  2810. }
  2811.  
  2812. if(fromItem->getItemCountOrSubtype() == 0) {
  2813. fromContainer->removeItem(fromItem);
  2814. this->FreeThing(fromItem);
  2815. }
  2816. }
  2817. else if(count < oldFromCount) {
  2818. int32_t subcount = oldFromCount - count;
  2819. fromItem->setItemCountOrSubtype(subcount);
  2820.  
  2821. Item *moveItem = Item::CreateItem(fromItem->getID(), count);
  2822. moveItem->pos = toPos;
  2823. toTile->addThing(moveItem);
  2824.  
  2825. if(fromItem->getItemCountOrSubtype() == 0) {
  2826. fromContainer->removeItem(fromItem);
  2827. this->FreeThing(fromItem);
  2828. }
  2829. }
  2830. else if(fromContainer->removeItem(fromItem)) {
  2831. fromItem->pos = toPos;
  2832. toTile->addThing(fromItem);
  2833. }
  2834. }
  2835. else if(fromContainer->removeItem(fromItem)) {
  2836. fromItem->pos = toPos;
  2837. toTile->addThing(fromItem);
  2838. }
  2839.  
  2840. if(player->isHoldingContainer(fromContainer)) {
  2841. player->updateInventoryWeigth();
  2842. }
  2843.  
  2844. SpectatorVec list;
  2845. SpectatorVec::iterator it;
  2846.  
  2847. getSpectators(Range(fromPos, false), list);
  2848.  
  2849. SpectatorVec tolist;
  2850. getSpectators(Range(toPos, true), tolist);
  2851.  
  2852. for(it = tolist.begin(); it != tolist.end(); ++it) {
  2853. if(std::find(list.begin(), list.end(), *it) == list.end()) {
  2854. list.push_back(*it);
  2855. }
  2856. }
  2857.  
  2858. //players
  2859. for(it = list.begin(); it != list.end(); ++it) {
  2860. if(dynamic_cast<Player*>(*it)) {
  2861. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2862. }
  2863. }
  2864.  
  2865. //none-players
  2866. for(it = list.begin(); it != list.end(); ++it) {
  2867. if(!dynamic_cast<Player*>(*it)) {
  2868. (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2869. }
  2870. }
  2871. }
  2872. }
  2873. else /*inventory to ground*/{
  2874. Item *fromItem = player->getItem(from_cid);
  2875. if(!fromItem || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()) || fromItem->getID() != itemid)
  2876. return;
  2877.  
  2878. if(onPrepareMoveThing(player, fromItem, player->pos, toPos, count) && onPrepareMoveThing(player, fromItem, NULL, toTile, count)) {
  2879. autoCloseTrade(fromItem, true);
  2880. Item* toItem = dynamic_cast<Item*>(toTile->getTopDownItem());
  2881. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2882. int32_t oldToCount = 0;
  2883.  
  2884. //bbk 2020
  2885. std::cout << "inventory to ground" << std::endl;
  2886. if(fromItem) fromItem->removeGlimmer();
  2887.  
  2888. //Do action...
  2889. #ifdef TP_TRASH_BINS
  2890. if(toItem && toItem->isDeleter())
  2891. {
  2892. player->removeItemInventory(from_cid, true);
  2893. FreeThing(fromItem);
  2894. }
  2895. else if(fromItem->isStackable()) {
  2896. #else
  2897. if(fromItem->isStackable()) {
  2898. #endif //TP_TRASH_BINS
  2899. if(toItem && toItem->getID() == fromItem->getID())
  2900. {
  2901. oldToCount = toItem->getItemCountOrSubtype();
  2902. int32_t newToCount = std::min(100, oldToCount + count);
  2903. toItem->setItemCountOrSubtype(newToCount);
  2904.  
  2905. if(oldToCount != newToCount) {
  2906. autoCloseTrade(toItem);
  2907. }
  2908.  
  2909. int32_t subcount = oldFromCount - count;
  2910. fromItem->setItemCountOrSubtype(subcount);
  2911.  
  2912. int32_t surplusCount = oldToCount + count - 100;
  2913. if(surplusCount > 0) {
  2914. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2915. surplusItem->pos = toPos;
  2916.  
  2917. toTile->addThing(surplusItem);
  2918. }
  2919.  
  2920. if(fromItem->getItemCountOrSubtype() == 0) {
  2921. player->removeItemInventory(from_cid, true);
  2922. this->FreeThing(fromItem);
  2923. }
  2924. }
  2925. else if(count < oldFromCount) {
  2926. int32_t subcount = oldFromCount - count;
  2927. fromItem->setItemCountOrSubtype(subcount);
  2928.  
  2929. Item *moveItem = Item::CreateItem(fromItem->getID(), count);
  2930. moveItem->pos = toPos;
  2931. toTile->addThing(moveItem);
  2932.  
  2933. if(fromItem->getItemCountOrSubtype() == 0) {
  2934. player->removeItemInventory(from_cid, true);
  2935. this->FreeThing(fromItem);
  2936. }
  2937. }
  2938. else if(player->removeItemInventory(from_cid, true)) {
  2939. fromItem->pos = toPos;
  2940. toTile->addThing(fromItem);
  2941. }
  2942. }
  2943. else if(player->removeItemInventory(from_cid, true)) {
  2944. fromItem->pos = toPos;
  2945. toTile->addThing(fromItem);
  2946. }
  2947.  
  2948. player->updateInventoryWeigth();
  2949.  
  2950. SpectatorVec list;
  2951. SpectatorVec::iterator it;
  2952.  
  2953. getSpectators(Range(player->pos, false), list);
  2954.  
  2955. SpectatorVec tolist;
  2956. getSpectators(Range(toPos, true), tolist);
  2957.  
  2958. for(it = tolist.begin(); it != tolist.end(); ++it) {
  2959. if(std::find(list.begin(), list.end(), *it) == list.end()) {
  2960. list.push_back(*it);
  2961. }
  2962. }
  2963.  
  2964. //players
  2965. for(it = list.begin(); it != list.end(); ++it) {
  2966. if(dynamic_cast<Player*>(*it)) {
  2967. (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2968. }
  2969. }
  2970.  
  2971. //none-players
  2972. for(it = list.begin(); it != list.end(); ++it) {
  2973. if(!dynamic_cast<Player*>(*it)) {
  2974. (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2975. }
  2976. }
  2977. }
  2978. }
  2979.  
  2980. }
  2981.  
  2982. //ground to container/inventory
  2983. void Game::thingMoveInternal(Player *player, const Position& fromPos, unsigned char stackPos,
  2984. uint16_t itemid, unsigned char to_cid, unsigned char to_slotid, bool toInventory, unsigned char count)
  2985. {
  2986. Tile *fromTile = map->getTile(fromPos);
  2987. if(!fromTile)
  2988. return;
  2989.  
  2990. Container *toContainer = NULL;
  2991.  
  2992. Item* fromItem = dynamic_cast<Item*>(fromTile->getTopDownItem());
  2993. Item *toItem = NULL;
  2994.  
  2995. if(!fromItem || (fromItem->getID() != itemid) || (fromItem != fromTile->getTopDownItem()))
  2996. return;
  2997.  
  2998. if(toInventory)
  2999. {
  3000. toItem = player->getItem(to_cid);
  3001. toContainer = dynamic_cast<Container*>(toItem);
  3002. }
  3003. else
  3004. {
  3005. toContainer = player->getContainer(to_cid);
  3006. if(!toContainer)
  3007. return;
  3008.  
  3009. toItem = toContainer->getItem(to_slotid);
  3010. Container *toSlotContainer = dynamic_cast<Container*>(toItem);
  3011.  
  3012. if(toSlotContainer)
  3013. {
  3014. toContainer = toSlotContainer;
  3015. toItem = NULL;
  3016. }
  3017. }
  3018.  
  3019. if((toItem == fromItem) || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()))
  3020. return;
  3021.  
  3022. /*ground to container*/
  3023. if(toContainer)
  3024. {
  3025. /*if(onPrepareMoveThing(player, fromItem, fromPos, player->pos, count) &&
  3026. onPrepareMoveThing(player, fromItem, NULL, toContainer, toItem, count))*/
  3027.  
  3028. Position toPos = (toContainer->pos.x == 0xFFFF ? player->pos : toContainer->pos);
  3029. if(onPrepareMoveThing(player, fromPos, NULL, fromItem, toPos, toContainer, toItem, count))
  3030. {
  3031. autoCloseTrade(fromItem, true);
  3032. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  3033. int32_t oldToCount = 0;
  3034. int32_t stackpos = fromTile->getThingStackPos(fromItem);
  3035.  
  3036. if(fromItem->isStackable())
  3037. {
  3038. if(toItem && toItem->getID() == fromItem->getID())
  3039. {
  3040. oldToCount = toItem->getItemCountOrSubtype();
  3041. int32_t newToCount = std::min(100, oldToCount + count);
  3042. toItem->setItemCountOrSubtype(newToCount);
  3043.  
  3044. if(oldToCount != newToCount)
  3045. {
  3046. autoCloseTrade(toItem);
  3047. }
  3048.  
  3049. int32_t subcount = oldFromCount - count;
  3050. fromItem->setItemCountOrSubtype(subcount);
  3051.  
  3052. int32_t surplusCount = oldToCount + count - 100;
  3053. if(surplusCount > 0)
  3054. {
  3055. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  3056.  
  3057. if(onPrepareMoveThing(player, fromPos, NULL, surplusItem, toPos, toContainer, NULL, count))
  3058. {
  3059. autoCloseTrade(toContainer);
  3060. toContainer->addItem(surplusItem);
  3061. }
  3062. else
  3063. {
  3064. delete surplusItem;
  3065. count -= surplusCount; //re-define the actual amount we move.
  3066. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  3067. }
  3068. }
  3069.  
  3070. if(fromItem->getItemCountOrSubtype() == 0)
  3071. {
  3072. if(fromTile->removeThing(fromItem))
  3073. {
  3074. this->FreeThing(fromItem);
  3075. }
  3076. }
  3077. }
  3078. else if(count < oldFromCount)
  3079. {
  3080. int32_t subcount = oldFromCount - count;
  3081. fromItem->setItemCountOrSubtype(subcount);
  3082.  
  3083. autoCloseTrade(toContainer);
  3084. toContainer->addItem(Item::CreateItem(fromItem->getID(), count));
  3085.  
  3086. if(fromItem->getItemCountOrSubtype() == 0)
  3087. {
  3088. if(fromTile->removeThing(fromItem))
  3089. {
  3090. this->FreeThing(fromItem);
  3091. }
  3092. }
  3093. }
  3094. else if(fromTile->removeThing(fromItem))
  3095. {
  3096. autoCloseTrade(toContainer);
  3097. toContainer->addItem(fromItem);
  3098. }
  3099. }
  3100. else
  3101. {
  3102. if(fromTile->removeThing(fromItem))
  3103. {
  3104. autoCloseTrade(toContainer);
  3105. toContainer->addItem(fromItem);
  3106. }
  3107. }
  3108.  
  3109. if(player->isHoldingContainer(toContainer))
  3110. {
  3111. player->updateInventoryWeigth();
  3112. }
  3113.  
  3114. SpectatorVec list;
  3115. SpectatorVec::iterator it;
  3116.  
  3117. getSpectators(Range(fromPos, true), list);
  3118.  
  3119. //players
  3120. for(it = list.begin(); it != list.end(); ++it)
  3121. {
  3122. if(dynamic_cast<Player*>(*it))
  3123. {
  3124. (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  3125. }
  3126. }
  3127.  
  3128. //none-players
  3129. for(it = list.begin(); it != list.end(); ++it)
  3130. {
  3131. if(!dynamic_cast<Player*>(*it))
  3132. {
  3133. (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  3134. }
  3135. }
  3136. }
  3137. }
  3138. //ground to inventory
  3139. else if(toInventory)
  3140. {
  3141. if(onPrepareMoveThing(player, fromPos, fromItem, (slots_t)to_cid, count) && onPrepareMoveThing(player, fromItem, (slots_t)to_cid, count))
  3142. {
  3143. autoCloseTrade(fromItem, true);
  3144. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  3145. int32_t oldToCount = 0;
  3146. int32_t stackpos = fromTile->getThingStackPos(fromItem);
  3147.  
  3148. //bbk 2020
  3149. std::cout << "ground to inventory" << std::endl;
  3150. if(fromItem && (slots_t)to_cid == SLOT_RING) {
  3151. fromItem->setGlimmer();
  3152. if(toItem) toItem->removeGlimmer();
  3153. }
  3154.  
  3155. if(fromItem->isStackable())
  3156. {
  3157. if(toItem && toItem->getID() == fromItem->getID())
  3158. {
  3159. oldToCount = toItem->getItemCountOrSubtype();
  3160. int32_t newToCount = std::min(100, oldToCount + count);
  3161. toItem->setItemCountOrSubtype(newToCount);
  3162.  
  3163. if(oldToCount != newToCount)
  3164. {
  3165. autoCloseTrade(toItem);
  3166. }
  3167.  
  3168. int32_t subcount = oldFromCount - count;
  3169. fromItem->setItemCountOrSubtype(subcount);
  3170.  
  3171. int32_t surplusCount = oldToCount + count - 100;
  3172. if(surplusCount > 0)
  3173. {
  3174. fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  3175. player->sendCancel("Sorry not enough room.");
  3176. }
  3177.  
  3178. if(fromItem->getItemCountOrSubtype() == 0)
  3179. {
  3180. if(fromTile->removeThing(fromItem))
  3181. {
  3182. this->FreeThing(fromItem);
  3183. }
  3184. }
  3185. }
  3186. else if(count < oldFromCount)
  3187. {
  3188. int32_t subcount = oldFromCount - count;
  3189. fromItem->setItemCountOrSubtype(subcount);
  3190.  
  3191. player->removeItemInventory(to_cid, true);
  3192. player->addItemInventory(Item::CreateItem(fromItem->getID(), count), to_cid, true);
  3193.  
  3194. if(toItem)
  3195. {
  3196. autoCloseTrade(toItem);
  3197. fromTile->addThing(toItem);
  3198. toItem->pos = fromPos;
  3199. }
  3200.  
  3201. if(fromItem->getItemCountOrSubtype() == 0)
  3202. {
  3203. if(fromTile->removeThing(fromItem))
  3204. {
  3205. this->FreeThing(fromItem);
  3206. }
  3207. }
  3208. }
  3209. else
  3210. {
  3211. if(fromTile->removeThing(fromItem))
  3212. {
  3213. player->removeItemInventory(to_cid, true);
  3214. player->addItemInventory(fromItem, to_cid, true);
  3215.  
  3216. if(toItem)
  3217. {
  3218. autoCloseTrade(toItem);
  3219. fromTile->addThing(toItem);
  3220. toItem->pos = fromPos;
  3221. }
  3222. }
  3223. }
  3224. }
  3225. else
  3226. {
  3227. if(fromTile->removeThing(fromItem))
  3228. {
  3229. player->removeItemInventory(to_cid, true);
  3230. player->addItemInventory(fromItem, to_cid, true);
  3231.  
  3232. if(toItem)
  3233. {
  3234. autoCloseTrade(toItem);
  3235. fromTile->addThing(toItem);
  3236. toItem->pos = fromPos;
  3237. }
  3238. }
  3239. }
  3240.  
  3241. player->updateInventoryWeigth();
  3242.  
  3243. SpectatorVec list;
  3244. SpectatorVec::iterator it;
  3245.  
  3246. getSpectators(Range(fromPos, true), list);
  3247.  
  3248. //players
  3249. for(it = list.begin(); it != list.end(); ++it)
  3250. {
  3251. if(dynamic_cast<Player*>(*it))
  3252. {
  3253. (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  3254. }
  3255. }
  3256.  
  3257. //none-players
  3258. for(it = list.begin(); it != list.end(); ++it)
  3259. {
  3260. if(!dynamic_cast<Player*>(*it))
  3261. {
  3262. (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  3263. }
  3264. }
  3265. }
  3266. }
  3267. }
  3268.  
  3269. //ground to ground
  3270. void Game::thingMoveInternal(Creature *creature, unsigned short from_x, unsigned short from_y, unsigned char from_z,
  3271. unsigned char stackPos, unsigned short itemid, unsigned short to_x, unsigned short to_y, unsigned char to_z, unsigned char count)
  3272. {
  3273. Tile *fromTile = getTile(from_x, from_y, from_z);
  3274. if(!fromTile)
  3275. return;
  3276.  
  3277. if(dynamic_cast<Player*>(creature) && fromTile && !fromTile->ground) {
  3278. dynamic_cast<Player*>(creature)->sendCancelWalk();
  3279. return;
  3280. }
  3281.  
  3282. Tile *toTile = getTile(to_x, to_y, to_z);
  3283. /*
  3284. if(!toTile){
  3285. if(dynamic_cast<Player*>(player))
  3286. dynamic_cast<Player*>(player)->sendCancelWalk("Sorry, not possible...");
  3287. return;
  3288. }
  3289. */
  3290.  
  3291. Thing *thing = fromTile->getThingByStackPos(stackPos);
  3292.  
  3293. if (!thing)
  3294. return;
  3295.  
  3296. Item* item = dynamic_cast<Item*>(thing);
  3297. Creature* creatureMoving = dynamic_cast<Creature*>(thing);
  3298. Player* playerMoving = dynamic_cast<Player*>(creatureMoving);
  3299. Player* player = dynamic_cast<Player*>(creature);
  3300.  
  3301. Position oldPos;
  3302. oldPos.x = from_x;
  3303. oldPos.y = from_y;
  3304. oldPos.z = from_z;
  3305.  
  3306. #ifdef TP_TRASH_BINS
  3307. if(toTile)
  3308. {
  3309. Thing *tothing = toTile->getThingByStackPos(stackPos);
  3310. Item *toItem = dynamic_cast<Item*>(tothing);
  3311.  
  3312. if(item && toItem && !playerMoving && !creature && toItem->isDeleter())
  3313. {
  3314. fromTile->removeThing(item);
  3315. this->FreeThing(item);
  3316. //creatureBroadcastTileUpdated(oldPos);
  3317. sendRemoveThing(player, item->pos, item, stackPos);
  3318. return;
  3319. }
  3320. }
  3321. #endif //TP_TRASH_BINS
  3322. /* if (toTile){
  3323. ItemVector::iterator brn;
  3324. for (brn = toTile->downItems.begin(); brn != toTile->downItems.end(); brn++)
  3325. {
  3326. 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)
  3327. */
  3328. if(toTile && player && playerMoving && playerMoving != player && toTile->getFieldItem())
  3329. {
  3330. player->sendCancel("Sorry, not possible.");
  3331. return;
  3332. }
  3333. // *** Creature moving itself to a non-tile
  3334. if(!toTile && creatureMoving && creatureMoving == creature){
  3335. //change level begin
  3336. Tile* downTile = getTile(to_x, to_y, to_z+1);
  3337. //diagonal begin
  3338. if(!downTile)
  3339. {
  3340. if(player) {
  3341. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  3342. player->sendCancelWalk();
  3343. }
  3344.  
  3345. return;
  3346. }
  3347.  
  3348. if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  3349. teleport(creatureMoving, Position(creatureMoving->pos.x-2, creatureMoving->pos.y+2, creatureMoving->pos.z+1));
  3350. }
  3351. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  3352. teleport(creatureMoving, Position(creatureMoving->pos.x+2, creatureMoving->pos.y+2, creatureMoving->pos.z+1));
  3353. }
  3354. else if(downTile->floorChange(SOUTH) && 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(SOUTH) && downTile->floorChange(WEST)){
  3358. teleport(creatureMoving, Position(creatureMoving->pos.x+2, creatureMoving->pos.y-2, creatureMoving->pos.z+1));
  3359. }
  3360. //diagonal end
  3361. else if(downTile->floorChange(NORTH)){
  3362. teleport(creatureMoving, Position(to_x, to_y + 1, creatureMoving->pos.z+1));
  3363. }
  3364. else if(downTile->floorChange(SOUTH)){
  3365. teleport(creatureMoving, Position(to_x, to_y - 1, creatureMoving->pos.z+1));
  3366. }
  3367. else if(downTile->floorChange(EAST)){
  3368. teleport(creatureMoving, Position(to_x - 1, to_y, creatureMoving->pos.z+1));
  3369. }
  3370. else if(downTile->floorChange(WEST)){
  3371. teleport(creatureMoving, Position(to_x + 1, to_y, creatureMoving->pos.z+1));
  3372. }
  3373. else
  3374. if(player) {
  3375. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  3376. player->sendCancelWalk();
  3377. }
  3378.  
  3379. //change level end
  3380. return;
  3381. }
  3382.  
  3383. #ifdef DT_PREMMY
  3384. if(player && playerMoving && !player->premmium == true){
  3385. if(!premmytiles.empty()){
  3386. for(int32_t o = 0; o < premmytiles.size(); o++) {
  3387. if((premmytiles[o].second.x != 0) &&
  3388. (premmytiles[o].second.y != 0) && (premmytiles[o].second.z != 0)){
  3389. if(Position(to_x, to_y, to_z) == premmytiles[o].first) {
  3390. player->sendCancelWalk();
  3391. teleport(playerMoving,
  3392. Position(premmytiles[o].second.x, premmytiles[o].second.y,
  3393. premmytiles[o].second.z));
  3394. player->sendMagicEffect(player->pos,
  3395. NM_ME_MAGIC_ENERGIE);
  3396. return;
  3397. }
  3398. }
  3399. else{
  3400. if(Position(to_x, to_y, to_z) == premmytiles[o].first) {
  3401. player->sendCancelWalk();
  3402. break;
  3403. }
  3404. }
  3405. }
  3406. }
  3407. }
  3408.  
  3409. #endif //DT_PREMMY
  3410.  
  3411.  
  3412.  
  3413. // *** Checking if the thing can be moved around
  3414.  
  3415. if(!toTile)
  3416. return;
  3417.  
  3418. if(!onPrepareMoveThing(creature, thing, oldPos, Position(to_x, to_y, to_z), count))
  3419. return;
  3420.  
  3421. if(creatureMoving && !onPrepareMoveCreature(creature, creatureMoving, fromTile, toTile))
  3422. return;
  3423.  
  3424. if(!onPrepareMoveThing(creature, thing, fromTile, toTile, count))
  3425. return;
  3426.  
  3427. Position to_pos;
  3428. to_pos.x = to_x;
  3429. to_pos.y = to_y;
  3430. to_pos.z = to_z;
  3431.  
  3432. Item* fromItem = dynamic_cast<Item*>(getThing(oldPos, stackPos, player));
  3433. Item* toItem = dynamic_cast<Item*>(toTile->getTopDownItem());
  3434.  
  3435. if(fromItem && fromItem->isStackable()){
  3436. if(fromItem->getItemCountOrSubtype() < count)
  3437. {
  3438. player->sendCancel("Sorry, not possible.");
  3439. return;
  3440. }
  3441.  
  3442. if((abs(player->pos.x - oldPos.x) > 1) || (abs(player->pos.y - oldPos.y) > 1) || (player->pos.z != oldPos.z)){
  3443. player->sendCancel("It's far away.");
  3444. return;
  3445. }
  3446. if(toItem && fromItem->getID() == toItem->getID()){
  3447. int32_t oldToCount = toItem->getItemCountOrSubtype();
  3448. int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  3449. int32_t newToCount = std::min(100, oldToCount + count);
  3450. toItem->setItemCountOrSubtype(newToCount);
  3451.  
  3452. if(oldToCount != newToCount) {
  3453. autoCloseTrade(toItem);
  3454. }
  3455.  
  3456. int32_t subcount = oldFromCount - count;
  3457. fromItem->setItemCountOrSubtype(subcount);
  3458.  
  3459. int32_t surplusCount = oldToCount + count - 100;
  3460. if(surplusCount > 0) {
  3461. Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  3462. surplusItem->pos = to_pos;
  3463. toTile->addThing(surplusItem);
  3464. }
  3465.  
  3466. if(fromItem->getItemCountOrSubtype() == 0) {
  3467. if(removeThing(player, oldPos, fromItem))
  3468. player->updateInventoryWeigth();
  3469. }
  3470.  
  3471. creatureBroadcastTileUpdated(to_pos);
  3472. creatureBroadcastTileUpdated(oldPos);
  3473.  
  3474. return;
  3475. }
  3476. else if(count < fromItem->getItemCountOrSubtype()) {
  3477. int32_t subcount = fromItem->getItemCountOrSubtype() - count;
  3478. fromItem->setItemCountOrSubtype(subcount);
  3479.  
  3480. Item *moveItem = Item::CreateItem(fromItem->getID(), count);
  3481. moveItem->pos = to_pos;
  3482. toTile->addThing(moveItem);
  3483.  
  3484. if(fromItem->getItemCountOrSubtype() == 0) {
  3485. if(removeThing(player, oldPos, fromItem))
  3486. player->updateInventoryWeigth();
  3487. }
  3488.  
  3489. creatureBroadcastTileUpdated(to_pos);
  3490. creatureBroadcastTileUpdated(oldPos);
  3491. return;
  3492. }
  3493. else{
  3494. Item *moveItem = Item::CreateItem(fromItem->getID(), fromItem->getItemCountOrSubtype());
  3495. moveItem->pos = to_pos;
  3496. toTile->addThing(moveItem);
  3497.  
  3498. if(removeThing(player, oldPos, fromItem))
  3499. player->updateInventoryWeigth();
  3500.  
  3501. creatureBroadcastTileUpdated(to_pos);
  3502. creatureBroadcastTileUpdated(oldPos);
  3503. return;
  3504. }
  3505.  
  3506. return;
  3507. }
  3508.  
  3509. /*
  3510. if(item && (item->getID() != itemid || item != fromTile->getTopDownItem()))
  3511. return;
  3512. */
  3513.  
  3514. // *** If the destiny is a teleport item, teleport the thing
  3515.  
  3516. const Teleport *teleportitem = toTile->getTeleportItem();
  3517. if(teleportitem) {
  3518. Player *player = dynamic_cast<Player*>(thing);
  3519. teleport(thing, teleportitem->getDestPos());
  3520. if(player) {
  3521. globalMagicEffect(player->pos, NM_ME_ENERGY_AREA);
  3522. }
  3523. return;
  3524. }
  3525.  
  3526. Monster* monsterMoving = dynamic_cast<Monster*>(creatureMoving);
  3527. if (monsterMoving && toTile->isPz()){
  3528. return;
  3529. }
  3530.  
  3531. #ifdef TLM_HOUSE_SYSTEM
  3532. if (playerMoving && toTile->getHouse() &&
  3533. (fromTile->getHouse() != toTile->getHouse() || playerMoving->houseRightsChanged))
  3534. {
  3535. if (playerMoving->access < g_config.ACCESS_HOUSE &&
  3536. toTile->getHouse()->getPlayerRights(playerMoving->getName()) == HOUSE_NONE)
  3537. {
  3538. playerMoving->sendTextMessage(MSG_SMALLINFO, "You are not invited.");
  3539. playerMoving->sendCancelWalk();
  3540. return;
  3541. }
  3542. else
  3543. playerMoving->houseRightsChanged = false; // if we are invited stop checking rights
  3544. }
  3545. #endif //TLM_HOUSE_SYSTEM
  3546.  
  3547. // *** Normal moving
  3548.  
  3549. if(creatureMoving)
  3550. {
  3551. // we need to update the direction the player is facing to...
  3552. // otherwise we are facing some problems in turning into the
  3553. // direction we were facing before the movement
  3554. // check y first cuz after a diagonal move we lock to east or west
  3555. if (to_y < oldPos.y) creatureMoving->direction = NORTH;
  3556. if (to_y > oldPos.y) creatureMoving->direction = SOUTH;
  3557. if (to_x > oldPos.x) creatureMoving->direction = EAST;
  3558. if (to_x < oldPos.x) creatureMoving->direction = WEST;
  3559. }
  3560.  
  3561. int32_t oldstackpos = fromTile->getThingStackPos(thing);
  3562. if (fromTile->removeThing(thing))
  3563. {
  3564. toTile->addThing(thing);
  3565.  
  3566. thing->pos.x = to_x;
  3567. thing->pos.y = to_y;
  3568. thing->pos.z = to_z;
  3569.  
  3570. SpectatorVec list;
  3571. SpectatorVec::iterator it;
  3572.  
  3573. getSpectators(Range(oldPos, Position(to_x, to_y, to_z)), list);
  3574.  
  3575. #ifdef TRS_GM_INVISIBLE
  3576. if(playerMoving && playerMoving->gmInvisible)
  3577. {
  3578. for(it = list.begin(); it != list.end(); ++it)
  3579. {
  3580. if(playerMoving == (*it) || (*it)->access >= playerMoving->access)
  3581. {
  3582. if(Player* p = dynamic_cast<Player*>(*it))
  3583. {
  3584. if(p->attackedCreature == creature->getID())
  3585. {
  3586. autoCloseAttack(p, creature);
  3587. }
  3588. (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3589. }
  3590. }
  3591. }
  3592. }
  3593. else if(playerMoving && !playerMoving->gmInvisible)
  3594. {
  3595. for(it = list.begin(); it != list.end(); ++it)
  3596. {
  3597. if(Player* p = dynamic_cast<Player*>(*it))
  3598. {
  3599. if(p->attackedCreature == creature->getID())
  3600. {
  3601. autoCloseAttack(p, creature);
  3602. }
  3603. (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3604. }
  3605. }
  3606. }
  3607. else
  3608. {
  3609. for(it = list.begin(); it != list.end(); ++it)
  3610. {
  3611. if(Player* p = dynamic_cast<Player*>(*it))
  3612. {
  3613. if(p->attackedCreature == creature->getID())
  3614. {
  3615. autoCloseAttack(p, creature);
  3616. }
  3617. (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3618. }
  3619. }
  3620. }
  3621. #else //TRS_GM_INVISIBLE
  3622. //players
  3623. for(it = list.begin(); it != list.end(); ++it)
  3624. {
  3625. if(Player* p = dynamic_cast<Player*>(*it)) {
  3626. if(p->attackedCreature == creature->getID()) {
  3627. autoCloseAttack(p, creature);
  3628. }
  3629. (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3630. }
  3631. }
  3632. #endif //TRS_GM_INVISIBLE
  3633.  
  3634. //none-players
  3635. for(it = list.begin(); it != list.end(); ++it)
  3636. {
  3637. if(!dynamic_cast<Player*>(*it)) {
  3638. (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3639. }
  3640. }
  3641.  
  3642. autoCloseTrade(item, true);
  3643. //depot tiles
  3644.  
  3645. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 426))
  3646. {
  3647. int32_t e = 0;
  3648. Container* c = playerMoving->getDepot(1);
  3649. std::stringstream s;
  3650. e += getDepot(c, e);
  3651. s << "Your depot contains " << e;
  3652. if(e > 1)
  3653. s << " items.";
  3654. else
  3655. s << " item.";
  3656. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3657. }
  3658.  
  3659. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 416))
  3660. {
  3661. int32_t e = 0;
  3662. Container* c = playerMoving->getDepot(2);
  3663. std::stringstream s;
  3664. e += getDepot(c, e);
  3665. s << "Your depot contains " << e;
  3666. if(e > 1)
  3667. s << " items.";
  3668. else
  3669. s << " item.";
  3670. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3671. }
  3672.  
  3673. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 446))
  3674. {
  3675. int32_t e = 0;
  3676. Container* c = playerMoving->getDepot(3);
  3677. std::stringstream s;
  3678. e += getDepot(c, e);
  3679. s << "Your depot contains " << e;
  3680. if(e > 1)
  3681. s << " items.";
  3682. else
  3683. s << " item.";
  3684. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3685. }
  3686.  
  3687. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 3216))
  3688. {
  3689. int32_t e = 0;
  3690. Container* c = playerMoving->getDepot(4);
  3691. std::stringstream s;
  3692. e += getDepot(c, e);
  3693. s << "Your depot contains " << e;
  3694. if(e > 1)
  3695. s << " items.";
  3696. else
  3697. s << " item.";
  3698. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3699. }
  3700.  
  3701. if(playerMoving && toTile && fromTile)
  3702. {
  3703. actions.luaWalk(playerMoving,playerMoving->pos,toTile->ground->getID(),toTile->ground->getUniqueId(),toTile->ground->getActionId()); //CHANGE onWalk
  3704. }
  3705.  
  3706. if(playerMoving && toTile && fromTile)
  3707. {
  3708. actions.luaWalkOff(playerMoving,oldPos,fromTile->ground->getID(),fromTile->ground->getUniqueId(),fromTile->ground->getActionId()); //CHANGE onWalk
  3709. }
  3710.  
  3711. if(playerMoving && fromTile && toTile && player == playerMoving)
  3712. switch(toTile->ground->getID())
  3713. {
  3714. case 416:
  3715. {
  3716. toTile->removeThing(toTile->ground);
  3717. toTile->addThing(new Item(417));
  3718. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3719. }
  3720. break;
  3721.  
  3722. case 426:
  3723. {
  3724. toTile->removeThing(toTile->ground);
  3725. toTile->addThing(new Item(425));
  3726. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3727. }
  3728. break;
  3729. case 3216:
  3730. {
  3731. toTile->removeThing(toTile->ground);
  3732. toTile->addThing(new Item(3217));
  3733. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3734. }
  3735. break;
  3736. case 446:
  3737. {
  3738. toTile->removeThing(toTile->ground);
  3739. toTile->addThing(new Item(447));
  3740. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3741. }
  3742. break;
  3743. case 293:
  3744. {
  3745. toTile->removeThing(toTile->ground);
  3746. toTile->addThing(new Item(294));
  3747. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3748. }
  3749. break;
  3750. }
  3751. switch(fromTile->ground->getID())
  3752. {
  3753. case 3217:
  3754. {
  3755. fromTile->removeThing(fromTile->ground);
  3756. fromTile->addThing(new Item(3216));
  3757. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3758. break;
  3759. }
  3760. case 417:
  3761. {
  3762. fromTile->removeThing(fromTile->ground);
  3763. fromTile->addThing(new Item(416));
  3764. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3765. break;
  3766. }
  3767. case 425:
  3768. {
  3769. fromTile->removeThing(fromTile->ground);
  3770. fromTile->addThing(new Item(426));
  3771. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3772. break;
  3773. }
  3774. case 447:
  3775. {
  3776. fromTile->removeThing(fromTile->ground);
  3777. fromTile->addThing(new Item(446));
  3778. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3779. break;
  3780. }
  3781. }
  3782. //end depot tiles-+
  3783. if (playerMoving)
  3784. {
  3785. if(playerMoving->attackedCreature != 0) {
  3786. Creature* attackedCreature = getCreatureByID(creatureMoving->attackedCreature);
  3787. if(attackedCreature){
  3788. autoCloseAttack(playerMoving, attackedCreature);
  3789. }
  3790. }
  3791.  
  3792. if(playerMoving->tradePartner != 0) {
  3793. Player* tradePartner = getPlayerByID(playerMoving->tradePartner);
  3794. if(tradePartner) {
  3795. if((std::abs(playerMoving->pos.x - tradePartner->pos.x) > 2) ||
  3796. (std::abs(playerMoving->pos.y - tradePartner->pos.y) > 2) || (playerMoving->pos.z != tradePartner->pos.z)
  3797. #ifdef HUCZU_FIX
  3798. || (fromTile->isHouse() && !toTile->isHouse())
  3799. #endif //HUCZU_FIX
  3800. ){
  3801. playerCloseTrade(playerMoving);
  3802. }
  3803. }
  3804. }
  3805.  
  3806. //change level begin
  3807. if(toTile->floorChangeDown())
  3808. {
  3809. Tile* downTile = getTile(to_x, to_y, to_z+1);
  3810. if(downTile){
  3811. //diagonal begin
  3812. if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  3813. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y+1, playerMoving->pos.z+1));
  3814. }
  3815. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  3816. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y+1, playerMoving->pos.z+1));
  3817. }
  3818. else if(downTile->floorChange(SOUTH) && 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(SOUTH) && downTile->floorChange(WEST)){
  3822. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y-1, playerMoving->pos.z+1));
  3823. }
  3824. //diagonal end
  3825. else if(downTile->floorChange(NORTH)){
  3826. teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y+1, playerMoving->pos.z+1));
  3827. }
  3828. else if(downTile->floorChange(SOUTH)){
  3829. teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y-1, playerMoving->pos.z+1));
  3830. }
  3831. else if(downTile->floorChange(EAST)){
  3832. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y, playerMoving->pos.z+1));
  3833. }
  3834. else if(downTile->floorChange(WEST)){
  3835. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y, playerMoving->pos.z+1));
  3836. }
  3837. else { //allow just real tiles to be hole'like
  3838. // TODO: later can be changed to check for piled items like chairs, boxes
  3839. teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y, playerMoving->pos.z+1));
  3840. }
  3841. }
  3842. }
  3843. //diagonal begin
  3844. else if(toTile->floorChange(NORTH) && toTile->floorChange(EAST)){
  3845. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y-1, playerMoving->pos.z-1));
  3846. }
  3847. else if(toTile->floorChange(NORTH) && toTile->floorChange(WEST)){
  3848. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y-1, playerMoving->pos.z-1));
  3849. }
  3850. else if(toTile->floorChange(SOUTH) && 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(SOUTH) && toTile->floorChange(WEST)){
  3854. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y+1, playerMoving->pos.z-1));
  3855. }
  3856. //diagonal end
  3857. else if(toTile->floorChange(NORTH)){
  3858. teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y-1, playerMoving->pos.z-1));
  3859. }
  3860. else if(toTile->floorChange(SOUTH)){
  3861. teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y+1, playerMoving->pos.z-1));
  3862. }
  3863. else if(toTile->floorChange(EAST)){
  3864. teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y, playerMoving->pos.z-1));
  3865. }
  3866. else if(toTile->floorChange(WEST)){
  3867. teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y, playerMoving->pos.z-1));
  3868. }
  3869. //change level end
  3870. }
  3871.  
  3872. // Magic Field in destiny field
  3873. #ifdef HUCZU_FIX
  3874. if(toTile && playerMoving && playerMoving->access < g_config.ACCESS_PROTECT && !toTile->downItems.empty() && !toTile->isPvpArena())
  3875. #else
  3876. if(toTile && playerMoving && playerMoving->access < g_config.ACCESS_PROTECT && !toTile->downItems.empty() || toTile && creatureMoving && creatureMoving->access < g_config.ACCESS_PROTECT && !toTile->downItems.empty())
  3877. #endif //HUCZU_FIX
  3878. {
  3879. ItemVector::iterator iit;
  3880. for (iit = toTile->downItems.begin(); iit != toTile->downItems.end(); iit++)
  3881. {
  3882. if(toTile->isPvpArena()) break;
  3883. if(!(*iit)) continue;
  3884. Item *item = dynamic_cast<Item*>(*iit);
  3885. if(!item) continue;
  3886. if(!creatureMoving || creatureMoving->isRemoved || creatureMoving->health <= 0) break;
  3887. if (item->getID() == 1492 || item->getID() == 1423 || item->getID() == 1487 || item->getID() == 1500){//Fire - Big
  3888. doFieldDamage(creatureMoving, 199 , NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 20);
  3889. // creature DamageColor, damageEffect, hitEffect attackType, offensive, damage
  3890. if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3891. CreateCondition(creatureMoving, NULL, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 10, 10, 2000, 10);
  3892. }
  3893. else if(item->getID() == 1493 || item->getID() == 1424 || item->getID() == 1488 || item->getID() == 1501){//Fire Medium
  3894. doFieldDamage(creatureMoving, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 10);
  3895. if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3896. CreateCondition(creatureMoving, NULL, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 10, 10, 2000, 10);
  3897. }
  3898. else if(item->getID() == 1495 || item->getID() == 1491 || item->getID() == 1504){//Energy
  3899. doFieldDamage(creatureMoving, 71, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 30);
  3900. if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3901. CreateCondition(creatureMoving, NULL, 71, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 30, 30, 2000, 3);
  3902. }
  3903. else if(item->getID() == 1496 || item->getID() == 1490 || item->getID() == 1503 || item->getID() == 1505){//Poison
  3904. doFieldDamage(creatureMoving, 30, NM_ME_POISEN, NM_ME_POISEN, ATTACK_POISON, true, 10);
  3905. if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3906. CreateCondition(creatureMoving, NULL, 30, NM_ME_POISEN, NM_ME_POISEN_RINGS, ATTACK_POISON, true, 10, 10, 2000, 10);
  3907. }
  3908. }
  3909. }
  3910. }
  3911.  
  3912. if(creatureMoving && !toTile->isPvpArena())
  3913. {
  3914. const MagicEffectItem* fieldItem = toTile->getFieldItem();
  3915.  
  3916. if(fieldItem) {
  3917. const MagicEffectTargetCreatureCondition *magicTargetCondition = fieldItem->getCondition();
  3918.  
  3919. if(!(getWorldType() == WORLD_TYPE_NO_PVP && playerMoving && magicTargetCondition && magicTargetCondition->getOwnerID() != 0)) {
  3920. fieldItem->getDamage(creatureMoving);
  3921. }
  3922.  
  3923. if(magicTargetCondition && ((magicTargetCondition->attackType == ATTACK_FIRE) ||
  3924. (magicTargetCondition->attackType == ATTACK_POISON) ||
  3925. (magicTargetCondition->attackType == ATTACK_ENERGY))) {
  3926. Creature *c = getCreatureByID(magicTargetCondition->getOwnerID());
  3927. creatureMakeMagic(c, thing->pos, magicTargetCondition);
  3928. }
  3929. }
  3930. }
  3931. }
  3932.  
  3933.  
  3934. void Game::getSpectators(const Range& range, SpectatorVec& list)
  3935. {
  3936. map->getSpectators(range, list);
  3937. }
  3938.  
  3939. void Game::creatureTurn(Creature *creature, Direction dir)
  3940. {
  3941. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureTurn()");
  3942.  
  3943. if (creature->direction != dir) {
  3944. creature->direction = dir;
  3945.  
  3946. int32_t stackpos = map->getTile(creature->pos)->getThingStackPos(creature);
  3947.  
  3948. SpectatorVec list;
  3949. SpectatorVec::iterator it;
  3950.  
  3951. map->getSpectators(Range(creature->pos, true), list);
  3952.  
  3953. //players
  3954. for(it = list.begin(); it != list.end(); ++it) {
  3955. if(dynamic_cast<Player*>(*it)) {
  3956. (*it)->onCreatureTurn(creature, stackpos);
  3957. }
  3958. }
  3959.  
  3960. //none-players
  3961. for(it = list.begin(); it != list.end(); ++it) {
  3962. if(!dynamic_cast<Player*>(*it)) {
  3963. (*it)->onCreatureTurn(creature, stackpos);
  3964. }
  3965. }
  3966. }
  3967. }
  3968.  
  3969. void Game::addCommandTag(std::string tag){
  3970. bool found = false;
  3971. for(size_t i=0;i< commandTags.size() ;i++){
  3972. if(commandTags[i] == tag){
  3973. found = true;
  3974. break;
  3975. }
  3976. }
  3977. if(!found){
  3978. commandTags.push_back(tag);
  3979. }
  3980. }
  3981.  
  3982. void Game::resetCommandTag(){
  3983. commandTags.clear();
  3984. }
  3985.  
  3986. void Game::creatureSay(Creature *creature, SpeakClasses type, const std::string &text)
  3987. {
  3988. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureSay()");
  3989. using std::string;
  3990. string spoken=text;
  3991. std::transform(spoken.begin(), spoken.end(), spoken.begin(), (int32_t(*)(int32_t))std::tolower);
  3992. bool GMcommand = false;
  3993. // First, check if this was a GM command
  3994. for(size_t i=0;i< commandTags.size() ;i++){
  3995. if(commandTags[i] == text.substr(0,1)){
  3996. if(commands.exeCommand(creature,text)){
  3997. GMcommand = true;
  3998. }
  3999. break;
  4000. }
  4001. }
  4002. Player* p = dynamic_cast<Player*>(creature);
  4003. Player* player = dynamic_cast<Player*>(creature);
  4004.  
  4005. #ifdef HUCZU_FIX
  4006. if (player && spoken == "exevo grav vita" && (!g_config.LEARN_SPELLS || player->knowsSpell("exevo grav vita")))
  4007. {
  4008. Tile *tile = NULL;
  4009. Position wgpos;
  4010. wgpos.z = player->pos.z;
  4011. switch(player->direction)
  4012. {
  4013. case NORTH:
  4014. wgpos.x = player->pos.x;
  4015. wgpos.y = player->pos.y-1;
  4016. break;
  4017. case SOUTH:
  4018. wgpos.x = player->pos.x;
  4019. wgpos.y = player->pos.y+1;
  4020. break;
  4021. case EAST:
  4022. wgpos.x = player->pos.x+1;
  4023. wgpos.y = player->pos.y;
  4024. break;
  4025. case WEST:
  4026. wgpos.x = player->pos.x-1;
  4027. wgpos.y = player->pos.y;
  4028. break;
  4029. default:
  4030. break;
  4031. }
  4032. tile = getTile(wgpos.x, wgpos.y, wgpos.z);
  4033. if(!tile || tile->isBlocking(BLOCK_SOLID,false,false) || tile->isPz())
  4034. {
  4035. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4036. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  4037. return;
  4038. }
  4039. if(player->access < 2)
  4040. {
  4041. if(player->mana < 220)
  4042. {
  4043. player->sendCancel("You do not have enough mana.");
  4044. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4045. return;
  4046. }
  4047. if(!player->premmium)
  4048. {
  4049. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4050. player->sendCancel("You need buy a premmium account for use this spell");
  4051. return;
  4052. }
  4053. if(player->maglevel < 26){
  4054. player->sendCancel("You do not have the magic level.");
  4055. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4056. return;
  4057. }
  4058. if(player->vocation != 2)
  4059. {
  4060. player->sendTextMessage(MSG_SMALLINFO, "You do not have the required vocation.");
  4061. player->sendMagicEffect(player->pos, 2);
  4062. return;
  4063. }
  4064. if (player->exhaustedTicks >= 1000)
  4065. {
  4066. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4067. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  4068. return;
  4069. }
  4070. }
  4071. player->mana -= 220;
  4072. player->addManaSpent(220);
  4073. player->exhaustedTicks = g_config.EXHAUSTED;
  4074. Item* Tree = Item::CreateItem(ITEM_WILDGROWTH, 1);
  4075. addThing(NULL, wgpos, Tree);
  4076. startDecay(Tree);
  4077. SpectatorVec list;
  4078. SpectatorVec::iterator it;
  4079. getSpectators(Range(player->pos), list);
  4080. for(it = list.begin(); it != list.end(); ++it) {
  4081. Player* playerek = dynamic_cast<Player*>(*it);
  4082. if(playerek)
  4083. playerek->sendMagicEffect(playerek->pos, NM_ME_MAGIC_POISEN);
  4084. }
  4085. player->sendMagicEffect(player->pos, NM_ME_MAGIC_ENERGIE);
  4086. }
  4087. #endif //HUCZU_FIX
  4088.  
  4089. if(spoken=="exana pox"){
  4090. MagicEffectClass pox;
  4091. pox.animationColor = 0;
  4092. pox.damageEffect = NM_ME_MAGIC_ENERGIE;
  4093. pox.hitEffect = 255;
  4094. pox.attackType = ATTACK_NONE;
  4095. pox.maxDamage = 0;
  4096. pox.minDamage = 0;
  4097. pox.offensive = false;
  4098. pox.manaCost = 30;
  4099. if(creatureMakeMagic(creature, creature->pos, &pox)){
  4100. creature->removeCondition(ATTACK_POISON);
  4101.  
  4102. if(player)
  4103. player->sendIcons();
  4104. }
  4105. }
  4106.  
  4107. if(!GMcommand){
  4108. Player* player = dynamic_cast<Player*>(creature);
  4109.  
  4110. if(text=="!besthit")
  4111. {
  4112. std::stringstream info;
  4113. if(player->maxDmg>0){
  4114. info << "Your best hit: " << player->maxDmg;}
  4115. else{
  4116. info << "You didn't any damage.";}
  4117. player->sendTextMessage(MSG_EVENT,info.str().c_str());
  4118. }
  4119.  
  4120. 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')) {
  4121.  
  4122. if(player->mana < 200) {
  4123. player->sendCancel("You do not have enough mana.");
  4124. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4125. return;
  4126. }
  4127. if(player->maglevel < 15) {
  4128. player->sendCancel("You do not have the magic level.");
  4129. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4130. return;
  4131. }
  4132. if(player->vocation != 1)
  4133. {
  4134. player->sendTextMessage(MSG_SMALLINFO, "You do not have the required vocation.");
  4135. player->sendMagicEffect(player->pos, 2);
  4136. return;
  4137. }
  4138. player->mana -= 200;
  4139. player->addManaSpent(200);
  4140. SpectatorVec list;
  4141. SpectatorVec::iterator it;
  4142. getSpectators(Range(creature->pos), list);
  4143. for(it = list.begin(); it != list.end(); ++it) {
  4144. if(Creature *c = dynamic_cast<Creature*>(*it)) {
  4145. if(c)
  4146. {
  4147. c->setInvisible(0);
  4148. creatureChangeOutfit(c);
  4149. }
  4150. }
  4151. player->sendMagicEffect(player->pos, NM_ME_MAGIC_ENERGIE);
  4152. }
  4153. }
  4154. if (player)
  4155. checkSpell(player, type, text);
  4156. // It was no command, or it was just a player
  4157. SpectatorVec list;
  4158. SpectatorVec::iterator it;
  4159. getSpectators(Range(creature->pos), list);
  4160. //players
  4161. for(it = list.begin(); it != list.end(); ++it) {
  4162. if(dynamic_cast<Player*>(*it)) {
  4163. (*it)->onCreatureSay(creature, type, text);
  4164. }
  4165. }
  4166.  
  4167. //none-players
  4168. for(it = list.begin(); it != list.end(); ++it) {
  4169. if(!dynamic_cast<Player*>(*it)) {
  4170. (*it)->onCreatureSay(creature, type, text);
  4171. }
  4172. }
  4173. }
  4174. }
  4175.  
  4176. void Game::teleport(Thing *thing, const Position& newPos)
  4177. {
  4178.  
  4179. if (newPos == thing->pos)
  4180. return;
  4181.  
  4182. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::teleport()");
  4183.  
  4184. //Tile *toTile = getTile( newPos.x, newPos.y, newPos.z );
  4185. Tile *toTile = map->getTile(newPos);
  4186. if (toTile)
  4187. {
  4188. Creature *creature = dynamic_cast<Creature*>(thing);
  4189. if (creature)
  4190. {
  4191. //Tile *fromTile = getTile( thing->pos.x, thing->pos.y, thing->pos.z );
  4192. Tile *fromTile = map->getTile(thing->pos);
  4193. if (!fromTile)
  4194. return;
  4195.  
  4196. int osp = fromTile->getThingStackPos(thing);
  4197. if (!fromTile->removeThing(thing))
  4198. return;
  4199.  
  4200. toTile->addThing(thing);
  4201. Position oldPos = thing->pos;
  4202.  
  4203. SpectatorVec list;
  4204. SpectatorVec::iterator it;
  4205.  
  4206. getSpectators(Range(thing->pos, true), list);
  4207.  
  4208. //players
  4209. for (it = list.begin(); it != list.end(); ++it)
  4210. {
  4211. if (Player* p = dynamic_cast<Player*>(*it))
  4212. {
  4213. if (p->attackedCreature == creature->getID())
  4214. {
  4215. autoCloseAttack(p, creature);
  4216. }
  4217.  
  4218. (*it)->onCreatureDisappear(creature, osp, true);
  4219. }
  4220. }
  4221.  
  4222. //none-players
  4223. for (it = list.begin(); it != list.end(); ++it)
  4224. {
  4225. if (!dynamic_cast<Player*>(*it))
  4226. {
  4227. (*it)->onCreatureDisappear(creature, osp, true);
  4228. }
  4229. }
  4230.  
  4231. if (newPos.y < oldPos.y)
  4232. creature->direction = NORTH;
  4233. if (newPos.y > oldPos.y)
  4234. creature->direction = SOUTH;
  4235. if (newPos.x > oldPos.x && (std::abs(newPos.x - oldPos.x) >= std::abs(newPos.y - oldPos.y)))
  4236. creature->direction = EAST;
  4237. if (newPos.x < oldPos.x && (std::abs(newPos.x - oldPos.x) >= std::abs(newPos.y - oldPos.y)))
  4238. creature->direction = WEST;
  4239.  
  4240. thing->pos = newPos;
  4241.  
  4242. Player *player = dynamic_cast<Player*>(creature);
  4243. if (player && player->attackedCreature != 0)
  4244. {
  4245. Creature* attackedCreature = getCreatureByID(player->attackedCreature);
  4246. if (attackedCreature)
  4247. {
  4248. autoCloseAttack(player, attackedCreature);
  4249. }
  4250. }
  4251.  
  4252. list.clear();
  4253. getSpectators(Range(thing->pos, true), list);
  4254.  
  4255. #ifdef TRS_GM_INVISIBLE
  4256. //players
  4257. for (it = list.begin(); it != list.end(); ++it)
  4258. {
  4259. if (player)
  4260. {
  4261. if (player->gmInvisible && player == (*it))
  4262. {
  4263. if (Player* p = dynamic_cast<Player*>(*it))
  4264. {
  4265. if (p->attackedCreature == creature->getID())
  4266. {
  4267. autoCloseAttack(p, creature);
  4268. }
  4269. (*it)->onTeleport(creature, &oldPos, osp);
  4270. }
  4271. }
  4272. else if (player->gmInvisible && player != (*it) && (*it)->access < player->access)
  4273. {
  4274. // Nothing Because he is invisible...
  4275. }
  4276. else
  4277. {
  4278. if (Player* p = dynamic_cast<Player*>(*it))
  4279. {
  4280. if (p->attackedCreature == creature->getID())
  4281. {
  4282. autoCloseAttack(p, creature);
  4283. }
  4284. (*it)->onTeleport(creature, &oldPos, osp);
  4285. }
  4286. }
  4287. }
  4288. else
  4289. creatureBroadcastTileUpdated(newPos);
  4290. }
  4291. #else //TRS_GM_INVISIBLE
  4292. //players
  4293. for (it = list.begin(); it != list.end(); ++it)
  4294. {
  4295. if (Player* p = dynamic_cast<Player*>(*it))
  4296. {
  4297. if (p->attackedCreature == creature->getID())
  4298. {
  4299. autoCloseAttack(p, creature);
  4300. }
  4301. (*it)->onTeleport(creature, &oldPos, osp);
  4302. }
  4303. }
  4304. #endif //TRS_GM_INVISIBLE
  4305.  
  4306. //none-players
  4307. for (it = list.begin(); it != list.end(); ++it)
  4308. {
  4309. if (!dynamic_cast<Player*>(*it))
  4310. {
  4311. (*it)->onTeleport(creature, &oldPos, osp);
  4312. }
  4313. }
  4314. }
  4315. else
  4316. {
  4317. if (removeThing(NULL, thing->pos, thing, false))
  4318. {
  4319. addThing(NULL, newPos, thing);
  4320. }
  4321. }
  4322. }//if(toTile)
  4323.  
  4324. }
  4325.  
  4326.  
  4327. void Game::creatureChangeOutfit(Creature *creature)
  4328. {
  4329. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureChangeOutfit()");
  4330.  
  4331. SpectatorVec list;
  4332. SpectatorVec::iterator it;
  4333.  
  4334. getSpectators(Range(creature->pos, true), list);
  4335.  
  4336. //players
  4337. for(it = list.begin(); it != list.end(); ++it) {
  4338. if(dynamic_cast<Player*>(*it)) {
  4339. (*it)->onCreatureChangeOutfit(creature);
  4340. }
  4341. }
  4342.  
  4343. //none-players
  4344. for(it = list.begin(); it != list.end(); ++it) {
  4345. if(!dynamic_cast<Player*>(*it)) {
  4346. (*it)->onCreatureChangeOutfit(creature);
  4347. }
  4348. }
  4349. }
  4350.  
  4351. void Game::creatureWhisper(Creature *creature, const std::string &text)
  4352. {
  4353. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureWhisper()");
  4354.  
  4355. SpectatorVec list;
  4356. SpectatorVec::iterator it;
  4357.  
  4358. getSpectators(Range(creature->pos), list);
  4359.  
  4360. //players
  4361. for(it = list.begin(); it != list.end(); ++it) {
  4362. if(dynamic_cast<Player*>(*it)) {
  4363. if(abs(creature->pos.x - (*it)->pos.x) > 1 || abs(creature->pos.y - (*it)->pos.y) > 1)
  4364. (*it)->onCreatureSay(creature, SPEAK_WHISPER, std::string("pspsps"));
  4365. else
  4366. (*it)->onCreatureSay(creature, SPEAK_WHISPER, text);
  4367. }
  4368. }
  4369.  
  4370. //none-players
  4371. for(it = list.begin(); it != list.end(); ++it) {
  4372. if(!dynamic_cast<Player*>(*it)) {
  4373. if(abs(creature->pos.x - (*it)->pos.x) > 1 || abs(creature->pos.y - (*it)->pos.y) > 1)
  4374. (*it)->onCreatureSay(creature, SPEAK_WHISPER, std::string("pspsps"));
  4375. else
  4376. (*it)->onCreatureSay(creature, SPEAK_WHISPER, text);
  4377. }
  4378. }
  4379. }
  4380.  
  4381. void Game::creatureYell(Creature *creature, std::string &text)
  4382. {
  4383. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureYell()");
  4384. if(!creature)
  4385. return;
  4386. #ifdef HUCZU_FIX
  4387. if(creature->level < 2 && creature->access < 2){
  4388. return;
  4389. }
  4390. #endif //HUCZU_FIX
  4391. std::transform(text.begin(), text.end(), text.begin(), upchar);
  4392.  
  4393. SpectatorVec list;
  4394. SpectatorVec::iterator it;
  4395. getSpectators(Range(creature->pos, 18, 18, 14, 14), list);
  4396.  
  4397. for(it = list.begin(); it != list.end(); ++it){
  4398. if(*it)
  4399. (*it)->onCreatureSay(creature, SPEAK_YELL, text);
  4400. }
  4401. }
  4402.  
  4403. //ZBÊ„NE
  4404. /*void Game::creatureYell(Creature *creature, std::string &text)
  4405. {
  4406. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureYell()");
  4407. Player* player = dynamic_cast<Player*>(creature);
  4408. #ifdef HUCZU_FIX
  4409. if(player && player->level < 2 && player->access < 2){
  4410. player->sendTextMessage(MSG_SMALLINFO, "You cannot yell.");
  4411. return;
  4412. }
  4413. #endif //HUCZU_FIX
  4414. if (player && player->access < g_config.ACCESS_PROTECT && player->exhaustedTicks >= 1000)
  4415. {
  4416. player->exhaustedTicks += g_config.EXHAUSTED_ADD;
  4417. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  4418. }
  4419. else {
  4420. creature->exhaustedTicks = g_config.EXHAUSTED;
  4421. std::transform(text.begin(), text.end(), text.begin(), upchar);
  4422.  
  4423. SpectatorVec list;
  4424. SpectatorVec::iterator it;
  4425.  
  4426. getSpectators(Range(creature->pos, 18, 18, 14, 14), list);
  4427.  
  4428. //players
  4429. for(it = list.begin(); it != list.end(); ++it) {
  4430. if(dynamic_cast<Player*>(*it)) {
  4431. (*it)->onCreatureSay(creature, SPEAK_YELL, text);
  4432. }
  4433. }
  4434. }
  4435. }*/
  4436.  
  4437. void Game::creatureSpeakTo(Creature *creature, SpeakClasses type,const std::string &receiver, const std::string &text)
  4438. {
  4439. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureSpeakTo");
  4440.  
  4441. Player* player = dynamic_cast<Player*>(creature);
  4442. if(!player)
  4443. return;
  4444.  
  4445. Player* toPlayer = getPlayerByName(receiver);
  4446. if(!toPlayer) {
  4447. player->sendTextMessage(MSG_SMALLINFO, "A player with this name is not online.");
  4448. return;
  4449. }
  4450. if(creature->access < g_config.ACCESS_TALK){
  4451. type = SPEAK_PRIVATE;
  4452. }
  4453.  
  4454. if(!toPlayer){
  4455. player->onCreatureSay(player, type, text);
  4456. }
  4457. time_t ticks = time(0);
  4458. tm* now = localtime(&ticks);
  4459. char buf[32];
  4460. strftime(buf, sizeof(buf), "%d/%m/%Y %H:%M", now);
  4461. std::ofstream out2("data/logs/private.log", std::ios::app);
  4462. out2 << '[' << buf << "] " << toPlayer->getName() << " from " << player->getName() << ": " << text << std::endl;
  4463. out2.close();
  4464.  
  4465. toPlayer->onCreatureSay(player, type, text);
  4466. std::stringstream ss;
  4467. ss << "Message sent to " << toPlayer->getName() << ".";
  4468. player->sendTextMessage(MSG_SMALLINFO, ss.str().c_str());
  4469. }
  4470.  
  4471. void Game::creatureTalkToChannel(Player *player, SpeakClasses type, std::string &text, uint16_t channelId)
  4472. {
  4473. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureTalkToChannel");
  4474.  
  4475. if(player->access < g_config.ACCESS_TALK){
  4476. type = SPEAK_CHANNEL_Y;
  4477. }
  4478.  
  4479. if(player->guildStatus == GUILD_LEADER && channelId == 0x00)
  4480. type = SPEAK_CHANNEL_R1;
  4481. if(player->guildStatus == GUILD_VICE && channelId == 0x00)
  4482. type = SPEAK_CHANNEL_O;
  4483.  
  4484. g_chat.talkToChannel(player, type, text, channelId);
  4485. }
  4486.  
  4487. void Game::creatureMonsterYell(Monster* monster, const std::string& text)
  4488. {
  4489. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureMonsterYell()");
  4490.  
  4491. SpectatorVec list;
  4492. SpectatorVec::iterator it;
  4493.  
  4494. map->getSpectators(Range(monster->pos, 18, 18, 14, 14), list);
  4495.  
  4496. //players
  4497. for(it = list.begin(); it != list.end(); ++it) {
  4498. if(dynamic_cast<Player*>(*it)) {
  4499. (*it)->onCreatureSay(monster, SPEAK_MONSTER1, text);
  4500. }
  4501. }
  4502. }
  4503.  
  4504. void Game::creatureBroadcastMessage(Creature *creature, const std::string &text)
  4505. {
  4506. if(creature->access < g_config.ACCESS_TALK)
  4507. return;
  4508.  
  4509. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureBroadcastMessage()");
  4510.  
  4511. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  4512. {
  4513. (*it).second->onCreatureSay(creature, SPEAK_BROADCAST, text);
  4514. }
  4515. }
  4516.  
  4517. /** \todo Someone _PLEASE_ clean up this mess */
  4518. bool Game::creatureMakeMagic(Creature *creature, const Position& centerpos, const MagicEffectClass* me)
  4519. {
  4520.  
  4521. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureMakeMagic()");
  4522.  
  4523. #ifdef __DEBUG__
  4524. cout << "creatureMakeMagic: " << (creature ? creature->getName() : "No name") << ", x: " << centerpos.x << ", y: " << centerpos.y << ", z: " << centerpos.z << std::endl;
  4525. #endif
  4526.  
  4527. Position frompos;
  4528.  
  4529. if(creature) {
  4530. frompos = creature->pos;
  4531.  
  4532. if(!creatureOnPrepareMagicAttack(creature, centerpos, me))
  4533. {
  4534.  
  4535. return false;
  4536. }
  4537. }
  4538. else {
  4539. frompos = centerpos;
  4540. }
  4541.  
  4542. MagicAreaVec tmpMagicAreaVec;
  4543. me->getArea(centerpos, tmpMagicAreaVec);
  4544.  
  4545. std::vector<Position> poslist;
  4546.  
  4547. Position topLeft(0xFFFF, 0xFFFF, frompos.z), bottomRight(0, 0, frompos.z);
  4548.  
  4549. //Filter out the tiles we actually can work on
  4550. for(MagicAreaVec::iterator maIt = tmpMagicAreaVec.begin(); maIt != tmpMagicAreaVec.end(); ++maIt) {
  4551. Tile *t = map->getTile(maIt->x, maIt->y, maIt->z);
  4552. if(t && (!creature || (creature->access >= g_config.ACCESS_PROTECT || !me->offensive || !t->isPz()) ) ) {
  4553. if((t->isBlocking(BLOCK_PROJECTILE) == RET_NOERROR) && (me->isIndirect() ||
  4554. //(map->canThrowItemTo(frompos, (*maIt), false, true) && !t->floorChange()))) {
  4555. ((map->canThrowObjectTo(centerpos, (*maIt), BLOCK_PROJECTILE) == RET_NOERROR) && !t->floorChange()))) {
  4556.  
  4557. if(maIt->x < topLeft.x)
  4558. topLeft.x = maIt->x;
  4559.  
  4560. if(maIt->y < topLeft.y)
  4561. topLeft.y = maIt->y;
  4562.  
  4563. if(maIt->x > bottomRight.x)
  4564. bottomRight.x = maIt->x;
  4565.  
  4566. if(maIt->y > bottomRight.y)
  4567. bottomRight.y = maIt->y;
  4568.  
  4569. poslist.push_back(*maIt);
  4570. }
  4571. }
  4572. }
  4573.  
  4574. topLeft.z = frompos.z;
  4575. bottomRight.z = frompos.z;
  4576.  
  4577. if(topLeft.x == 0xFFFF || topLeft.y == 0xFFFF || bottomRight.x == 0 || bottomRight.y == 0){
  4578.  
  4579. return false;
  4580. }
  4581.  
  4582. #ifdef __DEBUG__
  4583. printf("top left %d %d %d\n", topLeft.x, topLeft.y, topLeft.z);
  4584. printf("bottom right %d %d %d\n", bottomRight.x, bottomRight.y, bottomRight.z);
  4585. #endif
  4586.  
  4587. //We do all changes against a GameState to keep track of the changes,
  4588. //need some more work to work for all situations...
  4589. GameState gamestate(this, Range(topLeft, bottomRight));
  4590.  
  4591. //Tile *targettile = getTile(centerpos.x, centerpos.y, centerpos.z);
  4592. Tile *targettile = map->getTile(centerpos);
  4593. bool bSuccess = false;
  4594. bool hasTarget = false;
  4595. bool isBlocking = true;
  4596. if(targettile){
  4597. hasTarget = !targettile->creatures.empty();
  4598. isBlocking = (targettile->isBlocking(BLOCK_SOLID, true) != RET_NOERROR);
  4599. }
  4600.  
  4601. if(targettile && me->canCast(isBlocking, !targettile->creatures.empty())) {
  4602. bSuccess = true;
  4603.  
  4604. //Apply the permanent effect to the map
  4605. std::vector<Position>::const_iterator tlIt;
  4606. for(tlIt = poslist.begin(); tlIt != poslist.end(); ++tlIt) {
  4607. gamestate.onAttack(creature, Position(*tlIt), me);
  4608. }
  4609. }
  4610.  
  4611. SpectatorVec spectatorlist = gamestate.getSpectators();
  4612. SpectatorVec::iterator it;
  4613.  
  4614. for(it = spectatorlist.begin(); it != spectatorlist.end(); ++it) {
  4615. Player* spectator = dynamic_cast<Player*>(*it);
  4616.  
  4617. if(!spectator)
  4618. continue;
  4619.  
  4620. if(bSuccess) {
  4621. me->getDistanceShoot(spectator, creature, centerpos, hasTarget);
  4622.  
  4623. std::vector<Position>::const_iterator tlIt;
  4624. for(tlIt = poslist.begin(); tlIt != poslist.end(); ++tlIt) {
  4625. Position pos = *tlIt;
  4626. //Tile *tile = getTile(pos.x, pos.y, pos.z);
  4627. Tile *tile = map->getTile(pos);
  4628. const CreatureStateVec& creatureStateVec = gamestate.getCreatureStateList(tile);
  4629.  
  4630. if(creatureStateVec.empty()) { //no targets
  4631. me->getMagicEffect(spectator, creature, NULL, pos, 0, targettile->isPz(), isBlocking);
  4632. }
  4633. else {
  4634. for(CreatureStateVec::const_iterator csIt = creatureStateVec.begin(); csIt != creatureStateVec.end(); ++csIt) {
  4635. Creature *target = csIt->first;
  4636. const CreatureState& creatureState = csIt->second;
  4637.  
  4638. me->getMagicEffect(spectator, creature, target, target->pos, creatureState.damage, tile->isPz(), false);
  4639.  
  4640. //could be death due to a magic damage with no owner (fire/poison/energy)
  4641. if(creature && target->isRemoved == true) {
  4642.  
  4643. for(std::vector<Creature*>::const_iterator cit = creatureState.attackerlist.begin(); cit != creatureState.attackerlist.end(); ++cit) {
  4644. Creature* gainExpCreature = *cit;
  4645. if(dynamic_cast<Player*>(gainExpCreature))
  4646. dynamic_cast<Player*>(gainExpCreature)->sendStats();
  4647.  
  4648. if(spectator->CanSee(gainExpCreature->pos.x, gainExpCreature->pos.y, gainExpCreature->pos.z)){
  4649. std::stringstream exp;
  4650. exp << target->getGainedExperience(gainExpCreature);
  4651. spectator->sendAnimatedText(gainExpCreature->pos, 0xD7, exp.str());
  4652. }
  4653. }
  4654.  
  4655. }
  4656.  
  4657. if(spectator->CanSee(target->pos.x, target->pos.y, target->pos.z))
  4658. {
  4659. if(creatureState.damage != 0) {
  4660. std::stringstream dmg;
  4661. dmg << std::abs(creatureState.damage);
  4662. #ifdef TJ_MONSTER_BLOOD
  4663. if (me->attackType & ATTACK_PHYSICAL)
  4664. spectator->sendAnimatedText(target->pos, target->bloodcolor, dmg.str());
  4665. else
  4666. #endif //TJ_MONSTER_BLOOD
  4667. spectator->sendAnimatedText(target->pos, me->animationColor, dmg.str());
  4668. }
  4669.  
  4670. if(creatureState.manaDamage > 0){
  4671. spectator->sendMagicEffect(target->pos, NM_ME_LOOSE_ENERGY);
  4672. std::stringstream manaDmg;
  4673. manaDmg << std::abs(creatureState.manaDamage);
  4674. spectator->sendAnimatedText(target->pos, 2, manaDmg.str());
  4675. }
  4676.  
  4677. if (target->health > 0)
  4678. spectator->sendCreatureHealth(target);
  4679.  
  4680. if (spectator == target){
  4681. CreateManaDamageUpdate(target, creature, creatureState.manaDamage);
  4682. CreateDamageUpdate(target, creature, creatureState.damage);
  4683. }
  4684. }
  4685. }
  4686. }
  4687. }
  4688. }
  4689. else {
  4690. me->FailedToCast(spectator, creature, isBlocking, hasTarget);
  4691. }
  4692.  
  4693. }
  4694.  
  4695. return bSuccess;
  4696. }
  4697.  
  4698. void Game::creatureApplyDamage(Creature *creature, int32_t damage, int32_t &outDamage, int32_t &outManaDamage
  4699. #ifdef YUR_PVP_ARENA
  4700. , CreatureVector* arenaLosers
  4701. #endif //YUR_PVP_ARENA
  4702. )
  4703. {
  4704. outDamage = damage;
  4705. outManaDamage = 0;
  4706.  
  4707. if (damage > 0)
  4708. {
  4709. if (creature->manaShieldTicks >= 1000 && (damage < creature->mana) ) {
  4710. outManaDamage = damage;
  4711. outDamage = 0;
  4712. }
  4713. else if (creature->manaShieldTicks >= 1000 && (damage > creature->mana) ) {
  4714. outManaDamage = creature->mana;
  4715. outDamage -= outManaDamage;
  4716. }
  4717. else if((creature->manaShieldTicks < 1000) && (damage > creature->health))
  4718. outDamage = creature->health;
  4719. else if (creature->manaShieldTicks >= 1000 && (damage > (creature->health + creature->mana))) {
  4720. outDamage = creature->health;
  4721. outManaDamage = creature->mana;
  4722. }
  4723.  
  4724. if(creature->manaShieldTicks < 1000 || (creature->mana == 0))
  4725. #ifdef YUR_PVP_ARENA
  4726. creature->drainHealth(outDamage, arenaLosers);
  4727. #else
  4728. creature->drainHealth(outDamage);
  4729. #endif //YUR_PVP_ARENA
  4730. else if(outManaDamage > 0)
  4731. {
  4732. #ifdef YUR_PVP_ARENA
  4733. creature->drainHealth(outDamage, arenaLosers);
  4734. #else
  4735. creature->drainHealth(outDamage);
  4736. #endif //YUR_PVP_ARENA
  4737. creature->drainMana(outManaDamage);
  4738. }
  4739. else
  4740. creature->drainMana(outDamage);
  4741. }
  4742. else {
  4743. int32_t newhealth = creature->health - damage;
  4744. if(newhealth > creature->healthmax)
  4745. newhealth = creature->healthmax;
  4746.  
  4747. creature->health = newhealth;
  4748.  
  4749. outDamage = creature->health - newhealth;
  4750. outManaDamage = 0;
  4751. }
  4752. }
  4753.  
  4754. bool Game::creatureCastSpell(Creature *creature, const Position& centerpos, const MagicEffectClass& me)
  4755. {
  4756.  
  4757. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureCastSpell()");
  4758. std::cout << "Game::creatureCastSpell " << creature->getName() << std::endl;
  4759. // if(me.offensive == false && me.damageEffect > 0 && creature->conditions.hasCondition(ATTACK_PARALYZE))
  4760. if(me.damageEffect <= 0 && creature->conditions.hasCondition(ATTACK_PARALYZE))
  4761. {
  4762. creature->removeCondition(ATTACK_PARALYZE);
  4763. changeSpeed(creature->getID(), creature->getNormalSpeed()+creature->hasteSpeed);
  4764. Player *player = dynamic_cast<Player*>(creature);
  4765. if(player)
  4766. player->sendIcons();
  4767. }
  4768.  
  4769. return creatureMakeMagic(creature, centerpos, &me);
  4770. }
  4771.  
  4772.  
  4773. bool Game::creatureThrowRune(Creature *creature, const Position& centerpos, const MagicEffectClass& me) {
  4774.  
  4775.  
  4776. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureThrowRune()");
  4777. bool ret = false;
  4778. #ifdef HUCZU_FIX
  4779. int32_t dist_x = std::abs(creature->pos.x - centerpos.x);
  4780. int32_t dist_y = std::abs(creature->pos.y - centerpos.y);
  4781. #endif //HUCZU_FIX
  4782. if(creature->pos.z != centerpos.z) {
  4783. creature->sendCancel("You need to be on the same floor.");
  4784. }
  4785. #ifdef HUCZU_FIX
  4786. else if(dist_x > 7 || dist_y > 6)
  4787. return TOO_FAR;
  4788. #endif //HUCZU_FIX
  4789. //else if(!map->canThrowItemTo(creature->pos, centerpos, false, true)) {
  4790. else if(map->canThrowObjectTo(creature->pos, centerpos, BLOCK_PROJECTILE) != RET_NOERROR) {
  4791. creature->sendCancel("You cannot throw there.");
  4792. }
  4793. else
  4794. ret = creatureMakeMagic(creature, centerpos, &me);
  4795.  
  4796.  
  4797.  
  4798. return ret;
  4799. }
  4800.  
  4801. bool Game::creatureOnPrepareAttack(Creature *creature, Position pos)
  4802. {
  4803. if(creature){
  4804. Player* player = dynamic_cast<Player*>(creature);
  4805.  
  4806. //Tile* tile = (Tile*)getTile(creature->pos.x, creature->pos.y, creature->pos.z);
  4807. Tile* tile = map->getTile(creature->pos);
  4808. //Tile* targettile = getTile(pos.x, pos.y, pos.z);
  4809. Tile* targettile = map->getTile(pos);
  4810.  
  4811. if(creature->access < g_config.ACCESS_PROTECT) {
  4812. if(tile && tile->isPz()) {
  4813. if(player) {
  4814. player->sendTextMessage(MSG_SMALLINFO, "You may not attack a person while you are in a protection zone.");
  4815. playerSetAttackedCreature(player, 0);
  4816. }
  4817.  
  4818. return false;
  4819. }
  4820. else if(targettile && targettile->isPz()) {
  4821. if(player) {
  4822. player->sendTextMessage(MSG_SMALLINFO, "You may not attack a person in a protection zone.");
  4823. playerSetAttackedCreature(player, 0);
  4824. }
  4825.  
  4826. return false;
  4827. }
  4828. }
  4829.  
  4830. return true;
  4831. }
  4832.  
  4833. return false;
  4834. }
  4835.  
  4836. bool Game::creatureOnPrepareMagicAttack(Creature *creature, Position pos, const MagicEffectClass* me)
  4837. {
  4838. if(!me->offensive || me->isIndirect() || creatureOnPrepareAttack(creature, pos)) {
  4839. /*
  4840. if(creature->access < ACCESS_PROTECT) {
  4841. if(!((std::abs(creature->pos.x-centerpos.x) <= 8) && (std::abs(creature->pos.y-centerpos.y) <= 6) &&
  4842. (creature->pos.z == centerpos.z)))
  4843. return false;
  4844. }
  4845. */
  4846.  
  4847. Player* player = dynamic_cast<Player*>(creature);
  4848. if(player) {
  4849. if(player->access < g_config.ACCESS_PROTECT) {
  4850. if(player->exhaustedTicks >= 1000 && me->causeExhaustion(true)) {
  4851. if(me->offensive) {
  4852. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.",player->pos, NM_ME_PUFF);
  4853. player->exhaustedTicks += g_config.EXHAUSTED_ADD;
  4854. }
  4855.  
  4856. return false;
  4857. }
  4858. else if(player->mana < me->manaCost) {
  4859. player->sendTextMessage(MSG_SMALLINFO, "You do not have enough mana.",player->pos, NM_ME_PUFF);
  4860. return false;
  4861. }
  4862. else
  4863. player->mana -= me->manaCost;
  4864. //player->manaspent += me->manaCost;
  4865. player->addManaSpent(me->manaCost);
  4866. }
  4867. }
  4868.  
  4869. return true;
  4870. }
  4871.  
  4872. return false;
  4873. }
  4874.  
  4875. void Game::creatureMakeDamage(Creature *creature, Creature *attackedCreature, fight_t damagetype)
  4876. {
  4877. if(!creatureOnPrepareAttack(creature, attackedCreature->pos))
  4878. return;
  4879.  
  4880.  
  4881. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureMakeDamage()");
  4882.  
  4883. Player* player = dynamic_cast<Player*>(creature);
  4884. Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  4885.  
  4886. #ifdef ANTI_MISS
  4887. if(player && player->atkMode == 1 && player->access <= g_config.ACCESS_PROTECT && attackedPlayer && attackedPlayer->skullType == 0) {
  4888. player->sendCancelAttacking();
  4889. player->sendTextMessage(MSG_SMALLINFO, "Turn secure mode off if you really want to attack unmarked players.");
  4890. return;
  4891. }
  4892. #endif //ANTI_MISS
  4893.  
  4894. //Tile* targettile = getTile(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z);
  4895. Tile* targettile = map->getTile(attackedCreature->pos);
  4896.  
  4897. //can the attacker reach the attacked?
  4898. bool inReach = false;
  4899.  
  4900. switch(damagetype){
  4901. case FIGHT_MELEE:
  4902. if((std::abs(creature->pos.x-attackedCreature->pos.x) <= 1) &&
  4903. (std::abs(creature->pos.y-attackedCreature->pos.y) <= 1) &&
  4904. (creature->pos.z == attackedCreature->pos.z))
  4905. inReach = true;
  4906. break;
  4907. case FIGHT_DIST:
  4908. if((std::abs(creature->pos.x-attackedCreature->pos.x) <= 8) &&
  4909. (std::abs(creature->pos.y-attackedCreature->pos.y) <= 5) &&
  4910. (creature->pos.z == attackedCreature->pos.z)) {
  4911.  
  4912. //if(map->canThrowItemTo(creature->pos, attackedCreature->pos, false, true))
  4913. if(map->canThrowObjectTo(creature->pos, attackedCreature->pos, BLOCK_PROJECTILE) == RET_NOERROR)
  4914. inReach = true;
  4915. }
  4916. break;
  4917. case FIGHT_MAGICDIST:
  4918. if((std::abs(creature->pos.x-attackedCreature->pos.x) <= 8) &&
  4919. (std::abs(creature->pos.y-attackedCreature->pos.y) <= 5) &&
  4920. (creature->pos.z == attackedCreature->pos.z)) {
  4921.  
  4922. //if(map->canThrowItemTo(creature->pos, attackedCreature->pos, false, true))
  4923. if(map->canThrowObjectTo(creature->pos, attackedCreature->pos, BLOCK_PROJECTILE) == RET_NOERROR)
  4924. inReach = true;
  4925. }
  4926. break;
  4927.  
  4928. }
  4929.  
  4930. if (player && player->access < g_config.ACCESS_PROTECT)
  4931. {
  4932. #ifdef YUR_CVS_MODS
  4933. player->inFightTicks = std::max(g_config.PZ_LOCKED, player->inFightTicks);
  4934. #else
  4935. player->inFightTicks = g_config.PZ_LOCKED;
  4936. #endif //YUR_CVS_MODS
  4937.  
  4938. player->sendIcons();
  4939. if(attackedPlayer)
  4940. player->pzLocked = true;
  4941. }
  4942.  
  4943. if(attackedPlayer && attackedPlayer->access < g_config.ACCESS_PROTECT)
  4944. {
  4945. #ifdef YUR_CVS_MODS
  4946. attackedPlayer->inFightTicks = std::max(g_config.PZ_LOCKED, attackedPlayer->inFightTicks);
  4947. #else
  4948. attackedPlayer->inFightTicks = g_config.PZ_LOCKED;
  4949. #endif //YUR_CVS_MODS
  4950. attackedPlayer->sendIcons();
  4951. }
  4952.  
  4953. if(!inReach){
  4954. return;
  4955. }
  4956.  
  4957. //We do all changes against a GameState to keep track of the changes,
  4958. //need some more work to work for all situations...
  4959. GameState gamestate(this, Range(creature->pos, attackedCreature->pos));
  4960.  
  4961. gamestate.onAttack(creature, attackedCreature->pos, attackedCreature);
  4962.  
  4963. const CreatureStateVec& creatureStateVec = gamestate.getCreatureStateList(targettile);
  4964. const CreatureState& creatureState = creatureStateVec[0].second;
  4965.  
  4966. if(player && (creatureState.damage > 0 || creatureState.manaDamage > 0)) {
  4967. #ifdef WANDS_JIDDO
  4968. 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()))))
  4969. player->addSkillTry(2);
  4970. #else
  4971. player->addSkillTry(2);
  4972. #endif
  4973. }
  4974. else if(player){
  4975. #ifdef WANDS_JIDDO
  4976. if(player && ((player->items[SLOT_RIGHT] && (!player->items[SLOT_RIGHT]->getWand())) || (!player->items[SLOT_RIGHT] && !player->items[SLOT_LEFT]) || (player->items[SLOT_LEFT] && (!player->items[SLOT_LEFT]->getWand()))))
  4977. player->addSkillTry(1);
  4978. #else
  4979. player->addSkillTry(1);
  4980. #endif
  4981. }
  4982. if(attackedPlayer){
  4983. NetworkMessage msg;
  4984. msg.AddByte(0x86);
  4985. msg.AddU32(creature->getID());
  4986. msg.AddByte(0x00);
  4987. attackedPlayer->sendNetworkMessage(&msg);
  4988. }
  4989.  
  4990. SpectatorVec spectatorlist = gamestate.getSpectators();
  4991. SpectatorVec::iterator it;
  4992.  
  4993. for(it = spectatorlist.begin(); it != spectatorlist.end(); ++it) {
  4994. Player* spectator = dynamic_cast<Player*>(*it);
  4995. if(!spectator)
  4996. continue;
  4997.  
  4998. if(damagetype != FIGHT_MELEE){
  4999. spectator->sendDistanceShoot(creature->pos, attackedCreature->pos, creature->getSubFightType());
  5000. }
  5001.  
  5002. if (attackedCreature->manaShieldTicks < 1000 && (creatureState.damage == 0) &&
  5003. (spectator->CanSee(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z))) {
  5004. spectator->sendMagicEffect(attackedCreature->pos, NM_ME_PUFF);
  5005. }
  5006. else if (attackedCreature->manaShieldTicks < 1000 && (creatureState.damage < 0) &&
  5007. (spectator->CanSee(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z))) {
  5008. spectator->sendMagicEffect(attackedCreature->pos, NM_ME_BLOCKHIT);
  5009. }
  5010. else {
  5011. for(std::vector<Creature*>::const_iterator cit = creatureState.attackerlist.begin(); cit != creatureState.attackerlist.end(); ++cit) {
  5012. Creature* gainexpCreature = *cit;
  5013. if(dynamic_cast<Player*>(gainexpCreature))
  5014. dynamic_cast<Player*>(gainexpCreature)->sendStats();
  5015.  
  5016. if(spectator->CanSee(gainexpCreature->pos.x, gainexpCreature->pos.y, gainexpCreature->pos.z)) {
  5017. char exp[128];
  5018. #ifdef YUR_HIGH_LEVELS // TODO: format like this: 1,000,000
  5019. sprintf(exp,"%lld",attackedCreature->getGainedExperience(gainexpCreature));
  5020. spectator->sendAnimatedText(gainexpCreature->pos, 0xD7, exp);
  5021. #else
  5022. itoa(attackedCreature->getGainedExperience(gainexpCreature), exp, 10);
  5023. #endif //YUR_HIGH_LEVLES
  5024. spectator->sendAnimatedText(gainexpCreature->pos, 0xD7, exp);
  5025. }
  5026. }
  5027.  
  5028. if (spectator->CanSee(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z))
  5029. {
  5030. if(creatureState.damage > 0) {
  5031. std::stringstream dmg;
  5032. dmg << std::abs(creatureState.damage);
  5033. #ifdef TJ_MONSTER_BLOOD
  5034. spectator->sendAnimatedText(attackedCreature->pos, attackedCreature->bloodcolor, dmg.str());
  5035. spectator->sendMagicEffect(attackedCreature->pos, attackedCreature->bloodeffect);
  5036. #else
  5037. spectator->sendAnimatedText(attackedCreature->pos, 0xB4, dmg.str());
  5038. spectator->sendMagicEffect(attackedCreature->pos, NM_ME_DRAW_BLOOD);
  5039. #endif //TJ_MONSTER_BLOOD
  5040. }
  5041.  
  5042. if(creatureState.manaDamage >0) {
  5043. std::stringstream manaDmg;
  5044. manaDmg << std::abs(creatureState.manaDamage);
  5045. spectator->sendMagicEffect(attackedCreature->pos, NM_ME_LOOSE_ENERGY);
  5046. spectator->sendAnimatedText(attackedCreature->pos, 2, manaDmg.str());
  5047. }
  5048.  
  5049. if (attackedCreature->health > 0)
  5050. spectator->sendCreatureHealth(attackedCreature);
  5051.  
  5052. if (spectator == attackedCreature) {
  5053. CreateManaDamageUpdate(attackedCreature, creature, creatureState.manaDamage);
  5054. CreateDamageUpdate(attackedCreature, creature, creatureState.damage);
  5055. }
  5056. }
  5057. }
  5058. }
  5059.  
  5060. if(damagetype != FIGHT_MELEE && player) {
  5061. player->removeDistItem();
  5062. }
  5063.  
  5064.  
  5065. }
  5066.  
  5067. std::list<Position> Game::getPathTo(Creature *creature, Position start, Position to, bool creaturesBlock){
  5068. return map->getPathTo(creature, start, to, creaturesBlock);
  5069. }
  5070.  
  5071. std::list<Position> Game::getPathToEx(Creature *creature, Position start, Position to, bool creaturesBlock){
  5072. return map->getPathToEx(creature, start, to, creaturesBlock);
  5073. }
  5074.  
  5075.  
  5076. void Game::checkPlayerWalk(uint32_t id)
  5077. {
  5078. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkPlayerWalk");
  5079.  
  5080. Player *player = getPlayerByID(id);
  5081.  
  5082. if(!player)
  5083. return;
  5084. if(player->pathlist.empty()){
  5085. stopEvent(player->eventAutoWalk);
  5086. player->eventAutoWalk = 0;
  5087. return;
  5088. }
  5089.  
  5090. Position pos = player->pos;
  5091. Direction dir = player->pathlist.front();
  5092. player->pathlist.pop_front();
  5093.  
  5094. switch (dir) {
  5095. case NORTH:
  5096. pos.y--;
  5097. break;
  5098. case EAST:
  5099. pos.x++;
  5100. break;
  5101. case SOUTH:
  5102. pos.y++;
  5103. break;
  5104. case WEST:
  5105. pos.x--;
  5106. break;
  5107. case NORTHEAST:
  5108. pos.x++;
  5109. pos.y--;
  5110. break;
  5111. case NORTHWEST:
  5112. pos.x--;
  5113. pos.y--;
  5114. break;
  5115. case SOUTHWEST:
  5116. pos.x--;
  5117. pos.y++;
  5118. break;
  5119. case SOUTHEAST:
  5120. pos.x++;
  5121. pos.y++;
  5122. break;
  5123. }
  5124.  
  5125. /*
  5126. #ifdef __DEBUG__
  5127. std::cout << "move to: " << dir << std::endl;
  5128. #endif
  5129. */
  5130.  
  5131. player->lastmove = OTSYS_TIME();
  5132. thingMove(player, player, pos.x, pos.y, pos.z, 1);
  5133. flushSendBuffers();
  5134. if(!player->pathlist.empty()){
  5135. int ticks = (int)player->getSleepTicks();
  5136. player->eventAutoWalk = addEvent(makeTask(ticks, std::bind2nd(std::mem_fun(&Game::checkPlayerWalk), id)));
  5137. }
  5138. else
  5139. {
  5140. stopEvent(player->eventAutoWalk);//?
  5141. player->eventAutoWalk = 0;
  5142. }
  5143. }
  5144. void Game::checkCreature(uint32_t id)
  5145. {
  5146. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreature()");
  5147.  
  5148. Creature *creature = getCreatureByID(id);
  5149.  
  5150. if (creature && creature->isRemoved == false)
  5151. {
  5152. int32_t thinkTicks = 0;
  5153. int32_t oldThinkTicks = creature->onThink(thinkTicks);
  5154.  
  5155. if(thinkTicks > 0) {
  5156. creature->eventCheck = addEvent(makeTask(thinkTicks, std::bind2nd(std::mem_fun(&Game::checkCreature), id)));
  5157. }
  5158. else
  5159. creature->eventCheck = 0;
  5160.  
  5161. Player* player = dynamic_cast<Player*>(creature);
  5162. if(player)
  5163. {
  5164. //Tile *tile = getTile(player->pos.x, player->pos.y, player->pos.z);
  5165. Tile *tile = map->getTile(player->pos);
  5166. if(tile == NULL){
  5167. std::cout << "CheckPlayer NULL tile: " << player->getName() << std::endl;
  5168. return;
  5169. }
  5170.  
  5171.  
  5172.  
  5173. #ifdef _REX_CVS_MOD_
  5174. if(player->tradeTicks >= 1000)
  5175. player->tradeTicks -= thinkTicks;
  5176. #endif
  5177.  
  5178.  
  5179. #ifdef CVS_DAY_CYCLE
  5180. player->sendWorldLightLevel(lightlevel, 0xD7);
  5181. #endif //CVS_DAY_CYCLE
  5182. #ifdef REX_MUTED
  5183.  
  5184. #endif //REX_MUTED
  5185. #ifdef TR_ANTI_AFK
  5186. player->checkAfk(thinkTicks);
  5187. #endif //TR_ANTI_AF
  5188. #ifdef YUR_BOH
  5189. player->checkBoh();
  5190. #endif //YUR_BOH
  5191. #ifdef YUR_WH
  5192. player->checkWh();
  5193. #endif //YUR_WH
  5194.  
  5195. #ifdef YUR_RINGS_AMULETS
  5196. player->checkRing(thinkTicks);
  5197. #endif //YUR_RINGS_AMULETS
  5198.  
  5199. //SOFT BOOTS
  5200. if(player->softTicks >= 2) {
  5201. if(player->items[SLOT_FEET] && player->items[SLOT_FEET]->getID() == ITEM_SOFT_BOOTS && !tile->isPz()){
  5202. player->mana += min(g_config.SOFT_MANA, player->manamax - player->mana);
  5203. player->health += min(g_config.SOFT_HEALTH, player->healthmax - player->health);
  5204. }
  5205. player->softTicks = 0;
  5206. } else {
  5207. player->softTicks++;
  5208. }
  5209. // LIFE RING
  5210. if(player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_LIFE_RING_IN_USE && !tile->isPz()){
  5211. player->mana += min(g_config.LR_MANA, player->manamax - player->mana);
  5212. player->health += min(g_config.LR_HEALTH, player->healthmax - player->health);
  5213. }
  5214. // ROH
  5215. if(player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_RING_OF_HEALING_IN_USE && !tile->isPz()){
  5216. player->mana += min(g_config.ROH_MANA, player->manamax - player->mana);
  5217. player->health += min(g_config.ROH_HEALTH, player->healthmax - player->health);
  5218. }
  5219. // ROAH
  5220. // ROH 240
  5221. if(player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_STEALTH_RING_IN_USE && !tile->isPz()){
  5222. player->mana += min(g_config.ROAH_MANA, player->manamax - player->mana);
  5223. player->health += min(g_config.ROAH_HEALTH, player->healthmax - player->health);
  5224. }
  5225. // RAINBOW SHIELD
  5226. if(player->level >= 150){
  5227. if(player->items[SLOT_RIGHT] && player->items[SLOT_RIGHT]->getID() == ITEM_RAINBOW && !tile->isPz()){
  5228. if(player->items[SLOT_LEFT]){
  5229. if(player->items[SLOT_LEFT]->getID() != ITEM_RAINBOW)
  5230. if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5231. player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5232. player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5233. player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5234. }
  5235. }else{
  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. }
  5242. }
  5243. if(player->items[SLOT_LEFT] && player->items[SLOT_LEFT]->getID() == ITEM_RAINBOW && !tile->isPz()){
  5244. if(player->items[SLOT_RIGHT]){
  5245. if(player->items[SLOT_RIGHT]->getID() != ITEM_RAINBOW)
  5246. if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5247. player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5248. player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5249. player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5250. }
  5251. }else{
  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. }
  5258. }
  5259. }
  5260.  
  5261. // RING OF THE SKY
  5262. if(player->level >= 30 && player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_ROTS && !tile->isPz())
  5263. player->mana += min(1, player->manamax - player->mana);
  5264.  
  5265. // ORSHABAAL HEART
  5266. if(player->name == "Ekudron" || player->name == "Agecik" && player->items[SLOT_AMMO] && player->items[SLOT_AMMO]->getID() == ITEM_ORSHABAAL_HEARTH && !tile->isPz())
  5267. player->mana += min(4, player->manamax - player->mana);
  5268.  
  5269. #ifdef HUCZU_FIX
  5270. if(player->items[SLOT_FEET] && player->items[SLOT_FEET]->getID() == ITEM_SPECTRE_BOOTS)
  5271. player->immunities = ATTACK_PARALYZE;
  5272. else
  5273. player->immunities -= ATTACK_PARALYZE;
  5274. #endif //HUCZU_FIX
  5275.  
  5276. #ifdef YUR_LIGHT_ITEM
  5277. player->checkLightItem(thinkTicks);
  5278. #endif //YUR_LIGHT_ITEM
  5279. #ifdef HUCZU_EXHAUSTED
  5280. if(player->mmo > 0)
  5281. player->mmo -= 1;
  5282. else
  5283. player->mmo = 0;
  5284.  
  5285. if(player->lookex > 0)
  5286. player->lookex -= 1;
  5287. else
  5288. player->lookex = 0;
  5289.  
  5290. if(player->antyrainbow > 0)
  5291. player->antyrainbow -= 1;
  5292. else
  5293. player->antyrainbow = 0;
  5294.  
  5295. if(player->antyrainbow2 > 0)
  5296. player->antyrainbow2 -= 1;
  5297. else
  5298. player->antyrainbow2 = 0;
  5299.  
  5300. if(player->clin > 0)
  5301. player->clin -= 1;
  5302. else
  5303. player->clin = 0;
  5304.  
  5305. if(player->shut_d > 0)
  5306. player->shut_d -= 1;
  5307. else
  5308. player->shut_d = 0;
  5309.  
  5310. if(player->houseTicks > 0)
  5311. player->houseTicks -= 1;
  5312. else
  5313. player->houseTicks = 0;
  5314. #endif //HUCZU_EXHAUSTED
  5315.  
  5316. if(player->flamTicks >= 1000){
  5317. player->flamTicks -= thinkTicks;
  5318. if(player->flamTicks == 0){
  5319. player->flamBool = false;
  5320. }
  5321. }
  5322.  
  5323.  
  5324. if(player->items[SLOT_RIGHT] && player->items[SLOT_LEFT]){
  5325. 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)){
  5326. player->removeItemInventory(SLOT_RIGHT);
  5327. }
  5328. 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)){
  5329. player->removeItemInventory(SLOT_LEFT);
  5330. }
  5331. }
  5332.  
  5333. if(player->items[SLOT_RIGHT] && player->items[SLOT_LEFT]){
  5334. 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)){
  5335. player->removeItemInventory(SLOT_RIGHT);
  5336. }
  5337. 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)){
  5338. player->removeItemInventory(SLOT_LEFT);
  5339. }
  5340. }
  5341.  
  5342. #ifdef HUCZU_SKULLS
  5343. if (player->checkSkull(thinkTicks))
  5344. Skull(player);
  5345. #endif //HUCZU_SKULLS
  5346.  
  5347. #ifdef YUR_INVISIBLE
  5348. if (player->checkInvisible(thinkTicks))
  5349. creatureChangeOutfit(player);
  5350. #endif //YUR_INVISIBLE
  5351.  
  5352. #ifdef _BBK_PUSH_DELAY
  5353. if(player->pushDelay >= 1000)
  5354. {
  5355. player->pushDelay -= thinkTicks;
  5356. if(player->pushDelay < 0)
  5357. player->pushDelay = 0;
  5358. }
  5359. #endif //_BBK_PUSH_DELAY
  5360.  
  5361. if(player->training == true){
  5362. if(player->trainingTicks >= 1000){
  5363. player->trainingTicks -= thinkTicks;
  5364.  
  5365. if(player->trainingTicks < 0)
  5366. player->trainingTicks = 0;
  5367. }
  5368. if(player->trainingTicks == 0 && player->rewriteTicks == 0){
  5369. int code = random_range(47,99) * random_range(47,99);
  5370. player->rewriteCode = code;
  5371. player->needrewrite = true;
  5372. player->rewriteTicks = g_config.REWRITE_TICKS;
  5373. std::ostringstream info;
  5374. player->sendTextMessage(MSG_BLUE_TEXT,"You are training here pretty long.Are you using bot?");
  5375. info << "Please rewrite code: " << player->rewriteCode << std::ends;
  5376. player->sendTextMessage(MSG_BLUE_TEXT, info.str().c_str());
  5377. std::ostringstream info2;
  5378. info2 << "Use this command !train 1234. You have " << player->rewriteTicks/1000 << " seconds!" << std::ends;
  5379. player->sendTextMessage(MSG_BLUE_TEXT, info2.str().c_str());
  5380. }
  5381.  
  5382. if(player->needrewrite != false){
  5383. if(player->rewriteTicks >= 1000){
  5384. player->rewriteTicks -= thinkTicks;
  5385. }
  5386.  
  5387. if(player->rewriteTicks == 0){
  5388. this->teleport(player, player->masterPos);
  5389. player->training = false;
  5390. player->trainingTicks = 0;
  5391. player->needrewrite = false;
  5392. player->rewriteCode = 0;
  5393. player->rewriteTicks = 0;
  5394. player->kickPlayer();
  5395. //player->sendLogout();
  5396. }
  5397. }
  5398. }
  5399.  
  5400.  
  5401.  
  5402. #ifdef HUCZU_FIX
  5403. if(player->gainHealthTick()){
  5404. SpectatorVec list;
  5405. SpectatorVec::iterator it;
  5406. getSpectators(Range(creature->pos), list);
  5407. for(it = list.begin(); it != list.end(); ++it) {
  5408. Player* p = dynamic_cast<Player*>(*it);
  5409. if(p)
  5410. p->sendCreatureHealth(player);
  5411. }
  5412. }
  5413. #endif //HUCZU_FIX
  5414.  
  5415. if(player->lightTicks >= 1000){
  5416. player->lightTicks -= thinkTicks;
  5417. if(player->lightTicks <= 1000){
  5418. player->lightTicks = 1;
  5419. }
  5420. }
  5421. else if(player->lightTicks == 1){
  5422. if(player->lightlevel > 0){
  5423. creatureChangeLight(player, 0, player->lightlevel-1, 0xD7);
  5424. }
  5425. else{
  5426. creatureChangeLight(player, 0, 0, 0xD7);
  5427. player->lightTicks = 0;
  5428. player->lightItem = 0;
  5429. }
  5430. if(player->lightTries > 0){
  5431. player->lightTicks = 3*60*1000;
  5432. player->lightTries -= 1;
  5433. }
  5434. }
  5435.  
  5436. #ifdef HUCZU_SKULLS
  5437. checkSkullTime(player);
  5438. #endif //HUCZU_SKULLS
  5439.  
  5440.  
  5441. if(!tile->isPz()){
  5442. if(player->food > 1000){
  5443. player->gainManaTick();
  5444. player->food -= thinkTicks;
  5445. if(player->healthmax - player->health > 0){
  5446. if(player->gainHealthTick()){
  5447. SpectatorVec list;
  5448. SpectatorVec::iterator it;
  5449. getSpectators(Range(creature->pos), list);
  5450. for(it = list.begin(); it != list.end(); ++it) {
  5451. Player* p = dynamic_cast<Player*>(*it);
  5452. if(p)
  5453. p->sendCreatureHealth(player);
  5454. }
  5455. }
  5456. }
  5457. }
  5458. }
  5459.  
  5460. //send stast only if have changed
  5461. if(player->NeedUpdateStats()){
  5462. player->sendStats();
  5463. }
  5464.  
  5465. player->sendPing(thinkTicks);
  5466.  
  5467. if(player->inFightTicks >= 1000) {
  5468. player->inFightTicks -= thinkTicks;
  5469.  
  5470. if(player->inFightTicks < 1000)
  5471. player->pzLocked = false;
  5472. player->sendIcons();
  5473. }
  5474.  
  5475. if(player->drunkTicks >= 1000) {
  5476. int32_t random = random_range(1,100);
  5477. if(random <= 25){
  5478. creatureSay(creature, SPEAK_SAY, "Hicks!");
  5479. Position pos;
  5480. int32_t randomwalk = random_range(1,4);
  5481. switch(randomwalk){
  5482. case 1:pos.x++;break;
  5483. case 2:pos.x--;break;
  5484. case 3:pos.y++;break;
  5485. case 4:pos.y--;break;
  5486. }
  5487. Tile* toTile = getTile(pos.x, pos.y, pos.z);
  5488. //make sure they don't get teleported into a place they shouldn't
  5489. if(toTile &&
  5490. !toTile->isBlocking(1, false, false) &&
  5491. !toTile->isBlocking(2, false, false) &&
  5492. !toTile->isBlocking(4, false, false) &&
  5493. !toTile->isBlocking(8, false, false) &&
  5494. !toTile->isBlocking(16, false, false))
  5495. teleport(player,pos);
  5496. }
  5497. player->drunkTicks -= thinkTicks;
  5498. player->sendIcons();
  5499. }
  5500.  
  5501. if(player->exhaustedTicks >= 1000){
  5502. player->exhaustedTicks -= thinkTicks;
  5503.  
  5504. if(player->exhaustedTicks < 0)
  5505. player->exhaustedTicks = 0;
  5506. }
  5507.  
  5508. if(player->manaShieldTicks >=1000){
  5509. player->manaShieldTicks -= thinkTicks;
  5510.  
  5511. if(player->manaShieldTicks < 1000)
  5512. player->sendIcons();
  5513. }
  5514. if(player->dwarvenTicks > 0){
  5515. player->drunkTicks = 0;
  5516. player->sendIcons();
  5517. }
  5518. if(player->dwarvenTicks = 0){
  5519. player->drunkTicks = 4000;
  5520. player->sendIcons();
  5521. }
  5522.  
  5523. if(player->hasteTicks >=1000)
  5524. player->hasteTicks -= thinkTicks;
  5525. }else{
  5526.  
  5527. if(creature->manaShieldTicks >=1000){
  5528. creature->manaShieldTicks -= thinkTicks;
  5529. }
  5530.  
  5531. if(creature->hasteTicks >=1000){
  5532. creature->hasteTicks -= thinkTicks;
  5533. }
  5534.  
  5535. #ifdef YUR_INVISIBLE
  5536. if (creature->checkInvisible(thinkTicks))
  5537. creatureChangeOutfit(creature);
  5538. #endif //YUR_INVISIBLE
  5539. }
  5540.  
  5541. Conditions& conditions = creature->getConditions();
  5542. for(Conditions::iterator condIt = conditions.begin(); condIt != conditions.end(); ++condIt) {
  5543. if(condIt->first == ATTACK_FIRE || condIt->first == ATTACK_ENERGY || condIt->first == ATTACK_POISON) {
  5544. ConditionVec &condVec = condIt->second;
  5545.  
  5546. if(condVec.empty())
  5547. continue;
  5548.  
  5549. CreatureCondition& condition = condVec[0];
  5550.  
  5551. if(condition.onTick(oldThinkTicks)) {
  5552. const MagicEffectTargetCreatureCondition* magicTargetCondition = condition.getCondition();
  5553. Creature* c = getCreatureByID(magicTargetCondition->getOwnerID());
  5554. creatureMakeMagic(c, creature->pos, magicTargetCondition);
  5555.  
  5556. if(condition.getCount() <= 0) {
  5557. condVec.erase(condVec.begin());
  5558. if(dynamic_cast<Player*>(creature))
  5559. player->sendIcons();
  5560. }
  5561. }
  5562. }
  5563. if(condIt->first == ATTACK_PARALYZE)
  5564. {
  5565. ConditionVec &condVec = condIt->second;
  5566. if(condVec.empty())
  5567. continue;
  5568.  
  5569. CreatureCondition& condition = condVec[0];
  5570. if(condition.onTick(oldThinkTicks))
  5571. {
  5572. //Player* player = dynamic_cast<Player*>(creature);
  5573. if(creature->getImmunities() != ATTACK_PARALYZE)
  5574. {
  5575. changeSpeed(creature->getID(), 100);
  5576. if(player)
  5577. {
  5578. player->sendTextMessage(MSG_SMALLINFO, "You are paralyzed.");
  5579. player->sendIcons();
  5580. }
  5581. }
  5582.  
  5583. if(condition.getCount() <= 0)
  5584. {
  5585. condVec.erase(condVec.begin());
  5586. changeSpeed(creature->getID(), creature->getNormalSpeed()+creature->hasteSpeed);
  5587. if(player)
  5588. {
  5589. player->sendIcons();
  5590. }
  5591. }
  5592. }
  5593. }
  5594. }
  5595. flushSendBuffers();
  5596. }
  5597. }
  5598.  
  5599. void Game::changeOutfit(uint32_t id, int32_t looktype){
  5600.  
  5601. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::changeOutfit()");
  5602.  
  5603. Creature *creature = getCreatureByID(id);
  5604. if(creature){
  5605. creature->looktype = looktype;
  5606. if(creature->lookfeet_master != 0 || creature->lookhead_master != 0 ||
  5607. creature->looklegs_master != 0 || creature->lookbody_master != 0 ){
  5608. creature->lookhead = creature->lookhead_master;
  5609. creature->lookbody = creature->lookbody_master;
  5610. creature->looklegs = creature->looklegs_master;
  5611. creature->lookfeet = creature->lookfeet_master;
  5612.  
  5613. creature->lookhead_master = 0;
  5614. creature->lookbody_master = 0;
  5615. creature->looklegs_master = 0;
  5616. creature->lookfeet_master = 0;
  5617. }
  5618. creatureChangeOutfit(creature);
  5619. }
  5620. }
  5621.  
  5622. void Game::changeOutfitAfter(uint32_t id, int32_t looktype, long time)
  5623. {
  5624. addEvent(makeTask(time, boost::bind(&Game::changeOutfit, this,id, looktype)));
  5625. }
  5626.  
  5627. void Game::changeSpeed(uint32_t id, unsigned short speed)
  5628. {
  5629. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::changeSpeed()");
  5630. Creature *creature = getCreatureByID(id);
  5631. if(creature && /*creature->hasteTicks < 1000 && */creature->speed != speed)
  5632. {
  5633. creature->speed = speed;
  5634. Player* player = dynamic_cast<Player*>(creature);
  5635. if(player){
  5636. player->sendChangeSpeed(creature);
  5637. player->sendIcons();
  5638. }
  5639. SpectatorVec list;
  5640. SpectatorVec::iterator it;
  5641. getSpectators(Range(creature->pos), list);
  5642. //for(uint32_t i = 0; i < list.size(); i++)
  5643. for(it = list.begin(); it != list.end(); ++it) {
  5644. Player* p = dynamic_cast<Player*>(*it);
  5645. if(p)
  5646. p->sendChangeSpeed(creature);
  5647. }
  5648. }
  5649. }
  5650.  
  5651. void Game::checkCreatureAttacking(uint32_t id)
  5652. {
  5653. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreatureAttacking()");
  5654.  
  5655. Creature *creature = getCreatureByID(id);
  5656. if (creature != NULL && creature->isRemoved == false)
  5657. {
  5658.  
  5659. creature->eventCheckAttacking = 0;
  5660. Player *player = dynamic_cast<Player*>(creature);
  5661. Monster *monster = dynamic_cast<Monster*>(creature);
  5662. if (monster) {
  5663. monster->onAttack();
  5664. }
  5665. else {
  5666. if (creature->attackedCreature != 0)
  5667. {
  5668. Creature *attackedCreature = getCreatureByID(creature->attackedCreature);
  5669. if (attackedCreature)
  5670. {
  5671. // canAttack system BRY
  5672.  
  5673. Player *attacker = dynamic_cast<Player*>(creature);
  5674. Player *attacked = dynamic_cast<Player*>(attackedCreature);
  5675. bool canAttack = false;
  5676. if(attacker && attacked)
  5677. {
  5678. Tile* tile = getTile(attacker->pos.x,attacker->pos.y, attacker->pos.z);
  5679. if(attacked->level >= 1 && attacked->level < 30 && attacker->level >= 1 && attacker->level < 30)
  5680. canAttack = false;
  5681.  
  5682. else if(attacked->level >= 30 && attacked->level < 80 && attacker->level >= 30 && attacker->level < 80)
  5683. canAttack = true;
  5684.  
  5685. else if(attacked->level >= 81 && attacked->level < 999 && attacker->level >= 81 && attacker->level < 999)
  5686. canAttack = true;
  5687.  
  5688.  
  5689. else if(tile && tile->isPvpArena())
  5690. canAttack = true;
  5691. }
  5692.  
  5693.  
  5694.  
  5695. if(attacker && attacked && !canAttack)
  5696. {
  5697. attacker->sendCancelAttacking();
  5698. attacker->sendCancel("You may not attack this player yet.");
  5699. playerSetAttackedCreature(attacker, 0);
  5700. return;
  5701. }
  5702. //Tile* fromtile = getTile(creature->pos.x, creature->pos.y, creature->pos.z);
  5703. Tile* fromtile = map->getTile(creature->pos);
  5704. if(fromtile == NULL) {
  5705. std::cout << "checkCreatureAttacking NULL tile: " << creature->getName() << std::endl;
  5706. //return;
  5707. }
  5708. Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  5709. if (!attackedCreature->isAttackable() == 0 && fromtile && fromtile->isPz() && creature->access < g_config.ACCESS_PROTECT)
  5710. {
  5711. Player* player = dynamic_cast<Player*>(creature);
  5712. if (player) {
  5713. player->sendTextMessage(MSG_SMALLINFO, "You may not attack a person in a protection zone.");
  5714. //player->sendCancelAttacking();
  5715. playerSetAttackedCreature(player, 0);
  5716. return;
  5717. }
  5718. }
  5719. #ifdef YUR_INVISIBLE
  5720. if (attackedCreature->isInvisible())
  5721. {
  5722. Player* player = dynamic_cast<Player*>(creature);
  5723. Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  5724.  
  5725. if (player && !attackedPlayer) {
  5726. player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  5727. playerSetAttackedCreature(player, 0);
  5728. return;
  5729. }
  5730. }
  5731. #endif //YUR_INVISIBLE
  5732. else
  5733. {
  5734. if (attackedCreature != NULL && attackedCreature->isRemoved == false)
  5735. {
  5736.  
  5737. #ifdef ZS_SWORDS
  5738. int32_t swordid = player->getSwordId();
  5739. if (swordid > 0)
  5740. useSword(player, attackedCreature, swordid);
  5741. #endif //ZS_SWORDS
  5742.  
  5743. if(player && player->followMode == 0x01) {
  5744. player->followCreature = attackedCreature->getID();
  5745. playerAttackSetFollowCreature(player, attackedCreature->getID());
  5746. playerFollowAttacking(player, attackedCreature);
  5747. long long delay = player->getSleepTicks();
  5748. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollowAttack), player->getID())));
  5749. }
  5750.  
  5751.  
  5752. #ifdef WANDS_JIDDO
  5753. Player* player = dynamic_cast<Player*>(creature);
  5754. int32_t wandid = 0;
  5755. if(player && ((player->items[SLOT_RIGHT] && (wandid = player->items[SLOT_RIGHT]->getWand())) || (player->items[SLOT_LEFT] && (wandid = player->items[SLOT_LEFT]->getWand())))) {
  5756. useWand(creature, attackedCreature, wandid);
  5757. } else {
  5758. #endif
  5759. Player* player = dynamic_cast<Player*>(creature);
  5760. if (player)
  5761. {
  5762. #ifdef SD_BURST_ARROW
  5763. if (player->isUsingBurstArrows())
  5764. burstArrow(player, attackedCreature->pos);
  5765. #endif //SD_BURST_ARROW
  5766. if(player->flamBool == true){
  5767. Blasting(player, attackedCreature, attackedCreature->pos);
  5768. player->flamBool = false;
  5769. }
  5770. }
  5771. this->creatureMakeDamage(creature, attackedCreature, creature->getFightType());
  5772. #ifdef WANDS_JIDDO
  5773. }
  5774. #endif
  5775. }
  5776. }
  5777.  
  5778. if (player->vocation == 0) {
  5779. int32_t speed = int32_t(g_config.NO_VOC_SPEED * 1000);
  5780. creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5781. }
  5782. else if (player->vocation == 1) {
  5783. int32_t speed = int32_t(g_config.SORC_SPEED * 1000);
  5784. creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5785. }
  5786. else if (player->vocation == 2) {
  5787. int32_t speed = int32_t(g_config.DRUID_SPEED * 1000);
  5788. creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5789. }
  5790. else if (player->vocation == 3) {
  5791. int32_t speed = int32_t(g_config.PALLY_SPEED * 1000);
  5792. creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5793. }
  5794. else if (player->vocation == 4) {
  5795. int32_t speed = int32_t(g_config.KNIGHT_SPEED * 1000);
  5796. creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5797. }
  5798. else { //change the 2000 to whatever you want; 2000 = 2 seconds per attack
  5799. creature->eventCheckAttacking = addEvent(makeTask(1000, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5800. }
  5801. }
  5802. }
  5803. }
  5804. flushSendBuffers();
  5805. }
  5806. }
  5807. void Game::checkDecay(int32_t t)
  5808. {
  5809. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkDecay()");
  5810.  
  5811. addEvent(makeTask(DECAY_INTERVAL, boost::bind(&Game::checkDecay,this,DECAY_INTERVAL)));
  5812.  
  5813. list<decayBlock*>::iterator it;
  5814. for(it = decayVector.begin();it != decayVector.end();){
  5815. (*it)->decayTime -= t;
  5816. if((*it)->decayTime <= 0){
  5817. list<Item*>::iterator it2;
  5818. for(it2 = (*it)->decayItems.begin(); it2 != (*it)->decayItems.end(); it2++){
  5819. /*todo: Decaying item could be in a container carried by a player,
  5820. should all items have a pointer to their parent (like containers)?*/
  5821. Item* item = *it2;
  5822. item->isDecaying = false;
  5823. if(item->canDecay()){
  5824. if(item->pos.x != 0xFFFF){
  5825. Tile *tile = map->getTile(item->pos);
  5826. if(tile){
  5827. Position pos = item->pos;
  5828. Item* newitem = item->decay();
  5829.  
  5830. if(newitem){
  5831. int32_t stackpos = tile->getThingStackPos(item);
  5832. if(newitem == item){
  5833. sendUpdateThing(NULL,pos,newitem,stackpos);
  5834. }
  5835. else{
  5836. if(tile->removeThing(item)){
  5837. //autoclose containers
  5838. if(dynamic_cast<Container*>(item)){
  5839. SpectatorVec list;
  5840. SpectatorVec::iterator it;
  5841.  
  5842. getSpectators(Range(pos, true), list);
  5843.  
  5844. for(it = list.begin(); it != list.end(); ++it) {
  5845. Player* spectator = dynamic_cast<Player*>(*it);
  5846. if(spectator)
  5847. spectator->onThingRemove(item);
  5848. }
  5849. }
  5850.  
  5851. tile->insertThing(newitem, stackpos);
  5852. sendUpdateThing(NULL,pos,newitem,stackpos);
  5853. FreeThing(item);
  5854. }
  5855. }
  5856. startDecay(newitem);
  5857. }
  5858. else{
  5859. if(removeThing(NULL,pos,item)){
  5860. FreeThing(item);
  5861. }
  5862. }//newitem
  5863. }//tile
  5864. }//pos != 0xFFFF
  5865. }//item->canDecay()
  5866. FreeThing(item);
  5867. }//for it2
  5868. delete *it;
  5869. it = decayVector.erase(it);
  5870. }//(*it)->decayTime <= 0
  5871. else{
  5872. it++;
  5873. }
  5874. }//for it
  5875.  
  5876. flushSendBuffers();
  5877. }
  5878.  
  5879. void Game::startDecay(Item* item){
  5880. if(item->isDecaying)
  5881. return;//dont add 2 times the same item
  5882. //get decay time
  5883. item->isDecaying = true;
  5884. uint32_t dtime = item->getDecayTime();
  5885. if(dtime == 0)
  5886. return;
  5887. //round time
  5888. if(dtime < DECAY_INTERVAL)
  5889. dtime = DECAY_INTERVAL;
  5890. dtime = (dtime/DECAY_INTERVAL)*DECAY_INTERVAL;
  5891. item->useThing();
  5892. //search if there are any block with this time
  5893. list<decayBlock*>::iterator it;
  5894. for(it = decayVector.begin();it != decayVector.end();it++){
  5895. if((*it)->decayTime == dtime){
  5896. (*it)->decayItems.push_back(item);
  5897. return;
  5898. }
  5899. }
  5900. //we need a new decayBlock
  5901. decayBlock* db = new decayBlock;
  5902. db->decayTime = dtime;
  5903. db->decayItems.clear();
  5904. db->decayItems.push_back(item);
  5905. decayVector.push_back(db);
  5906. }
  5907.  
  5908. void Game::checkSpawns(int32_t t)
  5909. {
  5910. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkSpawns()");
  5911.  
  5912. SpawnManager::instance()->checkSpawns(t);
  5913. this->addEvent(makeTask(t, std::bind2nd(std::mem_fun(&Game::checkSpawns), t)));
  5914. }
  5915.  
  5916. void Game::CreateDamageUpdate(Creature* creature, Creature* attackCreature, int32_t damage)
  5917. {
  5918. Player* player = dynamic_cast<Player*>(creature);
  5919. Player* attackPlayer = dynamic_cast<Player*>(attackCreature);
  5920. if(!player)
  5921. return;
  5922. //player->sendStats();
  5923. //msg.AddPlayerStats(player);
  5924. if (damage > 0) {
  5925. std::stringstream dmgmesg, info;
  5926.  
  5927. if(damage == 1) {
  5928. dmgmesg << "You lose 1 hitpoint";
  5929. }
  5930. else
  5931. dmgmesg << "You lose " << damage << " hitpoints";
  5932.  
  5933. if(attackPlayer) {
  5934. dmgmesg << " due to an attack by " << attackCreature->getName();
  5935. }
  5936. else if(attackCreature) {
  5937. std::string strname = attackCreature->getName();
  5938. std::transform(strname.begin(), strname.end(), strname.begin(), (int32_t(*)(int32_t))tolower);
  5939. dmgmesg << " due to an attack by a " << strname;
  5940. }
  5941. dmgmesg <<".";
  5942.  
  5943. player->sendTextMessage(MSG_EVENT, dmgmesg.str().c_str());
  5944. //msg.AddTextMessage(MSG_EVENT, dmgmesg.str().c_str());
  5945. }
  5946. if (player->isRemoved == true){
  5947. player->sendTextMessage(MSG_ADVANCE, "You are dead.");
  5948. }
  5949. }
  5950.  
  5951.  
  5952. void Game::CreateManaDamageUpdate(Creature* creature, Creature* attackCreature, int32_t damage)
  5953. {
  5954. Player* player = dynamic_cast<Player*>(creature);
  5955. if(!player)
  5956. return;
  5957.  
  5958. if (damage > 0) {
  5959. std::stringstream dmgmesg;
  5960. dmgmesg << "You lose " << damage << " mana";
  5961. if(attackCreature) {
  5962. dmgmesg << " blocking an attack by " << attackCreature->getName();
  5963. }
  5964. dmgmesg <<".";
  5965.  
  5966. player->sendTextMessage(MSG_EVENT, dmgmesg.str().c_str());
  5967. }
  5968. }
  5969.  
  5970. bool Game::creatureSaySpell(Creature *creature, const std::string &text, bool say)
  5971. {
  5972. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureSaySpell()");
  5973.  
  5974. bool ret = false;
  5975.  
  5976. Player* player = dynamic_cast<Player*>(creature);
  5977. std::string temp, var;
  5978. uint32_t loc = (uint32_t)text.find( "\"", 0 );
  5979. if( loc != string::npos && loc >= 0){
  5980. temp = std::string(text, 0, loc-1);
  5981. var = std::string(text, (loc+1), text.size()-loc-1);
  5982. }
  5983. else {
  5984. temp = text;
  5985. var = std::string("");
  5986. }
  5987.  
  5988. std::transform(temp.begin(), temp.end(), temp.begin(), (int32_t(*)(int32_t))tolower);
  5989.  
  5990. if(creature->access >= g_config.ACCESS_PROTECT || !player){
  5991. std::map<std::string, Spell*>::iterator sit = spells.getAllSpells()->find(temp);
  5992. if (sit != spells.getAllSpells()->end()){
  5993. sit->second->getSpellScript()->castSpell(creature, creature->pos, var);
  5994. if (creature->access >= g_config.ACCESS_PROTECT && say == true)
  5995. this->creatureSay(creature, SPEAK_MONSTER1, text);
  5996. ret = true;
  5997. }
  5998. }
  5999. else if(player){
  6000. std::map<std::string, Spell*>* tmp = spells.getVocSpells(player->vocation);
  6001. if(tmp){
  6002. std::map<std::string, Spell*>::iterator sit = tmp->find(temp);
  6003. if(sit != tmp->end()){
  6004. if(player->maglevel >= sit->second->getMagLv()){
  6005. #ifdef YUR_LEARN_SPELLS
  6006. if (g_config.LEARN_SPELLS && !player->knowsSpell(temp))
  6007. ret = false;
  6008. else
  6009. #endif //YUR_LEARN_SPELLS
  6010. {
  6011. if(sit->second->getSpellScript()->castSpell(creature, creature->pos, var) && say == true)
  6012. this->creatureSay(player, SPEAK_MONSTER1, text);
  6013. ret = true;
  6014. }
  6015. }
  6016. }
  6017. }
  6018. }
  6019.  
  6020.  
  6021.  
  6022. return ret;
  6023. }
  6024.  
  6025. void Game::playerAutoWalk(Player* player, std::list<Direction>& path)
  6026. {
  6027. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerAutoWalk()");
  6028.  
  6029. stopEvent(player->eventAutoWalk);
  6030. player->eventAutoWalk = 0;
  6031.  
  6032. if(player->isRemoved)
  6033. return;
  6034.  
  6035. player->pathlist = path;
  6036. int32_t ticks = (int32_t)player->getSleepTicks();
  6037. /*
  6038. #ifdef __DEBUG__
  6039. std::cout << "playerAutoWalk - " << ticks << std::endl;
  6040. #endif
  6041. */
  6042. if(!player->pathlist.empty())
  6043. player->eventAutoWalk = addEvent(makeTask(ticks, std::bind2nd(std::mem_fun(&Game::checkPlayerWalk), player->getID())));
  6044.  
  6045. // then we schedule the movement...
  6046. // the interval seems to depend on the speed of the char?
  6047. //player->eventAutoWalk = addEvent(makeTask<Direction>(0, MovePlayer(player->getID()), path, 400, StopMovePlayer(player->getID())));
  6048. //player->pathlist = path;
  6049. }
  6050.  
  6051. bool Game::playerUseItemEx(Player *player, const Position& posFrom,const unsigned char stack_from,
  6052. const Position &posTo,const unsigned char stack_to, const unsigned short itemid)
  6053. {
  6054. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerUseItemEx()");
  6055.  
  6056. if(player->isRemoved)
  6057. return false;
  6058.  
  6059. bool ret = false;
  6060.  
  6061. Position thingpos = getThingMapPos(player, posFrom);
  6062. Item *item = dynamic_cast<Item*>(getThing(posFrom, stack_from, player));
  6063. Container* container = player->getContainer(player->shop_index);
  6064. if(container && item && !container->shop.empty() && container->isHoldingItem(item))
  6065. return false;
  6066.  
  6067. if(item) {
  6068. //Runes
  6069. std::map<unsigned short, Spell*>::iterator sit = spells.getAllRuneSpells()->find(item->getID());
  6070. if(sit != spells.getAllRuneSpells()->end()) {
  6071. #ifdef PALL_REQ_LVL
  6072. std::stringstream ss;
  6073. if(item->getReqLevel() > player->getLevel()){
  6074. ss << "\n Musisz miec " << item->getReqLevel() << " poziom aby tego uzyc.";
  6075. ret = false;
  6076. }
  6077. if(item->isWeapon() && item->getReqVoc() != player->getVocation()){
  6078. switch(item->getReqVoc()){
  6079. case 1:
  6080. ss << "\n You must be a sorcerer to use this weapon.";
  6081. ret = false;
  6082. break;
  6083. case 2:
  6084. ss << "\n You must be a druid to use this weapon.";
  6085. ret = false;
  6086. break;
  6087. case 3:
  6088. ss << "\n You must be a paladin to use this weapon.";
  6089. ret = false;
  6090. break;
  6091. case 4:
  6092. ss << "\n You must be a knight to use this weapon.";
  6093. ret = false;
  6094. break;
  6095. }
  6096. }
  6097. player->sendTextMessage(MSG_SMALLINFO, ss.str().c_str());
  6098. #endif //PALL_REQ_LVL
  6099. if( (abs(thingpos.x - player->pos.x) > 1) || (abs(thingpos.y - player->pos.y) > 1) ) {
  6100. player->sendCancel("Too far away.");
  6101. ret = false;
  6102. }
  6103. else {
  6104. std::string var = std::string("");
  6105. if(player->access >= g_config.ACCESS_PROTECT || sit->second->getMagLv() <= player->maglevel)
  6106. {
  6107. bool success = sit->second->getSpellScript()->castSpell(player, posTo, var);
  6108. ret = success;
  6109. if(success) {
  6110. autoCloseTrade(item);
  6111. item->setItemCharge(std::max((int32_t)item->getItemCharge() - 1, 0) );
  6112. if(item->getItemCharge() == 0) {
  6113. if(removeThing(player,posFrom,item)){
  6114. FreeThing(item);
  6115. }
  6116. }
  6117. }
  6118. }
  6119. else
  6120. {
  6121. player->sendCancel("You don't have the required magic level to use that rune.");
  6122. }
  6123. }
  6124. }
  6125. else{
  6126. actions.UseItemEx(player,posFrom,stack_from,posTo,stack_to,itemid);
  6127. ret = true;
  6128. }
  6129. }
  6130.  
  6131.  
  6132. return ret;
  6133. }
  6134.  
  6135.  
  6136. bool Game::playerUseItem(Player *player, const Position& pos, const unsigned char stackpos, const unsigned short itemid, unsigned char index)
  6137. {
  6138. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerUseItem()");
  6139. if(itemid == 2273 || itemid == 2275 ){
  6140.  
  6141. MagicEffectClass pox;
  6142. pox.animationColor = 0;
  6143. pox.damageEffect = NM_ME_MAGIC_ENERGIE;
  6144. pox.hitEffect = 255;
  6145. pox.attackType = ATTACK_NONE;
  6146. pox.maxDamage = 0;
  6147. pox.minDamage = 0;
  6148. pox.offensive = false;
  6149. pox.manaCost = 0;
  6150. if(creatureMakeMagic(player, player->pos, &pox)){
  6151. player->removeCondition(ATTACK_PARALYZE);
  6152. int32_t newspeed = player->getNormalSpeed()+player->hasteSpeed;
  6153. changeSpeed(player->getID(), (unsigned short)newspeed);
  6154.  
  6155. if(player)
  6156. player->sendIcons();
  6157. }
  6158. else{
  6159. player->sendCancel("Sorry, not possible.");
  6160. return false;
  6161. }
  6162. }
  6163. if(player->isRemoved)
  6164. return false;
  6165.  
  6166. actions.UseItem(player,pos,stackpos,itemid,index);
  6167. return true;
  6168. }
  6169.  
  6170. bool Game::playerUseBattleWindow(Player *player, Position &posFrom, unsigned char stackpos, unsigned short itemid, uint32_t creatureid)
  6171. {
  6172. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerUseBattleWindow");
  6173.  
  6174. if(player->isRemoved)
  6175. return false;
  6176.  
  6177. Creature *creature = getCreatureByID(creatureid);
  6178. if(!creature || dynamic_cast<Player*>(creature))
  6179. return false;
  6180.  
  6181. 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)
  6182. return false;
  6183.  
  6184. bool ret = false;
  6185.  
  6186. Position thingpos = getThingMapPos(player, posFrom);
  6187. Item *item = dynamic_cast<Item*>(getThing(posFrom, stackpos, player));
  6188. Container* container = player->getContainer(player->shop_index);
  6189. if(container && item && !container->shop.empty() && container->isHoldingItem(item))
  6190. return false;
  6191. if(item) {
  6192. //Runes
  6193. std::map<unsigned short, Spell*>::iterator sit = spells.getAllRuneSpells()->find(item->getID());
  6194. if(sit != spells.getAllRuneSpells()->end()) {
  6195. if( (abs(thingpos.x - player->pos.x) > 1) || (abs(thingpos.y - player->pos.y) > 1) ) {
  6196. player->sendCancel("Too far away.");
  6197. }
  6198. else {
  6199. std::string var = std::string("");
  6200. if(player->access >= g_config.ACCESS_PROTECT || sit->second->getMagLv() <= player->maglevel)
  6201. {
  6202. bool success = sit->second->getSpellScript()->castSpell(player, creature->pos, var);
  6203. ret = success;
  6204. if(success){
  6205. autoCloseTrade(item);
  6206. item->setItemCharge(std::max((int32_t)item->getItemCharge() - 1, 0) );
  6207. if(item->getItemCharge() == 0){
  6208. if(removeThing(player,posFrom,item)){
  6209. FreeThing(item);
  6210. }
  6211. }
  6212. }
  6213. }
  6214. else
  6215. {
  6216. player->sendCancel("You don't have the required magic level to use that rune.");
  6217. }
  6218. }
  6219. }
  6220. }
  6221. return ret;
  6222. }
  6223.  
  6224. bool Game::playerRotateItem(Player *player, const Position& pos, const unsigned char stackpos, const unsigned short itemid)
  6225. {
  6226. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerRotateItem()");
  6227.  
  6228. if(player->isRemoved)
  6229. return false;
  6230.  
  6231. if(std::abs(player->pos.x - pos.x) > 1 || std::abs(player->pos.y - pos.y) > 1 || player->pos.z != pos.z){
  6232. player->sendCancel("Too far away.");
  6233. return false;
  6234. }
  6235.  
  6236. Item *item = dynamic_cast<Item*>(getThing(pos, stackpos, player));
  6237. if(item && item->rotate()){
  6238. sendUpdateThing(player, pos, item, stackpos);
  6239. }
  6240.  
  6241. return false;
  6242. }
  6243.  
  6244. void Game::playerRequestTrade(Player* player, const Position& pos,
  6245. const unsigned char stackpos, const unsigned short itemid, uint32_t playerid)
  6246. {
  6247. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerRequestTrade()");
  6248.  
  6249. if(player->isRemoved)
  6250. return;
  6251.  
  6252. Player *tradePartner = getPlayerByID(playerid);
  6253. if(!tradePartner || tradePartner == player) {
  6254. player->sendTextMessage(MSG_INFO, "Sorry, not possible.");
  6255. return;
  6256. }
  6257.  
  6258. if(player->tradeState != TRADE_NONE && !(player->tradeState == TRADE_ACKNOWLEDGE && player->tradePartner == playerid)) {
  6259. player->sendCancel("You are already trading.");
  6260. return;
  6261. }
  6262. else if(tradePartner->tradeState != TRADE_NONE && tradePartner->tradePartner != player->getID()) {
  6263. player->sendCancel("This player is already trading.");
  6264. return;
  6265. }
  6266.  
  6267. Item *tradeItem = dynamic_cast<Item*>(getThing(pos, stackpos, player));
  6268. if(!tradeItem || tradeItem->getID() != itemid || !tradeItem->isPickupable()) {
  6269. player->sendCancel("Sorry, not possible.");
  6270. return;
  6271. }
  6272.  
  6273. #ifdef __KIRO_AKT__
  6274. if(tradeItem->getID() == ITEM_AKT)
  6275. {
  6276. Tile* tile = getTile(player->pos);
  6277. House* house = tile? tile->getHouse() : NULL;
  6278.  
  6279. if(!house)
  6280. {
  6281. player->sendCancel("You must stay in house!");
  6282. return;
  6283. }
  6284. if(house->getOwner() != player->getName())
  6285. {
  6286. player->sendCancel("You must stay in your house!");
  6287. return;
  6288. }
  6289. }
  6290.  
  6291. #endif
  6292.  
  6293. if(!player->removeItem(tradeItem, true)) {
  6294. /*if( (abs(player->pos.x - pos.x) > 1) || (abs(player->pos.y - pos.y) > 1) ) {
  6295. player->sendCancel("To far away...");
  6296. return;
  6297. }*/
  6298. player->sendCancel("Sorry, not possible.");
  6299. return;
  6300. }
  6301.  
  6302. std::map<Item*, uint32_t>::const_iterator it;
  6303. const Container* container = NULL;
  6304. for(it = tradeItems.begin(); it != tradeItems.end(); it++) {
  6305. if(tradeItem == it->first ||
  6306. ((container = dynamic_cast<const Container*>(tradeItem)) && container->isHoldingItem(it->first)) ||
  6307. ((container = dynamic_cast<const Container*>(it->first)) && container->isHoldingItem(tradeItem)))
  6308. {
  6309. player->sendTextMessage(MSG_INFO, "This item is already beeing traded.");
  6310. return;
  6311. }
  6312. }
  6313.  
  6314. Container* tradeContainer = dynamic_cast<Container*>(tradeItem);
  6315. if(tradeContainer && tradeContainer->getItemHoldingCount() + 1 > 100){
  6316. player->sendTextMessage(MSG_INFO, "You cannot trade more than 100 items.");
  6317. return;
  6318. }
  6319.  
  6320. player->tradePartner = playerid;
  6321. player->tradeItem = tradeItem;
  6322. player->tradeState = TRADE_INITIATED;
  6323. tradeItem->useThing();
  6324. tradeItems[tradeItem] = player->getID();
  6325.  
  6326. player->sendTradeItemRequest(player, tradeItem, true);
  6327.  
  6328. if(tradePartner->tradeState == TRADE_NONE){
  6329. std::stringstream trademsg;
  6330. trademsg << player->getName() <<" wants to trade with you.";
  6331. tradePartner->sendTextMessage(MSG_INFO, trademsg.str().c_str());
  6332. tradePartner->tradeState = TRADE_ACKNOWLEDGE;
  6333. tradePartner->tradePartner = player->getID();
  6334. }
  6335. else {
  6336. Item* counterOfferItem = tradePartner->tradeItem;
  6337. player->sendTradeItemRequest(tradePartner, counterOfferItem, false);
  6338. tradePartner->sendTradeItemRequest(player, tradeItem, false);
  6339. }
  6340. }
  6341.  
  6342. void Game::playerAcceptTrade(Player* player)
  6343. {
  6344. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerAcceptTrade()");
  6345.  
  6346. if(player->isRemoved)
  6347. return;
  6348.  
  6349. player->setAcceptTrade(true);
  6350. Player *tradePartner = getPlayerByID(player->tradePartner);
  6351. if(tradePartner && tradePartner->getAcceptTrade()) {
  6352. Item *tradeItem1 = player->tradeItem;
  6353. Item *tradeItem2 = tradePartner->tradeItem;
  6354.  
  6355. player->sendCloseTrade();
  6356. tradePartner->sendCloseTrade();
  6357.  
  6358. #ifdef __KIRO_AKT__
  6359. if(tradeItem1->getID() == ITEM_AKT)
  6360. {
  6361. Tile* tile = getTile(player->pos);
  6362. House* house = tile? tile->getHouse() : NULL;
  6363. Tile* tile2 = getTile(tradePartner->pos);
  6364. Creature* creature = getCreatureByName(house->getOwner());
  6365. Player* prevOwner = creature? dynamic_cast<Player*>(creature) : NULL;
  6366. if(!house || !tile->isHouse())
  6367. {
  6368. player->sendCancel("You must stay in house!");
  6369. return;
  6370. }
  6371. if(!tile->isHouse() && !tile2->isHouse() && player->tradeState != TRADE_INITIATED){
  6372. player->sendCancel("You can only sell act if you are in house and you are the owner!");
  6373. return;
  6374. }
  6375. if(house->getOwner() != player->getName())
  6376. {
  6377. player->sendCancel("You must stay in your house!");
  6378. return;
  6379. }
  6380.  
  6381. if(house && house->checkHouseCount(tradePartner) >= g_config.getGlobalNumber("maxhouses", 0)){
  6382. std::stringstream textmsg;
  6383. textmsg << "You cannot have more than " << g_config.getGlobalNumber("maxhouses", 1) << " house.";
  6384. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6385. return;
  6386. }
  6387.  
  6388. if (house && tradePartner->level < g_config.getGlobalNumber("buyhouselvlrook",1) && tradePartner->vocation == 0)
  6389. {
  6390. player->sendCancel("This player have too low level to buy house!");
  6391. std::stringstream textmsg;
  6392. textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("buyhouselvlrook",2) << " level.";
  6393. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6394. return;
  6395. }
  6396.  
  6397. if (house && tradePartner->level < g_config.getGlobalNumber("houselevel", 0) && tradePartner->vocation != 0)
  6398. {
  6399. player->sendCancel("This player have too low level to buy house!");
  6400. std::stringstream textmsg;
  6401. textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("houselevel", 0) << " level.";
  6402. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6403. return;
  6404. }
  6405.  
  6406. if(tradePartner->getFreeCapacity() < tradeItem1->getWeight())
  6407. {
  6408. return;
  6409. }
  6410.  
  6411. if(player->addItem(tradeItem2, true) && tradePartner->addItem(tradeItem1, true) &&
  6412. player->removeItem(tradeItem1, true) && tradePartner->removeItem(tradeItem2, true)){
  6413.  
  6414. player->removeItem(tradeItem1);
  6415. tradePartner->removeItem(tradeItem2);
  6416.  
  6417. player->onThingRemove(tradeItem1);
  6418. tradePartner->onThingRemove(tradeItem2);
  6419.  
  6420. player->addItem(tradeItem2);
  6421. tradePartner->addItem(tradeItem1);
  6422. }
  6423. else{
  6424. player->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6425. tradePartner->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6426. return;
  6427. }
  6428. player->removeItem(tradeItem1, true);
  6429. tradePartner->addItem(tradeItem1, true);
  6430. player->addItem(tradeItem2, true);
  6431. house->setOwner(tradePartner->getName());
  6432. teleport(player,tradePartner->pos);
  6433. if (prevOwner)
  6434. prevOwner->houseRightsChanged = true;
  6435. tradePartner->houseRightsChanged = true;
  6436. }
  6437. else if(tradeItem2->getID() == ITEM_AKT)
  6438. {
  6439. Tile* tile = getTile(tradePartner->pos);
  6440. House* house = tile? tile->getHouse() : NULL;
  6441. Tile* tile2 = getTile(player->pos);
  6442. Creature* creature = getCreatureByName(house->getOwner());
  6443. Player* prevOwner = creature? dynamic_cast<Player*>(creature) : NULL;
  6444. if(!house || !tile->isHouse())
  6445. {
  6446. tradePartner->sendCancel("You must stay in house!");
  6447. return;
  6448. }
  6449. if(!tile->isHouse() && !tile2->isHouse() && player->tradeState != TRADE_INITIATED){
  6450. player->sendCancel("You can only sell act if you are in house and you are the owner!");
  6451. return;
  6452. }
  6453. if(house->getOwner() != tradePartner->getName())
  6454. {
  6455. tradePartner->sendCancel("You must stay in your house!");
  6456. return;
  6457. }
  6458.  
  6459. if(house && house->checkHouseCount(player) >= g_config.getGlobalNumber("maxhouses", 0)){
  6460. std::stringstream textmsg;
  6461. textmsg << " You cannot have more than " << g_config.getGlobalNumber("maxhouses", 1) << " house.";
  6462. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6463. return;
  6464. }
  6465.  
  6466. if (house && tradePartner->level < g_config.getGlobalNumber("buyhouselvlrook",1) && tradePartner->vocation == 0)
  6467. {
  6468. player->sendCancel("This player have too low level to buy house!");
  6469. std::stringstream textmsg;
  6470. textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("buyhouselvlrook",2) << " level.";
  6471. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6472. return;
  6473. }
  6474.  
  6475. if (house && tradePartner->level < g_config.getGlobalNumber("houselevel", 0) && tradePartner->vocation != 0)
  6476. {
  6477. player->sendCancel("This player have too low level to buy house!");
  6478. std::stringstream textmsg;
  6479. textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("houselevel", 0) << " level.";
  6480. tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6481. return;
  6482. }
  6483.  
  6484. if(tradePartner->getFreeCapacity() < tradeItem1->getWeight())
  6485. {
  6486. return;
  6487. }
  6488.  
  6489. if(player->addItem(tradeItem2, true) && tradePartner->addItem(tradeItem1, true) &&
  6490. player->removeItem(tradeItem1, true) && tradePartner->removeItem(tradeItem2, true)){
  6491.  
  6492. player->removeItem(tradeItem1);
  6493. tradePartner->removeItem(tradeItem2);
  6494.  
  6495. player->onThingRemove(tradeItem1);
  6496. tradePartner->onThingRemove(tradeItem2);
  6497.  
  6498. player->addItem(tradeItem2);
  6499. tradePartner->addItem(tradeItem1);
  6500. }
  6501. else{
  6502. player->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6503. tradePartner->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6504. return;
  6505. }
  6506. tradePartner->removeItem(tradeItem1, true);
  6507. player->addItem(tradeItem1, true);
  6508. tradePartner->addItem(tradeItem2, true);
  6509. house->setOwner(player->getName());
  6510. teleport(tradePartner,player->pos);
  6511. if (prevOwner)
  6512. prevOwner->houseRightsChanged = true;
  6513. player->houseRightsChanged = true;
  6514. }
  6515. #endif
  6516.  
  6517. if(player->addItem(tradeItem2, true) && tradePartner->addItem(tradeItem1, true) &&
  6518. player->removeItem(tradeItem1, true) && tradePartner->removeItem(tradeItem2, true)){
  6519.  
  6520. player->removeItem(tradeItem1);
  6521. tradePartner->removeItem(tradeItem2);
  6522.  
  6523. player->onThingRemove(tradeItem1);
  6524. tradePartner->onThingRemove(tradeItem2);
  6525.  
  6526. player->addItem(tradeItem2);
  6527. tradePartner->addItem(tradeItem1);
  6528. }
  6529. else{
  6530. player->sendTextMessage(MSG_SMALLINFO, "Sorry not possible.");
  6531. tradePartner->sendTextMessage(MSG_SMALLINFO, "Sorry not possible.");
  6532. }
  6533.  
  6534. std::map<Item*, uint32_t>::iterator it;
  6535.  
  6536. it = tradeItems.find(tradeItem1);
  6537. if(it != tradeItems.end()) {
  6538. FreeThing(it->first);
  6539. tradeItems.erase(it);
  6540. }
  6541.  
  6542. it = tradeItems.find(tradeItem2);
  6543. if(it != tradeItems.end()) {
  6544. FreeThing(it->first);
  6545. tradeItems.erase(it);
  6546. }
  6547.  
  6548. player->setAcceptTrade(false);
  6549. tradePartner->setAcceptTrade(false);
  6550. }
  6551. }
  6552.  
  6553. void Game::playerLookInTrade(Player* player, bool lookAtCounterOffer, int32_t index)
  6554. {
  6555. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerLookInTrade()");
  6556.  
  6557. Player *tradePartner = getPlayerByID(player->tradePartner);
  6558. if(!tradePartner)
  6559. return;
  6560.  
  6561. Item *tradeItem = NULL;
  6562.  
  6563. if(lookAtCounterOffer)
  6564. tradeItem = tradePartner->getTradeItem();
  6565. else
  6566. tradeItem = player->getTradeItem();
  6567.  
  6568. if(!tradeItem)
  6569. return;
  6570.  
  6571. #ifdef __KIRO_AKT__
  6572. if(tradeItem->getID() == ITEM_AKT)
  6573. {
  6574. Tile* tile = getTile(tradePartner->pos);
  6575. House* house = tile? tile->getHouse() : NULL;
  6576.  
  6577.  
  6578. if(house && house->getOwner() == tradePartner->getName())
  6579. {
  6580. stringstream ss;
  6581. ss << "You see " << tradeItem->getDescription(true) << " applies to: " << house->getName() << ".";
  6582. player->sendTextMessage(MSG_INFO, ss.str().c_str());
  6583. return;
  6584. }
  6585.  
  6586. }
  6587. #endif
  6588.  
  6589. if(index == 0) {
  6590. stringstream ss;
  6591. ss << "You see " << tradeItem->getDescription(true);
  6592. player->sendTextMessage(MSG_INFO, ss.str().c_str());
  6593. return;
  6594. }
  6595.  
  6596. Container *tradeContainer = dynamic_cast<Container*>(tradeItem);
  6597. if(!tradeContainer || index > tradeContainer->getItemHoldingCount())
  6598. return;
  6599.  
  6600. bool foundItem = false;
  6601. std::list<const Container*> stack;
  6602. stack.push_back(tradeContainer);
  6603.  
  6604. ContainerList::const_iterator it;
  6605.  
  6606. while(!foundItem && stack.size() > 0) {
  6607. const Container *container = stack.front();
  6608. stack.pop_front();
  6609.  
  6610. for (it = container->getItems(); it != container->getEnd(); ++it) {
  6611. Container *container = dynamic_cast<Container*>(*it);
  6612. if(container) {
  6613. stack.push_back(container);
  6614. }
  6615.  
  6616. --index;
  6617. if(index == 0) {
  6618. tradeItem = *it;
  6619. foundItem = true;
  6620. break;
  6621. }
  6622. }
  6623. }
  6624.  
  6625. if(foundItem) {
  6626. stringstream ss;
  6627. ss << "You see " << tradeItem->getDescription(true);
  6628. player->sendTextMessage(MSG_INFO, ss.str().c_str());
  6629. }
  6630. }
  6631.  
  6632. void Game::playerCloseTrade(Player* player)
  6633. {
  6634. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerCloseTrade()");
  6635.  
  6636. Player* tradePartner = getPlayerByID(player->tradePartner);
  6637.  
  6638. std::vector<Item*>::iterator it;
  6639. if(player->getTradeItem()) {
  6640. std::map<Item*, uint32_t>::iterator it = tradeItems.find(player->getTradeItem());
  6641. if(it != tradeItems.end()) {
  6642. FreeThing(it->first);
  6643. tradeItems.erase(it);
  6644. }
  6645. }
  6646.  
  6647. player->setAcceptTrade(false);
  6648. player->sendTextMessage(MSG_SMALLINFO, "Trade cancelled.");
  6649. player->sendCloseTrade();
  6650.  
  6651. if(tradePartner) {
  6652. if(tradePartner->getTradeItem()) {
  6653. std::map<Item*, uint32_t>::iterator it = tradeItems.find(tradePartner->getTradeItem());
  6654. if(it != tradeItems.end()) {
  6655. FreeThing(it->first);
  6656. tradeItems.erase(it);
  6657. }
  6658. }
  6659.  
  6660. tradePartner->setAcceptTrade(false);
  6661. tradePartner->sendTextMessage(MSG_SMALLINFO, "Trade cancelled.");
  6662. tradePartner->sendCloseTrade();
  6663. }
  6664. }
  6665.  
  6666. void Game::autoCloseTrade(const Item* item, bool itemMoved /*= false*/)
  6667. {
  6668. if(!item)
  6669. return;
  6670.  
  6671. std::map<Item*, uint32_t>::const_iterator it;
  6672. const Container* container = NULL;
  6673. for(it = tradeItems.begin(); it != tradeItems.end(); it++) {
  6674. if(item == it->first ||
  6675. (itemMoved && (container = dynamic_cast<const Container*>(item)) && container->isHoldingItem(it->first)) ||
  6676. ((container = dynamic_cast<const Container*>(it->first)) && container->isHoldingItem(item)))
  6677. {
  6678. Player* player = getPlayerByID(it->second);
  6679. if(player){
  6680. playerCloseTrade(player);
  6681. }
  6682.  
  6683. break;
  6684. }
  6685. }
  6686. }
  6687.  
  6688. void Game::autoCloseAttack(Player* player, Creature* target)
  6689. {
  6690. if((std::abs(player->pos.x - target->pos.x) > 7) ||
  6691. (std::abs(player->pos.y - target->pos.y) > 5) || (player->pos.z != target->pos.z)){
  6692. player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  6693. playerSetAttackedCreature(player, 0);
  6694. }
  6695. }
  6696.  
  6697. void Game::playerSetAttackedCreature(Player* player, uint32_t creatureid)
  6698. {
  6699. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerSetAttackedCreature()");
  6700.  
  6701. if(player->isRemoved)
  6702. return;
  6703.  
  6704. if(player->attackedCreature != 0 && creatureid == 0) {
  6705. player->sendCancelAttacking();
  6706. }
  6707.  
  6708.  
  6709. Creature* attackedCreature = NULL;
  6710. if(creatureid != 0) {
  6711. attackedCreature = getCreatureByID(creatureid);
  6712. }
  6713.  
  6714. Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  6715. bool pvpArena = false, rook = false, attackedIsSummon = false;
  6716.  
  6717. #ifdef YUR_PVP_ARENA
  6718. if (player && attackedCreature)
  6719. {
  6720. Tile *t1 = map->getTile(player->pos), *t2 = map->getTile(attackedCreature->pos);
  6721. pvpArena = t1 && t2 && t1->isPvpArena() && t2->isPvpArena();
  6722. }
  6723. #endif //YUR_PVP_ARENA
  6724.  
  6725. #ifdef YUR_ROOKGARD
  6726. rook = player && player->isRookie() && attackedPlayer && attackedPlayer->isRookie();
  6727. #endif //YUR_ROOKGARD
  6728.  
  6729. #ifdef TR_SUMMONS
  6730. attackedIsSummon = (attackedCreature && attackedCreature->isPlayersSummon() && attackedCreature->getMaster() != player);
  6731. #endif //TR_SUMMONS
  6732.  
  6733. if(!attackedCreature || (attackedCreature->access >= g_config.ACCESS_PROTECT || ((getWorldType() == WORLD_TYPE_NO_PVP || rook) &&
  6734. !pvpArena && player->access < g_config.ACCESS_PROTECT && (dynamic_cast<Player*>(attackedCreature) || attackedIsSummon)))) {
  6735. if(attackedCreature) {
  6736. player->sendTextMessage(MSG_SMALLINFO, "You may not attack this player.");
  6737. }
  6738. player->sendCancelAttacking();
  6739. player->setAttackedCreature(NULL);
  6740. stopEvent(player->eventCheckAttacking);
  6741. player->eventCheckAttacking = 0;
  6742. }
  6743. else if(attackedCreature) {
  6744. player->setAttackedCreature(attackedCreature);
  6745. stopEvent(player->eventCheckAttacking);
  6746. player->eventCheckAttacking = addEvent(makeTask(g_config.getGlobalNumber("firstattack", 2000), std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), player->getID())));
  6747. }
  6748.  
  6749. }
  6750.  
  6751.  
  6752. void Game::flushSendBuffers()
  6753. {
  6754. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::flushSendBuffers()");
  6755.  
  6756. for(std::vector<Player*>::iterator it = BufferedPlayers.begin(); it != BufferedPlayers.end(); ++it) {
  6757. (*it)->flushMsg();
  6758. (*it)->SendBuffer = false;
  6759. (*it)->releaseThing();
  6760. /*
  6761. #ifdef __DEBUG__
  6762. std::cout << "flushSendBuffers() - releaseThing()" << std::endl;
  6763. #endif
  6764. */
  6765. }
  6766. BufferedPlayers.clear();
  6767.  
  6768. //free memory
  6769. for(std::vector<Thing*>::iterator it = ToReleaseThings.begin(); it != ToReleaseThings.end(); ++it){
  6770. (*it)->releaseThing();
  6771. }
  6772. ToReleaseThings.clear();
  6773.  
  6774.  
  6775. return;
  6776. }
  6777.  
  6778. void Game::addPlayerBuffer(Player* p)
  6779. {
  6780. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::addPlayerBuffer()");
  6781.  
  6782. /*
  6783. #ifdef __DEBUG__
  6784. std::cout << "addPlayerBuffer() - useThing()" << std::endl;
  6785. #endif
  6786. */
  6787. if(p->SendBuffer == false){
  6788. p->useThing();
  6789. BufferedPlayers.push_back(p);
  6790. p->SendBuffer = true;
  6791. }
  6792.  
  6793. return;
  6794. }
  6795.  
  6796. void Game::FreeThing(Thing* thing){
  6797.  
  6798. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::FreeThing()");
  6799. //std::cout << "freeThing() " << thing <<std::endl;
  6800. ToReleaseThings.push_back(thing);
  6801.  
  6802. return;
  6803. }
  6804. /*
  6805. ADD
  6806. container(player,pos-cid,thing)
  6807. inventory(player,pos-i,[ignored])
  6808. ground([ignored],postion,thing)
  6809.  
  6810. REMOVE
  6811. container(player,pos-cid,thing,autoclose?)
  6812. inventory(player,pos-i,thing,autoclose?)
  6813. ground([ignored],postion,thing,autoclose?,stackpos)
  6814.  
  6815. UPDATE
  6816. container(player,pos-cid,thing)
  6817. inventory(player,pos-i,[ignored])
  6818. ground([ignored],postion,thing,stackpos)
  6819. */
  6820. void Game::sendAddThing(Player* player,const Position &pos,const Thing* thing){
  6821. if(pos.x == 0xFFFF) {
  6822. if(!player)
  6823. return;
  6824. if(pos.y & 0x40) { //container
  6825. if(!thing)
  6826. return;
  6827.  
  6828. const Item *item = dynamic_cast<const Item*>(thing);
  6829. if(!item)
  6830. return;
  6831.  
  6832. unsigned char containerid = pos.y & 0x0F;
  6833. Container* container = player->getContainer(containerid);
  6834. if(!container)
  6835. return;
  6836.  
  6837. SpectatorVec list;
  6838. SpectatorVec::iterator it;
  6839.  
  6840. Position centerpos = (container->pos.x == 0xFFFF ? player->pos : container->pos);
  6841. getSpectators(Range(centerpos,2,2,2,2,false), list);
  6842.  
  6843. if(!list.empty()) {
  6844. for(it = list.begin(); it != list.end(); ++it) {
  6845. Player *spectator = dynamic_cast<Player*>(*it);
  6846. if(spectator)
  6847. spectator->onItemAddContainer(container,item);
  6848. }
  6849. }
  6850. else
  6851. player->onItemAddContainer(container,item);
  6852.  
  6853. }
  6854. else //inventory
  6855. {
  6856. player->sendInventory(pos.y);
  6857. }
  6858. }
  6859. else //ground
  6860. {
  6861. if(!thing)
  6862. return;
  6863.  
  6864. #ifdef SM_SUMMON_ATTACK
  6865. Monster* monster = dynamic_cast<Monster*>(const_cast<Thing*>(thing));
  6866. #endif //SM_SUMMON_ATTACK
  6867.  
  6868. SpectatorVec list;
  6869. SpectatorVec::iterator it;
  6870.  
  6871. getSpectators(Range(pos,true), list);
  6872.  
  6873. //players
  6874. for(it = list.begin(); it != list.end(); ++it) {
  6875. if(dynamic_cast<Player*>(*it)) {
  6876. (*it)->onThingAppear(thing);
  6877. #ifdef SM_SUMMON_ATTACK
  6878. if (monster && !monster->isSummon())
  6879. monster->onThingAppear(*it);
  6880. #endif //SM_SUMMON_ATTACK
  6881. }
  6882. }
  6883.  
  6884. //none-players
  6885. for(it = list.begin(); it != list.end(); ++it) {
  6886. if(!dynamic_cast<Player*>(*it)) {
  6887. (*it)->onThingAppear(thing);
  6888. }
  6889. }
  6890. }
  6891. }
  6892.  
  6893. void Game::sendRemoveThing(Player* player,const Position &pos,const Thing* thing,const unsigned char stackpos /*=1*/ ,const bool autoclose/* =false*/){
  6894. if(!thing)
  6895. return;
  6896.  
  6897. const Item *item = dynamic_cast<const Item*>(thing);
  6898. bool perform_autoclose = false;
  6899. if(autoclose && item){
  6900. const Container *container = dynamic_cast<const Container*>(item);
  6901. if(container)
  6902. perform_autoclose = true;
  6903. }
  6904.  
  6905. if(pos.x == 0xFFFF) {
  6906. if(!player)
  6907. return;
  6908. if(pos.y & 0x40) { //container
  6909. if(!item)
  6910. return;
  6911.  
  6912. unsigned char containerid = pos.y & 0x0F;
  6913. Container* container = player->getContainer(containerid);
  6914. if(!container)
  6915. return;
  6916.  
  6917. //check that item is in the container
  6918. unsigned char slot = container->getSlotNumberByItem(item);
  6919.  
  6920. SpectatorVec list;
  6921. SpectatorVec::iterator it;
  6922.  
  6923. Position centerpos = (container->pos.x == 0xFFFF ? player->pos : container->pos);
  6924. getSpectators(Range(centerpos,2,2,2,2,false), list);
  6925.  
  6926. if(!list.empty()) {
  6927. for(it = list.begin(); it != list.end(); ++it) {
  6928. Player *spectator = dynamic_cast<Player*>(*it);
  6929. if(spectator){
  6930. spectator->onItemRemoveContainer(container,slot);
  6931. if(perform_autoclose){
  6932. spectator->onThingRemove(thing);
  6933. }
  6934. }
  6935. }
  6936. }
  6937. else{
  6938. player->onItemRemoveContainer(container,slot);
  6939. if(perform_autoclose){
  6940. player->onThingRemove(thing);
  6941. }
  6942. }
  6943.  
  6944. }
  6945. else //inventory
  6946. {
  6947. player->removeItemInventory(pos.y);
  6948. if(perform_autoclose){
  6949. player->onThingRemove(thing);
  6950. }
  6951. }
  6952. }
  6953. else //ground
  6954. {
  6955. SpectatorVec list;
  6956. SpectatorVec::iterator it;
  6957.  
  6958. getSpectators(Range(pos,true), list);
  6959.  
  6960. //players
  6961. for(it = list.begin(); it != list.end(); ++it) {
  6962. Player *spectator = dynamic_cast<Player*>(*it);
  6963. if(spectator) {
  6964. spectator->onThingDisappear(thing,stackpos);
  6965.  
  6966. if(perform_autoclose){
  6967. spectator->onThingRemove(thing);
  6968. }
  6969. }
  6970. }
  6971.  
  6972. //none-players
  6973. for(it = list.begin(); it != list.end(); ++it) {
  6974. if(!dynamic_cast<Player*>(*it)) {
  6975. (*it)->onThingDisappear(thing,stackpos);
  6976. }
  6977. }
  6978. }
  6979. }
  6980.  
  6981. void Game::sendUpdateThing(Player* player,const Position &pos,const Thing* thing,const unsigned char stackpos/*=1*/){
  6982.  
  6983. if(pos.x == 0xFFFF) {
  6984. if(!player)
  6985. return;
  6986. if(pos.y & 0x40) { //container
  6987. if(!thing)
  6988. return;
  6989.  
  6990. const Item *item = dynamic_cast<const Item*>(thing);
  6991. if(!item)
  6992. return;
  6993.  
  6994. unsigned char containerid = pos.y & 0x0F;
  6995. Container* container = player->getContainer(containerid);
  6996. if(!container)
  6997. return;
  6998. //check that item is in the container
  6999. unsigned char slot = container->getSlotNumberByItem(item);
  7000.  
  7001. SpectatorVec list;
  7002. SpectatorVec::iterator it;
  7003.  
  7004. Position centerpos = (container->pos.x == 0xFFFF ? player->pos : container->pos);
  7005. getSpectators(Range(centerpos,2,2,2,2,false), list);
  7006.  
  7007. if(!list.empty()) {
  7008. for(it = list.begin(); it != list.end(); ++it) {
  7009. Player *spectator = dynamic_cast<Player*>(*it);
  7010. if(spectator)
  7011. spectator->onItemUpdateContainer(container,item,slot);
  7012. }
  7013. }
  7014. else{
  7015. //never should be here
  7016. std::cout << "Error: sendUpdateThing" << std::endl;
  7017. //player->onItemUpdateContainer(container,item,slot);
  7018. }
  7019.  
  7020. }
  7021. else //inventory
  7022. {
  7023. player->sendInventory(pos.y);
  7024. }
  7025. }
  7026. else //ground
  7027. {
  7028. if(!thing)
  7029. return;
  7030.  
  7031. SpectatorVec list;
  7032. SpectatorVec::iterator it;
  7033.  
  7034. getSpectators(Range(pos,true), list);
  7035.  
  7036. //players
  7037. for(it = list.begin(); it != list.end(); ++it) {
  7038. if(dynamic_cast<Player*>(*it)) {
  7039. (*it)->onThingTransform(thing,stackpos);
  7040. }
  7041. }
  7042.  
  7043. //none-players
  7044. for(it = list.begin(); it != list.end(); ++it) {
  7045. if(!dynamic_cast<Player*>(*it)) {
  7046. (*it)->onThingTransform(thing,stackpos);
  7047. }
  7048. }
  7049. }
  7050. }
  7051.  
  7052. void Game::addThing(Player* player,const Position &pos,Thing* thing)
  7053. {
  7054. if(!thing)
  7055. return;
  7056. Item *item = dynamic_cast<Item*>(thing);
  7057.  
  7058. if(pos.x == 0xFFFF) {
  7059. if(!player || !item)
  7060. return;
  7061.  
  7062. if(pos.y & 0x40) { //container
  7063. unsigned char containerid = pos.y & 0x0F;
  7064. Container* container = player->getContainer(containerid);
  7065. if(!container)
  7066. return;
  7067.  
  7068. container->addItem(item);
  7069. sendAddThing(player,pos,thing);
  7070. }
  7071. else //inventory
  7072. {
  7073. player->addItemInventory(item,pos.y,true);
  7074. sendAddThing(player,pos,thing);
  7075. }
  7076. }
  7077. else //ground
  7078. {
  7079. if(!thing)
  7080. return;
  7081. //Tile *tile = map->getTile(pos.x, pos.y, pos.z);
  7082. Tile *tile = map->getTile(pos);
  7083. if(tile){
  7084. thing->pos = pos;
  7085. if(item && item->isSplash()){
  7086. if(tile->splash){
  7087. int32_t oldstackpos = tile->getThingStackPos(tile->splash);
  7088. Item *oldsplash = tile->splash;
  7089.  
  7090. oldsplash->isRemoved = true;
  7091. FreeThing(oldsplash);
  7092.  
  7093. tile->splash = item;
  7094.  
  7095. sendUpdateThing(NULL, pos, item, oldstackpos);
  7096. }
  7097. else{
  7098. tile->splash = item;
  7099. sendAddThing(NULL,pos,tile->splash);
  7100. }
  7101. }
  7102. else if(item && item->isGroundTile()){
  7103. tile->ground = item;
  7104.  
  7105. SpectatorVec list;
  7106. SpectatorVec::iterator it;
  7107.  
  7108. getSpectators(Range(thing->pos, true), list);
  7109.  
  7110. //players
  7111. for(it = list.begin(); it != list.end(); ++it) {
  7112. if(dynamic_cast<Player*>(*it)) {
  7113. (*it)->onTileUpdated(pos);
  7114. }
  7115. }
  7116.  
  7117. //none-players
  7118. for(it = list.begin(); it != list.end(); ++it) {
  7119. if(!dynamic_cast<Player*>(*it)) {
  7120. (*it)->onTileUpdated(pos);
  7121. }
  7122. }
  7123.  
  7124. //Game::creatureBroadcastTileUpdated(thing->pos);
  7125. }
  7126. else if(item && item->isStackable()){
  7127. Item *topitem = tile->getTopDownItem();
  7128. if(topitem && topitem->getID() == item->getID() &&
  7129. topitem->getItemCountOrSubtype() + item->getItemCountOrSubtype() <= 100){
  7130. topitem->setItemCountOrSubtype(topitem->getItemCountOrSubtype() + item->getItemCountOrSubtype());
  7131. int32_t stackpos = tile->getThingStackPos(topitem);
  7132. sendUpdateThing(NULL,topitem->pos,topitem,stackpos);
  7133. item->pos.x = 0xFFFF;
  7134. FreeThing(item);
  7135. }
  7136. else{
  7137. tile->addThing(thing);
  7138. sendAddThing(player,pos,thing);
  7139. }
  7140. }
  7141. else{
  7142. tile->addThing(thing);
  7143. sendAddThing(player,pos,thing);
  7144. }
  7145. }
  7146. }
  7147. }
  7148.  
  7149. bool Game::removeThing(Player* player,const Position &pos,Thing* thing, bool setRemoved /*= true*/)
  7150. {
  7151. if(!thing)
  7152. return false;
  7153. Item *item = dynamic_cast<Item*>(thing);
  7154.  
  7155. if(pos.x == 0xFFFF) {
  7156. if(!player || !item)
  7157. return false;
  7158.  
  7159. if(pos.y & 0x40) { //container
  7160. unsigned char containerid = pos.y & 0x0F;
  7161. Container* container = player->getContainer(containerid);
  7162. if(!container)
  7163. return false;
  7164.  
  7165. sendRemoveThing(player,pos,thing,0,true);
  7166. if(!container->removeItem(item))
  7167. return false;
  7168.  
  7169. if(player && player->isHoldingContainer(container)) {
  7170. player->updateInventoryWeigth();
  7171. player->sendStats();
  7172. }
  7173. }
  7174. else //inventory
  7175. {
  7176. //sendRemoveThing(player,pos,thing,0,true);
  7177. if(!player->removeItemInventory(pos.y))
  7178. return false;
  7179. player->onThingRemove(thing);
  7180. //player->removeItemInventory(pos.y,true);
  7181. }
  7182. if(setRemoved)
  7183. item->isRemoved = true;
  7184. return true;
  7185. }
  7186. else //ground
  7187. {
  7188. //Tile *tile = map->getTile(pos.x, pos.y, pos.z);
  7189. Tile *tile = map->getTile(pos);
  7190. if(tile){
  7191. unsigned char stackpos = tile->getThingStackPos(thing);
  7192. if(!tile->removeThing(thing))
  7193. return false;
  7194. sendRemoveThing(NULL,pos,thing,stackpos,true);
  7195. }
  7196. else{
  7197. return false;
  7198. }
  7199. if(item && setRemoved){
  7200. item->isRemoved = true;
  7201. }
  7202. return true;
  7203. }
  7204. }
  7205.  
  7206. Position Game::getThingMapPos(Player *player, const Position &pos)
  7207. {
  7208. if(pos.x == 0xFFFF){
  7209. Position dummyPos(0,0,0);
  7210. if(!player)
  7211. return dummyPos;
  7212. if(pos.y & 0x40) { //from container
  7213. unsigned char containerid = pos.y & 0x0F;
  7214. const Container* container = player->getContainer(containerid);
  7215. if(!container){
  7216. return dummyPos;
  7217. }
  7218. while(container->getParent() != NULL) {
  7219. container = container->getParent();
  7220. }
  7221. if(container->pos.x == 0xFFFF)
  7222. return player->pos;
  7223. else
  7224. return container->pos;
  7225. }
  7226. else //from inventory
  7227. {
  7228. return player->pos;
  7229. }
  7230. }
  7231. else{
  7232. return pos;
  7233. }
  7234. }
  7235.  
  7236. Thing* Game::getThing(const Position &pos,unsigned char stack, Player* player /*=NULL*/)
  7237. {
  7238. if(pos.x == 0xFFFF) {
  7239. if(!player)
  7240. return NULL;
  7241. if(pos.y & 0x40) { //from container
  7242. unsigned char containerid = pos.y & 0x0F;
  7243. Container* container = player->getContainer(containerid);
  7244. if(!container)
  7245. return NULL;
  7246.  
  7247. return container->getItem(pos.z);
  7248. }
  7249. else //from inventory
  7250. {
  7251. return player->getItem(pos.y);
  7252. }
  7253. }
  7254. else //from ground
  7255. {
  7256. //Tile *t = getTile(pos.x, pos.y, pos.z);
  7257. Tile *t = map->getTile(pos);
  7258. if(!t)
  7259. return NULL;
  7260.  
  7261. return t->getThingByStackPos(stack);
  7262. }
  7263. }
  7264. int32_t Game::getDepot(Container* c, int32_t e)
  7265. {
  7266. for(int32_t a = 0; a < c->size(); a++)
  7267. {
  7268. Container* x = dynamic_cast<Container*>(dynamic_cast<Item*>(c->getItem(a)));
  7269. Item* i = dynamic_cast<Item*>(c->getItem(a));
  7270. if(i)
  7271. e++;
  7272. if(x)
  7273. e = getDepot(x, e);
  7274. }
  7275. return e;
  7276. }
  7277.  
  7278.  
  7279. #ifdef WOLV_LOAD_NPC
  7280. bool Game::loadNpcs()
  7281. {
  7282. xmlDocPtr doc;
  7283. doc = xmlParseFile((g_config.DATA_DIR + "world/npc.xml").c_str());
  7284. if (!doc)
  7285. return false;
  7286.  
  7287. xmlNodePtr root, npcNode;
  7288. root = xmlDocGetRootElement(doc);
  7289.  
  7290. if (xmlStrcmp(root->name, (const xmlChar*)"npclist"))
  7291. {
  7292. xmlFreeDoc(doc);
  7293. return false;
  7294. }
  7295.  
  7296. npcNode = root->children;
  7297. while (npcNode)
  7298. {
  7299. if (strcmp((const char*) npcNode->name, "npc") == 0)
  7300. {
  7301. std::string name = (const char*)xmlGetProp(npcNode, (const xmlChar *) "name");
  7302. int32_t x = atoi((const char*) xmlGetProp(npcNode, (const xmlChar*) "x"));
  7303. int32_t y = atoi((const char*) xmlGetProp(npcNode, (const xmlChar*) "y"));
  7304. int32_t z = atoi((const char*) xmlGetProp(npcNode, (const xmlChar*) "z"));
  7305.  
  7306. Npc* mynpc = new Npc(name, this);
  7307. mynpc->pos = Position(x, y, z);
  7308.  
  7309. if (!placeCreature(mynpc->pos, mynpc))
  7310. {
  7311. std::cout << "Could not place " << name << "!" << std::endl;
  7312. xmlFreeDoc(doc);
  7313. return false;
  7314. }
  7315.  
  7316. const char* tmp = (const char*)xmlGetProp(npcNode, (const xmlChar*) "dir");
  7317. if (tmp)
  7318. mynpc->setDirection((Direction)atoi(tmp));
  7319. }
  7320. npcNode = npcNode->next;
  7321. }
  7322.  
  7323. xmlFreeDoc(doc);
  7324. return true;
  7325. }
  7326. #endif //WOLV_LOAD_NPC
  7327.  
  7328. #ifdef TLM_SERVER_SAVE
  7329. void Game::serverSave()
  7330. {
  7331. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::serverSave()");
  7332. std::cout << ":: zapis serwera :: " << std::endl;
  7333. timer();
  7334.  
  7335. AutoList<Player>::listiterator it = Player::listPlayer.list.begin();
  7336. while (it != Player::listPlayer.list.end())
  7337. {
  7338. IOPlayer::instance()->savePlayer(it->second);
  7339. ++it;
  7340. }
  7341. std::cout << ":: Gracze [" << timer() << " s]" << std::endl;
  7342. Guilds::Save();
  7343. std::cout << "Gildie [" << timer() << " s]" << std::endl;
  7344. Houses::Save(this);
  7345. std::cout << ":: Domki [" << timer() << " s]" << std::endl;
  7346. loginQueue.save();
  7347. std::cout << ":: Kolejki [" << timer() << " s]" << std::endl;
  7348.  
  7349. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it);
  7350. }
  7351.  
  7352. void Game::autoServerSave()
  7353. {
  7354. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::autoServerSave()");
  7355. serverSave();
  7356. addEvent(makeTask(g_config.getGlobalNumber("autosave", 1)*60000, std::mem_fun(&Game::autoServerSave)));
  7357. }
  7358. #endif //TLM_SERVER_SAVE
  7359.  
  7360.  
  7361. #ifdef ELEM_VIP_LIST
  7362. /*void Game::vipLogin(Player* player)
  7363. {
  7364. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::vipLogin()");
  7365. std::string vipname = player->getName();
  7366.  
  7367. #ifdef _NG_BBK_VIP_SYSTEM__
  7368. std::transform(vipname.begin(), vipname.end(), vipname.begin(), (int32_t(*)(int32_t)) std::tolower);
  7369. #endif //_NG_BBK_VIP_SYSTEM__
  7370.  
  7371. for(AutoList<Creature>::listiterator cit = listCreature.list.begin(); cit != listCreature.list.end(); ++cit)
  7372. {
  7373. Player* player = dynamic_cast<Player*>((*cit).second);
  7374. if (player)
  7375. player->sendVipLogin(vipname);
  7376. }
  7377. }
  7378.  
  7379. void Game::vipLogout(std::string vipname)
  7380. {
  7381. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::vipLogout()");
  7382.  
  7383. #ifdef _NG_BBK_VIP_SYSTEM__
  7384. std::transform(vipname.begin(), vipname.end(), vipname.begin(), (int32_t(*)(int32_t)) std::tolower);
  7385. #endif //_NG_BBK_VIP_SYSTEM__
  7386.  
  7387. for(AutoList<Creature>::listiterator cit = listCreature.list.begin(); cit != listCreature.list.end(); ++cit)
  7388. {
  7389. Player* player = dynamic_cast<Player*>((*cit).second);
  7390. if (player)
  7391. player->sendVipLogout(vipname);
  7392. }
  7393. }*/
  7394.  
  7395. bool Game::isPlayer(std::string name)
  7396. {
  7397. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::isPlayer()");
  7398. extern xmlMutexPtr xmlmutex;
  7399.  
  7400. std::string datadir = g_config.getGlobalString("datadir");
  7401. std::string filenamecheck = datadir + "players/" + name + ".xml";
  7402. std::transform(filenamecheck.begin(),filenamecheck.end(), filenamecheck.begin(), (int32_t(*)(int32_t))tolower);
  7403.  
  7404. xmlDocPtr doc;
  7405. xmlMutexLock(xmlmutex);
  7406. doc = xmlParseFile(filenamecheck.c_str());
  7407.  
  7408. if (doc)
  7409. {
  7410. xmlMutexUnlock(xmlmutex);
  7411. xmlFreeDoc(doc);
  7412. return true;
  7413. }
  7414. else
  7415. {
  7416. xmlMutexUnlock(xmlmutex);
  7417. xmlFreeDoc(doc);
  7418. return false;
  7419. }
  7420. }
  7421. #endif //ELEM_VIP_LIST
  7422.  
  7423. void Game::checkSpell(Player* player, SpeakClasses type, std::string text)
  7424. {
  7425. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkSpell()");
  7426.  
  7427. if (player->isRookie())
  7428. return;
  7429.  
  7430. #ifdef TLM_HOUSE_SYSTEM
  7431. else if (text == "aleta gom") // edit owner
  7432. {
  7433. Tile* tile = getTile(player->pos);
  7434. House* house = tile? tile->getHouse() : NULL;
  7435.  
  7436. if (house && house->getPlayerRights(player->getName()) == HOUSE_OWNER)
  7437. {
  7438. player->sendHouseWindow(house, player->pos, HOUSE_OWNER);
  7439. }
  7440. else
  7441. {
  7442. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7443. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7444. }
  7445. }
  7446. else if (text == "aleta grav") // edit door owners
  7447. {
  7448. bool last = false;
  7449. for (int32_t x = player->pos.x-1; x <= player->pos.x+1 && !last; x++)
  7450. {
  7451. for(int32_t y = player->pos.y-1; y <= player->pos.y+1 && !last; y++)
  7452. {
  7453. Position doorPos(x, y, player->pos.z);
  7454. Tile* tile = getTile(doorPos);
  7455. House* house = tile? tile->getHouse() : NULL;
  7456.  
  7457. if (house && house->getPlayerRights(doorPos, player->getName()) == HOUSE_OWNER)
  7458. {
  7459. Item *item = dynamic_cast<Item*>(tile->getThingByStackPos(tile->getThingCount()-1));
  7460. if (item && Item::items[item->getID()].isDoor)
  7461. {
  7462. player->sendHouseWindow(house, doorPos, HOUSE_DOOROWNER);
  7463. last = true;
  7464. }
  7465. }
  7466. }
  7467. }
  7468. }
  7469. else if (text == "!buyhouse" || text == "!buyhome")
  7470. {
  7471. uint32_t money = player->getMoney();
  7472. bool last = false;
  7473. #ifdef HUCZU_EXHAUSTED
  7474. if(player->houseTicks > 0){
  7475. player->sendCancel("You're exhausted.");
  7476. return;
  7477. }
  7478. else
  7479. player->houseTicks += 5;
  7480. #endif //HUCZU_EXHAUSTED
  7481. int32_t houselevel = g_config.getGlobalNumber("houselevel", 0);
  7482. if(!player->premmium){
  7483. player->sendCancel("You must have a premium to buy house!");
  7484. return;
  7485. }
  7486. if( player->getLevel() < houselevel ){
  7487. std::stringstream textmsg2;
  7488. textmsg2 << " You need level " << houselevel << "+ to buy a house! ";
  7489. player->sendTextMessage(MSG_ADVANCE, textmsg2.str().c_str());
  7490. }
  7491. else{
  7492.  
  7493. for (int32_t x = player->pos.x-1; x <= player->pos.x+1 && !last; x++)
  7494. {
  7495. for(int32_t y = player->pos.y-1; y <= player->pos.y+1 && !last; y++)
  7496. {
  7497. Position doorPos(x, y, player->pos.z);
  7498. Tile* tile = getTile(doorPos);
  7499. House* house = tile? tile->getHouse() : NULL;
  7500. if(house){
  7501. if(house->getPlayerRights(player->getName()) == HOUSE_OWNER){
  7502. player->sendTextMessage(MSG_ADVANCE, "You own this house.");
  7503. return;
  7504. }
  7505. if(house->isBought()){
  7506. player->sendTextMessage(MSG_ADVANCE, "This house already has an owner.");
  7507. return;
  7508. }
  7509. if(house->checkHouseCount(player) >= g_config.getGlobalNumber("maxhouses", 0)){
  7510. std::stringstream textmsg;
  7511. textmsg << " You cant have more than " << g_config.getGlobalNumber("maxhouses", 1) << " houses ";
  7512. player->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  7513. return;
  7514. }
  7515. if(house->getPlayerRights(doorPos, player->getName()) == HOUSE_NONE && !house->isBought() && house->checkHouseCount(player) < g_config.getGlobalNumber("maxhouses", 1))
  7516. {
  7517. Item *item = dynamic_cast<Item*>(tile->getThingByStackPos(tile->getThingCount()-1));
  7518. long price = g_config.getGlobalNumber("priceforsqm", 0) * house->getHouseSQM(house->getName());
  7519.  
  7520. if (item && Item::items[item->getID()].isDoor && price <= money)
  7521. {
  7522. player->substractMoney(price);
  7523. house->setOwner(player->getName());
  7524. house->save();
  7525. player->sendTextMessage(MSG_ADVANCE, "You bought a house.");
  7526. last = true;
  7527. }
  7528. else{
  7529. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7530. player->sendTextMessage(MSG_SMALLINFO, "You dont have enough money to buy this house.");
  7531. }
  7532. }
  7533. }
  7534. }
  7535. }
  7536. }
  7537. }
  7538. else if (text == "aleta sio") // edit guests
  7539. {
  7540. Tile* tile = getTile(player->pos);
  7541. House* house = tile? tile->getHouse() : NULL;
  7542.  
  7543. if (house && house->getPlayerRights(player->getName()) >= HOUSE_SUBOWNER)
  7544. {
  7545. player->sendHouseWindow(house, player->pos, HOUSE_GUEST);
  7546. }
  7547. else
  7548. {
  7549. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7550. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7551. }
  7552. }
  7553. else if (text == "aleta som") // edit subowners
  7554. {
  7555. Tile* tile = getTile(player->pos);
  7556. House* house = tile? tile->getHouse() : NULL;
  7557.  
  7558. if (house && house->getPlayerRights(player->getName()) == HOUSE_OWNER)
  7559. {
  7560. player->sendHouseWindow(house, player->pos, HOUSE_SUBOWNER);
  7561. }
  7562. else
  7563. {
  7564. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7565. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7566. }
  7567. }
  7568. else if (text == "alana sio") // kick me
  7569. {
  7570. Tile* tile = getTile(player->pos);
  7571. House* house = tile? tile->getHouse() : NULL;
  7572.  
  7573. if (house)
  7574. {
  7575. teleport(player, house->getFrontDoor());
  7576. player->sendMagicEffect(player->pos, NM_ME_ENERGY_AREA);
  7577. }
  7578. else
  7579. {
  7580. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7581. player->sendTextMessage(MSG_SMALLINFO, "You are not in a house.");
  7582. }
  7583. }
  7584. else if (text.substr(0, 11) == "alana sio \"") // kick someone
  7585. {
  7586. Creature* c = getCreatureByName(text.substr(11).c_str());
  7587. Player *target = c? dynamic_cast<Player*>(c) : NULL;
  7588.  
  7589. if (target)
  7590. {
  7591. Tile* tile = getTile(player->pos);
  7592. Tile* targetTile = getTile(target->pos);
  7593. House* house = tile? tile->getHouse() : NULL;
  7594. House* targetHouse = targetTile? targetTile->getHouse() : NULL;
  7595.  
  7596. if (house && targetHouse && house == targetHouse &&
  7597. house->getPlayerRights(player->getName()) >= HOUSE_SUBOWNER)
  7598. {
  7599. Position pos = house->getFrontDoor();
  7600. if (pos.x != 0xFFFF && pos.y != 0xFFFF && pos.z != 0xFF)
  7601. {
  7602. teleport(target, pos);
  7603. player->sendMagicEffect(target->pos, NM_ME_ENERGY_AREA);
  7604. }
  7605. else
  7606. {
  7607. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7608. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7609. }
  7610. }
  7611. else
  7612. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7613. }
  7614. else
  7615. {
  7616. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7617. player->sendTextMessage(MSG_SMALLINFO, "This player does not exist.");
  7618. }
  7619. }
  7620. #endif //TLM_HOUSE_SYSTEM
  7621.  
  7622. #ifdef TR_SUMMONS
  7623. else if (text.substr(0, 11) == "utevo res \"" &&
  7624. (!g_config.LEARN_SPELLS || player->knowsSpell("utevo res")))
  7625. {
  7626. if (player->vocation == VOCATION_DRUID || player->vocation == VOCATION_SORCERER ||
  7627. (g_config.SUMMONS_ALL_VOC && player->vocation != VOCATION_NONE))
  7628. {
  7629. std::string name = text.substr(11);
  7630. int32_t reqMana = Summons::getRequiredMana(name);
  7631. Tile* tile = getTile(player->pos);
  7632.  
  7633. if (!tile)
  7634. {
  7635. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7636. player->sendCancel("Sorry, not possible.");
  7637. }
  7638. else if (reqMana < 0)
  7639. {
  7640. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7641. player->sendCancel("You cannot summon this creature.");
  7642. }
  7643. else if (tile->isPz())
  7644. {
  7645. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7646. player->sendCancel("You cannot summon creatures in protection zone.");
  7647. }
  7648. #ifdef YUR_PVP_ARENA
  7649. else if (tile->isPvpArena())
  7650. {
  7651. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7652. player->sendCancel("You cannot summon creatures on arena.");
  7653. }
  7654. #endif //YUR_PVP_ARENA
  7655. else if (player->getSummonCount() >= g_config.MAX_SUMMONS)
  7656. {
  7657. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7658. player->sendCancel("You cannot have more summons.");
  7659. }
  7660. else if (player->getMana() < reqMana)
  7661. {
  7662. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7663. player->sendCancel("Not enough mana.");
  7664. }
  7665. else if (!placeSummon(player, name))
  7666. {
  7667. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7668. player->sendCancel("Not enough room");
  7669. }
  7670. else
  7671. {
  7672. player->mana -= reqMana;
  7673. player->addManaSpent(reqMana);
  7674. }
  7675. }
  7676. }
  7677. #endif //TR_SUMMONS
  7678.  
  7679. /*
  7680. #ifdef HUCZU_FIX
  7681. else if (text == "exevo flam sio" &&
  7682. (!g_config.LEARN_SPELLS || player->knowsSpell("exevo flam sio")))
  7683. {
  7684. const int32_t REQ_MANA = 200;
  7685.  
  7686. if (player->mana < REQ_MANA)
  7687. {
  7688. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7689. player->sendTextMessage(MSG_SMALLINFO, "Not enough mana.");
  7690. }
  7691.  
  7692. else if (player->maglevel < 15)
  7693. {
  7694. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7695. player->sendTextMessage(MSG_SMALLINFO, "You don't have the required magic level.");
  7696. }
  7697.  
  7698. else if (player->exhaustedTicks >= 1000 && player->access < g_config.ACCESS_PROTECT)
  7699. {
  7700. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7701. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  7702. }
  7703.  
  7704. else if (player->flamTicks != 0 && player->access < g_config.ACCESS_PROTECT)
  7705. {
  7706. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7707. player->sendTextMessage(MSG_SMALLINFO, "Not ready yet.");
  7708. }
  7709.  
  7710. else
  7711. {
  7712. player->flamBool = true;
  7713. player->exhaustedTicks = 2*1000;
  7714. player->sendMagicEffect(player->pos, NM_ME_MAGIC_BLOOD);
  7715. }
  7716. }
  7717. #endif //HUCZU_FIX
  7718. */
  7719.  
  7720. else if (text.substr(0,7) == "exiva \"" &&
  7721. (!g_config.LEARN_SPELLS || player->knowsSpell("exiva")))
  7722. {
  7723. std::string name = text.substr(7);
  7724. Creature *c = getCreatureByName(name);
  7725. if (dynamic_cast<Player*>(c))
  7726. {
  7727. if(player->mana >= 20)
  7728. {
  7729. player->mana -= 20;
  7730. player->addManaSpent(20);
  7731. }
  7732. else if (player->exhaustedTicks >= 1000 && player->access < g_config.ACCESS_PROTECT)
  7733. {
  7734. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7735. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  7736. }
  7737. else
  7738. {
  7739. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7740. player->sendTextMessage(MSG_SMALLINFO, "Not enough mana.");
  7741. return;
  7742. }
  7743.  
  7744.  
  7745. int32_t x = c->pos.x - player->pos.x;
  7746. int32_t y = c->pos.y - player->pos.y;
  7747. int32_t z = c->pos.z - player->pos.z;
  7748. std::stringstream position;
  7749. position << name;
  7750.  
  7751. if(c->access < 3) {
  7752. if((x > 96 && y > 48) || (x > 48 && y > 94) || (x > 74 && y > 74))
  7753. position << " is very far to the south-east.";
  7754. else if((x > 96 && y < -48) || (x > 48 && y < -96) || (x > 74 && y < -74))
  7755. position << " is very far to the north-east.";
  7756. else if((x < -96 && y > 48) || (x < -48 && y > 96) || (x < -74 && y > 74))
  7757. position << " is very far to the south-west.";
  7758. else if((x < -96 && y < -48) || (x < -48 && y < -96) || (x < -74 && y < -74))
  7759. position << " is very far to the north-west.";
  7760.  
  7761. else if((x > 48 && y > 24) || (x > 24 && y > 48) || (x > 36 && y > 36))
  7762. position << " is far to the south-east.";
  7763. else if((x > 48 && y < -24) || (x > 24 && y < -48) || (x > 36 && y < -36))
  7764. position << " is far to the north-east.";
  7765. else if((x < -48 && y > 24) || (x < -24 && y > 48) || (x < -36 && y > 36))
  7766. position << " is far to the south-west.";
  7767. else if((x < -48 && y < -24) || (x < -24 && y < -48) || (x < -36 && y < -36))
  7768. position << " is far to the north-west.";
  7769.  
  7770. else if((x > 6 && y > 12 && z > 0) || (x > 12 && y > 6 && z > 0) || (x > 9 && y > 9 && z > 0))
  7771. position << " is on a lower lvl to the south-east.";
  7772. else if((x > 6 && y < -12 && z > 0) || (x > 12 && y < -6 && z > 0) || (x > 9 && y < -9 && z > 0))
  7773. position << " is on a lower lvl to the north-east.";
  7774. else if((x < -6 && y > 12 && z > 0) || (x < -12 && y > 6 && z > 0) || (x < -9 && y > 9 && z > 0))
  7775. position << " is on a lower lvl to the south-west.";
  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 north-west.";
  7778.  
  7779. else if((x > 6 && y > 12 && z < 0) || (x > 12 && y > 6 && z < 0) || (x > 9 && y > 9 && z < 0))
  7780. position << " is on a higher lvl to the south-east.";
  7781. else if((x > 6 && y < -12 && z < 0) || (x > 12 && y < -6 && z < 0) || (x > 9 && y < -9 && z < 0))
  7782. position << " is on a higher lvl to the north-east.";
  7783. else if((x < -6 && y > 12 && z < 0) || (x < -12 && y > 6 && z < 0) || (x < -9 && y > 9 && z < 0))
  7784. position << " is on a higher lvl to the south-west.";
  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 north-west.";
  7787.  
  7788. else if((x > 6 && y > 12 && z == 0) || (x > 12 && y > 6 && z == 0) || (x > 9 && y > 9 && z == 0))
  7789. position << " is to the south-east.";
  7790. else if((x > 6 && y < -12 && z == 0) || (x > 12 && y < -6 && z == 0) || (x > 9 && y < -9 && z == 0))
  7791. position << " is to the north-east.";
  7792. else if((x < -6 && y > 12 && z == 0) || (x < -12 && y > 6 && z == 0) || (x < -9 && y > 9 && z == 0))
  7793. position << " is to the south-west.";
  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 north-west.";
  7796.  
  7797. else if(x > 74)
  7798. position << " is very far to the east.";
  7799. else if(x < -74)
  7800. position << " is very far to the west.";
  7801. else if(y > 74)
  7802. position << " is very far to the south.";
  7803. else if(y < -74)
  7804. position << " is very far to the north.";
  7805.  
  7806. else if(x > 36)
  7807. position << " is far to the east.";
  7808. else if(x < -36)
  7809. position << " is far to the west.";
  7810. else if(y > 36)
  7811. position << " is far to the south.";
  7812. else if(y < -36)
  7813. position << " is far to the north.";
  7814.  
  7815. else if(x > 3 && z < 0)
  7816. position << " is on a higher lvl to the east.";
  7817. else if(x < -3 && z < 0)
  7818. position << " is on a higher lvl to the west.";
  7819. else if(y > 3 && z < 0)
  7820. position << " is on a higher lvl to the south.";
  7821. else if(y < -3 && z < 0)
  7822. position << " is on a higher lvl to the north.";
  7823.  
  7824. else if(x > 3 && z > 0)
  7825. position << " is on a lower lvl to the east.";
  7826. else if(x < -3 && z > 0)
  7827. position << " is on a lower lvl to the west.";
  7828. else if(y > 3 && z > 0)
  7829. position << " is on a lower lvl to the south.";
  7830. else if(y < -3 && z > 0)
  7831. position << " is on a lower lvl to the north.";
  7832.  
  7833. else if(x > 3 && z == 0)
  7834. position << " is to the east.";
  7835. else if(x < -3 && z == 0)
  7836. position << " is to the west.";
  7837. else if(y > 3 && z == 0)
  7838. position << " is to the south.";
  7839. else if(y < -3 && z == 0)
  7840. position << " is to the north.";
  7841.  
  7842. else if(x < 4 && y < 4 && z > 0)
  7843. position << " is below you.";
  7844. else if(x < 4 && y < 4 && z < 0)
  7845. position << " is above you.";
  7846. else
  7847. position << " is just beside you.";
  7848.  
  7849. player->sendTextMessage(MSG_INFO, position.str().c_str());
  7850. player->sendMagicEffect(player->pos, NM_ME_MAGIC_ENERGIE);
  7851. }else{
  7852. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7853. player->sendTextMessage(MSG_SMALLINFO, "Srry, you cant exiva GM's");
  7854. }
  7855. }else
  7856. player->sendTextMessage(MSG_SMALLINFO, "This player is not online.");
  7857. }
  7858.  
  7859. else if (text == "exani tera" &&
  7860. (!g_config.LEARN_SPELLS || player->knowsSpell("exani tera")))
  7861. {
  7862. const int32_t REQ_MANA = 20;
  7863. Tile* tile = getTile(player->pos);
  7864.  
  7865. if (!(tile && (tile->ground->getID() == ITEM_ROPE_SPOT1 || tile->ground->getID() == ITEM_ROPE_SPOT2)))
  7866. {
  7867. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7868. player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7869. }
  7870. else if (player->mana < REQ_MANA)
  7871. {
  7872. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7873. player->sendTextMessage(MSG_SMALLINFO, "Not enough mana.");
  7874. }
  7875. else if (player->maglevel < 0)
  7876. {
  7877. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7878. player->sendTextMessage(MSG_SMALLINFO, "You don't have the required magic level.");
  7879. }
  7880. else if (player->exhaustedTicks >= 1000 && player->access < g_config.ACCESS_PROTECT)
  7881. {
  7882. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7883. player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  7884. }
  7885. else
  7886. {
  7887. teleport(player, Position(player->pos.x, player->pos.y+1, player->pos.z-1));
  7888. player->sendMagicEffect(player->pos, NM_ME_ENERGY_AREA);
  7889.  
  7890. if (player->access < g_config.ACCESS_PROTECT)
  7891. {
  7892. player->mana -= REQ_MANA;
  7893. player->addManaSpent(REQ_MANA);
  7894. }
  7895. }
  7896. }
  7897. }
  7898.  
  7899. #ifdef TR_SUMMONS
  7900. bool Game::placeSummon(Player* p, const std::string& name)
  7901. {
  7902. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::placeSummon()");
  7903. Monster* monster = Monster::createMonster(name, this);
  7904.  
  7905. if(!monster)
  7906. return false;
  7907.  
  7908. Position pos = p->pos;
  7909. switch (p->direction)
  7910. {
  7911. case NORTH: pos.y--; break;
  7912. case SOUTH: pos.y++; break;
  7913. case EAST: pos.x++; break;
  7914. case WEST: pos.x--; break;
  7915. }
  7916.  
  7917. Tile* tile = getTile(pos);
  7918. #ifdef YUR_PVP_ARENA
  7919. if (!tile || tile->isPz() || tile->isPvpArena() || !placeCreature(pos, monster))
  7920. #else
  7921. if (!tile || tile->isPz() || !placeCreature(pos, monster))
  7922. #endif //YUR_PVP_ARENA
  7923. {
  7924. delete monster;
  7925. return false;
  7926. }
  7927. else
  7928. {
  7929. p->addSummon(monster);
  7930. return true;
  7931. }
  7932. }
  7933. #endif //TR_SUMMONS
  7934.  
  7935.  
  7936. #ifdef TRS_GM_INVISIBLE
  7937. void Game::creatureBroadcastTileUpdated(const Position& pos)
  7938. {
  7939. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureBroadcastTileUpdated()");
  7940. SpectatorVec list;
  7941. SpectatorVec::iterator it;
  7942. getSpectators(Range(pos, true), list);
  7943.  
  7944. //players
  7945. for(it = list.begin(); it != list.end(); ++it) {
  7946. if(dynamic_cast<Player*>(*it)) {
  7947. (*it)->onTileUpdated(pos);
  7948. }
  7949. }
  7950.  
  7951. //none-players
  7952. for(it = list.begin(); it != list.end(); ++it) {
  7953. if(!dynamic_cast<Player*>(*it)) {
  7954. (*it)->onTileUpdated(pos);
  7955. }
  7956. }
  7957. }
  7958. #endif //TRS_GM_INVISIBLE
  7959.  
  7960.  
  7961. #ifdef HUCZU_SKULLS
  7962. void Game::Skull(Player* player)
  7963. {
  7964. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::Skull()");
  7965. if (player)
  7966. {
  7967. SpectatorVec list;
  7968. SpectatorVec::iterator it;
  7969. getSpectators(Range(player->pos, true), list);
  7970.  
  7971. for(it = list.begin(); it != list.end(); ++it)
  7972. {
  7973. Player* spectator = dynamic_cast<Player*>(*it);
  7974. if(spectator)
  7975. if(player->skullType == SKULL_NONE ||
  7976. player->skullType == SKULL_WHITE ||
  7977. player->skullType == SKULL_RED ||
  7978. player->skullType == SKULL_YELLOW && player->isYellowTo(spectator))
  7979. spectator->onSkull(player);
  7980. }
  7981. }
  7982. }
  7983.  
  7984. void Game::onPvP(Creature* creature, Creature* attacked, bool murder)
  7985. {
  7986. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::onPvP()");
  7987. if (creature && creature->getMaster())
  7988. creature = creature->getMaster(); // pk-ing with summons fix
  7989.  
  7990. Player* player = dynamic_cast<Player*>(creature);
  7991. Player* attackedPlayer = dynamic_cast<Player*>(attacked);
  7992.  
  7993. if (player == attackedPlayer)
  7994. return;
  7995. if(!player || !attackedPlayer)
  7996. return;
  7997. if (player && player->access >= g_config.ACCESS_PROTECT || attackedPlayer && attackedPlayer->access >= g_config.ACCESS_PROTECT)
  7998. return;
  7999. if (player->party != 0 && attackedPlayer->party != 0 && player->party == attackedPlayer->party)
  8000. return;
  8001.  
  8002. Tile *p1 = map->getTile(player->pos), *p2 = map->getTile(attackedPlayer->pos);
  8003. if (p1->isPvpArena() && p2->isPvpArena()){
  8004. player->pzLocked = false;
  8005. attackedPlayer->pzLocked = false;
  8006. return;
  8007. }
  8008.  
  8009.  
  8010. player->pzLocked = true;
  8011.  
  8012. if (!murder)
  8013. {
  8014. if(!player->hasAttacked(attackedPlayer)){
  8015. player->attackedPlayers.push_back(attackedPlayer);
  8016. }
  8017.  
  8018. if (attackedPlayer->skullType == SKULL_NONE || attackedPlayer->skullType == SKULL_YELLOW && !attackedPlayer->isYellowTo(player))
  8019. {
  8020. if (player->skullType != SKULL_RED && player->skullType != SKULL_WHITE)
  8021. {
  8022. player->skullType = SKULL_WHITE;
  8023. Skull(player);
  8024. }
  8025. }
  8026.  
  8027. else if(attackedPlayer->skullType == SKULL_WHITE || attackedPlayer->skullType == SKULL_RED)
  8028. {
  8029. if(player->skullType == SKULL_NONE && !player->isYellowTo(attackedPlayer))//si no tiene skull y no es yellow, tenemos que ponerle yellow.
  8030. {
  8031. if(!attackedPlayer->hasAttacked(player))
  8032. {
  8033. player->skullType = SKULL_YELLOW;
  8034. attackedPlayer->hasAsYellow.push_back(player);
  8035. attackedPlayer->onSkull(player);
  8036. }
  8037. }
  8038. }
  8039. if(player->inFightTicks < (int32_t)g_config.PZ_LOCKED)
  8040. player->inFightTicks = (int32_t)g_config.PZ_LOCKED;
  8041. if(player->skullTicks < (int32_t)g_config.PZ_LOCKED)
  8042. player->skullTicks = (int32_t)g_config.PZ_LOCKED;
  8043.  
  8044. }
  8045. else // murder
  8046. {
  8047. 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.
  8048. {
  8049. player->skullKills++;
  8050. std::string justice(std::string("Warning! The murder of ") + attackedPlayer->getName() + " was not justified!");
  8051. player->sendTextMessage(MSG_RED_INFO, justice.c_str());
  8052.  
  8053. if (player->skullKills >= g_config.BAN_UNJUST)
  8054. {
  8055. banPlayer(player, "Excessive unjustifed player killing", "AccountBan", "Zagan Square 2.3 2011 (Braviera)", false);
  8056. }
  8057.  
  8058. if (player->skullKills >= g_config.RED_UNJUST)
  8059. {
  8060. player->skullType = SKULL_RED;
  8061. if(player->skullTicks < g_config.RED_TIME)
  8062. player->skullTicks = g_config.RED_TIME;
  8063. if(player->inFightTicks < g_config.WHITE_TIME)
  8064. player->inFightTicks = g_config.WHITE_TIME;
  8065. Skull(player);
  8066. }
  8067. else
  8068. {
  8069. player->skullType = SKULL_WHITE;
  8070. if(player->skullTicks < g_config.WHITE_TIME)
  8071. player->skullTicks = g_config.WHITE_TIME;
  8072. if(player->inFightTicks < g_config.WHITE_TIME)
  8073. player->inFightTicks = g_config.WHITE_TIME;
  8074. Skull(player);
  8075. }
  8076. }
  8077.  
  8078. else if (attackedPlayer->skullType == SKULL_RED)//victim had red skull..(fair kill)
  8079. {
  8080. if(player->inFightTicks < g_config.WHITE_TIME)
  8081. player->inFightTicks = g_config.WHITE_TIME;//not giving him a skull.. just setting the murder time.
  8082. }
  8083.  
  8084. else if (attackedPlayer->skullType == SKULL_WHITE) //victim had white skull.. (fair kill)
  8085. {
  8086. attackedPlayer->skullType = SKULL_NONE;
  8087. attackedPlayer->skullTicks = 0;
  8088. Skull(attackedPlayer);
  8089. if(player->inFightTicks < g_config.WHITE_TIME)
  8090. player->inFightTicks = g_config.WHITE_TIME;//not giving him a skull.. just setting the murder time.
  8091. }
  8092.  
  8093. else if (attackedPlayer->skullType == SKULL_YELLOW /*&& attackedPlayer->isYellowTo(player)*/)//el que murio era yellow skull para el que lo mato.
  8094. {
  8095. attackedPlayer->skullType = SKULL_NONE;
  8096. attackedPlayer->skullTicks = 0;
  8097. attackedPlayer->inFightTicks = 0;
  8098. Skull(attackedPlayer);
  8099. if(player->inFightTicks < g_config.WHITE_TIME)
  8100. player->inFightTicks = g_config.WHITE_TIME;
  8101. }
  8102. //attackedPlayer->clearAttacked();//czyszczenie listy zaatakowanych
  8103. //player->removeFromYellowList(attackedPlayer);//usuwanie gracza z Yellow skull z listy atakowanych z ys
  8104. //attackedPlayer->removeFromYellowList(player);
  8105. }
  8106. }
  8107.  
  8108. void Game::LeaveParty(Player *player)
  8109. {
  8110. int32_t members = 0;
  8111. std::stringstream bericht1;
  8112. bericht1 << player->getName() << " has left the party";
  8113. if(player->getID() == player->party)
  8114. {
  8115. disbandParty(player->party);
  8116. return;
  8117. }
  8118. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  8119. {
  8120. if((*it).second->party == player->party)
  8121. {
  8122. members++;
  8123. if((*it).second->getID() != player->getID())
  8124. (*it).second->sendTextMessage(MSG_INFO, bericht1.str().c_str());
  8125. (*it).second->onPartyIcons(player, 0, false, true);
  8126. player->onPartyIcons((*it).second, 0, false, true);
  8127. }
  8128. }
  8129. if(members <= 2)
  8130. {
  8131. disbandParty(player->party);
  8132. return;
  8133. }
  8134. player->sendTextMessage(MSG_INFO, "You have left the party.");
  8135. player->party = 0;
  8136. }
  8137.  
  8138. void Game::disbandParty(uint32_t partyID)
  8139. {
  8140. for(AutoList<Player>::listiterator cit = Player::listPlayer.list.begin(); cit != Player::listPlayer.list.end(); ++cit)
  8141. {
  8142. if((*cit).second->party == partyID)
  8143. {
  8144. (*cit).second->party = 0;
  8145. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  8146. {
  8147. (*cit).second->onPartyIcons((*it).second, 0, false, true);
  8148. if((*it).second->skullType == SKULL_NONE ||
  8149. (*it).second->skullType == SKULL_WHITE ||
  8150. (*it).second->skullType == SKULL_RED ||
  8151. (*it).second->skullType == SKULL_YELLOW &&
  8152. (*it).second->isYellowTo((*cit).second))
  8153. (*cit).second->onSkull((*it).second);
  8154. }
  8155. (*cit).second->sendTextMessage(MSG_INFO, "Your party has been disbanded.");
  8156. }
  8157. }
  8158. }
  8159. void Game::checkSkullTime(Player* player)
  8160. {
  8161. if(player->skullType == SKULL_NONE)//just in case
  8162. return;
  8163.  
  8164. if(player->skullTicks < player->inFightTicks)
  8165. player->skullTicks = player->inFightTicks;
  8166.  
  8167. if(player->skullType != SKULL_RED && player->skullTicks > player->inFightTicks) //we don't want to do that if the player has a red skull...
  8168. player->inFightTicks = player->skullTicks;
  8169.  
  8170. }
  8171. #endif //HUCZU_SKULLS
  8172.  
  8173.  
  8174.  
  8175. #ifdef SD_BURST_ARROW
  8176. class MagicEffectAreaNoExhaustionClass: public MagicEffectAreaClass {
  8177. public:
  8178. bool causeExhaustion(bool hasTarget) const { return false; }
  8179. };
  8180.  
  8181. void Game::burstArrow(Creature* c, const Position& pos)
  8182. {
  8183. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::burstArrow()");
  8184. std::vector<unsigned char> col;
  8185. MagicEffectAreaNoExhaustionClass runeAreaSpell;
  8186.  
  8187. Player* player = dynamic_cast<Player*>(c);
  8188.  
  8189. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8190. runeAreaSpell.animationEffect = NM_ANI_BURSTARROW;
  8191. runeAreaSpell.hitEffect = NM_ME_EXPLOSION_DAMAGE;
  8192. runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8193. runeAreaSpell.animationColor = 198; //DAMAGE_FIRE;
  8194. runeAreaSpell.drawblood = true;
  8195. runeAreaSpell.offensive = true;
  8196.  
  8197. /* Area of Spell */
  8198. col.push_back(1);
  8199. col.push_back(1);
  8200. col.push_back(1);
  8201. runeAreaSpell.areaVec.push_back(col);
  8202. col.clear();
  8203. col.push_back(1);
  8204. col.push_back(1);
  8205. col.push_back(1);
  8206. runeAreaSpell.areaVec.push_back(col);
  8207. col.clear();
  8208. col.push_back(1);
  8209. col.push_back(1);
  8210. col.push_back(1);
  8211. runeAreaSpell.areaVec.push_back(col);
  8212.  
  8213. /* hard no ? */
  8214. runeAreaSpell.direction = 1;
  8215.  
  8216. if (player->vocation == VOCATION_KNIGHT) {
  8217. 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);
  8218. 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);
  8219. }
  8220.  
  8221. if (player->vocation == VOCATION_PALADIN) {
  8222. 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);
  8223. 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);
  8224. }
  8225.  
  8226. if (player->vocation == VOCATION_DRUID) {
  8227. 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);
  8228. 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);
  8229. }
  8230.  
  8231. if (player->vocation == VOCATION_SORCERER) {
  8232. 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);
  8233. 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);
  8234. }
  8235.  
  8236. creatureThrowRune(c, pos, runeAreaSpell);
  8237. }
  8238. #endif //SD_BURST_ARROW
  8239.  
  8240.  
  8241. #ifdef YUR_SHUTDOWN
  8242. void Game::sheduleShutdown(int32_t minutes)
  8243. {
  8244. if (minutes > 0)
  8245. checkShutdown(minutes);
  8246. }
  8247.  
  8248. void Game::checkShutdown(int32_t minutes)
  8249. {
  8250. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkShutdown()");
  8251. if (minutes == 0)
  8252. {
  8253. setGameState(GAME_STATE_CLOSED);
  8254. while (!Player::listPlayer.list.empty())
  8255. Player::listPlayer.list.begin()->second->kickPlayer();
  8256.  
  8257. serverSave();
  8258. std::cout << "==| shutdown..." << std::endl;
  8259. //setGameState(GAME_STATE_SHUTDOWN);
  8260. OTSYS_SLEEP(1000);
  8261. exit(1);
  8262. }
  8263. else
  8264. {
  8265. std::stringstream msg;
  8266. msg << "Server going to shutdown in " << minutes << (minutes>1? " minutes. \n Please logout." : " minute. \n Please logout.") << std::ends;
  8267.  
  8268. AutoList<Player>::listiterator it = Player::listPlayer.list.begin();
  8269. while (it != Player::listPlayer.list.end())
  8270. {
  8271. (*it).second->sendTextMessage(MSG_RED_INFO, msg.str().c_str());
  8272. ++it;
  8273. }
  8274.  
  8275. addEvent(makeTask(60000, boost::bind(&Game::checkShutdown, this, minutes - 1)));
  8276. }
  8277. }
  8278. #endif //YUR_SHUTDOWN
  8279.  
  8280.  
  8281. #ifdef YUR_CMD_EXT
  8282. void Game::setMaxPlayers(uint32_t newmax)
  8283. {
  8284. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::setMaxPlayers()");
  8285. max_players = newmax;
  8286. Status::instance()->playersmax = newmax;
  8287. }
  8288. #endif //YUR_CMD_EXT
  8289.  
  8290. long Game::cleanMap()
  8291. {
  8292. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::cleanMap()");
  8293. return map->clean();
  8294. }
  8295.  
  8296. long Game::beforeClean()
  8297. {
  8298. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it) {
  8299. it->second->sendTextMessage(MSG_RED_INFO, "1 minute to clean. Get your things from floor now!");
  8300. }
  8301. addEvent(makeTask(60000, std::mem_fun(&Game::secondsToClean)));
  8302. }
  8303. long Game::beforeCleanTrzy()
  8304. {
  8305. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it) {
  8306. it->second->sendTextMessage(MSG_RED_INFO, "Warning! Clean in 3 minutes.");
  8307. }
  8308. addEvent(makeTask(60000, std::mem_fun(&Game::beforeCleanDwa)));
  8309. }
  8310. long Game::beforeCleanDwa()
  8311. {
  8312. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it) {
  8313. it->second->sendTextMessage(MSG_RED_INFO, "Warning! Clean in 2 minutes.");
  8314. }
  8315. addEvent(makeTask(60000, std::mem_fun(&Game::beforeClean)));
  8316. }
  8317. void Game::secondsToClean()
  8318. {
  8319. autocleanMap(5);
  8320. }
  8321. void Game::autocleanMap(int32_t seconds)
  8322. {
  8323. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::autocleanMap()");
  8324. if (seconds == 0)
  8325. {
  8326. std::cout << ":: auto clean... ";
  8327. timer();
  8328. long count = cleanMap();
  8329. double sec = timer();
  8330.  
  8331. std::stringstream msg;
  8332. msg << "Clean completed. Collected " << count << (count==1? " item." : " items.") << std::ends;
  8333. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  8334. if(dynamic_cast<Player*>(it->second))
  8335. (*it).second->sendTextMessage(MSG_RED_INFO, msg.str().c_str());
  8336. }
  8337.  
  8338. std::cout << "ok (" << timer() << "s)" << std::endl;
  8339. addEvent(makeTask((g_config.getGlobalNumber("autoclean", 2))*60000, std::mem_fun(&Game::beforeCleanTrzy)));
  8340. }
  8341. else
  8342. {
  8343. std::stringstream msg;
  8344. msg << "Clean in " << seconds << std::ends;
  8345.  
  8346. AutoList<Player>::listiterator it = Player::listPlayer.list.begin();
  8347. while (it != Player::listPlayer.list.end())
  8348. {
  8349. (*it).second->sendTextMessage(MSG_RED_INFO, msg.str().c_str());
  8350. ++it;
  8351. }
  8352.  
  8353. addEvent(makeTask(8000, boost::bind(&Game::autocleanMap, this, seconds - 1)));
  8354. }
  8355. }
  8356.  
  8357.  
  8358. #ifdef CVS_DAY_CYCLE
  8359. void Game::creatureChangeLight(Player* player, int32_t time, unsigned char lightlevel, unsigned char lightcolor)
  8360. {
  8361. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureChangeLight()");
  8362.  
  8363. player->setLightLevel(lightlevel, lightcolor);
  8364. SpectatorVec list;
  8365. getSpectators(Range(player->pos), list);
  8366.  
  8367. for (SpectatorVec::iterator iter = list.begin(); iter != list.end(); ++iter)
  8368. {
  8369. Player* spectator = dynamic_cast<Player*>(*iter);
  8370. if (spectator)
  8371. spectator->sendPlayerLightLevel(player);
  8372. }
  8373. }
  8374.  
  8375. void Game::checkLight(int32_t t)
  8376. {
  8377. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkLight()");
  8378. addEvent(makeTask(10000, boost::bind(&Game::checkLight, this, 10000)));
  8379.  
  8380. light_hour = light_hour + light_hour_delta;
  8381. if(light_hour > 1440)
  8382. light_hour = light_hour - 1440;
  8383.  
  8384. if(std::abs(light_hour - SUNRISE) < 2*light_hour_delta){
  8385. light_state = LIGHT_STATE_SUNRISE;
  8386. }
  8387. else if(std::abs(light_hour - SUNSET) < 2*light_hour_delta){
  8388. light_state = LIGHT_STATE_SUNSET;
  8389. }
  8390.  
  8391. int32_t newlightlevel = lightlevel;
  8392. switch(light_state){
  8393. case LIGHT_STATE_SUNRISE:
  8394. newlightlevel += (LIGHT_LEVEL_DAY - LIGHT_LEVEL_NIGHT)/30;
  8395. break;
  8396. case LIGHT_STATE_SUNSET:
  8397. newlightlevel -= (LIGHT_LEVEL_DAY - LIGHT_LEVEL_NIGHT)/30;
  8398. break;
  8399. }
  8400.  
  8401. if(newlightlevel <= LIGHT_LEVEL_NIGHT){
  8402. lightlevel = LIGHT_LEVEL_NIGHT;
  8403. light_state = LIGHT_STATE_NIGHT;
  8404. }
  8405. else if(newlightlevel >= LIGHT_LEVEL_DAY){
  8406. lightlevel = LIGHT_LEVEL_DAY;
  8407. light_state = LIGHT_STATE_DAY;
  8408. }
  8409. else{
  8410. lightlevel = newlightlevel;
  8411. }
  8412.  
  8413.  
  8414. // status, ten kod i tak jest brzydki
  8415. uint64_t time = OTSYS_TIME();
  8416. ofstream file;
  8417. file.open ("status");
  8418. file << time << " " << (time - Status::instance()->start)/1000 << " " << Status::instance()->playersonline << " " << Status::instance()->playersmax;
  8419. file.close();
  8420.  
  8421. file.open("online");
  8422. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  8423. std::string txt = (*it).second->getName();
  8424. file << (*it).second->getName() << ";" << (*it).second->getLevel() << "\n";
  8425. }
  8426. file.close();
  8427.  
  8428.  
  8429. }
  8430.  
  8431. unsigned char Game::getLightLevel(){
  8432. return lightlevel;
  8433. }
  8434. #endif //CVS_DAY_CYCLE
  8435.  
  8436.  
  8437. #ifdef WANDS_JIDDO
  8438. void Game::useWand(Creature *creature, Creature *attackedCreature, int32_t wandid) {
  8439.  
  8440. Player *player = dynamic_cast<Player*>(creature);
  8441. if(!player) return;
  8442.  
  8443. if((wandid == 5318 && (player->vocation == VOCATION_DRUID) && player->mana >= 15 && player->getLevel() >= 65)) { //Quagmire rod
  8444. int32_t dist = 6;
  8445. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8446. std::vector<unsigned char> col;
  8447. MagicEffectAreaClass runeAreaSpell;
  8448. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8449. runeAreaSpell.animationEffect = NM_ANI_SNOWBALL;
  8450. runeAreaSpell.hitEffect = NM_ME_LOOSE_ENERGY;
  8451. runeAreaSpell.areaEffect = NM_ME_DRAW_BLOOD;
  8452. runeAreaSpell.animationColor = 0x47;
  8453. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8454. col.push_back(0);
  8455. col.push_back(0);
  8456. col.push_back(0);
  8457. runeAreaSpell.areaVec.push_back(col);
  8458. col.clear();
  8459. col.push_back(0);
  8460. col.push_back(1);
  8461. col.push_back(0);
  8462. runeAreaSpell.areaVec.push_back(col);
  8463. col.clear();
  8464. col.push_back(0);
  8465. col.push_back(0);
  8466. col.push_back(0);
  8467. runeAreaSpell.areaVec.push_back(col);
  8468. col.clear();
  8469. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 70; runeAreaSpell.maxDamage = 150;
  8470. long tempExhaust = player->exhaustedTicks;
  8471. player->exhaustedTicks = 0;
  8472. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8473. player->exhaustedTicks = tempExhaust;
  8474. int32_t mana = 15;
  8475. player->addManaSpent(mana);
  8476. player->mana -= mana;
  8477. return;
  8478. }
  8479.  
  8480.  
  8481. if((wandid == 5319 && (player->vocation == VOCATION_SORCERER) && player->mana >= 15 && player->getLevel() >= 65)) { //Wand of cosmic energy
  8482. int32_t dist = 6;
  8483. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8484. std::vector<unsigned char> col;
  8485. MagicEffectAreaClass runeAreaSpell;
  8486. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8487. runeAreaSpell.animationEffect = NM_ANI_LARGEROCK;
  8488. runeAreaSpell.hitEffect = NM_ME_SOUND_WHITE;
  8489. runeAreaSpell.areaEffect = NM_ME_SOUND_WHITE;
  8490. runeAreaSpell.animationColor = 0xAC;
  8491. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8492. col.push_back(0);
  8493. col.push_back(0);
  8494. col.push_back(0);
  8495. runeAreaSpell.areaVec.push_back(col);
  8496. col.clear();
  8497. col.push_back(0);
  8498. col.push_back(1);
  8499. col.push_back(0);
  8500. runeAreaSpell.areaVec.push_back(col);
  8501. col.clear();
  8502. col.push_back(0);
  8503. col.push_back(0);
  8504. col.push_back(0);
  8505. runeAreaSpell.areaVec.push_back(col);
  8506. col.clear();
  8507. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 70; runeAreaSpell.maxDamage = 150;
  8508. long tempExhaust = player->exhaustedTicks;
  8509. player->exhaustedTicks = 0;
  8510. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8511. player->exhaustedTicks = tempExhaust;
  8512. int32_t mana = 15;
  8513. player->addManaSpent(mana);
  8514. player->mana -= mana;
  8515. return;
  8516. }
  8517.  
  8518. //SCEPTRE OF THE LOST SOULS
  8519. if((wandid == 5326 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_DRUID) && player->mana >= 50 && player->getLevel() >= 300)) {
  8520. int32_t dist = 4;
  8521. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8522. std::vector<unsigned char> col;
  8523. MagicEffectAreaClass runeAreaSpell;
  8524. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8525. runeAreaSpell.animationEffect = NM_ANI_ENERGY2;
  8526. runeAreaSpell.hitEffect = NM_ME_ENERGY_AREA;
  8527. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8528. runeAreaSpell.animationColor = 0x65;
  8529. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8530. col.push_back(0);
  8531. col.push_back(0);
  8532. col.push_back(0);
  8533. runeAreaSpell.areaVec.push_back(col);
  8534. col.clear();
  8535. col.push_back(0);
  8536. col.push_back(1);
  8537. col.push_back(0);
  8538. runeAreaSpell.areaVec.push_back(col);
  8539. col.clear();
  8540. col.push_back(0);
  8541. col.push_back(0);
  8542. col.push_back(0);
  8543. runeAreaSpell.areaVec.push_back(col);
  8544. col.clear();
  8545. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 350; runeAreaSpell.maxDamage = 450;
  8546. long tempExhaust = player->exhaustedTicks;
  8547. player->exhaustedTicks = 0;
  8548. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8549. player->exhaustedTicks = tempExhaust;
  8550. int32_t mana = 50;
  8551. player->addManaSpent(mana);
  8552. player->mana -= mana;
  8553. return;
  8554. }
  8555.  
  8556. //NATURE WAND
  8557. if((wandid == 2544 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_DRUID) && player->mana >= 35 && player->getLevel() >= 200)) {
  8558. int32_t dist = 5;
  8559. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8560. std::vector<unsigned char> col;
  8561. MagicEffectAreaClass runeAreaSpell;
  8562. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8563. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8564. runeAreaSpell.hitEffect = 20;
  8565. runeAreaSpell.areaEffect = 20;
  8566. runeAreaSpell.animationColor = 0x60;
  8567. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8568. col.push_back(0);
  8569. col.push_back(0);
  8570. col.push_back(0);
  8571. runeAreaSpell.areaVec.push_back(col);
  8572. col.clear();
  8573. col.push_back(0);
  8574. col.push_back(1);
  8575. col.push_back(0);
  8576. runeAreaSpell.areaVec.push_back(col);
  8577. col.clear();
  8578. col.push_back(0);
  8579. col.push_back(0);
  8580. col.push_back(0);
  8581. runeAreaSpell.areaVec.push_back(col);
  8582. col.clear();
  8583. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 200; runeAreaSpell.maxDamage = 350;
  8584. long tempExhaust = player->exhaustedTicks;
  8585. player->exhaustedTicks = 0;
  8586. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8587. player->exhaustedTicks = tempExhaust;
  8588. int32_t mana = 35;
  8589. player->addManaSpent(mana);
  8590. player->mana -= mana;
  8591. return;
  8592. }
  8593.  
  8594. //SPRITE WAND
  8595. if((wandid == 2453 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_DRUID) && player->mana >= 25 && player->getLevel() >= 150)) {
  8596. int32_t dist = 5;
  8597. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8598. std::vector<unsigned char> col;
  8599. MagicEffectAreaClass runeAreaSpell;
  8600. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8601. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8602. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8603. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8604. runeAreaSpell.animationColor = 0x11;
  8605. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8606. col.push_back(0);
  8607. col.push_back(0);
  8608. col.push_back(0);
  8609. runeAreaSpell.areaVec.push_back(col);
  8610. col.clear();
  8611. col.push_back(0);
  8612. col.push_back(1);
  8613. col.push_back(0);
  8614. runeAreaSpell.areaVec.push_back(col);
  8615. col.clear();
  8616. col.push_back(0);
  8617. col.push_back(0);
  8618. col.push_back(0);
  8619. runeAreaSpell.areaVec.push_back(col);
  8620. col.clear();
  8621. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 150; runeAreaSpell.maxDamage = 250;
  8622. long tempExhaust = player->exhaustedTicks;
  8623. player->exhaustedTicks = 0;
  8624. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8625. player->exhaustedTicks = tempExhaust;
  8626. int32_t mana = 25;
  8627. player->addManaSpent(mana);
  8628. player->mana -= mana;
  8629. return;
  8630. }
  8631.  
  8632.  
  8633. if((wandid == 2181 && (player->vocation == VOCATION_DRUID) && player->mana >= 8 && player->getLevel() >= 26)) { //Quagmire rod
  8634. int32_t dist = 2;
  8635. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8636. std::vector<unsigned char> col;
  8637. MagicEffectAreaClass runeAreaSpell;
  8638. runeAreaSpell.attackType = ATTACK_POISON;
  8639. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8640. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  8641. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  8642. runeAreaSpell.animationColor = 0x60;
  8643. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8644. col.push_back(0);
  8645. col.push_back(0);
  8646. col.push_back(0);
  8647. runeAreaSpell.areaVec.push_back(col);
  8648. col.clear();
  8649. col.push_back(0);
  8650. col.push_back(1);
  8651. col.push_back(0);
  8652. runeAreaSpell.areaVec.push_back(col);
  8653. col.clear();
  8654. col.push_back(0);
  8655. col.push_back(0);
  8656. col.push_back(0);
  8657. runeAreaSpell.areaVec.push_back(col);
  8658. col.clear();
  8659. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 40; runeAreaSpell.maxDamage = 50;
  8660. long tempExhaust = player->exhaustedTicks;
  8661. player->exhaustedTicks = 0;
  8662. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8663. player->exhaustedTicks = tempExhaust;
  8664. int32_t mana = 8;
  8665. player->addManaSpent(mana);
  8666. player->mana -= mana;
  8667. return;
  8668. }
  8669.  
  8670. if((wandid == 2182 && (player->vocation == VOCATION_DRUID) && player->mana >= 2 && player->getLevel() >= 7)) { //Snakebite rod
  8671. int32_t dist = 4;
  8672. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8673. std::vector<unsigned char> col;
  8674. MagicEffectAreaClass runeAreaSpell;
  8675. runeAreaSpell.attackType = ATTACK_POISON;
  8676. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8677. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  8678. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  8679. runeAreaSpell.animationColor = 0x60;
  8680. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8681. col.push_back(0);
  8682. col.push_back(0);
  8683. col.push_back(0);
  8684. runeAreaSpell.areaVec.push_back(col);
  8685. col.clear();
  8686. col.push_back(0);
  8687. col.push_back(1);
  8688. col.push_back(0);
  8689. runeAreaSpell.areaVec.push_back(col);
  8690. col.clear();
  8691. col.push_back(0);
  8692. col.push_back(0);
  8693. col.push_back(0);
  8694. runeAreaSpell.areaVec.push_back(col);
  8695. col.clear();
  8696. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 8; runeAreaSpell.maxDamage = 18;
  8697. long tempExhaust = player->exhaustedTicks;
  8698. player->exhaustedTicks = 0;
  8699. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8700. player->exhaustedTicks = tempExhaust;
  8701. int32_t mana = 2;
  8702. player->addManaSpent(mana);
  8703. player->mana -= mana;
  8704. return;
  8705. }
  8706.  
  8707.  
  8708.  
  8709. if((wandid == 2183 && (player->vocation == VOCATION_DRUID) && player->mana >= 13 && player->getLevel() >= 33)) { //Tempest rod
  8710. int32_t dist = 2;
  8711. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8712. std::vector<unsigned char> col;
  8713. MagicEffectAreaClass runeAreaSpell;
  8714. runeAreaSpell.attackType = ATTACK_ENERGY;
  8715. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8716. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8717. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8718. runeAreaSpell.animationColor = 0x11;
  8719. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8720. col.push_back(0);
  8721. col.push_back(0);
  8722. col.push_back(0);
  8723. runeAreaSpell.areaVec.push_back(col);
  8724. col.clear();
  8725. col.push_back(0);
  8726. col.push_back(1);
  8727. col.push_back(0);
  8728. runeAreaSpell.areaVec.push_back(col);
  8729. col.clear();
  8730. col.push_back(0);
  8731. col.push_back(0);
  8732. col.push_back(0);
  8733. runeAreaSpell.areaVec.push_back(col);
  8734. col.clear();
  8735. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 60; runeAreaSpell.maxDamage = 70;
  8736. long tempExhaust = player->exhaustedTicks;
  8737. player->exhaustedTicks = 0;
  8738. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8739. player->exhaustedTicks = tempExhaust;
  8740. int32_t mana = 13;
  8741. player->addManaSpent(mana);
  8742. player->mana -= mana;
  8743. return;
  8744. }
  8745.  
  8746.  
  8747. if((wandid == 2185 && (player->vocation == VOCATION_DRUID) && player->mana >= 5 && player->getLevel() >= 19)) { //Volcanic rod
  8748. int32_t dist = 2;
  8749. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8750. std::vector<unsigned char> col;
  8751. MagicEffectAreaClass runeAreaSpell;
  8752. runeAreaSpell.attackType = ATTACK_FIRE;
  8753. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  8754. runeAreaSpell.hitEffect = NM_ME_FIRE_AREA;
  8755. runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8756. runeAreaSpell.animationColor = 0xC7;
  8757. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8758. col.push_back(0);
  8759. col.push_back(0);
  8760. col.push_back(0);
  8761. runeAreaSpell.areaVec.push_back(col);
  8762. col.clear();
  8763. col.push_back(0);
  8764. col.push_back(1);
  8765. col.push_back(0);
  8766. runeAreaSpell.areaVec.push_back(col);
  8767. col.clear();
  8768. col.push_back(0);
  8769. col.push_back(0);
  8770. col.push_back(0);
  8771. runeAreaSpell.areaVec.push_back(col);
  8772. col.clear();
  8773. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 25; runeAreaSpell.maxDamage = 35;
  8774. long tempExhaust = player->exhaustedTicks;
  8775. player->exhaustedTicks = 0;
  8776. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8777. player->exhaustedTicks = tempExhaust;
  8778. int32_t mana = 5;
  8779. player->addManaSpent(mana);
  8780. player->mana -= mana;
  8781. return;
  8782. }
  8783.  
  8784.  
  8785. if((wandid == 2186 && (player->vocation == VOCATION_DRUID) && player->mana >= 3 && player->getLevel() >= 13)) { //Moonlight rod
  8786. int32_t dist = 3;
  8787. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8788. std::vector<unsigned char> col;
  8789. MagicEffectAreaClass runeAreaSpell;
  8790. runeAreaSpell.attackType = ATTACK_ENERGY;
  8791. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8792. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8793. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8794. runeAreaSpell.animationColor = 0x47;
  8795. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8796. col.push_back(0);
  8797. col.push_back(0);
  8798. col.push_back(0);
  8799. runeAreaSpell.areaVec.push_back(col);
  8800. col.clear();
  8801. col.push_back(0);
  8802. col.push_back(1);
  8803. col.push_back(0);
  8804. runeAreaSpell.areaVec.push_back(col);
  8805. col.clear();
  8806. col.push_back(0);
  8807. col.push_back(0);
  8808. col.push_back(0);
  8809. runeAreaSpell.areaVec.push_back(col);
  8810. col.clear();
  8811. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 14; runeAreaSpell.maxDamage = 24;
  8812. long tempExhaust = player->exhaustedTicks;
  8813. player->exhaustedTicks = 0;
  8814. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8815. player->exhaustedTicks = tempExhaust;
  8816. int32_t mana = 3;
  8817. player->addManaSpent(mana);
  8818. player->mana -= mana;
  8819. return;
  8820. }
  8821.  
  8822.  
  8823. if((wandid == 2187 && (player->vocation == VOCATION_SORCERER) && player->mana >= 13 && player->getLevel() >= 33)) { //Wand of inferno
  8824. int32_t dist = 2;
  8825. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8826. std::vector<unsigned char> col;
  8827. MagicEffectAreaClass runeAreaSpell;
  8828. runeAreaSpell.attackType = ATTACK_FIRE;
  8829. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  8830. runeAreaSpell.hitEffect = NM_ME_FIRE_AREA;
  8831. runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8832. runeAreaSpell.animationColor = 0xC7;
  8833. runeAreaSpell.drawblood = true;
  8834. runeAreaSpell.offensive = true;
  8835. col.push_back(0);
  8836. col.push_back(0);
  8837. col.push_back(0);
  8838. runeAreaSpell.areaVec.push_back(col);
  8839. col.clear();
  8840. col.push_back(0);
  8841. col.push_back(1);
  8842. col.push_back(0);
  8843. runeAreaSpell.areaVec.push_back(col);
  8844. col.clear();
  8845. col.push_back(0);
  8846. col.push_back(0);
  8847. col.push_back(0);
  8848. runeAreaSpell.areaVec.push_back(col);
  8849. col.clear();
  8850. runeAreaSpell.direction = 1;
  8851. runeAreaSpell.minDamage = 60;
  8852. runeAreaSpell.maxDamage = 70;
  8853. long tempExhaust = player->exhaustedTicks;
  8854. player->exhaustedTicks = 0;
  8855. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8856. player->exhaustedTicks = tempExhaust;
  8857. int32_t mana = 13;
  8858. player->addManaSpent(mana);
  8859. player->mana -= mana;
  8860.  
  8861. return;
  8862. }
  8863.  
  8864.  
  8865. if((wandid == 2188 && (player->vocation == VOCATION_SORCERER) && player->mana >= 5 && player->getLevel() >= 19)) { //Wand of plague
  8866. int32_t dist = 2;
  8867. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8868. std::vector<unsigned char> col;
  8869. MagicEffectAreaClass runeAreaSpell;
  8870. runeAreaSpell.attackType = ATTACK_POISON;
  8871. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8872. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  8873. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  8874. runeAreaSpell.animationColor = 0x60;
  8875. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8876. col.push_back(0);
  8877. col.push_back(0);
  8878. col.push_back(0);
  8879. runeAreaSpell.areaVec.push_back(col);
  8880. col.clear();
  8881. col.push_back(0);
  8882. col.push_back(1);
  8883. col.push_back(0);
  8884. runeAreaSpell.areaVec.push_back(col);
  8885. col.clear();
  8886. col.push_back(0);
  8887. col.push_back(0);
  8888. col.push_back(0);
  8889. runeAreaSpell.areaVec.push_back(col);
  8890. col.clear();
  8891. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 25; runeAreaSpell.maxDamage = 35;
  8892. long tempExhaust = player->exhaustedTicks;
  8893. player->exhaustedTicks = 0;
  8894. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8895. player->exhaustedTicks = tempExhaust;
  8896. int32_t mana = 5;
  8897. player->addManaSpent(mana);
  8898. player->mana -= mana;
  8899. return;
  8900. }
  8901.  
  8902.  
  8903. if((wandid == 2189 && (player->vocation == VOCATION_SORCERER) && player->mana >= 8 && player->getLevel() >= 26)) { //Wand of cosmic energy
  8904. int32_t dist = 2;
  8905. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8906. std::vector<unsigned char> col;
  8907. MagicEffectAreaClass runeAreaSpell;
  8908. runeAreaSpell.attackType = ATTACK_ENERGY;
  8909. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8910. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8911. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8912. runeAreaSpell.animationColor = 0x47;
  8913. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8914. col.push_back(0);
  8915. col.push_back(0);
  8916. col.push_back(0);
  8917. runeAreaSpell.areaVec.push_back(col);
  8918. col.clear();
  8919. col.push_back(0);
  8920. col.push_back(1);
  8921. col.push_back(0);
  8922. runeAreaSpell.areaVec.push_back(col);
  8923. col.clear();
  8924. col.push_back(0);
  8925. col.push_back(0);
  8926. col.push_back(0);
  8927. runeAreaSpell.areaVec.push_back(col);
  8928. col.clear();
  8929. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 40; runeAreaSpell.maxDamage = 50;
  8930. long tempExhaust = player->exhaustedTicks;
  8931. player->exhaustedTicks = 0;
  8932. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8933. player->exhaustedTicks = tempExhaust;
  8934. int32_t mana = 8;
  8935. player->addManaSpent(mana);
  8936. player->mana -= mana;
  8937. return;
  8938. }
  8939.  
  8940.  
  8941. if((wandid == 2190 && (player->vocation == VOCATION_SORCERER) && player->mana >= 2 && player->getLevel() >= 7)) { //Wand of vortex
  8942. int32_t dist = 3;
  8943. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8944. std::vector<unsigned char> col;
  8945. MagicEffectAreaClass runeAreaSpell;
  8946. runeAreaSpell.attackType = ATTACK_ENERGY;
  8947. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8948. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8949. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8950. runeAreaSpell.animationColor = 0x47;
  8951. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8952. col.push_back(0);
  8953. col.push_back(0);
  8954. col.push_back(0);
  8955. runeAreaSpell.areaVec.push_back(col);
  8956. col.clear();
  8957. col.push_back(0);
  8958. col.push_back(1);
  8959. col.push_back(0);
  8960. runeAreaSpell.areaVec.push_back(col);
  8961. col.clear();
  8962. col.push_back(0);
  8963. col.push_back(0);
  8964. col.push_back(0);
  8965. runeAreaSpell.areaVec.push_back(col);
  8966. col.clear();
  8967. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 8; runeAreaSpell.maxDamage = 18;
  8968. long tempExhaust = player->exhaustedTicks;
  8969. player->exhaustedTicks = 0;
  8970. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8971. player->exhaustedTicks = tempExhaust;
  8972. int32_t mana = 2;
  8973. player->addManaSpent(mana);
  8974. player->mana -= mana;
  8975. return;
  8976. }
  8977.  
  8978. if((wandid == 2191 && (player->vocation == VOCATION_SORCERER) && player->mana >= 3 && player->getLevel() >= 13)) { //Wand of dragonbreath
  8979. int32_t dist = 3;
  8980. if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8981. std::vector<unsigned char> col;
  8982. MagicEffectAreaClass runeAreaSpell;
  8983. runeAreaSpell.attackType = ATTACK_FIRE;
  8984. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  8985. runeAreaSpell.hitEffect = NM_ME_FIRE_AREA;
  8986. runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8987. runeAreaSpell.animationColor = 0xC7;
  8988. runeAreaSpell.drawblood = true; runeAreaSpell.offensive = true;
  8989. col.push_back(0);
  8990. col.push_back(0);
  8991. col.push_back(0);
  8992. runeAreaSpell.areaVec.push_back(col);
  8993. col.clear();
  8994. col.push_back(0);
  8995. col.push_back(1);
  8996. col.push_back(0);
  8997. runeAreaSpell.areaVec.push_back(col);
  8998. col.clear();
  8999. col.push_back(0);
  9000. col.push_back(0);
  9001. col.push_back(0);
  9002. runeAreaSpell.areaVec.push_back(col);
  9003. col.clear();
  9004. runeAreaSpell.direction = 1; runeAreaSpell.minDamage = 14; runeAreaSpell.maxDamage = 24;
  9005. long tempExhaust = player->exhaustedTicks;
  9006. player->exhaustedTicks = 0;
  9007. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  9008. player->exhaustedTicks = tempExhaust;
  9009. int32_t mana = 3;
  9010. player->addManaSpent(mana);
  9011. player->mana -= mana;
  9012. return;
  9013. }
  9014. //messages by Subarmy
  9015.  
  9016.  
  9017.  
  9018. 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
  9019. player->sendTextMessage(MSG_SMALLINFO, "This wand can only be wielded by sorcerers.");
  9020. }
  9021. 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
  9022. player->sendTextMessage(MSG_SMALLINFO, "This wand can only be wielded by druids.");
  9023. }
  9024. if((wandid == 2181 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 26)) {
  9025. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 26 level to wield this wand.");
  9026. }
  9027. if((wandid == 2544 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 200)) {
  9028. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 200 level to wield this wand.");
  9029. }
  9030. if((wandid == 5326 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 300)) {
  9031. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 300 level to wield this wand.");
  9032. }
  9033. if((wandid == 2453 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 150)) {
  9034. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 150 level to wield this wand.");
  9035. }
  9036. if((wandid == 2182 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 7)) {
  9037. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 7 level to wield this wand.");
  9038. }
  9039. if((wandid == 2183 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 33)) {
  9040. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 33 to wield this wand.");
  9041. }
  9042. if((wandid == 2185 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 19)) {
  9043. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 19 level to wield this wand.");
  9044. }
  9045. if((wandid == 2186 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 13)) {
  9046. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 13 level to wield this wand.");
  9047. }
  9048. if((wandid == 5318 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 65)) {
  9049. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 65 level to wield this wand.");
  9050. }
  9051. if((wandid == 2187 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 33)) {
  9052. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 33 level to wield this wand.");
  9053. }
  9054. if((wandid == 5319 && (player->vocation == VOCATION_SORCERER || (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 == 2453 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 150)) {
  9058. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 150 level to wield this wand.");
  9059. }
  9060. if((wandid == 2544 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 200)) {
  9061. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 200 level to wield this wand.");
  9062. }
  9063. if((wandid == 5326 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 300)) {
  9064. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 300 level to wield this wand.");
  9065. }
  9066. if((wandid == 2188 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 19)) {
  9067. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 19 level to wield this wand.");
  9068. }
  9069. if((wandid == 2189 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 26)) {
  9070. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 26 level to wield this wand.");
  9071. }
  9072. if((wandid == 2190 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 7)) {
  9073. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 7 level to wield this wand.");
  9074. }
  9075.  
  9076. if((wandid == 2191 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 13)) {
  9077. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 13 level to wield this wand.");
  9078. }//end messages by Subarmy
  9079. }
  9080. #endif
  9081. // ONLINE RECORD
  9082. void Game::checkRecord()
  9083. {
  9084. if(record < getPlayersOnline()){
  9085. record = getPlayersOnline();
  9086. saveRecord();
  9087.  
  9088. std::stringstream record;
  9089. record << "New record: " << getPlayersOnline() << " players are logged in." << std::endl;
  9090. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  9091. (*it).second->sendTextMessage(MSG_ADVANCE, record.str().c_str());
  9092. }
  9093.  
  9094. }
  9095.  
  9096. bool Game::loadRecord()
  9097. {
  9098. std::string filename = g_config.getGlobalString("datadir") + "record.xml";
  9099. xmlDocPtr doc;
  9100. xmlMutexLock(xmlmutex);
  9101. doc = xmlParseFile(filename.c_str());
  9102.  
  9103. if (doc)
  9104. {
  9105. xmlNodePtr root, tmp;
  9106. root = xmlDocGetRootElement(doc);
  9107.  
  9108. if (xmlStrcmp(root->name, (const xmlChar*)"record"))
  9109. {
  9110. xmlFreeDoc(doc);
  9111. xmlMutexUnlock(xmlmutex);
  9112. return false;
  9113. }
  9114.  
  9115. record = atoi((const char*)xmlGetProp(root, (const xmlChar *)"record"));
  9116.  
  9117. xmlFreeDoc(doc);
  9118. xmlMutexUnlock(xmlmutex);
  9119. return true;
  9120. }
  9121.  
  9122. xmlMutexUnlock(xmlmutex);
  9123. return false;
  9124. }
  9125.  
  9126. bool Game::saveRecord()
  9127. {
  9128. std::string filename = g_config.getGlobalString("datadir") + "record.xml";
  9129. xmlDocPtr doc;
  9130. xmlNodePtr root, tmp;
  9131. xmlMutexLock(xmlmutex);
  9132. time_t time = std::time(NULL);
  9133.  
  9134. doc = xmlNewDoc((const xmlChar*)"1.0");
  9135. doc->children = xmlNewDocNode(doc, NULL, (const xmlChar*)"record", NULL);
  9136. root = doc->children;
  9137.  
  9138. std::stringstream sb;
  9139. sb << record; xmlSetProp(root, (const xmlChar*) "record", (const xmlChar*)sb.str().c_str()); sb.str("");
  9140. sb << time; xmlSetProp(root, (const xmlChar*) "time", (const xmlChar*)sb.str().c_str()); sb.str("");
  9141.  
  9142. xmlSaveFile(filename.c_str(), doc);
  9143. xmlFreeDoc(doc);
  9144. xmlMutexUnlock(xmlmutex);
  9145. return true;
  9146. }
  9147. // ANIMATED TEXT WHEN ADVANCE
  9148. void Game::sendAnimatedTextExt(const Position pos,int32_t aniColor,const std::string &text)
  9149. {
  9150. SpectatorVec list;
  9151. SpectatorVec::iterator it;
  9152. getSpectators(Range(pos), list);
  9153. for(it = list.begin(); it != list.end(); ++it){
  9154. Player* spec = dynamic_cast<Player*>(*it);
  9155. if(spec)
  9156. spec->sendAnimatedText(pos, aniColor, text);
  9157. }
  9158. }
  9159. // CREATUREBYPOSITION
  9160. Creature* Game::getCreatureByPosition(int32_t x, int32_t y, int32_t z)
  9161. {
  9162. for(AutoList<Creature>::listiterator it = listCreature.list.begin(); it != listCreature.list.end(); ++it){
  9163. if(it->second->pos.x == x && it->second->pos.y == y && it->second->pos.z == z)
  9164. return it->second;
  9165. }
  9166.  
  9167. return NULL;
  9168. }
  9169. // CREATE CONDITION
  9170. 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)
  9171. {
  9172. uint32_t targetID;
  9173. if(target)
  9174. targetID = target->getID();
  9175. else
  9176. targetID = 0;
  9177.  
  9178. MagicEffectTargetCreatureCondition magicCondition = MagicEffectTargetCreatureCondition(targetID);
  9179. magicCondition.animationColor = animationColor;
  9180. magicCondition.damageEffect = damageEffect;
  9181. magicCondition.hitEffect = hitEffect;
  9182. magicCondition.attackType = attackType;
  9183. magicCondition.maxDamage = maxDamage;
  9184. magicCondition.minDamage = minDamage;
  9185. magicCondition.offensive = offensive;
  9186. CreatureCondition condition = CreatureCondition(ticks, count, magicCondition);
  9187. creature->addCondition(condition, true);
  9188.  
  9189. Player *player = dynamic_cast<Player*>(creature);
  9190. if(player)
  9191. player->sendIcons();
  9192. }
  9193. // Fields loaded from map - The Chaos
  9194. void Game::doFieldDamage(Creature* creature, unsigned char animationColor, unsigned char damageEffect,
  9195. unsigned char hitEffect, attacktype_t attackType, bool offensive, int32_t damage)
  9196. {
  9197. MagicEffectClass cd;
  9198. cd.animationColor = animationColor;
  9199. cd.damageEffect = damageEffect;
  9200. cd.hitEffect = hitEffect;
  9201. cd.attackType = attackType;
  9202. cd.offensive = offensive;
  9203. Player* itsHim = dynamic_cast<Player*>(getCreatureByID(creature->getID()));
  9204. if(itsHim){ //Since that was causing damage/2 against player, here its my solution =)
  9205. cd.maxDamage = damage*2;
  9206. cd.minDamage = damage*2;
  9207. }
  9208. else{
  9209. cd.maxDamage = damage;
  9210. cd.minDamage = damage;
  9211. }
  9212. creatureMakeMagic(NULL, creature->pos, &cd);
  9213. }
  9214. void Game::updateTile(const Position& pos)
  9215. {
  9216. SpectatorVec list;
  9217. SpectatorVec::iterator i;
  9218. getSpectators(Range(pos), list);
  9219. for(i = list.begin(); i != list.end(); ++i)
  9220. (*i)->onTileUpdated(pos);
  9221. }
  9222.  
  9223. void Game::banPlayer(Player *player, std::string reason, std::string action, std::string comment, bool IPban)
  9224. {
  9225. int32_t bantime = 0;
  9226.  
  9227. if(player){
  9228.  
  9229. if(comment=="deletion")
  9230. player->deleted = 1; // make player deleted
  9231. else
  9232. bantime = atoi(comment.c_str()) * 86400; // else make players banned for "comment" days (86400 = 1 day)
  9233.  
  9234. if(player->finalwarning == 1 || player->times == 4)
  9235. player->deleted = 1; // if player was already warned let delete thy char
  9236.  
  9237. if(action=="AccountBan+FinalWarning" || player->times == 3)
  9238. player->finalwarning = 1; // if player has warned set variable
  9239.  
  9240. if(reason=="Excessive unjustifed player killing")
  9241. bantime = g_config.getGlobalNumber("pkbandays",3) * 86400; // baannnnn pekaayssss (from config.lua)
  9242.  
  9243. player->banned = 1;
  9244. player->times++;
  9245. player->comment = comment;
  9246. player->reason = reason;
  9247. player->action = action;
  9248. player->banstart = std::time(NULL);
  9249. player->banend = player->banstart + bantime;
  9250. time_t endBan = player->banend;
  9251. player->banrealtime = ctime(&endBan); // this variable stores REAL ban date in string, so you wont see 11105220952 in accmaker ;)
  9252. if(IPban){
  9253. std::pair<uint32_t, uint32_t> IpNetMask;
  9254. IpNetMask.first = player->lastip;
  9255. IpNetMask.second = 0xFFFFFFFF;
  9256. if(IpNetMask.first > 0)
  9257. bannedIPs.push_back(IpNetMask);
  9258. }
  9259. std::stringstream ban;
  9260. ban << "You just have been banned for " << reason << "!";
  9261. player->sendTextMessage(MSG_INFO, ban.str().c_str());
  9262. player->kickPlayer();
  9263. }
  9264. }
  9265.  
  9266. #ifdef REX_MUTED
  9267.  
  9268. #endif //REX_MUTED
  9269. #ifdef HUCZU_FIX
  9270. bool Game::loadCities(Player* player, std::string name)
  9271. {
  9272. xmlDocPtr doc;
  9273. std::string file = "data/miasta.xml";
  9274. doc = xmlParseFile(file.c_str());
  9275. if(doc){
  9276. xmlNodePtr root, miasto;
  9277. root = xmlDocGetRootElement(doc);
  9278. if(xmlStrcmp(root->name, (const xmlChar*)"miasta")) {
  9279. xmlFreeDoc(doc);
  9280. return -1;
  9281. }
  9282. miasto = root->children;
  9283. while(miasto){
  9284. if(strcmp((char*) miasto->name, "miasto")==0){
  9285.  
  9286. std::string nameIN = (const char*)xmlGetProp(miasto, (const xmlChar *) "nazwa");
  9287. int32_t x = atoi((const char*)xmlGetProp(miasto, (const xmlChar *) "x"));
  9288. int32_t y = atoi((const char*)xmlGetProp(miasto, (const xmlChar *) "y"));
  9289. int32_t z = atoi((const char*)xmlGetProp(miasto, (const xmlChar *) "z"));
  9290. Position pos(x,y,z);
  9291. if(nameIN == name)
  9292. teleport(player,pos);
  9293. }
  9294. miasto = miasto->next;
  9295. }
  9296. xmlFreeDoc(doc);
  9297. return 0;
  9298. }
  9299. return -1;
  9300. }
  9301. #endif //HUCZU_FIX
  9302. // RAID SYSTEM
  9303. bool Game::loadRaid(std::string name)
  9304. {
  9305. xmlDocPtr doc;
  9306. std::cout << "Executing raid named " << name << "." << std::endl;
  9307. std::string file = "data/world/raids.xml";
  9308. doc = xmlParseFile(file.c_str());
  9309. if(doc){
  9310. xmlNodePtr root, raid, command;
  9311. root = xmlDocGetRootElement(doc);
  9312. if(xmlStrcmp(root->name, (const xmlChar*)"raids")) {
  9313. xmlFreeDoc(doc);
  9314. return -1;
  9315. }
  9316. raid = root->children;
  9317. while(raid){
  9318. if(strcmp((char*) raid->name, "raid")==0){
  9319.  
  9320. std::string nameIN = (const char*)xmlGetProp(raid, (const xmlChar *) "name");
  9321. if(nameIN == name) {
  9322. std::string messageIN = (const char*)xmlGetProp(raid, (const xmlChar *) "message");
  9323. std::string brodcasterIN = (const char*)xmlGetProp(raid, (const xmlChar *) "brodcaster");
  9324.  
  9325. Creature *c = getCreatureByName(brodcasterIN);
  9326. if(c) {
  9327. creatureBroadcastMessage(c,messageIN);
  9328. } else {
  9329. std::cout << "Could not send news msg! Brodcaster does not exist" << std::endl;
  9330. }
  9331.  
  9332. if(nameIN == name) {
  9333. command = raid->children;
  9334.  
  9335. while(command) {
  9336.  
  9337. if(strcmp((char*) command->name, "monster")==0){
  9338. std::string monstername = (const char*)xmlGetProp(command, (const xmlChar *) "name");
  9339. int32_t x = atoi((const char*)xmlGetProp(command, (const xmlChar *) "x"));
  9340. int32_t y = atoi((const char*)xmlGetProp(command, (const xmlChar *) "y"));
  9341. int32_t z = atoi((const char*)xmlGetProp(command, (const xmlChar *) "z"));
  9342.  
  9343. int32_t loot = atoi((const char*)xmlGetProp(command, (const xmlChar *) "lootid")); //Not yet implemented!
  9344. int32_t chance = atoi((const char*)xmlGetProp(command, (const xmlChar *) "chance")); //Not yet implemented!
  9345. placeRaidMonster(monstername, x, y, z);
  9346. }
  9347.  
  9348. if(strcmp((char*) command->name, "area")==0){
  9349. std::string monstername = (const char*)xmlGetProp(command, (const xmlChar *) "monster");
  9350. int32_t count = atoi((const char*)xmlGetProp(command, (const xmlChar *) "count"));
  9351. int32_t xf = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posxfrom"));
  9352. int32_t yf = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posyfrom"));
  9353. int32_t zf = atoi((const char*)xmlGetProp(command, (const xmlChar *) "poszfrom"));
  9354.  
  9355. int32_t xt = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posxto"));
  9356. int32_t yt = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posyto"));
  9357. int32_t zt = atoi((const char*)xmlGetProp(command, (const xmlChar *) "poszto"));
  9358.  
  9359. int32_t i = 0;
  9360. int32_t tries = 0;
  9361. while (i<=count && tries<=(count*10)) {
  9362. int32_t x = (int32_t)((xt-xf) * (rand()/(RAND_MAX+1.0)) + xf);
  9363. int32_t y = (int32_t)((yt-yf) * (rand()/(RAND_MAX+1.0)) + yf);
  9364. int32_t z = (int32_t)((zt-zf) * (rand()/(RAND_MAX+1.0)) + zf);
  9365. Tile* t = map->getTile(x,y,z);
  9366. if(t && t->isPz() == false) {
  9367. placeRaidMonster(monstername, x, y, z);
  9368. i++;
  9369. }
  9370. tries++;
  9371. }
  9372. }
  9373. if(strcmp((char*) command->name, "message")==0){
  9374. std::string msg = (const char*)xmlGetProp(command, (const xmlChar *) "text");
  9375. std::string brodcaster = (const char*)xmlGetProp(command, (const xmlChar *) "brodcaster");
  9376. Creature *c = getCreatureByName(brodcaster);
  9377. if(c) {
  9378. creatureBroadcastMessage(c,msg);
  9379. } else {
  9380. std::cout << "Could not send news msg! Brodcaster does not exist." << std::endl;
  9381. }
  9382. }
  9383. command = command->next;
  9384. }
  9385. }
  9386. }
  9387. }
  9388. raid = raid->next;
  9389. }
  9390. xmlFreeDoc(doc);
  9391. return 0;
  9392. }
  9393. return -1;
  9394. }
  9395. bool Game::placeRaidMonster(std::string name, int32_t x, int32_t y, int32_t z)
  9396. {
  9397. Monster* monster = Monster::createMonster(name, this);
  9398. //For new CVS use the following line:
  9399. //Monster* monster = Monster::createMonster(name, this);
  9400. if(!monster){
  9401. delete monster;
  9402. return false;
  9403. }
  9404. Position pos;
  9405. pos.x = x;
  9406. pos.y = y;
  9407. pos.z = z;
  9408.  
  9409. // Place the monster
  9410. if(!placeCreature(pos, monster)) {
  9411. delete monster;
  9412. return false;
  9413. }
  9414.  
  9415. return true;
  9416. }
  9417.  
  9418. void Game::spectatorText(Position pos, unsigned char color, std::string text)
  9419. {
  9420. SpectatorVec list;
  9421. SpectatorVec::iterator it;
  9422. getSpectators(Range(pos, true), list);
  9423.  
  9424. for(it = list.begin(); it != list.end(); ++it) {
  9425. if(Player* p = dynamic_cast<Player*>(*it)) {
  9426. p->sendAnimatedText(pos, color, text);
  9427. }
  9428. }
  9429. }
  9430.  
  9431. #ifdef DT_PREMMY
  9432. bool Game::countPremmy(Player *player)
  9433. {
  9434. Account acc = IOAccount::instance()->loadAccount(player->accountNumber);
  9435. int32_t cont;
  9436. if(acc.lastsaveday == 0)
  9437. cont = 0;
  9438. else
  9439. cont = acc.lastsaveday2 - acc.lastsaveday;
  9440. //std::cout << "Last Login in Acc: " << acc.lastsaveday << " - Today: " << acc.lastsaveday2 << " - Days removed from acc: " << cont << std::endl;
  9441. if(cont < 0){
  9442. cont =+ 365; //dodajemy caly rok
  9443. }
  9444. if((acc.premDays - cont) <= 0)
  9445. {
  9446. acc.premDays = 0;
  9447. player->premmium = false;
  9448. }
  9449. else
  9450. {
  9451. acc.premDays = acc.premDays - cont;
  9452. player->premmium = true;
  9453. }
  9454. if(g_config.FREE_PREMMY)
  9455. player->premmium = true;
  9456.  
  9457. IOAccount::instance()->saveAccount(acc);
  9458.  
  9459. }
  9460.  
  9461. #endif //DT_PREMMY
  9462.  
  9463.  
  9464. #ifdef ZS_SWORDS
  9465. void Game::useSword(Creature *creature, Creature *attackedCreature, int32_t swordid)
  9466. {
  9467. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::useSword()");
  9468.  
  9469. Player *player = dynamic_cast<Player*>(creature);
  9470. if(!player || !attackedCreature || player->pos.z != attackedCreature->pos.z)
  9471. return;
  9472.  
  9473. int32_t dist, mana = 0;
  9474. MagicEffectAreaNoExhaustionClass runeAreaSpell;
  9475. runeAreaSpell.drawblood = true;
  9476. runeAreaSpell.offensive = true;
  9477. runeAreaSpell.direction = 1;
  9478.  
  9479.  
  9480. // P O I S O N //
  9481.  
  9482. if (swordid == ITEM_P_MB && player->vocation == VOCATION_KNIGHT &&
  9483. player->mana >= g_config.MANA_P_MB && player->getLevel() >= 220)
  9484. {
  9485. dist = g_config.RANGE_P_MB;
  9486. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9487. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9488. return;
  9489.  
  9490. runeAreaSpell.attackType = ATTACK_SWORD;
  9491. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  9492. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  9493. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  9494. runeAreaSpell.animationColor = 0x60;
  9495.  
  9496. runeAreaSpell.minDamage = 10;
  9497. runeAreaSpell.maxDamage = 60;
  9498. mana = g_config.MANA_P_MB;
  9499. }
  9500.  
  9501. else if (swordid == ITEM_P_MAUL && player->vocation == VOCATION_KNIGHT &&
  9502. player->mana >= g_config.MANA_P_MAUL && player->getLevel() >= 220)
  9503. {
  9504. dist = g_config.RANGE_P_MAUL;
  9505. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9506. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9507. return;
  9508.  
  9509. runeAreaSpell.attackType = ATTACK_SWORD;
  9510. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  9511. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  9512. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  9513. runeAreaSpell.animationColor = 0x60;
  9514.  
  9515. runeAreaSpell.minDamage = 10;
  9516. runeAreaSpell.maxDamage = 60;
  9517. mana = g_config.MANA_P_MAUL;
  9518. }
  9519.  
  9520. else if (swordid == ITEM_P_HEAD && player->vocation == VOCATION_KNIGHT &&
  9521. player->mana >= g_config.MANA_P_HEAD && player->getLevel() >= 220)
  9522. {
  9523. dist = g_config.RANGE_P_HEAD;
  9524. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9525. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9526. return;
  9527.  
  9528. runeAreaSpell.attackType = ATTACK_SWORD;
  9529. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  9530. runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  9531. runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  9532. runeAreaSpell.animationColor = 0x60;
  9533.  
  9534. runeAreaSpell.minDamage = 10;
  9535. runeAreaSpell.maxDamage = 60;
  9536. mana = g_config.MANA_P_HEAD;
  9537. }
  9538.  
  9539. // F I R E //
  9540.  
  9541. else if (swordid == ITEM_F_MB && player->vocation == VOCATION_KNIGHT &&
  9542. player->mana >= g_config.MANA_F_MB && player->getLevel() >= 320)
  9543. {
  9544. dist = g_config.RANGE_F_MB;
  9545. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9546. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9547. return;
  9548.  
  9549. runeAreaSpell.attackType = ATTACK_SWORD;
  9550. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  9551. runeAreaSpell.hitEffect = NM_ME_EXPLOSION_AREA;
  9552. runeAreaSpell.areaEffect = NM_ME_EXPLOSION_AREA;
  9553. runeAreaSpell.animationColor = 0xC6;
  9554.  
  9555. runeAreaSpell.minDamage = 60;
  9556. runeAreaSpell.maxDamage = 110;
  9557. mana = g_config.MANA_F_MB;
  9558. }
  9559.  
  9560. else if (swordid == ITEM_F_MAUL && player->vocation == VOCATION_KNIGHT &&
  9561. player->mana >= g_config.MANA_F_MAUL && player->getLevel() >= 320)
  9562. {
  9563. dist = g_config.RANGE_F_MAUL;
  9564. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9565. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9566. return;
  9567.  
  9568. runeAreaSpell.attackType = ATTACK_SWORD;
  9569. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  9570. runeAreaSpell.hitEffect = NM_ME_EXPLOSION_AREA;
  9571. runeAreaSpell.areaEffect = NM_ME_EXPLOSION_AREA;
  9572. runeAreaSpell.animationColor = 0xC6;
  9573.  
  9574. runeAreaSpell.minDamage = 60;
  9575. runeAreaSpell.maxDamage = 110;
  9576. mana = g_config.MANA_F_MAUL;
  9577. }
  9578.  
  9579. else if (swordid == ITEM_F_HEAD && player->vocation == VOCATION_KNIGHT &&
  9580. player->mana >= g_config.MANA_F_HEAD && player->getLevel() >= 320)
  9581. {
  9582. dist = g_config.RANGE_F_HEAD;
  9583. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9584. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9585. return;
  9586.  
  9587. runeAreaSpell.attackType = ATTACK_SWORD;
  9588. runeAreaSpell.animationEffect = NM_ANI_FIRE;
  9589. runeAreaSpell.hitEffect = NM_ME_EXPLOSION_AREA;
  9590. runeAreaSpell.areaEffect = NM_ME_EXPLOSION_AREA;
  9591. runeAreaSpell.animationColor = 0xC6;
  9592.  
  9593. runeAreaSpell.minDamage = 60;
  9594. runeAreaSpell.maxDamage = 110;
  9595. mana = g_config.MANA_F_HEAD;
  9596. }
  9597.  
  9598. // E N E R G Y //
  9599.  
  9600. else if (swordid == ITEM_E_MB && player->vocation == VOCATION_KNIGHT &&
  9601. player->mana >= g_config.MANA_E_MB && player->getLevel() >= 420)
  9602. {
  9603. dist = g_config.RANGE_E_MB;
  9604. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9605. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9606. return;
  9607.  
  9608. runeAreaSpell.attackType = ATTACK_SWORD;
  9609. runeAreaSpell.animationEffect = NM_ANI_SUDDENDEATH;
  9610. runeAreaSpell.hitEffect = NM_ME_MORT_AREA;
  9611. runeAreaSpell.areaEffect = NM_ME_MORT_AREA;
  9612. runeAreaSpell.animationColor = 0xB9;
  9613.  
  9614. runeAreaSpell.minDamage = 110;
  9615. runeAreaSpell.maxDamage = 160;
  9616. mana = g_config.MANA_E_MB;
  9617. }
  9618.  
  9619. else if (swordid == ITEM_E_MAUL && player->vocation == VOCATION_KNIGHT &&
  9620. player->mana >= g_config.MANA_E_MAUL && player->getLevel() >= 420)
  9621. {
  9622. dist = g_config.RANGE_E_MAUL;
  9623. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9624. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9625. return;
  9626.  
  9627. runeAreaSpell.attackType = ATTACK_SWORD;
  9628. runeAreaSpell.animationEffect = NM_ANI_SUDDENDEATH;
  9629. runeAreaSpell.hitEffect = NM_ME_MORT_AREA;
  9630. runeAreaSpell.areaEffect = NM_ME_MORT_AREA;
  9631. runeAreaSpell.animationColor = 0xB9;
  9632.  
  9633. runeAreaSpell.minDamage = 110;
  9634. runeAreaSpell.maxDamage = 160;
  9635. mana = g_config.MANA_E_MAUL;
  9636. }
  9637.  
  9638. else if (swordid == ITEM_E_HEAD && player->vocation == VOCATION_KNIGHT &&
  9639. player->mana >= g_config.MANA_E_HEAD && player->getLevel() >= 420)
  9640. {
  9641. dist = g_config.RANGE_E_HEAD;
  9642. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9643. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9644. return;
  9645.  
  9646. runeAreaSpell.attackType = ATTACK_SWORD;
  9647. runeAreaSpell.animationEffect = NM_ANI_SUDDENDEATH;
  9648. runeAreaSpell.hitEffect = NM_ME_MORT_AREA;
  9649. runeAreaSpell.areaEffect = NM_ME_MORT_AREA;
  9650. runeAreaSpell.animationColor = 0xB9;
  9651.  
  9652. runeAreaSpell.minDamage = 110;
  9653. runeAreaSpell.maxDamage = 160;
  9654. mana = g_config.MANA_E_HEAD;
  9655. }
  9656.  
  9657. // P L A Y E R W E A P O N S //
  9658.  
  9659. else if (swordid == ITEM_HAIK_AXE && player->vocation == VOCATION_KNIGHT &&
  9660. player->mana >= g_config.MANA_HAIK_AXE && player->getLevel() >= 500)
  9661. {
  9662. dist = g_config.RANGE_HAIK_AXE;
  9663. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9664. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9665. return;
  9666.  
  9667. runeAreaSpell.attackType = ATTACK_SWORD;
  9668. runeAreaSpell.animationEffect = NM_ANI_STAR;
  9669. runeAreaSpell.hitEffect = NM_ME_STAR;
  9670. runeAreaSpell.areaEffect = NM_ME_STAR;
  9671. runeAreaSpell.animationColor = 0xD2;
  9672.  
  9673. runeAreaSpell.minDamage = 300;
  9674. runeAreaSpell.maxDamage = 350;
  9675. mana = g_config.MANA_HAIK_AXE;
  9676. }
  9677.  
  9678. else if (swordid == ITEM_BLETKA_AXE && player->vocation == VOCATION_KNIGHT &&
  9679. player->mana >= g_config.MANA_BLETKA_AXE)
  9680. {
  9681. dist = g_config.RANGE_BLETKA_AXE;
  9682. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9683. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9684. return;
  9685.  
  9686. runeAreaSpell.attackType = ATTACK_SWORD;
  9687. runeAreaSpell.animationEffect = NM_ANI_STAR;
  9688. runeAreaSpell.hitEffect = NM_ME_STAR;
  9689. runeAreaSpell.areaEffect = NM_ME_STAR;
  9690. runeAreaSpell.animationColor = 0xD2;
  9691.  
  9692. runeAreaSpell.minDamage = 150;
  9693. runeAreaSpell.maxDamage = 200;
  9694. mana = g_config.MANA_BLETKA_AXE;
  9695. }
  9696.  
  9697. // K U N I E C //
  9698.  
  9699. if (mana > 0)
  9700. {
  9701. std::vector<unsigned char> col;
  9702.  
  9703. col.push_back(0);
  9704. col.push_back(0);
  9705. col.push_back(0);
  9706. runeAreaSpell.areaVec.push_back(col);
  9707. col.clear();
  9708. col.push_back(0);
  9709. col.push_back(1);
  9710. col.push_back(0);
  9711. runeAreaSpell.areaVec.push_back(col);
  9712. col.clear();
  9713. col.push_back(0);
  9714. col.push_back(0);
  9715. col.push_back(0);
  9716. runeAreaSpell.areaVec.push_back(col);
  9717.  
  9718. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  9719. player->addManaSpent(mana);
  9720. player->mana -= mana;
  9721. }
  9722. }
  9723. #endif //ZS_SWORDS
  9724.  
  9725. #ifdef YUR_READABLES
  9726. bool Game::LoadReadables()
  9727. {
  9728. std::string file = g_config.getGlobalString("datadir") + "readables.xml";
  9729. xmlDocPtr doc;
  9730. xmlMutexLock(xmlmutex);
  9731.  
  9732. doc = xmlParseFile(file.c_str());
  9733. if (!doc)
  9734. return false;
  9735.  
  9736. xmlNodePtr root, readableNode;
  9737. root = xmlDocGetRootElement(doc);
  9738. if (xmlStrcmp(root->name, (const xmlChar*)"readables"))
  9739. {
  9740. xmlFreeDoc(doc);
  9741. xmlMutexUnlock(xmlmutex);
  9742. return false;
  9743. }
  9744.  
  9745. readableNode = root->children;
  9746. while (readableNode)
  9747. {
  9748. if (strcmp((char*) readableNode->name, "readable") == 0)
  9749. {
  9750. int32_t x = atoi((const char*)xmlGetProp(readableNode, (const xmlChar *) "x"));
  9751. int32_t y = atoi((const char*)xmlGetProp(readableNode, (const xmlChar *) "y"));
  9752. int32_t z = atoi((const char*)xmlGetProp(readableNode, (const xmlChar *) "z"));
  9753. std::string text = (const char*)xmlGetProp(readableNode, (const xmlChar *) "text");
  9754.  
  9755. for (size_t i = 0; i < text.length()-1; i++) // make real newlines
  9756. if (text.at(i) == '\\' && text.at(i+1) == 'n')
  9757. {
  9758. text[i] = ' ';
  9759. text[i+1] = '\n';
  9760. }
  9761.  
  9762. Tile* tile = getTile(x, y, z);
  9763. if (tile)
  9764. {
  9765. Thing* thing = tile->getTopThing();
  9766. Item* item = thing? dynamic_cast<Item*>(thing) : NULL;
  9767.  
  9768. if (item)
  9769. item->setReadable(text);
  9770. else
  9771. {
  9772. std::cout << "\nTop thing at " << Position(x,y,z) << " is not an item!";
  9773. return false;
  9774. }
  9775. }
  9776. else
  9777. {
  9778. std::cout << "\nTile " << Position(x,y,z) << " is not valid!";
  9779. return false;
  9780. }
  9781. }
  9782. readableNode = readableNode->next;
  9783. }
  9784.  
  9785. xmlFreeDoc(doc);
  9786. xmlMutexUnlock(xmlmutex);
  9787. return true;
  9788. }
  9789. #endif //YUR_READABLES
  9790.  
  9791. void Game::Blasting(Creature* c, Creature *attackedCreature, const Position& pos)
  9792. {
  9793. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::Blasting()");
  9794. Player* player = dynamic_cast<Player*>(c);
  9795. unsigned short dist = 6;
  9796. unsigned short REQ_MANA = 200;
  9797. uint32_t poziom = player->level;
  9798. uint32_t magpoziom = player->maglevel;
  9799.  
  9800. if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9801. abs(player->pos.y - attackedCreature->pos.y) > dist)
  9802. return;
  9803.  
  9804. MagicEffectAreaNoExhaustionClass runeAreaSpell;
  9805. runeAreaSpell.drawblood = true;
  9806. runeAreaSpell.offensive = true;
  9807. runeAreaSpell.direction = 1;
  9808. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  9809. runeAreaSpell.animationEffect = NM_ANI_REMOTE;
  9810. runeAreaSpell.hitEffect = NM_ME_EXPLO;
  9811. runeAreaSpell.areaEffect = NM_ME_EXPLO;
  9812. runeAreaSpell.animationColor = 0x60;
  9813.  
  9814. if((poziom * 2 + magpoziom * 3) >= 100){
  9815. runeAreaSpell.minDamage = int32_t((poziom * 2 + magpoziom * 3) * 1.6 );
  9816. runeAreaSpell.maxDamage = int32_t((poziom * 2 + magpoziom * 3) * 1.9 );
  9817. }else{
  9818. runeAreaSpell.minDamage = int32_t(100 * 1.5 );
  9819. runeAreaSpell.maxDamage = int32_t(100 * 1.8 );
  9820. }
  9821.  
  9822. std::vector<unsigned char> col;
  9823. col.push_back(0);
  9824. col.push_back(0);
  9825. col.push_back(0);
  9826. runeAreaSpell.areaVec.push_back(col);
  9827. col.clear();
  9828. col.push_back(0);
  9829. col.push_back(1);
  9830. col.push_back(0);
  9831. runeAreaSpell.areaVec.push_back(col);
  9832. col.clear();
  9833. col.push_back(0);
  9834. col.push_back(0);
  9835. col.push_back(0);
  9836. runeAreaSpell.areaVec.push_back(col);
  9837.  
  9838. creatureThrowRune(c, pos, runeAreaSpell);
  9839. player->flamTicks = 2*1000;
  9840. if (player->access < g_config.ACCESS_PROTECT)
  9841. {
  9842. player->mana -= REQ_MANA;
  9843. player->addManaSpent(REQ_MANA);
  9844. }
  9845. }
  9846. #ifdef KOSZ
  9847. bool Game::canDelete(Player *player, unsigned short itemid, Position toPos, Position fromPos, int32_t from_stack, unsigned char count)
  9848. {
  9849. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::canDelete()");
  9850.  
  9851. if(itemid == 99 || (itemid >= 4329 && itemid <= 4555))
  9852. return false;
  9853. else if(fromPos.x != 0xFFFF && ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  9854. return false;
  9855. else if(map->canThrowObjectTo(player->pos, toPos, BLOCK_PROJECTILE) != RET_NOERROR)
  9856. return false;
  9857. else if(toPos.x == 0xFFFF)
  9858. return false;
  9859. else if((player->access < g_config.ACCESS_REMOTE) &&
  9860. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  9861. return false;
  9862.  
  9863. Item* trash = dynamic_cast<Item*>(getThing(fromPos, from_stack, player));
  9864. if(trash){
  9865. trash->pos = fromPos;
  9866. if((abs(player->pos.x - toPos.x) > trash->throwRange) || (abs(player->pos.y - toPos.y) > trash->throwRange)) {
  9867. return false;
  9868. }
  9869.  
  9870. Tile *toTile = map->getTile(toPos);
  9871. if(toTile){
  9872. 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)){
  9873. if(!trash->isNotMoveable() && trash->isBlocking())
  9874. return false;
  9875. else if(trashObjects(player, toTile, trash, toPos, fromPos, from_stack, count))
  9876. return true;
  9877. }
  9878. Item *toItem = dynamic_cast<Item*>(toTile->getTopTopItem());
  9879.  
  9880. if(toItem && toItem->getID() == ITEM_DUSTBIN){
  9881. if(!trash->isNotMoveable() && trash->isBlocking())
  9882. return false;
  9883. else if(trashObjects(player, toTile, trash, toPos, fromPos, from_stack, count))
  9884. return true;
  9885. }
  9886. }
  9887. }
  9888.  
  9889. return false;
  9890. }
  9891.  
  9892. bool Game::trashObjects(Player *player, Tile *toTile, Item *trash, Position toPos, Position fromPos, int32_t from_stack, unsigned char count)
  9893. {
  9894. //OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::trashObjects()");
  9895.  
  9896. if(!player || !toTile || !trash || !from_stack || !count){
  9897. return false;}
  9898.  
  9899. if(toTile){
  9900. switch(toTile->ground->getID()){
  9901. case GROUND_WATER1:
  9902. case GROUND_WATER2:
  9903. case GROUND_WATER3:
  9904. case GROUND_WATER4:
  9905. case GROUND_WATER5:
  9906. case GROUND_WATER6:
  9907. case GROUND_WATER7:
  9908. case GROUND_WATER8:
  9909. case GROUND_WATER9:
  9910. case GROUND_WATER10:
  9911. case GROUND_WATER11:
  9912. case GROUND_WATER12:
  9913. case GROUND_WATER13:
  9914. case GROUND_WATER14:
  9915. case GROUND_WATER15:
  9916. case GROUND_WATER16:
  9917. case GROUND_WATER17:
  9918. case GROUND_WATER18:
  9919. case GROUND_WATER19:
  9920. case GROUND_WATER20:
  9921. case GROUND_WATER21:
  9922. case GROUND_WATER22:
  9923. case GROUND_WATER23:
  9924. case GROUND_WATER24:
  9925. case GROUND_WATER25:
  9926. case GROUND_WATER26:
  9927. case GROUND_WATER27:
  9928. case GROUND_WATER28:
  9929. case GROUND_WATER29:
  9930. case GROUND_WATER30:
  9931. case GROUND_WATER31:
  9932. case GROUND_WATER32:
  9933. case GROUND_WATER33:
  9934. case GROUND_WATER34:
  9935. case GROUND_WATER35:
  9936. case GROUND_WATER36:
  9937. case GROUND_WATER37:
  9938. case GROUND_WATER38:
  9939. case GROUND_WATER39:
  9940. case GROUND_WATER40:
  9941. case GROUND_WATER41:
  9942. case GROUND_WATER42:
  9943. case GROUND_WATER43:
  9944. case GROUND_WATER44:
  9945. spectatorEffect(toPos, NM_ME_LOOSE_ENERGY);
  9946. if(trashItems(player, trash, fromPos, from_stack, count))
  9947. return true;
  9948. break;
  9949. case GROUND_LAVA1:
  9950. case GROUND_LAVA2:
  9951. case GROUND_LAVA3:
  9952. case GROUND_LAVA4:
  9953. spectatorEffect(toPos, NM_ME_HITBY_FIRE);
  9954. if(trashItems(player, trash, fromPos, from_stack, count))
  9955. return true;
  9956. break;
  9957. case GROUND_SWAMP1:
  9958. case GROUND_SWAMP2:
  9959. case GROUND_SWAMP3:
  9960. case GROUND_SWAMP4:
  9961. spectatorEffect(toPos, NM_ME_POISEN_RINGS);
  9962. if(trashItems(player, trash, fromPos, from_stack, count))
  9963. return true;
  9964. break;
  9965. case GROUND_BLACK_SWAMP1:
  9966. case GROUND_BLACK_SWAMP2:
  9967. case GROUND_BLACK_SWAMP3:
  9968. case GROUND_BLACK_SWAMP4:
  9969. spectatorEffect(toPos, NM_ME_MORT_AREA);
  9970. if(trashItems(player, trash, fromPos, from_stack, count))
  9971. return true;
  9972. break;
  9973. }
  9974. }
  9975.  
  9976. return false;
  9977. }
  9978.  
  9979. bool Game::trashItems(Player *player, Item *trash, Position fromPos, int32_t from_stack, unsigned char count)
  9980. {
  9981. //OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::trashItems()");
  9982. if(!trash){return false;}
  9983. if(trash->getID() == 99 || (trash->getID() >= 4329 && trash->getID() <= 4555))
  9984. return false;
  9985. else if(fromPos.x != 0xFFFF && ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  9986. return false;
  9987. else if((player->access < g_config.ACCESS_REMOTE) &&
  9988. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  9989. return false;
  9990.  
  9991. if(trash && player){
  9992. if(trash->isStackable()){
  9993. if(trash->getItemCountOrSubtype() > count){
  9994. trash->setItemCountOrSubtype(trash->getItemCountOrSubtype() - count);
  9995. sendUpdateThing(player,fromPos,trash,from_stack);
  9996. player->updateInventoryWeigth();
  9997. return true;
  9998. }
  9999. else{
  10000. if(removeThing(player, fromPos, trash)){
  10001. player->updateInventoryWeigth();
  10002. return true;
  10003. }
  10004. }
  10005. }
  10006. else{
  10007. if(removeThing(player, fromPos, trash)){
  10008. player->updateInventoryWeigth();
  10009. return true;
  10010. }
  10011. }
  10012. }
  10013. return false;
  10014. }
  10015.  
  10016. bool Game::canTeleportItem(Player *player, unsigned short itemid, Position toPos, Position fromPos, int32_t from_stack, unsigned char count)
  10017. {
  10018. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::canTeleportItem()");
  10019.  
  10020. if(itemid == 99 || (itemid >= 4329 && itemid <= 4555))
  10021. return false;
  10022. else if(fromPos.x != 0xFFFF && ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  10023. return false;
  10024. else if(map->canThrowObjectTo(player->pos, toPos, BLOCK_PROJECTILE) != RET_NOERROR)
  10025. return false;
  10026. else if(toPos.x == 0xFFFF)
  10027. return false;
  10028. else if(!checkChangeFloor(map->getTile(toPos), getTile(toPos.x,toPos.y,toPos.z+1)))
  10029. return false;
  10030. else if((player->access < g_config.ACCESS_REMOTE) &&
  10031. ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  10032. return false;
  10033.  
  10034. Item* tpItem = dynamic_cast<Item*>(getThing(fromPos, from_stack, player));
  10035. if(tpItem){
  10036. tpItem->pos = fromPos;
  10037. if((abs(player->pos.x - toPos.x) > tpItem->throwRange) || (abs(player->pos.y - toPos.y) > tpItem->throwRange)) {
  10038. return false;
  10039. }
  10040.  
  10041. if(tpItem->isStackable()){
  10042. if(tpItem->getItemCountOrSubtype() > count){
  10043. tpItem->setItemCountOrSubtype(tpItem->getItemCountOrSubtype() - count);
  10044. Item *newitem = Item::CreateItem(tpItem->getID(), count);
  10045. addThing(player,getTeleportPos(toPos),newitem);
  10046. sendUpdateThing(player,fromPos,tpItem,from_stack);
  10047. player->updateInventoryWeigth();
  10048. return true;
  10049. }
  10050. else{
  10051. if(removeThing(player, fromPos, tpItem)){
  10052. addThing(player,getTeleportPos(toPos),tpItem);
  10053. player->updateInventoryWeigth();
  10054. return true;
  10055. }
  10056. }
  10057. }
  10058. else{
  10059. if(removeThing(player, fromPos, tpItem)){
  10060. addThing(player,getTeleportPos(toPos),tpItem);
  10061. player->updateInventoryWeigth();
  10062. return true;
  10063. }
  10064. }
  10065. }
  10066. return false;
  10067. }
  10068.  
  10069. void Game::spectatorEffect(Position pos, unsigned char type)
  10070. {
  10071. SpectatorVec list;
  10072. SpectatorVec::iterator it;
  10073. getSpectators(Range(pos, true), list);
  10074.  
  10075. for(it = list.begin(); it != list.end(); ++it) {
  10076. if(Player* p = dynamic_cast<Player*>(*it)) {
  10077. p->sendMagicEffect(pos, type);
  10078. }
  10079. }
  10080. }
  10081.  
  10082. bool Game::checkChangeFloor(Tile *toTile, Tile* downTile)
  10083. {
  10084. if(toTile->ground && toTile->ground->floorChangeDown())
  10085. {
  10086. if(downTile){
  10087. if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  10088. return true;
  10089. }
  10090. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  10091. return true;
  10092. }
  10093. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  10094. return true;
  10095. }
  10096. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  10097. return true;
  10098. }
  10099. else if(downTile->floorChange(NORTH)){
  10100. return true;
  10101. }
  10102. else if(downTile->floorChange(SOUTH)){
  10103. return true;
  10104. }
  10105. else if(downTile->floorChange(EAST)){
  10106. return true;
  10107. }
  10108. else if(downTile->floorChange(WEST)){
  10109. return true;
  10110. }
  10111. else if(Item::items[toTile->ground->getID()].floorChangeDown){
  10112. return true;
  10113. }
  10114. else {
  10115. return true;
  10116. }
  10117. }
  10118. }
  10119. else if(toTile->floorChange(NORTH) && toTile->floorChange(EAST)){
  10120. return true;
  10121. }
  10122. else if(toTile->floorChange(NORTH) && toTile->floorChange(WEST)){
  10123. return true;
  10124. }
  10125. else if(toTile->floorChange(SOUTH) && toTile->floorChange(EAST)){
  10126. return true;
  10127. }
  10128. else if(toTile->floorChange(SOUTH) && toTile->floorChange(WEST)){
  10129. return true;
  10130. }
  10131. else if(toTile->floorChange(NORTH)){
  10132. return true;
  10133. }
  10134. else if(toTile->floorChange(SOUTH)){
  10135. return true;
  10136. }
  10137. else if(toTile->floorChange(EAST)){
  10138. return true;
  10139. }
  10140. else if(toTile->floorChange(WEST)){
  10141. return true;
  10142. }
  10143. if(!toTile){
  10144. if(!downTile)
  10145. {
  10146. return false;
  10147. }
  10148. else if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  10149. return true;
  10150. }
  10151. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  10152. return true;
  10153. }
  10154. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  10155. return true;
  10156. }
  10157. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  10158. return true;
  10159. }
  10160. else if(downTile->floorChange(NORTH)){
  10161. return true;
  10162. }
  10163. else if(downTile->floorChange(SOUTH)){
  10164. return true;
  10165. }
  10166. else if(downTile->floorChange(EAST)){
  10167. return true;
  10168. }
  10169. else if(downTile->floorChange(WEST)){
  10170. return true;
  10171. }
  10172. }
  10173. return false;
  10174. }
  10175.  
  10176. Position Game::getTeleportPos(Position to)
  10177. {
  10178. Tile *toTile = map->getTile(to);
  10179.  
  10180. if(toTile->ground && toTile->ground->floorChangeDown())
  10181. {
  10182. Tile* downTile = getTile(to.x, to.y, to.z+1);
  10183. if(downTile){
  10184. //diagonal begin
  10185. if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  10186. return Position(to.x-1, to.y+1, to.z+1);
  10187. }
  10188. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  10189. return Position(to.x+1, to.y+1, to.z+1);
  10190. }
  10191. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  10192. return Position(to.x-1, to.y-1, to.z+1);
  10193. }
  10194. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  10195. return Position(to.x+1, to.y-1, to.z+1);
  10196. }
  10197. //diagonal end
  10198. else if(downTile->floorChange(NORTH)){
  10199. return Position(to.x, to.y+1, to.z+1);
  10200. }
  10201. else if(downTile->floorChange(SOUTH)){
  10202. return Position(to.x, to.y-1, to.z+1);
  10203. }
  10204. else if(downTile->floorChange(EAST)){
  10205. return Position(to.x-1, to.y, to.z+1);
  10206. }
  10207. else if(downTile->floorChange(WEST)){
  10208. return Position(to.x+1, to.y, to.z+1);
  10209. }
  10210. //floor change down
  10211. else if(Item::items[toTile->ground->getID()].floorChangeDown){
  10212. return Position(to.x, to.y, to.z+1);
  10213. }
  10214. else {
  10215. return Position(to.x, to.y, to.z+1);
  10216. }
  10217. }
  10218. }
  10219. //diagonal begin
  10220. else if(toTile->floorChange(NORTH) && toTile->floorChange(EAST)){
  10221. return Position(to.x+1, to.y-1, to.z-1);
  10222. }
  10223. else if(toTile->floorChange(NORTH) && toTile->floorChange(WEST)){
  10224. return Position(to.x-1, to.y-1, to.z-1);
  10225. }
  10226. else if(toTile->floorChange(SOUTH) && toTile->floorChange(EAST)){
  10227. return Position(to.x+1, to.y+1, to.z-1);
  10228. }
  10229. else if(toTile->floorChange(SOUTH) && toTile->floorChange(WEST)){
  10230. return Position(to.x-1, to.y+1, to.z-1);
  10231. }
  10232. else if(toTile->floorChange(NORTH)){
  10233. return Position(to.x, to.y-1, to.z-1);
  10234. }
  10235. else if(toTile->floorChange(SOUTH)){
  10236. return Position(to.x, to.y+1, to.z-1);
  10237. }
  10238. else if(toTile->floorChange(EAST)){
  10239. return Position(to.x+1, to.y, to.z-1);
  10240. }
  10241. else if(toTile->floorChange(WEST)){
  10242. return Position(to.x-1, to.y, to.z-1);
  10243. }
  10244. if(!toTile){
  10245. Tile* downTile = getTile(to.x, to.y, to.z+1);
  10246. if(!downTile)
  10247. {
  10248. return Position(0,0,0);
  10249. }
  10250. else if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  10251. return Position(to.x-2, to.y+2, to.z+1);
  10252. }
  10253. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  10254. return Position(to.x+2, to.y+2, to.z+1);
  10255. }
  10256. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  10257. return Position(to.x-2, to.y-2, to.z+1);
  10258. }
  10259. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  10260. return Position(to.x+2, to.y-2, to.z+1);
  10261. }
  10262. else if(downTile->floorChange(NORTH)){
  10263. return Position(to.x, to.y + 1, to.z+1);
  10264. }
  10265. else if(downTile->floorChange(SOUTH)){
  10266. return Position(to.x, to.y - 1, to.z+1);
  10267. }
  10268. else if(downTile->floorChange(EAST)){
  10269. return Position(to.x - 1, to.y, to.z+1);
  10270. }
  10271. else if(downTile->floorChange(WEST)){
  10272. return Position(to.x + 1, to.y, to.z+1);
  10273. }
  10274. }
  10275. }
  10276. #endif //KOSZ
  10277.  
  10278. void Game::globalMagicEffect(const Position pos, unsigned char type)
  10279. {
  10280. SpectatorVec list;
  10281. SpectatorVec::iterator it;
  10282. getSpectators(Range(pos), list);
  10283. for(it = list.begin(); it != list.end(); ++it){
  10284. Player* p = dynamic_cast<Player*>(*it);
  10285. if(p)
  10286. p->sendMagicEffect(pos, type);
  10287. }
  10288. }
  10289.  
  10290. void Game::checkCreatureFollow(uint32_t id)
  10291. {
  10292. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreatureFollow");
  10293. Player *player = getPlayerByID(id);
  10294. if(!player)
  10295. return;
  10296. if(!player->pathList.empty()) {
  10297. Creature *followCreature = getCreatureByID(player->followCreature);
  10298. if(followCreature == 0)
  10299. return;
  10300. if((std::abs(player->pos.x - followCreature->pos.x) > 7) ||
  10301. (std::abs(player->pos.y - followCreature->pos.y) > 5) || (player->pos.z != followCreature->pos.z)){
  10302. player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  10303. player->eventCheckFollow = 0;
  10304. player->followCreature = 0;
  10305. playerSetAttackedCreature(player, 0);
  10306. return;
  10307. }
  10308. if(followCreature && abs(followCreature->pos.x - player->pos.x) <= 1 && abs(followCreature->pos.y - player->pos.y) <= 1) player->pathList.clear();
  10309. else {
  10310. Position toPos = player->pathList.front();
  10311. player->pathList.pop_front();
  10312. player->lastmove = OTSYS_TIME();
  10313. this->thingMove(player, player, toPos.x, toPos.y, player->pos.z, 1);
  10314. flushSendBuffers();
  10315. }
  10316. }
  10317. if(!player->pathList.empty()) {
  10318. long long delay = player->getSleepTicks();
  10319. stopEvent(player->eventCheckFollow);
  10320. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollow), id)));
  10321. } else {
  10322. player->eventCheckFollow = 0;
  10323. }
  10324. }
  10325. void Game::checkCreatureFollowAttack(uint32_t id)
  10326. {
  10327. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreatureFollowAttack");
  10328. Player *player = getPlayerByID(id);
  10329. if(!player)
  10330. return;
  10331. if(!player->pathList.empty()) {
  10332. Creature *followCreature = getCreatureByID(player->followCreature);
  10333. if(followCreature == 0)
  10334. return;
  10335. if(player->followMode == 0x00) {
  10336. stopEvent(player->eventCheckFollow);
  10337. player->eventCheckFollow = 0;
  10338. player->followCreature = 0;
  10339. return;
  10340. }
  10341. if((std::abs(player->pos.x - followCreature->pos.x) > 7) ||
  10342. (std::abs(player->pos.y - followCreature->pos.y) > 5) || (player->pos.z != followCreature->pos.z)){
  10343. player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  10344. player->eventCheckFollow = 0;
  10345. player->followCreature = 0;
  10346. playerSetAttackedCreature(player, 0);
  10347. return;
  10348. }
  10349. if(followCreature && abs(followCreature->pos.x - player->pos.x) <= 1 && abs(followCreature->pos.y - player->pos.y) <= 1) player->pathList.clear();
  10350. else {
  10351. Position toPos = player->pathList.front();
  10352. player->pathList.pop_front();
  10353. player->lastmove = OTSYS_TIME();
  10354. this->thingMove(player, player, toPos.x, toPos.y, player->pos.z, 1);
  10355. flushSendBuffers();
  10356. }
  10357. }
  10358. if(!player->pathList.empty()) {
  10359. long long delay = player->getSleepTicks();
  10360. stopEvent(player->eventCheckFollow);
  10361. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollowAttack), id)));
  10362. } else {
  10363. player->eventCheckFollow = 0;
  10364. }
  10365. }
  10366. void Game::playerFollow(Player* player, Creature *followCreature)
  10367. {
  10368. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerFollow()");
  10369. if(followCreature->isRemoved || player->isRemoved || !player || !followCreature){
  10370. player->eventCheckFollow = 0;
  10371. player->followCreature = 0;
  10372. return;
  10373. }
  10374. player->pathList = getPathToEx(player, player->pos, followCreature->pos, false);
  10375. long long delay = player->getSleepTicks();
  10376. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollow), player->getID())));
  10377. }
  10378. void Game::playerFollowAttacking(Player* player, Creature *followCreature)
  10379. {
  10380. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerFollow()");
  10381. if(followCreature->isRemoved || player->isRemoved || !player || !followCreature){
  10382. player->eventCheckFollow = 0;
  10383. player->followCreature = 0;
  10384. return;
  10385. }
  10386. if(player->followMode == 0x00) {
  10387. stopEvent(player->eventCheckFollow);
  10388. player->eventCheckFollow = 0;
  10389. player->followCreature = 0;
  10390. return;
  10391. }
  10392. player->pathList = getPathToEx(player, player->pos, followCreature->pos, false);
  10393. long long delay = player->getSleepTicks();
  10394. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollowAttack), player->getID())));
  10395. }
  10396. void Game::playerSetFollowCreature(Player* player, uint32_t creatureid)
  10397. {
  10398. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerSetFollowCreature()");
  10399. if(player->isRemoved || !player)
  10400. return;
  10401. if(creatureid == 0) {
  10402. stopEvent(player->eventCheckFollow);
  10403. player->eventCheckFollow = 0;
  10404. player->followCreature = 0;
  10405. }
  10406. Creature* followCreature = NULL;
  10407. if(creatureid != 0) {
  10408. followCreature = getCreatureByID(creatureid);
  10409. }
  10410. if(followCreature) {
  10411. player->followCreature = followCreature->getID();
  10412. stopEvent(player->eventCheckFollow);
  10413. playerFollow(player, followCreature);
  10414. }
  10415. }
  10416. void Game::playerAttackSetFollowCreature(Player* player, uint32_t creatureid)
  10417. {
  10418. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerAttackSetFollowCreature()");
  10419. if(player->isRemoved || !player)
  10420. return;
  10421. if(player->followMode == 0x00) {
  10422. return;
  10423. }
  10424. if(creatureid == 0) {
  10425. stopEvent(player->eventCheckFollow);
  10426. player->eventCheckFollow = 0;
  10427. player->followCreature = 0;
  10428. }
  10429. Creature* followCreature = NULL;
  10430. if(creatureid != 0) {
  10431. followCreature = getCreatureByID(creatureid);
  10432. }
  10433. if(followCreature) {
  10434. player->followCreature = followCreature->getID();
  10435. stopEvent(player->eventCheckFollow);
  10436. playerFollowAttacking(player, followCreature);
  10437. }
  10438. }
  10439.  
  10440. #ifdef HUCZU_AUTORESTART
  10441. void Game::beforeRestart()
  10442. {
  10443. sheduleShutdown(5);
  10444. }
  10445. #endif
  10446.  
  10447. void Game::creatureUseShop(Creature *creature, int id, int count, std::string way){
  10448. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureUseShop()");
  10449.  
  10450. int stackpos = map->getTile(creature->pos)->getThingStackPos(creature);
  10451.  
  10452. SpectatorVec list;
  10453. SpectatorVec::iterator it;
  10454.  
  10455. map->getSpectators(Range(creature->pos, true), list);
  10456.  
  10457. for(it = list.begin(); it != list.end(); ++it) {
  10458. if(dynamic_cast<Npc*>(*it)) {
  10459. (*it)->onCreatureUseShop(creature, id, count, way);
  10460. }
  10461. }
  10462. }
Add Comment
Please, Sign In to add comment