Advertisement
Guest User

house.cpp

a guest
Aug 23rd, 2019
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 25.15 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement