Guest User

Untitled

a guest
Jul 16th, 2018
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 24.09 KB | None | 0 0
  1.  
  2. #include "otpch.h"
  3. #include "house.h"
  4.  
  5. #include "tools.h"
  6. #include "database.h"
  7. #include "beds.h"
  8. #include "town.h"
  9.  
  10. #include "iologindata.h"
  11. #include "ioguild.h"
  12. #include "iomapserialize.h"
  13.  
  14. #include "configmanager.h"
  15. #include "game.h"
  16.  
  17. extern ConfigManager g_config;
  18. extern Game g_game;
  19.  
  20. House::House(uint32_t houseId)
  21. {
  22.     guild = pendingTransfer = false;
  23.     name = "Forgotten headquarter (Flat 1, Area 42)";
  24.     entry = Position();
  25.     id = houseId;
  26.     rent = price = townId = paidUntil = owner = rentWarnings = lastWarning = 0;
  27.     syncFlags = HOUSE_SYNC_NAME | HOUSE_SYNC_TOWN | HOUSE_SYNC_SIZE | HOUSE_SYNC_PRICE | HOUSE_SYNC_RENT | HOUSE_SYNC_GUILD;
  28. }
  29.  
  30. void House::addTile(HouseTile* tile)
  31. {
  32.     tile->setFlag(TILESTATE_PROTECTIONZONE);
  33.     houseTiles.push_back(tile);
  34. }
  35.  
  36. void House::addBed(BedItem* bed)
  37. {
  38.     bedsList.push_back(bed);
  39.     bed->setHouse(this);
  40. }
  41.  
  42. void House::addDoor(Door* door)
  43. {
  44.     door->addRef();
  45.     doorList.push_back(door);
  46.  
  47.     door->setHouse(this);
  48.     updateDoorDescription("", door);
  49. }
  50.  
  51. void House::removeDoor(Door* door)
  52. {
  53.     HouseDoorList::iterator it = std::find(doorList.begin(), doorList.end(), door);
  54.     if(it != doorList.end())
  55.     {
  56.         (*it)->unRef();
  57.         doorList.erase(it);
  58.     }
  59. }
  60.  
  61. Door* House::getDoorByNumber(uint32_t doorId) const
  62. {
  63.     for(HouseDoorList::const_iterator it = doorList.begin(); it != doorList.end(); ++it)
  64.     {
  65.         if((*it)->getDoorId() == doorId)
  66.             return (*it);
  67.     }
  68.  
  69.     return NULL;
  70. }
  71.  
  72. Door* House::getDoorByPosition(const Position& pos)
  73. {
  74.     for(HouseDoorList::iterator it = doorList.begin(); it != doorList.end(); ++it)
  75.     {
  76.         if((*it)->getPosition() == pos)
  77.             return (*it);
  78.     }
  79.  
  80.     return NULL;
  81. }
  82.  
  83. void House::setOwner(uint32_t guid)
  84. {
  85.     owner = guid;
  86.     updateDoorDescription();
  87. }
  88.  
  89. bool House::setOwnerEx(uint32_t guid, bool transfer)
  90. {
  91.     if(owner == guid)
  92.         return true;
  93.  
  94.     if(isGuild() && guid)
  95.     {
  96.         Player* player = g_game.getPlayerByGuidEx(guid);
  97.         if(!player)
  98.             return false;
  99.  
  100.         guid = player->getGuildId();
  101.         if(player->isVirtual())
  102.             delete player;
  103.     }
  104.  
  105.     if(owner)
  106.     {
  107.         rentWarnings = paidUntil = 0;
  108.         if(transfer)
  109.             clean();
  110.  
  111.         setAccessList(SUBOWNER_LIST, "", !transfer);
  112.         setAccessList(GUEST_LIST, "", !transfer);
  113.         for(HouseDoorList::iterator it = doorList.begin(); it != doorList.end(); ++it)
  114.             (*it)->setAccessList("");
  115.     }
  116.  
  117.     setOwner(guid);
  118.     lastWarning = guid ? time(NULL) : 0;
  119.  
  120.     Database* db = Database::getInstance();
  121.     DBTransaction trans(db);
  122.     if(!trans.begin())
  123.         return false;
  124.  
  125.     IOMapSerialize::getInstance()->saveHouse(db, this);
  126.     return trans.commit();
  127. }
  128.  
  129. bool House::isGuild() const
  130. {
  131.     return g_config.getBool(ConfigManager::GUILD_HALLS) && guild;
  132. }
  133.  
  134. bool House::isBidded() const
  135. {
  136.     Database* db = Database::getInstance();
  137.     DBResult* result;
  138.  
  139.     DBQuery query;
  140.     query << "SELECT `house_id` FROM `house_auctions` WHERE `house_id` = " << id << " LIMIT 1";
  141.     if(!(result = db->storeQuery(query.str())))
  142.         return false;
  143.  
  144.     result->free();
  145.     return true;
  146. }
  147.  
  148. void House::updateDoorDescription(std::string _name/* = ""*/, Door* door/* = NULL*/)
  149. {
  150.     std::string tmp = "house";
  151.     if(isGuild())
  152.         tmp = "hall";
  153.  
  154.     char houseDescription[200];
  155.     if(owner)
  156.     {
  157.         if(isGuild())
  158.             IOGuild::getInstance()->getGuildById(_name, owner);
  159.         else if(_name.empty())
  160.             IOLoginData::getInstance()->getNameByGuid(owner, _name);
  161.  
  162.         sprintf(houseDescription, "It belongs to %s '%s'. %s owns this %s.", tmp.c_str(), name.c_str(), _name.c_str(), tmp.c_str());
  163.     }
  164.     else
  165.         sprintf(houseDescription, "It belongs to %s '%s'. Nobody owns this %s. It costs %d gold coins.", tmp.c_str(), name.c_str(), tmp.c_str(), price);
  166.  
  167.     if(!door)
  168.     {
  169.         for(HouseDoorList::iterator it = doorList.begin(); it != doorList.end(); ++it)
  170.             (*it)->setSpecialDescription(houseDescription);
  171.     }
  172.     else
  173.         door->setSpecialDescription(houseDescription);
  174. }
  175.  
  176. void House::removePlayer(Player* player, bool ignoreRights)
  177. {
  178.     if(!ignoreRights && player->hasFlag(PlayerFlag_CanEditHouses))
  179.         return;
  180.  
  181.     Position curPos = player->getPosition(), newPos = g_game.getClosestFreeTile(player, entry, false, false);
  182.     if(g_game.internalTeleport(player, newPos, false) == RET_NOERROR && !player->isGhost())
  183.     {
  184.         g_game.addMagicEffect(curPos, MAGIC_EFFECT_POFF);
  185.         g_game.addMagicEffect(newPos, MAGIC_EFFECT_TELEPORT);
  186.     }
  187. }
  188.  
  189. void House::removePlayers(bool ignoreInvites)
  190. {
  191.     PlayerVector kickList;
  192.     for(HouseTileList::iterator it = houseTiles.begin(); it != houseTiles.end(); ++it)
  193.     {
  194.         CreatureVector* creatures = (*it)->getCreatures();
  195.         if(!creatures)
  196.             continue;
  197.  
  198.         Player* player = NULL;
  199.         for(CreatureVector::iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
  200.         {
  201.             if((player = (*cit)->getPlayer()) && !player->isRemoved()
  202.                 && (ignoreInvites || !isInvited(player)))
  203.                 kickList.push_back(player);
  204.         }
  205.     }
  206.  
  207.     if(kickList.empty())
  208.         return;
  209.  
  210.     for(PlayerVector::iterator it = kickList.begin(); it != kickList.end(); ++it)
  211.         removePlayer((*it), false);
  212. }
  213.  
  214. bool House::kickPlayer(Player* player, Player* target)
  215. {
  216.     if(!target || target->isRemoved())
  217.         return false;
  218.  
  219.     HouseTile* houseTile = target->getTile()->getHouseTile();
  220.     if(!houseTile || houseTile->getHouse() != this)
  221.         return false;
  222.  
  223.     bool self = player == target;
  224.     if(getHouseAccessLevel(player) < getHouseAccessLevel(target) && !self)
  225.         return false;
  226.  
  227.     removePlayer(target, self);
  228.     return true;
  229. }
  230.  
  231. void House::clean()
  232. {
  233.     for(HouseBedList::iterator bit = bedsList.begin(); bit != bedsList.end(); ++bit)
  234.     {
  235.         if((*bit)->getSleeper())
  236.             (*bit)->wakeUp();
  237.     }
  238.  
  239.     removePlayers(true);
  240.     transferToDepot();
  241. }
  242.  
  243. bool House::transferToDepot()
  244. {
  245.     if(!townId)
  246.         return false;
  247.  
  248.     Player* player = NULL;
  249.     if(owner)
  250.     {
  251.         uint32_t tmp = owner;
  252.         if(isGuild() && !IOGuild::getInstance()->swapGuildIdToOwner(tmp))
  253.             tmp = 0;
  254.  
  255.         if(tmp)
  256.             player = g_game.getPlayerByGuidEx(tmp);
  257.     }
  258.  
  259.     Container* tmpContainer = NULL;
  260.     TileItemVector* items = NULL;
  261.  
  262.     ItemList moveList;
  263.     for(HouseTileList::iterator it = houseTiles.begin(); it != houseTiles.end(); ++it)
  264.     {
  265.         if(!(items = (*it)->getItemList()))
  266.             continue;
  267.  
  268.         for(ItemVector::iterator iit = items->begin(); iit != items->end(); ++iit)
  269.         {
  270.             if((*iit)->isPickupable())
  271.                 moveList.push_back(*iit);
  272.             else if((tmpContainer = (*iit)->getContainer()))
  273.             {
  274.                 for(ItemList::const_iterator cit = tmpContainer->getItems(); cit != tmpContainer->getEnd(); ++cit)
  275.                     moveList.push_back(*cit);
  276.             }
  277.         }
  278.     }
  279.  
  280.     if(player)
  281.     {
  282.         Depot* depot = player->getDepot(townId, true);
  283.         for(ItemList::iterator it = moveList.begin(); it != moveList.end(); ++it)
  284.             g_game.internalMoveItem(NULL, (*it)->getParent(), depot, INDEX_WHEREEVER, (*it), (*it)->getItemCount(), NULL, FLAG_NOLIMIT);
  285.  
  286.         if(player->isVirtual())
  287.         {
  288.             IOLoginData::getInstance()->savePlayer(player);
  289.             delete player;
  290.         }
  291.     }
  292.     else
  293.     {
  294.         for(ItemList::iterator it = moveList.begin(); it != moveList.end(); ++it)
  295.             g_game.internalRemoveItem(NULL, (*it), (*it)->getItemCount(), false, FLAG_NOLIMIT);
  296.     }
  297.  
  298.     return true;
  299. }
  300.  
  301. bool House::isInvited(const Player* player)
  302. {
  303.     return getHouseAccessLevel(player) != HOUSE_NO_INVITED;
  304. }
  305.  
  306. AccessHouseLevel_t House::getHouseAccessLevel(const Player* player)
  307. {
  308.     if(!player)
  309.         return HOUSE_NO_INVITED;
  310.  
  311.     if(player->hasFlag(PlayerFlag_CanEditHouses))
  312.         return HOUSE_OWNER;
  313.  
  314.     if(!owner)
  315.         return HOUSE_NO_INVITED;
  316.  
  317.     AccessHouseLevel_t tmp = HOUSE_NO_INVITED;
  318.     if(isGuild())
  319.     {
  320.         if(player->getGuildId() == owner)
  321.         {
  322.             switch(player->getGuildLevel())
  323.             {
  324.                 case GUILDLEVEL_LEADER:
  325.                     return HOUSE_OWNER;
  326.                 case GUILDLEVEL_VICE:
  327.                     return HOUSE_SUBOWNER;
  328.                 default:
  329.                     tmp = HOUSE_GUEST;
  330.             }
  331.         }
  332.     }
  333.     else if(player->getGUID() == owner || player->marriage == owner)
  334.         return HOUSE_OWNER;
  335.  
  336.     if(subOwnerList.isInList(player))
  337.         return HOUSE_SUBOWNER;
  338.  
  339.     if(guestList.isInList(player))
  340.         return HOUSE_GUEST;
  341.  
  342.     return tmp;
  343. }
  344.  
  345. bool House::canEditAccessList(uint32_t listId, const Player* player)
  346. {
  347.     switch(getHouseAccessLevel(player))
  348.     {
  349.         case HOUSE_OWNER:
  350.             return true;
  351.         case HOUSE_SUBOWNER:
  352.             return listId == GUEST_LIST;
  353.         default:
  354.             break;
  355.     }
  356.  
  357.     return false;
  358. }
  359.  
  360. bool House::getAccessList(uint32_t listId, std::string& list) const
  361. {
  362.     if(listId == GUEST_LIST)
  363.     {
  364.         guestList.getList(list);
  365.         return true;
  366.     }
  367.  
  368.     if(listId == SUBOWNER_LIST)
  369.     {
  370.         subOwnerList.getList(list);
  371.         return true;
  372.     }
  373.  
  374.     if(Door* door = getDoorByNumber(listId))
  375.         return door->getAccessList(list);
  376.  
  377.     #ifdef __DEBUG_HOUSES__
  378.     std::clog << "[Failure - House::getAccessList] door == NULL, listId = " << listId <<std::endl;
  379.     #endif
  380.     return false;
  381. }
  382.  
  383. void House::setAccessList(uint32_t listId, const std::string& textlist, bool teleport/* = true*/)
  384. {
  385.     if(listId == GUEST_LIST)
  386.         guestList.parseList(textlist);
  387.     else if(listId == SUBOWNER_LIST)
  388.         subOwnerList.parseList(textlist);
  389.     else
  390.     {
  391.         if(Door* door = getDoorByNumber(listId))
  392.             door->setAccessList(textlist);
  393.         #ifdef __DEBUG_HOUSES__
  394.         else
  395.             std::clog << "[Failure - House::setAccessList] door == NULL, listId = " << listId <<std::endl;
  396.         #endif
  397.  
  398.         return;
  399.     }
  400.  
  401.     if(teleport)
  402.         removePlayers(false);
  403. }
  404.  
  405. TransferItem* TransferItem::createTransferItem(House* house)
  406. {
  407.     TransferItem* transferItem = new TransferItem(house);
  408.     transferItem->addRef();
  409.     transferItem->setID(ITEM_HOUSE_TRANSFER);
  410.  
  411.     char buffer[150];
  412.     sprintf(buffer, "It is a %s transfer document for '%s'.", house->isGuild() ? "guild hall" : "house", house->getName().c_str());
  413.     transferItem->setSpecialDescription(buffer);
  414.  
  415.     transferItem->setSubType(1);
  416.     return transferItem;
  417. }
  418.  
  419. bool TransferItem::onTradeEvent(TradeEvents_t event, Player* owner, Player* seller)
  420. {
  421.     switch(event)
  422.     {
  423.         case ON_TRADE_TRANSFER:
  424.         {
  425.             if(house)
  426.                 house->setOwnerEx(owner->getGUID(), true);
  427.  
  428.             g_game.internalRemoveItem(NULL, this, getItemCount());
  429.             seller->transferContainer.setParent(NULL);
  430.             break;
  431.         }
  432.  
  433.         case ON_TRADE_CANCEL:
  434.         {
  435.             owner->transferContainer.setParent(NULL);
  436.             owner->transferContainer.__removeThing(this, getItemCount());
  437.             g_game.freeThing(this);
  438.             break;
  439.         }
  440.  
  441.         default:
  442.             return false;
  443.     }
  444.  
  445.     return true;
  446. }
  447.  
  448. void AccessList::getList(std::string& _list) const
  449. {
  450.     _list = list;
  451. }
  452.  
  453. bool AccessList::parseList(const std::string& _list)
  454. {
  455.     playerList.clear();
  456.     guildList.clear();
  457.     expressionList.clear();
  458.     regexList.clear();
  459.  
  460.     list = _list;
  461.     if(_list.empty())
  462.         return true;
  463.  
  464.     std::stringstream listStream(_list);
  465.     std::string line;
  466.     while(getline(listStream, line))
  467.     {
  468.         trimString(line);
  469.         trim_left(line, "\t");
  470.  
  471.         trim_right(line, "\t");
  472.         trimString(line);
  473.  
  474.         toLowerCaseString(line);
  475.         if(line.substr(0, 1) == "#" || line.length() > 100)
  476.             continue;
  477.  
  478.         if(line.find("@") != std::string::npos)
  479.         {
  480.             std::string::size_type pos = line.find("@");
  481.             addGuild(line.substr(pos + 1), line.substr(0, pos));
  482.         }
  483.         else if(line.find("!") != std::string::npos || line.find("*") != std::string::npos || line.find("?") != std::string::npos)
  484.             addExpression(line);
  485.         else
  486.             addPlayer(line);
  487.     }
  488.  
  489.     return true;
  490. }
  491.  
  492. bool AccessList::isInList(const Player* player)
  493. {
  494.     std::string name = player->getName();
  495.     boost::cmatch what;
  496.     try
  497.     {
  498.         toLowerCaseString(name);
  499.         for(RegexList::iterator it = regexList.begin(); it != regexList.end(); ++it)
  500.         {
  501.             if(boost::regex_match(name.c_str(), what, it->first))
  502.                 return it->second;
  503.         }
  504.     }
  505.     catch(...) {}
  506.  
  507.     if(playerList.find(player->getGUID()) != playerList.end())
  508.         return true;
  509.  
  510.     for(GuildList::iterator git = guildList.begin(); git != guildList.end(); ++git)
  511.     {
  512.         if(git->first == player->getGuildId() && ((uint32_t)git->second == player->getRankId() || git->second == -1))
  513.             return true;
  514.     }
  515.  
  516.     return false;
  517. }
  518.  
  519. bool AccessList::addPlayer(std::string& name)
  520. {
  521.     std::string tmp = name;
  522.     uint32_t guid;
  523.     if(!IOLoginData::getInstance()->getGuidByName(guid, tmp) || playerList.find(guid) != playerList.end())
  524.         return false;
  525.  
  526.     playerList.insert(guid);
  527.     return true;
  528. }
  529.  
  530. bool AccessList::addGuild(const std::string& guildName, const std::string& rankName)
  531. {
  532.     uint32_t guildId;
  533.     if(!IOGuild::getInstance()->getGuildId(guildId, guildName))
  534.         return false;
  535.  
  536.     std::string tmp = rankName;
  537.     int32_t rankId = IOGuild::getInstance()->getRankIdByName(guildId, tmp);
  538.     if(!rankId && (tmp.find("?") == std::string::npos || tmp.find("!") == std::string::npos || tmp.find("*") == std::string::npos))
  539.         rankId = -1;
  540.  
  541.     if(!rankId)
  542.         return false;
  543.  
  544.     for(GuildList::iterator git = guildList.begin(); git != guildList.end(); ++git)
  545.     {
  546.         if(git->first == guildId && git->second == rankId)
  547.             return true;
  548.     }
  549.  
  550.     guildList.push_back(std::make_pair(guildId, rankId));
  551.     return true;
  552. }
  553.  
  554. bool AccessList::addExpression(const std::string& expression)
  555. {
  556.     for(ExpressionList::iterator it = expressionList.begin(); it != expressionList.end(); ++it)
  557.     {
  558.         if((*it) == expression)
  559.             return false;
  560.     }
  561.  
  562.     std::string out, meta = ".[{}()\\+|^$";
  563.     for(std::string::const_iterator it = expression.begin(); it != expression.end(); ++it)
  564.     {
  565.         if(meta.find(*it) != std::string::npos)
  566.             out += "\\";
  567.  
  568.         out += (*it);
  569.     }
  570.  
  571.     replaceString(out, "**", "");
  572.     replaceString(out, "*", ".*");
  573.     replaceString(out, "?", ".?");
  574.  
  575.     try
  576.     {
  577.         if(out.length() > 0)
  578.         {
  579.             expressionList.push_back(out);
  580.             if(out.substr(0, 1) == "!")
  581.             {
  582.                 if(out.length() > 1)
  583.                     regexList.push_front(std::make_pair(boost::regex(out.substr(1)), false));
  584.             }
  585.             else
  586.                 regexList.push_back(std::make_pair(boost::regex(out), true));
  587.         }
  588.     }
  589.     catch(...) {}
  590.     return true;
  591. }
  592.  
  593. Door::~Door()
  594. {
  595.     delete accessList;
  596. }
  597.  
  598. Attr_ReadValue Door::readAttr(AttrTypes_t attr, PropStream& propStream)
  599. {
  600.     if(attr != ATTR_HOUSEDOORID)
  601.         return Item::readAttr(attr, propStream);
  602.  
  603.     uint8_t doorId = 0;
  604.     if(!propStream.getByte(doorId))
  605.         return ATTR_READ_ERROR;
  606.  
  607.     setDoorId(doorId);
  608.     return ATTR_READ_CONTINUE;
  609. }
  610.  
  611. void Door::copyAttributes(Item* item)
  612. {
  613.     Item::copyAttributes(item);
  614.     if(Door* door = item->getDoor())
  615.     {
  616.         std::string list;
  617.         if(door->getAccessList(list))
  618.             setAccessList(list);
  619.     }
  620. }
  621.  
  622. void Door::onRemoved()
  623. {
  624.     Item::onRemoved();
  625.     if(house)
  626.         house->removeDoor(this);
  627. }
  628.  
  629. bool Door::canUse(const Player* player)
  630. {
  631.     if(!house || house->getHouseAccessLevel(player) >= HOUSE_SUBOWNER)
  632.         return true;
  633.  
  634.     return accessList->isInList(player);
  635. }
  636.  
  637. void Door::setHouse(House* _house)
  638. {
  639.     if(house)
  640.         return;
  641.  
  642.     house = _house;
  643.     if(!accessList)
  644.         accessList = new AccessList();
  645. }
  646.  
  647. bool Door::getAccessList(std::string& list) const
  648. {
  649.     if(!house)
  650.         return false;
  651.  
  652.     accessList->getList(list);
  653.     return true;
  654. }
  655.  
  656. void Door::setAccessList(const std::string& textlist)
  657. {
  658.     if(!accessList)
  659.         accessList = new AccessList();
  660.  
  661.     accessList->parseList(textlist);
  662. }
  663.  
  664. Houses::Houses()
  665. {
  666.     rentPeriod = RENTPERIOD_NEVER;
  667.     std::string strValue = asLowerCaseString(g_config.getString(ConfigManager::HOUSE_RENT_PERIOD));
  668.     if(strValue == "yearly")
  669.         rentPeriod = RENTPERIOD_YEARLY;
  670.     else if(strValue == "monthly")
  671.         rentPeriod = RENTPERIOD_MONTHLY;
  672.     else if(strValue == "weekly")
  673.         rentPeriod = RENTPERIOD_WEEKLY;
  674.     else if(strValue == "daily")
  675.         rentPeriod = RENTPERIOD_DAILY;
  676. }
  677.  
  678. bool Houses::loadFromXml(std::string filename)
  679. {
  680.     xmlDocPtr doc = xmlParseFile(filename.c_str());
  681.     if(!doc)
  682.     {
  683.         std::clog << "[Warning - Houses::loadFromXml] Cannot load houses file." << std::endl;
  684.         std::clog << getLastXMLError() << std::endl;
  685.         return false;
  686.     }
  687.  
  688.     xmlNodePtr houseNode, root = xmlDocGetRootElement(doc);
  689.     if(xmlStrcmp(root->name,(const xmlChar*)"houses"))
  690.     {
  691.         std::clog << "[Error - Houses::loadFromXml] Malformed houses file." << std::endl;
  692.         xmlFreeDoc(doc);
  693.         return false;
  694.     }
  695.  
  696.     int32_t intValue;
  697.     std::string strValue;
  698.  
  699.     houseNode = root->children;
  700.     while(houseNode)
  701.     {
  702.         if(xmlStrcmp(houseNode->name,(const xmlChar*)"house"))
  703.         {
  704.             houseNode = houseNode->next;
  705.             continue;
  706.         }
  707.  
  708.         int32_t houseId = 0;
  709.         if(!readXMLInteger(houseNode, "houseid", houseId))
  710.         {
  711.             std::clog << "[Error - Houses::loadFromXml] Could not read houseId" << std::endl;
  712.             xmlFreeDoc(doc);
  713.             return false;
  714.         }
  715.  
  716.         House* house = Houses::getInstance()->getHouse(houseId);
  717.         if(!house)
  718.         {
  719.             std::clog << "[Error - Houses::loadFromXml] Unknown house with id: " << houseId << std::endl;
  720.             xmlFreeDoc(doc);
  721.             return false;
  722.         }
  723.  
  724.         Position entry(0, 0, 0);
  725.         if(readXMLInteger(houseNode, "entryx", intValue))
  726.             entry.x = intValue;
  727.  
  728.         if(readXMLInteger(houseNode, "entryy", intValue))
  729.             entry.y = intValue;
  730.  
  731.         if(readXMLInteger(houseNode, "entryz", intValue))
  732.             entry.z = intValue;
  733.  
  734.         house->setEntry(entry);
  735.         if(!entry.x || !entry.y)
  736.         {
  737.             std::clog << "[Warning - Houses::loadFromXml] House entry not set for: ";
  738.             std::clog << house->getName() << " (" << houseId << ")" << std::endl;
  739.         }
  740.  
  741.         if(readXMLString(houseNode, "name", strValue))
  742.             house->setName(strValue);
  743.         else
  744.             house->resetSyncFlag(House::HOUSE_SYNC_NAME);
  745.  
  746.         if(readXMLInteger(houseNode, "townid", intValue))
  747.             house->setTownId(intValue);
  748.         else
  749.             house->resetSyncFlag(House::HOUSE_SYNC_TOWN);
  750.  
  751.         if(readXMLInteger(houseNode, "size", intValue))
  752.             house->setSize(intValue);
  753.         else
  754.             house->resetSyncFlag(House::HOUSE_SYNC_SIZE);
  755.  
  756.         if(readXMLString(houseNode, "guildhall", strValue))
  757.             house->setGuild(booleanString(strValue));
  758.         else
  759.             house->resetSyncFlag(House::HOUSE_SYNC_GUILD);
  760.  
  761.         uint32_t rent = 0;
  762.         if(readXMLInteger(houseNode, "rent", intValue))
  763.             rent = intValue;
  764.  
  765.         uint32_t price = (house->getSize() + house->getBedsCount()) * g_config.getNumber(ConfigManager::HOUSE_PRICE);
  766.         // we should let players to pay only for walkable tiles + beds as single units not two items.
  767.         if(g_config.getBool(ConfigManager::HOUSE_RENTASPRICE) && rent)
  768.             price = rent;
  769.  
  770.         house->setPrice(price);
  771.         if(g_config.getBool(ConfigManager::HOUSE_PRICEASRENT))
  772.             house->setRent(price);
  773.         else
  774.             house->setRent(rent);
  775.  
  776.         house->setOwner(0);
  777.         houseNode = houseNode->next;
  778.     }
  779.  
  780.     xmlFreeDoc(doc);
  781.     return true;
  782. }
  783.  
  784. void Houses::check()
  785. {
  786.     uint64_t start = OTSYS_TIME();
  787.     std::clog << "> Checking houses..." << std::endl;
  788.  
  789.     time_t currentTime = time(NULL);
  790.     for(HouseMap::iterator it = houseMap.begin(); it != houseMap.end(); ++it)
  791.         payHouse(it->second, currentTime, 0);
  792.  
  793.     std::clog << "Houses checked in " << (OTSYS_TIME() - start) / (1000.) << " seconds." << std::endl;
  794. }
  795.  
  796. bool Houses::payRent(Player* player, House* house, uint32_t bid, time_t _time/* = 0*/)
  797. {
  798.     if(rentPeriod == RENTPERIOD_NEVER || !house->getOwner() ||
  799.         house->getPaidUntil() > _time || !house->getRent() ||
  800.         player->hasCustomFlag(PlayerCustomFlag_IgnoreHouseRent))
  801.         return true;
  802.  
  803.     Town* town = Towns::getInstance()->getTown(house->getTownId());
  804.     if(!town)
  805.         return false;
  806.  
  807.     bool paid = false;
  808.     uint32_t amount = house->getRent() + bid;
  809.     if(g_config.getBool(ConfigManager::BANK_SYSTEM) && player->balance >= amount)
  810.     {
  811.         player->balance -= amount;
  812.         paid = true;
  813.     }
  814.     else if(Depot* depot = player->getDepot(town->getID(), true))
  815.         paid = g_game.removeMoney(depot, amount, FLAG_NOLIMIT);
  816.  
  817.     if(!paid)
  818.         return false;
  819.  
  820.     if(!_time)
  821.         _time = time(NULL);
  822.  
  823.     uint32_t paidUntil = _time;
  824.     switch(rentPeriod)
  825.     {
  826.         case RENTPERIOD_DAILY:
  827.             paidUntil += 86400;
  828.             break;
  829.         case RENTPERIOD_WEEKLY:
  830.             paidUntil += 7 * 86400;
  831.             break;
  832.         case RENTPERIOD_MONTHLY:
  833.             paidUntil += 30 * 86400;
  834.             break;
  835.         case RENTPERIOD_YEARLY:
  836.             paidUntil += 365 * 86400;
  837.             break;
  838.         default:
  839.             break;
  840.     }
  841.  
  842.     house->setLastWarning(0);
  843.     house->setRentWarnings(0);
  844.  
  845.     house->setPaidUntil(paidUntil);
  846.     return true;
  847. }
  848.  
  849. bool Houses::payHouse(House* house, time_t _time, uint32_t bid)
  850. {
  851.     if(rentPeriod == RENTPERIOD_NEVER || !house->getOwner() ||
  852.         house->getPaidUntil() > _time || !house->getRent())
  853.         return true;
  854.  
  855.     Town* town = Towns::getInstance()->getTown(house->getTownId());
  856.     if(!town)
  857.         return false;
  858.  
  859.     uint32_t owner = house->getOwner();
  860.     if(house->isGuild() && !IOGuild::getInstance()->swapGuildIdToOwner(owner))
  861.     {
  862.         house->setOwnerEx(0, true);
  863.         return false;
  864.     }
  865.  
  866.     std::string name;
  867.     if(!IOLoginData::getInstance()->getNameByGuid(owner, name))
  868.     {
  869.         house->setOwnerEx(0, true);
  870.         return false;
  871.     }
  872.  
  873.     Player* player = g_game.getPlayerByNameEx(name);
  874.     if(!player)
  875.         return false;
  876.  
  877.     if(!player->isPremium() && g_config.getBool(ConfigManager::HOUSE_NEED_PREMIUM))
  878.     {
  879.         house->setOwnerEx(0, true);
  880.         if(player->isVirtual())
  881.             delete player;
  882.  
  883.         return false;
  884.     }
  885.  
  886.     int32_t loginClean = g_config.getNumber(ConfigManager::HOUSE_CLEAN_OLD);
  887.     if(loginClean && _time >= (player->getLastLogin() + loginClean))
  888.     {
  889.         house->setOwnerEx(0, true);
  890.         if(player->isVirtual())
  891.             delete player;
  892.  
  893.         return false;
  894.     }
  895.  
  896.     if(payRent(player, house, bid, _time) || _time < (house->getLastWarning() + 86400))
  897.     {
  898.         if(player->isVirtual())
  899.         {
  900.             IOLoginData::getInstance()->savePlayer(player);
  901.             delete player;
  902.         }
  903.  
  904.         return true;
  905.     }
  906.  
  907.     uint32_t warningsLimit = 7;
  908.     switch(rentPeriod)
  909.     {
  910.         case RENTPERIOD_DAILY:
  911.             warningsLimit = 1;
  912.             break;
  913.         case RENTPERIOD_WEEKLY:
  914.             warningsLimit = 3;
  915.             break;
  916.         case RENTPERIOD_YEARLY:
  917.             warningsLimit = 14;
  918.             break;
  919.         default:
  920.             break;
  921.     }
  922.  
  923.     uint32_t warnings = house->getRentWarnings();
  924.     if(warnings >= warningsLimit)
  925.     {
  926.         house->setOwnerEx(0, true);
  927.         if(player->isVirtual())
  928.             delete player;
  929.  
  930.         return false;
  931.     }
  932.  
  933.     if(Depot* depot = player->getDepot(town->getID(), true))
  934.     {
  935.         if(Item* letter = Item::CreateItem(ITEM_LETTER_STAMPED))
  936.         {
  937.             if(g_game.internalAddItem(NULL, depot, letter, INDEX_WHEREEVER, FLAG_NOLIMIT) == RET_NOERROR)
  938.             {
  939.                 letter->setWriter(g_config.getString(ConfigManager::SERVER_NAME));
  940.                 letter->setDate(std::time(NULL));
  941.                 std::stringstream s;
  942.  
  943.                 s << "Warning!\nThe ";
  944.                 switch(rentPeriod)
  945.                 {
  946.                     case RENTPERIOD_DAILY:
  947.                         s << "daily";
  948.                         break;
  949.                     case RENTPERIOD_WEEKLY:
  950.                         s << "weekly";
  951.                         break;
  952.                     case RENTPERIOD_MONTHLY:
  953.                         s << "monthly";
  954.                         break;
  955.                     case RENTPERIOD_YEARLY:
  956.                         s << "annual";
  957.                         break;
  958.                     default:
  959.                         break;
  960.                 }
  961.  
  962.                 s << " rent of " << house->getRent() << " gold for your "
  963.                     << (house->isGuild() ? "guild hall" : "house") << " \"" << house->getName()
  964.                     << "\" has to be paid. Have it within " << (warningsLimit - warnings)
  965.                     << " days or you will lose your " << (house->isGuild() ? "guild hall" : "house") << ".";
  966.  
  967.                 letter->setText(s.str().c_str());
  968.                 if(player->isVirtual())
  969.                     IOLoginData::getInstance()->savePlayer(player);
  970.             }
  971.  
  972.             else
  973.                 g_game.freeThing(letter);
  974.         }
  975.     }
  976.  
  977.     house->setLastWarning(_time);
  978.     house->setRentWarnings(++warnings);
  979.     if(player->isVirtual())
  980.         delete player;
  981.  
  982.     return false;
  983. }
  984.  
  985. House* Houses::getHouse(uint32_t houseId, bool add/*= false*/)
  986. {
  987.     HouseMap::iterator it = houseMap.find(houseId);
  988.     if(it != houseMap.end())
  989.         return it->second;
  990.  
  991.     if(!add)
  992.         return NULL;
  993.  
  994.     houseMap[houseId] = new House(houseId);
  995.     return houseMap[houseId];
  996. }
  997.  
  998. House* Houses::getHouseByPlayer(Player* player)
  999. {
  1000.     if(!player || player->isRemoved())
  1001.         return NULL;
  1002.  
  1003.     HouseTile* houseTile = player->getTile()->getHouseTile();
  1004.     if(!houseTile)
  1005.         return NULL;
  1006.  
  1007.     if(House* house = houseTile->getHouse())
  1008.         return house;
  1009.  
  1010.     return NULL;
  1011. }
  1012.  
  1013. House* Houses::getHouseByPlayerId(uint32_t playerId)
  1014. {
  1015.     for(HouseMap::iterator it = houseMap.begin(); it != houseMap.end(); ++it)
  1016.     {
  1017.         if(!it->second->isGuild() && it->second->getOwner() == playerId)
  1018.             return it->second;
  1019.     }
  1020.  
  1021.     return NULL;
  1022. }
  1023.  
  1024. House* Houses::getHouseByGuildId(uint32_t guildId)
  1025. {
  1026.     for(HouseMap::iterator it = houseMap.begin(); it != houseMap.end(); ++it)
  1027.     {
  1028.         if(it->second->isGuild() && it->second->getOwner() == guildId)
  1029.             return it->second;
  1030.     }
  1031.  
  1032.     return NULL;
  1033. }
  1034.  
  1035. uint32_t Houses::getHousesCount(uint32_t accId)
  1036. {
  1037.     Account account = IOLoginData::getInstance()->loadAccount(accId);
  1038.     uint32_t guid, count = 0;
  1039.     for(Characters::iterator it = account.charList.begin(); it != account.charList.end(); ++it)
  1040.     {
  1041. #ifndef __LOGIN_SERVER__
  1042.         if(IOLoginData::getInstance()->getGuidByName(guid, (*it)) && getHouseByPlayerId(guid))
  1043. #else
  1044.         if(IOLoginData::getInstance()->getGuidByName(guid, (std::string&)it->first) && getHouseByPlayerId(guid))
  1045. #endif
  1046.             count++;
  1047.     }
  1048.  
  1049.     return count;
  1050. }
Add Comment
Please, Sign In to add comment