diff --git a/config.lua.dist b/config.lua.dist index a6bd7b6ccaf..6c882bd4b47 100644 --- a/config.lua.dist +++ b/config.lua.dist @@ -286,6 +286,7 @@ houseRentRate = 1.0 houseOwnedByAccount = false houseBuyLevel = 100 housePurchasedShowPrice = false +houseLoseAfterInactivity = 30 -- days; 0 = never onlyInvitedCanMoveHouseItems = true togglehouseTransferOnRestart = true @@ -480,6 +481,7 @@ vipBonusSkill = 0 vipAutoLootVipOnly = false vipStayOnline = false vipFamiliarTimeCooldownReduction = 0 +vipKeepHouse = false -- NOTE: set rewardChestCollectEnabled to true to enable the reward collect system -- NOTE set rewardChestMaxCollectItems max items per collect action diff --git a/data/scripts/talkactions/player/server_info.lua b/data/scripts/talkactions/player/server_info.lua index 5c19c48df7f..136a271f7e4 100644 --- a/data/scripts/talkactions/player/server_info.lua +++ b/data/scripts/talkactions/player/server_info.lua @@ -54,10 +54,13 @@ function serverInfo.onSay(player, words, param) .. configManager.getNumber(configKeys.RATE_SPAWN) .. "x" end + local loseHouseText = configManager.getNumber(configKeys.HOUSE_LOSE_AFTER_INACTIVITY) > 0 and configManager.getNumber(configKeys.HOUSE_LOSE_AFTER_INACTIVITY) .. " days" or "never" text = text .. "\n\nMore Server Info: \n" .. "\nLevel to buy house: " .. configManager.getNumber(configKeys.HOUSE_BUY_LEVEL) + .. "\nLose house after inactivity: " + .. loseHouseText .. "\nProtection level: " .. configManager.getNumber(configKeys.PROTECTION_LEVEL) .. "\nWorldType: " diff --git a/src/config/config_definitions.hpp b/src/config/config_definitions.hpp index 417a5348a96..bf86266f3a9 100644 --- a/src/config/config_definitions.hpp +++ b/src/config/config_definitions.hpp @@ -84,6 +84,7 @@ enum booleanConfig_t { TOGGLE_ATTACK_SPEED_ONFIST, VIP_SYSTEM_ENABLED, VIP_AUTOLOOT_VIP_ONLY, + VIP_KEEP_HOUSE, VIP_STAY_ONLINE, REWARD_CHEST_COLLECT_ENABLED, TOGGLE_MOUNT_IN_PZ, @@ -145,6 +146,7 @@ enum integerConfig_t { RATE_KILLING_IN_THE_NAME_OF_POINTS, HOUSE_PRICE_PER_SQM, HOUSE_BUY_LEVEL, + HOUSE_LOSE_AFTER_INACTIVITY, MAX_MESSAGEBUFFER, ACTIONS_DELAY_INTERVAL, EX_ACTIONS_DELAY_INTERVAL, diff --git a/src/config/configmanager.cpp b/src/config/configmanager.cpp index 8f46b9b3f4d..5d52ca11b2a 100644 --- a/src/config/configmanager.cpp +++ b/src/config/configmanager.cpp @@ -223,6 +223,7 @@ bool ConfigManager::load() { integer[HOUSE_PRICE_PER_SQM] = getGlobalNumber(L, "housePriceEachSQM", 1000); integer[HOUSE_BUY_LEVEL] = getGlobalNumber(L, "houseBuyLevel", 0); + integer[HOUSE_LOSE_AFTER_INACTIVITY] = getGlobalNumber(L, "houseLoseAfterInactivity", 0); boolean[HOUSE_PURSHASED_SHOW_PRICE] = getGlobalBoolean(L, "housePurchasedShowPrice", false); boolean[ONLY_INVITED_CAN_MOVE_HOUSE_ITEMS] = getGlobalBoolean(L, "onlyInvitedCanMoveHouseItems", true); @@ -384,6 +385,7 @@ bool ConfigManager::load() { integer[VIP_BONUS_LOOT] = getGlobalNumber(L, "vipBonusLoot", 0); integer[VIP_BONUS_SKILL] = getGlobalNumber(L, "vipBonusSkill", 0); boolean[VIP_AUTOLOOT_VIP_ONLY] = getGlobalBoolean(L, "vipAutoLootVipOnly", false); + boolean[VIP_KEEP_HOUSE] = getGlobalBoolean(L, "vipKeepHouse", false); boolean[VIP_STAY_ONLINE] = getGlobalBoolean(L, "vipStayOnline", false); integer[VIP_FAMILIAR_TIME_COOLDOWN_REDUCTION] = getGlobalNumber(L, "vipFamiliarTimeCooldownReduction", 0); diff --git a/src/lua/functions/core/game/config_functions.cpp b/src/lua/functions/core/game/config_functions.cpp index bdeaa226fc1..96ce09cdcc7 100644 --- a/src/lua/functions/core/game/config_functions.cpp +++ b/src/lua/functions/core/game/config_functions.cpp @@ -103,6 +103,7 @@ void ConfigFunctions::init(lua_State* L) { registerEnumIn(L, "configKeys", RATE_KILLING_IN_THE_NAME_OF_POINTS); registerEnumIn(L, "configKeys", HOUSE_PRICE_PER_SQM); registerEnumIn(L, "configKeys", HOUSE_BUY_LEVEL); + registerEnumIn(L, "configKeys", HOUSE_LOSE_AFTER_INACTIVITY); registerEnumIn(L, "configKeys", MAX_MESSAGEBUFFER); registerEnumIn(L, "configKeys", ACTIONS_DELAY_INTERVAL); registerEnumIn(L, "configKeys", EX_ACTIONS_DELAY_INTERVAL); diff --git a/src/map/house/house.cpp b/src/map/house/house.cpp index 20af6ee4042..828753b8c56 100644 --- a/src/map/house/house.cpp +++ b/src/map/house/house.cpp @@ -752,11 +752,6 @@ void Houses::payHouses(RentPeriod_t rentPeriod) const { continue; } - const uint32_t rent = house->getRent(); - if (rent == 0 || house->getPaidUntil() > currentTime) { - continue; - } - const uint32_t ownerId = house->getOwner(); const auto &town = g_game().map.towns.getTown(house->getTownId()); if (!town) { @@ -770,6 +765,27 @@ void Houses::payHouses(RentPeriod_t rentPeriod) const { continue; } + // Player hasn't logged in for a while, reset house owner + auto daysToReset = g_configManager().getNumber(HOUSE_LOSE_AFTER_INACTIVITY); + if (daysToReset > 0) { + auto daysSinceLastLogin = (currentTime - player->getLastLoginSaved()) / (60 * 60 * 24); + bool vipKeep = g_configManager().getBoolean(VIP_KEEP_HOUSE) && player->isVip(); + bool activityKeep = daysSinceLastLogin < daysToReset; + if (vipKeep && !activityKeep) { + g_logger().info("Player {} has not logged in for {} days, but is a VIP, so the house will not be reset.", player->getName(), daysToReset); + } else if (!vipKeep && !activityKeep) { + g_logger().info("Player {} has not logged in for {} days, so the house will be reset.", player->getName(), daysToReset); + house->setOwner(0, true, player); + g_saveManager().savePlayer(player); + continue; + } + } + + const uint32_t rent = house->getRent(); + if (rent == 0 || house->getPaidUntil() > currentTime) { + continue; + } + if (player->getBankBalance() >= rent) { g_game().removeMoney(player, rent, 0, true);