Ledger Nano X - The secure hardware wallet
SHARE
TWEET

Untitled

a guest Mar 28th, 2020 97 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //////////////////////////////////////////////////////////////////////
  2. // OpenTibia - an opensource roleplaying game
  3. //////////////////////////////////////////////////////////////////////
  4. // class representing the gamestate
  5. //////////////////////////////////////////////////////////////////////
  6. // This program is free software; you can redistribute it and/or
  7. // modify it under the terms of the GNU General Public License
  8. // as published by the Free Software Foundation; either version 2
  9. // of the License, or (at your option) any later version.
  10. //
  11. // This program is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. // GNU General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU General Public License
  17. // along with this program; if not, write to the Free Software Foundation,
  18. // Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19. //////////////////////////////////////////////////////////////////////
  20.  
  21.  
  22. #include "patch.h"
  23. #include "definitions.h"
  24. #include <string>
  25. #include <sstream>
  26. #include <fstream>
  27. #include <ctime> //You may need to use ctime.h or time.h if this doesn't work.
  28.  
  29. #include <map>
  30. //#include <algorithm>
  31.  
  32. #ifdef __DEBUG_CRITICALSECTION__
  33. #include <iostream>
  34. #include <fstream>
  35. #endif
  36.  
  37. #include <boost/config.hpp>
  38. #include <boost/bind.hpp>
  39.  
  40. using namespace std;
  41.  
  42. #include <stdio.h>
  43. #include "otsystem.h"
  44. #include "items.h"
  45. #include "commands.h"
  46. #include "creature.h"
  47. #include "player.h"
  48. #include "monster.h"
  49. #include "npc.h"
  50. #include "game.h"
  51. #include "tile.h"
  52.  
  53. #include "spells.h"
  54. #include "actions.h"
  55. #include "ioplayer.h"
  56. #include "ioaccount.h"
  57. #include "chat.h"
  58. #include "status.h"
  59.  
  60. #include "luascript.h"
  61. #include "templates.h"
  62. #include "houses.h"
  63. #include "summons.h"
  64. #include "pvparena.h"
  65. #include <ctype.h>
  66. #if defined __EXCEPTION_TRACER__
  67. #include "exception.h"
  68. extern OTSYS_THREAD_LOCKVAR maploadlock;
  69. #endif
  70.  
  71. #define EVENT_CHECKCREATURE          123
  72. #define EVENT_CHECKCREATUREATTACKING 124
  73.  
  74. extern LuaScript g_config;
  75. extern Spells spells;
  76. extern Actions actions;
  77. extern Commands commands;
  78. extern Chat g_chat;
  79. extern xmlMutexPtr xmlmutex;
  80.  
  81. extern std::vector< std::pair<uint32_t, uint32_t> > bannedIPs;
  82.  
  83. GameState::GameState(Game *game, const Range &range)
  84. {
  85.     this->game = game;
  86.     game->getSpectators(range, spectatorlist);
  87. }
  88.  
  89. bool is_poof;
  90.  
  91. #ifdef YUR_PVP_ARENA
  92. bool GameState::isPvpArena(Creature* c)
  93. {
  94.     if (!c)
  95.         return false;
  96.     Tile *tile = game->map->getTile(c->pos);
  97.     return tile && tile->isPvpArena();
  98. }
  99. #endif //YUR_PVP_ARENA
  100.  
  101. #ifdef YUR_RINGS_AMULETS
  102. int32_t GameState::applyAmulets(Player* player, int32_t damage, attacktype_t atype)
  103. {
  104.     if (!player || atype == ATTACK_NONE)
  105.         return damage;
  106.  
  107.     double newDamage = (double)damage;
  108.     Item* necklace = player->getItem(SLOT_NECKLACE);
  109.     Item* ring = player->getItem(SLOT_RING);
  110.     Item* armor = player->getItem(SLOT_ARMOR);
  111.  
  112.     if(player && atype == ATTACK_PHYSICAL) {
  113.         if(player->getVocation() == VOCATION_KNIGHT) {
  114.             newDamage -= newDamage * (0.01 * (double)g_config.KNIGHT_LOOSE);
  115.         } else if(player->getVocation() == VOCATION_PALADIN) {
  116.             std::cout << "Before " << newDamage << std::endl;
  117.             newDamage += newDamage * (0.01 * (double)g_config.PALADIN_RAISE);
  118.             std::cout << "After " << newDamage << std::endl;
  119.         }
  120.     } else if(player) {
  121.         std::cout << "atype " << atype << std::endl;
  122.     }
  123.  
  124.     if (necklace && necklace->getCharges() > 0)
  125.     {
  126.         if (necklace->getID() == ITEM_STONE_SKIN_AMULET)
  127.         {
  128.             newDamage *= 0.10;
  129.             necklace->useCharge();
  130.         }
  131.        
  132.         else if (necklace->getID() == ITEM_PROTECTION_AMULET)
  133.         {
  134.             newDamage *= 0.80;
  135.             necklace->useCharge();
  136.         }
  137.        
  138.         else if ((necklace->getID() == ITEM_DRAGON_NECKLACE && (atype & ATTACK_FIRE)) ||
  139.             (necklace->getID() == ITEM_SILVER_AMULET && (atype & ATTACK_POISON)) ||
  140.             (necklace->getID() == ITEM_STRANGE_TALISMAN && (atype & ATTACK_ENERGY)) ||
  141.             (necklace->getID() == ITEM_ELVEN_AMULET))
  142.         {
  143.             newDamage *= 0.8;
  144.             necklace->useCharge();
  145.         }
  146.        
  147.        
  148.         else if ((necklace->getID() == ITEM_MAGMA_AMULET && (atype & ATTACK_FIRE)))
  149.         {
  150.             newDamage *= 0.7;
  151.             necklace->useCharge();
  152.         }
  153.        
  154.        
  155.  #ifdef YUR_DRAINS
  156.         else if (necklace->getID() == ITEM_BRONZE_AMULET && (atype & ATTACK_MANADRAIN))
  157.         {
  158.             newDamage *= 0.5;
  159.             necklace->useCharge();
  160.         }
  161.        
  162.         else if (necklace->getID() == ITEM_GARLIC_NECKLACE && (atype & ATTACK_LIFEDRAIN))
  163.         {
  164.             newDamage = 0.5;
  165.             necklace->useCharge();
  166.         }
  167.        
  168.  #endif //YUR_DRAINS
  169.  
  170.         if (necklace->getCharges() <= 0)
  171.             player->removeItemInventory(SLOT_NECKLACE);
  172.     }
  173.  
  174.     if (ring && ring->getCharges() > 0)
  175.     {
  176.         if (ring->getID() == ITEM_MIGHT_RING)
  177.         {
  178.             newDamage *= 0.8;
  179.             ring->useCharge();
  180.         }
  181.  
  182.         if (ring->getCharges() <= 0)
  183.             player->removeItemInventory(SLOT_RING);
  184.     }
  185. #ifdef HUCZU_FIX
  186.     if(armor)
  187.     {
  188.        if(armor->getID() == ITEM_FIRE_ARMOR && (atype & ATTACK_FIRE))
  189.          newDamage *= 0.8;
  190.     }
  191. #endif //HUCZU_FIX
  192.  
  193.     return (int32_t)newDamage;
  194. }
  195. #endif //YUR_RINGS_AMULETS
  196.  
  197. void GameState::onAttack(Creature* attacker, const Position& pos, const MagicEffectClass* me)
  198. {
  199.     Tile *tile = game->map->getTile(pos);
  200.  
  201.     if(!tile)
  202.         return;
  203.  
  204. #ifdef YUR_PVP_ARENA
  205.     CreatureVector arenaLosers;
  206. #endif //YUR_PVP_ARENA
  207.  
  208.     CreatureVector::iterator cit;
  209.     Player* attackPlayer = dynamic_cast<Player*>(attacker);
  210.     Creature *targetCreature = NULL;
  211.     Player *targetPlayer = NULL;
  212.     for(cit = tile->creatures.begin(); cit != tile->creatures.end(); ++cit) {
  213.         targetCreature = (*cit);
  214.         targetPlayer = dynamic_cast<Player*>(targetCreature);
  215.         bool pvpArena = false;
  216. #ifdef TR_SUMMONS
  217.         bool targetIsSummon = (targetCreature && targetCreature->isPlayersSummon());
  218.         bool summonVsPlayer = (attacker && attacker->isPlayersSummon() && targetPlayer);
  219. #endif //TR_SUMMONS
  220.  
  221.         int32_t damage = me->getDamage(targetCreature, attacker);
  222.         int32_t manaDamage = 0;
  223.        
  224.         if(attackPlayer){
  225.         if(!me->offensive && me->minDamage != 0 && g_config.getGlobalString("showHealingDamage") == "yes"){
  226.              int32_t lecz = std::min(std::abs(damage), attackPlayer->healthmax - attackPlayer->health);
  227.              std::stringstream anidamage;
  228.                 anidamage << "+" << lecz;
  229.                   if(lecz != 0)
  230.                      game->sendAnimatedTextExt(attackPlayer->pos, 96, anidamage.str().c_str());    
  231.         }
  232.         }
  233.  
  234. #ifdef YUR_RINGS_AMULETS
  235.         damage = applyAmulets(targetPlayer, damage, me->attackType);
  236. #endif //YUR_RINGS_AMULETS
  237.  
  238.         if (damage > 0) {
  239.             if(attackPlayer && attackPlayer->access < g_config.ACCESS_PROTECT) {
  240.                 if(targetPlayer && targetPlayer != attackPlayer && game->getWorldType() != WORLD_TYPE_NO_PVP)
  241.                     attackPlayer->pzLocked = true;
  242.             }  
  243.                
  244. if(targetCreature->access < g_config.ACCESS_PROTECT && targetPlayer && game->getWorldType() != WORLD_TYPE_NO_PVP)
  245. {
  246. #ifdef YUR_CVS_MODS
  247.                 targetPlayer->inFightTicks = std::max(g_config.PZ_LOCKED, targetPlayer->inFightTicks);
  248. #else
  249.                 targetPlayer->inFightTicks = g_config.PZ_LOCKED;
  250. #endif //YUR_CVS_MODS
  251.                 targetPlayer->sendIcons();
  252.             }
  253. #ifdef SURVIVAL_BLACKSQUARE
  254. if(damage > 0 && attackPlayer && targetPlayer && attackPlayer != targetPlayer){
  255. NetworkMessage attackedpmsg;
  256. attackedpmsg.AddPlayerAttacked(attacker);
  257. targetPlayer->sendNetworkMessage(&attackedpmsg);
  258. }
  259. #endif //SURVIVAL_BLACKSQUARE  
  260.  
  261. #ifdef YUR_PVP_ARENA
  262.             pvpArena = isPvpArena(attacker) && isPvpArena(targetCreature);
  263. #endif //YUR_PVP_ARENA
  264.  
  265. #ifdef TR_SUMMONS
  266.             if ((game->getWorldType() == WORLD_TYPE_NO_PVP && !pvpArena && summonVsPlayer) ||
  267.                 (game->getWorldType() == WORLD_TYPE_NO_PVP && !pvpArena && attackPlayer && (targetPlayer || targetIsSummon) && attackPlayer->access < g_config.ACCESS_PROTECT)) {
  268. #else
  269.             if(game->getWorldType() == WORLD_TYPE_NO_PVP && !pvpArena && attackPlayer && targetPlayer && attackPlayer->access < ACCESS_PROTECT){
  270. #endif //TR_SUMMONS
  271.                 damage = 0;
  272.             }
  273.         }
  274.  
  275.         if (damage != 0)
  276.         {
  277. // Bedzie pro ustawione all
  278. #ifdef HUCZU_FIX
  279.           if(attackPlayer){
  280.            Item* armor = attackPlayer->getItem(SLOT_ARMOR);
  281.            Item* legs = attackPlayer->getItem(SLOT_LEGS);
  282.            Item* helmet = attackPlayer->getItem(SLOT_HEAD);
  283.            Item* boots = attackPlayer->getItem(SLOT_FEET);
  284.            Item* ring = attackPlayer->getItem(SLOT_RING);
  285.            Item* amulet = attackPlayer->getItem(SLOT_NECKLACE);
  286.            
  287.             if(attackPlayer->vocation == 1 || attackPlayer->vocation == 2){
  288.               if(armor){
  289.                 if(armor->getID() == ITEM_GLACIER_ROBE){
  290.                     double newdamage = damage*2/100.0;
  291.                     damage += (int32_t)newdamage;
  292.                 }
  293.                 else if(armor->getID() == ITEM_ARCHMAGE_COAT){
  294.                     double newdamage = damage*5/100.0;
  295.                     damage += (int32_t)newdamage;
  296.                 }
  297.                 else if(armor->getID() == ITEM_BMC){
  298.                     double newdamage = damage*3/100.0;
  299.                     damage += (int32_t)newdamage;
  300.                 }
  301.               }
  302.               if(legs){
  303.                if(legs->getID() == ITEM_GLACIER_KIT){
  304.                  double newdamage = damage*2/100.0;
  305.                  damage += (int32_t)newdamage;
  306.                }                                
  307.               }
  308.             }    
  309.            
  310.             if(legs){
  311.                if(legs->getID() == ITEM_ZS_LEGS){
  312.                  double newdamage = damage*10/100.0;
  313.                  damage += (int32_t)newdamage;
  314.                }                                
  315.             }
  316.            
  317.             if(g_config.MGITEMS){
  318.                 if(helmet && helmet->getID() == g_config.MGITEMHELMET){
  319.                     double newdamage = damage*g_config.ITEM_MDOWNHELMET/100.0;
  320.                     damage += (int32_t)newdamage;
  321.                 }
  322.                 if(armor && armor->getID() == g_config.MGITEMARMOR){
  323.                     double newdamage = damage*g_config.ITEM_MDOWNARMOR/100.0;
  324.                     damage += (int32_t)newdamage;
  325.                 }
  326.                 if(legs && legs->getID() == g_config.MGITEMLEGS){
  327.                     double newdamage = damage*g_config.ITEM_MDOWNLEGS/100.0;
  328.                     damage += (int32_t)newdamage;
  329.                 }
  330.                 if(boots && boots->getID() == g_config.MGITEMBOOTS){
  331.                     double newdamage = damage*g_config.ITEM_MDOWNBOOTS/100.0;
  332.                     damage += (int32_t)newdamage;
  333.                 }
  334.                 if(ring && ring->getID() == g_config.MGITEMRINGS){
  335.                     double newdamage = damage*g_config.ITEM_MDOWNRING/100.0;
  336.                     damage += (int32_t)newdamage;
  337.                 }
  338.                 if(amulet && amulet->getID() == g_config.MGITEMAMU){
  339.                     double newdamage = damage*g_config.ITEM_MDOWNAMU/100.0;
  340.                     damage += (int32_t)newdamage;
  341.                 }
  342.            }
  343.           }
  344. #endif //HUCZU_FIX i git w chuj
  345.  
  346. #ifdef YUR_DRAINS
  347.             if (me->attackType & ATTACK_MANADRAIN)
  348.             {
  349.                 manaDamage = std::min(damage, targetCreature->mana);           
  350.                 targetCreature->drainMana(manaDamage);
  351.                 damage = 0;
  352.             }
  353.             else
  354. #endif //YUR_DRAINS
  355.             {
  356.                 game->creatureApplyDamage(targetCreature, damage, damage, manaDamage
  357. #ifdef YUR_PVP_ARENA
  358.                     , (pvpArena? &arenaLosers : NULL)
  359. #endif //YUR_PVP_ARENA
  360.                     );
  361.             }
  362.  
  363. #ifdef YUR_DRAINS
  364.             if (me->attackType & ATTACK_LIFEDRAIN)
  365.             {
  366.                 attacker->health = std::min(attacker->healthmax, attacker->health + damage);
  367.                 addCreatureState(tile, attacker, 0, 0, false);  // update attacker health
  368.             }
  369. #endif //YUR_DRAINS
  370.  
  371. #ifdef YUR_INVISIBLE
  372.             if (targetCreature && !targetPlayer)
  373.             {
  374.                 targetCreature->setInvisible(0);
  375.                 game->creatureChangeOutfit(targetCreature);
  376.             }
  377. #endif //YUR_INVISIBLE
  378.         }
  379.        
  380. #ifdef HUCZU_SKULLS
  381.         if (me->offensive && game->getWorldType() == WORLD_TYPE_PVP)
  382.             game->onPvP(attacker, targetCreature, targetCreature->health <= 0);
  383. #endif
  384.  
  385.         addCreatureState(tile, targetCreature, damage, manaDamage, me->drawblood);
  386.     }
  387.  
  388.     //Solid ground items/Magic items (fire/poison/energy)
  389.     MagicEffectItem *newmagicItem = me->getMagicItem(attacker, tile->isPz(),
  390.         (tile->isBlocking(BLOCK_SOLID, true) != RET_NOERROR));
  391.  
  392.     if(newmagicItem) {
  393.  
  394.         MagicEffectItem *magicItem = tile->getFieldItem();
  395.  
  396.         if(magicItem) {
  397.             //Replace existing magic field
  398.             magicItem->transform(newmagicItem);
  399.  
  400.             int32_t stackpos = tile->getThingStackPos(magicItem);
  401.             if(tile->removeThing(magicItem)) {
  402.  
  403.                 SpectatorVec list;
  404.                 SpectatorVec::iterator it;
  405.  
  406.                 game->getSpectators(Range(pos, true), list);
  407.  
  408.                 //players
  409.                 for(it = list.begin(); it != list.end(); ++it) {
  410.                     if(dynamic_cast<Player*>(*it)) {
  411.                         (*it)->onThingDisappear(magicItem, stackpos);
  412.                     }
  413.                 }
  414.  
  415.                 //none-players
  416.                 for(it = list.begin(); it != list.end(); ++it) {
  417.                     if(!dynamic_cast<Player*>(*it)) {
  418.                         (*it)->onThingDisappear(magicItem, stackpos);
  419.                     }
  420.                 }
  421.  
  422.                 tile->addThing(magicItem);
  423.  
  424.                 //players
  425.                 for(it = list.begin(); it != list.end(); ++it) {
  426.                     if(dynamic_cast<Player*>(*it)) {
  427.                         (*it)->onThingAppear(magicItem);
  428.                     }
  429.                 }
  430.  
  431.                 //none-players
  432.                 for(it = list.begin(); it != list.end(); ++it) {
  433.                     if(!dynamic_cast<Player*>(*it)) {
  434.                         (*it)->onThingAppear(magicItem);
  435.                     }
  436.                 }
  437.             }
  438.         }
  439.         else {
  440.             magicItem = new MagicEffectItem(*newmagicItem);
  441.             magicItem->useThing();
  442.             magicItem->pos = pos;
  443.  
  444.             tile->addThing(magicItem);
  445.  
  446.             SpectatorVec list;
  447.             SpectatorVec::iterator it;
  448.  
  449.             game->getSpectators(Range(pos, true), list);
  450.  
  451.             //players
  452.             for(it = list.begin(); it != list.end(); ++it) {
  453.                 if(dynamic_cast<Player*>(*it)) {
  454.                     (*it)->onThingAppear(magicItem);
  455.                 }
  456.             }
  457.  
  458.             //none-players
  459.             for(it = list.begin(); it != list.end(); ++it) {
  460.                 if(!dynamic_cast<Player*>(*it)) {
  461.                     (*it)->onThingAppear(magicItem);
  462.                 }
  463.             }
  464.  
  465.             magicItem->isRemoved = false;
  466.             game->startDecay(magicItem);
  467.         }
  468.     }
  469.  
  470.     //Clean up
  471.     for(CreatureStateVec::const_iterator csIt = creaturestates[tile].begin(); csIt != creaturestates[tile].end(); ++csIt) {
  472.         onAttackedCreature(tile, attacker, csIt->first, csIt->second.damage, csIt->second.drawBlood);
  473.     }
  474.  
  475.     if(attackPlayer && attackPlayer->access < g_config.ACCESS_PROTECT) {
  476.         //Add exhaustion
  477.         if(me->causeExhaustion(true) /*!areaTargetVec.empty())*/)
  478.         {
  479.                 attackPlayer->exhaustedTicks = g_config.EXHAUSTED;
  480.         }
  481.  
  482.         //Fight symbol
  483.         if(me->offensive /*&& !areaTargetVec.empty()*/)
  484.         {
  485. #ifdef YUR_CVS_MODS
  486.             attackPlayer->inFightTicks = std::max(g_config.PZ_LOCKED, attackPlayer->inFightTicks);
  487. #else
  488.             attackPlayer->inFightTicks = g_config.PZ_LOCKED;
  489. #endif //YUR_CVS_MODS
  490.         }
  491.     }
  492.  
  493. #ifdef YUR_PVP_ARENA
  494.     for (CreatureVector::iterator it = arenaLosers.begin(); it != arenaLosers.end(); ++it)
  495.     {
  496.         Tile* tile = game->getTile((*it)->pos);
  497.                
  498.         if (tile)
  499.         {
  500.             game->teleport(*it, tile->getPvpArenaExit());  
  501.         }
  502.        
  503.         if(Monster* monster = dynamic_cast<Monster*>(*it))
  504.         {
  505.             if(Tile *tile = game->map->getTile(monster->pos))
  506.             {    
  507.                 if(tile->isPvpArena())
  508.                 {
  509.                     game->removeCreature(monster);
  510.                 }
  511.             }
  512.         }
  513.     }
  514. #endif //YUR_PVP_ARENA
  515. }
  516.  
  517. void GameState::onAttack(Creature* attacker, const Position& pos, Creature* attackedCreature)
  518. {
  519.     bool pvpArena = false;
  520. #ifdef YUR_PVP_ARENA
  521.     CreatureVector arenaLosers;
  522.     pvpArena = isPvpArena(attacker) && isPvpArena(attackedCreature);
  523. #endif //YUR_PVP_ARENA
  524.  
  525.     //TODO: Decent formulas and such...
  526.     int32_t damage = attacker->getWeaponDamage();
  527.     int32_t armor = attackedCreature->getArmor();
  528.     int32_t defense = attackedCreature->getDefense();
  529.  
  530.     Player* attackPlayer = dynamic_cast<Player*>(attacker);
  531.     Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  532.  
  533.     if(attackedPlayer)
  534.         attackedPlayer->addSkillShieldTry(1);
  535.  
  536.     int32_t probability = rand() % 10000;
  537.  
  538. #ifdef YUR_CVS_MODS
  539.     if(probability * damage < defense * 3000)
  540.         damage = 0;
  541.     else
  542.         damage -= (int32_t)((damage*(armor/50.0)*(rand()/(RAND_MAX+1.0))) + (armor*2) + defense/1.5);
  543.         //damage -= (int32_t)((armor)*(rand()/(RAND_MAX+1.0))) + armor; // wik's
  544. #else
  545.     if(probability * damage < defense * 10000)
  546.         damage = 0;
  547.     else
  548.     {
  549.         damage -= (armor * (10000 + rand() % 10000)) / 10000;
  550.     }
  551. #endif //YUR_CVS_MODS
  552.  
  553.     int32_t manaDamage = 0;
  554.  
  555.     if(attackPlayer && attackedPlayer){
  556.         damage -= (int32_t) damage / 2;
  557.     }
  558.  
  559.  
  560.     if (attacker->access >= g_config.ACCESS_PROTECT)
  561.         damage += 1;
  562.  
  563.  
  564.     Tile* tile = game->map->getTile(pos);
  565.     bool blood;
  566.     if(damage > 0)
  567.     {
  568.               // F-AXE,F-SWORD,P-DAGGER
  569.               if(attackPlayer)
  570. {
  571.    for (int32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++)
  572.    {
  573.         if(g_config.EFFECT_ATACK && attackPlayer->getItem(slot) && (attackPlayer->getItem(slot)->getID() == ITEM_FAXE || attackPlayer->getItem(slot)->getID() == ITEM_FSWORD))
  574.         {
  575.              game->CreateCondition(attackedCreature, attacker, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 5, 5, 2000, 1);      
  576.         }
  577.        if(g_config.EFFECT_ATACK && attackPlayer->getItem(slot) && (attackPlayer->getItem(slot)->getID() == ITEM_PD))
  578.         {
  579.              game->CreateCondition(attackedCreature, attacker, 30, NM_ME_POISEN_RINGS, NM_ME_POISEN_RINGS, ATTACK_POISON, true, 5, 5, 2000, 3);
  580.         }
  581.    }
  582. }
  583.  
  584. // P-BOLT ENERGY
  585.    if(attackPlayer)
  586.                    {
  587.    int32_t slot = SLOT_AMMO;
  588. if(g_config.EFFECT_ATACK && attackPlayer->getItem(slot) && (attackPlayer->getItem(slot)->getID() == 5260))
  589. {
  590. game->CreateCondition(attackedCreature, attacker, 35, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 10, 10, 2000, 1);      
  591. }
  592. }
  593.  
  594. #ifdef YUR_ICE_RAPIER
  595.         if (attackPlayer)
  596.             for (int32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++)
  597.                 if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->getID() == ITEM_ICE_RAPIER)
  598.                     attackPlayer->removeItemInventory(slot);
  599. #endif //YUR_ICE_RAPIER
  600.  
  601. #ifdef PALL_REQ_LVL
  602.         if (attackPlayer){
  603.           for (int32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++){
  604.           if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->isWeapon() && attackPlayer->getItem(slot)->getReqLevel() > attackPlayer->getLevel())
  605.           {
  606.             int32_t newdamage = attackPlayer->getWeaponDamage() / random_range(4, 7);
  607.              if (attackPlayer->getWeaponDamage() >= 7)
  608.                 damage = 0;
  609.              else
  610.                 damage = newdamage;
  611.           }
  612.           if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->getAmuType() != 0 && attackPlayer->getItem(slot)->getReqLevel() > attackPlayer->getLevel())
  613.           {
  614.             int32_t newdamage = attackPlayer->getWeaponDamage() / random_range(4, 7);
  615.              if (attackPlayer->getWeaponDamage() >= 7)
  616.                 damage = 0;
  617.              else    
  618.                 damage = newdamage;
  619.           }
  620.           if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->isWeapon() && attackPlayer->getItem(slot)->getReqVoc() != attackPlayer->getVocation() && attackPlayer->getItem(slot)->getReqVoc() > 0)
  621.           {
  622.             int32_t newdamage = attackPlayer->getWeaponDamage() / random_range(4, 9);
  623.              if (attackPlayer->getWeaponDamage() >= 7)
  624.                 damage = 0;
  625.              else
  626.                 damage = newdamage;
  627.           }
  628.           }
  629.         }
  630. #endif //PALL_REQ_LVL
  631.  
  632. #ifdef YUR_RINGS_AMULETS
  633.         damage = applyAmulets(attackedPlayer, damage, ATTACK_PHYSICAL);
  634. #endif //YUR_RINGS_AMULETS
  635.  
  636.  
  637. #ifdef CHRIS_CRIT_HIT
  638. if(attackPlayer){
  639.     int32_t critcial_hit;
  640.     int32_t rand_hit = random_range(0, 700);
  641.     switch(rand_hit){
  642.         case 75:
  643.             critcial_hit = random_range(50, 100);
  644.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  645.         break;
  646.         case 87:
  647.             critcial_hit = random_range(50, 100);
  648.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  649.         break;
  650.         case 95:
  651.             critcial_hit = random_range(50, 100);
  652.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  653.         break;
  654.         case 113:
  655.             critcial_hit = random_range(80, 130);
  656.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  657.         break;
  658.         case 128:
  659.             critcial_hit = random_range(80, 130);
  660.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  661.         break;
  662.         case 133:
  663.             critcial_hit = random_range(80, 130);
  664.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  665.         break;
  666.         case 145:
  667.             critcial_hit = random_range(80, 130);
  668.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  669.         break;
  670.         case 157:
  671.             critcial_hit = random_range(80, 130);
  672.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  673.         break;
  674.         case 167:
  675.             critcial_hit = random_range(80, 130);
  676.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  677.         break;
  678.         case 187:
  679.             critcial_hit = random_range(80, 130);
  680.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  681.         break;
  682.         case 195:
  683.             critcial_hit = random_range(80, 130);
  684.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  685.         break;
  686.         case 202:
  687.             critcial_hit = random_range(110, 160);
  688.                if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  689.         break;
  690.         case 225:
  691.             critcial_hit = random_range(110, 160);
  692.                if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  693.         break;
  694.         case 238:
  695.             critcial_hit = random_range(110, 160);
  696.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  697.         break;
  698.         case 245:
  699.             critcial_hit = random_range(110, 160);
  700.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  701.         break;
  702.         case 268:
  703.             critcial_hit = random_range(110, 160);
  704.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  705.         break;
  706.         case 287:
  707.             critcial_hit = random_range(110, 160);
  708.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  709.         break;
  710.         case 298:
  711.             critcial_hit = random_range(110, 160);
  712.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  713.         break;
  714.         case 324:
  715.             critcial_hit = random_range(140, 400);
  716.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  717.         break;
  718.         case 356:
  719.             critcial_hit = random_range(140, 190);
  720.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  721.         break;
  722.         case 371:
  723.             critcial_hit = random_range(140, 190);
  724.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  725.         break;
  726.         case 380:
  727.             critcial_hit = random_range(140, 190);
  728.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  729.         break;
  730.         case 397:
  731.             critcial_hit = random_range(140, 190);
  732.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  733.         break;
  734.         case 399:
  735.             critcial_hit = random_range(140, 190);
  736.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  737.         break;
  738.         case 400:
  739.             critcial_hit = random_range(170, 210);
  740.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  741.         break;
  742.         case 428:
  743.             critcial_hit = random_range(170, 210);
  744.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  745.         break;
  746.         case 432:
  747.             critcial_hit = random_range(170, 210);
  748.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  749.         break;
  750.         case 444:
  751.             critcial_hit = random_range(170, 210);
  752.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  753.         break;
  754.         case 474:
  755.             critcial_hit = random_range(170, 210);
  756.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  757.         break;
  758.         default:
  759.             critcial_hit = 0;
  760.         break;
  761.     }
  762.  
  763. if (attackPlayer->vocation == 4){
  764.   if(critcial_hit != 0){
  765.      if(attackPlayer->level >= 150){                  
  766.        if(attackPlayer && attackPlayer->items[SLOT_RIGHT] && attackPlayer->items[SLOT_RIGHT]->getID() == ITEM_RAINBOW){
  767.          if(attackPlayer->items[SLOT_LEFT]){
  768.            if(attackPlayer->items[SLOT_LEFT]->getID() != ITEM_RAINBOW)
  769.              critcial_hit += critcial_hit*(25/100);
  770.              game->CreateCondition(attackedCreature, attacker, 35, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 25, 25, 1000, 1);
  771.           }
  772.          }
  773.         }
  774.         if(attackPlayer && attackPlayer->items[SLOT_LEFT] && attackPlayer->items[SLOT_LEFT]->getID() == ITEM_RAINBOW){
  775.           if(attackPlayer->items[SLOT_RIGHT]){
  776.             if(attackPlayer->items[SLOT_RIGHT]->getID() != ITEM_RAINBOW)
  777.               critcial_hit += critcial_hit*(25/100);
  778.               game->CreateCondition(attackedCreature, attacker, 35, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 25, 25, 1000, 1);
  779.            }
  780.           }
  781.          }
  782.    damage += critcial_hit;
  783.   }
  784. }
  785.  
  786. #endif //CHRIS_CRIT_HIT
  787.  
  788.         game->creatureApplyDamage(attackedCreature, damage, damage, manaDamage
  789.        
  790.  
  791. #ifdef YUR_PVP_ARENA
  792.             , (pvpArena? &arenaLosers : NULL)
  793. #endif //YUR_PVP_ARENA
  794.             );
  795.  
  796. #ifdef HUCZU_SKULLS
  797.             if (game->getWorldType() == WORLD_TYPE_PVP)
  798.             game->onPvP(attacker, attackedCreature, attackedCreature->health <= 0);
  799. #endif
  800.  
  801.         blood = true;
  802.        
  803.      if(attackPlayer && attackPlayer->maxDmg < damage) {
  804.        attackPlayer->maxDmg = (int32_t) damage;
  805.        std::stringstream MaxDmgMsg;
  806.        MaxDmgMsg << "Your new best damage is " <<  attackPlayer->maxDmg << ".";
  807.        attackPlayer->sendTextMessage(MSG_ADVANCE, MaxDmgMsg.str().c_str());
  808.      }
  809.     }
  810.     else{//no draw blood
  811.         blood = false;
  812.     }
  813.  
  814.     addCreatureState(tile, attackedCreature, damage, manaDamage, blood);
  815.     onAttackedCreature(tile, attacker, attackedCreature, damage,  true);
  816.  
  817. /*
  818.     if (attackPlayer && attackPlayer->isUsingSpears() && random_range(1,100000) > g_config.SPEAR_LOSE_CHANCE)
  819.     {
  820.         Item* spear = Item::CreateItem(ITEM_SPEAR, 1);
  821.         spear->pos = attackedCreature->pos;
  822.         game->addThing(attackPlayer, spear->pos, spear);
  823.     }
  824. */
  825.  
  826. #ifdef YUR_PVP_ARENA
  827.     for (CreatureVector::iterator it = arenaLosers.begin(); it != arenaLosers.end(); ++it){
  828.         Tile* tile = game->getTile((*it)->pos);
  829.         if (tile){
  830.             game->teleport(*it, tile->getPvpArenaExit());  
  831.         }
  832.         if(Monster* monster = dynamic_cast<Monster*>(*it)){
  833.             if(Tile *tile = game->map->getTile(monster->pos)){    
  834.                 if(tile->isPvpArena()){
  835.                     game->removeCreature(monster);
  836.                 }
  837.             }
  838.         }
  839.     }
  840. #endif //YUR_PVP_ARENA
  841. }
  842.  
  843. void GameState::addCreatureState(Tile* tile, Creature* attackedCreature, int32_t damage, int32_t manaDamage, bool drawBlood)
  844. {
  845.     CreatureState cs;
  846.     cs.damage = damage;
  847.     cs.manaDamage = manaDamage;
  848.     cs.drawBlood = drawBlood;
  849.  
  850.     creaturestates[tile].push_back( make_pair(attackedCreature, cs) );
  851. }
  852.  
  853. void GameState::onAttackedCreature(Tile* tile, Creature *attacker, Creature* attackedCreature, int32_t damage, bool drawBlood)
  854. {
  855.     Player *attackedplayer = dynamic_cast<Player*>(attackedCreature);
  856.     Position CreaturePos = attackedCreature->pos;
  857.  
  858. #ifdef TJ_MONSTER_BLOOD
  859.     bool dead = false;
  860. #endif //TJ_MONSTER_BLOOD
  861.  
  862. #ifdef TR_SUMMONS
  863. //Summon exp share by Yurez
  864.  Player *player = dynamic_cast<Player*>(attacker);
  865.  Creature* attackerMaster = attacker? attacker->getMaster() : NULL;
  866.     if(attackerMaster && dynamic_cast<Player*>(attackerMaster)){//attacker is players summon
  867.         attackedCreature->addInflictedDamage(attacker, damage/2);
  868.         attackedCreature->addInflictedDamage(attackerMaster, damage/2);  
  869.     }// end summon exp share
  870.     else if(player && player->party != 0){
  871.          int32_t partySize = 0;
  872.          SpectatorVec list;
  873.          SpectatorVec::iterator it;
  874.          game->getSpectators(Range(player->pos), list);
  875.          /*Get all specatators around this player
  876.            then check if they are in his party*/
  877.          for(it = list.begin(); it != list.end(); ++it){//find number too div by
  878.             Player* p = dynamic_cast<Player*>(*it);
  879.          if(p && p->party == player->party)//huczu_fix
  880.                partySize++;
  881.          }
  882.          for(it = list.begin(); it != list.end(); ++it){
  883.          Player* p = dynamic_cast<Player*>(*it);
  884.          if(p && p->party == player->party && partySize != 0/*dont div by 0*/)//same party add exp, huczu_fix
  885.             attackedCreature->addInflictedDamage(p, damage/partySize);
  886.          }
  887.     }
  888.     else
  889.         attackedCreature->addInflictedDamage(attacker, damage);
  890. #endif //TR_SUMMONS
  891.  
  892.     if(attackedplayer){
  893.         attackedplayer->sendStats();
  894.     }
  895.     //Remove player?
  896.     if(attackedCreature->health <= 0 && attackedCreature->isRemoved == false)
  897.     {
  898. #ifdef TJ_MONSTER_BLOOD
  899.         dead = true;
  900. #endif //TJ_MONSTER_BLOOD
  901. #ifdef JD_DEATH_LIST
  902.         if (attackedplayer && attacker)
  903.             attackedplayer->addDeath(attacker->getName(), attackedplayer->level, time(0));
  904. #endif //JD_DEATH_LIST
  905.         unsigned char stackpos = tile->getThingStackPos(attackedCreature);
  906.  
  907.  
  908. //tasksys                                  
  909.                             Player* attackingplayer = dynamic_cast<Player*>(attacker);                                    
  910.                             if(attackingplayer && attackedCreature->getName() == attackingplayer->taskmonster && attackingplayer->taskcount < attackingplayer->taskmax)
  911.               {
  912. //                              attackingplayer->taskcount++;
  913.                 std::stringstream info;      
  914.                 std::string mons = attackingplayer->taskmonster;
  915.                 std::transform(mons.begin(), mons.end(), mons.begin(), (int(*)(int))tolower);
  916.                                
  917.                                 if(attackingplayer->taskcount < attackingplayer->taskmax)
  918.                                 {
  919.                                     info << "You have killed " << attackingplayer->taskcount << " out of " << attackingplayer->taskmax << " " << mons << "s.";
  920.                                 }
  921.                                 else
  922.                                 {
  923.                                     info << "You have finished task of killing " << mons << "s. ";
  924.                                 }
  925.                                
  926. //                              attackingplayer->sendTextMessage(MSG_ORANGE, info.str().c_str());
  927.               }
  928.                             //tasksys
  929.  
  930.         //Prepare body
  931.         Item *corpseitem = Item::CreateItem(attackedCreature->getLookCorpse());
  932.         corpseitem->pos = CreaturePos;
  933.         tile->addThing(corpseitem);
  934.        
  935.         #ifdef _DEATH_EVENTS
  936.         if (!attackedplayer)
  937.         {
  938.             Monster* monster = dynamic_cast<Monster*>(attackedCreature);
  939.             Player* killer = dynamic_cast<Player*>(attacker);
  940.  
  941.             if (killer && monster && monster->getAction())
  942.             {
  943.                 actions.onCreatureKill(killer, attackedCreature, corpseitem, monster->getAction());
  944.             }
  945.  
  946.         }
  947. #endif //_DEATH_EVENTS
  948.        
  949.         #ifdef __MIZIAK_CREATURESCRIPTS__
  950.             if(dynamic_cast<Player*>(attacker) && attackedCreature)
  951.             actions.creatureEvent("kill", dynamic_cast<Player*>(attacker), attackedCreature, corpseitem, NULL);
  952.         #endif //__MIZIAK_CREATURESCRIPTS__
  953.        
  954.         //remove creature
  955.         if(attackedplayer){
  956.             actions.luaWalkOff(attackedplayer,attackedplayer->pos,tile->ground->getID(),tile->ground->getUniqueId(),tile->ground->getActionId()); //CHANGE onWalk
  957.             attackedplayer->onThingDisappear(attackedplayer,stackpos);
  958.            
  959.             #ifdef __MIZIAK_CREATURESCRIPTS__
  960.             attackedplayer->dieorlogout = true;
  961.             if(attacker)
  962.             actions.creatureEvent("death", attackedplayer, attacker, corpseitem, NULL);
  963.             #endif //__MIZIAK_CREATURESCRIPTS__
  964.  
  965.  
  966.             attackedplayer->die();        //handles exp/skills/maglevel loss
  967.         }
  968.        
  969.         //Add eventual loot
  970.         Container *lootcontainer = dynamic_cast<Container*>(corpseitem);
  971.         if(lootcontainer) {
  972.             attackedCreature->dropLoot(lootcontainer);
  973.            
  974.             #ifdef HUCZU_LOOT_INFO
  975.             Monster* monster = dynamic_cast<Monster*>(attackedCreature);
  976.             Player* atakujacy = dynamic_cast<Player*>(attacker);
  977.             if(monster && atakujacy){
  978.                 std::stringstream ss, info;
  979.                 //info << "Loot of " << monster->getName() << lootcontainer->getContentDescription() << ".";
  980.                 info << "Loot of " << monster->getName();
  981.                 ss << lootcontainer->getContentDescription() << ".";
  982.                 if(atakujacy->party != 0){
  983.                     for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  984.                         if((*it).second->party == atakujacy->party){
  985.                             if((*it).second->getID() != atakujacy->getID()){
  986.                                 (*it).second->sendToSpecialChannel(atakujacy, SPEAK_CHANNEL_O, ss.str().c_str(), 0x02, info.str().c_str());
  987.                                 //(*it).second->sendTextMessage(MSG_INFO, info.str().c_str());
  988.                             }
  989.                         }
  990.                     }
  991.                 }else{
  992.                     //atakujacy->sendTextMessage(MSG_INFO, info.str().c_str());
  993.                     atakujacy->sendToSpecialChannel(atakujacy, SPEAK_CHANNEL_O, ss.str().c_str(), 0x02, info.str().c_str());
  994.                 }
  995.             }
  996.             #endif //HUCZU_LOOT_INFO
  997.         }
  998.  
  999.         #ifdef HUCZU_MONSTER_QUEST
  1000.         Monster* monster = dynamic_cast<Monster*>(attackedCreature);
  1001.         Player* atakujacy = dynamic_cast<Player*>(attacker);
  1002.         int32_t value, kills;
  1003.        
  1004.         if(monster && atakujacy && monster->getQuestId() != 0){
  1005.                    
  1006.            if(monster->getQuestId() == 2 && atakujacy->getStorageValue(100, value) == 1){
  1007.              int32_t killsprzed = atakujacy->getQuestKills(2);
  1008.              atakujacy->addQuestKills(2, killsprzed+1);
  1009.            }
  1010.            
  1011.         }
  1012.         #endif //HUCZU_MONSTER_QUEST
  1013.  
  1014.  
  1015.         game->removeCreature(attackedCreature);
  1016.         // Update attackedCreature pos because contains
  1017.         //  temple position for players
  1018.         attackedCreature->pos = CreaturePos;
  1019.  
  1020.         //add body
  1021.         game->sendAddThing(NULL,corpseitem->pos,corpseitem);
  1022.  
  1023.         if(attackedplayer){
  1024.             std::stringstream ss;
  1025.             ss << corpseitem->getDescription(false);
  1026.  
  1027.             ss << "You recognize " << attackedplayer->getName() << ". ";
  1028.             if(attacker){
  1029.                 ss << (attackedplayer->getSex() == PLAYERSEX_FEMALE ? "She" : "He") << " was killed by ";
  1030.  
  1031.                 Player *attackerplayer = dynamic_cast<Player*>(attacker);
  1032.                 if(attackerplayer) {
  1033.                     ss << attacker->getName();
  1034.                 }
  1035.                 else {
  1036.                     std::string creaturename = attacker->getName();
  1037.                     std::transform(creaturename.begin(), creaturename.end(), creaturename.begin(), (int32_t(*)(int32_t))tolower);
  1038.                     ss << article(creaturename);
  1039.                 }
  1040.             }
  1041.  
  1042.             //set body special description
  1043.             corpseitem->setSpecialDescription(ss.str());
  1044.             //send corpse to the dead player. It is not in spectator list
  1045.             // because was removed
  1046.             attackedplayer->onThingAppear(corpseitem);
  1047.         }
  1048.         game->startDecay(corpseitem);
  1049.  
  1050.         //Get all creatures that will gain xp from this kill..
  1051.         CreatureState* attackedCreatureState = NULL;
  1052.         std::vector<long> creaturelist;
  1053.        
  1054.             if(!(dynamic_cast<Player*>(attackedCreature) && game->getWorldType() != WORLD_TYPE_PVP_ENFORCED)){
  1055.             creaturelist = attackedCreature->getInflicatedDamageCreatureList();
  1056.             CreatureStateVec& creatureStateVec = creaturestates[tile];
  1057.             for(CreatureStateVec::iterator csIt = creatureStateVec.begin(); csIt != creatureStateVec.end(); ++csIt) {
  1058.                 if(csIt->first == attackedCreature) {
  1059.                     attackedCreatureState = &csIt->second;
  1060.                     break;
  1061.                 }
  1062.             }
  1063.         }
  1064.  
  1065.         if(attackedCreatureState) { //should never be NULL..
  1066.             //Add experience
  1067.             for(std::vector<long>::const_iterator iit = creaturelist.begin(); iit != creaturelist.end(); ++iit) {
  1068.                 Creature* gainExpCreature = game->getCreatureByID(*iit);
  1069.                 if(gainExpCreature) {
  1070.                     exp_t gainedExperience = attackedCreature->getGainedExperience(gainExpCreature);
  1071.                     if(gainedExperience <= 0)
  1072.                         continue;
  1073.  
  1074.                     Player *gainExpPlayer = dynamic_cast<Player*>(gainExpCreature);
  1075.  
  1076.                     if(gainExpPlayer) {
  1077.                             gainExpPlayer->addExp(gainedExperience);
  1078.                             if(gainExpPlayer && attackedCreature->getName() == gainExpPlayer->taskmonster && gainExpPlayer->taskcount < gainExpPlayer->taskmax)
  1079.               {
  1080.                                 gainExpPlayer->taskcount++;
  1081.                 std::stringstream info;      
  1082.                 std::string mons = gainExpPlayer->taskmonster;
  1083.                 std::transform(mons.begin(), mons.end(), mons.begin(), (int(*)(int))tolower);
  1084.                                
  1085.                                 if(gainExpPlayer->taskcount < gainExpPlayer->taskmax)
  1086.                                 {
  1087.                                     info << "You have killed " << gainExpPlayer->taskcount << " out of " << gainExpPlayer->taskmax << " " << mons << "s.";
  1088.                                 }
  1089.                                 else
  1090.                                 {
  1091.                                     info << "You have finished task of killing " << mons << "s. ";
  1092.                                 }
  1093.                                 gainExpPlayer->sendTextMessage(MSG_ORANGE, info.str().c_str());
  1094.               }
  1095.  
  1096.  
  1097.  
  1098.                     }
  1099.                     //Need to add this creature and all that can see it to spectators, unless they already added
  1100.                     SpectatorVec creaturelist;
  1101.                     game->getSpectators(Range(gainExpCreature->pos, true), creaturelist);
  1102.  
  1103.                     for(SpectatorVec::const_iterator cit = creaturelist.begin(); cit != creaturelist.end(); ++cit) {
  1104.                         if(std::find(spectatorlist.begin(), spectatorlist.end(), *cit) == spectatorlist.end()) {
  1105.                             spectatorlist.push_back(*cit);
  1106.                         }
  1107.                     }
  1108.  
  1109.                     //Add creature to attackerlist
  1110.                     attackedCreatureState->attackerlist.push_back(gainExpCreature);
  1111.                 }
  1112.             }
  1113.         }
  1114.  
  1115.         Player *player = dynamic_cast<Player*>(attacker);
  1116.         if(player){
  1117.             player->sendStats();
  1118.         }
  1119.  
  1120.         if(attackedCreature && attackedCreature->getMaster() != NULL) {
  1121.             attackedCreature->getMaster()->removeSummon(attackedCreature);
  1122.         }
  1123.     }
  1124.  
  1125.  
  1126.     //Add blood?
  1127. #ifdef TJ_MONSTER_BLOOD
  1128.     if((drawBlood || attackedCreature->health <= 0) && damage > 0 && attackedCreature->bloodsplash != 255) {
  1129.         Item* splash = Item::CreateItem(dead? ITEM_POOL : ITEM_SPLASH, attackedCreature->bloodsplash);
  1130.         game->addThing(NULL, CreaturePos, splash);
  1131.         game->startDecay(splash);
  1132.         game->updateTile(CreaturePos);
  1133.     }
  1134. #else
  1135.     if((drawBlood || attackedCreature->health <= 0) && damage > 0) {
  1136.         Item* splash = Item::CreateItem(ITEM_SPLASH, FLUID_BLOOD);
  1137.         game->addThing(NULL, CreaturePos, splash);
  1138.         game->startDecay(splash);
  1139.         game->updateTile(CreaturePos);
  1140.     }
  1141. #endif //TJ_MONSTER_BLOOD
  1142. }
  1143.  
  1144.  
  1145. Game::Game()
  1146. {
  1147.     eventIdCount = 1000;
  1148.     this->game_state = GAME_STATE_NORMAL;
  1149.     this->map = NULL;
  1150.     this->worldType = WORLD_TYPE_PVP;
  1151.     OTSYS_THREAD_LOCKVARINIT(gameLock);
  1152.     OTSYS_THREAD_LOCKVARINIT(eventLock);
  1153.     OTSYS_THREAD_LOCKVARINIT(AutoID::autoIDLock);
  1154. #if defined __EXCEPTION_TRACER__
  1155.     OTSYS_THREAD_LOCKVARINIT(maploadlock);
  1156. #endif
  1157.     OTSYS_THREAD_SIGNALVARINIT(eventSignal);
  1158.     BufferedPlayers.clear();
  1159.     OTSYS_CREATE_THREAD(eventThread, this);
  1160.  
  1161. #ifdef __DEBUG_CRITICALSECTION__
  1162.     OTSYS_CREATE_THREAD(monitorThread, this);
  1163. #endif
  1164.  
  1165.     addEvent(makeTask(DECAY_INTERVAL, boost::bind(&Game::checkDecay,this,DECAY_INTERVAL)));
  1166.  
  1167. #ifdef CVS_DAY_CYCLE
  1168.     int32_t daycycle = 3600;
  1169.     light_hour_delta = 1440*10/daycycle;
  1170.     light_hour = 0;
  1171.     lightlevel = LIGHT_LEVEL_NIGHT;
  1172.     light_state = LIGHT_STATE_NIGHT;
  1173.     addEvent(makeTask(10000, boost::bind(&Game::checkLight, this, 10000)));
  1174. #endif //CVS_DAY_CYCLE
  1175. }
  1176.  
  1177.  
  1178. Game::~Game()
  1179. {
  1180.     if(map) {
  1181.         delete map;
  1182.     }
  1183. }
  1184.  
  1185. void Game::setWorldType(enum_world_type type)
  1186. {
  1187.     this->worldType = type;
  1188. }
  1189.  
  1190. enum_game_state Game::getGameState()
  1191. {
  1192.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::getGameState()");
  1193.     return game_state;
  1194. }
  1195.  
  1196. int32_t Game::loadMap(std::string filename, std::string filekind) {
  1197.     if(!map)
  1198.         map = new Map;
  1199.  
  1200.     max_players = atoi(g_config.getGlobalString("maxplayers").c_str());
  1201.     distanceToKill = atoi(g_config.getGlobalString("dist", "50").c_str());
  1202.     return map->loadMap(filename, filekind);
  1203. }
  1204.  
  1205.  
  1206.  
  1207. /*****************************************************************************/
  1208.  
  1209. #ifdef __DEBUG_CRITICALSECTION__
  1210.  
  1211. OTSYS_THREAD_RETURN Game::monitorThread(void *p)
  1212. {
  1213.   Game* _this = (Game*)p;
  1214.  
  1215.     while (true) {
  1216.         OTSYS_SLEEP(6000);
  1217.  
  1218.         int32_t ret = OTSYS_THREAD_LOCKEX(_this->gameLock, 60 * 2 * 1000);
  1219.         if(ret != OTSYS_THREAD_TIMEOUT) {
  1220.             OTSYS_THREAD_UNLOCK(_this->gameLock, NULL);
  1221.             continue;
  1222.         }
  1223.  
  1224.         bool file = false;
  1225.         std::ostream *outdriver;
  1226.         std::cout << "Error: generating critical section file..." <<std::endl;
  1227.         std::ofstream output("deadlock.txt",std::ios_base::app);
  1228.         if(output.fail()){
  1229.             outdriver = &std::cout;
  1230.             file = false;
  1231.         }
  1232.         else{
  1233.             file = true;
  1234.             outdriver = &output;
  1235.         }
  1236.  
  1237.         time_t rawtime;
  1238.         time(&rawtime);
  1239.         *outdriver << "*****************************************************" << std::endl;
  1240.         *outdriver << "Error report - " << std::ctime(&rawtime) << std::endl;
  1241.  
  1242.         OTSYS_THREAD_LOCK_CLASS::LogList::iterator it;
  1243.         for(it = OTSYS_THREAD_LOCK_CLASS::loglist.begin(); it != OTSYS_THREAD_LOCK_CLASS::loglist.end(); ++it) {
  1244.             *outdriver << (it->lock ? "lock - " : "unlock - ") << it->str
  1245.                 << " threadid: " << it->threadid
  1246.                 << " time: " << it->time
  1247.                 << " ptr: " << it->mutexaddr
  1248.                 << std::endl;
  1249.         }
  1250.  
  1251.         *outdriver << "*****************************************************" << std::endl;
  1252.         if(file)
  1253.             ((std::ofstream*)outdriver)->close();
  1254.  
  1255.         std::cout << "Error report generated. Killing server." <<std::endl;
  1256.         exit(1); //force exit
  1257.     }
  1258. }
  1259. #endif
  1260.  
  1261. OTSYS_THREAD_RETURN Game::eventThread(void *p)
  1262. {
  1263. #if defined __EXCEPTION_TRACER__
  1264.     ExceptionHandler eventExceptionHandler;
  1265.     eventExceptionHandler.InstallHandler();
  1266. #endif
  1267.  
  1268.   Game* _this = (Game*)p;
  1269.  
  1270.   // basically what we do is, look at the first scheduled item,
  1271.   // and then sleep until it's due (or if there is none, sleep until we get an event)
  1272.   // of course this means we need to get a notification if there are new events added
  1273.   while (true)
  1274.   {
  1275. #ifdef __DEBUG__EVENTSCHEDULER__
  1276.     std::cout << "schedulercycle start..." << std::endl;
  1277. #endif
  1278.  
  1279.     SchedulerTask* task = NULL;
  1280.         bool runtask = false;
  1281.  
  1282.     // check if there are events waiting...
  1283.     OTSYS_THREAD_LOCK(_this->eventLock, "eventThread()")
  1284.  
  1285.         int32_t ret;
  1286.     if (_this->eventList.size() == 0) {
  1287.       // unlock mutex and wait for signal
  1288.       ret = OTSYS_THREAD_WAITSIGNAL(_this->eventSignal, _this->eventLock);
  1289.     } else {
  1290.       // unlock mutex and wait for signal or timeout
  1291.       ret = OTSYS_THREAD_WAITSIGNAL_TIMED(_this->eventSignal, _this->eventLock, _this->eventList.top()->getCycle());
  1292.     }
  1293.     // the mutex is locked again now...
  1294.     if (ret == OTSYS_THREAD_TIMEOUT) {
  1295.       // ok we had a timeout, so there has to be an event we have to execute...
  1296. #ifdef __DEBUG__EVENTSCHEDULER__
  1297.       std::cout << "event found at " << OTSYS_TIME() << " which is to be scheduled at: " << _this->eventList.top()->getCycle() << std::endl;
  1298. #endif
  1299.       task = _this->eventList.top();
  1300.       _this->eventList.pop();
  1301.         }
  1302.  
  1303.         if(task) {
  1304.             std::map<uint32_t, SchedulerTask*>::iterator it = _this->eventIdMap.find(task->getEventId());
  1305.             if(it != _this->eventIdMap.end()) {
  1306.                 _this->eventIdMap.erase(it);
  1307.                 runtask = true;
  1308.             }
  1309.         }
  1310.  
  1311.         OTSYS_THREAD_UNLOCK(_this->eventLock, "eventThread()");
  1312.     if (task) {
  1313.             if(runtask) {
  1314.                 (*task)(_this);
  1315.             }
  1316.             delete task;
  1317.     }
  1318.   }
  1319. #if defined __EXCEPTION_TRACER__
  1320.     eventExceptionHandler.RemoveHandler();
  1321. #endif
  1322.  
  1323. }
  1324.  
  1325. uint32_t Game::addEvent(SchedulerTask* event) {
  1326.   bool do_signal = false;
  1327.   OTSYS_THREAD_LOCK(eventLock, "addEvent()")
  1328.  
  1329.     if(event->getEventId() == 0) {
  1330.         ++eventIdCount;
  1331.         event->setEventId(eventIdCount);
  1332.     }
  1333.  
  1334. #ifdef __DEBUG__EVENTSCHEDULER__
  1335.         std::cout << "addEvent - " << event->getEventId() << std::endl;
  1336. #endif
  1337.  
  1338.     eventIdMap[event->getEventId()] = event;
  1339.  
  1340.     /*
  1341.     if (eventList.empty() ||  *event < *eventList.top())
  1342.     do_signal = true;
  1343.     */
  1344.  
  1345.     bool isEmpty = eventList.empty();
  1346.     eventList.push(event);
  1347.  
  1348.     if(isEmpty || *event < *eventList.top())
  1349.         do_signal = true;
  1350.  
  1351.     /*
  1352.     if (eventList.empty() ||  *event < *eventList.top())
  1353.     do_signal = true;
  1354.     */
  1355.  
  1356.   OTSYS_THREAD_UNLOCK(eventLock, "addEvent()")
  1357.  
  1358.     if (do_signal)
  1359.         OTSYS_THREAD_SIGNAL_SEND(eventSignal);
  1360.  
  1361.     return event->getEventId();
  1362. }
  1363.  
  1364. bool Game::stopEvent(uint32_t eventid) {
  1365.     if(eventid == 0)
  1366.         return false;
  1367.  
  1368.   OTSYS_THREAD_LOCK(eventLock, "stopEvent()")
  1369.  
  1370.     std::map<uint32_t, SchedulerTask*>::iterator it = eventIdMap.find(eventid);
  1371.     if(it != eventIdMap.end()) {
  1372.  
  1373. #ifdef __DEBUG__EVENTSCHEDULER__
  1374.         std::cout << "stopEvent - eventid: " << eventid << "/" << it->second->getEventId() << std::endl;
  1375. #endif
  1376.  
  1377.         //it->second->setEventId(0); //invalidate the event
  1378.         eventIdMap.erase(it);
  1379.  
  1380.       OTSYS_THREAD_UNLOCK(eventLock, "stopEvent()")
  1381.         return true;
  1382.     }
  1383.  
  1384.   OTSYS_THREAD_UNLOCK(eventLock, "stopEvent()")
  1385.     return false;
  1386. }
  1387.  
  1388. /*****************************************************************************/
  1389.  
  1390. uint32_t Game::getPlayersOnline() {return (uint32_t)Player::listPlayer.list.size();};
  1391. uint32_t Game::getMonstersOnline() {return (uint32_t)Monster::listMonster.list.size();};
  1392. uint32_t Game::getNpcsOnline() {return (uint32_t)Npc::listNpc.list.size();};
  1393. uint32_t Game::getCreaturesOnline() {return (uint32_t)listCreature.list.size();};
  1394.  
  1395. Tile* Game::getTile(unsigned short _x, unsigned short _y, unsigned char _z)
  1396. {
  1397.     return map->getTile(_x, _y, _z);
  1398. }
  1399.  
  1400. Tile* Game::getTile(const Position& pos)
  1401. {
  1402.     return map->getTile(pos);
  1403. }
  1404.  
  1405. void Game::setTile(unsigned short _x, unsigned short _y, unsigned char _z, unsigned short groundId)
  1406. {
  1407.     map->setTile(_x, _y, _z, groundId);
  1408. }
  1409.  
  1410. Creature* Game::getCreatureByID(uint32_t id)
  1411. {
  1412.     if(id == 0)
  1413.         return NULL;
  1414.  
  1415.     AutoList<Creature>::listiterator it = listCreature.list.find(id);
  1416.     if(it != listCreature.list.end()) {
  1417.         return (*it).second;
  1418.     }
  1419.  
  1420.     return NULL; //just in case the player doesnt exist
  1421. }
  1422.  
  1423. Player* Game::getPlayerByID(uint32_t id)
  1424. {
  1425.     if(id == 0)
  1426.         return NULL;
  1427.  
  1428.     AutoList<Player>::listiterator it = Player::listPlayer.list.find(id);
  1429.     if(it != Player::listPlayer.list.end()) {
  1430.         return (*it).second;
  1431.     }
  1432.  
  1433.     return NULL; //just in case the player doesnt exist
  1434. }
  1435.  
  1436. Creature* Game::getCreatureByName(const std::string &s)
  1437. {
  1438.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::getCreatureByName()");
  1439.  
  1440.     std::string txt1 = s;
  1441.     std::transform(txt1.begin(), txt1.end(), txt1.begin(), upchar);
  1442.     for(AutoList<Creature>::listiterator it = listCreature.list.begin(); it != listCreature.list.end(); ++it){
  1443.         std::string txt2 = (*it).second->getName();
  1444.         std::transform(txt2.begin(), txt2.end(), txt2.begin(), upchar);
  1445.         if(txt1 == txt2)
  1446.             return it->second;
  1447.     }
  1448.  
  1449.     return NULL; //just in case the creature doesnt exist
  1450. }
  1451.  
  1452. Player* Game::getPlayerByName(const std::string &s)
  1453. {
  1454.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::getPlayerByName()");
  1455.  
  1456.     std::string txt1 = s;
  1457.     std::transform(txt1.begin(), txt1.end(), txt1.begin(), upchar);
  1458.     for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  1459.         std::string txt2 = (*it).second->getName();
  1460.         std::transform(txt2.begin(), txt2.end(), txt2.begin(), upchar);
  1461.         if(txt1 == txt2)
  1462.             return it->second;
  1463.     }
  1464.  
  1465.     return NULL; //just in case the player doesnt exist
  1466. }
  1467.  
  1468. bool Game::placeCreature(Position &pos, Creature* c
  1469. #ifdef YUR_LOGIN_QUEUE
  1470.                          , int32_t* placeInQueue
  1471. #endif //YUR_LOGIN_QUEUE
  1472.                         )
  1473. {
  1474.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::placeCreature()");
  1475.     bool success = false;
  1476.     Player *p = dynamic_cast<Player*>(c);
  1477.     Monster *monsterzin = dynamic_cast<Monster*>(c);
  1478.    
  1479. #ifdef YUR_LOGIN_QUEUE
  1480.     if (!p || c->access >= g_config.ACCESS_ENTER ||
  1481. #ifdef YUR_PREMIUM_PROMOTION
  1482.             (p->isPremmium() && !g_config.QUEUE_PREMMY) ||
  1483. #endif //YUR_PREMIUM_PROMOTION
  1484.             loginQueue.login(p->accountNumber, getPlayersOnline(), max_players, placeInQueue))
  1485.     {
  1486. #else //YUR_LOGIN_QUEUE
  1487.     if (!p || c->access >= g_config.ACCESS_ENTER || getPlayersOnline() < max_players)
  1488.     {
  1489. #endif //YUR_LOGIN_QUEUE
  1490.  
  1491.         success = map->placeCreature(pos, c);
  1492.         if(success)
  1493.         {
  1494.             c->useThing();
  1495.  
  1496.             c->setID();
  1497.             //std::cout << "place: " << c << " " << c->getID() << std::endl;
  1498.             listCreature.addList(c);
  1499.             c->addList();
  1500.             c->isRemoved = false;
  1501.  
  1502.             sendAddThing(NULL,c->pos,c);
  1503.  
  1504.             if(p)
  1505.             {
  1506.                  checkRecord();
  1507. #ifdef __DEBUG_PLAYERS__
  1508.                 std::cout << (uint32_t)getPlayersOnline() << " players online." << std::endl;
  1509. #endif
  1510. #ifdef YUR_GUILD_SYSTEM
  1511.                 Guilds::ReloadGuildInfo(p);
  1512. #endif //YUR_GUILD_SYSTEM
  1513. /*#ifdef ELEM_VIP_LIST
  1514.                 vipLogin(p);
  1515. #endif //ELEM_VIP_LIST*/
  1516.             }
  1517.  
  1518.             if(p){
  1519.                 c->eventCheck = addEvent(makeTask(1000, std::bind2nd(std::mem_fun(&Game::checkCreature), c->getID())));
  1520.             }
  1521.             else{
  1522.                 c->eventCheck = addEvent(makeTask(1000, std::bind2nd(std::mem_fun(&Game::checkCreature), c->getID())));
  1523.             }
  1524.  
  1525.             //c->eventCheckAttacking = addEvent(makeTask(2000, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), c->getID())));
  1526.         }
  1527.     }
  1528.     else {
  1529.         //we cant add the player, server is full
  1530.         success = false;
  1531.     }
  1532.    
  1533.      #ifdef __MIZIAK_CREATURESCRIPTS__
  1534.            if(p)
  1535.        actions.creatureEvent("login", p, NULL, NULL, NULL);
  1536.        #endif //__MIZIAK_CREATURESCRIPTS__
  1537.  
  1538.  
  1539.   if(monsterzin){
  1540.      c->masterPos.x = c->pos.x;
  1541.      c->masterPos.y = c->pos.y;
  1542.      c->masterPos.z = c->pos.z;        
  1543.   }
  1544.   return success;
  1545. }
  1546.  
  1547. bool Game::removeCreature(Creature* c)
  1548. {
  1549.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::removeCreature()");
  1550.     if(c->isRemoved == true)
  1551.         return false;
  1552. #ifdef __DEBUG__
  1553.     std::cout << "removing creature "<< std::endl;
  1554. #endif
  1555.  
  1556. #ifdef __MIZIAK_CREATURESCRIPTS__
  1557.     Player* pc = dynamic_cast<Player*>(c);
  1558.     if(pc)
  1559.         if(!pc->dieorlogout)
  1560.             actions.creatureEvent("logout", pc, NULL, NULL, NULL);
  1561. #endif //__MIZIAK_CREATURESCRIPTS__
  1562.  
  1563.     if(!removeThing(NULL,c->pos,c))
  1564.         return false;
  1565.  
  1566.     //std::cout << "remove: " << c << " " << c->getID() << std::endl;
  1567.     listCreature.removeList(c->getID());
  1568.     c->removeList();
  1569.     c->isRemoved = true;
  1570.  
  1571. if(g_config.SUMMON_BODIES){
  1572.     c->isRemoved = true;
  1573.  
  1574. Creature *summon = NULL;
  1575. for(std::list<Creature*>::iterator cit = c->summons.begin(); cit != c->summons.end(); ++cit) {
  1576. summon = (*cit);
  1577. Position CreaturePos = summon->pos;
  1578. Tile *tile = map->getTile(CreaturePos);
  1579. Item *corpseitem = Item::CreateItem(summon->getLookCorpse());
  1580. corpseitem->pos = CreaturePos; /*summoned bodies by Cayan*/
  1581. tile->addThing(corpseitem);
  1582. removeCreature(summon);
  1583. updateTile(CreaturePos);
  1584. }
  1585. }
  1586. else
  1587. {
  1588.  c->isRemoved = true;
  1589.  
  1590. //for(std::list<Creature*>::iterator cit = c->summons.begin(); cit != c->summons.end(); ++cit) {
  1591. //removeCreature(*cit);
  1592. //}
  1593. }
  1594.  
  1595.  
  1596.     stopEvent(c->eventCheck);
  1597.     stopEvent(c->eventCheckAttacking);
  1598.     stopEvent(c->eventCheckFollow);
  1599.  
  1600.     Player* player = dynamic_cast<Player*>(c);
  1601.     if(player){
  1602.  
  1603. #ifdef HUCZU_SKULLS
  1604.         for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  1605.            Player *on = dynamic_cast<Player*>(it->second);
  1606.            if(on && player->isYellowTo(on)){
  1607.            on->removeFromYellowList(player);
  1608.            }
  1609.            if(on && on->hasAttacked(player)){
  1610.            on->removeFromAttakedList(player);
  1611.            }
  1612.            player->clearAttakedList();
  1613.            player->clearYellowList();
  1614.         }
  1615.        
  1616.         if(player->party != 0)
  1617.             LeaveParty(player);
  1618. #endif //HUCZU_SKULLS
  1619.  
  1620.         if(player->tradePartner != 0) {
  1621.             playerCloseTrade(player);
  1622.         }
  1623.         if(player->eventAutoWalk)
  1624.             stopEvent(player->eventAutoWalk);
  1625.            
  1626.         Tile* fromT = getTile(player->pos);
  1627. if(fromT && fromT->ground)
  1628.         actions.luaWalkOff(player,player->pos,fromT->ground->getID(),fromT->ground->getUniqueId(),fromT->ground->getActionId());
  1629.          
  1630.         g_chat.removeUserFromAllChannels(player);
  1631.         if(!IOPlayer::instance()->savePlayer(player)){
  1632.             std::cout << "Error while saving player: " << player->getName() << std::endl;
  1633.         }
  1634.         std::cout << (uint32_t)getPlayersOnline() << " players online." << std::endl;
  1635.        
  1636.  
  1637. /*#ifdef ELEM_VIP_LIST
  1638.         vipLogout(c->getName());
  1639. #endif //ELEM_VIP_LIST*/
  1640.        
  1641.  
  1642.        }
  1643.     this->FreeThing(c);
  1644.     return true;
  1645. }
  1646.  
  1647. void Game::thingMove(Creature *creature, Thing *thing,
  1648.     unsigned short to_x, unsigned short to_y, unsigned char to_z, unsigned char count)
  1649. {
  1650.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 1");
  1651.  
  1652.     Tile *fromTile = map->getTile(thing->pos);
  1653.  
  1654.     if (fromTile)
  1655.     {
  1656.         int32_t oldstackpos = fromTile->getThingStackPos(thing);
  1657.         thingMoveInternal(creature, thing->pos.x, thing->pos.y, thing->pos.z, oldstackpos, 0, to_x, to_y, to_z, count);
  1658.     }
  1659. }
  1660.  
  1661.  
  1662. void Game::thingMove(Creature *creature, unsigned short from_x, unsigned short from_y, unsigned char from_z,
  1663.     unsigned char stackPos, unsigned short itemid, unsigned short to_x, unsigned short to_y, unsigned char to_z, unsigned char count)
  1664. {
  1665.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 2");
  1666.  
  1667.     Tile *fromTile = getTile(from_x, from_y, from_z);
  1668.     if(!fromTile)
  1669.         return;
  1670.        
  1671.     #ifdef FIXY
  1672.     if(dynamic_cast<Player*>(creature) && fromTile && !fromTile->ground) {
  1673.       dynamic_cast<Player*>(creature)->sendCancelWalk();
  1674.       return;
  1675.      }
  1676.     #endif //FIXY
  1677.    
  1678.             Tile *toTile = getTile(to_x, to_y, to_z);
  1679.     if(!toTile)
  1680.         return;
  1681.        
  1682.         #ifdef FIXY
  1683.     if (toTile->isHouse() && !fromTile->isHouse())
  1684.         return;
  1685.         #endif //FIXY
  1686.  
  1687.     Thing* thing = fromTile->getThingByStackPos(stackPos);
  1688.     if(!thing)
  1689.         return;
  1690.  
  1691.     Item* item = dynamic_cast<Item*>(thing);
  1692.  
  1693.     if(item && (item->getID() != itemid || item != fromTile->getTopDownItem()))
  1694.         return;
  1695.  
  1696.     thingMoveInternal(creature, from_x, from_y, from_z, stackPos, itemid, to_x, to_y, to_z, count);
  1697. }
  1698.  
  1699. //container/inventory to container/inventory
  1700. void Game::thingMove(Player *player,
  1701.     unsigned char from_cid, unsigned char from_slotid, unsigned short itemid, bool fromInventory,
  1702.     unsigned char to_cid, unsigned char to_slotid, bool toInventory,
  1703.     unsigned char count)
  1704. {
  1705.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 3");
  1706.  
  1707.     thingMoveInternal(player, from_cid, from_slotid, itemid, fromInventory,
  1708.         to_cid, to_slotid, toInventory, count);
  1709. }
  1710.  
  1711. //container/inventory to ground
  1712. void Game::thingMove(Player *player,
  1713.     unsigned char from_cid, unsigned char from_slotid, unsigned short itemid, bool fromInventory,
  1714.     const Position& toPos, unsigned char count)
  1715. {
  1716.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 4");
  1717. Container *fromContainer = player->getContainer(from_cid);
  1718.     if(fromContainer && !fromContainer->shop.empty())
  1719.         return;
  1720.    
  1721.     #ifdef FIXY
  1722.     Tile *toTile = getTile(toPos.x, toPos.y, toPos.z);
  1723.     if(!toTile)
  1724.         return;
  1725.    
  1726.     if (player) {
  1727.         Tile *fromTile = getTile(player->pos);
  1728.         if(!fromTile->isHouse() && toTile->isHouse())  
  1729.             return;
  1730.     }
  1731. #endif //FIXY
  1732.  
  1733.     thingMoveInternal(player, from_cid, from_slotid, itemid, fromInventory, toPos, count);
  1734. }
  1735.  
  1736. //ground to container/inventory
  1737. void Game::thingMove(Player *player,
  1738.     const Position& fromPos, unsigned char stackPos, unsigned short itemid,
  1739.     unsigned char to_cid, unsigned char to_slotid, bool toInventory,
  1740.     unsigned char count)
  1741. {
  1742.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 5");
  1743.     thingMoveInternal(player, fromPos, stackPos, itemid, to_cid, to_slotid, toInventory, count);
  1744. }
  1745.  
  1746. #ifdef FIXY
  1747. bool Game::onPrepareMoveThing(Creature* player, /*const*/ Thing* thing,
  1748. const Position& fromPos, const Position& toPos, int32_t count)
  1749. {
  1750.     const Creature* movingCreature = dynamic_cast<const Creature*>(thing);
  1751.     Player *playa = dynamic_cast<Player*>(thing);
  1752.    
  1753.         if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) &&
  1754.         ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  1755.         {
  1756.         player->sendCancel("Destination is out of reach.");
  1757.         return false;
  1758.         }
  1759.  //RZUCANIE GM PO EKRANIE?
  1760.  else if( ((abs(fromPos.x - toPos.x) > thing->throwRange) || (abs(fromPos.y - toPos.y) > thing->throwRange)
  1761.   || (fromPos.z != toPos.z)) && player->access >= g_config.ACCESS_REMOTE) {
  1762.         if(player == thing){
  1763.            teleport(player,toPos);
  1764.            
  1765.            if(!playa->gmInvisible){
  1766.            globalMagicEffect(fromPos, NM_ME_PUFF);
  1767.            globalMagicEffect(toPos, NM_ME_ENERGY_AREA);
  1768.            }
  1769.            else
  1770.            {    
  1771.            playa->sendMagicEffect(fromPos, NM_ME_PUFF);
  1772.            playa->sendMagicEffect(toPos, NM_ME_ENERGY_AREA);
  1773.            }
  1774.            }
  1775.         else
  1776.            teleport(thing,toPos);
  1777.     }  
  1778.  
  1779.  
  1780.     else if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) && ((abs(fromPos.x - toPos.x) > thing->throwRange || abs(fromPos.y - toPos.y) > thing->throwRange || (abs(fromPos.z - toPos.z+1) > thing->throwRange)))) {
  1781.         player->sendCancel("Destination is out of reach.");
  1782.         return false;
  1783.     }
  1784.  
  1785.          
  1786. else if(player->access < g_config.ACCESS_REMOTE && movingCreature && fromPos.z != toPos.z){
  1787.     player->sendCancel("Destination is out of reach.");
  1788.     return false;
  1789. }
  1790.  
  1791.     else {
  1792.         const Item* item = dynamic_cast<const Item*>(thing);
  1793.         if(item) {
  1794.           if(item->getID() == ITEM_FOOTBALL &&
  1795.                player->access < g_config.getGlobalNumber("accessfootball", 3) && (
  1796.                (abs(player->pos.x - toPos.x) > 2) ||
  1797.                (abs(player->pos.y - toPos.y) > 2) ||
  1798.                (player->pos.z != fromPos.z))
  1799.                 ){
  1800.                         player->sendCancel("Nie mozesz tak daleko kopnac.");
  1801.                         return false;
  1802.             }
  1803.             int32_t blockstate = 0;
  1804.             if(item->isBlocking())
  1805.                 blockstate |= BLOCK_SOLID;
  1806.  
  1807.             if(item->isPickupable() || !item->isNotMoveable())
  1808.                 blockstate |= BLOCK_PICKUPABLE;
  1809.  
  1810.             if(blockstate != 0) {
  1811.                 switch(map->canThrowObjectTo(fromPos, toPos, blockstate)) {
  1812.                     case RET_NOERROR:
  1813.                         return true;
  1814.                         break;
  1815.  
  1816.                     case RET_CANNOTTHROW:
  1817.                         player->sendCancel("Nie mozesz tam rzucic.");
  1818.                         return false;
  1819.                         break;
  1820.  
  1821.                     case RET_CREATUREBLOCK:
  1822.                     case RET_NOTENOUGHROOM:
  1823. #ifdef KOSZ
  1824.                       if(item->getID() != ITEM_DUSTBIN){
  1825.                         player->sendCancel("Przykro mi, nie ma miejsca.");
  1826.                         return false;
  1827.                       }
  1828. #else
  1829.                         player->sendCancel("Przykro mi, nie ma miejsca.");
  1830.                         return false;
  1831. #endif //KOSZ
  1832.                         break;
  1833.  
  1834.                     default:
  1835.                         player->sendCancel("Sorry not possible.");
  1836.                         return false;
  1837.                         break;
  1838.                 }
  1839.             }
  1840.         }
  1841.     }
  1842.  
  1843.     return true;
  1844. }
  1845. #else //FIXY
  1846. bool Game::onPrepareMoveThing(Creature* player, const Thing* thing,
  1847.     const Position& fromPos, const Position& toPos, int32_t count)
  1848. {
  1849.     if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) &&
  1850.         ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  1851.     {
  1852.         player->sendCancel("Za daleko...");
  1853.         return false;
  1854.     }
  1855.     else if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) &&
  1856.         ((abs(fromPos.x - toPos.x) > thing->throwRange) || (abs(fromPos.y - toPos.y) > thing->throwRange)
  1857.         || (fromPos.z != toPos.z) /*TODO: Make it possible to throw items to different floors ))*/
  1858.     {
  1859.         player->sendCancel("Destination is out of reach.");
  1860.         return false;
  1861.     }
  1862.     else {
  1863.         const Item* item = dynamic_cast<const Item*>(thing);
  1864.         if(item) {
  1865.             int32_t blockstate = 0;
  1866.             if(item->isBlocking())
  1867.                 blockstate |= BLOCK_SOLID;
  1868.  
  1869.             if(item->isPickupable() || !item->isNotMoveable())
  1870.                 blockstate |= BLOCK_PICKUPABLE;
  1871.  
  1872.             if(blockstate != 0) {
  1873.                 switch(map->canThrowObjectTo(fromPos, toPos, blockstate)) {
  1874.                     case RET_NOERROR:
  1875.                         return true;
  1876.                         break;
  1877.  
  1878.                     case RET_CANNOTTHROW:
  1879.                         player->sendCancel("Nie mozesz tam rzucic.");
  1880.                         return false;
  1881.                         break;
  1882.  
  1883.                     case RET_CREATUREBLOCK:
  1884.                     case RET_NOTENOUGHROOM:
  1885.                         player->sendCancel("Przykro mi, nie ma miejsca.");
  1886.                         return false;
  1887.                         break;
  1888.  
  1889.                     default:
  1890.                         player->sendCancel("Sorry not possible.");
  1891.                         return false;
  1892.                         break;
  1893.                 }
  1894.             }
  1895.         }
  1896.     }
  1897.     return true;
  1898. }
  1899. #endif //FIXY
  1900. /*ground -> ground*/
  1901. bool Game::onPrepareMoveThing(Creature* creature, const Thing* thing,
  1902.     const Tile* fromTile, const Tile *toTile, int32_t count)
  1903. {
  1904.     const Player* player = dynamic_cast<const Player*>(creature);
  1905.  
  1906.     const Item *item = dynamic_cast<const Item*>(thing);
  1907.     const Creature* movingCreature = dynamic_cast<const Creature*>(thing);
  1908.     const Player* movingPlayer = dynamic_cast<const Player*>(thing);
  1909.  
  1910.    /* if(movingCreature){
  1911.     addEvent(makeTask(2000, std::mem_fun(&Game::onPrepareMoveCreature, creature, movingCreature, fromTile, toTile))));
  1912.     }*/
  1913.     if(item && !item->canMovedTo(toTile)) {
  1914.         creature->sendCancel("Sorry, not possible.");
  1915.         return false;
  1916.     }
  1917.    
  1918.    else if(movingCreature && !movingCreature->canMovedTo(toTile)) {
  1919.    if(player && player->eventCheckFollow == 0) {
  1920.           player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  1921.           player->sendCancelWalk();
  1922.     }
  1923.  
  1924.         return false;
  1925.     }
  1926.     else if(!movingPlayer && toTile && toTile->floorChange()) {
  1927.         creature->sendCancel("Sorry, not possible.");
  1928.         return false;
  1929.     }
  1930.   else if(movingCreature && toTile && !toTile->ground) {
  1931.     if(player) {
  1932.       player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  1933.       player->sendCancelWalk();
  1934.     }
  1935.  
  1936.         return false;
  1937.     }
  1938.  
  1939.     if (fromTile && fromTile->splash == thing && fromTile->splash->isNotMoveable()) {
  1940.             creature->sendCancel("You cannot move this object.");
  1941. #ifdef __DEBUG__
  1942.         cout << creature->getName() << " is trying to move a splash item!" << std::endl;
  1943. #endif
  1944.         return false;
  1945.     }
  1946.     else if (item && item->isNotMoveable()) {
  1947.             creature->sendCancel("You cannot move this object.");
  1948. #ifdef __DEBUG__
  1949.         cout << creature->getName() << " is trying to move an unmoveable item!" << std::endl;
  1950. #endif
  1951.         return false;
  1952.     }
  1953.  
  1954. #ifdef TLM_HOUSE_SYSTEM
  1955.     if (item && toTile && toTile->isHouse())
  1956.     {
  1957.         const Container* container = dynamic_cast<const Container*>(item);
  1958.         int32_t moving = container? container->getItemHoldingCount() : 1;
  1959.  
  1960.         if (moving + toTile->getItemHoldingCount() > g_config.MAX_HOUSE_TILE_ITEMS)
  1961.         {
  1962.             creature->sendCancel("You cannot put more items on a house tile.");
  1963.             return false;
  1964.         }
  1965.     }
  1966. #endif //TLM_HOUSE_SYSTEM
  1967.  
  1968.     return true; //return thing->canMovedTo(toTile);
  1969. }
  1970. /*inventory -> container*/
  1971. bool Game::onPrepareMoveThing(Player* player, const Item* fromItem, slots_t fromSlot,
  1972.     const Container* toContainer, const Item* toItem, int32_t count)
  1973. {
  1974. if(toContainer && !toContainer->shop.empty()){
  1975.         creatureUseShop(player, fromItem->getID(), count, "toShop");
  1976.         return false;
  1977.     }
  1978. if(toContainer && toContainer->getParent() && !toContainer->getParent()->shop.empty())
  1979.         return false;
  1980.     if(!fromItem->isPickupable()) {
  1981.         player->sendCancel("Sorry, not possible.");
  1982.         return false;
  1983.     }
  1984.     else {
  1985.         const Container *itemContainer = dynamic_cast<const Container*>(fromItem);
  1986.         if(itemContainer) {
  1987.             if(itemContainer->isHoldingItem(toContainer) || (toContainer == itemContainer)) {
  1988.                 player->sendCancel("To jest niemozliwe!");
  1989.                 return false;
  1990.             }
  1991.         }
  1992.  
  1993.         if((!fromItem->isStackable() || !toItem || fromItem->getID() != toItem->getID() || toItem->getItemCountOrSubtype() >= 100) && toContainer->size() + 1 > toContainer->capacity()) {
  1994.             player->sendCancel("Przykro mi, nie ma miejsca.");
  1995.             return false;
  1996.         }
  1997.  
  1998.         Container const *topContainer = toContainer->getTopParent();
  1999.         int32_t itemsToadd;
  2000.         if(!topContainer)
  2001.             topContainer = toContainer;
  2002.  
  2003.         Container const *fromContainer = dynamic_cast<const Container*>(fromItem);
  2004.         if(fromContainer)
  2005.             itemsToadd = fromContainer->getItemHoldingCount() + 1;
  2006.         else
  2007.             itemsToadd = 1;
  2008.  
  2009.         if(topContainer->depot != 0 && player->max_depot_items != 0 && topContainer->getItemHoldingCount() + itemsToadd >= player->max_depot_items){
  2010.             player->sendCancel("Nie mozesz polozyc wiecej przedmiotow w depo.");
  2011.             return false;
  2012.         }
  2013.     }
  2014.     return true;
  2015. }
  2016.  
  2017. /*container -> container*/
  2018. /*ground -> container*/
  2019. bool Game::onPrepareMoveThing(Player* player,
  2020.     const Position& fromPos, const Container* fromContainer, const Item* fromItem,
  2021.     const Position& toPos, const Container* toContainer, const Item* toItem, int32_t count)
  2022. {
  2023. if(fromContainer && toContainer && (!fromContainer->shop.empty() || !toContainer->shop.empty())){
  2024.         creatureUseShop(player, fromItem->getID(), count, (!fromContainer->shop.empty() ? "fromShop" : "toShop"));
  2025.         return false;
  2026.     }
  2027.  
  2028.     if(!fromContainer && toContainer && !toContainer->shop.empty())
  2029.         return false;
  2030. if(toContainer && toContainer->getParent() && !toContainer->getParent()->shop.empty())
  2031.         return false;
  2032.  
  2033.     if (player->access < g_config.ACCESS_REMOTE &&
  2034.         ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  2035.     {
  2036.         player->sendCancel("Za daleko...");
  2037.         return false;
  2038.     }
  2039.     else if (player->access < g_config.ACCESS_REMOTE &&
  2040.         ((abs(fromPos.x - toPos.x) > fromItem->throwRange) || (abs(fromPos.y - toPos.y) > fromItem->throwRange)
  2041.         || (fromPos.z != toPos.z)))
  2042.     {
  2043.         player->sendCancel("Destination is out of reach.");
  2044.         return false;
  2045.     }
  2046.  
  2047.     if(!fromItem->isPickupable()) {
  2048.         player->sendCancel("You cannot move this object.");
  2049.         return false;
  2050.     }
  2051.     else {
  2052.         if((!fromItem->isStackable() || !toItem || fromItem->getID() != toItem->getID() || toItem->getItemCountOrSubtype() >= 100) && toContainer->size() + 1 > toContainer->capacity()) {
  2053.             player->sendCancel("Przykro mi, nie ma miejsca.");
  2054.             return false;
  2055.         }
  2056.  
  2057.         const Container *itemContainer = dynamic_cast<const Container*>(fromItem);
  2058.         if(itemContainer) {
  2059.             if(itemContainer->isHoldingItem(toContainer) || (toContainer == itemContainer) || (fromContainer && fromContainer == itemContainer)) {
  2060.                 player->sendCancel("To jest niemozliwe!");
  2061.                 return false;
  2062.             }
  2063.         }
  2064.  
  2065.         double itemWeight = (fromItem->isStackable() ? Item::items[fromItem->getID()].weight * std::max(1, count) : fromItem->getWeight());
  2066.         if((!fromContainer || !player->isHoldingContainer(fromContainer)) && player->isHoldingContainer(toContainer)) {
  2067.             if(player->access < g_config.ACCESS_PROTECT && player->getFreeCapacity() < itemWeight) {
  2068.                 player->sendCancel("Ten przedmiot jest za ciezki.");
  2069.                 return false;
  2070.             }
  2071.         }
  2072.  
  2073.         Container const *topContainer = toContainer->getTopParent();
  2074.         int32_t itemsToadd;
  2075.         if(!topContainer)
  2076.             topContainer = toContainer;
  2077.  
  2078.         Container const *fromContainer = dynamic_cast<const Container*>(fromItem);
  2079.         if(fromContainer)
  2080.             itemsToadd = fromContainer->getItemHoldingCount() + 1;
  2081.         else
  2082.             itemsToadd = 1;
  2083.  
  2084.         if(topContainer->depot != 0 && player->max_depot_items != 0 && topContainer->getItemHoldingCount() >= player->max_depot_items){
  2085.             player->sendCancel("Nie mozesz polozyc wiecej przedmiotow w depo.");
  2086.             return false;
  2087.         }
  2088.     }
  2089.     return true;
  2090. }
  2091.  
  2092. /*ground -> ground*/
  2093. bool Game::onPrepareMoveCreature(Creature *creature, const Creature* creatureMoving,
  2094.     const Tile *fromTile, const Tile *toTile)
  2095. {
  2096.     const Player* playerMoving = dynamic_cast<const Player*>(creatureMoving);
  2097.     Player* player = dynamic_cast<Player*>(creature);
  2098.  
  2099. #ifdef _BBK_PUSH_DELAY
  2100.     if(player && player != creatureMoving && player->pushDelay > 0)
  2101.     {
  2102.         player->sendCancel("Wait a moment.");
  2103.         return false;
  2104.     }
  2105.     else if(player)
  2106.        player->pushDelay = 2*1000; //2 sec
  2107.              
  2108.         //wypychanie z depo
  2109.         if(player && playerMoving && player != playerMoving && fromTile->isPz() && !toTile->isPz())
  2110.         {
  2111.             player->sendCancel("Sorry, not possible.");
  2112.       return false;
  2113.         }
  2114.         //wepchanie do depo
  2115.         if(player && playerMoving && playerMoving->pzLocked && toTile->isPz())
  2116.         {
  2117.             player->sendCancel("Sorry, not possible.");
  2118.             player->sendCancelWalk();
  2119.       return false;
  2120.         }
  2121.         //wchodzenie do depo
  2122.         if(player && player->pzLocked && toTile->isPz())
  2123.         {
  2124.             player->sendCancel("You can not enter a protection zone after attacking another player.");
  2125.             player->sendCancelWalk();
  2126.       return false;
  2127.         }
  2128. #endif //_BBK_PUSH_DELAY
  2129.    
  2130.     if (creature->access < g_config.ACCESS_PROTECT && creature != creatureMoving && !creatureMoving->isPushable())
  2131.     {
  2132.         creature->sendCancel("Sorry, not possible.");
  2133.         return false;
  2134.     }
  2135.     else if(creature != creatureMoving && toTile->floorChange()){
  2136.         creature->sendCancel("Sorry, not possible.");
  2137.         return false;
  2138.     }
  2139.   else if(creature != creatureMoving && toTile->getTeleportItem()){
  2140.         creature->sendCancel("Sorry, not possible.");
  2141.         return false;
  2142.   }
  2143.  
  2144.     return true;
  2145. }
  2146.  
  2147. /*ground -> inventory*/
  2148. bool Game::onPrepareMoveThing(Player *player, const Position& fromPos, const Item *item,
  2149.     slots_t toSlot, int32_t count)
  2150. {
  2151.     if (player->access < g_config.ACCESS_REMOTE &&  
  2152.         ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  2153.     {
  2154.         player->sendCancel("It's too far.");
  2155.         return false;
  2156.     }
  2157.     else if(!item->isPickupable()) {
  2158.         player->sendCancel("You cannot move this object.");
  2159.         return false;
  2160.     }
  2161.  
  2162.     double itemWeight = (item->isStackable() ? Item::items[item->getID()].weight * std::max(1, count) : item->getWeight());
  2163.     if(player->access < g_config.ACCESS_PROTECT && player->getFreeCapacity() < itemWeight) {
  2164.         player->sendCancel("This object is too heavy.");
  2165.         return false;
  2166.     }
  2167.  
  2168.     return true;
  2169. }
  2170.  
  2171. /*inventory -> inventory*/
  2172. bool Game::onPrepareMoveThing(Player *player, slots_t fromSlot, const Item *fromItem,
  2173.     slots_t toSlot, const Item *toItem, int32_t count)
  2174. {
  2175.     if(toItem && (!toItem->isStackable() || toItem->getID() != fromItem->getID())) {
  2176.         player->sendCancel("There is not enough room.");
  2177.         return false;
  2178.     }
  2179.  
  2180.     return true;
  2181. }
  2182.  
  2183. /*container -> inventory*/
  2184. bool Game::onPrepareMoveThing(Player *player, const Container *fromContainer, const Item *fromItem,
  2185.     slots_t toSlot, const Item *toItem, int32_t count)
  2186. {
  2187. if(fromContainer && !fromContainer->shop.empty()){
  2188.         creatureUseShop(player, fromItem->getID(), count, "fromShop");
  2189.         return false;
  2190.     }
  2191.     #ifdef _REX_FIGHT_MOD_
  2192.     if (toItem && (toItem->getID() == fromItem->getID() && !toItem->isStackable())){
  2193.     #else
  2194.     if(toItem && (!toItem->isStackable() || toItem->getID() != fromItem->getID())) {
  2195.     #endif //Segundo em container -> inventory
  2196.         player->sendCancel("There is not enough room.");
  2197.         return false;
  2198.     }
  2199.  
  2200.     double itemWeight = (fromItem->isStackable() ? Item::items[fromItem->getID()].weight * std::max(1, count) : fromItem->getWeight());
  2201.     if(player->access < g_config.ACCESS_PROTECT && !player->isHoldingContainer(fromContainer) &&
  2202.         player->getFreeCapacity() < itemWeight) {
  2203.         player->sendCancel("This object is too heavy.");
  2204.         return false;
  2205.     }
  2206.  
  2207.     return true;
  2208. }
  2209.  
  2210. /*->inventory*/
  2211. bool Game::onPrepareMoveThing(Player *player, const Item *item,
  2212.     slots_t toSlot, int32_t count)
  2213. {
  2214.     switch(toSlot)
  2215.     {
  2216.     case SLOT_HEAD:
  2217.         if(item->getSlotPosition() & SLOTP_HEAD)
  2218.             return true;
  2219.         break;
  2220.     case SLOT_NECKLACE:
  2221.         if(item->getSlotPosition() & SLOTP_NECKLACE)
  2222.             return true;
  2223.         break;
  2224.     case SLOT_BACKPACK:
  2225.         if(item->getSlotPosition() & SLOTP_BACKPACK)
  2226.             return true;
  2227.         break;
  2228.     case SLOT_ARMOR:
  2229.         if(item->getSlotPosition() & SLOTP_ARMOR)
  2230.             return true;
  2231.         break;
  2232.     case SLOT_RIGHT:
  2233.         if(item->getSlotPosition() & SLOTP_RIGHT){
  2234. #ifdef _REX_CVS_MOD_
  2235.             //One weapon for hand by ReX
  2236.             if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_LEFT] != NULL && player->items[SLOT_LEFT]->isWeapon() && player->items[SLOT_LEFT]->getWeaponType() != SHIELD){
  2237.              player->sendCancel("You may use only one weapon.");
  2238.              return false;
  2239.             }
  2240. #endif            
  2241.             else if(item->getSlotPosition() & SLOTP_TWO_HAND){
  2242.                 if(player->items[SLOT_LEFT] != NULL){
  2243.                     player->sendCancel("First remove the two-handed item.");
  2244.                     return false;
  2245.                 }
  2246.                 return true ;
  2247.             }
  2248.             else{
  2249.                 if(player->items[SLOT_LEFT]){
  2250.     #ifdef _REX_CVS_MOD_
  2251.                     //One weapon for hand by ReX
  2252.                     if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_LEFT] != NULL && player->items[SLOT_LEFT]->isWeapon() && player->items[SLOT_LEFT]->getWeaponType() != SHIELD){
  2253.                     player->sendCancel("You may use only one weapon.");
  2254.                     return false;
  2255.                     }
  2256.                     #endif
  2257.                     else if(player->items[SLOT_LEFT]->getSlotPosition() & SLOTP_TWO_HAND){
  2258.                         player->sendCancel("First remove the two-handed item.");
  2259.                         return false;
  2260.                     }
  2261.                     return true;
  2262.                 }
  2263.                 return true;
  2264.             }
  2265.         }
  2266.         break;
  2267.     case SLOT_LEFT:
  2268.         if(item->getSlotPosition() & SLOTP_LEFT){
  2269. #ifdef _REX_CVS_MOD_
  2270.             //One weapon for hand by ReX
  2271.             if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_RIGHT] != NULL && player->items[SLOT_RIGHT]->isWeapon() && player->items[SLOT_RIGHT]->getWeaponType() != SHIELD){
  2272.              player->sendCancel("You may use only one weapon.");
  2273.              return false;
  2274.             }
  2275. #endif
  2276.             else if(item->getSlotPosition() & SLOTP_TWO_HAND){
  2277.                 if(player->items[SLOT_RIGHT] != NULL){
  2278.                     player->sendCancel("First remove the two-handed item.");
  2279.                     return false;
  2280.                 }
  2281.                 return true ;
  2282.             }
  2283.             else{
  2284.                 if(player->items[SLOT_RIGHT]){
  2285.                                               #ifdef _REX_CVS_MOD_
  2286.                     //One weapon for hand by ReX
  2287.                     if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_RIGHT] != NULL && player->items[SLOT_RIGHT]->isWeapon() && player->items[SLOT_RIGHT]->getWeaponType() != SHIELD){
  2288.                     player->sendCancel("You may use only one weapon.");
  2289.                     return false;
  2290.                     }
  2291.                     #endif
  2292.                     else if(player->items[SLOT_RIGHT]->getSlotPosition() & SLOTP_TWO_HAND){
  2293.                         player->sendCancel("First remove the two-handed item.");
  2294.                         return false;
  2295.                     }
  2296.                     return true;
  2297.                 }
  2298.                 return true;
  2299.             }
  2300.         }
  2301.         break;
  2302.     case SLOT_LEGS:
  2303.         if(item->getSlotPosition() & SLOTP_LEGS)
  2304.             return true;
  2305.         break;
  2306.     case SLOT_FEET:
  2307.         if(item->getSlotPosition() & SLOTP_FEET)
  2308.             return true;
  2309.         break;
  2310.     case SLOT_RING:
  2311.         if(item->getSlotPosition() & SLOTP_RING
  2312.         #ifdef _REX_CVS_MOD_
  2313.         || item->getID() == 2208
  2314.         #endif
  2315.         )
  2316.             return true;
  2317.         break;
  2318.     case SLOT_AMMO:
  2319.         if(item->getSlotPosition() & SLOTP_AMMO)
  2320.             return true;
  2321.         break;
  2322.     }
  2323.  
  2324.     player->sendCancel("You cannot put that object in that place.");
  2325.     return false;
  2326. }
  2327.  
  2328. //container/inventory to container/inventory
  2329. void Game::thingMoveInternal(Player *player,
  2330.     unsigned short from_cid, unsigned short from_slotid, unsigned short itemid,
  2331.     bool fromInventory,unsigned short to_cid, unsigned short to_slotid, bool toInventory,
  2332.     unsigned short count)
  2333. {
  2334.     Container *fromContainer = NULL;
  2335.     Container *toContainer = NULL;
  2336.     Item *fromItem = NULL;
  2337.     Item *toItem = NULL;
  2338.  
  2339.     if(fromInventory) {
  2340.         fromItem = player->getItem(from_cid);
  2341.         fromContainer = dynamic_cast<Container *>(fromItem);
  2342.     }
  2343.     else {
  2344.         fromContainer = player->getContainer(from_cid);
  2345.  
  2346.         if(fromContainer) {
  2347.             if(from_slotid >= fromContainer->size())
  2348.                 return;
  2349.  
  2350.             fromItem = fromContainer->getItem(from_slotid);
  2351.         }
  2352.     }
  2353.  
  2354.     if(toInventory) {
  2355.         toItem = player->getItem(to_cid);
  2356.         toContainer = dynamic_cast<Container *>(toItem);
  2357.     }
  2358.     else {
  2359.         toContainer = player->getContainer(to_cid);
  2360.  
  2361.         if(toContainer) {
  2362.             if(to_slotid >= toContainer->capacity())
  2363.                 return;
  2364.  
  2365.             toItem = toContainer->getItem(to_slotid);
  2366.             Container *toSlotContainer = dynamic_cast<Container*>(toItem);
  2367.             if(toSlotContainer) {
  2368.                 toContainer = toSlotContainer;
  2369.                 toItem = NULL;
  2370.             }
  2371.         }
  2372.     }
  2373.  
  2374.     if(!fromItem || (toItem == fromItem) || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()) || fromItem->getID() != itemid)
  2375.         return;
  2376.  
  2377.     //Container to container
  2378.     if(!fromInventory && fromContainer && toContainer) {
  2379.         Position fromPos = (fromContainer->pos.x == 0xFFFF ? player->pos : fromContainer->pos);
  2380.         Position toPos = (toContainer->pos.x == 0xFFFF ? player->pos : toContainer->pos);
  2381.  
  2382.         if(onPrepareMoveThing(player, fromPos, fromContainer, fromItem, toPos, toContainer, toItem, count)) {
  2383.  
  2384.             autoCloseTrade(fromItem, true);
  2385.             int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2386.             int32_t oldToCount = 0;
  2387.  
  2388.             //move around an item in a container
  2389.             if(fromItem->isStackable()) {
  2390.                 if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2391.                 {
  2392.                     oldToCount = toItem->getItemCountOrSubtype();
  2393.                     int32_t newToCount = std::min(100, oldToCount + count);
  2394.                     toItem->setItemCountOrSubtype(newToCount);
  2395.  
  2396.                     if(oldToCount != newToCount) {
  2397.                         autoCloseTrade(toItem);
  2398.                     }
  2399.  
  2400.                     int32_t subcount = oldFromCount - count;
  2401.                     fromItem->setItemCountOrSubtype(subcount);
  2402.  
  2403.                     int32_t surplusCount = oldToCount + count  - 100;
  2404.                     if(surplusCount > 0) {
  2405.                         Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2406.                         if(onPrepareMoveThing(player, fromPos, fromContainer, surplusItem, toPos, toContainer, NULL, count)) {
  2407.                             autoCloseTrade(toContainer);
  2408.                             toContainer->addItem(surplusItem);
  2409.                         }
  2410.                         else {
  2411.                             delete surplusItem;
  2412.                             count -= surplusCount; //re-define the actual amount we move.
  2413.                             fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2414.                         }
  2415.                     }
  2416.                 }
  2417.                 else if(count < oldFromCount) {
  2418.                     int32_t subcount = oldFromCount - count;
  2419.                     fromItem->setItemCountOrSubtype(subcount);
  2420.  
  2421.                     Item* moveItem = Item::CreateItem(fromItem->getID(), count);
  2422.                     toContainer->addItem(moveItem);
  2423.                     autoCloseTrade(toContainer);
  2424.                 }
  2425.                 else {
  2426.                     if(fromContainer == toContainer) {
  2427.                         fromContainer->moveItem(from_slotid, 0);
  2428.                     }
  2429.                     else if(fromContainer->removeItem(fromItem)) {
  2430.                         autoCloseTrade(toContainer);
  2431.                         toContainer->addItem(fromItem);
  2432.                     }
  2433.                 }
  2434.  
  2435.                 if(fromItem->getItemCountOrSubtype() == 0) {
  2436.                     fromContainer->removeItem(fromItem);
  2437.                     this->FreeThing(fromItem);
  2438.                 }
  2439.             }
  2440.             else {
  2441.                 if(fromContainer == toContainer) {
  2442.                     fromContainer->moveItem(from_slotid, 0);
  2443.                 }
  2444.                 else if(fromContainer->removeItem(fromItem)) {
  2445.                     autoCloseTrade(toContainer);
  2446.                     toContainer->addItem(fromItem);
  2447.                 }
  2448.             }
  2449.  
  2450.             if(player->isHoldingContainer(fromContainer) != player->isHoldingContainer(toContainer)) {
  2451.                 player->updateInventoryWeigth();
  2452.             }
  2453.  
  2454.             SpectatorVec list;
  2455.             SpectatorVec::iterator it;
  2456.  
  2457.             if(fromPos == toPos) {
  2458.                 getSpectators(Range(fromPos, false), list);
  2459.             }
  2460.             else {
  2461.                 getSpectators(Range(fromPos, toPos), list);
  2462.             }
  2463.  
  2464.             if(!list.empty()) {
  2465.                 //players
  2466.                 for(it = list.begin(); it != list.end(); ++it) {
  2467.                     if(dynamic_cast<Player*>(*it)) {
  2468.                         (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2469.                     }
  2470.                 }
  2471.  
  2472.                 //none-players
  2473.                 for(it = list.begin(); it != list.end(); ++it) {
  2474.                     if(!dynamic_cast<Player*>(*it)) {
  2475.                         (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2476.                     }
  2477.                 }
  2478.             }
  2479.             else
  2480.                 player->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2481.         }
  2482.     }
  2483.     else {
  2484.         //inventory to inventory
  2485.         if(fromInventory && toInventory && !toContainer) {
  2486.             Position fromPos = player->pos;
  2487.             Position toPos = player->pos;
  2488.             if(onPrepareMoveThing(player, fromItem, (slots_t)to_cid, count) && onPrepareMoveThing(player, (slots_t)from_cid, fromItem, (slots_t)to_cid, toItem, count)) {
  2489.  
  2490.                 autoCloseTrade(fromItem, true);
  2491.                 int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2492.                 int32_t oldToCount = 0;
  2493.  
  2494.                 //bbk 2020
  2495.                 std::cout << "inventory to inventory" << std::endl;
  2496.                 if(fromItem && (slots_t)to_cid == SLOT_RING) fromItem->setGlimmer();
  2497.                 if(toItem && (slots_t)from_cid == SLOT_RING) toItem->removeGlimmer();
  2498.  
  2499.                 if(fromItem->isStackable()) {
  2500.                     if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2501.                     {
  2502.                         oldToCount = toItem->getItemCountOrSubtype();
  2503.                         int32_t newToCount = std::min(100, oldToCount + count);
  2504.                         toItem->setItemCountOrSubtype(newToCount);
  2505.  
  2506.                         if(oldToCount != newToCount) {
  2507.                             autoCloseTrade(toItem);
  2508.                         }
  2509.  
  2510.                         int32_t subcount = oldFromCount - count;
  2511.                         fromItem->setItemCountOrSubtype(subcount);
  2512.  
  2513.                         int32_t surplusCount = oldToCount + count  - 100;
  2514.                         if(surplusCount > 0) {
  2515.                             fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2516.                             player->sendCancel("There is not enough room.");
  2517.                         }
  2518.  
  2519.                         if(fromItem->getItemCountOrSubtype() == 0) {
  2520.                             player->removeItemInventory(from_cid, true);
  2521.                             this->FreeThing(fromItem);
  2522.                         }
  2523.                     }
  2524.                     else if(count < oldFromCount) {
  2525.                         int32_t subcount = oldFromCount - count;
  2526.                         fromItem->setItemCountOrSubtype(subcount);
  2527.  
  2528.                         autoCloseTrade(toItem);
  2529.                         player->removeItemInventory(to_cid, true);
  2530.                         player->addItemInventory(Item::CreateItem(fromItem->getID(), count), to_cid, true);
  2531.  
  2532.                         if(fromItem->getItemCountOrSubtype() == 0) {
  2533.                             player->removeItemInventory(from_cid, true);
  2534.                             this->FreeThing(fromItem);
  2535.                         }
  2536.                     }
  2537.                     else {
  2538.                         if(player->removeItemInventory(from_cid, true)) {
  2539.                             player->removeItemInventory(to_cid, true);
  2540.                             player->addItemInventory(fromItem, to_cid, true);
  2541.                         }
  2542.                     }
  2543.                 }
  2544.                 else if(player->removeItemInventory(from_cid, true)) {
  2545.                     player->removeItemInventory(to_cid, true);
  2546.                     player->addItemInventory(fromItem, to_cid, true);
  2547.                 }
  2548.  
  2549.                 player->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2550.             }
  2551.         }
  2552.         //container to inventory
  2553.         else if(!fromInventory && fromContainer && toInventory) {
  2554.             if(onPrepareMoveThing(player, fromItem, (slots_t)to_cid, count) && onPrepareMoveThing(player, fromContainer, fromItem, (slots_t)to_cid, toItem, count)) {
  2555.                 autoCloseTrade(fromItem, true);
  2556.                 int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2557.                 int32_t oldToCount = 0;
  2558.  
  2559.                 //bbk 2020
  2560.                 std::cout << "container to inventory" << std::endl;
  2561.                 if(fromItem) fromItem->removeGlimmer();
  2562.                 if(toItem ) toItem->removeGlimmer();
  2563.  
  2564.                 if(fromItem->isStackable()) {
  2565.                     if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2566.                     {
  2567.                         oldToCount = toItem->getItemCountOrSubtype();
  2568.                         int32_t newToCount = std::min(100, oldToCount + count);
  2569.                         toItem->setItemCountOrSubtype(newToCount);
  2570.  
  2571.                         if(oldToCount != newToCount) {
  2572.                             autoCloseTrade(toItem);
  2573.                         }
  2574.  
  2575.                         int32_t subcount = oldFromCount - count;
  2576.                         fromItem->setItemCountOrSubtype(subcount);
  2577.  
  2578.                         int32_t surplusCount = oldToCount + count  - 100;
  2579.                         if(surplusCount > 0) {
  2580.                             fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2581.                             player->sendCancel("There is not enough room.");
  2582.                         }
  2583.  
  2584.                         if(fromItem->getItemCountOrSubtype() == 0) {
  2585.                             fromContainer->removeItem(fromItem);
  2586.                             this->FreeThing(fromItem);
  2587.                         }
  2588.                     }
  2589.                     else if(count < oldFromCount) {
  2590.                         int32_t subcount = oldFromCount - count;
  2591.                         fromItem->setItemCountOrSubtype(subcount);
  2592.  
  2593.                         player->removeItemInventory(to_cid, true);
  2594.                         player->addItemInventory(Item::CreateItem(fromItem->getID(), count), to_cid, true);
  2595.  
  2596.                         if(toItem) {
  2597.                             fromContainer->addItem(toItem);
  2598.                         }
  2599.  
  2600.                         if(fromItem->getItemCountOrSubtype() == 0) {
  2601.                             fromContainer->removeItem(fromItem);
  2602.                             this->FreeThing(fromItem);
  2603.                         }
  2604.                     }
  2605.                     else {
  2606.                         if(fromContainer->removeItem(fromItem)) {
  2607.                             player->removeItemInventory(to_cid, true);
  2608.                             player->addItemInventory(fromItem, to_cid, true);
  2609.  
  2610.                             if(toItem) {
  2611.                                 fromContainer->addItem(toItem);
  2612.                             }
  2613.                         }
  2614.                     }
  2615.                 }
  2616.                 else if(fromContainer->removeItem(fromItem)) {
  2617.                     player->removeItemInventory(to_cid, true);
  2618.                     player->addItemInventory(fromItem, to_cid, true);
  2619.  
  2620.                     if(toItem) {
  2621.                         fromContainer->addItem(toItem);
  2622.                     }
  2623.                 }
  2624.  
  2625.                 if(!player->isHoldingContainer(fromContainer)) {
  2626.                     player->updateInventoryWeigth();
  2627.                 }
  2628.  
  2629.                 //if(fromContainer->pos.x != 0xFFFF) {
  2630.                 if(fromContainer->getTopParent()->pos.x != 0xFFFF) {
  2631.                     SpectatorVec list;
  2632.                     SpectatorVec::iterator it;
  2633.  
  2634.                     getSpectators(Range(fromContainer->getTopParent()->pos, false), list);
  2635.  
  2636.                     //players
  2637.                     for(it = list.begin(); it != list.end(); ++it) {
  2638.                         if(dynamic_cast<Player*>(*it)) {
  2639.                             (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2640.                         }
  2641.                     }
  2642.  
  2643.                     //none-players
  2644.                     for(it = list.begin(); it != list.end(); ++it) {
  2645.                         if(!dynamic_cast<Player*>(*it)) {
  2646.                             (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2647.                         }
  2648.                     }
  2649.                 }
  2650.                 else
  2651.                     player->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2652.             }
  2653.         }
  2654.         //inventory to container
  2655.         else if(fromInventory && toContainer) {
  2656.             Position fromPos = player->pos;
  2657.             Position toPos = (toContainer->pos.x == 0xFFFF ? player->pos : toContainer->pos);
  2658.  
  2659.             int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2660.             int32_t oldToCount = 0;
  2661.  
  2662.             //bbk 2020
  2663.             std::cout << "inventory to container" << std::endl;
  2664.             if(fromItem) fromItem->removeGlimmer();
  2665.             if(toItem) toItem->removeGlimmer();
  2666.  
  2667.             if(onPrepareMoveThing(player, fromItem, (slots_t)from_cid, toContainer, toItem, count)) {
  2668.                 autoCloseTrade(fromItem, true);
  2669.                 if(fromItem->isStackable()) {
  2670.                     if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2671.                     {
  2672.                         oldToCount = toItem->getItemCountOrSubtype();
  2673.                         int32_t newToCount = std::min(100, oldToCount + count);
  2674.                         toItem->setItemCountOrSubtype(newToCount);
  2675.  
  2676.                         if(oldToCount != newToCount) {
  2677.                             autoCloseTrade(toItem);
  2678.                         }
  2679.  
  2680.                         int32_t subcount = oldFromCount - count;
  2681.                         fromItem->setItemCountOrSubtype(subcount);
  2682.  
  2683.                         int32_t surplusCount = oldToCount + count  - 100;
  2684.                         if(surplusCount > 0) {
  2685.                             Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2686.  
  2687.                             if(onPrepareMoveThing(player, fromPos, NULL, surplusItem, toPos, toContainer, NULL, count)) {
  2688.                                 autoCloseTrade(toContainer);
  2689.                                 toContainer->addItem(surplusItem);
  2690.                             }
  2691.                             else {
  2692.                                 delete surplusItem;
  2693.                                 count -= surplusCount; //re-define the actual amount we move.
  2694.                                 fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2695.                             }
  2696.                         }
  2697.                     }
  2698.                     else if(count < oldFromCount) {
  2699.                         int32_t subcount = oldFromCount - count;
  2700.                         fromItem->setItemCountOrSubtype(subcount);
  2701.                         autoCloseTrade(toContainer);
  2702.                         toContainer->addItem(Item::CreateItem(fromItem->getID(), count));
  2703.                     }
  2704.                     else {
  2705.                         if(player->removeItemInventory((slots_t)from_cid, true)) {
  2706.                             autoCloseTrade(toContainer);
  2707.                             toContainer->addItem(fromItem);
  2708.  
  2709.                             if(player->isHoldingContainer(toContainer)) {
  2710.                                 player->updateInventoryWeigth();
  2711.                             }
  2712.                         }
  2713.                     }
  2714.  
  2715.                     if(fromItem->getItemCountOrSubtype() == 0) {
  2716.                         player->removeItemInventory(from_cid, true);
  2717.                         this->FreeThing(fromItem);
  2718.                     }
  2719.                 }
  2720.                 else if(player->removeItemInventory(from_cid, true)) {
  2721.                     autoCloseTrade(toContainer);
  2722.                     toContainer->addItem(fromItem);
  2723.  
  2724.                     if(player->isHoldingContainer(toContainer)) {
  2725.                         player->updateInventoryWeigth();
  2726.                     }
  2727.                 }
  2728.  
  2729.                 if(!player->isHoldingContainer(toContainer)) {
  2730.                     player->updateInventoryWeigth();
  2731.                 }
  2732.  
  2733.                 if(toContainer->getTopParent()->pos.x != 0xFFFF) {
  2734.                     SpectatorVec list;
  2735.                     SpectatorVec::iterator it;
  2736.  
  2737.                     getSpectators(Range(toContainer->getTopParent()->pos, false), list);
  2738.  
  2739.                     //players
  2740.                     for(it = list.begin(); it != list.end(); ++it) {
  2741.                         if(dynamic_cast<Player*>(*it)) {
  2742.                             (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2743.                         }
  2744.                     }
  2745.  
  2746.                     //none-players
  2747.                     for(it = list.begin(); it != list.end(); ++it) {
  2748.                         if(!dynamic_cast<Player*>(*it)) {
  2749.                             (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2750.                         }
  2751.                     }
  2752.                 }
  2753.                 else
  2754.                     player->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2755.             }
  2756.         }
  2757.     }
  2758. }
  2759.  
  2760. //container/inventory to ground
  2761. void Game::thingMoveInternal(Player *player,
  2762.     unsigned char from_cid, unsigned char from_slotid, unsigned short itemid, bool fromInventory,
  2763.     const Position& toPos, unsigned char count)
  2764. {
  2765.     Container *fromContainer = NULL;
  2766.     Tile *toTile = map->getTile(toPos);
  2767.     if(!toTile)
  2768.         return;
  2769.  
  2770.     /*container to ground*/
  2771.     if(!fromInventory) {
  2772.         fromContainer = player->getContainer(from_cid);
  2773.         if(!fromContainer)
  2774.             return;
  2775.  
  2776.         Position fromPos = (fromContainer->pos.x == 0xFFFF ? player->pos : fromContainer->pos);
  2777.         Item *fromItem = dynamic_cast<Item*>(fromContainer->getItem(from_slotid));
  2778.         Item* toItem = dynamic_cast<Item*>(toTile->getTopDownItem());
  2779.  
  2780.         if(!fromItem || (toItem == fromItem) || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()) || fromItem->getID() != itemid)
  2781.             return;
  2782.  
  2783.         if(onPrepareMoveThing(player, fromItem, fromPos, toPos, count) && onPrepareMoveThing(player, fromItem, NULL, toTile, count)) {
  2784.             autoCloseTrade(fromItem, true);
  2785.             int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2786.             int32_t oldToCount = 0;
  2787.  
  2788.             //Do action...
  2789. #ifdef TP_TRASH_BINS
  2790.             if (toItem && toItem->isDeleter())
  2791.             {
  2792.                 fromContainer->removeItem(fromItem);
  2793.                 FreeThing(fromItem);
  2794.             }
  2795.             else if(fromItem->isStackable()) {
  2796. #else
  2797.             if(fromItem->isStackable()) {
  2798. #endif //TP_TRASH_BINS
  2799.                 if(toItem && toItem->getID() == fromItem->getID())
  2800.                 {
  2801.                     oldToCount = toItem->getItemCountOrSubtype();
  2802.                     int32_t newToCount = std::min(100, oldToCount + count);
  2803.                     toItem->setItemCountOrSubtype(newToCount);
  2804.  
  2805.                     if(oldToCount != newToCount) {
  2806.                         autoCloseTrade(toItem);
  2807.                     }
  2808.  
  2809.                     int32_t subcount = oldFromCount - count;
  2810.                     fromItem->setItemCountOrSubtype(subcount);
  2811.  
  2812.                     int32_t surplusCount = oldToCount + count  - 100;
  2813.                     if(surplusCount > 0) {
  2814.                         Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2815.                         surplusItem->pos = toPos;
  2816.  
  2817.                         toTile->addThing(surplusItem);
  2818.                     }
  2819.  
  2820.                     if(fromItem->getItemCountOrSubtype() == 0) {
  2821.                         fromContainer->removeItem(fromItem);
  2822.                         this->FreeThing(fromItem);
  2823.                     }
  2824.                 }
  2825.                 else if(count < oldFromCount) {
  2826.                     int32_t subcount = oldFromCount - count;
  2827.                     fromItem->setItemCountOrSubtype(subcount);
  2828.  
  2829.                     Item *moveItem = Item::CreateItem(fromItem->getID(), count);
  2830.                     moveItem->pos = toPos;
  2831.                     toTile->addThing(moveItem);
  2832.  
  2833.                     if(fromItem->getItemCountOrSubtype() == 0) {
  2834.                         fromContainer->removeItem(fromItem);
  2835.                         this->FreeThing(fromItem);
  2836.                     }
  2837.                 }
  2838.                 else if(fromContainer->removeItem(fromItem)) {
  2839.                     fromItem->pos = toPos;
  2840.                     toTile->addThing(fromItem);
  2841.                 }
  2842.             }
  2843.             else if(fromContainer->removeItem(fromItem)) {
  2844.                 fromItem->pos = toPos;
  2845.                 toTile->addThing(fromItem);
  2846.             }
  2847.  
  2848.             if(player->isHoldingContainer(fromContainer)) {
  2849.                 player->updateInventoryWeigth();
  2850.             }
  2851.  
  2852.             SpectatorVec list;
  2853.             SpectatorVec::iterator it;
  2854.  
  2855.             getSpectators(Range(fromPos, false), list);
  2856.  
  2857.             SpectatorVec tolist;
  2858.             getSpectators(Range(toPos, true), tolist);
  2859.  
  2860.             for(it = tolist.begin(); it != tolist.end(); ++it) {
  2861.                 if(std::find(list.begin(), list.end(), *it) == list.end()) {
  2862.                     list.push_back(*it);
  2863.                 }
  2864.             }
  2865.  
  2866.             //players
  2867.             for(it = list.begin(); it != list.end(); ++it) {
  2868.                 if(dynamic_cast<Player*>(*it)) {
  2869.                     (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2870.                 }
  2871.             }
  2872.  
  2873.             //none-players
  2874.             for(it = list.begin(); it != list.end(); ++it) {
  2875.                 if(!dynamic_cast<Player*>(*it)) {
  2876.                     (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2877.                 }
  2878.             }
  2879.         }
  2880.     }
  2881.     else /*inventory to ground*/{
  2882.         Item *fromItem = player->getItem(from_cid);
  2883.         if(!fromItem || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()) || fromItem->getID() != itemid)
  2884.             return;
  2885.  
  2886.         if(onPrepareMoveThing(player, fromItem, player->pos, toPos, count) && onPrepareMoveThing(player, fromItem, NULL, toTile, count)) {
  2887.             autoCloseTrade(fromItem, true);
  2888.             Item* toItem = dynamic_cast<Item*>(toTile->getTopDownItem());
  2889.             int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2890.             int32_t oldToCount = 0;
  2891.  
  2892.             //bbk 2020
  2893.             std::cout << "inventory to ground" << std::endl;
  2894.             if(fromItem) fromItem->removeGlimmer();
  2895.  
  2896.             //Do action...
  2897. #ifdef TP_TRASH_BINS
  2898.             if(toItem && toItem->isDeleter())
  2899.             {
  2900.                 player->removeItemInventory(from_cid, true);
  2901.                 FreeThing(fromItem);
  2902.             }
  2903.             else if(fromItem->isStackable()) {
  2904. #else
  2905.             if(fromItem->isStackable()) {
  2906. #endif //TP_TRASH_BINS
  2907.                 if(toItem && toItem->getID() == fromItem->getID())
  2908.                 {
  2909.                     oldToCount = toItem->getItemCountOrSubtype();
  2910.                     int32_t newToCount = std::min(100, oldToCount + count);
  2911.                     toItem->setItemCountOrSubtype(newToCount);
  2912.  
  2913.                     if(oldToCount != newToCount) {
  2914.                         autoCloseTrade(toItem);
  2915.                     }
  2916.  
  2917.                     int32_t subcount = oldFromCount - count;
  2918.                     fromItem->setItemCountOrSubtype(subcount);
  2919.  
  2920.                     int32_t surplusCount = oldToCount + count  - 100;
  2921.                     if(surplusCount > 0) {
  2922.                         Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2923.                         surplusItem->pos = toPos;
  2924.  
  2925.                         toTile->addThing(surplusItem);
  2926.                     }
  2927.  
  2928.                     if(fromItem->getItemCountOrSubtype() == 0) {
  2929.                         player->removeItemInventory(from_cid, true);
  2930.                         this->FreeThing(fromItem);
  2931.                     }
  2932.                 }
  2933.                 else if(count < oldFromCount) {
  2934.                     int32_t subcount = oldFromCount - count;
  2935.                     fromItem->setItemCountOrSubtype(subcount);
  2936.  
  2937.                     Item *moveItem = Item::CreateItem(fromItem->getID(), count);
  2938.                     moveItem->pos = toPos;
  2939.                     toTile->addThing(moveItem);
  2940.  
  2941.                     if(fromItem->getItemCountOrSubtype() == 0) {
  2942.                         player->removeItemInventory(from_cid, true);
  2943.                         this->FreeThing(fromItem);
  2944.                     }
  2945.                 }
  2946.                 else if(player->removeItemInventory(from_cid, true)) {
  2947.                     fromItem->pos = toPos;
  2948.                     toTile->addThing(fromItem);
  2949.                 }
  2950.             }
  2951.             else if(player->removeItemInventory(from_cid, true)) {
  2952.                 fromItem->pos = toPos;
  2953.                 toTile->addThing(fromItem);
  2954.             }
  2955.  
  2956.             player->updateInventoryWeigth();
  2957.  
  2958.             SpectatorVec list;
  2959.             SpectatorVec::iterator it;
  2960.  
  2961.             getSpectators(Range(player->pos, false), list);
  2962.  
  2963.             SpectatorVec tolist;
  2964.             getSpectators(Range(toPos, true), tolist);
  2965.  
  2966.             for(it = tolist.begin(); it != tolist.end(); ++it) {
  2967.                 if(std::find(list.begin(), list.end(), *it) == list.end()) {
  2968.                     list.push_back(*it);
  2969.                 }
  2970.             }
  2971.  
  2972.             //players
  2973.             for(it = list.begin(); it != list.end(); ++it) {
  2974.                 if(dynamic_cast<Player*>(*it)) {
  2975.                     (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2976.                 }
  2977.             }
  2978.  
  2979.             //none-players
  2980.             for(it = list.begin(); it != list.end(); ++it) {
  2981.                 if(!dynamic_cast<Player*>(*it)) {
  2982.                     (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2983.                 }
  2984.             }
  2985.         }
  2986.     }
  2987.  
  2988. }
  2989.  
  2990. //ground to container/inventory
  2991. void Game::thingMoveInternal(Player *player, const Position& fromPos, unsigned char stackPos,
  2992.                              uint16_t itemid, unsigned char to_cid, unsigned char to_slotid, bool toInventory, unsigned char count)
  2993. {
  2994.     Tile *fromTile = map->getTile(fromPos);
  2995.     if(!fromTile)
  2996.         return;
  2997.  
  2998.     Container *toContainer = NULL;
  2999.  
  3000.     Item* fromItem = dynamic_cast<Item*>(fromTile->getTopDownItem());
  3001.     Item *toItem = NULL;
  3002.  
  3003.     if(!fromItem || (fromItem->getID() != itemid) || (fromItem != fromTile->getTopDownItem()))
  3004.         return;
  3005.  
  3006.     if(toInventory)
  3007.     {
  3008.         toItem = player->getItem(to_cid);
  3009.         toContainer = dynamic_cast<Container*>(toItem);
  3010.     }
  3011.     else
  3012.     {
  3013.         toContainer = player->getContainer(to_cid);
  3014.         if(!toContainer)
  3015.             return;
  3016.  
  3017.         toItem = toContainer->getItem(to_slotid);
  3018.         Container *toSlotContainer = dynamic_cast<Container*>(toItem);
  3019.  
  3020.         if(toSlotContainer)
  3021.         {
  3022.             toContainer = toSlotContainer;
  3023.             toItem = NULL;
  3024.         }
  3025.     }
  3026.  
  3027.     if((toItem == fromItem) || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()))
  3028.         return;
  3029.  
  3030.     /*ground to container*/
  3031.     if(toContainer)
  3032.     {
  3033.         /*if(onPrepareMoveThing(player, fromItem, fromPos, player->pos, count) &&
  3034.                 onPrepareMoveThing(player, fromItem, NULL, toContainer, toItem, count))*/
  3035.  
  3036.         Position toPos = (toContainer->pos.x == 0xFFFF ? player->pos : toContainer->pos);
  3037.         if(onPrepareMoveThing(player, fromPos, NULL, fromItem, toPos, toContainer, toItem, count))
  3038.         {
  3039.             autoCloseTrade(fromItem, true);
  3040.             int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  3041.             int32_t oldToCount = 0;
  3042.             int32_t stackpos = fromTile->getThingStackPos(fromItem);
  3043.  
  3044.             if(fromItem->isStackable())
  3045.             {
  3046.                 if(toItem && toItem->getID() == fromItem->getID())
  3047.                 {
  3048.                     oldToCount = toItem->getItemCountOrSubtype();
  3049.                     int32_t newToCount = std::min(100, oldToCount + count);
  3050.                     toItem->setItemCountOrSubtype(newToCount);
  3051.  
  3052.                     if(oldToCount != newToCount)
  3053.                     {
  3054.                         autoCloseTrade(toItem);
  3055.                     }
  3056.  
  3057.                     int32_t subcount = oldFromCount - count;
  3058.                     fromItem->setItemCountOrSubtype(subcount);
  3059.  
  3060.                     int32_t surplusCount = oldToCount + count  - 100;
  3061.                     if(surplusCount > 0)
  3062.                     {
  3063.                         Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  3064.  
  3065.                         if(onPrepareMoveThing(player, fromPos, NULL, surplusItem, toPos, toContainer, NULL, count))
  3066.                         {
  3067.                             autoCloseTrade(toContainer);
  3068.                             toContainer->addItem(surplusItem);
  3069.                         }
  3070.                         else
  3071.                         {
  3072.                             delete surplusItem;
  3073.                             count -= surplusCount; //re-define the actual amount we move.
  3074.                             fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  3075.                         }
  3076.                     }
  3077.  
  3078.                     if(fromItem->getItemCountOrSubtype() == 0)
  3079.                     {
  3080.                         if(fromTile->removeThing(fromItem))
  3081.                         {
  3082.                             this->FreeThing(fromItem);
  3083.                         }
  3084.                     }
  3085.                 }
  3086.                 else if(count < oldFromCount)
  3087.                 {
  3088.                     int32_t subcount = oldFromCount - count;
  3089.                     fromItem->setItemCountOrSubtype(subcount);
  3090.  
  3091.                     autoCloseTrade(toContainer);
  3092.                     toContainer->addItem(Item::CreateItem(fromItem->getID(), count));
  3093.  
  3094.                     if(fromItem->getItemCountOrSubtype() == 0)
  3095.                     {
  3096.                         if(fromTile->removeThing(fromItem))
  3097.                         {
  3098.                             this->FreeThing(fromItem);
  3099.                         }
  3100.                     }
  3101.                 }
  3102.                 else if(fromTile->removeThing(fromItem))
  3103.                 {
  3104.                     autoCloseTrade(toContainer);
  3105.                     toContainer->addItem(fromItem);
  3106.                 }
  3107.             }
  3108.             else
  3109.             {
  3110.                 if(fromTile->removeThing(fromItem))
  3111.                 {
  3112.                     autoCloseTrade(toContainer);
  3113.                     toContainer->addItem(fromItem);
  3114.                 }
  3115.             }
  3116.  
  3117.             if(player->isHoldingContainer(toContainer))
  3118.             {
  3119.                 player->updateInventoryWeigth();
  3120.             }
  3121.  
  3122.             SpectatorVec list;
  3123.             SpectatorVec::iterator it;
  3124.  
  3125.             getSpectators(Range(fromPos, true), list);
  3126.  
  3127.             //players
  3128.             for(it = list.begin(); it != list.end(); ++it)
  3129.             {
  3130.                 if(dynamic_cast<Player*>(*it))
  3131.                 {
  3132.                     (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  3133.                 }
  3134.             }
  3135.  
  3136.             //none-players
  3137.             for(it = list.begin(); it != list.end(); ++it)
  3138.             {
  3139.                 if(!dynamic_cast<Player*>(*it))
  3140.                 {
  3141.                     (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  3142.                 }
  3143.             }
  3144.         }
  3145.     }
  3146.     //ground to inventory
  3147.     else if(toInventory)
  3148.     {
  3149.         if(onPrepareMoveThing(player, fromPos, fromItem, (slots_t)to_cid, count) && onPrepareMoveThing(player, fromItem, (slots_t)to_cid, count))
  3150.         {
  3151.             autoCloseTrade(fromItem, true);
  3152.             int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  3153.             int32_t oldToCount = 0;
  3154.             int32_t stackpos = fromTile->getThingStackPos(fromItem);
  3155.  
  3156.             //bbk 2020
  3157.             std::cout << "ground to inventory" << std::endl;
  3158.             if(fromItem && (slots_t)to_cid == SLOT_RING) {
  3159.                 fromItem->setGlimmer();
  3160.                 if(toItem) toItem->removeGlimmer();
  3161.             }
  3162.  
  3163.             if(fromItem->isStackable())
  3164.             {
  3165.                 if(toItem && toItem->getID() == fromItem->getID())
  3166.                 {
  3167.                     oldToCount = toItem->getItemCountOrSubtype();
  3168.                     int32_t newToCount = std::min(100, oldToCount + count);
  3169.                     toItem->setItemCountOrSubtype(newToCount);
  3170.  
  3171.                     if(oldToCount != newToCount)
  3172.                     {
  3173.                         autoCloseTrade(toItem);
  3174.                     }
  3175.  
  3176.                     int32_t subcount = oldFromCount - count;
  3177.                     fromItem->setItemCountOrSubtype(subcount);
  3178.  
  3179.                     int32_t surplusCount = oldToCount + count  - 100;
  3180.                     if(surplusCount > 0)
  3181.                     {
  3182.                         fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  3183.                         player->sendCancel("Sorry not enough room.");
  3184.                     }
  3185.  
  3186.                     if(fromItem->getItemCountOrSubtype() == 0)
  3187.                     {
  3188.                         if(fromTile->removeThing(fromItem))
  3189.                         {
  3190.                             this->FreeThing(fromItem);
  3191.                         }
  3192.                     }
  3193.                 }
  3194.                 else if(count < oldFromCount)
  3195.                 {
  3196.                     int32_t subcount = oldFromCount - count;
  3197.                     fromItem->setItemCountOrSubtype(subcount);
  3198.  
  3199.                     player->removeItemInventory(to_cid, true);
  3200.                     player->addItemInventory(Item::CreateItem(fromItem->getID(), count), to_cid, true);
  3201.  
  3202.                     if(toItem)
  3203.                     {
  3204.                         autoCloseTrade(toItem);
  3205.                         fromTile->addThing(toItem);
  3206.                         toItem->pos = fromPos;
  3207.                     }
  3208.  
  3209.                     if(fromItem->getItemCountOrSubtype() == 0)
  3210.                     {
  3211.                         if(fromTile->removeThing(fromItem))
  3212.                         {
  3213.                             this->FreeThing(fromItem);
  3214.                         }
  3215.                     }
  3216.                 }
  3217.                 else
  3218.                 {
  3219.                     if(fromTile->removeThing(fromItem))
  3220.                     {
  3221.                         player->removeItemInventory(to_cid, true);
  3222.                         player->addItemInventory(fromItem, to_cid, true);
  3223.  
  3224.                         if(toItem)
  3225.                         {
  3226.                             autoCloseTrade(toItem);
  3227.                             fromTile->addThing(toItem);
  3228.                             toItem->pos = fromPos;
  3229.                         }
  3230.                     }
  3231.                 }
  3232.             }
  3233.             else
  3234.             {
  3235.                 if(fromTile->removeThing(fromItem))
  3236.                 {
  3237.                     player->removeItemInventory(to_cid, true);
  3238.                     player->addItemInventory(fromItem, to_cid, true);
  3239.  
  3240.                     if(toItem)
  3241.                     {
  3242.                         autoCloseTrade(toItem);
  3243.                         fromTile->addThing(toItem);
  3244.                         toItem->pos = fromPos;
  3245.                     }
  3246.                 }
  3247.             }
  3248.  
  3249.             player->updateInventoryWeigth();
  3250.  
  3251.             SpectatorVec list;
  3252.             SpectatorVec::iterator it;
  3253.  
  3254.             getSpectators(Range(fromPos, true), list);
  3255.  
  3256.             //players
  3257.             for(it = list.begin(); it != list.end(); ++it)
  3258.             {
  3259.                 if(dynamic_cast<Player*>(*it))
  3260.                 {
  3261.                     (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  3262.                 }
  3263.             }
  3264.  
  3265.             //none-players
  3266.             for(it = list.begin(); it != list.end(); ++it)
  3267.             {
  3268.                 if(!dynamic_cast<Player*>(*it))
  3269.                 {
  3270.                     (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  3271.                 }
  3272.             }
  3273.         }
  3274.     }
  3275. }
  3276.  
  3277. //ground to ground
  3278. void Game::thingMoveInternal(Creature *creature, unsigned short from_x, unsigned short from_y, unsigned char from_z,
  3279.     unsigned char stackPos, unsigned short itemid, unsigned short to_x, unsigned short to_y, unsigned char to_z, unsigned char count)
  3280. {
  3281.     Tile *fromTile = getTile(from_x, from_y, from_z);
  3282.     if(!fromTile)
  3283.         return;
  3284.        
  3285. if(dynamic_cast<Player*>(creature) && fromTile && !fromTile->ground) {
  3286. dynamic_cast<Player*>(creature)->sendCancelWalk();
  3287. return;
  3288. }
  3289.  
  3290.     Tile *toTile   = getTile(to_x, to_y, to_z);
  3291.     /*
  3292.     if(!toTile){
  3293.         if(dynamic_cast<Player*>(player))
  3294.             dynamic_cast<Player*>(player)->sendCancelWalk("Sorry, not possible...");
  3295.         return;
  3296.     }
  3297.     */
  3298.  
  3299.     Thing *thing = fromTile->getThingByStackPos(stackPos);
  3300.  
  3301.     if (!thing)
  3302.         return;
  3303.  
  3304.     Item* item = dynamic_cast<Item*>(thing);
  3305.     Creature* creatureMoving = dynamic_cast<Creature*>(thing);
  3306.     Player* playerMoving = dynamic_cast<Player*>(creatureMoving);
  3307.     Player* player = dynamic_cast<Player*>(creature);
  3308.  
  3309.     Position oldPos;
  3310.     oldPos.x = from_x;
  3311.     oldPos.y = from_y;
  3312.     oldPos.z = from_z;
  3313.    
  3314. #ifdef TP_TRASH_BINS
  3315.     if(toTile)
  3316.     {
  3317.         Thing *tothing = toTile->getThingByStackPos(stackPos);
  3318.         Item *toItem = dynamic_cast<Item*>(tothing);
  3319.  
  3320.         if(item && toItem && !playerMoving && !creature && toItem->isDeleter())
  3321.         {
  3322.             fromTile->removeThing(item);
  3323.             this->FreeThing(item);
  3324.             //creatureBroadcastTileUpdated(oldPos);
  3325.             sendRemoveThing(player, item->pos, item, stackPos);
  3326.             return;
  3327.         }
  3328.     }
  3329. #endif //TP_TRASH_BINS
  3330. /* if (toTile){
  3331. ItemVector::iterator brn;
  3332. for (brn = toTile->downItems.begin(); brn != toTile->downItems.end(); brn++)
  3333. {
  3334. if (playerMoving && (*brn)->getID() == 1397 && player != thing || playerMoving && (*brn)->getID() == 1487 && player != thing || playerMoving && (*brn)->getID() == 1488 && player != thing || playerMoving && (*brn)->getID() == 1490 && player != thing || playerMoving && (*brn)->getID() == 1491 && player != thing || playerMoving && (*brn)->getID() == 1492 && player != thing || playerMoving && (*brn)->getID() == 1493 && player != thing || playerMoving && (*brn)->getID() == 1495 && player != thing || playerMoving && (*brn)->getID() == 1496 && player != thing || playerMoving && (*brn)->getID() == 1500 && player != thing || playerMoving && (*brn)->getID() == 1501 && player != thing || playerMoving && (*brn)->getID() == 1503 && player != thing || playerMoving && (*brn)->getID() == 1504 && player != thing || playerMoving && (*brn)->getID() == 1505 && player != thing || playerMoving && (*brn)->getID() == 1506 && player != thing || playerMoving && (*brn)->getID() == 1507 && player != thing || playerMoving && (*brn)->getID() == 1423 && player != thing || playerMoving && (*brn)->getID() == 1424 && player != thing || playerMoving && (*brn)->getID() == 1425 && player != thing)
  3335. */
  3336. if(toTile && player && playerMoving && playerMoving != player && toTile->getFieldItem())
  3337. {
  3338. player->sendCancel("Sorry, not possible.");
  3339. return;
  3340. }
  3341.     // *** Creature moving itself to a non-tile
  3342.     if(!toTile && creatureMoving && creatureMoving == creature){
  3343.         //change level begin
  3344.         Tile* downTile = getTile(to_x, to_y, to_z+1);
  3345.         //diagonal begin
  3346.         if(!downTile)
  3347.         {
  3348.             if(player) {
  3349.                 player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  3350.                 player->sendCancelWalk();
  3351.             }
  3352.  
  3353.             return;
  3354.         }
  3355.        
  3356.         if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  3357.             teleport(creatureMoving, Position(creatureMoving->pos.x-2, creatureMoving->pos.y+2, creatureMoving->pos.z+1));
  3358.         }
  3359.         else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  3360.             teleport(creatureMoving, Position(creatureMoving->pos.x+2, creatureMoving->pos.y+2, creatureMoving->pos.z+1));
  3361.         }
  3362.         else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  3363.             teleport(creatureMoving, Position(creatureMoving->pos.x-2, creatureMoving->pos.y-2, creatureMoving->pos.z+1));
  3364.         }
  3365.         else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  3366.             teleport(creatureMoving, Position(creatureMoving->pos.x+2, creatureMoving->pos.y-2, creatureMoving->pos.z+1));
  3367.         }
  3368.         //diagonal end
  3369.         else if(downTile->floorChange(NORTH)){
  3370.             teleport(creatureMoving, Position(to_x, to_y + 1, creatureMoving->pos.z+1));
  3371.         }
  3372.         else if(downTile->floorChange(SOUTH)){
  3373.             teleport(creatureMoving, Position(to_x, to_y - 1, creatureMoving->pos.z+1));
  3374.         }
  3375.         else if(downTile->floorChange(EAST)){
  3376.             teleport(creatureMoving, Position(to_x - 1, to_y, creatureMoving->pos.z+1));
  3377.         }
  3378.         else if(downTile->floorChange(WEST)){
  3379.             teleport(creatureMoving, Position(to_x + 1, to_y, creatureMoving->pos.z+1));
  3380.         }
  3381.         else
  3382.             if(player) {
  3383.                 player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  3384.                 player->sendCancelWalk();
  3385.             }
  3386.  
  3387.         //change level end
  3388.         return;
  3389.     }
  3390.    
  3391.     #ifdef DT_PREMMY
  3392.       if(player && playerMoving && !player->premmium == true){
  3393.            if(!premmytiles.empty()){
  3394.             for(int32_t o = 0; o < premmytiles.size(); o++) {
  3395.                 if((premmytiles[o].second.x != 0) &&
  3396. (premmytiles[o].second.y != 0) && (premmytiles[o].second.z != 0)){
  3397.                     if(Position(to_x, to_y, to_z) == premmytiles[o].first) {
  3398.                         player->sendCancelWalk();
  3399.                         teleport(playerMoving,
  3400. Position(premmytiles[o].second.x, premmytiles[o].second.y,
  3401. premmytiles[o].second.z));
  3402.                         player->sendMagicEffect(player->pos,
  3403. NM_ME_MAGIC_ENERGIE);
  3404.                         return;
  3405.                     }
  3406.                 }
  3407.                 else{
  3408.                     if(Position(to_x, to_y, to_z) == premmytiles[o].first) {
  3409.                         player->sendCancelWalk();
  3410.                         break;
  3411.                     }
  3412.                 }
  3413.             }
  3414.         }
  3415.     }
  3416.  
  3417. #endif //DT_PREMMY
  3418.  
  3419.  
  3420.  
  3421.     // *** Checking if the thing can be moved around
  3422.  
  3423.     if(!toTile)
  3424.         return;
  3425.  
  3426.     if(!onPrepareMoveThing(creature, thing, oldPos, Position(to_x, to_y, to_z), count))
  3427.         return;
  3428.  
  3429.     if(creatureMoving && !onPrepareMoveCreature(creature, creatureMoving, fromTile, toTile))
  3430.         return;
  3431.  
  3432.     if(!onPrepareMoveThing(creature, thing, fromTile, toTile, count))
  3433.         return;
  3434.        
  3435.              Position to_pos;
  3436.      to_pos.x = to_x;
  3437.      to_pos.y = to_y;
  3438.      to_pos.z = to_z;
  3439.  
  3440.     Item* fromItem = dynamic_cast<Item*>(getThing(oldPos, stackPos, player));
  3441.     Item* toItem = dynamic_cast<Item*>(toTile->getTopDownItem());
  3442.  
  3443.     if(fromItem && fromItem->isStackable()){
  3444.                 if(fromItem->getItemCountOrSubtype() < count)
  3445.                 {
  3446.                 player->sendCancel("Sorry, not possible.");
  3447.                 return;
  3448.                 }
  3449.  
  3450.         if((abs(player->pos.x - oldPos.x) > 1) || (abs(player->pos.y - oldPos.y) > 1) || (player->pos.z != oldPos.z)){
  3451.                player->sendCancel("It's far away.");
  3452.                return;
  3453.         }
  3454.         if(toItem && fromItem->getID() == toItem->getID()){
  3455.             int32_t oldToCount = toItem->getItemCountOrSubtype();
  3456.             int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  3457.             int32_t newToCount = std::min(100, oldToCount + count);
  3458.             toItem->setItemCountOrSubtype(newToCount);
  3459.  
  3460.             if(oldToCount != newToCount) {
  3461.                 autoCloseTrade(toItem);
  3462.             }
  3463.  
  3464.             int32_t subcount = oldFromCount - count;
  3465.             fromItem->setItemCountOrSubtype(subcount);
  3466.  
  3467.             int32_t surplusCount = oldToCount + count  - 100;
  3468.             if(surplusCount > 0) {
  3469.                 Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  3470.                 surplusItem->pos = to_pos;
  3471.                 toTile->addThing(surplusItem);
  3472.             }
  3473.  
  3474.             if(fromItem->getItemCountOrSubtype() == 0) {
  3475.                 if(removeThing(player, oldPos, fromItem))
  3476.                     player->updateInventoryWeigth();
  3477.             }
  3478.  
  3479.             creatureBroadcastTileUpdated(to_pos);
  3480.             creatureBroadcastTileUpdated(oldPos);
  3481.  
  3482.             return;
  3483.        }
  3484.        else if(count < fromItem->getItemCountOrSubtype()) {
  3485.             int32_t subcount = fromItem->getItemCountOrSubtype() - count;
  3486.             fromItem->setItemCountOrSubtype(subcount);
  3487.  
  3488.             Item *moveItem = Item::CreateItem(fromItem->getID(), count);
  3489.             moveItem->pos = to_pos;
  3490.             toTile->addThing(moveItem);
  3491.  
  3492.             if(fromItem->getItemCountOrSubtype() == 0) {
  3493.                 if(removeThing(player, oldPos, fromItem))
  3494.                           player->updateInventoryWeigth();
  3495.             }
  3496.  
  3497.             creatureBroadcastTileUpdated(to_pos);
  3498.                creatureBroadcastTileUpdated(oldPos);
  3499.             return;
  3500.           }
  3501.           else{
  3502.                Item *moveItem = Item::CreateItem(fromItem->getID(), fromItem->getItemCountOrSubtype());
  3503.                moveItem->pos = to_pos;
  3504.                toTile->addThing(moveItem);
  3505.  
  3506.                if(removeThing(player, oldPos, fromItem))
  3507.                     player->updateInventoryWeigth();
  3508.  
  3509.                creatureBroadcastTileUpdated(to_pos);
  3510.                creatureBroadcastTileUpdated(oldPos);
  3511.                return;
  3512.           }
  3513.  
  3514.           return;
  3515.     }
  3516.  
  3517.     /*
  3518.     if(item && (item->getID() != itemid || item != fromTile->getTopDownItem()))
  3519.         return;
  3520.     */
  3521.  
  3522.     // *** If the destiny is a teleport item, teleport the thing
  3523.  
  3524. const Teleport *teleportitem = toTile->getTeleportItem();
  3525.     if(teleportitem) {
  3526.         Player *player = dynamic_cast<Player*>(thing);
  3527.         teleport(thing, teleportitem->getDestPos());
  3528.         if(player) {
  3529.         globalMagicEffect(player->pos, NM_ME_ENERGY_AREA);
  3530.         }
  3531.         return;
  3532.     }
  3533.  
  3534.    Monster* monsterMoving = dynamic_cast<Monster*>(creatureMoving);
  3535.    if (monsterMoving && toTile->isPz()){
  3536.    return;
  3537.    }
  3538.    
  3539. #ifdef TLM_HOUSE_SYSTEM
  3540.     if (playerMoving && toTile->getHouse() &&
  3541.         (fromTile->getHouse() != toTile->getHouse() || playerMoving->houseRightsChanged))
  3542.     {
  3543.         if (playerMoving->access < g_config.ACCESS_HOUSE &&
  3544.             toTile->getHouse()->getPlayerRights(playerMoving->getName()) == HOUSE_NONE)
  3545.         {
  3546.             playerMoving->sendTextMessage(MSG_SMALLINFO, "You are not invited.");
  3547.             playerMoving->sendCancelWalk();
  3548.             return;
  3549.         }
  3550.         else
  3551.             playerMoving->houseRightsChanged = false;   // if we are invited stop checking rights
  3552.     }
  3553. #endif //TLM_HOUSE_SYSTEM
  3554.  
  3555.     // *** Normal moving
  3556.  
  3557.     if(creatureMoving)
  3558.     {
  3559.         // we need to update the direction the player is facing to...
  3560.         // otherwise we are facing some problems in turning into the
  3561.         // direction we were facing before the movement
  3562.         // check y first cuz after a diagonal move we lock to east or west
  3563.         if (to_y < oldPos.y) creatureMoving->direction = NORTH;
  3564.         if (to_y > oldPos.y) creatureMoving->direction = SOUTH;
  3565.         if (to_x > oldPos.x) creatureMoving->direction = EAST;
  3566.         if (to_x < oldPos.x) creatureMoving->direction = WEST;
  3567.     }
  3568.  
  3569.     int32_t oldstackpos = fromTile->getThingStackPos(thing);
  3570.     if (fromTile->removeThing(thing))
  3571.     {
  3572.         toTile->addThing(thing);
  3573.  
  3574.         thing->pos.x = to_x;
  3575.         thing->pos.y = to_y;
  3576.         thing->pos.z = to_z;
  3577.  
  3578.         SpectatorVec list;
  3579.         SpectatorVec::iterator it;
  3580.  
  3581.         getSpectators(Range(oldPos, Position(to_x, to_y, to_z)), list);
  3582.  
  3583. #ifdef TRS_GM_INVISIBLE
  3584.         if(playerMoving && playerMoving->gmInvisible)
  3585.         {
  3586.             for(it = list.begin(); it != list.end(); ++it)
  3587.             {
  3588.                 if(playerMoving == (*it) || (*it)->access >= playerMoving->access)
  3589.                 {
  3590.                     if(Player* p = dynamic_cast<Player*>(*it))
  3591.                     {
  3592.                         if(p->attackedCreature == creature->getID())
  3593.                         {
  3594.                             autoCloseAttack(p, creature);
  3595.                         }
  3596.                         (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3597.                     }
  3598.                 }
  3599.             }
  3600.         }
  3601.         else if(playerMoving && !playerMoving->gmInvisible)
  3602.         {
  3603.             for(it = list.begin(); it != list.end(); ++it)
  3604.             {
  3605.                 if(Player* p = dynamic_cast<Player*>(*it))
  3606.                 {
  3607.                     if(p->attackedCreature == creature->getID())
  3608.                     {
  3609.                         autoCloseAttack(p, creature);
  3610.                     }
  3611.                     (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3612.                 }
  3613.             }
  3614.         }
  3615.         else
  3616.         {
  3617.             for(it = list.begin(); it != list.end(); ++it)
  3618.             {
  3619.                 if(Player* p = dynamic_cast<Player*>(*it))
  3620.                 {
  3621.                     if(p->attackedCreature == creature->getID())
  3622.                     {
  3623.                         autoCloseAttack(p, creature);
  3624.                     }
  3625.                     (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3626.                 }
  3627.             }
  3628.         }
  3629. #else //TRS_GM_INVISIBLE
  3630.         //players
  3631.         for(it = list.begin(); it != list.end(); ++it)
  3632.         {
  3633.             if(Player* p = dynamic_cast<Player*>(*it)) {
  3634.         if(p->attackedCreature == creature->getID()) {
  3635.           autoCloseAttack(p, creature);
  3636.         }
  3637.                 (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3638.             }
  3639.         }
  3640. #endif //TRS_GM_INVISIBLE
  3641.  
  3642.         //none-players
  3643.         for(it = list.begin(); it != list.end(); ++it)
  3644.         {
  3645.             if(!dynamic_cast<Player*>(*it)) {
  3646.                 (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3647.             }
  3648.         }
  3649.  
  3650.         autoCloseTrade(item, true);
  3651.         //depot tiles
  3652.        
  3653.         if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 426))
  3654. {
  3655. int32_t e = 0;
  3656. Container* c = playerMoving->getDepot(1);
  3657. std::stringstream s;
  3658. e += getDepot(c, e);
  3659. s << "Your depot contains " << e;
  3660. if(e > 1)
  3661. s << " items.";
  3662. else
  3663. s << " item.";
  3664. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3665. }
  3666.  
  3667. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 416))
  3668. {
  3669. int32_t e = 0;
  3670. Container* c = playerMoving->getDepot(2);
  3671. std::stringstream s;
  3672. e += getDepot(c, e);
  3673. s << "Your depot contains " << e;
  3674. if(e > 1)
  3675. s << " items.";
  3676. else
  3677. s << " item.";
  3678. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3679. }
  3680.  
  3681. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 446))
  3682. {
  3683. int32_t e = 0;
  3684. Container* c = playerMoving->getDepot(3);
  3685. std::stringstream s;
  3686. e += getDepot(c, e);
  3687. s << "Your depot contains " << e;
  3688. if(e > 1)
  3689. s << " items.";
  3690. else
  3691. s << " item.";
  3692. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3693. }
  3694.  
  3695. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 3216))
  3696. {
  3697. int32_t e = 0;
  3698. Container* c = playerMoving->getDepot(4);
  3699. std::stringstream s;
  3700. e += getDepot(c, e);
  3701. s << "Your depot contains " << e;
  3702. if(e > 1)
  3703. s << " items.";
  3704. else
  3705. s << " item.";
  3706. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3707. }
  3708.        
  3709.         if(playerMoving && toTile && fromTile)
  3710.         {
  3711.             actions.luaWalk(playerMoving,playerMoving->pos,toTile->ground->getID(),toTile->ground->getUniqueId(),toTile->ground->getActionId()); //CHANGE onWalk
  3712.         }
  3713.  
  3714.         if(playerMoving && toTile && fromTile)
  3715.         {
  3716.             actions.luaWalkOff(playerMoving,oldPos,fromTile->ground->getID(),fromTile->ground->getUniqueId(),fromTile->ground->getActionId()); //CHANGE onWalk
  3717.         }
  3718.        
  3719. if(playerMoving && fromTile && toTile && player == playerMoving)
  3720. switch(toTile->ground->getID())
  3721. {
  3722. case 416:
  3723. {
  3724. toTile->removeThing(toTile->ground);
  3725. toTile->addThing(new Item(417));
  3726. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3727. }
  3728. break;
  3729.  
  3730. case 426:
  3731. {
  3732. toTile->removeThing(toTile->ground);
  3733. toTile->addThing(new Item(425));
  3734. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3735. }
  3736. break;
  3737. case 3216:
  3738. {
  3739. toTile->removeThing(toTile->ground);
  3740. toTile->addThing(new Item(3217));
  3741. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3742. }
  3743. break;
  3744. case 446:
  3745. {
  3746. toTile->removeThing(toTile->ground);
  3747. toTile->addThing(new Item(447));
  3748. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3749. }
  3750. break;
  3751. case 293:
  3752. {
  3753. toTile->removeThing(toTile->ground);
  3754. toTile->addThing(new Item(294));
  3755. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3756. }
  3757. break;
  3758. }
  3759. switch(fromTile->ground->getID())
  3760. {
  3761. case 3217:
  3762. {
  3763. fromTile->removeThing(fromTile->ground);
  3764. fromTile->addThing(new Item(3216));
  3765. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3766. break;
  3767. }
  3768. case 417:
  3769. {
  3770. fromTile->removeThing(fromTile->ground);
  3771. fromTile->addThing(new Item(416));
  3772. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3773. break;
  3774. }
  3775. case 425:
  3776. {
  3777. fromTile->removeThing(fromTile->ground);
  3778. fromTile->addThing(new Item(426));
  3779. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3780. break;
  3781. }
  3782. case 447:
  3783. {
  3784. fromTile->removeThing(fromTile->ground);
  3785. fromTile->addThing(new Item(446));
  3786. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3787. break;
  3788. }
  3789. }
  3790. //end depot tiles-+
  3791.         if (playerMoving)
  3792.         {
  3793.             if(playerMoving->attackedCreature != 0) {
  3794.                 Creature* attackedCreature = getCreatureByID(creatureMoving->attackedCreature);
  3795.                 if(attackedCreature){
  3796.           autoCloseAttack(playerMoving, attackedCreature);
  3797.                 }
  3798.             }
  3799.  
  3800.             if(playerMoving->tradePartner != 0) {
  3801.                 Player* tradePartner = getPlayerByID(playerMoving->tradePartner);
  3802.                 if(tradePartner) {
  3803.                     if((std::abs(playerMoving->pos.x - tradePartner->pos.x) > 2) ||
  3804.                     (std::abs(playerMoving->pos.y - tradePartner->pos.y) > 2) || (playerMoving->pos.z != tradePartner->pos.z)
  3805.                     #ifdef HUCZU_FIX
  3806.                     || (fromTile->isHouse() && !toTile->isHouse())
  3807.                     #endif //HUCZU_FIX
  3808.                     ){
  3809.                         playerCloseTrade(playerMoving);
  3810.                     }
  3811.                 }
  3812.             }
  3813.  
  3814.             //change level begin
  3815.             if(toTile->floorChangeDown())
  3816.             {
  3817.                 Tile* downTile = getTile(to_x, to_y, to_z+1);
  3818.                 if(downTile){
  3819.                     //diagonal begin
  3820.                     if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  3821.                         teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y+1, playerMoving->pos.z+1));
  3822.                     }
  3823.                     else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  3824.                         teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y+1, playerMoving->pos.z+1));
  3825.                     }
  3826.                     else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  3827.                         teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y-1, playerMoving->pos.z+1));
  3828.                     }
  3829.                     else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  3830.                         teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y-1, playerMoving->pos.z+1));
  3831.                     }
  3832.                     //diagonal end
  3833.                     else if(downTile->floorChange(NORTH)){
  3834.                         teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y+1, playerMoving->pos.z+1));
  3835.                     }
  3836.                     else if(downTile->floorChange(SOUTH)){
  3837.                         teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y-1, playerMoving->pos.z+1));
  3838.                     }
  3839.                     else if(downTile->floorChange(EAST)){
  3840.                         teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y, playerMoving->pos.z+1));
  3841.                     }
  3842.                     else if(downTile->floorChange(WEST)){
  3843.                         teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y, playerMoving->pos.z+1));
  3844.                     }
  3845.                     else { //allow just real tiles to be hole'like
  3846.                         // TODO: later can be changed to check for piled items like chairs, boxes
  3847.                         teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y, playerMoving->pos.z+1));
  3848.                     }
  3849.                 }
  3850.             }
  3851.             //diagonal begin
  3852.             else if(toTile->floorChange(NORTH) && toTile->floorChange(EAST)){
  3853.                 teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y-1, playerMoving->pos.z-1));
  3854.             }
  3855.             else if(toTile->floorChange(NORTH) && toTile->floorChange(WEST)){
  3856.                 teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y-1, playerMoving->pos.z-1));
  3857.             }
  3858.             else if(toTile->floorChange(SOUTH) && toTile->floorChange(EAST)){
  3859.                 teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y+1, playerMoving->pos.z-1));
  3860.             }
  3861.             else if(toTile->floorChange(SOUTH) && toTile->floorChange(WEST)){
  3862.                 teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y+1, playerMoving->pos.z-1));
  3863.             }
  3864.             //diagonal end
  3865.             else if(toTile->floorChange(NORTH)){
  3866.                 teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y-1, playerMoving->pos.z-1));
  3867.             }
  3868.             else if(toTile->floorChange(SOUTH)){
  3869.                 teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y+1, playerMoving->pos.z-1));
  3870.             }
  3871.             else if(toTile->floorChange(EAST)){
  3872.                 teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y, playerMoving->pos.z-1));
  3873.             }
  3874.             else if(toTile->floorChange(WEST)){
  3875.                 teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y, playerMoving->pos.z-1));
  3876.             }
  3877.             //change level end
  3878.         }
  3879.  
  3880. // Magic Field in destiny field
  3881. #ifdef HUCZU_FIX
  3882.                 if(toTile && playerMoving && playerMoving->access < g_config.ACCESS_PROTECT && !toTile->downItems.empty() && !toTile->isPvpArena())
  3883. #else
  3884.                 if(toTile && playerMoving && playerMoving->access < g_config.ACCESS_PROTECT && !toTile->downItems.empty() || toTile && creatureMoving && creatureMoving->access < g_config.ACCESS_PROTECT && !toTile->downItems.empty())
  3885. #endif //HUCZU_FIX            
  3886.             {
  3887.                ItemVector::iterator iit;
  3888.                for (iit = toTile->downItems.begin(); iit != toTile->downItems.end(); iit++)
  3889.                {
  3890.                   if(toTile->isPvpArena()) break;
  3891.                   if(!(*iit)) continue;
  3892.                   Item *item = dynamic_cast<Item*>(*iit);
  3893.                   if(!item) continue;
  3894.                   if(!creatureMoving || creatureMoving->isRemoved || creatureMoving->health <= 0) break;
  3895.                   if (item->getID() == 1492 || item->getID() == 1423 || item->getID() == 1487 || item->getID() == 1500){//Fire - Big
  3896.                      doFieldDamage(creatureMoving,        199     , NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE,  true,       20);
  3897.                     //                creature     DamageColor,    damageEffect,      hitEffect      attackType, offensive,   damage
  3898.                      if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3899.                         CreateCondition(creatureMoving, NULL, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 10, 10, 2000, 10);
  3900.                   }
  3901.                   else if(item->getID() == 1493 || item->getID() == 1424 || item->getID() == 1488 || item->getID() == 1501){//Fire Medium
  3902.                     doFieldDamage(creatureMoving, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 10);
  3903.                     if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3904.                        CreateCondition(creatureMoving, NULL, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 10, 10, 2000, 10);  
  3905.                   }
  3906.                   else if(item->getID() == 1495 || item->getID() == 1491 || item->getID() == 1504){//Energy
  3907.                     doFieldDamage(creatureMoving, 71, NM_ME_ENERGY_DAMAGE,  NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 30);
  3908.                     if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3909.                        CreateCondition(creatureMoving, NULL, 71, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 30, 30, 2000, 3);  
  3910.                   }
  3911.                   else if(item->getID() == 1496 || item->getID() == 1490 || item->getID() == 1503 || item->getID() == 1505){//Poison
  3912.                     doFieldDamage(creatureMoving, 30, NM_ME_POISEN, NM_ME_POISEN, ATTACK_POISON, true, 10);
  3913.                     if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3914.                        CreateCondition(creatureMoving, NULL, 30, NM_ME_POISEN, NM_ME_POISEN_RINGS, ATTACK_POISON, true, 10, 10, 2000, 10);  
  3915.                   }
  3916.                   }
  3917.             }
  3918.             }
  3919.        
  3920.                 if(creatureMoving && !toTile->isPvpArena())
  3921.         {
  3922.             const MagicEffectItem* fieldItem = toTile->getFieldItem();
  3923.  
  3924.             if(fieldItem) {
  3925.                 const MagicEffectTargetCreatureCondition *magicTargetCondition = fieldItem->getCondition();
  3926.  
  3927.                 if(!(getWorldType() == WORLD_TYPE_NO_PVP && playerMoving && magicTargetCondition && magicTargetCondition->getOwnerID() != 0)) {
  3928.                     fieldItem->getDamage(creatureMoving);
  3929.                 }
  3930.  
  3931.                 if(magicTargetCondition && ((magicTargetCondition->attackType == ATTACK_FIRE) ||
  3932.                         (magicTargetCondition->attackType == ATTACK_POISON) ||
  3933.                         (magicTargetCondition->attackType == ATTACK_ENERGY))) {
  3934.                     Creature *c = getCreatureByID(magicTargetCondition->getOwnerID());
  3935.                     creatureMakeMagic(c, thing->pos, magicTargetCondition);
  3936.                 }
  3937.           }
  3938.     }
  3939. }
  3940.    
  3941.  
  3942. void Game::getSpectators(const Range& range, SpectatorVec& list)
  3943. {
  3944.     map->getSpectators(range, list);
  3945. }
  3946.  
  3947. void Game::creatureTurn(Creature *creature, Direction dir)
  3948. {
  3949.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureTurn()");
  3950.  
  3951.     if (creature->direction != dir) {
  3952.         creature->direction = dir;
  3953.  
  3954.         int32_t stackpos = map->getTile(creature->pos)->getThingStackPos(creature);
  3955.  
  3956.         SpectatorVec list;
  3957.         SpectatorVec::iterator it;
  3958.  
  3959.         map->getSpectators(Range(creature->pos, true), list);
  3960.  
  3961.         //players
  3962.         for(it = list.begin(); it != list.end(); ++it) {
  3963.             if(dynamic_cast<Player*>(*it)) {
  3964.                 (*it)->onCreatureTurn(creature, stackpos);
  3965.             }
  3966.         }
  3967.  
  3968.         //none-players
  3969.         for(it = list.begin(); it != list.end(); ++it) {
  3970.             if(!dynamic_cast<Player*>(*it)) {
  3971.                 (*it)->onCreatureTurn(creature, stackpos);
  3972.             }
  3973.         }
  3974.     }
  3975. }
  3976.  
  3977. void Game::addCommandTag(std::string tag){
  3978.     bool found = false;
  3979.     for(size_t i=0;i< commandTags.size() ;i++){
  3980.         if(commandTags[i] == tag){
  3981.             found = true;
  3982.             break;
  3983.         }
  3984.     }
  3985.     if(!found){
  3986.         commandTags.push_back(tag);
  3987.     }
  3988. }
  3989.  
  3990. void Game::resetCommandTag(){
  3991.     commandTags.clear();
  3992. }
  3993.  
  3994. void Game::creatureSay(Creature *creature, SpeakClasses type, const std::string &text)
  3995. {
  3996.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureSay()");
  3997.     using std::string;
  3998.     string spoken=text;
  3999.     std::transform(spoken.begin(), spoken.end(), spoken.begin(), (int32_t(*)(int32_t))std::tolower);
  4000.     bool GMcommand = false;
  4001.     // First, check if this was a GM command
  4002.     for(size_t i=0;i< commandTags.size() ;i++){
  4003.         if(commandTags[i] == text.substr(0,1)){
  4004.             if(commands.exeCommand(creature,text)){
  4005.                 GMcommand = true;
  4006.             }
  4007.             break;
  4008.         }
  4009.     }
  4010.     Player* p = dynamic_cast<Player*>(creature);
  4011.     Player* player = dynamic_cast<Player*>(creature);
  4012.  
  4013. #ifdef HUCZU_FIX
  4014.     if (player && spoken == "exevo grav vita" && (!g_config.LEARN_SPELLS || player->knowsSpell("exevo grav vita")))
  4015.      {
  4016.       Tile *tile = NULL;
  4017.       Position wgpos;
  4018.       wgpos.z = player->pos.z;
  4019.        switch(player->direction)
  4020.         {
  4021.                 case NORTH:
  4022.                 wgpos.x = player->pos.x;
  4023.                 wgpos.y = player->pos.y-1;
  4024.                 break;
  4025.               case SOUTH:
  4026.                 wgpos.x = player->pos.x;
  4027.                 wgpos.y = player->pos.y+1;
  4028.                 break;
  4029.               case EAST:
  4030.                 wgpos.x = player->pos.x+1;
  4031.                 wgpos.y = player->pos.y;
  4032.                 break;
  4033.               case WEST:
  4034.                 wgpos.x = player->pos.x-1;
  4035.                 wgpos.y = player->pos.y;
  4036.                 break;
  4037.               default:
  4038.                 break;
  4039.             }
  4040.             tile = getTile(wgpos.x, wgpos.y, wgpos.z);
  4041.             if(!tile || tile->isBlocking(BLOCK_SOLID,false,false) || tile->isPz())
  4042.               {
  4043.                player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4044.                player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  4045.                return;
  4046.               }
  4047.         if(player->access < 2)
  4048.         {
  4049.            if(player->mana < 220)
  4050.            {
  4051.               player->sendCancel("You do not have enough mana.");
  4052.               player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4053.               return;
  4054.            }
  4055.            if(!player->premmium)           
  4056.            {               
  4057.              player->sendMagicEffect(player->pos, NM_ME_PUFF);         
  4058.              player->sendCancel("You need buy a premmium account for use this spell");         
  4059.              return;       
  4060.            }  
  4061.            if(player->maglevel < 26){
  4062.              player->sendCancel("You do not have the magic level.");
  4063.              player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4064.              return;
  4065.            }
  4066.            if(player->vocation != 2)
  4067.            {
  4068.            player->sendTextMessage(MSG_SMALLINFO, "You do not have the required vocation.");  
  4069.            player->sendMagicEffect(player->pos, 2);    
  4070.            return;
  4071.            }  
  4072.            if (player->exhaustedTicks >= 1000)
  4073.            {
  4074.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4075.             player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");  
  4076.             return;
  4077.            }
  4078.         }          
  4079.                 player->mana -= 220;
  4080.                 player->addManaSpent(220);
  4081.                 player->exhaustedTicks = g_config.EXHAUSTED;
  4082.                 Item* Tree = Item::CreateItem(ITEM_WILDGROWTH, 1);  
  4083.                 addThing(NULL, wgpos, Tree);
  4084.                 startDecay(Tree);
  4085.                 SpectatorVec list;
  4086.                 SpectatorVec::iterator it;
  4087.                 getSpectators(Range(player->pos), list);
  4088.                   for(it = list.begin(); it != list.end(); ++it) {
  4089.                     Player* playerek = dynamic_cast<Player*>(*it);
  4090.                       if(playerek)
  4091.                         playerek->sendMagicEffect(playerek->pos, NM_ME_MAGIC_POISEN);  
  4092.                   }
  4093.                 player->sendMagicEffect(player->pos, NM_ME_MAGIC_ENERGIE);
  4094.             }
  4095. #endif //HUCZU_FIX
  4096.  
  4097. if(spoken=="exana pox"){
  4098.            MagicEffectClass pox;
  4099.            pox.animationColor = 0;
  4100.            pox.damageEffect = NM_ME_MAGIC_ENERGIE;
  4101.            pox.hitEffect = 255;
  4102.            pox.attackType = ATTACK_NONE;
  4103.            pox.maxDamage = 0;
  4104.            pox.minDamage = 0;
  4105.            pox.offensive = false;
  4106.            pox.manaCost = 30;
  4107.            if(creatureMakeMagic(creature, creature->pos, &pox)){
  4108.            creature->removeCondition(ATTACK_POISON);
  4109.            
  4110.            if(player)
  4111.            player->sendIcons();
  4112.            }
  4113.         }
  4114.        
  4115.     if(!GMcommand){
  4116.  Player* player = dynamic_cast<Player*>(creature);
  4117.  
  4118.    if(text=="!besthit")
  4119.         {
  4120.                 std::stringstream info;
  4121.                 if(player->maxDmg>0){
  4122.                 info << "Your best hit: " << player->maxDmg;}
  4123.                 else{
  4124.                 info << "You didn't any damage.";}
  4125.                 player->sendTextMessage(MSG_EVENT,info.str().c_str());
  4126.         }
  4127.  
  4128. if(player && (text[0] == 'e' || text[0] == 'E') && (text[1] == 'x' || text[1] == 'X') && (text[2] == 'a' || text[2] == 'A') && (text[3] == 'n' || text[3] == 'N') && (text[4] == 'a' || text[4] == 'A') && (text[5] == ' ') && (text[6] == 'a' || text[6] == 'A') && (text[7] == 'n' || text[7] == 'N') && (text[8] == 'i' || text[8] == 'i')) {
  4129.  
  4130.          if(player->mana < 200) {
  4131.              player->sendCancel("You do not have enough mana.");
  4132.              player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4133.              return;
  4134.          }
  4135.          if(player->maglevel < 15) {
  4136.              player->sendCancel("You do not have the magic level.");
  4137.              player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4138.              return;
  4139.          }
  4140.          if(player->vocation != 1)
  4141. {
  4142. player->sendTextMessage(MSG_SMALLINFO, "You do not have the required vocation.");  
  4143. player->sendMagicEffect(player->pos, 2);    
  4144. return;
  4145. }
  4146.          player->mana -= 200;
  4147.          player->addManaSpent(200);
  4148.          SpectatorVec list;
  4149.          SpectatorVec::iterator it;
  4150.          getSpectators(Range(creature->pos), list);
  4151.          for(it = list.begin(); it != list.end(); ++it) {
  4152.             if(Creature *c = dynamic_cast<Creature*>(*it)) {
  4153.     if(c)
  4154. {
  4155.         c->setInvisible(0);
  4156.         creatureChangeOutfit(c);
  4157.             }
  4158.          }
  4159.          player->sendMagicEffect(player->pos, NM_ME_MAGIC_ENERGIE);
  4160.     }    
  4161.     }
  4162.         if (player)
  4163.         checkSpell(player, type, text);
  4164.         // It was no command, or it was just a player
  4165.         SpectatorVec list;
  4166.         SpectatorVec::iterator it;
  4167.         getSpectators(Range(creature->pos), list);
  4168.         //players
  4169.         for(it = list.begin(); it != list.end(); ++it) {
  4170.             if(dynamic_cast<Player*>(*it)) {
  4171.                 (*it)->onCreatureSay(creature, type, text);
  4172.             }
  4173.         }
  4174.  
  4175.         //none-players
  4176.         for(it = list.begin(); it != list.end(); ++it) {
  4177.             if(!dynamic_cast<Player*>(*it)) {
  4178.                 (*it)->onCreatureSay(creature, type, text);
  4179.             }
  4180.         }
  4181.     }
  4182. }
  4183.  
  4184. void Game::teleport(Thing *thing, const Position& newPos)
  4185. {
  4186.  
  4187.     if (newPos == thing->pos)
  4188.         return;
  4189.  
  4190.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::teleport()");
  4191.  
  4192.     //Tile *toTile = getTile( newPos.x, newPos.y, newPos.z );
  4193.     Tile *toTile = map->getTile(newPos);
  4194.     if (toTile)
  4195.     {
  4196.         Creature *creature = dynamic_cast<Creature*>(thing);
  4197.         if (creature)
  4198.         {
  4199.             //Tile *fromTile = getTile( thing->pos.x, thing->pos.y, thing->pos.z );
  4200.             Tile *fromTile = map->getTile(thing->pos);
  4201.             if (!fromTile)
  4202.                 return;
  4203.  
  4204.             int osp = fromTile->getThingStackPos(thing);
  4205.             if (!fromTile->removeThing(thing))
  4206.                 return;
  4207.  
  4208.             toTile->addThing(thing);
  4209.             Position oldPos = thing->pos;
  4210.  
  4211.             SpectatorVec list;
  4212.             SpectatorVec::iterator it;
  4213.  
  4214.             getSpectators(Range(thing->pos, true), list);
  4215.  
  4216.             //players
  4217.             for (it = list.begin(); it != list.end(); ++it)
  4218.             {
  4219.                 if (Player* p = dynamic_cast<Player*>(*it))
  4220.                 {
  4221.                     if (p->attackedCreature == creature->getID())
  4222.                     {
  4223.                         autoCloseAttack(p, creature);
  4224.                     }
  4225.  
  4226.                     (*it)->onCreatureDisappear(creature, osp, true);
  4227.                 }
  4228.             }
  4229.  
  4230.             //none-players
  4231.             for (it = list.begin(); it != list.end(); ++it)
  4232.             {
  4233.                 if (!dynamic_cast<Player*>(*it))
  4234.                 {
  4235.                     (*it)->onCreatureDisappear(creature, osp, true);
  4236.                 }
  4237.             }
  4238.  
  4239.             if (newPos.y < oldPos.y)
  4240.                 creature->direction = NORTH;
  4241.             if (newPos.y > oldPos.y)
  4242.                 creature->direction = SOUTH;
  4243.             if (newPos.x > oldPos.x && (std::abs(newPos.x - oldPos.x) >= std::abs(newPos.y - oldPos.y)))
  4244.                 creature->direction = EAST;
  4245.             if (newPos.x < oldPos.x && (std::abs(newPos.x - oldPos.x) >= std::abs(newPos.y - oldPos.y)))
  4246.                 creature->direction = WEST;
  4247.  
  4248.             thing->pos = newPos;
  4249.  
  4250.             Player *player = dynamic_cast<Player*>(creature);
  4251.             if (player && player->attackedCreature != 0)
  4252.             {
  4253.                 Creature* attackedCreature = getCreatureByID(player->attackedCreature);
  4254.                 if (attackedCreature)
  4255.                 {
  4256.                     autoCloseAttack(player, attackedCreature);
  4257.                 }
  4258.             }
  4259.  
  4260.             list.clear();
  4261.             getSpectators(Range(thing->pos, true), list);
  4262.  
  4263. #ifdef TRS_GM_INVISIBLE
  4264.             //players
  4265.             for (it = list.begin(); it != list.end(); ++it)
  4266.             {
  4267.                 if (player)
  4268.                 {
  4269.                     if (player->gmInvisible && player == (*it))
  4270.                     {
  4271.                         if (Player* p = dynamic_cast<Player*>(*it))
  4272.                         {
  4273.                             if (p->attackedCreature == creature->getID())
  4274.                             {
  4275.                                 autoCloseAttack(p, creature);
  4276.                             }
  4277.                             (*it)->onTeleport(creature, &oldPos, osp);
  4278.                         }
  4279.                     }
  4280.                     else if (player->gmInvisible && player != (*it) && (*it)->access < player->access)
  4281.                     {
  4282.                         // Nothing Because he is invisible...
  4283.                     }
  4284.                     else
  4285.                     {
  4286.                         if (Player* p = dynamic_cast<Player*>(*it))
  4287.                         {
  4288.                             if (p->attackedCreature == creature->getID())
  4289.                             {
  4290.                                 autoCloseAttack(p, creature);
  4291.                             }
  4292.                             (*it)->onTeleport(creature, &oldPos, osp);
  4293.                         }
  4294.                     }
  4295.                 }
  4296.                 else
  4297.                     creatureBroadcastTileUpdated(newPos);
  4298.             }
  4299. #else //TRS_GM_INVISIBLE
  4300.             //players
  4301.             for (it = list.begin(); it != list.end(); ++it)
  4302.             {
  4303.                 if (Player* p = dynamic_cast<Player*>(*it))
  4304.                 {
  4305.                     if (p->attackedCreature == creature->getID())
  4306.                     {
  4307.                         autoCloseAttack(p, creature);
  4308.                     }
  4309.                     (*it)->onTeleport(creature, &oldPos, osp);
  4310.                 }
  4311.             }
  4312. #endif //TRS_GM_INVISIBLE
  4313.  
  4314.             //none-players
  4315.             for (it = list.begin(); it != list.end(); ++it)
  4316.             {
  4317.                 if (!dynamic_cast<Player*>(*it))
  4318.                 {
  4319.                     (*it)->onTeleport(creature, &oldPos, osp);
  4320.                 }
  4321.             }
  4322.         }
  4323.         else
  4324.         {
  4325.             if (removeThing(NULL, thing->pos, thing, false))
  4326.             {
  4327.                 addThing(NULL, newPos, thing);
  4328.             }
  4329.         }
  4330.     }//if(toTile)
  4331.  
  4332. }
  4333.  
  4334.  
  4335. void Game::creatureChangeOutfit(Creature *creature)
  4336. {
  4337.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureChangeOutfit()");
  4338.  
  4339.     SpectatorVec list;
  4340.     SpectatorVec::iterator it;
  4341.  
  4342.     getSpectators(Range(creature->pos, true), list);
  4343.  
  4344.     //players
  4345.     for(it = list.begin(); it != list.end(); ++it) {
  4346.         if(dynamic_cast<Player*>(*it)) {
  4347.             (*it)->onCreatureChangeOutfit(creature);
  4348.         }
  4349.     }
  4350.  
  4351.     //none-players
  4352.     for(it = list.begin(); it != list.end(); ++it) {
  4353.         if(!dynamic_cast<Player*>(*it)) {
  4354.             (*it)->onCreatureChangeOutfit(creature);
  4355.         }
  4356.     }
  4357. }
  4358.  
  4359. void Game::creatureWhisper(Creature *creature, const std::string &text)
  4360. {
  4361.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureWhisper()");
  4362.  
  4363.     SpectatorVec list;
  4364.     SpectatorVec::iterator it;
  4365.  
  4366.     getSpectators(Range(creature->pos), list);
  4367.  
  4368.     //players
  4369.     for(it = list.begin(); it != list.end(); ++it) {
  4370.         if(dynamic_cast<Player*>(*it)) {
  4371.             if(abs(creature->pos.x - (*it)->pos.x) > 1 || abs(creature->pos.y - (*it)->pos.y) > 1)
  4372.                 (*it)->onCreatureSay(creature, SPEAK_WHISPER, std::string("pspsps"));
  4373.             else
  4374.                 (*it)->onCreatureSay(creature, SPEAK_WHISPER, text);
  4375.         }
  4376.     }
  4377.  
  4378.     //none-players
  4379.     for(it = list.begin(); it != list.end(); ++it) {
  4380.         if(!dynamic_cast<Player*>(*it)) {
  4381.             if(abs(creature->pos.x - (*it)->pos.x) > 1 || abs(creature->pos.y - (*it)->pos.y) > 1)
  4382.                 (*it)->onCreatureSay(creature, SPEAK_WHISPER, std::string("pspsps"));
  4383.             else
  4384.                 (*it)->onCreatureSay(creature, SPEAK_WHISPER, text);
  4385.         }
  4386.     }
  4387. }
  4388.  
  4389. void Game::creatureYell(Creature *creature, std::string &text)
  4390. {
  4391.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureYell()");
  4392.     if(!creature)
  4393.         return;
  4394. #ifdef HUCZU_FIX
  4395.     if(creature->level < 2 && creature->access < 2){
  4396.         return;
  4397.     }
  4398. #endif //HUCZU_FIX
  4399.     std::transform(text.begin(), text.end(), text.begin(), upchar);
  4400.  
  4401.     SpectatorVec list;
  4402.     SpectatorVec::iterator it;
  4403.     getSpectators(Range(creature->pos, 18, 18, 14, 14), list);
  4404.  
  4405.     for(it = list.begin(); it != list.end(); ++it){
  4406.         if(*it)
  4407.             (*it)->onCreatureSay(creature, SPEAK_YELL, text);
  4408.     }
  4409. }
  4410.  
  4411. //ZBĘ„NE
  4412. /*void Game::creatureYell(Creature *creature, std::string &text)
  4413. {
  4414.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureYell()");
  4415.     Player* player = dynamic_cast<Player*>(creature);
  4416. #ifdef HUCZU_FIX
  4417.     if(player && player->level < 2 && player->access < 2){
  4418.         player->sendTextMessage(MSG_SMALLINFO, "You cannot yell.");
  4419.         return;
  4420.               }
  4421. #endif //HUCZU_FIX
  4422.     if (player && player->access < g_config.ACCESS_PROTECT && player->exhaustedTicks >= 1000)
  4423.     {
  4424.         player->exhaustedTicks += g_config.EXHAUSTED_ADD;
  4425.         player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  4426.     }
  4427.     else {
  4428.         creature->exhaustedTicks = g_config.EXHAUSTED;
  4429.         std::transform(text.begin(), text.end(), text.begin(), upchar);
  4430.  
  4431.         SpectatorVec list;
  4432.         SpectatorVec::iterator it;
  4433.  
  4434.         getSpectators(Range(creature->pos, 18, 18, 14, 14), list);
  4435.  
  4436.         //players
  4437.         for(it = list.begin(); it != list.end(); ++it) {
  4438.             if(dynamic_cast<Player*>(*it)) {
  4439.                 (*it)->onCreatureSay(creature, SPEAK_YELL, text);
  4440.             }
  4441.         }
  4442.     }
  4443. }*/
  4444.  
  4445. void Game::creatureSpeakTo(Creature *creature, SpeakClasses type,const std::string &receiver, const std::string &text)
  4446. {
  4447.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureSpeakTo");
  4448.  
  4449.     Player* player = dynamic_cast<Player*>(creature);
  4450.     if(!player)
  4451.         return;
  4452.  
  4453.     Player* toPlayer = getPlayerByName(receiver);
  4454.     if(!toPlayer) {
  4455.         player->sendTextMessage(MSG_SMALLINFO, "A player with this name is not online.");
  4456.         return;
  4457.     }
  4458.     if(creature->access < g_config.ACCESS_TALK){
  4459.         type = SPEAK_PRIVATE;
  4460.     }
  4461.    
  4462.     if(!toPlayer){
  4463.         player->onCreatureSay(player, type, text);
  4464.     }
  4465.         time_t ticks = time(0);
  4466.         tm* now = localtime(&ticks);
  4467.         char buf[32];
  4468.         strftime(buf, sizeof(buf), "%d/%m/%Y %H:%M", now);
  4469.         std::ofstream out2("data/logs/private.log", std::ios::app);
  4470.         out2 << '[' << buf << "] " << toPlayer->getName() << " from " << player->getName() << ": " << text << std::endl;
  4471.         out2.close();      
  4472.        
  4473.     toPlayer->onCreatureSay(player, type, text);
  4474.     std::stringstream ss;
  4475.     ss << "Message sent to " << toPlayer->getName() << ".";
  4476.     player->sendTextMessage(MSG_SMALLINFO, ss.str().c_str());
  4477.     }
  4478.  
  4479. void Game::creatureTalkToChannel(Player *player, SpeakClasses type, std::string &text, uint16_t channelId)
  4480. {
  4481.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureTalkToChannel");
  4482.  
  4483.     if(player->access < g_config.ACCESS_TALK){
  4484.         type = SPEAK_CHANNEL_Y;
  4485.     }
  4486.  
  4487. if(player->guildStatus == GUILD_LEADER && channelId == 0x00)
  4488.         type = SPEAK_CHANNEL_R1;
  4489. if(player->guildStatus == GUILD_VICE && channelId == 0x00)
  4490.         type = SPEAK_CHANNEL_O;
  4491.  
  4492.     g_chat.talkToChannel(player, type, text, channelId);
  4493. }
  4494.  
  4495. void Game::creatureMonsterYell(Monster* monster, const std::string& text)
  4496. {
  4497.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureMonsterYell()");
  4498.  
  4499.     SpectatorVec list;
  4500.     SpectatorVec::iterator it;
  4501.  
  4502.     map->getSpectators(Range(monster->pos, 18, 18, 14, 14), list);
  4503.  
  4504.     //players
  4505.     for(it = list.begin(); it != list.end(); ++it) {
  4506.         if(dynamic_cast<Player*>(*it)) {
  4507.             (*it)->onCreatureSay(monster, SPEAK_MONSTER1, text);
  4508.         }
  4509.     }
  4510. }
  4511.  
  4512. void Game::creatureBroadcastMessage(Creature *creature, const std::string &text)
  4513. {
  4514.     if(creature->access < g_config.ACCESS_TALK)
  4515.         return;
  4516.  
  4517.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureBroadcastMessage()");
  4518.  
  4519.     for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  4520.     {
  4521.         (*it).second->onCreatureSay(creature, SPEAK_BROADCAST, text);
  4522.     }
  4523. }
  4524.  
  4525. /** \todo Someone _PLEASE_ clean up this mess */
  4526. bool Game::creatureMakeMagic(Creature *creature, const Position& centerpos, const MagicEffectClass* me)
  4527. {
  4528.  
  4529.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureMakeMagic()");
  4530.  
  4531. #ifdef __DEBUG__
  4532.     cout << "creatureMakeMagic: " << (creature ? creature->getName() : "No name") << ", x: " << centerpos.x << ", y: " << centerpos.y << ", z: " << centerpos.z << std::endl;
  4533. #endif
  4534.  
  4535.     Position frompos;
  4536.  
  4537.     if(creature) {
  4538.         frompos = creature->pos;
  4539.  
  4540.         if(!creatureOnPrepareMagicAttack(creature, centerpos, me))
  4541.         {
  4542.  
  4543.             return false;
  4544.         }
  4545.     }
  4546.     else {
  4547.         frompos = centerpos;
  4548.     }
  4549.  
  4550.     MagicAreaVec tmpMagicAreaVec;
  4551.     me->getArea(centerpos, tmpMagicAreaVec);
  4552.  
  4553.     std::vector<Position> poslist;
  4554.  
  4555.     Position topLeft(0xFFFF, 0xFFFF, frompos.z), bottomRight(0, 0, frompos.z);
  4556.  
  4557.     //Filter out the tiles we actually can work on
  4558.     for(MagicAreaVec::iterator maIt = tmpMagicAreaVec.begin(); maIt != tmpMagicAreaVec.end(); ++maIt) {
  4559.         Tile *t = map->getTile(maIt->x, maIt->y, maIt->z);
  4560.         if(t && (!creature || (creature->access >= g_config.ACCESS_PROTECT || !me->offensive || !t->isPz()) ) ) {
  4561.             if((t->isBlocking(BLOCK_PROJECTILE) == RET_NOERROR) && (me->isIndirect() ||
  4562.                 //(map->canThrowItemTo(frompos, (*maIt), false, true) && !t->floorChange()))) {
  4563.                 ((map->canThrowObjectTo(centerpos, (*maIt), BLOCK_PROJECTILE) == RET_NOERROR) && !t->floorChange()))) {
  4564.  
  4565.                 if(maIt->x < topLeft.x)
  4566.                     topLeft.x = maIt->x;
  4567.  
  4568.                 if(maIt->y < topLeft.y)
  4569.                     topLeft.y = maIt->y;
  4570.  
  4571.                 if(maIt->x > bottomRight.x)
  4572.                     bottomRight.x = maIt->x;
  4573.  
  4574.                 if(maIt->y > bottomRight.y)
  4575.                     bottomRight.y = maIt->y;
  4576.  
  4577.                 poslist.push_back(*maIt);
  4578.             }
  4579.         }
  4580.     }
  4581.  
  4582.     topLeft.z = frompos.z;
  4583.     bottomRight.z = frompos.z;
  4584.  
  4585.     if(topLeft.x == 0xFFFF || topLeft.y == 0xFFFF || bottomRight.x == 0 || bottomRight.y == 0){
  4586.  
  4587.     return false;
  4588.     }
  4589.  
  4590. #ifdef __DEBUG__
  4591.     printf("top left %d %d %d\n", topLeft.x, topLeft.y, topLeft.z);
  4592.     printf("bottom right %d %d %d\n", bottomRight.x, bottomRight.y, bottomRight.z);
  4593. #endif
  4594.  
  4595.     //We do all changes against a GameState to keep track of the changes,
  4596.     //need some more work to work for all situations...
  4597.     GameState gamestate(this, Range(topLeft, bottomRight));
  4598.  
  4599.     //Tile *targettile = getTile(centerpos.x, centerpos.y, centerpos.z);
  4600.     Tile *targettile = map->getTile(centerpos);
  4601.     bool bSuccess = false;
  4602.     bool hasTarget = false;
  4603.     bool isBlocking = true;
  4604.     if(targettile){
  4605.         hasTarget = !targettile->creatures.empty();
  4606.         isBlocking = (targettile->isBlocking(BLOCK_SOLID, true) != RET_NOERROR);
  4607.     }
  4608.  
  4609.     if(targettile && me->canCast(isBlocking, !targettile->creatures.empty())) {
  4610.         bSuccess = true;
  4611.  
  4612.         //Apply the permanent effect to the map
  4613.         std::vector<Position>::const_iterator tlIt;
  4614.         for(tlIt = poslist.begin(); tlIt != poslist.end(); ++tlIt) {
  4615.             gamestate.onAttack(creature, Position(*tlIt), me);
  4616.         }
  4617.     }
  4618.  
  4619.     SpectatorVec spectatorlist = gamestate.getSpectators();
  4620.     SpectatorVec::iterator it;
  4621.  
  4622.     for(it = spectatorlist.begin(); it != spectatorlist.end(); ++it) {
  4623.         Player* spectator = dynamic_cast<Player*>(*it);
  4624.  
  4625.         if(!spectator)
  4626.             continue;
  4627.  
  4628.         if(bSuccess) {
  4629.             me->getDistanceShoot(spectator, creature, centerpos, hasTarget);
  4630.  
  4631.             std::vector<Position>::const_iterator tlIt;
  4632.             for(tlIt = poslist.begin(); tlIt != poslist.end(); ++tlIt) {
  4633.                 Position pos = *tlIt;
  4634.                 //Tile *tile = getTile(pos.x, pos.y, pos.z);
  4635.                 Tile *tile = map->getTile(pos);
  4636.                 const CreatureStateVec& creatureStateVec = gamestate.getCreatureStateList(tile);
  4637.  
  4638.                 if(creatureStateVec.empty()) { //no targets
  4639.                     me->getMagicEffect(spectator, creature, NULL, pos, 0, targettile->isPz(), isBlocking);
  4640.                 }
  4641.                 else {
  4642.                     for(CreatureStateVec::const_iterator csIt = creatureStateVec.begin(); csIt != creatureStateVec.end(); ++csIt) {
  4643.                         Creature *target = csIt->first;
  4644.                         const CreatureState& creatureState = csIt->second;
  4645.  
  4646.                         me->getMagicEffect(spectator, creature, target, target->pos, creatureState.damage, tile->isPz(), false);
  4647.  
  4648.                         //could be death due to a magic damage with no owner (fire/poison/energy)
  4649.                         if(creature && target->isRemoved == true) {
  4650.  
  4651.                             for(std::vector<Creature*>::const_iterator cit = creatureState.attackerlist.begin(); cit != creatureState.attackerlist.end(); ++cit) {
  4652.                                 Creature* gainExpCreature = *cit;
  4653.                                 if(dynamic_cast<Player*>(gainExpCreature))
  4654.                                     dynamic_cast<Player*>(gainExpCreature)->sendStats();
  4655.  
  4656. if(spectator->CanSee(gainExpCreature->pos.x, gainExpCreature->pos.y, gainExpCreature->pos.z)){
  4657.             std::stringstream exp;
  4658.             exp << target->getGainedExperience(gainExpCreature);
  4659.             spectator->sendAnimatedText(gainExpCreature->pos, 0xD7, exp.str());
  4660. }
  4661.                             }
  4662.  
  4663.                         }
  4664.  
  4665.                         if(spectator->CanSee(target->pos.x, target->pos.y, target->pos.z))
  4666.                         {
  4667.                             if(creatureState.damage != 0) {
  4668.                                 std::stringstream dmg;
  4669.                                 dmg << std::abs(creatureState.damage);
  4670. #ifdef TJ_MONSTER_BLOOD
  4671.                                 if (me->attackType & ATTACK_PHYSICAL)
  4672.                                     spectator->sendAnimatedText(target->pos, target->bloodcolor, dmg.str());
  4673.                                 else
  4674. #endif //TJ_MONSTER_BLOOD
  4675.                             spectator->sendAnimatedText(target->pos, me->animationColor, dmg.str());
  4676.                             }
  4677.  
  4678.                             if(creatureState.manaDamage > 0){
  4679.                                 spectator->sendMagicEffect(target->pos, NM_ME_LOOSE_ENERGY);
  4680.                                 std::stringstream manaDmg;
  4681.                                 manaDmg << std::abs(creatureState.manaDamage);
  4682.                                 spectator->sendAnimatedText(target->pos, 2, manaDmg.str());
  4683.                             }
  4684.  
  4685.                             if (target->health > 0)
  4686.                                 spectator->sendCreatureHealth(target);
  4687.  
  4688.                             if (spectator == target){
  4689.                                 CreateManaDamageUpdate(target, creature, creatureState.manaDamage);
  4690.                                 CreateDamageUpdate(target, creature, creatureState.damage);
  4691.                             }
  4692.                         }
  4693.                     }
  4694.                 }
  4695.             }
  4696.         }
  4697.         else {
  4698.             me->FailedToCast(spectator, creature, isBlocking, hasTarget);
  4699.         }
  4700.  
  4701.     }
  4702.  
  4703.     return bSuccess;
  4704. }
  4705.  
  4706. void Game::creatureApplyDamage(Creature *creature, int32_t damage, int32_t &outDamage, int32_t &outManaDamage
  4707. #ifdef YUR_PVP_ARENA
  4708.                                , CreatureVector* arenaLosers
  4709. #endif //YUR_PVP_ARENA
  4710.                                )
  4711. {
  4712.     outDamage = damage;
  4713.     outManaDamage = 0;
  4714.  
  4715.     if (damage > 0)
  4716.     {
  4717.         if (creature->manaShieldTicks >= 1000 && (damage < creature->mana) ) {
  4718.             outManaDamage = damage;
  4719.             outDamage = 0;
  4720.         }
  4721.         else if (creature->manaShieldTicks >= 1000 && (damage > creature->mana) ) {
  4722.             outManaDamage = creature->mana;
  4723.             outDamage -= outManaDamage;
  4724.         }
  4725.         else if((creature->manaShieldTicks < 1000) && (damage > creature->health))
  4726.             outDamage = creature->health;
  4727.         else if (creature->manaShieldTicks >= 1000 && (damage > (creature->health + creature->mana))) {
  4728.             outDamage = creature->health;
  4729.             outManaDamage = creature->mana;
  4730.         }
  4731.  
  4732.         if(creature->manaShieldTicks < 1000 || (creature->mana == 0))
  4733. #ifdef YUR_PVP_ARENA
  4734.             creature->drainHealth(outDamage, arenaLosers);
  4735. #else
  4736.             creature->drainHealth(outDamage);
  4737. #endif //YUR_PVP_ARENA
  4738.         else if(outManaDamage > 0)
  4739.         {
  4740. #ifdef YUR_PVP_ARENA
  4741.             creature->drainHealth(outDamage, arenaLosers);
  4742. #else
  4743.             creature->drainHealth(outDamage);
  4744. #endif //YUR_PVP_ARENA
  4745.             creature->drainMana(outManaDamage);
  4746.         }
  4747.         else
  4748.             creature->drainMana(outDamage);
  4749.     }
  4750.     else {
  4751.         int32_t newhealth = creature->health - damage;
  4752.         if(newhealth > creature->healthmax)
  4753.             newhealth = creature->healthmax;
  4754.  
  4755.         creature->health = newhealth;
  4756.  
  4757.         outDamage = creature->health - newhealth;
  4758.         outManaDamage = 0;
  4759.     }
  4760. }
  4761.  
  4762. bool Game::creatureCastSpell(Creature *creature, const Position& centerpos, const MagicEffectClass& me)
  4763. {
  4764.  
  4765.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureCastSpell()");
  4766. std::cout << "Game::creatureCastSpell " << creature->getName() << std::endl;
  4767. //    if(me.offensive == false && me.damageEffect > 0 && creature->conditions.hasCondition(ATTACK_PARALYZE))
  4768.     if(me.damageEffect <= 0 && creature->conditions.hasCondition(ATTACK_PARALYZE))
  4769.     {
  4770.         creature->removeCondition(ATTACK_PARALYZE);
  4771.         changeSpeed(creature->getID(), creature->getNormalSpeed()+creature->hasteSpeed);
  4772.         Player *player = dynamic_cast<Player*>(creature);
  4773.         if(player)
  4774.             player->sendIcons();
  4775.     }
  4776.  
  4777.     return creatureMakeMagic(creature, centerpos, &me);
  4778. }
  4779.  
  4780.  
  4781. bool Game::creatureThrowRune(Creature *creature, const Position& centerpos, const MagicEffectClass& me) {
  4782.  
  4783.  
  4784.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureThrowRune()");
  4785.     bool ret = false;
  4786.     #ifdef HUCZU_FIX
  4787.     int32_t dist_x = std::abs(creature->pos.x - centerpos.x);
  4788.     int32_t dist_y = std::abs(creature->pos.y - centerpos.y);
  4789.     #endif //HUCZU_FIX
  4790.     if(creature->pos.z != centerpos.z) {
  4791.         creature->sendCancel("You need to be on the same floor.");
  4792.     }
  4793.     #ifdef HUCZU_FIX
  4794.     else if(dist_x > 7 || dist_y > 6)
  4795.        return TOO_FAR;
  4796.     #endif //HUCZU_FIX
  4797.     //else if(!map->canThrowItemTo(creature->pos, centerpos, false, true)) {
  4798.     else if(map->canThrowObjectTo(creature->pos, centerpos, BLOCK_PROJECTILE) != RET_NOERROR) {
  4799.         creature->sendCancel("You cannot throw there.");
  4800.     }
  4801.     else
  4802.         ret = creatureMakeMagic(creature, centerpos, &me);
  4803.  
  4804.  
  4805.  
  4806.     return ret;
  4807. }
  4808.  
  4809. bool Game::creatureOnPrepareAttack(Creature *creature, Position pos)
  4810. {
  4811.   if(creature){
  4812.         Player* player = dynamic_cast<Player*>(creature);
  4813.  
  4814.         //Tile* tile = (Tile*)getTile(creature->pos.x, creature->pos.y, creature->pos.z);
  4815.         Tile* tile = map->getTile(creature->pos);
  4816.         //Tile* targettile = getTile(pos.x, pos.y, pos.z);
  4817.         Tile* targettile = map->getTile(pos);
  4818.  
  4819.         if(creature->access < g_config.ACCESS_PROTECT) {
  4820.             if(tile && tile->isPz()) {
  4821.                 if(player) {
  4822.                     player->sendTextMessage(MSG_SMALLINFO, "You may not attack a person while you are in a protection zone.");
  4823.                     playerSetAttackedCreature(player, 0);
  4824.                 }
  4825.  
  4826.                 return false;
  4827.             }
  4828.             else if(targettile && targettile->isPz()) {
  4829.                 if(player) {
  4830.                     player->sendTextMessage(MSG_SMALLINFO, "You may not attack a person in a protection zone.");
  4831.                     playerSetAttackedCreature(player, 0);
  4832.                 }
  4833.  
  4834.                 return false;
  4835.             }
  4836.         }
  4837.  
  4838.         return true;
  4839.     }
  4840.  
  4841.     return false;
  4842. }
  4843.  
  4844. bool Game::creatureOnPrepareMagicAttack(Creature *creature, Position pos, const MagicEffectClass* me)
  4845. {
  4846.     if(!me->offensive || me->isIndirect() || creatureOnPrepareAttack(creature, pos)) {
  4847.         /*
  4848.             if(creature->access < ACCESS_PROTECT) {
  4849.                 if(!((std::abs(creature->pos.x-centerpos.x) <= 8) && (std::abs(creature->pos.y-centerpos.y) <= 6) &&
  4850.                     (creature->pos.z == centerpos.z)))
  4851.                     return false;
  4852.             }
  4853.         */
  4854.  
  4855.         Player* player = dynamic_cast<Player*>(creature);
  4856.         if(player) {
  4857.             if(player->access < g_config.ACCESS_PROTECT) {
  4858.                 if(player->exhaustedTicks >= 1000 && me->causeExhaustion(true)) {
  4859.                     if(me->offensive) {
  4860.                         player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.",player->pos, NM_ME_PUFF);
  4861.                         player->exhaustedTicks += g_config.EXHAUSTED_ADD;
  4862.                     }
  4863.  
  4864.                     return false;
  4865.                 }
  4866.                 else if(player->mana < me->manaCost) {
  4867.                     player->sendTextMessage(MSG_SMALLINFO, "You do not have enough mana.",player->pos, NM_ME_PUFF);
  4868.                     return false;
  4869.                 }
  4870.                 else
  4871.                     player->mana -= me->manaCost;
  4872.                     //player->manaspent += me->manaCost;
  4873.                     player->addManaSpent(me->manaCost);
  4874.             }
  4875.         }
  4876.  
  4877.         return true;
  4878.     }
  4879.  
  4880.     return false;
  4881. }
  4882.  
  4883. void Game::creatureMakeDamage(Creature *creature, Creature *attackedCreature, fight_t damagetype)
  4884. {
  4885.     if(!creatureOnPrepareAttack(creature, attackedCreature->pos))
  4886.         return;
  4887.  
  4888.  
  4889.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureMakeDamage()");
  4890.  
  4891.     Player* player = dynamic_cast<Player*>(creature);
  4892.     Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  4893.    
  4894.    #ifdef ANTI_MISS
  4895.     if(player && player->atkMode == 1 && player->access <= g_config.ACCESS_PROTECT && attackedPlayer && attackedPlayer->skullType == 0) {
  4896.     player->sendCancelAttacking();
  4897.         player->sendTextMessage(MSG_SMALLINFO, "Turn secure mode off if you really want to attack unmarked players.");
  4898.         return;
  4899.         }
  4900.     #endif //ANTI_MISS
  4901.    
  4902.     //Tile* targettile = getTile(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z);
  4903.     Tile* targettile = map->getTile(attackedCreature->pos);
  4904.    
  4905.     //can the attacker reach the attacked?
  4906.     bool inReach = false;
  4907.  
  4908.     switch(damagetype){
  4909.         case FIGHT_MELEE:
  4910.             if((std::abs(creature->pos.x-attackedCreature->pos.x) <= 1) &&
  4911.                 (std::abs(creature->pos.y-attackedCreature->pos.y) <= 1) &&
  4912.                 (creature->pos.z == attackedCreature->pos.z))
  4913.                     inReach = true;
  4914.         break;
  4915.         case FIGHT_DIST:
  4916.             if((std::abs(creature->pos.x-attackedCreature->pos.x) <= 8) &&
  4917.                 (std::abs(creature->pos.y-attackedCreature->pos.y) <= 5) &&
  4918.                 (creature->pos.z == attackedCreature->pos.z)) {
  4919.  
  4920.                     //if(map->canThrowItemTo(creature->pos, attackedCreature->pos, false, true))
  4921.                     if(map->canThrowObjectTo(creature->pos, attackedCreature->pos, BLOCK_PROJECTILE) == RET_NOERROR)
  4922.                         inReach = true;
  4923.                 }
  4924.         break;
  4925.         case FIGHT_MAGICDIST:
  4926.             if((std::abs(creature->pos.x-attackedCreature->pos.x) <= 8) &&
  4927.                 (std::abs(creature->pos.y-attackedCreature->pos.y) <= 5) &&
  4928.                 (creature->pos.z == attackedCreature->pos.z)) {
  4929.  
  4930.                     //if(map->canThrowItemTo(creature->pos, attackedCreature->pos, false, true))
  4931.                     if(map->canThrowObjectTo(creature->pos, attackedCreature->pos, BLOCK_PROJECTILE) == RET_NOERROR)
  4932.                         inReach = true;
  4933.                 }
  4934.         break;
  4935.  
  4936.     }
  4937.  
  4938.     if (player && player->access < g_config.ACCESS_PROTECT)
  4939.     {
  4940. #ifdef YUR_CVS_MODS
  4941.         player->inFightTicks = std::max(g_config.PZ_LOCKED, player->inFightTicks);
  4942. #else
  4943.         player->inFightTicks = g_config.PZ_LOCKED;
  4944. #endif //YUR_CVS_MODS
  4945.  
  4946.         player->sendIcons();
  4947.         if(attackedPlayer)
  4948.             player->pzLocked = true;
  4949.     }
  4950.  
  4951.     if(attackedPlayer && attackedPlayer->access < g_config.ACCESS_PROTECT)
  4952.     {
  4953. #ifdef YUR_CVS_MODS
  4954.         attackedPlayer->inFightTicks = std::max(g_config.PZ_LOCKED, attackedPlayer->inFightTicks);
  4955. #else
  4956.         attackedPlayer->inFightTicks = g_config.PZ_LOCKED;
  4957. #endif //YUR_CVS_MODS
  4958.      attackedPlayer->sendIcons();
  4959.   }
  4960.  
  4961.     if(!inReach){
  4962.         return;
  4963.     }
  4964.  
  4965.     //We do all changes against a GameState to keep track of the changes,
  4966.     //need some more work to work for all situations...
  4967.     GameState gamestate(this, Range(creature->pos, attackedCreature->pos));
  4968.  
  4969.     gamestate.onAttack(creature, attackedCreature->pos, attackedCreature);
  4970.  
  4971.     const CreatureStateVec& creatureStateVec = gamestate.getCreatureStateList(targettile);
  4972.     const CreatureState& creatureState = creatureStateVec[0].second;
  4973.  
  4974. if(player && (creatureState.damage > 0 || creatureState.manaDamage > 0)) {
  4975.         #ifdef WANDS_JIDDO
  4976.         if(player && ((player->items[SLOT_RIGHT] && (!player->items[SLOT_RIGHT]->getWand())) || (!player->items[SLOT_RIGHT] && !player->items[SLOT_LEFT]) || (player->items[SLOT_LEFT] && (!player->items[SLOT_LEFT]->getWand()))))
  4977.         player->addSkillTry(2);
  4978.         #else
  4979.         player->addSkillTry(2);
  4980.         #endif
  4981.     }
  4982.     else if(player){
  4983.         #ifdef WANDS_JIDDO
  4984.         if(player && ((player->items[SLOT_RIGHT] && (!player->items[SLOT_RIGHT]->getWand())) || (!player->items[SLOT_RIGHT] && !player->items[SLOT_LEFT]) || (player->items[SLOT_LEFT] && (!player->items[SLOT_LEFT]->getWand()))))
  4985.         player->addSkillTry(1);
  4986.         #else
  4987.         player->addSkillTry(1);
  4988.         #endif
  4989.     }
  4990. if(attackedPlayer){
  4991. NetworkMessage msg;
  4992. msg.AddByte(0x86);
  4993. msg.AddU32(creature->getID());
  4994. msg.AddByte(0x00);
  4995. attackedPlayer->sendNetworkMessage(&msg);
  4996. }
  4997.  
  4998.     SpectatorVec spectatorlist = gamestate.getSpectators();
  4999.     SpectatorVec::iterator it;
  5000.  
  5001.     for(it = spectatorlist.begin(); it != spectatorlist.end(); ++it) {
  5002.         Player* spectator = dynamic_cast<Player*>(*it);
  5003.         if(!spectator)
  5004.             continue;
  5005.  
  5006.         if(damagetype != FIGHT_MELEE){
  5007.             spectator->sendDistanceShoot(creature->pos, attackedCreature->pos, creature->getSubFightType());
  5008.         }
  5009.  
  5010.         if (attackedCreature->manaShieldTicks < 1000 && (creatureState.damage == 0) &&
  5011.             (spectator->CanSee(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z))) {
  5012.                 spectator->sendMagicEffect(attackedCreature->pos, NM_ME_PUFF);
  5013.         }
  5014.         else if (attackedCreature->manaShieldTicks < 1000 && (creatureState.damage < 0) &&
  5015.             (spectator->CanSee(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z))) {
  5016.                 spectator->sendMagicEffect(attackedCreature->pos, NM_ME_BLOCKHIT);
  5017.         }
  5018.         else {
  5019.             for(std::vector<Creature*>::const_iterator cit = creatureState.attackerlist.begin(); cit != creatureState.attackerlist.end(); ++cit) {
  5020.                 Creature* gainexpCreature = *cit;
  5021.                 if(dynamic_cast<Player*>(gainexpCreature))
  5022.                     dynamic_cast<Player*>(gainexpCreature)->sendStats();
  5023.  
  5024.                 if(spectator->CanSee(gainexpCreature->pos.x, gainexpCreature->pos.y, gainexpCreature->pos.z)) {
  5025.                     char exp[128];
  5026. #ifdef YUR_HIGH_LEVELS  // TODO: format like this: 1,000,000
  5027.                     sprintf(exp,"%lld",attackedCreature->getGainedExperience(gainexpCreature));
  5028.                     spectator->sendAnimatedText(gainexpCreature->pos, 0xD7, exp);
  5029. #else
  5030.                     itoa(attackedCreature->getGainedExperience(gainexpCreature), exp, 10);
  5031. #endif //YUR_HIGH_LEVLES
  5032.                     spectator->sendAnimatedText(gainexpCreature->pos, 0xD7, exp);
  5033.                 }
  5034.             }
  5035.  
  5036.             if (spectator->CanSee(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z))
  5037.             {
  5038.                 if(creatureState.damage > 0) {
  5039.                     std::stringstream dmg;
  5040.                     dmg << std::abs(creatureState.damage);
  5041. #ifdef TJ_MONSTER_BLOOD
  5042.                     spectator->sendAnimatedText(attackedCreature->pos, attackedCreature->bloodcolor, dmg.str());
  5043.                     spectator->sendMagicEffect(attackedCreature->pos, attackedCreature->bloodeffect);
  5044. #else
  5045.                     spectator->sendAnimatedText(attackedCreature->pos, 0xB4, dmg.str());
  5046.                     spectator->sendMagicEffect(attackedCreature->pos, NM_ME_DRAW_BLOOD);
  5047. #endif //TJ_MONSTER_BLOOD
  5048.                 }
  5049.  
  5050.                 if(creatureState.manaDamage >0) {
  5051.                     std::stringstream manaDmg;
  5052.                     manaDmg << std::abs(creatureState.manaDamage);
  5053.                     spectator->sendMagicEffect(attackedCreature->pos, NM_ME_LOOSE_ENERGY);
  5054.                     spectator->sendAnimatedText(attackedCreature->pos, 2, manaDmg.str());
  5055.                 }
  5056.  
  5057.                 if (attackedCreature->health > 0)
  5058.                     spectator->sendCreatureHealth(attackedCreature);
  5059.  
  5060.                 if (spectator == attackedCreature) {
  5061.                     CreateManaDamageUpdate(attackedCreature, creature, creatureState.manaDamage);
  5062.                     CreateDamageUpdate(attackedCreature, creature, creatureState.damage);
  5063.                 }
  5064.             }
  5065.         }
  5066.     }
  5067.  
  5068.     if(damagetype != FIGHT_MELEE && player) {
  5069.         player->removeDistItem();
  5070.     }
  5071.  
  5072.  
  5073. }
  5074.  
  5075. std::list<Position> Game::getPathTo(Creature *creature, Position start, Position to, bool creaturesBlock){
  5076.     return map->getPathTo(creature, start, to, creaturesBlock);
  5077. }
  5078.  
  5079. std::list<Position> Game::getPathToEx(Creature *creature, Position start, Position to, bool creaturesBlock){
  5080.     return map->getPathToEx(creature, start, to, creaturesBlock);
  5081. }
  5082.  
  5083.  
  5084. void Game::checkPlayerWalk(uint32_t id)
  5085. {
  5086.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkPlayerWalk");
  5087.  
  5088.     Player *player = getPlayerByID(id);
  5089.  
  5090.     if(!player)
  5091.         return;
  5092. if(player->pathlist.empty()){
  5093.         stopEvent(player->eventAutoWalk);
  5094.         player->eventAutoWalk = 0;
  5095.         return;
  5096.     }
  5097.  
  5098.     Position pos = player->pos;
  5099.     Direction dir = player->pathlist.front();
  5100.     player->pathlist.pop_front();
  5101.  
  5102.     switch (dir) {
  5103.         case NORTH:
  5104.             pos.y--;
  5105.             break;
  5106.         case EAST:
  5107.             pos.x++;
  5108.             break;
  5109.         case SOUTH:
  5110.             pos.y++;
  5111.             break;
  5112.         case WEST:
  5113.             pos.x--;
  5114.             break;
  5115.         case NORTHEAST:
  5116.             pos.x++;
  5117.             pos.y--;
  5118.             break;
  5119.         case NORTHWEST:
  5120.             pos.x--;
  5121.             pos.y--;
  5122.             break;
  5123.         case SOUTHWEST:
  5124.             pos.x--;
  5125.             pos.y++;
  5126.             break;
  5127.         case SOUTHEAST:
  5128.             pos.x++;
  5129.             pos.y++;
  5130.             break;
  5131.     }
  5132.  
  5133. /*
  5134. #ifdef __DEBUG__
  5135.     std::cout << "move to: " << dir << std::endl;
  5136. #endif
  5137. */
  5138.  
  5139.     player->lastmove = OTSYS_TIME();
  5140.     thingMove(player, player, pos.x, pos.y, pos.z, 1);
  5141.     flushSendBuffers();
  5142.     if(!player->pathlist.empty()){
  5143.         int ticks = (int)player->getSleepTicks();
  5144.         player->eventAutoWalk = addEvent(makeTask(ticks, std::bind2nd(std::mem_fun(&Game::checkPlayerWalk), id)));
  5145.     }
  5146.     else
  5147.     {
  5148.         stopEvent(player->eventAutoWalk);//?
  5149.         player->eventAutoWalk = 0;
  5150.     }
  5151. }
  5152. void Game::checkCreature(uint32_t id)
  5153. {
  5154.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreature()");
  5155.  
  5156.     Creature *creature = getCreatureByID(id);
  5157.  
  5158.     if (creature && creature->isRemoved == false)
  5159.     {
  5160.         int32_t thinkTicks = 0;
  5161.         int32_t oldThinkTicks = creature->onThink(thinkTicks);
  5162.  
  5163.         if(thinkTicks > 0) {
  5164.             creature->eventCheck = addEvent(makeTask(thinkTicks, std::bind2nd(std::mem_fun(&Game::checkCreature), id)));
  5165.         }
  5166.         else
  5167.             creature->eventCheck = 0;
  5168.  
  5169.         Player* player = dynamic_cast<Player*>(creature);
  5170.         if(player)
  5171.         {
  5172.             //Tile *tile = getTile(player->pos.x, player->pos.y, player->pos.z);
  5173.             Tile *tile = map->getTile(player->pos);
  5174.             if(tile == NULL){
  5175.                 std::cout << "CheckPlayer NULL tile: " << player->getName() << std::endl;
  5176.                 return;
  5177.             }
  5178.            
  5179.            
  5180.            
  5181.             #ifdef _REX_CVS_MOD_
  5182.             if(player->tradeTicks >= 1000)
  5183.             player->tradeTicks -= thinkTicks;
  5184.             #endif
  5185.  
  5186.  
  5187. #ifdef CVS_DAY_CYCLE
  5188.             player->sendWorldLightLevel(lightlevel, 0xD7);
  5189. #endif //CVS_DAY_CYCLE
  5190. #ifdef REX_MUTED
  5191.  
  5192. #endif //REX_MUTED
  5193. #ifdef TR_ANTI_AFK
  5194.             player->checkAfk(thinkTicks);
  5195. #endif //TR_ANTI_AF
  5196. #ifdef YUR_BOH
  5197.             player->checkBoh();
  5198. #endif //YUR_BOH
  5199. #ifdef YUR_WH
  5200.             player->checkWh();
  5201. #endif //YUR_WH
  5202.  
  5203. #ifdef YUR_RINGS_AMULETS
  5204.             player->checkRing(thinkTicks);
  5205. #endif //YUR_RINGS_AMULETS
  5206.  
  5207. //SOFT BOOTS
  5208.        if(player->softTicks >= 2) {
  5209.        if(player->items[SLOT_FEET] && player->items[SLOT_FEET]->getID() == ITEM_SOFT_BOOTS && !tile->isPz()){
  5210.          player->mana += min(g_config.SOFT_MANA, player->manamax - player->mana);
  5211.          player->health += min(g_config.SOFT_HEALTH, player->healthmax - player->health);
  5212.        }
  5213. player->softTicks = 0;
  5214. } else {
  5215. player->softTicks++;
  5216. }
  5217. // LIFE RING
  5218.        if(player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_LIFE_RING_IN_USE && !tile->isPz()){
  5219.          player->mana += min(g_config.LR_MANA, player->manamax - player->mana);
  5220.          player->health += min(g_config.LR_HEALTH, player->healthmax - player->health);
  5221.        }
  5222. // ROH      
  5223.        if(player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_RING_OF_HEALING_IN_USE && !tile->isPz()){
  5224.          player->mana += min(g_config.ROH_MANA, player->manamax - player->mana);
  5225.          player->health += min(g_config.ROH_HEALTH, player->healthmax - player->health);
  5226.        }
  5227. // ROAH
  5228. // ROH 240      
  5229.        if(player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_STEALTH_RING_IN_USE && !tile->isPz()){
  5230.          player->mana += min(g_config.ROAH_MANA, player->manamax - player->mana);
  5231.          player->health += min(g_config.ROAH_HEALTH, player->healthmax - player->health);
  5232.        }
  5233. // RAINBOW SHIELD
  5234.        if(player->level >= 150){
  5235.         if(player->items[SLOT_RIGHT] && player->items[SLOT_RIGHT]->getID() == ITEM_RAINBOW && !tile->isPz()){
  5236.          if(player->items[SLOT_LEFT]){
  5237.           if(player->items[SLOT_LEFT]->getID() != ITEM_RAINBOW)
  5238.            if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5239.              player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5240.              player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5241.              player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5242.            }
  5243.          }else{
  5244.           if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5245.             player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5246.             player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5247.             player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5248.           }
  5249.          }
  5250.         }
  5251.         if(player->items[SLOT_LEFT] && player->items[SLOT_LEFT]->getID() == ITEM_RAINBOW && !tile->isPz()){
  5252.          if(player->items[SLOT_RIGHT]){
  5253.           if(player->items[SLOT_RIGHT]->getID() != ITEM_RAINBOW)
  5254.            if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5255.              player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5256.              player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5257.              player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5258.            }
  5259.          }else{
  5260.           if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5261.             player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5262.             player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5263.             player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5264.           }
  5265.          }
  5266.         }
  5267.        }
  5268.        
  5269. // RING OF THE SKY
  5270.        if(player->level >= 30 && player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_ROTS && !tile->isPz())
  5271.          player->mana += min(1, player->manamax - player->mana);
  5272.          
  5273. // ORSHABAAL HEART
  5274.        if(player->name == "Ekudron" || player->name == "Agecik" && player->items[SLOT_AMMO] && player->items[SLOT_AMMO]->getID() == ITEM_ORSHABAAL_HEARTH && !tile->isPz())
  5275.          player->mana += min(4, player->manamax - player->mana);
  5276.          
  5277.          #ifdef HUCZU_FIX
  5278.        if(player->items[SLOT_FEET] && player->items[SLOT_FEET]->getID() == ITEM_SPECTRE_BOOTS)
  5279.          player->immunities = ATTACK_PARALYZE;
  5280.          else
  5281.          player->immunities -= ATTACK_PARALYZE;
  5282.          #endif //HUCZU_FIX
  5283.  
  5284. #ifdef YUR_LIGHT_ITEM
  5285.             player->checkLightItem(thinkTicks);
  5286. #endif //YUR_LIGHT_ITEM
  5287. #ifdef HUCZU_EXHAUSTED
  5288.             if(player->mmo > 0)
  5289.                 player->mmo -= 1;
  5290.             else
  5291.                 player->mmo = 0;
  5292.    
  5293.             if(player->lookex > 0)
  5294.                 player->lookex -= 1;
  5295.             else
  5296.                 player->lookex = 0;
  5297.            
  5298.             if(player->antyrainbow > 0)
  5299.                 player->antyrainbow -= 1;
  5300.             else
  5301.                 player->antyrainbow = 0;
  5302.                
  5303.             if(player->antyrainbow2 > 0)
  5304.                 player->antyrainbow2 -= 1;
  5305.             else
  5306.                 player->antyrainbow2 = 0;
  5307.                
  5308.                             if(player->clin > 0)
  5309.                             player->clin -= 1;
  5310.                             else
  5311.                             player->clin = 0;
  5312.                            
  5313.                             if(player->shut_d > 0)
  5314.                             player->shut_d -= 1;
  5315.                             else
  5316.                             player->shut_d = 0;
  5317.                
  5318.             if(player->houseTicks > 0)
  5319.                 player->houseTicks -= 1;
  5320.             else
  5321.                 player->houseTicks = 0;  
  5322. #endif //HUCZU_EXHAUSTED
  5323.  
  5324.              if(player->flamTicks >= 1000){
  5325.                 player->flamTicks -= thinkTicks;
  5326.              if(player->flamTicks == 0){
  5327.                 player->flamBool = false;
  5328.               }
  5329.             }
  5330.                  
  5331.                  
  5332.             if(player->items[SLOT_RIGHT] &&  player->items[SLOT_LEFT]){
  5333.              if((player->items[SLOT_RIGHT]->getID() == ITEM_BOW || player->items[SLOT_RIGHT]->getID() == ITEM_XBOW) && (player->items[SLOT_LEFT]->getWeaponType() == SHIELD || player->items[SLOT_LEFT]->getWeaponType() == SWORD || player->items[SLOT_LEFT]->getWeaponType() == AXE || player->items[SLOT_LEFT]->getWeaponType() == CLUB)){
  5334.                player->removeItemInventory(SLOT_RIGHT);
  5335.              }
  5336.              if((player->items[SLOT_LEFT]->getID() == ITEM_BOW || player->items[SLOT_LEFT]->getID() == ITEM_XBOW) && (player->items[SLOT_RIGHT]->getWeaponType() == SHIELD || player->items[SLOT_RIGHT]->getWeaponType() == SWORD || player->items[SLOT_RIGHT]->getWeaponType() == AXE || player->items[SLOT_RIGHT]->getWeaponType() == CLUB)){
  5337.                player->removeItemInventory(SLOT_LEFT);
  5338.              }
  5339.             }
  5340.  
  5341.             if(player->items[SLOT_RIGHT] &&  player->items[SLOT_LEFT]){
  5342.              if((player->items[SLOT_RIGHT]->getID() == ITEM_SPEAR || player->items[SLOT_RIGHT]->getID() == ITEM_KNIFE || player->items[SLOT_RIGHT]->getID() == ITEM_STONE || player->items[SLOT_RIGHT]->getID() == ITEM_SNOWBALL || player->items[SLOT_RIGHT]->getID() == ITEM_STAR) && (player->items[SLOT_LEFT]->getWeaponType() == SWORD || player->items[SLOT_LEFT]->getWeaponType() == AXE || player->items[SLOT_LEFT]->getWeaponType() == CLUB)){
  5343.                player->removeItemInventory(SLOT_RIGHT);
  5344.              }
  5345.              if((player->items[SLOT_LEFT]->getID() == ITEM_SPEAR || player->items[SLOT_LEFT]->getID() == ITEM_KNIFE || player->items[SLOT_LEFT]->getID() == ITEM_STONE || player->items[SLOT_LEFT]->getID() == ITEM_SNOWBALL || player->items[SLOT_LEFT]->getID() == ITEM_STAR) && (player->items[SLOT_RIGHT]->getWeaponType() == SWORD || player->items[SLOT_RIGHT]->getWeaponType() == AXE || player->items[SLOT_RIGHT]->getWeaponType() == CLUB)){
  5346.                player->removeItemInventory(SLOT_LEFT);
  5347.              }
  5348.             }
  5349.  
  5350. #ifdef HUCZU_SKULLS
  5351.             if (player->checkSkull(thinkTicks))
  5352.                 Skull(player);
  5353. #endif //HUCZU_SKULLS
  5354.  
  5355. #ifdef YUR_INVISIBLE
  5356.             if (player->checkInvisible(thinkTicks))
  5357.                 creatureChangeOutfit(player);
  5358. #endif //YUR_INVISIBLE
  5359.  
  5360. #ifdef _BBK_PUSH_DELAY
  5361.             if(player->pushDelay >= 1000)
  5362.             {
  5363.                 player->pushDelay -= thinkTicks;
  5364.                 if(player->pushDelay < 0)
  5365.                     player->pushDelay = 0;
  5366.             }
  5367. #endif //_BBK_PUSH_DELAY
  5368.  
  5369. if(player->training == true){
  5370.               if(player->trainingTicks >= 1000){
  5371.                 player->trainingTicks -= thinkTicks;
  5372.  
  5373.                 if(player->trainingTicks < 0)
  5374.                     player->trainingTicks = 0;
  5375.             }                    
  5376.         if(player->trainingTicks == 0 && player->rewriteTicks == 0){
  5377.            int code = random_range(47,99) * random_range(47,99);
  5378.            player->rewriteCode = code;
  5379.            player->needrewrite = true;
  5380.            player->rewriteTicks = g_config.REWRITE_TICKS;
  5381.            std::ostringstream info;    
  5382.            player->sendTextMessage(MSG_BLUE_TEXT,"You are training here pretty long.Are you using bot?");        
  5383.            info << "Please rewrite code: " << player->rewriteCode << std::ends;
  5384.            player->sendTextMessage(MSG_BLUE_TEXT, info.str().c_str());
  5385.            std::ostringstream info2;
  5386.            info2 << "Use this command !train 1234. You have " << player->rewriteTicks/1000 << " seconds!" << std::ends;
  5387.            player->sendTextMessage(MSG_BLUE_TEXT, info2.str().c_str());    
  5388.         }
  5389.  
  5390.         if(player->needrewrite != false){
  5391.               if(player->rewriteTicks >= 1000){
  5392.                 player->rewriteTicks -= thinkTicks;
  5393.             }
  5394.  
  5395.            if(player->rewriteTicks == 0){
  5396.               this->teleport(player, player->masterPos);
  5397.               player->training = false;
  5398.               player->trainingTicks = 0;
  5399.               player->needrewrite  = false;
  5400.               player->rewriteCode = 0;
  5401.               player->rewriteTicks = 0;
  5402.               player->kickPlayer();
  5403.               //player->sendLogout();
  5404.            }    
  5405.         }
  5406.     }
  5407.  
  5408.  
  5409.  
  5410. #ifdef HUCZU_FIX
  5411. if(player->gainHealthTick()){
  5412.                             SpectatorVec list;
  5413.                             SpectatorVec::iterator it;
  5414.                             getSpectators(Range(creature->pos), list);
  5415.                             for(it = list.begin(); it != list.end(); ++it) {      
  5416.                                 Player* p = dynamic_cast<Player*>(*it);
  5417.                                 if(p)
  5418.                                     p->sendCreatureHealth(player);
  5419.                             }
  5420.                         }
  5421. #endif //HUCZU_FIX
  5422.  
  5423. if(player->lightTicks >= 1000){
  5424.              player->lightTicks -= thinkTicks;
  5425.               if(player->lightTicks <= 1000){
  5426.                 player->lightTicks = 1;
  5427.               }
  5428.             }
  5429.             else if(player->lightTicks == 1){
  5430.               if(player->lightlevel > 0){
  5431.                 creatureChangeLight(player, 0, player->lightlevel-1, 0xD7);
  5432.               }
  5433.               else{
  5434.                 creatureChangeLight(player, 0, 0, 0xD7);
  5435.                 player->lightTicks = 0;
  5436.                 player->lightItem = 0;
  5437.               }
  5438.               if(player->lightTries > 0){
  5439.                 player->lightTicks = 3*60*1000;
  5440.                 player->lightTries -= 1;
  5441.               }
  5442.             }
  5443.            
  5444. #ifdef HUCZU_SKULLS
  5445.             checkSkullTime(player);
  5446. #endif //HUCZU_SKULLS
  5447.  
  5448.  
  5449.             if(!tile->isPz()){
  5450.                 if(player->food > 1000){
  5451.                     player->gainManaTick();
  5452.                     player->food -= thinkTicks;
  5453.                     if(player->healthmax - player->health > 0){
  5454.                         if(player->gainHealthTick()){
  5455.                             SpectatorVec list;
  5456.                             SpectatorVec::iterator it;
  5457.                             getSpectators(Range(creature->pos), list);
  5458.                             for(it = list.begin(); it != list.end(); ++it) {
  5459.                                 Player* p = dynamic_cast<Player*>(*it);
  5460.                                 if(p)
  5461.                                     p->sendCreatureHealth(player);
  5462.                             }
  5463.                         }
  5464.                     }
  5465.                 }
  5466.             }
  5467.  
  5468.             //send stast only if have changed
  5469.             if(player->NeedUpdateStats()){
  5470.                 player->sendStats();
  5471.             }
  5472.  
  5473.             player->sendPing(thinkTicks);
  5474.  
  5475.             if(player->inFightTicks >= 1000) {
  5476.                 player->inFightTicks -= thinkTicks;
  5477.  
  5478.                 if(player->inFightTicks < 1000)
  5479.                     player->pzLocked = false;
  5480.                     player->sendIcons();
  5481.             }
  5482.            
  5483.             if(player->drunkTicks >= 1000) {
  5484.               int32_t random = random_range(1,100);
  5485.                if(random <= 25){
  5486.                  creatureSay(creature, SPEAK_SAY, "Hicks!");
  5487.                  Position pos;
  5488.                  int32_t randomwalk = random_range(1,4);
  5489.                  switch(randomwalk){
  5490.                   case 1:pos.x++;break;
  5491.                   case 2:pos.x--;break;
  5492.                   case 3:pos.y++;break;
  5493.                   case 4:pos.y--;break;
  5494.                  }
  5495.                  Tile* toTile = getTile(pos.x, pos.y, pos.z);
  5496. //make sure they don't get teleported into a place they shouldn't
  5497.                  if(toTile &&
  5498.                  !toTile->isBlocking(1, false, false) &&
  5499.                  !toTile->isBlocking(2, false, false) &&
  5500.                  !toTile->isBlocking(4, false, false) &&
  5501.                  !toTile->isBlocking(8, false, false) &&
  5502.                  !toTile->isBlocking(16, false, false))
  5503.                    teleport(player,pos);
  5504.                }
  5505.                player->drunkTicks -= thinkTicks;
  5506.                player->sendIcons();
  5507.             }
  5508.  
  5509.             if(player->exhaustedTicks >= 1000){
  5510.                 player->exhaustedTicks -= thinkTicks;
  5511.  
  5512.                 if(player->exhaustedTicks < 0)
  5513.                     player->exhaustedTicks = 0;
  5514.             }
  5515.  
  5516.             if(player->manaShieldTicks >=1000){
  5517.                 player->manaShieldTicks -= thinkTicks;
  5518.  
  5519.                 if(player->manaShieldTicks  < 1000)
  5520.                     player->sendIcons();
  5521.             }
  5522.             if(player->dwarvenTicks > 0){
  5523.               player->drunkTicks = 0;
  5524.               player->sendIcons();
  5525.             }
  5526.             if(player->dwarvenTicks = 0){
  5527.               player->drunkTicks = 4000;
  5528.               player->sendIcons();
  5529.             }
  5530.  
  5531.             if(player->hasteTicks >=1000)
  5532.                 player->hasteTicks -= thinkTicks;
  5533.         }else{
  5534.            
  5535.             if(creature->manaShieldTicks >=1000){
  5536.                 creature->manaShieldTicks -= thinkTicks;
  5537.             }
  5538.  
  5539.             if(creature->hasteTicks >=1000){
  5540.                 creature->hasteTicks -= thinkTicks;
  5541.             }
  5542.  
  5543. #ifdef YUR_INVISIBLE
  5544.             if (creature->checkInvisible(thinkTicks))
  5545.                 creatureChangeOutfit(creature);
  5546. #endif //YUR_INVISIBLE
  5547.         }
  5548.  
  5549.         Conditions& conditions = creature->getConditions();
  5550.         for(Conditions::iterator condIt = conditions.begin(); condIt != conditions.end(); ++condIt) {
  5551.             if(condIt->first == ATTACK_FIRE || condIt->first == ATTACK_ENERGY || condIt->first == ATTACK_POISON) {
  5552.                 ConditionVec &condVec = condIt->second;
  5553.  
  5554.                 if(condVec.empty())
  5555.                     continue;
  5556.  
  5557.                 CreatureCondition& condition = condVec[0];
  5558.  
  5559.                 if(condition.onTick(oldThinkTicks)) {
  5560.                     const MagicEffectTargetCreatureCondition* magicTargetCondition =  condition.getCondition();
  5561.                     Creature* c = getCreatureByID(magicTargetCondition->getOwnerID());
  5562.                     creatureMakeMagic(c, creature->pos, magicTargetCondition);
  5563.  
  5564.                     if(condition.getCount() <= 0) {
  5565.                         condVec.erase(condVec.begin());
  5566.                               if(dynamic_cast<Player*>(creature))
  5567.                                 player->sendIcons();
  5568.                     }
  5569.                 }
  5570.             }
  5571.          if(condIt->first == ATTACK_PARALYZE)
  5572.             {
  5573.                 ConditionVec &condVec = condIt->second;
  5574.                 if(condVec.empty())
  5575.                     continue;
  5576.  
  5577.                 CreatureCondition& condition = condVec[0];
  5578.                 if(condition.onTick(oldThinkTicks))
  5579.                 {
  5580.                     //Player* player = dynamic_cast<Player*>(creature);
  5581.                     if(creature->getImmunities() != ATTACK_PARALYZE)
  5582.                     {
  5583.                         changeSpeed(creature->getID(), 100);
  5584.                         if(player)
  5585.                         {
  5586.                             player->sendTextMessage(MSG_SMALLINFO, "You are paralyzed.");
  5587.                             player->sendIcons();
  5588.                         }
  5589.                     }
  5590.  
  5591.                     if(condition.getCount() <= 0)
  5592.                     {
  5593.                         condVec.erase(condVec.begin());
  5594.                         changeSpeed(creature->getID(), creature->getNormalSpeed()+creature->hasteSpeed);
  5595.                         if(player)
  5596.                         {
  5597.                             player->sendIcons();
  5598.                         }
  5599.                     }
  5600.                 }
  5601.             }
  5602.         }
  5603.         flushSendBuffers();
  5604.     }
  5605. }
  5606.  
  5607. void Game::changeOutfit(uint32_t id, int32_t looktype){
  5608.      
  5609.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::changeOutfit()");
  5610.  
  5611.     Creature *creature = getCreatureByID(id);
  5612.     if(creature){
  5613.         creature->looktype = looktype;
  5614.         if(creature->lookfeet_master != 0 || creature->lookhead_master != 0 || 
  5615.            creature->looklegs_master != 0 || creature->lookbody_master != 0 ){
  5616.            creature->lookhead = creature->lookhead_master;
  5617.            creature->lookbody = creature->lookbody_master;
  5618.            creature->looklegs = creature->looklegs_master;
  5619.            creature->lookfeet = creature->lookfeet_master;
  5620.            
  5621.            creature->lookhead_master = 0;
  5622.            creature->lookbody_master = 0;
  5623.            creature->looklegs_master = 0;
  5624.            creature->lookfeet_master = 0;
  5625.         }  
  5626.         creatureChangeOutfit(creature);
  5627.     }
  5628. }
  5629.  
  5630. void Game::changeOutfitAfter(uint32_t id, int32_t looktype, long time)
  5631. {
  5632.     addEvent(makeTask(time, boost::bind(&Game::changeOutfit, this,id, looktype)));
  5633. }
  5634.  
  5635. void Game::changeSpeed(uint32_t id, unsigned short speed)
  5636. {
  5637.  OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::changeSpeed()");
  5638.  Creature *creature = getCreatureByID(id);
  5639.  if(creature && /*creature->hasteTicks < 1000 && */creature->speed != speed)
  5640.  {
  5641.   creature->speed = speed;
  5642.   Player* player = dynamic_cast<Player*>(creature);
  5643.   if(player){
  5644.    player->sendChangeSpeed(creature);
  5645.    player->sendIcons();
  5646.   }
  5647.   SpectatorVec list;
  5648.   SpectatorVec::iterator it;
  5649.   getSpectators(Range(creature->pos), list);
  5650.   //for(uint32_t i = 0; i < list.size(); i++)
  5651.   for(it = list.begin(); it != list.end(); ++it) {
  5652.    Player* p = dynamic_cast<Player*>(*it);
  5653.    if(p)
  5654.     p->sendChangeSpeed(creature);
  5655.   }
  5656.  }
  5657. }
  5658.  
  5659. void Game::checkCreatureAttacking(uint32_t id)
  5660. {
  5661.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreatureAttacking()");
  5662.  
  5663.     Creature *creature = getCreatureByID(id);
  5664.     if (creature != NULL && creature->isRemoved == false)
  5665.     {
  5666.            
  5667.         creature->eventCheckAttacking = 0;
  5668.         Player *player = dynamic_cast<Player*>(creature);
  5669.         Monster *monster = dynamic_cast<Monster*>(creature);
  5670.         if (monster) {
  5671.             monster->onAttack();
  5672.         }
  5673.         else {
  5674.             if (creature->attackedCreature != 0)
  5675.             {
  5676.                 Creature *attackedCreature = getCreatureByID(creature->attackedCreature);
  5677.                 if (attackedCreature)
  5678.                 {
  5679.                                      // canAttack system BRY
  5680.  
  5681. Player *attacker = dynamic_cast<Player*>(creature);
  5682. Player *attacked = dynamic_cast<Player*>(attackedCreature);
  5683. bool canAttack = false;
  5684. if(attacker && attacked)
  5685.  {
  5686.    Tile* tile = getTile(attacker->pos.x,attacker->pos.y, attacker->pos.z);
  5687.    if(attacked->level >= 1 && attacked->level < 30 && attacker->level >= 1 && attacker->level < 30)
  5688.    canAttack = false;
  5689.    
  5690.    else if(attacked->level >= 30 && attacked->level < 80 && attacker->level >= 30 && attacker->level < 80)
  5691.    canAttack = true;
  5692.    
  5693.    else if(attacked->level >= 81 && attacked->level < 999 && attacker->level >= 81 && attacker->level < 999)
  5694.    canAttack = true;
  5695.    
  5696.    
  5697.    else if(tile && tile->isPvpArena())
  5698.    canAttack = true;
  5699.    }
  5700.    
  5701.  
  5702.  
  5703. if(attacker && attacked && !canAttack)
  5704. {
  5705. attacker->sendCancelAttacking();
  5706. attacker->sendCancel("You may not attack this player yet.");
  5707. playerSetAttackedCreature(attacker, 0);
  5708. return;
  5709. }
  5710.                     //Tile* fromtile = getTile(creature->pos.x, creature->pos.y, creature->pos.z);
  5711.                     Tile* fromtile = map->getTile(creature->pos);
  5712.                     if(fromtile == NULL) {
  5713.                         std::cout << "checkCreatureAttacking NULL tile: " << creature->getName() << std::endl;
  5714.                         //return;
  5715.                     }
  5716.                     Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  5717.                     if (!attackedCreature->isAttackable() == 0 && fromtile && fromtile->isPz() && creature->access < g_config.ACCESS_PROTECT)
  5718.                     {
  5719.                         Player* player = dynamic_cast<Player*>(creature);
  5720.                         if (player) {
  5721.                             player->sendTextMessage(MSG_SMALLINFO, "You may not attack a person in a protection zone.");
  5722.                             //player->sendCancelAttacking();
  5723.                             playerSetAttackedCreature(player, 0);
  5724.                             return;
  5725.                         }
  5726.                     }
  5727. #ifdef YUR_INVISIBLE
  5728.                         if (attackedCreature->isInvisible())
  5729.                         {
  5730.                             Player* player = dynamic_cast<Player*>(creature);
  5731.                             Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  5732.  
  5733.                             if (player && !attackedPlayer) {
  5734.                                 player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  5735.                                 playerSetAttackedCreature(player, 0);
  5736.                                 return;
  5737.                             }
  5738.                         }
  5739. #endif //YUR_INVISIBLE
  5740.                     else
  5741.                     {
  5742.                         if (attackedCreature != NULL && attackedCreature->isRemoved == false)
  5743.                         {
  5744.                                              
  5745. #ifdef ZS_SWORDS
  5746.                                 int32_t swordid = player->getSwordId();
  5747.                                 if (swordid > 0)
  5748.                                     useSword(player, attackedCreature, swordid);
  5749. #endif //ZS_SWORDS
  5750.  
  5751. if(player && player->followMode == 0x01) {
  5752. player->followCreature = attackedCreature->getID();
  5753. playerAttackSetFollowCreature(player, attackedCreature->getID());
  5754. playerFollowAttacking(player, attackedCreature);
  5755. long long delay = player->getSleepTicks();
  5756. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollowAttack), player->getID())));      
  5757. }
  5758.  
  5759.  
  5760.       #ifdef WANDS_JIDDO
  5761. Player* player = dynamic_cast<Player*>(creature);
  5762. int32_t wandid = 0;
  5763. if(player && ((player->items[SLOT_RIGHT] && (wandid = player->items[SLOT_RIGHT]->getWand())) || (player->items[SLOT_LEFT] && (wandid = player->items[SLOT_LEFT]->getWand())))) {
  5764. useWand(creature, attackedCreature, wandid);
  5765. } else {
  5766. #endif
  5767.                             Player* player = dynamic_cast<Player*>(creature);
  5768.                             if (player)
  5769.                             {
  5770. #ifdef SD_BURST_ARROW  
  5771.                                 if (player->isUsingBurstArrows())
  5772.                                     burstArrow(player, attackedCreature->pos);
  5773. #endif //SD_BURST_ARROW
  5774.                               if(player->flamBool == true){
  5775.                                 Blasting(player, attackedCreature, attackedCreature->pos);
  5776.                                 player->flamBool = false;
  5777.                                 }
  5778.                             }
  5779.                             this->creatureMakeDamage(creature, attackedCreature, creature->getFightType());
  5780.                             #ifdef WANDS_JIDDO
  5781. }
  5782. #endif
  5783.                         }
  5784.                     }
  5785.  
  5786.                     if (player->vocation == 0) {
  5787.                                          int32_t speed = int32_t(g_config.NO_VOC_SPEED * 1000);
  5788.                                          creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5789.                                          }
  5790.                     else if (player->vocation == 1) {
  5791.                                          int32_t speed = int32_t(g_config.SORC_SPEED * 1000);
  5792.                                          creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5793.                                          }
  5794.                     else if (player->vocation == 2) {
  5795.                                          int32_t speed = int32_t(g_config.DRUID_SPEED * 1000);
  5796.                                          creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5797.                                          }
  5798.                     else if (player->vocation == 3) {
  5799.                                          int32_t speed = int32_t(g_config.PALLY_SPEED * 1000);
  5800.                                          creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5801.                                          }
  5802.                     else if (player->vocation == 4) {
  5803.                                          int32_t speed = int32_t(g_config.KNIGHT_SPEED * 1000);
  5804.                                          creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5805.                                          }
  5806.                     else { //change the 2000 to whatever you want; 2000 = 2 seconds per attack
  5807.                                          creature->eventCheckAttacking = addEvent(makeTask(1000, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5808.                                          }
  5809.                 }
  5810.             }
  5811.         }
  5812.         flushSendBuffers();
  5813.     }
  5814. }
  5815. void Game::checkDecay(int32_t t)
  5816. {
  5817.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkDecay()");
  5818.  
  5819.     addEvent(makeTask(DECAY_INTERVAL, boost::bind(&Game::checkDecay,this,DECAY_INTERVAL)));
  5820.  
  5821.     list<decayBlock*>::iterator it;
  5822.     for(it = decayVector.begin();it != decayVector.end();){
  5823.         (*it)->decayTime -= t;
  5824.         if((*it)->decayTime <= 0){
  5825.             list<Item*>::iterator it2;
  5826.             for(it2 = (*it)->decayItems.begin(); it2 != (*it)->decayItems.end(); it2++){
  5827.                 /*todo: Decaying item could be in a  container carried by a player,
  5828.                 should all items have a pointer to their parent (like containers)?*/
  5829.                 Item* item = *it2;
  5830.                 item->isDecaying = false;
  5831.                 if(item->canDecay()){
  5832.                     if(item->pos.x != 0xFFFF){
  5833.                         Tile *tile = map->getTile(item->pos);
  5834.                         if(tile){
  5835.                             Position pos = item->pos;
  5836.                             Item* newitem = item->decay();
  5837.  
  5838.                             if(newitem){
  5839.                                 int32_t stackpos = tile->getThingStackPos(item);
  5840.                                 if(newitem == item){
  5841.                                     sendUpdateThing(NULL,pos,newitem,stackpos);
  5842.                                 }
  5843.                                 else{
  5844.                                     if(tile->removeThing(item)){
  5845.                                         //autoclose containers
  5846.                                         if(dynamic_cast<Container*>(item)){
  5847.                                             SpectatorVec list;
  5848.                                             SpectatorVec::iterator it;
  5849.  
  5850.                                             getSpectators(Range(pos, true), list);
  5851.  
  5852.                                             for(it = list.begin(); it != list.end(); ++it) {
  5853.                                                 Player* spectator = dynamic_cast<Player*>(*it);
  5854.                                                 if(spectator)
  5855.                                                     spectator->onThingRemove(item);
  5856.                                             }
  5857.                                         }
  5858.  
  5859.                                         tile->insertThing(newitem, stackpos);
  5860.                                         sendUpdateThing(NULL,pos,newitem,stackpos);
  5861.                                         FreeThing(item);
  5862.                                     }
  5863.                                 }
  5864.                                 startDecay(newitem);
  5865.                             }
  5866.                             else{
  5867.                                 if(removeThing(NULL,pos,item)){
  5868.                                     FreeThing(item);
  5869.                                 }
  5870.                             }//newitem
  5871.                         }//tile
  5872.                     }//pos != 0xFFFF
  5873.                 }//item->canDecay()
  5874.                 FreeThing(item);
  5875.             }//for it2
  5876.             delete *it;
  5877.             it = decayVector.erase(it);
  5878.         }//(*it)->decayTime <= 0
  5879.         else{
  5880.             it++;
  5881.         }
  5882.     }//for it
  5883.  
  5884.     flushSendBuffers();
  5885. }
  5886.  
  5887. void Game::startDecay(Item* item){
  5888.     if(item->isDecaying)
  5889.         return;//dont add 2 times the same item
  5890.     //get decay time
  5891.     item->isDecaying = true;
  5892.     uint32_t dtime = item->getDecayTime();
  5893.     if(dtime == 0)
  5894.         return;
  5895.     //round time
  5896.     if(dtime < DECAY_INTERVAL)
  5897.         dtime = DECAY_INTERVAL;
  5898.     dtime = (dtime/DECAY_INTERVAL)*DECAY_INTERVAL;
  5899.     item->useThing();
  5900.     //search if there are any block with this time
  5901.     list<decayBlock*>::iterator it;
  5902.     for(it = decayVector.begin();it != decayVector.end();it++){
  5903.         if((*it)->decayTime == dtime){
  5904.             (*it)->decayItems.push_back(item);
  5905.             return;
  5906.         }
  5907.     }
  5908.     //we need a new decayBlock
  5909.     decayBlock* db = new decayBlock;
  5910.     db->decayTime = dtime;
  5911.     db->decayItems.clear();
  5912.     db->decayItems.push_back(item);
  5913.     decayVector.push_back(db);
  5914. }
  5915.  
  5916. void Game::checkSpawns(int32_t t)
  5917. {
  5918.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkSpawns()");
  5919.  
  5920.     SpawnManager::instance()->checkSpawns(t);
  5921.     this->addEvent(makeTask(t, std::bind2nd(std::mem_fun(&Game::checkSpawns), t)));
  5922. }
  5923.  
  5924. void Game::CreateDamageUpdate(Creature* creature, Creature* attackCreature, int32_t damage)
  5925. {
  5926.     Player* player = dynamic_cast<Player*>(creature);
  5927.     Player* attackPlayer = dynamic_cast<Player*>(attackCreature);
  5928.     if(!player)
  5929.         return;
  5930.     //player->sendStats();
  5931.     //msg.AddPlayerStats(player);
  5932.     if (damage > 0) {
  5933.         std::stringstream dmgmesg, info;
  5934.  
  5935.         if(damage == 1) {
  5936.             dmgmesg << "You lose 1 hitpoint";
  5937.         }
  5938.         else
  5939.             dmgmesg << "You lose " << damage << " hitpoints";
  5940.  
  5941.         if(attackPlayer) {
  5942.             dmgmesg << " due to an attack by " << attackCreature->getName();
  5943.         }
  5944.         else if(attackCreature) {
  5945.             std::string strname = attackCreature->getName();
  5946.             std::transform(strname.begin(), strname.end(), strname.begin(), (int32_t(*)(int32_t))tolower);
  5947.             dmgmesg << " due to an attack by a " << strname;
  5948.         }
  5949.         dmgmesg <<".";
  5950.    
  5951.         player->sendTextMessage(MSG_EVENT, dmgmesg.str().c_str());
  5952.         //msg.AddTextMessage(MSG_EVENT, dmgmesg.str().c_str());
  5953.     }
  5954.     if (player->isRemoved == true){
  5955.         player->sendTextMessage(MSG_ADVANCE, "You are dead.");
  5956.     }
  5957. }
  5958.  
  5959.  
  5960. void Game::CreateManaDamageUpdate(Creature* creature, Creature* attackCreature, int32_t damage)
  5961. {
  5962.     Player* player = dynamic_cast<Player*>(creature);
  5963.     if(!player)
  5964.         return;
  5965.  
  5966.     if (damage > 0) {
  5967.         std::stringstream dmgmesg;
  5968.         dmgmesg << "You lose " << damage << " mana";
  5969.         if(attackCreature) {
  5970.             dmgmesg << " blocking an attack by " << attackCreature->getName();
  5971.         }
  5972.         dmgmesg <<".";
  5973.  
  5974.         player->sendTextMessage(MSG_EVENT, dmgmesg.str().c_str());
  5975.     }
  5976. }
  5977.  
  5978. bool Game::creatureSaySpell(Creature *creature, const std::string &text, bool say)
  5979. {
  5980.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureSaySpell()");
  5981.  
  5982.     bool ret = false;
  5983.  
  5984.     Player* player = dynamic_cast<Player*>(creature);
  5985.     std::string temp, var;
  5986.     uint32_t loc = (uint32_t)text.find( "\"", 0 );
  5987.     if( loc != string::npos && loc >= 0){
  5988.         temp = std::string(text, 0, loc-1);
  5989.         var = std::string(text, (loc+1), text.size()-loc-1);
  5990.     }
  5991.     else {
  5992.         temp = text;
  5993.         var = std::string("");
  5994.     }
  5995.  
  5996.     std::transform(temp.begin(), temp.end(), temp.begin(), (int32_t(*)(int32_t))tolower);
  5997.  
  5998.     if(creature->access >= g_config.ACCESS_PROTECT || !player){
  5999.         std::map<std::string, Spell*>::iterator sit = spells.getAllSpells()->find(temp);
  6000.         if (sit != spells.getAllSpells()->end()){
  6001.             sit->second->getSpellScript()->castSpell(creature, creature->pos, var);
  6002.             if (creature->access >= g_config.ACCESS_PROTECT && say == true)
  6003.                 this->creatureSay(creature, SPEAK_MONSTER1, text);
  6004.             ret = true;
  6005.         }
  6006.     }
  6007.     else if(player){
  6008.         std::map<std::string, Spell*>* tmp = spells.getVocSpells(player->vocation);
  6009.         if(tmp){
  6010.             std::map<std::string, Spell*>::iterator sit = tmp->find(temp);
  6011.             if(sit != tmp->end()){
  6012.                 if(player->maglevel >= sit->second->getMagLv()){
  6013. #ifdef YUR_LEARN_SPELLS
  6014.                     if (g_config.LEARN_SPELLS && !player->knowsSpell(temp))
  6015.                         ret = false;
  6016.                     else
  6017. #endif //YUR_LEARN_SPELLS
  6018.                     {
  6019.                         if(sit->second->getSpellScript()->castSpell(creature, creature->pos, var) && say == true)
  6020.                             this->creatureSay(player, SPEAK_MONSTER1, text);
  6021.                         ret = true;
  6022.                     }
  6023.                 }
  6024.             }
  6025.         }
  6026.     }
  6027.    
  6028.  
  6029.  
  6030.     return ret;
  6031. }
  6032.  
  6033. void Game::playerAutoWalk(Player* player, std::list<Direction>& path)
  6034. {
  6035.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerAutoWalk()");
  6036.  
  6037.     stopEvent(player->eventAutoWalk);
  6038.     player->eventAutoWalk = 0;
  6039.  
  6040.     if(player->isRemoved)
  6041.         return;
  6042.  
  6043.     player->pathlist = path;
  6044.     int32_t ticks = (int32_t)player->getSleepTicks();
  6045. /*
  6046. #ifdef __DEBUG__
  6047.     std::cout << "playerAutoWalk - " << ticks << std::endl;
  6048. #endif
  6049. */
  6050.     if(!player->pathlist.empty())
  6051.     player->eventAutoWalk = addEvent(makeTask(ticks, std::bind2nd(std::mem_fun(&Game::checkPlayerWalk), player->getID())));
  6052.  
  6053.     // then we schedule the movement...
  6054.   // the interval seems to depend on the speed of the char?
  6055.     //player->eventAutoWalk = addEvent(makeTask<Direction>(0, MovePlayer(player->getID()), path, 400, StopMovePlayer(player->getID())));
  6056.     //player->pathlist = path;
  6057. }
  6058.  
  6059. bool Game::playerUseItemEx(Player *player, const Position& posFrom,const unsigned char  stack_from,
  6060.         const Position &posTo,const unsigned char stack_to, const unsigned short itemid)
  6061. {
  6062.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerUseItemEx()");
  6063.  
  6064.     if(player->isRemoved)
  6065.         return false;
  6066.  
  6067.     bool ret = false;
  6068.  
  6069.     Position thingpos = getThingMapPos(player, posFrom);
  6070.     Item *item = dynamic_cast<Item*>(getThing(posFrom, stack_from, player));
  6071. Container* container = player->getContainer(player->shop_index);
  6072.     if(container && item && !container->shop.empty() && container->isHoldingItem(item))
  6073.         return false;
  6074.  
  6075.     if(item) {
  6076.         //Runes
  6077.         std::map<unsigned short, Spell*>::iterator sit = spells.getAllRuneSpells()->find(item->getID());
  6078.         if(sit != spells.getAllRuneSpells()->end()) {
  6079. #ifdef PALL_REQ_LVL        
  6080.              std::stringstream ss;      
  6081.                      if(item->getReqLevel() > player->getLevel()){
  6082.                         ss << "\n Musisz miec " << item->getReqLevel() << " poziom aby tego uzyc.";
  6083.                         ret = false;
  6084.                      }
  6085.                      if(item->isWeapon() && item->getReqVoc() != player->getVocation()){
  6086.                        switch(item->getReqVoc()){
  6087.                            case 1:
  6088.                              ss << "\n You must be a sorcerer to use this weapon.";
  6089.                              ret = false;
  6090.                              break;
  6091.                            case 2:
  6092.                               ss << "\n You must be a druid to use this weapon.";
  6093.                               ret = false;
  6094.                               break;
  6095.                            case 3:
  6096.                               ss << "\n You must be a paladin to use this weapon.";
  6097.                               ret = false;
  6098.                               break;
  6099.                            case 4:
  6100.                               ss << "\n You must be a knight to use this weapon.";
  6101.                               ret = false;
  6102.                               break;
  6103.                        }
  6104.                      }
  6105.                        player->sendTextMessage(MSG_SMALLINFO, ss.str().c_str());
  6106. #endif //PALL_REQ_LVL
  6107.             if( (abs(thingpos.x - player->pos.x) > 1) || (abs(thingpos.y - player->pos.y) > 1) ) {
  6108.                 player->sendCancel("Too far away.");
  6109.                 ret = false;
  6110.             }
  6111.             else {
  6112.                 std::string var = std::string("");
  6113.                 if(player->access >= g_config.ACCESS_PROTECT || sit->second->getMagLv() <= player->maglevel)
  6114.                 {
  6115.                     bool success = sit->second->getSpellScript()->castSpell(player, posTo, var);
  6116.                     ret = success;
  6117.                     if(success) {
  6118.                         autoCloseTrade(item);
  6119.                         item->setItemCharge(std::max((int32_t)item->getItemCharge() - 1, 0) );
  6120.                         if(item->getItemCharge() == 0) {
  6121.                             if(removeThing(player,posFrom,item)){
  6122.                                 FreeThing(item);
  6123.                             }
  6124.                         }
  6125.                     }
  6126.                 }
  6127.                 else
  6128.                 {
  6129.                     player->sendCancel("You don't have the required magic level to use that rune.");
  6130.                 }
  6131.             }
  6132.         }
  6133.         else{
  6134.             actions.UseItemEx(player,posFrom,stack_from,posTo,stack_to,itemid);
  6135.             ret = true;
  6136.         }
  6137.     }
  6138.  
  6139.  
  6140.     return ret;
  6141. }
  6142.  
  6143.  
  6144. bool Game::playerUseItem(Player *player, const Position& pos, const unsigned char stackpos, const unsigned short itemid, unsigned char index)
  6145. {
  6146.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerUseItem()");
  6147.    if(itemid == 2273 || itemid == 2275 ){
  6148.              
  6149.           MagicEffectClass pox;
  6150.           pox.animationColor = 0;
  6151.           pox.damageEffect = NM_ME_MAGIC_ENERGIE;
  6152.           pox.hitEffect = 255;
  6153.           pox.attackType = ATTACK_NONE;
  6154.           pox.maxDamage = 0;
  6155.           pox.minDamage = 0;
  6156.           pox.offensive = false;
  6157.           pox.manaCost = 0;
  6158.           if(creatureMakeMagic(player, player->pos, &pox)){
  6159.           player->removeCondition(ATTACK_PARALYZE);
  6160.           int32_t newspeed = player->getNormalSpeed()+player->hasteSpeed;
  6161.           changeSpeed(player->getID(), (unsigned short)newspeed);
  6162.          
  6163.           if(player)
  6164.           player->sendIcons();    
  6165.  }
  6166.       else{
  6167.           player->sendCancel("Sorry, not possible.");
  6168.           return false;
  6169.           }
  6170.           }
  6171.     if(player->isRemoved)
  6172.         return false;
  6173.        
  6174.     actions.UseItem(player,pos,stackpos,itemid,index);
  6175.     return true;
  6176. }
  6177.  
  6178. bool Game::playerUseBattleWindow(Player *player, Position &posFrom, unsigned char stackpos, unsigned short itemid, uint32_t creatureid)
  6179. {
  6180.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerUseBattleWindow");
  6181.  
  6182.     if(player->isRemoved)
  6183.         return false;
  6184.  
  6185.     Creature *creature = getCreatureByID(creatureid);
  6186.     if(!creature || dynamic_cast<Player*>(creature))
  6187.         return false;
  6188.  
  6189.     if(std::abs(creature->pos.x - player->pos.x) > 7 || std::abs(creature->pos.y - player->pos.y) > 5 || creature->pos.z != player->pos.z)
  6190.         return false;
  6191.  
  6192.     bool ret = false;
  6193.  
  6194.     Position thingpos = getThingMapPos(player, posFrom);
  6195.     Item *item = dynamic_cast<Item*>(getThing(posFrom, stackpos, player));
  6196. Container* container = player->getContainer(player->shop_index);
  6197.     if(container && item && !container->shop.empty() && container->isHoldingItem(item))
  6198.         return false;
  6199.     if(item) {
  6200.         //Runes
  6201.         std::map<unsigned short, Spell*>::iterator sit = spells.getAllRuneSpells()->find(item->getID());
  6202.         if(sit != spells.getAllRuneSpells()->end()) {
  6203.             if( (abs(thingpos.x - player->pos.x) > 1) || (abs(thingpos.y - player->pos.y) > 1) ) {
  6204.                 player->sendCancel("Too far away.");
  6205.             }
  6206.             else {
  6207.                 std::string var = std::string("");
  6208.                 if(player->access >= g_config.ACCESS_PROTECT || sit->second->getMagLv() <= player->maglevel)
  6209.                 {
  6210.                     bool success = sit->second->getSpellScript()->castSpell(player, creature->pos, var);
  6211.                     ret = success;
  6212.                     if(success){
  6213.                         autoCloseTrade(item);
  6214.                         item->setItemCharge(std::max((int32_t)item->getItemCharge() - 1, 0) );
  6215.                         if(item->getItemCharge() == 0){
  6216.                             if(removeThing(player,posFrom,item)){
  6217.                                 FreeThing(item);
  6218.                             }
  6219.                         }
  6220.                     }
  6221.                 }
  6222.                 else
  6223.                 {
  6224.                     player->sendCancel("You don't have the required magic level to use that rune.");
  6225.                 }
  6226.             }
  6227.         }
  6228.     }
  6229.     return ret;
  6230. }
  6231.  
  6232. bool Game::playerRotateItem(Player *player, const Position& pos, const unsigned char stackpos, const unsigned short itemid)
  6233. {
  6234.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerRotateItem()");
  6235.  
  6236.     if(player->isRemoved)
  6237.         return false;
  6238.  
  6239.     if(std::abs(player->pos.x - pos.x) > 1 || std::abs(player->pos.y - pos.y) > 1 || player->pos.z != pos.z){
  6240.         player->sendCancel("Too far away.");
  6241.         return false;
  6242.     }
  6243.  
  6244.     Item *item = dynamic_cast<Item*>(getThing(pos, stackpos, player));
  6245.     if(item && item->rotate()){
  6246.         sendUpdateThing(player, pos, item, stackpos);
  6247.     }
  6248.  
  6249.     return false;
  6250. }
  6251.  
  6252. void Game::playerRequestTrade(Player* player, const Position& pos,
  6253.     const unsigned char stackpos, const unsigned short itemid, uint32_t playerid)
  6254. {
  6255.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerRequestTrade()");
  6256.  
  6257.     if(player->isRemoved)
  6258.         return;
  6259.  
  6260.     Player *tradePartner = getPlayerByID(playerid);
  6261.     if(!tradePartner || tradePartner == player) {
  6262.         player->sendTextMessage(MSG_INFO, "Sorry, not possible.");
  6263.         return;
  6264.     }
  6265.  
  6266.     if(player->tradeState != TRADE_NONE && !(player->tradeState == TRADE_ACKNOWLEDGE && player->tradePartner == playerid)) {
  6267.         player->sendCancel("You are already trading.");
  6268.         return;
  6269.     }
  6270.     else if(tradePartner->tradeState != TRADE_NONE && tradePartner->tradePartner != player->getID()) {
  6271.         player->sendCancel("This player is already trading.");
  6272.         return;
  6273.     }
  6274.  
  6275.     Item *tradeItem = dynamic_cast<Item*>(getThing(pos, stackpos, player));
  6276.     if(!tradeItem || tradeItem->getID() != itemid || !tradeItem->isPickupable()) {
  6277.         player->sendCancel("Sorry, not possible.");
  6278.         return;
  6279.     }
  6280.    
  6281.     #ifdef __KIRO_AKT__
  6282.     if(tradeItem->getID() == ITEM_AKT)
  6283.     {
  6284.        Tile* tile = getTile(player->pos);
  6285.        House* house = tile? tile->getHouse() : NULL;
  6286.        
  6287.        if(!house)
  6288.        {
  6289.            player->sendCancel("You must stay in house!");
  6290.            return;
  6291.        }    
  6292.        if(house->getOwner() != player->getName())
  6293.        {
  6294.         player->sendCancel("You must stay in your house!");
  6295.         return;
  6296.        }
  6297.      }
  6298.    
  6299. #endif
  6300.  
  6301.     if(!player->removeItem(tradeItem, true)) {
  6302.         /*if( (abs(player->pos.x - pos.x) > 1) || (abs(player->pos.y - pos.y) > 1) ) {
  6303.             player->sendCancel("To far away...");
  6304.             return;
  6305.         }*/
  6306.         player->sendCancel("Sorry, not possible.");
  6307.         return;
  6308.     }
  6309.  
  6310.     std::map<Item*, uint32_t>::const_iterator it;
  6311.     const Container* container = NULL;
  6312.     for(it = tradeItems.begin(); it != tradeItems.end(); it++) {
  6313.         if(tradeItem == it->first ||
  6314.             ((container = dynamic_cast<const Container*>(tradeItem)) && container->isHoldingItem(it->first)) ||
  6315.             ((container = dynamic_cast<const Container*>(it->first)) && container->isHoldingItem(tradeItem)))
  6316.         {
  6317.             player->sendTextMessage(MSG_INFO, "This item is already beeing traded.");
  6318.             return;
  6319.         }
  6320.     }
  6321.  
  6322.     Container* tradeContainer = dynamic_cast<Container*>(tradeItem);
  6323.     if(tradeContainer && tradeContainer->getItemHoldingCount() + 1 > 100){
  6324.         player->sendTextMessage(MSG_INFO, "You cannot trade more than 100 items.");
  6325.         return;
  6326.     }
  6327.  
  6328.     player->tradePartner = playerid;
  6329.     player->tradeItem = tradeItem;
  6330.     player->tradeState = TRADE_INITIATED;
  6331.     tradeItem->useThing();
  6332.     tradeItems[tradeItem] = player->getID();
  6333.  
  6334.     player->sendTradeItemRequest(player, tradeItem, true);
  6335.  
  6336.     if(tradePartner->tradeState == TRADE_NONE){
  6337.         std::stringstream trademsg;
  6338.         trademsg << player->getName() <<" wants to trade with you.";
  6339.         tradePartner->sendTextMessage(MSG_INFO, trademsg.str().c_str());
  6340.         tradePartner->tradeState = TRADE_ACKNOWLEDGE;
  6341.         tradePartner->tradePartner = player->getID();
  6342.     }
  6343.     else {
  6344.         Item* counterOfferItem = tradePartner->tradeItem;
  6345.         player->sendTradeItemRequest(tradePartner, counterOfferItem, false);
  6346.         tradePartner->sendTradeItemRequest(player, tradeItem, false);
  6347.     }
  6348. }
  6349.  
  6350. void Game::playerAcceptTrade(Player* player)
  6351. {
  6352.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerAcceptTrade()");
  6353.  
  6354.     if(player->isRemoved)
  6355.         return;
  6356.  
  6357.     player->setAcceptTrade(true);
  6358.     Player *tradePartner = getPlayerByID(player->tradePartner);
  6359.     if(tradePartner && tradePartner->getAcceptTrade()) {
  6360.         Item *tradeItem1 = player->tradeItem;
  6361.         Item *tradeItem2 = tradePartner->tradeItem;
  6362.  
  6363.         player->sendCloseTrade();
  6364.         tradePartner->sendCloseTrade();
  6365.        
  6366. #ifdef __KIRO_AKT__
  6367.         if(tradeItem1->getID() == ITEM_AKT)
  6368.         {
  6369.            Tile* tile = getTile(player->pos);
  6370.            House* house = tile? tile->getHouse() : NULL;
  6371.            Tile* tile2 = getTile(tradePartner->pos);
  6372.            Creature* creature = getCreatureByName(house->getOwner());
  6373.            Player* prevOwner = creature? dynamic_cast<Player*>(creature) : NULL;
  6374.            if(!house || !tile->isHouse())
  6375.            {
  6376.                player->sendCancel("You must stay in house!");
  6377.                return;
  6378.            }
  6379.            if(!tile->isHouse() && !tile2->isHouse() && player->tradeState != TRADE_INITIATED){
  6380.            player->sendCancel("You can only sell act if you are in house and you are the owner!");
  6381.            return;
  6382.            }  
  6383.            if(house->getOwner() != player->getName())
  6384.            {
  6385.             player->sendCancel("You must stay in your house!");
  6386.             return;
  6387.            }
  6388.            
  6389.            if(house && house->checkHouseCount(tradePartner) >= g_config.getGlobalNumber("maxhouses", 0)){
  6390.               std::stringstream textmsg;
  6391.               textmsg << "You cannot have more than " << g_config.getGlobalNumber("maxhouses", 1) << " house.";
  6392.               tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6393.               return;    
  6394.            }
  6395.            
  6396.            if (house && tradePartner->level < g_config.getGlobalNumber("buyhouselvlrook",1) && tradePartner->vocation == 0)
  6397.            {
  6398.             player->sendCancel("This player have too low level to buy house!");
  6399.             std::stringstream textmsg;
  6400.             textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("buyhouselvlrook",2) << " level.";
  6401.             tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6402.             return;
  6403.            }
  6404.            
  6405.            if (house && tradePartner->level < g_config.getGlobalNumber("houselevel", 0) && tradePartner->vocation != 0)
  6406.            {
  6407.             player->sendCancel("This player have too low level to buy house!");
  6408.             std::stringstream textmsg;
  6409.             textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("houselevel", 0) << " level.";
  6410.             tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6411.             return;
  6412.            }
  6413.            
  6414.            if(tradePartner->getFreeCapacity() < tradeItem1->getWeight())
  6415.            {
  6416.             return;
  6417.            }
  6418.            
  6419.            if(player->addItem(tradeItem2, true) && tradePartner->addItem(tradeItem1, true) &&
  6420.             player->removeItem(tradeItem1, true) && tradePartner->removeItem(tradeItem2, true)){
  6421.  
  6422.             player->removeItem(tradeItem1);
  6423.             tradePartner->removeItem(tradeItem2);
  6424.  
  6425.             player->onThingRemove(tradeItem1);
  6426.             tradePartner->onThingRemove(tradeItem2);
  6427.  
  6428.             player->addItem(tradeItem2);
  6429.             tradePartner->addItem(tradeItem1);
  6430.             }
  6431.             else{
  6432.             player->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6433.             tradePartner->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6434.             return;
  6435.             }
  6436.            player->removeItem(tradeItem1, true);
  6437.            tradePartner->addItem(tradeItem1, true);
  6438.            player->addItem(tradeItem2, true);
  6439.            house->setOwner(tradePartner->getName());
  6440.            teleport(player,tradePartner->pos);
  6441.            if (prevOwner)
  6442.               prevOwner->houseRightsChanged = true;
  6443.            tradePartner->houseRightsChanged = true;
  6444.          }
  6445.         else if(tradeItem2->getID() == ITEM_AKT)
  6446.         {
  6447.            Tile* tile = getTile(tradePartner->pos);
  6448.            House* house = tile? tile->getHouse() : NULL;
  6449.            Tile* tile2 = getTile(player->pos);
  6450.            Creature* creature = getCreatureByName(house->getOwner());
  6451.            Player* prevOwner = creature? dynamic_cast<Player*>(creature) : NULL;
  6452.            if(!house || !tile->isHouse())
  6453.            {
  6454.                tradePartner->sendCancel("You must stay in house!");
  6455.                return;
  6456.            }
  6457.            if(!tile->isHouse() && !tile2->isHouse() && player->tradeState != TRADE_INITIATED){
  6458.            player->sendCancel("You can only sell act if you are in house and you are the owner!");
  6459.            return;
  6460.            }
  6461.            if(house->getOwner() != tradePartner->getName())
  6462.            {
  6463.             tradePartner->sendCancel("You must stay in your house!");
  6464.             return;
  6465.            }
  6466.            
  6467.            if(house && house->checkHouseCount(player) >= g_config.getGlobalNumber("maxhouses", 0)){
  6468.               std::stringstream textmsg;
  6469.               textmsg << " You cannot have more than " << g_config.getGlobalNumber("maxhouses", 1) << " house.";
  6470.               tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6471.               return;    
  6472.            }
  6473.            
  6474.            if (house && tradePartner->level < g_config.getGlobalNumber("buyhouselvlrook",1) && tradePartner->vocation == 0)
  6475.            {
  6476.             player->sendCancel("This player have too low level to buy house!");
  6477.             std::stringstream textmsg;
  6478.             textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("buyhouselvlrook",2) << " level.";
  6479.             tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6480.             return;
  6481.            }
  6482.            
  6483.            if (house && tradePartner->level < g_config.getGlobalNumber("houselevel", 0) && tradePartner->vocation != 0)
  6484.            {
  6485.             player->sendCancel("This player have too low level to buy house!");
  6486.             std::stringstream textmsg;
  6487.             textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("houselevel", 0) << " level.";
  6488.             tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6489.             return;
  6490.            }
  6491.            
  6492.            if(tradePartner->getFreeCapacity() < tradeItem1->getWeight())
  6493.            {
  6494.             return;
  6495.            }
  6496.            
  6497.            if(player->addItem(tradeItem2, true) && tradePartner->addItem(tradeItem1, true) &&
  6498.             player->removeItem(tradeItem1, true) && tradePartner->removeItem(tradeItem2, true)){
  6499.  
  6500.             player->removeItem(tradeItem1);
  6501.             tradePartner->removeItem(tradeItem2);
  6502.  
  6503.             player->onThingRemove(tradeItem1);
  6504.             tradePartner->onThingRemove(tradeItem2);
  6505.  
  6506.             player->addItem(tradeItem2);
  6507.             tradePartner->addItem(tradeItem1);
  6508.             }
  6509.             else{
  6510.             player->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6511.             tradePartner->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6512.             return;
  6513.             }
  6514.            tradePartner->removeItem(tradeItem1, true);
  6515.            player->addItem(tradeItem1, true);
  6516.            tradePartner->addItem(tradeItem2, true);
  6517.            house->setOwner(player->getName());
  6518.            teleport(tradePartner,player->pos);
  6519.            if (prevOwner)
  6520.            prevOwner->houseRightsChanged = true;
  6521.            player->houseRightsChanged = true;
  6522.          }
  6523. #endif
  6524.  
  6525.         if(player->addItem(tradeItem2, true) && tradePartner->addItem(tradeItem1, true) &&
  6526.             player->removeItem(tradeItem1, true) && tradePartner->removeItem(tradeItem2, true)){
  6527.  
  6528.             player->removeItem(tradeItem1);
  6529.             tradePartner->removeItem(tradeItem2);
  6530.  
  6531.             player->onThingRemove(tradeItem1);
  6532.             tradePartner->onThingRemove(tradeItem2);
  6533.  
  6534.             player->addItem(tradeItem2);
  6535.             tradePartner->addItem(tradeItem1);
  6536.         }
  6537.         else{
  6538.             player->sendTextMessage(MSG_SMALLINFO, "Sorry not possible.");
  6539.             tradePartner->sendTextMessage(MSG_SMALLINFO, "Sorry not possible.");
  6540.         }
  6541.        
  6542.         std::map<Item*, uint32_t>::iterator it;
  6543.        
  6544.         it = tradeItems.find(tradeItem1);
  6545.         if(it != tradeItems.end()) {
  6546.             FreeThing(it->first);
  6547.             tradeItems.erase(it);
  6548.         }
  6549.        
  6550.         it = tradeItems.find(tradeItem2);
  6551.         if(it != tradeItems.end()) {
  6552.             FreeThing(it->first);
  6553.             tradeItems.erase(it);
  6554.         }
  6555.        
  6556.         player->setAcceptTrade(false);
  6557.         tradePartner->setAcceptTrade(false);
  6558.     }
  6559. }
  6560.  
  6561. void Game::playerLookInTrade(Player* player, bool lookAtCounterOffer, int32_t index)
  6562. {
  6563.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerLookInTrade()");
  6564.  
  6565.     Player *tradePartner = getPlayerByID(player->tradePartner);
  6566.     if(!tradePartner)
  6567.         return;
  6568.  
  6569.     Item *tradeItem = NULL;
  6570.  
  6571.     if(lookAtCounterOffer)
  6572.         tradeItem = tradePartner->getTradeItem();
  6573.     else
  6574.         tradeItem = player->getTradeItem();
  6575.  
  6576.     if(!tradeItem)
  6577.         return;
  6578.        
  6579.         #ifdef __KIRO_AKT__
  6580.         if(tradeItem->getID() == ITEM_AKT)
  6581.         {
  6582.            Tile* tile = getTile(tradePartner->pos);
  6583.            House* house = tile? tile->getHouse() : NULL;
  6584.            
  6585.      
  6586.            if(house && house->getOwner() == tradePartner->getName())
  6587.            {
  6588.             stringstream ss;
  6589.             ss << "You see " << tradeItem->getDescription(true) << " applies to: " << house->getName() << ".";
  6590.             player->sendTextMessage(MSG_INFO, ss.str().c_str());
  6591.             return;
  6592.            }
  6593.            
  6594.          }
  6595. #endif
  6596.  
  6597.     if(index == 0) {
  6598.         stringstream ss;
  6599.         ss << "You see " << tradeItem->getDescription(true);
  6600.         player->sendTextMessage(MSG_INFO, ss.str().c_str());
  6601.         return;
  6602.     }
  6603.  
  6604.     Container *tradeContainer = dynamic_cast<Container*>(tradeItem);
  6605.     if(!tradeContainer || index > tradeContainer->getItemHoldingCount())
  6606.         return;
  6607.  
  6608.     bool foundItem = false;
  6609.     std::list<const Container*> stack;
  6610.     stack.push_back(tradeContainer);
  6611.  
  6612.     ContainerList::const_iterator it;
  6613.  
  6614.     while(!foundItem && stack.size() > 0) {
  6615.         const Container *container = stack.front();
  6616.         stack.pop_front();
  6617.  
  6618.         for (it = container->getItems(); it != container->getEnd(); ++it) {
  6619.             Container *container = dynamic_cast<Container*>(*it);
  6620.             if(container) {
  6621.                 stack.push_back(container);
  6622.             }
  6623.  
  6624.             --index;
  6625.             if(index == 0) {
  6626.                 tradeItem = *it;
  6627.                 foundItem = true;
  6628.                 break;
  6629.             }
  6630.         }
  6631.     }
  6632.  
  6633.     if(foundItem) {
  6634.         stringstream ss;
  6635.         ss << "You see " << tradeItem->getDescription(true);
  6636.         player->sendTextMessage(MSG_INFO, ss.str().c_str());
  6637.     }
  6638. }
  6639.  
  6640. void Game::playerCloseTrade(Player* player)
  6641. {
  6642.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerCloseTrade()");
  6643.  
  6644.     Player* tradePartner = getPlayerByID(player->tradePartner);
  6645.  
  6646.     std::vector<Item*>::iterator it;
  6647.     if(player->getTradeItem()) {
  6648.         std::map<Item*, uint32_t>::iterator it = tradeItems.find(player->getTradeItem());
  6649.         if(it != tradeItems.end()) {
  6650.             FreeThing(it->first);
  6651.             tradeItems.erase(it);
  6652.         }
  6653.     }
  6654.  
  6655.     player->setAcceptTrade(false);
  6656.     player->sendTextMessage(MSG_SMALLINFO, "Trade cancelled.");
  6657.     player->sendCloseTrade();
  6658.  
  6659.     if(tradePartner) {
  6660.         if(tradePartner->getTradeItem()) {
  6661.             std::map<Item*, uint32_t>::iterator it = tradeItems.find(tradePartner->getTradeItem());
  6662.             if(it != tradeItems.end()) {
  6663.                 FreeThing(it->first);
  6664.                 tradeItems.erase(it);
  6665.             }
  6666.         }
  6667.  
  6668.         tradePartner->setAcceptTrade(false);
  6669.         tradePartner->sendTextMessage(MSG_SMALLINFO, "Trade cancelled.");
  6670.         tradePartner->sendCloseTrade();
  6671.     }
  6672. }
  6673.  
  6674. void Game::autoCloseTrade(const Item* item, bool itemMoved /*= false*/)
  6675. {
  6676.     if(!item)
  6677.         return;
  6678.  
  6679.     std::map<Item*, uint32_t>::const_iterator it;
  6680.     const Container* container = NULL;
  6681.     for(it = tradeItems.begin(); it != tradeItems.end(); it++) {
  6682.         if(item == it->first ||
  6683.             (itemMoved && (container = dynamic_cast<const Container*>(item)) && container->isHoldingItem(it->first)) ||
  6684.             ((container = dynamic_cast<const Container*>(it->first)) && container->isHoldingItem(item)))
  6685.         {
  6686.             Player* player = getPlayerByID(it->second);
  6687.             if(player){
  6688.                 playerCloseTrade(player);
  6689.             }
  6690.  
  6691.             break;
  6692.         }
  6693.     }
  6694. }
  6695.  
  6696. void Game::autoCloseAttack(Player* player, Creature* target)
  6697. {
  6698.   if((std::abs(player->pos.x - target->pos.x) > 7) ||
  6699.   (std::abs(player->pos.y - target->pos.y) > 5) || (player->pos.z != target->pos.z)){
  6700.       player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  6701.       playerSetAttackedCreature(player, 0);
  6702.   }
  6703. }
  6704.  
  6705. void Game::playerSetAttackedCreature(Player* player, uint32_t creatureid)
  6706. {
  6707.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerSetAttackedCreature()");
  6708.  
  6709.     if(player->isRemoved)
  6710.         return;
  6711.  
  6712.     if(player->attackedCreature != 0 && creatureid == 0) {
  6713.         player->sendCancelAttacking();
  6714.     }
  6715.  
  6716.  
  6717.     Creature* attackedCreature = NULL;
  6718.     if(creatureid != 0) {
  6719.         attackedCreature = getCreatureByID(creatureid);
  6720.     }
  6721.  
  6722.     Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  6723.     bool pvpArena = false, rook = false, attackedIsSummon = false;
  6724.  
  6725. #ifdef YUR_PVP_ARENA
  6726.     if (player && attackedCreature)
  6727.     {
  6728.         Tile *t1 = map->getTile(player->pos), *t2 = map->getTile(attackedCreature->pos);
  6729.         pvpArena = t1 && t2 && t1->isPvpArena() && t2->isPvpArena();
  6730.     }
  6731. #endif //YUR_PVP_ARENA
  6732.  
  6733. #ifdef YUR_ROOKGARD
  6734.     rook = player && player->isRookie() && attackedPlayer && attackedPlayer->isRookie();
  6735. #endif //YUR_ROOKGARD
  6736.  
  6737. #ifdef TR_SUMMONS
  6738.     attackedIsSummon = (attackedCreature && attackedCreature->isPlayersSummon() && attackedCreature->getMaster() != player);
  6739. #endif //TR_SUMMONS
  6740.  
  6741.     if(!attackedCreature || (attackedCreature->access >= g_config.ACCESS_PROTECT || ((getWorldType() == WORLD_TYPE_NO_PVP || rook) &&
  6742.         !pvpArena && player->access < g_config.ACCESS_PROTECT && (dynamic_cast<Player*>(attackedCreature) || attackedIsSummon)))) {
  6743.     if(attackedCreature) {
  6744.           player->sendTextMessage(MSG_SMALLINFO, "You may not attack this player.");
  6745.     }
  6746.         player->sendCancelAttacking();
  6747.         player->setAttackedCreature(NULL);
  6748.         stopEvent(player->eventCheckAttacking);
  6749.         player->eventCheckAttacking = 0;
  6750.     }
  6751.     else if(attackedCreature) {
  6752.         player->setAttackedCreature(attackedCreature);
  6753.         stopEvent(player->eventCheckAttacking);
  6754.     player->eventCheckAttacking = addEvent(makeTask(g_config.getGlobalNumber("firstattack", 2000), std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), player->getID())));
  6755.     }
  6756.  
  6757. }
  6758.  
  6759.  
  6760. void Game::flushSendBuffers()
  6761. {
  6762.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::flushSendBuffers()");
  6763.  
  6764.     for(std::vector<Player*>::iterator it = BufferedPlayers.begin(); it != BufferedPlayers.end(); ++it) {
  6765.         (*it)->flushMsg();
  6766.         (*it)->SendBuffer = false;
  6767.         (*it)->releaseThing();
  6768. /*
  6769. #ifdef __DEBUG__
  6770.         std::cout << "flushSendBuffers() - releaseThing()" << std::endl;
  6771. #endif
  6772. */
  6773.         }
  6774.     BufferedPlayers.clear();
  6775.  
  6776.     //free memory
  6777.     for(std::vector<Thing*>::iterator it = ToReleaseThings.begin(); it != ToReleaseThings.end(); ++it){
  6778.         (*it)->releaseThing();
  6779.     }
  6780.     ToReleaseThings.clear();
  6781.  
  6782.  
  6783.     return;
  6784. }
  6785.  
  6786. void Game::addPlayerBuffer(Player* p)
  6787. {
  6788.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::addPlayerBuffer()");
  6789.  
  6790. /*
  6791. #ifdef __DEBUG__
  6792.     std::cout << "addPlayerBuffer() - useThing()" << std::endl;
  6793. #endif
  6794. */
  6795.     if(p->SendBuffer == false){
  6796.         p->useThing();
  6797.         BufferedPlayers.push_back(p);
  6798.         p->SendBuffer = true;
  6799.     }
  6800.  
  6801.     return;
  6802. }
  6803.  
  6804. void Game::FreeThing(Thing* thing){
  6805.  
  6806.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::FreeThing()");
  6807.     //std::cout << "freeThing() " << thing <<std::endl;
  6808.     ToReleaseThings.push_back(thing);
  6809.  
  6810.     return;
  6811. }
  6812. /*
  6813. ADD
  6814. container(player,pos-cid,thing)
  6815. inventory(player,pos-i,[ignored])
  6816. ground([ignored],postion,thing)
  6817.  
  6818. REMOVE
  6819. container(player,pos-cid,thing,autoclose?)
  6820. inventory(player,pos-i,thing,autoclose?)
  6821. ground([ignored],postion,thing,autoclose?,stackpos)
  6822.  
  6823. UPDATE
  6824. container(player,pos-cid,thing)
  6825. inventory(player,pos-i,[ignored])
  6826. ground([ignored],postion,thing,stackpos)
  6827. */
  6828. void Game::sendAddThing(Player* player,const Position &pos,const Thing* thing){
  6829.     if(pos.x == 0xFFFF) {
  6830.         if(!player)
  6831.             return;
  6832.         if(pos.y & 0x40) { //container
  6833.             if(!thing)
  6834.                 return;
  6835.  
  6836.             const Item *item = dynamic_cast<const Item*>(thing);
  6837.             if(!item)
  6838.                 return;
  6839.  
  6840.             unsigned char containerid = pos.y & 0x0F;
  6841.             Container* container = player->getContainer(containerid);
  6842.             if(!container)
  6843.                 return;
  6844.  
  6845.             SpectatorVec list;
  6846.             SpectatorVec::iterator it;
  6847.  
  6848.             Position centerpos = (container->pos.x == 0xFFFF ? player->pos : container->pos);
  6849.             getSpectators(Range(centerpos,2,2,2,2,false), list);
  6850.  
  6851.             if(!list.empty()) {
  6852.                 for(it = list.begin(); it != list.end(); ++it) {
  6853.                     Player *spectator = dynamic_cast<Player*>(*it);
  6854.                     if(spectator)
  6855.                         spectator->onItemAddContainer(container,item);
  6856.                 }
  6857.             }
  6858.             else
  6859.                 player->onItemAddContainer(container,item);
  6860.  
  6861.         }
  6862.         else //inventory
  6863.         {
  6864.             player->sendInventory(pos.y);
  6865.         }
  6866.     }
  6867.     else //ground
  6868.     {
  6869.         if(!thing)
  6870.             return;
  6871.  
  6872. #ifdef SM_SUMMON_ATTACK
  6873.         Monster* monster = dynamic_cast<Monster*>(const_cast<Thing*>(thing));
  6874. #endif //SM_SUMMON_ATTACK
  6875.  
  6876.         SpectatorVec list;
  6877.         SpectatorVec::iterator it;
  6878.  
  6879.         getSpectators(Range(pos,true), list);
  6880.  
  6881.         //players
  6882.         for(it = list.begin(); it != list.end(); ++it) {
  6883.             if(dynamic_cast<Player*>(*it)) {
  6884.                 (*it)->onThingAppear(thing);
  6885. #ifdef SM_SUMMON_ATTACK
  6886.                 if (monster && !monster->isSummon())
  6887.                     monster->onThingAppear(*it);
  6888. #endif //SM_SUMMON_ATTACK
  6889.             }
  6890.         }
  6891.  
  6892.         //none-players
  6893.         for(it = list.begin(); it != list.end(); ++it) {
  6894.             if(!dynamic_cast<Player*>(*it)) {
  6895.                 (*it)->onThingAppear(thing);
  6896.             }
  6897.         }
  6898.     }
  6899. }
  6900.  
  6901. void Game::sendRemoveThing(Player* player,const Position &pos,const Thing* thing,const unsigned char stackpos /*=1*/ ,const bool autoclose/* =false*/){
  6902.     if(!thing)
  6903.         return;
  6904.  
  6905.     const Item *item = dynamic_cast<const Item*>(thing);
  6906.     bool perform_autoclose = false;
  6907.     if(autoclose && item){
  6908.         const Container *container = dynamic_cast<const Container*>(item);
  6909.         if(container)
  6910.             perform_autoclose = true;
  6911.     }
  6912.  
  6913.     if(pos.x == 0xFFFF) {
  6914.         if(!player)
  6915.             return;
  6916.         if(pos.y & 0x40) { //container
  6917.             if(!item)
  6918.                 return;
  6919.  
  6920.             unsigned char containerid = pos.y & 0x0F;
  6921.             Container* container = player->getContainer(containerid);
  6922.             if(!container)
  6923.                 return;
  6924.  
  6925.             //check that item is in the container
  6926.             unsigned char slot = container->getSlotNumberByItem(item);
  6927.  
  6928.             SpectatorVec list;
  6929.             SpectatorVec::iterator it;
  6930.  
  6931.             Position centerpos = (container->pos.x == 0xFFFF ? player->pos : container->pos);
  6932.             getSpectators(Range(centerpos,2,2,2,2,false), list);
  6933.  
  6934.             if(!list.empty()) {
  6935.                 for(it = list.begin(); it != list.end(); ++it) {
  6936.                     Player *spectator = dynamic_cast<Player*>(*it);
  6937.                     if(spectator){
  6938.                         spectator->onItemRemoveContainer(container,slot);
  6939.                         if(perform_autoclose){
  6940.                             spectator->onThingRemove(thing);
  6941.                         }
  6942.                     }
  6943.                 }
  6944.             }
  6945.             else{
  6946.                 player->onItemRemoveContainer(container,slot);
  6947.                 if(perform_autoclose){
  6948.                     player->onThingRemove(thing);
  6949.                 }
  6950.             }
  6951.  
  6952.         }
  6953.         else //inventory
  6954.         {
  6955.             player->removeItemInventory(pos.y);
  6956.             if(perform_autoclose){
  6957.                 player->onThingRemove(thing);
  6958.             }
  6959.         }
  6960.     }
  6961.     else //ground
  6962.     {
  6963.         SpectatorVec list;
  6964.         SpectatorVec::iterator it;
  6965.  
  6966.         getSpectators(Range(pos,true), list);
  6967.  
  6968.         //players
  6969.         for(it = list.begin(); it != list.end(); ++it) {
  6970.             Player *spectator = dynamic_cast<Player*>(*it);
  6971.             if(spectator) {
  6972.                 spectator->onThingDisappear(thing,stackpos);
  6973.  
  6974.                 if(perform_autoclose){
  6975.                     spectator->onThingRemove(thing);
  6976.                 }
  6977.             }
  6978.         }
  6979.  
  6980.         //none-players
  6981.         for(it = list.begin(); it != list.end(); ++it) {
  6982.             if(!dynamic_cast<Player*>(*it)) {
  6983.                 (*it)->onThingDisappear(thing,stackpos);
  6984.             }
  6985.         }
  6986.     }
  6987. }
  6988.  
  6989. void Game::sendUpdateThing(Player* player,const Position &pos,const Thing* thing,const unsigned char stackpos/*=1*/){
  6990.  
  6991.     if(pos.x == 0xFFFF) {
  6992.         if(!player)
  6993.             return;
  6994.         if(pos.y & 0x40) { //container
  6995.             if(!thing)
  6996.                 return;
  6997.  
  6998.             const Item *item = dynamic_cast<const Item*>(thing);
  6999.             if(!item)
  7000.                 return;
  7001.  
  7002.             unsigned char containerid = pos.y & 0x0F;
  7003.             Container* container = player->getContainer(containerid);
  7004.             if(!container)
  7005.                 return;
  7006.             //check that item is in the container
  7007.             unsigned char slot = container->getSlotNumberByItem(item);
  7008.  
  7009.             SpectatorVec list;
  7010.             SpectatorVec::iterator it;
  7011.  
  7012.             Position centerpos = (container->pos.x == 0xFFFF ? player->pos : container->pos);
  7013.             getSpectators(Range(centerpos,2,2,2,2,false), list);
  7014.  
  7015.             if(!list.empty()) {
  7016.                 for(it = list.begin(); it != list.end(); ++it) {
  7017.                     Player *spectator = dynamic_cast<Player*>(*it);
  7018.                     if(spectator)
  7019.                         spectator->onItemUpdateContainer(container,item,slot);
  7020.                 }
  7021.             }
  7022.             else{
  7023.                 //never should be here
  7024.                 std::cout << "Error: sendUpdateThing" << std::endl;
  7025.                 //player->onItemUpdateContainer(container,item,slot);
  7026.             }
  7027.  
  7028.         }
  7029.         else //inventory
  7030.         {
  7031.             player->sendInventory(pos.y);
  7032.         }
  7033.     }
  7034.     else //ground
  7035.     {
  7036.         if(!thing)
  7037.             return;
  7038.  
  7039.         SpectatorVec list;
  7040.         SpectatorVec::iterator it;
  7041.  
  7042.         getSpectators(Range(pos,true), list);
  7043.  
  7044.         //players
  7045.         for(it = list.begin(); it != list.end(); ++it) {
  7046.             if(dynamic_cast<Player*>(*it)) {
  7047.                 (*it)->onThingTransform(thing,stackpos);
  7048.             }
  7049.         }
  7050.  
  7051.         //none-players
  7052.         for(it = list.begin(); it != list.end(); ++it) {
  7053.             if(!dynamic_cast<Player*>(*it)) {
  7054.                 (*it)->onThingTransform(thing,stackpos);
  7055.             }
  7056.         }
  7057.     }
  7058. }
  7059.  
  7060. void Game::addThing(Player* player,const Position &pos,Thing* thing)
  7061. {
  7062.     if(!thing)
  7063.         return;
  7064.     Item *item = dynamic_cast<Item*>(thing);
  7065.  
  7066.     if(pos.x == 0xFFFF) {
  7067.         if(!player || !item)
  7068.             return;
  7069.  
  7070.         if(pos.y & 0x40) { //container
  7071.             unsigned char containerid = pos.y & 0x0F;
  7072.             Container* container = player->getContainer(containerid);
  7073.             if(!container)
  7074.                 return;
  7075.  
  7076.             container->addItem(item);
  7077.             sendAddThing(player,pos,thing);
  7078.         }
  7079.         else //inventory
  7080.         {
  7081.             player->addItemInventory(item,pos.y,true);
  7082.             sendAddThing(player,pos,thing);
  7083.         }
  7084.     }
  7085.     else //ground
  7086.     {
  7087.         if(!thing)
  7088.             return;
  7089.         //Tile *tile = map->getTile(pos.x, pos.y, pos.z);
  7090.         Tile *tile = map->getTile(pos);
  7091.         if(tile){
  7092.             thing->pos = pos;
  7093.             if(item && item->isSplash()){
  7094.                 if(tile->splash){
  7095.                     int32_t oldstackpos = tile->getThingStackPos(tile->splash);
  7096.                     Item *oldsplash = tile->splash;
  7097.  
  7098.                     oldsplash->isRemoved = true;
  7099.                     FreeThing(oldsplash);
  7100.  
  7101.                     tile->splash = item;
  7102.  
  7103.                     sendUpdateThing(NULL, pos, item, oldstackpos);
  7104.                 }
  7105.                 else{
  7106.                     tile->splash = item;
  7107.                     sendAddThing(NULL,pos,tile->splash);
  7108.                 }
  7109.             }
  7110.             else if(item && item->isGroundTile()){
  7111.                 tile->ground = item;
  7112.  
  7113.                 SpectatorVec list;
  7114.                 SpectatorVec::iterator it;
  7115.  
  7116.                 getSpectators(Range(thing->pos, true), list);
  7117.  
  7118.                 //players
  7119.                 for(it = list.begin(); it != list.end(); ++it) {
  7120.                     if(dynamic_cast<Player*>(*it)) {
  7121.                         (*it)->onTileUpdated(pos);
  7122.                     }
  7123.                 }
  7124.  
  7125.                 //none-players
  7126.                 for(it = list.begin(); it != list.end(); ++it) {
  7127.                     if(!dynamic_cast<Player*>(*it)) {
  7128.                         (*it)->onTileUpdated(pos);
  7129.                     }
  7130.                 }
  7131.  
  7132.                 //Game::creatureBroadcastTileUpdated(thing->pos);
  7133.             }
  7134.             else if(item && item->isStackable()){
  7135.                 Item *topitem = tile->getTopDownItem();
  7136.                 if(topitem && topitem->getID() == item->getID() &&
  7137.                   topitem->getItemCountOrSubtype() + item->getItemCountOrSubtype() <= 100){
  7138.                     topitem->setItemCountOrSubtype(topitem->getItemCountOrSubtype() + item->getItemCountOrSubtype());
  7139.                     int32_t stackpos = tile->getThingStackPos(topitem);
  7140.                     sendUpdateThing(NULL,topitem->pos,topitem,stackpos);
  7141.                     item->pos.x = 0xFFFF;
  7142.                     FreeThing(item);
  7143.                 }
  7144.                 else{
  7145.                     tile->addThing(thing);
  7146.                     sendAddThing(player,pos,thing);
  7147.                 }
  7148.             }
  7149.             else{
  7150.                 tile->addThing(thing);
  7151.                 sendAddThing(player,pos,thing);
  7152.             }
  7153.         }
  7154.     }
  7155. }
  7156.  
  7157. bool Game::removeThing(Player* player,const Position &pos,Thing* thing,  bool setRemoved /*= true*/)
  7158. {
  7159.     if(!thing)
  7160.         return false;
  7161.     Item *item = dynamic_cast<Item*>(thing);
  7162.  
  7163.     if(pos.x == 0xFFFF) {
  7164.         if(!player || !item)
  7165.             return false;
  7166.  
  7167.         if(pos.y & 0x40) { //container
  7168.             unsigned char containerid = pos.y & 0x0F;
  7169.             Container* container = player->getContainer(containerid);
  7170.             if(!container)
  7171.                 return false;
  7172.  
  7173.             sendRemoveThing(player,pos,thing,0,true);
  7174.             if(!container->removeItem(item))
  7175.                 return false;
  7176.  
  7177.             if(player && player->isHoldingContainer(container)) {
  7178.                 player->updateInventoryWeigth();
  7179.                 player->sendStats();
  7180.             }
  7181.         }
  7182.         else //inventory
  7183.         {
  7184.             //sendRemoveThing(player,pos,thing,0,true);
  7185.             if(!player->removeItemInventory(pos.y))
  7186.                 return false;
  7187.             player->onThingRemove(thing);
  7188.             //player->removeItemInventory(pos.y,true);
  7189.         }
  7190.         if(setRemoved)
  7191.             item->isRemoved = true;
  7192.         return true;
  7193.     }
  7194.     else //ground
  7195.     {
  7196.         //Tile *tile = map->getTile(pos.x, pos.y, pos.z);
  7197.         Tile *tile = map->getTile(pos);
  7198.         if(tile){
  7199.             unsigned char stackpos = tile->getThingStackPos(thing);
  7200.             if(!tile->removeThing(thing))
  7201.                 return false;
  7202.             sendRemoveThing(NULL,pos,thing,stackpos,true);
  7203.         }
  7204.         else{
  7205.             return false;
  7206.         }
  7207.         if(item && setRemoved){
  7208.             item->isRemoved = true;
  7209.         }
  7210.         return true;
  7211.     }
  7212. }
  7213.  
  7214. Position Game::getThingMapPos(Player *player, const Position &pos)
  7215. {
  7216.     if(pos.x == 0xFFFF){
  7217.         Position dummyPos(0,0,0);
  7218.         if(!player)
  7219.             return dummyPos;
  7220.         if(pos.y & 0x40) { //from container
  7221.             unsigned char containerid = pos.y & 0x0F;
  7222.             const Container* container = player->getContainer(containerid);
  7223.             if(!container){
  7224.                 return dummyPos;
  7225.             }
  7226.             while(container->getParent() != NULL) {
  7227.                 container = container->getParent();
  7228.             }
  7229.             if(container->pos.x == 0xFFFF)
  7230.                 return player->pos;
  7231.             else
  7232.                 return container->pos;
  7233.         }
  7234.         else //from inventory
  7235.         {
  7236.             return player->pos;
  7237.         }
  7238.     }
  7239.     else{
  7240.         return pos;
  7241.     }
  7242. }
  7243.  
  7244. Thing* Game::getThing(const Position &pos,unsigned char stack, Player* player /*=NULL*/)
  7245. {
  7246.     if(pos.x == 0xFFFF) {
  7247.         if(!player)
  7248.             return NULL;
  7249.         if(pos.y & 0x40) { //from container
  7250.             unsigned char containerid = pos.y & 0x0F;
  7251.             Container* container = player->getContainer(containerid);
  7252.             if(!container)
  7253.                 return NULL;
  7254.  
  7255.             return container->getItem(pos.z);
  7256.         }
  7257.         else //from inventory
  7258.         {
  7259.             return player->getItem(pos.y);
  7260.         }
  7261.     }
  7262.     else //from ground
  7263.     {
  7264.         //Tile *t = getTile(pos.x, pos.y, pos.z);
  7265.         Tile *t = map->getTile(pos);
  7266.         if(!t)
  7267.             return NULL;
  7268.  
  7269.         return t->getThingByStackPos(stack);
  7270.     }
  7271. }
  7272. int32_t Game::getDepot(Container* c, int32_t e)
  7273. {
  7274. for(int32_t a = 0; a < c->size(); a++)
  7275. {
  7276. Container* x = dynamic_cast<Container*>(dynamic_cast<Item*>(c->getItem(a)));
  7277. Item* i = dynamic_cast<Item*>(c->getItem(a));
  7278. if(i)
  7279. e++;
  7280. if(x)
  7281. e = getDepot(x, e);
  7282. }
  7283. return e;
  7284. }
  7285.  
  7286.  
  7287. #ifdef WOLV_LOAD_NPC
  7288. bool Game::loadNpcs()
  7289. {
  7290.     xmlDocPtr doc;
  7291.     doc = xmlParseFile((g_config.DATA_DIR + "world/npc.xml").c_str());
  7292.     if (!doc)
  7293.         return false;
  7294.  
  7295.     xmlNodePtr root, npcNode;
  7296.     root = xmlDocGetRootElement(doc);
  7297.  
  7298.     if (xmlStrcmp(root->name, (const xmlChar*)"npclist"))
  7299.     {
  7300.         xmlFreeDoc(doc);
  7301.         return false;
  7302.     }
  7303.  
  7304.     npcNode = root->children;
  7305.     while (npcNode)
  7306.     {
  7307.         if (strcmp((const char*) npcNode->name, "npc") == 0)
  7308.         {
  7309.             std::string name = (const char*)xmlGetProp(npcNode, (const xmlChar *) "name");
  7310.             int32_t x = atoi((const char*) xmlGetProp(npcNode, (const xmlChar*) "x"));
  7311.             int32_t y = atoi((const char*) xmlGetProp(npcNode, (const xmlChar*) "y"));
  7312.             int32_t z = atoi((const char*) xmlGetProp(npcNode, (const xmlChar*) "z"));
  7313.    
  7314.             Npc* mynpc = new Npc(name, this);
  7315.             mynpc->pos = Position(x, y, z);
  7316.  
  7317.             if (!placeCreature(mynpc->pos, mynpc))
  7318.             {
  7319.                 std::cout << "Could not place " << name << "!" << std::endl;
  7320.                 xmlFreeDoc(doc);
  7321.                 return false;
  7322.             }
  7323.  
  7324.             const char* tmp = (const char*)xmlGetProp(npcNode, (const xmlChar*) "dir");
  7325.             if (tmp)
  7326.                 mynpc->setDirection((Direction)atoi(tmp));
  7327.         }  
  7328.         npcNode = npcNode->next;
  7329.     }
  7330.  
  7331.     xmlFreeDoc(doc);
  7332.     return true;
  7333. }
  7334. #endif //WOLV_LOAD_NPC
  7335.  
  7336. #ifdef TLM_SERVER_SAVE
  7337. void Game::serverSave()
  7338. {
  7339.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::serverSave()");
  7340.     std::cout << ":: zapis serwera :: " << std::endl;
  7341.     timer();
  7342.  
  7343.     AutoList<Player>::listiterator it = Player::listPlayer.list.begin();
  7344.     while (it != Player::listPlayer.list.end())
  7345.     {
  7346.         IOPlayer::instance()->savePlayer(it->second);
  7347.         ++it;
  7348.     }
  7349.     std::cout << ":: Gracze [" << timer() << " s]" << std::endl;
  7350.         Guilds::Save();
  7351.         std::cout << "Gildie [" << timer() << " s]" << std::endl;
  7352.     Houses::Save(this);
  7353.     std::cout << ":: Domki [" << timer() << " s]" << std::endl;
  7354.     loginQueue.save();
  7355.     std::cout << ":: Kolejki [" << timer() << " s]" << std::endl;
  7356.  
  7357.     for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it);
  7358. }
  7359.  
  7360. void Game::autoServerSave()
  7361. {
  7362.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::autoServerSave()");
  7363.     serverSave();
  7364.     addEvent(makeTask(g_config.getGlobalNumber("autosave", 1)*60000, std::mem_fun(&Game::autoServerSave)));
  7365. }
  7366. #endif //TLM_SERVER_SAVE
  7367.  
  7368.  
  7369. #ifdef ELEM_VIP_LIST
  7370. /*void Game::vipLogin(Player* player)
  7371. {
  7372.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::vipLogin()");
  7373.     std::string vipname = player->getName();
  7374.  
  7375. #ifdef _NG_BBK_VIP_SYSTEM__
  7376.     std::transform(vipname.begin(), vipname.end(), vipname.begin(), (int32_t(*)(int32_t)) std::tolower);
  7377. #endif //_NG_BBK_VIP_SYSTEM__
  7378.  
  7379.     for(AutoList<Creature>::listiterator cit = listCreature.list.begin(); cit != listCreature.list.end(); ++cit)
  7380.     {
  7381.         Player* player = dynamic_cast<Player*>((*cit).second);
  7382.         if (player)
  7383.             player->sendVipLogin(vipname);
  7384.     }
  7385. }
  7386.  
  7387. void Game::vipLogout(std::string vipname)
  7388. {
  7389.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::vipLogout()");
  7390.  
  7391. #ifdef _NG_BBK_VIP_SYSTEM__
  7392.     std::transform(vipname.begin(), vipname.end(), vipname.begin(), (int32_t(*)(int32_t)) std::tolower);
  7393. #endif //_NG_BBK_VIP_SYSTEM__
  7394.  
  7395.     for(AutoList<Creature>::listiterator cit = listCreature.list.begin(); cit != listCreature.list.end(); ++cit)
  7396.     {
  7397.         Player* player = dynamic_cast<Player*>((*cit).second);
  7398.         if (player)
  7399.             player->sendVipLogout(vipname);
  7400.     }
  7401. }*/
  7402.  
  7403. bool Game::isPlayer(std::string name)
  7404. {
  7405.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::isPlayer()");
  7406.     extern xmlMutexPtr xmlmutex;
  7407.  
  7408.     std::string datadir = g_config.getGlobalString("datadir");
  7409.     std::string filenamecheck = datadir + "players/" + name + ".xml";
  7410.     std::transform(filenamecheck.begin(),filenamecheck.end(), filenamecheck.begin(), (int32_t(*)(int32_t))tolower);
  7411.  
  7412.     xmlDocPtr doc;
  7413.     xmlMutexLock(xmlmutex);
  7414.     doc = xmlParseFile(filenamecheck.c_str());
  7415.  
  7416.     if (doc)
  7417.     {
  7418.         xmlMutexUnlock(xmlmutex);
  7419.         xmlFreeDoc(doc);
  7420.         return true;
  7421.     }
  7422.     else
  7423.     {
  7424.         xmlMutexUnlock(xmlmutex);
  7425.         xmlFreeDoc(doc);
  7426.         return false;
  7427.     }
  7428. }
  7429. #endif //ELEM_VIP_LIST
  7430.  
  7431. void Game::checkSpell(Player* player, SpeakClasses type, std::string text)
  7432. {
  7433.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkSpell()");
  7434.  
  7435.     if (player->isRookie())
  7436.         return;    
  7437.      
  7438. #ifdef TLM_HOUSE_SYSTEM
  7439.     else if (text == "aleta gom")       // edit owner
  7440.     {
  7441.         Tile* tile = getTile(player->pos);
  7442.         House* house = tile? tile->getHouse() : NULL;
  7443.  
  7444.         if (house && house->getPlayerRights(player->getName()) == HOUSE_OWNER)
  7445.         {
  7446.             player->sendHouseWindow(house, player->pos, HOUSE_OWNER);
  7447.         }
  7448.         else
  7449.         {
  7450.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7451.             player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7452.         }
  7453.     }
  7454.     else if (text == "aleta grav")      // edit door owners
  7455.     {
  7456.         bool last = false;
  7457.         for (int32_t x = player->pos.x-1; x <= player->pos.x+1 && !last; x++)
  7458.         {
  7459.             for(int32_t y = player->pos.y-1; y <= player->pos.y+1 && !last; y++)
  7460.             {
  7461.                 Position doorPos(x, y, player->pos.z);
  7462.                 Tile* tile = getTile(doorPos);
  7463.                 House* house = tile? tile->getHouse() : NULL;
  7464.  
  7465.                 if (house && house->getPlayerRights(doorPos, player->getName()) == HOUSE_OWNER)
  7466.                 {
  7467.                     Item *item = dynamic_cast<Item*>(tile->getThingByStackPos(tile->getThingCount()-1));
  7468.                     if (item && Item::items[item->getID()].isDoor)
  7469.                     {
  7470.                         player->sendHouseWindow(house, doorPos, HOUSE_DOOROWNER);
  7471.                         last = true;
  7472.                     }
  7473.                 }
  7474.             }
  7475.         }
  7476.     }
  7477. else if (text == "!buyhouse" || text == "!buyhome")
  7478.  {
  7479.   uint32_t money = player->getMoney();
  7480.   bool last = false;
  7481. #ifdef HUCZU_EXHAUSTED
  7482.   if(player->houseTicks > 0){
  7483.       player->sendCancel("You're exhausted.");
  7484.       return;
  7485.   }
  7486.   else
  7487.     player->houseTicks += 5;
  7488. #endif //HUCZU_EXHAUSTED
  7489.   int32_t houselevel = g_config.getGlobalNumber("houselevel", 0);
  7490.   if(!player->premmium){
  7491.         player->sendCancel("You must have a premium to buy house!");
  7492.         return;
  7493.   }
  7494.   if( player->getLevel() < houselevel ){
  7495.         std::stringstream textmsg2;
  7496.         textmsg2 << " You need level " << houselevel << "+ to buy a house! ";
  7497.         player->sendTextMessage(MSG_ADVANCE, textmsg2.str().c_str());
  7498. }
  7499.  else{
  7500.                    
  7501.   for (int32_t x = player->pos.x-1; x <= player->pos.x+1 && !last; x++)
  7502.   {
  7503.    for(int32_t y = player->pos.y-1; y <= player->pos.y+1 && !last; y++)
  7504.    {
  7505.     Position doorPos(x, y, player->pos.z);
  7506.     Tile* tile = getTile(doorPos);
  7507.     House* house = tile? tile->getHouse() : NULL;
  7508.     if(house){
  7509.      if(house->getPlayerRights(player->getName()) == HOUSE_OWNER){
  7510.               player->sendTextMessage(MSG_ADVANCE, "You own this house.");
  7511.               return;
  7512.      }
  7513.      if(house->isBought()){
  7514.               player->sendTextMessage(MSG_ADVANCE, "This house already has an owner.");
  7515.               return;
  7516.      }
  7517.      if(house->checkHouseCount(player) >= g_config.getGlobalNumber("maxhouses", 0)){
  7518.               std::stringstream textmsg;
  7519.               textmsg << " You cant have more than " << g_config.getGlobalNumber("maxhouses", 1) << " houses ";
  7520.               player->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  7521.               return;
  7522.      }
  7523.      if(house->getPlayerRights(doorPos, player->getName()) == HOUSE_NONE && !house->isBought() && house->checkHouseCount(player) < g_config.getGlobalNumber("maxhouses", 1))
  7524.      {
  7525.      Item *item = dynamic_cast<Item*>(tile->getThingByStackPos(tile->getThingCount()-1));
  7526.      long price = g_config.getGlobalNumber("priceforsqm", 0) * house->getHouseSQM(house->getName());
  7527.  
  7528.       if (item && Item::items[item->getID()].isDoor && price <= money)
  7529.       {
  7530.        player->substractMoney(price);
  7531.        house->setOwner(player->getName());
  7532.        house->save();
  7533.        player->sendTextMessage(MSG_ADVANCE, "You bought a house.");
  7534.        last = true;
  7535.       }
  7536.       else{
  7537.        player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7538.        player->sendTextMessage(MSG_SMALLINFO, "You dont have enough money to buy this house.");
  7539.       }
  7540.      }
  7541.    }
  7542.   }
  7543.  }
  7544. }
  7545. }
  7546.     else if (text == "aleta sio")       // edit guests
  7547.     {
  7548.         Tile* tile = getTile(player->pos);
  7549.         House* house = tile? tile->getHouse() : NULL;
  7550.  
  7551.         if (house && house->getPlayerRights(player->getName()) >= HOUSE_SUBOWNER)
  7552.         {
  7553.             player->sendHouseWindow(house, player->pos, HOUSE_GUEST);
  7554.         }
  7555.         else
  7556.         {
  7557.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7558.             player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7559.         }
  7560.     }
  7561.     else if (text == "aleta som")       // edit subowners
  7562.     {
  7563.         Tile* tile = getTile(player->pos);
  7564.         House* house = tile? tile->getHouse() : NULL;
  7565.  
  7566.         if (house && house->getPlayerRights(player->getName()) == HOUSE_OWNER)
  7567.         {
  7568.             player->sendHouseWindow(house, player->pos, HOUSE_SUBOWNER);
  7569.         }
  7570.         else
  7571.         {
  7572.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7573.             player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7574.         }
  7575.     }
  7576.     else if (text == "alana sio")   // kick me
  7577.     {
  7578.         Tile* tile = getTile(player->pos);
  7579.         House* house = tile? tile->getHouse() : NULL;
  7580.  
  7581.         if (house)
  7582.         {
  7583.             teleport(player, house->getFrontDoor());
  7584.             player->sendMagicEffect(player->pos, NM_ME_ENERGY_AREA);
  7585.         }
  7586.         else
  7587.         {
  7588.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7589.             player->sendTextMessage(MSG_SMALLINFO, "You are not in a house.");
  7590.         }
  7591.     }
  7592.     else if (text.substr(0, 11) == "alana sio \"")  // kick someone
  7593.     {
  7594.         Creature* c = getCreatureByName(text.substr(11).c_str());
  7595.         Player *target = c? dynamic_cast<Player*>(c) : NULL;
  7596.  
  7597.         if (target)
  7598.         {
  7599.             Tile* tile = getTile(player->pos);
  7600.             Tile* targetTile = getTile(target->pos);
  7601.             House* house = tile? tile->getHouse() : NULL;
  7602.             House* targetHouse = targetTile? targetTile->getHouse() : NULL;
  7603.  
  7604.             if (house && targetHouse && house == targetHouse &&
  7605.                 house->getPlayerRights(player->getName()) >= HOUSE_SUBOWNER)
  7606.             {
  7607.                 Position pos = house->getFrontDoor();
  7608.                 if (pos.x != 0xFFFF && pos.y != 0xFFFF && pos.z != 0xFF)
  7609.                 {
  7610.                     teleport(target, pos);
  7611.                     player->sendMagicEffect(target->pos, NM_ME_ENERGY_AREA);
  7612.                 }
  7613.                 else
  7614.                 {
  7615.                     player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7616.                     player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7617.                 }
  7618.             }
  7619.             else
  7620.                 player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7621.         }
  7622.         else
  7623.         {
  7624.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7625.             player->sendTextMessage(MSG_SMALLINFO, "This player does not exist.");
  7626.         }
  7627.     }
  7628. #endif //TLM_HOUSE_SYSTEM
  7629.  
  7630. #ifdef TR_SUMMONS
  7631.     else if (text.substr(0, 11) == "utevo res \"" &&
  7632.         (!g_config.LEARN_SPELLS || player->knowsSpell("utevo res")))
  7633.     {
  7634.         if (player->vocation == VOCATION_DRUID || player->vocation == VOCATION_SORCERER ||
  7635.             (g_config.SUMMONS_ALL_VOC && player->vocation != VOCATION_NONE))
  7636.         {
  7637.             std::string name = text.substr(11);
  7638.             int32_t reqMana = Summons::getRequiredMana(name);
  7639.             Tile* tile = getTile(player->pos);
  7640.  
  7641.             if (!tile)
  7642.             {
  7643.                 player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7644.                 player->sendCancel("Sorry, not possible.");
  7645.             }
  7646.             else if (reqMana < 0)
  7647.             {
  7648.                 player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7649.                 player->sendCancel("You cannot summon this creature.");
  7650.             }
  7651.             else if (tile->isPz())
  7652.             {
  7653.                 player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7654.                 player->sendCancel("You cannot summon creatures in protection zone.");
  7655.             }
  7656. #ifdef YUR_PVP_ARENA
  7657.             else if (tile->isPvpArena())
  7658.             {
  7659.                 player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7660.                 player->sendCancel("You cannot summon creatures on arena.");
  7661.             }
  7662. #endif //YUR_PVP_ARENA
  7663.             else if (player->getSummonCount() >= g_config.MAX_SUMMONS)
  7664.             {
  7665.                 player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7666.                 player->sendCancel("You cannot have more summons.");
  7667.             }
  7668.             else if (player->getMana() < reqMana)
  7669.             {
  7670.                 player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7671.                 player->sendCancel("Not enough mana.");
  7672.             }
  7673.             else if (!placeSummon(player, name))
  7674.             {
  7675.                 player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7676.                 player->sendCancel("Not enough room");
  7677.             }
  7678.             else
  7679.             {
  7680.                 player->mana -= reqMana;
  7681.                 player->addManaSpent(reqMana);
  7682.             }
  7683.         }
  7684.     }
  7685. #endif //TR_SUMMONS
  7686.  
  7687. /*
  7688. #ifdef HUCZU_FIX
  7689.       else if (text == "exevo flam sio" &&
  7690.         (!g_config.LEARN_SPELLS || player->knowsSpell("exevo flam sio")))
  7691.     {
  7692.         const int32_t REQ_MANA = 200;
  7693.    
  7694.         if (player->mana < REQ_MANA)
  7695.         {
  7696.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7697.             player->sendTextMessage(MSG_SMALLINFO, "Not enough mana.");
  7698.         }
  7699.        
  7700.         else if (player->maglevel < 15)
  7701.         {
  7702.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7703.             player->sendTextMessage(MSG_SMALLINFO, "You don't have the required magic level.");
  7704.         }
  7705.        
  7706.         else if (player->exhaustedTicks >= 1000 && player->access < g_config.ACCESS_PROTECT)
  7707.         {
  7708.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7709.             player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");  
  7710.         }
  7711.        
  7712.         else if (player->flamTicks != 0 && player->access < g_config.ACCESS_PROTECT)
  7713.         {
  7714.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7715.             player->sendTextMessage(MSG_SMALLINFO, "Not ready yet.");  
  7716.         }
  7717.  
  7718.         else
  7719.         {
  7720.             player->flamBool = true;
  7721.             player->exhaustedTicks = 2*1000;
  7722.             player->sendMagicEffect(player->pos, NM_ME_MAGIC_BLOOD);
  7723.           }
  7724.        }
  7725. #endif //HUCZU_FIX
  7726. */
  7727.  
  7728. else if (text.substr(0,7) == "exiva \"" &&
  7729. (!g_config.LEARN_SPELLS || player->knowsSpell("exiva")))
  7730. {
  7731. std::string name = text.substr(7);
  7732. Creature *c = getCreatureByName(name);
  7733. if (dynamic_cast<Player*>(c))
  7734. {
  7735. if(player->mana >= 20)
  7736. {
  7737. player->mana -= 20;
  7738. player->addManaSpent(20);
  7739. }
  7740. else if (player->exhaustedTicks >= 1000 && player->access < g_config.ACCESS_PROTECT)
  7741.         {
  7742.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7743.             player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");  
  7744.         }
  7745.      else
  7746. {
  7747. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7748. player->sendTextMessage(MSG_SMALLINFO, "Not enough mana.");
  7749. return;
  7750. }
  7751.  
  7752.  
  7753. int32_t x = c->pos.x - player->pos.x;
  7754. int32_t y = c->pos.y - player->pos.y;
  7755. int32_t z = c->pos.z - player->pos.z;
  7756. std::stringstream position;
  7757. position << name;
  7758.  
  7759. if(c->access < 3) {
  7760.          if((x > 96 && y > 48) || (x > 48 && y > 94) || (x > 74 && y > 74))
  7761.             position << " is very far to the south-east.";
  7762.          else if((x > 96 && y < -48) || (x > 48 && y < -96) || (x > 74 && y < -74))
  7763.             position << " is very far to the north-east.";
  7764.          else if((x < -96 && y > 48) || (x < -48 && y > 96) || (x < -74 && y > 74))
  7765.             position << " is very far to the south-west.";
  7766.          else if((x < -96 && y < -48) || (x < -48 && y < -96) || (x < -74 && y < -74))
  7767.             position << " is very far to the north-west.";
  7768.  
  7769.          else if((x > 48 && y > 24) || (x > 24 && y > 48) || (x > 36 && y > 36))
  7770.             position << " is far to the south-east.";
  7771.          else if((x > 48 && y < -24) || (x > 24 && y < -48) || (x > 36 && y < -36))
  7772.             position << " is far to the north-east.";
  7773.          else if((x < -48 && y > 24) || (x < -24 && y > 48) || (x < -36 && y > 36))
  7774.             position << " is far to the south-west.";
  7775.          else if((x < -48 && y < -24) || (x < -24 && y < -48) || (x < -36 && y < -36))
  7776.             position << " is far to the north-west.";
  7777.  
  7778.          else if((x > 6 && y > 12 && z > 0) || (x > 12 && y > 6 && z > 0) || (x > 9 && y > 9 && z > 0))
  7779.             position << " is on a lower lvl to the south-east.";
  7780.          else if((x > 6 && y < -12 && z > 0) || (x > 12 && y < -6 && z > 0) || (x > 9 && y < -9 && z > 0))
  7781.             position << " is on a lower lvl to the north-east.";
  7782.          else if((x < -6 && y > 12 && z > 0) || (x < -12 && y > 6 && z > 0) || (x < -9 && y > 9 && z > 0))
  7783.             position << " is on a lower lvl to the south-west.";
  7784.          else if((x < -6 && y < -12 && z > 0) || (x < -12 && y < -6 && z > 0) || (x < -9 && y < -9 && z > 0))
  7785.             position << " is on a lower lvl to the north-west.";
  7786.  
  7787.          else if((x > 6 && y > 12 && z < 0) || (x > 12 && y > 6 && z < 0) || (x > 9 && y > 9 && z < 0))
  7788.             position << " is on a higher lvl to the south-east.";
  7789.          else if((x > 6 && y < -12 && z < 0) || (x > 12 && y < -6 && z < 0) || (x > 9 && y < -9 && z < 0))
  7790.             position << " is on a higher lvl to the north-east.";
  7791.          else if((x < -6 && y > 12 && z < 0) || (x < -12 && y > 6 && z < 0) || (x < -9 && y > 9 && z < 0))
  7792.             position << " is on a higher lvl to the south-west.";
  7793.          else if((x < -6 && y < -12 && z < 0) || (x < -12 && y < -6 && z < 0) || (x < -9 && y < -9 && z < 0))
  7794.             position << " is on a higher lvl to the north-west.";
  7795.  
  7796.          else if((x > 6 && y > 12 && z == 0) || (x > 12 && y > 6 && z == 0) || (x > 9 && y > 9 && z == 0))
  7797.             position << " is to the south-east.";
  7798.          else if((x > 6 && y < -12 && z == 0) || (x > 12 && y < -6 && z == 0) || (x > 9 && y < -9 && z == 0))
  7799.             position << " is to the north-east.";
  7800.          else if((x < -6 && y > 12 && z == 0) || (x < -12 && y > 6 && z == 0) || (x < -9 && y > 9 && z == 0))
  7801.             position << " is to the south-west.";
  7802.          else if((x < -6 && y < -12 && z == 0) || (x < -12 && y < -6 && z == 0) || (x < -9 && y < -9 && z == 0))
  7803.             position << " is to the north-west.";
  7804.            
  7805.          else if(x > 74)
  7806.             position << " is very far to the east.";
  7807.          else if(x < -74)
  7808.             position << " is very far to the west.";
  7809.          else if(y > 74)
  7810.             position << " is very far to the south.";
  7811.          else if(y < -74)
  7812.             position << " is very far to the north.";
  7813.  
  7814.          else if(x > 36)
  7815.             position << " is far to the east.";
  7816.          else if(x < -36)
  7817.             position << " is far to the west.";
  7818.          else if(y > 36)
  7819.             position << " is far to the south.";
  7820.          else if(y < -36)
  7821.             position << " is far to the north.";
  7822.  
  7823.          else if(x > 3 && z < 0)
  7824.             position << " is on a higher lvl to the east.";
  7825.          else if(x < -3 && z < 0)
  7826.             position << " is on a higher lvl to the west.";
  7827.          else if(y > 3 && z < 0)
  7828.             position << " is on a higher lvl to the south.";
  7829.          else if(y < -3 && z < 0)
  7830.             position << " is on a higher lvl to the north.";
  7831.  
  7832.          else if(x > 3 && z > 0)
  7833.             position << " is on a lower lvl to the east.";
  7834.          else if(x < -3 && z > 0)
  7835.             position << " is on a lower lvl to the west.";
  7836.          else if(y > 3 && z > 0)
  7837.             position << " is on a lower lvl to the south.";
  7838.          else if(y < -3 && z > 0)
  7839.             position << " is on a lower lvl to the north.";
  7840.  
  7841.          else if(x > 3 && z == 0)
  7842.             position << " is to the east.";
  7843.          else if(x < -3 && z == 0)
  7844.             position << " is to the west.";
  7845.          else if(y > 3 && z == 0)
  7846.             position << " is to the south.";
  7847.          else if(y < -3 && z == 0)
  7848.             position << " is to the north.";
  7849.  
  7850.          else if(x < 4 && y < 4 && z > 0)
  7851.             position << " is below you.";
  7852.          else if(x < 4 && y < 4 && z < 0)
  7853.             position << " is above you.";
  7854.          else
  7855.             position << " is just beside you.";
  7856.  
  7857. player->sendTextMessage(MSG_INFO, position.str().c_str());
  7858. player->sendMagicEffect(player->pos, NM_ME_MAGIC_ENERGIE);
  7859. }else{
  7860. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7861. player->sendTextMessage(MSG_SMALLINFO, "Srry, you cant exiva GM's");
  7862.     }
  7863. }else
  7864. player->sendTextMessage(MSG_SMALLINFO, "This player is not online.");
  7865. }
  7866.  
  7867.     else if (text == "exani tera" &&
  7868.         (!g_config.LEARN_SPELLS || player->knowsSpell("exani tera")))
  7869.     {
  7870.         const int32_t REQ_MANA = 20;
  7871.         Tile* tile = getTile(player->pos);
  7872.    
  7873.         if (!(tile && (tile->ground->getID() == ITEM_ROPE_SPOT1 || tile->ground->getID() == ITEM_ROPE_SPOT2)))
  7874.         {
  7875.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7876.             player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7877.         }
  7878.         else if (player->mana < REQ_MANA)
  7879.         {
  7880.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7881.             player->sendTextMessage(MSG_SMALLINFO, "Not enough mana.");
  7882.         }
  7883.         else if (player->maglevel < 0)
  7884.         {
  7885.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7886.             player->sendTextMessage(MSG_SMALLINFO, "You don't have the required magic level.");
  7887.         }
  7888.         else if (player->exhaustedTicks >= 1000 && player->access < g_config.ACCESS_PROTECT)
  7889.         {
  7890.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7891.             player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");  
  7892.         }
  7893.         else
  7894.         {
  7895.             teleport(player, Position(player->pos.x, player->pos.y+1, player->pos.z-1));
  7896.             player->sendMagicEffect(player->pos, NM_ME_ENERGY_AREA);
  7897.  
  7898.             if (player->access < g_config.ACCESS_PROTECT)
  7899.             {
  7900.                 player->mana -= REQ_MANA;
  7901.                 player->addManaSpent(REQ_MANA);
  7902.             }
  7903.         }
  7904.     }
  7905. }
  7906.    
  7907. #ifdef TR_SUMMONS
  7908. bool Game::placeSummon(Player* p, const std::string& name)
  7909. {
  7910.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::placeSummon()");
  7911.     Monster* monster = Monster::createMonster(name, this);
  7912.  
  7913.     if(!monster)
  7914.         return false;
  7915.  
  7916.     Position pos = p->pos;
  7917.     switch (p->direction)
  7918.     {
  7919.         case NORTH: pos.y--; break;
  7920.         case SOUTH: pos.y++; break;
  7921.         case EAST: pos.x++; break;
  7922.         case WEST: pos.x--; break;
  7923.     }
  7924.  
  7925.     Tile* tile = getTile(pos);
  7926. #ifdef YUR_PVP_ARENA
  7927.     if (!tile || tile->isPz() || tile->isPvpArena() || !placeCreature(pos, monster))
  7928. #else
  7929.     if (!tile || tile->isPz() || !placeCreature(pos, monster))
  7930. #endif //YUR_PVP_ARENA
  7931.     {
  7932.         delete monster;
  7933.         return false;
  7934.     }
  7935.     else
  7936.     {
  7937.         p->addSummon(monster);
  7938.         return true;
  7939.     }
  7940. }
  7941. #endif //TR_SUMMONS
  7942.  
  7943.  
  7944. #ifdef TRS_GM_INVISIBLE
  7945. void Game::creatureBroadcastTileUpdated(const Position& pos)
  7946. {
  7947.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureBroadcastTileUpdated()");
  7948.     SpectatorVec list;
  7949.     SpectatorVec::iterator it;
  7950.     getSpectators(Range(pos, true), list);
  7951.  
  7952.     //players
  7953.     for(it = list.begin(); it != list.end(); ++it) {
  7954.         if(dynamic_cast<Player*>(*it)) {
  7955.             (*it)->onTileUpdated(pos);
  7956.         }
  7957.     }
  7958.  
  7959.     //none-players
  7960.     for(it = list.begin(); it != list.end(); ++it) {
  7961.         if(!dynamic_cast<Player*>(*it)) {
  7962.             (*it)->onTileUpdated(pos);
  7963.         }
  7964.     }
  7965. }
  7966. #endif //TRS_GM_INVISIBLE
  7967.  
  7968.  
  7969. #ifdef HUCZU_SKULLS
  7970. void Game::Skull(Player* player)
  7971. {
  7972.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::Skull()");
  7973.     if (player)
  7974.     {
  7975.         SpectatorVec list;
  7976.         SpectatorVec::iterator it;
  7977.         getSpectators(Range(player->pos, true), list);
  7978.  
  7979.         for(it = list.begin(); it != list.end(); ++it)
  7980.         {
  7981.             Player* spectator = dynamic_cast<Player*>(*it);
  7982.             if(spectator)
  7983.                 if(player->skullType == SKULL_NONE ||
  7984.                         player->skullType == SKULL_WHITE ||
  7985.                         player->skullType == SKULL_RED ||
  7986.                         player->skullType == SKULL_YELLOW && player->isYellowTo(spectator))
  7987.                     spectator->onSkull(player);
  7988.         }
  7989.     }
  7990. }
  7991.  
  7992. void Game::onPvP(Creature* creature, Creature* attacked, bool murder)
  7993. {
  7994.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::onPvP()");
  7995.     if (creature && creature->getMaster())
  7996.         creature = creature->getMaster();   // pk-ing with summons fix
  7997.        
  7998.     Player* player = dynamic_cast<Player*>(creature);
  7999.     Player* attackedPlayer = dynamic_cast<Player*>(attacked);
  8000.  
  8001.     if (player == attackedPlayer)
  8002.         return;
  8003.     if(!player || !attackedPlayer)
  8004.         return;
  8005.     if (player && player->access >= g_config.ACCESS_PROTECT || attackedPlayer && attackedPlayer->access >= g_config.ACCESS_PROTECT)
  8006.         return;
  8007.     if (player->party != 0 && attackedPlayer->party != 0 && player->party == attackedPlayer->party)
  8008.         return;
  8009.        
  8010.     Tile *p1 = map->getTile(player->pos), *p2 = map->getTile(attackedPlayer->pos);
  8011.     if (p1->isPvpArena() && p2->isPvpArena()){
  8012.          player->pzLocked = false;
  8013.          attackedPlayer->pzLocked = false;
  8014.         return;
  8015.     }
  8016.  
  8017.  
  8018.     player->pzLocked = true;
  8019.  
  8020.     if (!murder)
  8021.     {
  8022.         if(!player->hasAttacked(attackedPlayer)){
  8023.         player->attackedPlayers.push_back(attackedPlayer);
  8024.         }
  8025.        
  8026.     if (attackedPlayer->skullType == SKULL_NONE || attackedPlayer->skullType == SKULL_YELLOW && !attackedPlayer->isYellowTo(player))
  8027.         {    
  8028.             if (player->skullType != SKULL_RED && player->skullType != SKULL_WHITE)
  8029.             {
  8030.                 player->skullType = SKULL_WHITE;
  8031.                 Skull(player);
  8032.             }  
  8033.         }
  8034.        
  8035.         else if(attackedPlayer->skullType == SKULL_WHITE || attackedPlayer->skullType == SKULL_RED)
  8036.         {
  8037.             if(player->skullType == SKULL_NONE && !player->isYellowTo(attackedPlayer))//si no tiene skull y no es yellow, tenemos que ponerle yellow.
  8038.             {
  8039.                     if(!attackedPlayer->hasAttacked(player))
  8040.                     {
  8041.                     player->skullType = SKULL_YELLOW;
  8042.                     attackedPlayer->hasAsYellow.push_back(player);
  8043.                     attackedPlayer->onSkull(player);
  8044.                  }
  8045.             }
  8046.         }
  8047.         if(player->inFightTicks < (int32_t)g_config.PZ_LOCKED)
  8048.             player->inFightTicks = (int32_t)g_config.PZ_LOCKED;
  8049.         if(player->skullTicks < (int32_t)g_config.PZ_LOCKED)
  8050.             player->skullTicks = (int32_t)g_config.PZ_LOCKED;
  8051.        
  8052.     }
  8053.     else    // murder
  8054.     {
  8055.         if (attackedPlayer->skullType == SKULL_NONE || (attackedPlayer->skullType == SKULL_YELLOW && !player->isYellowTo(attackedPlayer))) //Ofiara nie miala skulla oraz miala yellow ale nie na graczu ktora go zabil.
  8056.         {
  8057.             player->skullKills++;
  8058.             std::string justice(std::string("Warning! The murder of ") + attackedPlayer->getName() + " was not justified!");
  8059.             player->sendTextMessage(MSG_RED_INFO, justice.c_str());
  8060.              
  8061.                 if (player->skullKills >= g_config.BAN_UNJUST)
  8062.                 {
  8063.                     banPlayer(player, "Excessive unjustifed player killing", "AccountBan", "Zagan Square 2.3 2011 (Braviera)", false);
  8064.                 }
  8065.                
  8066.                 if (player->skullKills >= g_config.RED_UNJUST)
  8067.                 {
  8068.                     player->skullType = SKULL_RED;
  8069.                     if(player->skullTicks < g_config.RED_TIME)
  8070.                         player->skullTicks = g_config.RED_TIME;
  8071.                     if(player->inFightTicks < g_config.WHITE_TIME)
  8072.                         player->inFightTicks = g_config.WHITE_TIME;
  8073.                     Skull(player);
  8074.                 }
  8075.                 else
  8076.                 {
  8077.                     player->skullType = SKULL_WHITE;
  8078.                     if(player->skullTicks < g_config.WHITE_TIME)
  8079.                         player->skullTicks = g_config.WHITE_TIME;
  8080.                     if(player->inFightTicks < g_config.WHITE_TIME)
  8081.                         player->inFightTicks = g_config.WHITE_TIME;
  8082.                     Skull(player);
  8083.                 }
  8084.         }
  8085.            
  8086.             else if (attackedPlayer->skullType == SKULL_RED)//victim had red skull..(fair kill)
  8087.             {
  8088.                       if(player->inFightTicks < g_config.WHITE_TIME)
  8089.                       player->inFightTicks = g_config.WHITE_TIME;//not giving him a skull.. just setting the murder time.
  8090.             }
  8091.            
  8092.             else if (attackedPlayer->skullType == SKULL_WHITE) //victim had white skull.. (fair kill)
  8093.             {
  8094.                     attackedPlayer->skullType = SKULL_NONE;
  8095.                     attackedPlayer->skullTicks = 0;
  8096.                     Skull(attackedPlayer);
  8097.                     if(player->inFightTicks < g_config.WHITE_TIME)
  8098.                     player->inFightTicks = g_config.WHITE_TIME;//not giving him a skull.. just setting the murder time.
  8099.             }
  8100.            
  8101.            else if (attackedPlayer->skullType == SKULL_YELLOW /*&& attackedPlayer->isYellowTo(player)*/)//el que murio era yellow skull para el que lo mato.
  8102.            {
  8103.             attackedPlayer->skullType = SKULL_NONE;
  8104.             attackedPlayer->skullTicks = 0;
  8105.             attackedPlayer->inFightTicks = 0;
  8106.             Skull(attackedPlayer);
  8107.                 if(player->inFightTicks < g_config.WHITE_TIME)
  8108.                    player->inFightTicks = g_config.WHITE_TIME;
  8109.             }
  8110.         //attackedPlayer->clearAttacked();//czyszczenie listy zaatakowanych
  8111.         //player->removeFromYellowList(attackedPlayer);//usuwanie gracza z Yellow skull z listy atakowanych z ys
  8112.         //attackedPlayer->removeFromYellowList(player);
  8113.         }
  8114.     }
  8115.  
  8116. void Game::LeaveParty(Player *player)
  8117. {
  8118.     int32_t members = 0;
  8119.     std::stringstream bericht1;
  8120.     bericht1 << player->getName() << " has left the party";
  8121.     if(player->getID() == player->party)
  8122.     {
  8123.         disbandParty(player->party);
  8124.         return;
  8125.     }
  8126.     for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  8127.     {
  8128.         if((*it).second->party == player->party)
  8129.         {
  8130.             members++;
  8131.             if((*it).second->getID() != player->getID())
  8132.                 (*it).second->sendTextMessage(MSG_INFO, bericht1.str().c_str());
  8133.             (*it).second->onPartyIcons(player, 0, false, true);
  8134.             player->onPartyIcons((*it).second, 0, false, true);
  8135.         }
  8136.     }
  8137.     if(members <= 2)
  8138.     {
  8139.         disbandParty(player->party);
  8140.         return;
  8141.     }
  8142.     player->sendTextMessage(MSG_INFO, "You have left the party.");
  8143.     player->party = 0;
  8144. }
  8145.  
  8146. void Game::disbandParty(uint32_t partyID)
  8147. {
  8148.     for(AutoList<Player>::listiterator cit = Player::listPlayer.list.begin(); cit != Player::listPlayer.list.end(); ++cit)
  8149.     {
  8150.         if((*cit).second->party == partyID)
  8151.         {
  8152.             (*cit).second->party = 0;
  8153.             for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  8154.             {
  8155.                 (*cit).second->onPartyIcons((*it).second, 0, false, true);
  8156.                  if((*it).second->skullType == SKULL_NONE ||
  8157.                  (*it).second->skullType == SKULL_WHITE ||
  8158.                  (*it).second->skullType == SKULL_RED ||
  8159.                  (*it).second->skullType == SKULL_YELLOW &&
  8160.                  (*it).second->isYellowTo((*cit).second))
  8161.                 (*cit).second->onSkull((*it).second);
  8162.             }
  8163.             (*cit).second->sendTextMessage(MSG_INFO, "Your party has been disbanded.");
  8164.         }
  8165.     }
  8166. }
  8167. void Game::checkSkullTime(Player* player)
  8168. {
  8169.     if(player->skullType == SKULL_NONE)//just in case
  8170.     return;
  8171.    
  8172.     if(player->skullTicks < player->inFightTicks)
  8173.     player->skullTicks = player->inFightTicks;
  8174.    
  8175.     if(player->skullType != SKULL_RED && player->skullTicks > player->inFightTicks) //we don't want to do that if the player has a red skull...
  8176.     player->inFightTicks = player->skullTicks;
  8177.  
  8178. }    
  8179. #endif //HUCZU_SKULLS
  8180.  
  8181.  
  8182.  
  8183. #ifdef SD_BURST_ARROW
  8184. class MagicEffectAreaNoExhaustionClass: public MagicEffectAreaClass {
  8185. public:
  8186.     bool causeExhaustion(bool hasTarget) const { return false; }
  8187. };
  8188.  
  8189. void Game::burstArrow(Creature* c, const Position& pos)
  8190. {
  8191.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::burstArrow()");
  8192.     std::vector<unsigned char> col;
  8193.     MagicEffectAreaNoExhaustionClass runeAreaSpell;
  8194.    
  8195.     Player* player = dynamic_cast<Player*>(c);
  8196.  
  8197.     runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8198.     runeAreaSpell.animationEffect = NM_ANI_BURSTARROW;
  8199.     runeAreaSpell.hitEffect = NM_ME_EXPLOSION_DAMAGE;
  8200.     runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8201.     runeAreaSpell.animationColor = 198; //DAMAGE_FIRE;
  8202.     runeAreaSpell.drawblood = true;
  8203.     runeAreaSpell.offensive = true;
  8204.  
  8205.     /* Area of Spell */
  8206.     col.push_back(1);
  8207.     col.push_back(1);
  8208.     col.push_back(1);
  8209.     runeAreaSpell.areaVec.push_back(col);
  8210.     col.clear();
  8211.     col.push_back(1);
  8212.     col.push_back(1);
  8213.     col.push_back(1);
  8214.     runeAreaSpell.areaVec.push_back(col);
  8215.     col.clear();
  8216.     col.push_back(1);
  8217.     col.push_back(1);
  8218.     col.push_back(1);
  8219.     runeAreaSpell.areaVec.push_back(col);
  8220.  
  8221.     /* hard no ? */
  8222.     runeAreaSpell.direction = 1;
  8223.    
  8224.     if (player->vocation == VOCATION_KNIGHT) {
  8225.     runeAreaSpell.minDamage = int32_t(((c->level*g_config.KNIGHT_BURST_DMG_LVL)+(c->maglevel*g_config.KNIGHT_BURST_DMG_MLVL))*g_config.KNIGHT_BURST_DMG_LO);
  8226.     runeAreaSpell.maxDamage = int32_t(((c->level*g_config.KNIGHT_BURST_DMG_LVL)+(c->maglevel*g_config.KNIGHT_BURST_DMG_MLVL))*g_config.KNIGHT_BURST_DMG_HI);
  8227.     }
  8228.    
  8229.     if (player->vocation == VOCATION_PALADIN) {
  8230.     runeAreaSpell.minDamage = int32_t(((c->level*g_config.PALADIN_BURST_DMG_LVL)+(c->maglevel*g_config.PALADIN_BURST_DMG_MLVL))*g_config.PALADIN_BURST_DMG_LO);
  8231.     runeAreaSpell.maxDamage = int32_t(((c->level*g_config.PALADIN_BURST_DMG_LVL)+(c->maglevel*g_config.PALADIN_BURST_DMG_MLVL))*g_config.PALADIN_BURST_DMG_HI);
  8232.     }
  8233.    
  8234.     if (player->vocation == VOCATION_DRUID) {
  8235.     runeAreaSpell.minDamage = int32_t(((c->level*g_config.DRUID_BURST_DMG_LVL)+(c->maglevel*g_config.DRUID_BURST_DMG_MLVL))*g_config.DRUID_BURST_DMG_LO);
  8236.     runeAreaSpell.maxDamage = int32_t(((c->level*g_config.DRUID_BURST_DMG_LVL)+(c->maglevel*g_config.DRUID_BURST_DMG_MLVL))*g_config.DRUID_BURST_DMG_HI);
  8237.     }
  8238.    
  8239.     if (player->vocation == VOCATION_SORCERER) {
  8240.     runeAreaSpell.minDamage = int32_t(((c->level*g_config.SORCERER_BURST_DMG_LVL)+(c->maglevel*g_config.SORCERER_BURST_DMG_MLVL))*g_config.SORCERER_BURST_DMG_LO);
  8241.     runeAreaSpell.maxDamage = int32_t(((c->level*g_config.SORCERER_BURST_DMG_LVL)+(c->maglevel*g_config.SORCERER_BURST_DMG_MLVL))*g_config.SORCERER_BURST_DMG_HI);
  8242.     }
  8243.    
  8244.     creatureThrowRune(c, pos, runeAreaSpell);
  8245. }
  8246. #endif //SD_BURST_ARROW
  8247.  
  8248.  
  8249. #ifdef YUR_SHUTDOWN
  8250. void Game::sheduleShutdown(int32_t minutes)
  8251. {
  8252.     if (minutes > 0)
  8253.         checkShutdown(minutes);
  8254. }
  8255.  
  8256. void Game::checkShutdown(int32_t minutes)
  8257. {
  8258.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkShutdown()");
  8259.     if (minutes == 0)
  8260.     {
  8261.         setGameState(GAME_STATE_CLOSED);
  8262.         while (!Player::listPlayer.list.empty())
  8263.             Player::listPlayer.list.begin()->second->kickPlayer();
  8264.  
  8265.         serverSave();
  8266.         std::cout << "==| shutdown..." << std::endl;
  8267.         //setGameState(GAME_STATE_SHUTDOWN);
  8268.         OTSYS_SLEEP(1000);
  8269.         exit(1);
  8270.     }
  8271.     else
  8272.     {
  8273.         std::stringstream msg;
  8274.         msg << "Server going to shutdown in " << minutes << (minutes>1? " minutes. \n Please logout." : " minute. \n Please logout.") << std::ends;
  8275.  
  8276.         AutoList<Player>::listiterator it = Player::listPlayer.list.begin();
  8277.         while (it != Player::listPlayer.list.end())
  8278.         {
  8279.             (*it).second->sendTextMessage(MSG_RED_INFO, msg.str().c_str());
  8280.             ++it;
  8281.         }
  8282.  
  8283.         addEvent(makeTask(60000, boost::bind(&Game::checkShutdown, this, minutes - 1)));
  8284.     }
  8285. }
  8286. #endif //YUR_SHUTDOWN
  8287.  
  8288.  
  8289. #ifdef YUR_CMD_EXT
  8290. void Game::setMaxPlayers(uint32_t newmax)
  8291. {
  8292.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::setMaxPlayers()");
  8293.     max_players = newmax;
  8294.     Status::instance()->playersmax = newmax;
  8295. }
  8296. #endif //YUR_CMD_EXT
  8297.  
  8298. long Game::cleanMap()
  8299. {
  8300. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::cleanMap()");
  8301. return map->clean();
  8302. }
  8303.  
  8304. long Game::beforeClean()
  8305. {
  8306. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it) {
  8307. it->second->sendTextMessage(MSG_RED_INFO, "1 minute to clean. Get your things from floor now!");
  8308. }
  8309. addEvent(makeTask(60000, std::mem_fun(&Game::secondsToClean)));
  8310. }
  8311. long Game::beforeCleanTrzy()
  8312. {
  8313. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it) {
  8314. it->second->sendTextMessage(MSG_RED_INFO, "Warning! Clean in 3 minutes.");
  8315. }
  8316. addEvent(makeTask(60000, std::mem_fun(&Game::beforeCleanDwa)));
  8317. }
  8318. long Game::beforeCleanDwa()
  8319. {
  8320. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it) {
  8321. it->second->sendTextMessage(MSG_RED_INFO, "Warning! Clean in 2 minutes.");
  8322. }
  8323. addEvent(makeTask(60000, std::mem_fun(&Game::beforeClean)));
  8324. }
  8325. void Game::secondsToClean()
  8326. {
  8327.    autocleanMap(5);
  8328. }
  8329. void Game::autocleanMap(int32_t seconds)
  8330. {
  8331.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::autocleanMap()");
  8332.     if (seconds == 0)
  8333.     {
  8334.        std::cout << ":: auto clean... ";
  8335.        timer();
  8336.        long count = cleanMap();
  8337.        double sec = timer();
  8338.  
  8339.        std::stringstream msg;
  8340.        msg << "Clean completed. Collected " << count << (count==1? " item." : " items.") << std::ends;
  8341.        for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  8342.        if(dynamic_cast<Player*>(it->second))
  8343.        (*it).second->sendTextMessage(MSG_RED_INFO, msg.str().c_str());
  8344.        }
  8345.  
  8346.        std::cout << "ok (" << timer() << "s)" << std::endl;
  8347.        addEvent(makeTask((g_config.getGlobalNumber("autoclean", 2))*60000, std::mem_fun(&Game::beforeCleanTrzy)));
  8348.     }
  8349.     else
  8350.     {
  8351.         std::stringstream msg;
  8352.         msg << "Clean in " << seconds << std::ends;
  8353.  
  8354.         AutoList<Player>::listiterator it = Player::listPlayer.list.begin();
  8355.         while (it != Player::listPlayer.list.end())
  8356.         {
  8357.             (*it).second->sendTextMessage(MSG_RED_INFO, msg.str().c_str());
  8358.             ++it;
  8359.         }
  8360.  
  8361.         addEvent(makeTask(8000, boost::bind(&Game::autocleanMap, this, seconds - 1)));
  8362.     }
  8363. }
  8364.  
  8365.  
  8366. #ifdef CVS_DAY_CYCLE
  8367. void Game::creatureChangeLight(Player* player, int32_t time, unsigned char lightlevel, unsigned char lightcolor)
  8368. {
  8369.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureChangeLight()");
  8370.  
  8371.     player->setLightLevel(lightlevel, lightcolor);
  8372.     SpectatorVec list;
  8373.     getSpectators(Range(player->pos), list);
  8374.  
  8375.     for (SpectatorVec::iterator iter = list.begin(); iter != list.end(); ++iter)
  8376.     {
  8377.         Player* spectator = dynamic_cast<Player*>(*iter);
  8378.         if (spectator)
  8379.              spectator->sendPlayerLightLevel(player);
  8380.     }
  8381. }
  8382.  
  8383. void Game::checkLight(int32_t t)
  8384. {
  8385.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkLight()");
  8386.     addEvent(makeTask(10000, boost::bind(&Game::checkLight, this, 10000)));
  8387.    
  8388.     light_hour = light_hour + light_hour_delta;
  8389.     if(light_hour > 1440)
  8390.         light_hour = light_hour - 1440;
  8391.    
  8392.     if(std::abs(light_hour - SUNRISE) < 2*light_hour_delta){
  8393.         light_state = LIGHT_STATE_SUNRISE;
  8394.     }
  8395.     else if(std::abs(light_hour - SUNSET) < 2*light_hour_delta){
  8396.         light_state = LIGHT_STATE_SUNSET;
  8397.     }
  8398.    
  8399.     int32_t newlightlevel = lightlevel;
  8400.     switch(light_state){
  8401.     case LIGHT_STATE_SUNRISE:
  8402.         newlightlevel += (LIGHT_LEVEL_DAY - LIGHT_LEVEL_NIGHT)/30;
  8403.         break;
  8404.     case LIGHT_STATE_SUNSET:
  8405.         newlightlevel -= (LIGHT_LEVEL_DAY - LIGHT_LEVEL_NIGHT)/30;
  8406.         break;
  8407.     }
  8408.    
  8409.     if(newlightlevel <= LIGHT_LEVEL_NIGHT){
  8410.         lightlevel = LIGHT_LEVEL_NIGHT;
  8411.         light_state = LIGHT_STATE_NIGHT;
  8412.     }
  8413.     else if(newlightlevel >= LIGHT_LEVEL_DAY){
  8414.         lightlevel = LIGHT_LEVEL_DAY;
  8415.         light_state = LIGHT_STATE_DAY;
  8416.     }
  8417.     else{
  8418.         lightlevel = newlightlevel;
  8419.     }
  8420.  
  8421.  
  8422.     // status, ten kod i tak jest brzydki
  8423.     uint64_t time = OTSYS_TIME();
  8424.     ofstream file;
  8425.     file.open ("status");
  8426.     file << time << " " << (time - Status::instance()->start)/1000 <<  " " << Status::instance()->playersonline << " " << Status::instance()->playersmax;
  8427.     file.close();
  8428.  
  8429.     file.open("online");
  8430.     for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  8431.             std::string txt = (*it).second->getName();
  8432.         file << (*it).second->getName() << ";" << (*it).second->getLevel() << "\n";
  8433.     }
  8434.     file.close();
  8435.  
  8436.    
  8437. }
  8438.  
  8439. unsigned char Game::getLightLevel(){
  8440.     return lightlevel;
  8441. }
  8442. #endif //CVS_DAY_CYCLE
  8443.  
  8444.  
  8445. #ifdef WANDS_JIDDO
  8446. void Game::useWand(Creature *creature, Creature *attackedCreature, int32_t wandid) {
  8447.    
  8448.    Player *player = dynamic_cast<Player*>(creature);
  8449.    if(!player) return;
  8450.    
  8451.      if((wandid == 5318 && (player->vocation == VOCATION_DRUID) && player->mana >= 15 && player->getLevel() >= 65)) { //Quagmire rod
  8452.       int32_t dist = 6;
  8453.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8454.       std::vector<unsigned char> col;
  8455.       MagicEffectAreaClass runeAreaSpell;
  8456.       runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8457.       runeAreaSpell.animationEffect = NM_ANI_SNOWBALL;
  8458.       runeAreaSpell.hitEffect = NM_ME_LOOSE_ENERGY;
  8459.       runeAreaSpell.areaEffect = NM_ME_DRAW_BLOOD;
  8460.       runeAreaSpell.animationColor = 0x47;
  8461.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8462.       col.push_back(0);
  8463.       col.push_back(0);
  8464.       col.push_back(0);
  8465.       runeAreaSpell.areaVec.push_back(col);
  8466.       col.clear();
  8467.       col.push_back(0);
  8468.       col.push_back(1);
  8469.       col.push_back(0);
  8470.       runeAreaSpell.areaVec.push_back(col);
  8471.       col.clear();
  8472.       col.push_back(0);
  8473.       col.push_back(0);
  8474.       col.push_back(0);
  8475.       runeAreaSpell.areaVec.push_back(col);
  8476.       col.clear();
  8477.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 70;   runeAreaSpell.maxDamage = 150;
  8478.       long tempExhaust = player->exhaustedTicks;
  8479. player->exhaustedTicks = 0;
  8480. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8481. player->exhaustedTicks = tempExhaust;
  8482.       int32_t mana = 15;
  8483.       player->addManaSpent(mana);
  8484.       player->mana -= mana;
  8485.       return;
  8486.    }
  8487.    
  8488.    
  8489.    if((wandid == 5319 && (player->vocation == VOCATION_SORCERER) && player->mana >= 15 && player->getLevel() >= 65)) { //Wand of cosmic energy
  8490.       int32_t dist = 6;
  8491.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8492.       std::vector<unsigned char> col;
  8493.       MagicEffectAreaClass runeAreaSpell;
  8494.       runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8495.       runeAreaSpell.animationEffect = NM_ANI_LARGEROCK;
  8496.       runeAreaSpell.hitEffect = NM_ME_SOUND_WHITE;
  8497.       runeAreaSpell.areaEffect = NM_ME_SOUND_WHITE;
  8498.       runeAreaSpell.animationColor = 0xAC;
  8499.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8500.       col.push_back(0);
  8501.       col.push_back(0);
  8502.       col.push_back(0);
  8503.       runeAreaSpell.areaVec.push_back(col);
  8504.       col.clear();
  8505.       col.push_back(0);
  8506.       col.push_back(1);
  8507.       col.push_back(0);
  8508.       runeAreaSpell.areaVec.push_back(col);
  8509.       col.clear();
  8510.       col.push_back(0);
  8511.       col.push_back(0);
  8512.       col.push_back(0);
  8513.       runeAreaSpell.areaVec.push_back(col);
  8514.       col.clear();
  8515.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 70;   runeAreaSpell.maxDamage = 150;
  8516.             long tempExhaust = player->exhaustedTicks;
  8517. player->exhaustedTicks = 0;
  8518. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8519. player->exhaustedTicks = tempExhaust;
  8520.       int32_t mana = 15;
  8521.       player->addManaSpent(mana);
  8522.       player->mana -= mana;
  8523.       return;
  8524.    }
  8525.    
  8526.    //SCEPTRE OF THE LOST SOULS
  8527.    if((wandid == 5326 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_DRUID) && player->mana >= 50 && player->getLevel() >= 300)) {
  8528.       int32_t dist = 4;
  8529.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8530.       std::vector<unsigned char> col;
  8531.       MagicEffectAreaClass runeAreaSpell;
  8532. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8533. runeAreaSpell.animationEffect = NM_ANI_ENERGY2;
  8534.       runeAreaSpell.hitEffect = NM_ME_ENERGY_AREA;
  8535.       runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8536.       runeAreaSpell.animationColor = 0x65;
  8537.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8538.       col.push_back(0);
  8539.       col.push_back(0);
  8540.       col.push_back(0);
  8541.       runeAreaSpell.areaVec.push_back(col);
  8542.       col.clear();
  8543.       col.push_back(0);
  8544.       col.push_back(1);
  8545.       col.push_back(0);
  8546.       runeAreaSpell.areaVec.push_back(col);
  8547.       col.clear();
  8548.       col.push_back(0);
  8549.       col.push_back(0);
  8550.       col.push_back(0);
  8551.       runeAreaSpell.areaVec.push_back(col);
  8552.       col.clear();
  8553.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 350;   runeAreaSpell.maxDamage = 450;
  8554.       long tempExhaust = player->exhaustedTicks;
  8555. player->exhaustedTicks = 0;
  8556. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8557. player->exhaustedTicks = tempExhaust;
  8558.       int32_t mana = 50;
  8559.       player->addManaSpent(mana);
  8560.       player->mana -= mana;
  8561.       return;
  8562.    }
  8563.    
  8564.       //NATURE WAND
  8565.       if((wandid == 2544 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_DRUID) && player->mana >= 35 && player->getLevel() >= 200)) {
  8566.       int32_t dist = 5;
  8567.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8568.       std::vector<unsigned char> col;
  8569.       MagicEffectAreaClass runeAreaSpell;
  8570. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8571. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8572.       runeAreaSpell.hitEffect = 20;
  8573.       runeAreaSpell.areaEffect = 20;
  8574.       runeAreaSpell.animationColor = 0x60;
  8575.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8576.       col.push_back(0);
  8577.       col.push_back(0);
  8578.       col.push_back(0);
  8579.       runeAreaSpell.areaVec.push_back(col);
  8580.       col.clear();
  8581.       col.push_back(0);
  8582.       col.push_back(1);
  8583.       col.push_back(0);
  8584.       runeAreaSpell.areaVec.push_back(col);
  8585.       col.clear();
  8586.       col.push_back(0);
  8587.       col.push_back(0);
  8588.       col.push_back(0);
  8589.       runeAreaSpell.areaVec.push_back(col);
  8590.       col.clear();
  8591.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 200;   runeAreaSpell.maxDamage = 350;
  8592.       long tempExhaust = player->exhaustedTicks;
  8593. player->exhaustedTicks = 0;
  8594. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8595. player->exhaustedTicks = tempExhaust;
  8596.       int32_t mana = 35;
  8597.       player->addManaSpent(mana);
  8598.       player->mana -= mana;
  8599.       return;
  8600.    }
  8601.    
  8602.    //SPRITE WAND
  8603.    if((wandid == 2453 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_DRUID) && player->mana >= 25 && player->getLevel() >= 150)) {
  8604.       int32_t dist = 5;
  8605.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8606.       std::vector<unsigned char> col;
  8607.       MagicEffectAreaClass runeAreaSpell;
  8608. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8609. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8610. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8611. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8612. runeAreaSpell.animationColor = 0x11;
  8613.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8614.       col.push_back(0);
  8615.       col.push_back(0);
  8616.       col.push_back(0);
  8617.       runeAreaSpell.areaVec.push_back(col);
  8618.       col.clear();
  8619.       col.push_back(0);
  8620.       col.push_back(1);
  8621.       col.push_back(0);
  8622.       runeAreaSpell.areaVec.push_back(col);
  8623.       col.clear();
  8624.       col.push_back(0);
  8625.       col.push_back(0);
  8626.       col.push_back(0);
  8627.       runeAreaSpell.areaVec.push_back(col);
  8628.       col.clear();
  8629.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 150;   runeAreaSpell.maxDamage = 250;
  8630.       long tempExhaust = player->exhaustedTicks;
  8631. player->exhaustedTicks = 0;
  8632. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8633. player->exhaustedTicks = tempExhaust;
  8634.       int32_t mana = 25;
  8635.       player->addManaSpent(mana);
  8636.       player->mana -= mana;
  8637.       return;
  8638.    }
  8639.    
  8640.    
  8641.    if((wandid == 2181 && (player->vocation == VOCATION_DRUID) && player->mana >= 8 && player->getLevel() >= 26)) { //Quagmire rod
  8642.       int32_t dist = 2;
  8643.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8644.       std::vector<unsigned char> col;
  8645.       MagicEffectAreaClass runeAreaSpell;
  8646.       runeAreaSpell.attackType = ATTACK_POISON;
  8647.       runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8648.       runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  8649.       runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  8650.       runeAreaSpell.animationColor = 0x60;
  8651.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8652.       col.push_back(0);
  8653.       col.push_back(0);
  8654.       col.push_back(0);
  8655.       runeAreaSpell.areaVec.push_back(col);
  8656.       col.clear();
  8657.       col.push_back(0);
  8658.       col.push_back(1);
  8659.       col.push_back(0);
  8660.       runeAreaSpell.areaVec.push_back(col);
  8661.       col.clear();
  8662.       col.push_back(0);
  8663.       col.push_back(0);
  8664.       col.push_back(0);
  8665.       runeAreaSpell.areaVec.push_back(col);
  8666.       col.clear();
  8667.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 40;   runeAreaSpell.maxDamage = 50;
  8668.       long tempExhaust = player->exhaustedTicks;
  8669. player->exhaustedTicks = 0;
  8670. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8671. player->exhaustedTicks = tempExhaust;
  8672.       int32_t mana = 8;
  8673.       player->addManaSpent(mana);
  8674.       player->mana -= mana;
  8675.       return;
  8676.    }
  8677.      
  8678.      if((wandid == 2182 && (player->vocation == VOCATION_DRUID) && player->mana >= 2 && player->getLevel() >= 7)) { //Snakebite rod
  8679.       int32_t dist = 4;
  8680.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8681.       std::vector<unsigned char> col;
  8682.       MagicEffectAreaClass runeAreaSpell;
  8683.       runeAreaSpell.attackType = ATTACK_POISON;
  8684.       runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8685.       runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  8686.       runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  8687.       runeAreaSpell.animationColor = 0x60;
  8688.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8689.       col.push_back(0);
  8690.       col.push_back(0);
  8691.       col.push_back(0);
  8692.       runeAreaSpell.areaVec.push_back(col);
  8693.       col.clear();
  8694.       col.push_back(0);
  8695.       col.push_back(1);
  8696.       col.push_back(0);
  8697.       runeAreaSpell.areaVec.push_back(col);
  8698.       col.clear();
  8699.       col.push_back(0);
  8700.       col.push_back(0);
  8701.       col.push_back(0);
  8702.       runeAreaSpell.areaVec.push_back(col);
  8703.       col.clear();
  8704.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 8;   runeAreaSpell.maxDamage = 18;
  8705.             long tempExhaust = player->exhaustedTicks;
  8706. player->exhaustedTicks = 0;
  8707. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8708. player->exhaustedTicks = tempExhaust;
  8709.       int32_t mana = 2;
  8710.       player->addManaSpent(mana);
  8711.       player->mana -= mana;
  8712.       return;
  8713.    }
  8714.  
  8715.    
  8716.    
  8717.    if((wandid == 2183 && (player->vocation == VOCATION_DRUID) && player->mana >= 13 && player->getLevel() >= 33)) { //Tempest rod
  8718.       int32_t dist = 2;
  8719.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8720.       std::vector<unsigned char> col;
  8721.       MagicEffectAreaClass runeAreaSpell;
  8722.       runeAreaSpell.attackType = ATTACK_ENERGY;
  8723.       runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8724.       runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8725.       runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8726.       runeAreaSpell.animationColor = 0x11;
  8727.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8728.       col.push_back(0);
  8729.       col.push_back(0);
  8730.       col.push_back(0);
  8731.       runeAreaSpell.areaVec.push_back(col);
  8732.       col.clear();
  8733.       col.push_back(0);
  8734.       col.push_back(1);
  8735.       col.push_back(0);
  8736.       runeAreaSpell.areaVec.push_back(col);
  8737.       col.clear();
  8738.       col.push_back(0);
  8739.       col.push_back(0);
  8740.       col.push_back(0);
  8741.       runeAreaSpell.areaVec.push_back(col);
  8742.       col.clear();
  8743.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 60;   runeAreaSpell.maxDamage = 70;
  8744.       long tempExhaust = player->exhaustedTicks;
  8745. player->exhaustedTicks = 0;
  8746. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8747. player->exhaustedTicks = tempExhaust;
  8748.       int32_t mana = 13;
  8749.       player->addManaSpent(mana);
  8750.       player->mana -= mana;
  8751.       return;
  8752.    }
  8753.    
  8754.    
  8755.    if((wandid == 2185 && (player->vocation == VOCATION_DRUID) && player->mana >= 5 && player->getLevel() >= 19)) { //Volcanic rod
  8756.       int32_t dist = 2;
  8757.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8758.       std::vector<unsigned char> col;
  8759.       MagicEffectAreaClass runeAreaSpell;
  8760.       runeAreaSpell.attackType = ATTACK_FIRE;
  8761.       runeAreaSpell.animationEffect = NM_ANI_FIRE;
  8762.       runeAreaSpell.hitEffect = NM_ME_FIRE_AREA;
  8763.       runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8764.       runeAreaSpell.animationColor = 0xC7;
  8765.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8766.       col.push_back(0);
  8767.       col.push_back(0);
  8768.       col.push_back(0);
  8769.       runeAreaSpell.areaVec.push_back(col);
  8770.       col.clear();
  8771.       col.push_back(0);
  8772.       col.push_back(1);
  8773.       col.push_back(0);
  8774.       runeAreaSpell.areaVec.push_back(col);
  8775.       col.clear();
  8776.       col.push_back(0);
  8777.       col.push_back(0);
  8778.       col.push_back(0);
  8779.       runeAreaSpell.areaVec.push_back(col);
  8780.       col.clear();
  8781.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 25;   runeAreaSpell.maxDamage = 35;
  8782.       long tempExhaust = player->exhaustedTicks;
  8783. player->exhaustedTicks = 0;
  8784. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8785. player->exhaustedTicks = tempExhaust;
  8786.       int32_t mana = 5;
  8787.       player->addManaSpent(mana);
  8788.       player->mana -= mana;
  8789.       return;
  8790.    }
  8791.    
  8792.    
  8793.    if((wandid == 2186 && (player->vocation == VOCATION_DRUID) && player->mana >= 3 && player->getLevel() >= 13)) { //Moonlight rod
  8794.       int32_t dist = 3;
  8795.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8796.       std::vector<unsigned char> col;
  8797.       MagicEffectAreaClass runeAreaSpell;
  8798.       runeAreaSpell.attackType = ATTACK_ENERGY;
  8799.       runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8800.       runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8801.       runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8802.       runeAreaSpell.animationColor = 0x47;
  8803.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8804.       col.push_back(0);
  8805.       col.push_back(0);
  8806.       col.push_back(0);
  8807.       runeAreaSpell.areaVec.push_back(col);
  8808.       col.clear();
  8809.       col.push_back(0);
  8810.       col.push_back(1);
  8811.       col.push_back(0);
  8812.       runeAreaSpell.areaVec.push_back(col);
  8813.       col.clear();
  8814.       col.push_back(0);
  8815.       col.push_back(0);
  8816.       col.push_back(0);
  8817.       runeAreaSpell.areaVec.push_back(col);
  8818.       col.clear();
  8819.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 14;   runeAreaSpell.maxDamage = 24;
  8820.       long tempExhaust = player->exhaustedTicks;
  8821. player->exhaustedTicks = 0;
  8822. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8823. player->exhaustedTicks = tempExhaust;
  8824.       int32_t mana = 3;
  8825.       player->addManaSpent(mana);
  8826.       player->mana -= mana;
  8827.       return;
  8828.    }
  8829.    
  8830.    
  8831.    if((wandid == 2187 && (player->vocation == VOCATION_SORCERER) && player->mana >= 13 && player->getLevel() >= 33)) { //Wand of inferno
  8832.       int32_t dist = 2;
  8833.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8834.       std::vector<unsigned char> col;
  8835.       MagicEffectAreaClass runeAreaSpell;
  8836.       runeAreaSpell.attackType = ATTACK_FIRE;
  8837.       runeAreaSpell.animationEffect = NM_ANI_FIRE;
  8838.       runeAreaSpell.hitEffect = NM_ME_FIRE_AREA;
  8839.       runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8840.       runeAreaSpell.animationColor = 0xC7;
  8841.       runeAreaSpell.drawblood = true;
  8842.       runeAreaSpell.offensive = true;
  8843.       col.push_back(0);
  8844.       col.push_back(0);
  8845.       col.push_back(0);
  8846.       runeAreaSpell.areaVec.push_back(col);
  8847.       col.clear();
  8848.       col.push_back(0);
  8849.       col.push_back(1);
  8850.       col.push_back(0);
  8851.       runeAreaSpell.areaVec.push_back(col);
  8852.       col.clear();
  8853.       col.push_back(0);
  8854.       col.push_back(0);
  8855.       col.push_back(0);
  8856.       runeAreaSpell.areaVec.push_back(col);
  8857.       col.clear();
  8858.       runeAreaSpell.direction = 1;
  8859.       runeAreaSpell.minDamage = 60;
  8860.       runeAreaSpell.maxDamage = 70;
  8861.       long tempExhaust = player->exhaustedTicks;
  8862. player->exhaustedTicks = 0;
  8863. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8864. player->exhaustedTicks = tempExhaust;
  8865.       int32_t mana = 13;
  8866.       player->addManaSpent(mana);
  8867.       player->mana -= mana;
  8868.      
  8869.       return;
  8870.    }
  8871.    
  8872.    
  8873.    if((wandid == 2188 && (player->vocation == VOCATION_SORCERER) && player->mana >= 5 && player->getLevel() >= 19)) { //Wand of plague
  8874.       int32_t dist = 2;
  8875.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8876.       std::vector<unsigned char> col;
  8877.       MagicEffectAreaClass runeAreaSpell;
  8878.       runeAreaSpell.attackType = ATTACK_POISON;
  8879.       runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8880.       runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  8881.       runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  8882.       runeAreaSpell.animationColor = 0x60;
  8883.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8884.       col.push_back(0);
  8885.       col.push_back(0);
  8886.       col.push_back(0);
  8887.       runeAreaSpell.areaVec.push_back(col);
  8888.       col.clear();
  8889.       col.push_back(0);
  8890.       col.push_back(1);
  8891.       col.push_back(0);
  8892.       runeAreaSpell.areaVec.push_back(col);
  8893.       col.clear();
  8894.       col.push_back(0);
  8895.       col.push_back(0);
  8896.       col.push_back(0);
  8897.       runeAreaSpell.areaVec.push_back(col);
  8898.       col.clear();
  8899.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 25;   runeAreaSpell.maxDamage = 35;
  8900.       long tempExhaust = player->exhaustedTicks;
  8901. player->exhaustedTicks = 0;
  8902. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8903. player->exhaustedTicks = tempExhaust;
  8904.       int32_t mana = 5;
  8905.       player->addManaSpent(mana);
  8906.       player->mana -= mana;
  8907.       return;
  8908.    }
  8909.    
  8910.    
  8911.    if((wandid == 2189 && (player->vocation == VOCATION_SORCERER) && player->mana >= 8 && player->getLevel() >= 26)) { //Wand of cosmic energy
  8912.       int32_t dist = 2;
  8913.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8914.       std::vector<unsigned char> col;
  8915.       MagicEffectAreaClass runeAreaSpell;
  8916.       runeAreaSpell.attackType = ATTACK_ENERGY;
  8917.       runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8918.       runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8919.       runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8920.       runeAreaSpell.animationColor = 0x47;
  8921.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8922.       col.push_back(0);
  8923.       col.push_back(0);
  8924.       col.push_back(0);
  8925.       runeAreaSpell.areaVec.push_back(col);
  8926.       col.clear();
  8927.       col.push_back(0);
  8928.       col.push_back(1);
  8929.       col.push_back(0);
  8930.       runeAreaSpell.areaVec.push_back(col);
  8931.       col.clear();
  8932.       col.push_back(0);
  8933.       col.push_back(0);
  8934.       col.push_back(0);
  8935.       runeAreaSpell.areaVec.push_back(col);
  8936.       col.clear();
  8937.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 40;   runeAreaSpell.maxDamage = 50;
  8938.             long tempExhaust = player->exhaustedTicks;
  8939. player->exhaustedTicks = 0;
  8940. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8941. player->exhaustedTicks = tempExhaust;
  8942.       int32_t mana = 8;
  8943.       player->addManaSpent(mana);
  8944.       player->mana -= mana;
  8945.       return;
  8946.    }
  8947.    
  8948.    
  8949.    if((wandid == 2190 && (player->vocation == VOCATION_SORCERER) && player->mana >= 2 && player->getLevel() >= 7)) { //Wand of vortex
  8950.       int32_t dist = 3;
  8951.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8952.       std::vector<unsigned char> col;
  8953.       MagicEffectAreaClass runeAreaSpell;
  8954.       runeAreaSpell.attackType = ATTACK_ENERGY;
  8955.       runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8956.       runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8957.       runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8958.       runeAreaSpell.animationColor = 0x47;
  8959.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8960.       col.push_back(0);
  8961.       col.push_back(0);
  8962.       col.push_back(0);
  8963.       runeAreaSpell.areaVec.push_back(col);
  8964.       col.clear();
  8965.       col.push_back(0);
  8966.       col.push_back(1);
  8967.       col.push_back(0);
  8968.       runeAreaSpell.areaVec.push_back(col);
  8969.       col.clear();
  8970.       col.push_back(0);
  8971.       col.push_back(0);
  8972.       col.push_back(0);
  8973.       runeAreaSpell.areaVec.push_back(col);
  8974.       col.clear();
  8975.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 8;   runeAreaSpell.maxDamage = 18;
  8976.       long tempExhaust = player->exhaustedTicks;
  8977. player->exhaustedTicks = 0;
  8978. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8979. player->exhaustedTicks = tempExhaust;
  8980.       int32_t mana = 2;
  8981.       player->addManaSpent(mana);
  8982.       player->mana -= mana;
  8983.       return;
  8984.    }
  8985.    
  8986.    if((wandid == 2191 && (player->vocation == VOCATION_SORCERER) && player->mana >= 3 && player->getLevel() >= 13)) { //Wand of dragonbreath
  8987.       int32_t dist = 3;
  8988.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8989.       std::vector<unsigned char> col;
  8990.       MagicEffectAreaClass runeAreaSpell;
  8991.       runeAreaSpell.attackType = ATTACK_FIRE;
  8992.       runeAreaSpell.animationEffect = NM_ANI_FIRE;
  8993.       runeAreaSpell.hitEffect = NM_ME_FIRE_AREA;
  8994.       runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8995.       runeAreaSpell.animationColor = 0xC7;
  8996.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8997.       col.push_back(0);
  8998.       col.push_back(0);
  8999.       col.push_back(0);
  9000.       runeAreaSpell.areaVec.push_back(col);
  9001.       col.clear();
  9002.       col.push_back(0);
  9003.       col.push_back(1);
  9004.       col.push_back(0);
  9005.       runeAreaSpell.areaVec.push_back(col);
  9006.       col.clear();
  9007.       col.push_back(0);
  9008.       col.push_back(0);
  9009.       col.push_back(0);
  9010.       runeAreaSpell.areaVec.push_back(col);
  9011.       col.clear();
  9012.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 14;   runeAreaSpell.maxDamage = 24;
  9013.       long tempExhaust = player->exhaustedTicks;
  9014. player->exhaustedTicks = 0;
  9015. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  9016. player->exhaustedTicks = tempExhaust;
  9017.       int32_t mana = 3;
  9018.       player->addManaSpent(mana);
  9019.       player->mana -= mana;
  9020.       return;
  9021.    }
  9022. //messages by Subarmy  
  9023.  
  9024.  
  9025.  
  9026. if((wandid == 2191 || wandid == 2190 || wandid == 5319 || wandid == 2189 || wandid == 2188 || wandid == 2187 || wandid == 2453 || wandid == 2544 && (player->vocation == VOCATION_DRUID || player->vocation == VOCATION_KNIGHT || player->vocation == VOCATION_PALADIN || (player->vocation >= 0 && player->access > 0)))) { //msg when wrong voc  
  9027. player->sendTextMessage(MSG_SMALLINFO, "This wand can only be wielded by sorcerers.");
  9028. }
  9029. if((wandid == 2186 || wandid == 2185 || wandid == 5318  || wandid == 2183 || wandid == 2182 || wandid == 2181 || wandid == 2453 || wandid == 2544 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_KNIGHT || player->vocation == VOCATION_PALADIN || (player->vocation >= 0 && player->access > 0)))) { //msg when wrong voc  
  9030. player->sendTextMessage(MSG_SMALLINFO, "This wand can only be wielded by druids.");
  9031. }
  9032. if((wandid == 2181 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 26)) {
  9033. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 26 level to wield this wand.");
  9034. }
  9035. if((wandid == 2544 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 200)) {
  9036. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 200 level to wield this wand.");
  9037. }
  9038. if((wandid == 5326 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 300)) {
  9039. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 300 level to wield this wand.");
  9040. }
  9041. if((wandid == 2453 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 150)) {
  9042. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 150 level to wield this wand.");
  9043. }
  9044. if((wandid == 2182 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 7)) {
  9045. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 7 level to wield this wand.");
  9046. }
  9047. if((wandid == 2183 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 33)) {
  9048. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 33 to wield this wand.");
  9049. }
  9050. if((wandid == 2185 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 19)) {
  9051. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 19 level to wield this wand.");
  9052. }
  9053. if((wandid == 2186 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 13)) {
  9054. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 13 level to wield this wand.");
  9055. }
  9056. if((wandid == 5318 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 65)) {
  9057. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 65 level to wield this wand.");
  9058. }
  9059. if((wandid == 2187 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 33)) {
  9060. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 33 level to wield this wand.");
  9061. }
  9062. if((wandid == 5319 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 65)) {
  9063. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 65 level to wield this wand.");
  9064. }
  9065. if((wandid == 2453 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 150)) {
  9066. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 150 level to wield this wand.");
  9067. }
  9068. if((wandid == 2544 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 200)) {
  9069. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 200 level to wield this wand.");
  9070. }
  9071. if((wandid == 5326 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 300)) {
  9072. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 300 level to wield this wand.");
  9073. }
  9074. if((wandid == 2188 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 19)) {
  9075. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 19 level to wield this wand.");
  9076. }
  9077. if((wandid == 2189 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 26)) {
  9078. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 26 level to wield this wand.");
  9079. }
  9080. if((wandid == 2190 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 7)) {
  9081. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 7 level to wield this wand.");
  9082. }
  9083.  
  9084. if((wandid == 2191 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 13)) {
  9085. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 13 level to wield this wand.");
  9086. }//end messages by Subarmy
  9087. }
  9088. #endif
  9089. // ONLINE RECORD
  9090. void Game::checkRecord()
  9091. {
  9092.     if(record < getPlayersOnline()){
  9093.         record = getPlayersOnline();
  9094.         saveRecord();
  9095.  
  9096.         std::stringstream record;
  9097.         record << "New record: " << getPlayersOnline() << " players are logged in." << std::endl;
  9098.         for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  9099.             (*it).second->sendTextMessage(MSG_ADVANCE, record.str().c_str());
  9100.     }
  9101.  
  9102. }
  9103.  
  9104. bool Game::loadRecord()
  9105. {
  9106.     std::string filename = g_config.getGlobalString("datadir") + "record.xml";
  9107.     xmlDocPtr doc;
  9108.     xmlMutexLock(xmlmutex);
  9109.     doc = xmlParseFile(filename.c_str());
  9110.  
  9111.     if (doc)
  9112.     {
  9113.         xmlNodePtr root, tmp;
  9114.         root = xmlDocGetRootElement(doc);
  9115.  
  9116.         if (xmlStrcmp(root->name, (const xmlChar*)"record"))
  9117.         {
  9118.             xmlFreeDoc(doc);
  9119.             xmlMutexUnlock(xmlmutex);
  9120.             return false;
  9121.         }
  9122.  
  9123.         record = atoi((const char*)xmlGetProp(root, (const xmlChar *)"record"));
  9124.  
  9125.         xmlFreeDoc(doc);
  9126.         xmlMutexUnlock(xmlmutex);
  9127.         return true;
  9128.     }
  9129.  
  9130.     xmlMutexUnlock(xmlmutex);
  9131.     return false;
  9132. }
  9133.  
  9134. bool Game::saveRecord()
  9135. {
  9136.     std::string filename = g_config.getGlobalString("datadir") + "record.xml";
  9137.     xmlDocPtr doc;
  9138.     xmlNodePtr root, tmp;
  9139.     xmlMutexLock(xmlmutex);
  9140.     time_t time = std::time(NULL);
  9141.  
  9142.     doc = xmlNewDoc((const xmlChar*)"1.0");
  9143.     doc->children = xmlNewDocNode(doc, NULL, (const xmlChar*)"record", NULL);
  9144.      root = doc->children;
  9145.  
  9146.     std::stringstream sb;
  9147.     sb << record; xmlSetProp(root, (const xmlChar*) "record", (const xmlChar*)sb.str().c_str()); sb.str("");
  9148.     sb << time; xmlSetProp(root, (const xmlChar*) "time", (const xmlChar*)sb.str().c_str()); sb.str("");
  9149.  
  9150.     xmlSaveFile(filename.c_str(), doc);
  9151.      xmlFreeDoc(doc);
  9152.     xmlMutexUnlock(xmlmutex);
  9153.     return true;
  9154. }
  9155. // ANIMATED TEXT WHEN ADVANCE
  9156. void Game::sendAnimatedTextExt(const Position pos,int32_t aniColor,const std::string &text)
  9157. {
  9158.      SpectatorVec list;
  9159.      SpectatorVec::iterator it;
  9160.      getSpectators(Range(pos), list);
  9161.      for(it = list.begin(); it != list.end(); ++it){
  9162.         Player* spec = dynamic_cast<Player*>(*it);
  9163.         if(spec)
  9164.           spec->sendAnimatedText(pos, aniColor, text);
  9165.      }
  9166. }
  9167. // CREATUREBYPOSITION
  9168. Creature* Game::getCreatureByPosition(int32_t x, int32_t y, int32_t z)
  9169. {
  9170.     for(AutoList<Creature>::listiterator it = listCreature.list.begin(); it != listCreature.list.end(); ++it){
  9171.         if(it->second->pos.x == x && it->second->pos.y == y && it->second->pos.z == z)
  9172.             return it->second;
  9173.     }
  9174.  
  9175.     return NULL;
  9176. }
  9177. // CREATE CONDITION
  9178. void Game::CreateCondition(Creature* creature, Creature* target, unsigned char animationColor, unsigned char damageEffect, unsigned char hitEffect, attacktype_t attackType, bool offensive, int32_t maxDamage, int32_t minDamage, long ticks, long count)
  9179. {
  9180.     uint32_t targetID;
  9181.     if(target)
  9182.     targetID = target->getID();
  9183.     else
  9184.     targetID = 0;
  9185.    
  9186.     MagicEffectTargetCreatureCondition magicCondition = MagicEffectTargetCreatureCondition(targetID);
  9187.     magicCondition.animationColor = animationColor;
  9188.     magicCondition.damageEffect = damageEffect;
  9189.     magicCondition.hitEffect = hitEffect;
  9190.     magicCondition.attackType = attackType;
  9191.     magicCondition.maxDamage = maxDamage;
  9192.     magicCondition.minDamage = minDamage;
  9193.     magicCondition.offensive = offensive;
  9194.     CreatureCondition condition = CreatureCondition(ticks, count, magicCondition);
  9195.     creature->addCondition(condition, true);
  9196.    
  9197.     Player *player = dynamic_cast<Player*>(creature);
  9198.     if(player)
  9199.  player->sendIcons();
  9200. }
  9201. // Fields loaded from map - The Chaos
  9202. void Game::doFieldDamage(Creature* creature, unsigned char animationColor, unsigned char damageEffect,
  9203.        unsigned char hitEffect, attacktype_t attackType, bool offensive, int32_t damage)
  9204. {
  9205.    MagicEffectClass cd;
  9206.    cd.animationColor = animationColor;
  9207.    cd.damageEffect = damageEffect;
  9208.    cd.hitEffect = hitEffect;
  9209.    cd.attackType = attackType;
  9210.    cd.offensive = offensive;
  9211.    Player* itsHim = dynamic_cast<Player*>(getCreatureByID(creature->getID()));
  9212.    if(itsHim){ //Since that was causing damage/2 against player, here its my solution =)
  9213.       cd.maxDamage = damage*2;
  9214.       cd.minDamage = damage*2;
  9215.    }
  9216.    else{
  9217.       cd.maxDamage = damage;
  9218.       cd.minDamage = damage;
  9219.    }
  9220.    creatureMakeMagic(NULL, creature->pos, &cd);
  9221. }
  9222. void Game::updateTile(const Position& pos)
  9223. {
  9224.   SpectatorVec list;
  9225.   SpectatorVec::iterator i;
  9226.   getSpectators(Range(pos), list);
  9227.   for(i = list.begin(); i != list.end(); ++i)
  9228.     (*i)->onTileUpdated(pos);
  9229. }
  9230.  
  9231. void Game::banPlayer(Player *player, std::string reason, std::string action, std::string comment, bool IPban)
  9232. {
  9233.     int32_t bantime = 0;
  9234.    
  9235.      if(player){
  9236.  
  9237.         if(comment=="deletion")
  9238.         player->deleted = 1;  // make player deleted
  9239.         else
  9240.         bantime = atoi(comment.c_str()) * 86400;  // else make players banned for "comment" days (86400 = 1 day)
  9241.        
  9242.         if(player->finalwarning == 1 || player->times == 4)
  9243.         player->deleted = 1; // if player was already warned let delete thy char
  9244.        
  9245.         if(action=="AccountBan+FinalWarning" || player->times == 3)
  9246.         player->finalwarning = 1; // if player has warned set variable
  9247.        
  9248.         if(reason=="Excessive unjustifed player killing")
  9249.         bantime = g_config.getGlobalNumber("pkbandays",3) * 86400;  // baannnnn pekaayssss (from config.lua)
  9250.  
  9251.         player->banned = 1;
  9252.         player->times++;
  9253.         player->comment = comment;
  9254.         player->reason = reason;
  9255.         player->action = action;
  9256.         player->banstart = std::time(NULL);
  9257.         player->banend = player->banstart + bantime;
  9258.         time_t endBan = player->banend;
  9259.         player->banrealtime = ctime(&endBan); // this variable stores REAL ban date in string, so you wont see 11105220952 in accmaker ;)
  9260.         if(IPban){
  9261.             std::pair<uint32_t, uint32_t> IpNetMask;
  9262. IpNetMask.first = player->lastip;
  9263. IpNetMask.second = 0xFFFFFFFF;
  9264. if(IpNetMask.first > 0)
  9265.     bannedIPs.push_back(IpNetMask);
  9266.         }
  9267.         std::stringstream ban;
  9268.         ban << "You just have been banned for " << reason << "!";
  9269.         player->sendTextMessage(MSG_INFO, ban.str().c_str());
  9270.         player->kickPlayer();
  9271.      }
  9272. }
  9273.  
  9274. #ifdef REX_MUTED
  9275.  
  9276. #endif //REX_MUTED
  9277. #ifdef HUCZU_FIX
  9278. bool Game::loadCities(Player* player, std::string name)
  9279. {
  9280.   xmlDocPtr doc;
  9281.   std::string file = "data/miasta.xml";
  9282.   doc = xmlParseFile(file.c_str());
  9283.   if(doc){
  9284.   xmlNodePtr root, miasto;
  9285.   root = xmlDocGetRootElement(doc);
  9286.   if(xmlStrcmp(root->name, (const xmlChar*)"miasta")) {
  9287.      xmlFreeDoc(doc);
  9288.      return -1;
  9289.   }
  9290.    miasto = root->children;
  9291.    while(miasto){
  9292.       if(strcmp((char*) miasto->name, "miasto")==0){
  9293.  
  9294.          std::string nameIN = (const char*)xmlGetProp(miasto, (const xmlChar *) "nazwa");
  9295.                   int32_t x = atoi((const char*)xmlGetProp(miasto, (const xmlChar *) "x"));
  9296.                   int32_t y = atoi((const char*)xmlGetProp(miasto, (const xmlChar *) "y"));
  9297.                   int32_t z = atoi((const char*)xmlGetProp(miasto, (const xmlChar *) "z"));
  9298.                   Position pos(x,y,z);
  9299.                   if(nameIN == name)
  9300.                   teleport(player,pos);
  9301.    }
  9302.    miasto = miasto->next;
  9303.    }    
  9304.    xmlFreeDoc(doc);
  9305.    return 0;
  9306.   }
  9307.   return -1;
  9308. }
  9309. #endif //HUCZU_FIX
  9310. // RAID SYSTEM
  9311. bool Game::loadRaid(std::string name)
  9312. {
  9313.   xmlDocPtr doc;
  9314.   std::cout << "Executing raid named " << name << "." << std::endl;
  9315.   std::string file = "data/world/raids.xml";
  9316.   doc = xmlParseFile(file.c_str());
  9317.   if(doc){
  9318.   xmlNodePtr root, raid, command;
  9319.   root = xmlDocGetRootElement(doc);
  9320.   if(xmlStrcmp(root->name, (const xmlChar*)"raids")) {
  9321.      xmlFreeDoc(doc);
  9322.      return -1;
  9323.   }
  9324.    raid = root->children;
  9325.    while(raid){
  9326.       if(strcmp((char*) raid->name, "raid")==0){
  9327.  
  9328.          std::string nameIN = (const char*)xmlGetProp(raid, (const xmlChar *) "name");
  9329.          if(nameIN == name) {
  9330.          std::string messageIN = (const char*)xmlGetProp(raid, (const xmlChar *) "message");
  9331.          std::string brodcasterIN = (const char*)xmlGetProp(raid, (const xmlChar *) "brodcaster");
  9332.  
  9333.          Creature *c = getCreatureByName(brodcasterIN);
  9334.          if(c) {
  9335.             creatureBroadcastMessage(c,messageIN);
  9336.          } else {
  9337.             std::cout << "Could not send news msg! Brodcaster does not exist" << std::endl;
  9338.          }
  9339.  
  9340.          if(nameIN == name) {
  9341.             command = raid->children;
  9342.  
  9343.             while(command) {
  9344.  
  9345.                if(strcmp((char*) command->name, "monster")==0){
  9346.                   std::string monstername = (const char*)xmlGetProp(command, (const xmlChar *) "name");
  9347.                   int32_t x = atoi((const char*)xmlGetProp(command, (const xmlChar *) "x"));
  9348.                   int32_t y = atoi((const char*)xmlGetProp(command, (const xmlChar *) "y"));
  9349.                   int32_t z = atoi((const char*)xmlGetProp(command, (const xmlChar *) "z"));
  9350.  
  9351.                   int32_t loot = atoi((const char*)xmlGetProp(command, (const xmlChar *) "lootid"));  //Not yet implemented!
  9352.                   int32_t chance = atoi((const char*)xmlGetProp(command, (const xmlChar *) "chance"));  //Not yet implemented!
  9353.                   placeRaidMonster(monstername, x, y, z);
  9354.                }
  9355.  
  9356.                if(strcmp((char*) command->name, "area")==0){
  9357.                   std::string monstername = (const char*)xmlGetProp(command, (const xmlChar *) "monster");
  9358.                   int32_t count = atoi((const char*)xmlGetProp(command, (const xmlChar *) "count"));
  9359.                   int32_t xf = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posxfrom"));
  9360.                   int32_t yf = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posyfrom"));
  9361.                   int32_t zf = atoi((const char*)xmlGetProp(command, (const xmlChar *) "poszfrom"));
  9362.  
  9363.                   int32_t xt = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posxto"));
  9364.                   int32_t yt = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posyto"));
  9365.                   int32_t zt = atoi((const char*)xmlGetProp(command, (const xmlChar *) "poszto"));
  9366.  
  9367.                   int32_t i = 0;
  9368.                   int32_t tries = 0;
  9369.                   while (i<=count && tries<=(count*10)) {
  9370.                       int32_t x = (int32_t)((xt-xf) * (rand()/(RAND_MAX+1.0)) + xf);
  9371.                       int32_t y = (int32_t)((yt-yf) * (rand()/(RAND_MAX+1.0)) + yf);
  9372.                       int32_t z = (int32_t)((zt-zf) * (rand()/(RAND_MAX+1.0)) + zf);
  9373.                       Tile* t = map->getTile(x,y,z);
  9374.                       if(t && t->isPz() == false) {
  9375.                          placeRaidMonster(monstername, x, y, z);
  9376.                          i++;
  9377.                       }
  9378.                       tries++;
  9379.                   }
  9380.                }
  9381.                if(strcmp((char*) command->name, "message")==0){
  9382.                   std::string msg = (const char*)xmlGetProp(command, (const xmlChar *) "text");
  9383.                   std::string brodcaster = (const char*)xmlGetProp(command, (const xmlChar *) "brodcaster");
  9384.                   Creature *c = getCreatureByName(brodcaster);
  9385.                   if(c) {
  9386.                      creatureBroadcastMessage(c,msg);
  9387.                   } else {
  9388.                      std::cout << "Could not send news msg! Brodcaster does not exist." << std::endl;
  9389.                   }
  9390.                }
  9391.                command = command->next;
  9392.             }
  9393.          }
  9394.       }
  9395.    }
  9396.    raid = raid->next;
  9397.    }    
  9398.    xmlFreeDoc(doc);
  9399.    return 0;
  9400.   }
  9401.   return -1;
  9402. }
  9403. bool Game::placeRaidMonster(std::string name, int32_t x, int32_t y, int32_t z)
  9404. {
  9405.  Monster* monster = Monster::createMonster(name, this);
  9406. //For new CVS use the following line:
  9407. //Monster* monster = Monster::createMonster(name, this);
  9408.  if(!monster){
  9409.   delete monster;
  9410.   return false;
  9411.  }
  9412.  Position pos;
  9413.  pos.x = x;
  9414.  pos.y = y;
  9415.  pos.z = z;
  9416.  
  9417.  // Place the monster
  9418.  if(!placeCreature(pos, monster)) {
  9419.   delete monster;
  9420.   return false;
  9421.  }
  9422.  
  9423.  return true;
  9424. }
  9425.  
  9426. void Game::spectatorText(Position pos, unsigned char color, std::string text)
  9427. {
  9428.     SpectatorVec list;
  9429.     SpectatorVec::iterator it;
  9430.     getSpectators(Range(pos, true), list);
  9431.          
  9432.     for(it = list.begin(); it != list.end(); ++it) {
  9433.         if(Player* p = dynamic_cast<Player*>(*it)) {
  9434.             p->sendAnimatedText(pos, color, text);
  9435.         }
  9436.     }
  9437. }
  9438.  
  9439. #ifdef DT_PREMMY
  9440. bool Game::countPremmy(Player *player)
  9441. {
  9442.     Account acc = IOAccount::instance()->loadAccount(player->accountNumber);
  9443.     int32_t cont;
  9444.     if(acc.lastsaveday == 0)
  9445.         cont = 0;
  9446.     else
  9447.         cont = acc.lastsaveday2 - acc.lastsaveday;
  9448.        //std::cout << "Last Login in Acc: " << acc.lastsaveday << " - Today: " << acc.lastsaveday2 << " - Days removed from acc: " << cont << std::endl;
  9449.        if(cont < 0){
  9450.         cont =+ 365; //dodajemy caly rok
  9451.         }
  9452.     if((acc.premDays - cont) <= 0)
  9453.     {
  9454.         acc.premDays = 0;
  9455.         player->premmium = false;
  9456.     }
  9457.     else
  9458.     {
  9459.         acc.premDays = acc.premDays - cont;
  9460.         player->premmium = true;
  9461.     }
  9462.     if(g_config.FREE_PREMMY)
  9463.       player->premmium = true;
  9464.    
  9465.     IOAccount::instance()->saveAccount(acc);
  9466.  
  9467.         }
  9468.  
  9469. #endif //DT_PREMMY
  9470.  
  9471.  
  9472. #ifdef ZS_SWORDS
  9473. void Game::useSword(Creature *creature, Creature *attackedCreature, int32_t swordid)
  9474. {
  9475.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::useSword()");
  9476.  
  9477.     Player *player = dynamic_cast<Player*>(creature);
  9478.     if(!player || !attackedCreature || player->pos.z != attackedCreature->pos.z)
  9479.         return;
  9480.  
  9481.     int32_t dist, mana = 0;
  9482.     MagicEffectAreaNoExhaustionClass runeAreaSpell;
  9483.     runeAreaSpell.drawblood = true;
  9484.     runeAreaSpell.offensive = true;
  9485.     runeAreaSpell.direction = 1;
  9486.    
  9487.  
  9488.     // P O I S O N //
  9489.  
  9490.     if (swordid == ITEM_P_MB && player->vocation == VOCATION_KNIGHT &&
  9491.         player->mana >= g_config.MANA_P_MB && player->getLevel() >= 220)
  9492.     {
  9493.         dist = g_config.RANGE_P_MB;
  9494.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9495.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9496.             return;
  9497.  
  9498.         runeAreaSpell.attackType = ATTACK_SWORD;
  9499.         runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  9500.         runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  9501.         runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  9502.         runeAreaSpell.animationColor = 0x60;
  9503.    
  9504.         runeAreaSpell.minDamage = 10;
  9505.         runeAreaSpell.maxDamage = 60;
  9506.         mana = g_config.MANA_P_MB;
  9507.     }
  9508.    
  9509.     else if (swordid == ITEM_P_MAUL && player->vocation == VOCATION_KNIGHT &&
  9510.         player->mana >= g_config.MANA_P_MAUL && player->getLevel() >= 220)
  9511.     {
  9512.         dist = g_config.RANGE_P_MAUL;
  9513.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9514.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9515.             return;
  9516.  
  9517.         runeAreaSpell.attackType = ATTACK_SWORD;
  9518.         runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  9519.         runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  9520.         runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  9521.         runeAreaSpell.animationColor = 0x60;
  9522.    
  9523.         runeAreaSpell.minDamage = 10;
  9524.         runeAreaSpell.maxDamage = 60;
  9525.         mana = g_config.MANA_P_MAUL;
  9526.     }
  9527.    
  9528.     else if (swordid == ITEM_P_HEAD && player->vocation == VOCATION_KNIGHT &&
  9529.         player->mana >= g_config.MANA_P_HEAD && player->getLevel() >= 220)
  9530.     {
  9531.         dist = g_config.RANGE_P_HEAD;
  9532.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9533.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9534.             return;
  9535.        
  9536.         runeAreaSpell.attackType = ATTACK_SWORD;
  9537.         runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  9538.         runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  9539.         runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  9540.         runeAreaSpell.animationColor = 0x60;
  9541.    
  9542.         runeAreaSpell.minDamage = 10;
  9543.         runeAreaSpell.maxDamage = 60;
  9544.         mana = g_config.MANA_P_HEAD;
  9545.     }
  9546.    
  9547.     // F I R E //
  9548.    
  9549.     else if (swordid == ITEM_F_MB && player->vocation == VOCATION_KNIGHT &&
  9550.         player->mana >= g_config.MANA_F_MB && player->getLevel() >= 320)
  9551.     {
  9552.         dist = g_config.RANGE_F_MB;
  9553.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9554.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9555.             return;
  9556.        
  9557.         runeAreaSpell.attackType = ATTACK_SWORD;
  9558.         runeAreaSpell.animationEffect = NM_ANI_FIRE;
  9559.         runeAreaSpell.hitEffect = NM_ME_EXPLOSION_AREA;
  9560.         runeAreaSpell.areaEffect = NM_ME_EXPLOSION_AREA;
  9561.         runeAreaSpell.animationColor = 0xC6;
  9562.        
  9563.         runeAreaSpell.minDamage = 60;
  9564.         runeAreaSpell.maxDamage = 110;
  9565.         mana = g_config.MANA_F_MB;
  9566.     }
  9567.    
  9568.     else if (swordid == ITEM_F_MAUL && player->vocation == VOCATION_KNIGHT &&
  9569.         player->mana >= g_config.MANA_F_MAUL && player->getLevel() >= 320)
  9570.     {
  9571.         dist = g_config.RANGE_F_MAUL;
  9572.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9573.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9574.             return;
  9575.  
  9576.         runeAreaSpell.attackType = ATTACK_SWORD;
  9577.         runeAreaSpell.animationEffect = NM_ANI_FIRE;
  9578.         runeAreaSpell.hitEffect = NM_ME_EXPLOSION_AREA;
  9579.         runeAreaSpell.areaEffect = NM_ME_EXPLOSION_AREA;
  9580.         runeAreaSpell.animationColor = 0xC6;
  9581.        
  9582.         runeAreaSpell.minDamage = 60;
  9583.         runeAreaSpell.maxDamage = 110;
  9584.         mana = g_config.MANA_F_MAUL;
  9585.     }
  9586.    
  9587.     else if (swordid == ITEM_F_HEAD && player->vocation == VOCATION_KNIGHT &&
  9588.         player->mana >= g_config.MANA_F_HEAD && player->getLevel() >= 320)
  9589.     {
  9590.         dist = g_config.RANGE_F_HEAD;
  9591.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9592.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9593.             return;
  9594.  
  9595.         runeAreaSpell.attackType = ATTACK_SWORD;
  9596.         runeAreaSpell.animationEffect = NM_ANI_FIRE;
  9597.         runeAreaSpell.hitEffect = NM_ME_EXPLOSION_AREA;
  9598.         runeAreaSpell.areaEffect = NM_ME_EXPLOSION_AREA;
  9599.         runeAreaSpell.animationColor = 0xC6;
  9600.        
  9601.         runeAreaSpell.minDamage = 60;
  9602.         runeAreaSpell.maxDamage = 110;
  9603.         mana = g_config.MANA_F_HEAD;
  9604.     }
  9605.    
  9606.     // E N E R G Y //
  9607.    
  9608.     else if (swordid == ITEM_E_MB && player->vocation == VOCATION_KNIGHT &&
  9609.         player->mana >= g_config.MANA_E_MB && player->getLevel() >= 420)
  9610.     {
  9611.         dist = g_config.RANGE_E_MB;
  9612.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9613.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9614.             return;
  9615.  
  9616.         runeAreaSpell.attackType = ATTACK_SWORD;
  9617.         runeAreaSpell.animationEffect = NM_ANI_SUDDENDEATH;
  9618.         runeAreaSpell.hitEffect = NM_ME_MORT_AREA;
  9619.         runeAreaSpell.areaEffect = NM_ME_MORT_AREA;
  9620.         runeAreaSpell.animationColor = 0xB9;
  9621.        
  9622.         runeAreaSpell.minDamage = 110;
  9623.         runeAreaSpell.maxDamage = 160;
  9624.         mana = g_config.MANA_E_MB;
  9625.     }
  9626.    
  9627.     else if (swordid == ITEM_E_MAUL && player->vocation == VOCATION_KNIGHT &&
  9628.         player->mana >= g_config.MANA_E_MAUL && player->getLevel() >= 420)
  9629.     {
  9630.         dist = g_config.RANGE_E_MAUL;
  9631.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9632.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9633.             return;
  9634.  
  9635.         runeAreaSpell.attackType = ATTACK_SWORD;
  9636.         runeAreaSpell.animationEffect = NM_ANI_SUDDENDEATH;
  9637.         runeAreaSpell.hitEffect = NM_ME_MORT_AREA;
  9638.         runeAreaSpell.areaEffect = NM_ME_MORT_AREA;
  9639.         runeAreaSpell.animationColor = 0xB9;
  9640.        
  9641.         runeAreaSpell.minDamage = 110;
  9642.         runeAreaSpell.maxDamage = 160;
  9643.         mana = g_config.MANA_E_MAUL;
  9644.     }
  9645.    
  9646.     else if (swordid == ITEM_E_HEAD && player->vocation == VOCATION_KNIGHT &&
  9647.         player->mana >= g_config.MANA_E_HEAD && player->getLevel() >= 420)
  9648.     {
  9649.         dist = g_config.RANGE_E_HEAD;
  9650.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9651.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9652.             return;
  9653.  
  9654.         runeAreaSpell.attackType = ATTACK_SWORD;
  9655.         runeAreaSpell.animationEffect = NM_ANI_SUDDENDEATH;
  9656.         runeAreaSpell.hitEffect = NM_ME_MORT_AREA;
  9657.         runeAreaSpell.areaEffect = NM_ME_MORT_AREA;
  9658.         runeAreaSpell.animationColor = 0xB9;
  9659.        
  9660.         runeAreaSpell.minDamage = 110;
  9661.         runeAreaSpell.maxDamage = 160;
  9662.         mana = g_config.MANA_E_HEAD;
  9663.     }
  9664.    
  9665.     // P L A Y E R   W E A P O N S //
  9666.    
  9667.     else if (swordid == ITEM_HAIK_AXE && player->vocation == VOCATION_KNIGHT &&
  9668.         player->mana >= g_config.MANA_HAIK_AXE && player->getLevel() >= 500)
  9669.     {
  9670.         dist = g_config.RANGE_HAIK_AXE;
  9671.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9672.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9673.             return;
  9674.    
  9675.         runeAreaSpell.attackType = ATTACK_SWORD;
  9676.         runeAreaSpell.animationEffect = NM_ANI_STAR;
  9677.         runeAreaSpell.hitEffect = NM_ME_STAR;
  9678.         runeAreaSpell.areaEffect = NM_ME_STAR;
  9679.         runeAreaSpell.animationColor = 0xD2;
  9680.        
  9681.         runeAreaSpell.minDamage = 300;
  9682.         runeAreaSpell.maxDamage = 350;
  9683.         mana = g_config.MANA_HAIK_AXE;
  9684.     }
  9685.    
  9686.     else if (swordid == ITEM_BLETKA_AXE && player->vocation == VOCATION_KNIGHT &&
  9687.         player->mana >= g_config.MANA_BLETKA_AXE)
  9688.     {
  9689.         dist = g_config.RANGE_BLETKA_AXE;
  9690.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9691.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9692.             return;
  9693.    
  9694.         runeAreaSpell.attackType = ATTACK_SWORD;
  9695.         runeAreaSpell.animationEffect = NM_ANI_STAR;
  9696.         runeAreaSpell.hitEffect = NM_ME_STAR;
  9697.         runeAreaSpell.areaEffect = NM_ME_STAR;
  9698.         runeAreaSpell.animationColor = 0xD2;
  9699.        
  9700.         runeAreaSpell.minDamage = 150;
  9701.         runeAreaSpell.maxDamage = 200;
  9702.         mana = g_config.MANA_BLETKA_AXE;
  9703.     }
  9704.    
  9705.     // K U N I E C //
  9706.    
  9707.     if (mana > 0)
  9708.     {
  9709.         std::vector<unsigned char> col;
  9710.                
  9711.         col.push_back(0);
  9712.         col.push_back(0);
  9713.         col.push_back(0);
  9714.         runeAreaSpell.areaVec.push_back(col);
  9715.         col.clear();
  9716.         col.push_back(0);
  9717.         col.push_back(1);
  9718.         col.push_back(0);
  9719.         runeAreaSpell.areaVec.push_back(col);
  9720.         col.clear();
  9721.         col.push_back(0);
  9722.         col.push_back(0);
  9723.         col.push_back(0);
  9724.         runeAreaSpell.areaVec.push_back(col);
  9725.              
  9726.         creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  9727.         player->addManaSpent(mana);
  9728.         player->mana -= mana;
  9729.     }
  9730. }
  9731. #endif //ZS_SWORDS
  9732.  
  9733. #ifdef YUR_READABLES
  9734. bool Game::LoadReadables()
  9735. {
  9736.     std::string file = g_config.getGlobalString("datadir") + "readables.xml";
  9737.     xmlDocPtr doc;
  9738.     xmlMutexLock(xmlmutex);
  9739.  
  9740.     doc = xmlParseFile(file.c_str());
  9741.     if (!doc)
  9742.         return false;
  9743.  
  9744.     xmlNodePtr root, readableNode;
  9745.     root = xmlDocGetRootElement(doc);
  9746.     if (xmlStrcmp(root->name, (const xmlChar*)"readables"))
  9747.     {
  9748.         xmlFreeDoc(doc);
  9749.         xmlMutexUnlock(xmlmutex);
  9750.         return false;
  9751.     }
  9752.  
  9753.     readableNode = root->children;
  9754.     while (readableNode)
  9755.     {
  9756.         if (strcmp((char*) readableNode->name, "readable") == 0)
  9757.         {
  9758.             int32_t x = atoi((const char*)xmlGetProp(readableNode, (const xmlChar *) "x"));
  9759.             int32_t y = atoi((const char*)xmlGetProp(readableNode, (const xmlChar *) "y"));
  9760.             int32_t z = atoi((const char*)xmlGetProp(readableNode, (const xmlChar *) "z"));
  9761.             std::string text = (const char*)xmlGetProp(readableNode, (const xmlChar *) "text");
  9762.  
  9763.             for (size_t i = 0; i < text.length()-1; i++)    // make real newlines
  9764.                 if (text.at(i) == '\\' && text.at(i+1) == 'n')
  9765.                 {
  9766.                     text[i] = ' ';
  9767.       &