Skip to content

Commit

Permalink
fix: bestiary double counting in party
Browse files Browse the repository at this point in the history
  • Loading branch information
luan committed Oct 28, 2023
1 parent 178372b commit d36b1ea
Show file tree
Hide file tree
Showing 11 changed files with 193 additions and 163 deletions.
40 changes: 20 additions & 20 deletions data/libs/concoctions_lib.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,26 @@ ConcoctionTickType = {
Concoction = {}
Concoction.__index = Concoction
Concoction.Ids = {
KooldownAid = 36723,
StaminaExtension = 36725,
StrikeEnhancement = 36724,
CharmUpgrade = 36726,
WealthDuplex = 36727,
BestiaryBetterment = 36728,
FireResilience = 36729,
IceResilience = 36730,
EarthResilience = 36731,
EnergyResilience = 36732,
HolyResilience = 36733,
DeathResilience = 36734,
PhysicalResilience = 36735,
FireAmplification = 36736,
IceAmplification = 36737,
EarthAmplification = 36738,
EnergyAmplification = 36739,
HolyAmplification = 36740,
DeathAmplification = 36741,
PhysicalAmplification = 36742,
KooldownAid = Concoction_KooldownAid,
StaminaExtension = Concoction_StaminaExtension,
StrikeEnhancement = Concoction_StrikeEnhancement,
CharmUpgrade = Concoction_CharmUpgrade,
WealthDuplex = Concoction_WealthDuplex,
BestiaryBetterment = Concoction_BestiaryBetterment,
FireResilience = Concoction_FireResilience,
IceResilience = Concoction_IceResilience,
EarthResilience = Concoction_EarthResilience,
EnergyResilience = Concoction_EnergyResilience,
HolyResilience = Concoction_HolyResilience,
DeathResilience = Concoction_DeathResilience,
PhysicalResilience = Concoction_PhysicalResilience,
FireAmplification = Concoction_FireAmplification,
IceAmplification = Concoction_IceAmplification,
EarthAmplification = Concoction_EarthAmplification,
EnergyAmplification = Concoction_EnergyAmplification,
HolyAmplification = Concoction_HolyAmplification,
DeathAmplification = Concoction_DeathAmplification,
PhysicalAmplification = Concoction_PhysicalAmplification,
}

function Concoction.find(identifier)
Expand Down
35 changes: 0 additions & 35 deletions data/scripts/creatureevents/bestiary_kill.lua

This file was deleted.

33 changes: 0 additions & 33 deletions data/scripts/creatureevents/bosstiary_kill.lua

This file was deleted.

22 changes: 8 additions & 14 deletions src/creatures/creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,14 +625,6 @@ void Creature::onCreatureMove(std::shared_ptr<Creature> creature, std::shared_pt
void Creature::onDeath() {
bool lastHitUnjustified = false;
bool mostDamageUnjustified = false;
std::shared_ptr<Creature> lastHitCreature = g_game().getCreatureByID(lastHitCreatureId);
std::shared_ptr<Creature> lastHitCreatureMaster;
if (lastHitCreature) {
lastHitUnjustified = lastHitCreature->onKilledCreature(static_self_cast<Creature>(), true);
lastHitCreatureMaster = lastHitCreature->getMaster();
} else {
lastHitCreatureMaster = nullptr;
}

std::shared_ptr<Creature> mostDamageCreature = nullptr;

Expand Down Expand Up @@ -674,13 +666,15 @@ void Creature::onDeath() {
it.first->onGainExperience(it.second, getCreature());
}

std::shared_ptr<Creature> mostDamageCreatureMaster = nullptr;
if (mostDamageCreature) {
if (mostDamageCreature != lastHitCreature && mostDamageCreature != lastHitCreatureMaster) {
auto mostDamageCreatureMaster = mostDamageCreature->getMaster();
if (lastHitCreature != mostDamageCreatureMaster && (lastHitCreatureMaster == nullptr || mostDamageCreatureMaster != lastHitCreatureMaster)) {
mostDamageUnjustified = mostDamageCreature->onKilledCreature(static_self_cast<Creature>(), false);
}
}
mostDamageCreatureMaster = mostDamageCreature->getMaster();
mostDamageUnjustified = mostDamageCreature->onKilledCreature(getCreature(), false);
}

std::shared_ptr<Creature> lastHitCreature = g_game().getCreatureByID(lastHitCreatureId);
if (lastHitCreature && lastHitCreature != mostDamageCreature && lastHitCreature != mostDamageCreatureMaster) {
lastHitUnjustified = lastHitCreature->onKilledCreature(getCreature(), true);
}

bool droppedCorpse = dropCorpse(lastHitCreature, mostDamageCreature, lastHitUnjustified, mostDamageUnjustified);
Expand Down
10 changes: 7 additions & 3 deletions src/creatures/monsters/monsters.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,15 +185,19 @@ class MonsterType {
}

float getHealthMultiplier() const {
return info.bosstiaryClass.empty() ? g_configManager().getFloat(RATE_MONSTER_HEALTH) : g_configManager().getFloat(RATE_BOSS_HEALTH);
return isBoss() ? g_configManager().getFloat(RATE_MONSTER_HEALTH) : g_configManager().getFloat(RATE_BOSS_HEALTH);
}

float getAttackMultiplier() const {
return info.bosstiaryClass.empty() ? g_configManager().getFloat(RATE_MONSTER_ATTACK) : g_configManager().getFloat(RATE_BOSS_ATTACK);
return isBoss() ? g_configManager().getFloat(RATE_MONSTER_ATTACK) : g_configManager().getFloat(RATE_BOSS_ATTACK);
}

float getDefenseMultiplier() const {
return info.bosstiaryClass.empty() ? g_configManager().getFloat(RATE_MONSTER_DEFENSE) : g_configManager().getFloat(RATE_BOSS_DEFENSE);
return isBoss() ? g_configManager().getFloat(RATE_MONSTER_DEFENSE) : g_configManager().getFloat(RATE_BOSS_DEFENSE);
}

bool isBoss() const {
return !info.bosstiaryClass.empty();
}

void loadLoot(const std::shared_ptr<MonsterType> monsterType, LootBlock lootblock);
Expand Down
10 changes: 9 additions & 1 deletion src/creatures/players/grouping/party.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ class Party : public SharedObject {
std::shared_ptr<Player> getLeader() const {
return m_leader.lock();
}
std::vector<std::shared_ptr<Player>> getPlayers() const {
std::vector<std::shared_ptr<Player>> players;
for (auto &member : memberList) {
players.push_back(member);
}
players.push_back(getLeader());
return players;
}
std::vector<std::shared_ptr<Player>> getMembers() {
return memberList;
}
Expand Down Expand Up @@ -68,7 +76,7 @@ class Party : public SharedObject {
void shareExperience(uint64_t experience, std::shared_ptr<Creature> target = nullptr);
bool setSharedExperience(std::shared_ptr<Player> player, bool sharedExpActive, bool silent = false);
bool isSharedExperienceActive() const {
return sharedExpActive;
return sharedExpEnabled && sharedExpActive;
}
bool isSharedExperienceEnabled() const {
return sharedExpEnabled;
Expand Down
143 changes: 86 additions & 57 deletions src/creatures/players/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4583,75 +4583,104 @@ void Player::onTargetCreatureGainHealth(std::shared_ptr<Creature> target, int32_
}
}

bool Player::onKilledCreature(std::shared_ptr<Creature> target, bool lastHit /* = true*/) {
bool Player::onKilledPlayer(const std::shared_ptr<Player> &target, bool lastHit) {
bool unjustified = false;

if (hasFlag(PlayerFlags_t::NotGenerateLoot)) {
if (target->getZoneType() == ZONE_PVP) {
target->setDropLoot(false);
}

Creature::onKilledCreature(target, lastHit);

if (auto targetPlayer = target->getPlayer()) {
if (targetPlayer && targetPlayer->getZoneType() == ZONE_PVP) {
targetPlayer->setDropLoot(false);
targetPlayer->setSkillLoss(false);
} else if (!hasFlag(PlayerFlags_t::NotGainInFight) && !isPartner(targetPlayer)) {
if (!Combat::isInPvpZone(getPlayer(), targetPlayer) && hasAttacked(targetPlayer) && !targetPlayer->hasAttacked(getPlayer()) && !isGuildMate(targetPlayer) && targetPlayer != getPlayer()) {
if (targetPlayer->hasKilled(getPlayer())) {
for (auto &kill : targetPlayer->unjustifiedKills) {
if (kill.target == getGUID() && kill.unavenged) {
kill.unavenged = false;
auto it = attackedSet.find(targetPlayer->guid);
attackedSet.erase(it);
break;
}
target->setSkillLoss(false);
} else if (!hasFlag(PlayerFlags_t::NotGainInFight) && !isPartner(target)) {
if (!Combat::isInPvpZone(getPlayer(), target) && hasAttacked(target) && !target->hasAttacked(getPlayer()) && !isGuildMate(target) && target != getPlayer()) {
if (target->hasKilled(getPlayer())) {
for (auto &kill : target->unjustifiedKills) {
if (kill.target == getGUID() && kill.unavenged) {

Check warning on line 4595 in src/creatures/players/player.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

[cppcheck] src/creatures/players/player.cpp#L4595

Consider using std::find_if algorithm instead of a raw loop.
Raw output
src/creatures/players/player.cpp:4595:Consider using std::find_if algorithm instead of a raw loop.
kill.unavenged = false;
auto it = attackedSet.find(target->guid);
attackedSet.erase(it);
break;
}
} else if (targetPlayer->getSkull() == SKULL_NONE && !isInWar(targetPlayer)) {
unjustified = true;
addUnjustifiedDead(targetPlayer);
}

if (lastHit && hasCondition(CONDITION_INFIGHT)) {
pzLocked = true;
std::shared_ptr<Condition> condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_INFIGHT, g_configManager().getNumber(WHITE_SKULL_TIME), 0);
addCondition(condition);
}
}
}
} else if (std::shared_ptr<Monster> monster = target->getMonster()) {
// Access to the monster's map damage to check if the player attacked it
for (auto [playerId, damage] : monster->getDamageMap()) {
auto damagePlayer = g_game().getPlayerByID(playerId);
if (!damagePlayer) {
continue;
} else if (target->getSkull() == SKULL_NONE && !isInWar(target)) {
unjustified = true;
addUnjustifiedDead(target);
}

// If the player is not in a party and sharing exp active and enabled
// And it's not the player killing the creature, then we ignore everything else
auto damageParty = damagePlayer->getParty();
if (static_self_cast<Player>()->getID() != damagePlayer->getID() && (!damageParty || !damageParty->isSharedExperienceActive() || !damageParty->isSharedExperienceEnabled())) {
continue;
if (lastHit && hasCondition(CONDITION_INFIGHT)) {
pzLocked = true;
std::shared_ptr<Condition> condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_INFIGHT, g_configManager().getNumber(WHITE_SKULL_TIME), 0);
addCondition(condition);
}
}
}
return unjustified;
}

const auto &taskSlot = damagePlayer->getTaskHuntingWithCreature(monster->getRaceId());
if (!taskSlot || monster->isSummon()) {
continue;
}
void Player::addHuntingTaskKill(const std::shared_ptr<MonsterType> &mType) {
const auto &taskSlot = getTaskHuntingWithCreature(mType->info.raceid);
if (!taskSlot) {
return;
}

if (const auto &option = g_ioprey().getTaskRewardOption(taskSlot)) {
taskSlot->currentKills += 1;
if ((taskSlot->upgrade && taskSlot->currentKills >= option->secondKills) || (!taskSlot->upgrade && taskSlot->currentKills >= option->firstKills)) {
taskSlot->state = PreyTaskDataState_Completed;
std::string message = "You succesfully finished your hunting task. Your reward is ready to be claimed!";
damagePlayer->sendTextMessage(MESSAGE_STATUS, message);
}
damagePlayer->reloadTaskSlot(taskSlot->id);
}
if (const auto &option = g_ioprey().getTaskRewardOption(taskSlot)) {
taskSlot->currentKills += 1;
if ((taskSlot->upgrade && taskSlot->currentKills >= option->secondKills) || (!taskSlot->upgrade && taskSlot->currentKills >= option->firstKills)) {
taskSlot->state = PreyTaskDataState_Completed;
std::string message = "You succesfully finished your hunting task. Your reward is ready to be claimed!";
sendTextMessage(MESSAGE_STATUS, message);
}
reloadTaskSlot(taskSlot->id);
}
}

return unjustified;
void Player::addBestiaryKill(const std::shared_ptr<MonsterType> &mType) {
if (mType->isBoss()) {
return;
}
uint32_t kills = g_configManager().getNumber(BESTIARY_KILL_MULTIPLIER);
if (isConcoctionActive(Concoction_t::BestiaryBetterment)) {
kills *= 2;
}
g_iobestiary().addBestiaryKill(getPlayer(), mType, kills);
}

void Player::addBosstiaryKill(const std::shared_ptr<MonsterType> &mType) {
if (!mType->isBoss()) {
return;
}
uint32_t kills = g_configManager().getNumber(BOSSTIARY_KILL_MULTIPLIER);

g_ioBosstiary().addBosstiaryKill(getPlayer(), mType, kills);
}

bool Player::onKilledMonster(const std::shared_ptr<Monster> &monster, bool lastHit) {
if (lastHit || monster->isSummon()) {
return false;
}
auto party = getParty();
auto participants = party && party->isSharedExperienceActive() ? party->getPlayers() : std::vector<std::shared_ptr<Player>> { getPlayer() };
auto mType = monster->getMonsterType();
for (const auto &player : participants) {
player->addHuntingTaskKill(mType);
player->addBestiaryKill(mType);
player->addBosstiaryKill(mType);
}

return false;
}

bool Player::onKilledCreature(std::shared_ptr<Creature> target, bool lastHit /* = true*/) {
if (hasFlag(PlayerFlags_t::NotGenerateLoot)) {
target->setDropLoot(false);
}

Creature::onKilledCreature(target, lastHit);

if (auto targetPlayer = target->getPlayer()) {
return onKilledPlayer(targetPlayer, lastHit);
} else if (auto targetMonster = target->getMonster()) {
return onKilledMonster(targetMonster, lastHit);
}

return false;
}

void Player::gainExperience(uint64_t gainExp, std::shared_ptr<Creature> target) {
Expand Down
14 changes: 14 additions & 0 deletions src/creatures/players/player.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2487,6 +2487,14 @@ class Player final : public Creature, public Cylinder, public Bankable {
std::map<uint16_t, uint16_t> getActiveConcoctions() const {
return activeConcoctions;
}
bool isConcoctionActive(Concoction_t concotion) const {
uint16_t itemId = static_cast<uint16_t>(concotion);
if (!activeConcoctions.contains(itemId)) {
return false;
}
auto timeLeft = activeConcoctions.at(itemId);
return timeLeft > 0;
}

bool checkAutoLoot() const {
const bool autoLoot = g_configManager().getBoolean(AUTOLOOT) && getStorageValue(STORAGEVALUE_AUTO_LOOT) != 0;
Expand Down Expand Up @@ -2589,6 +2597,12 @@ class Player final : public Creature, public Cylinder, public Bankable {
void internalAddThing(std::shared_ptr<Thing> thing) override;
void internalAddThing(uint32_t index, std::shared_ptr<Thing> thing) override;

void addHuntingTaskKill(const std::shared_ptr<MonsterType> &mType);
void addBestiaryKill(const std::shared_ptr<MonsterType> &mType);
void addBosstiaryKill(const std::shared_ptr<MonsterType> &mType);
bool onKilledPlayer(const std::shared_ptr<Player> &target, bool lastHit);
bool onKilledMonster(const std::shared_ptr<Monster> &target, bool lastHit);

phmap::flat_hash_set<uint32_t> attackedSet;

phmap::flat_hash_set<uint32_t> VIPList;
Expand Down
Loading

0 comments on commit d36b1ea

Please sign in to comment.