From 432058d0ae232b2f0341b1e379e0f9b4a9515eb8 Mon Sep 17 00:00:00 2001 From: Corey Sotiropoulos Date: Sun, 9 Feb 2020 18:18:55 -0500 Subject: [PATCH 1/2] Claim updates * Add var to char entity to track currently claimed mob. * Move all claiming mechanics to claim function. * Add unclaiming mechanics. * Dirty exp based on max party size, clean exp when back to 100%. * Change how claim is applied based on if player is engaged to their claimed mob. * Properly dirty exp with spikes damage. * Refactor Aern mixin --- scripts/mixins/families/aern.lua | 54 +++--- src/map/ai/controllers/mob_controller.cpp | 2 + src/map/ai/states/ability_state.cpp | 9 +- src/map/ai/states/magic_state.cpp | 16 +- src/map/entities/battleentity.cpp | 15 ++ src/map/entities/charentity.cpp | 5 +- src/map/entities/charentity.h | 3 +- src/map/entities/mobentity.cpp | 22 +-- src/map/entities/mobentity.h | 1 + src/map/utils/battleutils.cpp | 199 ++++++++++++---------- src/map/utils/battleutils.h | 2 + src/map/utils/charutils.cpp | 3 +- src/map/zone_entities.cpp | 2 + 13 files changed, 185 insertions(+), 148 deletions(-) diff --git a/scripts/mixins/families/aern.lua b/scripts/mixins/families/aern.lua index 021dee380dc..f6436c29027 100644 --- a/scripts/mixins/families/aern.lua +++ b/scripts/mixins/families/aern.lua @@ -11,34 +11,34 @@ g_mixins = g_mixins or {} g_mixins.families = g_mixins.families or {} g_mixins.families.aern = function(mob) - mob:addListener("DEATH", "AERN_DEATH", function(mob) - local reraises = mob:getLocalVar("AERN_RERAISE_MAX") - local curr_reraise = mob:getLocalVar("AERN_RERAISES") - if reraises == 0 then - if math.random() < 0.4 then - reraises = 1 - end - end - if curr_reraise < reraises then - local dropid = mob:getDropID() - mob:setDropID(0) - local target = mob:getTarget() - local targetid = 0 - if target then targetid = target:getShortID() end - mob:timer(12000, function(mob) - mob:setHP(mob:getMaxHP()) - mob:setDropID(dropid) - mob:AnimationSub(3) - mob:setLocalVar("AERN_RERAISES", curr_reraise + 1) - mob:resetAI() - mob:stun(3000) - local new_target = mob:getEntity(targetid) - if new_target and mob:checkDistance(new_target) < 40 then - mob:updateClaim(new_target) - mob:updateEnmity(new_target) + mob:addListener("DEATH", "AERN_DEATH", function(mob, killer) + if killer then + local reraises = mob:getLocalVar("AERN_RERAISE_MAX") + local curr_reraise = mob:getLocalVar("AERN_RERAISES") + if reraises == 0 then + if math.random() < 0.4 then + reraises = 1 end - mob:triggerListener("AERN_RERAISE", mob, curr_reraise + 1) - end) + end + if curr_reraise < reraises then + local dropid = mob:getDropID() + mob:setDropID(0) + local target = mob:getTarget() + if target then killer = target end + mob:timer(12000, function(mob) + mob:setHP(mob:getMaxHP()) + mob:setDropID(dropid) + mob:AnimationSub(3) + mob:setLocalVar("AERN_RERAISES", curr_reraise + 1) + mob:resetAI() + mob:stun(3000) + if mob:checkDistance(killer) < 40 then + mob:updateClaim(killer) + mob:updateEnmity(killer) + end + mob:triggerListener("AERN_RERAISE", mob, curr_reraise + 1) + end) + end end end) end diff --git a/src/map/ai/controllers/mob_controller.cpp b/src/map/ai/controllers/mob_controller.cpp index 163879d1443..61e4acc754c 100644 --- a/src/map/ai/controllers/mob_controller.cpp +++ b/src/map/ai/controllers/mob_controller.cpp @@ -727,6 +727,8 @@ void CMobController::DoRoamTick(time_point tick) if (PMob->GetHPP() == 100) { // at max health undirty exp + PMob->m_HiPCLvl = 0; + PMob->m_HiPartySize = 0; PMob->m_giveExp = true; } } diff --git a/src/map/ai/states/ability_state.cpp b/src/map/ai/states/ability_state.cpp index af3abb4f6f6..dfbff1e17bb 100644 --- a/src/map/ai/states/ability_state.cpp +++ b/src/map/ai/states/ability_state.cpp @@ -83,15 +83,8 @@ void CAbilityState::ApplyEnmity() !(m_PAbility->getCE() == 0 && m_PAbility->getVE() == 0)) { CMobEntity* mob = (CMobEntity*)PTarget; - if (!mob->CalledForHelp()) - { - mob->m_OwnerID.id = m_PEntity->id; - mob->m_OwnerID.targid = m_PEntity->targid; - } - mob->updatemask |= UPDATE_STATUS; + battleutils::ClaimMob(mob, m_PEntity); mob->PEnmityContainer->UpdateEnmity(m_PEntity, m_PAbility->getCE(), m_PAbility->getVE(), false, m_PAbility->getID() == ABILITY_CHARM); - if (mob->m_HiPCLvl < m_PEntity->GetMLevel()) - mob->m_HiPCLvl = m_PEntity->GetMLevel(); } } else if (PTarget->allegiance == m_PEntity->allegiance) diff --git a/src/map/ai/states/magic_state.cpp b/src/map/ai/states/magic_state.cpp index ee1c539d984..5d344dc8b36 100644 --- a/src/map/ai/states/magic_state.cpp +++ b/src/map/ai/states/magic_state.cpp @@ -303,20 +303,12 @@ void CMagicState::ApplyEnmity(CBattleEntity* PTarget, int ce, int ve) if (!(m_PSpell->isHeal()) || m_PSpell->tookEffect()) //can't claim mob with cure unless it does damage { - if (m_PEntity->objtype == TYPE_PC || (m_PEntity->PMaster && m_PEntity->PMaster->objtype == TYPE_PC)) - { - auto claimer = m_PEntity->objtype == TYPE_PC ? m_PEntity : m_PEntity->PMaster; - - if (!mob->CalledForHelp()) - { - mob->m_OwnerID.id = claimer->id; - mob->m_OwnerID.targid = claimer->targid; - } - mob->updatemask |= UPDATE_STATUS; + if (PTarget->isDead()) + { // claim mob only on death (for aoe) + battleutils::ClaimMob(PTarget, m_PEntity); } + battleutils::DirtyExp(PTarget, m_PEntity); mob->PEnmityContainer->UpdateEnmity(m_PEntity, ce, ve); - if (mob->m_HiPCLvl < m_PEntity->GetMLevel()) - mob->m_HiPCLvl = m_PEntity->GetMLevel(); enmityApplied = true; } } diff --git a/src/map/entities/battleentity.cpp b/src/map/entities/battleentity.cpp index 13b266f8ac2..ebfd0223231 100644 --- a/src/map/entities/battleentity.cpp +++ b/src/map/entities/battleentity.cpp @@ -1181,9 +1181,20 @@ void CBattleEntity::Spawn() void CBattleEntity::Die() { if (CBaseEntity* PKiller = GetEntity(m_OwnerID.targid)) + { + static_cast(PKiller)->ForAlliance([this](CBattleEntity* PMember){ + CCharEntity* member = static_cast(PMember); + if (member->PClaimedMob == this) + { + member->PClaimedMob = nullptr; + } + }); PAI->EventHandler.triggerListener("DEATH", this, PKiller); + } else + { PAI->EventHandler.triggerListener("DEATH", this); + } SetBattleTargetID(0); } @@ -1323,6 +1334,10 @@ void CBattleEntity::OnCastFinished(CMagicState& state, action_t& action) luautils::OnMagicHit(this, PTarget, PSpell); } } + if ((!(PSpell->isHeal()) || PSpell->tookEffect()) && PActionTarget->isAlive()) + { + battleutils::ClaimMob(PActionTarget, this); + } // TODO: Pixies will probably break here, once they're added. if (this->allegiance != PActionTarget->allegiance) diff --git a/src/map/entities/charentity.cpp b/src/map/entities/charentity.cpp index 60d41c5b5ee..54d83839d7f 100644 --- a/src/map/entities/charentity.cpp +++ b/src/map/entities/charentity.cpp @@ -183,6 +183,7 @@ CCharEntity::CCharEntity() PWideScanTarget = nullptr; PAutomaton = nullptr; + PClaimedMob = nullptr; PRecastContainer = std::make_unique(this); PLatentEffectContainer = new CLatentEffectContainer(this); @@ -631,6 +632,7 @@ void CCharEntity::OnEngage(CAttackState& state) void CCharEntity::OnDisengage(CAttackState& state) { + battleutils::RelinquishClaim(this); CBattleEntity::OnDisengage(state); if (state.HasErrorMsg()) { @@ -898,6 +900,7 @@ void CCharEntity::OnWeaponSkillFinished(CWeaponSkillState& state, action_t& acti } } } + battleutils::ClaimMob(PBattleTarget, this); } else { @@ -1322,7 +1325,6 @@ void CCharEntity::OnRangedAttack(CRangeState& state, action_t& action) actionTarget.messageID = 354; battleutils::ClaimMob(PTarget, this); - hitCount = i; // end barrage, shot missed } @@ -1657,6 +1659,7 @@ void CCharEntity::Die() else loc.zone->PushPacket(this, CHAR_INRANGE_SELF, new CMessageBasicPacket(this, this, 0, 0, MSGBASIC_FALLS_TO_GROUND)); + battleutils::RelinquishClaim(this); Die(death_duration); SetDeathTimestamp((uint32)time(nullptr)); diff --git a/src/map/entities/charentity.h b/src/map/entities/charentity.h index 407efc1c91f..e96be7f8b19 100644 --- a/src/map/entities/charentity.h +++ b/src/map/entities/charentity.h @@ -213,6 +213,7 @@ class CCharEntity : public CBattleEntity CAutomatonEntity* PAutomaton; // Automaton statistics std::vector PTrusts; // Active trusts + CBattleEntity* PClaimedMob; // Эти миссии не нуждаются в списке пройденных, т.к. клиент автоматически @@ -321,7 +322,7 @@ class CCharEntity : public CBattleEntity CItemEquipment* getEquip(SLOTTYPE slot); - void ReloadPartyInc(); + void ReloadPartyInc(); void ReloadPartyDec(); bool ReloadParty(); void ClearTrusts(); diff --git a/src/map/entities/mobentity.cpp b/src/map/entities/mobentity.cpp index 6e87a35ff5c..eb9a84dc690 100644 --- a/src/map/entities/mobentity.cpp +++ b/src/map/entities/mobentity.cpp @@ -81,6 +81,7 @@ CMobEntity::CMobEntity() m_EcoSystem = SYSTEM_UNCLASSIFIED; m_Element = 0; m_HiPCLvl = 0; + m_HiPartySize = 0; m_THLvl = 0; m_ItemStolen = false; @@ -505,6 +506,7 @@ void CMobEntity::Spawn() CBattleEntity::Spawn(); m_giveExp = true; m_HiPCLvl = 0; + m_HiPartySize = 0; m_THLvl = 0; m_ItemStolen = false; m_DropItemTime = 1000; @@ -666,18 +668,11 @@ void CMobEntity::OnMobSkillFinished(CMobSkillState& state, action_t& action) this->PAI->EventHandler.triggerListener("WEAPONSKILL_USE", this, PTarget, PSkill->getID(), state.GetSpentTP(), &action); PTarget->PAI->EventHandler.triggerListener("WEAPONSKILL_TAKE", PTarget, this, PSkill->getID(), state.GetSpentTP(), &action); } - - if (objtype == TYPE_PET && PMaster && PMaster->objtype == TYPE_PC ) + if (PTarget->isDead()) { - auto mob = dynamic_cast(PTarget); - if (mob && !mob->CalledForHelp()) - { - mob->m_OwnerID.id = PMaster->id; - mob->m_OwnerID.targid = PMaster->targid; - mob->updatemask |= UPDATE_STATUS; //This can go here because we only wanna call the updatemask if this happens - } + battleutils::ClaimMob(PTarget, this); } - + battleutils::DirtyExp(PTarget, this); if (msg == 0) { msg = PSkill->getMsg(); @@ -732,6 +727,12 @@ void CMobEntity::OnMobSkillFinished(CMobSkillState& state, action_t& action) } PTarget->StatusEffectContainer->DelStatusEffectsByFlag(EFFECTFLAG_DETECTABLE); } + PTarget = static_cast(state.GetTarget()); + if (PTarget->isDead()) + { + battleutils::ClaimMob(PTarget, this); + } + battleutils::DirtyExp(PTarget, this); } void CMobEntity::DistributeRewards() @@ -1025,6 +1026,7 @@ void CMobEntity::Die() loc.zone->PushPacket(this, CHAR_INRANGE, new CMessageBasicPacket(this, this, 0, 0, MSGBASIC_FALLS_TO_GROUND)); DistributeRewards(); + m_OwnerID.clean(); } })); if (PMaster && PMaster->PPet == this && PMaster->objtype == TYPE_PC) diff --git a/src/map/entities/mobentity.h b/src/map/entities/mobentity.h index 7d1d8a09cd7..9e6ce3a0e8f 100644 --- a/src/map/entities/mobentity.h +++ b/src/map/entities/mobentity.h @@ -230,6 +230,7 @@ class CMobEntity : public CBattleEntity uint8 m_Element; uint8 m_HiPCLvl; // Highest Level of Player Character that hit the Monster + uint8 m_HiPartySize; // Largest party size that hit the Monster int16 m_THLvl; // Highest Level of Treasure Hunter that apply to drops bool m_ItemStolen; // if true, mob has already been robbed. reset on respawn. also used for thf maat fight uint16 m_Family; diff --git a/src/map/utils/battleutils.cpp b/src/map/utils/battleutils.cpp index 646749c622c..3c879b4b7ea 100644 --- a/src/map/utils/battleutils.cpp +++ b/src/map/utils/battleutils.cpp @@ -704,9 +704,10 @@ namespace battleutils // Check for status effect proc. Todo: move to scripts soon™ after item additionalEffect refactor Teo is working on HandleSpikesStatusEffect(PAttacker, PDefender, Action); - if (PAttacker->objtype == TYPE_MOB && ((CMobEntity*)PAttacker)->m_HiPCLvl < PDefender->GetMLevel()) + battleutils::DirtyExp(PAttacker, PDefender); + if (PAttacker->isDead()) { - ((CMobEntity*)PAttacker)->m_HiPCLvl = PDefender->GetMLevel(); + battleutils::ClaimMob(PAttacker, PDefender); } return true; } @@ -1898,32 +1899,7 @@ namespace battleutils if (damage < 0) damage = -corrected; - auto PMob = dynamic_cast(PDefender); - if (PAttacker->PMaster != nullptr) - { - if (!PMob || !PMob->CalledForHelp()) - { - PDefender->m_OwnerID.id = PAttacker->PMaster->id; - PDefender->m_OwnerID.targid = PAttacker->PMaster->targid; - } - PDefender->updatemask |= UPDATE_STATUS; - } - else - { - if (PAttacker->objtype == TYPE_MOB && PAttacker->PMaster == nullptr) - { - //uncharmed mob still attacking another mob - dont allow 2 mobs to go purple - } - else - { - if (!PMob || !PMob->CalledForHelp()) - { - PDefender->m_OwnerID.id = PAttacker->id; - PDefender->m_OwnerID.targid = PAttacker->targid; - } - PDefender->updatemask |= UPDATE_STATUS; - } - } + battleutils::ClaimMob(PDefender, PAttacker); if (damage > 0) { @@ -2063,28 +2039,7 @@ namespace battleutils if (damage < 0) damage = -corrected; - auto PMob = dynamic_cast(PDefender); - if (PDefender->objtype == TYPE_MOB) - { - if (PAttacker->PMaster != nullptr) - { - if (!PMob || !PMob->CalledForHelp()) - { - PDefender->m_OwnerID.id = PAttacker->PMaster->id; - PDefender->m_OwnerID.targid = PAttacker->PMaster->targid; - } - PDefender->updatemask |= UPDATE_STATUS; - } - else - { - if (!PMob || !PMob->CalledForHelp()) - { - PDefender->m_OwnerID.id = PAttacker->id; - PDefender->m_OwnerID.targid = PAttacker->targid; - } - PDefender->updatemask |= UPDATE_STATUS; - } - } + battleutils::ClaimMob(PDefender, PAttacker); int16 standbyTp = 0; @@ -3140,23 +3095,7 @@ namespace battleutils PDefender->takeDamage(damage, PAttacker, ATTACK_SPECIAL, appliedEle == ELEMENT_NONE ? DAMAGE_NONE : (DAMAGETYPE)(DAMAGE_ELEMENTAL + appliedEle)); - auto PMob = dynamic_cast(PDefender); - if (PAttacker->PMaster != nullptr) - { - if (!PMob || !PMob->CalledForHelp()) - { - PDefender->m_OwnerID.id = PAttacker->PMaster->id; - PDefender->m_OwnerID.targid = PAttacker->PMaster->targid; - } - } - else - { - if (!PMob || !PMob->CalledForHelp()) - { - PDefender->m_OwnerID.id = PAttacker->id; - PDefender->m_OwnerID.targid = PAttacker->targid; - } - } + battleutils::ClaimMob(PDefender, PAttacker); PDefender->updatemask |= UPDATE_STATUS; PDefender->StatusEffectContainer->DelStatusEffectsByFlag(EFFECTFLAG_DAMAGE); @@ -3940,6 +3879,10 @@ namespace battleutils charutils::BuildingCharPetAbilityTable((CCharEntity*)PCharmer, (CPetEntity*)PVictim, PVictim->id); ((CCharEntity*)PCharmer)->pushPacket(new CCharUpdatePacket((CCharEntity*)PCharmer)); ((CCharEntity*)PCharmer)->pushPacket(new CPetSyncPacket((CCharEntity*)PCharmer)); + PCharmer->ForAlliance([&PVictim](CBattleEntity* PMember){ + if (static_cast(PMember)->PClaimedMob == PVictim) + static_cast(PMember)->PClaimedMob = nullptr; + }); ((CMobEntity*)PVictim)->m_OwnerID.clean(); PVictim->updatemask |= UPDATE_STATUS; } @@ -3952,6 +3895,7 @@ namespace battleutils } PVictim->PAI->SetController(std::make_unique(static_cast(PVictim))); + battleutils::RelinquishClaim(static_cast(PVictim)); PVictim->PMaster = PCharmer; PVictim->updatemask |= UPDATE_ALL_CHAR; } @@ -4098,13 +4042,12 @@ namespace battleutils { if (PDefender->objtype == TYPE_MOB) { - CMobEntity* mob = (CMobEntity*)PDefender; - - mob->PEnmityContainer->UpdateEnmity(PAttacker, 0, 0); - if (PAttacker->objtype != TYPE_PC) { - if (PAttacker->PMaster != nullptr) - { - // claim by master + CBattleEntity* battleTarget = PAttacker->GetBattleTarget(); + CMobEntity* mob = static_cast(PDefender); + if (PAttacker->objtype != TYPE_PC) + { + if (PAttacker->PMaster && PAttacker->PMaster->objtype == TYPE_PC) + { // claim by master PAttacker = PAttacker->PMaster; } else @@ -4112,24 +4055,105 @@ namespace battleutils PAttacker = nullptr; } } - if (PAttacker) { - if (mob->m_HiPCLvl < PAttacker->GetMLevel()) + CCharEntity* attacker = static_cast(PAttacker); + battleutils::DirtyExp(PDefender, PAttacker); + if (!battleTarget || battleTarget == PDefender || battleTarget != attacker->PClaimedMob || PDefender->isDead()) { - mob->m_HiPCLvl = PAttacker->GetMLevel(); + if (PDefender->isAlive() && attacker->PClaimedMob && attacker->PClaimedMob != PDefender + && attacker->PClaimedMob->isAlive() && attacker->PClaimedMob->m_OwnerID.id == attacker->id) + { // unclaim any other living mobs owned by attacker + attacker->PClaimedMob->m_OwnerID.clean(); + attacker->PClaimedMob->updatemask |= UPDATE_STATUS; + attacker->PClaimedMob = nullptr; + } + if (!mob->CalledForHelp()) + { + if (battleutils::HasClaim(PAttacker, PDefender)) + { // mob is currently claimed by your alliance, update ownership + mob->m_OwnerID.id = PAttacker->id; + mob->m_OwnerID.targid = PAttacker->targid; + if (PDefender->isAlive()) + { // ignore killing blow + mob->updatemask |= UPDATE_STATUS; + attacker->PClaimedMob = PDefender; + } + } + else + { // mob is unclaimed + PAttacker->ForAlliance([&PAttacker, &PDefender, &mob, &attacker](CBattleEntity* PMember){ + if (mob->PEnmityContainer->GetHighestEnmity() == PMember || mob->PEnmityContainer->GetHighestEnmity() == PMember->PPet) + { // someone in your alliance is top of hate list, claim for your alliance + mob->m_OwnerID.id = PAttacker->id; + mob->m_OwnerID.targid = PAttacker->targid; + if (PDefender->isAlive()) + { // ignore killing blow + mob->updatemask |= UPDATE_STATUS; + attacker->PClaimedMob = PDefender; + } + } + }); + } + } } + } + } + } - if (!mob->CalledForHelp()) + void DirtyExp(CBattleEntity* PDefender, CBattleEntity* PAttacker) + { + if (PDefender->objtype == TYPE_MOB) + { + CMobEntity* mob = static_cast(PDefender); + if (PAttacker->objtype != TYPE_PC) + { + if (PAttacker->PMaster && PAttacker->PMaster->objtype == TYPE_PC) + { + PAttacker = PAttacker->PMaster; + } + else { - mob->m_OwnerID.id = PAttacker->id; - mob->m_OwnerID.targid = PAttacker->targid; + PAttacker = nullptr; } - mob->updatemask |= UPDATE_STATUS; + } + if (PAttacker) + { + uint8 pcinzone = 0; + PAttacker->ForAlliance([&pcinzone, &mob](CBattleEntity* PMember) { + if (PMember->getZone() == mob->getZone() && distance(PMember->loc.p, mob->loc.p) < 100) + { + pcinzone++; + } + }); + mob->m_HiPartySize = std::max(pcinzone, mob->m_HiPartySize); + mob->m_HiPCLvl = std::max(PAttacker->GetMLevel(), mob->m_HiPCLvl); } } } + void RelinquishClaim(CCharEntity* PChar) + { + CBattleEntity* mob = PChar->PClaimedMob; + if (mob && mob->isAlive() && mob->m_OwnerID.id == PChar->id) + { // if we currently own a mob + bool found = false; + static_cast(PChar)->ForAlliance([&PChar, &mob, &found](CBattleEntity* PMember){ + CCharEntity* member = static_cast(PMember); + if (member != PChar && !found && member->getZone() == PChar->getZone() && member->isAlive() && (!member->PClaimedMob || member->PClaimedMob == mob)) + { // check if we can pass claim to someone else + found = true; + battleutils::ClaimMob(mob, PMember); + } + }); + if (!found) + { // if mob didn't pass to someone else, unclaim it + mob->m_OwnerID.clean(); + mob->updatemask |= UPDATE_STATUS; + } + } + PChar->PClaimedMob = nullptr; + } int32 BreathDmgTaken(CBattleEntity* PDefender, int32 damage) { @@ -5005,8 +5029,7 @@ namespace battleutils PMaster = PEntity->PMaster; } - if (PTarget->m_OwnerID.id == 0 || PTarget->m_OwnerID.id == PMaster->id || PTarget->objtype == TYPE_PC || - PTarget->objtype == TYPE_PET) + if (PTarget->m_OwnerID.id == PMaster->id) { return true; } @@ -5014,11 +5037,11 @@ namespace battleutils bool found = false; PMaster->ForAlliance([&PTarget, &found](CBattleEntity* PChar){ - if (PChar->id == PTarget->m_OwnerID.id) - { - found = true; - } - }); + if (PChar->id == PTarget->m_OwnerID.id) + { + found = true; + } + }); return found; } diff --git a/src/map/utils/battleutils.h b/src/map/utils/battleutils.h index 9b16595a024..1dffa1fb69d 100644 --- a/src/map/utils/battleutils.h +++ b/src/map/utils/battleutils.h @@ -194,6 +194,8 @@ namespace battleutils uint8 getStoreTPbonusFromMerit(CBattleEntity* PEntity); void ClaimMob(CBattleEntity* PDefender, CBattleEntity* PAttacker); + void DirtyExp(CBattleEntity* PDefender, CBattleEntity* PAttacker); + void RelinquishClaim(CCharEntity* PDefender); int32 BreathDmgTaken(CBattleEntity* PDefender, int32 damage); int32 MagicDmgTaken(CBattleEntity* PDefender, int32 damage, ELEMENT element); diff --git a/src/map/utils/charutils.cpp b/src/map/utils/charutils.cpp index fecd877ad29..b3b8f9000f4 100644 --- a/src/map/utils/charutils.cpp +++ b/src/map/utils/charutils.cpp @@ -3219,7 +3219,7 @@ namespace charutils void DistributeExperiencePoints(CCharEntity* PChar, CMobEntity* PMob) { - auto pcinzone = 0; + uint8 pcinzone = 0; uint8 minlevel = 0, maxlevel = PChar->GetMLevel(); REGIONTYPE region = PChar->loc.zone->GetRegionID(); @@ -3260,6 +3260,7 @@ namespace charutils pcinzone++; } }); + pcinzone = std::max(pcinzone, PMob->m_HiPartySize); PChar->ForAlliance([&PMob, ®ion, &minlevel, &maxlevel, &pcinzone](CBattleEntity* PPartyMember) { diff --git a/src/map/zone_entities.cpp b/src/map/zone_entities.cpp index 2a0aea4d02f..0f86993f841 100644 --- a/src/map/zone_entities.cpp +++ b/src/map/zone_entities.cpp @@ -286,6 +286,8 @@ void CZoneEntities::DecreaseZoneCounter(CCharEntity* PChar) TPZ_DEBUG_BREAK_IF(PChar == nullptr); TPZ_DEBUG_BREAK_IF(PChar->loc.zone != m_zone); + PChar->PClaimedMob = nullptr; + //remove pets if (PChar->PPet != nullptr) { From 776bfeecacfdda25a9f9e9c5d1860f807fda13b9 Mon Sep 17 00:00:00 2001 From: Corey Sotiropoulos Date: Wed, 25 Mar 2020 16:50:46 -0400 Subject: [PATCH 2/2] Track max level in party when any member attacks --- src/map/utils/battleutils.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/map/utils/battleutils.cpp b/src/map/utils/battleutils.cpp index 3c879b4b7ea..535a48ed098 100644 --- a/src/map/utils/battleutils.cpp +++ b/src/map/utils/battleutils.cpp @@ -4120,14 +4120,16 @@ namespace battleutils if (PAttacker) { uint8 pcinzone = 0; - PAttacker->ForAlliance([&pcinzone, &mob](CBattleEntity* PMember) { + uint8 maxLevel = 0; + PAttacker->ForAlliance([&pcinzone, &maxLevel, &mob](CBattleEntity* PMember) { if (PMember->getZone() == mob->getZone() && distance(PMember->loc.p, mob->loc.p) < 100) { + maxLevel = std::max(maxLevel, PMember->GetMLevel()); pcinzone++; } }); mob->m_HiPartySize = std::max(pcinzone, mob->m_HiPartySize); - mob->m_HiPCLvl = std::max(PAttacker->GetMLevel(), mob->m_HiPCLvl); + mob->m_HiPCLvl = std::max(maxLevel, mob->m_HiPCLvl); } } }