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

C++ [Sabrehaven] Corpses stuck as DECAYING_PENDING

Dawg

Member
Joined
Mar 23, 2014
Messages
184
Reaction score
23
Noticed something odd about Sabrehaven distro: items that can decay which are also containers (so, for the most part, monster corpses) stop decaying if you relog with them in your inventory.

For example: you kill a rat. When you look at the corpse on a God character, it prints out extra info (item ID, decay to ID, position), the output looks like this:

21:23 You see a dead rat (Vol:5).
It weights 63.00 oz.
item ID: 3994
Decays to: 3995
Decaying in 20 minutes (1200 seconds).
Position: 32802, 32278, 7

Then, you put the dead rat in your backpack, and logout. Immediately log back in, shift click on the rat, you get this:
21:23 You see a dead rat (Vol:5).
It weights 63.00 oz.
item ID: 3994
Decays to: 3995
Position: 32802, 32278, 7

But if you do this with an item that is NOT a container (a torch, magic light wand, burning heart, candle, etc), there is no problem. I added prints to iologindata.cpp in the loadItems function. I saw that both the torch and the dead rat get loaded with the correct duration and decaystate of 2, which is "decaying_pending". This happens when the attributes get read from stream:
C++:
Attr_ReadValue Item::readAttr(AttrTypes_t attr, PropStream& propStream)
{
    switch (attr) {
    //other cases
    case ATTR_DECAYING_STATE: {
        uint8_t state;
        if (!propStream.read<uint8_t>(state)) {
            return ATTR_READ_ERROR;
        }

        if (state != DECAYING_FALSE) {
            setDecaying(DECAYING_PENDING);
        }
        break;
    }
//rest of function
}

However, the torch gets set to DECAYING_TRUE (or "1") somewhere, while the rat does not.

I tried manually forcing the startDecay in void IOLoginData::loadItems: just to see what would happen:
C++:
if (item->getDuration() > 0) {
                std::cout << "Starting decay for item ID: " << item->getID() << " with duration: " << item->getDuration() << std::endl;
                g_game.startDecay(item);
            }
And while that does run, the dead rat still wasn't decaying. I also tried forcing decaystate of 1:
C++:
if (item->getDuration() > 0 && item->getIntAttr(ITEM_ATTRIBUTE_DECAYSTATE) == 2) {
                std::cout << "Starting decay for item ID: " << item->getID() << " with duration: " << item->getDuration() << std::endl;
                item->setIntAttr(ITEM_ATTRIBUTE_DECAYSTATE, 1);
                g_game.startDecay(item);
            }
That didn't work either, but in a different way. The dead rat (and the torch) now had a decaystate of 1, so shift clicking on them did show the remaining time, but the timer never went down. It was frozen.

I have tried global searches for item->startDecaying(), g_game.startDecay(item), and everywhere I find this function called (or in the functions themselves), there does not seem to be anything that excludes containers. I have also checked internalDecayItem(), checkDecay() and setDecaying(). Containers have no problem decaying during active gameplay, because when any monster is killed, its corpses all decay just fine, and always have.

TL;DR: not sure why logging in and out with a corpse in your bag stops the decay timer.
Thanks~
 
Back
Top