• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

TFS 0.X House Rent

potinho

Intermediate OT User
Joined
Oct 11, 2009
Messages
1,397
Solutions
17
Reaction score
148
Location
Brazil
Hi guys, I saw it on the forum but the answer varied. The rent on my OT is not being charged, does anyone know how to guide me? I would like the rent for the houses to be charged weekly.

Lua:
buyableAndSellableHouses = true
houseNeedPremium = true
bedsRequirePremium = true
levelToBuyHouse = 50
housesPerAccount = 1
houseRentAsPrice = true
housePriceAsRent = false
housePriceEachSquare = 3000
houseRentPeriod = "weekly"
houseCleanOld = 0
guildHalls = true
houseSkipInitialRent = true
houseProtection = true

Config.LUA is like this, but not charging, in database the columm "rent" is 0.

1633911385634.png
 
What do you mean "change depots town"?
I had changed all "town id" to 1, then reverted that setting in houses.xml. But within the RME, I went to each depot in the other cities and pointed them as depots in the main city, for all depots to open the same.
 
Check what town IDs you have defined in RME.
Map>Edit Towns
1637673072411.png

You could add some debug prints in house.cpp payRent() function. Maybe it will help you to find solution.
 
i guess towns are ok, one id per town

1637673329249.png

some things about rent at house.cpp

C++:
House::House(uint32_t houseId)
{
    guild = pendingTransfer = false;
    name = "OTX headquarter (Flat 1, Area 42)";
    entry = Position();
    id = houseId;
    rent = price = townId = paidUntil = owner = rentWarnings = lastWarning = 0;
    syncFlags = HOUSE_SYNC_NAME | HOUSE_SYNC_TOWN | HOUSE_SYNC_SIZE | HOUSE_SYNC_PRICE | HOUSE_SYNC_RENT | HOUSE_SYNC_GUILD;
}

bool House::setOwnerEx(uint32_t guid, bool transfer)
{
    if(owner == guid)
        return true;

    if(owner)
    {
        rentWarnings = paidUntil = 0;
        if(transfer)
            clean();

        setAccessList(SUBOWNER_LIST, "", !transfer);
        setAccessList(GUEST_LIST, "", !transfer);
        for(HouseDoorList::iterator it = doorList.begin(); it != doorList.end(); ++it)
            (*it)->setAccessList("");
    }

    setOwner(guid);
    lastWarning = guid ? time(NULL) : 0;

    Database* db = Database::getInstance();
    DBTransaction trans(db);
    if(!trans.begin())
        return false;

    IOMapSerialize::getInstance()->saveHouse(db, this);
    return trans.commit();
}

Houses::Houses()
{
    rentPeriod = RENTPERIOD_NEVER;
    std::string strValue = asLowerCaseString(g_config.getString(ConfigManager::HOUSE_RENT_PERIOD));
    if(strValue == "yearly")
        rentPeriod = RENTPERIOD_YEARLY;
    else if(strValue == "monthly")
        rentPeriod = RENTPERIOD_MONTHLY;
    else if(strValue == "weekly")
        rentPeriod = RENTPERIOD_WEEKLY;
    else if(strValue == "daily")
        rentPeriod = RENTPERIOD_DAILY;
}

    int32_t houseId = 0;
        if(!readXMLInteger(houseNode, "houseid", houseId))
        {
            std::clog << "[Error - Houses::loadFromXml] Could not read houseId" << std::endl;
            xmlFreeDoc(doc);
            return false;
        }

        House* house = Houses::getInstance()->getHouse(houseId);
        if(!house)
        {
            std::clog << "[Error - Houses::loadFromXml] Unknown house with id: " << houseId << std::endl;
            xmlFreeDoc(doc);
            return false;
        }

        Position entry(0, 0, 0);
        if(readXMLInteger(houseNode, "entryx", intValue))
            entry.x = intValue;

        if(readXMLInteger(houseNode, "entryy", intValue))
            entry.y = intValue;

        if(readXMLInteger(houseNode, "entryz", intValue))
            entry.z = intValue;

        if(readXMLString(houseNode, "name", strValue))
            house->setName(strValue);
        else
            house->resetSyncFlag(House::HOUSE_SYNC_NAME);

        house->setEntry(entry);
        if(!entry.x || !entry.y)
        {
            std::clog << "[Warning - Houses::loadFromXml] House entry not set for: "
                << house->getName() << " (" << houseId << ")" << std::endl;
        }

        if(readXMLInteger(houseNode, "townid", intValue))
            house->setTownId(intValue);
        else
            house->resetSyncFlag(House::HOUSE_SYNC_TOWN);

        if(readXMLInteger(houseNode, "size", intValue))
            house->setSize(intValue);
        else
            house->resetSyncFlag(House::HOUSE_SYNC_SIZE);

        if(readXMLString(houseNode, "guildhall", strValue))
            house->setGuild(booleanString(strValue));
        else
            house->resetSyncFlag(House::HOUSE_SYNC_GUILD);

        uint32_t rent = 0;
        if(readXMLInteger(houseNode, "rent", intValue))
            rent = intValue;

        uint32_t price = (house->getSize() + house->getBedsCount()) * g_config.getNumber(ConfigManager::HOUSE_PRICE);
        // we should let players to pay only for walkable tiles + beds as single units not two items.
        if(g_config.getBool(ConfigManager::HOUSE_RENTASPRICE) && rent)
            price = rent;

        house->setPrice(price);
        if(g_config.getBool(ConfigManager::HOUSE_PRICEASRENT))
            house->setRent(price);
        else
            house->setRent(rent);

        house->setOwner(0);
        houseNode = houseNode->next;
    }

    xmlFreeDoc(doc);
    return true;
}

