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

Feature Attributes MOD

Attributes MOD additional attributes

ADDITIONAL ATTRIBUTES
  • managain
  • manaticks
  • healthgain
  • healthticks
  • maxhealthpercent
  • maxmanapercent
  • soulpercent
  • magiclevelpercent

IMPLEMENTATION

  1. Find the following code in attributesmod.h:
    PHP:
    struct CONVERSION { 
        static const char* SKILL[7]; 
        static const char* STATS[5]; 
    };
  2. Replace with:
    PHP:
    struct CONVERSION {
        static const char* SKILL[7];
        static const char* STATS[5];
        static const char* STAT_PERCENT[5];
    
        static const char* MANA_REGEN_GAIN;
        static const char* MANA_REGEN_TICK;
        static const char* HEALTH_REGEN_GAIN;
        static const char* HEALTH_REGEN_TICK;
    };
  3. Find the following code in attributesmod.cpp:
    PHP:
    const char* CONVERSION::STATS[5] =
    {
        "maxhealthpoints",          // Increase max health
        "maxmanapoints",            // Increase max mana
        "soulpoints",               // Soul points bonus
        "level_not_implemented",    // Level increase not implemented, but can easily be
                                    // Just set an appropriate attribute name here and follow the comments in movement.cpp and item.cpp
        "magiclevel",               // Magic level bonus
    };
  4. Add this underneath:
    PHP:
    const char* CONVERSION::STAT_PERCENT[5] =
    {
        "maxhealthpercent",           // Increase max health
        "maxmanapercent",             // Increase max mana
        "soulpercent",                  // Soul points bonus
        "level_not_implemented",      // Level increase not implemented, but can easily be
                                      // Just set an appropriate attribute name here and follow the comments in movement.cpp and item.cpp
        "magiclevelpercent",          // Magic level bonus
    };
    
    const char* CONVERSION::HEALTH_REGEN_GAIN = "healthgain";
    const char* CONVERSION::HEALTH_REGEN_TICK = "healthticks";
    const char* CONVERSION::MANA_REGEN_GAIN = "managain";
    const char* CONVERSION::MANA_REGEN_TICK = "manaticks";
  5. Find the following code in movement.cpp:
    PHP:
        if(it.abilities.regeneration)
        {
            Condition* condition = Condition::createCondition((ConditionId_t)slot, CONDITION_REGENERATION, -1, 0);
            if(it.abilities.healthGain)
                condition->setParam(CONDITIONPARAM_HEALTHGAIN, it.abilities.healthGain);
    
            if(it.abilities.healthTicks)
                condition->setParam(CONDITIONPARAM_HEALTHTICKS, it.abilities.healthTicks);
    
            if(it.abilities.manaGain)
                condition->setParam(CONDITIONPARAM_MANAGAIN, it.abilities.manaGain);
    
            if(it.abilities.manaTicks)
                condition->setParam(CONDITIONPARAM_MANATICKS, it.abilities.manaTicks);
    
            player->addCondition(condition);
        }
  6. Replace with:
    PHP:
    // BEGIN ATTRIBUTES MOD
        if(it.abilities.regeneration || 
                !item->getAttribute(CONVERSION::HEALTH_REGEN_GAIN).empty() ||
                !item->getAttribute(CONVERSION::HEALTH_REGEN_TICK).empty() ||
                !item->getAttribute(CONVERSION::MANA_REGEN_GAIN).empty() ||
                !item->getAttribute(CONVERSION::MANA_REGEN_TICK).empty() )
        {
            Condition* condition = Condition::createCondition((ConditionId_t)slot, CONDITION_REGENERATION, -1, 0);
            boost::any attr;
    
            attr = item->getAttribute(CONVERSION::HEALTH_REGEN_GAIN);
            if(it.abilities.healthGain || !attr.empty())
            {
                int32_t val = 0;
    
                if (it.abilities.healthGain)
                    val += it.abilities.healthGain;
                if (!attr.empty() && ((attr.type() == typeid(float)) || (attr.type() == typeid(int32_t))))
                    val += boost::any_cast<int32_t>(attr);
    
                condition->setParam(CONDITIONPARAM_HEALTHGAIN, val);
            }
    
            attr = item->getAttribute(CONVERSION::HEALTH_REGEN_TICK);
            if(it.abilities.healthTicks || !attr.empty())
            {
                int32_t val = 0;
    
                if (it.abilities.healthTicks)
                    val += it.abilities.healthTicks;
                if (!attr.empty() && ((attr.type() == typeid(float)) || (attr.type() == typeid(int32_t))))
                    val += boost::any_cast<int32_t>(attr);
    
                condition->setParam(CONDITIONPARAM_HEALTHTICKS, val);
            }
    
            attr = item->getAttribute(CONVERSION::MANA_REGEN_GAIN);
            if(it.abilities.manaGain || !attr.empty())
            {
                int32_t val = 0;
    
                if (it.abilities.manaGain)
                    val += it.abilities.manaGain;
                if (!attr.empty() && ((attr.type() == typeid(float)) || (attr.type() == typeid(int32_t))))
                    val += boost::any_cast<int32_t>(attr);
    
                condition->setParam(CONDITIONPARAM_MANAGAIN, val);
            }
    
            attr = item->getAttribute(CONVERSION::MANA_REGEN_TICK);
            if(it.abilities.manaTicks || !attr.empty())
            {
                int32_t val = 0;
    
                if (it.abilities.manaTicks)
                    val += it.abilities.manaTicks;
                if (!attr.empty() && ((attr.type() == typeid(float)) || (attr.type() == typeid(int32_t))))
                    val += boost::any_cast<int32_t>(attr);
    
                condition->setParam(CONDITIONPARAM_MANATICKS, val);
            }
    
            player->addCondition(condition);
        }
        // END ATTRIBUTES MOD
  7. Find the following code in movement.cpp:
    PHP:
    // BEGIN ATTRIBUTES MOD 
            if ((stats_t)s != STAT_LEVEL) 
            { 
                boost::any statValue = item->getAttribute(CONVERSION::STATS[s]); 
    
                if (!statValue.empty())  
                { 
                    if ((statValue.type() == typeid(float)) || (statValue.type() == typeid(int32_t)))  
                    { 
                        player->setVarStats((stats_t)s, boost::any_cast<int32_t>(statValue)); 
                        if(!needUpdateStats) 
                            needUpdateStats = true; 
                    } 
                } 
            } 
            // END ATTRIBUTES MOD
  8. Replace with:
    PHP:
            // BEGIN ATTRIBUTES MOD
            if((stats_t)s != STAT_LEVEL) 
            {
                boost::any statValue = item->getAttribute(CONVERSION::STATS[s]);
    
                if (!statValue.empty())
                {
                    if ((statValue.type() == typeid(float)) || (statValue.type() == typeid(int32_t)))
                    {
                        player->setVarStats((stats_t)s, boost::any_cast<int32_t>(statValue));
                        if(!needUpdateStats)
                            needUpdateStats = true;
                    }
                }
    
                statValue = item->getAttribute(CONVERSION::STAT_PERCENT[s]);
    
                if(!statValue.empty())
                {
                    if ((statValue.type() == typeid(float)) || (statValue.type() == typeid(int32_t)))
                    {
                        player->setVarStats((stats_t)s, (int32_t)(player->getDefaultStats((stats_t)s) * ((boost::any_cast<int32_t>(statValue) - 100) / 100.f)));
                        if(!needUpdateStats)
                            needUpdateStats = true;
                    }
                }
            }
            // END ATTRIBUTES MOD
  9. Find the following code in movement.cpp:
    PHP:
    // BEGIN ATTRIBUTES MOD 
            if ((stats_t)s != STAT_LEVEL) 
            { 
                boost::any statValue = item->getAttribute(CONVERSION::STATS[s]); 
    
                if (!statValue.empty())  
                { 
                    if ((statValue.type() == typeid(float)) || (statValue.type() == typeid(int32_t)))  
                    { 
                        player->setVarStats((stats_t)s, -boost::any_cast<int32_t>(statValue)); 
                        if(!needUpdateStats) 
                            needUpdateStats = true; 
                    } 
                } 
            } 
            // END ATTRIBUTES MOD
  10. Replace with:
    PHP:
            // BEGIN ATTRIBUTES MOD
            if ((stats_t)s != STAT_LEVEL)
            {
                boost::any statValue = item->getAttribute(CONVERSION::STATS[s]);
    
                if (!statValue.empty()) 
                {
                    if ((statValue.type() == typeid(float)) || (statValue.type() == typeid(int32_t))) 
                    {
                        player->setVarStats((stats_t)s, -boost::any_cast<int32_t>(statValue));
                        if(!needUpdateStats)
                            needUpdateStats = true;
                    }
                }
    
                statValue = item->getAttribute(CONVERSION::STAT_PERCENT[s]);
    
                if(!statValue.empty())
                {
                    if ((statValue.type() == typeid(float)) || (statValue.type() == typeid(int32_t)))
                    {
                        player->setVarStats((stats_t)s, -(int32_t)(player->getDefaultStats((stats_t)s) * ((boost::any_cast<int32_t>(statValue) - 100) / 100.f)));
                        if(!needUpdateStats)
                            needUpdateStats = true;
                    }
                }
            }
            // END ATTRIBUTES MOD
  11. Find the following code in item.cpp:
    PHP:
    if(it.abilities.regeneration)
        {
  12. Replace all occurrences with:
    PHP:
    // BEGIN ATTRIBUTES MOD
            if(it.abilities.regeneration || 
                !item->getAttribute(CONVERSION::HEALTH_REGEN_GAIN).empty() ||
                !item->getAttribute(CONVERSION::HEALTH_REGEN_TICK).empty() ||
                !item->getAttribute(CONVERSION::MANA_REGEN_GAIN).empty() ||
                !item->getAttribute(CONVERSION::MANA_REGEN_TICK).empty() )
                // END ATTRIBUTES MOD
            {

Just recompile and you are done!
Does magic level percent work like increaceMagicpercent? The old attribute.
 
This code have 4 years... So it won't work on TFS 1.0, 1.1 and 1.2
Oh, that hurts the truth would be great if you were to tfs 1.x+.
But thanks for taking the time to respond! :D
 
#digging I have seg fault on TFS 0.4 after adding this anybody could help me with that :C
 
Can I make an attribute that changes attack speed, walk speed, critical hit, critical chance, etc?
 
Hello,
First of all, thank you for sharing this amazing MOD.
I made all you posted in your thread "attributes MOD" Feature - Attributes MOD and works fine for all skills. Problem comes with STATS, ONLY works with "magiclevel" stat... not with any others.
Maybe you have to source-edit the other stats like maxhealth, maxmana...? to get them work? So, I just did the same as you did for STAT_MAGICLEVEL, but for MAXHEALTH:
C++:
boost::any attr2 = item->getAttribute(CONVERSION::STATS[STAT_MAXHEALTH]);
            if (it.abilities->stats[STAT_MAXHEALTH] || !attr2.empty())
           
            {
                if (begin)
                {
                    begin = false;
                    s << " (";
                }
                else
                    s << ", ";
                // Holds the total increased value
                int32_t val2 = 0;

                // If we have an ability then include that into the value
                if (it.abilities->stats[STAT_MAXHEALTH])
                    val2 = (int32_t)it.abilities->stats[STAT_MAXHEALTH];
                // Make sure the value exist and that it is either float or integer.
                if (!attr2.empty() && ((attr2.type() == typeid(float)) || (attr2.type() == typeid(int32_t))))
                {
                    // Add attribute value to val
                    val2 += boost::any_cast<int32_t>(attr2);
                }
                s << "max health " << std::showpos << it.abilities->stats[STAT_MAXHEALTH] << std::noshowpos;
            }
It seems fine, but then my item gets 'max health +0' BUT when I equip it, IT WORKS! how is it possible?
PS. If you noted, I used variables 'attr' and 'val', as 'attr2' and 'val2' because if not, visual studio doesn't let me compile it.
 
Hello guys. I know this is old. But I have an issue.
Is possible do it with the function absorbpercent?
Can someone help me?
Thanks.
 
this system work good but need to make it work auto without registering anyone can help me in code
im use 0.4
 
all itens movements need to add in movements.lua. The almost just is there.
You have sucess to add this in tfs 0.4?
 
Just a simple itens dont are in movements. But if you hunt to upgrade someone is needed to put there to active.
 
anyone use this system must be careful about 2 things.
first one this system crash server when player look on items from npc windows
u can fix it by this way

second thing regeneration work after you remove items from slot
u can fix this by
remove this
Code:
    if(it.abilities.regeneration)
        player->removeCondition(CONDITION_REGENERATION, (ConditionId_t)slot);

to be like be
Code:
    if(it.abilities.regeneration || item->getAttribute(CONVERSION::HEALTH_REGEN_GAIN).empty()
        || item->getAttribute(CONVERSION::HEALTH_REGEN_TICK).empty()
        || item->getAttribute(CONVERSION::MANA_REGEN_GAIN).empty()
        ||item->getAttribute(CONVERSION::MANA_REGEN_TICK).empty())
        player->removeCondition(CONDITION_REGENERATION, (ConditionId_t)slot);

no more error

to use speed
change
Code:
    if(it.abilities.speed)
        g_game.changeSpeed(player, it.abilities.speed);
to
Code:
 if(it.abilities.speed  || item->getAttribute(CONVERSION::SPEED).empty())
    {
        boost::any attr;
        attr = item->getAttribute(CONVERSION::SPEED);
        int32_t val = 0;
                if (it.abilities.speed)
                val += it.abilities.speed;
            if (!attr.empty() && ((attr.type() == typeid(float)) || (attr.type() == typeid(int32_t))))
                val += boost::any_cast<int32_t>(attr);
        g_game.changeSpeed(player, val);
};

and replace
Code:
    if(it.abilities.speed)
        g_game.changeSpeed(player, -it.abilities.speed);
to
Code:
    if(it.abilities.speed || item->getAttribute(CONVERSION::SPEED).empty())
        g_game.changeSpeed(player, -it.abilities.speed);
and in attributesmod.cpp replace
Code:
const char* CONVERSION::HEALTH_REGEN_GAIN = "healthgain";
const char* CONVERSION::HEALTH_REGEN_TICK = "healthticks";
const char* CONVERSION::MANA_REGEN_GAIN = "managain";
const char* CONVERSION::MANA_REGEN_TICK = "manaticks";

to

Code:
const char* CONVERSION::SPEED = "speed";
const char* CONVERSION::HEALTH_REGEN_GAIN = "healthgain";
const char* CONVERSION::HEALTH_REGEN_TICK = "healthticks";
const char* CONVERSION::MANA_REGEN_GAIN = "managain";
const char* CONVERSION::MANA_REGEN_TICK = "manaticks";

and in attributesmod.h replace
Code:
    static const char* MANA_REGEN_GAIN;
    static const char* MANA_REGEN_TICK;
    static const char* HEALTH_REGEN_GAIN;
    static const char* HEALTH_REGEN_TICK;

to
Code:
    static const char* SPEED;
    static const char* MANA_REGEN_GAIN;
    static const char* MANA_REGEN_TICK;
    static const char* HEALTH_REGEN_GAIN;
    static const char* HEALTH_REGEN_TICK;
 
Last edited:
Back
Top