void CEnmityContainer::UpdateEnmityFromCure(CBattleEntity* PEntity, uint16 level, uint16 CureAmount, bool isCureV) { if (isCureV) { UpdateEnmity(PEntity, 400, 700); } else { CureAmount = (CureAmount < 1 ? 1 : CureAmount); uint16 mod = battleutils::GetEnmityModCure(level); uint16 CE = 40. / mod * CureAmount; uint16 VE = 240. / mod * CureAmount; // you're too far away so i'm ignoring you if (!IsWithinEnmityRange(PEntity)) { CE = 0; VE = 0; } // Crash fix, PEntity was in ACTION_FALL if (PEntity->PBattleAI->GetCurrentAction() == ACTION_FALL) return; EnmityList_t::iterator PEnmity = m_EnmityList.lower_bound(PEntity->id); // current highest enmity before this update CBattleEntity* OldEntity = GetHighestEnmity(); if (PEnmity != m_EnmityList.end() && !m_EnmityList.key_comp()(PEntity->id, PEnmity->first)) { float bonus = CalculateEnmityBonus(PEntity); float tranquilHeartReduction = 1.f - battleutils::HandleTranquilHeart(PEntity); int newCE = PEnmity->second->CE + (CE * bonus * tranquilHeartReduction); int newVE = PEnmity->second->VE + (VE * bonus * tranquilHeartReduction); //Check for cap limit PEnmity->second->CE = dsp_cap(newCE, 1, 10000); PEnmity->second->VE = dsp_cap(newVE, 0, 10000); } else if (CE >= 0 && VE >= 0) { EnmityObject_t* PEnmityObject = new EnmityObject_t; float bonus = CalculateEnmityBonus(PEntity); float tranquilHeartReduction = 1.f - battleutils::HandleTranquilHeart(PEntity); PEnmityObject->CE = dsp_cap(CE * bonus * tranquilHeartReduction, 1, 10000); PEnmityObject->VE = dsp_cap(VE * bonus * tranquilHeartReduction, 0, 10000); PEnmityObject->PEnmityOwner = PEntity; PEnmityObject->maxTH = 0; m_EnmityList.insert(PEnmity, EnmityList_t::value_type(PEntity->id, PEnmityObject)); } } }
void CEnmityContainer::LowerEnmityByPercent(CBattleEntity* PEntity, uint8 percent, CBattleEntity* HateReceiver) { EnmityList_t::iterator PEnmity = m_EnmityList.lower_bound(PEntity->id); // current highest enmity before this update CBattleEntity* OldEntity = GetHighestEnmity(); if (PEnmity != m_EnmityList.end() && !m_EnmityList.key_comp()(PEntity->id, PEnmity->first)) { float mod = ((float)(percent) / 100.0f); int32 CEValue = (float)(PEnmity->second->CE * mod); PEnmity->second->CE -= (CEValue < 0 ? 0 : CEValue); int32 VEValue = (float)(PEnmity->second->VE * mod); PEnmity->second->VE -= (VEValue < 0 ? 0 : VEValue); // transfer hate if HateReceiver not nullptr if (HateReceiver != nullptr) { UpdateEnmity(HateReceiver, 0, 0); EnmityList_t::iterator PEnmityReceiver = m_EnmityList.lower_bound(HateReceiver->id); PEnmityReceiver->second->CE = dsp_cap(PEnmityReceiver->second->CE + CEValue,1,10000); PEnmityReceiver->second->VE = dsp_cap(PEnmityReceiver->second->VE + VEValue,0,10000); } } // highest enmity holder after this update CBattleEntity* NewEntity = GetHighestEnmity(); // PEntity is now the target, face the target if (OldEntity != NewEntity && !m_EnmityHolder->isAsleep()) { if ((m_EnmityHolder->objtype == TYPE_MOB && !(((CMobEntity*)m_EnmityHolder)->m_Behaviour & BEHAVIOUR_NO_TURN)) || m_EnmityHolder->objtype != TYPE_MOB) { uint8 angle = getangle(m_EnmityHolder->loc.p, NewEntity->loc.p); m_EnmityHolder->loc.p.rotation = angle; m_EnmityHolder->loc.zone->PushPacket(m_EnmityHolder, CHAR_INRANGE, new CEntityUpdatePacket(m_EnmityHolder, ENTITY_UPDATE, UPDATE_POS)); } } }
void CEnmityContainer::LowerEnmityByPercent(CBattleEntity* PEntity, uint8 percent, CBattleEntity* HateReceiver) { EnmityList_t::iterator PEnmity = m_EnmityList.lower_bound(PEntity->id); // current highest enmity before this update CBattleEntity* OldEntity = GetHighestEnmity(); if( PEnmity != m_EnmityList.end() && !m_EnmityList.key_comp()(PEntity->id, PEnmity->first)) { float mod = ((float)(percent)/100.0f); int32 CEValue = (float)(PEnmity->second->CE * mod); PEnmity->second->CE -= (CEValue < 0 ? 0 : CEValue); int32 VEValue = (float)(PEnmity->second->VE * mod); PEnmity->second->VE -= (VEValue < 0 ? 0 : VEValue); // transfer hate if HateReceiver not null if (HateReceiver != NULL) { UpdateEnmity(HateReceiver,0,0); EnmityList_t::iterator PEnmityReceiver = m_EnmityList.lower_bound(HateReceiver->id); PEnmityReceiver->second->CE += CEValue; PEnmityReceiver->second->VE += VEValue; } } // highest enmity holder after this update CBattleEntity* NewEntity = GetHighestEnmity(); // PEntity is now the target, face the target if (OldEntity != NewEntity && !m_EnmityHolder->isAsleep()) { uint8 angle = getangle(m_EnmityHolder->loc.p, NewEntity->loc.p); m_EnmityHolder->loc.p.rotation = angle; m_EnmityHolder->loc.zone->PushPacket(m_EnmityHolder,CHAR_INRANGE, new CEntityUpdatePacket(m_EnmityHolder, ENTITY_UPDATE)); } }
CBattleEntity* CEnmityContainer::GetHighestEnmity() { if (m_EnmityList.empty()) { return nullptr; } uint32 HighestEnmity = 0; auto highest = m_EnmityList.end(); bool active = false; for (auto it = m_EnmityList.begin(); it != m_EnmityList.end(); ++it) { const EnmityObject_t& PEnmityObject = it->second; uint32 Enmity = PEnmityObject.CE + PEnmityObject.VE; if (Enmity >= HighestEnmity && ((PEnmityObject.active == active) || (PEnmityObject.active && !active))) { auto POwner = PEnmityObject.PEnmityOwner; if (!POwner || (POwner->allegiance != m_EnmityHolder->allegiance)) { active = PEnmityObject.active; HighestEnmity = Enmity; highest = it; } } } CBattleEntity* PEntity = nullptr; if (highest != m_EnmityList.end()) { PEntity = highest->second.PEnmityOwner; if (!PEntity) { PEntity = zoneutils::GetChar(highest->first); } if (!PEntity || PEntity->getZone() != m_EnmityHolder->getZone() || PEntity->PInstance != m_EnmityHolder->PInstance) { m_EnmityList.erase(highest); PEntity = GetHighestEnmity(); } } return PEntity; }
void CEnmityContainer::UpdateEnmity(CBattleEntity* PEntity, int16 CE, int16 VE, bool withMaster) { // you're too far away so i'm ignoring you if(!IsWithinEnmityRange(PEntity)) { CE = 0; VE = 0; } // Crash fix, PEntity was in ACTION_FALL if (PEntity->PBattleAI->GetCurrentAction() == ACTION_FALL) return; EnmityList_t::iterator PEnmity = m_EnmityList.lower_bound(PEntity->id); // current highest enmity before this update CBattleEntity* OldEntity = GetHighestEnmity(); if( PEnmity != m_EnmityList.end() && !m_EnmityList.key_comp()(PEntity->id, PEnmity->first)) { int8 enmityBonus = 0; if (PEntity->objtype & TYPE_PC) { enmityBonus = ((CCharEntity*)PEntity)->PMeritPoints->GetMeritValue(MERIT_ENMITY_INCREASE, (CCharEntity*)PEntity) - ((CCharEntity*)PEntity)->PMeritPoints->GetMeritValue(MERIT_ENMITY_DECREASE, (CCharEntity*)PEntity); } float bonus = (100.0f + dsp_cap(PEntity->getMod(MOD_ENMITY)+enmityBonus, -50, 100)) / 100.0f; PEnmity->second->CE += CE * bonus; PEnmity->second->VE += VE * bonus; //Check for cap limit PEnmity->second->CE = dsp_cap(PEnmity->second->CE, 1, 10000); PEnmity->second->VE = dsp_cap(PEnmity->second->VE, 1, 10000); } else { EnmityObject_t* PEnmityObject = new EnmityObject_t; int8 enmityBonus = 0; if (PEntity->objtype & TYPE_PC) { enmityBonus = ((CCharEntity*)PEntity)->PMeritPoints->GetMeritValue(MERIT_ENMITY_INCREASE, (CCharEntity*)PEntity) - ((CCharEntity*)PEntity)->PMeritPoints->GetMeritValue(MERIT_ENMITY_DECREASE, (CCharEntity*)PEntity); } float bonus = (100.0f + dsp_cap(PEntity->getMod(MOD_ENMITY)+enmityBonus, -50, 100)) / 100.0f; PEnmityObject->CE = CE * bonus; PEnmityObject->VE = VE * bonus; PEnmityObject->PEnmityOwner = PEntity; m_EnmityList.insert(PEnmity, EnmityList_t::value_type(PEntity->id, PEnmityObject)); if(withMaster && PEntity->PMaster != NULL) { //add master to the enmity list //add master to the enmity list (charmed mob) if(PEntity->objtype == TYPE_PET || PEntity->objtype == TYPE_MOB && PEntity->PMaster!=NULL && PEntity->PMaster->objtype == TYPE_PC) { UpdateEnmity(PEntity->PMaster, 0, 0); } } } }
void CEnmityContainer::UpdateEnmity(CBattleEntity* PEntity, int16 CE, int16 VE, bool withMaster, bool aggroEnmity) { // you're too far away so i'm ignoring you if (!IsWithinEnmityRange(PEntity)) { CE = 0; VE = 0; } auto PMob = dynamic_cast<CMobEntity*>(m_EnmityHolder); if (PMob && PMob->m_HiPCLvl < PEntity->GetMLevel()) PMob->m_HiPCLvl = PEntity->GetMLevel(); EnmityList_t::iterator PEnmity = m_EnmityList.lower_bound(PEntity->id); // current highest enmity before this update CBattleEntity* OldEntity = GetHighestEnmity(); if (PEnmity != m_EnmityList.end() && !m_EnmityList.key_comp()(PEntity->id, PEnmity->first)) { float bonus = CalculateEnmityBonus(PEntity); if (PEnmity->second->CE == 0 && CE + VE <= 0) return; int newCE = PEnmity->second->CE + ((CE > 0) ? CE * bonus : CE); int newVE = PEnmity->second->VE + ((VE > 0) ? VE * bonus : VE); //Check for cap limit PEnmity->second->CE = dsp_cap(newCE, 1, 10000); PEnmity->second->VE = dsp_cap(newVE, 0, 10000); PEnmity->second->isAggroEnmity = aggroEnmity; if (CE + VE > 0 && PEntity->getMod(MOD_TREASURE_HUNTER) > PEnmity->second->maxTH) PEnmity->second->maxTH = (uint8)(PEntity->getMod(MOD_TREASURE_HUNTER)); } else if (CE >= 0 && VE >= 0) { EnmityObject_t* PEnmityObject = new EnmityObject_t; bool initial = true; for (auto&& enmityObject : m_EnmityList) { if (enmityObject.second->CE > 0 || enmityObject.second->VE > 0) { initial = false; break; } } if (initial) CE += 200; float bonus = CalculateEnmityBonus(PEntity); PEnmityObject->CE = dsp_cap(CE * bonus, 0, 10000); PEnmityObject->VE = dsp_cap(VE * bonus, 0, 10000); PEnmityObject->PEnmityOwner = PEntity; PEnmityObject->isAggroEnmity = aggroEnmity; if (CE + VE > 0) PEnmityObject->maxTH = (uint8)(PEntity->getMod(MOD_TREASURE_HUNTER)); else PEnmityObject->maxTH = 0; m_EnmityList.insert(PEnmity, EnmityList_t::value_type(PEntity->id, PEnmityObject)); if (withMaster && PEntity->PMaster != nullptr) { //add master to the enmity list //add master to the enmity list (charmed mob) if (PEntity->objtype == TYPE_PET || PEntity->objtype == TYPE_MOB && PEntity->PMaster != nullptr && PEntity->PMaster->objtype == TYPE_PC) { UpdateEnmity(PEntity->PMaster, 0, 0); } } } }
void CEnmityContainer::UpdateEnmity(CBattleEntity* PEntity, int16 CE, int16 VE, bool withMaster) { // you're too far away so i'm ignoring you if(!IsWithinEnmityRange(PEntity)) { CE = 0; VE = 0; } // Crash fix, PEntity was in ACTION_FALL if (PEntity->PBattleAI->GetCurrentAction() == ACTION_FALL) return; EnmityList_t::iterator PEnmity = m_EnmityList.lower_bound(PEntity->id); // current highest enmity before this update CBattleEntity* OldEntity = GetHighestEnmity(); if( PEnmity != m_EnmityList.end() && !m_EnmityList.key_comp()(PEntity->id, PEnmity->first)) { float bonus = CalculateEnmityBonus(PEntity); if (PEnmity->second->CE == 0 && CE + VE <= 0) return; PEnmity->second->CE += CE > 0 ? CE * bonus : CE; PEnmity->second->VE += VE > 0 ? VE * bonus : VE; //Check for cap limit PEnmity->second->CE = dsp_cap(PEnmity->second->CE, 1, 10000); PEnmity->second->VE = dsp_cap(PEnmity->second->VE, 0, 10000); if (CE + VE > 0 && PEntity->getMod(MOD_TREASURE_HUNTER) > PEnmity->second->maxTH) PEnmity->second->maxTH = (uint8)(PEntity->getMod(MOD_TREASURE_HUNTER)); } else if (CE >= 0 && VE >= 0) { EnmityObject_t* PEnmityObject = new EnmityObject_t; float bonus = CalculateEnmityBonus(PEntity); PEnmityObject->CE = CE * bonus; PEnmityObject->VE = VE * bonus; PEnmityObject->PEnmityOwner = PEntity; if (CE + VE > 0) PEnmityObject->maxTH = (uint8)(PEntity->getMod(MOD_TREASURE_HUNTER)); else PEnmityObject->maxTH = 0; m_EnmityList.insert(PEnmity, EnmityList_t::value_type(PEntity->id, PEnmityObject)); if(withMaster && PEntity->PMaster != NULL) { //add master to the enmity list //add master to the enmity list (charmed mob) if(PEntity->objtype == TYPE_PET || PEntity->objtype == TYPE_MOB && PEntity->PMaster!=NULL && PEntity->PMaster->objtype == TYPE_PC) { UpdateEnmity(PEntity->PMaster, 0, 0); } } } }