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

Imbu don't show in CharacterCombatStats

Newone0

Member
Joined
Nov 22, 2021
Messages
59
Reaction score
7
Imbu absorb is not showing in combat stats

C++:
void ProtocolGame::sendCyclopediaCharacterCombatStats()
{
    NetworkMessage msg;
    msg.addByte(0xDA);
    msg.addByte(CYCLOPEDIA_CHARACTERINFO_COMBATSTATS);
    msg.addByte(0x00);
    for (uint8_t i = SKILL_CRITICAL_HIT_CHANCE; i <= SKILL_LAST; ++i)
    {
        msg.add<uint16_t>(std::min<int32_t>(player->getSkillLevel(i), std::numeric_limits<uint16_t>::max()));
        msg.add<uint16_t>(0);
    }
    
    // Cleave (12.70)
    msg.add<uint16_t>(0);
    // Magic shield capacity (12.70)
    msg.add<uint16_t>(0); // Direct bonus
    msg.add<uint16_t>(0); // Percentage bonus

    // Perfect shot range (12.70)
    for (uint16_t i = 1; i <= 5; i++)
    {
        msg.add<uint16_t>(0x00);
    }

    // Damage reflection
    msg.add<uint16_t>(0);
    
    uint8_t haveBlesses = 0;
    uint8_t blessings = 8;
    for (uint8_t i = 1; i < blessings; ++i)
    {
        if (player->hasBlessing(i))
        {
            ++haveBlesses;
        }
    }
    msg.addByte(haveBlesses);
    msg.addByte(blessings);
    const Item *weapon = player->getWeapon();
    if (weapon)
    {
        const ItemType &it = Item::items[weapon->getID()];
        if (it.weaponType == WEAPON_WAND)
        {
            msg.add<uint16_t>(it.maxHitChance);
            msg.addByte(getCipbiaElement(it.combatType));
            msg.addByte(0);
            msg.addByte(CIPBIA_ELEMENTAL_UNDEFINED);
        }
        else if (it.weaponType == WEAPON_DISTANCE || it.weaponType == WEAPON_AMMO)
        {
            int32_t attackValue = weapon->getAttack();
            if (it.weaponType == WEAPON_AMMO)
            {
                const Item *weaponItem = player->getWeapon(true);
                if (weaponItem)
                {
                    attackValue += weaponItem->getAttack();
                }
            }

            int32_t attackSkill = player->getSkillLevel(SKILL_DISTANCE);
            float attackFactor = player->getAttackFactor();
            int32_t maxDamage = static_cast<int32_t>(Weapons::getMaxWeaponDamage(player->getLevel(), attackSkill, attackValue, attackFactor, true) * player->getVocation()->distDamageMultiplier);
            if (it.abilities && it.abilities->elementType != COMBAT_NONE)
            {
                maxDamage += static_cast<int32_t>(Weapons::getMaxWeaponDamage(player->getLevel(), attackSkill, attackValue - weapon->getAttack() + it.abilities->elementDamage, attackFactor, true) * player->getVocation()->distDamageMultiplier);
            }
            msg.add<uint16_t>(maxDamage >> 1);
            msg.addByte(CIPBIA_ELEMENTAL_PHYSICAL);
            if (it.abilities && it.abilities->elementType != COMBAT_NONE)
            {
                msg.addByte(static_cast<uint32_t>(it.abilities->elementDamage) * 100 / attackValue);
                msg.addByte(getCipbiaElement(it.abilities->elementType));
            }
            else
            {
                msg.addByte(0);
                msg.addByte(CIPBIA_ELEMENTAL_UNDEFINED);
            }
        }
        else
        {
            int32_t attackValue = std::max<int32_t>(0, weapon->getAttack());
            int32_t attackSkill = player->getWeaponSkill(weapon);
            float attackFactor = player->getAttackFactor();
            int32_t maxDamage = static_cast<int32_t>(Weapons::getMaxWeaponDamage(player->getLevel(), attackSkill, attackValue, attackFactor, true) * player->getVocation()->meleeDamageMultiplier);
            if (it.abilities && it.abilities->elementType != COMBAT_NONE)
            {
                maxDamage += static_cast<int32_t>(Weapons::getMaxWeaponDamage(player->getLevel(), attackSkill, it.abilities->elementDamage, attackFactor, true) * player->getVocation()->meleeDamageMultiplier);
            }
            msg.add<uint16_t>(maxDamage >> 1);
            msg.addByte(CIPBIA_ELEMENTAL_PHYSICAL);
            if (it.abilities && it.abilities->elementType != COMBAT_NONE)
            {
                msg.addByte(static_cast<uint32_t>(it.abilities->elementDamage) * 100 / attackValue);
                msg.addByte(getCipbiaElement(it.abilities->elementType));
            }
            else
            {
                msg.addByte(0);
                msg.addByte(CIPBIA_ELEMENTAL_UNDEFINED);
            }
        }
    }
    else
    {
        float attackFactor = player->getAttackFactor();
        int32_t attackSkill = player->getSkillLevel(SKILL_FIST);
        int32_t attackValue = 7;

        int32_t maxDamage = Weapons::getMaxWeaponDamage(player->getLevel(), attackSkill, attackValue, attackFactor, true);
        msg.add<uint16_t>(maxDamage >> 1);
        msg.addByte(CIPBIA_ELEMENTAL_PHYSICAL);
        msg.addByte(0);
        msg.addByte(CIPBIA_ELEMENTAL_UNDEFINED);
    }
    msg.add<uint16_t>(player->getArmor());
    msg.add<uint16_t>(player->getDefense());

    uint8_t combats = 0;
    auto startCombats = msg.getBufferPosition();
    msg.skipBytes(1);

    alignas(16) int16_t absorbs[COMBAT_COUNT] = {};
    for (int32_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; ++slot)
    {
        if (!player->isItemAbilityEnabled(static_cast<slots_t>(slot)))
        {
            continue;
        }

        Item *item = player->getInventoryItem(static_cast<slots_t>(slot));
        if (!item)
        {
            continue;
        }

        const ItemType &it = Item::items[item->getID()];
        if (!it.abilities)
        {
            continue;
        }

        if (COMBAT_COUNT == 12)
        {
            absorbs[0] += it.abilities->absorbPercent[0];
            absorbs[1] += it.abilities->absorbPercent[1];
            absorbs[2] += it.abilities->absorbPercent[2];
            absorbs[3] += it.abilities->absorbPercent[3];
            absorbs[4] += it.abilities->absorbPercent[4];
            absorbs[5] += it.abilities->absorbPercent[5];
            absorbs[6] += it.abilities->absorbPercent[6];
            absorbs[7] += it.abilities->absorbPercent[7];
            absorbs[8] += it.abilities->absorbPercent[8];
            absorbs[9] += it.abilities->absorbPercent[9];
            absorbs[10] += it.abilities->absorbPercent[10];
            absorbs[11] += it.abilities->absorbPercent[11];
        }
        else
        {
            for (uint16_t i = 0; i < COMBAT_COUNT; ++i)
            {
                absorbs[i] += it.abilities->absorbPercent[i];
            }
        }
    }

    static const Cipbia_Elementals_t cipbiaCombats[] = {CIPBIA_ELEMENTAL_PHYSICAL, CIPBIA_ELEMENTAL_ENERGY, CIPBIA_ELEMENTAL_EARTH, CIPBIA_ELEMENTAL_FIRE, CIPBIA_ELEMENTAL_UNDEFINED,
                                                        CIPBIA_ELEMENTAL_LIFEDRAIN, CIPBIA_ELEMENTAL_UNDEFINED, CIPBIA_ELEMENTAL_HEALING, CIPBIA_ELEMENTAL_DROWN, CIPBIA_ELEMENTAL_ICE, CIPBIA_ELEMENTAL_HOLY, CIPBIA_ELEMENTAL_DEATH};
    for (size_t i = 0; i < COMBAT_COUNT; ++i)
    {
        if (absorbs[i] != 0)
        {
            msg.addByte(cipbiaCombats[i]);
            msg.addByte(std::max<int16_t>(-100, std::min<int16_t>(100, absorbs[i])));
            ++combats;
        }
    }

    // Concoctions potions (12.70)
    msg.addByte(0x00);

    msg.setBufferPosition(startCombats);
    msg.addByte(combats);

    writeToOutputBuffer(msg);
}
 
Back
Top