Does magic level percent work like increaceMagicpercent? The old attribute.Attributes MOD additional attributes
ADDITIONAL ATTRIBUTES
- managain
- manaticks
- healthgain
- healthticks
- maxhealthpercent
- maxmanapercent
- soulpercent
- magiclevelpercent
IMPLEMENTATION
- Find the following code in attributesmod.h:
PHP:struct CONVERSION { static const char* SKILL[7]; static const char* STATS[5]; };
- 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; };
- 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 };
- 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";
- 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); }
- 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
- 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
- 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
- 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
- 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
- Find the following code in item.cpp:
PHP:if(it.abilities.regeneration) {
- 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!
This code have 4 years... So it won't work on TFS 1.0, 1.1 and 1.2Tfs 1.2?
Oh, that hurts the truth would be great if you were to tfs 1.x+.This code have 4 years... So it won't work on TFS 1.0, 1.1 and 1.2
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;
}
if use real map i have to add all items in movements?? in real map not all items added in movementsall itens movements need to add in movements.lua. The almost just is there.
You have sucess to add this in tfs 0.4?
if(it.abilities.regeneration)
player->removeCondition(CONDITION_REGENERATION, (ConditionId_t)slot);
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);
if(it.abilities.speed)
g_game.changeSpeed(player, it.abilities.speed);
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);
};
if(it.abilities.speed)
g_game.changeSpeed(player, -it.abilities.speed);
if(it.abilities.speed || item->getAttribute(CONVERSION::SPEED).empty())
g_game.changeSpeed(player, -it.abilities.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";
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";
static const char* MANA_REGEN_GAIN;
static const char* MANA_REGEN_TICK;
static const char* HEALTH_REGEN_GAIN;
static const char* HEALTH_REGEN_TICK;
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;
Have you been able to fix the bug where an item goes directly to a slot and subtracts the skill? For example, I use doPlayerAddItem with a skill attribute of shield +2. If the item goes directly to the inventory, it doesn't add the bonus, and when the item is removed, it subtracts it. For instance, I have 10 shield, and when I remove the shield, it becomes 8. When I log out and log back in, it returns to normal.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
![]()
Looking at items npc trade server crash
Looking at items npc trade server crash.. I have that problem, the Feature - Attributes MOD system, could anyone help? ItemAttributes::getAttribute (this=this@entry=0x0, key=0x619fcd "skillfist") at itemattributes.cpp:76 76 if(!attributes) (gdb) Undefined command...otland.net
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
toCode:if(it.abilities.speed) g_game.changeSpeed(player, it.abilities.speed);
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
toCode:if(it.abilities.speed) g_game.changeSpeed(player, -it.abilities.speed);
and in attributesmod.cpp replaceCode:if(it.abilities.speed || item->getAttribute(CONVERSION::SPEED).empty()) g_game.changeSpeed(player, -it.abilities.speed);
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;
Have you been able to fix the bug where an item goes directly to a slot and subtracts the skill? For example, I use doPlayerAddItem with a skill attribute of shield +2. If the item goes directly to the inventory, it doesn't add the bonus, and when the item is removed, it subtracts it. For instance, I have 10 shield, and when I remove the shield, it becomes 8. When I log out and log back in, it returns to normal.
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);
};
if(it.abilities.speed || item->getAttribute(CONVERSION::SPEED).empty())
g_game.changeSpeed(player, -it.abilities.speed);