qben360

Untitled

Apr 1st, 2020
201
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 348.90 KB | None | 0 0
  1. //////////////////////////////////////////////////////////////////////
  2. // OpenTibia - an opensource roleplaying game
  3. //////////////////////////////////////////////////////////////////////
  4. // class representing the gamestate
  5. //////////////////////////////////////////////////////////////////////
  6. // This program is free software; you can redistribute it and/or
  7. // modify it under the terms of the GNU General Public License
  8. // as published by the Free Software Foundation; either version 2
  9. // of the License, or (at your option) any later version.
  10. //
  11. // This program is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. // GNU General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU General Public License
  17. // along with this program; if not, write to the Free Software Foundation,
  18. // Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19. //////////////////////////////////////////////////////////////////////
  20.  
  21.  
  22. #include "patch.h"
  23. #include "definitions.h"
  24. #include <string>
  25. #include <sstream>
  26. #include <fstream>
  27. #include <ctime> //You may need to use ctime.h or time.h if this doesn't work.
  28.  
  29. #include <map>
  30. //#include <algorithm>
  31.  
  32. #ifdef __DEBUG_CRITICALSECTION__
  33. #include <iostream>
  34. #include <fstream>
  35. #endif
  36.  
  37. #include <boost/config.hpp>
  38. #include <boost/bind.hpp>
  39.  
  40. using namespace std;
  41.  
  42. #include <stdio.h>
  43. #include "otsystem.h"
  44. #include "items.h"
  45. #include "commands.h"
  46. #include "creature.h"
  47. #include "player.h"
  48. #include "monster.h"
  49. #include "npc.h"
  50. #include "game.h"
  51. #include "tile.h"
  52.  
  53. #include "spells.h"
  54. #include "actions.h"
  55. #include "ioplayer.h"
  56. #include "ioaccount.h"
  57. #include "chat.h"
  58. #include "status.h"
  59.  
  60. #include "luascript.h"
  61. #include "templates.h"
  62. #include "houses.h"
  63. #include "summons.h"
  64. #include "pvparena.h"
  65. #include <ctype.h>
  66. #if defined __EXCEPTION_TRACER__
  67. #include "exception.h"
  68. extern OTSYS_THREAD_LOCKVAR maploadlock;
  69. #endif
  70.  
  71. #define EVENT_CHECKCREATURE          123
  72. #define EVENT_CHECKCREATUREATTACKING 124
  73.  
  74. extern LuaScript g_config;
  75. extern Spells spells;
  76. extern Actions actions;
  77. extern Commands commands;
  78. extern Chat g_chat;
  79. extern xmlMutexPtr xmlmutex;
  80.  
  81. extern std::vector< std::pair<uint32_t, uint32_t> > bannedIPs;
  82.  
  83. GameState::GameState(Game *game, const Range &range)
  84. {
  85.     this->game = game;
  86.     game->getSpectators(range, spectatorlist);
  87. }
  88.  
  89. bool is_poof;
  90.  
  91. #ifdef YUR_PVP_ARENA
  92. bool GameState::isPvpArena(Creature* c)
  93. {
  94.     if (!c)
  95.         return false;
  96.     Tile *tile = game->map->getTile(c->pos);
  97.     return tile && tile->isPvpArena();
  98. }
  99. #endif //YUR_PVP_ARENA
  100.  
  101. #ifdef YUR_RINGS_AMULETS
  102. int32_t GameState::applyAmulets(Player* player, int32_t damage, attacktype_t atype)
  103. {
  104.     if (!player || atype == ATTACK_NONE)
  105.         return damage;
  106.  
  107.     double newDamage = (double)damage;
  108.     Item* necklace = player->getItem(SLOT_NECKLACE);
  109.     Item* ring = player->getItem(SLOT_RING);
  110.     Item* armor = player->getItem(SLOT_ARMOR);
  111.  
  112.     if (necklace && necklace->getCharges() > 0)
  113.     {
  114.         if (necklace->getID() == ITEM_STONE_SKIN_AMULET)
  115.         {
  116.             newDamage *= 0.10;
  117.             necklace->useCharge();
  118.         }
  119.        
  120.         else if (necklace->getID() == ITEM_PROTECTION_AMULET)
  121.         {
  122.             newDamage *= 0.80;
  123.             necklace->useCharge();
  124.         }
  125.        
  126.         else if ((necklace->getID() == ITEM_DRAGON_NECKLACE && (atype & ATTACK_FIRE)) ||
  127.             (necklace->getID() == ITEM_SILVER_AMULET && (atype & ATTACK_POISON)) ||
  128.             (necklace->getID() == ITEM_STRANGE_TALISMAN && (atype & ATTACK_ENERGY)) ||
  129.             (necklace->getID() == ITEM_ELVEN_AMULET))
  130.         {
  131.             newDamage *= 0.8;
  132.             necklace->useCharge();
  133.         }
  134.        
  135.        
  136.         else if ((necklace->getID() == ITEM_MAGMA_AMULET && (atype & ATTACK_FIRE)))
  137.         {
  138.             newDamage *= 0.7;
  139.             necklace->useCharge();
  140.         }
  141.        
  142.        
  143.  #ifdef YUR_DRAINS
  144.         else if (necklace->getID() == ITEM_BRONZE_AMULET && (atype & ATTACK_MANADRAIN))
  145.         {
  146.             newDamage *= 0.5;
  147.             necklace->useCharge();
  148.         }
  149.        
  150.         else if (necklace->getID() == ITEM_GARLIC_NECKLACE && (atype & ATTACK_LIFEDRAIN))
  151.         {
  152.             newDamage = 0.5;
  153.             necklace->useCharge();
  154.         }
  155.        
  156.  #endif //YUR_DRAINS
  157.  
  158.         if (necklace->getCharges() <= 0)
  159.             player->removeItemInventory(SLOT_NECKLACE);
  160.     }
  161.  
  162.     if (ring && ring->getCharges() > 0)
  163.     {
  164.         if (ring->getID() == ITEM_MIGHT_RING)
  165.         {
  166.             newDamage *= 0.8;
  167.             ring->useCharge();
  168.         }
  169.  
  170.         if (ring->getCharges() <= 0)
  171.             player->removeItemInventory(SLOT_RING);
  172.     }
  173. #ifdef HUCZU_FIX
  174.     if(armor)
  175.     {
  176.        if(armor->getID() == ITEM_FIRE_ARMOR && (atype & ATTACK_FIRE))
  177.          newDamage *= 0.8;
  178.     }
  179. #endif //HUCZU_FIX
  180.  
  181.     return (int32_t)newDamage;
  182. }
  183. #endif //YUR_RINGS_AMULETS
  184.  
  185. void GameState::onAttack(Creature* attacker, const Position& pos, const MagicEffectClass* me)
  186. {
  187.     Tile *tile = game->map->getTile(pos);
  188.  
  189.     if(!tile)
  190.         return;
  191.  
  192. #ifdef YUR_PVP_ARENA
  193.     CreatureVector arenaLosers;
  194. #endif //YUR_PVP_ARENA
  195.  
  196.     CreatureVector::iterator cit;
  197.     Player* attackPlayer = dynamic_cast<Player*>(attacker);
  198.     Creature *targetCreature = NULL;
  199.     Player *targetPlayer = NULL;
  200.     for(cit = tile->creatures.begin(); cit != tile->creatures.end(); ++cit) {
  201.         targetCreature = (*cit);
  202.         targetPlayer = dynamic_cast<Player*>(targetCreature);
  203.         bool pvpArena = false;
  204. #ifdef TR_SUMMONS
  205.         bool targetIsSummon = (targetCreature && targetCreature->isPlayersSummon());
  206.         bool summonVsPlayer = (attacker && attacker->isPlayersSummon() && targetPlayer);
  207. #endif //TR_SUMMONS
  208.  
  209.         int32_t damage = me->getDamage(targetCreature, attacker);
  210.         int32_t manaDamage = 0;
  211.        
  212.         if(attackPlayer){
  213.         if(!me->offensive && me->minDamage != 0 && g_config.getGlobalString("showHealingDamage") == "yes"){
  214.              int32_t lecz = std::min(std::abs(damage), attackPlayer->healthmax - attackPlayer->health);
  215.              std::stringstream anidamage;
  216.                 anidamage << "+" << lecz;
  217.                   if(lecz != 0)
  218.                      game->sendAnimatedTextExt(attackPlayer->pos, 96, anidamage.str().c_str());    
  219.         }
  220.         }
  221.  
  222. #ifdef YUR_RINGS_AMULETS
  223.         damage = applyAmulets(targetPlayer, damage, me->attackType);
  224. #endif //YUR_RINGS_AMULETS
  225.  
  226.         if (damage > 0) {
  227.             if(attackPlayer && attackPlayer->access < g_config.ACCESS_PROTECT) {
  228.                 if(targetPlayer && targetPlayer != attackPlayer && game->getWorldType() != WORLD_TYPE_NO_PVP)
  229.                     attackPlayer->pzLocked = true;
  230.             }  
  231.                
  232. if(targetCreature->access < g_config.ACCESS_PROTECT && targetPlayer && game->getWorldType() != WORLD_TYPE_NO_PVP)
  233. {
  234. #ifdef YUR_CVS_MODS
  235.                 targetPlayer->inFightTicks = std::max(g_config.PZ_LOCKED, targetPlayer->inFightTicks);
  236. #else
  237.                 targetPlayer->inFightTicks = g_config.PZ_LOCKED;
  238. #endif //YUR_CVS_MODS
  239.                 targetPlayer->sendIcons();
  240.             }
  241. #ifdef SURVIVAL_BLACKSQUARE
  242. if(damage > 0 && attackPlayer && targetPlayer && attackPlayer != targetPlayer){
  243. NetworkMessage attackedpmsg;
  244. attackedpmsg.AddPlayerAttacked(attacker);
  245. targetPlayer->sendNetworkMessage(&attackedpmsg);
  246. }
  247. #endif //SURVIVAL_BLACKSQUARE  
  248.  
  249. #ifdef YUR_PVP_ARENA
  250.             pvpArena = isPvpArena(attacker) && isPvpArena(targetCreature);
  251. #endif //YUR_PVP_ARENA
  252.  
  253. #ifdef TR_SUMMONS
  254.             if ((game->getWorldType() == WORLD_TYPE_NO_PVP && !pvpArena && summonVsPlayer) ||
  255.                 (game->getWorldType() == WORLD_TYPE_NO_PVP && !pvpArena && attackPlayer && (targetPlayer || targetIsSummon) && attackPlayer->access < g_config.ACCESS_PROTECT)) {
  256. #else
  257.             if(game->getWorldType() == WORLD_TYPE_NO_PVP && !pvpArena && attackPlayer && targetPlayer && attackPlayer->access < ACCESS_PROTECT){
  258. #endif //TR_SUMMONS
  259.                 damage = 0;
  260.             }
  261.         }
  262.  
  263.         if (damage != 0)
  264.         {
  265. // Bedzie pro ustawione all
  266. #ifdef HUCZU_FIX
  267.           if(attackPlayer){
  268.            Item* armor = attackPlayer->getItem(SLOT_ARMOR);
  269.            Item* legs = attackPlayer->getItem(SLOT_LEGS);
  270.            Item* helmet = attackPlayer->getItem(SLOT_HEAD);
  271.            Item* boots = attackPlayer->getItem(SLOT_FEET);
  272.            Item* ring = attackPlayer->getItem(SLOT_RING);
  273.            Item* amulet = attackPlayer->getItem(SLOT_NECKLACE);
  274.            
  275.             if(attackPlayer->vocation == 1 || attackPlayer->vocation == 2){
  276.               if(armor){
  277.                 if(armor->getID() == ITEM_GLACIER_ROBE){
  278.                     double newdamage = damage*2/100.0;
  279.                     damage += (int32_t)newdamage;
  280.                 }
  281.                 else if(armor->getID() == ITEM_ARCHMAGE_COAT){
  282.                     double newdamage = damage*5/100.0;
  283.                     damage += (int32_t)newdamage;
  284.                 }
  285.                 else if(armor->getID() == ITEM_BMC){
  286.                     double newdamage = damage*3/100.0;
  287.                     damage += (int32_t)newdamage;
  288.                 }
  289.               }
  290.               if(legs){
  291.                if(legs->getID() == ITEM_GLACIER_KIT){
  292.                  double newdamage = damage*2/100.0;
  293.                  damage += (int32_t)newdamage;
  294.                }                                
  295.               }
  296.             }    
  297.            
  298.             if(legs){
  299.                if(legs->getID() == ITEM_ZS_LEGS){
  300.                  double newdamage = damage*10/100.0;
  301.                  damage += (int32_t)newdamage;
  302.                }                                
  303.             }
  304.            
  305.             if(g_config.MGITEMS){
  306.                 if(helmet && helmet->getID() == g_config.MGITEMHELMET){
  307.                     double newdamage = damage*g_config.ITEM_MDOWNHELMET/100.0;
  308.                     damage += (int32_t)newdamage;
  309.                 }
  310.                 if(armor && armor->getID() == g_config.MGITEMARMOR){
  311.                     double newdamage = damage*g_config.ITEM_MDOWNARMOR/100.0;
  312.                     damage += (int32_t)newdamage;
  313.                 }
  314.                 if(legs && legs->getID() == g_config.MGITEMLEGS){
  315.                     double newdamage = damage*g_config.ITEM_MDOWNLEGS/100.0;
  316.                     damage += (int32_t)newdamage;
  317.                 }
  318.                 if(boots && boots->getID() == g_config.MGITEMBOOTS){
  319.                     double newdamage = damage*g_config.ITEM_MDOWNBOOTS/100.0;
  320.                     damage += (int32_t)newdamage;
  321.                 }
  322.                 if(ring && ring->getID() == g_config.MGITEMRINGS){
  323.                     double newdamage = damage*g_config.ITEM_MDOWNRING/100.0;
  324.                     damage += (int32_t)newdamage;
  325.                 }
  326.                 if(amulet && amulet->getID() == g_config.MGITEMAMU){
  327.                     double newdamage = damage*g_config.ITEM_MDOWNAMU/100.0;
  328.                     damage += (int32_t)newdamage;
  329.                 }
  330.            }
  331.           }
  332. #endif //HUCZU_FIX i git w chuj
  333.  
  334. #ifdef YUR_DRAINS
  335.             if (me->attackType & ATTACK_MANADRAIN)
  336.             {
  337.                 manaDamage = std::min(damage, targetCreature->mana);           
  338.                 targetCreature->drainMana(manaDamage);
  339.                 damage = 0;
  340.             }
  341.             else
  342. #endif //YUR_DRAINS
  343.             {
  344.                 game->creatureApplyDamage(targetCreature, damage, damage, manaDamage
  345. #ifdef YUR_PVP_ARENA
  346.                     , (pvpArena? &arenaLosers : NULL)
  347. #endif //YUR_PVP_ARENA
  348.                     );
  349.             }
  350.  
  351. #ifdef YUR_DRAINS
  352.             if (me->attackType & ATTACK_LIFEDRAIN)
  353.             {
  354.                 attacker->health = std::min(attacker->healthmax, attacker->health + damage);
  355.                 addCreatureState(tile, attacker, 0, 0, false);  // update attacker health
  356.             }
  357. #endif //YUR_DRAINS
  358.  
  359. #ifdef YUR_INVISIBLE
  360.             if (targetCreature && !targetPlayer)
  361.             {
  362.                 targetCreature->setInvisible(0);
  363.                 game->creatureChangeOutfit(targetCreature);
  364.             }
  365. #endif //YUR_INVISIBLE
  366.         }
  367.        
  368. #ifdef HUCZU_SKULLS
  369.         if (me->offensive && game->getWorldType() == WORLD_TYPE_PVP)
  370.             game->onPvP(attacker, targetCreature, targetCreature->health <= 0);
  371. #endif
  372.  
  373.         addCreatureState(tile, targetCreature, damage, manaDamage, me->drawblood);
  374.     }
  375.  
  376.     //Solid ground items/Magic items (fire/poison/energy)
  377.     MagicEffectItem *newmagicItem = me->getMagicItem(attacker, tile->isPz(),
  378.         (tile->isBlocking(BLOCK_SOLID, true) != RET_NOERROR));
  379.  
  380.     if(newmagicItem) {
  381.  
  382.         MagicEffectItem *magicItem = tile->getFieldItem();
  383.  
  384.         if(magicItem) {
  385.             //Replace existing magic field
  386.             magicItem->transform(newmagicItem);
  387.  
  388.             int32_t stackpos = tile->getThingStackPos(magicItem);
  389.             if(tile->removeThing(magicItem)) {
  390.  
  391.                 SpectatorVec list;
  392.                 SpectatorVec::iterator it;
  393.  
  394.                 game->getSpectators(Range(pos, true), list);
  395.  
  396.                 //players
  397.                 for(it = list.begin(); it != list.end(); ++it) {
  398.                     if(dynamic_cast<Player*>(*it)) {
  399.                         (*it)->onThingDisappear(magicItem, stackpos);
  400.                     }
  401.                 }
  402.  
  403.                 //none-players
  404.                 for(it = list.begin(); it != list.end(); ++it) {
  405.                     if(!dynamic_cast<Player*>(*it)) {
  406.                         (*it)->onThingDisappear(magicItem, stackpos);
  407.                     }
  408.                 }
  409.  
  410.                 tile->addThing(magicItem);
  411.  
  412.                 //players
  413.                 for(it = list.begin(); it != list.end(); ++it) {
  414.                     if(dynamic_cast<Player*>(*it)) {
  415.                         (*it)->onThingAppear(magicItem);
  416.                     }
  417.                 }
  418.  
  419.                 //none-players
  420.                 for(it = list.begin(); it != list.end(); ++it) {
  421.                     if(!dynamic_cast<Player*>(*it)) {
  422.                         (*it)->onThingAppear(magicItem);
  423.                     }
  424.                 }
  425.             }
  426.         }
  427.         else {
  428.             magicItem = new MagicEffectItem(*newmagicItem);
  429.             magicItem->useThing();
  430.             magicItem->pos = pos;
  431.  
  432.             tile->addThing(magicItem);
  433.  
  434.             SpectatorVec list;
  435.             SpectatorVec::iterator it;
  436.  
  437.             game->getSpectators(Range(pos, true), list);
  438.  
  439.             //players
  440.             for(it = list.begin(); it != list.end(); ++it) {
  441.                 if(dynamic_cast<Player*>(*it)) {
  442.                     (*it)->onThingAppear(magicItem);
  443.                 }
  444.             }
  445.  
  446.             //none-players
  447.             for(it = list.begin(); it != list.end(); ++it) {
  448.                 if(!dynamic_cast<Player*>(*it)) {
  449.                     (*it)->onThingAppear(magicItem);
  450.                 }
  451.             }
  452.  
  453.             magicItem->isRemoved = false;
  454.             game->startDecay(magicItem);
  455.         }
  456.     }
  457.  
  458.     //Clean up
  459.     for(CreatureStateVec::const_iterator csIt = creaturestates[tile].begin(); csIt != creaturestates[tile].end(); ++csIt) {
  460.         onAttackedCreature(tile, attacker, csIt->first, csIt->second.damage, csIt->second.drawBlood);
  461.     }
  462.  
  463.     if(attackPlayer && attackPlayer->access < g_config.ACCESS_PROTECT) {
  464.         //Add exhaustion
  465.         if(me->causeExhaustion(true) /*!areaTargetVec.empty())*/)
  466.         {
  467.                 attackPlayer->exhaustedTicks = g_config.EXHAUSTED;
  468.         }
  469.  
  470.         //Fight symbol
  471.         if(me->offensive /*&& !areaTargetVec.empty()*/)
  472.         {
  473. #ifdef YUR_CVS_MODS
  474.             attackPlayer->inFightTicks = std::max(g_config.PZ_LOCKED, attackPlayer->inFightTicks);
  475. #else
  476.             attackPlayer->inFightTicks = g_config.PZ_LOCKED;
  477. #endif //YUR_CVS_MODS
  478.         }
  479.     }
  480.  
  481. #ifdef YUR_PVP_ARENA
  482.     for (CreatureVector::iterator it = arenaLosers.begin(); it != arenaLosers.end(); ++it)
  483.     {
  484.         Tile* tile = game->getTile((*it)->pos);
  485.                
  486.         if (tile)
  487.         {
  488.             game->teleport(*it, tile->getPvpArenaExit());  
  489.         }
  490.        
  491.         if(Monster* monster = dynamic_cast<Monster*>(*it))
  492.         {
  493.             if(Tile *tile = game->map->getTile(monster->pos))
  494.             {    
  495.                 if(tile->isPvpArena())
  496.                 {
  497.                     game->removeCreature(monster);
  498.                 }
  499.             }
  500.         }
  501.     }
  502. #endif //YUR_PVP_ARENA
  503. }
  504.  
  505. void GameState::onAttack(Creature* attacker, const Position& pos, Creature* attackedCreature)
  506. {
  507.     bool pvpArena = false;
  508. #ifdef YUR_PVP_ARENA
  509.     CreatureVector arenaLosers;
  510.     pvpArena = isPvpArena(attacker) && isPvpArena(attackedCreature);
  511. #endif //YUR_PVP_ARENA
  512.  
  513.     //TODO: Decent formulas and such...
  514.     int32_t damage = attacker->getWeaponDamage();
  515.     int32_t armor = attackedCreature->getArmor();
  516.     int32_t defense = attackedCreature->getDefense();
  517.  
  518.     Player* attackPlayer = dynamic_cast<Player*>(attacker);
  519.     Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  520.  
  521.     if(attackedPlayer)
  522.         attackedPlayer->addSkillShieldTry(1);
  523.  
  524.     int32_t probability = rand() % 10000;
  525.  
  526. #ifdef YUR_CVS_MODS
  527.     if(probability * damage < defense * 3000)
  528.         damage = 0;
  529.     else
  530.         damage -= (int32_t)((damage*(armor/50.0)*(rand()/(RAND_MAX+1.0))) + (armor*2) + defense/1.5);
  531.         //damage -= (int32_t)((armor)*(rand()/(RAND_MAX+1.0))) + armor; // wik's
  532. #else
  533.     if(probability * damage < defense * 10000)
  534.         damage = 0;
  535.     else
  536.     {
  537.         damage -= (armor * (10000 + rand() % 10000)) / 10000;
  538.     }
  539. #endif //YUR_CVS_MODS
  540.  
  541.     int32_t manaDamage = 0;
  542.  
  543.     if(attackPlayer && attackedPlayer){
  544.         damage -= (int32_t) damage / 2;
  545.     }
  546.  
  547.  
  548.     if (attacker->access >= g_config.ACCESS_PROTECT)
  549.         damage += 1;
  550.  
  551.  
  552.     Tile* tile = game->map->getTile(pos);
  553.     bool blood;
  554.     if(damage > 0)
  555.     {
  556.               // F-AXE,F-SWORD,P-DAGGER
  557.               if(attackPlayer)
  558. {
  559.    for (int32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++)
  560.    {
  561.         if(g_config.EFFECT_ATACK && attackPlayer->getItem(slot) && (attackPlayer->getItem(slot)->getID() == ITEM_FAXE || attackPlayer->getItem(slot)->getID() == ITEM_FSWORD))
  562.         {
  563.              game->CreateCondition(attackedCreature, attacker, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 5, 5, 2000, 1);      
  564.         }
  565.        if(g_config.EFFECT_ATACK && attackPlayer->getItem(slot) && (attackPlayer->getItem(slot)->getID() == ITEM_PD))
  566.         {
  567.              game->CreateCondition(attackedCreature, attacker, 30, NM_ME_POISEN_RINGS, NM_ME_POISEN_RINGS, ATTACK_POISON, true, 5, 5, 2000, 3);
  568.         }
  569.    }
  570. }
  571.  
  572. // P-BOLT ENERGY
  573.    if(attackPlayer)
  574.                    {
  575.    int32_t slot = SLOT_AMMO;
  576. if(g_config.EFFECT_ATACK && attackPlayer->getItem(slot) && (attackPlayer->getItem(slot)->getID() == 5260))
  577. {
  578. game->CreateCondition(attackedCreature, attacker, 35, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 10, 10, 2000, 1);      
  579. }
  580. }
  581.  
  582. #ifdef YUR_ICE_RAPIER
  583.         if (attackPlayer)
  584.             for (int32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++)
  585.                 if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->getID() == ITEM_ICE_RAPIER)
  586.                     attackPlayer->removeItemInventory(slot);
  587. #endif //YUR_ICE_RAPIER
  588.  
  589. #ifdef PALL_REQ_LVL
  590.         if (attackPlayer){
  591.           for (int32_t slot = SLOT_RIGHT; slot <= SLOT_LEFT; slot++){
  592.           if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->isWeapon() && attackPlayer->getItem(slot)->getReqLevel() > attackPlayer->getLevel())
  593.           {
  594.             int32_t newdamage = attackPlayer->getWeaponDamage() / random_range(4, 7);
  595.              if (attackPlayer->getWeaponDamage() >= 7)
  596.                 damage = 0;
  597.              else
  598.                 damage = newdamage;
  599.           }
  600.           if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->getAmuType() != 0 && attackPlayer->getItem(slot)->getReqLevel() > attackPlayer->getLevel())
  601.           {
  602.             int32_t newdamage = attackPlayer->getWeaponDamage() / random_range(4, 7);
  603.              if (attackPlayer->getWeaponDamage() >= 7)
  604.                 damage = 0;
  605.              else    
  606.                 damage = newdamage;
  607.           }
  608.           if(attackPlayer->getItem(slot) && attackPlayer->getItem(slot)->isWeapon() && attackPlayer->getItem(slot)->getReqVoc() != attackPlayer->getVocation() && attackPlayer->getItem(slot)->getReqVoc() > 0)
  609.           {
  610.             int32_t newdamage = attackPlayer->getWeaponDamage() / random_range(4, 9);
  611.              if (attackPlayer->getWeaponDamage() >= 7)
  612.                 damage = 0;
  613.              else
  614.                 damage = newdamage;
  615.           }
  616.           }
  617.         }
  618. #endif //PALL_REQ_LVL
  619.  
  620. if(attackPlayer && attackPlayer->getVocation() == VOCATION_PALADIN) {
  621.     std::cout << "Before Pall atk: " << damage << std::endl;
  622.     damage += damage * (0.01 * (double)g_config.PALADIN_RAISE);
  623.     std::cout << "After Pall atk: " << damage << std::endl;
  624. }
  625. if(attackPlayer && attackPlayer->getVocation() == VOCATION_KNIGHT) {
  626.     std::cout << "Before Knight atk: " << damage << std::endl;
  627.     damage *= 0.5;
  628.     std::cout << "After Knight atk: " << damage << std::endl;
  629. }
  630. #ifdef YUR_RINGS_AMULETS
  631.         damage = applyAmulets(attackedPlayer, damage, ATTACK_PHYSICAL);
  632. #endif //YUR_RINGS_AMULETS
  633.  
  634.  
  635. #ifdef CHRIS_CRIT_HIT
  636. if(attackPlayer){
  637.     int32_t critcial_hit;
  638.     int32_t rand_hit = random_range(0, 700);
  639.     switch(rand_hit){
  640.         case 75:
  641.             critcial_hit = random_range(50, 100);
  642.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  643.         break;
  644.         case 87:
  645.             critcial_hit = random_range(50, 100);
  646.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  647.         break;
  648.         case 95:
  649.             critcial_hit = random_range(50, 100);
  650.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  651.         break;
  652.         case 113:
  653.             critcial_hit = random_range(80, 130);
  654.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  655.         break;
  656.         case 128:
  657.             critcial_hit = random_range(80, 130);
  658.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  659.         break;
  660.         case 133:
  661.             critcial_hit = random_range(80, 130);
  662.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  663.         break;
  664.         case 145:
  665.             critcial_hit = random_range(80, 130);
  666.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  667.         break;
  668.         case 157:
  669.             critcial_hit = random_range(80, 130);
  670.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  671.         break;
  672.         case 167:
  673.             critcial_hit = random_range(80, 130);
  674.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  675.         break;
  676.         case 187:
  677.             critcial_hit = random_range(80, 130);
  678.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  679.         break;
  680.         case 195:
  681.             critcial_hit = random_range(80, 130);
  682.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  683.         break;
  684.         case 202:
  685.             critcial_hit = random_range(110, 160);
  686.                if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  687.         break;
  688.         case 225:
  689.             critcial_hit = random_range(110, 160);
  690.                if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  691.         break;
  692.         case 238:
  693.             critcial_hit = random_range(110, 160);
  694.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  695.         break;
  696.         case 245:
  697.             critcial_hit = random_range(110, 160);
  698.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  699.         break;
  700.         case 268:
  701.             critcial_hit = random_range(110, 160);
  702.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  703.         break;
  704.         case 287:
  705.             critcial_hit = random_range(110, 160);
  706.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  707.         break;
  708.         case 298:
  709.             critcial_hit = random_range(110, 160);
  710.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  711.         break;
  712.         case 324:
  713.             critcial_hit = random_range(140, 400);
  714.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  715.         break;
  716.         case 356:
  717.             critcial_hit = random_range(140, 190);
  718.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  719.         break;
  720.         case 371:
  721.             critcial_hit = random_range(140, 190);
  722.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  723.         break;
  724.         case 380:
  725.             critcial_hit = random_range(140, 190);
  726.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  727.         break;
  728.         case 397:
  729.             critcial_hit = random_range(140, 190);
  730.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  731.         break;
  732.         case 399:
  733.             critcial_hit = random_range(140, 190);
  734.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  735.         break;
  736.         case 400:
  737.             critcial_hit = random_range(170, 210);
  738.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  739.         break;
  740.         case 428:
  741.             critcial_hit = random_range(170, 210);
  742.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  743.         break;
  744.         case 432:
  745.             critcial_hit = random_range(170, 210);
  746.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  747.         break;
  748.         case 444:
  749.             critcial_hit = random_range(170, 210);
  750.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  751.         break;
  752.         case 474:
  753.             critcial_hit = random_range(170, 210);
  754.                 if (attackPlayer->vocation == 4)(game->sendAnimatedTextExt(attackPlayer->pos, 180, "CRITICAL"));
  755.         break;
  756.         default:
  757.             critcial_hit = 0;
  758.         break;
  759.     }
  760.  
  761. if (attackPlayer->vocation == 4){
  762.   if(critcial_hit != 0){
  763.      if(attackPlayer->level >= 150){                  
  764.        if(attackPlayer && attackPlayer->items[SLOT_RIGHT] && attackPlayer->items[SLOT_RIGHT]->getID() == ITEM_RAINBOW){
  765.          if(attackPlayer->items[SLOT_LEFT]){
  766.            if(attackPlayer->items[SLOT_LEFT]->getID() != ITEM_RAINBOW)
  767.              critcial_hit += critcial_hit*(25/100);
  768.              game->CreateCondition(attackedCreature, attacker, 35, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 25, 25, 1000, 1);
  769.           }
  770.          }
  771.         }
  772.         if(attackPlayer && attackPlayer->items[SLOT_LEFT] && attackPlayer->items[SLOT_LEFT]->getID() == ITEM_RAINBOW){
  773.           if(attackPlayer->items[SLOT_RIGHT]){
  774.             if(attackPlayer->items[SLOT_RIGHT]->getID() != ITEM_RAINBOW)
  775.               critcial_hit += critcial_hit*(25/100);
  776.               game->CreateCondition(attackedCreature, attacker, 35, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 25, 25, 1000, 1);
  777.            }
  778.           }
  779.          }
  780.    damage += critcial_hit;
  781.   }
  782. }
  783.  
  784. #endif //CHRIS_CRIT_HIT
  785.  
  786.         game->creatureApplyDamage(attackedCreature, damage, damage, manaDamage
  787.        
  788.  
  789. #ifdef YUR_PVP_ARENA
  790.             , (pvpArena? &arenaLosers : NULL)
  791. #endif //YUR_PVP_ARENA
  792.             );
  793.  
  794. #ifdef HUCZU_SKULLS
  795.             if (game->getWorldType() == WORLD_TYPE_PVP)
  796.             game->onPvP(attacker, attackedCreature, attackedCreature->health <= 0);
  797. #endif
  798.  
  799.         blood = true;
  800.        
  801.      if(attackPlayer && attackPlayer->maxDmg < damage) {
  802.        attackPlayer->maxDmg = (int32_t) damage;
  803.        std::stringstream MaxDmgMsg;
  804.        MaxDmgMsg << "Your new best damage is " <<  attackPlayer->maxDmg << ".";
  805.        attackPlayer->sendTextMessage(MSG_ADVANCE, MaxDmgMsg.str().c_str());
  806.      }
  807.     }
  808.     else{//no draw blood
  809.         blood = false;
  810.     }
  811.  
  812.     addCreatureState(tile, attackedCreature, damage, manaDamage, blood);
  813.     onAttackedCreature(tile, attacker, attackedCreature, damage,  true);
  814.  
  815. /*
  816.     if (attackPlayer && attackPlayer->isUsingSpears() && random_range(1,100000) > g_config.SPEAR_LOSE_CHANCE)
  817.     {
  818.         Item* spear = Item::CreateItem(ITEM_SPEAR, 1);
  819.         spear->pos = attackedCreature->pos;
  820.         game->addThing(attackPlayer, spear->pos, spear);
  821.     }
  822. */
  823.  
  824. #ifdef YUR_PVP_ARENA
  825.     for (CreatureVector::iterator it = arenaLosers.begin(); it != arenaLosers.end(); ++it){
  826.         Tile* tile = game->getTile((*it)->pos);
  827.         if (tile){
  828.             game->teleport(*it, tile->getPvpArenaExit());  
  829.         }
  830.         if(Monster* monster = dynamic_cast<Monster*>(*it)){
  831.             if(Tile *tile = game->map->getTile(monster->pos)){    
  832.                 if(tile->isPvpArena()){
  833.                     game->removeCreature(monster);
  834.                 }
  835.             }
  836.         }
  837.     }
  838. #endif //YUR_PVP_ARENA
  839. }
  840.  
  841. void GameState::addCreatureState(Tile* tile, Creature* attackedCreature, int32_t damage, int32_t manaDamage, bool drawBlood)
  842. {
  843.     CreatureState cs;
  844.     cs.damage = damage;
  845.     cs.manaDamage = manaDamage;
  846.     cs.drawBlood = drawBlood;
  847.  
  848.     creaturestates[tile].push_back( make_pair(attackedCreature, cs) );
  849. }
  850.  
  851. void GameState::onAttackedCreature(Tile* tile, Creature *attacker, Creature* attackedCreature, int32_t damage, bool drawBlood)
  852. {
  853.     Player *attackedplayer = dynamic_cast<Player*>(attackedCreature);
  854.     Position CreaturePos = attackedCreature->pos;
  855.  
  856. #ifdef TJ_MONSTER_BLOOD
  857.     bool dead = false;
  858. #endif //TJ_MONSTER_BLOOD
  859.  
  860. #ifdef TR_SUMMONS
  861. //Summon exp share by Yurez
  862.  Player *player = dynamic_cast<Player*>(attacker);
  863.  Creature* attackerMaster = attacker? attacker->getMaster() : NULL;
  864.     if(attackerMaster && dynamic_cast<Player*>(attackerMaster)){//attacker is players summon
  865.         attackedCreature->addInflictedDamage(attacker, damage/2);
  866.         attackedCreature->addInflictedDamage(attackerMaster, damage/2);  
  867.     }// end summon exp share
  868.     else if(player && player->party != 0){
  869.          int32_t partySize = 0;
  870.          SpectatorVec list;
  871.          SpectatorVec::iterator it;
  872.          game->getSpectators(Range(player->pos), list);
  873.          /*Get all specatators around this player
  874.            then check if they are in his party*/
  875.          for(it = list.begin(); it != list.end(); ++it){//find number too div by
  876.             Player* p = dynamic_cast<Player*>(*it);
  877.          if(p && p->party == player->party)//huczu_fix
  878.                partySize++;
  879.          }
  880.          for(it = list.begin(); it != list.end(); ++it){
  881.          Player* p = dynamic_cast<Player*>(*it);
  882.          if(p && p->party == player->party && partySize != 0/*dont div by 0*/)//same party add exp, huczu_fix
  883.             attackedCreature->addInflictedDamage(p, damage/partySize);
  884.          }
  885.     }
  886.     else
  887.         attackedCreature->addInflictedDamage(attacker, damage);
  888. #endif //TR_SUMMONS
  889.  
  890.     if(attackedplayer){
  891.         attackedplayer->sendStats();
  892.     }
  893.     //Remove player?
  894.     if(attackedCreature->health <= 0 && attackedCreature->isRemoved == false)
  895.     {
  896. #ifdef TJ_MONSTER_BLOOD
  897.         dead = true;
  898. #endif //TJ_MONSTER_BLOOD
  899. #ifdef JD_DEATH_LIST
  900.         if (attackedplayer && attacker)
  901.             attackedplayer->addDeath(attacker->getName(), attackedplayer->level, time(0));
  902. #endif //JD_DEATH_LIST
  903.         unsigned char stackpos = tile->getThingStackPos(attackedCreature);
  904.  
  905.  
  906. //tasksys                                  
  907.                             Player* attackingplayer = dynamic_cast<Player*>(attacker);                                    
  908.                             if(attackingplayer && attackedCreature->getName() == attackingplayer->taskmonster && attackingplayer->taskcount < attackingplayer->taskmax)
  909.               {
  910. //                              attackingplayer->taskcount++;
  911.                 std::stringstream info;      
  912.                 std::string mons = attackingplayer->taskmonster;
  913.                 std::transform(mons.begin(), mons.end(), mons.begin(), (int(*)(int))tolower);
  914.                                
  915.                                 if(attackingplayer->taskcount < attackingplayer->taskmax)
  916.                                 {
  917.                                     info << "You have killed " << attackingplayer->taskcount << " out of " << attackingplayer->taskmax << " " << mons << "s.";
  918.                                 }
  919.                                 else
  920.                                 {
  921.                                     info << "You have finished task of killing " << mons << "s. ";
  922.                                 }
  923.                                
  924. //                              attackingplayer->sendTextMessage(MSG_ORANGE, info.str().c_str());
  925.               }
  926.                             //tasksys
  927.  
  928.         //Prepare body
  929.         Item *corpseitem = Item::CreateItem(attackedCreature->getLookCorpse());
  930.         corpseitem->pos = CreaturePos;
  931.         tile->addThing(corpseitem);
  932.        
  933.         #ifdef _DEATH_EVENTS
  934.         if (!attackedplayer)
  935.         {
  936.             Monster* monster = dynamic_cast<Monster*>(attackedCreature);
  937.             Player* killer = dynamic_cast<Player*>(attacker);
  938.  
  939.             if (killer && monster && monster->getAction())
  940.             {
  941.                 actions.onCreatureKill(killer, attackedCreature, corpseitem, monster->getAction());
  942.             }
  943.  
  944.         }
  945. #endif //_DEATH_EVENTS
  946.        
  947.         #ifdef __MIZIAK_CREATURESCRIPTS__
  948.             if(dynamic_cast<Player*>(attacker) && attackedCreature)
  949.             actions.creatureEvent("kill", dynamic_cast<Player*>(attacker), attackedCreature, corpseitem, NULL);
  950.         #endif //__MIZIAK_CREATURESCRIPTS__
  951.        
  952.         //remove creature
  953.         if(attackedplayer){
  954.             actions.luaWalkOff(attackedplayer,attackedplayer->pos,tile->ground->getID(),tile->ground->getUniqueId(),tile->ground->getActionId()); //CHANGE onWalk
  955.             attackedplayer->onThingDisappear(attackedplayer,stackpos);
  956.            
  957.             #ifdef __MIZIAK_CREATURESCRIPTS__
  958.             attackedplayer->dieorlogout = true;
  959.             if(attacker)
  960.             actions.creatureEvent("death", attackedplayer, attacker, corpseitem, NULL);
  961.             #endif //__MIZIAK_CREATURESCRIPTS__
  962.  
  963.  
  964.             attackedplayer->die();        //handles exp/skills/maglevel loss
  965.         }
  966.        
  967.         //Add eventual loot
  968.         Container *lootcontainer = dynamic_cast<Container*>(corpseitem);
  969.         if(lootcontainer) {
  970.             attackedCreature->dropLoot(lootcontainer);
  971.            
  972.             #ifdef HUCZU_LOOT_INFO
  973.             Monster* monster = dynamic_cast<Monster*>(attackedCreature);
  974.             Player* atakujacy = dynamic_cast<Player*>(attacker);
  975.             if(monster && atakujacy){
  976.                 std::stringstream ss, info;
  977.                 //info << "Loot of " << monster->getName() << lootcontainer->getContentDescription() << ".";
  978.                 info << "Loot of " << monster->getName();
  979.                 ss << lootcontainer->getContentDescription() << ".";
  980.                 if(atakujacy->party != 0){
  981.                     for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  982.                         if((*it).second->party == atakujacy->party){
  983.                             if((*it).second->getID() != atakujacy->getID()){
  984.                                 (*it).second->sendToSpecialChannel(atakujacy, SPEAK_CHANNEL_O, ss.str().c_str(), 0x02, info.str().c_str());
  985.                                 //(*it).second->sendTextMessage(MSG_INFO, info.str().c_str());
  986.                             }
  987.                         }
  988.                     }
  989.                 }else{
  990.                     //atakujacy->sendTextMessage(MSG_INFO, info.str().c_str());
  991.                     atakujacy->sendToSpecialChannel(atakujacy, SPEAK_CHANNEL_O, ss.str().c_str(), 0x02, info.str().c_str());
  992.                 }
  993.             }
  994.             #endif //HUCZU_LOOT_INFO
  995.         }
  996.  
  997.         #ifdef HUCZU_MONSTER_QUEST
  998.         Monster* monster = dynamic_cast<Monster*>(attackedCreature);
  999.         Player* atakujacy = dynamic_cast<Player*>(attacker);
  1000.         int32_t value, kills;
  1001.        
  1002.         if(monster && atakujacy && monster->getQuestId() != 0){
  1003.                    
  1004.            if(monster->getQuestId() == 2 && atakujacy->getStorageValue(100, value) == 1){
  1005.              int32_t killsprzed = atakujacy->getQuestKills(2);
  1006.              atakujacy->addQuestKills(2, killsprzed+1);
  1007.            }
  1008.            
  1009.         }
  1010.         #endif //HUCZU_MONSTER_QUEST
  1011.  
  1012.  
  1013.         game->removeCreature(attackedCreature);
  1014.         // Update attackedCreature pos because contains
  1015.         //  temple position for players
  1016.         attackedCreature->pos = CreaturePos;
  1017.  
  1018.         //add body
  1019.         game->sendAddThing(NULL,corpseitem->pos,corpseitem);
  1020.  
  1021.         if(attackedplayer){
  1022.             std::stringstream ss;
  1023.             ss << corpseitem->getDescription(false);
  1024.  
  1025.             ss << "You recognize " << attackedplayer->getName() << ". ";
  1026.             if(attacker){
  1027.                 ss << (attackedplayer->getSex() == PLAYERSEX_FEMALE ? "She" : "He") << " was killed by ";
  1028.  
  1029.                 Player *attackerplayer = dynamic_cast<Player*>(attacker);
  1030.                 if(attackerplayer) {
  1031.                     ss << attacker->getName();
  1032.                 }
  1033.                 else {
  1034.                     std::string creaturename = attacker->getName();
  1035.                     std::transform(creaturename.begin(), creaturename.end(), creaturename.begin(), (int32_t(*)(int32_t))tolower);
  1036.                     ss << article(creaturename);
  1037.                 }
  1038.             }
  1039.  
  1040.             //set body special description
  1041.             corpseitem->setSpecialDescription(ss.str());
  1042.             //send corpse to the dead player. It is not in spectator list
  1043.             // because was removed
  1044.             attackedplayer->onThingAppear(corpseitem);
  1045.         }
  1046.         game->startDecay(corpseitem);
  1047.  
  1048.         //Get all creatures that will gain xp from this kill..
  1049.         CreatureState* attackedCreatureState = NULL;
  1050.         std::vector<long> creaturelist;
  1051.        
  1052.             if(!(dynamic_cast<Player*>(attackedCreature) && game->getWorldType() != WORLD_TYPE_PVP_ENFORCED)){
  1053.             creaturelist = attackedCreature->getInflicatedDamageCreatureList();
  1054.             CreatureStateVec& creatureStateVec = creaturestates[tile];
  1055.             for(CreatureStateVec::iterator csIt = creatureStateVec.begin(); csIt != creatureStateVec.end(); ++csIt) {
  1056.                 if(csIt->first == attackedCreature) {
  1057.                     attackedCreatureState = &csIt->second;
  1058.                     break;
  1059.                 }
  1060.             }
  1061.         }
  1062.  
  1063.         if(attackedCreatureState) { //should never be NULL..
  1064.             //Add experience
  1065.             for(std::vector<long>::const_iterator iit = creaturelist.begin(); iit != creaturelist.end(); ++iit) {
  1066.                 Creature* gainExpCreature = game->getCreatureByID(*iit);
  1067.                 if(gainExpCreature) {
  1068.                     exp_t gainedExperience = attackedCreature->getGainedExperience(gainExpCreature);
  1069.                     if(gainedExperience <= 0)
  1070.                         continue;
  1071.  
  1072.                     Player *gainExpPlayer = dynamic_cast<Player*>(gainExpCreature);
  1073.  
  1074.                     if(gainExpPlayer) {
  1075.                             gainExpPlayer->addExp(gainedExperience);
  1076.                             if(gainExpPlayer && attackedCreature->getName() == gainExpPlayer->taskmonster && gainExpPlayer->taskcount < gainExpPlayer->taskmax)
  1077.               {
  1078.                                 gainExpPlayer->taskcount++;
  1079.                 std::stringstream info;      
  1080.                 std::string mons = gainExpPlayer->taskmonster;
  1081.                 std::transform(mons.begin(), mons.end(), mons.begin(), (int(*)(int))tolower);
  1082.                                
  1083.                                 if(gainExpPlayer->taskcount < gainExpPlayer->taskmax)
  1084.                                 {
  1085.                                     info << "You have killed " << gainExpPlayer->taskcount << " out of " << gainExpPlayer->taskmax << " " << mons << "s.";
  1086.                                 }
  1087.                                 else
  1088.                                 {
  1089.                                     info << "You have finished task of killing " << mons << "s. ";
  1090.                                 }
  1091.                                 gainExpPlayer->sendTextMessage(MSG_ORANGE, info.str().c_str());
  1092.               }
  1093.  
  1094.  
  1095.  
  1096.                     }
  1097.                     //Need to add this creature and all that can see it to spectators, unless they already added
  1098.                     SpectatorVec creaturelist;
  1099.                     game->getSpectators(Range(gainExpCreature->pos, true), creaturelist);
  1100.  
  1101.                     for(SpectatorVec::const_iterator cit = creaturelist.begin(); cit != creaturelist.end(); ++cit) {
  1102.                         if(std::find(spectatorlist.begin(), spectatorlist.end(), *cit) == spectatorlist.end()) {
  1103.                             spectatorlist.push_back(*cit);
  1104.                         }
  1105.                     }
  1106.  
  1107.                     //Add creature to attackerlist
  1108.                     attackedCreatureState->attackerlist.push_back(gainExpCreature);
  1109.                 }
  1110.             }
  1111.         }
  1112.  
  1113.         Player *player = dynamic_cast<Player*>(attacker);
  1114.         if(player){
  1115.             player->sendStats();
  1116.         }
  1117.  
  1118.         if(attackedCreature && attackedCreature->getMaster() != NULL) {
  1119.             attackedCreature->getMaster()->removeSummon(attackedCreature);
  1120.         }
  1121.     }
  1122.  
  1123.  
  1124.     //Add blood?
  1125. #ifdef TJ_MONSTER_BLOOD
  1126.     if((drawBlood || attackedCreature->health <= 0) && damage > 0 && attackedCreature->bloodsplash != 255) {
  1127.         Item* splash = Item::CreateItem(dead? ITEM_POOL : ITEM_SPLASH, attackedCreature->bloodsplash);
  1128.         game->addThing(NULL, CreaturePos, splash);
  1129.         game->startDecay(splash);
  1130.         game->updateTile(CreaturePos);
  1131.     }
  1132. #else
  1133.     if((drawBlood || attackedCreature->health <= 0) && damage > 0) {
  1134.         Item* splash = Item::CreateItem(ITEM_SPLASH, FLUID_BLOOD);
  1135.         game->addThing(NULL, CreaturePos, splash);
  1136.         game->startDecay(splash);
  1137.         game->updateTile(CreaturePos);
  1138.     }
  1139. #endif //TJ_MONSTER_BLOOD
  1140. }
  1141.  
  1142.  
  1143. Game::Game()
  1144. {
  1145.     eventIdCount = 1000;
  1146.     this->game_state = GAME_STATE_NORMAL;
  1147.     this->map = NULL;
  1148.     this->worldType = WORLD_TYPE_PVP;
  1149.     OTSYS_THREAD_LOCKVARINIT(gameLock);
  1150.     OTSYS_THREAD_LOCKVARINIT(eventLock);
  1151.     OTSYS_THREAD_LOCKVARINIT(AutoID::autoIDLock);
  1152. #if defined __EXCEPTION_TRACER__
  1153.     OTSYS_THREAD_LOCKVARINIT(maploadlock);
  1154. #endif
  1155.     OTSYS_THREAD_SIGNALVARINIT(eventSignal);
  1156.     BufferedPlayers.clear();
  1157.     OTSYS_CREATE_THREAD(eventThread, this);
  1158.  
  1159. #ifdef __DEBUG_CRITICALSECTION__
  1160.     OTSYS_CREATE_THREAD(monitorThread, this);
  1161. #endif
  1162.  
  1163.     addEvent(makeTask(DECAY_INTERVAL, boost::bind(&Game::checkDecay,this,DECAY_INTERVAL)));
  1164.  
  1165. #ifdef CVS_DAY_CYCLE
  1166.     int32_t daycycle = 3600;
  1167.     light_hour_delta = 1440*10/daycycle;
  1168.     light_hour = 0;
  1169.     lightlevel = LIGHT_LEVEL_NIGHT;
  1170.     light_state = LIGHT_STATE_NIGHT;
  1171.     addEvent(makeTask(10000, boost::bind(&Game::checkLight, this, 10000)));
  1172. #endif //CVS_DAY_CYCLE
  1173. }
  1174.  
  1175.  
  1176. Game::~Game()
  1177. {
  1178.     if(map) {
  1179.         delete map;
  1180.     }
  1181. }
  1182.  
  1183. void Game::setWorldType(enum_world_type type)
  1184. {
  1185.     this->worldType = type;
  1186. }
  1187.  
  1188. enum_game_state Game::getGameState()
  1189. {
  1190.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::getGameState()");
  1191.     return game_state;
  1192. }
  1193.  
  1194. int32_t Game::loadMap(std::string filename, std::string filekind) {
  1195.     if(!map)
  1196.         map = new Map;
  1197.  
  1198.     max_players = atoi(g_config.getGlobalString("maxplayers").c_str());
  1199.     distanceToKill = atoi(g_config.getGlobalString("dist", "50").c_str());
  1200.     return map->loadMap(filename, filekind);
  1201. }
  1202.  
  1203.  
  1204.  
  1205. /*****************************************************************************/
  1206.  
  1207. #ifdef __DEBUG_CRITICALSECTION__
  1208.  
  1209. OTSYS_THREAD_RETURN Game::monitorThread(void *p)
  1210. {
  1211.   Game* _this = (Game*)p;
  1212.  
  1213.     while (true) {
  1214.         OTSYS_SLEEP(6000);
  1215.  
  1216.         int32_t ret = OTSYS_THREAD_LOCKEX(_this->gameLock, 60 * 2 * 1000);
  1217.         if(ret != OTSYS_THREAD_TIMEOUT) {
  1218.             OTSYS_THREAD_UNLOCK(_this->gameLock, NULL);
  1219.             continue;
  1220.         }
  1221.  
  1222.         bool file = false;
  1223.         std::ostream *outdriver;
  1224.         std::cout << "Error: generating critical section file..." <<std::endl;
  1225.         std::ofstream output("deadlock.txt",std::ios_base::app);
  1226.         if(output.fail()){
  1227.             outdriver = &std::cout;
  1228.             file = false;
  1229.         }
  1230.         else{
  1231.             file = true;
  1232.             outdriver = &output;
  1233.         }
  1234.  
  1235.         time_t rawtime;
  1236.         time(&rawtime);
  1237.         *outdriver << "*****************************************************" << std::endl;
  1238.         *outdriver << "Error report - " << std::ctime(&rawtime) << std::endl;
  1239.  
  1240.         OTSYS_THREAD_LOCK_CLASS::LogList::iterator it;
  1241.         for(it = OTSYS_THREAD_LOCK_CLASS::loglist.begin(); it != OTSYS_THREAD_LOCK_CLASS::loglist.end(); ++it) {
  1242.             *outdriver << (it->lock ? "lock - " : "unlock - ") << it->str
  1243.                 << " threadid: " << it->threadid
  1244.                 << " time: " << it->time
  1245.                 << " ptr: " << it->mutexaddr
  1246.                 << std::endl;
  1247.         }
  1248.  
  1249.         *outdriver << "*****************************************************" << std::endl;
  1250.         if(file)
  1251.             ((std::ofstream*)outdriver)->close();
  1252.  
  1253.         std::cout << "Error report generated. Killing server." <<std::endl;
  1254.         exit(1); //force exit
  1255.     }
  1256. }
  1257. #endif
  1258.  
  1259. OTSYS_THREAD_RETURN Game::eventThread(void *p)
  1260. {
  1261. #if defined __EXCEPTION_TRACER__
  1262.     ExceptionHandler eventExceptionHandler;
  1263.     eventExceptionHandler.InstallHandler();
  1264. #endif
  1265.  
  1266.   Game* _this = (Game*)p;
  1267.  
  1268.   // basically what we do is, look at the first scheduled item,
  1269.   // and then sleep until it's due (or if there is none, sleep until we get an event)
  1270.   // of course this means we need to get a notification if there are new events added
  1271.   while (true)
  1272.   {
  1273. #ifdef __DEBUG__EVENTSCHEDULER__
  1274.     std::cout << "schedulercycle start..." << std::endl;
  1275. #endif
  1276.  
  1277.     SchedulerTask* task = NULL;
  1278.         bool runtask = false;
  1279.  
  1280.     // check if there are events waiting...
  1281.     OTSYS_THREAD_LOCK(_this->eventLock, "eventThread()")
  1282.  
  1283.         int32_t ret;
  1284.     if (_this->eventList.size() == 0) {
  1285.       // unlock mutex and wait for signal
  1286.       ret = OTSYS_THREAD_WAITSIGNAL(_this->eventSignal, _this->eventLock);
  1287.     } else {
  1288.       // unlock mutex and wait for signal or timeout
  1289.       ret = OTSYS_THREAD_WAITSIGNAL_TIMED(_this->eventSignal, _this->eventLock, _this->eventList.top()->getCycle());
  1290.     }
  1291.     // the mutex is locked again now...
  1292.     if (ret == OTSYS_THREAD_TIMEOUT) {
  1293.       // ok we had a timeout, so there has to be an event we have to execute...
  1294. #ifdef __DEBUG__EVENTSCHEDULER__
  1295.       std::cout << "event found at " << OTSYS_TIME() << " which is to be scheduled at: " << _this->eventList.top()->getCycle() << std::endl;
  1296. #endif
  1297.       task = _this->eventList.top();
  1298.       _this->eventList.pop();
  1299.         }
  1300.  
  1301.         if(task) {
  1302.             std::map<uint32_t, SchedulerTask*>::iterator it = _this->eventIdMap.find(task->getEventId());
  1303.             if(it != _this->eventIdMap.end()) {
  1304.                 _this->eventIdMap.erase(it);
  1305.                 runtask = true;
  1306.             }
  1307.         }
  1308.  
  1309.         OTSYS_THREAD_UNLOCK(_this->eventLock, "eventThread()");
  1310.     if (task) {
  1311.             if(runtask) {
  1312.                 (*task)(_this);
  1313.             }
  1314.             delete task;
  1315.     }
  1316.   }
  1317. #if defined __EXCEPTION_TRACER__
  1318.     eventExceptionHandler.RemoveHandler();
  1319. #endif
  1320.  
  1321. }
  1322.  
  1323. uint32_t Game::addEvent(SchedulerTask* event) {
  1324.   bool do_signal = false;
  1325.   OTSYS_THREAD_LOCK(eventLock, "addEvent()")
  1326.  
  1327.     if(event->getEventId() == 0) {
  1328.         ++eventIdCount;
  1329.         event->setEventId(eventIdCount);
  1330.     }
  1331.  
  1332. #ifdef __DEBUG__EVENTSCHEDULER__
  1333.         std::cout << "addEvent - " << event->getEventId() << std::endl;
  1334. #endif
  1335.  
  1336.     eventIdMap[event->getEventId()] = event;
  1337.  
  1338.     /*
  1339.     if (eventList.empty() ||  *event < *eventList.top())
  1340.     do_signal = true;
  1341.     */
  1342.  
  1343.     bool isEmpty = eventList.empty();
  1344.     eventList.push(event);
  1345.  
  1346.     if(isEmpty || *event < *eventList.top())
  1347.         do_signal = true;
  1348.  
  1349.     /*
  1350.     if (eventList.empty() ||  *event < *eventList.top())
  1351.     do_signal = true;
  1352.     */
  1353.  
  1354.   OTSYS_THREAD_UNLOCK(eventLock, "addEvent()")
  1355.  
  1356.     if (do_signal)
  1357.         OTSYS_THREAD_SIGNAL_SEND(eventSignal);
  1358.  
  1359.     return event->getEventId();
  1360. }
  1361.  
  1362. bool Game::stopEvent(uint32_t eventid) {
  1363.     if(eventid == 0)
  1364.         return false;
  1365.  
  1366.   OTSYS_THREAD_LOCK(eventLock, "stopEvent()")
  1367.  
  1368.     std::map<uint32_t, SchedulerTask*>::iterator it = eventIdMap.find(eventid);
  1369.     if(it != eventIdMap.end()) {
  1370.  
  1371. #ifdef __DEBUG__EVENTSCHEDULER__
  1372.         std::cout << "stopEvent - eventid: " << eventid << "/" << it->second->getEventId() << std::endl;
  1373. #endif
  1374.  
  1375.         //it->second->setEventId(0); //invalidate the event
  1376.         eventIdMap.erase(it);
  1377.  
  1378.       OTSYS_THREAD_UNLOCK(eventLock, "stopEvent()")
  1379.         return true;
  1380.     }
  1381.  
  1382.   OTSYS_THREAD_UNLOCK(eventLock, "stopEvent()")
  1383.     return false;
  1384. }
  1385.  
  1386. /*****************************************************************************/
  1387.  
  1388. uint32_t Game::getPlayersOnline() {return (uint32_t)Player::listPlayer.list.size();};
  1389. uint32_t Game::getMonstersOnline() {return (uint32_t)Monster::listMonster.list.size();};
  1390. uint32_t Game::getNpcsOnline() {return (uint32_t)Npc::listNpc.list.size();};
  1391. uint32_t Game::getCreaturesOnline() {return (uint32_t)listCreature.list.size();};
  1392.  
  1393. Tile* Game::getTile(unsigned short _x, unsigned short _y, unsigned char _z)
  1394. {
  1395.     return map->getTile(_x, _y, _z);
  1396. }
  1397.  
  1398. Tile* Game::getTile(const Position& pos)
  1399. {
  1400.     return map->getTile(pos);
  1401. }
  1402.  
  1403. void Game::setTile(unsigned short _x, unsigned short _y, unsigned char _z, unsigned short groundId)
  1404. {
  1405.     map->setTile(_x, _y, _z, groundId);
  1406. }
  1407.  
  1408. Creature* Game::getCreatureByID(uint32_t id)
  1409. {
  1410.     if(id == 0)
  1411.         return NULL;
  1412.  
  1413.     AutoList<Creature>::listiterator it = listCreature.list.find(id);
  1414.     if(it != listCreature.list.end()) {
  1415.         return (*it).second;
  1416.     }
  1417.  
  1418.     return NULL; //just in case the player doesnt exist
  1419. }
  1420.  
  1421. Player* Game::getPlayerByID(uint32_t id)
  1422. {
  1423.     if(id == 0)
  1424.         return NULL;
  1425.  
  1426.     AutoList<Player>::listiterator it = Player::listPlayer.list.find(id);
  1427.     if(it != Player::listPlayer.list.end()) {
  1428.         return (*it).second;
  1429.     }
  1430.  
  1431.     return NULL; //just in case the player doesnt exist
  1432. }
  1433.  
  1434. Creature* Game::getCreatureByName(const std::string &s)
  1435. {
  1436.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::getCreatureByName()");
  1437.  
  1438.     std::string txt1 = s;
  1439.     std::transform(txt1.begin(), txt1.end(), txt1.begin(), upchar);
  1440.     for(AutoList<Creature>::listiterator it = listCreature.list.begin(); it != listCreature.list.end(); ++it){
  1441.         std::string txt2 = (*it).second->getName();
  1442.         std::transform(txt2.begin(), txt2.end(), txt2.begin(), upchar);
  1443.         if(txt1 == txt2)
  1444.             return it->second;
  1445.     }
  1446.  
  1447.     return NULL; //just in case the creature doesnt exist
  1448. }
  1449.  
  1450. Player* Game::getPlayerByName(const std::string &s)
  1451. {
  1452.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::getPlayerByName()");
  1453.  
  1454.     std::string txt1 = s;
  1455.     std::transform(txt1.begin(), txt1.end(), txt1.begin(), upchar);
  1456.     for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  1457.         std::string txt2 = (*it).second->getName();
  1458.         std::transform(txt2.begin(), txt2.end(), txt2.begin(), upchar);
  1459.         if(txt1 == txt2)
  1460.             return it->second;
  1461.     }
  1462.  
  1463.     return NULL; //just in case the player doesnt exist
  1464. }
  1465.  
  1466. bool Game::placeCreature(Position &pos, Creature* c
  1467. #ifdef YUR_LOGIN_QUEUE
  1468.                          , int32_t* placeInQueue
  1469. #endif //YUR_LOGIN_QUEUE
  1470.                         )
  1471. {
  1472.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::placeCreature()");
  1473.     bool success = false;
  1474.     Player *p = dynamic_cast<Player*>(c);
  1475.     Monster *monsterzin = dynamic_cast<Monster*>(c);
  1476.    
  1477. #ifdef YUR_LOGIN_QUEUE
  1478.     if (!p || c->access >= g_config.ACCESS_ENTER ||
  1479. #ifdef YUR_PREMIUM_PROMOTION
  1480.             (p->isPremmium() && !g_config.QUEUE_PREMMY) ||
  1481. #endif //YUR_PREMIUM_PROMOTION
  1482.             loginQueue.login(p->accountNumber, getPlayersOnline(), max_players, placeInQueue))
  1483.     {
  1484. #else //YUR_LOGIN_QUEUE
  1485.     if (!p || c->access >= g_config.ACCESS_ENTER || getPlayersOnline() < max_players)
  1486.     {
  1487. #endif //YUR_LOGIN_QUEUE
  1488.  
  1489.         success = map->placeCreature(pos, c);
  1490.         if(success)
  1491.         {
  1492.             c->useThing();
  1493.  
  1494.             c->setID();
  1495.             //std::cout << "place: " << c << " " << c->getID() << std::endl;
  1496.             listCreature.addList(c);
  1497.             c->addList();
  1498.             c->isRemoved = false;
  1499.  
  1500.             sendAddThing(NULL,c->pos,c);
  1501.  
  1502.             if(p)
  1503.             {
  1504.                  checkRecord();
  1505. #ifdef __DEBUG_PLAYERS__
  1506.                 std::cout << (uint32_t)getPlayersOnline() << " players online." << std::endl;
  1507. #endif
  1508. #ifdef YUR_GUILD_SYSTEM
  1509.                 Guilds::ReloadGuildInfo(p);
  1510. #endif //YUR_GUILD_SYSTEM
  1511. /*#ifdef ELEM_VIP_LIST
  1512.                 vipLogin(p);
  1513. #endif //ELEM_VIP_LIST*/
  1514.             }
  1515.  
  1516.             if(p){
  1517.                 c->eventCheck = addEvent(makeTask(1000, std::bind2nd(std::mem_fun(&Game::checkCreature), c->getID())));
  1518.             }
  1519.             else{
  1520.                 c->eventCheck = addEvent(makeTask(1000, std::bind2nd(std::mem_fun(&Game::checkCreature), c->getID())));
  1521.             }
  1522.  
  1523.             //c->eventCheckAttacking = addEvent(makeTask(2000, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), c->getID())));
  1524.         }
  1525.     }
  1526.     else {
  1527.         //we cant add the player, server is full
  1528.         success = false;
  1529.     }
  1530.    
  1531.      #ifdef __MIZIAK_CREATURESCRIPTS__
  1532.            if(p)
  1533.        actions.creatureEvent("login", p, NULL, NULL, NULL);
  1534.        #endif //__MIZIAK_CREATURESCRIPTS__
  1535.  
  1536.  
  1537.   if(monsterzin){
  1538.      c->masterPos.x = c->pos.x;
  1539.      c->masterPos.y = c->pos.y;
  1540.      c->masterPos.z = c->pos.z;        
  1541.   }
  1542.   return success;
  1543. }
  1544.  
  1545. bool Game::removeCreature(Creature* c)
  1546. {
  1547.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::removeCreature()");
  1548.     if(c->isRemoved == true)
  1549.         return false;
  1550. #ifdef __DEBUG__
  1551.     std::cout << "removing creature "<< std::endl;
  1552. #endif
  1553.  
  1554. #ifdef __MIZIAK_CREATURESCRIPTS__
  1555.     Player* pc = dynamic_cast<Player*>(c);
  1556.     if(pc)
  1557.         if(!pc->dieorlogout)
  1558.             actions.creatureEvent("logout", pc, NULL, NULL, NULL);
  1559. #endif //__MIZIAK_CREATURESCRIPTS__
  1560.  
  1561.     if(!removeThing(NULL,c->pos,c))
  1562.         return false;
  1563.  
  1564.     //std::cout << "remove: " << c << " " << c->getID() << std::endl;
  1565.     listCreature.removeList(c->getID());
  1566.     c->removeList();
  1567.     c->isRemoved = true;
  1568.  
  1569. if(g_config.SUMMON_BODIES){
  1570.     c->isRemoved = true;
  1571.  
  1572. Creature *summon = NULL;
  1573. for(std::list<Creature*>::iterator cit = c->summons.begin(); cit != c->summons.end(); ++cit) {
  1574. summon = (*cit);
  1575. Position CreaturePos = summon->pos;
  1576. Tile *tile = map->getTile(CreaturePos);
  1577. Item *corpseitem = Item::CreateItem(summon->getLookCorpse());
  1578. corpseitem->pos = CreaturePos; /*summoned bodies by Cayan*/
  1579. tile->addThing(corpseitem);
  1580. removeCreature(summon);
  1581. updateTile(CreaturePos);
  1582. }
  1583. }
  1584. else
  1585. {
  1586.  c->isRemoved = true;
  1587.  
  1588. //for(std::list<Creature*>::iterator cit = c->summons.begin(); cit != c->summons.end(); ++cit) {
  1589. //removeCreature(*cit);
  1590. //}
  1591. }
  1592.  
  1593.  
  1594.     stopEvent(c->eventCheck);
  1595.     stopEvent(c->eventCheckAttacking);
  1596.     stopEvent(c->eventCheckFollow);
  1597.  
  1598.     Player* player = dynamic_cast<Player*>(c);
  1599.     if(player){
  1600.  
  1601. #ifdef HUCZU_SKULLS
  1602.         for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  1603.            Player *on = dynamic_cast<Player*>(it->second);
  1604.            if(on && player->isYellowTo(on)){
  1605.            on->removeFromYellowList(player);
  1606.            }
  1607.            if(on && on->hasAttacked(player)){
  1608.            on->removeFromAttakedList(player);
  1609.            }
  1610.            player->clearAttakedList();
  1611.            player->clearYellowList();
  1612.         }
  1613.        
  1614.         if(player->party != 0)
  1615.             LeaveParty(player);
  1616. #endif //HUCZU_SKULLS
  1617.  
  1618.         if(player->tradePartner != 0) {
  1619.             playerCloseTrade(player);
  1620.         }
  1621.         if(player->eventAutoWalk)
  1622.             stopEvent(player->eventAutoWalk);
  1623.            
  1624.         Tile* fromT = getTile(player->pos);
  1625. if(fromT && fromT->ground)
  1626.         actions.luaWalkOff(player,player->pos,fromT->ground->getID(),fromT->ground->getUniqueId(),fromT->ground->getActionId());
  1627.          
  1628.         g_chat.removeUserFromAllChannels(player);
  1629.         if(!IOPlayer::instance()->savePlayer(player)){
  1630.             std::cout << "Error while saving player: " << player->getName() << std::endl;
  1631.         }
  1632.         std::cout << (uint32_t)getPlayersOnline() << " players online." << std::endl;
  1633.        
  1634.  
  1635. /*#ifdef ELEM_VIP_LIST
  1636.         vipLogout(c->getName());
  1637. #endif //ELEM_VIP_LIST*/
  1638.        
  1639.  
  1640.        }
  1641.     this->FreeThing(c);
  1642.     return true;
  1643. }
  1644.  
  1645. void Game::thingMove(Creature *creature, Thing *thing,
  1646.     unsigned short to_x, unsigned short to_y, unsigned char to_z, unsigned char count)
  1647. {
  1648.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 1");
  1649.  
  1650.     Tile *fromTile = map->getTile(thing->pos);
  1651.  
  1652.     if (fromTile)
  1653.     {
  1654.         int32_t oldstackpos = fromTile->getThingStackPos(thing);
  1655.         thingMoveInternal(creature, thing->pos.x, thing->pos.y, thing->pos.z, oldstackpos, 0, to_x, to_y, to_z, count);
  1656.     }
  1657. }
  1658.  
  1659.  
  1660. void Game::thingMove(Creature *creature, unsigned short from_x, unsigned short from_y, unsigned char from_z,
  1661.     unsigned char stackPos, unsigned short itemid, unsigned short to_x, unsigned short to_y, unsigned char to_z, unsigned char count)
  1662. {
  1663.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 2");
  1664.  
  1665.     Tile *fromTile = getTile(from_x, from_y, from_z);
  1666.     if(!fromTile)
  1667.         return;
  1668.        
  1669.     #ifdef FIXY
  1670.     if(dynamic_cast<Player*>(creature) && fromTile && !fromTile->ground) {
  1671.       dynamic_cast<Player*>(creature)->sendCancelWalk();
  1672.       return;
  1673.      }
  1674.     #endif //FIXY
  1675.    
  1676.             Tile *toTile = getTile(to_x, to_y, to_z);
  1677.     if(!toTile)
  1678.         return;
  1679.        
  1680.         #ifdef FIXY
  1681.     if (toTile->isHouse() && !fromTile->isHouse())
  1682.         return;
  1683.         #endif //FIXY
  1684.  
  1685.     Thing* thing = fromTile->getThingByStackPos(stackPos);
  1686.     if(!thing)
  1687.         return;
  1688.  
  1689.     Item* item = dynamic_cast<Item*>(thing);
  1690.  
  1691.     if(item && (item->getID() != itemid || item != fromTile->getTopDownItem()))
  1692.         return;
  1693.  
  1694.     thingMoveInternal(creature, from_x, from_y, from_z, stackPos, itemid, to_x, to_y, to_z, count);
  1695. }
  1696.  
  1697. //container/inventory to container/inventory
  1698. void Game::thingMove(Player *player,
  1699.     unsigned char from_cid, unsigned char from_slotid, unsigned short itemid, bool fromInventory,
  1700.     unsigned char to_cid, unsigned char to_slotid, bool toInventory,
  1701.     unsigned char count)
  1702. {
  1703.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 3");
  1704.  
  1705.     thingMoveInternal(player, from_cid, from_slotid, itemid, fromInventory,
  1706.         to_cid, to_slotid, toInventory, count);
  1707. }
  1708.  
  1709. //container/inventory to ground
  1710. void Game::thingMove(Player *player,
  1711.     unsigned char from_cid, unsigned char from_slotid, unsigned short itemid, bool fromInventory,
  1712.     const Position& toPos, unsigned char count)
  1713. {
  1714.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 4");
  1715. Container *fromContainer = player->getContainer(from_cid);
  1716.     if(fromContainer && !fromContainer->shop.empty())
  1717.         return;
  1718.    
  1719.     #ifdef FIXY
  1720.     Tile *toTile = getTile(toPos.x, toPos.y, toPos.z);
  1721.     if(!toTile)
  1722.         return;
  1723.    
  1724.     if (player) {
  1725.         Tile *fromTile = getTile(player->pos);
  1726.         if(!fromTile->isHouse() && toTile->isHouse())  
  1727.             return;
  1728.     }
  1729. #endif //FIXY
  1730.  
  1731.     thingMoveInternal(player, from_cid, from_slotid, itemid, fromInventory, toPos, count);
  1732. }
  1733.  
  1734. //ground to container/inventory
  1735. void Game::thingMove(Player *player,
  1736.     const Position& fromPos, unsigned char stackPos, unsigned short itemid,
  1737.     unsigned char to_cid, unsigned char to_slotid, bool toInventory,
  1738.     unsigned char count)
  1739. {
  1740.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::thingMove() - 5");
  1741.     thingMoveInternal(player, fromPos, stackPos, itemid, to_cid, to_slotid, toInventory, count);
  1742. }
  1743.  
  1744. #ifdef FIXY
  1745. bool Game::onPrepareMoveThing(Creature* player, /*const*/ Thing* thing,
  1746. const Position& fromPos, const Position& toPos, int32_t count)
  1747. {
  1748.     const Creature* movingCreature = dynamic_cast<const Creature*>(thing);
  1749.     Player *playa = dynamic_cast<Player*>(thing);
  1750.    
  1751.         if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) &&
  1752.         ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  1753.         {
  1754.         player->sendCancel("Destination is out of reach.");
  1755.         return false;
  1756.         }
  1757.  //RZUCANIE GM PO EKRANIE?
  1758.  else if( ((abs(fromPos.x - toPos.x) > thing->throwRange) || (abs(fromPos.y - toPos.y) > thing->throwRange)
  1759.   || (fromPos.z != toPos.z)) && player->access >= g_config.ACCESS_REMOTE) {
  1760.         if(player == thing){
  1761.            teleport(player,toPos);
  1762.            
  1763.            if(!playa->gmInvisible){
  1764.            globalMagicEffect(fromPos, NM_ME_PUFF);
  1765.            globalMagicEffect(toPos, NM_ME_ENERGY_AREA);
  1766.            }
  1767.            else
  1768.            {    
  1769.            playa->sendMagicEffect(fromPos, NM_ME_PUFF);
  1770.            playa->sendMagicEffect(toPos, NM_ME_ENERGY_AREA);
  1771.            }
  1772.            }
  1773.         else
  1774.            teleport(thing,toPos);
  1775.     }  
  1776.  
  1777.  
  1778.     else if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) && ((abs(fromPos.x - toPos.x) > thing->throwRange || abs(fromPos.y - toPos.y) > thing->throwRange || (abs(fromPos.z - toPos.z+1) > thing->throwRange)))) {
  1779.         player->sendCancel("Destination is out of reach.");
  1780.         return false;
  1781.     }
  1782.  
  1783.          
  1784. else if(player->access < g_config.ACCESS_REMOTE && movingCreature && fromPos.z != toPos.z){
  1785.     player->sendCancel("Destination is out of reach.");
  1786.     return false;
  1787. }
  1788.  
  1789.     else {
  1790.         const Item* item = dynamic_cast<const Item*>(thing);
  1791.         if(item) {
  1792.           if(item->getID() == ITEM_FOOTBALL &&
  1793.                player->access < g_config.getGlobalNumber("accessfootball", 3) && (
  1794.                (abs(player->pos.x - toPos.x) > 2) ||
  1795.                (abs(player->pos.y - toPos.y) > 2) ||
  1796.                (player->pos.z != fromPos.z))
  1797.                 ){
  1798.                         player->sendCancel("Nie mozesz tak daleko kopnac.");
  1799.                         return false;
  1800.             }
  1801.             int32_t blockstate = 0;
  1802.             if(item->isBlocking())
  1803.                 blockstate |= BLOCK_SOLID;
  1804.  
  1805.             if(item->isPickupable() || !item->isNotMoveable())
  1806.                 blockstate |= BLOCK_PICKUPABLE;
  1807.  
  1808.             if(blockstate != 0) {
  1809.                 switch(map->canThrowObjectTo(fromPos, toPos, blockstate)) {
  1810.                     case RET_NOERROR:
  1811.                         return true;
  1812.                         break;
  1813.  
  1814.                     case RET_CANNOTTHROW:
  1815.                         player->sendCancel("Nie mozesz tam rzucic.");
  1816.                         return false;
  1817.                         break;
  1818.  
  1819.                     case RET_CREATUREBLOCK:
  1820.                     case RET_NOTENOUGHROOM:
  1821. #ifdef KOSZ
  1822.                       if(item->getID() != ITEM_DUSTBIN){
  1823.                         player->sendCancel("Przykro mi, nie ma miejsca.");
  1824.                         return false;
  1825.                       }
  1826. #else
  1827.                         player->sendCancel("Przykro mi, nie ma miejsca.");
  1828.                         return false;
  1829. #endif //KOSZ
  1830.                         break;
  1831.  
  1832.                     default:
  1833.                         player->sendCancel("Sorry not possible.");
  1834.                         return false;
  1835.                         break;
  1836.                 }
  1837.             }
  1838.         }
  1839.     }
  1840.  
  1841.     return true;
  1842. }
  1843. #else //FIXY
  1844. bool Game::onPrepareMoveThing(Creature* player, const Thing* thing,
  1845.     const Position& fromPos, const Position& toPos, int32_t count)
  1846. {
  1847.     if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) &&
  1848.         ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  1849.     {
  1850.         player->sendCancel("Za daleko...");
  1851.         return false;
  1852.     }
  1853.     else if ((player->access < g_config.ACCESS_REMOTE || dynamic_cast<const Player*>(thing)) &&
  1854.         ((abs(fromPos.x - toPos.x) > thing->throwRange) || (abs(fromPos.y - toPos.y) > thing->throwRange)
  1855.         || (fromPos.z != toPos.z) /*TODO: Make it possible to throw items to different floors ))*/
  1856.     {
  1857.         player->sendCancel("Destination is out of reach.");
  1858.         return false;
  1859.     }
  1860.     else {
  1861.         const Item* item = dynamic_cast<const Item*>(thing);
  1862.         if(item) {
  1863.             int32_t blockstate = 0;
  1864.             if(item->isBlocking())
  1865.                 blockstate |= BLOCK_SOLID;
  1866.  
  1867.             if(item->isPickupable() || !item->isNotMoveable())
  1868.                 blockstate |= BLOCK_PICKUPABLE;
  1869.  
  1870.             if(blockstate != 0) {
  1871.                 switch(map->canThrowObjectTo(fromPos, toPos, blockstate)) {
  1872.                     case RET_NOERROR:
  1873.                         return true;
  1874.                         break;
  1875.  
  1876.                     case RET_CANNOTTHROW:
  1877.                         player->sendCancel("Nie mozesz tam rzucic.");
  1878.                         return false;
  1879.                         break;
  1880.  
  1881.                     case RET_CREATUREBLOCK:
  1882.                     case RET_NOTENOUGHROOM:
  1883.                         player->sendCancel("Przykro mi, nie ma miejsca.");
  1884.                         return false;
  1885.                         break;
  1886.  
  1887.                     default:
  1888.                         player->sendCancel("Sorry not possible.");
  1889.                         return false;
  1890.                         break;
  1891.                 }
  1892.             }
  1893.         }
  1894.     }
  1895.     return true;
  1896. }
  1897. #endif //FIXY
  1898. /*ground -> ground*/
  1899. bool Game::onPrepareMoveThing(Creature* creature, const Thing* thing,
  1900.     const Tile* fromTile, const Tile *toTile, int32_t count)
  1901. {
  1902.     const Player* player = dynamic_cast<const Player*>(creature);
  1903.  
  1904.     const Item *item = dynamic_cast<const Item*>(thing);
  1905.     const Creature* movingCreature = dynamic_cast<const Creature*>(thing);
  1906.     const Player* movingPlayer = dynamic_cast<const Player*>(thing);
  1907.  
  1908.    /* if(movingCreature){
  1909.     addEvent(makeTask(2000, std::mem_fun(&Game::onPrepareMoveCreature, creature, movingCreature, fromTile, toTile))));
  1910.     }*/
  1911.     if(item && !item->canMovedTo(toTile)) {
  1912.         creature->sendCancel("Sorry, not possible.");
  1913.         return false;
  1914.     }
  1915.    
  1916.    else if(movingCreature && !movingCreature->canMovedTo(toTile)) {
  1917.    if(player && player->eventCheckFollow == 0) {
  1918.           player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  1919.           player->sendCancelWalk();
  1920.     }
  1921.  
  1922.         return false;
  1923.     }
  1924.     else if(!movingPlayer && toTile && toTile->floorChange()) {
  1925.         creature->sendCancel("Sorry, not possible.");
  1926.         return false;
  1927.     }
  1928.   else if(movingCreature && toTile && !toTile->ground) {
  1929.     if(player) {
  1930.       player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  1931.       player->sendCancelWalk();
  1932.     }
  1933.  
  1934.         return false;
  1935.     }
  1936.  
  1937.     if (fromTile && fromTile->splash == thing && fromTile->splash->isNotMoveable()) {
  1938.             creature->sendCancel("You cannot move this object.");
  1939. #ifdef __DEBUG__
  1940.         cout << creature->getName() << " is trying to move a splash item!" << std::endl;
  1941. #endif
  1942.         return false;
  1943.     }
  1944.     else if (item && item->isNotMoveable()) {
  1945.             creature->sendCancel("You cannot move this object.");
  1946. #ifdef __DEBUG__
  1947.         cout << creature->getName() << " is trying to move an unmoveable item!" << std::endl;
  1948. #endif
  1949.         return false;
  1950.     }
  1951.  
  1952. #ifdef TLM_HOUSE_SYSTEM
  1953.     if (item && toTile && toTile->isHouse())
  1954.     {
  1955.         const Container* container = dynamic_cast<const Container*>(item);
  1956.         int32_t moving = container? container->getItemHoldingCount() : 1;
  1957.  
  1958.         if (moving + toTile->getItemHoldingCount() > g_config.MAX_HOUSE_TILE_ITEMS)
  1959.         {
  1960.             creature->sendCancel("You cannot put more items on a house tile.");
  1961.             return false;
  1962.         }
  1963.     }
  1964. #endif //TLM_HOUSE_SYSTEM
  1965.  
  1966.     return true; //return thing->canMovedTo(toTile);
  1967. }
  1968. /*inventory -> container*/
  1969. bool Game::onPrepareMoveThing(Player* player, const Item* fromItem, slots_t fromSlot,
  1970.     const Container* toContainer, const Item* toItem, int32_t count)
  1971. {
  1972. if(toContainer && !toContainer->shop.empty()){
  1973.         creatureUseShop(player, fromItem->getID(), count, "toShop");
  1974.         return false;
  1975.     }
  1976. if(toContainer && toContainer->getParent() && !toContainer->getParent()->shop.empty())
  1977.         return false;
  1978.     if(!fromItem->isPickupable()) {
  1979.         player->sendCancel("Sorry, not possible.");
  1980.         return false;
  1981.     }
  1982.     else {
  1983.         const Container *itemContainer = dynamic_cast<const Container*>(fromItem);
  1984.         if(itemContainer) {
  1985.             if(itemContainer->isHoldingItem(toContainer) || (toContainer == itemContainer)) {
  1986.                 player->sendCancel("To jest niemozliwe!");
  1987.                 return false;
  1988.             }
  1989.         }
  1990.  
  1991.         if((!fromItem->isStackable() || !toItem || fromItem->getID() != toItem->getID() || toItem->getItemCountOrSubtype() >= 100) && toContainer->size() + 1 > toContainer->capacity()) {
  1992.             player->sendCancel("Przykro mi, nie ma miejsca.");
  1993.             return false;
  1994.         }
  1995.  
  1996.         Container const *topContainer = toContainer->getTopParent();
  1997.         int32_t itemsToadd;
  1998.         if(!topContainer)
  1999.             topContainer = toContainer;
  2000.  
  2001.         Container const *fromContainer = dynamic_cast<const Container*>(fromItem);
  2002.         if(fromContainer)
  2003.             itemsToadd = fromContainer->getItemHoldingCount() + 1;
  2004.         else
  2005.             itemsToadd = 1;
  2006.  
  2007.         if(topContainer->depot != 0 && player->max_depot_items != 0 && topContainer->getItemHoldingCount() + itemsToadd >= player->max_depot_items){
  2008.             player->sendCancel("Nie mozesz polozyc wiecej przedmiotow w depo.");
  2009.             return false;
  2010.         }
  2011.     }
  2012.     return true;
  2013. }
  2014.  
  2015. /*container -> container*/
  2016. /*ground -> container*/
  2017. bool Game::onPrepareMoveThing(Player* player,
  2018.     const Position& fromPos, const Container* fromContainer, const Item* fromItem,
  2019.     const Position& toPos, const Container* toContainer, const Item* toItem, int32_t count)
  2020. {
  2021. if(fromContainer && toContainer && (!fromContainer->shop.empty() || !toContainer->shop.empty())){
  2022.         creatureUseShop(player, fromItem->getID(), count, (!fromContainer->shop.empty() ? "fromShop" : "toShop"));
  2023.         return false;
  2024.     }
  2025.  
  2026.     if(!fromContainer && toContainer && !toContainer->shop.empty())
  2027.         return false;
  2028. if(toContainer && toContainer->getParent() && !toContainer->getParent()->shop.empty())
  2029.         return false;
  2030.  
  2031.     if (player->access < g_config.ACCESS_REMOTE &&
  2032.         ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  2033.     {
  2034.         player->sendCancel("Za daleko...");
  2035.         return false;
  2036.     }
  2037.     else if (player->access < g_config.ACCESS_REMOTE &&
  2038.         ((abs(fromPos.x - toPos.x) > fromItem->throwRange) || (abs(fromPos.y - toPos.y) > fromItem->throwRange)
  2039.         || (fromPos.z != toPos.z)))
  2040.     {
  2041.         player->sendCancel("Destination is out of reach.");
  2042.         return false;
  2043.     }
  2044.  
  2045.     if(!fromItem->isPickupable()) {
  2046.         player->sendCancel("You cannot move this object.");
  2047.         return false;
  2048.     }
  2049.     else {
  2050.         if((!fromItem->isStackable() || !toItem || fromItem->getID() != toItem->getID() || toItem->getItemCountOrSubtype() >= 100) && toContainer->size() + 1 > toContainer->capacity()) {
  2051.             player->sendCancel("Przykro mi, nie ma miejsca.");
  2052.             return false;
  2053.         }
  2054.  
  2055.         const Container *itemContainer = dynamic_cast<const Container*>(fromItem);
  2056.         if(itemContainer) {
  2057.             if(itemContainer->isHoldingItem(toContainer) || (toContainer == itemContainer) || (fromContainer && fromContainer == itemContainer)) {
  2058.                 player->sendCancel("To jest niemozliwe!");
  2059.                 return false;
  2060.             }
  2061.         }
  2062.  
  2063.         double itemWeight = (fromItem->isStackable() ? Item::items[fromItem->getID()].weight * std::max(1, count) : fromItem->getWeight());
  2064.         if((!fromContainer || !player->isHoldingContainer(fromContainer)) && player->isHoldingContainer(toContainer)) {
  2065.             if(player->access < g_config.ACCESS_PROTECT && player->getFreeCapacity() < itemWeight) {
  2066.                 player->sendCancel("Ten przedmiot jest za ciezki.");
  2067.                 return false;
  2068.             }
  2069.         }
  2070.  
  2071.         Container const *topContainer = toContainer->getTopParent();
  2072.         int32_t itemsToadd;
  2073.         if(!topContainer)
  2074.             topContainer = toContainer;
  2075.  
  2076.         Container const *fromContainer = dynamic_cast<const Container*>(fromItem);
  2077.         if(fromContainer)
  2078.             itemsToadd = fromContainer->getItemHoldingCount() + 1;
  2079.         else
  2080.             itemsToadd = 1;
  2081.  
  2082.         if(topContainer->depot != 0 && player->max_depot_items != 0 && topContainer->getItemHoldingCount() >= player->max_depot_items){
  2083.             player->sendCancel("Nie mozesz polozyc wiecej przedmiotow w depo.");
  2084.             return false;
  2085.         }
  2086.     }
  2087.     return true;
  2088. }
  2089.  
  2090. /*ground -> ground*/
  2091. bool Game::onPrepareMoveCreature(Creature *creature, const Creature* creatureMoving,
  2092.     const Tile *fromTile, const Tile *toTile)
  2093. {
  2094.     const Player* playerMoving = dynamic_cast<const Player*>(creatureMoving);
  2095.     Player* player = dynamic_cast<Player*>(creature);
  2096.  
  2097. #ifdef _BBK_PUSH_DELAY
  2098.     if(player && player != creatureMoving && player->pushDelay > 0)
  2099.     {
  2100.         player->sendCancel("Wait a moment.");
  2101.         return false;
  2102.     }
  2103.     else if(player)
  2104.        player->pushDelay = 2*1000; //2 sec
  2105.              
  2106.         //wypychanie z depo
  2107.         if(player && playerMoving && player != playerMoving && fromTile->isPz() && !toTile->isPz())
  2108.         {
  2109.             player->sendCancel("Sorry, not possible.");
  2110.       return false;
  2111.         }
  2112.         //wepchanie do depo
  2113.         if(player && playerMoving && playerMoving->pzLocked && toTile->isPz())
  2114.         {
  2115.             player->sendCancel("Sorry, not possible.");
  2116.             player->sendCancelWalk();
  2117.       return false;
  2118.         }
  2119.         //wchodzenie do depo
  2120.         if(player && player->pzLocked && toTile->isPz())
  2121.         {
  2122.             player->sendCancel("You can not enter a protection zone after attacking another player.");
  2123.             player->sendCancelWalk();
  2124.       return false;
  2125.         }
  2126. #endif //_BBK_PUSH_DELAY
  2127.    
  2128.     if (creature->access < g_config.ACCESS_PROTECT && creature != creatureMoving && !creatureMoving->isPushable())
  2129.     {
  2130.         creature->sendCancel("Sorry, not possible.");
  2131.         return false;
  2132.     }
  2133.     else if(creature != creatureMoving && toTile->floorChange()){
  2134.         creature->sendCancel("Sorry, not possible.");
  2135.         return false;
  2136.     }
  2137.   else if(creature != creatureMoving && toTile->getTeleportItem()){
  2138.         creature->sendCancel("Sorry, not possible.");
  2139.         return false;
  2140.   }
  2141.  
  2142.     return true;
  2143. }
  2144.  
  2145. /*ground -> inventory*/
  2146. bool Game::onPrepareMoveThing(Player *player, const Position& fromPos, const Item *item,
  2147.     slots_t toSlot, int32_t count)
  2148. {
  2149.     if (player->access < g_config.ACCESS_REMOTE &&  
  2150.         ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  2151.     {
  2152.         player->sendCancel("It's too far.");
  2153.         return false;
  2154.     }
  2155.     else if(!item->isPickupable()) {
  2156.         player->sendCancel("You cannot move this object.");
  2157.         return false;
  2158.     }
  2159.  
  2160.     double itemWeight = (item->isStackable() ? Item::items[item->getID()].weight * std::max(1, count) : item->getWeight());
  2161.     if(player->access < g_config.ACCESS_PROTECT && player->getFreeCapacity() < itemWeight) {
  2162.         player->sendCancel("This object is too heavy.");
  2163.         return false;
  2164.     }
  2165.  
  2166.     return true;
  2167. }
  2168.  
  2169. /*inventory -> inventory*/
  2170. bool Game::onPrepareMoveThing(Player *player, slots_t fromSlot, const Item *fromItem,
  2171.     slots_t toSlot, const Item *toItem, int32_t count)
  2172. {
  2173.     if(toItem && (!toItem->isStackable() || toItem->getID() != fromItem->getID())) {
  2174.         player->sendCancel("There is not enough room.");
  2175.         return false;
  2176.     }
  2177.  
  2178.     return true;
  2179. }
  2180.  
  2181. /*container -> inventory*/
  2182. bool Game::onPrepareMoveThing(Player *player, const Container *fromContainer, const Item *fromItem,
  2183.     slots_t toSlot, const Item *toItem, int32_t count)
  2184. {
  2185. if(fromContainer && !fromContainer->shop.empty()){
  2186.         creatureUseShop(player, fromItem->getID(), count, "fromShop");
  2187.         return false;
  2188.     }
  2189.     #ifdef _REX_FIGHT_MOD_
  2190.     if (toItem && (toItem->getID() == fromItem->getID() && !toItem->isStackable())){
  2191.     #else
  2192.     if(toItem && (!toItem->isStackable() || toItem->getID() != fromItem->getID())) {
  2193.     #endif //Segundo em container -> inventory
  2194.         player->sendCancel("There is not enough room.");
  2195.         return false;
  2196.     }
  2197.  
  2198.     double itemWeight = (fromItem->isStackable() ? Item::items[fromItem->getID()].weight * std::max(1, count) : fromItem->getWeight());
  2199.     if(player->access < g_config.ACCESS_PROTECT && !player->isHoldingContainer(fromContainer) &&
  2200.         player->getFreeCapacity() < itemWeight) {
  2201.         player->sendCancel("This object is too heavy.");
  2202.         return false;
  2203.     }
  2204.  
  2205.     return true;
  2206. }
  2207.  
  2208. /*->inventory*/
  2209. bool Game::onPrepareMoveThing(Player *player, const Item *item,
  2210.     slots_t toSlot, int32_t count)
  2211. {
  2212.     switch(toSlot)
  2213.     {
  2214.     case SLOT_HEAD:
  2215.         if(item->getSlotPosition() & SLOTP_HEAD)
  2216.             return true;
  2217.         break;
  2218.     case SLOT_NECKLACE:
  2219.         if(item->getSlotPosition() & SLOTP_NECKLACE)
  2220.             return true;
  2221.         break;
  2222.     case SLOT_BACKPACK:
  2223.         if(item->getSlotPosition() & SLOTP_BACKPACK)
  2224.             return true;
  2225.         break;
  2226.     case SLOT_ARMOR:
  2227.         if(item->getSlotPosition() & SLOTP_ARMOR)
  2228.             return true;
  2229.         break;
  2230.     case SLOT_RIGHT:
  2231.         if(item->getSlotPosition() & SLOTP_RIGHT){
  2232. #ifdef _REX_CVS_MOD_
  2233.             //One weapon for hand by ReX
  2234.             if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_LEFT] != NULL && player->items[SLOT_LEFT]->isWeapon() && player->items[SLOT_LEFT]->getWeaponType() != SHIELD){
  2235.              player->sendCancel("You may use only one weapon.");
  2236.              return false;
  2237.             }
  2238. #endif            
  2239.             else if(item->getSlotPosition() & SLOTP_TWO_HAND){
  2240.                 if(player->items[SLOT_LEFT] != NULL){
  2241.                     player->sendCancel("First remove the two-handed item.");
  2242.                     return false;
  2243.                 }
  2244.                 return true ;
  2245.             }
  2246.             else{
  2247.                 if(player->items[SLOT_LEFT]){
  2248.     #ifdef _REX_CVS_MOD_
  2249.                     //One weapon for hand by ReX
  2250.                     if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_LEFT] != NULL && player->items[SLOT_LEFT]->isWeapon() && player->items[SLOT_LEFT]->getWeaponType() != SHIELD){
  2251.                     player->sendCancel("You may use only one weapon.");
  2252.                     return false;
  2253.                     }
  2254.                     #endif
  2255.                     else if(player->items[SLOT_LEFT]->getSlotPosition() & SLOTP_TWO_HAND){
  2256.                         player->sendCancel("First remove the two-handed item.");
  2257.                         return false;
  2258.                     }
  2259.                     return true;
  2260.                 }
  2261.                 return true;
  2262.             }
  2263.         }
  2264.         break;
  2265.     case SLOT_LEFT:
  2266.         if(item->getSlotPosition() & SLOTP_LEFT){
  2267. #ifdef _REX_CVS_MOD_
  2268.             //One weapon for hand by ReX
  2269.             if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_RIGHT] != NULL && player->items[SLOT_RIGHT]->isWeapon() && player->items[SLOT_RIGHT]->getWeaponType() != SHIELD){
  2270.              player->sendCancel("You may use only one weapon.");
  2271.              return false;
  2272.             }
  2273. #endif
  2274.             else if(item->getSlotPosition() & SLOTP_TWO_HAND){
  2275.                 if(player->items[SLOT_RIGHT] != NULL){
  2276.                     player->sendCancel("First remove the two-handed item.");
  2277.                     return false;
  2278.                 }
  2279.                 return true ;
  2280.             }
  2281.             else{
  2282.                 if(player->items[SLOT_RIGHT]){
  2283.                                               #ifdef _REX_CVS_MOD_
  2284.                     //One weapon for hand by ReX
  2285.                     if(item && item->isWeapon() && item->getWeaponType() != SHIELD && player->items[SLOT_RIGHT] != NULL && player->items[SLOT_RIGHT]->isWeapon() && player->items[SLOT_RIGHT]->getWeaponType() != SHIELD){
  2286.                     player->sendCancel("You may use only one weapon.");
  2287.                     return false;
  2288.                     }
  2289.                     #endif
  2290.                     else if(player->items[SLOT_RIGHT]->getSlotPosition() & SLOTP_TWO_HAND){
  2291.                         player->sendCancel("First remove the two-handed item.");
  2292.                         return false;
  2293.                     }
  2294.                     return true;
  2295.                 }
  2296.                 return true;
  2297.             }
  2298.         }
  2299.         break;
  2300.     case SLOT_LEGS:
  2301.         if(item->getSlotPosition() & SLOTP_LEGS)
  2302.             return true;
  2303.         break;
  2304.     case SLOT_FEET:
  2305.         if(item->getSlotPosition() & SLOTP_FEET)
  2306.             return true;
  2307.         break;
  2308.     case SLOT_RING:
  2309.         if(item->getSlotPosition() & SLOTP_RING
  2310.         #ifdef _REX_CVS_MOD_
  2311.         || item->getID() == 2208
  2312.         #endif
  2313.         )
  2314.             return true;
  2315.         break;
  2316.     case SLOT_AMMO:
  2317.         if(item->getSlotPosition() & SLOTP_AMMO)
  2318.             return true;
  2319.         break;
  2320.     }
  2321.  
  2322.     player->sendCancel("You cannot put that object in that place.");
  2323.     return false;
  2324. }
  2325.  
  2326. //container/inventory to container/inventory
  2327. void Game::thingMoveInternal(Player *player,
  2328.     unsigned short from_cid, unsigned short from_slotid, unsigned short itemid,
  2329.     bool fromInventory,unsigned short to_cid, unsigned short to_slotid, bool toInventory,
  2330.     unsigned short count)
  2331. {
  2332.     Container *fromContainer = NULL;
  2333.     Container *toContainer = NULL;
  2334.     Item *fromItem = NULL;
  2335.     Item *toItem = NULL;
  2336.  
  2337.     if(fromInventory) {
  2338.         fromItem = player->getItem(from_cid);
  2339.         fromContainer = dynamic_cast<Container *>(fromItem);
  2340.     }
  2341.     else {
  2342.         fromContainer = player->getContainer(from_cid);
  2343.  
  2344.         if(fromContainer) {
  2345.             if(from_slotid >= fromContainer->size())
  2346.                 return;
  2347.  
  2348.             fromItem = fromContainer->getItem(from_slotid);
  2349.         }
  2350.     }
  2351.  
  2352.     if(toInventory) {
  2353.         toItem = player->getItem(to_cid);
  2354.         toContainer = dynamic_cast<Container *>(toItem);
  2355.     }
  2356.     else {
  2357.         toContainer = player->getContainer(to_cid);
  2358.  
  2359.         if(toContainer) {
  2360.             if(to_slotid >= toContainer->capacity())
  2361.                 return;
  2362.  
  2363.             toItem = toContainer->getItem(to_slotid);
  2364.             Container *toSlotContainer = dynamic_cast<Container*>(toItem);
  2365.             if(toSlotContainer) {
  2366.                 toContainer = toSlotContainer;
  2367.                 toItem = NULL;
  2368.             }
  2369.         }
  2370.     }
  2371.  
  2372.     if(!fromItem || (toItem == fromItem) || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()) || fromItem->getID() != itemid)
  2373.         return;
  2374.  
  2375.     //Container to container
  2376.     if(!fromInventory && fromContainer && toContainer) {
  2377.         Position fromPos = (fromContainer->pos.x == 0xFFFF ? player->pos : fromContainer->pos);
  2378.         Position toPos = (toContainer->pos.x == 0xFFFF ? player->pos : toContainer->pos);
  2379.  
  2380.         if(onPrepareMoveThing(player, fromPos, fromContainer, fromItem, toPos, toContainer, toItem, count)) {
  2381.  
  2382.             autoCloseTrade(fromItem, true);
  2383.             int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2384.             int32_t oldToCount = 0;
  2385.  
  2386.             //move around an item in a container
  2387.             if(fromItem->isStackable()) {
  2388.                 if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2389.                 {
  2390.                     oldToCount = toItem->getItemCountOrSubtype();
  2391.                     int32_t newToCount = std::min(100, oldToCount + count);
  2392.                     toItem->setItemCountOrSubtype(newToCount);
  2393.  
  2394.                     if(oldToCount != newToCount) {
  2395.                         autoCloseTrade(toItem);
  2396.                     }
  2397.  
  2398.                     int32_t subcount = oldFromCount - count;
  2399.                     fromItem->setItemCountOrSubtype(subcount);
  2400.  
  2401.                     int32_t surplusCount = oldToCount + count  - 100;
  2402.                     if(surplusCount > 0) {
  2403.                         Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2404.                         if(onPrepareMoveThing(player, fromPos, fromContainer, surplusItem, toPos, toContainer, NULL, count)) {
  2405.                             autoCloseTrade(toContainer);
  2406.                             toContainer->addItem(surplusItem);
  2407.                         }
  2408.                         else {
  2409.                             delete surplusItem;
  2410.                             count -= surplusCount; //re-define the actual amount we move.
  2411.                             fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2412.                         }
  2413.                     }
  2414.                 }
  2415.                 else if(count < oldFromCount) {
  2416.                     int32_t subcount = oldFromCount - count;
  2417.                     fromItem->setItemCountOrSubtype(subcount);
  2418.  
  2419.                     Item* moveItem = Item::CreateItem(fromItem->getID(), count);
  2420.                     toContainer->addItem(moveItem);
  2421.                     autoCloseTrade(toContainer);
  2422.                 }
  2423.                 else {
  2424.                     if(fromContainer == toContainer) {
  2425.                         fromContainer->moveItem(from_slotid, 0);
  2426.                     }
  2427.                     else if(fromContainer->removeItem(fromItem)) {
  2428.                         autoCloseTrade(toContainer);
  2429.                         toContainer->addItem(fromItem);
  2430.                     }
  2431.                 }
  2432.  
  2433.                 if(fromItem->getItemCountOrSubtype() == 0) {
  2434.                     fromContainer->removeItem(fromItem);
  2435.                     this->FreeThing(fromItem);
  2436.                 }
  2437.             }
  2438.             else {
  2439.                 if(fromContainer == toContainer) {
  2440.                     fromContainer->moveItem(from_slotid, 0);
  2441.                 }
  2442.                 else if(fromContainer->removeItem(fromItem)) {
  2443.                     autoCloseTrade(toContainer);
  2444.                     toContainer->addItem(fromItem);
  2445.                 }
  2446.             }
  2447.  
  2448.             if(player->isHoldingContainer(fromContainer) != player->isHoldingContainer(toContainer)) {
  2449.                 player->updateInventoryWeigth();
  2450.             }
  2451.  
  2452.             SpectatorVec list;
  2453.             SpectatorVec::iterator it;
  2454.  
  2455.             if(fromPos == toPos) {
  2456.                 getSpectators(Range(fromPos, false), list);
  2457.             }
  2458.             else {
  2459.                 getSpectators(Range(fromPos, toPos), list);
  2460.             }
  2461.  
  2462.             if(!list.empty()) {
  2463.                 //players
  2464.                 for(it = list.begin(); it != list.end(); ++it) {
  2465.                     if(dynamic_cast<Player*>(*it)) {
  2466.                         (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2467.                     }
  2468.                 }
  2469.  
  2470.                 //none-players
  2471.                 for(it = list.begin(); it != list.end(); ++it) {
  2472.                     if(!dynamic_cast<Player*>(*it)) {
  2473.                         (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2474.                     }
  2475.                 }
  2476.             }
  2477.             else
  2478.                 player->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2479.         }
  2480.     }
  2481.     else {
  2482.         //inventory to inventory
  2483.         if(fromInventory && toInventory && !toContainer) {
  2484.             Position fromPos = player->pos;
  2485.             Position toPos = player->pos;
  2486.             if(onPrepareMoveThing(player, fromItem, (slots_t)to_cid, count) && onPrepareMoveThing(player, (slots_t)from_cid, fromItem, (slots_t)to_cid, toItem, count)) {
  2487.  
  2488.                 autoCloseTrade(fromItem, true);
  2489.                 int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2490.                 int32_t oldToCount = 0;
  2491.  
  2492.                 //bbk 2020
  2493.                 std::cout << "inventory to inventory" << std::endl;
  2494.                 if(fromItem && (slots_t)to_cid == SLOT_RING) fromItem->setGlimmer();
  2495.                 if(toItem && (slots_t)from_cid == SLOT_RING) toItem->removeGlimmer();
  2496.  
  2497.                 if(fromItem->isStackable()) {
  2498.                     if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2499.                     {
  2500.                         oldToCount = toItem->getItemCountOrSubtype();
  2501.                         int32_t newToCount = std::min(100, oldToCount + count);
  2502.                         toItem->setItemCountOrSubtype(newToCount);
  2503.  
  2504.                         if(oldToCount != newToCount) {
  2505.                             autoCloseTrade(toItem);
  2506.                         }
  2507.  
  2508.                         int32_t subcount = oldFromCount - count;
  2509.                         fromItem->setItemCountOrSubtype(subcount);
  2510.  
  2511.                         int32_t surplusCount = oldToCount + count  - 100;
  2512.                         if(surplusCount > 0) {
  2513.                             fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2514.                             player->sendCancel("There is not enough room.");
  2515.                         }
  2516.  
  2517.                         if(fromItem->getItemCountOrSubtype() == 0) {
  2518.                             player->removeItemInventory(from_cid, true);
  2519.                             this->FreeThing(fromItem);
  2520.                         }
  2521.                     }
  2522.                     else if(count < oldFromCount) {
  2523.                         int32_t subcount = oldFromCount - count;
  2524.                         fromItem->setItemCountOrSubtype(subcount);
  2525.  
  2526.                         autoCloseTrade(toItem);
  2527.                         player->removeItemInventory(to_cid, true);
  2528.                         player->addItemInventory(Item::CreateItem(fromItem->getID(), count), to_cid, true);
  2529.  
  2530.                         if(fromItem->getItemCountOrSubtype() == 0) {
  2531.                             player->removeItemInventory(from_cid, true);
  2532.                             this->FreeThing(fromItem);
  2533.                         }
  2534.                     }
  2535.                     else {
  2536.                         if(player->removeItemInventory(from_cid, true)) {
  2537.                             player->removeItemInventory(to_cid, true);
  2538.                             player->addItemInventory(fromItem, to_cid, true);
  2539.                         }
  2540.                     }
  2541.                 }
  2542.                 else if(player->removeItemInventory(from_cid, true)) {
  2543.                     player->removeItemInventory(to_cid, true);
  2544.                     player->addItemInventory(fromItem, to_cid, true);
  2545.                 }
  2546.  
  2547.                 player->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2548.             }
  2549.         }
  2550.         //container to inventory
  2551.         else if(!fromInventory && fromContainer && toInventory) {
  2552.             if(onPrepareMoveThing(player, fromItem, (slots_t)to_cid, count) && onPrepareMoveThing(player, fromContainer, fromItem, (slots_t)to_cid, toItem, count)) {
  2553.                 autoCloseTrade(fromItem, true);
  2554.                 int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2555.                 int32_t oldToCount = 0;
  2556.  
  2557.                 //bbk 2020
  2558.                 std::cout << "container to inventory" << std::endl;
  2559.                 if(fromItem) fromItem->removeGlimmer();
  2560.                 if(toItem ) toItem->removeGlimmer();
  2561.  
  2562.                 if(fromItem->isStackable()) {
  2563.                     if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2564.                     {
  2565.                         oldToCount = toItem->getItemCountOrSubtype();
  2566.                         int32_t newToCount = std::min(100, oldToCount + count);
  2567.                         toItem->setItemCountOrSubtype(newToCount);
  2568.  
  2569.                         if(oldToCount != newToCount) {
  2570.                             autoCloseTrade(toItem);
  2571.                         }
  2572.  
  2573.                         int32_t subcount = oldFromCount - count;
  2574.                         fromItem->setItemCountOrSubtype(subcount);
  2575.  
  2576.                         int32_t surplusCount = oldToCount + count  - 100;
  2577.                         if(surplusCount > 0) {
  2578.                             fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2579.                             player->sendCancel("There is not enough room.");
  2580.                         }
  2581.  
  2582.                         if(fromItem->getItemCountOrSubtype() == 0) {
  2583.                             fromContainer->removeItem(fromItem);
  2584.                             this->FreeThing(fromItem);
  2585.                         }
  2586.                     }
  2587.                     else if(count < oldFromCount) {
  2588.                         int32_t subcount = oldFromCount - count;
  2589.                         fromItem->setItemCountOrSubtype(subcount);
  2590.  
  2591.                         player->removeItemInventory(to_cid, true);
  2592.                         player->addItemInventory(Item::CreateItem(fromItem->getID(), count), to_cid, true);
  2593.  
  2594.                         if(toItem) {
  2595.                             fromContainer->addItem(toItem);
  2596.                         }
  2597.  
  2598.                         if(fromItem->getItemCountOrSubtype() == 0) {
  2599.                             fromContainer->removeItem(fromItem);
  2600.                             this->FreeThing(fromItem);
  2601.                         }
  2602.                     }
  2603.                     else {
  2604.                         if(fromContainer->removeItem(fromItem)) {
  2605.                             player->removeItemInventory(to_cid, true);
  2606.                             player->addItemInventory(fromItem, to_cid, true);
  2607.  
  2608.                             if(toItem) {
  2609.                                 fromContainer->addItem(toItem);
  2610.                             }
  2611.                         }
  2612.                     }
  2613.                 }
  2614.                 else if(fromContainer->removeItem(fromItem)) {
  2615.                     player->removeItemInventory(to_cid, true);
  2616.                     player->addItemInventory(fromItem, to_cid, true);
  2617.  
  2618.                     if(toItem) {
  2619.                         fromContainer->addItem(toItem);
  2620.                     }
  2621.                 }
  2622.  
  2623.                 if(!player->isHoldingContainer(fromContainer)) {
  2624.                     player->updateInventoryWeigth();
  2625.                 }
  2626.  
  2627.                 //if(fromContainer->pos.x != 0xFFFF) {
  2628.                 if(fromContainer->getTopParent()->pos.x != 0xFFFF) {
  2629.                     SpectatorVec list;
  2630.                     SpectatorVec::iterator it;
  2631.  
  2632.                     getSpectators(Range(fromContainer->getTopParent()->pos, false), list);
  2633.  
  2634.                     //players
  2635.                     for(it = list.begin(); it != list.end(); ++it) {
  2636.                         if(dynamic_cast<Player*>(*it)) {
  2637.                             (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2638.                         }
  2639.                     }
  2640.  
  2641.                     //none-players
  2642.                     for(it = list.begin(); it != list.end(); ++it) {
  2643.                         if(!dynamic_cast<Player*>(*it)) {
  2644.                             (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2645.                         }
  2646.                     }
  2647.                 }
  2648.                 else
  2649.                     player->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  2650.             }
  2651.         }
  2652.         //inventory to container
  2653.         else if(fromInventory && toContainer) {
  2654.             Position fromPos = player->pos;
  2655.             Position toPos = (toContainer->pos.x == 0xFFFF ? player->pos : toContainer->pos);
  2656.  
  2657.             int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2658.             int32_t oldToCount = 0;
  2659.  
  2660.             //bbk 2020
  2661.             std::cout << "inventory to container" << std::endl;
  2662.             if(fromItem) fromItem->removeGlimmer();
  2663.             if(toItem) toItem->removeGlimmer();
  2664.  
  2665.             if(onPrepareMoveThing(player, fromItem, (slots_t)from_cid, toContainer, toItem, count)) {
  2666.                 autoCloseTrade(fromItem, true);
  2667.                 if(fromItem->isStackable()) {
  2668.                     if(toItem && toItem != fromItem && toItem->getID() == fromItem->getID())
  2669.                     {
  2670.                         oldToCount = toItem->getItemCountOrSubtype();
  2671.                         int32_t newToCount = std::min(100, oldToCount + count);
  2672.                         toItem->setItemCountOrSubtype(newToCount);
  2673.  
  2674.                         if(oldToCount != newToCount) {
  2675.                             autoCloseTrade(toItem);
  2676.                         }
  2677.  
  2678.                         int32_t subcount = oldFromCount - count;
  2679.                         fromItem->setItemCountOrSubtype(subcount);
  2680.  
  2681.                         int32_t surplusCount = oldToCount + count  - 100;
  2682.                         if(surplusCount > 0) {
  2683.                             Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2684.  
  2685.                             if(onPrepareMoveThing(player, fromPos, NULL, surplusItem, toPos, toContainer, NULL, count)) {
  2686.                                 autoCloseTrade(toContainer);
  2687.                                 toContainer->addItem(surplusItem);
  2688.                             }
  2689.                             else {
  2690.                                 delete surplusItem;
  2691.                                 count -= surplusCount; //re-define the actual amount we move.
  2692.                                 fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  2693.                             }
  2694.                         }
  2695.                     }
  2696.                     else if(count < oldFromCount) {
  2697.                         int32_t subcount = oldFromCount - count;
  2698.                         fromItem->setItemCountOrSubtype(subcount);
  2699.                         autoCloseTrade(toContainer);
  2700.                         toContainer->addItem(Item::CreateItem(fromItem->getID(), count));
  2701.                     }
  2702.                     else {
  2703.                         if(player->removeItemInventory((slots_t)from_cid, true)) {
  2704.                             autoCloseTrade(toContainer);
  2705.                             toContainer->addItem(fromItem);
  2706.  
  2707.                             if(player->isHoldingContainer(toContainer)) {
  2708.                                 player->updateInventoryWeigth();
  2709.                             }
  2710.                         }
  2711.                     }
  2712.  
  2713.                     if(fromItem->getItemCountOrSubtype() == 0) {
  2714.                         player->removeItemInventory(from_cid, true);
  2715.                         this->FreeThing(fromItem);
  2716.                     }
  2717.                 }
  2718.                 else if(player->removeItemInventory(from_cid, true)) {
  2719.                     autoCloseTrade(toContainer);
  2720.                     toContainer->addItem(fromItem);
  2721.  
  2722.                     if(player->isHoldingContainer(toContainer)) {
  2723.                         player->updateInventoryWeigth();
  2724.                     }
  2725.                 }
  2726.  
  2727.                 if(!player->isHoldingContainer(toContainer)) {
  2728.                     player->updateInventoryWeigth();
  2729.                 }
  2730.  
  2731.                 if(toContainer->getTopParent()->pos.x != 0xFFFF) {
  2732.                     SpectatorVec list;
  2733.                     SpectatorVec::iterator it;
  2734.  
  2735.                     getSpectators(Range(toContainer->getTopParent()->pos, false), list);
  2736.  
  2737.                     //players
  2738.                     for(it = list.begin(); it != list.end(); ++it) {
  2739.                         if(dynamic_cast<Player*>(*it)) {
  2740.                             (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2741.                         }
  2742.                     }
  2743.  
  2744.                     //none-players
  2745.                     for(it = list.begin(); it != list.end(); ++it) {
  2746.                         if(!dynamic_cast<Player*>(*it)) {
  2747.                             (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2748.                         }
  2749.                     }
  2750.                 }
  2751.                 else
  2752.                     player->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  2753.             }
  2754.         }
  2755.     }
  2756. }
  2757.  
  2758. //container/inventory to ground
  2759. void Game::thingMoveInternal(Player *player,
  2760.     unsigned char from_cid, unsigned char from_slotid, unsigned short itemid, bool fromInventory,
  2761.     const Position& toPos, unsigned char count)
  2762. {
  2763.     Container *fromContainer = NULL;
  2764.     Tile *toTile = map->getTile(toPos);
  2765.     if(!toTile)
  2766.         return;
  2767.  
  2768.     /*container to ground*/
  2769.     if(!fromInventory) {
  2770.         fromContainer = player->getContainer(from_cid);
  2771.         if(!fromContainer)
  2772.             return;
  2773.  
  2774.         Position fromPos = (fromContainer->pos.x == 0xFFFF ? player->pos : fromContainer->pos);
  2775.         Item *fromItem = dynamic_cast<Item*>(fromContainer->getItem(from_slotid));
  2776.         Item* toItem = dynamic_cast<Item*>(toTile->getTopDownItem());
  2777.  
  2778.         if(!fromItem || (toItem == fromItem) || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()) || fromItem->getID() != itemid)
  2779.             return;
  2780.  
  2781.         if(onPrepareMoveThing(player, fromItem, fromPos, toPos, count) && onPrepareMoveThing(player, fromItem, NULL, toTile, count)) {
  2782.             autoCloseTrade(fromItem, true);
  2783.             int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2784.             int32_t oldToCount = 0;
  2785.  
  2786.             //Do action...
  2787. #ifdef TP_TRASH_BINS
  2788.             if (toItem && toItem->isDeleter())
  2789.             {
  2790.                 fromContainer->removeItem(fromItem);
  2791.                 FreeThing(fromItem);
  2792.             }
  2793.             else if(fromItem->isStackable()) {
  2794. #else
  2795.             if(fromItem->isStackable()) {
  2796. #endif //TP_TRASH_BINS
  2797.                 if(toItem && toItem->getID() == fromItem->getID())
  2798.                 {
  2799.                     oldToCount = toItem->getItemCountOrSubtype();
  2800.                     int32_t newToCount = std::min(100, oldToCount + count);
  2801.                     toItem->setItemCountOrSubtype(newToCount);
  2802.  
  2803.                     if(oldToCount != newToCount) {
  2804.                         autoCloseTrade(toItem);
  2805.                     }
  2806.  
  2807.                     int32_t subcount = oldFromCount - count;
  2808.                     fromItem->setItemCountOrSubtype(subcount);
  2809.  
  2810.                     int32_t surplusCount = oldToCount + count  - 100;
  2811.                     if(surplusCount > 0) {
  2812.                         Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2813.                         surplusItem->pos = toPos;
  2814.  
  2815.                         toTile->addThing(surplusItem);
  2816.                     }
  2817.  
  2818.                     if(fromItem->getItemCountOrSubtype() == 0) {
  2819.                         fromContainer->removeItem(fromItem);
  2820.                         this->FreeThing(fromItem);
  2821.                     }
  2822.                 }
  2823.                 else if(count < oldFromCount) {
  2824.                     int32_t subcount = oldFromCount - count;
  2825.                     fromItem->setItemCountOrSubtype(subcount);
  2826.  
  2827.                     Item *moveItem = Item::CreateItem(fromItem->getID(), count);
  2828.                     moveItem->pos = toPos;
  2829.                     toTile->addThing(moveItem);
  2830.  
  2831.                     if(fromItem->getItemCountOrSubtype() == 0) {
  2832.                         fromContainer->removeItem(fromItem);
  2833.                         this->FreeThing(fromItem);
  2834.                     }
  2835.                 }
  2836.                 else if(fromContainer->removeItem(fromItem)) {
  2837.                     fromItem->pos = toPos;
  2838.                     toTile->addThing(fromItem);
  2839.                 }
  2840.             }
  2841.             else if(fromContainer->removeItem(fromItem)) {
  2842.                 fromItem->pos = toPos;
  2843.                 toTile->addThing(fromItem);
  2844.             }
  2845.  
  2846.             if(player->isHoldingContainer(fromContainer)) {
  2847.                 player->updateInventoryWeigth();
  2848.             }
  2849.  
  2850.             SpectatorVec list;
  2851.             SpectatorVec::iterator it;
  2852.  
  2853.             getSpectators(Range(fromPos, false), list);
  2854.  
  2855.             SpectatorVec tolist;
  2856.             getSpectators(Range(toPos, true), tolist);
  2857.  
  2858.             for(it = tolist.begin(); it != tolist.end(); ++it) {
  2859.                 if(std::find(list.begin(), list.end(), *it) == list.end()) {
  2860.                     list.push_back(*it);
  2861.                 }
  2862.             }
  2863.  
  2864.             //players
  2865.             for(it = list.begin(); it != list.end(); ++it) {
  2866.                 if(dynamic_cast<Player*>(*it)) {
  2867.                     (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2868.                 }
  2869.             }
  2870.  
  2871.             //none-players
  2872.             for(it = list.begin(); it != list.end(); ++it) {
  2873.                 if(!dynamic_cast<Player*>(*it)) {
  2874.                     (*it)->onThingMove(player, fromContainer, from_slotid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2875.                 }
  2876.             }
  2877.         }
  2878.     }
  2879.     else /*inventory to ground*/{
  2880.         Item *fromItem = player->getItem(from_cid);
  2881.         if(!fromItem || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()) || fromItem->getID() != itemid)
  2882.             return;
  2883.  
  2884.         if(onPrepareMoveThing(player, fromItem, player->pos, toPos, count) && onPrepareMoveThing(player, fromItem, NULL, toTile, count)) {
  2885.             autoCloseTrade(fromItem, true);
  2886.             Item* toItem = dynamic_cast<Item*>(toTile->getTopDownItem());
  2887.             int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  2888.             int32_t oldToCount = 0;
  2889.  
  2890.             //bbk 2020
  2891.             std::cout << "inventory to ground" << std::endl;
  2892.             if(fromItem) fromItem->removeGlimmer();
  2893.  
  2894.             //Do action...
  2895. #ifdef TP_TRASH_BINS
  2896.             if(toItem && toItem->isDeleter())
  2897.             {
  2898.                 player->removeItemInventory(from_cid, true);
  2899.                 FreeThing(fromItem);
  2900.             }
  2901.             else if(fromItem->isStackable()) {
  2902. #else
  2903.             if(fromItem->isStackable()) {
  2904. #endif //TP_TRASH_BINS
  2905.                 if(toItem && toItem->getID() == fromItem->getID())
  2906.                 {
  2907.                     oldToCount = toItem->getItemCountOrSubtype();
  2908.                     int32_t newToCount = std::min(100, oldToCount + count);
  2909.                     toItem->setItemCountOrSubtype(newToCount);
  2910.  
  2911.                     if(oldToCount != newToCount) {
  2912.                         autoCloseTrade(toItem);
  2913.                     }
  2914.  
  2915.                     int32_t subcount = oldFromCount - count;
  2916.                     fromItem->setItemCountOrSubtype(subcount);
  2917.  
  2918.                     int32_t surplusCount = oldToCount + count  - 100;
  2919.                     if(surplusCount > 0) {
  2920.                         Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  2921.                         surplusItem->pos = toPos;
  2922.  
  2923.                         toTile->addThing(surplusItem);
  2924.                     }
  2925.  
  2926.                     if(fromItem->getItemCountOrSubtype() == 0) {
  2927.                         player->removeItemInventory(from_cid, true);
  2928.                         this->FreeThing(fromItem);
  2929.                     }
  2930.                 }
  2931.                 else if(count < oldFromCount) {
  2932.                     int32_t subcount = oldFromCount - count;
  2933.                     fromItem->setItemCountOrSubtype(subcount);
  2934.  
  2935.                     Item *moveItem = Item::CreateItem(fromItem->getID(), count);
  2936.                     moveItem->pos = toPos;
  2937.                     toTile->addThing(moveItem);
  2938.  
  2939.                     if(fromItem->getItemCountOrSubtype() == 0) {
  2940.                         player->removeItemInventory(from_cid, true);
  2941.                         this->FreeThing(fromItem);
  2942.                     }
  2943.                 }
  2944.                 else if(player->removeItemInventory(from_cid, true)) {
  2945.                     fromItem->pos = toPos;
  2946.                     toTile->addThing(fromItem);
  2947.                 }
  2948.             }
  2949.             else if(player->removeItemInventory(from_cid, true)) {
  2950.                 fromItem->pos = toPos;
  2951.                 toTile->addThing(fromItem);
  2952.             }
  2953.  
  2954.             player->updateInventoryWeigth();
  2955.  
  2956.             SpectatorVec list;
  2957.             SpectatorVec::iterator it;
  2958.  
  2959.             getSpectators(Range(player->pos, false), list);
  2960.  
  2961.             SpectatorVec tolist;
  2962.             getSpectators(Range(toPos, true), tolist);
  2963.  
  2964.             for(it = tolist.begin(); it != tolist.end(); ++it) {
  2965.                 if(std::find(list.begin(), list.end(), *it) == list.end()) {
  2966.                     list.push_back(*it);
  2967.                 }
  2968.             }
  2969.  
  2970.             //players
  2971.             for(it = list.begin(); it != list.end(); ++it) {
  2972.                 if(dynamic_cast<Player*>(*it)) {
  2973.                     (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2974.                 }
  2975.             }
  2976.  
  2977.             //none-players
  2978.             for(it = list.begin(); it != list.end(); ++it) {
  2979.                 if(!dynamic_cast<Player*>(*it)) {
  2980.                     (*it)->onThingMove(player, (slots_t)from_cid, fromItem, oldFromCount, toPos, toItem, oldToCount, count);
  2981.                 }
  2982.             }
  2983.         }
  2984.     }
  2985.  
  2986. }
  2987.  
  2988. //ground to container/inventory
  2989. void Game::thingMoveInternal(Player *player, const Position& fromPos, unsigned char stackPos,
  2990.                              uint16_t itemid, unsigned char to_cid, unsigned char to_slotid, bool toInventory, unsigned char count)
  2991. {
  2992.     Tile *fromTile = map->getTile(fromPos);
  2993.     if(!fromTile)
  2994.         return;
  2995.  
  2996.     Container *toContainer = NULL;
  2997.  
  2998.     Item* fromItem = dynamic_cast<Item*>(fromTile->getTopDownItem());
  2999.     Item *toItem = NULL;
  3000.  
  3001.     if(!fromItem || (fromItem->getID() != itemid) || (fromItem != fromTile->getTopDownItem()))
  3002.         return;
  3003.  
  3004.     if(toInventory)
  3005.     {
  3006.         toItem = player->getItem(to_cid);
  3007.         toContainer = dynamic_cast<Container*>(toItem);
  3008.     }
  3009.     else
  3010.     {
  3011.         toContainer = player->getContainer(to_cid);
  3012.         if(!toContainer)
  3013.             return;
  3014.  
  3015.         toItem = toContainer->getItem(to_slotid);
  3016.         Container *toSlotContainer = dynamic_cast<Container*>(toItem);
  3017.  
  3018.         if(toSlotContainer)
  3019.         {
  3020.             toContainer = toSlotContainer;
  3021.             toItem = NULL;
  3022.         }
  3023.     }
  3024.  
  3025.     if((toItem == fromItem) || (fromItem->isStackable() && count > fromItem->getItemCountOrSubtype()))
  3026.         return;
  3027.  
  3028.     /*ground to container*/
  3029.     if(toContainer)
  3030.     {
  3031.         /*if(onPrepareMoveThing(player, fromItem, fromPos, player->pos, count) &&
  3032.                 onPrepareMoveThing(player, fromItem, NULL, toContainer, toItem, count))*/
  3033.  
  3034.         Position toPos = (toContainer->pos.x == 0xFFFF ? player->pos : toContainer->pos);
  3035.         if(onPrepareMoveThing(player, fromPos, NULL, fromItem, toPos, toContainer, toItem, count))
  3036.         {
  3037.             autoCloseTrade(fromItem, true);
  3038.             int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  3039.             int32_t oldToCount = 0;
  3040.             int32_t stackpos = fromTile->getThingStackPos(fromItem);
  3041.  
  3042.             if(fromItem->isStackable())
  3043.             {
  3044.                 if(toItem && toItem->getID() == fromItem->getID())
  3045.                 {
  3046.                     oldToCount = toItem->getItemCountOrSubtype();
  3047.                     int32_t newToCount = std::min(100, oldToCount + count);
  3048.                     toItem->setItemCountOrSubtype(newToCount);
  3049.  
  3050.                     if(oldToCount != newToCount)
  3051.                     {
  3052.                         autoCloseTrade(toItem);
  3053.                     }
  3054.  
  3055.                     int32_t subcount = oldFromCount - count;
  3056.                     fromItem->setItemCountOrSubtype(subcount);
  3057.  
  3058.                     int32_t surplusCount = oldToCount + count  - 100;
  3059.                     if(surplusCount > 0)
  3060.                     {
  3061.                         Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  3062.  
  3063.                         if(onPrepareMoveThing(player, fromPos, NULL, surplusItem, toPos, toContainer, NULL, count))
  3064.                         {
  3065.                             autoCloseTrade(toContainer);
  3066.                             toContainer->addItem(surplusItem);
  3067.                         }
  3068.                         else
  3069.                         {
  3070.                             delete surplusItem;
  3071.                             count -= surplusCount; //re-define the actual amount we move.
  3072.                             fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  3073.                         }
  3074.                     }
  3075.  
  3076.                     if(fromItem->getItemCountOrSubtype() == 0)
  3077.                     {
  3078.                         if(fromTile->removeThing(fromItem))
  3079.                         {
  3080.                             this->FreeThing(fromItem);
  3081.                         }
  3082.                     }
  3083.                 }
  3084.                 else if(count < oldFromCount)
  3085.                 {
  3086.                     int32_t subcount = oldFromCount - count;
  3087.                     fromItem->setItemCountOrSubtype(subcount);
  3088.  
  3089.                     autoCloseTrade(toContainer);
  3090.                     toContainer->addItem(Item::CreateItem(fromItem->getID(), count));
  3091.  
  3092.                     if(fromItem->getItemCountOrSubtype() == 0)
  3093.                     {
  3094.                         if(fromTile->removeThing(fromItem))
  3095.                         {
  3096.                             this->FreeThing(fromItem);
  3097.                         }
  3098.                     }
  3099.                 }
  3100.                 else if(fromTile->removeThing(fromItem))
  3101.                 {
  3102.                     autoCloseTrade(toContainer);
  3103.                     toContainer->addItem(fromItem);
  3104.                 }
  3105.             }
  3106.             else
  3107.             {
  3108.                 if(fromTile->removeThing(fromItem))
  3109.                 {
  3110.                     autoCloseTrade(toContainer);
  3111.                     toContainer->addItem(fromItem);
  3112.                 }
  3113.             }
  3114.  
  3115.             if(player->isHoldingContainer(toContainer))
  3116.             {
  3117.                 player->updateInventoryWeigth();
  3118.             }
  3119.  
  3120.             SpectatorVec list;
  3121.             SpectatorVec::iterator it;
  3122.  
  3123.             getSpectators(Range(fromPos, true), list);
  3124.  
  3125.             //players
  3126.             for(it = list.begin(); it != list.end(); ++it)
  3127.             {
  3128.                 if(dynamic_cast<Player*>(*it))
  3129.                 {
  3130.                     (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  3131.                 }
  3132.             }
  3133.  
  3134.             //none-players
  3135.             for(it = list.begin(); it != list.end(); ++it)
  3136.             {
  3137.                 if(!dynamic_cast<Player*>(*it))
  3138.                 {
  3139.                     (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, toContainer, to_slotid, toItem, oldToCount, count);
  3140.                 }
  3141.             }
  3142.         }
  3143.     }
  3144.     //ground to inventory
  3145.     else if(toInventory)
  3146.     {
  3147.         if(onPrepareMoveThing(player, fromPos, fromItem, (slots_t)to_cid, count) && onPrepareMoveThing(player, fromItem, (slots_t)to_cid, count))
  3148.         {
  3149.             autoCloseTrade(fromItem, true);
  3150.             int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  3151.             int32_t oldToCount = 0;
  3152.             int32_t stackpos = fromTile->getThingStackPos(fromItem);
  3153.  
  3154.             //bbk 2020
  3155.             std::cout << "ground to inventory" << std::endl;
  3156.             if(fromItem && (slots_t)to_cid == SLOT_RING) {
  3157.                 fromItem->setGlimmer();
  3158.                 if(toItem) toItem->removeGlimmer();
  3159.             }
  3160.  
  3161.             if(fromItem->isStackable())
  3162.             {
  3163.                 if(toItem && toItem->getID() == fromItem->getID())
  3164.                 {
  3165.                     oldToCount = toItem->getItemCountOrSubtype();
  3166.                     int32_t newToCount = std::min(100, oldToCount + count);
  3167.                     toItem->setItemCountOrSubtype(newToCount);
  3168.  
  3169.                     if(oldToCount != newToCount)
  3170.                     {
  3171.                         autoCloseTrade(toItem);
  3172.                     }
  3173.  
  3174.                     int32_t subcount = oldFromCount - count;
  3175.                     fromItem->setItemCountOrSubtype(subcount);
  3176.  
  3177.                     int32_t surplusCount = oldToCount + count  - 100;
  3178.                     if(surplusCount > 0)
  3179.                     {
  3180.                         fromItem->setItemCountOrSubtype(fromItem->getItemCountOrSubtype() + surplusCount);
  3181.                         player->sendCancel("Sorry not enough room.");
  3182.                     }
  3183.  
  3184.                     if(fromItem->getItemCountOrSubtype() == 0)
  3185.                     {
  3186.                         if(fromTile->removeThing(fromItem))
  3187.                         {
  3188.                             this->FreeThing(fromItem);
  3189.                         }
  3190.                     }
  3191.                 }
  3192.                 else if(count < oldFromCount)
  3193.                 {
  3194.                     int32_t subcount = oldFromCount - count;
  3195.                     fromItem->setItemCountOrSubtype(subcount);
  3196.  
  3197.                     player->removeItemInventory(to_cid, true);
  3198.                     player->addItemInventory(Item::CreateItem(fromItem->getID(), count), to_cid, true);
  3199.  
  3200.                     if(toItem)
  3201.                     {
  3202.                         autoCloseTrade(toItem);
  3203.                         fromTile->addThing(toItem);
  3204.                         toItem->pos = fromPos;
  3205.                     }
  3206.  
  3207.                     if(fromItem->getItemCountOrSubtype() == 0)
  3208.                     {
  3209.                         if(fromTile->removeThing(fromItem))
  3210.                         {
  3211.                             this->FreeThing(fromItem);
  3212.                         }
  3213.                     }
  3214.                 }
  3215.                 else
  3216.                 {
  3217.                     if(fromTile->removeThing(fromItem))
  3218.                     {
  3219.                         player->removeItemInventory(to_cid, true);
  3220.                         player->addItemInventory(fromItem, to_cid, true);
  3221.  
  3222.                         if(toItem)
  3223.                         {
  3224.                             autoCloseTrade(toItem);
  3225.                             fromTile->addThing(toItem);
  3226.                             toItem->pos = fromPos;
  3227.                         }
  3228.                     }
  3229.                 }
  3230.             }
  3231.             else
  3232.             {
  3233.                 if(fromTile->removeThing(fromItem))
  3234.                 {
  3235.                     player->removeItemInventory(to_cid, true);
  3236.                     player->addItemInventory(fromItem, to_cid, true);
  3237.  
  3238.                     if(toItem)
  3239.                     {
  3240.                         autoCloseTrade(toItem);
  3241.                         fromTile->addThing(toItem);
  3242.                         toItem->pos = fromPos;
  3243.                     }
  3244.                 }
  3245.             }
  3246.  
  3247.             player->updateInventoryWeigth();
  3248.  
  3249.             SpectatorVec list;
  3250.             SpectatorVec::iterator it;
  3251.  
  3252.             getSpectators(Range(fromPos, true), list);
  3253.  
  3254.             //players
  3255.             for(it = list.begin(); it != list.end(); ++it)
  3256.             {
  3257.                 if(dynamic_cast<Player*>(*it))
  3258.                 {
  3259.                     (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  3260.                 }
  3261.             }
  3262.  
  3263.             //none-players
  3264.             for(it = list.begin(); it != list.end(); ++it)
  3265.             {
  3266.                 if(!dynamic_cast<Player*>(*it))
  3267.                 {
  3268.                     (*it)->onThingMove(player, fromPos, stackpos, fromItem, oldFromCount, (slots_t)to_cid, toItem, oldToCount, count);
  3269.                 }
  3270.             }
  3271.         }
  3272.     }
  3273. }
  3274.  
  3275. //ground to ground
  3276. void Game::thingMoveInternal(Creature *creature, unsigned short from_x, unsigned short from_y, unsigned char from_z,
  3277.     unsigned char stackPos, unsigned short itemid, unsigned short to_x, unsigned short to_y, unsigned char to_z, unsigned char count)
  3278. {
  3279.     Tile *fromTile = getTile(from_x, from_y, from_z);
  3280.     if(!fromTile)
  3281.         return;
  3282.        
  3283. if(dynamic_cast<Player*>(creature) && fromTile && !fromTile->ground) {
  3284. dynamic_cast<Player*>(creature)->sendCancelWalk();
  3285. return;
  3286. }
  3287.  
  3288.     Tile *toTile   = getTile(to_x, to_y, to_z);
  3289.     /*
  3290.     if(!toTile){
  3291.         if(dynamic_cast<Player*>(player))
  3292.             dynamic_cast<Player*>(player)->sendCancelWalk("Sorry, not possible...");
  3293.         return;
  3294.     }
  3295.     */
  3296.  
  3297.     Thing *thing = fromTile->getThingByStackPos(stackPos);
  3298.  
  3299.     if (!thing)
  3300.         return;
  3301.  
  3302.     Item* item = dynamic_cast<Item*>(thing);
  3303.     Creature* creatureMoving = dynamic_cast<Creature*>(thing);
  3304.     Player* playerMoving = dynamic_cast<Player*>(creatureMoving);
  3305.     Player* player = dynamic_cast<Player*>(creature);
  3306.  
  3307.     Position oldPos;
  3308.     oldPos.x = from_x;
  3309.     oldPos.y = from_y;
  3310.     oldPos.z = from_z;
  3311.    
  3312. #ifdef TP_TRASH_BINS
  3313.     if(toTile)
  3314.     {
  3315.         Thing *tothing = toTile->getThingByStackPos(stackPos);
  3316.         Item *toItem = dynamic_cast<Item*>(tothing);
  3317.  
  3318.         if(item && toItem && !playerMoving && !creature && toItem->isDeleter())
  3319.         {
  3320.             fromTile->removeThing(item);
  3321.             this->FreeThing(item);
  3322.             //creatureBroadcastTileUpdated(oldPos);
  3323.             sendRemoveThing(player, item->pos, item, stackPos);
  3324.             return;
  3325.         }
  3326.     }
  3327. #endif //TP_TRASH_BINS
  3328. /* if (toTile){
  3329. ItemVector::iterator brn;
  3330. for (brn = toTile->downItems.begin(); brn != toTile->downItems.end(); brn++)
  3331. {
  3332. if (playerMoving && (*brn)->getID() == 1397 && player != thing || playerMoving && (*brn)->getID() == 1487 && player != thing || playerMoving && (*brn)->getID() == 1488 && player != thing || playerMoving && (*brn)->getID() == 1490 && player != thing || playerMoving && (*brn)->getID() == 1491 && player != thing || playerMoving && (*brn)->getID() == 1492 && player != thing || playerMoving && (*brn)->getID() == 1493 && player != thing || playerMoving && (*brn)->getID() == 1495 && player != thing || playerMoving && (*brn)->getID() == 1496 && player != thing || playerMoving && (*brn)->getID() == 1500 && player != thing || playerMoving && (*brn)->getID() == 1501 && player != thing || playerMoving && (*brn)->getID() == 1503 && player != thing || playerMoving && (*brn)->getID() == 1504 && player != thing || playerMoving && (*brn)->getID() == 1505 && player != thing || playerMoving && (*brn)->getID() == 1506 && player != thing || playerMoving && (*brn)->getID() == 1507 && player != thing || playerMoving && (*brn)->getID() == 1423 && player != thing || playerMoving && (*brn)->getID() == 1424 && player != thing || playerMoving && (*brn)->getID() == 1425 && player != thing)
  3333. */
  3334. if(toTile && player && playerMoving && playerMoving != player && toTile->getFieldItem())
  3335. {
  3336. player->sendCancel("Sorry, not possible.");
  3337. return;
  3338. }
  3339.     // *** Creature moving itself to a non-tile
  3340.     if(!toTile && creatureMoving && creatureMoving == creature){
  3341.         //change level begin
  3342.         Tile* downTile = getTile(to_x, to_y, to_z+1);
  3343.         //diagonal begin
  3344.         if(!downTile)
  3345.         {
  3346.             if(player) {
  3347.                 player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  3348.                 player->sendCancelWalk();
  3349.             }
  3350.  
  3351.             return;
  3352.         }
  3353.        
  3354.         if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  3355.             teleport(creatureMoving, Position(creatureMoving->pos.x-2, creatureMoving->pos.y+2, creatureMoving->pos.z+1));
  3356.         }
  3357.         else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  3358.             teleport(creatureMoving, Position(creatureMoving->pos.x+2, creatureMoving->pos.y+2, creatureMoving->pos.z+1));
  3359.         }
  3360.         else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  3361.             teleport(creatureMoving, Position(creatureMoving->pos.x-2, creatureMoving->pos.y-2, creatureMoving->pos.z+1));
  3362.         }
  3363.         else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  3364.             teleport(creatureMoving, Position(creatureMoving->pos.x+2, creatureMoving->pos.y-2, creatureMoving->pos.z+1));
  3365.         }
  3366.         //diagonal end
  3367.         else if(downTile->floorChange(NORTH)){
  3368.             teleport(creatureMoving, Position(to_x, to_y + 1, creatureMoving->pos.z+1));
  3369.         }
  3370.         else if(downTile->floorChange(SOUTH)){
  3371.             teleport(creatureMoving, Position(to_x, to_y - 1, creatureMoving->pos.z+1));
  3372.         }
  3373.         else if(downTile->floorChange(EAST)){
  3374.             teleport(creatureMoving, Position(to_x - 1, to_y, creatureMoving->pos.z+1));
  3375.         }
  3376.         else if(downTile->floorChange(WEST)){
  3377.             teleport(creatureMoving, Position(to_x + 1, to_y, creatureMoving->pos.z+1));
  3378.         }
  3379.         else
  3380.             if(player) {
  3381.                 player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  3382.                 player->sendCancelWalk();
  3383.             }
  3384.  
  3385.         //change level end
  3386.         return;
  3387.     }
  3388.    
  3389.     #ifdef DT_PREMMY
  3390.       if(player && playerMoving && !player->premmium == true){
  3391.            if(!premmytiles.empty()){
  3392.             for(int32_t o = 0; o < premmytiles.size(); o++) {
  3393.                 if((premmytiles[o].second.x != 0) &&
  3394. (premmytiles[o].second.y != 0) && (premmytiles[o].second.z != 0)){
  3395.                     if(Position(to_x, to_y, to_z) == premmytiles[o].first) {
  3396.                         player->sendCancelWalk();
  3397.                         teleport(playerMoving,
  3398. Position(premmytiles[o].second.x, premmytiles[o].second.y,
  3399. premmytiles[o].second.z));
  3400.                         player->sendMagicEffect(player->pos,
  3401. NM_ME_MAGIC_ENERGIE);
  3402.                         return;
  3403.                     }
  3404.                 }
  3405.                 else{
  3406.                     if(Position(to_x, to_y, to_z) == premmytiles[o].first) {
  3407.                         player->sendCancelWalk();
  3408.                         break;
  3409.                     }
  3410.                 }
  3411.             }
  3412.         }
  3413.     }
  3414.  
  3415. #endif //DT_PREMMY
  3416.  
  3417.  
  3418.  
  3419.     // *** Checking if the thing can be moved around
  3420.  
  3421.     if(!toTile)
  3422.         return;
  3423.  
  3424.     if(!onPrepareMoveThing(creature, thing, oldPos, Position(to_x, to_y, to_z), count))
  3425.         return;
  3426.  
  3427.     if(creatureMoving && !onPrepareMoveCreature(creature, creatureMoving, fromTile, toTile))
  3428.         return;
  3429.  
  3430.     if(!onPrepareMoveThing(creature, thing, fromTile, toTile, count))
  3431.         return;
  3432.        
  3433.              Position to_pos;
  3434.      to_pos.x = to_x;
  3435.      to_pos.y = to_y;
  3436.      to_pos.z = to_z;
  3437.  
  3438.     Item* fromItem = dynamic_cast<Item*>(getThing(oldPos, stackPos, player));
  3439.     Item* toItem = dynamic_cast<Item*>(toTile->getTopDownItem());
  3440.  
  3441.     if(fromItem && fromItem->isStackable()){
  3442.                 if(fromItem->getItemCountOrSubtype() < count)
  3443.                 {
  3444.                 player->sendCancel("Sorry, not possible.");
  3445.                 return;
  3446.                 }
  3447.  
  3448.         if((abs(player->pos.x - oldPos.x) > 1) || (abs(player->pos.y - oldPos.y) > 1) || (player->pos.z != oldPos.z)){
  3449.                player->sendCancel("It's far away.");
  3450.                return;
  3451.         }
  3452.         if(toItem && fromItem->getID() == toItem->getID()){
  3453.             int32_t oldToCount = toItem->getItemCountOrSubtype();
  3454.             int32_t oldFromCount = fromItem->getItemCountOrSubtype();
  3455.             int32_t newToCount = std::min(100, oldToCount + count);
  3456.             toItem->setItemCountOrSubtype(newToCount);
  3457.  
  3458.             if(oldToCount != newToCount) {
  3459.                 autoCloseTrade(toItem);
  3460.             }
  3461.  
  3462.             int32_t subcount = oldFromCount - count;
  3463.             fromItem->setItemCountOrSubtype(subcount);
  3464.  
  3465.             int32_t surplusCount = oldToCount + count  - 100;
  3466.             if(surplusCount > 0) {
  3467.                 Item *surplusItem = Item::CreateItem(fromItem->getID(), surplusCount);
  3468.                 surplusItem->pos = to_pos;
  3469.                 toTile->addThing(surplusItem);
  3470.             }
  3471.  
  3472.             if(fromItem->getItemCountOrSubtype() == 0) {
  3473.                 if(removeThing(player, oldPos, fromItem))
  3474.                     player->updateInventoryWeigth();
  3475.             }
  3476.  
  3477.             creatureBroadcastTileUpdated(to_pos);
  3478.             creatureBroadcastTileUpdated(oldPos);
  3479.  
  3480.             return;
  3481.        }
  3482.        else if(count < fromItem->getItemCountOrSubtype()) {
  3483.             int32_t subcount = fromItem->getItemCountOrSubtype() - count;
  3484.             fromItem->setItemCountOrSubtype(subcount);
  3485.  
  3486.             Item *moveItem = Item::CreateItem(fromItem->getID(), count);
  3487.             moveItem->pos = to_pos;
  3488.             toTile->addThing(moveItem);
  3489.  
  3490.             if(fromItem->getItemCountOrSubtype() == 0) {
  3491.                 if(removeThing(player, oldPos, fromItem))
  3492.                           player->updateInventoryWeigth();
  3493.             }
  3494.  
  3495.             creatureBroadcastTileUpdated(to_pos);
  3496.                creatureBroadcastTileUpdated(oldPos);
  3497.             return;
  3498.           }
  3499.           else{
  3500.                Item *moveItem = Item::CreateItem(fromItem->getID(), fromItem->getItemCountOrSubtype());
  3501.                moveItem->pos = to_pos;
  3502.                toTile->addThing(moveItem);
  3503.  
  3504.                if(removeThing(player, oldPos, fromItem))
  3505.                     player->updateInventoryWeigth();
  3506.  
  3507.                creatureBroadcastTileUpdated(to_pos);
  3508.                creatureBroadcastTileUpdated(oldPos);
  3509.                return;
  3510.           }
  3511.  
  3512.           return;
  3513.     }
  3514.  
  3515.     /*
  3516.     if(item && (item->getID() != itemid || item != fromTile->getTopDownItem()))
  3517.         return;
  3518.     */
  3519.  
  3520.     // *** If the destiny is a teleport item, teleport the thing
  3521.  
  3522. const Teleport *teleportitem = toTile->getTeleportItem();
  3523.     if(teleportitem) {
  3524.         Player *player = dynamic_cast<Player*>(thing);
  3525.         teleport(thing, teleportitem->getDestPos());
  3526.         if(player) {
  3527.         globalMagicEffect(player->pos, NM_ME_ENERGY_AREA);
  3528.         }
  3529.         return;
  3530.     }
  3531.  
  3532.    Monster* monsterMoving = dynamic_cast<Monster*>(creatureMoving);
  3533.    if (monsterMoving && toTile->isPz()){
  3534.    return;
  3535.    }
  3536.    
  3537. #ifdef TLM_HOUSE_SYSTEM
  3538.     if (playerMoving && toTile->getHouse() &&
  3539.         (fromTile->getHouse() != toTile->getHouse() || playerMoving->houseRightsChanged))
  3540.     {
  3541.         if (playerMoving->access < g_config.ACCESS_HOUSE &&
  3542.             toTile->getHouse()->getPlayerRights(playerMoving->getName()) == HOUSE_NONE)
  3543.         {
  3544.             playerMoving->sendTextMessage(MSG_SMALLINFO, "You are not invited.");
  3545.             playerMoving->sendCancelWalk();
  3546.             return;
  3547.         }
  3548.         else
  3549.             playerMoving->houseRightsChanged = false;   // if we are invited stop checking rights
  3550.     }
  3551. #endif //TLM_HOUSE_SYSTEM
  3552.  
  3553.     // *** Normal moving
  3554.  
  3555.     if(creatureMoving)
  3556.     {
  3557.         // we need to update the direction the player is facing to...
  3558.         // otherwise we are facing some problems in turning into the
  3559.         // direction we were facing before the movement
  3560.         // check y first cuz after a diagonal move we lock to east or west
  3561.         if (to_y < oldPos.y) creatureMoving->direction = NORTH;
  3562.         if (to_y > oldPos.y) creatureMoving->direction = SOUTH;
  3563.         if (to_x > oldPos.x) creatureMoving->direction = EAST;
  3564.         if (to_x < oldPos.x) creatureMoving->direction = WEST;
  3565.     }
  3566.  
  3567.     int32_t oldstackpos = fromTile->getThingStackPos(thing);
  3568.     if (fromTile->removeThing(thing))
  3569.     {
  3570.         toTile->addThing(thing);
  3571.  
  3572.         thing->pos.x = to_x;
  3573.         thing->pos.y = to_y;
  3574.         thing->pos.z = to_z;
  3575.  
  3576.         SpectatorVec list;
  3577.         SpectatorVec::iterator it;
  3578.  
  3579.         getSpectators(Range(oldPos, Position(to_x, to_y, to_z)), list);
  3580.  
  3581. #ifdef TRS_GM_INVISIBLE
  3582.         if(playerMoving && playerMoving->gmInvisible)
  3583.         {
  3584.             for(it = list.begin(); it != list.end(); ++it)
  3585.             {
  3586.                 if(playerMoving == (*it) || (*it)->access >= playerMoving->access)
  3587.                 {
  3588.                     if(Player* p = dynamic_cast<Player*>(*it))
  3589.                     {
  3590.                         if(p->attackedCreature == creature->getID())
  3591.                         {
  3592.                             autoCloseAttack(p, creature);
  3593.                         }
  3594.                         (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3595.                     }
  3596.                 }
  3597.             }
  3598.         }
  3599.         else if(playerMoving && !playerMoving->gmInvisible)
  3600.         {
  3601.             for(it = list.begin(); it != list.end(); ++it)
  3602.             {
  3603.                 if(Player* p = dynamic_cast<Player*>(*it))
  3604.                 {
  3605.                     if(p->attackedCreature == creature->getID())
  3606.                     {
  3607.                         autoCloseAttack(p, creature);
  3608.                     }
  3609.                     (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3610.                 }
  3611.             }
  3612.         }
  3613.         else
  3614.         {
  3615.             for(it = list.begin(); it != list.end(); ++it)
  3616.             {
  3617.                 if(Player* p = dynamic_cast<Player*>(*it))
  3618.                 {
  3619.                     if(p->attackedCreature == creature->getID())
  3620.                     {
  3621.                         autoCloseAttack(p, creature);
  3622.                     }
  3623.                     (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3624.                 }
  3625.             }
  3626.         }
  3627. #else //TRS_GM_INVISIBLE
  3628.         //players
  3629.         for(it = list.begin(); it != list.end(); ++it)
  3630.         {
  3631.             if(Player* p = dynamic_cast<Player*>(*it)) {
  3632.         if(p->attackedCreature == creature->getID()) {
  3633.           autoCloseAttack(p, creature);
  3634.         }
  3635.                 (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3636.             }
  3637.         }
  3638. #endif //TRS_GM_INVISIBLE
  3639.  
  3640.         //none-players
  3641.         for(it = list.begin(); it != list.end(); ++it)
  3642.         {
  3643.             if(!dynamic_cast<Player*>(*it)) {
  3644.                 (*it)->onThingMove(creature, thing, &oldPos, oldstackpos, 1, 1);
  3645.             }
  3646.         }
  3647.  
  3648.         autoCloseTrade(item, true);
  3649.         //depot tiles
  3650.        
  3651.         if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 426))
  3652. {
  3653. int32_t e = 0;
  3654. Container* c = playerMoving->getDepot(1);
  3655. std::stringstream s;
  3656. e += getDepot(c, e);
  3657. s << "Your depot contains " << e;
  3658. if(e > 1)
  3659. s << " items.";
  3660. else
  3661. s << " item.";
  3662. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3663. }
  3664.  
  3665. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 416))
  3666. {
  3667. int32_t e = 0;
  3668. Container* c = playerMoving->getDepot(2);
  3669. std::stringstream s;
  3670. e += getDepot(c, e);
  3671. s << "Your depot contains " << e;
  3672. if(e > 1)
  3673. s << " items.";
  3674. else
  3675. s << " item.";
  3676. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3677. }
  3678.  
  3679. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 446))
  3680. {
  3681. int32_t e = 0;
  3682. Container* c = playerMoving->getDepot(3);
  3683. std::stringstream s;
  3684. e += getDepot(c, e);
  3685. s << "Your depot contains " << e;
  3686. if(e > 1)
  3687. s << " items.";
  3688. else
  3689. s << " item.";
  3690. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3691. }
  3692.  
  3693. if(playerMoving && toTile && fromTile && toTile->isPz() && fromTile->isPz() && (toTile->ground->getID() == 3216))
  3694. {
  3695. int32_t e = 0;
  3696. Container* c = playerMoving->getDepot(4);
  3697. std::stringstream s;
  3698. e += getDepot(c, e);
  3699. s << "Your depot contains " << e;
  3700. if(e > 1)
  3701. s << " items.";
  3702. else
  3703. s << " item.";
  3704. playerMoving->sendTextMessage(MSG_EVENT, s.str().c_str());
  3705. }
  3706.        
  3707.         if(playerMoving && toTile && fromTile)
  3708.         {
  3709.             actions.luaWalk(playerMoving,playerMoving->pos,toTile->ground->getID(),toTile->ground->getUniqueId(),toTile->ground->getActionId()); //CHANGE onWalk
  3710.         }
  3711.  
  3712.         if(playerMoving && toTile && fromTile)
  3713.         {
  3714.             actions.luaWalkOff(playerMoving,oldPos,fromTile->ground->getID(),fromTile->ground->getUniqueId(),fromTile->ground->getActionId()); //CHANGE onWalk
  3715.         }
  3716.        
  3717. if(playerMoving && fromTile && toTile && player == playerMoving)
  3718. switch(toTile->ground->getID())
  3719. {
  3720. case 416:
  3721. {
  3722. toTile->removeThing(toTile->ground);
  3723. toTile->addThing(new Item(417));
  3724. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3725. }
  3726. break;
  3727.  
  3728. case 426:
  3729. {
  3730. toTile->removeThing(toTile->ground);
  3731. toTile->addThing(new Item(425));
  3732. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3733. }
  3734. break;
  3735. case 3216:
  3736. {
  3737. toTile->removeThing(toTile->ground);
  3738. toTile->addThing(new Item(3217));
  3739. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3740. }
  3741. break;
  3742. case 446:
  3743. {
  3744. toTile->removeThing(toTile->ground);
  3745. toTile->addThing(new Item(447));
  3746. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3747. }
  3748. break;
  3749. case 293:
  3750. {
  3751. toTile->removeThing(toTile->ground);
  3752. toTile->addThing(new Item(294));
  3753. creature->onTileUpdated(Position(to_x,to_y,to_z));
  3754. }
  3755. break;
  3756. }
  3757. switch(fromTile->ground->getID())
  3758. {
  3759. case 3217:
  3760. {
  3761. fromTile->removeThing(fromTile->ground);
  3762. fromTile->addThing(new Item(3216));
  3763. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3764. break;
  3765. }
  3766. case 417:
  3767. {
  3768. fromTile->removeThing(fromTile->ground);
  3769. fromTile->addThing(new Item(416));
  3770. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3771. break;
  3772. }
  3773. case 425:
  3774. {
  3775. fromTile->removeThing(fromTile->ground);
  3776. fromTile->addThing(new Item(426));
  3777. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3778. break;
  3779. }
  3780. case 447:
  3781. {
  3782. fromTile->removeThing(fromTile->ground);
  3783. fromTile->addThing(new Item(446));
  3784. creature->onTileUpdated(Position(from_x,from_y,from_z));
  3785. break;
  3786. }
  3787. }
  3788. //end depot tiles-+
  3789.         if (playerMoving)
  3790.         {
  3791.             if(playerMoving->attackedCreature != 0) {
  3792.                 Creature* attackedCreature = getCreatureByID(creatureMoving->attackedCreature);
  3793.                 if(attackedCreature){
  3794.           autoCloseAttack(playerMoving, attackedCreature);
  3795.                 }
  3796.             }
  3797.  
  3798.             if(playerMoving->tradePartner != 0) {
  3799.                 Player* tradePartner = getPlayerByID(playerMoving->tradePartner);
  3800.                 if(tradePartner) {
  3801.                     if((std::abs(playerMoving->pos.x - tradePartner->pos.x) > 2) ||
  3802.                     (std::abs(playerMoving->pos.y - tradePartner->pos.y) > 2) || (playerMoving->pos.z != tradePartner->pos.z)
  3803.                     #ifdef HUCZU_FIX
  3804.                     || (fromTile->isHouse() && !toTile->isHouse())
  3805.                     #endif //HUCZU_FIX
  3806.                     ){
  3807.                         playerCloseTrade(playerMoving);
  3808.                     }
  3809.                 }
  3810.             }
  3811.  
  3812.             //change level begin
  3813.             if(toTile->floorChangeDown())
  3814.             {
  3815.                 Tile* downTile = getTile(to_x, to_y, to_z+1);
  3816.                 if(downTile){
  3817.                     //diagonal begin
  3818.                     if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  3819.                         teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y+1, playerMoving->pos.z+1));
  3820.                     }
  3821.                     else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  3822.                         teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y+1, playerMoving->pos.z+1));
  3823.                     }
  3824.                     else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  3825.                         teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y-1, playerMoving->pos.z+1));
  3826.                     }
  3827.                     else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  3828.                         teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y-1, playerMoving->pos.z+1));
  3829.                     }
  3830.                     //diagonal end
  3831.                     else if(downTile->floorChange(NORTH)){
  3832.                         teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y+1, playerMoving->pos.z+1));
  3833.                     }
  3834.                     else if(downTile->floorChange(SOUTH)){
  3835.                         teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y-1, playerMoving->pos.z+1));
  3836.                     }
  3837.                     else if(downTile->floorChange(EAST)){
  3838.                         teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y, playerMoving->pos.z+1));
  3839.                     }
  3840.                     else if(downTile->floorChange(WEST)){
  3841.                         teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y, playerMoving->pos.z+1));
  3842.                     }
  3843.                     else { //allow just real tiles to be hole'like
  3844.                         // TODO: later can be changed to check for piled items like chairs, boxes
  3845.                         teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y, playerMoving->pos.z+1));
  3846.                     }
  3847.                 }
  3848.             }
  3849.             //diagonal begin
  3850.             else if(toTile->floorChange(NORTH) && toTile->floorChange(EAST)){
  3851.                 teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y-1, playerMoving->pos.z-1));
  3852.             }
  3853.             else if(toTile->floorChange(NORTH) && toTile->floorChange(WEST)){
  3854.                 teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y-1, playerMoving->pos.z-1));
  3855.             }
  3856.             else if(toTile->floorChange(SOUTH) && toTile->floorChange(EAST)){
  3857.                 teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y+1, playerMoving->pos.z-1));
  3858.             }
  3859.             else if(toTile->floorChange(SOUTH) && toTile->floorChange(WEST)){
  3860.                 teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y+1, playerMoving->pos.z-1));
  3861.             }
  3862.             //diagonal end
  3863.             else if(toTile->floorChange(NORTH)){
  3864.                 teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y-1, playerMoving->pos.z-1));
  3865.             }
  3866.             else if(toTile->floorChange(SOUTH)){
  3867.                 teleport(playerMoving, Position(playerMoving->pos.x, playerMoving->pos.y+1, playerMoving->pos.z-1));
  3868.             }
  3869.             else if(toTile->floorChange(EAST)){
  3870.                 teleport(playerMoving, Position(playerMoving->pos.x+1, playerMoving->pos.y, playerMoving->pos.z-1));
  3871.             }
  3872.             else if(toTile->floorChange(WEST)){
  3873.                 teleport(playerMoving, Position(playerMoving->pos.x-1, playerMoving->pos.y, playerMoving->pos.z-1));
  3874.             }
  3875.             //change level end
  3876.         }
  3877.  
  3878. // Magic Field in destiny field
  3879. #ifdef HUCZU_FIX
  3880.                 if(toTile && playerMoving && playerMoving->access < g_config.ACCESS_PROTECT && !toTile->downItems.empty() && !toTile->isPvpArena())
  3881. #else
  3882.                 if(toTile && playerMoving && playerMoving->access < g_config.ACCESS_PROTECT && !toTile->downItems.empty() || toTile && creatureMoving && creatureMoving->access < g_config.ACCESS_PROTECT && !toTile->downItems.empty())
  3883. #endif //HUCZU_FIX            
  3884.             {
  3885.                ItemVector::iterator iit;
  3886.                for (iit = toTile->downItems.begin(); iit != toTile->downItems.end(); iit++)
  3887.                {
  3888.                   if(toTile->isPvpArena()) break;
  3889.                   if(!(*iit)) continue;
  3890.                   Item *item = dynamic_cast<Item*>(*iit);
  3891.                   if(!item) continue;
  3892.                   if(!creatureMoving || creatureMoving->isRemoved || creatureMoving->health <= 0) break;
  3893.                   if (item->getID() == 1492 || item->getID() == 1423 || item->getID() == 1487 || item->getID() == 1500){//Fire - Big
  3894.                      doFieldDamage(creatureMoving,        199     , NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE,  true,       20);
  3895.                     //                creature     DamageColor,    damageEffect,      hitEffect      attackType, offensive,   damage
  3896.                      if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3897.                         CreateCondition(creatureMoving, NULL, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 10, 10, 2000, 10);
  3898.                   }
  3899.                   else if(item->getID() == 1493 || item->getID() == 1424 || item->getID() == 1488 || item->getID() == 1501){//Fire Medium
  3900.                     doFieldDamage(creatureMoving, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 10);
  3901.                     if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3902.                        CreateCondition(creatureMoving, NULL, 199, NM_ME_HITBY_FIRE, NM_ME_HITBY_FIRE, ATTACK_FIRE, true, 10, 10, 2000, 10);  
  3903.                   }
  3904.                   else if(item->getID() == 1495 || item->getID() == 1491 || item->getID() == 1504){//Energy
  3905.                     doFieldDamage(creatureMoving, 71, NM_ME_ENERGY_DAMAGE,  NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 30);
  3906.                     if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3907.                        CreateCondition(creatureMoving, NULL, 71, NM_ME_ENERGY_DAMAGE, NM_ME_ENERGY_DAMAGE, ATTACK_ENERGY, true, 30, 30, 2000, 3);  
  3908.                   }
  3909.                   else if(item->getID() == 1496 || item->getID() == 1490 || item->getID() == 1503 || item->getID() == 1505){//Poison
  3910.                     doFieldDamage(creatureMoving, 30, NM_ME_POISEN, NM_ME_POISEN, ATTACK_POISON, true, 10);
  3911.                     if(creatureMoving && !creatureMoving->isRemoved && creatureMoving->health > 0)
  3912.                        CreateCondition(creatureMoving, NULL, 30, NM_ME_POISEN, NM_ME_POISEN_RINGS, ATTACK_POISON, true, 10, 10, 2000, 10);  
  3913.                   }
  3914.                   }
  3915.             }
  3916.             }
  3917.        
  3918.                 if(creatureMoving && !toTile->isPvpArena())
  3919.         {
  3920.             const MagicEffectItem* fieldItem = toTile->getFieldItem();
  3921.  
  3922.             if(fieldItem) {
  3923.                 const MagicEffectTargetCreatureCondition *magicTargetCondition = fieldItem->getCondition();
  3924.  
  3925.                 if(!(getWorldType() == WORLD_TYPE_NO_PVP && playerMoving && magicTargetCondition && magicTargetCondition->getOwnerID() != 0)) {
  3926.                     fieldItem->getDamage(creatureMoving);
  3927.                 }
  3928.  
  3929.                 if(magicTargetCondition && ((magicTargetCondition->attackType == ATTACK_FIRE) ||
  3930.                         (magicTargetCondition->attackType == ATTACK_POISON) ||
  3931.                         (magicTargetCondition->attackType == ATTACK_ENERGY))) {
  3932.                     Creature *c = getCreatureByID(magicTargetCondition->getOwnerID());
  3933.                     creatureMakeMagic(c, thing->pos, magicTargetCondition);
  3934.                 }
  3935.           }
  3936.     }
  3937. }
  3938.    
  3939.  
  3940. void Game::getSpectators(const Range& range, SpectatorVec& list)
  3941. {
  3942.     map->getSpectators(range, list);
  3943. }
  3944.  
  3945. void Game::creatureTurn(Creature *creature, Direction dir)
  3946. {
  3947.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureTurn()");
  3948.  
  3949.     if (creature->direction != dir) {
  3950.         creature->direction = dir;
  3951.  
  3952.         int32_t stackpos = map->getTile(creature->pos)->getThingStackPos(creature);
  3953.  
  3954.         SpectatorVec list;
  3955.         SpectatorVec::iterator it;
  3956.  
  3957.         map->getSpectators(Range(creature->pos, true), list);
  3958.  
  3959.         //players
  3960.         for(it = list.begin(); it != list.end(); ++it) {
  3961.             if(dynamic_cast<Player*>(*it)) {
  3962.                 (*it)->onCreatureTurn(creature, stackpos);
  3963.             }
  3964.         }
  3965.  
  3966.         //none-players
  3967.         for(it = list.begin(); it != list.end(); ++it) {
  3968.             if(!dynamic_cast<Player*>(*it)) {
  3969.                 (*it)->onCreatureTurn(creature, stackpos);
  3970.             }
  3971.         }
  3972.     }
  3973. }
  3974.  
  3975. void Game::addCommandTag(std::string tag){
  3976.     bool found = false;
  3977.     for(size_t i=0;i< commandTags.size() ;i++){
  3978.         if(commandTags[i] == tag){
  3979.             found = true;
  3980.             break;
  3981.         }
  3982.     }
  3983.     if(!found){
  3984.         commandTags.push_back(tag);
  3985.     }
  3986. }
  3987.  
  3988. void Game::resetCommandTag(){
  3989.     commandTags.clear();
  3990. }
  3991.  
  3992. void Game::creatureSay(Creature *creature, SpeakClasses type, const std::string &text)
  3993. {
  3994.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureSay()");
  3995.     using std::string;
  3996.     string spoken=text;
  3997.     std::transform(spoken.begin(), spoken.end(), spoken.begin(), (int32_t(*)(int32_t))std::tolower);
  3998.     bool GMcommand = false;
  3999.     // First, check if this was a GM command
  4000.     for(size_t i=0;i< commandTags.size() ;i++){
  4001.         if(commandTags[i] == text.substr(0,1)){
  4002.             if(commands.exeCommand(creature,text)){
  4003.                 GMcommand = true;
  4004.             }
  4005.             break;
  4006.         }
  4007.     }
  4008.     Player* p = dynamic_cast<Player*>(creature);
  4009.     Player* player = dynamic_cast<Player*>(creature);
  4010.  
  4011. #ifdef HUCZU_FIX
  4012.     if (player && spoken == "exevo grav vita" && (!g_config.LEARN_SPELLS || player->knowsSpell("exevo grav vita")))
  4013.      {
  4014.       Tile *tile = NULL;
  4015.       Position wgpos;
  4016.       wgpos.z = player->pos.z;
  4017.        switch(player->direction)
  4018.         {
  4019.                 case NORTH:
  4020.                 wgpos.x = player->pos.x;
  4021.                 wgpos.y = player->pos.y-1;
  4022.                 break;
  4023.               case SOUTH:
  4024.                 wgpos.x = player->pos.x;
  4025.                 wgpos.y = player->pos.y+1;
  4026.                 break;
  4027.               case EAST:
  4028.                 wgpos.x = player->pos.x+1;
  4029.                 wgpos.y = player->pos.y;
  4030.                 break;
  4031.               case WEST:
  4032.                 wgpos.x = player->pos.x-1;
  4033.                 wgpos.y = player->pos.y;
  4034.                 break;
  4035.               default:
  4036.                 break;
  4037.             }
  4038.             tile = getTile(wgpos.x, wgpos.y, wgpos.z);
  4039.             if(!tile || tile->isBlocking(BLOCK_SOLID,false,false) || tile->isPz())
  4040.               {
  4041.                player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4042.                player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  4043.                return;
  4044.               }
  4045.         if(player->access < 2)
  4046.         {
  4047.            if(player->mana < 220)
  4048.            {
  4049.               player->sendCancel("You do not have enough mana.");
  4050.               player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4051.               return;
  4052.            }
  4053.            if(!player->premmium)           
  4054.            {               
  4055.              player->sendMagicEffect(player->pos, NM_ME_PUFF);         
  4056.              player->sendCancel("You need buy a premmium account for use this spell");         
  4057.              return;       
  4058.            }  
  4059.            if(player->maglevel < 26){
  4060.              player->sendCancel("You do not have the magic level.");
  4061.              player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4062.              return;
  4063.            }
  4064.            if(player->vocation != 2)
  4065.            {
  4066.            player->sendTextMessage(MSG_SMALLINFO, "You do not have the required vocation.");  
  4067.            player->sendMagicEffect(player->pos, 2);    
  4068.            return;
  4069.            }  
  4070.            if (player->exhaustedTicks >= 1000)
  4071.            {
  4072.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4073.             player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");  
  4074.             return;
  4075.            }
  4076.         }          
  4077.                 player->mana -= 220;
  4078.                 player->addManaSpent(220);
  4079.                 player->exhaustedTicks = g_config.EXHAUSTED;
  4080.                 Item* Tree = Item::CreateItem(ITEM_WILDGROWTH, 1);  
  4081.                 addThing(NULL, wgpos, Tree);
  4082.                 startDecay(Tree);
  4083.                 SpectatorVec list;
  4084.                 SpectatorVec::iterator it;
  4085.                 getSpectators(Range(player->pos), list);
  4086.                   for(it = list.begin(); it != list.end(); ++it) {
  4087.                     Player* playerek = dynamic_cast<Player*>(*it);
  4088.                       if(playerek)
  4089.                         playerek->sendMagicEffect(playerek->pos, NM_ME_MAGIC_POISEN);  
  4090.                   }
  4091.                 player->sendMagicEffect(player->pos, NM_ME_MAGIC_ENERGIE);
  4092.             }
  4093. #endif //HUCZU_FIX
  4094.  
  4095. if(spoken=="exana pox"){
  4096.            MagicEffectClass pox;
  4097.            pox.animationColor = 0;
  4098.            pox.damageEffect = NM_ME_MAGIC_ENERGIE;
  4099.            pox.hitEffect = 255;
  4100.            pox.attackType = ATTACK_NONE;
  4101.            pox.maxDamage = 0;
  4102.            pox.minDamage = 0;
  4103.            pox.offensive = false;
  4104.            pox.manaCost = 30;
  4105.            if(creatureMakeMagic(creature, creature->pos, &pox)){
  4106.            creature->removeCondition(ATTACK_POISON);
  4107.            
  4108.            if(player)
  4109.            player->sendIcons();
  4110.            }
  4111.         }
  4112.        
  4113.     if(!GMcommand){
  4114.  Player* player = dynamic_cast<Player*>(creature);
  4115.  
  4116.    if(text=="!besthit")
  4117.         {
  4118.                 std::stringstream info;
  4119.                 if(player->maxDmg>0){
  4120.                 info << "Your best hit: " << player->maxDmg;}
  4121.                 else{
  4122.                 info << "You didn't any damage.";}
  4123.                 player->sendTextMessage(MSG_EVENT,info.str().c_str());
  4124.         }
  4125.  
  4126. if(player && (text[0] == 'e' || text[0] == 'E') && (text[1] == 'x' || text[1] == 'X') && (text[2] == 'a' || text[2] == 'A') && (text[3] == 'n' || text[3] == 'N') && (text[4] == 'a' || text[4] == 'A') && (text[5] == ' ') && (text[6] == 'a' || text[6] == 'A') && (text[7] == 'n' || text[7] == 'N') && (text[8] == 'i' || text[8] == 'i')) {
  4127.  
  4128.          if(player->mana < 200) {
  4129.              player->sendCancel("You do not have enough mana.");
  4130.              player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4131.              return;
  4132.          }
  4133.          if(player->maglevel < 15) {
  4134.              player->sendCancel("You do not have the magic level.");
  4135.              player->sendMagicEffect(player->pos, NM_ME_PUFF);
  4136.              return;
  4137.          }
  4138.          if(player->vocation != 1)
  4139. {
  4140. player->sendTextMessage(MSG_SMALLINFO, "You do not have the required vocation.");  
  4141. player->sendMagicEffect(player->pos, 2);    
  4142. return;
  4143. }
  4144.          player->mana -= 200;
  4145.          player->addManaSpent(200);
  4146.          SpectatorVec list;
  4147.          SpectatorVec::iterator it;
  4148.          getSpectators(Range(creature->pos), list);
  4149.          for(it = list.begin(); it != list.end(); ++it) {
  4150.             if(Creature *c = dynamic_cast<Creature*>(*it)) {
  4151.     if(c)
  4152. {
  4153.         c->setInvisible(0);
  4154.         creatureChangeOutfit(c);
  4155.             }
  4156.          }
  4157.          player->sendMagicEffect(player->pos, NM_ME_MAGIC_ENERGIE);
  4158.     }    
  4159.     }
  4160.         if (player)
  4161.         checkSpell(player, type, text);
  4162.         // It was no command, or it was just a player
  4163.         SpectatorVec list;
  4164.         SpectatorVec::iterator it;
  4165.         getSpectators(Range(creature->pos), list);
  4166.         //players
  4167.         for(it = list.begin(); it != list.end(); ++it) {
  4168.             if(dynamic_cast<Player*>(*it)) {
  4169.                 (*it)->onCreatureSay(creature, type, text);
  4170.             }
  4171.         }
  4172.  
  4173.         //none-players
  4174.         for(it = list.begin(); it != list.end(); ++it) {
  4175.             if(!dynamic_cast<Player*>(*it)) {
  4176.                 (*it)->onCreatureSay(creature, type, text);
  4177.             }
  4178.         }
  4179.     }
  4180. }
  4181.  
  4182. void Game::teleport(Thing *thing, const Position& newPos)
  4183. {
  4184.  
  4185.     if (newPos == thing->pos)
  4186.         return;
  4187.  
  4188.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::teleport()");
  4189.  
  4190.     //Tile *toTile = getTile( newPos.x, newPos.y, newPos.z );
  4191.     Tile *toTile = map->getTile(newPos);
  4192.     if (toTile)
  4193.     {
  4194.         Creature *creature = dynamic_cast<Creature*>(thing);
  4195.         if (creature)
  4196.         {
  4197.             //Tile *fromTile = getTile( thing->pos.x, thing->pos.y, thing->pos.z );
  4198.             Tile *fromTile = map->getTile(thing->pos);
  4199.             if (!fromTile)
  4200.                 return;
  4201.  
  4202.             int osp = fromTile->getThingStackPos(thing);
  4203.             if (!fromTile->removeThing(thing))
  4204.                 return;
  4205.  
  4206.             toTile->addThing(thing);
  4207.             Position oldPos = thing->pos;
  4208.  
  4209.             SpectatorVec list;
  4210.             SpectatorVec::iterator it;
  4211.  
  4212.             getSpectators(Range(thing->pos, true), list);
  4213.  
  4214.             //players
  4215.             for (it = list.begin(); it != list.end(); ++it)
  4216.             {
  4217.                 if (Player* p = dynamic_cast<Player*>(*it))
  4218.                 {
  4219.                     if (p->attackedCreature == creature->getID())
  4220.                     {
  4221.                         autoCloseAttack(p, creature);
  4222.                     }
  4223.  
  4224.                     (*it)->onCreatureDisappear(creature, osp, true);
  4225.                 }
  4226.             }
  4227.  
  4228.             //none-players
  4229.             for (it = list.begin(); it != list.end(); ++it)
  4230.             {
  4231.                 if (!dynamic_cast<Player*>(*it))
  4232.                 {
  4233.                     (*it)->onCreatureDisappear(creature, osp, true);
  4234.                 }
  4235.             }
  4236.  
  4237.             if (newPos.y < oldPos.y)
  4238.                 creature->direction = NORTH;
  4239.             if (newPos.y > oldPos.y)
  4240.                 creature->direction = SOUTH;
  4241.             if (newPos.x > oldPos.x && (std::abs(newPos.x - oldPos.x) >= std::abs(newPos.y - oldPos.y)))
  4242.                 creature->direction = EAST;
  4243.             if (newPos.x < oldPos.x && (std::abs(newPos.x - oldPos.x) >= std::abs(newPos.y - oldPos.y)))
  4244.                 creature->direction = WEST;
  4245.  
  4246.             thing->pos = newPos;
  4247.  
  4248.             Player *player = dynamic_cast<Player*>(creature);
  4249.             if (player && player->attackedCreature != 0)
  4250.             {
  4251.                 Creature* attackedCreature = getCreatureByID(player->attackedCreature);
  4252.                 if (attackedCreature)
  4253.                 {
  4254.                     autoCloseAttack(player, attackedCreature);
  4255.                 }
  4256.             }
  4257.  
  4258.             list.clear();
  4259.             getSpectators(Range(thing->pos, true), list);
  4260.  
  4261. #ifdef TRS_GM_INVISIBLE
  4262.             //players
  4263.             for (it = list.begin(); it != list.end(); ++it)
  4264.             {
  4265.                 if (player)
  4266.                 {
  4267.                     if (player->gmInvisible && player == (*it))
  4268.                     {
  4269.                         if (Player* p = dynamic_cast<Player*>(*it))
  4270.                         {
  4271.                             if (p->attackedCreature == creature->getID())
  4272.                             {
  4273.                                 autoCloseAttack(p, creature);
  4274.                             }
  4275.                             (*it)->onTeleport(creature, &oldPos, osp);
  4276.                         }
  4277.                     }
  4278.                     else if (player->gmInvisible && player != (*it) && (*it)->access < player->access)
  4279.                     {
  4280.                         // Nothing Because he is invisible...
  4281.                     }
  4282.                     else
  4283.                     {
  4284.                         if (Player* p = dynamic_cast<Player*>(*it))
  4285.                         {
  4286.                             if (p->attackedCreature == creature->getID())
  4287.                             {
  4288.                                 autoCloseAttack(p, creature);
  4289.                             }
  4290.                             (*it)->onTeleport(creature, &oldPos, osp);
  4291.                         }
  4292.                     }
  4293.                 }
  4294.                 else
  4295.                     creatureBroadcastTileUpdated(newPos);
  4296.             }
  4297. #else //TRS_GM_INVISIBLE
  4298.             //players
  4299.             for (it = list.begin(); it != list.end(); ++it)
  4300.             {
  4301.                 if (Player* p = dynamic_cast<Player*>(*it))
  4302.                 {
  4303.                     if (p->attackedCreature == creature->getID())
  4304.                     {
  4305.                         autoCloseAttack(p, creature);
  4306.                     }
  4307.                     (*it)->onTeleport(creature, &oldPos, osp);
  4308.                 }
  4309.             }
  4310. #endif //TRS_GM_INVISIBLE
  4311.  
  4312.             //none-players
  4313.             for (it = list.begin(); it != list.end(); ++it)
  4314.             {
  4315.                 if (!dynamic_cast<Player*>(*it))
  4316.                 {
  4317.                     (*it)->onTeleport(creature, &oldPos, osp);
  4318.                 }
  4319.             }
  4320.         }
  4321.         else
  4322.         {
  4323.             if (removeThing(NULL, thing->pos, thing, false))
  4324.             {
  4325.                 addThing(NULL, newPos, thing);
  4326.             }
  4327.         }
  4328.     }//if(toTile)
  4329.  
  4330. }
  4331.  
  4332.  
  4333. void Game::creatureChangeOutfit(Creature *creature)
  4334. {
  4335.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureChangeOutfit()");
  4336.  
  4337.     SpectatorVec list;
  4338.     SpectatorVec::iterator it;
  4339.  
  4340.     getSpectators(Range(creature->pos, true), list);
  4341.  
  4342.     //players
  4343.     for(it = list.begin(); it != list.end(); ++it) {
  4344.         if(dynamic_cast<Player*>(*it)) {
  4345.             (*it)->onCreatureChangeOutfit(creature);
  4346.         }
  4347.     }
  4348.  
  4349.     //none-players
  4350.     for(it = list.begin(); it != list.end(); ++it) {
  4351.         if(!dynamic_cast<Player*>(*it)) {
  4352.             (*it)->onCreatureChangeOutfit(creature);
  4353.         }
  4354.     }
  4355. }
  4356.  
  4357. void Game::creatureWhisper(Creature *creature, const std::string &text)
  4358. {
  4359.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureWhisper()");
  4360.  
  4361.     SpectatorVec list;
  4362.     SpectatorVec::iterator it;
  4363.  
  4364.     getSpectators(Range(creature->pos), list);
  4365.  
  4366.     //players
  4367.     for(it = list.begin(); it != list.end(); ++it) {
  4368.         if(dynamic_cast<Player*>(*it)) {
  4369.             if(abs(creature->pos.x - (*it)->pos.x) > 1 || abs(creature->pos.y - (*it)->pos.y) > 1)
  4370.                 (*it)->onCreatureSay(creature, SPEAK_WHISPER, std::string("pspsps"));
  4371.             else
  4372.                 (*it)->onCreatureSay(creature, SPEAK_WHISPER, text);
  4373.         }
  4374.     }
  4375.  
  4376.     //none-players
  4377.     for(it = list.begin(); it != list.end(); ++it) {
  4378.         if(!dynamic_cast<Player*>(*it)) {
  4379.             if(abs(creature->pos.x - (*it)->pos.x) > 1 || abs(creature->pos.y - (*it)->pos.y) > 1)
  4380.                 (*it)->onCreatureSay(creature, SPEAK_WHISPER, std::string("pspsps"));
  4381.             else
  4382.                 (*it)->onCreatureSay(creature, SPEAK_WHISPER, text);
  4383.         }
  4384.     }
  4385. }
  4386.  
  4387. void Game::creatureYell(Creature *creature, std::string &text)
  4388. {
  4389.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureYell()");
  4390.     if(!creature)
  4391.         return;
  4392. #ifdef HUCZU_FIX
  4393.     if(creature->level < 2 && creature->access < 2){
  4394.         return;
  4395.     }
  4396. #endif //HUCZU_FIX
  4397.     std::transform(text.begin(), text.end(), text.begin(), upchar);
  4398.  
  4399.     SpectatorVec list;
  4400.     SpectatorVec::iterator it;
  4401.     getSpectators(Range(creature->pos, 18, 18, 14, 14), list);
  4402.  
  4403.     for(it = list.begin(); it != list.end(); ++it){
  4404.         if(*it)
  4405.             (*it)->onCreatureSay(creature, SPEAK_YELL, text);
  4406.     }
  4407. }
  4408.  
  4409. //ZBʄNE
  4410. /*void Game::creatureYell(Creature *creature, std::string &text)
  4411. {
  4412.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureYell()");
  4413.     Player* player = dynamic_cast<Player*>(creature);
  4414. #ifdef HUCZU_FIX
  4415.     if(player && player->level < 2 && player->access < 2){
  4416.         player->sendTextMessage(MSG_SMALLINFO, "You cannot yell.");
  4417.         return;
  4418.               }
  4419. #endif //HUCZU_FIX
  4420.     if (player && player->access < g_config.ACCESS_PROTECT && player->exhaustedTicks >= 1000)
  4421.     {
  4422.         player->exhaustedTicks += g_config.EXHAUSTED_ADD;
  4423.         player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");
  4424.     }
  4425.     else {
  4426.         creature->exhaustedTicks = g_config.EXHAUSTED;
  4427.         std::transform(text.begin(), text.end(), text.begin(), upchar);
  4428.  
  4429.         SpectatorVec list;
  4430.         SpectatorVec::iterator it;
  4431.  
  4432.         getSpectators(Range(creature->pos, 18, 18, 14, 14), list);
  4433.  
  4434.         //players
  4435.         for(it = list.begin(); it != list.end(); ++it) {
  4436.             if(dynamic_cast<Player*>(*it)) {
  4437.                 (*it)->onCreatureSay(creature, SPEAK_YELL, text);
  4438.             }
  4439.         }
  4440.     }
  4441. }*/
  4442.  
  4443. void Game::creatureSpeakTo(Creature *creature, SpeakClasses type,const std::string &receiver, const std::string &text)
  4444. {
  4445.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureSpeakTo");
  4446.  
  4447.     Player* player = dynamic_cast<Player*>(creature);
  4448.     if(!player)
  4449.         return;
  4450.  
  4451.     Player* toPlayer = getPlayerByName(receiver);
  4452.     if(!toPlayer) {
  4453.         player->sendTextMessage(MSG_SMALLINFO, "A player with this name is not online.");
  4454.         return;
  4455.     }
  4456.     if(creature->access < g_config.ACCESS_TALK){
  4457.         type = SPEAK_PRIVATE;
  4458.     }
  4459.    
  4460.     if(!toPlayer){
  4461.         player->onCreatureSay(player, type, text);
  4462.     }
  4463.         time_t ticks = time(0);
  4464.         tm* now = localtime(&ticks);
  4465.         char buf[32];
  4466.         strftime(buf, sizeof(buf), "%d/%m/%Y %H:%M", now);
  4467.         std::ofstream out2("data/logs/private.log", std::ios::app);
  4468.         out2 << '[' << buf << "] " << toPlayer->getName() << " from " << player->getName() << ": " << text << std::endl;
  4469.         out2.close();      
  4470.        
  4471.     toPlayer->onCreatureSay(player, type, text);
  4472.     std::stringstream ss;
  4473.     ss << "Message sent to " << toPlayer->getName() << ".";
  4474.     player->sendTextMessage(MSG_SMALLINFO, ss.str().c_str());
  4475.     }
  4476.  
  4477. void Game::creatureTalkToChannel(Player *player, SpeakClasses type, std::string &text, uint16_t channelId)
  4478. {
  4479.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureTalkToChannel");
  4480.  
  4481.     if(player->access < g_config.ACCESS_TALK){
  4482.         type = SPEAK_CHANNEL_Y;
  4483.     }
  4484.  
  4485. if(player->guildStatus == GUILD_LEADER && channelId == 0x00)
  4486.         type = SPEAK_CHANNEL_R1;
  4487. if(player->guildStatus == GUILD_VICE && channelId == 0x00)
  4488.         type = SPEAK_CHANNEL_O;
  4489.  
  4490.     g_chat.talkToChannel(player, type, text, channelId);
  4491. }
  4492.  
  4493. void Game::creatureMonsterYell(Monster* monster, const std::string& text)
  4494. {
  4495.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureMonsterYell()");
  4496.  
  4497.     SpectatorVec list;
  4498.     SpectatorVec::iterator it;
  4499.  
  4500.     map->getSpectators(Range(monster->pos, 18, 18, 14, 14), list);
  4501.  
  4502.     //players
  4503.     for(it = list.begin(); it != list.end(); ++it) {
  4504.         if(dynamic_cast<Player*>(*it)) {
  4505.             (*it)->onCreatureSay(monster, SPEAK_MONSTER1, text);
  4506.         }
  4507.     }
  4508. }
  4509.  
  4510. void Game::creatureBroadcastMessage(Creature *creature, const std::string &text)
  4511. {
  4512.     if(creature->access < g_config.ACCESS_TALK)
  4513.         return;
  4514.  
  4515.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureBroadcastMessage()");
  4516.  
  4517.     for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  4518.     {
  4519.         (*it).second->onCreatureSay(creature, SPEAK_BROADCAST, text);
  4520.     }
  4521. }
  4522.  
  4523. /** \todo Someone _PLEASE_ clean up this mess */
  4524. bool Game::creatureMakeMagic(Creature *creature, const Position& centerpos, const MagicEffectClass* me)
  4525. {
  4526.  
  4527.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureMakeMagic()");
  4528.  
  4529. #ifdef __DEBUG__
  4530.     cout << "creatureMakeMagic: " << (creature ? creature->getName() : "No name") << ", x: " << centerpos.x << ", y: " << centerpos.y << ", z: " << centerpos.z << std::endl;
  4531. #endif
  4532.  
  4533.     Position frompos;
  4534.  
  4535.     if(creature) {
  4536.         frompos = creature->pos;
  4537.  
  4538.         if(!creatureOnPrepareMagicAttack(creature, centerpos, me))
  4539.         {
  4540.  
  4541.             return false;
  4542.         }
  4543.     }
  4544.     else {
  4545.         frompos = centerpos;
  4546.     }
  4547.  
  4548.     MagicAreaVec tmpMagicAreaVec;
  4549.     me->getArea(centerpos, tmpMagicAreaVec);
  4550.  
  4551.     std::vector<Position> poslist;
  4552.  
  4553.     Position topLeft(0xFFFF, 0xFFFF, frompos.z), bottomRight(0, 0, frompos.z);
  4554.  
  4555.     //Filter out the tiles we actually can work on
  4556.     for(MagicAreaVec::iterator maIt = tmpMagicAreaVec.begin(); maIt != tmpMagicAreaVec.end(); ++maIt) {
  4557.         Tile *t = map->getTile(maIt->x, maIt->y, maIt->z);
  4558.         if(t && (!creature || (creature->access >= g_config.ACCESS_PROTECT || !me->offensive || !t->isPz()) ) ) {
  4559.             if((t->isBlocking(BLOCK_PROJECTILE) == RET_NOERROR) && (me->isIndirect() ||
  4560.                 //(map->canThrowItemTo(frompos, (*maIt), false, true) && !t->floorChange()))) {
  4561.                 ((map->canThrowObjectTo(centerpos, (*maIt), BLOCK_PROJECTILE) == RET_NOERROR) && !t->floorChange()))) {
  4562.  
  4563.                 if(maIt->x < topLeft.x)
  4564.                     topLeft.x = maIt->x;
  4565.  
  4566.                 if(maIt->y < topLeft.y)
  4567.                     topLeft.y = maIt->y;
  4568.  
  4569.                 if(maIt->x > bottomRight.x)
  4570.                     bottomRight.x = maIt->x;
  4571.  
  4572.                 if(maIt->y > bottomRight.y)
  4573.                     bottomRight.y = maIt->y;
  4574.  
  4575.                 poslist.push_back(*maIt);
  4576.             }
  4577.         }
  4578.     }
  4579.  
  4580.     topLeft.z = frompos.z;
  4581.     bottomRight.z = frompos.z;
  4582.  
  4583.     if(topLeft.x == 0xFFFF || topLeft.y == 0xFFFF || bottomRight.x == 0 || bottomRight.y == 0){
  4584.  
  4585.     return false;
  4586.     }
  4587.  
  4588. #ifdef __DEBUG__
  4589.     printf("top left %d %d %d\n", topLeft.x, topLeft.y, topLeft.z);
  4590.     printf("bottom right %d %d %d\n", bottomRight.x, bottomRight.y, bottomRight.z);
  4591. #endif
  4592.  
  4593.     //We do all changes against a GameState to keep track of the changes,
  4594.     //need some more work to work for all situations...
  4595.     GameState gamestate(this, Range(topLeft, bottomRight));
  4596.  
  4597.     //Tile *targettile = getTile(centerpos.x, centerpos.y, centerpos.z);
  4598.     Tile *targettile = map->getTile(centerpos);
  4599.     bool bSuccess = false;
  4600.     bool hasTarget = false;
  4601.     bool isBlocking = true;
  4602.     if(targettile){
  4603.         hasTarget = !targettile->creatures.empty();
  4604.         isBlocking = (targettile->isBlocking(BLOCK_SOLID, true) != RET_NOERROR);
  4605.     }
  4606.  
  4607.     if(targettile && me->canCast(isBlocking, !targettile->creatures.empty())) {
  4608.         bSuccess = true;
  4609.  
  4610.         //Apply the permanent effect to the map
  4611.         std::vector<Position>::const_iterator tlIt;
  4612.         for(tlIt = poslist.begin(); tlIt != poslist.end(); ++tlIt) {
  4613.             gamestate.onAttack(creature, Position(*tlIt), me);
  4614.         }
  4615.     }
  4616.  
  4617.     SpectatorVec spectatorlist = gamestate.getSpectators();
  4618.     SpectatorVec::iterator it;
  4619.  
  4620.     for(it = spectatorlist.begin(); it != spectatorlist.end(); ++it) {
  4621.         Player* spectator = dynamic_cast<Player*>(*it);
  4622.  
  4623.         if(!spectator)
  4624.             continue;
  4625.  
  4626.         if(bSuccess) {
  4627.             me->getDistanceShoot(spectator, creature, centerpos, hasTarget);
  4628.  
  4629.             std::vector<Position>::const_iterator tlIt;
  4630.             for(tlIt = poslist.begin(); tlIt != poslist.end(); ++tlIt) {
  4631.                 Position pos = *tlIt;
  4632.                 //Tile *tile = getTile(pos.x, pos.y, pos.z);
  4633.                 Tile *tile = map->getTile(pos);
  4634.                 const CreatureStateVec& creatureStateVec = gamestate.getCreatureStateList(tile);
  4635.  
  4636.                 if(creatureStateVec.empty()) { //no targets
  4637.                     me->getMagicEffect(spectator, creature, NULL, pos, 0, targettile->isPz(), isBlocking);
  4638.                 }
  4639.                 else {
  4640.                     for(CreatureStateVec::const_iterator csIt = creatureStateVec.begin(); csIt != creatureStateVec.end(); ++csIt) {
  4641.                         Creature *target = csIt->first;
  4642.                         const CreatureState& creatureState = csIt->second;
  4643.  
  4644.                         me->getMagicEffect(spectator, creature, target, target->pos, creatureState.damage, tile->isPz(), false);
  4645.  
  4646.                         //could be death due to a magic damage with no owner (fire/poison/energy)
  4647.                         if(creature && target->isRemoved == true) {
  4648.  
  4649.                             for(std::vector<Creature*>::const_iterator cit = creatureState.attackerlist.begin(); cit != creatureState.attackerlist.end(); ++cit) {
  4650.                                 Creature* gainExpCreature = *cit;
  4651.                                 if(dynamic_cast<Player*>(gainExpCreature))
  4652.                                     dynamic_cast<Player*>(gainExpCreature)->sendStats();
  4653.  
  4654. if(spectator->CanSee(gainExpCreature->pos.x, gainExpCreature->pos.y, gainExpCreature->pos.z)){
  4655.             std::stringstream exp;
  4656.             exp << target->getGainedExperience(gainExpCreature);
  4657.             spectator->sendAnimatedText(gainExpCreature->pos, 0xD7, exp.str());
  4658. }
  4659.                             }
  4660.  
  4661.                         }
  4662.  
  4663.                         if(spectator->CanSee(target->pos.x, target->pos.y, target->pos.z))
  4664.                         {
  4665.                             if(creatureState.damage != 0) {
  4666.                                 std::stringstream dmg;
  4667.                                 dmg << std::abs(creatureState.damage);
  4668. #ifdef TJ_MONSTER_BLOOD
  4669.                                 if (me->attackType & ATTACK_PHYSICAL)
  4670.                                     spectator->sendAnimatedText(target->pos, target->bloodcolor, dmg.str());
  4671.                                 else
  4672. #endif //TJ_MONSTER_BLOOD
  4673.                             spectator->sendAnimatedText(target->pos, me->animationColor, dmg.str());
  4674.                             }
  4675.  
  4676.                             if(creatureState.manaDamage > 0){
  4677.                                 spectator->sendMagicEffect(target->pos, NM_ME_LOOSE_ENERGY);
  4678.                                 std::stringstream manaDmg;
  4679.                                 manaDmg << std::abs(creatureState.manaDamage);
  4680.                                 spectator->sendAnimatedText(target->pos, 2, manaDmg.str());
  4681.                             }
  4682.  
  4683.                             if (target->health > 0)
  4684.                                 spectator->sendCreatureHealth(target);
  4685.  
  4686.                             if (spectator == target){
  4687.                                 CreateManaDamageUpdate(target, creature, creatureState.manaDamage);
  4688.                                 CreateDamageUpdate(target, creature, creatureState.damage);
  4689.                             }
  4690.                         }
  4691.                     }
  4692.                 }
  4693.             }
  4694.         }
  4695.         else {
  4696.             me->FailedToCast(spectator, creature, isBlocking, hasTarget);
  4697.         }
  4698.  
  4699.     }
  4700.  
  4701.     return bSuccess;
  4702. }
  4703.  
  4704. void Game::creatureApplyDamage(Creature *creature, int32_t damage, int32_t &outDamage, int32_t &outManaDamage
  4705. #ifdef YUR_PVP_ARENA
  4706.                                , CreatureVector* arenaLosers
  4707. #endif //YUR_PVP_ARENA
  4708.                                )
  4709. {
  4710.     outDamage = damage;
  4711.     outManaDamage = 0;
  4712.  
  4713.     if (damage > 0)
  4714.     {
  4715.         if (creature->manaShieldTicks >= 1000 && (damage < creature->mana) ) {
  4716.             outManaDamage = damage;
  4717.             outDamage = 0;
  4718.         }
  4719.         else if (creature->manaShieldTicks >= 1000 && (damage > creature->mana) ) {
  4720.             outManaDamage = creature->mana;
  4721.             outDamage -= outManaDamage;
  4722.         }
  4723.         else if((creature->manaShieldTicks < 1000) && (damage > creature->health))
  4724.             outDamage = creature->health;
  4725.         else if (creature->manaShieldTicks >= 1000 && (damage > (creature->health + creature->mana))) {
  4726.             outDamage = creature->health;
  4727.             outManaDamage = creature->mana;
  4728.         }
  4729.  
  4730.         if(creature->manaShieldTicks < 1000 || (creature->mana == 0))
  4731. #ifdef YUR_PVP_ARENA
  4732.             creature->drainHealth(outDamage, arenaLosers);
  4733. #else
  4734.             creature->drainHealth(outDamage);
  4735. #endif //YUR_PVP_ARENA
  4736.         else if(outManaDamage > 0)
  4737.         {
  4738. #ifdef YUR_PVP_ARENA
  4739.             creature->drainHealth(outDamage, arenaLosers);
  4740. #else
  4741.             creature->drainHealth(outDamage);
  4742. #endif //YUR_PVP_ARENA
  4743.             creature->drainMana(outManaDamage);
  4744.         }
  4745.         else
  4746.             creature->drainMana(outDamage);
  4747.     }
  4748.     else {
  4749.         int32_t newhealth = creature->health - damage;
  4750.         if(newhealth > creature->healthmax)
  4751.             newhealth = creature->healthmax;
  4752.  
  4753.         creature->health = newhealth;
  4754.  
  4755.         outDamage = creature->health - newhealth;
  4756.         outManaDamage = 0;
  4757.     }
  4758. }
  4759.  
  4760. bool Game::creatureCastSpell(Creature *creature, const Position& centerpos, const MagicEffectClass& me)
  4761. {
  4762.  
  4763.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureCastSpell()");
  4764. std::cout << "Game::creatureCastSpell " << creature->getName() << std::endl;
  4765. //    if(me.offensive == false && me.damageEffect > 0 && creature->conditions.hasCondition(ATTACK_PARALYZE))
  4766.     if(me.damageEffect <= 0 && creature->conditions.hasCondition(ATTACK_PARALYZE))
  4767.     {
  4768.         creature->removeCondition(ATTACK_PARALYZE);
  4769.         changeSpeed(creature->getID(), creature->getNormalSpeed()+creature->hasteSpeed);
  4770.         Player *player = dynamic_cast<Player*>(creature);
  4771.         if(player)
  4772.             player->sendIcons();
  4773.     }
  4774.  
  4775.     return creatureMakeMagic(creature, centerpos, &me);
  4776. }
  4777.  
  4778.  
  4779. bool Game::creatureThrowRune(Creature *creature, const Position& centerpos, const MagicEffectClass& me) {
  4780.  
  4781.  
  4782.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureThrowRune()");
  4783.     bool ret = false;
  4784.     #ifdef HUCZU_FIX
  4785.     int32_t dist_x = std::abs(creature->pos.x - centerpos.x);
  4786.     int32_t dist_y = std::abs(creature->pos.y - centerpos.y);
  4787.     #endif //HUCZU_FIX
  4788.     if(creature->pos.z != centerpos.z) {
  4789.         creature->sendCancel("You need to be on the same floor.");
  4790.     }
  4791.     #ifdef HUCZU_FIX
  4792.     else if(dist_x > 7 || dist_y > 6)
  4793.        return TOO_FAR;
  4794.     #endif //HUCZU_FIX
  4795.     //else if(!map->canThrowItemTo(creature->pos, centerpos, false, true)) {
  4796.     else if(map->canThrowObjectTo(creature->pos, centerpos, BLOCK_PROJECTILE) != RET_NOERROR) {
  4797.         creature->sendCancel("You cannot throw there.");
  4798.     }
  4799.     else
  4800.         ret = creatureMakeMagic(creature, centerpos, &me);
  4801.  
  4802.  
  4803.  
  4804.     return ret;
  4805. }
  4806.  
  4807. bool Game::creatureOnPrepareAttack(Creature *creature, Position pos)
  4808. {
  4809.   if(creature){
  4810.         Player* player = dynamic_cast<Player*>(creature);
  4811.  
  4812.         //Tile* tile = (Tile*)getTile(creature->pos.x, creature->pos.y, creature->pos.z);
  4813.         Tile* tile = map->getTile(creature->pos);
  4814.         //Tile* targettile = getTile(pos.x, pos.y, pos.z);
  4815.         Tile* targettile = map->getTile(pos);
  4816.  
  4817.         if(creature->access < g_config.ACCESS_PROTECT) {
  4818.             if(tile && tile->isPz()) {
  4819.                 if(player) {
  4820.                     player->sendTextMessage(MSG_SMALLINFO, "You may not attack a person while you are in a protection zone.");
  4821.                     playerSetAttackedCreature(player, 0);
  4822.                 }
  4823.  
  4824.                 return false;
  4825.             }
  4826.             else if(targettile && targettile->isPz()) {
  4827.                 if(player) {
  4828.                     player->sendTextMessage(MSG_SMALLINFO, "You may not attack a person in a protection zone.");
  4829.                     playerSetAttackedCreature(player, 0);
  4830.                 }
  4831.  
  4832.                 return false;
  4833.             }
  4834.         }
  4835.  
  4836.         return true;
  4837.     }
  4838.  
  4839.     return false;
  4840. }
  4841.  
  4842. bool Game::creatureOnPrepareMagicAttack(Creature *creature, Position pos, const MagicEffectClass* me)
  4843. {
  4844.     if(!me->offensive || me->isIndirect() || creatureOnPrepareAttack(creature, pos)) {
  4845.         /*
  4846.             if(creature->access < ACCESS_PROTECT) {
  4847.                 if(!((std::abs(creature->pos.x-centerpos.x) <= 8) && (std::abs(creature->pos.y-centerpos.y) <= 6) &&
  4848.                     (creature->pos.z == centerpos.z)))
  4849.                     return false;
  4850.             }
  4851.         */
  4852.  
  4853.         Player* player = dynamic_cast<Player*>(creature);
  4854.         if(player) {
  4855.             if(player->access < g_config.ACCESS_PROTECT) {
  4856.                 if(player->exhaustedTicks >= 1000 && me->causeExhaustion(true)) {
  4857.                     if(me->offensive) {
  4858.                         player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.",player->pos, NM_ME_PUFF);
  4859.                         player->exhaustedTicks += g_config.EXHAUSTED_ADD;
  4860.                     }
  4861.  
  4862.                     return false;
  4863.                 }
  4864.                 else if(player->mana < me->manaCost) {
  4865.                     player->sendTextMessage(MSG_SMALLINFO, "You do not have enough mana.",player->pos, NM_ME_PUFF);
  4866.                     return false;
  4867.                 }
  4868.                 else
  4869.                     player->mana -= me->manaCost;
  4870.                     //player->manaspent += me->manaCost;
  4871.                     player->addManaSpent(me->manaCost);
  4872.             }
  4873.         }
  4874.  
  4875.         return true;
  4876.     }
  4877.  
  4878.     return false;
  4879. }
  4880.  
  4881. void Game::creatureMakeDamage(Creature *creature, Creature *attackedCreature, fight_t damagetype)
  4882. {
  4883.     if(!creatureOnPrepareAttack(creature, attackedCreature->pos))
  4884.         return;
  4885.  
  4886.  
  4887.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureMakeDamage()");
  4888.  
  4889.     Player* player = dynamic_cast<Player*>(creature);
  4890.     Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  4891.    
  4892.    #ifdef ANTI_MISS
  4893.     if(player && player->atkMode == 1 && player->access <= g_config.ACCESS_PROTECT && attackedPlayer && attackedPlayer->skullType == 0) {
  4894.     player->sendCancelAttacking();
  4895.         player->sendTextMessage(MSG_SMALLINFO, "Turn secure mode off if you really want to attack unmarked players.");
  4896.         return;
  4897.         }
  4898.     #endif //ANTI_MISS
  4899.    
  4900.     //Tile* targettile = getTile(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z);
  4901.     Tile* targettile = map->getTile(attackedCreature->pos);
  4902.    
  4903.     //can the attacker reach the attacked?
  4904.     bool inReach = false;
  4905.  
  4906.     switch(damagetype){
  4907.         case FIGHT_MELEE:
  4908.             if((std::abs(creature->pos.x-attackedCreature->pos.x) <= 1) &&
  4909.                 (std::abs(creature->pos.y-attackedCreature->pos.y) <= 1) &&
  4910.                 (creature->pos.z == attackedCreature->pos.z))
  4911.                     inReach = true;
  4912.         break;
  4913.         case FIGHT_DIST:
  4914.             if((std::abs(creature->pos.x-attackedCreature->pos.x) <= 8) &&
  4915.                 (std::abs(creature->pos.y-attackedCreature->pos.y) <= 5) &&
  4916.                 (creature->pos.z == attackedCreature->pos.z)) {
  4917.  
  4918.                     //if(map->canThrowItemTo(creature->pos, attackedCreature->pos, false, true))
  4919.                     if(map->canThrowObjectTo(creature->pos, attackedCreature->pos, BLOCK_PROJECTILE) == RET_NOERROR)
  4920.                         inReach = true;
  4921.                 }
  4922.         break;
  4923.         case FIGHT_MAGICDIST:
  4924.             if((std::abs(creature->pos.x-attackedCreature->pos.x) <= 8) &&
  4925.                 (std::abs(creature->pos.y-attackedCreature->pos.y) <= 5) &&
  4926.                 (creature->pos.z == attackedCreature->pos.z)) {
  4927.  
  4928.                     //if(map->canThrowItemTo(creature->pos, attackedCreature->pos, false, true))
  4929.                     if(map->canThrowObjectTo(creature->pos, attackedCreature->pos, BLOCK_PROJECTILE) == RET_NOERROR)
  4930.                         inReach = true;
  4931.                 }
  4932.         break;
  4933.  
  4934.     }
  4935.  
  4936.     if (player && player->access < g_config.ACCESS_PROTECT)
  4937.     {
  4938. #ifdef YUR_CVS_MODS
  4939.         player->inFightTicks = std::max(g_config.PZ_LOCKED, player->inFightTicks);
  4940. #else
  4941.         player->inFightTicks = g_config.PZ_LOCKED;
  4942. #endif //YUR_CVS_MODS
  4943.  
  4944.         player->sendIcons();
  4945.         if(attackedPlayer)
  4946.             player->pzLocked = true;
  4947.     }
  4948.  
  4949.     if(attackedPlayer && attackedPlayer->access < g_config.ACCESS_PROTECT)
  4950.     {
  4951. #ifdef YUR_CVS_MODS
  4952.         attackedPlayer->inFightTicks = std::max(g_config.PZ_LOCKED, attackedPlayer->inFightTicks);
  4953. #else
  4954.         attackedPlayer->inFightTicks = g_config.PZ_LOCKED;
  4955. #endif //YUR_CVS_MODS
  4956.      attackedPlayer->sendIcons();
  4957.   }
  4958.  
  4959.     if(!inReach){
  4960.         return;
  4961.     }
  4962.  
  4963.     //We do all changes against a GameState to keep track of the changes,
  4964.     //need some more work to work for all situations...
  4965.     GameState gamestate(this, Range(creature->pos, attackedCreature->pos));
  4966.  
  4967.     gamestate.onAttack(creature, attackedCreature->pos, attackedCreature);
  4968.  
  4969.     const CreatureStateVec& creatureStateVec = gamestate.getCreatureStateList(targettile);
  4970.     const CreatureState& creatureState = creatureStateVec[0].second;
  4971.  
  4972. if(player && (creatureState.damage > 0 || creatureState.manaDamage > 0)) {
  4973.         #ifdef WANDS_JIDDO
  4974.         if(player && ((player->items[SLOT_RIGHT] && (!player->items[SLOT_RIGHT]->getWand())) || (!player->items[SLOT_RIGHT] && !player->items[SLOT_LEFT]) || (player->items[SLOT_LEFT] && (!player->items[SLOT_LEFT]->getWand()))))
  4975.         player->addSkillTry(2);
  4976.         #else
  4977.         player->addSkillTry(2);
  4978.         #endif
  4979.     }
  4980.     else if(player){
  4981.         #ifdef WANDS_JIDDO
  4982.         if(player && ((player->items[SLOT_RIGHT] && (!player->items[SLOT_RIGHT]->getWand())) || (!player->items[SLOT_RIGHT] && !player->items[SLOT_LEFT]) || (player->items[SLOT_LEFT] && (!player->items[SLOT_LEFT]->getWand()))))
  4983.         player->addSkillTry(1);
  4984.         #else
  4985.         player->addSkillTry(1);
  4986.         #endif
  4987.     }
  4988. if(attackedPlayer){
  4989. NetworkMessage msg;
  4990. msg.AddByte(0x86);
  4991. msg.AddU32(creature->getID());
  4992. msg.AddByte(0x00);
  4993. attackedPlayer->sendNetworkMessage(&msg);
  4994. }
  4995.  
  4996.     SpectatorVec spectatorlist = gamestate.getSpectators();
  4997.     SpectatorVec::iterator it;
  4998.  
  4999.     for(it = spectatorlist.begin(); it != spectatorlist.end(); ++it) {
  5000.         Player* spectator = dynamic_cast<Player*>(*it);
  5001.         if(!spectator)
  5002.             continue;
  5003.  
  5004.         if(damagetype != FIGHT_MELEE){
  5005.             spectator->sendDistanceShoot(creature->pos, attackedCreature->pos, creature->getSubFightType());
  5006.         }
  5007.  
  5008.         if (attackedCreature->manaShieldTicks < 1000 && (creatureState.damage == 0) &&
  5009.             (spectator->CanSee(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z))) {
  5010.                 spectator->sendMagicEffect(attackedCreature->pos, NM_ME_PUFF);
  5011.         }
  5012.         else if (attackedCreature->manaShieldTicks < 1000 && (creatureState.damage < 0) &&
  5013.             (spectator->CanSee(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z))) {
  5014.                 spectator->sendMagicEffect(attackedCreature->pos, NM_ME_BLOCKHIT);
  5015.         }
  5016.         else {
  5017.             for(std::vector<Creature*>::const_iterator cit = creatureState.attackerlist.begin(); cit != creatureState.attackerlist.end(); ++cit) {
  5018.                 Creature* gainexpCreature = *cit;
  5019.                 if(dynamic_cast<Player*>(gainexpCreature))
  5020.                     dynamic_cast<Player*>(gainexpCreature)->sendStats();
  5021.  
  5022.                 if(spectator->CanSee(gainexpCreature->pos.x, gainexpCreature->pos.y, gainexpCreature->pos.z)) {
  5023.                     char exp[128];
  5024. #ifdef YUR_HIGH_LEVELS  // TODO: format like this: 1,000,000
  5025.                     sprintf(exp,"%lld",attackedCreature->getGainedExperience(gainexpCreature));
  5026.                     spectator->sendAnimatedText(gainexpCreature->pos, 0xD7, exp);
  5027. #else
  5028.                     itoa(attackedCreature->getGainedExperience(gainexpCreature), exp, 10);
  5029. #endif //YUR_HIGH_LEVLES
  5030.                     spectator->sendAnimatedText(gainexpCreature->pos, 0xD7, exp);
  5031.                 }
  5032.             }
  5033.  
  5034.             if (spectator->CanSee(attackedCreature->pos.x, attackedCreature->pos.y, attackedCreature->pos.z))
  5035.             {
  5036.                 if(creatureState.damage > 0) {
  5037.                     std::stringstream dmg;
  5038.                     dmg << std::abs(creatureState.damage);
  5039. #ifdef TJ_MONSTER_BLOOD
  5040.                     spectator->sendAnimatedText(attackedCreature->pos, attackedCreature->bloodcolor, dmg.str());
  5041.                     spectator->sendMagicEffect(attackedCreature->pos, attackedCreature->bloodeffect);
  5042. #else
  5043.                     spectator->sendAnimatedText(attackedCreature->pos, 0xB4, dmg.str());
  5044.                     spectator->sendMagicEffect(attackedCreature->pos, NM_ME_DRAW_BLOOD);
  5045. #endif //TJ_MONSTER_BLOOD
  5046.                 }
  5047.  
  5048.                 if(creatureState.manaDamage >0) {
  5049.                     std::stringstream manaDmg;
  5050.                     manaDmg << std::abs(creatureState.manaDamage);
  5051.                     spectator->sendMagicEffect(attackedCreature->pos, NM_ME_LOOSE_ENERGY);
  5052.                     spectator->sendAnimatedText(attackedCreature->pos, 2, manaDmg.str());
  5053.                 }
  5054.  
  5055.                 if (attackedCreature->health > 0)
  5056.                     spectator->sendCreatureHealth(attackedCreature);
  5057.  
  5058.                 if (spectator == attackedCreature) {
  5059.                     CreateManaDamageUpdate(attackedCreature, creature, creatureState.manaDamage);
  5060.                     CreateDamageUpdate(attackedCreature, creature, creatureState.damage);
  5061.                 }
  5062.             }
  5063.         }
  5064.     }
  5065.  
  5066.     if(damagetype != FIGHT_MELEE && player) {
  5067.         player->removeDistItem();
  5068.     }
  5069.  
  5070.  
  5071. }
  5072.  
  5073. std::list<Position> Game::getPathTo(Creature *creature, Position start, Position to, bool creaturesBlock){
  5074.     return map->getPathTo(creature, start, to, creaturesBlock);
  5075. }
  5076.  
  5077. std::list<Position> Game::getPathToEx(Creature *creature, Position start, Position to, bool creaturesBlock){
  5078.     return map->getPathToEx(creature, start, to, creaturesBlock);
  5079. }
  5080.  
  5081.  
  5082. void Game::checkPlayerWalk(uint32_t id)
  5083. {
  5084.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkPlayerWalk");
  5085.  
  5086.     Player *player = getPlayerByID(id);
  5087.  
  5088.     if(!player)
  5089.         return;
  5090. if(player->pathlist.empty()){
  5091.         stopEvent(player->eventAutoWalk);
  5092.         player->eventAutoWalk = 0;
  5093.         return;
  5094.     }
  5095.  
  5096.     Position pos = player->pos;
  5097.     Direction dir = player->pathlist.front();
  5098.     player->pathlist.pop_front();
  5099.  
  5100.     switch (dir) {
  5101.         case NORTH:
  5102.             pos.y--;
  5103.             break;
  5104.         case EAST:
  5105.             pos.x++;
  5106.             break;
  5107.         case SOUTH:
  5108.             pos.y++;
  5109.             break;
  5110.         case WEST:
  5111.             pos.x--;
  5112.             break;
  5113.         case NORTHEAST:
  5114.             pos.x++;
  5115.             pos.y--;
  5116.             break;
  5117.         case NORTHWEST:
  5118.             pos.x--;
  5119.             pos.y--;
  5120.             break;
  5121.         case SOUTHWEST:
  5122.             pos.x--;
  5123.             pos.y++;
  5124.             break;
  5125.         case SOUTHEAST:
  5126.             pos.x++;
  5127.             pos.y++;
  5128.             break;
  5129.     }
  5130.  
  5131. /*
  5132. #ifdef __DEBUG__
  5133.     std::cout << "move to: " << dir << std::endl;
  5134. #endif
  5135. */
  5136.  
  5137.     player->lastmove = OTSYS_TIME();
  5138.     thingMove(player, player, pos.x, pos.y, pos.z, 1);
  5139.     flushSendBuffers();
  5140.     if(!player->pathlist.empty()){
  5141.         int ticks = (int)player->getSleepTicks();
  5142.         player->eventAutoWalk = addEvent(makeTask(ticks, std::bind2nd(std::mem_fun(&Game::checkPlayerWalk), id)));
  5143.     }
  5144.     else
  5145.     {
  5146.         stopEvent(player->eventAutoWalk);//?
  5147.         player->eventAutoWalk = 0;
  5148.     }
  5149. }
  5150. void Game::checkCreature(uint32_t id)
  5151. {
  5152.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreature()");
  5153.  
  5154.     Creature *creature = getCreatureByID(id);
  5155.  
  5156.     if (creature && creature->isRemoved == false)
  5157.     {
  5158.         int32_t thinkTicks = 0;
  5159.         int32_t oldThinkTicks = creature->onThink(thinkTicks);
  5160.  
  5161.         if(thinkTicks > 0) {
  5162.             creature->eventCheck = addEvent(makeTask(thinkTicks, std::bind2nd(std::mem_fun(&Game::checkCreature), id)));
  5163.         }
  5164.         else
  5165.             creature->eventCheck = 0;
  5166.  
  5167.         Player* player = dynamic_cast<Player*>(creature);
  5168.         if(player)
  5169.         {
  5170.             //Tile *tile = getTile(player->pos.x, player->pos.y, player->pos.z);
  5171.             Tile *tile = map->getTile(player->pos);
  5172.             if(tile == NULL){
  5173.                 std::cout << "CheckPlayer NULL tile: " << player->getName() << std::endl;
  5174.                 return;
  5175.             }
  5176.            
  5177.            
  5178.            
  5179.             #ifdef _REX_CVS_MOD_
  5180.             if(player->tradeTicks >= 1000)
  5181.             player->tradeTicks -= thinkTicks;
  5182.             #endif
  5183.  
  5184.  
  5185. #ifdef CVS_DAY_CYCLE
  5186.             player->sendWorldLightLevel(lightlevel, 0xD7);
  5187. #endif //CVS_DAY_CYCLE
  5188. #ifdef REX_MUTED
  5189.  
  5190. #endif //REX_MUTED
  5191. #ifdef TR_ANTI_AFK
  5192.             player->checkAfk(thinkTicks);
  5193. #endif //TR_ANTI_AF
  5194. #ifdef YUR_BOH
  5195.             player->checkBoh();
  5196. #endif //YUR_BOH
  5197. #ifdef YUR_WH
  5198.             player->checkWh();
  5199. #endif //YUR_WH
  5200.  
  5201. #ifdef YUR_RINGS_AMULETS
  5202.             player->checkRing(thinkTicks);
  5203. #endif //YUR_RINGS_AMULETS
  5204.  
  5205. //SOFT BOOTS
  5206.        if(player->softTicks >= 2) {
  5207.        if(player->items[SLOT_FEET] && player->items[SLOT_FEET]->getID() == ITEM_SOFT_BOOTS && !tile->isPz()){
  5208.          player->mana += min(g_config.SOFT_MANA, player->manamax - player->mana);
  5209.          player->health += min(g_config.SOFT_HEALTH, player->healthmax - player->health);
  5210.        }
  5211. player->softTicks = 0;
  5212. } else {
  5213. player->softTicks++;
  5214. }
  5215. // LIFE RING
  5216.        if(player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_LIFE_RING_IN_USE && !tile->isPz()){
  5217.          player->mana += min(g_config.LR_MANA, player->manamax - player->mana);
  5218.          player->health += min(g_config.LR_HEALTH, player->healthmax - player->health);
  5219.        }
  5220. // ROH      
  5221.        if(player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_RING_OF_HEALING_IN_USE && !tile->isPz()){
  5222.          player->mana += min(g_config.ROH_MANA, player->manamax - player->mana);
  5223.          player->health += min(g_config.ROH_HEALTH, player->healthmax - player->health);
  5224.        }
  5225. // ROAH
  5226. // ROH 240      
  5227.        if(player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_STEALTH_RING_IN_USE && !tile->isPz()){
  5228.          player->mana += min(g_config.ROAH_MANA, player->manamax - player->mana);
  5229.          player->health += min(g_config.ROAH_HEALTH, player->healthmax - player->health);
  5230.        }
  5231. // RAINBOW SHIELD
  5232.        if(player->level >= 150){
  5233.         if(player->items[SLOT_RIGHT] && player->items[SLOT_RIGHT]->getID() == ITEM_RAINBOW && !tile->isPz()){
  5234.          if(player->items[SLOT_LEFT]){
  5235.           if(player->items[SLOT_LEFT]->getID() != ITEM_RAINBOW)
  5236.            if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5237.              player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5238.              player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5239.              player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5240.            }
  5241.          }else{
  5242.           if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5243.             player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5244.             player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5245.             player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5246.           }
  5247.          }
  5248.         }
  5249.         if(player->items[SLOT_LEFT] && player->items[SLOT_LEFT]->getID() == ITEM_RAINBOW && !tile->isPz()){
  5250.          if(player->items[SLOT_RIGHT]){
  5251.           if(player->items[SLOT_RIGHT]->getID() != ITEM_RAINBOW)
  5252.            if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5253.              player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5254.              player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5255.              player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5256.            }
  5257.          }else{
  5258.           if(player->mana > g_config.getGlobalNumber("rainbow_mana", 4) && player->health < player->healthmax){
  5259.             player->mana -= g_config.getGlobalNumber("rainbow_mana", 1);
  5260.             player->health += min(g_config.getGlobalNumber("rainbow_health", 1), player->healthmax - player->health);
  5261.             player->addManaSpent(g_config.getGlobalNumber("rainbow_mana",5));
  5262.           }
  5263.          }
  5264.         }
  5265.        }
  5266.        
  5267. // RING OF THE SKY
  5268.        if(player->level >= 30 && player->items[SLOT_RING] && player->items[SLOT_RING]->getID() == ITEM_ROTS && !tile->isPz())
  5269.          player->mana += min(1, player->manamax - player->mana);
  5270.          
  5271. // ORSHABAAL HEART
  5272.        if(player->name == "Ekudron" || player->name == "Agecik" && player->items[SLOT_AMMO] && player->items[SLOT_AMMO]->getID() == ITEM_ORSHABAAL_HEARTH && !tile->isPz())
  5273.          player->mana += min(4, player->manamax - player->mana);
  5274.          
  5275.          #ifdef HUCZU_FIX
  5276.        if(player->items[SLOT_FEET] && player->items[SLOT_FEET]->getID() == ITEM_SPECTRE_BOOTS)
  5277.          player->immunities = ATTACK_PARALYZE;
  5278.          else
  5279.          player->immunities -= ATTACK_PARALYZE;
  5280.          #endif //HUCZU_FIX
  5281.  
  5282. #ifdef YUR_LIGHT_ITEM
  5283.             player->checkLightItem(thinkTicks);
  5284. #endif //YUR_LIGHT_ITEM
  5285. #ifdef HUCZU_EXHAUSTED
  5286.             if(player->mmo > 0)
  5287.                 player->mmo -= 1;
  5288.             else
  5289.                 player->mmo = 0;
  5290.    
  5291.             if(player->lookex > 0)
  5292.                 player->lookex -= 1;
  5293.             else
  5294.                 player->lookex = 0;
  5295.            
  5296.             if(player->antyrainbow > 0)
  5297.                 player->antyrainbow -= 1;
  5298.             else
  5299.                 player->antyrainbow = 0;
  5300.                
  5301.             if(player->antyrainbow2 > 0)
  5302.                 player->antyrainbow2 -= 1;
  5303.             else
  5304.                 player->antyrainbow2 = 0;
  5305.                
  5306.                             if(player->clin > 0)
  5307.                             player->clin -= 1;
  5308.                             else
  5309.                             player->clin = 0;
  5310.                            
  5311.                             if(player->shut_d > 0)
  5312.                             player->shut_d -= 1;
  5313.                             else
  5314.                             player->shut_d = 0;
  5315.                
  5316.             if(player->houseTicks > 0)
  5317.                 player->houseTicks -= 1;
  5318.             else
  5319.                 player->houseTicks = 0;  
  5320. #endif //HUCZU_EXHAUSTED
  5321.  
  5322.              if(player->flamTicks >= 1000){
  5323.                 player->flamTicks -= thinkTicks;
  5324.              if(player->flamTicks == 0){
  5325.                 player->flamBool = false;
  5326.               }
  5327.             }
  5328.                  
  5329.                  
  5330.             if(player->items[SLOT_RIGHT] &&  player->items[SLOT_LEFT]){
  5331.              if((player->items[SLOT_RIGHT]->getID() == ITEM_BOW || player->items[SLOT_RIGHT]->getID() == ITEM_XBOW) && (player->items[SLOT_LEFT]->getWeaponType() == SHIELD || player->items[SLOT_LEFT]->getWeaponType() == SWORD || player->items[SLOT_LEFT]->getWeaponType() == AXE || player->items[SLOT_LEFT]->getWeaponType() == CLUB)){
  5332.                player->removeItemInventory(SLOT_RIGHT);
  5333.              }
  5334.              if((player->items[SLOT_LEFT]->getID() == ITEM_BOW || player->items[SLOT_LEFT]->getID() == ITEM_XBOW) && (player->items[SLOT_RIGHT]->getWeaponType() == SHIELD || player->items[SLOT_RIGHT]->getWeaponType() == SWORD || player->items[SLOT_RIGHT]->getWeaponType() == AXE || player->items[SLOT_RIGHT]->getWeaponType() == CLUB)){
  5335.                player->removeItemInventory(SLOT_LEFT);
  5336.              }
  5337.             }
  5338.  
  5339.             if(player->items[SLOT_RIGHT] &&  player->items[SLOT_LEFT]){
  5340.              if((player->items[SLOT_RIGHT]->getID() == ITEM_SPEAR || player->items[SLOT_RIGHT]->getID() == ITEM_KNIFE || player->items[SLOT_RIGHT]->getID() == ITEM_STONE || player->items[SLOT_RIGHT]->getID() == ITEM_SNOWBALL || player->items[SLOT_RIGHT]->getID() == ITEM_STAR) && (player->items[SLOT_LEFT]->getWeaponType() == SWORD || player->items[SLOT_LEFT]->getWeaponType() == AXE || player->items[SLOT_LEFT]->getWeaponType() == CLUB)){
  5341.                player->removeItemInventory(SLOT_RIGHT);
  5342.              }
  5343.              if((player->items[SLOT_LEFT]->getID() == ITEM_SPEAR || player->items[SLOT_LEFT]->getID() == ITEM_KNIFE || player->items[SLOT_LEFT]->getID() == ITEM_STONE || player->items[SLOT_LEFT]->getID() == ITEM_SNOWBALL || player->items[SLOT_LEFT]->getID() == ITEM_STAR) && (player->items[SLOT_RIGHT]->getWeaponType() == SWORD || player->items[SLOT_RIGHT]->getWeaponType() == AXE || player->items[SLOT_RIGHT]->getWeaponType() == CLUB)){
  5344.                player->removeItemInventory(SLOT_LEFT);
  5345.              }
  5346.             }
  5347.  
  5348. #ifdef HUCZU_SKULLS
  5349.             if (player->checkSkull(thinkTicks))
  5350.                 Skull(player);
  5351. #endif //HUCZU_SKULLS
  5352.  
  5353. #ifdef YUR_INVISIBLE
  5354.             if (player->checkInvisible(thinkTicks))
  5355.                 creatureChangeOutfit(player);
  5356. #endif //YUR_INVISIBLE
  5357.  
  5358. #ifdef _BBK_PUSH_DELAY
  5359.             if(player->pushDelay >= 1000)
  5360.             {
  5361.                 player->pushDelay -= thinkTicks;
  5362.                 if(player->pushDelay < 0)
  5363.                     player->pushDelay = 0;
  5364.             }
  5365. #endif //_BBK_PUSH_DELAY
  5366.  
  5367. if(player->training == true){
  5368.               if(player->trainingTicks >= 1000){
  5369.                 player->trainingTicks -= thinkTicks;
  5370.  
  5371.                 if(player->trainingTicks < 0)
  5372.                     player->trainingTicks = 0;
  5373.             }                    
  5374.         if(player->trainingTicks == 0 && player->rewriteTicks == 0){
  5375.            int code = random_range(47,99) * random_range(47,99);
  5376.            player->rewriteCode = code;
  5377.            player->needrewrite = true;
  5378.            player->rewriteTicks = g_config.REWRITE_TICKS;
  5379.            std::ostringstream info;    
  5380.            player->sendTextMessage(MSG_BLUE_TEXT,"You are training here pretty long.Are you using bot?");        
  5381.            info << "Please rewrite code: " << player->rewriteCode << std::ends;
  5382.            player->sendTextMessage(MSG_BLUE_TEXT, info.str().c_str());
  5383.            std::ostringstream info2;
  5384.            info2 << "Use this command !train 1234. You have " << player->rewriteTicks/1000 << " seconds!" << std::ends;
  5385.            player->sendTextMessage(MSG_BLUE_TEXT, info2.str().c_str());    
  5386.         }
  5387.  
  5388.         if(player->needrewrite != false){
  5389.               if(player->rewriteTicks >= 1000){
  5390.                 player->rewriteTicks -= thinkTicks;
  5391.             }
  5392.  
  5393.            if(player->rewriteTicks == 0){
  5394.               this->teleport(player, player->masterPos);
  5395.               player->training = false;
  5396.               player->trainingTicks = 0;
  5397.               player->needrewrite  = false;
  5398.               player->rewriteCode = 0;
  5399.               player->rewriteTicks = 0;
  5400.               player->kickPlayer();
  5401.               //player->sendLogout();
  5402.            }    
  5403.         }
  5404.     }
  5405.  
  5406.  
  5407.  
  5408. #ifdef HUCZU_FIX
  5409. if(player->gainHealthTick()){
  5410.                             SpectatorVec list;
  5411.                             SpectatorVec::iterator it;
  5412.                             getSpectators(Range(creature->pos), list);
  5413.                             for(it = list.begin(); it != list.end(); ++it) {      
  5414.                                 Player* p = dynamic_cast<Player*>(*it);
  5415.                                 if(p)
  5416.                                     p->sendCreatureHealth(player);
  5417.                             }
  5418.                         }
  5419. #endif //HUCZU_FIX
  5420.  
  5421. if(player->lightTicks >= 1000){
  5422.              player->lightTicks -= thinkTicks;
  5423.               if(player->lightTicks <= 1000){
  5424.                 player->lightTicks = 1;
  5425.               }
  5426.             }
  5427.             else if(player->lightTicks == 1){
  5428.               if(player->lightlevel > 0){
  5429.                 creatureChangeLight(player, 0, player->lightlevel-1, 0xD7);
  5430.               }
  5431.               else{
  5432.                 creatureChangeLight(player, 0, 0, 0xD7);
  5433.                 player->lightTicks = 0;
  5434.                 player->lightItem = 0;
  5435.               }
  5436.               if(player->lightTries > 0){
  5437.                 player->lightTicks = 3*60*1000;
  5438.                 player->lightTries -= 1;
  5439.               }
  5440.             }
  5441.            
  5442. #ifdef HUCZU_SKULLS
  5443.             checkSkullTime(player);
  5444. #endif //HUCZU_SKULLS
  5445.  
  5446.  
  5447.             if(!tile->isPz()){
  5448.                 if(player->food > 1000){
  5449.                     player->gainManaTick();
  5450.                     player->food -= thinkTicks;
  5451.                     if(player->healthmax - player->health > 0){
  5452.                         if(player->gainHealthTick()){
  5453.                             SpectatorVec list;
  5454.                             SpectatorVec::iterator it;
  5455.                             getSpectators(Range(creature->pos), list);
  5456.                             for(it = list.begin(); it != list.end(); ++it) {
  5457.                                 Player* p = dynamic_cast<Player*>(*it);
  5458.                                 if(p)
  5459.                                     p->sendCreatureHealth(player);
  5460.                             }
  5461.                         }
  5462.                     }
  5463.                 }
  5464.             }
  5465.  
  5466.             //send stast only if have changed
  5467.             if(player->NeedUpdateStats()){
  5468.                 player->sendStats();
  5469.             }
  5470.  
  5471.             player->sendPing(thinkTicks);
  5472.  
  5473.             if(player->inFightTicks >= 1000) {
  5474.                 player->inFightTicks -= thinkTicks;
  5475.  
  5476.                 if(player->inFightTicks < 1000)
  5477.                     player->pzLocked = false;
  5478.                     player->sendIcons();
  5479.             }
  5480.            
  5481.             if(player->drunkTicks >= 1000) {
  5482.               int32_t random = random_range(1,100);
  5483.                if(random <= 25){
  5484.                  creatureSay(creature, SPEAK_SAY, "Hicks!");
  5485.                  Position pos;
  5486.                  int32_t randomwalk = random_range(1,4);
  5487.                  switch(randomwalk){
  5488.                   case 1:pos.x++;break;
  5489.                   case 2:pos.x--;break;
  5490.                   case 3:pos.y++;break;
  5491.                   case 4:pos.y--;break;
  5492.                  }
  5493.                  Tile* toTile = getTile(pos.x, pos.y, pos.z);
  5494. //make sure they don't get teleported into a place they shouldn't
  5495.                  if(toTile &&
  5496.                  !toTile->isBlocking(1, false, false) &&
  5497.                  !toTile->isBlocking(2, false, false) &&
  5498.                  !toTile->isBlocking(4, false, false) &&
  5499.                  !toTile->isBlocking(8, false, false) &&
  5500.                  !toTile->isBlocking(16, false, false))
  5501.                    teleport(player,pos);
  5502.                }
  5503.                player->drunkTicks -= thinkTicks;
  5504.                player->sendIcons();
  5505.             }
  5506.  
  5507.             if(player->exhaustedTicks >= 1000){
  5508.                 player->exhaustedTicks -= thinkTicks;
  5509.  
  5510.                 if(player->exhaustedTicks < 0)
  5511.                     player->exhaustedTicks = 0;
  5512.             }
  5513.  
  5514.             if(player->manaShieldTicks >=1000){
  5515.                 player->manaShieldTicks -= thinkTicks;
  5516.  
  5517.                 if(player->manaShieldTicks  < 1000)
  5518.                     player->sendIcons();
  5519.             }
  5520.             if(player->dwarvenTicks > 0){
  5521.               player->drunkTicks = 0;
  5522.               player->sendIcons();
  5523.             }
  5524.             if(player->dwarvenTicks = 0){
  5525.               player->drunkTicks = 4000;
  5526.               player->sendIcons();
  5527.             }
  5528.  
  5529.             if(player->hasteTicks >=1000)
  5530.                 player->hasteTicks -= thinkTicks;
  5531.         }else{
  5532.            
  5533.             if(creature->manaShieldTicks >=1000){
  5534.                 creature->manaShieldTicks -= thinkTicks;
  5535.             }
  5536.  
  5537.             if(creature->hasteTicks >=1000){
  5538.                 creature->hasteTicks -= thinkTicks;
  5539.             }
  5540.  
  5541. #ifdef YUR_INVISIBLE
  5542.             if (creature->checkInvisible(thinkTicks))
  5543.                 creatureChangeOutfit(creature);
  5544. #endif //YUR_INVISIBLE
  5545.         }
  5546.  
  5547.         Conditions& conditions = creature->getConditions();
  5548.         for(Conditions::iterator condIt = conditions.begin(); condIt != conditions.end(); ++condIt) {
  5549.             if(condIt->first == ATTACK_FIRE || condIt->first == ATTACK_ENERGY || condIt->first == ATTACK_POISON) {
  5550.                 ConditionVec &condVec = condIt->second;
  5551.  
  5552.                 if(condVec.empty())
  5553.                     continue;
  5554.  
  5555.                 CreatureCondition& condition = condVec[0];
  5556.  
  5557.                 if(condition.onTick(oldThinkTicks)) {
  5558.                     const MagicEffectTargetCreatureCondition* magicTargetCondition =  condition.getCondition();
  5559.                     Creature* c = getCreatureByID(magicTargetCondition->getOwnerID());
  5560.                     creatureMakeMagic(c, creature->pos, magicTargetCondition);
  5561.  
  5562.                     if(condition.getCount() <= 0) {
  5563.                         condVec.erase(condVec.begin());
  5564.                               if(dynamic_cast<Player*>(creature))
  5565.                                 player->sendIcons();
  5566.                     }
  5567.                 }
  5568.             }
  5569.          if(condIt->first == ATTACK_PARALYZE)
  5570.             {
  5571.                 ConditionVec &condVec = condIt->second;
  5572.                 if(condVec.empty())
  5573.                     continue;
  5574.  
  5575.                 CreatureCondition& condition = condVec[0];
  5576.                 if(condition.onTick(oldThinkTicks))
  5577.                 {
  5578.                     //Player* player = dynamic_cast<Player*>(creature);
  5579.                     if(creature->getImmunities() != ATTACK_PARALYZE)
  5580.                     {
  5581.                         changeSpeed(creature->getID(), 100);
  5582.                         if(player)
  5583.                         {
  5584.                             player->sendTextMessage(MSG_SMALLINFO, "You are paralyzed.");
  5585.                             player->sendIcons();
  5586.                         }
  5587.                     }
  5588.  
  5589.                     if(condition.getCount() <= 0)
  5590.                     {
  5591.                         condVec.erase(condVec.begin());
  5592.                         changeSpeed(creature->getID(), creature->getNormalSpeed()+creature->hasteSpeed);
  5593.                         if(player)
  5594.                         {
  5595.                             player->sendIcons();
  5596.                         }
  5597.                     }
  5598.                 }
  5599.             }
  5600.         }
  5601.         flushSendBuffers();
  5602.     }
  5603. }
  5604.  
  5605. void Game::changeOutfit(uint32_t id, int32_t looktype){
  5606.      
  5607.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::changeOutfit()");
  5608.  
  5609.     Creature *creature = getCreatureByID(id);
  5610.     if(creature){
  5611.         creature->looktype = looktype;
  5612.         if(creature->lookfeet_master != 0 || creature->lookhead_master != 0 || 
  5613.            creature->looklegs_master != 0 || creature->lookbody_master != 0 ){
  5614.            creature->lookhead = creature->lookhead_master;
  5615.            creature->lookbody = creature->lookbody_master;
  5616.            creature->looklegs = creature->looklegs_master;
  5617.            creature->lookfeet = creature->lookfeet_master;
  5618.            
  5619.            creature->lookhead_master = 0;
  5620.            creature->lookbody_master = 0;
  5621.            creature->looklegs_master = 0;
  5622.            creature->lookfeet_master = 0;
  5623.         }  
  5624.         creatureChangeOutfit(creature);
  5625.     }
  5626. }
  5627.  
  5628. void Game::changeOutfitAfter(uint32_t id, int32_t looktype, long time)
  5629. {
  5630.     addEvent(makeTask(time, boost::bind(&Game::changeOutfit, this,id, looktype)));
  5631. }
  5632.  
  5633. void Game::changeSpeed(uint32_t id, unsigned short speed)
  5634. {
  5635.  OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::changeSpeed()");
  5636.  Creature *creature = getCreatureByID(id);
  5637.  if(creature && /*creature->hasteTicks < 1000 && */creature->speed != speed)
  5638.  {
  5639.   creature->speed = speed;
  5640.   Player* player = dynamic_cast<Player*>(creature);
  5641.   if(player){
  5642.    player->sendChangeSpeed(creature);
  5643.    player->sendIcons();
  5644.   }
  5645.   SpectatorVec list;
  5646.   SpectatorVec::iterator it;
  5647.   getSpectators(Range(creature->pos), list);
  5648.   //for(uint32_t i = 0; i < list.size(); i++)
  5649.   for(it = list.begin(); it != list.end(); ++it) {
  5650.    Player* p = dynamic_cast<Player*>(*it);
  5651.    if(p)
  5652.     p->sendChangeSpeed(creature);
  5653.   }
  5654.  }
  5655. }
  5656.  
  5657. void Game::checkCreatureAttacking(uint32_t id)
  5658. {
  5659.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreatureAttacking()");
  5660.  
  5661.     Creature *creature = getCreatureByID(id);
  5662.     if (creature != NULL && creature->isRemoved == false)
  5663.     {
  5664.            
  5665.         creature->eventCheckAttacking = 0;
  5666.         Player *player = dynamic_cast<Player*>(creature);
  5667.         Monster *monster = dynamic_cast<Monster*>(creature);
  5668.         if (monster) {
  5669.             monster->onAttack();
  5670.         }
  5671.         else {
  5672.             if (creature->attackedCreature != 0)
  5673.             {
  5674.                 Creature *attackedCreature = getCreatureByID(creature->attackedCreature);
  5675.                 if (attackedCreature)
  5676.                 {
  5677.                                      // canAttack system BRY
  5678.  
  5679. Player *attacker = dynamic_cast<Player*>(creature);
  5680. Player *attacked = dynamic_cast<Player*>(attackedCreature);
  5681. bool canAttack = false;
  5682. if(attacker && attacked)
  5683.  {
  5684.    Tile* tile = getTile(attacker->pos.x,attacker->pos.y, attacker->pos.z);
  5685.    if(attacked->level >= 1 && attacked->level < 30 && attacker->level >= 1 && attacker->level < 30)
  5686.    canAttack = false;
  5687.    
  5688.    else if(attacked->level >= 30 && attacked->level < 80 && attacker->level >= 30 && attacker->level < 80)
  5689.    canAttack = true;
  5690.    
  5691.    else if(attacked->level >= 80 && attacked->level < 999 && attacker->level >= 80 && attacker->level < 999)
  5692.    canAttack = true;
  5693.    
  5694.    
  5695.    else if(tile && tile->isPvpArena())
  5696.    canAttack = true;
  5697.    }
  5698.    
  5699.  
  5700.  
  5701. if(attacker && attacked && !canAttack)
  5702. {
  5703. attacker->sendCancelAttacking();
  5704. attacker->sendCancel("You may not attack this player yet.");
  5705. playerSetAttackedCreature(attacker, 0);
  5706. return;
  5707. }
  5708.                     //Tile* fromtile = getTile(creature->pos.x, creature->pos.y, creature->pos.z);
  5709.                     Tile* fromtile = map->getTile(creature->pos);
  5710.                     if(fromtile == NULL) {
  5711.                         std::cout << "checkCreatureAttacking NULL tile: " << creature->getName() << std::endl;
  5712.                         //return;
  5713.                     }
  5714.                     Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  5715.                     if (!attackedCreature->isAttackable() == 0 && fromtile && fromtile->isPz() && creature->access < g_config.ACCESS_PROTECT)
  5716.                     {
  5717.                         Player* player = dynamic_cast<Player*>(creature);
  5718.                         if (player) {
  5719.                             player->sendTextMessage(MSG_SMALLINFO, "You may not attack a person in a protection zone.");
  5720.                             //player->sendCancelAttacking();
  5721.                             playerSetAttackedCreature(player, 0);
  5722.                             return;
  5723.                         }
  5724.                     }
  5725. #ifdef YUR_INVISIBLE
  5726.                         if (attackedCreature->isInvisible())
  5727.                         {
  5728.                             Player* player = dynamic_cast<Player*>(creature);
  5729.                             Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  5730.  
  5731.                             if (player && !attackedPlayer) {
  5732.                                 player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  5733.                                 playerSetAttackedCreature(player, 0);
  5734.                                 return;
  5735.                             }
  5736.                         }
  5737. #endif //YUR_INVISIBLE
  5738.                     else
  5739.                     {
  5740.                         if (attackedCreature != NULL && attackedCreature->isRemoved == false)
  5741.                         {
  5742.                                              
  5743. #ifdef ZS_SWORDS
  5744.                                 int32_t swordid = player->getSwordId();
  5745.                                 if (swordid > 0)
  5746.                                     useSword(player, attackedCreature, swordid);
  5747. #endif //ZS_SWORDS
  5748.  
  5749. if(player && player->followMode == 0x01) {
  5750. player->followCreature = attackedCreature->getID();
  5751. playerAttackSetFollowCreature(player, attackedCreature->getID());
  5752. playerFollowAttacking(player, attackedCreature);
  5753. long long delay = player->getSleepTicks();
  5754. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollowAttack), player->getID())));      
  5755. }
  5756.  
  5757.  
  5758.       #ifdef WANDS_JIDDO
  5759. Player* player = dynamic_cast<Player*>(creature);
  5760. int32_t wandid = 0;
  5761. if(player && ((player->items[SLOT_RIGHT] && (wandid = player->items[SLOT_RIGHT]->getWand())) || (player->items[SLOT_LEFT] && (wandid = player->items[SLOT_LEFT]->getWand())))) {
  5762. useWand(creature, attackedCreature, wandid);
  5763. } else {
  5764. #endif
  5765.                             Player* player = dynamic_cast<Player*>(creature);
  5766.                             if (player)
  5767.                             {
  5768. #ifdef SD_BURST_ARROW  
  5769.                                 if (player->isUsingBurstArrows())
  5770.                                     burstArrow(player, attackedCreature->pos);
  5771. #endif //SD_BURST_ARROW
  5772.                               if(player->flamBool == true){
  5773.                                 Blasting(player, attackedCreature, attackedCreature->pos);
  5774.                                 player->flamBool = false;
  5775.                                 }
  5776.                             }
  5777.                             this->creatureMakeDamage(creature, attackedCreature, creature->getFightType());
  5778.                             #ifdef WANDS_JIDDO
  5779. }
  5780. #endif
  5781.                         }
  5782.                     }
  5783.  
  5784.                     if (player->vocation == 0) {
  5785.                                          int32_t speed = int32_t(g_config.NO_VOC_SPEED * 1000);
  5786.                                          creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5787.                                          }
  5788.                     else if (player->vocation == 1) {
  5789.                                          int32_t speed = int32_t(g_config.SORC_SPEED * 1000);
  5790.                                          creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5791.                                          }
  5792.                     else if (player->vocation == 2) {
  5793.                                          int32_t speed = int32_t(g_config.DRUID_SPEED * 1000);
  5794.                                          creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5795.                                          }
  5796.                     else if (player->vocation == 3) {
  5797.                                          int32_t speed = int32_t(g_config.PALLY_SPEED * 1000);
  5798.                                          creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5799.                                          }
  5800.                     else if (player->vocation == 4) {
  5801.                                          int32_t speed = int32_t(g_config.KNIGHT_SPEED * 1000);
  5802.                                          creature->eventCheckAttacking = addEvent(makeTask(speed, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5803.                                          }
  5804.                     else { //change the 2000 to whatever you want; 2000 = 2 seconds per attack
  5805.                                          creature->eventCheckAttacking = addEvent(makeTask(1000, std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), id)));
  5806.                                          }
  5807.                 }
  5808.             }
  5809.         }
  5810.         flushSendBuffers();
  5811.     }
  5812. }
  5813. void Game::checkDecay(int32_t t)
  5814. {
  5815.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkDecay()");
  5816.  
  5817.     addEvent(makeTask(DECAY_INTERVAL, boost::bind(&Game::checkDecay,this,DECAY_INTERVAL)));
  5818.  
  5819.     list<decayBlock*>::iterator it;
  5820.     for(it = decayVector.begin();it != decayVector.end();){
  5821.         (*it)->decayTime -= t;
  5822.         if((*it)->decayTime <= 0){
  5823.             list<Item*>::iterator it2;
  5824.             for(it2 = (*it)->decayItems.begin(); it2 != (*it)->decayItems.end(); it2++){
  5825.                 /*todo: Decaying item could be in a  container carried by a player,
  5826.                 should all items have a pointer to their parent (like containers)?*/
  5827.                 Item* item = *it2;
  5828.                 item->isDecaying = false;
  5829.                 if(item->canDecay()){
  5830.                     if(item->pos.x != 0xFFFF){
  5831.                         Tile *tile = map->getTile(item->pos);
  5832.                         if(tile){
  5833.                             Position pos = item->pos;
  5834.                             Item* newitem = item->decay();
  5835.  
  5836.                             if(newitem){
  5837.                                 int32_t stackpos = tile->getThingStackPos(item);
  5838.                                 if(newitem == item){
  5839.                                     sendUpdateThing(NULL,pos,newitem,stackpos);
  5840.                                 }
  5841.                                 else{
  5842.                                     if(tile->removeThing(item)){
  5843.                                         //autoclose containers
  5844.                                         if(dynamic_cast<Container*>(item)){
  5845.                                             SpectatorVec list;
  5846.                                             SpectatorVec::iterator it;
  5847.  
  5848.                                             getSpectators(Range(pos, true), list);
  5849.  
  5850.                                             for(it = list.begin(); it != list.end(); ++it) {
  5851.                                                 Player* spectator = dynamic_cast<Player*>(*it);
  5852.                                                 if(spectator)
  5853.                                                     spectator->onThingRemove(item);
  5854.                                             }
  5855.                                         }
  5856.  
  5857.                                         tile->insertThing(newitem, stackpos);
  5858.                                         sendUpdateThing(NULL,pos,newitem,stackpos);
  5859.                                         FreeThing(item);
  5860.                                     }
  5861.                                 }
  5862.                                 startDecay(newitem);
  5863.                             }
  5864.                             else{
  5865.                                 if(removeThing(NULL,pos,item)){
  5866.                                     FreeThing(item);
  5867.                                 }
  5868.                             }//newitem
  5869.                         }//tile
  5870.                     }//pos != 0xFFFF
  5871.                 }//item->canDecay()
  5872.                 FreeThing(item);
  5873.             }//for it2
  5874.             delete *it;
  5875.             it = decayVector.erase(it);
  5876.         }//(*it)->decayTime <= 0
  5877.         else{
  5878.             it++;
  5879.         }
  5880.     }//for it
  5881.  
  5882.     flushSendBuffers();
  5883. }
  5884.  
  5885. void Game::startDecay(Item* item){
  5886.     if(item->isDecaying)
  5887.         return;//dont add 2 times the same item
  5888.     //get decay time
  5889.     item->isDecaying = true;
  5890.     uint32_t dtime = item->getDecayTime();
  5891.     if(dtime == 0)
  5892.         return;
  5893.     //round time
  5894.     if(dtime < DECAY_INTERVAL)
  5895.         dtime = DECAY_INTERVAL;
  5896.     dtime = (dtime/DECAY_INTERVAL)*DECAY_INTERVAL;
  5897.     item->useThing();
  5898.     //search if there are any block with this time
  5899.     list<decayBlock*>::iterator it;
  5900.     for(it = decayVector.begin();it != decayVector.end();it++){
  5901.         if((*it)->decayTime == dtime){
  5902.             (*it)->decayItems.push_back(item);
  5903.             return;
  5904.         }
  5905.     }
  5906.     //we need a new decayBlock
  5907.     decayBlock* db = new decayBlock;
  5908.     db->decayTime = dtime;
  5909.     db->decayItems.clear();
  5910.     db->decayItems.push_back(item);
  5911.     decayVector.push_back(db);
  5912. }
  5913.  
  5914. void Game::checkSpawns(int32_t t)
  5915. {
  5916.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkSpawns()");
  5917.  
  5918.     SpawnManager::instance()->checkSpawns(t);
  5919.     this->addEvent(makeTask(t, std::bind2nd(std::mem_fun(&Game::checkSpawns), t)));
  5920. }
  5921.  
  5922. void Game::CreateDamageUpdate(Creature* creature, Creature* attackCreature, int32_t damage)
  5923. {
  5924.     Player* player = dynamic_cast<Player*>(creature);
  5925.     Player* attackPlayer = dynamic_cast<Player*>(attackCreature);
  5926.     if(!player)
  5927.         return;
  5928.     //player->sendStats();
  5929.     //msg.AddPlayerStats(player);
  5930.     if (damage > 0) {
  5931.         std::stringstream dmgmesg, info;
  5932.  
  5933.         if(damage == 1) {
  5934.             dmgmesg << "You lose 1 hitpoint";
  5935.         }
  5936.         else
  5937.             dmgmesg << "You lose " << damage << " hitpoints";
  5938.  
  5939.         if(attackPlayer) {
  5940.             dmgmesg << " due to an attack by " << attackCreature->getName();
  5941.         }
  5942.         else if(attackCreature) {
  5943.             std::string strname = attackCreature->getName();
  5944.             std::transform(strname.begin(), strname.end(), strname.begin(), (int32_t(*)(int32_t))tolower);
  5945.             dmgmesg << " due to an attack by a " << strname;
  5946.         }
  5947.         dmgmesg <<".";
  5948.    
  5949.         player->sendTextMessage(MSG_EVENT, dmgmesg.str().c_str());
  5950.         //msg.AddTextMessage(MSG_EVENT, dmgmesg.str().c_str());
  5951.     }
  5952.     if (player->isRemoved == true){
  5953.         player->sendTextMessage(MSG_ADVANCE, "You are dead.");
  5954.     }
  5955. }
  5956.  
  5957.  
  5958. void Game::CreateManaDamageUpdate(Creature* creature, Creature* attackCreature, int32_t damage)
  5959. {
  5960.     Player* player = dynamic_cast<Player*>(creature);
  5961.     if(!player)
  5962.         return;
  5963.  
  5964.     if (damage > 0) {
  5965.         std::stringstream dmgmesg;
  5966.         dmgmesg << "You lose " << damage << " mana";
  5967.         if(attackCreature) {
  5968.             dmgmesg << " blocking an attack by " << attackCreature->getName();
  5969.         }
  5970.         dmgmesg <<".";
  5971.  
  5972.         player->sendTextMessage(MSG_EVENT, dmgmesg.str().c_str());
  5973.     }
  5974. }
  5975.  
  5976. bool Game::creatureSaySpell(Creature *creature, const std::string &text, bool say)
  5977. {
  5978.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureSaySpell()");
  5979.  
  5980.     bool ret = false;
  5981.  
  5982.     Player* player = dynamic_cast<Player*>(creature);
  5983.     std::string temp, var;
  5984.     uint32_t loc = (uint32_t)text.find( "\"", 0 );
  5985.     if( loc != string::npos && loc >= 0){
  5986.         temp = std::string(text, 0, loc-1);
  5987.         var = std::string(text, (loc+1), text.size()-loc-1);
  5988.     }
  5989.     else {
  5990.         temp = text;
  5991.         var = std::string("");
  5992.     }
  5993.  
  5994.     std::transform(temp.begin(), temp.end(), temp.begin(), (int32_t(*)(int32_t))tolower);
  5995.  
  5996.     if(creature->access >= g_config.ACCESS_PROTECT || !player){
  5997.         std::map<std::string, Spell*>::iterator sit = spells.getAllSpells()->find(temp);
  5998.         if (sit != spells.getAllSpells()->end()){
  5999.             sit->second->getSpellScript()->castSpell(creature, creature->pos, var);
  6000.             if (creature->access >= g_config.ACCESS_PROTECT && say == true)
  6001.                 this->creatureSay(creature, SPEAK_MONSTER1, text);
  6002.             ret = true;
  6003.         }
  6004.     }
  6005.     else if(player){
  6006.         std::map<std::string, Spell*>* tmp = spells.getVocSpells(player->vocation);
  6007.         if(tmp){
  6008.             std::map<std::string, Spell*>::iterator sit = tmp->find(temp);
  6009.             if(sit != tmp->end()){
  6010.                 if(player->maglevel >= sit->second->getMagLv()){
  6011. #ifdef YUR_LEARN_SPELLS
  6012.                     if (g_config.LEARN_SPELLS && !player->knowsSpell(temp))
  6013.                         ret = false;
  6014.                     else
  6015. #endif //YUR_LEARN_SPELLS
  6016.                     {
  6017.                         if(sit->second->getSpellScript()->castSpell(creature, creature->pos, var) && say == true)
  6018.                             this->creatureSay(player, SPEAK_MONSTER1, text);
  6019.                         ret = true;
  6020.                     }
  6021.                 }
  6022.             }
  6023.         }
  6024.     }
  6025.    
  6026.  
  6027.  
  6028.     return ret;
  6029. }
  6030.  
  6031. void Game::playerAutoWalk(Player* player, std::list<Direction>& path)
  6032. {
  6033.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerAutoWalk()");
  6034.  
  6035.     stopEvent(player->eventAutoWalk);
  6036.     player->eventAutoWalk = 0;
  6037.  
  6038.     if(player->isRemoved)
  6039.         return;
  6040.  
  6041.     player->pathlist = path;
  6042.     int32_t ticks = (int32_t)player->getSleepTicks();
  6043. /*
  6044. #ifdef __DEBUG__
  6045.     std::cout << "playerAutoWalk - " << ticks << std::endl;
  6046. #endif
  6047. */
  6048.     if(!player->pathlist.empty())
  6049.     player->eventAutoWalk = addEvent(makeTask(ticks, std::bind2nd(std::mem_fun(&Game::checkPlayerWalk), player->getID())));
  6050.  
  6051.     // then we schedule the movement...
  6052.   // the interval seems to depend on the speed of the char?
  6053.     //player->eventAutoWalk = addEvent(makeTask<Direction>(0, MovePlayer(player->getID()), path, 400, StopMovePlayer(player->getID())));
  6054.     //player->pathlist = path;
  6055. }
  6056.  
  6057. bool Game::playerUseItemEx(Player *player, const Position& posFrom,const unsigned char  stack_from,
  6058.         const Position &posTo,const unsigned char stack_to, const unsigned short itemid)
  6059. {
  6060.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerUseItemEx()");
  6061.  
  6062.     if(player->isRemoved)
  6063.         return false;
  6064.  
  6065.     bool ret = false;
  6066.  
  6067.     Position thingpos = getThingMapPos(player, posFrom);
  6068.     Item *item = dynamic_cast<Item*>(getThing(posFrom, stack_from, player));
  6069. Container* container = player->getContainer(player->shop_index);
  6070.     if(container && item && !container->shop.empty() && container->isHoldingItem(item))
  6071.         return false;
  6072.  
  6073.     if(item) {
  6074.         //Runes
  6075.         std::map<unsigned short, Spell*>::iterator sit = spells.getAllRuneSpells()->find(item->getID());
  6076.         if(sit != spells.getAllRuneSpells()->end()) {
  6077. #ifdef PALL_REQ_LVL        
  6078.              std::stringstream ss;      
  6079.                      if(item->getReqLevel() > player->getLevel()){
  6080.                         ss << "\n Musisz miec " << item->getReqLevel() << " poziom aby tego uzyc.";
  6081.                         ret = false;
  6082.                      }
  6083.                      if(item->isWeapon() && item->getReqVoc() != player->getVocation()){
  6084.                        switch(item->getReqVoc()){
  6085.                            case 1:
  6086.                              ss << "\n You must be a sorcerer to use this weapon.";
  6087.                              ret = false;
  6088.                              break;
  6089.                            case 2:
  6090.                               ss << "\n You must be a druid to use this weapon.";
  6091.                               ret = false;
  6092.                               break;
  6093.                            case 3:
  6094.                               ss << "\n You must be a paladin to use this weapon.";
  6095.                               ret = false;
  6096.                               break;
  6097.                            case 4:
  6098.                               ss << "\n You must be a knight to use this weapon.";
  6099.                               ret = false;
  6100.                               break;
  6101.                        }
  6102.                      }
  6103.                        player->sendTextMessage(MSG_SMALLINFO, ss.str().c_str());
  6104. #endif //PALL_REQ_LVL
  6105.             if( (abs(thingpos.x - player->pos.x) > 1) || (abs(thingpos.y - player->pos.y) > 1) ) {
  6106.                 player->sendCancel("Too far away.");
  6107.                 ret = false;
  6108.             }
  6109.             else {
  6110.                 std::string var = std::string("");
  6111.                 if(player->access >= g_config.ACCESS_PROTECT || sit->second->getMagLv() <= player->maglevel)
  6112.                 {
  6113.                     bool success = sit->second->getSpellScript()->castSpell(player, posTo, var);
  6114.                     ret = success;
  6115.                     if(success) {
  6116.                         autoCloseTrade(item);
  6117.                         item->setItemCharge(std::max((int32_t)item->getItemCharge() - 1, 0) );
  6118.                         if(item->getItemCharge() == 0) {
  6119.                             if(removeThing(player,posFrom,item)){
  6120.                                 FreeThing(item);
  6121.                             }
  6122.                         }
  6123.                     }
  6124.                 }
  6125.                 else
  6126.                 {
  6127.                     player->sendCancel("You don't have the required magic level to use that rune.");
  6128.                 }
  6129.             }
  6130.         }
  6131.         else{
  6132.             actions.UseItemEx(player,posFrom,stack_from,posTo,stack_to,itemid);
  6133.             ret = true;
  6134.         }
  6135.     }
  6136.  
  6137.  
  6138.     return ret;
  6139. }
  6140.  
  6141.  
  6142. bool Game::playerUseItem(Player *player, const Position& pos, const unsigned char stackpos, const unsigned short itemid, unsigned char index)
  6143. {
  6144.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerUseItem()");
  6145.    if(itemid == 2273 || itemid == 2275 ){
  6146.              
  6147.           MagicEffectClass pox;
  6148.           pox.animationColor = 0;
  6149.           pox.damageEffect = NM_ME_MAGIC_ENERGIE;
  6150.           pox.hitEffect = 255;
  6151.           pox.attackType = ATTACK_NONE;
  6152.           pox.maxDamage = 0;
  6153.           pox.minDamage = 0;
  6154.           pox.offensive = false;
  6155.           pox.manaCost = 0;
  6156.           if(creatureMakeMagic(player, player->pos, &pox)){
  6157.           player->removeCondition(ATTACK_PARALYZE);
  6158.           int32_t newspeed = player->getNormalSpeed()+player->hasteSpeed;
  6159.           changeSpeed(player->getID(), (unsigned short)newspeed);
  6160.          
  6161.           if(player)
  6162.           player->sendIcons();    
  6163.  }
  6164.       else{
  6165.           player->sendCancel("Sorry, not possible.");
  6166.           return false;
  6167.           }
  6168.           }
  6169.     if(player->isRemoved)
  6170.         return false;
  6171.        
  6172.     actions.UseItem(player,pos,stackpos,itemid,index);
  6173.     return true;
  6174. }
  6175.  
  6176. bool Game::playerUseBattleWindow(Player *player, Position &posFrom, unsigned char stackpos, unsigned short itemid, uint32_t creatureid)
  6177. {
  6178.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerUseBattleWindow");
  6179.  
  6180.     if(player->isRemoved)
  6181.         return false;
  6182.  
  6183.     Creature *creature = getCreatureByID(creatureid);
  6184.     if(!creature || dynamic_cast<Player*>(creature))
  6185.         return false;
  6186.  
  6187.     if(std::abs(creature->pos.x - player->pos.x) > 7 || std::abs(creature->pos.y - player->pos.y) > 5 || creature->pos.z != player->pos.z)
  6188.         return false;
  6189.  
  6190.     bool ret = false;
  6191.  
  6192.     Position thingpos = getThingMapPos(player, posFrom);
  6193.     Item *item = dynamic_cast<Item*>(getThing(posFrom, stackpos, player));
  6194. Container* container = player->getContainer(player->shop_index);
  6195.     if(container && item && !container->shop.empty() && container->isHoldingItem(item))
  6196.         return false;
  6197.     if(item) {
  6198.         //Runes
  6199.         std::map<unsigned short, Spell*>::iterator sit = spells.getAllRuneSpells()->find(item->getID());
  6200.         if(sit != spells.getAllRuneSpells()->end()) {
  6201.             if( (abs(thingpos.x - player->pos.x) > 1) || (abs(thingpos.y - player->pos.y) > 1) ) {
  6202.                 player->sendCancel("Too far away.");
  6203.             }
  6204.             else {
  6205.                 std::string var = std::string("");
  6206.                 if(player->access >= g_config.ACCESS_PROTECT || sit->second->getMagLv() <= player->maglevel)
  6207.                 {
  6208.                     bool success = sit->second->getSpellScript()->castSpell(player, creature->pos, var);
  6209.                     ret = success;
  6210.                     if(success){
  6211.                         autoCloseTrade(item);
  6212.                         item->setItemCharge(std::max((int32_t)item->getItemCharge() - 1, 0) );
  6213.                         if(item->getItemCharge() == 0){
  6214.                             if(removeThing(player,posFrom,item)){
  6215.                                 FreeThing(item);
  6216.                             }
  6217.                         }
  6218.                     }
  6219.                 }
  6220.                 else
  6221.                 {
  6222.                     player->sendCancel("You don't have the required magic level to use that rune.");
  6223.                 }
  6224.             }
  6225.         }
  6226.     }
  6227.     return ret;
  6228. }
  6229.  
  6230. bool Game::playerRotateItem(Player *player, const Position& pos, const unsigned char stackpos, const unsigned short itemid)
  6231. {
  6232.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerRotateItem()");
  6233.  
  6234.     if(player->isRemoved)
  6235.         return false;
  6236.  
  6237.     if(std::abs(player->pos.x - pos.x) > 1 || std::abs(player->pos.y - pos.y) > 1 || player->pos.z != pos.z){
  6238.         player->sendCancel("Too far away.");
  6239.         return false;
  6240.     }
  6241.  
  6242.     Item *item = dynamic_cast<Item*>(getThing(pos, stackpos, player));
  6243.     if(item && item->rotate()){
  6244.         sendUpdateThing(player, pos, item, stackpos);
  6245.     }
  6246.  
  6247.     return false;
  6248. }
  6249.  
  6250. void Game::playerRequestTrade(Player* player, const Position& pos,
  6251.     const unsigned char stackpos, const unsigned short itemid, uint32_t playerid)
  6252. {
  6253.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerRequestTrade()");
  6254.  
  6255.     if(player->isRemoved)
  6256.         return;
  6257.  
  6258.     Player *tradePartner = getPlayerByID(playerid);
  6259.     if(!tradePartner || tradePartner == player) {
  6260.         player->sendTextMessage(MSG_INFO, "Sorry, not possible.");
  6261.         return;
  6262.     }
  6263.  
  6264.     if(player->tradeState != TRADE_NONE && !(player->tradeState == TRADE_ACKNOWLEDGE && player->tradePartner == playerid)) {
  6265.         player->sendCancel("You are already trading.");
  6266.         return;
  6267.     }
  6268.     else if(tradePartner->tradeState != TRADE_NONE && tradePartner->tradePartner != player->getID()) {
  6269.         player->sendCancel("This player is already trading.");
  6270.         return;
  6271.     }
  6272.  
  6273.     Item *tradeItem = dynamic_cast<Item*>(getThing(pos, stackpos, player));
  6274.     if(!tradeItem || tradeItem->getID() != itemid || !tradeItem->isPickupable()) {
  6275.         player->sendCancel("Sorry, not possible.");
  6276.         return;
  6277.     }
  6278.    
  6279.     #ifdef __KIRO_AKT__
  6280.     if(tradeItem->getID() == ITEM_AKT)
  6281.     {
  6282.        Tile* tile = getTile(player->pos);
  6283.        House* house = tile? tile->getHouse() : NULL;
  6284.        
  6285.        if(!house)
  6286.        {
  6287.            player->sendCancel("You must stay in house!");
  6288.            return;
  6289.        }    
  6290.        if(house->getOwner() != player->getName())
  6291.        {
  6292.         player->sendCancel("You must stay in your house!");
  6293.         return;
  6294.        }
  6295.      }
  6296.    
  6297. #endif
  6298.  
  6299.     if(!player->removeItem(tradeItem, true)) {
  6300.         /*if( (abs(player->pos.x - pos.x) > 1) || (abs(player->pos.y - pos.y) > 1) ) {
  6301.             player->sendCancel("To far away...");
  6302.             return;
  6303.         }*/
  6304.         player->sendCancel("Sorry, not possible.");
  6305.         return;
  6306.     }
  6307.  
  6308.     std::map<Item*, uint32_t>::const_iterator it;
  6309.     const Container* container = NULL;
  6310.     for(it = tradeItems.begin(); it != tradeItems.end(); it++) {
  6311.         if(tradeItem == it->first ||
  6312.             ((container = dynamic_cast<const Container*>(tradeItem)) && container->isHoldingItem(it->first)) ||
  6313.             ((container = dynamic_cast<const Container*>(it->first)) && container->isHoldingItem(tradeItem)))
  6314.         {
  6315.             player->sendTextMessage(MSG_INFO, "This item is already beeing traded.");
  6316.             return;
  6317.         }
  6318.     }
  6319.  
  6320.     Container* tradeContainer = dynamic_cast<Container*>(tradeItem);
  6321.     if(tradeContainer && tradeContainer->getItemHoldingCount() + 1 > 100){
  6322.         player->sendTextMessage(MSG_INFO, "You cannot trade more than 100 items.");
  6323.         return;
  6324.     }
  6325.  
  6326.     player->tradePartner = playerid;
  6327.     player->tradeItem = tradeItem;
  6328.     player->tradeState = TRADE_INITIATED;
  6329.     tradeItem->useThing();
  6330.     tradeItems[tradeItem] = player->getID();
  6331.  
  6332.     player->sendTradeItemRequest(player, tradeItem, true);
  6333.  
  6334.     if(tradePartner->tradeState == TRADE_NONE){
  6335.         std::stringstream trademsg;
  6336.         trademsg << player->getName() <<" wants to trade with you.";
  6337.         tradePartner->sendTextMessage(MSG_INFO, trademsg.str().c_str());
  6338.         tradePartner->tradeState = TRADE_ACKNOWLEDGE;
  6339.         tradePartner->tradePartner = player->getID();
  6340.     }
  6341.     else {
  6342.         Item* counterOfferItem = tradePartner->tradeItem;
  6343.         player->sendTradeItemRequest(tradePartner, counterOfferItem, false);
  6344.         tradePartner->sendTradeItemRequest(player, tradeItem, false);
  6345.     }
  6346. }
  6347.  
  6348. void Game::playerAcceptTrade(Player* player)
  6349. {
  6350.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerAcceptTrade()");
  6351.  
  6352.     if(player->isRemoved)
  6353.         return;
  6354.  
  6355.     player->setAcceptTrade(true);
  6356.     Player *tradePartner = getPlayerByID(player->tradePartner);
  6357.     if(tradePartner && tradePartner->getAcceptTrade()) {
  6358.         Item *tradeItem1 = player->tradeItem;
  6359.         Item *tradeItem2 = tradePartner->tradeItem;
  6360.  
  6361.         player->sendCloseTrade();
  6362.         tradePartner->sendCloseTrade();
  6363.        
  6364. #ifdef __KIRO_AKT__
  6365.         if(tradeItem1->getID() == ITEM_AKT)
  6366.         {
  6367.            Tile* tile = getTile(player->pos);
  6368.            House* house = tile? tile->getHouse() : NULL;
  6369.            Tile* tile2 = getTile(tradePartner->pos);
  6370.            Creature* creature = getCreatureByName(house->getOwner());
  6371.            Player* prevOwner = creature? dynamic_cast<Player*>(creature) : NULL;
  6372.            if(!house || !tile->isHouse())
  6373.            {
  6374.                player->sendCancel("You must stay in house!");
  6375.                return;
  6376.            }
  6377.            if(!tile->isHouse() && !tile2->isHouse() && player->tradeState != TRADE_INITIATED){
  6378.            player->sendCancel("You can only sell act if you are in house and you are the owner!");
  6379.            return;
  6380.            }  
  6381.            if(house->getOwner() != player->getName())
  6382.            {
  6383.             player->sendCancel("You must stay in your house!");
  6384.             return;
  6385.            }
  6386.            
  6387.            if(house && house->checkHouseCount(tradePartner) >= g_config.getGlobalNumber("maxhouses", 0)){
  6388.               std::stringstream textmsg;
  6389.               textmsg << "You cannot have more than " << g_config.getGlobalNumber("maxhouses", 1) << " house.";
  6390.               tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6391.               return;    
  6392.            }
  6393.            
  6394.            if (house && tradePartner->level < g_config.getGlobalNumber("buyhouselvlrook",1) && tradePartner->vocation == 0)
  6395.            {
  6396.             player->sendCancel("This player have too low level to buy house!");
  6397.             std::stringstream textmsg;
  6398.             textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("buyhouselvlrook",2) << " level.";
  6399.             tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6400.             return;
  6401.            }
  6402.            
  6403.            if (house && tradePartner->level < g_config.getGlobalNumber("houselevel", 0) && tradePartner->vocation != 0)
  6404.            {
  6405.             player->sendCancel("This player have too low level to buy house!");
  6406.             std::stringstream textmsg;
  6407.             textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("houselevel", 0) << " level.";
  6408.             tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6409.             return;
  6410.            }
  6411.            
  6412.            if(tradePartner->getFreeCapacity() < tradeItem1->getWeight())
  6413.            {
  6414.             return;
  6415.            }
  6416.            
  6417.            if(player->addItem(tradeItem2, true) && tradePartner->addItem(tradeItem1, true) &&
  6418.             player->removeItem(tradeItem1, true) && tradePartner->removeItem(tradeItem2, true)){
  6419.  
  6420.             player->removeItem(tradeItem1);
  6421.             tradePartner->removeItem(tradeItem2);
  6422.  
  6423.             player->onThingRemove(tradeItem1);
  6424.             tradePartner->onThingRemove(tradeItem2);
  6425.  
  6426.             player->addItem(tradeItem2);
  6427.             tradePartner->addItem(tradeItem1);
  6428.             }
  6429.             else{
  6430.             player->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6431.             tradePartner->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6432.             return;
  6433.             }
  6434.            player->removeItem(tradeItem1, true);
  6435.            tradePartner->addItem(tradeItem1, true);
  6436.            player->addItem(tradeItem2, true);
  6437.            house->setOwner(tradePartner->getName());
  6438.            teleport(player,tradePartner->pos);
  6439.            if (prevOwner)
  6440.               prevOwner->houseRightsChanged = true;
  6441.            tradePartner->houseRightsChanged = true;
  6442.          }
  6443.         else if(tradeItem2->getID() == ITEM_AKT)
  6444.         {
  6445.            Tile* tile = getTile(tradePartner->pos);
  6446.            House* house = tile? tile->getHouse() : NULL;
  6447.            Tile* tile2 = getTile(player->pos);
  6448.            Creature* creature = getCreatureByName(house->getOwner());
  6449.            Player* prevOwner = creature? dynamic_cast<Player*>(creature) : NULL;
  6450.            if(!house || !tile->isHouse())
  6451.            {
  6452.                tradePartner->sendCancel("You must stay in house!");
  6453.                return;
  6454.            }
  6455.            if(!tile->isHouse() && !tile2->isHouse() && player->tradeState != TRADE_INITIATED){
  6456.            player->sendCancel("You can only sell act if you are in house and you are the owner!");
  6457.            return;
  6458.            }
  6459.            if(house->getOwner() != tradePartner->getName())
  6460.            {
  6461.             tradePartner->sendCancel("You must stay in your house!");
  6462.             return;
  6463.            }
  6464.            
  6465.            if(house && house->checkHouseCount(player) >= g_config.getGlobalNumber("maxhouses", 0)){
  6466.               std::stringstream textmsg;
  6467.               textmsg << " You cannot have more than " << g_config.getGlobalNumber("maxhouses", 1) << " house.";
  6468.               tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6469.               return;    
  6470.            }
  6471.            
  6472.            if (house && tradePartner->level < g_config.getGlobalNumber("buyhouselvlrook",1) && tradePartner->vocation == 0)
  6473.            {
  6474.             player->sendCancel("This player have too low level to buy house!");
  6475.             std::stringstream textmsg;
  6476.             textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("buyhouselvlrook",2) << " level.";
  6477.             tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6478.             return;
  6479.            }
  6480.            
  6481.            if (house && tradePartner->level < g_config.getGlobalNumber("houselevel", 0) && tradePartner->vocation != 0)
  6482.            {
  6483.             player->sendCancel("This player have too low level to buy house!");
  6484.             std::stringstream textmsg;
  6485.             textmsg << "You have too low level to buy house! You must have " << g_config.getGlobalNumber("houselevel", 0) << " level.";
  6486.             tradePartner->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  6487.             return;
  6488.            }
  6489.            
  6490.            if(tradePartner->getFreeCapacity() < tradeItem1->getWeight())
  6491.            {
  6492.             return;
  6493.            }
  6494.            
  6495.            if(player->addItem(tradeItem2, true) && tradePartner->addItem(tradeItem1, true) &&
  6496.             player->removeItem(tradeItem1, true) && tradePartner->removeItem(tradeItem2, true)){
  6497.  
  6498.             player->removeItem(tradeItem1);
  6499.             tradePartner->removeItem(tradeItem2);
  6500.  
  6501.             player->onThingRemove(tradeItem1);
  6502.             tradePartner->onThingRemove(tradeItem2);
  6503.  
  6504.             player->addItem(tradeItem2);
  6505.             tradePartner->addItem(tradeItem1);
  6506.             }
  6507.             else{
  6508.             player->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6509.             tradePartner->sendTextMessage(MSG_SMALLINFO, "Sorry, you don't have space.");
  6510.             return;
  6511.             }
  6512.            tradePartner->removeItem(tradeItem1, true);
  6513.            player->addItem(tradeItem1, true);
  6514.            tradePartner->addItem(tradeItem2, true);
  6515.            house->setOwner(player->getName());
  6516.            teleport(tradePartner,player->pos);
  6517.            if (prevOwner)
  6518.            prevOwner->houseRightsChanged = true;
  6519.            player->houseRightsChanged = true;
  6520.          }
  6521. #endif
  6522.  
  6523.         if(player->addItem(tradeItem2, true) && tradePartner->addItem(tradeItem1, true) &&
  6524.             player->removeItem(tradeItem1, true) && tradePartner->removeItem(tradeItem2, true)){
  6525.  
  6526.             player->removeItem(tradeItem1);
  6527.             tradePartner->removeItem(tradeItem2);
  6528.  
  6529.             player->onThingRemove(tradeItem1);
  6530.             tradePartner->onThingRemove(tradeItem2);
  6531.  
  6532.             player->addItem(tradeItem2);
  6533.             tradePartner->addItem(tradeItem1);
  6534.         }
  6535.         else{
  6536.             player->sendTextMessage(MSG_SMALLINFO, "Sorry not possible.");
  6537.             tradePartner->sendTextMessage(MSG_SMALLINFO, "Sorry not possible.");
  6538.         }
  6539.        
  6540.         std::map<Item*, uint32_t>::iterator it;
  6541.        
  6542.         it = tradeItems.find(tradeItem1);
  6543.         if(it != tradeItems.end()) {
  6544.             FreeThing(it->first);
  6545.             tradeItems.erase(it);
  6546.         }
  6547.        
  6548.         it = tradeItems.find(tradeItem2);
  6549.         if(it != tradeItems.end()) {
  6550.             FreeThing(it->first);
  6551.             tradeItems.erase(it);
  6552.         }
  6553.        
  6554.         player->setAcceptTrade(false);
  6555.         tradePartner->setAcceptTrade(false);
  6556.     }
  6557. }
  6558.  
  6559. void Game::playerLookInTrade(Player* player, bool lookAtCounterOffer, int32_t index)
  6560. {
  6561.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerLookInTrade()");
  6562.  
  6563.     Player *tradePartner = getPlayerByID(player->tradePartner);
  6564.     if(!tradePartner)
  6565.         return;
  6566.  
  6567.     Item *tradeItem = NULL;
  6568.  
  6569.     if(lookAtCounterOffer)
  6570.         tradeItem = tradePartner->getTradeItem();
  6571.     else
  6572.         tradeItem = player->getTradeItem();
  6573.  
  6574.     if(!tradeItem)
  6575.         return;
  6576.        
  6577.         #ifdef __KIRO_AKT__
  6578.         if(tradeItem->getID() == ITEM_AKT)
  6579.         {
  6580.            Tile* tile = getTile(tradePartner->pos);
  6581.            House* house = tile? tile->getHouse() : NULL;
  6582.            
  6583.      
  6584.            if(house && house->getOwner() == tradePartner->getName())
  6585.            {
  6586.             stringstream ss;
  6587.             ss << "You see " << tradeItem->getDescription(true) << " applies to: " << house->getName() << ".";
  6588.             player->sendTextMessage(MSG_INFO, ss.str().c_str());
  6589.             return;
  6590.            }
  6591.            
  6592.          }
  6593. #endif
  6594.  
  6595.     if(index == 0) {
  6596.         stringstream ss;
  6597.         ss << "You see " << tradeItem->getDescription(true);
  6598.         player->sendTextMessage(MSG_INFO, ss.str().c_str());
  6599.         return;
  6600.     }
  6601.  
  6602.     Container *tradeContainer = dynamic_cast<Container*>(tradeItem);
  6603.     if(!tradeContainer || index > tradeContainer->getItemHoldingCount())
  6604.         return;
  6605.  
  6606.     bool foundItem = false;
  6607.     std::list<const Container*> stack;
  6608.     stack.push_back(tradeContainer);
  6609.  
  6610.     ContainerList::const_iterator it;
  6611.  
  6612.     while(!foundItem && stack.size() > 0) {
  6613.         const Container *container = stack.front();
  6614.         stack.pop_front();
  6615.  
  6616.         for (it = container->getItems(); it != container->getEnd(); ++it) {
  6617.             Container *container = dynamic_cast<Container*>(*it);
  6618.             if(container) {
  6619.                 stack.push_back(container);
  6620.             }
  6621.  
  6622.             --index;
  6623.             if(index == 0) {
  6624.                 tradeItem = *it;
  6625.                 foundItem = true;
  6626.                 break;
  6627.             }
  6628.         }
  6629.     }
  6630.  
  6631.     if(foundItem) {
  6632.         stringstream ss;
  6633.         ss << "You see " << tradeItem->getDescription(true);
  6634.         player->sendTextMessage(MSG_INFO, ss.str().c_str());
  6635.     }
  6636. }
  6637.  
  6638. void Game::playerCloseTrade(Player* player)
  6639. {
  6640.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerCloseTrade()");
  6641.  
  6642.     Player* tradePartner = getPlayerByID(player->tradePartner);
  6643.  
  6644.     std::vector<Item*>::iterator it;
  6645.     if(player->getTradeItem()) {
  6646.         std::map<Item*, uint32_t>::iterator it = tradeItems.find(player->getTradeItem());
  6647.         if(it != tradeItems.end()) {
  6648.             FreeThing(it->first);
  6649.             tradeItems.erase(it);
  6650.         }
  6651.     }
  6652.  
  6653.     player->setAcceptTrade(false);
  6654.     player->sendTextMessage(MSG_SMALLINFO, "Trade cancelled.");
  6655.     player->sendCloseTrade();
  6656.  
  6657.     if(tradePartner) {
  6658.         if(tradePartner->getTradeItem()) {
  6659.             std::map<Item*, uint32_t>::iterator it = tradeItems.find(tradePartner->getTradeItem());
  6660.             if(it != tradeItems.end()) {
  6661.                 FreeThing(it->first);
  6662.                 tradeItems.erase(it);
  6663.             }
  6664.         }
  6665.  
  6666.         tradePartner->setAcceptTrade(false);
  6667.         tradePartner->sendTextMessage(MSG_SMALLINFO, "Trade cancelled.");
  6668.         tradePartner->sendCloseTrade();
  6669.     }
  6670. }
  6671.  
  6672. void Game::autoCloseTrade(const Item* item, bool itemMoved /*= false*/)
  6673. {
  6674.     if(!item)
  6675.         return;
  6676.  
  6677.     std::map<Item*, uint32_t>::const_iterator it;
  6678.     const Container* container = NULL;
  6679.     for(it = tradeItems.begin(); it != tradeItems.end(); it++) {
  6680.         if(item == it->first ||
  6681.             (itemMoved && (container = dynamic_cast<const Container*>(item)) && container->isHoldingItem(it->first)) ||
  6682.             ((container = dynamic_cast<const Container*>(it->first)) && container->isHoldingItem(item)))
  6683.         {
  6684.             Player* player = getPlayerByID(it->second);
  6685.             if(player){
  6686.                 playerCloseTrade(player);
  6687.             }
  6688.  
  6689.             break;
  6690.         }
  6691.     }
  6692. }
  6693.  
  6694. void Game::autoCloseAttack(Player* player, Creature* target)
  6695. {
  6696.   if((std::abs(player->pos.x - target->pos.x) > 7) ||
  6697.   (std::abs(player->pos.y - target->pos.y) > 5) || (player->pos.z != target->pos.z)){
  6698.       player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  6699.       playerSetAttackedCreature(player, 0);
  6700.   }
  6701. }
  6702.  
  6703. void Game::playerSetAttackedCreature(Player* player, uint32_t creatureid)
  6704. {
  6705.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerSetAttackedCreature()");
  6706.  
  6707.     if(player->isRemoved)
  6708.         return;
  6709.  
  6710.     if(player->attackedCreature != 0 && creatureid == 0) {
  6711.         player->sendCancelAttacking();
  6712.     }
  6713.  
  6714.  
  6715.     Creature* attackedCreature = NULL;
  6716.     if(creatureid != 0) {
  6717.         attackedCreature = getCreatureByID(creatureid);
  6718.     }
  6719.  
  6720.     Player* attackedPlayer = dynamic_cast<Player*>(attackedCreature);
  6721.     bool pvpArena = false, rook = false, attackedIsSummon = false;
  6722.  
  6723. #ifdef YUR_PVP_ARENA
  6724.     if (player && attackedCreature)
  6725.     {
  6726.         Tile *t1 = map->getTile(player->pos), *t2 = map->getTile(attackedCreature->pos);
  6727.         pvpArena = t1 && t2 && t1->isPvpArena() && t2->isPvpArena();
  6728.     }
  6729. #endif //YUR_PVP_ARENA
  6730.  
  6731. #ifdef YUR_ROOKGARD
  6732.     rook = player && player->isRookie() && attackedPlayer && attackedPlayer->isRookie();
  6733. #endif //YUR_ROOKGARD
  6734.  
  6735. #ifdef TR_SUMMONS
  6736.     attackedIsSummon = (attackedCreature && attackedCreature->isPlayersSummon() && attackedCreature->getMaster() != player);
  6737. #endif //TR_SUMMONS
  6738.  
  6739.     if(!attackedCreature || (attackedCreature->access >= g_config.ACCESS_PROTECT || ((getWorldType() == WORLD_TYPE_NO_PVP || rook) &&
  6740.         !pvpArena && player->access < g_config.ACCESS_PROTECT && (dynamic_cast<Player*>(attackedCreature) || attackedIsSummon)))) {
  6741.     if(attackedCreature) {
  6742.           player->sendTextMessage(MSG_SMALLINFO, "You may not attack this player.");
  6743.     }
  6744.         player->sendCancelAttacking();
  6745.         player->setAttackedCreature(NULL);
  6746.         stopEvent(player->eventCheckAttacking);
  6747.         player->eventCheckAttacking = 0;
  6748.     }
  6749.     else if(attackedCreature) {
  6750.         player->setAttackedCreature(attackedCreature);
  6751.         stopEvent(player->eventCheckAttacking);
  6752.     player->eventCheckAttacking = addEvent(makeTask(g_config.getGlobalNumber("firstattack", 2000), std::bind2nd(std::mem_fun(&Game::checkCreatureAttacking), player->getID())));
  6753.     }
  6754.  
  6755. }
  6756.  
  6757.  
  6758. void Game::flushSendBuffers()
  6759. {
  6760.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::flushSendBuffers()");
  6761.  
  6762.     for(std::vector<Player*>::iterator it = BufferedPlayers.begin(); it != BufferedPlayers.end(); ++it) {
  6763.         (*it)->flushMsg();
  6764.         (*it)->SendBuffer = false;
  6765.         (*it)->releaseThing();
  6766. /*
  6767. #ifdef __DEBUG__
  6768.         std::cout << "flushSendBuffers() - releaseThing()" << std::endl;
  6769. #endif
  6770. */
  6771.         }
  6772.     BufferedPlayers.clear();
  6773.  
  6774.     //free memory
  6775.     for(std::vector<Thing*>::iterator it = ToReleaseThings.begin(); it != ToReleaseThings.end(); ++it){
  6776.         (*it)->releaseThing();
  6777.     }
  6778.     ToReleaseThings.clear();
  6779.  
  6780.  
  6781.     return;
  6782. }
  6783.  
  6784. void Game::addPlayerBuffer(Player* p)
  6785. {
  6786.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::addPlayerBuffer()");
  6787.  
  6788. /*
  6789. #ifdef __DEBUG__
  6790.     std::cout << "addPlayerBuffer() - useThing()" << std::endl;
  6791. #endif
  6792. */
  6793.     if(p->SendBuffer == false){
  6794.         p->useThing();
  6795.         BufferedPlayers.push_back(p);
  6796.         p->SendBuffer = true;
  6797.     }
  6798.  
  6799.     return;
  6800. }
  6801.  
  6802. void Game::FreeThing(Thing* thing){
  6803.  
  6804.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::FreeThing()");
  6805.     //std::cout << "freeThing() " << thing <<std::endl;
  6806.     ToReleaseThings.push_back(thing);
  6807.  
  6808.     return;
  6809. }
  6810. /*
  6811. ADD
  6812. container(player,pos-cid,thing)
  6813. inventory(player,pos-i,[ignored])
  6814. ground([ignored],postion,thing)
  6815.  
  6816. REMOVE
  6817. container(player,pos-cid,thing,autoclose?)
  6818. inventory(player,pos-i,thing,autoclose?)
  6819. ground([ignored],postion,thing,autoclose?,stackpos)
  6820.  
  6821. UPDATE
  6822. container(player,pos-cid,thing)
  6823. inventory(player,pos-i,[ignored])
  6824. ground([ignored],postion,thing,stackpos)
  6825. */
  6826. void Game::sendAddThing(Player* player,const Position &pos,const Thing* thing){
  6827.     if(pos.x == 0xFFFF) {
  6828.         if(!player)
  6829.             return;
  6830.         if(pos.y & 0x40) { //container
  6831.             if(!thing)
  6832.                 return;
  6833.  
  6834.             const Item *item = dynamic_cast<const Item*>(thing);
  6835.             if(!item)
  6836.                 return;
  6837.  
  6838.             unsigned char containerid = pos.y & 0x0F;
  6839.             Container* container = player->getContainer(containerid);
  6840.             if(!container)
  6841.                 return;
  6842.  
  6843.             SpectatorVec list;
  6844.             SpectatorVec::iterator it;
  6845.  
  6846.             Position centerpos = (container->pos.x == 0xFFFF ? player->pos : container->pos);
  6847.             getSpectators(Range(centerpos,2,2,2,2,false), list);
  6848.  
  6849.             if(!list.empty()) {
  6850.                 for(it = list.begin(); it != list.end(); ++it) {
  6851.                     Player *spectator = dynamic_cast<Player*>(*it);
  6852.                     if(spectator)
  6853.                         spectator->onItemAddContainer(container,item);
  6854.                 }
  6855.             }
  6856.             else
  6857.                 player->onItemAddContainer(container,item);
  6858.  
  6859.         }
  6860.         else //inventory
  6861.         {
  6862.             player->sendInventory(pos.y);
  6863.         }
  6864.     }
  6865.     else //ground
  6866.     {
  6867.         if(!thing)
  6868.             return;
  6869.  
  6870. #ifdef SM_SUMMON_ATTACK
  6871.         Monster* monster = dynamic_cast<Monster*>(const_cast<Thing*>(thing));
  6872. #endif //SM_SUMMON_ATTACK
  6873.  
  6874.         SpectatorVec list;
  6875.         SpectatorVec::iterator it;
  6876.  
  6877.         getSpectators(Range(pos,true), list);
  6878.  
  6879.         //players
  6880.         for(it = list.begin(); it != list.end(); ++it) {
  6881.             if(dynamic_cast<Player*>(*it)) {
  6882.                 (*it)->onThingAppear(thing);
  6883. #ifdef SM_SUMMON_ATTACK
  6884.                 if (monster && !monster->isSummon())
  6885.                     monster->onThingAppear(*it);
  6886. #endif //SM_SUMMON_ATTACK
  6887.             }
  6888.         }
  6889.  
  6890.         //none-players
  6891.         for(it = list.begin(); it != list.end(); ++it) {
  6892.             if(!dynamic_cast<Player*>(*it)) {
  6893.                 (*it)->onThingAppear(thing);
  6894.             }
  6895.         }
  6896.     }
  6897. }
  6898.  
  6899. void Game::sendRemoveThing(Player* player,const Position &pos,const Thing* thing,const unsigned char stackpos /*=1*/ ,const bool autoclose/* =false*/){
  6900.     if(!thing)
  6901.         return;
  6902.  
  6903.     const Item *item = dynamic_cast<const Item*>(thing);
  6904.     bool perform_autoclose = false;
  6905.     if(autoclose && item){
  6906.         const Container *container = dynamic_cast<const Container*>(item);
  6907.         if(container)
  6908.             perform_autoclose = true;
  6909.     }
  6910.  
  6911.     if(pos.x == 0xFFFF) {
  6912.         if(!player)
  6913.             return;
  6914.         if(pos.y & 0x40) { //container
  6915.             if(!item)
  6916.                 return;
  6917.  
  6918.             unsigned char containerid = pos.y & 0x0F;
  6919.             Container* container = player->getContainer(containerid);
  6920.             if(!container)
  6921.                 return;
  6922.  
  6923.             //check that item is in the container
  6924.             unsigned char slot = container->getSlotNumberByItem(item);
  6925.  
  6926.             SpectatorVec list;
  6927.             SpectatorVec::iterator it;
  6928.  
  6929.             Position centerpos = (container->pos.x == 0xFFFF ? player->pos : container->pos);
  6930.             getSpectators(Range(centerpos,2,2,2,2,false), list);
  6931.  
  6932.             if(!list.empty()) {
  6933.                 for(it = list.begin(); it != list.end(); ++it) {
  6934.                     Player *spectator = dynamic_cast<Player*>(*it);
  6935.                     if(spectator){
  6936.                         spectator->onItemRemoveContainer(container,slot);
  6937.                         if(perform_autoclose){
  6938.                             spectator->onThingRemove(thing);
  6939.                         }
  6940.                     }
  6941.                 }
  6942.             }
  6943.             else{
  6944.                 player->onItemRemoveContainer(container,slot);
  6945.                 if(perform_autoclose){
  6946.                     player->onThingRemove(thing);
  6947.                 }
  6948.             }
  6949.  
  6950.         }
  6951.         else //inventory
  6952.         {
  6953.             player->removeItemInventory(pos.y);
  6954.             if(perform_autoclose){
  6955.                 player->onThingRemove(thing);
  6956.             }
  6957.         }
  6958.     }
  6959.     else //ground
  6960.     {
  6961.         SpectatorVec list;
  6962.         SpectatorVec::iterator it;
  6963.  
  6964.         getSpectators(Range(pos,true), list);
  6965.  
  6966.         //players
  6967.         for(it = list.begin(); it != list.end(); ++it) {
  6968.             Player *spectator = dynamic_cast<Player*>(*it);
  6969.             if(spectator) {
  6970.                 spectator->onThingDisappear(thing,stackpos);
  6971.  
  6972.                 if(perform_autoclose){
  6973.                     spectator->onThingRemove(thing);
  6974.                 }
  6975.             }
  6976.         }
  6977.  
  6978.         //none-players
  6979.         for(it = list.begin(); it != list.end(); ++it) {
  6980.             if(!dynamic_cast<Player*>(*it)) {
  6981.                 (*it)->onThingDisappear(thing,stackpos);
  6982.             }
  6983.         }
  6984.     }
  6985. }
  6986.  
  6987. void Game::sendUpdateThing(Player* player,const Position &pos,const Thing* thing,const unsigned char stackpos/*=1*/){
  6988.  
  6989.     if(pos.x == 0xFFFF) {
  6990.         if(!player)
  6991.             return;
  6992.         if(pos.y & 0x40) { //container
  6993.             if(!thing)
  6994.                 return;
  6995.  
  6996.             const Item *item = dynamic_cast<const Item*>(thing);
  6997.             if(!item)
  6998.                 return;
  6999.  
  7000.             unsigned char containerid = pos.y & 0x0F;
  7001.             Container* container = player->getContainer(containerid);
  7002.             if(!container)
  7003.                 return;
  7004.             //check that item is in the container
  7005.             unsigned char slot = container->getSlotNumberByItem(item);
  7006.  
  7007.             SpectatorVec list;
  7008.             SpectatorVec::iterator it;
  7009.  
  7010.             Position centerpos = (container->pos.x == 0xFFFF ? player->pos : container->pos);
  7011.             getSpectators(Range(centerpos,2,2,2,2,false), list);
  7012.  
  7013.             if(!list.empty()) {
  7014.                 for(it = list.begin(); it != list.end(); ++it) {
  7015.                     Player *spectator = dynamic_cast<Player*>(*it);
  7016.                     if(spectator)
  7017.                         spectator->onItemUpdateContainer(container,item,slot);
  7018.                 }
  7019.             }
  7020.             else{
  7021.                 //never should be here
  7022.                 std::cout << "Error: sendUpdateThing" << std::endl;
  7023.                 //player->onItemUpdateContainer(container,item,slot);
  7024.             }
  7025.  
  7026.         }
  7027.         else //inventory
  7028.         {
  7029.             player->sendInventory(pos.y);
  7030.         }
  7031.     }
  7032.     else //ground
  7033.     {
  7034.         if(!thing)
  7035.             return;
  7036.  
  7037.         SpectatorVec list;
  7038.         SpectatorVec::iterator it;
  7039.  
  7040.         getSpectators(Range(pos,true), list);
  7041.  
  7042.         //players
  7043.         for(it = list.begin(); it != list.end(); ++it) {
  7044.             if(dynamic_cast<Player*>(*it)) {
  7045.                 (*it)->onThingTransform(thing,stackpos);
  7046.             }
  7047.         }
  7048.  
  7049.         //none-players
  7050.         for(it = list.begin(); it != list.end(); ++it) {
  7051.             if(!dynamic_cast<Player*>(*it)) {
  7052.                 (*it)->onThingTransform(thing,stackpos);
  7053.             }
  7054.         }
  7055.     }
  7056. }
  7057.  
  7058. void Game::addThing(Player* player,const Position &pos,Thing* thing)
  7059. {
  7060.     if(!thing)
  7061.         return;
  7062.     Item *item = dynamic_cast<Item*>(thing);
  7063.  
  7064.     if(pos.x == 0xFFFF) {
  7065.         if(!player || !item)
  7066.             return;
  7067.  
  7068.         if(pos.y & 0x40) { //container
  7069.             unsigned char containerid = pos.y & 0x0F;
  7070.             Container* container = player->getContainer(containerid);
  7071.             if(!container)
  7072.                 return;
  7073.  
  7074.             container->addItem(item);
  7075.             sendAddThing(player,pos,thing);
  7076.         }
  7077.         else //inventory
  7078.         {
  7079.             player->addItemInventory(item,pos.y,true);
  7080.             sendAddThing(player,pos,thing);
  7081.         }
  7082.     }
  7083.     else //ground
  7084.     {
  7085.         if(!thing)
  7086.             return;
  7087.         //Tile *tile = map->getTile(pos.x, pos.y, pos.z);
  7088.         Tile *tile = map->getTile(pos);
  7089.         if(tile){
  7090.             thing->pos = pos;
  7091.             if(item && item->isSplash()){
  7092.                 if(tile->splash){
  7093.                     int32_t oldstackpos = tile->getThingStackPos(tile->splash);
  7094.                     Item *oldsplash = tile->splash;
  7095.  
  7096.                     oldsplash->isRemoved = true;
  7097.                     FreeThing(oldsplash);
  7098.  
  7099.                     tile->splash = item;
  7100.  
  7101.                     sendUpdateThing(NULL, pos, item, oldstackpos);
  7102.                 }
  7103.                 else{
  7104.                     tile->splash = item;
  7105.                     sendAddThing(NULL,pos,tile->splash);
  7106.                 }
  7107.             }
  7108.             else if(item && item->isGroundTile()){
  7109.                 tile->ground = item;
  7110.  
  7111.                 SpectatorVec list;
  7112.                 SpectatorVec::iterator it;
  7113.  
  7114.                 getSpectators(Range(thing->pos, true), list);
  7115.  
  7116.                 //players
  7117.                 for(it = list.begin(); it != list.end(); ++it) {
  7118.                     if(dynamic_cast<Player*>(*it)) {
  7119.                         (*it)->onTileUpdated(pos);
  7120.                     }
  7121.                 }
  7122.  
  7123.                 //none-players
  7124.                 for(it = list.begin(); it != list.end(); ++it) {
  7125.                     if(!dynamic_cast<Player*>(*it)) {
  7126.                         (*it)->onTileUpdated(pos);
  7127.                     }
  7128.                 }
  7129.  
  7130.                 //Game::creatureBroadcastTileUpdated(thing->pos);
  7131.             }
  7132.             else if(item && item->isStackable()){
  7133.                 Item *topitem = tile->getTopDownItem();
  7134.                 if(topitem && topitem->getID() == item->getID() &&
  7135.                   topitem->getItemCountOrSubtype() + item->getItemCountOrSubtype() <= 100){
  7136.                     topitem->setItemCountOrSubtype(topitem->getItemCountOrSubtype() + item->getItemCountOrSubtype());
  7137.                     int32_t stackpos = tile->getThingStackPos(topitem);
  7138.                     sendUpdateThing(NULL,topitem->pos,topitem,stackpos);
  7139.                     item->pos.x = 0xFFFF;
  7140.                     FreeThing(item);
  7141.                 }
  7142.                 else{
  7143.                     tile->addThing(thing);
  7144.                     sendAddThing(player,pos,thing);
  7145.                 }
  7146.             }
  7147.             else{
  7148.                 tile->addThing(thing);
  7149.                 sendAddThing(player,pos,thing);
  7150.             }
  7151.         }
  7152.     }
  7153. }
  7154.  
  7155. bool Game::removeThing(Player* player,const Position &pos,Thing* thing,  bool setRemoved /*= true*/)
  7156. {
  7157.     if(!thing)
  7158.         return false;
  7159.     Item *item = dynamic_cast<Item*>(thing);
  7160.  
  7161.     if(pos.x == 0xFFFF) {
  7162.         if(!player || !item)
  7163.             return false;
  7164.  
  7165.         if(pos.y & 0x40) { //container
  7166.             unsigned char containerid = pos.y & 0x0F;
  7167.             Container* container = player->getContainer(containerid);
  7168.             if(!container)
  7169.                 return false;
  7170.  
  7171.             sendRemoveThing(player,pos,thing,0,true);
  7172.             if(!container->removeItem(item))
  7173.                 return false;
  7174.  
  7175.             if(player && player->isHoldingContainer(container)) {
  7176.                 player->updateInventoryWeigth();
  7177.                 player->sendStats();
  7178.             }
  7179.         }
  7180.         else //inventory
  7181.         {
  7182.             //sendRemoveThing(player,pos,thing,0,true);
  7183.             if(!player->removeItemInventory(pos.y))
  7184.                 return false;
  7185.             player->onThingRemove(thing);
  7186.             //player->removeItemInventory(pos.y,true);
  7187.         }
  7188.         if(setRemoved)
  7189.             item->isRemoved = true;
  7190.         return true;
  7191.     }
  7192.     else //ground
  7193.     {
  7194.         //Tile *tile = map->getTile(pos.x, pos.y, pos.z);
  7195.         Tile *tile = map->getTile(pos);
  7196.         if(tile){
  7197.             unsigned char stackpos = tile->getThingStackPos(thing);
  7198.             if(!tile->removeThing(thing))
  7199.                 return false;
  7200.             sendRemoveThing(NULL,pos,thing,stackpos,true);
  7201.         }
  7202.         else{
  7203.             return false;
  7204.         }
  7205.         if(item && setRemoved){
  7206.             item->isRemoved = true;
  7207.         }
  7208.         return true;
  7209.     }
  7210. }
  7211.  
  7212. Position Game::getThingMapPos(Player *player, const Position &pos)
  7213. {
  7214.     if(pos.x == 0xFFFF){
  7215.         Position dummyPos(0,0,0);
  7216.         if(!player)
  7217.             return dummyPos;
  7218.         if(pos.y & 0x40) { //from container
  7219.             unsigned char containerid = pos.y & 0x0F;
  7220.             const Container* container = player->getContainer(containerid);
  7221.             if(!container){
  7222.                 return dummyPos;
  7223.             }
  7224.             while(container->getParent() != NULL) {
  7225.                 container = container->getParent();
  7226.             }
  7227.             if(container->pos.x == 0xFFFF)
  7228.                 return player->pos;
  7229.             else
  7230.                 return container->pos;
  7231.         }
  7232.         else //from inventory
  7233.         {
  7234.             return player->pos;
  7235.         }
  7236.     }
  7237.     else{
  7238.         return pos;
  7239.     }
  7240. }
  7241.  
  7242. Thing* Game::getThing(const Position &pos,unsigned char stack, Player* player /*=NULL*/)
  7243. {
  7244.     if(pos.x == 0xFFFF) {
  7245.         if(!player)
  7246.             return NULL;
  7247.         if(pos.y & 0x40) { //from container
  7248.             unsigned char containerid = pos.y & 0x0F;
  7249.             Container* container = player->getContainer(containerid);
  7250.             if(!container)
  7251.                 return NULL;
  7252.  
  7253.             return container->getItem(pos.z);
  7254.         }
  7255.         else //from inventory
  7256.         {
  7257.             return player->getItem(pos.y);
  7258.         }
  7259.     }
  7260.     else //from ground
  7261.     {
  7262.         //Tile *t = getTile(pos.x, pos.y, pos.z);
  7263.         Tile *t = map->getTile(pos);
  7264.         if(!t)
  7265.             return NULL;
  7266.  
  7267.         return t->getThingByStackPos(stack);
  7268.     }
  7269. }
  7270. int32_t Game::getDepot(Container* c, int32_t e)
  7271. {
  7272. for(int32_t a = 0; a < c->size(); a++)
  7273. {
  7274. Container* x = dynamic_cast<Container*>(dynamic_cast<Item*>(c->getItem(a)));
  7275. Item* i = dynamic_cast<Item*>(c->getItem(a));
  7276. if(i)
  7277. e++;
  7278. if(x)
  7279. e = getDepot(x, e);
  7280. }
  7281. return e;
  7282. }
  7283.  
  7284.  
  7285. #ifdef WOLV_LOAD_NPC
  7286. bool Game::loadNpcs()
  7287. {
  7288.     xmlDocPtr doc;
  7289.     doc = xmlParseFile((g_config.DATA_DIR + "world/npc.xml").c_str());
  7290.     if (!doc)
  7291.         return false;
  7292.  
  7293.     xmlNodePtr root, npcNode;
  7294.     root = xmlDocGetRootElement(doc);
  7295.  
  7296.     if (xmlStrcmp(root->name, (const xmlChar*)"npclist"))
  7297.     {
  7298.         xmlFreeDoc(doc);
  7299.         return false;
  7300.     }
  7301.  
  7302.     npcNode = root->children;
  7303.     while (npcNode)
  7304.     {
  7305.         if (strcmp((const char*) npcNode->name, "npc") == 0)
  7306.         {
  7307.             std::string name = (const char*)xmlGetProp(npcNode, (const xmlChar *) "name");
  7308.             int32_t x = atoi((const char*) xmlGetProp(npcNode, (const xmlChar*) "x"));
  7309.             int32_t y = atoi((const char*) xmlGetProp(npcNode, (const xmlChar*) "y"));
  7310.             int32_t z = atoi((const char*) xmlGetProp(npcNode, (const xmlChar*) "z"));
  7311.    
  7312.             Npc* mynpc = new Npc(name, this);
  7313.             mynpc->pos = Position(x, y, z);
  7314.  
  7315.             if (!placeCreature(mynpc->pos, mynpc))
  7316.             {
  7317.                 std::cout << "Could not place " << name << "!" << std::endl;
  7318.                 xmlFreeDoc(doc);
  7319.                 return false;
  7320.             }
  7321.  
  7322.             const char* tmp = (const char*)xmlGetProp(npcNode, (const xmlChar*) "dir");
  7323.             if (tmp)
  7324.                 mynpc->setDirection((Direction)atoi(tmp));
  7325.         }  
  7326.         npcNode = npcNode->next;
  7327.     }
  7328.  
  7329.     xmlFreeDoc(doc);
  7330.     return true;
  7331. }
  7332. #endif //WOLV_LOAD_NPC
  7333.  
  7334. #ifdef TLM_SERVER_SAVE
  7335. void Game::serverSave()
  7336. {
  7337.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::serverSave()");
  7338.     std::cout << ":: zapis serwera :: " << std::endl;
  7339.     timer();
  7340.  
  7341.     AutoList<Player>::listiterator it = Player::listPlayer.list.begin();
  7342.     while (it != Player::listPlayer.list.end())
  7343.     {
  7344.         IOPlayer::instance()->savePlayer(it->second);
  7345.         ++it;
  7346.     }
  7347.     std::cout << ":: Gracze [" << timer() << " s]" << std::endl;
  7348.         Guilds::Save();
  7349.         std::cout << "Gildie [" << timer() << " s]" << std::endl;
  7350.     Houses::Save(this);
  7351.     std::cout << ":: Domki [" << timer() << " s]" << std::endl;
  7352.     loginQueue.save();
  7353.     std::cout << ":: Kolejki [" << timer() << " s]" << std::endl;
  7354.  
  7355.     for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it);
  7356. }
  7357.  
  7358. void Game::autoServerSave()
  7359. {
  7360.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::autoServerSave()");
  7361.     serverSave();
  7362.     addEvent(makeTask(g_config.getGlobalNumber("autosave", 1)*60000, std::mem_fun(&Game::autoServerSave)));
  7363. }
  7364. #endif //TLM_SERVER_SAVE
  7365.  
  7366.  
  7367. #ifdef ELEM_VIP_LIST
  7368. /*void Game::vipLogin(Player* player)
  7369. {
  7370.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::vipLogin()");
  7371.     std::string vipname = player->getName();
  7372.  
  7373. #ifdef _NG_BBK_VIP_SYSTEM__
  7374.     std::transform(vipname.begin(), vipname.end(), vipname.begin(), (int32_t(*)(int32_t)) std::tolower);
  7375. #endif //_NG_BBK_VIP_SYSTEM__
  7376.  
  7377.     for(AutoList<Creature>::listiterator cit = listCreature.list.begin(); cit != listCreature.list.end(); ++cit)
  7378.     {
  7379.         Player* player = dynamic_cast<Player*>((*cit).second);
  7380.         if (player)
  7381.             player->sendVipLogin(vipname);
  7382.     }
  7383. }
  7384.  
  7385. void Game::vipLogout(std::string vipname)
  7386. {
  7387.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::vipLogout()");
  7388.  
  7389. #ifdef _NG_BBK_VIP_SYSTEM__
  7390.     std::transform(vipname.begin(), vipname.end(), vipname.begin(), (int32_t(*)(int32_t)) std::tolower);
  7391. #endif //_NG_BBK_VIP_SYSTEM__
  7392.  
  7393.     for(AutoList<Creature>::listiterator cit = listCreature.list.begin(); cit != listCreature.list.end(); ++cit)
  7394.     {
  7395.         Player* player = dynamic_cast<Player*>((*cit).second);
  7396.         if (player)
  7397.             player->sendVipLogout(vipname);
  7398.     }
  7399. }*/
  7400.  
  7401. bool Game::isPlayer(std::string name)
  7402. {
  7403.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::isPlayer()");
  7404.     extern xmlMutexPtr xmlmutex;
  7405.  
  7406.     std::string datadir = g_config.getGlobalString("datadir");
  7407.     std::string filenamecheck = datadir + "players/" + name + ".xml";
  7408.     std::transform(filenamecheck.begin(),filenamecheck.end(), filenamecheck.begin(), (int32_t(*)(int32_t))tolower);
  7409.  
  7410.     xmlDocPtr doc;
  7411.     xmlMutexLock(xmlmutex);
  7412.     doc = xmlParseFile(filenamecheck.c_str());
  7413.  
  7414.     if (doc)
  7415.     {
  7416.         xmlMutexUnlock(xmlmutex);
  7417.         xmlFreeDoc(doc);
  7418.         return true;
  7419.     }
  7420.     else
  7421.     {
  7422.         xmlMutexUnlock(xmlmutex);
  7423.         xmlFreeDoc(doc);
  7424.         return false;
  7425.     }
  7426. }
  7427. #endif //ELEM_VIP_LIST
  7428.  
  7429. void Game::checkSpell(Player* player, SpeakClasses type, std::string text)
  7430. {
  7431.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkSpell()");
  7432.  
  7433.     if (player->isRookie())
  7434.         return;    
  7435.      
  7436. #ifdef TLM_HOUSE_SYSTEM
  7437.     else if (text == "aleta gom")       // edit owner
  7438.     {
  7439.         Tile* tile = getTile(player->pos);
  7440.         House* house = tile? tile->getHouse() : NULL;
  7441.  
  7442.         if (house && house->getPlayerRights(player->getName()) == HOUSE_OWNER)
  7443.         {
  7444.             player->sendHouseWindow(house, player->pos, HOUSE_OWNER);
  7445.         }
  7446.         else
  7447.         {
  7448.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7449.             player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7450.         }
  7451.     }
  7452.     else if (text == "aleta grav")      // edit door owners
  7453.     {
  7454.         bool last = false;
  7455.         for (int32_t x = player->pos.x-1; x <= player->pos.x+1 && !last; x++)
  7456.         {
  7457.             for(int32_t y = player->pos.y-1; y <= player->pos.y+1 && !last; y++)
  7458.             {
  7459.                 Position doorPos(x, y, player->pos.z);
  7460.                 Tile* tile = getTile(doorPos);
  7461.                 House* house = tile? tile->getHouse() : NULL;
  7462.  
  7463.                 if (house && house->getPlayerRights(doorPos, player->getName()) == HOUSE_OWNER)
  7464.                 {
  7465.                     Item *item = dynamic_cast<Item*>(tile->getThingByStackPos(tile->getThingCount()-1));
  7466.                     if (item && Item::items[item->getID()].isDoor)
  7467.                     {
  7468.                         player->sendHouseWindow(house, doorPos, HOUSE_DOOROWNER);
  7469.                         last = true;
  7470.                     }
  7471.                 }
  7472.             }
  7473.         }
  7474.     }
  7475. else if (text == "!buyhouse" || text == "!buyhome")
  7476.  {
  7477.   uint32_t money = player->getMoney();
  7478.   bool last = false;
  7479. #ifdef HUCZU_EXHAUSTED
  7480.   if(player->houseTicks > 0){
  7481.       player->sendCancel("You're exhausted.");
  7482.       return;
  7483.   }
  7484.   else
  7485.     player->houseTicks += 5;
  7486. #endif //HUCZU_EXHAUSTED
  7487.   int32_t houselevel = g_config.getGlobalNumber("houselevel", 0);
  7488.   if(!player->premmium){
  7489.         player->sendCancel("You must have a premium to buy house!");
  7490.         return;
  7491.   }
  7492.   if( player->getLevel() < houselevel ){
  7493.         std::stringstream textmsg2;
  7494.         textmsg2 << " You need level " << houselevel << "+ to buy a house! ";
  7495.         player->sendTextMessage(MSG_ADVANCE, textmsg2.str().c_str());
  7496. }
  7497.  else{
  7498.                    
  7499.   for (int32_t x = player->pos.x-1; x <= player->pos.x+1 && !last; x++)
  7500.   {
  7501.    for(int32_t y = player->pos.y-1; y <= player->pos.y+1 && !last; y++)
  7502.    {
  7503.     Position doorPos(x, y, player->pos.z);
  7504.     Tile* tile = getTile(doorPos);
  7505.     House* house = tile? tile->getHouse() : NULL;
  7506.     if(house){
  7507.      if(house->getPlayerRights(player->getName()) == HOUSE_OWNER){
  7508.               player->sendTextMessage(MSG_ADVANCE, "You own this house.");
  7509.               return;
  7510.      }
  7511.      if(house->isBought()){
  7512.               player->sendTextMessage(MSG_ADVANCE, "This house already has an owner.");
  7513.               return;
  7514.      }
  7515.      if(house->checkHouseCount(player) >= g_config.getGlobalNumber("maxhouses", 0)){
  7516.               std::stringstream textmsg;
  7517.               textmsg << " You cant have more than " << g_config.getGlobalNumber("maxhouses", 1) << " houses ";
  7518.               player->sendTextMessage(MSG_ADVANCE, textmsg.str().c_str());
  7519.               return;
  7520.      }
  7521.      if(house->getPlayerRights(doorPos, player->getName()) == HOUSE_NONE && !house->isBought() && house->checkHouseCount(player) < g_config.getGlobalNumber("maxhouses", 1))
  7522.      {
  7523.      Item *item = dynamic_cast<Item*>(tile->getThingByStackPos(tile->getThingCount()-1));
  7524.      long price = g_config.getGlobalNumber("priceforsqm", 0) * house->getHouseSQM(house->getName());
  7525.  
  7526.       if (item && Item::items[item->getID()].isDoor && price <= money)
  7527.       {
  7528.        player->substractMoney(price);
  7529.        house->setOwner(player->getName());
  7530.        house->save();
  7531.        player->sendTextMessage(MSG_ADVANCE, "You bought a house.");
  7532.        last = true;
  7533.       }
  7534.       else{
  7535.        player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7536.        player->sendTextMessage(MSG_SMALLINFO, "You dont have enough money to buy this house.");
  7537.       }
  7538.      }
  7539.    }
  7540.   }
  7541.  }
  7542. }
  7543. }
  7544.     else if (text == "aleta sio")       // edit guests
  7545.     {
  7546.         Tile* tile = getTile(player->pos);
  7547.         House* house = tile? tile->getHouse() : NULL;
  7548.  
  7549.         if (house && house->getPlayerRights(player->getName()) >= HOUSE_SUBOWNER)
  7550.         {
  7551.             player->sendHouseWindow(house, player->pos, HOUSE_GUEST);
  7552.         }
  7553.         else
  7554.         {
  7555.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7556.             player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7557.         }
  7558.     }
  7559.     else if (text == "aleta som")       // edit subowners
  7560.     {
  7561.         Tile* tile = getTile(player->pos);
  7562.         House* house = tile? tile->getHouse() : NULL;
  7563.  
  7564.         if (house && house->getPlayerRights(player->getName()) == HOUSE_OWNER)
  7565.         {
  7566.             player->sendHouseWindow(house, player->pos, HOUSE_SUBOWNER);
  7567.         }
  7568.         else
  7569.         {
  7570.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7571.             player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7572.         }
  7573.     }
  7574.     else if (text == "alana sio")   // kick me
  7575.     {
  7576.         Tile* tile = getTile(player->pos);
  7577.         House* house = tile? tile->getHouse() : NULL;
  7578.  
  7579.         if (house)
  7580.         {
  7581.             teleport(player, house->getFrontDoor());
  7582.             player->sendMagicEffect(player->pos, NM_ME_ENERGY_AREA);
  7583.         }
  7584.         else
  7585.         {
  7586.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7587.             player->sendTextMessage(MSG_SMALLINFO, "You are not in a house.");
  7588.         }
  7589.     }
  7590.     else if (text.substr(0, 11) == "alana sio \"")  // kick someone
  7591.     {
  7592.         Creature* c = getCreatureByName(text.substr(11).c_str());
  7593.         Player *target = c? dynamic_cast<Player*>(c) : NULL;
  7594.  
  7595.         if (target)
  7596.         {
  7597.             Tile* tile = getTile(player->pos);
  7598.             Tile* targetTile = getTile(target->pos);
  7599.             House* house = tile? tile->getHouse() : NULL;
  7600.             House* targetHouse = targetTile? targetTile->getHouse() : NULL;
  7601.  
  7602.             if (house && targetHouse && house == targetHouse &&
  7603.                 house->getPlayerRights(player->getName()) >= HOUSE_SUBOWNER)
  7604.             {
  7605.                 Position pos = house->getFrontDoor();
  7606.                 if (pos.x != 0xFFFF && pos.y != 0xFFFF && pos.z != 0xFF)
  7607.                 {
  7608.                     teleport(target, pos);
  7609.                     player->sendMagicEffect(target->pos, NM_ME_ENERGY_AREA);
  7610.                 }
  7611.                 else
  7612.                 {
  7613.                     player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7614.                     player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7615.                 }
  7616.             }
  7617.             else
  7618.                 player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7619.         }
  7620.         else
  7621.         {
  7622.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7623.             player->sendTextMessage(MSG_SMALLINFO, "This player does not exist.");
  7624.         }
  7625.     }
  7626. #endif //TLM_HOUSE_SYSTEM
  7627.  
  7628. #ifdef TR_SUMMONS
  7629.     else if (text.substr(0, 11) == "utevo res \"" &&
  7630.         (!g_config.LEARN_SPELLS || player->knowsSpell("utevo res")))
  7631.     {
  7632.         if (player->vocation == VOCATION_DRUID || player->vocation == VOCATION_SORCERER ||
  7633.             (g_config.SUMMONS_ALL_VOC && player->vocation != VOCATION_NONE))
  7634.         {
  7635.             std::string name = text.substr(11);
  7636.             int32_t reqMana = Summons::getRequiredMana(name);
  7637.             Tile* tile = getTile(player->pos);
  7638.  
  7639.             if (!tile)
  7640.             {
  7641.                 player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7642.                 player->sendCancel("Sorry, not possible.");
  7643.             }
  7644.             else if (reqMana < 0)
  7645.             {
  7646.                 player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7647.                 player->sendCancel("You cannot summon this creature.");
  7648.             }
  7649.             else if (tile->isPz())
  7650.             {
  7651.                 player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7652.                 player->sendCancel("You cannot summon creatures in protection zone.");
  7653.             }
  7654. #ifdef YUR_PVP_ARENA
  7655.             else if (tile->isPvpArena())
  7656.             {
  7657.                 player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7658.                 player->sendCancel("You cannot summon creatures on arena.");
  7659.             }
  7660. #endif //YUR_PVP_ARENA
  7661.             else if (player->getSummonCount() >= g_config.MAX_SUMMONS)
  7662.             {
  7663.                 player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7664.                 player->sendCancel("You cannot have more summons.");
  7665.             }
  7666.             else if (player->getMana() < reqMana)
  7667.             {
  7668.                 player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7669.                 player->sendCancel("Not enough mana.");
  7670.             }
  7671.             else if (!placeSummon(player, name))
  7672.             {
  7673.                 player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7674.                 player->sendCancel("Not enough room");
  7675.             }
  7676.             else
  7677.             {
  7678.                 player->mana -= reqMana;
  7679.                 player->addManaSpent(reqMana);
  7680.             }
  7681.         }
  7682.     }
  7683. #endif //TR_SUMMONS
  7684.  
  7685. /*
  7686. #ifdef HUCZU_FIX
  7687.       else if (text == "exevo flam sio" &&
  7688.         (!g_config.LEARN_SPELLS || player->knowsSpell("exevo flam sio")))
  7689.     {
  7690.         const int32_t REQ_MANA = 200;
  7691.    
  7692.         if (player->mana < REQ_MANA)
  7693.         {
  7694.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7695.             player->sendTextMessage(MSG_SMALLINFO, "Not enough mana.");
  7696.         }
  7697.        
  7698.         else if (player->maglevel < 15)
  7699.         {
  7700.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7701.             player->sendTextMessage(MSG_SMALLINFO, "You don't have the required magic level.");
  7702.         }
  7703.        
  7704.         else if (player->exhaustedTicks >= 1000 && player->access < g_config.ACCESS_PROTECT)
  7705.         {
  7706.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7707.             player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");  
  7708.         }
  7709.        
  7710.         else if (player->flamTicks != 0 && player->access < g_config.ACCESS_PROTECT)
  7711.         {
  7712.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7713.             player->sendTextMessage(MSG_SMALLINFO, "Not ready yet.");  
  7714.         }
  7715.  
  7716.         else
  7717.         {
  7718.             player->flamBool = true;
  7719.             player->exhaustedTicks = 2*1000;
  7720.             player->sendMagicEffect(player->pos, NM_ME_MAGIC_BLOOD);
  7721.           }
  7722.        }
  7723. #endif //HUCZU_FIX
  7724. */
  7725.  
  7726. else if (text.substr(0,7) == "exiva \"" &&
  7727. (!g_config.LEARN_SPELLS || player->knowsSpell("exiva")))
  7728. {
  7729. std::string name = text.substr(7);
  7730. Creature *c = getCreatureByName(name);
  7731. if (dynamic_cast<Player*>(c))
  7732. {
  7733. if(player->mana >= 20)
  7734. {
  7735. player->mana -= 20;
  7736. player->addManaSpent(20);
  7737. }
  7738. else if (player->exhaustedTicks >= 1000 && player->access < g_config.ACCESS_PROTECT)
  7739.         {
  7740.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7741.             player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");  
  7742.         }
  7743.      else
  7744. {
  7745. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7746. player->sendTextMessage(MSG_SMALLINFO, "Not enough mana.");
  7747. return;
  7748. }
  7749.  
  7750.  
  7751. int32_t x = c->pos.x - player->pos.x;
  7752. int32_t y = c->pos.y - player->pos.y;
  7753. int32_t z = c->pos.z - player->pos.z;
  7754. std::stringstream position;
  7755. position << name;
  7756.  
  7757. if(c->access < 3) {
  7758.          if((x > 96 && y > 48) || (x > 48 && y > 94) || (x > 74 && y > 74))
  7759.             position << " is very far to the south-east.";
  7760.          else if((x > 96 && y < -48) || (x > 48 && y < -96) || (x > 74 && y < -74))
  7761.             position << " is very far to the north-east.";
  7762.          else if((x < -96 && y > 48) || (x < -48 && y > 96) || (x < -74 && y > 74))
  7763.             position << " is very far to the south-west.";
  7764.          else if((x < -96 && y < -48) || (x < -48 && y < -96) || (x < -74 && y < -74))
  7765.             position << " is very far to the north-west.";
  7766.  
  7767.          else if((x > 48 && y > 24) || (x > 24 && y > 48) || (x > 36 && y > 36))
  7768.             position << " is far to the south-east.";
  7769.          else if((x > 48 && y < -24) || (x > 24 && y < -48) || (x > 36 && y < -36))
  7770.             position << " is far to the north-east.";
  7771.          else if((x < -48 && y > 24) || (x < -24 && y > 48) || (x < -36 && y > 36))
  7772.             position << " is far to the south-west.";
  7773.          else if((x < -48 && y < -24) || (x < -24 && y < -48) || (x < -36 && y < -36))
  7774.             position << " is far to the north-west.";
  7775.  
  7776.          else if((x > 6 && y > 12 && z > 0) || (x > 12 && y > 6 && z > 0) || (x > 9 && y > 9 && z > 0))
  7777.             position << " is on a lower lvl to the south-east.";
  7778.          else if((x > 6 && y < -12 && z > 0) || (x > 12 && y < -6 && z > 0) || (x > 9 && y < -9 && z > 0))
  7779.             position << " is on a lower lvl to the north-east.";
  7780.          else if((x < -6 && y > 12 && z > 0) || (x < -12 && y > 6 && z > 0) || (x < -9 && y > 9 && z > 0))
  7781.             position << " is on a lower lvl to the south-west.";
  7782.          else if((x < -6 && y < -12 && z > 0) || (x < -12 && y < -6 && z > 0) || (x < -9 && y < -9 && z > 0))
  7783.             position << " is on a lower lvl to the north-west.";
  7784.  
  7785.          else if((x > 6 && y > 12 && z < 0) || (x > 12 && y > 6 && z < 0) || (x > 9 && y > 9 && z < 0))
  7786.             position << " is on a higher lvl to the south-east.";
  7787.          else if((x > 6 && y < -12 && z < 0) || (x > 12 && y < -6 && z < 0) || (x > 9 && y < -9 && z < 0))
  7788.             position << " is on a higher lvl to the north-east.";
  7789.          else if((x < -6 && y > 12 && z < 0) || (x < -12 && y > 6 && z < 0) || (x < -9 && y > 9 && z < 0))
  7790.             position << " is on a higher lvl to the south-west.";
  7791.          else if((x < -6 && y < -12 && z < 0) || (x < -12 && y < -6 && z < 0) || (x < -9 && y < -9 && z < 0))
  7792.             position << " is on a higher lvl to the north-west.";
  7793.  
  7794.          else if((x > 6 && y > 12 && z == 0) || (x > 12 && y > 6 && z == 0) || (x > 9 && y > 9 && z == 0))
  7795.             position << " is to the south-east.";
  7796.          else if((x > 6 && y < -12 && z == 0) || (x > 12 && y < -6 && z == 0) || (x > 9 && y < -9 && z == 0))
  7797.             position << " is to the north-east.";
  7798.          else if((x < -6 && y > 12 && z == 0) || (x < -12 && y > 6 && z == 0) || (x < -9 && y > 9 && z == 0))
  7799.             position << " is to the south-west.";
  7800.          else if((x < -6 && y < -12 && z == 0) || (x < -12 && y < -6 && z == 0) || (x < -9 && y < -9 && z == 0))
  7801.             position << " is to the north-west.";
  7802.            
  7803.          else if(x > 74)
  7804.             position << " is very far to the east.";
  7805.          else if(x < -74)
  7806.             position << " is very far to the west.";
  7807.          else if(y > 74)
  7808.             position << " is very far to the south.";
  7809.          else if(y < -74)
  7810.             position << " is very far to the north.";
  7811.  
  7812.          else if(x > 36)
  7813.             position << " is far to the east.";
  7814.          else if(x < -36)
  7815.             position << " is far to the west.";
  7816.          else if(y > 36)
  7817.             position << " is far to the south.";
  7818.          else if(y < -36)
  7819.             position << " is far to the north.";
  7820.  
  7821.          else if(x > 3 && z < 0)
  7822.             position << " is on a higher lvl to the east.";
  7823.          else if(x < -3 && z < 0)
  7824.             position << " is on a higher lvl to the west.";
  7825.          else if(y > 3 && z < 0)
  7826.             position << " is on a higher lvl to the south.";
  7827.          else if(y < -3 && z < 0)
  7828.             position << " is on a higher lvl to the north.";
  7829.  
  7830.          else if(x > 3 && z > 0)
  7831.             position << " is on a lower lvl to the east.";
  7832.          else if(x < -3 && z > 0)
  7833.             position << " is on a lower lvl to the west.";
  7834.          else if(y > 3 && z > 0)
  7835.             position << " is on a lower lvl to the south.";
  7836.          else if(y < -3 && z > 0)
  7837.             position << " is on a lower lvl to the north.";
  7838.  
  7839.          else if(x > 3 && z == 0)
  7840.             position << " is to the east.";
  7841.          else if(x < -3 && z == 0)
  7842.             position << " is to the west.";
  7843.          else if(y > 3 && z == 0)
  7844.             position << " is to the south.";
  7845.          else if(y < -3 && z == 0)
  7846.             position << " is to the north.";
  7847.  
  7848.          else if(x < 4 && y < 4 && z > 0)
  7849.             position << " is below you.";
  7850.          else if(x < 4 && y < 4 && z < 0)
  7851.             position << " is above you.";
  7852.          else
  7853.             position << " is just beside you.";
  7854.  
  7855. player->sendTextMessage(MSG_INFO, position.str().c_str());
  7856. player->sendMagicEffect(player->pos, NM_ME_MAGIC_ENERGIE);
  7857. }else{
  7858. player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7859. player->sendTextMessage(MSG_SMALLINFO, "Srry, you cant exiva GM's");
  7860.     }
  7861. }else
  7862. player->sendTextMessage(MSG_SMALLINFO, "This player is not online.");
  7863. }
  7864.  
  7865.     else if (text == "exani tera" &&
  7866.         (!g_config.LEARN_SPELLS || player->knowsSpell("exani tera")))
  7867.     {
  7868.         const int32_t REQ_MANA = 20;
  7869.         Tile* tile = getTile(player->pos);
  7870.    
  7871.         if (!(tile && (tile->ground->getID() == ITEM_ROPE_SPOT1 || tile->ground->getID() == ITEM_ROPE_SPOT2)))
  7872.         {
  7873.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7874.             player->sendTextMessage(MSG_SMALLINFO, "Sorry, not possible.");
  7875.         }
  7876.         else if (player->mana < REQ_MANA)
  7877.         {
  7878.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7879.             player->sendTextMessage(MSG_SMALLINFO, "Not enough mana.");
  7880.         }
  7881.         else if (player->maglevel < 0)
  7882.         {
  7883.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7884.             player->sendTextMessage(MSG_SMALLINFO, "You don't have the required magic level.");
  7885.         }
  7886.         else if (player->exhaustedTicks >= 1000 && player->access < g_config.ACCESS_PROTECT)
  7887.         {
  7888.             player->sendMagicEffect(player->pos, NM_ME_PUFF);
  7889.             player->sendTextMessage(MSG_SMALLINFO, "You are exhausted.");  
  7890.         }
  7891.         else
  7892.         {
  7893.             teleport(player, Position(player->pos.x, player->pos.y+1, player->pos.z-1));
  7894.             player->sendMagicEffect(player->pos, NM_ME_ENERGY_AREA);
  7895.  
  7896.             if (player->access < g_config.ACCESS_PROTECT)
  7897.             {
  7898.                 player->mana -= REQ_MANA;
  7899.                 player->addManaSpent(REQ_MANA);
  7900.             }
  7901.         }
  7902.     }
  7903. }
  7904.    
  7905. #ifdef TR_SUMMONS
  7906. bool Game::placeSummon(Player* p, const std::string& name)
  7907. {
  7908.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::placeSummon()");
  7909.     Monster* monster = Monster::createMonster(name, this);
  7910.  
  7911.     if(!monster)
  7912.         return false;
  7913.  
  7914.     Position pos = p->pos;
  7915.     switch (p->direction)
  7916.     {
  7917.         case NORTH: pos.y--; break;
  7918.         case SOUTH: pos.y++; break;
  7919.         case EAST: pos.x++; break;
  7920.         case WEST: pos.x--; break;
  7921.     }
  7922.  
  7923.     Tile* tile = getTile(pos);
  7924. #ifdef YUR_PVP_ARENA
  7925.     if (!tile || tile->isPz() || tile->isPvpArena() || !placeCreature(pos, monster))
  7926. #else
  7927.     if (!tile || tile->isPz() || !placeCreature(pos, monster))
  7928. #endif //YUR_PVP_ARENA
  7929.     {
  7930.         delete monster;
  7931.         return false;
  7932.     }
  7933.     else
  7934.     {
  7935.         p->addSummon(monster);
  7936.         return true;
  7937.     }
  7938. }
  7939. #endif //TR_SUMMONS
  7940.  
  7941.  
  7942. #ifdef TRS_GM_INVISIBLE
  7943. void Game::creatureBroadcastTileUpdated(const Position& pos)
  7944. {
  7945.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureBroadcastTileUpdated()");
  7946.     SpectatorVec list;
  7947.     SpectatorVec::iterator it;
  7948.     getSpectators(Range(pos, true), list);
  7949.  
  7950.     //players
  7951.     for(it = list.begin(); it != list.end(); ++it) {
  7952.         if(dynamic_cast<Player*>(*it)) {
  7953.             (*it)->onTileUpdated(pos);
  7954.         }
  7955.     }
  7956.  
  7957.     //none-players
  7958.     for(it = list.begin(); it != list.end(); ++it) {
  7959.         if(!dynamic_cast<Player*>(*it)) {
  7960.             (*it)->onTileUpdated(pos);
  7961.         }
  7962.     }
  7963. }
  7964. #endif //TRS_GM_INVISIBLE
  7965.  
  7966.  
  7967. #ifdef HUCZU_SKULLS
  7968. void Game::Skull(Player* player)
  7969. {
  7970.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::Skull()");
  7971.     if (player)
  7972.     {
  7973.         SpectatorVec list;
  7974.         SpectatorVec::iterator it;
  7975.         getSpectators(Range(player->pos, true), list);
  7976.  
  7977.         for(it = list.begin(); it != list.end(); ++it)
  7978.         {
  7979.             Player* spectator = dynamic_cast<Player*>(*it);
  7980.             if(spectator)
  7981.                 if(player->skullType == SKULL_NONE ||
  7982.                         player->skullType == SKULL_WHITE ||
  7983.                         player->skullType == SKULL_RED ||
  7984.                         player->skullType == SKULL_YELLOW && player->isYellowTo(spectator))
  7985.                     spectator->onSkull(player);
  7986.         }
  7987.     }
  7988. }
  7989.  
  7990. void Game::onPvP(Creature* creature, Creature* attacked, bool murder)
  7991. {
  7992.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::onPvP()");
  7993.     if (creature && creature->getMaster())
  7994.         creature = creature->getMaster();   // pk-ing with summons fix
  7995.        
  7996.     Player* player = dynamic_cast<Player*>(creature);
  7997.     Player* attackedPlayer = dynamic_cast<Player*>(attacked);
  7998.  
  7999.     if (player == attackedPlayer)
  8000.         return;
  8001.     if(!player || !attackedPlayer)
  8002.         return;
  8003.     if (player && player->access >= g_config.ACCESS_PROTECT || attackedPlayer && attackedPlayer->access >= g_config.ACCESS_PROTECT)
  8004.         return;
  8005.     if (player->party != 0 && attackedPlayer->party != 0 && player->party == attackedPlayer->party)
  8006.         return;
  8007.        
  8008.     Tile *p1 = map->getTile(player->pos), *p2 = map->getTile(attackedPlayer->pos);
  8009.     if (p1->isPvpArena() && p2->isPvpArena()){
  8010.          player->pzLocked = false;
  8011.          attackedPlayer->pzLocked = false;
  8012.         return;
  8013.     }
  8014.  
  8015.  
  8016.     player->pzLocked = true;
  8017.  
  8018.     if (!murder)
  8019.     {
  8020.         if(!player->hasAttacked(attackedPlayer)){
  8021.         player->attackedPlayers.push_back(attackedPlayer);
  8022.         }
  8023.        
  8024.     if (attackedPlayer->skullType == SKULL_NONE || attackedPlayer->skullType == SKULL_YELLOW && !attackedPlayer->isYellowTo(player))
  8025.         {    
  8026.             if (player->skullType != SKULL_RED && player->skullType != SKULL_WHITE)
  8027.             {
  8028.                 player->skullType = SKULL_WHITE;
  8029.                 Skull(player);
  8030.             }  
  8031.         }
  8032.        
  8033.         else if(attackedPlayer->skullType == SKULL_WHITE || attackedPlayer->skullType == SKULL_RED)
  8034.         {
  8035.             if(player->skullType == SKULL_NONE && !player->isYellowTo(attackedPlayer))//si no tiene skull y no es yellow, tenemos que ponerle yellow.
  8036.             {
  8037.                     if(!attackedPlayer->hasAttacked(player))
  8038.                     {
  8039.                     player->skullType = SKULL_YELLOW;
  8040.                     attackedPlayer->hasAsYellow.push_back(player);
  8041.                     attackedPlayer->onSkull(player);
  8042.                  }
  8043.             }
  8044.         }
  8045.         if(player->inFightTicks < (int32_t)g_config.PZ_LOCKED)
  8046.             player->inFightTicks = (int32_t)g_config.PZ_LOCKED;
  8047.         if(player->skullTicks < (int32_t)g_config.PZ_LOCKED)
  8048.             player->skullTicks = (int32_t)g_config.PZ_LOCKED;
  8049.        
  8050.     }
  8051.     else    // murder
  8052.     {
  8053.         if (attackedPlayer->skullType == SKULL_NONE || (attackedPlayer->skullType == SKULL_YELLOW && !player->isYellowTo(attackedPlayer))) //Ofiara nie miala skulla oraz miala yellow ale nie na graczu ktora go zabil.
  8054.         {
  8055.             player->skullKills++;
  8056.             std::string justice(std::string("Warning! The murder of ") + attackedPlayer->getName() + " was not justified!");
  8057.             player->sendTextMessage(MSG_RED_INFO, justice.c_str());
  8058.              
  8059.                 if (player->skullKills >= g_config.BAN_UNJUST)
  8060.                 {
  8061.                     banPlayer(player, "Excessive unjustifed player killing", "AccountBan", "Zagan Square 2.3 2011 (Braviera)", false);
  8062.                 }
  8063.                
  8064.                 if (player->skullKills >= g_config.RED_UNJUST)
  8065.                 {
  8066.                     player->skullType = SKULL_RED;
  8067.                     if(player->skullTicks < g_config.RED_TIME)
  8068.                         player->skullTicks = g_config.RED_TIME;
  8069.                     if(player->inFightTicks < g_config.WHITE_TIME)
  8070.                         player->inFightTicks = g_config.WHITE_TIME;
  8071.                     Skull(player);
  8072.                 }
  8073.                 else
  8074.                 {
  8075.                     player->skullType = SKULL_WHITE;
  8076.                     if(player->skullTicks < g_config.WHITE_TIME)
  8077.                         player->skullTicks = g_config.WHITE_TIME;
  8078.                     if(player->inFightTicks < g_config.WHITE_TIME)
  8079.                         player->inFightTicks = g_config.WHITE_TIME;
  8080.                     Skull(player);
  8081.                 }
  8082.         }
  8083.            
  8084.             else if (attackedPlayer->skullType == SKULL_RED)//victim had red skull..(fair kill)
  8085.             {
  8086.                       if(player->inFightTicks < g_config.WHITE_TIME)
  8087.                       player->inFightTicks = g_config.WHITE_TIME;//not giving him a skull.. just setting the murder time.
  8088.             }
  8089.            
  8090.             else if (attackedPlayer->skullType == SKULL_WHITE) //victim had white skull.. (fair kill)
  8091.             {
  8092.                     attackedPlayer->skullType = SKULL_NONE;
  8093.                     attackedPlayer->skullTicks = 0;
  8094.                     Skull(attackedPlayer);
  8095.                     if(player->inFightTicks < g_config.WHITE_TIME)
  8096.                     player->inFightTicks = g_config.WHITE_TIME;//not giving him a skull.. just setting the murder time.
  8097.             }
  8098.            
  8099.            else if (attackedPlayer->skullType == SKULL_YELLOW /*&& attackedPlayer->isYellowTo(player)*/)//el que murio era yellow skull para el que lo mato.
  8100.            {
  8101.             attackedPlayer->skullType = SKULL_NONE;
  8102.             attackedPlayer->skullTicks = 0;
  8103.             attackedPlayer->inFightTicks = 0;
  8104.             Skull(attackedPlayer);
  8105.                 if(player->inFightTicks < g_config.WHITE_TIME)
  8106.                    player->inFightTicks = g_config.WHITE_TIME;
  8107.             }
  8108.         //attackedPlayer->clearAttacked();//czyszczenie listy zaatakowanych
  8109.         //player->removeFromYellowList(attackedPlayer);//usuwanie gracza z Yellow skull z listy atakowanych z ys
  8110.         //attackedPlayer->removeFromYellowList(player);
  8111.         }
  8112.     }
  8113.  
  8114. void Game::LeaveParty(Player *player)
  8115. {
  8116.     int32_t members = 0;
  8117.     std::stringstream bericht1;
  8118.     bericht1 << player->getName() << " has left the party";
  8119.     if(player->getID() == player->party)
  8120.     {
  8121.         disbandParty(player->party);
  8122.         return;
  8123.     }
  8124.     for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  8125.     {
  8126.         if((*it).second->party == player->party)
  8127.         {
  8128.             members++;
  8129.             if((*it).second->getID() != player->getID())
  8130.                 (*it).second->sendTextMessage(MSG_INFO, bericht1.str().c_str());
  8131.             (*it).second->onPartyIcons(player, 0, false, true);
  8132.             player->onPartyIcons((*it).second, 0, false, true);
  8133.         }
  8134.     }
  8135.     if(members <= 2)
  8136.     {
  8137.         disbandParty(player->party);
  8138.         return;
  8139.     }
  8140.     player->sendTextMessage(MSG_INFO, "You have left the party.");
  8141.     player->party = 0;
  8142. }
  8143.  
  8144. void Game::disbandParty(uint32_t partyID)
  8145. {
  8146.     for(AutoList<Player>::listiterator cit = Player::listPlayer.list.begin(); cit != Player::listPlayer.list.end(); ++cit)
  8147.     {
  8148.         if((*cit).second->party == partyID)
  8149.         {
  8150.             (*cit).second->party = 0;
  8151.             for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  8152.             {
  8153.                 (*cit).second->onPartyIcons((*it).second, 0, false, true);
  8154.                  if((*it).second->skullType == SKULL_NONE ||
  8155.                  (*it).second->skullType == SKULL_WHITE ||
  8156.                  (*it).second->skullType == SKULL_RED ||
  8157.                  (*it).second->skullType == SKULL_YELLOW &&
  8158.                  (*it).second->isYellowTo((*cit).second))
  8159.                 (*cit).second->onSkull((*it).second);
  8160.             }
  8161.             (*cit).second->sendTextMessage(MSG_INFO, "Your party has been disbanded.");
  8162.         }
  8163.     }
  8164. }
  8165. void Game::checkSkullTime(Player* player)
  8166. {
  8167.     if(player->skullType == SKULL_NONE)//just in case
  8168.     return;
  8169.    
  8170.     if(player->skullTicks < player->inFightTicks)
  8171.     player->skullTicks = player->inFightTicks;
  8172.    
  8173.     if(player->skullType != SKULL_RED && player->skullTicks > player->inFightTicks) //we don't want to do that if the player has a red skull...
  8174.     player->inFightTicks = player->skullTicks;
  8175.  
  8176. }    
  8177. #endif //HUCZU_SKULLS
  8178.  
  8179.  
  8180.  
  8181. #ifdef SD_BURST_ARROW
  8182. class MagicEffectAreaNoExhaustionClass: public MagicEffectAreaClass {
  8183. public:
  8184.     bool causeExhaustion(bool hasTarget) const { return false; }
  8185. };
  8186.  
  8187. void Game::burstArrow(Creature* c, const Position& pos)
  8188. {
  8189.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::burstArrow()");
  8190.     std::vector<unsigned char> col;
  8191.     MagicEffectAreaNoExhaustionClass runeAreaSpell;
  8192.    
  8193.     Player* player = dynamic_cast<Player*>(c);
  8194.  
  8195.     runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8196.     runeAreaSpell.animationEffect = NM_ANI_BURSTARROW;
  8197.     runeAreaSpell.hitEffect = NM_ME_EXPLOSION_DAMAGE;
  8198.     runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8199.     runeAreaSpell.animationColor = 198; //DAMAGE_FIRE;
  8200.     runeAreaSpell.drawblood = true;
  8201.     runeAreaSpell.offensive = true;
  8202.  
  8203.     /* Area of Spell */
  8204.     col.push_back(1);
  8205.     col.push_back(1);
  8206.     col.push_back(1);
  8207.     runeAreaSpell.areaVec.push_back(col);
  8208.     col.clear();
  8209.     col.push_back(1);
  8210.     col.push_back(1);
  8211.     col.push_back(1);
  8212.     runeAreaSpell.areaVec.push_back(col);
  8213.     col.clear();
  8214.     col.push_back(1);
  8215.     col.push_back(1);
  8216.     col.push_back(1);
  8217.     runeAreaSpell.areaVec.push_back(col);
  8218.  
  8219.     /* hard no ? */
  8220.     runeAreaSpell.direction = 1;
  8221.    
  8222.     if (player->vocation == VOCATION_KNIGHT) {
  8223.     runeAreaSpell.minDamage = int32_t(((c->level*g_config.KNIGHT_BURST_DMG_LVL)+(c->maglevel*g_config.KNIGHT_BURST_DMG_MLVL))*g_config.KNIGHT_BURST_DMG_LO);
  8224.     runeAreaSpell.maxDamage = int32_t(((c->level*g_config.KNIGHT_BURST_DMG_LVL)+(c->maglevel*g_config.KNIGHT_BURST_DMG_MLVL))*g_config.KNIGHT_BURST_DMG_HI);
  8225.     }
  8226.    
  8227.     if (player->vocation == VOCATION_PALADIN) {
  8228.     runeAreaSpell.minDamage = int32_t(((c->level*g_config.PALADIN_BURST_DMG_LVL)+(c->maglevel*g_config.PALADIN_BURST_DMG_MLVL))*g_config.PALADIN_BURST_DMG_LO);
  8229.     runeAreaSpell.maxDamage = int32_t(((c->level*g_config.PALADIN_BURST_DMG_LVL)+(c->maglevel*g_config.PALADIN_BURST_DMG_MLVL))*g_config.PALADIN_BURST_DMG_HI);
  8230.     }
  8231.    
  8232.     if (player->vocation == VOCATION_DRUID) {
  8233.     runeAreaSpell.minDamage = int32_t(((c->level*g_config.DRUID_BURST_DMG_LVL)+(c->maglevel*g_config.DRUID_BURST_DMG_MLVL))*g_config.DRUID_BURST_DMG_LO);
  8234.     runeAreaSpell.maxDamage = int32_t(((c->level*g_config.DRUID_BURST_DMG_LVL)+(c->maglevel*g_config.DRUID_BURST_DMG_MLVL))*g_config.DRUID_BURST_DMG_HI);
  8235.     }
  8236.    
  8237.     if (player->vocation == VOCATION_SORCERER) {
  8238.     runeAreaSpell.minDamage = int32_t(((c->level*g_config.SORCERER_BURST_DMG_LVL)+(c->maglevel*g_config.SORCERER_BURST_DMG_MLVL))*g_config.SORCERER_BURST_DMG_LO);
  8239.     runeAreaSpell.maxDamage = int32_t(((c->level*g_config.SORCERER_BURST_DMG_LVL)+(c->maglevel*g_config.SORCERER_BURST_DMG_MLVL))*g_config.SORCERER_BURST_DMG_HI);
  8240.     }
  8241.    
  8242.     creatureThrowRune(c, pos, runeAreaSpell);
  8243. }
  8244. #endif //SD_BURST_ARROW
  8245.  
  8246.  
  8247. #ifdef YUR_SHUTDOWN
  8248. void Game::sheduleShutdown(int32_t minutes)
  8249. {
  8250.     if (minutes > 0)
  8251.         checkShutdown(minutes);
  8252. }
  8253.  
  8254. void Game::checkShutdown(int32_t minutes)
  8255. {
  8256.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkShutdown()");
  8257.     if (minutes == 0)
  8258.     {
  8259.         setGameState(GAME_STATE_CLOSED);
  8260.         while (!Player::listPlayer.list.empty())
  8261.             Player::listPlayer.list.begin()->second->kickPlayer();
  8262.  
  8263.         serverSave();
  8264.         std::cout << "==| shutdown..." << std::endl;
  8265.         //setGameState(GAME_STATE_SHUTDOWN);
  8266.         OTSYS_SLEEP(1000);
  8267.         exit(1);
  8268.     }
  8269.     else
  8270.     {
  8271.         std::stringstream msg;
  8272.         msg << "Server going to shutdown in " << minutes << (minutes>1? " minutes. \n Please logout." : " minute. \n Please logout.") << std::ends;
  8273.  
  8274.         AutoList<Player>::listiterator it = Player::listPlayer.list.begin();
  8275.         while (it != Player::listPlayer.list.end())
  8276.         {
  8277.             (*it).second->sendTextMessage(MSG_RED_INFO, msg.str().c_str());
  8278.             ++it;
  8279.         }
  8280.  
  8281.         addEvent(makeTask(60000, boost::bind(&Game::checkShutdown, this, minutes - 1)));
  8282.     }
  8283. }
  8284. #endif //YUR_SHUTDOWN
  8285.  
  8286.  
  8287. #ifdef YUR_CMD_EXT
  8288. void Game::setMaxPlayers(uint32_t newmax)
  8289. {
  8290.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::setMaxPlayers()");
  8291.     max_players = newmax;
  8292.     Status::instance()->playersmax = newmax;
  8293. }
  8294. #endif //YUR_CMD_EXT
  8295.  
  8296. long Game::cleanMap()
  8297. {
  8298. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::cleanMap()");
  8299. return map->clean();
  8300. }
  8301.  
  8302. long Game::beforeClean()
  8303. {
  8304. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it) {
  8305. it->second->sendTextMessage(MSG_RED_INFO, "1 minute to clean. Get your things from floor now!");
  8306. }
  8307. addEvent(makeTask(60000, std::mem_fun(&Game::secondsToClean)));
  8308. }
  8309. long Game::beforeCleanTrzy()
  8310. {
  8311. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it) {
  8312. it->second->sendTextMessage(MSG_RED_INFO, "Warning! Clean in 3 minutes.");
  8313. }
  8314. addEvent(makeTask(60000, std::mem_fun(&Game::beforeCleanDwa)));
  8315. }
  8316. long Game::beforeCleanDwa()
  8317. {
  8318. for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it) {
  8319. it->second->sendTextMessage(MSG_RED_INFO, "Warning! Clean in 2 minutes.");
  8320. }
  8321. addEvent(makeTask(60000, std::mem_fun(&Game::beforeClean)));
  8322. }
  8323. void Game::secondsToClean()
  8324. {
  8325.    autocleanMap(5);
  8326. }
  8327. void Game::autocleanMap(int32_t seconds)
  8328. {
  8329.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::autocleanMap()");
  8330.     if (seconds == 0)
  8331.     {
  8332.        std::cout << ":: auto clean... ";
  8333.        timer();
  8334.        long count = cleanMap();
  8335.        double sec = timer();
  8336.  
  8337.        std::stringstream msg;
  8338.        msg << "Clean completed. Collected " << count << (count==1? " item." : " items.") << std::ends;
  8339.        for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  8340.        if(dynamic_cast<Player*>(it->second))
  8341.        (*it).second->sendTextMessage(MSG_RED_INFO, msg.str().c_str());
  8342.        }
  8343.  
  8344.        std::cout << "ok (" << timer() << "s)" << std::endl;
  8345.        addEvent(makeTask((g_config.getGlobalNumber("autoclean", 2))*60000, std::mem_fun(&Game::beforeCleanTrzy)));
  8346.     }
  8347.     else
  8348.     {
  8349.         std::stringstream msg;
  8350.         msg << "Clean in " << seconds << std::ends;
  8351.  
  8352.         AutoList<Player>::listiterator it = Player::listPlayer.list.begin();
  8353.         while (it != Player::listPlayer.list.end())
  8354.         {
  8355.             (*it).second->sendTextMessage(MSG_RED_INFO, msg.str().c_str());
  8356.             ++it;
  8357.         }
  8358.  
  8359.         addEvent(makeTask(8000, boost::bind(&Game::autocleanMap, this, seconds - 1)));
  8360.     }
  8361. }
  8362.  
  8363.  
  8364. #ifdef CVS_DAY_CYCLE
  8365. void Game::creatureChangeLight(Player* player, int32_t time, unsigned char lightlevel, unsigned char lightcolor)
  8366. {
  8367.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureChangeLight()");
  8368.  
  8369.     player->setLightLevel(lightlevel, lightcolor);
  8370.     SpectatorVec list;
  8371.     getSpectators(Range(player->pos), list);
  8372.  
  8373.     for (SpectatorVec::iterator iter = list.begin(); iter != list.end(); ++iter)
  8374.     {
  8375.         Player* spectator = dynamic_cast<Player*>(*iter);
  8376.         if (spectator)
  8377.              spectator->sendPlayerLightLevel(player);
  8378.     }
  8379. }
  8380.  
  8381. void Game::checkLight(int32_t t)
  8382. {
  8383.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkLight()");
  8384.     addEvent(makeTask(10000, boost::bind(&Game::checkLight, this, 10000)));
  8385.    
  8386.     light_hour = light_hour + light_hour_delta;
  8387.     if(light_hour > 1440)
  8388.         light_hour = light_hour - 1440;
  8389.    
  8390.     if(std::abs(light_hour - SUNRISE) < 2*light_hour_delta){
  8391.         light_state = LIGHT_STATE_SUNRISE;
  8392.     }
  8393.     else if(std::abs(light_hour - SUNSET) < 2*light_hour_delta){
  8394.         light_state = LIGHT_STATE_SUNSET;
  8395.     }
  8396.    
  8397.     int32_t newlightlevel = lightlevel;
  8398.     switch(light_state){
  8399.     case LIGHT_STATE_SUNRISE:
  8400.         newlightlevel += (LIGHT_LEVEL_DAY - LIGHT_LEVEL_NIGHT)/30;
  8401.         break;
  8402.     case LIGHT_STATE_SUNSET:
  8403.         newlightlevel -= (LIGHT_LEVEL_DAY - LIGHT_LEVEL_NIGHT)/30;
  8404.         break;
  8405.     }
  8406.    
  8407.     if(newlightlevel <= LIGHT_LEVEL_NIGHT){
  8408.         lightlevel = LIGHT_LEVEL_NIGHT;
  8409.         light_state = LIGHT_STATE_NIGHT;
  8410.     }
  8411.     else if(newlightlevel >= LIGHT_LEVEL_DAY){
  8412.         lightlevel = LIGHT_LEVEL_DAY;
  8413.         light_state = LIGHT_STATE_DAY;
  8414.     }
  8415.     else{
  8416.         lightlevel = newlightlevel;
  8417.     }
  8418.  
  8419.  
  8420.     // status, ten kod i tak jest brzydki
  8421.     uint64_t time = OTSYS_TIME();
  8422.     ofstream file;
  8423.     file.open ("status");
  8424.     file << time << " " << (time - Status::instance()->start)/1000 <<  " " << Status::instance()->playersonline << " " << Status::instance()->playersmax;
  8425.     file.close();
  8426.  
  8427.     file.open("online");
  8428.     for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it){
  8429.             std::string txt = (*it).second->getName();
  8430.         file << (*it).second->getName() << ";" << (*it).second->getLevel() << "\n";
  8431.     }
  8432.     file.close();
  8433.  
  8434.    
  8435. }
  8436.  
  8437. unsigned char Game::getLightLevel(){
  8438.     return lightlevel;
  8439. }
  8440. #endif //CVS_DAY_CYCLE
  8441.  
  8442.  
  8443. #ifdef WANDS_JIDDO
  8444. void Game::useWand(Creature *creature, Creature *attackedCreature, int32_t wandid) {
  8445.    
  8446.    Player *player = dynamic_cast<Player*>(creature);
  8447.    if(!player) return;
  8448.    
  8449.      if((wandid == 5318 && (player->vocation == VOCATION_DRUID) && player->mana >= 10 && player->getLevel() >= 65)) { //Quagmire rod
  8450.       int32_t dist = 6;
  8451.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8452.       std::vector<unsigned char> col;
  8453.       MagicEffectAreaClass runeAreaSpell;
  8454.       runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8455.       runeAreaSpell.animationEffect = NM_ANI_SNOWBALL;
  8456.       runeAreaSpell.hitEffect = NM_ME_LOOSE_ENERGY;
  8457.       runeAreaSpell.areaEffect = NM_ME_DRAW_BLOOD;
  8458.       runeAreaSpell.animationColor = 0x47;
  8459.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8460.       col.push_back(0);
  8461.       col.push_back(0);
  8462.       col.push_back(0);
  8463.       runeAreaSpell.areaVec.push_back(col);
  8464.       col.clear();
  8465.       col.push_back(0);
  8466.       col.push_back(1);
  8467.       col.push_back(0);
  8468.       runeAreaSpell.areaVec.push_back(col);
  8469.       col.clear();
  8470.       col.push_back(0);
  8471.       col.push_back(0);
  8472.       col.push_back(0);
  8473.       runeAreaSpell.areaVec.push_back(col);
  8474.       col.clear();
  8475.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 70;   runeAreaSpell.maxDamage = 150;
  8476.       long tempExhaust = player->exhaustedTicks;
  8477. player->exhaustedTicks = 0;
  8478. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8479. player->exhaustedTicks = tempExhaust;
  8480.       int32_t mana = 10;
  8481.       player->addManaSpent(mana);
  8482.       player->mana -= mana;
  8483.       return;
  8484.    }
  8485.    
  8486.    
  8487.    if((wandid == 5319 && (player->vocation == VOCATION_SORCERER) && player->mana >= 10 && player->getLevel() >= 65)) { //Wand of cosmic energy
  8488.       int32_t dist = 6;
  8489.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8490.       std::vector<unsigned char> col;
  8491.       MagicEffectAreaClass runeAreaSpell;
  8492.       runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8493.       runeAreaSpell.animationEffect = NM_ANI_LARGEROCK;
  8494.       runeAreaSpell.hitEffect = NM_ME_SOUND_WHITE;
  8495.       runeAreaSpell.areaEffect = NM_ME_SOUND_WHITE;
  8496.       runeAreaSpell.animationColor = 0xAC;
  8497.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8498.       col.push_back(0);
  8499.       col.push_back(0);
  8500.       col.push_back(0);
  8501.       runeAreaSpell.areaVec.push_back(col);
  8502.       col.clear();
  8503.       col.push_back(0);
  8504.       col.push_back(1);
  8505.       col.push_back(0);
  8506.       runeAreaSpell.areaVec.push_back(col);
  8507.       col.clear();
  8508.       col.push_back(0);
  8509.       col.push_back(0);
  8510.       col.push_back(0);
  8511.       runeAreaSpell.areaVec.push_back(col);
  8512.       col.clear();
  8513.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 70;   runeAreaSpell.maxDamage = 150;
  8514.             long tempExhaust = player->exhaustedTicks;
  8515. player->exhaustedTicks = 0;
  8516. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8517. player->exhaustedTicks = tempExhaust;
  8518.       int32_t mana = 10;
  8519.       player->addManaSpent(mana);
  8520.       player->mana -= mana;
  8521.       return;
  8522.    }
  8523.    
  8524.    //SCEPTRE OF THE LOST SOULS
  8525.    if((wandid == 5326 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_DRUID) && player->mana >= 50 && player->getLevel() >= 300)) {
  8526.       int32_t dist = 4;
  8527.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8528.       std::vector<unsigned char> col;
  8529.       MagicEffectAreaClass runeAreaSpell;
  8530. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8531. runeAreaSpell.animationEffect = NM_ANI_ENERGY2;
  8532.       runeAreaSpell.hitEffect = NM_ME_ENERGY_AREA;
  8533.       runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8534.       runeAreaSpell.animationColor = 0x65;
  8535.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8536.       col.push_back(0);
  8537.       col.push_back(0);
  8538.       col.push_back(0);
  8539.       runeAreaSpell.areaVec.push_back(col);
  8540.       col.clear();
  8541.       col.push_back(0);
  8542.       col.push_back(1);
  8543.       col.push_back(0);
  8544.       runeAreaSpell.areaVec.push_back(col);
  8545.       col.clear();
  8546.       col.push_back(0);
  8547.       col.push_back(0);
  8548.       col.push_back(0);
  8549.       runeAreaSpell.areaVec.push_back(col);
  8550.       col.clear();
  8551.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 350;   runeAreaSpell.maxDamage = 450;
  8552.       long tempExhaust = player->exhaustedTicks;
  8553. player->exhaustedTicks = 0;
  8554. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8555. player->exhaustedTicks = tempExhaust;
  8556.       int32_t mana = 50;
  8557.       player->addManaSpent(mana);
  8558.       player->mana -= mana;
  8559.       return;
  8560.    }
  8561.    
  8562.       //NATURE WAND
  8563.       if((wandid == 2544 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_DRUID) && player->mana >= 35 && player->getLevel() >= 200)) {
  8564.       int32_t dist = 5;
  8565.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8566.       std::vector<unsigned char> col;
  8567.       MagicEffectAreaClass runeAreaSpell;
  8568. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8569. runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8570.       runeAreaSpell.hitEffect = 20;
  8571.       runeAreaSpell.areaEffect = 20;
  8572.       runeAreaSpell.animationColor = 0x60;
  8573.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8574.       col.push_back(0);
  8575.       col.push_back(0);
  8576.       col.push_back(0);
  8577.       runeAreaSpell.areaVec.push_back(col);
  8578.       col.clear();
  8579.       col.push_back(0);
  8580.       col.push_back(1);
  8581.       col.push_back(0);
  8582.       runeAreaSpell.areaVec.push_back(col);
  8583.       col.clear();
  8584.       col.push_back(0);
  8585.       col.push_back(0);
  8586.       col.push_back(0);
  8587.       runeAreaSpell.areaVec.push_back(col);
  8588.       col.clear();
  8589.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 200;   runeAreaSpell.maxDamage = 350;
  8590.       long tempExhaust = player->exhaustedTicks;
  8591. player->exhaustedTicks = 0;
  8592. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8593. player->exhaustedTicks = tempExhaust;
  8594.       int32_t mana = 35;
  8595.       player->addManaSpent(mana);
  8596.       player->mana -= mana;
  8597.       return;
  8598.    }
  8599.    
  8600.    //SPRITE WAND
  8601.    if((wandid == 2453 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_DRUID) && player->mana >= 25 && player->getLevel() >= 150)) {
  8602.       int32_t dist = 5;
  8603.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8604.       std::vector<unsigned char> col;
  8605.       MagicEffectAreaClass runeAreaSpell;
  8606. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  8607. runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8608. runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8609. runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8610. runeAreaSpell.animationColor = 0x11;
  8611.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8612.       col.push_back(0);
  8613.       col.push_back(0);
  8614.       col.push_back(0);
  8615.       runeAreaSpell.areaVec.push_back(col);
  8616.       col.clear();
  8617.       col.push_back(0);
  8618.       col.push_back(1);
  8619.       col.push_back(0);
  8620.       runeAreaSpell.areaVec.push_back(col);
  8621.       col.clear();
  8622.       col.push_back(0);
  8623.       col.push_back(0);
  8624.       col.push_back(0);
  8625.       runeAreaSpell.areaVec.push_back(col);
  8626.       col.clear();
  8627.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 150;   runeAreaSpell.maxDamage = 250;
  8628.       long tempExhaust = player->exhaustedTicks;
  8629. player->exhaustedTicks = 0;
  8630. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8631. player->exhaustedTicks = tempExhaust;
  8632.       int32_t mana = 25;
  8633.       player->addManaSpent(mana);
  8634.       player->mana -= mana;
  8635.       return;
  8636.    }
  8637.    
  8638.    
  8639.    if((wandid == 2181 && (player->vocation == VOCATION_DRUID) && player->mana >= 8 && player->getLevel() >= 26)) { //Quagmire rod
  8640.       int32_t dist = 2;
  8641.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8642.       std::vector<unsigned char> col;
  8643.       MagicEffectAreaClass runeAreaSpell;
  8644.       runeAreaSpell.attackType = ATTACK_POISON;
  8645.       runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8646.       runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  8647.       runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  8648.       runeAreaSpell.animationColor = 0x60;
  8649.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8650.       col.push_back(0);
  8651.       col.push_back(0);
  8652.       col.push_back(0);
  8653.       runeAreaSpell.areaVec.push_back(col);
  8654.       col.clear();
  8655.       col.push_back(0);
  8656.       col.push_back(1);
  8657.       col.push_back(0);
  8658.       runeAreaSpell.areaVec.push_back(col);
  8659.       col.clear();
  8660.       col.push_back(0);
  8661.       col.push_back(0);
  8662.       col.push_back(0);
  8663.       runeAreaSpell.areaVec.push_back(col);
  8664.       col.clear();
  8665.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 40;   runeAreaSpell.maxDamage = 50;
  8666.       long tempExhaust = player->exhaustedTicks;
  8667. player->exhaustedTicks = 0;
  8668. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8669. player->exhaustedTicks = tempExhaust;
  8670.       int32_t mana = 8;
  8671.       player->addManaSpent(mana);
  8672.       player->mana -= mana;
  8673.       return;
  8674.    }
  8675.      
  8676.      if((wandid == 2182 && (player->vocation == VOCATION_DRUID) && player->mana >= 2 && player->getLevel() >= 7)) { //Snakebite rod
  8677.       int32_t dist = 4;
  8678.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8679.       std::vector<unsigned char> col;
  8680.       MagicEffectAreaClass runeAreaSpell;
  8681.       runeAreaSpell.attackType = ATTACK_POISON;
  8682.       runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8683.       runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  8684.       runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  8685.       runeAreaSpell.animationColor = 0x60;
  8686.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8687.       col.push_back(0);
  8688.       col.push_back(0);
  8689.       col.push_back(0);
  8690.       runeAreaSpell.areaVec.push_back(col);
  8691.       col.clear();
  8692.       col.push_back(0);
  8693.       col.push_back(1);
  8694.       col.push_back(0);
  8695.       runeAreaSpell.areaVec.push_back(col);
  8696.       col.clear();
  8697.       col.push_back(0);
  8698.       col.push_back(0);
  8699.       col.push_back(0);
  8700.       runeAreaSpell.areaVec.push_back(col);
  8701.       col.clear();
  8702.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 8;   runeAreaSpell.maxDamage = 18;
  8703.             long tempExhaust = player->exhaustedTicks;
  8704. player->exhaustedTicks = 0;
  8705. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8706. player->exhaustedTicks = tempExhaust;
  8707.       int32_t mana = 2;
  8708.       player->addManaSpent(mana);
  8709.       player->mana -= mana;
  8710.       return;
  8711.    }
  8712.  
  8713.    
  8714.    
  8715.    if((wandid == 2183 && (player->vocation == VOCATION_DRUID) && player->mana >= 13 && player->getLevel() >= 33)) { //Tempest rod
  8716.       int32_t dist = 2;
  8717.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8718.       std::vector<unsigned char> col;
  8719.       MagicEffectAreaClass runeAreaSpell;
  8720.       runeAreaSpell.attackType = ATTACK_ENERGY;
  8721.       runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8722.       runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8723.       runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8724.       runeAreaSpell.animationColor = 0x11;
  8725.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8726.       col.push_back(0);
  8727.       col.push_back(0);
  8728.       col.push_back(0);
  8729.       runeAreaSpell.areaVec.push_back(col);
  8730.       col.clear();
  8731.       col.push_back(0);
  8732.       col.push_back(1);
  8733.       col.push_back(0);
  8734.       runeAreaSpell.areaVec.push_back(col);
  8735.       col.clear();
  8736.       col.push_back(0);
  8737.       col.push_back(0);
  8738.       col.push_back(0);
  8739.       runeAreaSpell.areaVec.push_back(col);
  8740.       col.clear();
  8741.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 60;   runeAreaSpell.maxDamage = 70;
  8742.       long tempExhaust = player->exhaustedTicks;
  8743. player->exhaustedTicks = 0;
  8744. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8745. player->exhaustedTicks = tempExhaust;
  8746.       int32_t mana = 13;
  8747.       player->addManaSpent(mana);
  8748.       player->mana -= mana;
  8749.       return;
  8750.    }
  8751.    
  8752.    
  8753.    if((wandid == 2185 && (player->vocation == VOCATION_DRUID) && player->mana >= 5 && player->getLevel() >= 19)) { //Volcanic rod
  8754.       int32_t dist = 2;
  8755.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8756.       std::vector<unsigned char> col;
  8757.       MagicEffectAreaClass runeAreaSpell;
  8758.       runeAreaSpell.attackType = ATTACK_FIRE;
  8759.       runeAreaSpell.animationEffect = NM_ANI_FIRE;
  8760.       runeAreaSpell.hitEffect = NM_ME_FIRE_AREA;
  8761.       runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8762.       runeAreaSpell.animationColor = 0xC7;
  8763.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8764.       col.push_back(0);
  8765.       col.push_back(0);
  8766.       col.push_back(0);
  8767.       runeAreaSpell.areaVec.push_back(col);
  8768.       col.clear();
  8769.       col.push_back(0);
  8770.       col.push_back(1);
  8771.       col.push_back(0);
  8772.       runeAreaSpell.areaVec.push_back(col);
  8773.       col.clear();
  8774.       col.push_back(0);
  8775.       col.push_back(0);
  8776.       col.push_back(0);
  8777.       runeAreaSpell.areaVec.push_back(col);
  8778.       col.clear();
  8779.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 25;   runeAreaSpell.maxDamage = 35;
  8780.       long tempExhaust = player->exhaustedTicks;
  8781. player->exhaustedTicks = 0;
  8782. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8783. player->exhaustedTicks = tempExhaust;
  8784.       int32_t mana = 5;
  8785.       player->addManaSpent(mana);
  8786.       player->mana -= mana;
  8787.       return;
  8788.    }
  8789.    
  8790.    
  8791.    if((wandid == 2186 && (player->vocation == VOCATION_DRUID) && player->mana >= 3 && player->getLevel() >= 13)) { //Moonlight rod
  8792.       int32_t dist = 3;
  8793.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8794.       std::vector<unsigned char> col;
  8795.       MagicEffectAreaClass runeAreaSpell;
  8796.       runeAreaSpell.attackType = ATTACK_ENERGY;
  8797.       runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8798.       runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8799.       runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8800.       runeAreaSpell.animationColor = 0x47;
  8801.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8802.       col.push_back(0);
  8803.       col.push_back(0);
  8804.       col.push_back(0);
  8805.       runeAreaSpell.areaVec.push_back(col);
  8806.       col.clear();
  8807.       col.push_back(0);
  8808.       col.push_back(1);
  8809.       col.push_back(0);
  8810.       runeAreaSpell.areaVec.push_back(col);
  8811.       col.clear();
  8812.       col.push_back(0);
  8813.       col.push_back(0);
  8814.       col.push_back(0);
  8815.       runeAreaSpell.areaVec.push_back(col);
  8816.       col.clear();
  8817.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 14;   runeAreaSpell.maxDamage = 24;
  8818.       long tempExhaust = player->exhaustedTicks;
  8819. player->exhaustedTicks = 0;
  8820. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8821. player->exhaustedTicks = tempExhaust;
  8822.       int32_t mana = 3;
  8823.       player->addManaSpent(mana);
  8824.       player->mana -= mana;
  8825.       return;
  8826.    }
  8827.    
  8828.    
  8829.    if((wandid == 2187 && (player->vocation == VOCATION_SORCERER) && player->mana >= 13 && player->getLevel() >= 33)) { //Wand of inferno
  8830.       int32_t dist = 2;
  8831.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8832.       std::vector<unsigned char> col;
  8833.       MagicEffectAreaClass runeAreaSpell;
  8834.       runeAreaSpell.attackType = ATTACK_FIRE;
  8835.       runeAreaSpell.animationEffect = NM_ANI_FIRE;
  8836.       runeAreaSpell.hitEffect = NM_ME_FIRE_AREA;
  8837.       runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8838.       runeAreaSpell.animationColor = 0xC7;
  8839.       runeAreaSpell.drawblood = true;
  8840.       runeAreaSpell.offensive = true;
  8841.       col.push_back(0);
  8842.       col.push_back(0);
  8843.       col.push_back(0);
  8844.       runeAreaSpell.areaVec.push_back(col);
  8845.       col.clear();
  8846.       col.push_back(0);
  8847.       col.push_back(1);
  8848.       col.push_back(0);
  8849.       runeAreaSpell.areaVec.push_back(col);
  8850.       col.clear();
  8851.       col.push_back(0);
  8852.       col.push_back(0);
  8853.       col.push_back(0);
  8854.       runeAreaSpell.areaVec.push_back(col);
  8855.       col.clear();
  8856.       runeAreaSpell.direction = 1;
  8857.       runeAreaSpell.minDamage = 60;
  8858.       runeAreaSpell.maxDamage = 70;
  8859.       long tempExhaust = player->exhaustedTicks;
  8860. player->exhaustedTicks = 0;
  8861. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8862. player->exhaustedTicks = tempExhaust;
  8863.       int32_t mana = 13;
  8864.       player->addManaSpent(mana);
  8865.       player->mana -= mana;
  8866.      
  8867.       return;
  8868.    }
  8869.    
  8870.    
  8871.    if((wandid == 2188 && (player->vocation == VOCATION_SORCERER) && player->mana >= 5 && player->getLevel() >= 19)) { //Wand of plague
  8872.       int32_t dist = 2;
  8873.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8874.       std::vector<unsigned char> col;
  8875.       MagicEffectAreaClass runeAreaSpell;
  8876.       runeAreaSpell.attackType = ATTACK_POISON;
  8877.       runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  8878.       runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  8879.       runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  8880.       runeAreaSpell.animationColor = 0x60;
  8881.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8882.       col.push_back(0);
  8883.       col.push_back(0);
  8884.       col.push_back(0);
  8885.       runeAreaSpell.areaVec.push_back(col);
  8886.       col.clear();
  8887.       col.push_back(0);
  8888.       col.push_back(1);
  8889.       col.push_back(0);
  8890.       runeAreaSpell.areaVec.push_back(col);
  8891.       col.clear();
  8892.       col.push_back(0);
  8893.       col.push_back(0);
  8894.       col.push_back(0);
  8895.       runeAreaSpell.areaVec.push_back(col);
  8896.       col.clear();
  8897.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 25;   runeAreaSpell.maxDamage = 35;
  8898.       long tempExhaust = player->exhaustedTicks;
  8899. player->exhaustedTicks = 0;
  8900. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8901. player->exhaustedTicks = tempExhaust;
  8902.       int32_t mana = 5;
  8903.       player->addManaSpent(mana);
  8904.       player->mana -= mana;
  8905.       return;
  8906.    }
  8907.    
  8908.    
  8909.    if((wandid == 2189 && (player->vocation == VOCATION_SORCERER) && player->mana >= 8 && player->getLevel() >= 26)) { //Wand of cosmic energy
  8910.       int32_t dist = 2;
  8911.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8912.       std::vector<unsigned char> col;
  8913.       MagicEffectAreaClass runeAreaSpell;
  8914.       runeAreaSpell.attackType = ATTACK_ENERGY;
  8915.       runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8916.       runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8917.       runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8918.       runeAreaSpell.animationColor = 0x47;
  8919.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8920.       col.push_back(0);
  8921.       col.push_back(0);
  8922.       col.push_back(0);
  8923.       runeAreaSpell.areaVec.push_back(col);
  8924.       col.clear();
  8925.       col.push_back(0);
  8926.       col.push_back(1);
  8927.       col.push_back(0);
  8928.       runeAreaSpell.areaVec.push_back(col);
  8929.       col.clear();
  8930.       col.push_back(0);
  8931.       col.push_back(0);
  8932.       col.push_back(0);
  8933.       runeAreaSpell.areaVec.push_back(col);
  8934.       col.clear();
  8935.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 40;   runeAreaSpell.maxDamage = 50;
  8936.             long tempExhaust = player->exhaustedTicks;
  8937. player->exhaustedTicks = 0;
  8938. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8939. player->exhaustedTicks = tempExhaust;
  8940.       int32_t mana = 8;
  8941.       player->addManaSpent(mana);
  8942.       player->mana -= mana;
  8943.       return;
  8944.    }
  8945.    
  8946.    
  8947.    if((wandid == 2190 && (player->vocation == VOCATION_SORCERER) && player->mana >= 2 && player->getLevel() >= 7)) { //Wand of vortex
  8948.       int32_t dist = 3;
  8949.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8950.       std::vector<unsigned char> col;
  8951.       MagicEffectAreaClass runeAreaSpell;
  8952.       runeAreaSpell.attackType = ATTACK_ENERGY;
  8953.       runeAreaSpell.animationEffect = NM_ANI_ENERGY;
  8954.       runeAreaSpell.hitEffect = NM_ME_ENERGY_DAMAGE;
  8955.       runeAreaSpell.areaEffect = NM_ME_ENERGY_AREA;
  8956.       runeAreaSpell.animationColor = 0x47;
  8957.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8958.       col.push_back(0);
  8959.       col.push_back(0);
  8960.       col.push_back(0);
  8961.       runeAreaSpell.areaVec.push_back(col);
  8962.       col.clear();
  8963.       col.push_back(0);
  8964.       col.push_back(1);
  8965.       col.push_back(0);
  8966.       runeAreaSpell.areaVec.push_back(col);
  8967.       col.clear();
  8968.       col.push_back(0);
  8969.       col.push_back(0);
  8970.       col.push_back(0);
  8971.       runeAreaSpell.areaVec.push_back(col);
  8972.       col.clear();
  8973.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 8;   runeAreaSpell.maxDamage = 18;
  8974.       long tempExhaust = player->exhaustedTicks;
  8975. player->exhaustedTicks = 0;
  8976. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  8977. player->exhaustedTicks = tempExhaust;
  8978.       int32_t mana = 2;
  8979.       player->addManaSpent(mana);
  8980.       player->mana -= mana;
  8981.       return;
  8982.    }
  8983.    
  8984.    if((wandid == 2191 && (player->vocation == VOCATION_SORCERER) && player->mana >= 3 && player->getLevel() >= 13)) { //Wand of dragonbreath
  8985.       int32_t dist = 3;
  8986.       if(abs(player->pos.x - attackedCreature->pos.x) > dist || abs(player->pos.y - attackedCreature->pos.y) > dist || player->pos.z != attackedCreature->pos.z) return;
  8987.       std::vector<unsigned char> col;
  8988.       MagicEffectAreaClass runeAreaSpell;
  8989.       runeAreaSpell.attackType = ATTACK_FIRE;
  8990.       runeAreaSpell.animationEffect = NM_ANI_FIRE;
  8991.       runeAreaSpell.hitEffect = NM_ME_FIRE_AREA;
  8992.       runeAreaSpell.areaEffect = NM_ME_FIRE_AREA;
  8993.       runeAreaSpell.animationColor = 0xC7;
  8994.       runeAreaSpell.drawblood = true;   runeAreaSpell.offensive = true;
  8995.       col.push_back(0);
  8996.       col.push_back(0);
  8997.       col.push_back(0);
  8998.       runeAreaSpell.areaVec.push_back(col);
  8999.       col.clear();
  9000.       col.push_back(0);
  9001.       col.push_back(1);
  9002.       col.push_back(0);
  9003.       runeAreaSpell.areaVec.push_back(col);
  9004.       col.clear();
  9005.       col.push_back(0);
  9006.       col.push_back(0);
  9007.       col.push_back(0);
  9008.       runeAreaSpell.areaVec.push_back(col);
  9009.       col.clear();
  9010.       runeAreaSpell.direction = 1;   runeAreaSpell.minDamage = 14;   runeAreaSpell.maxDamage = 24;
  9011.       long tempExhaust = player->exhaustedTicks;
  9012. player->exhaustedTicks = 0;
  9013. creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  9014. player->exhaustedTicks = tempExhaust;
  9015.       int32_t mana = 3;
  9016.       player->addManaSpent(mana);
  9017.       player->mana -= mana;
  9018.       return;
  9019.    }
  9020. //messages by Subarmy  
  9021.  
  9022.  
  9023.  
  9024. if((wandid == 2191 || wandid == 2190 || wandid == 5319 || wandid == 2189 || wandid == 2188 || wandid == 2187 || wandid == 2453 || wandid == 2544 && (player->vocation == VOCATION_DRUID || player->vocation == VOCATION_KNIGHT || player->vocation == VOCATION_PALADIN || (player->vocation >= 0 && player->access > 0)))) { //msg when wrong voc  
  9025. player->sendTextMessage(MSG_SMALLINFO, "This wand can only be wielded by sorcerers.");
  9026. }
  9027. if((wandid == 2186 || wandid == 2185 || wandid == 5318  || wandid == 2183 || wandid == 2182 || wandid == 2181 || wandid == 2453 || wandid == 2544 && (player->vocation == VOCATION_SORCERER || player->vocation == VOCATION_KNIGHT || player->vocation == VOCATION_PALADIN || (player->vocation >= 0 && player->access > 0)))) { //msg when wrong voc  
  9028. player->sendTextMessage(MSG_SMALLINFO, "This wand can only be wielded by druids.");
  9029. }
  9030. if((wandid == 2181 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 26)) {
  9031. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 26 level to wield this wand.");
  9032. }
  9033. if((wandid == 2544 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 200)) {
  9034. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 200 level to wield this wand.");
  9035. }
  9036. if((wandid == 5326 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 300)) {
  9037. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 300 level to wield this wand.");
  9038. }
  9039. if((wandid == 2453 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 150)) {
  9040. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 150 level to wield this wand.");
  9041. }
  9042. if((wandid == 2182 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 7)) {
  9043. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 7 level to wield this wand.");
  9044. }
  9045. if((wandid == 2183 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 33)) {
  9046. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 33 to wield this wand.");
  9047. }
  9048. if((wandid == 2185 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 19)) {
  9049. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 19 level to wield this wand.");
  9050. }
  9051. if((wandid == 2186 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 13)) {
  9052. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 13 level to wield this wand.");
  9053. }
  9054. if((wandid == 5318 && (player->vocation == VOCATION_DRUID || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 65)) {
  9055. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 65 level to wield this wand.");
  9056. }
  9057. if((wandid == 2187 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 33)) {
  9058. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 33 level to wield this wand.");
  9059. }
  9060. if((wandid == 5319 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 65)) {
  9061. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 65 level to wield this wand.");
  9062. }
  9063. if((wandid == 2453 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 150)) {
  9064. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 150 level to wield this wand.");
  9065. }
  9066. if((wandid == 2544 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 200)) {
  9067. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 200 level to wield this wand.");
  9068. }
  9069. if((wandid == 5326 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 300)) {
  9070. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 300 level to wield this wand.");
  9071. }
  9072. if((wandid == 2188 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 19)) {
  9073. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 19 level to wield this wand.");
  9074. }
  9075. if((wandid == 2189 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 26)) {
  9076. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 26 level to wield this wand.");
  9077. }
  9078. if((wandid == 2190 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 7)) {
  9079. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 7 level to wield this wand.");
  9080. }
  9081.  
  9082. if((wandid == 2191 && (player->vocation == VOCATION_SORCERER || (player->vocation >= 0 && player->access > 0)) && player->getLevel() <= 13)) {
  9083. player->sendTextMessage(MSG_SMALLINFO, "You need to be at least at 13 level to wield this wand.");
  9084. }//end messages by Subarmy
  9085. }
  9086. #endif
  9087. // ONLINE RECORD
  9088. void Game::checkRecord()
  9089. {
  9090.     if(record < getPlayersOnline()){
  9091.         record = getPlayersOnline();
  9092.         saveRecord();
  9093.  
  9094.         std::stringstream record;
  9095.         record << "New record: " << getPlayersOnline() << " players are logged in." << std::endl;
  9096.         for(AutoList<Player>::listiterator it = Player::listPlayer.list.begin(); it != Player::listPlayer.list.end(); ++it)
  9097.             (*it).second->sendTextMessage(MSG_ADVANCE, record.str().c_str());
  9098.     }
  9099.  
  9100. }
  9101.  
  9102. bool Game::loadRecord()
  9103. {
  9104.     std::string filename = g_config.getGlobalString("datadir") + "record.xml";
  9105.     xmlDocPtr doc;
  9106.     xmlMutexLock(xmlmutex);
  9107.     doc = xmlParseFile(filename.c_str());
  9108.  
  9109.     if (doc)
  9110.     {
  9111.         xmlNodePtr root, tmp;
  9112.         root = xmlDocGetRootElement(doc);
  9113.  
  9114.         if (xmlStrcmp(root->name, (const xmlChar*)"record"))
  9115.         {
  9116.             xmlFreeDoc(doc);
  9117.             xmlMutexUnlock(xmlmutex);
  9118.             return false;
  9119.         }
  9120.  
  9121.         record = atoi((const char*)xmlGetProp(root, (const xmlChar *)"record"));
  9122.  
  9123.         xmlFreeDoc(doc);
  9124.         xmlMutexUnlock(xmlmutex);
  9125.         return true;
  9126.     }
  9127.  
  9128.     xmlMutexUnlock(xmlmutex);
  9129.     return false;
  9130. }
  9131.  
  9132. bool Game::saveRecord()
  9133. {
  9134.     std::string filename = g_config.getGlobalString("datadir") + "record.xml";
  9135.     xmlDocPtr doc;
  9136.     xmlNodePtr root, tmp;
  9137.     xmlMutexLock(xmlmutex);
  9138.     time_t time = std::time(NULL);
  9139.  
  9140.     doc = xmlNewDoc((const xmlChar*)"1.0");
  9141.     doc->children = xmlNewDocNode(doc, NULL, (const xmlChar*)"record", NULL);
  9142.      root = doc->children;
  9143.  
  9144.     std::stringstream sb;
  9145.     sb << record; xmlSetProp(root, (const xmlChar*) "record", (const xmlChar*)sb.str().c_str()); sb.str("");
  9146.     sb << time; xmlSetProp(root, (const xmlChar*) "time", (const xmlChar*)sb.str().c_str()); sb.str("");
  9147.  
  9148.     xmlSaveFile(filename.c_str(), doc);
  9149.      xmlFreeDoc(doc);
  9150.     xmlMutexUnlock(xmlmutex);
  9151.     return true;
  9152. }
  9153. // ANIMATED TEXT WHEN ADVANCE
  9154. void Game::sendAnimatedTextExt(const Position pos,int32_t aniColor,const std::string &text)
  9155. {
  9156.      SpectatorVec list;
  9157.      SpectatorVec::iterator it;
  9158.      getSpectators(Range(pos), list);
  9159.      for(it = list.begin(); it != list.end(); ++it){
  9160.         Player* spec = dynamic_cast<Player*>(*it);
  9161.         if(spec)
  9162.           spec->sendAnimatedText(pos, aniColor, text);
  9163.      }
  9164. }
  9165. // CREATUREBYPOSITION
  9166. Creature* Game::getCreatureByPosition(int32_t x, int32_t y, int32_t z)
  9167. {
  9168.     for(AutoList<Creature>::listiterator it = listCreature.list.begin(); it != listCreature.list.end(); ++it){
  9169.         if(it->second->pos.x == x && it->second->pos.y == y && it->second->pos.z == z)
  9170.             return it->second;
  9171.     }
  9172.  
  9173.     return NULL;
  9174. }
  9175. // CREATE CONDITION
  9176. void Game::CreateCondition(Creature* creature, Creature* target, unsigned char animationColor, unsigned char damageEffect, unsigned char hitEffect, attacktype_t attackType, bool offensive, int32_t maxDamage, int32_t minDamage, long ticks, long count)
  9177. {
  9178.     uint32_t targetID;
  9179.     if(target)
  9180.     targetID = target->getID();
  9181.     else
  9182.     targetID = 0;
  9183.    
  9184.     MagicEffectTargetCreatureCondition magicCondition = MagicEffectTargetCreatureCondition(targetID);
  9185.     magicCondition.animationColor = animationColor;
  9186.     magicCondition.damageEffect = damageEffect;
  9187.     magicCondition.hitEffect = hitEffect;
  9188.     magicCondition.attackType = attackType;
  9189.     magicCondition.maxDamage = maxDamage;
  9190.     magicCondition.minDamage = minDamage;
  9191.     magicCondition.offensive = offensive;
  9192.     CreatureCondition condition = CreatureCondition(ticks, count, magicCondition);
  9193.     creature->addCondition(condition, true);
  9194.    
  9195.     Player *player = dynamic_cast<Player*>(creature);
  9196.     if(player)
  9197.  player->sendIcons();
  9198. }
  9199. // Fields loaded from map - The Chaos
  9200. void Game::doFieldDamage(Creature* creature, unsigned char animationColor, unsigned char damageEffect,
  9201.        unsigned char hitEffect, attacktype_t attackType, bool offensive, int32_t damage)
  9202. {
  9203.    MagicEffectClass cd;
  9204.    cd.animationColor = animationColor;
  9205.    cd.damageEffect = damageEffect;
  9206.    cd.hitEffect = hitEffect;
  9207.    cd.attackType = attackType;
  9208.    cd.offensive = offensive;
  9209.    Player* itsHim = dynamic_cast<Player*>(getCreatureByID(creature->getID()));
  9210.    if(itsHim){ //Since that was causing damage/2 against player, here its my solution =)
  9211.       cd.maxDamage = damage*2;
  9212.       cd.minDamage = damage*2;
  9213.    }
  9214.    else{
  9215.       cd.maxDamage = damage;
  9216.       cd.minDamage = damage;
  9217.    }
  9218.    creatureMakeMagic(NULL, creature->pos, &cd);
  9219. }
  9220. void Game::updateTile(const Position& pos)
  9221. {
  9222.   SpectatorVec list;
  9223.   SpectatorVec::iterator i;
  9224.   getSpectators(Range(pos), list);
  9225.   for(i = list.begin(); i != list.end(); ++i)
  9226.     (*i)->onTileUpdated(pos);
  9227. }
  9228.  
  9229. void Game::banPlayer(Player *player, std::string reason, std::string action, std::string comment, bool IPban)
  9230. {
  9231.     int32_t bantime = 0;
  9232.    
  9233.      if(player){
  9234.  
  9235.         if(comment=="deletion")
  9236.         player->deleted = 1;  // make player deleted
  9237.         else
  9238.         bantime = atoi(comment.c_str()) * 86400;  // else make players banned for "comment" days (86400 = 1 day)
  9239.        
  9240.         if(player->finalwarning == 1 || player->times == 4)
  9241.         player->deleted = 1; // if player was already warned let delete thy char
  9242.        
  9243.         if(action=="AccountBan+FinalWarning" || player->times == 3)
  9244.         player->finalwarning = 1; // if player has warned set variable
  9245.        
  9246.         if(reason=="Excessive unjustifed player killing")
  9247.         bantime = g_config.getGlobalNumber("pkbandays",3) * 86400;  // baannnnn pekaayssss (from config.lua)
  9248.  
  9249.         player->banned = 1;
  9250.         player->times++;
  9251.         player->comment = comment;
  9252.         player->reason = reason;
  9253.         player->action = action;
  9254.         player->banstart = std::time(NULL);
  9255.         player->banend = player->banstart + bantime;
  9256.         time_t endBan = player->banend;
  9257.         player->banrealtime = ctime(&endBan); // this variable stores REAL ban date in string, so you wont see 11105220952 in accmaker ;)
  9258.         if(IPban){
  9259.             std::pair<uint32_t, uint32_t> IpNetMask;
  9260. IpNetMask.first = player->lastip;
  9261. IpNetMask.second = 0xFFFFFFFF;
  9262. if(IpNetMask.first > 0)
  9263.     bannedIPs.push_back(IpNetMask);
  9264.         }
  9265.         std::stringstream ban;
  9266.         ban << "You just have been banned for " << reason << "!";
  9267.         player->sendTextMessage(MSG_INFO, ban.str().c_str());
  9268.         player->kickPlayer();
  9269.      }
  9270. }
  9271.  
  9272. #ifdef REX_MUTED
  9273.  
  9274. #endif //REX_MUTED
  9275. #ifdef HUCZU_FIX
  9276. bool Game::loadCities(Player* player, std::string name)
  9277. {
  9278.   xmlDocPtr doc;
  9279.   std::string file = "data/miasta.xml";
  9280.   doc = xmlParseFile(file.c_str());
  9281.   if(doc){
  9282.   xmlNodePtr root, miasto;
  9283.   root = xmlDocGetRootElement(doc);
  9284.   if(xmlStrcmp(root->name, (const xmlChar*)"miasta")) {
  9285.      xmlFreeDoc(doc);
  9286.      return -1;
  9287.   }
  9288.    miasto = root->children;
  9289.    while(miasto){
  9290.       if(strcmp((char*) miasto->name, "miasto")==0){
  9291.  
  9292.          std::string nameIN = (const char*)xmlGetProp(miasto, (const xmlChar *) "nazwa");
  9293.                   int32_t x = atoi((const char*)xmlGetProp(miasto, (const xmlChar *) "x"));
  9294.                   int32_t y = atoi((const char*)xmlGetProp(miasto, (const xmlChar *) "y"));
  9295.                   int32_t z = atoi((const char*)xmlGetProp(miasto, (const xmlChar *) "z"));
  9296.                   Position pos(x,y,z);
  9297.                   if(nameIN == name)
  9298.                   teleport(player,pos);
  9299.    }
  9300.    miasto = miasto->next;
  9301.    }    
  9302.    xmlFreeDoc(doc);
  9303.    return 0;
  9304.   }
  9305.   return -1;
  9306. }
  9307. #endif //HUCZU_FIX
  9308. // RAID SYSTEM
  9309. bool Game::loadRaid(std::string name)
  9310. {
  9311.   xmlDocPtr doc;
  9312.   std::cout << "Executing raid named " << name << "." << std::endl;
  9313.   std::string file = "data/world/raids.xml";
  9314.   doc = xmlParseFile(file.c_str());
  9315.   if(doc){
  9316.   xmlNodePtr root, raid, command;
  9317.   root = xmlDocGetRootElement(doc);
  9318.   if(xmlStrcmp(root->name, (const xmlChar*)"raids")) {
  9319.      xmlFreeDoc(doc);
  9320.      return -1;
  9321.   }
  9322.    raid = root->children;
  9323.    while(raid){
  9324.       if(strcmp((char*) raid->name, "raid")==0){
  9325.  
  9326.          std::string nameIN = (const char*)xmlGetProp(raid, (const xmlChar *) "name");
  9327.          if(nameIN == name) {
  9328.          std::string messageIN = (const char*)xmlGetProp(raid, (const xmlChar *) "message");
  9329.          std::string brodcasterIN = (const char*)xmlGetProp(raid, (const xmlChar *) "brodcaster");
  9330.  
  9331.          Creature *c = getCreatureByName(brodcasterIN);
  9332.          if(c) {
  9333.             creatureBroadcastMessage(c,messageIN);
  9334.          } else {
  9335.             std::cout << "Could not send news msg! Brodcaster does not exist" << std::endl;
  9336.          }
  9337.  
  9338.          if(nameIN == name) {
  9339.             command = raid->children;
  9340.  
  9341.             while(command) {
  9342.  
  9343.                if(strcmp((char*) command->name, "monster")==0){
  9344.                   std::string monstername = (const char*)xmlGetProp(command, (const xmlChar *) "name");
  9345.                   int32_t x = atoi((const char*)xmlGetProp(command, (const xmlChar *) "x"));
  9346.                   int32_t y = atoi((const char*)xmlGetProp(command, (const xmlChar *) "y"));
  9347.                   int32_t z = atoi((const char*)xmlGetProp(command, (const xmlChar *) "z"));
  9348.  
  9349.                   int32_t loot = atoi((const char*)xmlGetProp(command, (const xmlChar *) "lootid"));  //Not yet implemented!
  9350.                   int32_t chance = atoi((const char*)xmlGetProp(command, (const xmlChar *) "chance"));  //Not yet implemented!
  9351.                   placeRaidMonster(monstername, x, y, z);
  9352.                }
  9353.  
  9354.                if(strcmp((char*) command->name, "area")==0){
  9355.                   std::string monstername = (const char*)xmlGetProp(command, (const xmlChar *) "monster");
  9356.                   int32_t count = atoi((const char*)xmlGetProp(command, (const xmlChar *) "count"));
  9357.                   int32_t xf = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posxfrom"));
  9358.                   int32_t yf = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posyfrom"));
  9359.                   int32_t zf = atoi((const char*)xmlGetProp(command, (const xmlChar *) "poszfrom"));
  9360.  
  9361.                   int32_t xt = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posxto"));
  9362.                   int32_t yt = atoi((const char*)xmlGetProp(command, (const xmlChar *) "posyto"));
  9363.                   int32_t zt = atoi((const char*)xmlGetProp(command, (const xmlChar *) "poszto"));
  9364.  
  9365.                   int32_t i = 0;
  9366.                   int32_t tries = 0;
  9367.                   while (i<=count && tries<=(count*10)) {
  9368.                       int32_t x = (int32_t)((xt-xf) * (rand()/(RAND_MAX+1.0)) + xf);
  9369.                       int32_t y = (int32_t)((yt-yf) * (rand()/(RAND_MAX+1.0)) + yf);
  9370.                       int32_t z = (int32_t)((zt-zf) * (rand()/(RAND_MAX+1.0)) + zf);
  9371.                       Tile* t = map->getTile(x,y,z);
  9372.                       if(t && t->isPz() == false) {
  9373.                          placeRaidMonster(monstername, x, y, z);
  9374.                          i++;
  9375.                       }
  9376.                       tries++;
  9377.                   }
  9378.                }
  9379.                if(strcmp((char*) command->name, "message")==0){
  9380.                   std::string msg = (const char*)xmlGetProp(command, (const xmlChar *) "text");
  9381.                   std::string brodcaster = (const char*)xmlGetProp(command, (const xmlChar *) "brodcaster");
  9382.                   Creature *c = getCreatureByName(brodcaster);
  9383.                   if(c) {
  9384.                      creatureBroadcastMessage(c,msg);
  9385.                   } else {
  9386.                      std::cout << "Could not send news msg! Brodcaster does not exist." << std::endl;
  9387.                   }
  9388.                }
  9389.                command = command->next;
  9390.             }
  9391.          }
  9392.       }
  9393.    }
  9394.    raid = raid->next;
  9395.    }    
  9396.    xmlFreeDoc(doc);
  9397.    return 0;
  9398.   }
  9399.   return -1;
  9400. }
  9401. bool Game::placeRaidMonster(std::string name, int32_t x, int32_t y, int32_t z)
  9402. {
  9403.  Monster* monster = Monster::createMonster(name, this);
  9404. //For new CVS use the following line:
  9405. //Monster* monster = Monster::createMonster(name, this);
  9406.  if(!monster){
  9407.   delete monster;
  9408.   return false;
  9409.  }
  9410.  Position pos;
  9411.  pos.x = x;
  9412.  pos.y = y;
  9413.  pos.z = z;
  9414.  
  9415.  // Place the monster
  9416.  if(!placeCreature(pos, monster)) {
  9417.   delete monster;
  9418.   return false;
  9419.  }
  9420.  
  9421.  return true;
  9422. }
  9423.  
  9424. void Game::spectatorText(Position pos, unsigned char color, std::string text)
  9425. {
  9426.     SpectatorVec list;
  9427.     SpectatorVec::iterator it;
  9428.     getSpectators(Range(pos, true), list);
  9429.          
  9430.     for(it = list.begin(); it != list.end(); ++it) {
  9431.         if(Player* p = dynamic_cast<Player*>(*it)) {
  9432.             p->sendAnimatedText(pos, color, text);
  9433.         }
  9434.     }
  9435. }
  9436.  
  9437. #ifdef DT_PREMMY
  9438. bool Game::countPremmy(Player *player)
  9439. {
  9440.     Account acc = IOAccount::instance()->loadAccount(player->accountNumber);
  9441.     int32_t cont;
  9442.     if(acc.lastsaveday == 0)
  9443.         cont = 0;
  9444.     else
  9445.         cont = acc.lastsaveday2 - acc.lastsaveday;
  9446.        //std::cout << "Last Login in Acc: " << acc.lastsaveday << " - Today: " << acc.lastsaveday2 << " - Days removed from acc: " << cont << std::endl;
  9447.        if(cont < 0){
  9448.         cont =+ 365; //dodajemy caly rok
  9449.         }
  9450.     if((acc.premDays - cont) <= 0)
  9451.     {
  9452.         acc.premDays = 0;
  9453.         player->premmium = false;
  9454.     }
  9455.     else
  9456.     {
  9457.         acc.premDays = acc.premDays - cont;
  9458.         player->premmium = true;
  9459.     }
  9460.     if(g_config.FREE_PREMMY)
  9461.       player->premmium = true;
  9462.    
  9463.     IOAccount::instance()->saveAccount(acc);
  9464.  
  9465.         }
  9466.  
  9467. #endif //DT_PREMMY
  9468.  
  9469.  
  9470. #ifdef ZS_SWORDS
  9471. void Game::useSword(Creature *creature, Creature *attackedCreature, int32_t swordid)
  9472. {
  9473.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::useSword()");
  9474.  
  9475.     Player *player = dynamic_cast<Player*>(creature);
  9476.     if(!player || !attackedCreature || player->pos.z != attackedCreature->pos.z)
  9477.         return;
  9478.  
  9479.     int32_t dist, mana = 0;
  9480.     MagicEffectAreaNoExhaustionClass runeAreaSpell;
  9481.     runeAreaSpell.drawblood = true;
  9482.     runeAreaSpell.offensive = true;
  9483.     runeAreaSpell.direction = 1;
  9484.    
  9485.  
  9486.     // P O I S O N //
  9487.  
  9488.     if (swordid == ITEM_P_MB && player->vocation == VOCATION_KNIGHT &&
  9489.         player->mana >= g_config.MANA_P_MB && player->getLevel() >= 220)
  9490.     {
  9491.         dist = g_config.RANGE_P_MB;
  9492.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9493.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9494.             return;
  9495.  
  9496.         runeAreaSpell.attackType = ATTACK_SWORD;
  9497.         runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  9498.         runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  9499.         runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  9500.         runeAreaSpell.animationColor = 0x60;
  9501.    
  9502.         runeAreaSpell.minDamage = 10;
  9503.         runeAreaSpell.maxDamage = 60;
  9504.         mana = g_config.MANA_P_MB;
  9505.     }
  9506.    
  9507.     else if (swordid == ITEM_P_MAUL && player->vocation == VOCATION_KNIGHT &&
  9508.         player->mana >= g_config.MANA_P_MAUL && player->getLevel() >= 220)
  9509.     {
  9510.         dist = g_config.RANGE_P_MAUL;
  9511.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9512.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9513.             return;
  9514.  
  9515.         runeAreaSpell.attackType = ATTACK_SWORD;
  9516.         runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  9517.         runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  9518.         runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  9519.         runeAreaSpell.animationColor = 0x60;
  9520.    
  9521.         runeAreaSpell.minDamage = 10;
  9522.         runeAreaSpell.maxDamage = 60;
  9523.         mana = g_config.MANA_P_MAUL;
  9524.     }
  9525.    
  9526.     else if (swordid == ITEM_P_HEAD && player->vocation == VOCATION_KNIGHT &&
  9527.         player->mana >= g_config.MANA_P_HEAD && player->getLevel() >= 220)
  9528.     {
  9529.         dist = g_config.RANGE_P_HEAD;
  9530.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9531.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9532.             return;
  9533.        
  9534.         runeAreaSpell.attackType = ATTACK_SWORD;
  9535.         runeAreaSpell.animationEffect = NM_ANI_FLYPOISONFIELD;
  9536.         runeAreaSpell.hitEffect = NM_ME_POISEN_RINGS;
  9537.         runeAreaSpell.areaEffect = NM_ME_POISEN_RINGS;
  9538.         runeAreaSpell.animationColor = 0x60;
  9539.    
  9540.         runeAreaSpell.minDamage = 10;
  9541.         runeAreaSpell.maxDamage = 60;
  9542.         mana = g_config.MANA_P_HEAD;
  9543.     }
  9544.    
  9545.     // F I R E //
  9546.    
  9547.     else if (swordid == ITEM_F_MB && player->vocation == VOCATION_KNIGHT &&
  9548.         player->mana >= g_config.MANA_F_MB && player->getLevel() >= 320)
  9549.     {
  9550.         dist = g_config.RANGE_F_MB;
  9551.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9552.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9553.             return;
  9554.        
  9555.         runeAreaSpell.attackType = ATTACK_SWORD;
  9556.         runeAreaSpell.animationEffect = NM_ANI_FIRE;
  9557.         runeAreaSpell.hitEffect = NM_ME_EXPLOSION_AREA;
  9558.         runeAreaSpell.areaEffect = NM_ME_EXPLOSION_AREA;
  9559.         runeAreaSpell.animationColor = 0xC6;
  9560.        
  9561.         runeAreaSpell.minDamage = 60;
  9562.         runeAreaSpell.maxDamage = 110;
  9563.         mana = g_config.MANA_F_MB;
  9564.     }
  9565.    
  9566.     else if (swordid == ITEM_F_MAUL && player->vocation == VOCATION_KNIGHT &&
  9567.         player->mana >= g_config.MANA_F_MAUL && player->getLevel() >= 320)
  9568.     {
  9569.         dist = g_config.RANGE_F_MAUL;
  9570.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9571.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9572.             return;
  9573.  
  9574.         runeAreaSpell.attackType = ATTACK_SWORD;
  9575.         runeAreaSpell.animationEffect = NM_ANI_FIRE;
  9576.         runeAreaSpell.hitEffect = NM_ME_EXPLOSION_AREA;
  9577.         runeAreaSpell.areaEffect = NM_ME_EXPLOSION_AREA;
  9578.         runeAreaSpell.animationColor = 0xC6;
  9579.        
  9580.         runeAreaSpell.minDamage = 60;
  9581.         runeAreaSpell.maxDamage = 110;
  9582.         mana = g_config.MANA_F_MAUL;
  9583.     }
  9584.    
  9585.     else if (swordid == ITEM_F_HEAD && player->vocation == VOCATION_KNIGHT &&
  9586.         player->mana >= g_config.MANA_F_HEAD && player->getLevel() >= 320)
  9587.     {
  9588.         dist = g_config.RANGE_F_HEAD;
  9589.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9590.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9591.             return;
  9592.  
  9593.         runeAreaSpell.attackType = ATTACK_SWORD;
  9594.         runeAreaSpell.animationEffect = NM_ANI_FIRE;
  9595.         runeAreaSpell.hitEffect = NM_ME_EXPLOSION_AREA;
  9596.         runeAreaSpell.areaEffect = NM_ME_EXPLOSION_AREA;
  9597.         runeAreaSpell.animationColor = 0xC6;
  9598.        
  9599.         runeAreaSpell.minDamage = 60;
  9600.         runeAreaSpell.maxDamage = 110;
  9601.         mana = g_config.MANA_F_HEAD;
  9602.     }
  9603.    
  9604.     // E N E R G Y //
  9605.    
  9606.     else if (swordid == ITEM_E_MB && player->vocation == VOCATION_KNIGHT &&
  9607.         player->mana >= g_config.MANA_E_MB && player->getLevel() >= 420)
  9608.     {
  9609.         dist = g_config.RANGE_E_MB;
  9610.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9611.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9612.             return;
  9613.  
  9614.         runeAreaSpell.attackType = ATTACK_SWORD;
  9615.         runeAreaSpell.animationEffect = NM_ANI_SUDDENDEATH;
  9616.         runeAreaSpell.hitEffect = NM_ME_MORT_AREA;
  9617.         runeAreaSpell.areaEffect = NM_ME_MORT_AREA;
  9618.         runeAreaSpell.animationColor = 0xB9;
  9619.        
  9620.         runeAreaSpell.minDamage = 110;
  9621.         runeAreaSpell.maxDamage = 160;
  9622.         mana = g_config.MANA_E_MB;
  9623.     }
  9624.    
  9625.     else if (swordid == ITEM_E_MAUL && player->vocation == VOCATION_KNIGHT &&
  9626.         player->mana >= g_config.MANA_E_MAUL && player->getLevel() >= 420)
  9627.     {
  9628.         dist = g_config.RANGE_E_MAUL;
  9629.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9630.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9631.             return;
  9632.  
  9633.         runeAreaSpell.attackType = ATTACK_SWORD;
  9634.         runeAreaSpell.animationEffect = NM_ANI_SUDDENDEATH;
  9635.         runeAreaSpell.hitEffect = NM_ME_MORT_AREA;
  9636.         runeAreaSpell.areaEffect = NM_ME_MORT_AREA;
  9637.         runeAreaSpell.animationColor = 0xB9;
  9638.        
  9639.         runeAreaSpell.minDamage = 110;
  9640.         runeAreaSpell.maxDamage = 160;
  9641.         mana = g_config.MANA_E_MAUL;
  9642.     }
  9643.    
  9644.     else if (swordid == ITEM_E_HEAD && player->vocation == VOCATION_KNIGHT &&
  9645.         player->mana >= g_config.MANA_E_HEAD && player->getLevel() >= 420)
  9646.     {
  9647.         dist = g_config.RANGE_E_HEAD;
  9648.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9649.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9650.             return;
  9651.  
  9652.         runeAreaSpell.attackType = ATTACK_SWORD;
  9653.         runeAreaSpell.animationEffect = NM_ANI_SUDDENDEATH;
  9654.         runeAreaSpell.hitEffect = NM_ME_MORT_AREA;
  9655.         runeAreaSpell.areaEffect = NM_ME_MORT_AREA;
  9656.         runeAreaSpell.animationColor = 0xB9;
  9657.        
  9658.         runeAreaSpell.minDamage = 110;
  9659.         runeAreaSpell.maxDamage = 160;
  9660.         mana = g_config.MANA_E_HEAD;
  9661.     }
  9662.    
  9663.     // P L A Y E R   W E A P O N S //
  9664.    
  9665.     else if (swordid == ITEM_HAIK_AXE && player->vocation == VOCATION_KNIGHT &&
  9666.         player->mana >= g_config.MANA_HAIK_AXE && player->getLevel() >= 500)
  9667.     {
  9668.         dist = g_config.RANGE_HAIK_AXE;
  9669.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9670.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9671.             return;
  9672.    
  9673.         runeAreaSpell.attackType = ATTACK_SWORD;
  9674.         runeAreaSpell.animationEffect = NM_ANI_STAR;
  9675.         runeAreaSpell.hitEffect = NM_ME_STAR;
  9676.         runeAreaSpell.areaEffect = NM_ME_STAR;
  9677.         runeAreaSpell.animationColor = 0xD2;
  9678.        
  9679.         runeAreaSpell.minDamage = 300;
  9680.         runeAreaSpell.maxDamage = 350;
  9681.         mana = g_config.MANA_HAIK_AXE;
  9682.     }
  9683.    
  9684.     else if (swordid == ITEM_BLETKA_AXE && player->vocation == VOCATION_KNIGHT &&
  9685.         player->mana >= g_config.MANA_BLETKA_AXE)
  9686.     {
  9687.         dist = g_config.RANGE_BLETKA_AXE;
  9688.         if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9689.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9690.             return;
  9691.    
  9692.         runeAreaSpell.attackType = ATTACK_SWORD;
  9693.         runeAreaSpell.animationEffect = NM_ANI_STAR;
  9694.         runeAreaSpell.hitEffect = NM_ME_STAR;
  9695.         runeAreaSpell.areaEffect = NM_ME_STAR;
  9696.         runeAreaSpell.animationColor = 0xD2;
  9697.        
  9698.         runeAreaSpell.minDamage = 150;
  9699.         runeAreaSpell.maxDamage = 200;
  9700.         mana = g_config.MANA_BLETKA_AXE;
  9701.     }
  9702.    
  9703.     // K U N I E C //
  9704.    
  9705.     if (mana > 0)
  9706.     {
  9707.         std::vector<unsigned char> col;
  9708.                
  9709.         col.push_back(0);
  9710.         col.push_back(0);
  9711.         col.push_back(0);
  9712.         runeAreaSpell.areaVec.push_back(col);
  9713.         col.clear();
  9714.         col.push_back(0);
  9715.         col.push_back(1);
  9716.         col.push_back(0);
  9717.         runeAreaSpell.areaVec.push_back(col);
  9718.         col.clear();
  9719.         col.push_back(0);
  9720.         col.push_back(0);
  9721.         col.push_back(0);
  9722.         runeAreaSpell.areaVec.push_back(col);
  9723.              
  9724.         creatureThrowRune(player, attackedCreature->pos, runeAreaSpell);
  9725.         player->addManaSpent(mana);
  9726.         player->mana -= mana;
  9727.     }
  9728. }
  9729. #endif //ZS_SWORDS
  9730.  
  9731. #ifdef YUR_READABLES
  9732. bool Game::LoadReadables()
  9733. {
  9734.     std::string file = g_config.getGlobalString("datadir") + "readables.xml";
  9735.     xmlDocPtr doc;
  9736.     xmlMutexLock(xmlmutex);
  9737.  
  9738.     doc = xmlParseFile(file.c_str());
  9739.     if (!doc)
  9740.         return false;
  9741.  
  9742.     xmlNodePtr root, readableNode;
  9743.     root = xmlDocGetRootElement(doc);
  9744.     if (xmlStrcmp(root->name, (const xmlChar*)"readables"))
  9745.     {
  9746.         xmlFreeDoc(doc);
  9747.         xmlMutexUnlock(xmlmutex);
  9748.         return false;
  9749.     }
  9750.  
  9751.     readableNode = root->children;
  9752.     while (readableNode)
  9753.     {
  9754.         if (strcmp((char*) readableNode->name, "readable") == 0)
  9755.         {
  9756.             int32_t x = atoi((const char*)xmlGetProp(readableNode, (const xmlChar *) "x"));
  9757.             int32_t y = atoi((const char*)xmlGetProp(readableNode, (const xmlChar *) "y"));
  9758.             int32_t z = atoi((const char*)xmlGetProp(readableNode, (const xmlChar *) "z"));
  9759.             std::string text = (const char*)xmlGetProp(readableNode, (const xmlChar *) "text");
  9760.  
  9761.             for (size_t i = 0; i < text.length()-1; i++)    // make real newlines
  9762.                 if (text.at(i) == '\\' && text.at(i+1) == 'n')
  9763.                 {
  9764.                     text[i] = ' ';
  9765.                     text[i+1] = '\n';
  9766.                 }
  9767.  
  9768.             Tile* tile = getTile(x, y, z);
  9769.             if (tile)
  9770.             {
  9771.                 Thing* thing = tile->getTopThing();
  9772.                 Item* item = thing? dynamic_cast<Item*>(thing) : NULL;
  9773.  
  9774.                 if (item)
  9775.                     item->setReadable(text);
  9776.                 else
  9777.                 {
  9778.                     std::cout << "\nTop thing at " << Position(x,y,z) << " is not an item!";
  9779.                     return false;
  9780.                 }
  9781.             }
  9782.             else
  9783.             {
  9784.                 std::cout << "\nTile " << Position(x,y,z) << " is not valid!";
  9785.                 return false;
  9786.             }
  9787.         }
  9788.         readableNode = readableNode->next;
  9789.     }
  9790.  
  9791.     xmlFreeDoc(doc);
  9792.     xmlMutexUnlock(xmlmutex);
  9793.     return true;
  9794. }
  9795. #endif //YUR_READABLES
  9796.  
  9797. void Game::Blasting(Creature* c, Creature *attackedCreature, const Position& pos)
  9798. {
  9799.   OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::Blasting()");
  9800.    Player* player = dynamic_cast<Player*>(c);
  9801.    unsigned short dist = 6;
  9802.    unsigned short REQ_MANA = 200;
  9803.    uint32_t poziom = player->level;
  9804.    uint32_t magpoziom = player->maglevel;
  9805.    
  9806.   if (abs(player->pos.x - attackedCreature->pos.x) > dist ||
  9807.             abs(player->pos.y - attackedCreature->pos.y) > dist)
  9808.             return;
  9809.  
  9810. MagicEffectAreaNoExhaustionClass runeAreaSpell;
  9811. runeAreaSpell.drawblood = true;
  9812. runeAreaSpell.offensive = true;
  9813. runeAreaSpell.direction = 1;
  9814. runeAreaSpell.attackType = ATTACK_PHYSICAL;
  9815. runeAreaSpell.animationEffect = NM_ANI_REMOTE;
  9816. runeAreaSpell.hitEffect = NM_ME_EXPLO;
  9817. runeAreaSpell.areaEffect = NM_ME_EXPLO;
  9818. runeAreaSpell.animationColor = 0x60;
  9819.  
  9820. if((poziom * 2 + magpoziom * 3) >= 100){
  9821. runeAreaSpell.minDamage = int32_t((poziom * 2 + magpoziom * 3) * 1.6 );
  9822. runeAreaSpell.maxDamage = int32_t((poziom * 2 + magpoziom * 3) * 1.9 );
  9823. }else{
  9824. runeAreaSpell.minDamage = int32_t(100 * 1.5 );
  9825. runeAreaSpell.maxDamage = int32_t(100 * 1.8 );
  9826. }      
  9827.  
  9828. std::vector<unsigned char> col;
  9829. col.push_back(0);
  9830. col.push_back(0);
  9831. col.push_back(0);
  9832. runeAreaSpell.areaVec.push_back(col);
  9833. col.clear();
  9834. col.push_back(0);
  9835. col.push_back(1);
  9836. col.push_back(0);
  9837. runeAreaSpell.areaVec.push_back(col);
  9838. col.clear();
  9839. col.push_back(0);
  9840. col.push_back(0);
  9841. col.push_back(0);
  9842. runeAreaSpell.areaVec.push_back(col);
  9843.  
  9844. creatureThrowRune(c, pos, runeAreaSpell);
  9845. player->flamTicks = 2*1000;
  9846.             if (player->access < g_config.ACCESS_PROTECT)
  9847.             {
  9848.                 player->mana -= REQ_MANA;
  9849.                 player->addManaSpent(REQ_MANA);
  9850.          }
  9851. }
  9852. #ifdef KOSZ
  9853. bool Game::canDelete(Player *player, unsigned short itemid, Position toPos, Position fromPos, int32_t from_stack, unsigned char count)
  9854. {
  9855.      OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::canDelete()");
  9856.  
  9857.      if(itemid == 99 || (itemid >= 4329 && itemid <= 4555))
  9858.          return false;
  9859.      else if(fromPos.x != 0xFFFF && ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  9860.         return false;
  9861.      else if(map->canThrowObjectTo(player->pos, toPos, BLOCK_PROJECTILE) != RET_NOERROR)
  9862.         return false;
  9863.      else if(toPos.x == 0xFFFF)
  9864.          return false;
  9865.      else if((player->access < g_config.ACCESS_REMOTE) &&
  9866.         ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  9867.         return false;
  9868.  
  9869.      Item* trash = dynamic_cast<Item*>(getThing(fromPos, from_stack, player));
  9870.      if(trash){
  9871.          trash->pos = fromPos;
  9872.          if((abs(player->pos.x - toPos.x) > trash->throwRange) || (abs(player->pos.y - toPos.y) > trash->throwRange)) {        
  9873.             return false;
  9874.          }
  9875.  
  9876.          Tile *toTile = map->getTile(toPos);
  9877.          if(toTile){
  9878. if((toTile->ground->getID() >= GROUND_WATER1 && toTile->ground->getID() <= GROUND_WATER4) || (toTile->ground->getID() >= GROUND_WATER5 && toTile->ground->getID() <= GROUND_WATER16) || (toTile->ground->getID() == GROUND_WATER17) || (toTile->ground->getID() >= GROUND_WATER18 && toTile->ground->getID() <= GROUND_WATER35) || (toTile->ground->getID() >= GROUND_WATER36 && toTile->ground->getID() <= GROUND_WATER38) || (toTile->ground->getID() >= GROUND_WATER39 && toTile->ground->getID() <= GROUND_WATER44) || (toTile->ground->getID() >= GROUND_LAVA1 && toTile->ground->getID() <= GROUND_SWAMP4) || (toTile->ground->getID() >= GROUND_BLACK_SWAMP1 && toTile->ground->getID() <= GROUND_BLACK_SWAMP4)){
  9879.                  if(!trash->isNotMoveable() && trash->isBlocking())
  9880.                      return false;
  9881.                  else if(trashObjects(player, toTile, trash, toPos, fromPos, from_stack, count))
  9882.                      return true;
  9883.              }
  9884. Item *toItem = dynamic_cast<Item*>(toTile->getTopTopItem());
  9885.  
  9886.              if(toItem && toItem->getID() == ITEM_DUSTBIN){
  9887.                  if(!trash->isNotMoveable() && trash->isBlocking())
  9888.                      return false;
  9889.                  else if(trashObjects(player, toTile, trash, toPos, fromPos, from_stack, count))
  9890.                      return true;
  9891.              }
  9892.          }
  9893.      }
  9894.  
  9895.      return false;
  9896. }    
  9897.  
  9898. bool Game::trashObjects(Player *player, Tile *toTile, Item *trash, Position toPos, Position fromPos, int32_t from_stack, unsigned char count)
  9899. {
  9900.      //OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::trashObjects()");
  9901.  
  9902. if(!player || !toTile || !trash || !from_stack || !count){
  9903.    return false;}
  9904.  
  9905. if(toTile){
  9906.          switch(toTile->ground->getID()){
  9907.              case GROUND_WATER1:
  9908.              case GROUND_WATER2:
  9909.              case GROUND_WATER3:
  9910.              case GROUND_WATER4:
  9911.              case GROUND_WATER5:
  9912.              case GROUND_WATER6:
  9913.              case GROUND_WATER7:
  9914.              case GROUND_WATER8:
  9915.              case GROUND_WATER9:
  9916.              case GROUND_WATER10:
  9917.              case GROUND_WATER11:
  9918.              case GROUND_WATER12:
  9919.              case GROUND_WATER13:
  9920.              case GROUND_WATER14:
  9921.              case GROUND_WATER15:
  9922.              case GROUND_WATER16:
  9923.              case GROUND_WATER17:
  9924.              case GROUND_WATER18:
  9925.              case GROUND_WATER19:
  9926.              case GROUND_WATER20:
  9927.              case GROUND_WATER21:
  9928.              case GROUND_WATER22:
  9929.              case GROUND_WATER23:
  9930.              case GROUND_WATER24:
  9931.              case GROUND_WATER25:
  9932.              case GROUND_WATER26:
  9933.              case GROUND_WATER27:
  9934.              case GROUND_WATER28:
  9935.              case GROUND_WATER29:
  9936.              case GROUND_WATER30:
  9937.              case GROUND_WATER31:
  9938.              case GROUND_WATER32:
  9939.              case GROUND_WATER33:
  9940.              case GROUND_WATER34:
  9941.              case GROUND_WATER35:
  9942.              case GROUND_WATER36:
  9943.              case GROUND_WATER37:
  9944.              case GROUND_WATER38:
  9945.              case GROUND_WATER39:
  9946.              case GROUND_WATER40:
  9947.              case GROUND_WATER41:
  9948.              case GROUND_WATER42:
  9949.              case GROUND_WATER43:
  9950.              case GROUND_WATER44:
  9951.              spectatorEffect(toPos, NM_ME_LOOSE_ENERGY);
  9952.              if(trashItems(player, trash, fromPos, from_stack, count))
  9953.                  return true;    
  9954.              break;
  9955.              case GROUND_LAVA1:
  9956.              case GROUND_LAVA2:
  9957.              case GROUND_LAVA3:
  9958.              case GROUND_LAVA4:
  9959.              spectatorEffect(toPos, NM_ME_HITBY_FIRE);
  9960.              if(trashItems(player, trash, fromPos, from_stack, count))
  9961.                  return true;
  9962.              break;
  9963.              case GROUND_SWAMP1:
  9964.              case GROUND_SWAMP2:
  9965.              case GROUND_SWAMP3:
  9966.              case GROUND_SWAMP4:
  9967.              spectatorEffect(toPos, NM_ME_POISEN_RINGS);
  9968.              if(trashItems(player, trash, fromPos, from_stack, count))
  9969.                  return true;
  9970.              break;
  9971.              case GROUND_BLACK_SWAMP1:
  9972.              case GROUND_BLACK_SWAMP2:
  9973.              case GROUND_BLACK_SWAMP3:
  9974.              case GROUND_BLACK_SWAMP4:
  9975.              spectatorEffect(toPos, NM_ME_MORT_AREA);
  9976.              if(trashItems(player, trash, fromPos, from_stack, count))
  9977.                  return true;
  9978.              break;
  9979.          }
  9980.      }
  9981.  
  9982.      return false;
  9983. }
  9984.  
  9985. bool Game::trashItems(Player *player, Item *trash, Position fromPos, int32_t from_stack, unsigned char count)
  9986. {
  9987.     //OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::trashItems()");
  9988.      if(!trash){return false;}
  9989.      if(trash->getID() == 99 || (trash->getID() >= 4329 && trash->getID() <= 4555))
  9990.          return false;
  9991.      else if(fromPos.x != 0xFFFF && ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  9992.         return false;
  9993.      else if((player->access < g_config.ACCESS_REMOTE) &&
  9994.         ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  9995.         return false;
  9996.  
  9997.     if(trash && player){
  9998.         if(trash->isStackable()){
  9999.             if(trash->getItemCountOrSubtype() > count){
  10000.                 trash->setItemCountOrSubtype(trash->getItemCountOrSubtype() - count);
  10001.                 sendUpdateThing(player,fromPos,trash,from_stack);
  10002.                 player->updateInventoryWeigth();
  10003.                 return true;
  10004.             }
  10005.             else{
  10006.                 if(removeThing(player, fromPos, trash)){
  10007.                     player->updateInventoryWeigth();
  10008.                     return true;
  10009.                 }
  10010.             }
  10011.         }
  10012.         else{
  10013.             if(removeThing(player, fromPos, trash)){
  10014.                 player->updateInventoryWeigth();
  10015.                 return true;
  10016.              }
  10017.         }
  10018.     }
  10019.     return false;
  10020. }
  10021.  
  10022. bool Game::canTeleportItem(Player *player, unsigned short itemid, Position toPos, Position fromPos, int32_t from_stack, unsigned char count)
  10023. {
  10024.      OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::canTeleportItem()");
  10025.  
  10026.      if(itemid == 99 || (itemid >= 4329 && itemid <= 4555))
  10027.          return false;
  10028.      else if(fromPos.x != 0xFFFF && ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  10029.          return false;
  10030.      else if(map->canThrowObjectTo(player->pos, toPos, BLOCK_PROJECTILE) != RET_NOERROR)
  10031.          return false;
  10032.      else if(toPos.x == 0xFFFF)
  10033.          return false;
  10034.      else if(!checkChangeFloor(map->getTile(toPos), getTile(toPos.x,toPos.y,toPos.z+1)))
  10035.          return false;
  10036.      else if((player->access < g_config.ACCESS_REMOTE) &&
  10037.         ((abs(player->pos.x - fromPos.x) > 1) || (abs(player->pos.y - fromPos.y) > 1) || (player->pos.z != fromPos.z)))
  10038.          return false;
  10039.  
  10040.      Item* tpItem = dynamic_cast<Item*>(getThing(fromPos, from_stack, player));
  10041.      if(tpItem){
  10042.          tpItem->pos = fromPos;
  10043.          if((abs(player->pos.x - toPos.x) > tpItem->throwRange) || (abs(player->pos.y - toPos.y) > tpItem->throwRange)) {        
  10044.             return false;
  10045.          }
  10046.  
  10047.          if(tpItem->isStackable()){
  10048.              if(tpItem->getItemCountOrSubtype() > count){
  10049.                  tpItem->setItemCountOrSubtype(tpItem->getItemCountOrSubtype() - count);
  10050.                  Item *newitem = Item::CreateItem(tpItem->getID(), count);
  10051.                  addThing(player,getTeleportPos(toPos),newitem);
  10052.                  sendUpdateThing(player,fromPos,tpItem,from_stack);
  10053.                  player->updateInventoryWeigth();
  10054.                  return true;
  10055.              }
  10056.              else{
  10057.                  if(removeThing(player, fromPos, tpItem)){
  10058.                      addThing(player,getTeleportPos(toPos),tpItem);
  10059.                      player->updateInventoryWeigth();
  10060.                      return true;
  10061.                  }
  10062.              }
  10063.          }
  10064.          else{
  10065.              if(removeThing(player, fromPos, tpItem)){
  10066.                  addThing(player,getTeleportPos(toPos),tpItem);
  10067.                  player->updateInventoryWeigth();
  10068.                  return true;
  10069.              }
  10070.          }
  10071.      }
  10072.      return false;
  10073. }
  10074.  
  10075. void Game::spectatorEffect(Position pos, unsigned char type)
  10076. {
  10077.     SpectatorVec list;
  10078.     SpectatorVec::iterator it;
  10079.     getSpectators(Range(pos, true), list);
  10080.          
  10081.     for(it = list.begin(); it != list.end(); ++it) {
  10082.         if(Player* p = dynamic_cast<Player*>(*it)) {
  10083.             p->sendMagicEffect(pos, type);
  10084.         }
  10085.     }
  10086. }
  10087.  
  10088. bool Game::checkChangeFloor(Tile *toTile, Tile* downTile)
  10089. {
  10090. if(toTile->ground && toTile->ground->floorChangeDown())
  10091. {
  10092. if(downTile){
  10093. if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  10094. return true;
  10095. }
  10096. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  10097. return true;
  10098. }
  10099. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  10100. return true;
  10101. }
  10102. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  10103. return true;
  10104. }
  10105. else if(downTile->floorChange(NORTH)){
  10106. return true;
  10107. }
  10108. else if(downTile->floorChange(SOUTH)){
  10109. return true;
  10110. }
  10111. else if(downTile->floorChange(EAST)){
  10112. return true;
  10113. }
  10114. else if(downTile->floorChange(WEST)){
  10115. return true;
  10116. }
  10117. else if(Item::items[toTile->ground->getID()].floorChangeDown){
  10118. return true;
  10119. }
  10120. else {
  10121. return true;
  10122. }
  10123. }
  10124. }
  10125. else if(toTile->floorChange(NORTH) && toTile->floorChange(EAST)){
  10126. return true;
  10127. }
  10128. else if(toTile->floorChange(NORTH) && toTile->floorChange(WEST)){
  10129. return true;
  10130. }
  10131. else if(toTile->floorChange(SOUTH) && toTile->floorChange(EAST)){
  10132. return true;
  10133. }
  10134. else if(toTile->floorChange(SOUTH) && toTile->floorChange(WEST)){
  10135. return true;
  10136. }                    
  10137. else if(toTile->floorChange(NORTH)){
  10138. return true;
  10139. }
  10140. else if(toTile->floorChange(SOUTH)){
  10141. return true;
  10142. }
  10143. else if(toTile->floorChange(EAST)){
  10144. return true;
  10145. }
  10146. else if(toTile->floorChange(WEST)){
  10147. return true;
  10148. }
  10149. if(!toTile){
  10150. if(!downTile)
  10151. {
  10152. return false;
  10153. }
  10154. else if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  10155. return true;
  10156. }
  10157. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  10158. return true;
  10159. }
  10160. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  10161. return true;
  10162. }
  10163. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  10164. return true;
  10165. }                                                      
  10166. else if(downTile->floorChange(NORTH)){
  10167. return true;
  10168. }
  10169. else if(downTile->floorChange(SOUTH)){
  10170. return true;
  10171. }
  10172. else if(downTile->floorChange(EAST)){
  10173. return true;
  10174. }
  10175. else if(downTile->floorChange(WEST)){
  10176. return true;
  10177. }
  10178. }
  10179. return false;
  10180. }
  10181.  
  10182. Position Game::getTeleportPos(Position to)
  10183. {
  10184. Tile *toTile = map->getTile(to);
  10185.  
  10186. if(toTile->ground && toTile->ground->floorChangeDown())
  10187. {
  10188. Tile* downTile = getTile(to.x, to.y, to.z+1);
  10189. if(downTile){
  10190. //diagonal begin
  10191. if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  10192. return Position(to.x-1, to.y+1, to.z+1);
  10193. }
  10194. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  10195. return Position(to.x+1, to.y+1, to.z+1);
  10196. }
  10197. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  10198. return Position(to.x-1, to.y-1, to.z+1);
  10199. }
  10200. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  10201. return Position(to.x+1, to.y-1, to.z+1);
  10202. }
  10203. //diagonal end
  10204. else if(downTile->floorChange(NORTH)){
  10205. return Position(to.x, to.y+1, to.z+1);
  10206. }
  10207. else if(downTile->floorChange(SOUTH)){
  10208. return Position(to.x, to.y-1, to.z+1);
  10209. }
  10210. else if(downTile->floorChange(EAST)){
  10211. return Position(to.x-1, to.y, to.z+1);
  10212. }
  10213. else if(downTile->floorChange(WEST)){
  10214. return Position(to.x+1, to.y, to.z+1);
  10215. }
  10216. //floor change down
  10217. else if(Item::items[toTile->ground->getID()].floorChangeDown){
  10218. return Position(to.x, to.y, to.z+1);
  10219. }
  10220. else {
  10221. return Position(to.x, to.y, to.z+1);
  10222. }
  10223. }
  10224. }
  10225. //diagonal begin
  10226. else if(toTile->floorChange(NORTH) && toTile->floorChange(EAST)){
  10227. return Position(to.x+1, to.y-1, to.z-1);
  10228. }
  10229. else if(toTile->floorChange(NORTH) && toTile->floorChange(WEST)){
  10230. return Position(to.x-1, to.y-1, to.z-1);
  10231. }
  10232. else if(toTile->floorChange(SOUTH) && toTile->floorChange(EAST)){
  10233. return Position(to.x+1, to.y+1, to.z-1);
  10234. }
  10235. else if(toTile->floorChange(SOUTH) && toTile->floorChange(WEST)){
  10236. return Position(to.x-1, to.y+1, to.z-1);
  10237. }                  
  10238. else if(toTile->floorChange(NORTH)){
  10239. return Position(to.x, to.y-1, to.z-1);
  10240. }
  10241. else if(toTile->floorChange(SOUTH)){
  10242. return Position(to.x, to.y+1, to.z-1);
  10243. }
  10244. else if(toTile->floorChange(EAST)){
  10245. return Position(to.x+1, to.y, to.z-1);
  10246. }
  10247. else if(toTile->floorChange(WEST)){
  10248. return Position(to.x-1, to.y, to.z-1);
  10249. }                                      
  10250. if(!toTile){
  10251. Tile* downTile = getTile(to.x, to.y, to.z+1);
  10252. if(!downTile)
  10253. {
  10254. return Position(0,0,0);
  10255. }
  10256. else if(downTile->floorChange(NORTH) && downTile->floorChange(EAST)){
  10257. return Position(to.x-2, to.y+2, to.z+1);
  10258. }
  10259. else if(downTile->floorChange(NORTH) && downTile->floorChange(WEST)){
  10260. return Position(to.x+2, to.y+2, to.z+1);
  10261. }
  10262. else if(downTile->floorChange(SOUTH) && downTile->floorChange(EAST)){
  10263. return Position(to.x-2, to.y-2, to.z+1);
  10264. }
  10265. else if(downTile->floorChange(SOUTH) && downTile->floorChange(WEST)){
  10266. return Position(to.x+2, to.y-2, to.z+1);
  10267. }                                                    
  10268. else if(downTile->floorChange(NORTH)){
  10269. return Position(to.x, to.y + 1, to.z+1);
  10270. }
  10271. else if(downTile->floorChange(SOUTH)){
  10272. return Position(to.x, to.y - 1, to.z+1);
  10273. }
  10274. else if(downTile->floorChange(EAST)){
  10275. return Position(to.x - 1, to.y, to.z+1);
  10276. }
  10277. else if(downTile->floorChange(WEST)){
  10278. return Position(to.x + 1, to.y, to.z+1);
  10279. }
  10280. }
  10281. }
  10282. #endif //KOSZ
  10283.  
  10284. void Game::globalMagicEffect(const Position pos, unsigned char type)
  10285. {
  10286. SpectatorVec list;
  10287. SpectatorVec::iterator it;
  10288. getSpectators(Range(pos), list);
  10289. for(it = list.begin(); it != list.end(); ++it){
  10290. Player* p = dynamic_cast<Player*>(*it);
  10291. if(p)
  10292. p->sendMagicEffect(pos, type);
  10293. }
  10294. }
  10295.  
  10296. void Game::checkCreatureFollow(uint32_t id)
  10297. {
  10298.    OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreatureFollow");
  10299.    Player *player = getPlayerByID(id);
  10300.    if(!player)
  10301.       return;
  10302.    if(!player->pathList.empty()) {                                                                                        
  10303.       Creature *followCreature = getCreatureByID(player->followCreature);
  10304.             if(followCreature == 0)
  10305.             return;
  10306.   if((std::abs(player->pos.x - followCreature->pos.x) > 7) ||
  10307.   (std::abs(player->pos.y - followCreature->pos.y) > 5) || (player->pos.z != followCreature->pos.z)){
  10308.       player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  10309.       player->eventCheckFollow = 0;
  10310.       player->followCreature = 0;      
  10311.       playerSetAttackedCreature(player, 0);
  10312.       return;
  10313.   }      
  10314.       if(followCreature && abs(followCreature->pos.x - player->pos.x) <= 1 && abs(followCreature->pos.y - player->pos.y) <= 1) player->pathList.clear();
  10315.       else {
  10316.          Position toPos = player->pathList.front();
  10317.          player->pathList.pop_front();
  10318.          player->lastmove = OTSYS_TIME();
  10319.          this->thingMove(player, player, toPos.x, toPos.y, player->pos.z, 1);
  10320.          flushSendBuffers();
  10321.       }
  10322.    }
  10323.    if(!player->pathList.empty()) {
  10324.       long long delay = player->getSleepTicks();
  10325.       stopEvent(player->eventCheckFollow);
  10326.       player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollow), id)));
  10327.    } else {
  10328.       player->eventCheckFollow = 0;
  10329.    }
  10330. }
  10331. void Game::checkCreatureFollowAttack(uint32_t id)
  10332. {
  10333.    OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::checkCreatureFollowAttack");
  10334.    Player *player = getPlayerByID(id);
  10335.    if(!player)
  10336.       return;
  10337.    if(!player->pathList.empty()) {                                                              
  10338.       Creature *followCreature = getCreatureByID(player->followCreature);
  10339.       if(followCreature == 0)
  10340.       return;
  10341.       if(player->followMode == 0x00) {                    
  10342. stopEvent(player->eventCheckFollow);
  10343. player->eventCheckFollow = 0;
  10344. player->followCreature = 0;  
  10345.       return;
  10346.       }
  10347.   if((std::abs(player->pos.x - followCreature->pos.x) > 7) ||
  10348.   (std::abs(player->pos.y - followCreature->pos.y) > 5) || (player->pos.z != followCreature->pos.z)){
  10349.       player->sendTextMessage(MSG_SMALLINFO, "Target lost.");
  10350.       player->eventCheckFollow = 0;
  10351.       player->followCreature = 0;      
  10352.       playerSetAttackedCreature(player, 0);
  10353.       return;
  10354.   }        
  10355.       if(followCreature && abs(followCreature->pos.x - player->pos.x) <= 1 && abs(followCreature->pos.y - player->pos.y) <= 1) player->pathList.clear();
  10356.       else {
  10357.          Position toPos = player->pathList.front();
  10358.          player->pathList.pop_front();
  10359.          player->lastmove = OTSYS_TIME();
  10360.          this->thingMove(player, player, toPos.x, toPos.y, player->pos.z, 1);
  10361.          flushSendBuffers();
  10362.       }
  10363.    }
  10364.    if(!player->pathList.empty()) {
  10365.       long long delay = player->getSleepTicks();
  10366.       stopEvent(player->eventCheckFollow);
  10367.       player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollowAttack), id)));
  10368.    } else {
  10369.       player->eventCheckFollow = 0;
  10370.    }
  10371. }
  10372. void Game::playerFollow(Player* player, Creature *followCreature)
  10373. {
  10374. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerFollow()");
  10375. if(followCreature->isRemoved || player->isRemoved || !player || !followCreature){
  10376. player->eventCheckFollow = 0;
  10377. player->followCreature = 0;
  10378. return;
  10379. }
  10380. player->pathList = getPathToEx(player, player->pos, followCreature->pos, false);
  10381. long long delay = player->getSleepTicks();
  10382. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollow), player->getID())));
  10383. }
  10384. void Game::playerFollowAttacking(Player* player, Creature *followCreature)
  10385. {
  10386. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerFollow()");
  10387. if(followCreature->isRemoved || player->isRemoved || !player || !followCreature){
  10388. player->eventCheckFollow = 0;
  10389. player->followCreature = 0;
  10390. return;
  10391. }
  10392. if(player->followMode == 0x00) {
  10393. stopEvent(player->eventCheckFollow);
  10394. player->eventCheckFollow = 0;
  10395. player->followCreature = 0;
  10396. return;
  10397. }
  10398. player->pathList = getPathToEx(player, player->pos, followCreature->pos, false);
  10399. long long delay = player->getSleepTicks();
  10400. player->eventCheckFollow = addEvent(makeTask(delay, std::bind2nd(std::mem_fun(&Game::checkCreatureFollowAttack), player->getID())));
  10401. }
  10402. void Game::playerSetFollowCreature(Player* player, uint32_t creatureid)
  10403. {
  10404. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerSetFollowCreature()");
  10405. if(player->isRemoved || !player)
  10406. return;
  10407. if(creatureid == 0) {
  10408. stopEvent(player->eventCheckFollow);
  10409. player->eventCheckFollow = 0;
  10410. player->followCreature = 0;
  10411. }
  10412. Creature* followCreature = NULL;
  10413. if(creatureid != 0) {
  10414. followCreature = getCreatureByID(creatureid);
  10415. }
  10416. if(followCreature) {
  10417. player->followCreature = followCreature->getID();
  10418. stopEvent(player->eventCheckFollow);
  10419. playerFollow(player, followCreature);
  10420. }
  10421. }
  10422. void Game::playerAttackSetFollowCreature(Player* player, uint32_t creatureid)
  10423. {
  10424. OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::playerAttackSetFollowCreature()");
  10425. if(player->isRemoved || !player)
  10426. return;
  10427. if(player->followMode == 0x00) {
  10428. return;
  10429. }
  10430. if(creatureid == 0) {
  10431. stopEvent(player->eventCheckFollow);
  10432. player->eventCheckFollow = 0;
  10433. player->followCreature = 0;
  10434. }
  10435. Creature* followCreature = NULL;
  10436. if(creatureid != 0) {
  10437. followCreature = getCreatureByID(creatureid);
  10438. }
  10439. if(followCreature) {
  10440. player->followCreature = followCreature->getID();
  10441. stopEvent(player->eventCheckFollow);
  10442. playerFollowAttacking(player, followCreature);
  10443. }
  10444. }
  10445.  
  10446. #ifdef HUCZU_AUTORESTART
  10447. void Game::beforeRestart()
  10448. {
  10449.     sheduleShutdown(5);
  10450. }
  10451. #endif
  10452.  
  10453. void Game::creatureUseShop(Creature *creature, int id, int count, std::string way){
  10454.     OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::creatureUseShop()");
  10455.  
  10456.     int stackpos = map->getTile(creature->pos)->getThingStackPos(creature);
  10457.  
  10458.     SpectatorVec list;
  10459.     SpectatorVec::iterator it;
  10460.  
  10461.     map->getSpectators(Range(creature->pos, true), list);
  10462.  
  10463.     for(it = list.begin(); it != list.end(); ++it) {
  10464.         if(dynamic_cast<Npc*>(*it)) {
  10465.             (*it)->onCreatureUseShop(creature, id, count, way);
  10466.         }
  10467.     }
  10468. }
Add Comment
Please, Sign In to add comment