• 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 Dropping all items on death, even with bless

allanet

Member
Joined
Jan 20, 2012
Messages
19
Reaction score
9
Distribuition: TFS 0.3.7 , protocol 8.10

When a player die, he lose all items, backpack and equipments, and receive an empty bag, even with all the blessings.

This is only prevented using a amulet of loss, in that case everything works normal (no drop backpack or equipments drop, and aol is removed).

I tried to fix-it but i can't find where, but my guess is that the functions that deals with death, rook the equipment of everyone on death, because aside from dropping everything, the player receives an empty bag

PS: everything else works flawless, when a player die he loses only small amount of skill and level, only the equipment drop is wrong.

My player.cpp onDeath() function:


C++:
bool Player::onDeath()
{
    Item *preventLoss = NULL, *preventDrop = NULL;
    if (getZone() == ZONE_HARDCORE)
    {
        setDropLoot(LOOT_DROP_NONE);
        setLossSkill(false);
    }
    else if (skull < SKULL_RED)
    {
        Item* item = NULL;
        for (int32_t i = SLOT_FIRST; ((!preventDrop || !preventLoss) && i < SLOT_LAST); ++i)
        {
            if (!(item = getInventoryItem((slots_t)i)) || item->isRemoved() ||
                (g_moveEvents->hasEquipEvent(item) && !isItemAbilityEnabled((slots_t)i)))
                continue;

            const ItemType& it = Item::items[item->getID()];
            if (!it.hasAbilities())
                continue;

            if (lootDrop == LOOT_DROP_FULL && it.abilities->preventDrop)
            {
                setDropLoot(LOOT_DROP_PREVENT);
                preventDrop = item;
            }

            if (skillLoss && !preventLoss && it.abilities->preventLoss)
                preventLoss = item;
        }
    }

    if (!Creature::onDeath())
    {
        if (preventDrop)
            setDropLoot(LOOT_DROP_FULL);

        return false;
    }

    uint32_t totalDamage = 0, pvpDamage = 0, opponents = 0;
    for (CountMap::iterator it = damageMap.begin(); it != damageMap.end(); ++it)
    {
        if (((OTSYS_TIME() - it->second.ticks) / 1000) > g_config.getNumber(
            ConfigManager::FAIRFIGHT_TIMERANGE))
            continue;

        totalDamage += it->second.total;
        if (Creature* creature = g_game.getCreatureByID(it->first))
        {
            Player* player = creature->getPlayer();
            if (!player)
                player = creature->getPlayerMaster();

            if (!player)
                continue;

            opponents += player->getLevel();
            pvpDamage += it->second.total;
        }
    }

    bool usePVPBlessing = false;
    if (preventLoss)
    {
        setLossSkill(false);
        g_game.transformItem(preventLoss, preventLoss->getID(), std::max(0, (int32_t)preventLoss->getCharges() - 1));
    }
    else if (pvpBlessing && (int32_t)std::floor((100. * pvpDamage) / std::max(
        1U, totalDamage)) >= g_config.getNumber(ConfigManager::PVP_BLESSING_THRESHOLD))
        usePVPBlessing = true;

    if (preventDrop && preventDrop != preventLoss && !usePVPBlessing)
        g_game.transformItem(preventDrop, preventDrop->getID(), std::max(0, (int32_t)preventDrop->getCharges() - 1));

    removeConditions(CONDITIONEND_DEATH);
    if (skillLoss)
    {
        double reduction = 1.;
        if (g_config.getBool(ConfigManager::FAIRFIGHT_REDUCTION) && opponents > level)
            reduction -= (double)level / opponents;

        uint64_t lossExperience = (uint64_t)std::floor(reduction * getLostExperience()), currExperience = experience;
        removeExperience(lossExperience, false);
        double percent = 1. - ((double)(currExperience - lossExperience) / std::max((uint64_t)1, currExperience));

        // magic level loss
        uint64_t sumMana = 0, lostMana = 0;
        for (uint32_t i = 1; i <= magLevel; ++i)
            sumMana += vocation->getReqMana(i);

        sumMana += manaSpent;
        lostMana = (uint64_t)std::ceil((percent * lossPercent[LOSS_MANA] / 100.) * sumMana);
        while (lostMana > manaSpent && magLevel > 0)
        {
            lostMana -= manaSpent;
            manaSpent = vocation->getReqMana(magLevel);
            magLevel--;
        }

        manaSpent -= lostMana;
        uint64_t nextReqMana = vocation->getReqMana(magLevel + 1);
        if (nextReqMana > vocation->getReqMana(magLevel))
            magLevelPercent = Player::getPercentLevel(manaSpent, nextReqMana);
        else
            magLevelPercent = 0;

        // skill loss
        uint64_t lostSkillTries, sumSkillTries;
        for (int16_t i = 0; i < 7; ++i) // for each skill
        {
            lostSkillTries = sumSkillTries = 0;
            for (uint32_t c = 11; c <= skills[i][SKILL_LEVEL]; ++c) // sum up all required tries for all skill levels
                sumSkillTries += vocation->getReqSkillTries(i, c);

            sumSkillTries += skills[i][SKILL_TRIES];
            lostSkillTries = (uint64_t)std::ceil((percent * lossPercent[LOSS_SKILLS] / 100.) * sumSkillTries);
            while (lostSkillTries > skills[i][SKILL_TRIES] && skills[i][SKILL_LEVEL] > 10)
            {
                lostSkillTries -= skills[i][SKILL_TRIES];
                skills[i][SKILL_TRIES] = vocation->getReqSkillTries(i, skills[i][SKILL_LEVEL]);
                skills[i][SKILL_LEVEL]--;
            }

            skills[i][SKILL_TRIES] -= lostSkillTries;
        }

        if (usePVPBlessing)
            pvpBlessing = false;
        else
            blessings = 0;

        loginPosition = masterPosition;
        if (vocationId > VOCATION_NONE && g_config.getBool(ConfigManager::ROOK_SYSTEM) &&
            level <= (uint32_t)g_config.getNumber(ConfigManager::ROOK_LEVELTO))
        {
            if (Town* rook = Towns::getInstance()->getTown(g_config.getNumber(ConfigManager::ROOK_TOWN)))
            {
                level = 1;
                soulMax = soul = 100;
                capacity = 400;
                stamina = STAMINA_MAX;
                health = healthMax = 150;
                loginPosition = masterPosition = rook->getPosition();
                experience = magLevel = manaSpent = mana = manaMax = balance = marriage = 0;
                promotionLevel = defaultOutfit.lookAddons = 0;

                setTown(rook->getID());
                setVocation(0);
                leaveGuild();

                storageMap.clear();
                for (uint32_t i = SKILL_FIRST; i <= SKILL_LAST; ++i)
                {
                    skills[i][SKILL_LEVEL] = 10;
                    skills[i][SKILL_TRIES] = 0;
                }

                for (uint32_t i = SLOT_FIRST; i < SLOT_LAST; ++i)
                {
                    if (inventory[i])
                        g_game.internalRemoveItem(NULL, inventory[i]);
                }
            }
        }
        else if (!inventory[SLOT_BACKPACK]) // FIXME: you should receive the bag after you login back...
            __internalAddThing(SLOT_BACKPACK, Item::CreateItem(g_config.getNumber(ConfigManager::DEATH_CONTAINER)));

        sendIcons();
        sendStats();
        sendSkills();

        g_creatureEvents->playerLogout(this, true);
        g_game.removeCreature(this, false);
        sendReLoginWindow();
    }
    else
    {
        setLossSkill(true);
        if (preventLoss)
        {
            loginPosition = masterPosition;
            g_creatureEvents->playerLogout(this, true);

            g_game.removeCreature(this, false);
            sendReLoginWindow();
        }
    }

    return true;
}
 
