Rodrigo Tolomeo
Member
Hello everyone,
First of all, I have some programming experience and familiarity with it. However, this is my first encounter with Tibia's code, and it's also a different programming language than the one I'm used to.
I'm facing an issue in my C++ code related to calculating shared experience in an online game. I have a party system where players can hunt together and share the experience gained from creature kills. However, I'm having difficulties ensuring that the experience is evenly distributed among all party members when one player deals the majority of the damage.
Here's a summary of my problem:
Here's the relevant code snippet where I'm facing this issue.
With my experience, I've managed to identify some relevant functions, but I must admit that I'm confused. Here they are:
getDamageRatio Function
onDeath Function
I've tried to change it and reformulate the logic a bit to what I need, but without any success.
I'd be grateful if anyone could help!
First of all, I have some programming experience and familiarity with it. However, this is my first encounter with Tibia's code, and it's also a different programming language than the one I'm used to.
I'm facing an issue in my C++ code related to calculating shared experience in an online game. I have a party system where players can hunt together and share the experience gained from creature kills. However, I'm having difficulties ensuring that the experience is evenly distributed among all party members when one player deals the majority of the damage.
Here's a summary of my problem:
- When a party is hunting, and only one of the players can deal around 80% to 90% of the creature's damage, while the other party members deal the remaining damage, the experience is being distributed based on the damage dealt by the attacker, rather than evenly among all party members.
- If only the party leader deals 100% of the damage, the experience is incorrectly share.
- If only one party member deals 100% of the damage, the experience is share incorrectly.
- Here, the player "Teste02" dealt approximately 80% to 90% of the creature's health, while the player "Teste01" dealt the remaining damage.
- If each member, including the party leader, deals around 50% of the creature's health, the experience is divided correctly.
- I need the experience to be shared equally among all party members, regardless of who dealt the most damage. Since my server version is 7.2 to 7.6, and the vocations deal higher damage than usual, not all players will be able to deal a high percentage of damage to the creatures they are hunting when they are in a party.
Here's the relevant code snippet where I'm facing this issue.
With my experience, I've managed to identify some relevant functions, but I must admit that I'm confused. Here they are:
getDamageRatio Function
C++:
double Creature::getDamageRatio(Creature* attacker) const
{
uint32_t totalDamage = 0;
uint32_t attackerDamage = 0;
for (const auto& it : damageMap) {
const CountBlock_t& cb = it.second;
totalDamage += cb.total;
if (it.first == attacker->getID()) {
attackerDamage += cb.total;
}
}
if (totalDamage == 0) {
return 0;
}
return (static_cast<double>(attackerDamage) / totalDamage);
}
onDeath Function
C++:
void Creature::onDeath()
{
bool lastHitUnjustified = false;
bool mostDamageUnjustified = false;
Creature* lastHitCreature = g_game.getCreatureByID(lastHitCreatureId);
Creature* lastHitCreatureMaster;
if (lastHitCreature) {
lastHitUnjustified = lastHitCreature->onKilledCreature(this);
lastHitCreatureMaster = lastHitCreature->getMaster();
} else {
lastHitCreatureMaster = nullptr;
}
Creature* mostDamageCreature = nullptr;
const int64_t timeNow = OTSYS_TIME();
const uint32_t inFightTicks = g_config.getNumber(ConfigManager::PZ_LOCKED);
int32_t mostDamage = 0;
std::map<Creature*, uint64_t> experienceMap;
for (const auto& it : damageMap) {
if (Creature* attacker = g_game.getCreatureByID(it.first)) {
CountBlock_t cb = it.second;
if ((cb.total > mostDamage && (timeNow - cb.ticks <= inFightTicks))) {
mostDamage = cb.total;
mostDamageCreature = attacker;
}
if (attacker != this) {
uint64_t gainExp = getGainedExperience(attacker);
if (Player* attackerPlayer = attacker->getPlayer()) {
attackerPlayer->removeAttacked(getPlayer());
Party* party = attackerPlayer->getParty();
if (party && party->getLeader() && party->isSharedExperienceActive() &&
party->isSharedExperienceEnabled()) {
attacker = party->getLeader();
}
}
auto tmpIt = experienceMap.find(attacker);
if (tmpIt == experienceMap.end()) {
experienceMap[attacker] = gainExp;
} else {
tmpIt->second += gainExp;
}
}
}
}
for (const auto& it : experienceMap) {
it.first->onGainExperience(it.second, this);
}
if (mostDamageCreature) {
if (mostDamageCreature != lastHitCreature && mostDamageCreature != lastHitCreatureMaster) {
Creature* mostDamageCreatureMaster = mostDamageCreature->getMaster();
if (lastHitCreature != mostDamageCreatureMaster &&
(!lastHitCreatureMaster || mostDamageCreatureMaster != lastHitCreatureMaster)) {
mostDamageUnjustified = mostDamageCreature->onKilledCreature(this, false);
}
}
}
bool droppedCorpse = dropCorpse(lastHitCreature, mostDamageCreature, lastHitUnjustified, mostDamageUnjustified);
death(lastHitCreature);
if (master) {
setMaster(nullptr);
}
if (droppedCorpse) {
g_game.removeCreature(this, false);
}
}
I've tried to change it and reformulate the logic a bit to what I need, but without any success.
I'd be grateful if anyone could help!
Last edited: