• 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!

Fix/Patch TFS 0.2+ Clean (including Protection Zones)

Evil Hero

Legacy Member
TFS Developer
Joined
Dec 12, 2007
Messages
1,246
Solutions
26
Reaction score
713
Location
Germany
I've tested it before and it works 100% but still use it on your own risk!

replace your "uint32_t Map::clean()"
with this.

map.cpp:
Code:
uint32_t Map::clean()
{
	g_game.setGameState(GAME_STATE_MAINTAIN);

	g_game.setStateTime(0);
	uint64_t start = OTSYS_TIME();
	uint64_t count = 0;
	Tile* tile = NULL;
	Item *item = NULL;

	QTreeLeafNode* startLeaf;
	QTreeLeafNode* leafE;
	QTreeLeafNode* leafS;
	Floor* floor;

	startLeaf = getLeaf(0, 0);
	leafS = startLeaf;

	for(int32_t ny = 0; ny <= 0xFFFF; ny += FLOOR_SIZE)
	{
		leafE = leafS;
		for(int32_t nx = 0; nx <= 0xFFFF; nx += FLOOR_SIZE)
		{
			if(leafE)
			{
				for(int32_t nz = 0; nz < MAP_MAX_LAYERS; ++nz)
				{
					if(leafE && (floor = leafE->getFloor(nz)))
					{
						for(int32_t ly = 0; ly < FLOOR_SIZE; ++ly)
						{
							for(int32_t lx = 0; lx < FLOOR_SIZE; ++lx)
							{
								if(floor && (tile = floor->tiles[(nx + lx) & FLOOR_MASK][(ny + ly) & FLOOR_MASK]))
								{
                                    if(g_config.getBoolean(ConfigManager::CLEAN_PROTECTION_ZONE))
                                    {
			                            if(!tile->hasFlag(TILESTATE_HOUSE))
			                            {
										    for(uint32_t i = 0; i < tile->getThingCount(); ++i)
										    {
											    item = tile->__getThing(i)->getItem();
											    if(item && !item->isLoadedFromMap() && !item->isNotMoveable())
											    {
												    g_game.internalRemoveItem(item);
												    i--;
												    count++;
                                                }
											}
										}
									}
									else if(!g_config.getBoolean(ConfigManager::CLEAN_PROTECTION_ZONE))
									{
                                        if(!tile->hasFlag(TILESTATE_PROTECTIONZONE))
			                            {  
                                            for(uint32_t i = 0; i < tile->getThingCount(); ++i)
	                                        {
                                                item = tile->__getThing(i)->getItem();
                                                if(item && !item->isLoadedFromMap() && !item->isNotMoveable())
                                                {
                                                    g_game.internalRemoveItem(item);
                                                    i--;
                                                    count++;
                                                }
                                            }
					                    }
								    }
                                }
							}
						}
					}
				}
				leafE = leafE->stepEast();
			}
			else
				leafE = getLeaf(nx + FLOOR_SIZE, ny);
		}
		if(leafS)
			leafS = leafS->stepSouth();
		else
			leafS = getLeaf(0, ny + FLOOR_SIZE);
	}

	std::cout << "> Cleaning time: " << (OTSYS_TIME() - start) / (1000.) << " seconds, collected " << count << " item" << (count != 1 ? "s" : "") << "." << std::endl;
	g_game.setStateTime(OTSYS_TIME() + STATE_TIME);
	g_game.setGameState(GAME_STATE_NORMAL);
	return count;
}

configmanager.cpp:

after:
Code:
m_confBoolean[SHOW_GAMEMASTERS_ONLINE] = (getGlobalString(L, "displayGamemastersWithOnlineCommand", "no") == "yes");

paste this:
Code:
m_confBoolean[CLEAN_PROTECTION_ZONE] = (getGlobalString(L, "cleanProtectionZone", "no") == "yes");

configmanager.h:

after this
Code:
SHOW_GAMEMASTERS_ONLINE,

paste this
Code:
CLEAN_PROTECTION_ZONE,

then add this into your config.lua

Code:
cleanProtectionZone = "yes"

If you want improvements etc. feel free to ask me for them :)


kind regards, Evil Hero
 
it removed stuffs from houses too! :/

EDIT: NVM works fine
 
You're 100% that it doesn't clean houses?
Looks brilliant if that's true!

Red
 
You're 100% that it doesn't clean houses?
Looks brilliant if that's true!

Red

I've tried it several times now, it worked without any bugs, still, test it first before using it on a main server :p
 
Last edited:
i cant get it work, please if you use tfs 0.2.4 upload your EXE?


Edit; how long time it takes until it cleans?
 
i cant get it work, please if you use tfs 0.2.4 upload your EXE?


Edit; how long time it takes until it cleans?

It is the function "clean()" you can change the time in globalevents.xml
 
It is the function "clean()" you can change the time in globalevents.xml

Sorry i cant find it, anyways, i did c++ it and its not working.. :O? Or maybe i need to change the time when it cleans, please show me.
 
Hi there, anyone knows about something similar working in TFS 1.2?

This is my Map::clean