bool Houses::payRent(Player* player, House* house, uint32_t bid, time_t _time/* = 0*/)
{
    if(rentPeriod == RENTPERIOD_NEVER || !house->getOwner() ||
        house->getPaidUntil() > _time || !house->getRent() ||
        player->hasCustomFlag(PlayerCustomFlag_IgnoreHouseRent))
        return true;

    Town* town = Towns::getInstance()->getTown(house->getTownId());
    if(!town)
        return false;

    bool paid = false;
    uint32_t amount = house->getRent() + bid;
    if(g_config.getBool(ConfigManager::BANK_SYSTEM) && player->balance >= amount)
    {
        player->balance -= amount;
        paid = true;
    }
    else if(Depot* depot = player->getDepot(town->getID(), true))
        paid = g_game.removeMoney(depot, amount, FLAG_NOLIMIT);

    if(!paid)
        return false;

    if(!_time)
        _time = time(NULL);

    uint32_t paidUntil = _time;
    switch(rentPeriod)
    {
        case RENTPERIOD_DAILY:
            paidUntil += 86400;
            break;
        case RENTPERIOD_WEEKLY:
            paidUntil += 7 * 86400;
            break;
        case RENTPERIOD_MONTHLY:
            paidUntil += 30 * 86400;
            break;
        case RENTPERIOD_YEARLY:
            paidUntil += 365 * 86400;
            break;
        default:
            break;
    }

    house->setLastWarning(0);
    house->setRentWarnings(0);

    house->setPaidUntil(paidUntil);
    return true;
}

bool Houses::payHouse(House* house, time_t _time, uint32_t bid)
{
    if(rentPeriod == RENTPERIOD_NEVER || !house->getOwner() ||
        house->getPaidUntil() > _time || !house->getRent())
        return true;

    Town* town = Towns::getInstance()->getTown(house->getTownId());
    if(!town)
        return false;

    uint32_t owner = house->getOwner();
    if(house->isGuild() && !IOGuild::getInstance()->swapGuildIdToOwner(owner))
    {
        house->setOwnerEx(0, true);
        return false;
    }

    std::string name;
    if(!IOLoginData::getInstance()->getNameByGuid(owner, name))
    {
        house->setOwnerEx(0, true);
        return false;
    }

    Player* player = g_game.getPlayerByNameEx(name);
    if(!player)
        return false;

    if(!player->isPremium() && g_config.getBool(ConfigManager::HOUSE_NEED_PREMIUM))
    {
        house->setOwnerEx(0, true);
        if(player->isVirtual())
            delete player;

        return false;
    }

    int32_t loginClean = g_config.getNumber(ConfigManager::HOUSE_CLEAN_OLD);
    if(loginClean && _time >= (player->getLastLogin() + loginClean))
    {
        house->setOwnerEx(0, true);
        if(player->isVirtual())
            delete player;

        return false;
    }

    if(payRent(player, house, bid, _time) || _time < (house->getLastWarning() + 86400))
    {
        if(player->isVirtual())
        {
            IOLoginData::getInstance()->savePlayer(player);
            delete player;
        }

        return true;
    }

    uint32_t warningsLimit = 7;
    switch(rentPeriod)
    {
        case RENTPERIOD_DAILY:
            warningsLimit = 1;
            break;
        case RENTPERIOD_WEEKLY:
            warningsLimit = 3;
            break;
        case RENTPERIOD_YEARLY:
            warningsLimit = 14;
            break;
        default:
            break;
    }

    uint32_t warnings = house->getRentWarnings();
    if(warnings >= warningsLimit)
    {
        house->setOwnerEx(0, true);
        if(player->isVirtual())
            delete player;

        return false;
    }

    if(Depot* depot = player->getDepot(town->getID(), true))
    {
        if(Item* letter = Item::CreateItem(ITEM_LETTER_STAMPED))
        {
            if(g_game.internalAddItem(NULL, depot, letter, INDEX_WHEREEVER, FLAG_NOLIMIT) == RET_NOERROR)
            {
                letter->setWriter(g_config.getString(ConfigManager::SERVER_NAME));
                letter->setDate(std::time(NULL));
                std::stringstream s;

                s << "Warning!\nThe ";
                switch(rentPeriod)
                {
                    case RENTPERIOD_DAILY:
                        s << "daily";
                        break;
                    case RENTPERIOD_WEEKLY:
                        s << "weekly";
                        break;
                    case RENTPERIOD_MONTHLY:
                        s << "monthly";
                        break;
                    case RENTPERIOD_YEARLY:
                        s << "annual";
                        break;
                    default:
                        break;
                }

                s << " rent of " << house->getRent() << " gold for your "
                    << (house->isGuild() ? "guild hall" : "house") << " \"" << house->getName()
                    << "\" has to be paid. Have it within " << (warningsLimit - warnings)
                    << " days or you will lose your " << (house->isGuild() ? "guild hall" : "house") << ".";

                letter->setText(s.str().c_str());
                if(player->isVirtual())
                    IOLoginData::getInstance()->savePlayer(player);
            }
            else
                g_game.freeThing(letter);
        }
    }

    house->setLastWarning(_time);
    house->setRentWarnings(++warnings);
    if(player->isVirtual())
        delete player;

    return false;
}
 
I dont know how, but rent is back charging, i've got another problem: i changed all depots to same city (town 1) to open same depot in all areas, but letter warning about rent its not sent if house isn't ! town id 1
 
I dont know how, but rent is back charging, i've got another problem: i changed all depots to same city (town 1) to open same depot in all areas, but letter warning about rent its not sent if house isn't ! town id 1
Do you have set townid values to townid="1"?
Screenshot from 2022-02-03 21-10-02.png
The house is trying to send letter to some depot with town id different to 1
 
Back
Top