Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: display imbuement damage reductions in cyclopedia #819

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions data/items/items.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<items>
<!-- Liquids -->
<!-- Fluid type 0 is same as water (id="1") -->
<item id="1" name="water" />
<item id="1" name="water" />
<item id="2" name="wine" />
<item id="3" name="beer" />
<item id="4" name="mud" />
Expand Down Expand Up @@ -20752,7 +20752,7 @@
</item>
<item id="11258" article="a" name="unknown item">
<attribute key="duration" value="10"/>
<attribute key="decayTo" value="11257"/>
<attribute key="decayTo" value="11257"/>
</item>
<item fromid="11259" toid="11262" article="a" name="banner"/>
<item fromid="11263" toid="11264" article="a" name="tapestry"/>
Expand Down Expand Up @@ -35287,7 +35287,7 @@
<attribute key="healthgain" value="3"/>
<attribute key="speed" value="30"/>
<attribute key="duration" value="3600"/>
<attribute key="transformdeequipto" value="23477"/>
<attribute key="transformdeequipto" value="23477"/>
<attribute key="decayTo" value="0"/>
<attribute key="armor" value="2"/>
<attribute key="weight" value="1500"/>
Expand Down Expand Up @@ -52606,7 +52606,7 @@
<attribute key="description" value="Juding by the pinching of his beak, this one seems to be born to joust"/>
<attribute key="wrapableto" value="23398"/>
</item>
<!-- Unmoveable decorative items -->
<!-- Unmoveable decorative items -->
<item id="37213" article="a" name="blue balloon"/>
<item id="37214" article="a" name="green balloon"/>
<item id="37215" article="an" name="orange balloon"/>
Expand Down Expand Up @@ -52664,7 +52664,7 @@
<item id="37297" article="a" name="blue Tibia carpet"/>
<item id="37298" article="a" name="purple Tibia carpet"/>
<item id="37299" article="a" name="pink Tibia carpet"/>
<!-- End of Unmoveable Decorative items-->
<!-- End of Unmoveable Decorative items-->
<item id="37303" article="a" name="half empty picture album">
<attribute key="description" value="Eight pictures are missing. Under the first missing one you read: &quot;Banner of the Falcon Order&quot;" />
<attribute key="weight" value="500"/>
Expand Down
59 changes: 57 additions & 2 deletions src/creatures/players/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@ void Player::updateInventoryImbuement()
for (auto item : getAllInventoryItems())
{
// Iterate through all imbuement slots on the item

for (uint8_t slotid = 0; slotid < item->getImbuementSlot(); slotid++)
{
ImbuementInfo imbuementInfo;
Expand Down Expand Up @@ -1363,7 +1364,7 @@ void Player::sendMarketEnter(uint32_t depotId)
if (!client || this->getLastDepotId() == -1 || !depotId) {
return;
}

client->sendMarketEnter(depotId);
}

Expand Down Expand Up @@ -3719,6 +3720,60 @@ std::vector<Item*> Player::getInventoryItemsFromId(uint16_t itemId, bool ignore
return itemVector;
}

std::array<double_t, COMBAT_COUNT> Player::getFinalDamageReduction() const {
std::array<double_t, COMBAT_COUNT> combatReductionArray;
combatReductionArray.fill(0);
calculateDamageReductionFromEquipedItems(combatReductionArray);
for (int combatTypeIndex = 0; combatTypeIndex < COMBAT_COUNT; combatTypeIndex++) {
combatReductionArray[combatTypeIndex] = std::clamp<int8_t>(std::floor(combatReductionArray[combatTypeIndex]), -100, 100);
}
return combatReductionArray;
}


void Player::calculateDamageReductionFromEquipedItems(std::array<double_t, COMBAT_COUNT> &combatReductionArray) const {
for (uint8_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; ++slot) {
Item *item = inventory[slot];
if (item) {
calculateDamageReductionFromItem(combatReductionArray, item);
}
}
}

void Player::calculateDamageReductionFromItem(std::array<double_t, COMBAT_COUNT> &combatReductionArray, Item *item) const {
for (uint16_t combatTypeIndex = 0; combatTypeIndex < COMBAT_COUNT; combatTypeIndex++) {
updateDamageReductionFromItemImbuement(combatReductionArray, item, combatTypeIndex);
updateDamageReductionFromItemAbility(combatReductionArray, item, combatTypeIndex);
}
}

void Player::updateDamageReductionFromItemImbuement(std::array<double_t, COMBAT_COUNT> &combatReductionArray, Item *item, uint16_t combatTypeIndex) const {
for (uint8_t imbueSlotId = 0; imbueSlotId < item->getImbuementSlot(); imbueSlotId++) {
ImbuementInfo imbuementInfo;
if (item->getImbuementInfo(imbueSlotId, &imbuementInfo) && imbuementInfo.imbuement) {
int16_t imbuementAbsorption = imbuementInfo.imbuement->absorbPercent[combatTypeIndex];
if(imbuementAbsorption != 0) {
combatReductionArray[combatTypeIndex] = calculateDamageReduction(combatReductionArray[combatTypeIndex], imbuementAbsorption);
}
}
}
}

void Player::updateDamageReductionFromItemAbility(std::array<double_t, COMBAT_COUNT> &combatReductionArray, const Item *item, uint16_t combatTypeIndex) const {
if(!item) return;
const ItemType &itemType = Item::items[item->getID()];
if (itemType.abilities) {
int16_t elementReduction = itemType.abilities->absorbPercent[combatTypeIndex];
if (elementReduction != 0) {
combatReductionArray[combatTypeIndex] = calculateDamageReduction(combatReductionArray[combatTypeIndex], elementReduction);
}
}
}

double_t Player::calculateDamageReduction(double_t currentTotal, int16_t resistance) const {
return (100 - currentTotal) / 100.0 * resistance + currentTotal;
}

std::vector<Item*> Player::getAllInventoryItems(bool ignoreEquiped /*= false*/) const
{
std::vector<Item*> itemVector;
Expand Down Expand Up @@ -5973,7 +6028,7 @@ std::string Player::getBlessingsName() const
std::ostringstream os;
for (uint8_t i = 1; i <= 8; i++) {
if (hasBlessing(i)) {
if (auto blessName = BlessingNames.find(static_cast<Blessings_t>(i));
if (auto blessName = BlessingNames.find(static_cast<Blessings_t>(i));
blessName != BlessingNames.end()) {
os << (*blessName).second;
} else {
Expand Down
18 changes: 14 additions & 4 deletions src/creatures/players/player.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ struct ForgeHistory {
bool tierLoss = false;
bool successCore = false;
bool tierCore = false;

std::string description;
std::string firstItemName;
std::string secondItemName;
Expand Down Expand Up @@ -382,7 +382,7 @@ class Player final : public Creature, public Cylinder
uint8_t getBlessingCount(uint8_t index) const {
return blessings[index - 1];
}
std::string getBlessingsName() const;
std::string getBlessingsName() const;

bool isOffline() const {
return (getID() == 0);
Expand Down Expand Up @@ -2085,7 +2085,7 @@ class Player final : public Creature, public Cylinder
void forgeTransferItemTier(uint16_t donorItemId, uint8_t tier, uint16_t receiveItemId);
void forgeResourceConversion(uint8_t action);
void forgeHistory(uint8_t page) const;

void sendOpenForge() const
{
if (client)
Expand Down Expand Up @@ -2181,6 +2181,8 @@ class Player final : public Creature, public Cylinder

void registerForgeHistoryDescription(ForgeHistory history);

std::map<uint16_t, Item*> getEquippedItemsWithEnabledAbilitiesBySlot() const;

private:
std::forward_list<Condition*> getMuteConditions() const;

Expand Down Expand Up @@ -2521,7 +2523,15 @@ class Player final : public Creature, public Cylinder
friend class MoveEvent;
friend class BedItem;

account::Account *account_;
account::Account *account_;

std::array<double_t, COMBAT_COUNT> getFinalDamageReduction() const;
void calculateDamageReductionFromEquipedItems(std::array<double_t, COMBAT_COUNT> &combatReductionMap) const;
void calculateDamageReductionFromItem(std::array<double_t, COMBAT_COUNT> &combatReductionMap, Item *item) const;
void updateDamageReductionFromItemImbuement(std::array<double_t, COMBAT_COUNT> &combatReductionMap, Item *item, uint16_t combatTypeIndex) const;
void updateDamageReductionFromItemAbility(std::array<double_t, COMBAT_COUNT> &combatReductionMap, const Item *item, uint16_t combatTypeIndex) const;
double_t calculateDamageReduction(double_t currentTotal, int16_t resistance) const;
};


#endif // SRC_CREATURES_PLAYERS_PLAYER_H_
68 changes: 12 additions & 56 deletions src/server/network/protocol/protocolgame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ void ProtocolGame::AddItem(NetworkMessage &msg, const Item *item)
}
else if (it.isSplash() || it.isFluidContainer())
{
msg.addByte(static_cast<uint8_t>(item->getFluidType()));
msg.addByte(static_cast<uint8_t>(item->getFluidType()));
}
else if (it.isContainer())
{
Expand Down Expand Up @@ -3185,58 +3185,14 @@ void ProtocolGame::sendCyclopediaCharacterCombatStats()
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 (size_t i = 0; i < COMBAT_COUNT; ++i)
{
absorbs[i] += it.abilities->absorbPercent[i];
}
}
}

const std::array<double_t, COMBAT_COUNT> &damageReduction = player->getFinalDamageReduction();
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)
{
for (size_t i = 0; i < COMBAT_COUNT; ++i) {
int8_t finalDamage = damageReduction[i];
if (finalDamage != 0) {
msg.addByte(cipbiaCombats[i]);
msg.addByte(std::max<int16_t>(-100, std::min<int16_t>(100, absorbs[i])));
msg.addByte(finalDamage);
++combats;
}
}
Expand Down Expand Up @@ -4574,7 +4530,7 @@ void ProtocolGame::sendForgeHistory(uint8_t page)
msg.addByte((history.bonus >= 1 && history.bonus < 8) ? 0x01 : 0x00);
}
}

writeToOutputBuffer(msg);
}

Expand Down Expand Up @@ -6225,7 +6181,7 @@ void ProtocolGame::sendPreyData(const PreySlot* slot)
msg.addByte(player->isPremium() ? 0x01 : 0x00);
} else if (slot->state == PreyDataState_Inactive) {
// Empty
} else if (slot->state == PreyDataState_Active) {
} else if (slot->state == PreyDataState_Active) {
if (const MonsterType* mtype = g_monsters().getMonsterTypeByRaceId(slot->selectedRaceId)) {
msg.addString(mtype->name);
const Outfit_t outfit = mtype->info.outfit;
Expand Down Expand Up @@ -7329,7 +7285,7 @@ void ProtocolGame::parseDepotSearchItemRequest(NetworkMessage &msg)
if (Item::items[itemId].upgradeClassification > 0) {
itemTier = msg.getByte();
}

addGameTask(&Game::playerRequestDepotSearchItem, player->getID(), itemId, itemTier);
}

Expand All @@ -7341,7 +7297,7 @@ void ProtocolGame::parseRetrieveDepotSearch(NetworkMessage &msg)
itemTier = msg.getByte();
}
uint8_t type = msg.getByte();

addGameTask(&Game::playerRequestDepotSearchRetrieve, player->getID(), itemId, itemTier, type);
}

Expand All @@ -7355,7 +7311,7 @@ void ProtocolGame::parseOpenParentContainer(NetworkMessage &msg)
void ProtocolGame::sendUpdateCreature(const Creature* creature)
{
if (!creature || !player) {
return;
return;
}

if (!canSee(creature))
Expand All @@ -7366,7 +7322,7 @@ void ProtocolGame::sendUpdateCreature(const Creature* creature)
return;
}

NetworkMessage msg;
NetworkMessage msg;
msg.addByte(0x6B);
msg.addPosition(creature->getPosition());
msg.addByte(static_cast<uint8_t>(stackPos));
Expand Down