Code:
uint32_t Map::clean() const
{
    uint64_t start = OTSYS_TIME();
    size_t count = 0, tiles = 0;

    if (g_game.getGameState() == GAME_STATE_NORMAL) {
        g_game.setGameState(GAME_STATE_MAINTAIN);
    }

    std::vector<const QTreeNode*> nodes {
        &root
    };
    std::vector<Item*> toRemove;
    do {
        const QTreeNode* node = nodes.back();
        nodes.pop_back();
        if (node->isLeaf()) {
            const QTreeLeafNode* leafNode = static_cast<const QTreeLeafNode*>(node);
            for (uint8_t z = 0; z < MAP_MAX_LAYERS; ++z) {
                Floor* floor = leafNode->getFloor(z);
                if (!floor) {
                    continue;
                }

                for (size_t x = 0; x < FLOOR_SIZE; ++x) {
                    for (size_t y = 0; y < FLOOR_SIZE; ++y) {
                        Tile* tile = floor->tiles[x][y];
                        if (!tile || tile->hasFlag(TILESTATE_PROTECTIONZONE)) {
                            continue;
                        }

                        TileItemVector* itemList = tile->getItemList();
                        if (!itemList) {
                            continue;
                        }

                        ++tiles;
                        for (Item* item : *itemList) {
                            if (item->isCleanable()) {
                                toRemove.push_back(item);
                            }
                        }

                        for (Item* item : toRemove) {
                            g_game.internalRemoveItem(item, -1);
                        }
                        count += toRemove.size();
                        toRemove.clear();
                    }
                }
            }
        } else {
            for (size_t i = 0; i < 4; ++i) {
                QTreeNode* childNode = node->child[i];
                if (childNode) {
                    nodes.push_back(childNode);
                }
            }
        }
    } while (!nodes.empty());

    if (g_game.getGameState() == GAME_STATE_MAINTAIN) {
        g_game.setGameState(GAME_STATE_NORMAL);
    }

    std::cout << "> CLEAN: Removed " << count << " item" << (count != 1 ? "s" : "")
              << " from " << tiles << " tile" << (tiles != 1 ? "s" : "") << " in "
              << (OTSYS_TIME() - start) / (1000.) << " seconds." << std::endl;
    return count;
}

Tried switching from
Code:
if (!tile || tile->hasFlag(TILESTATE_PROTECTIONZONE)) {
to
Code:
if (!tile || tile->hasFlag(TILESTATE_HOUSE)) {

Did not work.


Code:
1>..\src\map.cpp(1000): error C2065: 'TILESTATE_HOUSE': undeclared identifier
 
Last edited:
Hi there, anyone knows about something similar working in TFS 1.2?

This is my Map::clean

Code:
uint32_t Map::clean() const
{
    uint64_t start = OTSYS_TIME();
    size_t count = 0, tiles = 0;

    if (g_game.getGameState() == GAME_STATE_NORMAL) {
        g_game.setGameState(GAME_STATE_MAINTAIN);
    }

    std::vector<const QTreeNode*> nodes {
        &root
    };
    std::vector<Item*> toRemove;
    do {
        const QTreeNode* node = nodes.back();
        nodes.pop_back();
        if (node->isLeaf()) {
            const QTreeLeafNode* leafNode = static_cast<const QTreeLeafNode*>(node);
            for (uint8_t z = 0; z < MAP_MAX_LAYERS; ++z) {
                Floor* floor = leafNode->getFloor(z);
                if (!floor) {
                    continue;
                }

                for (size_t x = 0; x < FLOOR_SIZE; ++x) {
                    for (size_t y = 0; y < FLOOR_SIZE; ++y) {
                        Tile* tile = floor->tiles[x][y];
                        if (!tile || tile->hasFlag(TILESTATE_PROTECTIONZONE)) {
                            continue;
                        }

                        TileItemVector* itemList = tile->getItemList();
                        if (!itemList) {
                            continue;
                        }

                        ++tiles;
                        for (Item* item : *itemList) {
                            if (item->isCleanable()) {
                                toRemove.push_back(item);
                            }
                        }

                        for (Item* item : toRemove) {
                            g_game.internalRemoveItem(item, -1);
                        }
                        count += toRemove.size();
                        toRemove.clear();
                    }
                }
            }
        } else {
            for (size_t i = 0; i < 4; ++i) {
                QTreeNode* childNode = node->child[i];
                if (childNode) {
                    nodes.push_back(childNode);
                }
            }
        }
    } while (!nodes.empty());

    if (g_game.getGameState() == GAME_STATE_MAINTAIN) {
        g_game.setGameState(GAME_STATE_NORMAL);
    }

    std::cout << "> CLEAN: Removed " << count << " item" << (count != 1 ? "s" : "")
              << " from " << tiles << " tile" << (tiles != 1 ? "s" : "") << " in "
              << (OTSYS_TIME() - start) / (1000.) << " seconds." << std::endl;
    return count;
}

Tried switching from
Code:
if (!tile || tile->hasFlag(TILESTATE_PROTECTIONZONE)) {
to
Code:
if (!tile || tile->hasFlag(TILESTATE_HOUSE)) {

Did not work.


Code:
1>..\src\map.cpp(1000): error C2065: 'TILESTATE_HOUSE': undeclared identifier
TILESTATE_HOUSE was removed, use this instead:

Code:
    HouseTile* houseTile = dynamic_cast<HouseTile*>(tile);
    if (!tile || (houseTile && houseTile->getHouse())) {
        continue;
    }
 
Back
Top