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

Lua Function [TFS 1.3] Item abilities via Lua

absorb % don't work for me, and magic level have this issue
no change
Code:
01:38 You see a book of lies (Def:18) (magic level +20, magic level percent +20%, protection earth +20%).
It can only be wielded properly by sorcerers and druids of level 200 or higher.
It weighs 25.60 oz.
it can only be wielded properly by druids and sorcerers of level 150 or higher

if i use this script using "ITEM_ABILITY_MAGICPOINTSPERCENT", add magic level but don't show in look
Lua:
function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if not target:isItem() then
        return false
    end
    local position = (toPosition.x ~= 65535 and toPosition or player:getPosition())
    target:setAbility(ITEM_ABILITY_MAGICPOINTSPERCENT, math.random(1, 10))
    position:sendMagicEffect(CONST_ME_MAGIC_RED)
    item:remove()
    return true
end
if i change to
Code:
01:44 You see a book of lies (Def:18) (magic level +3, magic level percent +3%, protection earth +20%).
It can only be wielded properly by sorcerers and druids of level 200 or higher.
It weighs 25.60 oz.
it can only be wielded properly by druids and sorcerers of level 150 or higher
 
Update: Fix magic level %, & code improvement
i've uploaded an attachment with the compiled version with the latest changes

absorb % don't work for me, and magic level have this issue
no change
Code:
01:38 You see a book of lies (Def:18) (magic level +20, magic level percent +20%, protection earth +20%).
It can only be wielded properly by sorcerers and druids of level 200 or higher.
It weighs 25.60 oz.
it can only be wielded properly by druids and sorcerers of level 150 or higher

if i use this script using "ITEM_ABILITY_MAGICPOINTSPERCENT", add magic level but don't show in look
Lua:
function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if not target:isItem() then
        return false
    end
    local position = (toPosition.x ~= 65535 and toPosition or player:getPosition())
    target:setAbility(ITEM_ABILITY_MAGICPOINTSPERCENT, math.random(1, 10))
    position:sendMagicEffect(CONST_ME_MAGIC_RED)
    item:remove()
    return true
end
if i change to
Code:
01:44 You see a book of lies (Def:18) (magic level +3, magic level percent +3%, protection earth +20%).
It can only be wielded properly by sorcerers and druids of level 200 or higher.
It weighs 25.60 oz.
it can only be wielded properly by druids and sorcerers of level 150 or higher
i've tested absorb % (and retested it while i was fixing magic level % to make sure), and it works just fine for me
 

Attachments

  • theforgottenserver.exe
    2.1 MB · Views: 17 · VirusTotal
I think that made the runes pvp damage don't work. Look:


C++:
//CHANGED! BUG FIX SPECIAL CRITIC SKILLS
void Combat::CombatHealthFunc(Creature* caster, Creature* target, const CombatParams& params, CombatDamage* data)
{
   assert(data);
   CombatDamage damage = *data;
   if (g_game.combatBlockHit(damage, caster, target, params.blockedByShield, params.blockedByArmor, params.itemId != 0)) {
       return;
   }

   Player* attackerPlayer = caster ? caster->getPlayer() : nullptr;
   Player* targetPlayer = target ? target->getPlayer() : nullptr;

   if (attackerPlayer && damage.primary.value < 0 || damage.secondary.value < 0) {
       uint16_t chance = attackerPlayer->getSpecialSkill(SPECIALSKILL_HITPOINTSLEECHCHANCE);
       uint16_t skill = attackerPlayer->getSpecialSkill(SPECIALSKILL_HITPOINTSLEECHAMOUNT);
       if (chance != 0 && uniform_random(1, 100) <= chance) {
           CombatDamage lifeLeech;
           lifeLeech.primary.value = std::round(damage.primary.value * (skill / 100.));
           lifeLeech.primary.value += std::round(damage.secondary.value * (skill / 100.));
           g_game.combatChangeHealth(nullptr, attackerPlayer, lifeLeech);
       }

       chance = attackerPlayer->getSpecialSkill(SPECIALSKILL_MANAPOINTSLEECHCHANCE);
       skill = attackerPlayer->getSpecialSkill(SPECIALSKILL_MANAPOINTSLEECHAMOUNT);
       if (chance != 0 && uniform_random(1, 100) <= chance) {
           CombatDamage manaLeech;
           manaLeech.primary.value = std::round(damage.primary.value * (skill / 100.));
           manaLeech.primary.value += std::round(damage.secondary.value * (skill / 100.));
           g_game.combatChangeMana(nullptr, attackerPlayer, manaLeech);
       }

       chance = attackerPlayer->getSpecialSkill(SPECIALSKILL_CRITICALHITCHANCE);
       skill = attackerPlayer->getSpecialSkill(SPECIALSKILL_CRITICALHITAMOUNT);
       if (chance != 0 && uniform_random(1, 100) <= chance) {
           damage.primary.value += std::round(damage.primary.value * (skill / 100.));
           damage.secondary.value += std::round(damage.secondary.value * (skill / 100.));
           g_game.addMagicEffect(target->getPosition(), CONST_ME_CRITICAL_DAMAGE);
       }
   }

   if (g_game.combatChangeHealth(caster, target, damage)) {
       CombatConditionFunc(caster, target, params, &damage);
       CombatDispelFunc(caster, target, params, nullptr);
   }
}

Original combat.cpp:
C++:
void Combat::CombatHealthFunc(Creature* caster, Creature* target, const CombatParams& params, CombatDamage* data)
{
   assert(data);
   CombatDamage damage = *data;
   if (g_game.combatBlockHit(damage, caster, target, params.blockedByShield, params.blockedByArmor, params.itemId != 0)) {
       return;
   }

   if ((damage.primary.value < 0 || damage.secondary.value < 0) && caster) {
       Player* targetPlayer = target->getPlayer();
       if (targetPlayer && caster->getPlayer() && targetPlayer->getSkull() != SKULL_BLACK) {
           damage.primary.value /= 2;
           damage.secondary.value /= 2;
       }
   }

   if (g_game.combatChangeHealth(caster, target, damage)) {
       CombatConditionFunc(caster, target, params, &damage);
       CombatDispelFunc(caster, target, params, nullptr);
   }
}

On the original formula there is a check:
C++:
if (targetPlayer && caster->getPlayer() && targetPlayer->getSkull() != SKULL_BLACK) {
           damage.primary.value /= 2;
           damage.secondary.value /= 2;
       }
 
Hi Vulcan, how are you?
Could you share with us an updated tutorial on dual-weilding?
The ones I found here in the forum gave a problem in tfs 1.3.

Thank you!
 
I managed to compile however when I run the file theforgottenserver-x64.exe opens the window and then closes.

I had this error in the compilation (1>..\src\otserv.cpp(250): warning C4242:), but I believe that this is not the problem.
 
I managed to compile however when I run the file theforgottenserver-x64.exe opens the window and then closes.

I had this error in the compilation (1>..\src\otserv.cpp(250): warning C4242:), but I believe that this is not the problem.
how new are the tfs 1.3 sources you downloaded?
if it's within the past few weeks you need the key.pem file in the same directory as your server exe
 
I was able to compile but the server gets black and then it closes.
See this file.
anyone know why?
 

Attachments

Back
Top