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);
}