• 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!
  • 2026 staff recruitment is open! Check it out and consider applying!

Lua PlayerLoss not working properly..

Extrodus

|| Blazera.net ||
Joined
Dec 22, 2008
Messages
2,691
Solutions
7
Reaction score
549
Location
Canada
So I've created a talk action that enables a certain amount of protection through player loss (sort of like blessings) except just a little more basic for now.

As of right now, items, skills and containers still drop. Even though the PlayerLoss is set and saved.. so I have no idea what is causing this. I have looked through player.cpp and the parts where the item loss does get defined, it seems a bit iffy. Any help is appreciated.

onLogin Creature Script:
Code:
    if isPlayer(cid) and getPlayerLevel(cid) < 30 then
            print("Low Level Loss Protection")
            setPlayerStorageValue(cid, 13337, 4)
            doPlayerSetLossPercent(cid, PLAYERLOSS_EXPERIENCE, 0)
            doPlayerSetLossPercent(cid, PLAYERLOSS_MANA, 0)
            doPlayerSetLossPercent(cid, PLAYERLOSS_SKILL, 0)
            doPlayerSetLossPercent(cid, PLAYERLOSS_ITEMS, 0)
            doPlayerSetLossPercent(cid, PLAYERLOSS_CONTAINERS, 0)
            doPlayerSendTextMessage(cid, 18, "Protection: Your Experience and Item Loss is reduced to 0% while you are under level 30!")
            doSavePlayer(cid)
    end

TalkAction Code for First Blessing that uses the same method:
Code:
function onSay(cid, words, param)
        if getPlayerStorageValue(cid, 13337) == 1 then
            doPlayerSendTextMessage(cid, MESSAGE_EVENT_DEFAULT, "You already have the first blessing!")
        elseif getPlayerStorageValue(cid, 13337) == 2 or getPlayerStorageValue(cid, 13337) == 3 or getPlayerStorageValue(cid, 13337) == 4 or getPlayerStorageValue(cid, 13337) == 5 then
            doPlayerSendTextMessage(cid, MESSAGE_EVENT_DEFAULT, "You already have a stronger blessing!")
        elseif doPlayerRemoveMoney(cid, 7500) then
            setPlayerStorageValue(cid, 13337, 1)
            doPlayerSetLossPercent(cid, PLAYERLOSS_EXPERIENCE, 70)
            doPlayerSetLossPercent(cid, PLAYERLOSS_MANA, 70)
            doPlayerSetLossPercent(cid, PLAYERLOSS_SKILL, 70)
            doPlayerSetLossPercent(cid, PLAYERLOSS_ITEMS, 7)
            doPlayerSetLossPercent(cid, PLAYERLOSS_CONTAINERS, 70)
            doSavePlayer(cid)
            doPlayerSendTextMessage(cid, MESSAGE_EVENT_DEFAULT, "You have successfully purchased the first blessing for 70% Loss Percent.")
        else
            doPlayerSendTextMessage(cid, MESSAGE_EVENT_DEFAULT, "You dont have enough gold coins {7,500gp} to purchase this!")
        end
    return false
end

Sources: https://github.com/TwistedScorpio/OTHire/tree/fe351b2cbfdc1bfe1148822bf83eebf7ca01791d

If anyone can help find and solve the problem as I have not been able to find it over the past week of trying different methods, thanks for any help in advance!

Regards,
Extrodus
 
Last edited by a moderator:
The enum names seems to be pointed correctly:
Code:
enum lossTypes_t {
    LOSS_FIRST = 0,
    LOSS_EXPERIENCE = LOSS_FIRST,
    LOSS_MANASPENT = 1,
    LOSS_SKILLTRIES = 2,
    LOSS_ITEMS = 3,
    LOSS_CONTAINERS = 4,
    LOSS_LAST = LOSS_CONTAINERS
};
In relation to:
Code:
PLAYERLOSS_EXPERIENCE = 0
PLAYERLOSS_MANA = 1
PLAYERLOSS_SKILL = 2
PLAYERLOSS_ITEMS = 3
PLAYERLOSS_CONTAINERS = 4

The LuA function seems to be coded correctly.

