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

Help With Item Attributes OTCv8

Derlexy

Intermediate OT User
Joined
Jun 29, 2011
Messages
219
Reaction score
101
Hello guys, how are you? I hope youre all okay.

Quick Resume: I have a upgrade system on my server that players can upgrade items from +1 to +9. Each upgrade gives the item a attribute bonus based on item attributes pool. This system is fully working on server side! Ive implemented it by creating new item attributes. What Im trying to do is to read this attribute values on client side and set a colored frame on items that have been upgraded.

First things first:


How I have implemented it:
I'll not show every piece of code, it would be too long, but you can assume that its working, all the functions on server side works like every original attributes. If you want to know something i've omited, feel free to ask.

Server side: item.h

C++:
enum AttrTypes_t {
    //ATTR_DESCRIPTION = 1,
    //ATTR_EXT_FILE = 2,
    ATTR_TILE_FLAGS = 3,
    ATTR_ACTION_ID = 4,
    ATTR_MOVEMENT_ID = 5,
    ATTR_TEXT = 6,
    ATTR_DESC = 7,
    ATTR_TELE_DEST = 8,
    ATTR_ITEM = 9,
    ATTR_DEPOT_ID = 10,
    //ATTR_EXT_SPAWN_FILE = 11,
    ATTR_RUNE_CHARGES = 12,
    //ATTR_EXT_HOUSE_FILE = 13,
    ATTR_HOUSEDOORID = 14,
    ATTR_COUNT = 15,
    ATTR_DURATION = 16,
    ATTR_DECAYING_STATE = 17,
    ATTR_WRITTENDATE = 18,
    ATTR_WRITTENBY = 19,
    ATTR_SLEEPERGUID = 20,
    ATTR_SLEEPSTART = 21,
    ATTR_CHARGES = 22,
    ATTR_KEYNUMBER = 23,
    ATTR_KEYHOLENUMBER = 24,
    ATTR_DOORQUESTNUMBER = 25,
    ATTR_DOORQUESTVALUE = 26,
    ATTR_DOORLEVEL = 27,
    ATTR_CHESTQUESTNUMBER = 28,
    // add non-OTBM attributes after here
    ATTR_CONTAINER_ITEMS = 29,
    ATTR_NAME = 30,
    ATTR_ARTICLE = 31,
    ATTR_PLURALNAME = 32,
    ATTR_WEIGHT = 33,
    ATTR_ATTACK = 34,
    ATTR_DEFENSE = 35,
    ATTR_ARMOR = 36,
    ATTR_SHOOTRANGE = 37,
    ATTR_ITEMCLASS = 38,
    ATTR_UPGRADES = 39,
    ATTR_UPG_ATTACK = 40,
    ATTR_UPG_DEFENSE = 41,
    ATTR_UPG_ARMOR = 42,
    ATTR_UPG_SPEED = 43,
    ATTR_UPG_LEAN = 44,
    ATTR_UPG_CAPACITY = 45,
    ATTR_UPG_RANGE = 46,
    ATTR_UPG_HEALTH = 47,
    ATTR_UPG_MANA = 48,
    ATTR_UPG_MAGIC = 49,
    ATTR_UPG_SWORD = 50,
    ATTR_UPG_AXE = 51,
    ATTR_UPG_CLUB = 52,
    ATTR_UPG_SHIELD = 53,
    ATTR_UPG_DISTANCE = 54,
};

Server side: item.cpp at "void Item::serializeAttr(PropWriteStream& propWriteStream) const":
C++:
if (hasAttribute(ITEM_ATTRIBUTE_UPGRADES)) {
    propWriteStream.write<uint8_t>(ATTR_UPGRADES);
    propWriteStream.write<int32_t>(getIntAttr(ITEM_ATTRIBUTE_UPGRADES));
}

As I said, the server side stuff is working, items are correctly being saved on database, all the attributes effects are being applied and are working in game.