Last edited:
Solution
Well, I'm glad you got the first bit sorted!
Have you followed the path of blessings from the first point of acquisition (to confirm that it has been applied to the character), check their blessed status on logout, check it on login, and check it on death?
Blessing is only a part of the problem.
With or without blessing the player drops EVERYTHING on death, without any skull, and receives an empty bag.
Only amulet of loss can prevent losing items.



I have tried, dont work, still dropping everything on death with bless or without it.

What is line 22, LOOT_DROP_FULL referencing?

player.cpp
C++:
void Player::dropLoot(Container* corpse)
{
    if (!corpse || lootDrop != LOOT_DROP_FULL)
        return;

    uint32_t loss = lossPercent[LOSS_CONTAINERS], start = g_config.getNumber(
        ConfigManager::BLESS_REDUCTION_BASE), bless = getBlessings();
    while (bless > 0 && loss > 0)
    {
        loss -= start;
        start -= g_config.getNumber(ConfigManager::BLESS_REDUCTION_DECREMENT);
        --bless;
    }

    uint32_t itemLoss = (uint32_t)std::floor((5. + loss) * lossPercent[LOSS_ITEMS] / 1000.);
    for (int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i)
    {
        Item* item = inventory[i];
        if (!item)
            continue;

        uint32_t tmp = random_range(1, 100);
        if (skull > SKULL_WHITE || (item->getContainer() && tmp < loss) || (!item->getContainer() && tmp < itemLoss))
        {
            g_game.internalMoveItem(NULL, this, corpse, INDEX_WHEREEVER, item, item->getItemCount(), 0);
            sendRemoveInventoryItem((slots_t)i, inventory[(slots_t)i]);
        }
    }
}

