Feature [TFS 1.2] Reflection attribute

Stigma

Support Team
Support Team
Joined
Feb 14, 2015
Messages
4,753
Best answers
422
Reaction score
2,320
enums.h

under the last attribute in itemAttrTypes (ITEM_ATTRIBUTE_DOORID = 1 << 22, if you haven't edited it, and use the number after << + 1 for reflection)
C++:
ITEM_ATTRIBUTE_REFLECTION = 1 << 23,
under ORIGIN_RANGED in CombatOrigin
C++:
ORIGIN_REFLECT,
item.h

in:
C++:
inline static bool isIntAttrType
take the hex value (default is 0x7FFE13) and use bitwise or ( | ) with (1 << 23) and replace the hex with the new value you get (you can do this at Lua: demo) with this code:
Lua:
print(string.format("0x%x", 0x7FFE13 | (1 << 23)))
you should now get 0xFFFE13, replace the value in isIntAttrType with the new hex value we have

under int8_t getHitChance, put:
C++:
        int32_t getReflection() const {
            if (hasAttribute(ITEM_ATTRIBUTE_REFLECTION)) {
                return getIntAttr(ITEM_ATTRIBUTE_REFLECTION);
            }
            return items[id].reflection;
        }
item.cpp

find this code:
C++:
            int32_t attack, defense, extraDefense;
            if (item) {
                attack = item->getAttack();
                defense = item->getDefense();
                extraDefense = item->getExtraDefense();
            } else {
                attack = it.attack;
                defense = it.defense;
                extraDefense = it.extraDefense;
            }
replace it with:
C++:
            int32_t attack, defense, extraDefense, reflection;
            if (item) {
                attack = item->getAttack();
                defense = item->getDefense();
                extraDefense = item->getExtraDefense();
                reflection = item->getReflection();
            } else {
                attack = it.attack;
                defense = it.defense;
                extraDefense = it.extraDefense;
                reflection = it.reflection;
            }
find this piece of code (should be around line 896)
C++:
            if (defense != 0 || extraDefense != 0) {
                if (begin) {
                    begin = false;
                    s << " (";
                } else {
                    s << ", ";
                }

                s << "Def:" << defense;
                if (extraDefense != 0) {
                    s << ' ' << std::showpos << extraDefense << std::noshowpos;
                }
            }
and put this below the code above
C++:
            if (reflection != 0) {
                if (begin) {
                    begin = false;
                    s << " (";
                } else {
                    s << ", ";
                }
               
                s << "Reflection: " << reflection << std::noshowpos << "%";

            }

items.h

under
C++:
int32_t defense = 0;
put
C++:
int32_t reflection = 0;
items.cpp

find:
C++:
        } else if (tmpStrValue == "defense") {
            it.defense = pugi::cast<int32_t>(valueAttribute.value());
put this under it:
C++:
        } else if (tmpStrValue == "reflect") {
            it.reflection = pugi::cast<int32_t>(valueAttribute.value());
player.h

under
C++:
int32_t getArmor() const final;
put
C++:
int32_t getReflection() const;
player.cpp

under:
C++:
int32_t Player::getArmor() const
{
    int32_t armor = 0;

    static const slots_t armorSlots[] = {CONST_SLOT_HEAD, CONST_SLOT_NECKLACE, CONST_SLOT_ARMOR, CONST_SLOT_LEGS, CONST_SLOT_FEET, CONST_SLOT_RING};
    for (slots_t slot : armorSlots) {
        Item* inventoryItem = inventory[slot];
        if (inventoryItem) {
            armor += inventoryItem->getArmor();
        }
    }
    return static_cast<int32_t>(armor * vocation->armorMultiplier);
}
put:
C++:
int32_t Player::getReflection() const
{
    int32_t reflection = 0;

    static const slots_t armorSlots[] = { CONST_SLOT_HEAD, CONST_SLOT_NECKLACE, CONST_SLOT_ARMOR, CONST_SLOT_LEGS, CONST_SLOT_FEET, CONST_SLOT_RING, CONST_SLOT_LEFT, CONST_SLOT_RIGHT };
    for (slots_t slot : armorSlots) {
        Item* inventoryItem = inventory[slot];
        if (inventoryItem) {
            reflection += inventoryItem->getReflection();
        }
    }
    return reflection;
}
game.cpp

inside of
C++:
bool Game::combatChangeHealth(Creature* attacker, Creature* target, CombatDamage& damage)
under:
C++:
target->drainMana(attacker, manaDamage);
put:
C++:
                // mana reflect
                if (targetPlayer && damage.origin != ORIGIN_REFLECT) {
                    int32_t reflection = targetPlayer->getReflection();
                    if (reflection != 0) {
                        CombatDamage reflectDamage;
                        reflectDamage.primary.value = static_cast<int32_t>(-damage.primary.value * (reflection / 100.0));
                        reflectDamage.secondary.value = static_cast<int32_t>(-damage.secondary.value * (reflection / 100.0));
                        reflectDamage.primary.type = damage.primary.type;
                        reflectDamage.secondary.type = damage.secondary.type;
                        reflectDamage.origin = ORIGIN_REFLECT; // create a new origin ORIGIN_REFLECT to avoid infinite reflection between 2 players
                        combatChangeHealth(target, attacker, reflectDamage);
                    }
                }
under: target->drainHealth(attacker, realDamage);
put:
C++:
        // reflect health
        if (targetPlayer && damage.origin != ORIGIN_REFLECT) {
            int32_t reflection = targetPlayer->getReflection();
            if (reflection != 0) {
                CombatDamage reflectDamage;
                reflectDamage.primary.value = static_cast<int32_t>(-damage.primary.value * (reflection / 100.0));
                reflectDamage.secondary.value = static_cast<int32_t>(-damage.secondary.value * (reflection / 100.0));
                reflectDamage.primary.type = damage.primary.type;
                reflectDamage.secondary.type = damage.secondary.type;
                reflectDamage.origin = ORIGIN_REFLECT;
                combatChangeHealth(target, attacker, reflectDamage);
            }
        }


the rest of the code is for scripting purposes, so this isn't 100% necessary if you aren't planning on tampering with reflection using lua

luascript.h

under:
C++:
static int luaItemTypeGetArmor(lua_State* L);
put:
C++:
static int luaItemTypeGetReflection(lua_State* L);
luascript.cpp

under:
C++:
registerEnum(ITEM_ATTRIBUTE_DOORID)
put:
C++:
registerEnum(ITEM_ATTRIBUTE_REFLECTION)
under:
C++:
registerEnum(ORIGIN_RANGED)
put:
C++:
registerEnum(ORIGIN_REFLECT)
under:
C++:
registerMethod("ItemType", "getArmor", LuaScriptInterface::luaItemTypeGetArmor);
put:
C++:
registerMethod("ItemType", "getReflection", LuaScriptInterface::luaItemTypeGetReflection);
under:
C++:
int LuaScriptInterface::luaItemTypeGetArmor(lua_State* L)
{
    // itemType:getArmor()
    const ItemType* itemType = getUserdata<const ItemType>(L, 1);
    if (itemType) {
        lua_pushnumber(L, itemType->armor);
    } else {
        lua_pushnil(L);
    }
    return 1;
}
put:
C++:
int LuaScriptInterface::luaItemTypeGetReflection(lua_State* L)
{
    // itemType:getReflection()
    const ItemType* itemType = getUserdata<const ItemType>(L, -1);
    if (itemType) {
        lua_pushnumber(L, itemType->reflection);
    } else {
        lua_pushnil(L);
    }
    return 1;
}
now you can use ITEM_ATTRIBUTE_REFLECTION, ORIGIN_REFLECT, and itemType:getReflection() in your scripts
you can set reflection inside of items.xml with:
XML:
<attribute key="reflect" value="10"/>
you can set reflection of items with lua using:
Lua:
item:setAttribute(ITEM_ATTRIBUTE_REFLECTION, 10)
also forgot, inside of game.cpp in bool Game::combatChangeHealth(Creature* attacker, Creature* target, CombatDamage& damage)
put
C++:
    if (!target) {
        return false;
    }
at the top of the function, otherwise it will crash when stepping on magic fields that damage you
 
Last edited by a moderator:

Codinablack

Dreamer
Joined
Dec 26, 2013
Messages
1,217
Best answers
4
Reaction score
373
Very nice release! I love that you included the full instructions to properly follow master-branch's coding protocols and standards as with the lua demo you have there :D That's awesome! Lots to learn from here
 

imkingran

Learning everyday.
Premium User
Joined
Jan 15, 2014
Messages
1,258
Best answers
18
Reaction score
379
boiiii :p

Thanks!
 

Fortera Global

Premium User
Premium User
Joined
Nov 20, 2015
Messages
1,063
Best answers
0
Reaction score
47
@Static_ can you give your skype? I need to do something and I will pay for it, please?
 
OP
Stigma

Stigma

Support Team
Support Team
Joined
Feb 14, 2015
Messages
4,753
Best answers
422
Reaction score
2,320
it's an attribute so it only works for items
 

Peonso

Godly Member
Joined
Jan 14, 2008
Messages
1,515
Best answers
24
Reaction score
1,003
item.h

in:
C++:
inline static bool isIntAttrType
take the hex value (default is 0x7FFE13) and use bitwise or ( | ) with (1 << 23) and replace the hex with the new value you get (you can do this at Lua: demo) with this code:
Lua:
print(string.format("0x%x", 0x7FFE13 | (1 << 23)))
you should now get 0xFFFE13, replace the value in isIntAttrType with the new hex value we have
You my hero.
 

Allesn

Member
Joined
May 4, 2011
Messages
208
Best answers
1
Reaction score
23
I did everything correctly, I inserted in the following script: CreatureEvent - [TFS 1.1] Random Item Stats
How can I know if it's working? Is there going to be some animation showing the monster taking damage when attacking me, or will it only subside?
 

Allesn

Member
Joined
May 4, 2011
Messages
208
Best answers
1
Reaction score
23
I did everything correctly, I inserted in the following script: CreatureEvent - [TFS 1.1] Random Item Stats
How can I know if it's working? Is there going to be some animation showing the monster taking damage when attacking me, or will it only subside?
Since I can not edit my comment, I'll say it right here.
I solved the problem, was that I noticed that by default, the item will always have 0 of reflect, so in the script I modified so that when it had 0, a base value was added
 
OP
Stigma

Stigma

Support Team
Support Team
Joined
Feb 14, 2015
Messages
4,753
Best answers
422
Reaction score
2,320
i left something out in this post and i haven't felt like fixing it cause i didn't think people would use this
but to make this feature work correctly you also need to serialize the attribute in Item::serializeAttr
C++:
    if (hasAttribute(ITEM_ATTRIBUTE_REFLECTION)) {
        propWriteStream.write<uint8_t>(ATTR_REFLECTION);
        propWriteStream.write<uint8_t>(getIntAttr(ITEM_ATTRIBUTE_REFLECTION));
    }
and you also need to read the serialized attribute when the item is loaded in Item::readAttr
C++:
        case ATTR_REFLECTION: {
            uint8_t reflection;
            if (!propStream.read<uint8_t>(reflection)) {
                return ATTR_READ_ERROR;
            }

            setIntAttr(ITEM_ATTRIBUTE_REFLECTION, reflection);
            break;
        }
 

Allesn

Member
Joined
May 4, 2011
Messages
208
Best answers
1
Reaction score
23
i left something out in this post and i haven't felt like fixing it cause i didn't think people would use this
but to make this feature work correctly you also need to serialize the attribute in Item::serializeAttr
C++:
    if (hasAttribute(ITEM_ATTRIBUTE_REFLECTION)) {
        propWriteStream.write<uint8_t>(ATTR_REFLECTION);
        propWriteStream.write<uint8_t>(getIntAttr(ITEM_ATTRIBUTE_REFLECTION));
    }
and you also need to read the serialized attribute when the item is loaded in Item::readAttr
C++:
        case ATTR_REFLECTION: {
            uint8_t reflection;
            if (!propStream.read<uint8_t>(reflection)) {
                return ATTR_READ_ERROR;
            }

            setIntAttr(ITEM_ATTRIBUTE_REFLECTION, reflection);
            break;
        }
Error:
identifier "ATTR_REFLECTION" is undefined
 
OP
Stigma

Stigma

Support Team
Support Team
Joined
Feb 14, 2015
Messages
4,753
Best answers
422
Reaction score
2,320
item.h
enum AttrTypes_t {
after ATTR_SHOOTRANGE = 33,
add ATTR_REFLECTION = 34,
 

Fileey

Well-Known Member
Joined
Sep 30, 2009
Messages
45
Best answers
0
Reaction score
6
@Vulcan_ Could you specify above which part I should put the fix for crashing when walking on fields causing damage with a reflection item equipped? Can't seem to get it work correctly..
 

sebaloko

Member
Joined
Jul 5, 2013
Messages
33
Best answers
0
Reaction score
6
Hi vulcan the reflection attribute works great, but i can get to work it to appear on description
Code:
if (reflection != 0) {
                if (begin) {
                    begin = false;
                    s << " (";
                } else {
                    s << ", ";
                }
              
                s << "Reflection: " << reflection << std::noshowpos << "%";
            }
thanks in advance
 
OP
Stigma

Stigma

Support Team
Support Team
Joined
Feb 14, 2015
Messages
4,753
Best answers
422
Reaction score
2,320
Hi vulcan the reflection attribute works great, but i can get to work it to appear on description
Code:
if (reflection != 0) {
                if (begin) {
                    begin = false;
                    s << " (";
                } else {
                    s << ", ";
                }
             
                s << "Reflection: " << reflection << std::noshowpos << "%";
            }
thanks in advance
you CAN or CANT ?
 
Top