What I have on my OTCv8:
To be abble to debug if the attributes that are being serialized (on server side) are being read on client side, i have implemented this tooltip: Item stats on Hover-Mouse (https://otland.net/threads/item-stats-on-hover-mouse.272007/#post-2619950)
Lua:
function UIItem:onHoverChange(hovered)
  UIWidget.onHoverChange(self, hovered)
   
  local item = self:getItem()
  if item and not self:getTooltip() then
    self:setTooltip('Item Count: ' .. item:getCount())
  end

  if self:isVirtual() or not self:isDraggable() then return end

  local draggingWidget = g_ui.getDraggingWidget()
  if draggingWidget and self ~= draggingWidget then
    local gotMap = draggingWidget:getClassName() == 'UIGameMap'
    local gotItem = draggingWidget:getClassName() == 'UIItem' and not draggingWidget:isVirtual()
    if hovered and (gotItem or gotMap) then
      self:setBorderWidth(1)
      draggingWidget.hoveredWho = self
    else
      self:setBorderWidth(0)
      draggingWidget.hoveredWho = nil
    end
  end
end
The tooltop is working, like you can see here:
s5mvVt4.png

BTs0q7A.png


Client side: item.h:
As you can se here, on server side the attrbiute ATTR_UPGRADES = 39 and on client side this attribute is ATTR_HITCHANCE = 39. I believe the name doesnt matter, its just a enumeration, but, 39 is what we want, right?
C++:
enum ItemAttr : uint8
{
    ATTR_END = 0,
    //ATTR_DESCRIPTION = 1,
    //ATTR_EXT_FILE = 2,
    ATTR_TILE_FLAGS = 3,
    ATTR_ACTION_ID = 4,
    ATTR_UNIQUE_ID = 5,
    ATTR_TEXT = 6,
    ATTR_DESC = 7,
    ATTR_TELE_DEST = 8,
    ATTR_ITEM = 9,
    ATTR_DEPOT_ID = 10,
    //ATTR_EXT_SPAWN_FILE = 11,
    ATTR_RUNE_CHARGES = 12,
    //ATTR_EXT_HOUSE_FILE = 13,
    ATTR_HOUSEDOORID = 14,
    ATTR_COUNT = 15,
    ATTR_DURATION = 16,
    ATTR_DECAYING_STATE = 17,
    ATTR_WRITTENDATE = 18,
    ATTR_WRITTENBY = 19,
    ATTR_SLEEPERGUID = 20,
    ATTR_SLEEPSTART = 21,
    ATTR_CHARGES = 22,
    ATTR_CONTAINER_ITEMS = 23,
    ATTR_NAME = 30,
    ATTR_PLURALNAME = 31,
    ATTR_ATTACK = 33,
    ATTR_EXTRAATTACK = 34,
    ATTR_DEFENSE = 35,
    ATTR_EXTRADEFENSE = 36,
    ATTR_ARMOR = 37,
    ATTR_ATTACKSPEED = 38,
    ATTR_HITCHANCE = 39,
    ATTR_SHOOTRANGE = 40,
    ATTR_ARTICLE = 41,
    ATTR_SCRIPTPROTECTED = 42,
    ATTR_DUALWIELD = 43,
    ATTR_ATTRIBUTE_MAP = 128
};

Client side: item.cpp at "void Item::unserializeItem(const BinaryTreePtr &in)":
As we can see here, the attribute 39 (on client side its enumerated as ATTR_HITCHANCE) is being read and saved on m_attribs, right?

C++:
void Item::unserializeItem(const BinaryTreePtr &in)
{
    try {
        while(in->canRead()) {
            int attrib = in->getU8();
            if(attrib == 0)
                break;

            switch(attrib) {
                case ATTR_COUNT:
                case ATTR_RUNE_CHARGES:
                    setCount(in->getU8());
                    break;
                case ATTR_CHARGES:
                    setCount(in->getU16());
                    break;
                case ATTR_HOUSEDOORID:
                case ATTR_SCRIPTPROTECTED:
                case ATTR_DUALWIELD:
                case ATTR_DECAYING_STATE:
                    m_attribs.set(attrib, in->getU8());
                    break;
                case ATTR_ACTION_ID:
                case ATTR_UNIQUE_ID:
                case ATTR_DEPOT_ID:
                    m_attribs.set(attrib, in->getU16());
                    break;
                case ATTR_CONTAINER_ITEMS:
                case ATTR_ATTACK:
                case ATTR_EXTRAATTACK:
                case ATTR_DEFENSE:
                case ATTR_EXTRADEFENSE:
                case ATTR_ARMOR:
                case ATTR_ATTACKSPEED:
                case ATTR_HITCHANCE:
                case ATTR_DURATION:
                case ATTR_WRITTENDATE:
                case ATTR_SLEEPERGUID:
                case ATTR_SLEEPSTART:
                case ATTR_ATTRIBUTE_MAP:
                    m_attribs.set(attrib, in->getU32());
                    break;
                case ATTR_TELE_DEST: {
                    Position pos;
                    pos.x = in->getU16();
                    pos.y = in->getU16();
                    pos.z = in->getU8();
                    m_attribs.set(attrib, pos);
                    break;
                }
                case ATTR_NAME:
                case ATTR_TEXT:
                case ATTR_DESC:
                case ATTR_ARTICLE:
                case ATTR_WRITTENBY:
                    m_attribs.set(attrib, in->getString());
                    break;
                default:
                    stdext::throw_exception(stdext::format("invalid item attribute %d", attrib));
            }
        }
    } catch(stdext::exception& e) {
        g_logger.error(stdext::format("Failed to unserialize OTBM item: %s", e.what()));
    }
}

So, to be able to get this attribute value, i tried to do this:

On item.cpp i changed this:
C++:
int Item::getCount()
{
    if(isStackable())
        return m_countOrSubType;
    return 1;
}

To this:
C++:
int Item::getCount()
{
    return m_attribs.get<uint32>(ATTR_HITCHANCE);
    // if(isStackable())
    //     return m_countOrSubType;
    // return 1;
}

But, as we can see, the result i have is as follows:
xK3RzqF.png


It should show "Item Count: 7" if this attribute reading was working... But why 7? Because this blue robe is upgraded to +7, and the attribute that holds this 7 number is the ATTR_UPGRADES on server side, the attribute enumerated as 39:

ilSuAHN.png


Where the hell the description gets this +7 alongside the item name? From here: server side at item.cpp on "std::string Item::getDescription(lot of parameters)":
C++:
std::string Item::getDescription(const ItemType& it, int32_t lookDistance,
    const Item* item /*= nullptr*/, int32_t subType /*= -1*/, bool addArticle /*= true*/)
{
    // some code before
   
    if (item->getUpgrades() > 0) {
        s << " +" << item->getUpgrades();
    }
   
    // lot of code after
}
This getUpgrades() functions gets the value stored at item attribute 39.

Can someonse please help me to understand that?
 
Back
Top