AND

C++:
void Player::setDropLoot(lootDrop_t _lootDrop)
{
    if(vocation && !vocation->getDropLoot())
        _lootDrop = LOOT_DROP_PREVENT;

    Creature::setDropLoot(_lootDrop);
}
 
Almost fixed, loot drop is working correctly now, but bless still not working.

I had change the function onDeath from player.cpp (I had replaced mine with the old tfs 0.3.6pl1)

C++:
bool Player::onDeath()
{
    Item* preventLoss = NULL;
    Item* preventDrop = NULL;
    if (getZone() == ZONE_HARDCORE)
    {
        setDropLoot(LOOT_DROP_NONE);
        setLossSkill(false);
    }
    else if (skull < SKULL_RED && g_game.getWorldType() != WORLDTYPE_HARDCORE)
    {
        Item* item = NULL;
        for (int32_t i = SLOT_FIRST; ((skillLoss || lootDrop == LOOT_DROP_FULL) && i < SLOT_LAST); ++i)
        {
            if (!(item = getInventoryItem((slots_t)i)) || (g_moveEvents->hasEquipEvent(item)
                && !isItemAbilityEnabled((slots_t)i)))
                continue;

            const ItemType& it = Item::items[item->getID()];
            if (lootDrop == LOOT_DROP_FULL && it.abilities->preventDrop)
            {
                setDropLoot(LOOT_DROP_PREVENT);
                preventDrop = item;
            }

            if (skillLoss && !preventLoss && it.abilities->preventLoss)
                preventLoss = item;
        }
    }

    if (!Creature::onDeath())
    {
        if (preventDrop)
            setDropLoot(LOOT_DROP_FULL);

        return false;
    }

    if (preventLoss)
    {
        setLossSkill(false);
        if (preventLoss->getCharges() > 1) //weird, but transform failed to remove for some hosters
            g_game.transformItem(preventLoss, preventLoss->getID(), std::max(0, ((int32_t)preventLoss->getCharges() - 1)));
        else
            g_game.internalRemoveItem(NULL, preventDrop);
    }

    if (preventDrop && preventDrop != preventLoss)
    {
        if (preventDrop->getCharges() > 1) //weird, but transform failed to remove for some hosters
            g_game.transformItem(preventDrop, preventDrop->getID(), std::max(0, ((int32_t)preventDrop->getCharges() - 1)));
        else
            g_game.internalRemoveItem(NULL, preventDrop);
    }

    removeConditions(CONDITIONEND_DEATH);
    if (skillLoss)
    {
        uint64_t lossExperience = getLostExperience();
        removeExperience(lossExperience, false);
        double percent = 1. - ((double)(experience - lossExperience) / experience);

        //Magic level loss
        uint32_t sumMana = 0;
        uint64_t lostMana = 0;
        for (uint32_t i = 1; i <= magLevel; ++i)
            sumMana += vocation->getReqMana(i);

        sumMana += manaSpent;
        lostMana = (uint64_t)std::ceil(sumMana * ((double)(percent * lossPercent[LOSS_MANA]) / 100.));
        while (lostMana > manaSpent && magLevel > 0)
        {
            lostMana -= manaSpent;
            manaSpent = vocation->getReqMana(magLevel);
            magLevel--;
        }

        manaSpent -= std::max((int32_t)0, (int32_t)lostMana);
        uint64_t nextReqMana = vocation->getReqMana(magLevel + 1);
        if (nextReqMana > vocation->getReqMana(magLevel))
            magLevelPercent = Player::getPercentLevel(manaSpent, nextReqMana);
        else
            magLevelPercent = 0;

        //Skill loss
        uint32_t lostSkillTries, sumSkillTries;
        for (int16_t i = 0; i < 7; ++i) //for each skill
        {
            lostSkillTries = sumSkillTries = 0;
            for (uint32_t c = 11; c <= skills[i][SKILL_LEVEL]; ++c) //sum up all required tries for all skill levels
                sumSkillTries += vocation->getReqSkillTries(i, c);

            sumSkillTries += skills[i][SKILL_TRIES];
            lostSkillTries = (uint32_t)std::ceil(sumSkillTries * ((double)(percent * lossPercent[LOSS_SKILLS]) / 100.));
            while (lostSkillTries > skills[i][SKILL_TRIES])
            {
                lostSkillTries -= skills[i][SKILL_TRIES];
                skills[i][SKILL_TRIES] = vocation->getReqSkillTries(i, skills[i][SKILL_LEVEL]);
                if (skills[i][SKILL_LEVEL] < 11)
                {
                    skills[i][SKILL_LEVEL] = 10;
                    skills[i][SKILL_TRIES] = lostSkillTries = 0;
                    break;
                }
                else
                    skills[i][SKILL_LEVEL]--;
            }

            skills[i][SKILL_TRIES] = std::max((int32_t)0, (int32_t)(skills[i][SKILL_TRIES] - lostSkillTries));
        }

        blessings = 0;
        loginPosition = masterPosition;
        if (!inventory[SLOT_BACKPACK])
            __internalAddThing(SLOT_BACKPACK, Item::CreateItem(g_config.getNumber(ConfigManager::DEATH_CONTAINER)));

        sendIcons();
        sendStats();
        sendSkills();

        sendReLoginWindow();
        g_game.removeCreature(this, false);
    }
    else
    {
        setLossSkill(true);
        if (preventLoss)
        {
            loginPosition = masterPosition;
            sendReLoginWindow();
            g_game.removeCreature(this, false);
        }
    }

    return true;
}

BUT BLESSINGS ARE STILL NOT WORKING

If the player buy all 5 five blessings, logout and returns, he can buy all 5 blessings again, and he still loses the backpack when die with 5 blessings
 
Last edited:
Well, I'm glad you got the first bit sorted!
Have you followed the path of blessings from the first point of acquisition (to confirm that it has been applied to the character), check their blessed status on logout, check it on login, and check it on death?
 
Solution
Well, I follow the path from npc that sells bless, and realize why blessings dont work.

my config.lua
Lua:
    -- Blessings

    blessings = false
    blessingOnlyPremium = true
    blessingReductionBase = 30
    blessingReductionDecrement = 5
    eachBlessReduction = 8
    useFairfightReduction = true
    pvpBlessingThreshold = 40
    fairFightTimeRange = 60

blessing was disabled :eek:
now everything is working as intended, thanks everyone for the help
 
Back
Top