SHARE
TWEET

item.cpp

a guest Apr 3rd, 2014 59 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ////////////////////////////////////////////////////////////////////////
  2. // OpenTibia - an opensource roleplaying game
  3. ////////////////////////////////////////////////////////////////////////
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16. ////////////////////////////////////////////////////////////////////////
  17. #include "otpch.h"
  18. #include <iostream>
  19. #include <iomanip>
  20.  
  21. #include "item.h"
  22. #include "container.h"
  23. #include "depotchest.h"
  24. #include "depotlocker.h"
  25.  
  26. #include "teleport.h"
  27. #include "trashholder.h"
  28. #include "mailbox.h"
  29.  
  30. #include "luascript.h"
  31. #include "combat.h"
  32.  
  33. #include "house.h"
  34. #include "beds.h"
  35.  
  36. #include "actions.h"
  37. #include "configmanager.h"
  38. #include "game.h"
  39. #include "movement.h"
  40. #include "attributesmod.h"
  41.  
  42. extern Game g_game;
  43. extern ConfigManager g_config;
  44. extern MoveEvents* g_moveEvents;
  45.  
  46. Items Item::items;
  47. Item* Item::CreateItem(const uint16_t type, uint16_t amount/* = 0*/)
  48. {
  49.         const ItemType& it = Item::items[type];
  50.         if(it.group == ITEM_GROUP_DEPRECATED)
  51.         {
  52.                 #ifdef __DEBUG__
  53.                 std::clog << "[Error - Item::CreateItem] Item " << it.id << " has been declared as deprecated" << std::endl;
  54.                 #endif
  55.                 return NULL;
  56.         }
  57.  
  58.         if(!it.id)
  59.                 return NULL;
  60.  
  61.         Item* newItem = NULL;
  62.         if(it.isDepot())
  63.                 newItem = new DepotLocker(type);
  64.         else if(it.isContainer())
  65.                 newItem = new Container(type);
  66.         else if(it.isTeleport())
  67.                 newItem = new Teleport(type);
  68.         else if(it.isMagicField())
  69.                 newItem = new MagicField(type);
  70.         else if(it.isDoor())
  71.                 newItem = new Door(type);
  72.         else if(it.isTrashHolder())
  73.                 newItem = new TrashHolder(type, it.magicEffect);
  74.         else if(it.isMailbox())
  75.                 newItem = new Mailbox(type);
  76.         else if(it.isBed())
  77.                 newItem = new BedItem(type);
  78.         else if(it.id >= 2210 && it.id <= 2212)
  79.                 newItem = new Item(type - 3, amount);
  80.         else if(it.id == 2215 || it.id == 2216)
  81.                 newItem = new Item(type - 2, amount);
  82.         else if(it.id >= 2202 && it.id <= 2206)
  83.                 newItem = new Item(type - 37, amount);
  84.         else if(it.id == 2640)
  85.                 newItem = new Item(6132, amount);
  86.         else if(it.id == 6301)
  87.                 newItem = new Item(6300, amount);
  88.         else if(it.id == 18528)
  89.                 newItem = new Item(18408, amount);
  90.         else
  91.                 newItem = new Item(type, amount);
  92.  
  93.         newItem->addRef();
  94.         return newItem;
  95. }
  96.  
  97. Item* Item::CreateItem(PropStream& propStream)
  98. {
  99.         uint16_t type;
  100.         if(!propStream.getShort(type))
  101.                 return NULL;
  102.  
  103.         return Item::CreateItem(items.getRandomizedItem(type), 0);
  104. }
  105.  
  106. bool Item::loadItem(xmlNodePtr node, Container* parent)
  107. {
  108.         if(!xmlStrcmp(node->name, (const xmlChar*)"item"))
  109.                 return false;
  110.  
  111.         int32_t intValue;
  112.         std::string strValue;
  113.  
  114.         Item* item = NULL;
  115.         if(readXMLInteger(node, "id", intValue))
  116.                 item = Item::CreateItem(intValue);
  117.  
  118.         if(!item)
  119.                 return false;
  120.  
  121.         if(readXMLString(node, "attributes", strValue))
  122.         {
  123.                 StringVec v, attr = explodeString(strValue, ";");
  124.                 for(StringVec::iterator it = attr.begin(); it != attr.end(); ++it)
  125.                 {
  126.                         v = explodeString((*it), ",");
  127.                         if(v.size() < 2)
  128.                                 continue;
  129.  
  130.                         if(atoi(v[1].c_str()) || v[1] == "0")
  131.                                 item->setAttribute(v[0].c_str(), atoi(v[1].c_str()));
  132.                         else
  133.                                 item->setAttribute(v[0].c_str(), v[1]);
  134.                 }
  135.         }
  136.  
  137.         //compatibility
  138.         if(readXMLInteger(node, "subtype", intValue) || readXMLInteger(node, "subType", intValue))
  139.                 item->setSubType(intValue);
  140.  
  141.         if(readXMLInteger(node, "actionId", intValue) || readXMLInteger(node, "actionid", intValue)
  142.                 || readXMLInteger(node, "aid", intValue))
  143.                 item->setActionId(intValue);
  144.  
  145.         if(readXMLInteger(node, "uniqueId", intValue) || readXMLInteger(node, "uniqueid", intValue)
  146.                 || readXMLInteger(node, "uid", intValue))
  147.                 item->setUniqueId(intValue);
  148.  
  149.         if(readXMLString(node, "text", strValue))
  150.                 item->setText(strValue);
  151.  
  152.         if(item->getContainer())
  153.                 loadContainer(node, item->getContainer());
  154.  
  155.         if(parent)
  156.                 parent->addItem(item);
  157.  
  158.         return true;
  159. }
  160.  
  161. bool Item::loadContainer(xmlNodePtr parentNode, Container* parent)
  162. {
  163.         for(xmlNodePtr node = parentNode->children; node; node = node->next)
  164.         {
  165.                 if(node->type != XML_ELEMENT_NODE)
  166.                         continue;
  167.  
  168.                 if(!xmlStrcmp(node->name, (const xmlChar*)"item") && !loadItem(node, parent))
  169.                         return false;
  170.         }
  171.  
  172.         return true;
  173. }
  174.  
  175. Item::Item(const uint16_t type, uint16_t amount/* = 0*/):
  176.         ItemAttributes(), id(type)
  177. {
  178.         raid = NULL;
  179.         loadedFromMap = false;
  180.  
  181.         setItemCount(1);
  182.         setDefaultDuration();
  183.  
  184.         const ItemType& it = items[type];
  185.         if(it.isFluidContainer() || it.isSplash())
  186.                 setFluidType(amount);
  187.         else if(it.stackable)
  188.         {
  189.                 if(amount)
  190.                         setItemCount(amount);
  191.                 else if(it.charges)
  192.                         setItemCount(it.charges);
  193.         }
  194.         else if(it.charges)
  195.                 setCharges(amount ? amount : it.charges);
  196. }
  197.  
  198. Item* Item::clone() const
  199. {
  200.         Item* tmp = Item::CreateItem(id, count);
  201.         if(!tmp)
  202.                 return NULL;
  203.  
  204.         if(!attributes || attributes->empty())
  205.                 return tmp;
  206.  
  207.         tmp->createAttributes();
  208.         *tmp->attributes = *attributes;
  209.         tmp->eraseAttribute("uid");
  210.         return tmp;
  211. }
  212.  
  213. void Item::copyAttributes(Item* item)
  214. {
  215.         if(item && item->attributes && !item->attributes->empty())
  216.         {
  217.                 createAttributes();
  218.                 *attributes = *item->attributes;
  219.                 eraseAttribute("uid");
  220.         }
  221.  
  222.         eraseAttribute("decaying");
  223.         eraseAttribute("duration");
  224. }
  225.  
  226. void Item::makeUnique(Item* parent)
  227. {
  228.         if(!parent || !parent->getUniqueId())
  229.                 return;
  230.  
  231.         ScriptEnviroment::removeUniqueThing(parent);
  232.         setUniqueId(parent->getUniqueId());
  233.         parent->eraseAttribute("uid");
  234. }
  235.  
  236. void Item::onRemoved()
  237. {
  238.         if(raid)
  239.         {
  240.                 raid->unRef();
  241.                 raid = NULL;
  242.         }
  243.  
  244.         ScriptEnviroment::removeTempItem(this);
  245.         if(getUniqueId())
  246.                 ScriptEnviroment::removeUniqueThing(this);
  247. }
  248.  
  249. void Item::setDefaultSubtype()
  250. {
  251.         setItemCount(1);
  252.         const ItemType& it = items[id];
  253.         if(it.charges)
  254.                 setCharges(it.charges);
  255. }
  256.  
  257. void Item::setID(uint16_t newId)
  258. {
  259.         const ItemType& it = Item::items[newId];
  260.         const ItemType& pit = Item::items[id];
  261.         id = newId;
  262.  
  263.         uint32_t newDuration = it.decayTime * 1000;
  264.         if(!newDuration && !it.stopTime && it.decayTo == -1)
  265.         {
  266.                 eraseAttribute("decaying");
  267.                 eraseAttribute("duration");
  268.         }
  269.  
  270.         eraseAttribute("corpseowner");
  271.         if(newDuration > 0 && (!pit.stopTime || !hasIntegerAttribute("duration")))
  272.         {
  273.                 setDecaying(DECAYING_FALSE);
  274.                 setDuration(newDuration);
  275.         }
  276. }
  277.  
  278. bool Item::floorChange(FloorChange_t change/* = CHANGE_NONE*/) const
  279. {
  280.         if(change < CHANGE_NONE)
  281.                 return Item::items[id].floorChange[change];
  282.  
  283.         for(int32_t i = CHANGE_PRE_FIRST; i < CHANGE_LAST; ++i)
  284.         {
  285.                 if(Item::items[id].floorChange[i])
  286.                         return true;
  287.         }
  288.  
  289.         return false;
  290. }
  291.  
  292. Player* Item::getHoldingPlayer()
  293. {
  294.         for(Cylinder* p = getParent(); p; p = p->getParent())
  295.         {
  296.                 if(p->getCreature())
  297.                         return p->getCreature()->getPlayer();
  298.         }
  299.  
  300.         return NULL;
  301. }
  302.  
  303. const Player* Item::getHoldingPlayer() const
  304. {
  305.         return const_cast<Item*>(this)->getHoldingPlayer();
  306. }
  307.  
  308. uint16_t Item::getSubType() const
  309. {
  310.         const ItemType& it = items[id];
  311.         if(it.isFluidContainer() || it.isSplash())
  312.                 return getFluidType();
  313.  
  314.         if(it.charges)
  315.                 return getCharges();
  316.  
  317.         return count;
  318. }
  319.  
  320. void Item::setSubType(uint16_t n)
  321. {
  322.         const ItemType& it = items[id];
  323.         if(it.isFluidContainer() || it.isSplash())
  324.                 setFluidType(n);
  325.         else if(it.charges)
  326.                 setCharges(n);
  327.         else
  328.                 count = n;
  329. }
  330.  
  331. Attr_ReadValue Item::readAttr(AttrTypes_t attr, PropStream& propStream)
  332. {
  333.         switch(attr)
  334.         {
  335.                 case ATTR_COUNT:
  336.                 {
  337.                         uint8_t _count;
  338.                         if(!propStream.getByte(_count))
  339.                                 return ATTR_READ_ERROR;
  340.  
  341.                         setSubType((uint16_t)_count);
  342.                         break;
  343.                 }
  344.  
  345.                 case ATTR_ACTION_ID:
  346.                 {
  347.                         uint16_t aid;
  348.                         if(!propStream.getShort(aid))
  349.                                 return ATTR_READ_ERROR;
  350.  
  351.                         setAttribute("aid", aid);
  352.                         break;
  353.                 }
  354.  
  355.                 case ATTR_UNIQUE_ID:
  356.                 {
  357.                         uint16_t uid;
  358.                         if(!propStream.getShort(uid))
  359.                                 return ATTR_READ_ERROR;
  360.  
  361.                         setUniqueId(uid);
  362.                         break;
  363.                 }
  364.  
  365.                 case ATTR_NAME:
  366.                 {
  367.                         std::string name;
  368.                         if(!propStream.getString(name))
  369.                                 return ATTR_READ_ERROR;
  370.  
  371.                         setAttribute("name", name);
  372.                         break;
  373.                 }
  374.  
  375.                 case ATTR_PLURALNAME:
  376.                 {
  377.                         std::string name;
  378.                         if(!propStream.getString(name))
  379.                                 return ATTR_READ_ERROR;
  380.  
  381.                         setAttribute("pluralname", name);
  382.                         break;
  383.                 }
  384.  
  385.                 case ATTR_ARTICLE:
  386.                 {
  387.                         std::string article;
  388.                         if(!propStream.getString(article))
  389.                                 return ATTR_READ_ERROR;
  390.  
  391.                         setAttribute("article", article);
  392.                         break;
  393.                 }
  394.  
  395.                 case ATTR_ATTACK:
  396.                 {
  397.                         int32_t attack;
  398.                         if(!propStream.getLong((uint32_t&)attack))
  399.                                 return ATTR_READ_ERROR;
  400.  
  401.                         setAttribute("attack", attack);
  402.                         break;
  403.                 }
  404.  
  405.                 case ATTR_EXTRAATTACK:
  406.                 {
  407.                         int32_t attack;
  408.                         if(!propStream.getLong((uint32_t&)attack))
  409.                                 return ATTR_READ_ERROR;
  410.  
  411.                         setAttribute("extraattack", attack);
  412.                         break;
  413.                 }
  414.  
  415.                 case ATTR_DEFENSE:
  416.                 {
  417.                         int32_t defense;
  418.                         if(!propStream.getLong((uint32_t&)defense))
  419.                                 return ATTR_READ_ERROR;
  420.  
  421.                         setAttribute("defense", defense);
  422.                         break;
  423.                 }
  424.  
  425.                 case ATTR_EXTRADEFENSE:
  426.                 {
  427.                         int32_t defense;
  428.                         if(!propStream.getLong((uint32_t&)defense))
  429.                                 return ATTR_READ_ERROR;
  430.  
  431.                         setAttribute("extradefense", defense);
  432.                         break;
  433.                 }
  434.  
  435.                 case ATTR_ARMOR:
  436.                 {
  437.                         int32_t armor;
  438.                         if(!propStream.getLong((uint32_t&)armor))
  439.                                 return ATTR_READ_ERROR;
  440.  
  441.                         setAttribute("armor", armor);
  442.                         break;
  443.                 }
  444.  
  445.                 case ATTR_ATTACKSPEED:
  446.                 {
  447.                         int32_t attackSpeed;
  448.                         if(!propStream.getLong((uint32_t&)attackSpeed))
  449.                                 return ATTR_READ_ERROR;
  450.  
  451.                         setAttribute("attackspeed", attackSpeed);
  452.                         break;
  453.                 }
  454.  
  455.                 case ATTR_HITCHANCE:
  456.                 {
  457.                         int32_t hitChance;
  458.                         if(!propStream.getLong((uint32_t&)hitChance))
  459.                                 return ATTR_READ_ERROR;
  460.  
  461.                         setAttribute("hitchance", hitChance);
  462.                         break;
  463.                 }
  464.  
  465.                 case ATTR_SCRIPTPROTECTED:
  466.                 {
  467.                         uint8_t protection;
  468.                         if(!propStream.getByte(protection))
  469.                                 return ATTR_READ_ERROR;
  470.  
  471.                         setAttribute("scriptprotected", protection != 0);
  472.                         break;
  473.                 }
  474.  
  475.                 case ATTR_DUALWIELD:
  476.                 {
  477.                         uint8_t wield;
  478.                         if(!propStream.getByte(wield))
  479.                                 return ATTR_READ_ERROR;
  480.  
  481.                         setAttribute("dualwield", wield != 0);
  482.                         break;
  483.                 }
  484.  
  485.                 case ATTR_TEXT:
  486.                 {
  487.                         std::string text;
  488.                         if(!propStream.getString(text))
  489.                                 return ATTR_READ_ERROR;
  490.  
  491.                         setAttribute("text", text);
  492.                         break;
  493.                 }
  494.  
  495.                 case ATTR_WRITTENDATE:
  496.                 {
  497.                         int32_t date;
  498.                         if(!propStream.getLong((uint32_t&)date))
  499.                                 return ATTR_READ_ERROR;
  500.  
  501.                         setAttribute("date", date);
  502.                         break;
  503.                 }
  504.  
  505.                 case ATTR_WRITTENBY:
  506.                 {
  507.                         std::string writer;
  508.                         if(!propStream.getString(writer))
  509.                                 return ATTR_READ_ERROR;
  510.  
  511.                         setAttribute("writer", writer);
  512.                         break;
  513.                 }
  514.  
  515.                 case ATTR_DESC:
  516.                 {
  517.                         std::string text;
  518.                         if(!propStream.getString(text))
  519.                                 return ATTR_READ_ERROR;
  520.  
  521.                         setAttribute("description", text);
  522.                         break;
  523.                 }
  524.  
  525.                 case ATTR_RUNE_CHARGES:
  526.                 {
  527.                         uint8_t charges;
  528.                         if(!propStream.getByte(charges))
  529.                                 return ATTR_READ_ERROR;
  530.  
  531.                         setSubType((uint16_t)charges);
  532.                         break;
  533.                 }
  534.  
  535.                 case ATTR_CHARGES:
  536.                 {
  537.                         uint16_t charges;
  538.                         if(!propStream.getShort(charges))
  539.                                 return ATTR_READ_ERROR;
  540.  
  541.                         setSubType(charges);
  542.                         break;
  543.                 }
  544.  
  545.                 case ATTR_DURATION:
  546.                 {
  547.                         int32_t duration;
  548.                         if(!propStream.getLong((uint32_t&)duration))
  549.                                 return ATTR_READ_ERROR;
  550.  
  551.                         setAttribute("duration", duration);
  552.                         break;
  553.                 }
  554.  
  555.                 case ATTR_DECAYING_STATE:
  556.                 {
  557.                         uint8_t state;
  558.                         if(!propStream.getByte(state))
  559.                                 return ATTR_READ_ERROR;
  560.  
  561.                         if((ItemDecayState_t)state != DECAYING_FALSE)
  562.                                 setAttribute("decaying", (int32_t)DECAYING_PENDING);
  563.  
  564.                         break;
  565.                 }
  566.  
  567.                 //these should be handled through derived classes
  568.                 //if these are called then something has changed in the items.otb since the map was saved
  569.                 //just read the values
  570.  
  571.                 //Depot class
  572.                 case ATTR_DEPOT_ID:
  573.                 {
  574.                         uint16_t depot;
  575.                         if(!propStream.getShort(depot))
  576.                                 return ATTR_READ_ERROR;
  577.  
  578.                         break;
  579.                 }
  580.  
  581.                 //Door class
  582.                 case ATTR_HOUSEDOORID:
  583.                 {
  584.                         uint8_t door;
  585.                         if(!propStream.getByte(door))
  586.                                 return ATTR_READ_ERROR;
  587.  
  588.                         break;
  589.                 }
  590.  
  591.                 //Teleport class
  592.                 case ATTR_TELE_DEST:
  593.                 {
  594.                         TeleportDest* dest;
  595.                         if(!propStream.getStruct(dest))
  596.                                 return ATTR_READ_ERROR;
  597.  
  598.                         break;
  599.                 }
  600.  
  601.                 //Bed class
  602.                 case ATTR_SLEEPERGUID:
  603.                 {
  604.                         uint32_t sleeper;
  605.                         if(!propStream.getLong(sleeper))
  606.                                 return ATTR_READ_ERROR;
  607.  
  608.                         break;
  609.                 }
  610.  
  611.                 case ATTR_SLEEPSTART:
  612.                 {
  613.                         uint32_t sleepStart;
  614.                         if(!propStream.getLong(sleepStart))
  615.                                 return ATTR_READ_ERROR;
  616.  
  617.                         break;
  618.                 }
  619.  
  620.                 //Container class
  621.                 case ATTR_CONTAINER_ITEMS:
  622.                 {
  623.                         uint32_t _count;
  624.                         propStream.getLong(_count);
  625.                         return ATTR_READ_ERROR;
  626.                 }
  627.  
  628.                 //ItemAttributes class
  629.                 case ATTR_ATTRIBUTE_MAP:
  630.                 {
  631.                         bool unique = hasIntegerAttribute("uid"), ret = unserializeMap(propStream);
  632.                         if(!unique && hasIntegerAttribute("uid")) // unfortunately we have to do this
  633.                                 ScriptEnviroment::addUniqueThing(this);
  634.  
  635.                         // this attribute has a custom behavior as well
  636.                         if(getDecaying() != DECAYING_FALSE)
  637.                                 setDecaying(DECAYING_PENDING);
  638.  
  639.                         if(ret)
  640.                                 break;
  641.                 }
  642.  
  643.                 default:
  644.                         return ATTR_READ_ERROR;
  645.         }
  646.  
  647.         return ATTR_READ_CONTINUE;
  648. }
  649.  
  650. bool Item::unserializeAttr(PropStream& propStream)
  651. {
  652.         uint8_t attrType = ATTR_END;
  653.         while(propStream.getByte(attrType) && attrType != ATTR_END)
  654.         {
  655.                 switch(readAttr((AttrTypes_t)attrType, propStream))
  656.                 {
  657.                         case ATTR_READ_ERROR:
  658.                                 return false;
  659.  
  660.                         case ATTR_READ_END:
  661.                                 return true;
  662.  
  663.                         default:
  664.                                 break;
  665.                 }
  666.         }
  667.  
  668.         return true;
  669. }
  670.  
  671. bool Item::serializeAttr(PropWriteStream& propWriteStream) const
  672. {
  673.         if(isStackable() || isFluidContainer() || isSplash())
  674.         {
  675.                 propWriteStream.addByte(ATTR_COUNT);
  676.                 propWriteStream.addByte((uint8_t)getSubType());
  677.         }
  678.  
  679.         if(attributes && !attributes->empty())
  680.         {
  681.                 propWriteStream.addByte(ATTR_ATTRIBUTE_MAP);
  682.                 serializeMap(propWriteStream);
  683.         }
  684.  
  685.         return true;
  686. }
  687.  
  688. bool Item::hasProperty(enum ITEMPROPERTY prop) const
  689. {
  690.         const ItemType& it = items[id];
  691.         switch(prop)
  692.         {
  693.                 case BLOCKSOLID:
  694.                         if(it.blockSolid)
  695.                                 return true;
  696.  
  697.                         break;
  698.  
  699.                 case MOVABLE:
  700.                         if(it.movable && (!loadedFromMap || (!getUniqueId()
  701.                                 && (!getActionId() || !getContainer()))))
  702.                                 return true;
  703.  
  704.                         break;
  705.  
  706.                 case HASHEIGHT:
  707.                         if(it.hasHeight)
  708.                                 return true;
  709.  
  710.                         break;
  711.  
  712.                 case BLOCKPROJECTILE:
  713.                         if(it.blockProjectile)
  714.                                 return true;
  715.  
  716.                         break;
  717.  
  718.                 case BLOCKPATH:
  719.                         if(it.blockPathFind)
  720.                                 return true;
  721.  
  722.                         break;
  723.  
  724.                 case ISVERTICAL:
  725.                         if(it.isVertical)
  726.                                 return true;
  727.  
  728.                         break;
  729.  
  730.                 case ISHORIZONTAL:
  731.                         if(it.isHorizontal)
  732.                                 return true;
  733.  
  734.                         break;
  735.  
  736.                 case IMMOVABLEBLOCKSOLID:
  737.                         if(it.blockSolid && (!it.movable || (loadedFromMap &&
  738.                                 (getUniqueId() || (getActionId() && getContainer())))))
  739.                                 return true;
  740.  
  741.                         break;
  742.  
  743.                 case IMMOVABLEBLOCKPATH:
  744.                         if(it.blockPathFind && (!it.movable || (loadedFromMap &&
  745.                                 (getUniqueId() || (getActionId() && getContainer())))))
  746.                                 return true;
  747.  
  748.                         break;
  749.  
  750.                 case SUPPORTHANGABLE:
  751.                         if(it.isHorizontal || it.isVertical)
  752.                                 return true;
  753.  
  754.                         break;
  755.  
  756.                 case IMMOVABLENOFIELDBLOCKPATH:
  757.                         if(!it.isMagicField() && it.blockPathFind && (!it.movable || (loadedFromMap &&
  758.                                 (getUniqueId() || (getActionId() && getContainer())))))
  759.                                 return true;
  760.  
  761.                         break;
  762.  
  763.                 case NOFIELDBLOCKPATH:
  764.                         if(!it.isMagicField() && it.blockPathFind)
  765.                                 return true;
  766.  
  767.                         break;
  768.  
  769.                 case FLOORCHANGEDOWN:
  770.                         if(it.floorChange[CHANGE_DOWN])
  771.                                 return true;
  772.  
  773.                         break;
  774.  
  775.                 case FLOORCHANGEUP:
  776.                         for(uint16_t i = CHANGE_FIRST; i <= CHANGE_PRE_LAST; ++i)
  777.                         {
  778.                                 if(it.floorChange[i])
  779.                                         return true;
  780.                         }
  781.  
  782.                         break;
  783.  
  784.                 default:
  785.                         break;
  786.         }
  787.  
  788.         return false;
  789. }
  790.  
  791. double Item::getWeight() const
  792. {
  793.         if(isStackable())
  794.                 return items[id].weight * std::max((int32_t)1, (int32_t)count);
  795.  
  796.         return items[id].weight;
  797. }
  798.  
  799. std::string Item::getDescription(const ItemType& it, int32_t lookDistance, const Item* item/* = NULL*/,
  800.         int32_t subType/* = -1*/, bool addArticle/* = true*/)
  801. {
  802.         std::stringstream s;
  803.         s << getNameDescription(it, item, subType, addArticle);
  804.         if(item)
  805.                 subType = item->getSubType();
  806.  
  807.         bool dot = true;
  808.         if(it.isRune())
  809.         {
  810.                 if(!it.runeSpellName.empty())
  811.                         s << "(\"" << it.runeSpellName << "\")";
  812.  
  813.                 if(it.runeLevel > 0 || it.runeMagLevel > 0 || (it.vocationString != "" && it.wieldInfo == 0))
  814.                 {
  815.                         s << "." << std::endl << "It can only be used";
  816.                         if(it.vocationString != "" && it.wieldInfo == 0)
  817.                                 s << " by " << it.vocationString;
  818.  
  819.                         bool begin = true;
  820.                         if(it.runeLevel > 0)
  821.                         {
  822.                                 begin = false;
  823.                                 s << " with level " << it.runeLevel;
  824.                         }
  825.  
  826.                         if(it.runeMagLevel > 0)
  827.                         {
  828.                                 begin = false;
  829.                                 s << " " << (begin ? "with" : "and") << " magic level " << it.runeMagLevel;
  830.                         }
  831.  
  832.                         if(!begin)
  833.                                 s << " or higher";
  834.                 }
  835.         }
  836.         else if(it.weaponType != WEAPON_NONE)
  837.         {
  838.                 bool begin = true;
  839.                 if(it.weaponType == WEAPON_DIST && it.ammoType != AMMO_NONE)
  840.                 {
  841.                         begin = false;
  842.                         s << " (Range:" << int32_t(item ? item->getShootRange() : it.shootRange);
  843.                         if(it.attack || it.extraAttack || (item && (item->getAttack() || item->getExtraAttack())))
  844.                         {
  845.                                 s << ", Atk " << std::showpos << int32_t(item ? item->getAttack() : it.attack);
  846.                                 if(it.extraAttack || (item && item->getExtraAttack()))
  847.                                         s << " " << std::showpos << int32_t(item ? item->getExtraAttack() : it.extraAttack) << std::noshowpos;
  848.                         }
  849.  
  850.                         if(it.hitChance != -1 || (item && item->getHitChance() != -1))
  851.                                 s << ", Hit% " << std::showpos << (item ? item->getHitChance() : it.hitChance) << std::noshowpos;
  852.  
  853.                         if(it.attackSpeed || (item && item->getAttackSpeed()))
  854.                                 s << ", AS: " << (item ? item->getAttackSpeed() : it.attackSpeed);
  855.                 }
  856.                 else if(it.weaponType != WEAPON_AMMO && it.weaponType != WEAPON_WAND)
  857.         {
  858.             if(it.attack || it.extraAttack || (item && (item->getAttack() || item->getExtraAttack())))
  859.             {
  860.                 begin = false;
  861.                 s << " (Atk:";
  862.                 if(it.abilities.elementType != COMBAT_NONE)
  863.                 {
  864.                     s << std::max((int32_t)0, int32_t((item ? item->getAttack() : it.attack) - it.abilities.elementDamage));
  865.                     if(it.extraAttack || (item && item->getExtraAttack()))
  866.                         s << " " << std::showpos << int32_t(item ? item->getExtraAttack() : it.extraAttack) << std::noshowpos;
  867.  
  868.                     s << " physical + " << it.abilities.elementDamage << " " << getCombatName(it.abilities.elementType);
  869.                 }
  870.                 else
  871.                 {
  872.                     s << int32_t(item ? item->getAttack() : it.attack);
  873.                     if(it.extraAttack || (item && item->getExtraAttack()))
  874.                         s << " " << std::showpos << int32_t(item ? item->getExtraAttack() : it.extraAttack) << std::noshowpos;
  875.                 }
  876.             }
  877.  
  878.             if(it.defense || it.extraDefense || (item && (item->getDefense() || item->getExtraDefense())))
  879.             {
  880.                 if(begin)
  881.                 {
  882.                     begin = false;
  883.                     s << " (";
  884.                 }
  885.                 else
  886.                     s << ", ";
  887.  
  888.                 s << "Def:" << int32_t(item ? item->getDefense() : it.defense);
  889.                 if(it.extraDefense || (item && item->getExtraDefense()))
  890.                     s << " " << std::showpos << int32_t(item ? item->getExtraDefense() : it.extraDefense) << std::noshowpos;
  891.             }
  892.         }
  893.  
  894.         for(uint16_t i = SKILL_FIRST; i <= SKILL_LAST; ++i)
  895.         {
  896.             // BEGIN ATTRIBUTES MOD
  897.             // Get the value if any from items attribute list
  898.             boost::any attr = item->getAttribute(CONVERSION::SKILL[i]);
  899.  
  900.             // Make sure we either have abilities or an attribute
  901.             if(!it.abilities.skills[i] && attr.empty())
  902.                 continue;
  903.  
  904.             if(begin)
  905.             {
  906.                 begin = false;
  907.                 s << " (";
  908.             }
  909.             else
  910.                 s << ", ";
  911.  
  912.             // Holds the total increased value
  913.             int32_t val = 0;
  914.  
  915.             // If we have an ability then include that into the answer
  916.             if (it.abilities.skills[i])
  917.                 val = (int32_t)it.abilities.skills[i];
  918.            
  919.             // Make sure the value exist and that it is either float or integer.
  920.             if (!attr.empty() && ((attr.type() == typeid(float)) || (attr.type() == typeid(int32_t))))
  921.             {
  922.                 // Add attribute value to val
  923.                 val += boost::any_cast<int32_t>(attr);
  924.             }
  925.  
  926.             s << getSkillName(i) << " " << std::showpos << val << std::noshowpos;
  927.             // END ATTRIBUTES MOD
  928.         }
  929.  
  930.         // BEGIN ATTRIBUTES MOD
  931.         boost::any attr = item->getAttribute(CONVERSION::STATS[STAT_MAGICLEVEL]);
  932.  
  933.         if(it.abilities.stats[STAT_MAGICLEVEL] || !attr.empty())
  934.         {
  935.             if(begin)
  936.             {
  937.                 begin = false;
  938.                 s << " (";
  939.             }
  940.             else
  941.                 s << ", ";
  942.  
  943.             // Holds the total increased value
  944.             int32_t val = 0;
  945.  
  946.             // If we have an ability then include that into the value
  947.             if (it.abilities.stats[STAT_MAGICLEVEL])
  948.                 val = (int32_t)it.abilities.stats[STAT_MAGICLEVEL];
  949.  
  950.             // Make sure the value exist and that it is either float or integer.
  951.             if (!attr.empty() && ((attr.type() == typeid(float)) || (attr.type() == typeid(int32_t))))
  952.             {
  953.                 // Add attribute value to val
  954.                 val += boost::any_cast<int32_t>(attr);
  955.             }
  956.  
  957.             s << "magic level " << std::showpos << val << std::noshowpos;
  958.         }
  959.         // END ATTRIBUTES MOD
  960.  
  961.                         int32_t show = it.abilities->absorb[COMBAT_ALL];
  962.                         if(!show)
  963.                         {
  964.                                 bool tmp = true;
  965.                                 for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
  966.                                 {
  967.                                         if(!it.abilities->absorb[i])
  968.                                                 continue;
  969.  
  970.                                         if(tmp)
  971.                                         {
  972.                                                 tmp = false;
  973.                                                 if(begin)
  974.                                                 {
  975.                                                         begin = false;
  976.                                                         s << " (";
  977.                                                 }
  978.                                                 else
  979.                                                         s << ", ";
  980.  
  981.                                                 s << "protection ";
  982.                                         }
  983.                                         else
  984.                                                 s << ", ";
  985.  
  986.                                         s << getCombatName((CombatType_t)i) << " " << std::showpos << it.abilities->absorb[i] << std::noshowpos << "%";
  987.                                 }
  988.                         }
  989.                         else
  990.                         {
  991.                                 if(begin)
  992.                                 {
  993.                                         begin = false;
  994.                                         s << " (";
  995.                                 }
  996.                                 else
  997.                                         s << ", ";
  998.  
  999.                                 s << "protection all " << std::showpos << show << std::noshowpos << "%";
  1000.                         }
  1001.  
  1002.                         show = it.abilities->fieldAbsorb[COMBAT_ALL];
  1003.                         if(!show)
  1004.                         {
  1005.                                 bool tmp = true;
  1006.                                 for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
  1007.                                 {
  1008.                                         if(!it.abilities->fieldAbsorb[i])
  1009.                                                 continue;
  1010.  
  1011.                                         if(tmp)
  1012.                                         {
  1013.                                                 tmp = false;
  1014.                                                 if(begin)
  1015.                                                 {
  1016.                                                         begin = false;
  1017.                                                         s << " (";
  1018.                                                 }
  1019.                                                 else
  1020.                                                         s << ", ";
  1021.  
  1022.                                                 s << "protection ";
  1023.                                         }
  1024.                                         else
  1025.                                                 s << ", ";
  1026.  
  1027.                                         s << getCombatName((CombatType_t)i) << " field " << std::showpos << it.abilities->absorb[i] << std::noshowpos << "%";
  1028.                                 }
  1029.                         }
  1030.                         else
  1031.                         {
  1032.                                 if(begin)
  1033.                                 {
  1034.                                         begin = false;
  1035.                                         s << " (";
  1036.                                 }
  1037.                                 else
  1038.                                         s << ", ";
  1039.  
  1040.                                 s << "protection all fields " << std::showpos << show << std::noshowpos << "%";
  1041.                         }
  1042.  
  1043.                         show = it.abilities->reflect[REFLECT_CHANCE][COMBAT_ALL];
  1044.                         if(!show)
  1045.                         {
  1046.                                 bool tmp = true;
  1047.                                 for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
  1048.                                 {
  1049.                                         if(!it.abilities->reflect[REFLECT_CHANCE][i] || !it.abilities->reflect[REFLECT_PERCENT][i])
  1050.                                                 continue;
  1051.  
  1052.                                         if(tmp)
  1053.                                         {
  1054.                                                 tmp = false;
  1055.                                                 if(begin)
  1056.                                                 {
  1057.                                                         begin = false;
  1058.                                                         s << " (";
  1059.                                                 }
  1060.                                                 else
  1061.                                                         s << ", ";
  1062.  
  1063.                                                 s << "reflect: ";
  1064.                                         }
  1065.                                         else
  1066.                                                 s << ", ";
  1067.  
  1068.                                         s << it.abilities->reflect[REFLECT_CHANCE][i] << "% for ";
  1069.                                         if(it.abilities->reflect[REFLECT_PERCENT][i] > 99)
  1070.                                                 s << "whole";
  1071.                                         else if(it.abilities->reflect[REFLECT_PERCENT][i] >= 75)
  1072.                                                 s << "huge";
  1073.                                         else if(it.abilities->reflect[REFLECT_PERCENT][i] >= 50)
  1074.                                                 s << "medium";
  1075.                                         else if(it.abilities->reflect[REFLECT_PERCENT][i] >= 25)
  1076.                                                 s << "small";
  1077.                                         else
  1078.                                                 s << "tiny";
  1079.  
  1080.                                         s << getCombatName((CombatType_t)i);
  1081.                                 }
  1082.  
  1083.                                 if(!tmp)
  1084.                                         s << " damage";
  1085.                         }
  1086.                         else
  1087.                         {
  1088.                                 if(begin)
  1089.                                 {
  1090.                                         begin = false;
  1091.                                         s << " (";
  1092.                                 }
  1093.                                 else
  1094.                                         s << ", ";
  1095.  
  1096.                                 int32_t tmp = it.abilities->reflect[REFLECT_PERCENT][COMBAT_ALL];
  1097.                                 s << "reflect: " << show << "% for ";
  1098.                                 if(tmp)
  1099.                                 {
  1100.                                         if(tmp > 99)
  1101.                                                 s << "whole";
  1102.                                         else if(tmp >= 75)
  1103.                                                 s << "huge";
  1104.                                         else if(tmp >= 50)
  1105.                                                 s << "medium";
  1106.                                         else if(tmp >= 25)
  1107.                                                 s << "small";
  1108.                                         else
  1109.                                                 s << "tiny";
  1110.                                 }
  1111.                                 else
  1112.                                         s << "mixed";
  1113.  
  1114.                                 s << " damage";
  1115.                         }
  1116.  
  1117.                         if(it.abilities->speed)
  1118.                         {
  1119.                                 if(begin)
  1120.                                 {
  1121.                                         begin = false;
  1122.                                         s << " (";
  1123.                                 }
  1124.                                 else
  1125.                                         s << ", ";
  1126.  
  1127.                                 s << "speed " << std::showpos << (int32_t)(it.abilities->speed / 2) << std::noshowpos;
  1128.                         }
  1129.  
  1130.                         if(it.abilities->invisible)
  1131.                         {
  1132.                                 if(begin)
  1133.                                 {
  1134.                                         begin = false;
  1135.                                         s << " (";
  1136.                                 }
  1137.                                 else
  1138.                                         s << ", ";
  1139.  
  1140.                                 s << "invisibility";
  1141.                         }
  1142.  
  1143.                         if(it.abilities->regeneration)
  1144.                         {
  1145.                                 if(begin)
  1146.                                 {
  1147.                                         begin = false;
  1148.                                         s << " (";
  1149.                                 }
  1150.                                 else
  1151.                                         s << ", ";
  1152.  
  1153.                                 s << "faster regeneration";
  1154.                         }
  1155.  
  1156.                         if(it.abilities->manaShield)
  1157.                         {
  1158.                                 if(begin)
  1159.                                 {
  1160.                                         begin = false;
  1161.                                         s << " (";
  1162.                                 }
  1163.                                 else
  1164.                                         s << ", ";
  1165.  
  1166.                                 s << "mana shield";
  1167.                         }
  1168.  
  1169.                         if(hasBitSet(CONDITION_DRUNK, it.abilities->conditionSuppressions))
  1170.                         {
  1171.                                 if(begin)
  1172.                                 {
  1173.                                         begin = false;
  1174.                                         s << " (";
  1175.                                 }
  1176.                                 else
  1177.                                         s << ", ";
  1178.  
  1179.                                 s << "hard drinking";
  1180.                         }
  1181.                 }
  1182.  
  1183.                 if(it.dualWield || (item && item->isDualWield()))
  1184.                 {
  1185.                         if(begin)
  1186.                         {
  1187.                                 begin = false;
  1188.                                 s << " (";
  1189.                         }
  1190.                         else
  1191.                                 s << ", ";
  1192.  
  1193.                         s << "dual wielding";
  1194.                 }
  1195.  
  1196.                 if(!begin)
  1197.                         s << ")";
  1198.         }
  1199.         else if(it.armor || (item && item->getArmor()) || it.showAttributes)
  1200.     {
  1201.         int32_t tmp = it.armor;
  1202.         if(item)
  1203.             tmp = item->getArmor();
  1204.  
  1205.         bool begin = true;
  1206.         if(tmp)
  1207.         {
  1208.             s << " (Arm:" << tmp;
  1209.             begin = false;
  1210.         }
  1211.  
  1212.         for(uint16_t i = SKILL_FIRST; i <= SKILL_LAST; ++i)
  1213.         {
  1214.             // BEGIN ATTRIBUTES MOD
  1215.             // Get the value if any from items attribute list
  1216.             boost::any attr = item->getAttribute(CONVERSION::SKILL[i]);
  1217.  
  1218.             // Make sure we either have abilities or an attribute
  1219.             if(!it.abilities.skills[i] && attr.empty())
  1220.                 continue;
  1221.  
  1222.             if(begin)
  1223.             {
  1224.                 begin = false;
  1225.                 s << " (";
  1226.             }
  1227.             else
  1228.                 s << ", ";
  1229.  
  1230.             // Holds the total increased value
  1231.             int32_t val = 0;
  1232.  
  1233.             // If we have an ability then include that into the value
  1234.             if (it.abilities.skills[i])
  1235.                 val = (int32_t)it.abilities.skills[i];
  1236.  
  1237.             // Make sure the value exist and that it is either float or integer.
  1238.             if (!attr.empty() && ((attr.type() == typeid(float)) || (attr.type() == typeid(int32_t))))
  1239.             {
  1240.                 // Add attribute value to val
  1241.                 val += boost::any_cast<int32_t>(attr);
  1242.             }
  1243.  
  1244.             s << getSkillName(i) << " " << std::showpos << val << std::noshowpos;
  1245.             // END ATTRIBUTES MOD
  1246.         }
  1247.  
  1248.         // BEGIN ATTRIBUTES MOD
  1249.         boost::any attr = item->getAttribute(CONVERSION::STATS[STAT_MAGICLEVEL]);
  1250.  
  1251.         if(it.abilities.stats[STAT_MAGICLEVEL] || !attr.empty())
  1252.         {
  1253.             if(begin)
  1254.             {
  1255.                 begin = false;
  1256.                 s << " (";
  1257.             }
  1258.             else
  1259.                 s << ", ";
  1260.  
  1261.             // Holds the total increased value
  1262.             int32_t val = 0;
  1263.  
  1264.             // If we have an ability then include that into the value
  1265.             if (it.abilities.stats[STAT_MAGICLEVEL])
  1266.                 val = (int32_t)it.abilities.stats[STAT_MAGICLEVEL];
  1267.  
  1268.             // Make sure the value exist and that it is either float or integer.
  1269.             if (!attr.empty() && ((attr.type() == typeid(float)) || (attr.type() == typeid(int32_t))))
  1270.             {
  1271.                 // Add attribute value to val
  1272.                 val += boost::any_cast<int32_t>(attr);
  1273.             }
  1274.  
  1275.             s << "magic level " << std::showpos << val << std::noshowpos;
  1276.         }
  1277.         // END ATTRIBUTES MOD
  1278.  
  1279.                         int32_t show = it.abilities->absorb[COMBAT_ALL];
  1280.                         if(!show)
  1281.                         {
  1282.                                 bool tmp = true;
  1283.                                 for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
  1284.                                 {
  1285.                                         if(!it.abilities->absorb[i])
  1286.                                                 continue;
  1287.  
  1288.                                         if(tmp)
  1289.                                         {
  1290.                                                 tmp = false;
  1291.                                                 if(begin)
  1292.                                                 {
  1293.                                                         begin = false;
  1294.                                                         s << " (";
  1295.                                                 }
  1296.                                                 else
  1297.                                                         s << ", ";
  1298.  
  1299.                                                 s << "protection ";
  1300.                                         }
  1301.                                         else
  1302.                                                 s << ", ";
  1303.  
  1304.                                         s << getCombatName((CombatType_t)i) << " " << std::showpos << it.abilities->absorb[i] << std::noshowpos << "%";
  1305.                                 }
  1306.                         }
  1307.                         else
  1308.                         {
  1309.                                 if(begin)
  1310.                                 {
  1311.                                         begin = false;
  1312.                                         s << " (";
  1313.                                 }
  1314.                                 else
  1315.                                         s << ", ";
  1316.  
  1317.                                 s << "protection all " << std::showpos << show << std::noshowpos << "%";
  1318.                         }
  1319.  
  1320.                         show = it.abilities->reflect[REFLECT_CHANCE][COMBAT_ALL];
  1321.                         if(!show)
  1322.                         {
  1323.                                 bool tmp = true;
  1324.                                 for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
  1325.                                 {
  1326.                                         if(!it.abilities->reflect[REFLECT_CHANCE][i] || !it.abilities->reflect[REFLECT_PERCENT][i])
  1327.                                                 continue;
  1328.  
  1329.                                         if(tmp)
  1330.                                         {
  1331.                                                 tmp = false;
  1332.                                                 if(begin)
  1333.                                                 {
  1334.                                                         begin = false;
  1335.                                                         s << " (";
  1336.                                                 }
  1337.                                                 else
  1338.                                                         s << ", ";
  1339.  
  1340.                                                 s << "reflect: ";
  1341.                                         }
  1342.                                         else
  1343.                                                 s << ", ";
  1344.  
  1345.                                         s << it.abilities->reflect[REFLECT_CHANCE][i] << "% for ";
  1346.                                         if(it.abilities->reflect[REFLECT_PERCENT][i] > 99)
  1347.                                                 s << "whole";
  1348.                                         else if(it.abilities->reflect[REFLECT_PERCENT][i] >= 75)
  1349.                                                 s << "huge";
  1350.                                         else if(it.abilities->reflect[REFLECT_PERCENT][i] >= 50)
  1351.                                                 s << "medium";
  1352.                                         else if(it.abilities->reflect[REFLECT_PERCENT][i] >= 25)
  1353.                                                 s << "small";
  1354.                                         else
  1355.                                                 s << "tiny";
  1356.  
  1357.                                         s << getCombatName((CombatType_t)i);
  1358.                                 }
  1359.  
  1360.                                 if(!tmp)
  1361.                                         s << " damage";
  1362.                         }
  1363.                         else
  1364.                         {
  1365.                                 if(begin)
  1366.                                 {
  1367.                                         begin = false;
  1368.                                         s << " (";
  1369.                                 }
  1370.                                 else
  1371.                                         s << ", ";
  1372.  
  1373.                                 int32_t tmp = it.abilities->reflect[REFLECT_PERCENT][COMBAT_ALL];
  1374.                                 s << "reflect: " << show << "% for ";
  1375.                                 if(tmp)
  1376.                                 {
  1377.                                         if(tmp > 99)
  1378.                                                 s << "whole";
  1379.                                         else if(tmp >= 75)
  1380.                                                 s << "huge";
  1381.                                         else if(tmp >= 50)
  1382.                                                 s << "medium";
  1383.                                         else if(tmp >= 25)
  1384.                                                 s << "small";
  1385.                                         else
  1386.                                                 s << "tiny";
  1387.                                 }
  1388.                                 else
  1389.                                         s << "mixed";
  1390.  
  1391.                                 s << " damage";
  1392.                         }
  1393.  
  1394.                         if(it.abilities->speed)
  1395.                         {
  1396.                                 if(begin)
  1397.                                 {
  1398.                                         begin = false;
  1399.                                         s << " (";
  1400.                                 }
  1401.                                 else
  1402.                                         s << ", ";
  1403.  
  1404.                                 s << "speed " << std::showpos << (int32_t)(it.abilities->speed / 2) << std::noshowpos;
  1405.                         }
  1406.  
  1407.                         if(it.abilities->invisible)
  1408.                         {
  1409.                                 if(begin)
  1410.                                 {
  1411.                                         begin = false;
  1412.                                         s << " (";
  1413.                                 }
  1414.                                 else
  1415.                                         s << ", ";
  1416.  
  1417.                                 s << "invisibility";
  1418.                         }
  1419.  
  1420.                         if(it.abilities.regeneration ||
  1421.             !item->getAttribute(CONVERSION::HEALTH_REGEN_GAIN).empty() ||
  1422.             !item->getAttribute(CONVERSION::HEALTH_REGEN_TICK).empty() ||
  1423.             !item->getAttribute(CONVERSION::MANA_REGEN_GAIN).empty() ||
  1424.             !item->getAttribute(CONVERSION::MANA_REGEN_TICK).empty() )
  1425.             // END ATTRIBUTES MOD
  1426.                         {      
  1427.                                 if(begin)
  1428.                                 {
  1429.                                         begin = false;
  1430.                                         s << " (";
  1431.                                 }
  1432.                                 else
  1433.                                         s << ", ";
  1434.  
  1435.                                 s << "faster regeneration";
  1436.                         }
  1437.  
  1438.                         if(it.abilities->manaShield)
  1439.                         {
  1440.                                 if(begin)
  1441.                                 {
  1442.                                         begin = false;
  1443.                                         s << " (";
  1444.                                 }
  1445.                                 else
  1446.                                         s << ", ";
  1447.  
  1448.                                 s << "mana shield";
  1449.                         }
  1450.  
  1451.                         if(hasBitSet(CONDITION_DRUNK, it.abilities->conditionSuppressions))
  1452.                         {
  1453.                                 if(begin)
  1454.                                 {
  1455.                                         begin = false;
  1456.                                         s << " (";
  1457.                                 }
  1458.                                 else
  1459.                                         s << ", ";
  1460.  
  1461.                                 s << "hard drinking";
  1462.                         }
  1463.  
  1464.                         if(!begin)
  1465.                                 s << ")";
  1466.                 }
  1467.         }
  1468.         else if(it.isContainer())
  1469.                 s << " (Vol:" << (int32_t)it.maxItems << ")";
  1470.         else if(it.isKey())
  1471.                 s << " (Key:" << (item ? (int32_t)item->getActionId() : 0) << ")";
  1472.         else if(it.isFluidContainer())
  1473.         {
  1474.                 if(subType > 0)
  1475.                         s << " of " << (items[subType].name.length() ? items[subType].name : "unknown");
  1476.                 else
  1477.                         s << ". It is empty";
  1478.         }
  1479.         else if(it.isSplash())
  1480.         {
  1481.                 s << " of ";
  1482.                 if(subType > 0 && items[subType].name.length())
  1483.                         s << items[subType].name;
  1484.                 else
  1485.                         s << "unknown";
  1486.         }
  1487.         else if(it.allowDistRead)
  1488.         {
  1489.                 s << "." << std::endl;
  1490.                 if(item && !item->getText().empty())
  1491.                 {
  1492.                         if(lookDistance <= 4)
  1493.                         {
  1494.                                 if(!item->getWriter().empty())
  1495.                                 {
  1496.                                         s << item->getWriter() << " wrote";
  1497.                                         time_t date = item->getDate();
  1498.                                         if(date > 0)
  1499.                                                 s << " on " << formatDate(date);
  1500.  
  1501.                                         s << ": ";
  1502.                                 }
  1503.                                 else
  1504.                                         s << "You read: ";
  1505.  
  1506.                                 std::string text = item->getText();
  1507.                                 s << text;
  1508.  
  1509.                                 char end = *text.rbegin();
  1510.                                 if(end == '?' || end == '!' || end == '.')
  1511.                                         dot = false;
  1512.                         }
  1513.                         else
  1514.                                 s << "You are too far away to read it";
  1515.                 }
  1516.                 else
  1517.                         s << "Nothing is written on it";
  1518.         }
  1519.         else if(it.levelDoor && item && item->getActionId() >= (int32_t)it.levelDoor && item->getActionId()
  1520.                 <= ((int32_t)it.levelDoor + g_config.getNumber(ConfigManager::MAXIMUM_DOOR_LEVEL)))
  1521.                 s << " for level " << item->getActionId() - it.levelDoor;
  1522.  
  1523.         if(it.showCharges)
  1524.                 s << " that has " << subType << " charge" << (subType != 1 ? "s" : "") << " left";
  1525.  
  1526.         if(it.showDuration)
  1527.         {
  1528.                 if(item && item->hasIntegerAttribute("duration"))
  1529.                 {
  1530.                         int32_t duration = item->getDuration() / 1000;
  1531.                         s << " that will expire in ";
  1532.                         if(duration >= 86400)
  1533.                         {
  1534.                                 uint16_t days = duration / 86400;
  1535.                                 uint16_t hours = (duration % 86400) / 3600;
  1536.                                 s << days << " day" << (days > 1 ? "s" : "");
  1537.                                 if(hours > 0)
  1538.                                         s << " and " << hours << " hour" << (hours > 1 ? "s" : "");
  1539.                         }
  1540.                         else if(duration >= 3600)
  1541.                         {
  1542.                                 uint16_t hours = duration / 3600;
  1543.                                 uint16_t minutes = (duration % 3600) / 60;
  1544.                                 s << hours << " hour" << (hours > 1 ? "s" : "");
  1545.                                 if(hours > 0)
  1546.                                         s << " and " << minutes << " minute" << (minutes > 1 ? "s" : "");
  1547.                         }
  1548.                         else if(duration >= 60)
  1549.                         {
  1550.                                 uint16_t minutes = duration / 60;
  1551.                                 uint16_t seconds = duration % 60;
  1552.                                 s << minutes << " minute" << (minutes > 1 ? "s" : "");
  1553.                                 if(seconds > 0)
  1554.                                         s << " and " << seconds << " second" << (seconds > 1 ? "s" : "");
  1555.                         }
  1556.                         else
  1557.                                 s << duration << " second" << (duration > 1 ? "s" : "");
  1558.                 }
  1559.                 else
  1560.                         s << " that is brand-new";
  1561.         }
  1562.  
  1563.         if(dot)
  1564.                 s << ".";
  1565.  
  1566.         if(it.wieldInfo)
  1567.         {
  1568.                 s << std::endl << "It can only be wielded properly by ";
  1569.                 if(it.wieldInfo & WIELDINFO_PREMIUM)
  1570.                         s << "premium ";
  1571.  
  1572.                 if(it.wieldInfo & WIELDINFO_VOCREQ)
  1573.                         s << it.vocationString;
  1574.                 else
  1575.                         s << "players";
  1576.  
  1577.                 if(it.wieldInfo & WIELDINFO_LEVEL)
  1578.                         s << " of level " << (int32_t)it.minReqLevel << " or higher";
  1579.  
  1580.                 if(it.wieldInfo & WIELDINFO_MAGLV)
  1581.                 {
  1582.                         if(it.wieldInfo & WIELDINFO_LEVEL)
  1583.                                 s << " and";
  1584.                         else
  1585.                                 s << " of";
  1586.  
  1587.                         s << " magic level " << (int32_t)it.minReqMagicLevel << " or higher";
  1588.                 }
  1589.  
  1590.                 s << ".";
  1591.         }
  1592.  
  1593.         if(lookDistance <= 1 && it.pickupable)
  1594.         {
  1595.                 std::string tmp;
  1596.                 if(!item)
  1597.                         tmp = getWeightDescription(it.weight, it.stackable && it.showCount, subType);
  1598.                 else
  1599.                         tmp = item->getWeightDescription();
  1600.  
  1601.                 if(!tmp.empty())
  1602.                         s << std::endl << tmp;
  1603.         }
  1604.  
  1605.         if(item && !item->getSpecialDescription().empty())
  1606.                 s << std::endl << item->getSpecialDescription();
  1607.         else if(!it.description.empty() && lookDistance <= 1)
  1608.                 s << std::endl << it.description;
  1609.  
  1610.         std::string str = s.str();
  1611.         if(str.find("|PLAYERNAME|") != std::string::npos)
  1612.         {
  1613.                 std::string tmp = "You";
  1614.                 if(item)
  1615.                 {
  1616.                         if(const Player* player = item->getHoldingPlayer())
  1617.                                 tmp = player->getName();
  1618.                 }
  1619.  
  1620.                 replaceString(str, "|PLAYERNAME|", tmp);
  1621.         }
  1622.  
  1623.         if(str.find("|TIME|") != std::string::npos || str.find("|DATE|") != std::string::npos || str.find(
  1624.                 "|DAY|") != std::string::npos || str.find("|MONTH|") != std::string::npos || str.find(
  1625.                 "|YEAR|") != std::string::npos || str.find("|HOUR|") != std::string::npos || str.find(
  1626.                 "|MINUTES|") != std::string::npos || str.find("|SECONDS|") != std::string::npos ||
  1627.                 str.find("|WEEKDAY|") != std::string::npos || str.find("|YEARDAY|") != std::string::npos)
  1628.         {
  1629.                 time_t now = time(NULL);
  1630.                 tm* ts = localtime(&now);
  1631.  
  1632.                 std::stringstream ss;
  1633.                 ss << ts->tm_sec;
  1634.                 replaceString(str, "|SECONDS|", ss.str());
  1635.  
  1636.                 ss.str("");
  1637.                 ss << ts->tm_min;
  1638.                 replaceString(str, "|MINUTES|", ss.str());
  1639.  
  1640.                 ss.str("");
  1641.                 ss << ts->tm_hour;
  1642.                 replaceString(str, "|HOUR|", ss.str());
  1643.  
  1644.                 ss.str("");
  1645.                 ss << ts->tm_mday;
  1646.                 replaceString(str, "|DAY|", ss.str());
  1647.  
  1648.                 ss.str("");
  1649.                 ss << (ts->tm_mon + 1);
  1650.                 replaceString(str, "|MONTH|", ss.str());
  1651.  
  1652.                 ss.str("");
  1653.                 ss << (ts->tm_year + 1900);
  1654.                 replaceString(str, "|YEAR|", ss.str());
  1655.  
  1656.                 ss.str("");
  1657.                 ss << ts->tm_wday;
  1658.                 replaceString(str, "|WEEKDAY|", ss.str());
  1659.  
  1660.                 ss.str("");
  1661.                 ss << ts->tm_yday;
  1662.                 replaceString(str, "|YEARDAY|", ss.str());
  1663.  
  1664.                 ss.str("");
  1665.                 ss << ts->tm_hour << ":" << ts->tm_min << ":" << ts->tm_sec;
  1666.                 replaceString(str, "|TIME|", ss.str());
  1667.  
  1668.                 ss.str("");
  1669.                 replaceString(str, "|DATE|", formatDateEx(now));
  1670.         }
  1671.  
  1672.         return str;
  1673. }
  1674.  
  1675. std::string Item::getNameDescription(const ItemType& it, const Item* item/* = NULL*/, int32_t subType/* = -1*/, bool addArticle/* = true*/)
  1676. {
  1677.         if(item)
  1678.                 subType = item->getSubType();
  1679.  
  1680.         std::stringstream s;
  1681.         if(it.loaded || (item && !item->getName().empty()))
  1682.         {
  1683.                 if(subType > 1 && it.stackable && it.showCount)
  1684.                         s << subType << " " << (item ? item->getPluralName() : it.pluralName);
  1685.                 else
  1686.                 {
  1687.                         if(addArticle)
  1688.                         {
  1689.                                 if(item && !item->getArticle().empty())
  1690.                                         s << item->getArticle() << " ";
  1691.                                 else if(!it.article.empty())
  1692.                                         s << it.article << " ";
  1693.                         }
  1694.  
  1695.                         s << (item ? item->getName() : it.name);
  1696.                 }
  1697.         }
  1698.         else if(it.name.empty())
  1699.                 s << "an item of type " << it.id << ", please report it to gamemaster";
  1700.         else
  1701.                 s << "an item '" << it.name << "', please report it to gamemaster";
  1702.  
  1703.         return s.str();
  1704. }
  1705.  
  1706. std::string Item::getWeightDescription(double weight, bool stackable, uint32_t count/* = 1*/)
  1707. {
  1708.         if(weight <= 0)
  1709.                 return "";
  1710.  
  1711.         std::stringstream s;
  1712.         if(stackable && count > 1)
  1713.                 s << "They weigh " << std::fixed << std::setprecision(2) << weight << " oz.";
  1714.         else
  1715.                 s << "It weighs " << std::fixed << std::setprecision(2) << weight << " oz.";
  1716.  
  1717.         return s.str();
  1718. }
  1719.  
  1720. void Item::setActionId(int32_t aid, bool callEvent/* = true*/)
  1721. {
  1722.         Tile* tile = NULL;
  1723.         if(callEvent)
  1724.                 tile = getTile();
  1725.  
  1726.         if(tile && getActionId())
  1727.                 g_moveEvents->onRemoveTileItem(tile, this);
  1728.  
  1729.         setAttribute("aid", aid);
  1730.         if(tile)
  1731.                 g_moveEvents->onAddTileItem(tile, this);
  1732. }
  1733.  
  1734. void Item::resetActionId(bool callEvent/* = true*/)
  1735. {
  1736.         if(!getActionId())
  1737.                 return;
  1738.  
  1739.         Tile* tile = NULL;
  1740.         if(callEvent)
  1741.                 tile = getTile();
  1742.  
  1743.         eraseAttribute("aid");
  1744.         if(tile)
  1745.                 g_moveEvents->onAddTileItem(tile, this);
  1746. }
  1747.  
  1748. void Item::setUniqueId(int32_t uid)
  1749. {
  1750.         if(getUniqueId())
  1751.                 return;
  1752.  
  1753.         setAttribute("uid", uid);
  1754.         ScriptEnviroment::addUniqueThing(this);
  1755. }
  1756.  
  1757. bool Item::canDecay()
  1758. {
  1759.         if(isRemoved())
  1760.                 return false;
  1761.  
  1762.         if(loadedFromMap && (getUniqueId() || (getActionId() && getContainer())))
  1763.                 return false;
  1764.  
  1765.         const ItemType& it = Item::items[id];
  1766.         return it.decayTo >= 0 && it.decayTime;
  1767. }
  1768.  
  1769. void Item::getLight(LightInfo& lightInfo)
  1770. {
  1771.         const ItemType& it = items[id];
  1772.         lightInfo.color = it.lightColor;
  1773.         lightInfo.level = it.lightLevel;
  1774. }
  1775.  
  1776. void Item::__startDecaying()
  1777. {
  1778.         g_game.startDecay(this);
  1779. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top