I would debug these lines at Player.cpp(line 2463):
Code:
double lossPercentSkill = lostPercent * lossPercent[LOSS_SKILLTRIES] / 100;
lostSkillTries = (uint32_t)std::ceil(sumSkillTries * lossPercentSkill);

while(lostSkillTries > skills[i][SKILL_TRIES]){
To check if it retrieves lossPercent accordingly.

Also set out some debug printers inside this function:
Code:
void Player::dropLoot(Container* corpse)
{
    if(!corpse){
        return;
    }

    uint32_t itemLoss = lossPercent[LOSS_ITEMS];
    uint32_t backpackLoss = lossPercent[LOSS_CONTAINERS];
#ifdef __SKULLSYSTEM__
    if(getSkull() == SKULL_RED){
        itemLoss = 100;
        backpackLoss = 100;
    }
#endif
    if(!lootDrop){
        itemLoss = 0;
        backpackLoss = 0;
    }

    if(itemLoss > 0 || backpackLoss > 0){
        for(int i = SLOT_FIRST; i < SLOT_LAST; ++i){
            Item* item = inventory[i];
            if(item){
                if((item->getContainer() && (uint32_t)random_range(1, 100) <= backpackLoss) || (!item->getContainer() && (uint32_t)random_range(1, 100) <= itemLoss)){
                    g_game.internalMoveItem(this, corpse, INDEX_WHEREEVER, item, item->getItemCount(), 0);
                }
            }
        }
    }
}

As this one handles the drop items/containers situation.
 
@Vanderlay, well that's strange. I have tried it multiple different ways and it always drops the backpack, sometimes items as well. Nothing I do stops the exp/skills/mg lvl from decreasing. Getting a bit weirded out by this because it should be working.

If anyone has ideas, please let me know!
 
To the top, still trying to figure this out.

What I have found is this.. which seems like it is using skill tries, and mana spent to calculate how much magic level and skills the player will lose rather than checking the loss percent.

player.cpp
Code:
//Skill loss
uint32_t lostSkillTries;
uint32_t sumSkillTries;
for(uint32_t i = 0; i <= 6; ++i){
lostSkillTries = 0;
sumSkillTries = 0;
for(uint32_t c = 11; c <= skills[i][SKILL_LEVEL]; ++c) {
sumSkillTries += vocation->getReqSkillTries(i, c);
}
sumSkillTries += skills[i][SKILL_TRIES];
double lossPercentSkill = lostPercent * lossPercent[LOSS_SKILLTRIES] / 100;
lostSkillTries = (uint32_t)std::ceil(sumSkillTries * lossPercentSkill);
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] > 10){
skills[i][SKILL_LEVEL]--;
}
else{
skills[i][SKILL_LEVEL] = 10;
skills[i][SKILL_TRIES] = 0;
lostSkillTries = 0;
break;
}
}
skills[i][SKILL_TRIES] = std::max((int32_t)0, (int32_t)(skills[i][SKILL_TRIES] - lostSkillTries));
}
}

Then this is magic,
Code:
//Magic level loss
uint64_t sumMana = 0;
uint64_t lostMana = 0;
for(uint32_t i = 1; i <= magLevel; ++i){
sumMana += vocation->getReqMana(i);
}
sumMana += manaSpent;
double lostPercentMana = lostPercent * lossPercent[LOSS_MANASPENT] / 100;
lostMana = (uint64_t)std::ceil(sumMana * lostPercentMana);
while((uint64_t)lostMana > manaSpent && magLevel > 0){
lostMana -= manaSpent;
manaSpent = vocation->getReqMana(magLevel);
magLevel--;
}
manaSpent = std::max((uint64_t)0, (uint64_t)manaSpent - lostMana);
magLevelPercent = Player::getPercentLevel(manaSpent, vocation->getReqMana(magLevel + 1));

This is all defined under,
Code:
if(getZone() != ZONE_PVP){
loginPosition = masterPos;
if(skillLoss){
uint64_t expLost = getLostExperience();

So it may not even be the proper location since its addressing if it is a PVP Zone/Tile but its the most I could find when searching "Loss_Experience" or "Loss_Skill".
 
Last edited:
Back
Top