SHARE
TWEET

house.cpp

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