Changed hate counter to uint32 to prevent negative rollback, this most likely can will be an issue but more uncommon

Renamed and refactored most functions and variables in hate_list.h/cpp for readability
Refactored how hate works in some local functions mixing the use of hate variable and split it out into different status variables
hate_list.cpp/.h style cleanup
hate_list.h header function sort, comment erase
functions should clearly state their function
This commit is contained in:
Akkadius 2014-12-27 18:24:42 -06:00
parent b63dbd50a8
commit 3a488e3a61
19 changed files with 413 additions and 494 deletions

View File

@ -1298,7 +1298,7 @@ bool Mob::PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id) {
void Mob::RogueEvade(Mob *other) void Mob::RogueEvade(Mob *other)
{ {
int amount = other->GetHateAmount(this) - (GetLevel() * 13); int amount = other->GetHateAmount(this) - (GetLevel() * 13);
other->SetHate(this, std::max(1, amount)); other->SetHateAmountOnEnt(this, std::max(1, amount));
return; return;
} }

View File

@ -1518,7 +1518,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
} }
entity_list.RemoveFromTargets(this); entity_list.RemoveFromTargets(this);
hate_list.RemoveEnt(this); hate_list.RemoveEntFromHateList(this);
RemoveAutoXTargets(); RemoveAutoXTargets();
//remove ourself from all proximities //remove ourself from all proximities
@ -2076,12 +2076,12 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
if (killerMob) { if (killerMob) {
if(GetClass() != LDON_TREASURE) if(GetClass() != LDON_TREASURE)
hate_list.Add(killerMob, damage); hate_list.AddEntToHateList(killerMob, damage);
} }
safe_delete(app); safe_delete(app);
Mob *give_exp = hate_list.GetDamageTop(this); Mob *give_exp = hate_list.GetDamageTopOnHateList(this);
if(give_exp == nullptr) if(give_exp == nullptr)
give_exp = killer; give_exp = killer;
@ -2488,7 +2488,7 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
&& other && (buffs[spellbonuses.ImprovedTaunt[2]].casterid != other->GetID())) && other && (buffs[spellbonuses.ImprovedTaunt[2]].casterid != other->GetID()))
hate = (hate*spellbonuses.ImprovedTaunt[1])/100; hate = (hate*spellbonuses.ImprovedTaunt[1])/100;
hate_list.Add(other, hate, damage, bFrenzy, !iBuffTic); hate_list.AddEntToHateList(other, hate, damage, bFrenzy, !iBuffTic);
if(other->IsClient()) if(other->IsClient())
other->CastToClient()->AddAutoXTarget(this); other->CastToClient()->AddAutoXTarget(this);
@ -2500,8 +2500,8 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
AddFeignMemory(other->CastToBot()->GetBotOwner()->CastToClient()); AddFeignMemory(other->CastToBot()->GetBotOwner()->CastToClient());
} }
else { else {
if(!hate_list.IsOnHateList(other->CastToBot()->GetBotOwner())) if(!hate_list.IsEntOnHateList(other->CastToBot()->GetBotOwner()))
hate_list.Add(other->CastToBot()->GetBotOwner(), 0, 0, false, true); hate_list.AddEntToHateList(other->CastToBot()->GetBotOwner(), 0, 0, false, true);
} }
} }
#endif //BOTS #endif //BOTS
@ -2512,8 +2512,8 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
AddFeignMemory(other->CastToMerc()->GetMercOwner()->CastToClient()); AddFeignMemory(other->CastToMerc()->GetMercOwner()->CastToClient());
} }
else { else {
if(!hate_list.IsOnHateList(other->CastToMerc()->GetMercOwner())) if(!hate_list.IsEntOnHateList(other->CastToMerc()->GetMercOwner()))
hate_list.Add(other->CastToMerc()->GetMercOwner(), 0, 0, false, true); hate_list.AddEntToHateList(other->CastToMerc()->GetMercOwner(), 0, 0, false, true);
} }
} //MERC } //MERC
@ -2528,7 +2528,7 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
// owner must get on list, but he's not actually gained any hate yet // owner must get on list, but he's not actually gained any hate yet
if(!owner->GetSpecialAbility(IMMUNE_AGGRO)) if(!owner->GetSpecialAbility(IMMUNE_AGGRO))
{ {
hate_list.Add(owner, 0, 0, false, !iBuffTic); hate_list.AddEntToHateList(owner, 0, 0, false, !iBuffTic);
if(owner->IsClient()) if(owner->IsClient())
owner->CastToClient()->AddAutoXTarget(this); owner->CastToClient()->AddAutoXTarget(this);
} }
@ -2537,10 +2537,10 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
if (mypet && (!(GetAA(aaPetDiscipline) && mypet->IsHeld()))) { // I have a pet, add other to it if (mypet && (!(GetAA(aaPetDiscipline) && mypet->IsHeld()))) { // I have a pet, add other to it
if(!mypet->IsFamiliar() && !mypet->GetSpecialAbility(IMMUNE_AGGRO)) if(!mypet->IsFamiliar() && !mypet->GetSpecialAbility(IMMUNE_AGGRO))
mypet->hate_list.Add(other, 0, 0, bFrenzy); mypet->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
} else if (myowner) { // I am a pet, add other to owner if it's NPC/LD } else if (myowner) { // I am a pet, add other to owner if it's NPC/LD
if (myowner->IsAIControlled() && !myowner->GetSpecialAbility(IMMUNE_AGGRO)) if (myowner->IsAIControlled() && !myowner->GetSpecialAbility(IMMUNE_AGGRO))
myowner->hate_list.Add(other, 0, 0, bFrenzy); myowner->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
} }
if (other->GetTempPetCount()) if (other->GetTempPetCount())

View File

@ -3422,9 +3422,9 @@ void Bot::AI_Process() {
rest_timer.Disable(); rest_timer.Disable();
if(IsRooted()) if(IsRooted())
SetTarget(hate_list.GetClosest(this)); SetTarget(hate_list.GetClosestEntOnHateList(this));
else else
SetTarget(hate_list.GetTop(this)); SetTarget(hate_list.GetEntWithMostHateInRange(this));
if(!GetTarget()) if(!GetTarget())
return; return;
@ -3791,9 +3791,9 @@ void Bot::PetAIProcess() {
if (IsEngaged()) { if (IsEngaged()) {
if (botPet->IsRooted()) if (botPet->IsRooted())
botPet->SetTarget(hate_list.GetClosest(botPet)); botPet->SetTarget(hate_list.GetClosestEntOnHateList(botPet));
else else
botPet->SetTarget(hate_list.GetTop(botPet)); botPet->SetTarget(hate_list.GetEntWithMostHateInRange(botPet));
// Let's check if we have a los with our target. // Let's check if we have a los with our target.
// If we don't, our hate_list is wiped. // If we don't, our hate_list is wiped.
@ -5854,7 +5854,7 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, SkillUseTypes att
Save(); Save();
Mob *give_exp = hate_list.GetDamageTop(this); Mob *give_exp = hate_list.GetDamageTopOnHateList(this);
Client *give_exp_client = nullptr; Client *give_exp_client = nullptr;
if(give_exp && give_exp->IsClient()) if(give_exp && give_exp->IsClient())

View File

@ -5227,7 +5227,7 @@ void Client::Handle_OP_DeleteSpawn(const EQApplicationPacket *app)
entity_list.QueueClients(this, outapp, false); entity_list.QueueClients(this, outapp, false);
safe_delete(outapp); safe_delete(outapp);
hate_list.RemoveEnt(this->CastToMob()); hate_list.RemoveEntFromHateList(this->CastToMob());
Disconnect(); Disconnect();
return; return;

View File

@ -2434,7 +2434,7 @@ void EntityList::RemoveFromHateLists(Mob *mob, bool settoone)
if (!settoone) if (!settoone)
it->second->RemoveFromHateList(mob); it->second->RemoveFromHateList(mob);
else else
it->second->SetHate(mob, 1); it->second->SetHateAmountOnEnt(mob, 1);
} }
++it; ++it;
} }
@ -2818,7 +2818,7 @@ void EntityList::DoubleAggro(Mob *who)
auto it = npc_list.begin(); auto it = npc_list.begin();
while (it != npc_list.end()) { while (it != npc_list.end()) {
if (it->second->CheckAggro(who)) if (it->second->CheckAggro(who))
it->second->SetHate(who, it->second->CastToNPC()->GetHateAmount(who), it->second->SetHateAmountOnEnt(who, it->second->CastToNPC()->GetHateAmount(who),
it->second->CastToNPC()->GetHateAmount(who) * 2); it->second->CastToNPC()->GetHateAmount(who) * 2);
++it; ++it;
} }
@ -2829,7 +2829,7 @@ void EntityList::HalveAggro(Mob *who)
auto it = npc_list.begin(); auto it = npc_list.begin();
while (it != npc_list.end()) { while (it != npc_list.end()) {
if (it->second->CastToNPC()->CheckAggro(who)) if (it->second->CastToNPC()->CheckAggro(who))
it->second->CastToNPC()->SetHate(who, it->second->CastToNPC()->GetHateAmount(who) / 2); it->second->CastToNPC()->SetHateAmountOnEnt(who, it->second->CastToNPC()->GetHateAmount(who) / 2);
++it; ++it;
} }
} }
@ -2844,9 +2844,9 @@ void EntityList::Evade(Mob *who)
amt = it->second->CastToNPC()->GetHateAmount(who); amt = it->second->CastToNPC()->GetHateAmount(who);
amt -= flatval; amt -= flatval;
if (amt > 0) if (amt > 0)
it->second->CastToNPC()->SetHate(who, amt); it->second->CastToNPC()->SetHateAmountOnEnt(who, amt);
else else
it->second->CastToNPC()->SetHate(who, 0); it->second->CastToNPC()->SetHateAmountOnEnt(who, 0);
} }
++it; ++it;
} }
@ -3647,7 +3647,7 @@ void EntityList::AddTempPetsToHateList(Mob *owner, Mob* other, bool bFrenzy)
if (n->GetSwarmInfo()) { if (n->GetSwarmInfo()) {
if (n->GetSwarmInfo()->owner_id == owner->GetID()) { if (n->GetSwarmInfo()->owner_id == owner->GetID()) {
if (!n->GetSpecialAbility(IMMUNE_AGGRO)) if (!n->GetSpecialAbility(IMMUNE_AGGRO))
n->hate_list.Add(other, 0, 0, bFrenzy); n->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
} }
} }
++it; ++it;

View File

@ -45,431 +45,377 @@ HateList::~HateList()
// added for frenzy support // added for frenzy support
// checks if target still is in frenzy mode // checks if target still is in frenzy mode
void HateList::CheckFrenzyHate() void HateList::IsEntityInFrenzyMode()
{ {
auto iterator = list.begin(); auto iterator = list.begin();
while(iterator != list.end()) while (iterator != list.end()) {
{ if ((*iterator)->entity_on_hatelist->GetHPRatio() >= 20) {
if ((*iterator)->ent->GetHPRatio() >= 20) (*iterator)->is_entity_frenzy = false;
(*iterator)->bFrenzy = false; }
++iterator; ++iterator;
} }
} }
void HateList::Wipe() void HateList::WipeHateList()
{ {
auto iterator = list.begin(); auto iterator = list.begin();
while (iterator != list.end()) {
while(iterator != list.end()) Mob* m = (*iterator)->entity_on_hatelist;
{ if (m) {
Mob* m = (*iterator)->ent;
if(m)
{
parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), m, "0", 0); parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), m, "0", 0);
if (m->IsClient()) {
if(m->IsClient())
m->CastToClient()->DecrementAggroCount(); m->CastToClient()->DecrementAggroCount();
} }
}
delete (*iterator); delete (*iterator);
iterator = list.erase(iterator); iterator = list.erase(iterator);
} }
} }
bool HateList::IsOnHateList(Mob *mob) bool HateList::IsEntOnHateList(Mob *mob)
{ {
if(Find(mob)) if (Find(mob)) {
return true; return true;
}
return false; return false;
} }
tHateEntry *HateList::Find(Mob *ent) struct_HateList *HateList::Find(Mob *ent)
{ {
auto iterator = list.begin(); auto iterator = list.begin();
while(iterator != list.end()) while (iterator != list.end()) {
{ if ((*iterator)->entity_on_hatelist == ent) {
if((*iterator)->ent == ent)
return (*iterator); return (*iterator);
}
++iterator; ++iterator;
} }
return nullptr; return nullptr;
} }
void HateList::Set(Mob* other, uint32 in_hate, uint32 in_dam) void HateList::SetHateAmountOnEnt(Mob* other, uint32 in_hate, uint32 in_damage)
{ {
tHateEntry *p = Find(other); struct_HateList *hate_list = Find(other);
if(p) if (hate_list) {
{ if (in_damage > 0) {
if(in_dam > 0) hate_list->hatelist_damage = in_damage;
p->damage = in_dam; }
if(in_hate > 0) if (in_hate > 0) {
p->hate = in_hate; hate_list->stored_hate_amount = in_hate;
}
} }
} }
Mob* HateList::GetDamageTop(Mob* hater) Mob* HateList::GetDamageTopOnHateList(Mob* hater)
{ {
Mob* current = nullptr; Mob* current = nullptr;
Group* grp = nullptr; Group* grp = nullptr;
Raid* r = nullptr; Raid* r = nullptr;
uint32 dmg_amt = 0; uint32 dmg_amt = 0;
auto iterator = list.begin(); auto iterator = list.begin();
while(iterator != list.end()) while (iterator != list.end()) {
{
grp = nullptr; grp = nullptr;
r = nullptr; r = nullptr;
if ((*iterator)->entity_on_hatelist && (*iterator)->entity_on_hatelist->IsClient()) {
if((*iterator)->ent && (*iterator)->ent->IsClient()){ r = entity_list.GetRaidByClient((*iterator)->entity_on_hatelist->CastToClient());
r = entity_list.GetRaidByClient((*iterator)->ent->CastToClient());
} }
grp = entity_list.GetGroupByMob((*iterator)->entity_on_hatelist);
grp = entity_list.GetGroupByMob((*iterator)->ent); if ((*iterator)->entity_on_hatelist && r) {
if (r->GetTotalRaidDamage(hater) >= dmg_amt) {
if((*iterator)->ent && r){ current = (*iterator)->entity_on_hatelist;
if(r->GetTotalRaidDamage(hater) >= dmg_amt)
{
current = (*iterator)->ent;
dmg_amt = r->GetTotalRaidDamage(hater); dmg_amt = r->GetTotalRaidDamage(hater);
} }
} } else if ((*iterator)->entity_on_hatelist != nullptr && grp != nullptr) {
else if ((*iterator)->ent != nullptr && grp != nullptr) if (grp->GetTotalGroupDamage(hater) >= dmg_amt) {
{ current = (*iterator)->entity_on_hatelist;
if (grp->GetTotalGroupDamage(hater) >= dmg_amt)
{
current = (*iterator)->ent;
dmg_amt = grp->GetTotalGroupDamage(hater); dmg_amt = grp->GetTotalGroupDamage(hater);
} }
} } else if ((*iterator)->entity_on_hatelist != nullptr && (uint32)(*iterator)->hatelist_damage >= dmg_amt) {
else if ((*iterator)->ent != nullptr && (uint32)(*iterator)->damage >= dmg_amt) current = (*iterator)->entity_on_hatelist;
{ dmg_amt = (*iterator)->hatelist_damage;
current = (*iterator)->ent;
dmg_amt = (*iterator)->damage;
} }
++iterator; ++iterator;
} }
return current; return current;
} }
Mob* HateList::GetClosest(Mob *hater) { Mob* HateList::GetClosestEntOnHateList(Mob *hater)
Mob* close = nullptr; {
float closedist = 99999.9f; Mob* close_entity = nullptr;
float thisdist; float close_distance = 99999.9f;
float this_distance;
auto iterator = list.begin(); auto iterator = list.begin();
while(iterator != list.end()) { while (iterator != list.end()) {
thisdist = (*iterator)->ent->DistNoRootNoZ(*hater); this_distance = (*iterator)->entity_on_hatelist->DistNoRootNoZ(*hater);
if((*iterator)->ent != nullptr && thisdist <= closedist) { if ((*iterator)->entity_on_hatelist != nullptr && this_distance <= close_distance) {
closedist = thisdist; close_distance = this_distance;
close = (*iterator)->ent; close_entity = (*iterator)->entity_on_hatelist;
} }
++iterator; ++iterator;
} }
if ((!close_entity && hater->IsNPC()) || (close_entity && close_entity->DivineAura())) {
if ((!close && hater->IsNPC()) || (close && close->DivineAura())) close_entity = hater->CastToNPC()->GetHateTop();
close = hater->CastToNPC()->GetHateTop(); }
return close_entity;
return close;
} }
void HateList::AddEntToHateList(Mob *in_entity, int32 in_hate, int32 in_damage, bool in_is_entity_frenzy, bool iAddIfNotExist)
// a few comments added, rearranged code for readability
void HateList::Add(Mob *ent, int32 in_hate, int32 in_dam, bool bFrenzy, bool iAddIfNotExist)
{ {
if(!ent) if (!in_entity) {
return; return;
if(ent->IsCorpse())
return;
if(ent->IsClient() && ent->CastToClient()->IsDead())
return;
tHateEntry *p = Find(ent);
if (p)
{
p->damage+=(in_dam>=0)?in_dam:0;
p->hate+=in_hate;
p->bFrenzy = bFrenzy;
} }
else if (iAddIfNotExist) { if (in_entity->IsCorpse()) {
p = new tHateEntry; return;
p->ent = ent; }
p->damage = (in_dam>=0)?in_dam:0; if (in_entity->IsClient() && in_entity->CastToClient()->IsDead()) {
p->hate = in_hate; return;
p->bFrenzy = bFrenzy; }
list.push_back(p); struct_HateList *hate_list = Find(in_entity);
parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), ent, "1", 0); if (hate_list) {
hate_list->hatelist_damage += (in_damage >= 0) ? in_damage : 0;
if (ent->IsClient()) { hate_list->stored_hate_amount += in_hate;
if (owner->CastToNPC()->IsRaidTarget()) hate_list->is_entity_frenzy = in_is_entity_frenzy;
ent->CastToClient()->SetEngagedRaidTarget(true); } else if (iAddIfNotExist) {
ent->CastToClient()->IncrementAggroCount(); hate_list = new struct_HateList;
hate_list->entity_on_hatelist = in_entity;
hate_list->hatelist_damage = (in_damage >= 0) ? in_damage : 0;
hate_list->stored_hate_amount = in_hate;
hate_list->is_entity_frenzy = in_is_entity_frenzy;
list.push_back(hate_list);
parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), in_entity, "1", 0);
if (in_entity->IsClient()) {
if (owner->CastToNPC()->IsRaidTarget()) {
in_entity->CastToClient()->SetEngagedRaidTarget(true);
}
in_entity->CastToClient()->IncrementAggroCount();
} }
} }
} }
bool HateList::RemoveEnt(Mob *ent) bool HateList::RemoveEntFromHateList(Mob *in_entity)
{ {
if (!ent) if (!in_entity) {
return false; return false;
}
bool found = false; bool found = false;
auto iterator = list.begin(); auto iterator = list.begin();
while (iterator != list.end()) {
while(iterator != list.end()) if ((*iterator)->entity_on_hatelist == in_entity) {
{ if (in_entity) {
if((*iterator)->ent == ent) parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), in_entity, "0", 0);
{ }
if(ent)
parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), ent, "0", 0);
found = true; found = true;
if (in_entity && in_entity->IsClient()) {
in_entity->CastToClient()->DecrementAggroCount();
if(ent && ent->IsClient()) }
ent->CastToClient()->DecrementAggroCount();
delete (*iterator); delete (*iterator);
iterator = list.erase(iterator); iterator = list.erase(iterator);
} else {
}
else
++iterator; ++iterator;
} }
}
return found; return found;
} }
void HateList::DoFactionHits(int32 nfl_id) { void HateList::DoFactionHits(int32 npc_faction_level_id)
if (nfl_id <= 0) {
if (npc_faction_level_id <= 0) {
return; return;
}
auto iterator = list.begin(); auto iterator = list.begin();
while(iterator != list.end()) while (iterator != list.end()) {
{ Client *client;
Client *p; if ((*iterator)->entity_on_hatelist && (*iterator)->entity_on_hatelist->IsClient()) {
client = (*iterator)->entity_on_hatelist->CastToClient();
if ((*iterator)->ent && (*iterator)->ent->IsClient()) } else {
p = (*iterator)->ent->CastToClient(); client = nullptr;
else }
p = nullptr; if (client) {
client->SetFactionLevel(client->CharacterID(), npc_faction_level_id, client->GetBaseClass(), client->GetBaseRace(), client->GetDeity());
if (p) }
p->SetFactionLevel(p->CharacterID(), nfl_id, p->GetBaseClass(), p->GetBaseRace(), p->GetDeity());
++iterator; ++iterator;
} }
} }
int HateList::SummonedPetCount(Mob *hater) { int HateList::GetSummonedPetCountOnHateList(Mob *hater)
{
//Function to get number of 'Summoned' pets on a targets hate list to allow calculations for certian spell effects.
//Unclear from description that pets are required to be 'summoned body type'. Will not require at this time.
int petcount = 0; int petcount = 0;
auto iterator = list.begin(); auto iterator = list.begin();
while(iterator != list.end()) { while (iterator != list.end()) {
if ((*iterator)->entity_on_hatelist != nullptr && (*iterator)->entity_on_hatelist->IsNPC() && ((*iterator)->entity_on_hatelist->CastToNPC()->IsPet() || ((*iterator)->entity_on_hatelist->CastToNPC()->GetSwarmOwner() > 0))) {
if((*iterator)->ent != nullptr && (*iterator)->ent->IsNPC() && ((*iterator)->ent->CastToNPC()->IsPet() || ((*iterator)->ent->CastToNPC()->GetSwarmOwner() > 0)))
{
++petcount; ++petcount;
} }
++iterator; ++iterator;
} }
return petcount; return petcount;
} }
Mob *HateList::GetTop(Mob *center) Mob *HateList::GetEntWithMostHateInRange(Mob *entity_as_center)
{ {
// hack fix for zone shutdown crashes on some servers /* Hack fix for zone shutdown crashes on some servers */
if (!zone->IsLoaded()) if (!zone->IsLoaded()) {
return nullptr; return nullptr;
}
Mob* top = nullptr; Mob* entity_with_most_hate = nullptr;
int32 hate = -1; int32 hate_status = -1;
uint32 temp_hate_tracker = 0;
if(center == nullptr) if (entity_as_center == nullptr) {
return nullptr; return nullptr;
}
if (RuleB(Aggro,SmartAggroList)){ if (RuleB(Aggro, SmartAggroList)) {
Mob* topClientTypeInRange = nullptr; Mob* top_client_type_in_range = nullptr;
int32 hateClientTypeInRange = -1; int32 hate_client_type_in_range = -1;
int skipped_count = 0; int skipped_count = 0;
auto iterator = list.begin(); auto iterator = list.begin();
while(iterator != list.end()) while (iterator != list.end()) {
{ struct_HateList *hate_list = (*iterator);
tHateEntry *cur = (*iterator); int16 aggro_mod = 0;
int16 aggroMod = 0; if (!hate_list) {
if(!cur){
++iterator; ++iterator;
continue; continue;
} }
if (!hate_list->entity_on_hatelist) {
if(!cur->ent){
++iterator; ++iterator;
continue; continue;
} }
if (entity_as_center->IsNPC() && entity_as_center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if(center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { if (!zone->watermap->InLiquid(hate_list->entity_on_hatelist->GetX(), hate_list->entity_on_hatelist->GetY(), hate_list->entity_on_hatelist->GetZ())) {
if(!zone->watermap->InLiquid(cur->ent->GetX(), cur->ent->GetY(), cur->ent->GetZ())) {
skipped_count++; skipped_count++;
++iterator; ++iterator;
continue; continue;
} }
} }
if (hate_list->entity_on_hatelist->Sanctuary()) {
if (cur->ent->Sanctuary()) { if (hate_status == -1) {
if(hate == -1) entity_with_most_hate = hate_list->entity_on_hatelist;
{ hate_status = 1;
top = cur->ent;
hate = 1;
} }
++iterator; ++iterator;
continue; continue;
} }
if (hate_list->entity_on_hatelist->DivineAura() || hate_list->entity_on_hatelist->IsMezzed() || hate_list->entity_on_hatelist->IsFeared()) {
if(cur->ent->DivineAura() || cur->ent->IsMezzed() || cur->ent->IsFeared()){ if (hate_status == -1) {
if(hate == -1) entity_with_most_hate = hate_list->entity_on_hatelist;
{ hate_status = 0;
top = cur->ent;
hate = 0;
} }
++iterator; ++iterator;
continue; continue;
} }
uint32 current_stored_hate = hate_list->stored_hate_amount;
int32 currentHate = cur->hate; if (hate_list->entity_on_hatelist->IsClient()) {
if (hate_list->entity_on_hatelist->CastToClient()->IsSitting()) {
if(cur->ent->IsClient()){ aggro_mod += RuleI(Aggro, SittingAggroMod);
if(cur->ent->CastToClient()->IsSitting()){
aggroMod += RuleI(Aggro, SittingAggroMod);
} }
if (entity_as_center) {
if(center){ if (entity_as_center->GetTarget() == hate_list->entity_on_hatelist) {
if(center->GetTarget() == cur->ent) aggro_mod += RuleI(Aggro, CurrentTargetAggroMod);
aggroMod += RuleI(Aggro, CurrentTargetAggroMod); }
if(RuleI(Aggro, MeleeRangeAggroMod) != 0) if (RuleI(Aggro, MeleeRangeAggroMod) != 0) {
{ if (entity_as_center->CombatRange(hate_list->entity_on_hatelist)) {
if(center->CombatRange(cur->ent)){ aggro_mod += RuleI(Aggro, MeleeRangeAggroMod);
aggroMod += RuleI(Aggro, MeleeRangeAggroMod); if (current_stored_hate > hate_client_type_in_range || hate_list->is_entity_frenzy) {
hate_client_type_in_range = current_stored_hate;
if(currentHate > hateClientTypeInRange || cur->bFrenzy){ top_client_type_in_range = hate_list->entity_on_hatelist;
hateClientTypeInRange = currentHate;
topClientTypeInRange = cur->ent;
} }
} }
} }
} }
}
else{
if(center){
if(center->GetTarget() == cur->ent)
aggroMod += RuleI(Aggro, CurrentTargetAggroMod);
if(RuleI(Aggro, MeleeRangeAggroMod) != 0)
{
if(center->CombatRange(cur->ent)){
aggroMod += RuleI(Aggro, MeleeRangeAggroMod);
}
}
}
}
if(cur->ent->GetMaxHP() != 0 && ((cur->ent->GetHP()*100/cur->ent->GetMaxHP()) < 20)){
aggroMod += RuleI(Aggro, CriticallyWoundedAggroMod);
}
if(aggroMod){
currentHate += (currentHate * aggroMod / 100);
}
if(currentHate > hate || cur->bFrenzy){
hate = currentHate;
top = cur->ent;
}
++iterator;
}
if(topClientTypeInRange != nullptr && top != nullptr) {
bool isTopClientType = top->IsClient();
#ifdef BOTS
if(!isTopClientType) {
if(top->IsBot()) {
isTopClientType = true;
topClientTypeInRange = top;
}
}
#endif //BOTS
if(!isTopClientType) {
if(top->IsMerc()) {
isTopClientType = true;
topClientTypeInRange = top;
}
}
if (!isTopClientType) {
if (top->GetSpecialAbility(ALLOW_TO_TANK)){
isTopClientType = true;
topClientTypeInRange = top;
}
}
if(!isTopClientType)
return topClientTypeInRange ? topClientTypeInRange : nullptr;
return top ? top : nullptr;
} }
else { else {
if(top == nullptr && skipped_count > 0) { if (entity_as_center) {
return center->GetTarget() ? center->GetTarget() : nullptr; if (entity_as_center->GetTarget() == hate_list->entity_on_hatelist) {
aggro_mod += RuleI(Aggro, CurrentTargetAggroMod);
} }
return top ? top : nullptr; if (RuleI(Aggro, MeleeRangeAggroMod) != 0) {
if (entity_as_center->CombatRange(hate_list->entity_on_hatelist)) {
aggro_mod += RuleI(Aggro, MeleeRangeAggroMod);
} }
} }
else{ }
}
if (hate_list->entity_on_hatelist->GetMaxHP() != 0 && ((hate_list->entity_on_hatelist->GetHP() * 100 / hate_list->entity_on_hatelist->GetMaxHP()) < 20)) {
aggro_mod += RuleI(Aggro, CriticallyWoundedAggroMod);
}
if (aggro_mod) {
current_stored_hate += (current_stored_hate * aggro_mod / 100);
}
if (current_stored_hate > temp_hate_tracker || hate_list->is_entity_frenzy) {
temp_hate_tracker = current_stored_hate;
entity_with_most_hate = hate_list->entity_on_hatelist;
}
++iterator;
}
if (top_client_type_in_range != nullptr && entity_with_most_hate != nullptr) {
bool is_top_client_type = entity_with_most_hate->IsClient();
#ifdef BOTS
if (!is_top_client_type) {
if (entity_with_most_hate->IsBot()) {
is_top_client_type = true;
top_client_type_in_range = entity_with_most_hate;
}
}
#endif //BOTS
if (!is_top_client_type) {
if (entity_with_most_hate->IsMerc()) {
is_top_client_type = true;
top_client_type_in_range = entity_with_most_hate;
}
}
if (!is_top_client_type) {
if (entity_with_most_hate->GetSpecialAbility(ALLOW_TO_TANK)) {
is_top_client_type = true;
top_client_type_in_range = entity_with_most_hate;
}
}
if (!is_top_client_type) {
return top_client_type_in_range ? top_client_type_in_range : nullptr;
}
return entity_with_most_hate ? entity_with_most_hate : nullptr;
} else {
if (entity_with_most_hate == nullptr && skipped_count > 0) {
return entity_as_center->GetTarget() ? entity_as_center->GetTarget() : nullptr;
}
return entity_with_most_hate ? entity_with_most_hate : nullptr;
}
}
/* Process not so smart aggro list */
else {
auto iterator = list.begin(); auto iterator = list.begin();
int skipped_count = 0; int skipped_count = 0;
while(iterator != list.end()) while (iterator != list.end()) {
{ struct_HateList *hate_list = (*iterator);
tHateEntry *cur = (*iterator); if (entity_as_center->IsNPC() && entity_as_center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if(center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { if (!zone->watermap->InLiquid(hate_list->entity_on_hatelist->GetX(), hate_list->entity_on_hatelist->GetY(), hate_list->entity_on_hatelist->GetZ())) {
if(!zone->watermap->InLiquid(cur->ent->GetX(), cur->ent->GetY(), cur->ent->GetZ())) {
skipped_count++; skipped_count++;
++iterator; ++iterator;
continue; continue;
} }
} }
if (hate_list->entity_on_hatelist != nullptr && ((hate_list->stored_hate_amount > temp_hate_tracker) || hate_list->is_entity_frenzy )) {
if(cur->ent != nullptr && ((cur->hate > hate) || cur->bFrenzy )) entity_with_most_hate = hate_list->entity_on_hatelist;
{ temp_hate_tracker = hate_list->stored_hate_amount;
top = cur->ent;
hate = cur->hate;
} }
++iterator; ++iterator;
} }
if(top == nullptr && skipped_count > 0) { if (entity_with_most_hate == nullptr && skipped_count > 0) {
return center->GetTarget() ? center->GetTarget() : nullptr; return entity_as_center->GetTarget() ? entity_as_center->GetTarget() : nullptr;
} }
return top ? top : nullptr; return entity_with_most_hate ? entity_with_most_hate : nullptr;
} }
return nullptr; return nullptr;
} }
Mob *HateList::GetMostHate(){ Mob *HateList::GetEntWithMostHateOnList()
{
Mob* top = nullptr; Mob* top = nullptr;
int32 hate = -1; uint32 hate = 0;
auto iterator = list.begin(); auto iterator = list.begin();
while(iterator != list.end()) while (iterator != list.end()) {
{ struct_HateList *cur = (*iterator);
tHateEntry *cur = (*iterator); if (cur->entity_on_hatelist != nullptr && (cur->stored_hate_amount > hate)) {
if(cur->ent != nullptr && (cur->hate > hate)) top = cur->entity_on_hatelist;
{ hate = cur->stored_hate_amount;
top = cur->ent;
hate = cur->hate;
} }
++iterator; ++iterator;
} }
@ -477,110 +423,97 @@ Mob *HateList::GetMostHate(){
} }
Mob *HateList::GetRandom() Mob *HateList::GetRandomEntOnHateList()
{ {
int count = list.size(); int count = list.size();
if(count == 0) //If we don't have any entries it'll crash getting a random 0, -1 position. if (count == 0) { //If we don't have any entries it'll crash getting a random 0, -1 position.
return NULL; return NULL;
}
if(count == 1) //No need to do all that extra work if we only have one hate entry if (count == 1) { //No need to do all that extra work if we only have one hate entry
{ if (*list.begin()) { // Just in case tHateEntry is invalidated somehow...
if(*list.begin()) // Just in case tHateEntry is invalidated somehow... return (*list.begin())->entity_on_hatelist;
return (*list.begin())->ent; }
return NULL; return NULL;
} }
auto iterator = list.begin(); auto iterator = list.begin();
int random = zone->random.Int(0, count - 1); int random = zone->random.Int(0, count - 1);
for (int i = 0; i < random; i++) for (int i = 0; i < random; i++) {
++iterator; ++iterator;
}
return (*iterator)->ent; return (*iterator)->entity_on_hatelist;
} }
int32 HateList::GetEntHate(Mob *ent, bool damage) uint32 HateList::GetEntHateAmount(Mob *ent, bool damage /*= false*/)
{ {
tHateEntry *p; struct_HateList *hate_list;
hate_list = Find(ent);
p = Find(ent); if ( hate_list && damage) {
return hate_list->hatelist_damage;
if ( p && damage) } else if (hate_list) {
return p->damage; return hate_list->stored_hate_amount;
else if (p) } else {
return p->hate;
else
return 0; return 0;
}
} }
//looking for any mob with hate > -1 bool HateList::IsHateListEmpty()
bool HateList::IsEmpty() { {
return(list.size() == 0); return (list.size() == 0);
} }
// Prints hate list to a client void HateList::PrintHateListToClient(Client *c)
void HateList::PrintToClient(Client *c)
{ {
auto iterator = list.begin(); auto iterator = list.begin();
while (iterator != list.end()) while (iterator != list.end()) {
{ struct_HateList *hate_list = (*iterator);
tHateEntry *e = (*iterator);
c->Message(0, "- name: %s, damage: %d, hate: %d",
(e->ent && e->ent->GetName()) ? e->ent->GetName() : "(null)",
e->damage, e->hate);
c->Message(0, "- name: %s, damage: %d, hate: %d",
(hate_list->entity_on_hatelist && hate_list->entity_on_hatelist->GetName()) ? hate_list->entity_on_hatelist->GetName() : "(null)",
hate_list->hatelist_damage, hate_list->stored_hate_amount);
++iterator; ++iterator;
} }
} }
int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts) int HateList::AreaRampage(Mob *in_caster, Mob *in_target, int in_count, ExtraAttackOptions *options)
{ {
if(!target || !caster) if (!in_target || !in_caster) {
return 0; return 0;
}
int ret = 0; int ret = 0;
std::list<uint32> id_list; std::list<uint32> id_list;
auto iterator = list.begin(); auto iterator = list.begin();
while (iterator != list.end()) while (iterator != list.end()) {
{ struct_HateList *h = (*iterator);
tHateEntry *h = (*iterator);
++iterator; ++iterator;
if(h && h->ent && h->ent != caster) if (h && h->entity_on_hatelist && h->entity_on_hatelist != in_caster) {
{ if (in_caster->CombatRange(h->entity_on_hatelist)) {
if(caster->CombatRange(h->ent)) id_list.push_back(h->entity_on_hatelist->GetID());
{
id_list.push_back(h->ent->GetID());
++ret; ++ret;
} }
} }
} }
std::list<uint32>::iterator iter = id_list.begin(); std::list<uint32>::iterator iter = id_list.begin();
while(iter != id_list.end()) while (iter != id_list.end()) {
{
Mob *cur = entity_list.GetMobID((*iter)); Mob *cur = entity_list.GetMobID((*iter));
if(cur) if (cur) {
{ for (int i = 0; i < in_count; ++i) {
for(int i = 0; i < count; ++i) { in_caster->Attack(cur, MainPrimary, false, false, false, options);
caster->Attack(cur, MainPrimary, false, false, false, opts);
} }
} }
iter++; iter++;
} }
return ret; return ret;
} }
void HateList::SpellCast(Mob *caster, uint32 spell_id, float range, Mob* ae_center) void HateList::SpellCast(Mob *caster, uint32 spell_id, float range, Mob* ae_center)
{ {
if(!caster) if (!caster) {
return; return;
}
Mob* center = caster; Mob* center = caster;
if (ae_center) {
if (ae_center)
center = ae_center; center = ae_center;
}
//this is slower than just iterating through the list but avoids //this is slower than just iterating through the list but avoids
//crashes when people kick the bucket in the middle of this call //crashes when people kick the bucket in the middle of this call
//that invalidates our iterator but there's no way to know sadly //that invalidates our iterator but there's no way to know sadly
@ -590,32 +523,24 @@ void HateList::SpellCast(Mob *caster, uint32 spell_id, float range, Mob* ae_cent
float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range; float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range;
float dist_targ = 0; float dist_targ = 0;
auto iterator = list.begin(); auto iterator = list.begin();
while (iterator != list.end()) while (iterator != list.end()) {
{ struct_HateList *h = (*iterator);
tHateEntry *h = (*iterator); if (range > 0) {
if(range > 0) dist_targ = center->DistNoRoot(*h->entity_on_hatelist);
{ if (dist_targ <= range && dist_targ >= min_range2) {
dist_targ = center->DistNoRoot(*h->ent); id_list.push_back(h->entity_on_hatelist->GetID());
if(dist_targ <= range && dist_targ >= min_range2) h->entity_on_hatelist->CalcSpellPowerDistanceMod(spell_id, dist_targ);
{
id_list.push_back(h->ent->GetID());
h->ent->CalcSpellPowerDistanceMod(spell_id, dist_targ);
} }
} } else {
else id_list.push_back(h->entity_on_hatelist->GetID());
{ h->entity_on_hatelist->CalcSpellPowerDistanceMod(spell_id, 0, caster);
id_list.push_back(h->ent->GetID());
h->ent->CalcSpellPowerDistanceMod(spell_id, 0, caster);
} }
++iterator; ++iterator;
} }
std::list<uint32>::iterator iter = id_list.begin(); std::list<uint32>::iterator iter = id_list.begin();
while(iter != id_list.end()) while (iter != id_list.end()) {
{
Mob *cur = entity_list.GetMobID((*iter)); Mob *cur = entity_list.GetMobID((*iter));
if(cur) if (cur) {
{
caster->SpellOnTarget(spell_id, cur); caster->SpellOnTarget(spell_id, cur);
} }
iter++; iter++;

View File

@ -1,5 +1,5 @@
/* EQEMu: Everquest Server Emulator /* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) Copyright (C) 2001-2015 EQEMu Development Team (http://eqemu.org)
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -25,65 +25,59 @@ class Mob;
class Raid; class Raid;
struct ExtraAttackOptions; struct ExtraAttackOptions;
struct tHateEntry struct struct_HateList {
{ Mob *entity_on_hatelist;
Mob *ent; uint32 hatelist_damage;
int32 damage, hate; uint32 stored_hate_amount;
bool bFrenzy; bool is_entity_frenzy;
}; };
class HateList class HateList
{ {
public: public:
HateList(); HateList();
~HateList(); ~HateList();
// adds a mob to the hatelist Mob *GetClosestEntOnHateList(Mob *hater);
void Add(Mob *ent, int32 in_hate=0, int32 in_dam=0, bool bFrenzy = false, bool iAddIfNotExist = true); Mob *GetDamageTopOnHateList(Mob *hater);
// sets existing hate Mob *GetRandomEntOnHateList();
void Set(Mob *other, uint32 in_hate, uint32 in_dam); Mob *GetEntWithMostHateInRange(Mob *center);
// removes mobs from hatelist Mob* GetEntWithMostHateOnList();
bool RemoveEnt(Mob *ent);
// Remove all bool IsEntOnHateList(Mob *);
void Wipe(); bool IsHateListEmpty();
// ??? bool RemoveEntFromHateList(Mob *ent);
void DoFactionHits(int32 nfl_id);
// Gets Hate amount for mob
int32 GetEntHate(Mob *ent, bool damage = false);
// gets top hated mob
Mob *GetTop(Mob *center);
// gets any on the list
Mob *GetRandom();
// get closest mob or nullptr if list empty
Mob *GetClosest(Mob *hater);
// gets top mob or nullptr if hate list empty
Mob *GetDamageTop(Mob *hater);
// used to check if mob is on hatelist
bool IsOnHateList(Mob *);
// used to remove or add frenzy hate
void CheckFrenzyHate();
//Gets the target with the most hate regardless of things like frenzy etc.
Mob* GetMostHate();
// Count 'Summoned' pets on hatelist
int SummonedPetCount(Mob *hater);
int AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts); int AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts);
int GetSummonedPetCountOnHateList(Mob *hater);
uint32 GetEntHateAmount(Mob *in_entity, bool damage = false);
void AddEntToHateList(Mob *in_entity, int32 in_hate = 0, int32 in_damage = 0, bool in_is_frenzied = false, bool add_to_hate_list_if_not_exist = true);
void DoFactionHits(int32 npc_faction_level_id);
void IsEntityInFrenzyMode();
void PrintHateListToClient(Client *c);
void SetHateAmountOnEnt(Mob *other, uint32 in_hate, uint32 in_dam);
void SpellCast(Mob *caster, uint32 spell_id, float range, Mob *ae_center = nullptr); void SpellCast(Mob *caster, uint32 spell_id, float range, Mob *ae_center = nullptr);
void WipeHateList();
bool IsEmpty();
void PrintToClient(Client *c);
//For accessing the hate list via perl; don't use for anything else /* For accessing the hate list via perl; don't use for anything else */
std::list<tHateEntry*>& GetHateList() { return list; } std::list<struct_HateList*>& GetHateList()
{
return list;
}
//setting owner /* Setting owner*/
void SetOwner(Mob *newOwner) { owner = newOwner; } void SetOwner(Mob *new_owner)
{
owner = new_owner;
}
protected: protected:
tHateEntry* Find(Mob *ent); struct_HateList* Find(Mob *ent);
private: private:
std::list<tHateEntry*> list; std::list<struct_HateList*> list;
Mob *owner; Mob *owner;
}; };

View File

@ -12,42 +12,42 @@
Lua_Mob Lua_HateEntry::GetEnt() { Lua_Mob Lua_HateEntry::GetEnt() {
Lua_Safe_Call_Class(Lua_Mob); Lua_Safe_Call_Class(Lua_Mob);
return Lua_Mob(self->ent); return Lua_Mob(self->entity_on_hatelist);
} }
void Lua_HateEntry::SetEnt(Lua_Mob e) { void Lua_HateEntry::SetEnt(Lua_Mob e) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->ent = e; self->entity_on_hatelist = e;
} }
int Lua_HateEntry::GetDamage() { int Lua_HateEntry::GetDamage() {
Lua_Safe_Call_Int(); Lua_Safe_Call_Int();
return self->damage; return self->hatelist_damage;
} }
void Lua_HateEntry::SetDamage(int value) { void Lua_HateEntry::SetDamage(int value) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->damage = value; self->hatelist_damage = value;
} }
int Lua_HateEntry::GetHate() { int Lua_HateEntry::GetHate() {
Lua_Safe_Call_Int(); Lua_Safe_Call_Int();
return self->hate; return self->stored_hate_amount;
} }
void Lua_HateEntry::SetHate(int value) { void Lua_HateEntry::SetHate(int value) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->hate = value; self->stored_hate_amount = value;
} }
int Lua_HateEntry::GetFrenzy() { int Lua_HateEntry::GetFrenzy() {
Lua_Safe_Call_Int(); Lua_Safe_Call_Int();
return self->bFrenzy; return self->is_entity_frenzy;
} }
void Lua_HateEntry::SetFrenzy(bool value) { void Lua_HateEntry::SetFrenzy(bool value) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->bFrenzy = value; self->is_entity_frenzy = value;
} }
luabind::scope lua_register_hate_entry() { luabind::scope lua_register_hate_entry() {

View File

@ -5,17 +5,17 @@
#include "lua_ptr.h" #include "lua_ptr.h"
class Lua_Mob; class Lua_Mob;
struct tHateEntry; struct struct_HateList;
luabind::scope lua_register_hate_entry(); luabind::scope lua_register_hate_entry();
luabind::scope lua_register_hate_list(); luabind::scope lua_register_hate_list();
class Lua_HateEntry : public Lua_Ptr<tHateEntry> class Lua_HateEntry : public Lua_Ptr<struct_HateList>
{ {
typedef tHateEntry NativeType; typedef struct_HateList NativeType;
public: public:
Lua_HateEntry() : Lua_Ptr(nullptr) { } Lua_HateEntry() : Lua_Ptr(nullptr) { }
Lua_HateEntry(tHateEntry *d) : Lua_Ptr(d) { } Lua_HateEntry(struct_HateList *d) : Lua_Ptr(d) { }
virtual ~Lua_HateEntry() { } virtual ~Lua_HateEntry() { }
Lua_Mob GetEnt(); Lua_Mob GetEnt();

View File

@ -895,17 +895,17 @@ void Lua_Mob::AddToHateList(Lua_Mob other, int hate, int damage, bool yell_for_h
void Lua_Mob::SetHate(Lua_Mob other) { void Lua_Mob::SetHate(Lua_Mob other) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->SetHate(other); self->SetHateAmountOnEnt(other);
} }
void Lua_Mob::SetHate(Lua_Mob other, int hate) { void Lua_Mob::SetHate(Lua_Mob other, int hate) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->SetHate(other, hate); self->SetHateAmountOnEnt(other, hate);
} }
void Lua_Mob::SetHate(Lua_Mob other, int hate, int damage) { void Lua_Mob::SetHate(Lua_Mob other, int hate, int damage) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->SetHate(other, hate, damage); self->SetHateAmountOnEnt(other, hate, damage);
} }
void Lua_Mob::HalveAggro(Lua_Mob other) { void Lua_Mob::HalveAggro(Lua_Mob other) {

View File

@ -1385,7 +1385,7 @@ void Merc::AI_Process() {
rest_timer.Disable(); rest_timer.Disable();
if(IsRooted()) if(IsRooted())
SetTarget(hate_list.GetClosest(this)); SetTarget(hate_list.GetClosestEntOnHateList(this));
else else
FindTarget(); FindTarget();
@ -2454,11 +2454,11 @@ void Merc::CheckHateList() {
Mob* groupMember = g->members[counter]; Mob* groupMember = g->members[counter];
if(groupMember) { if(groupMember) {
if(npc->IsOnHatelist(groupMember)) { if(npc->IsOnHatelist(groupMember)) {
if(!hate_list.IsOnHateList(npc)) { if(!hate_list.IsEntOnHateList(npc)) {
float range = g->HasRole(groupMember, RolePuller) ? RuleI(Mercs, AggroRadiusPuller) : RuleI(Mercs, AggroRadius); float range = g->HasRole(groupMember, RolePuller) ? RuleI(Mercs, AggroRadiusPuller) : RuleI(Mercs, AggroRadius);
range *= range; range *= range;
if(npc->DistNoRootNoZ(*this) < range) { if(npc->DistNoRootNoZ(*this) < range) {
hate_list.Add(npc, 1); hate_list.AddEntToHateList(npc, 1);
} }
} }
} }

View File

@ -2556,8 +2556,8 @@ bool Mob::RemoveFromHateList(Mob* mob)
bool bFound = false; bool bFound = false;
if(IsEngaged()) if(IsEngaged())
{ {
bFound = hate_list.RemoveEnt(mob); bFound = hate_list.RemoveEntFromHateList(mob);
if(hate_list.IsEmpty()) if(hate_list.IsHateListEmpty())
{ {
AI_Event_NoLongerEngaged(); AI_Event_NoLongerEngaged();
zone->DelAggroMob(); zone->DelAggroMob();
@ -2565,7 +2565,7 @@ bool Mob::RemoveFromHateList(Mob* mob)
} }
if(GetTarget() == mob) if(GetTarget() == mob)
{ {
SetTarget(hate_list.GetTop(this)); SetTarget(hate_list.GetEntWithMostHateInRange(this));
} }
return bFound; return bFound;
@ -2575,12 +2575,12 @@ void Mob::WipeHateList()
{ {
if(IsEngaged()) if(IsEngaged())
{ {
hate_list.Wipe(); hate_list.WipeHateList();
AI_Event_NoLongerEngaged(); AI_Event_NoLongerEngaged();
} }
else else
{ {
hate_list.Wipe(); hate_list.WipeHateList();
} }
} }
@ -3501,7 +3501,7 @@ void Mob::TryTriggerOnValueAmount(bool IsHP, bool IsMana, bool IsEndur, bool IsP
} }
else if (IsPet){ else if (IsPet){
int count = hate_list.SummonedPetCount(this); int count = hate_list.GetSummonedPetCountOnHateList(this);
if ((base2 >= 220 && base2 <= 250) && count >= (base2 - 220)){ if ((base2 >= 220 && base2 <= 250) && count >= (base2 - 220)){
use_spell = true; use_spell = true;
} }

View File

@ -455,16 +455,16 @@ public:
virtual void AddToHateList(Mob* other, int32 hate = 0, int32 damage = 0, bool iYellForHelp = true, virtual void AddToHateList(Mob* other, int32 hate = 0, int32 damage = 0, bool iYellForHelp = true,
bool bFrenzy = false, bool iBuffTic = false); bool bFrenzy = false, bool iBuffTic = false);
bool RemoveFromHateList(Mob* mob); bool RemoveFromHateList(Mob* mob);
void SetHate(Mob* other, int32 hate = 0, int32 damage = 0) { hate_list.Set(other,hate,damage);} void SetHateAmountOnEnt(Mob* other, int32 hate = 0, int32 damage = 0) { hate_list.SetHateAmountOnEnt(other,hate,damage);}
void HalveAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHate(other, (in_hate > 1 ? in_hate / 2 : 1)); } void HalveAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHateAmountOnEnt(other, (in_hate > 1 ? in_hate / 2 : 1)); }
void DoubleAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHate(other, (in_hate ? in_hate * 2 : 1)); } void DoubleAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHateAmountOnEnt(other, (in_hate ? in_hate * 2 : 1)); }
uint32 GetHateAmount(Mob* tmob, bool is_dam = false) { return hate_list.GetEntHate(tmob,is_dam);} uint32 GetHateAmount(Mob* tmob, bool is_dam = false) { return hate_list.GetEntHateAmount(tmob,is_dam);}
uint32 GetDamageAmount(Mob* tmob) { return hate_list.GetEntHate(tmob, true);} uint32 GetDamageAmount(Mob* tmob) { return hate_list.GetEntHateAmount(tmob, true);}
Mob* GetHateTop() { return hate_list.GetTop(this);} Mob* GetHateTop() { return hate_list.GetEntWithMostHateInRange(this);}
Mob* GetHateDamageTop(Mob* other) { return hate_list.GetDamageTop(other);} Mob* GetHateDamageTop(Mob* other) { return hate_list.GetDamageTopOnHateList(other);}
Mob* GetHateRandom() { return hate_list.GetRandom();} Mob* GetHateRandom() { return hate_list.GetRandomEntOnHateList();}
Mob* GetHateMost() { return hate_list.GetMostHate();} Mob* GetHateMost() { return hate_list.GetEntWithMostHateOnList();}
bool IsEngaged() { return(!hate_list.IsEmpty()); } bool IsEngaged() { return(!hate_list.IsHateListEmpty()); }
bool HateSummon(); bool HateSummon();
void FaceTarget(Mob* MobToFace = 0); void FaceTarget(Mob* MobToFace = 0);
void SetHeading(float iHeading) { if(heading != iHeading) { pLastChange = Timer::GetCurrentTime(); void SetHeading(float iHeading) { if(heading != iHeading) { pLastChange = Timer::GetCurrentTime();
@ -473,8 +473,8 @@ public:
void AddFeignMemory(Client* attacker); void AddFeignMemory(Client* attacker);
void RemoveFromFeignMemory(Client* attacker); void RemoveFromFeignMemory(Client* attacker);
void ClearFeignMemory(); void ClearFeignMemory();
void PrintHateListToClient(Client *who) { hate_list.PrintToClient(who); } void PrintHateListToClient(Client *who) { hate_list.PrintHateListToClient(who); }
std::list<tHateEntry*>& GetHateList() { return hate_list.GetHateList(); } std::list<struct_HateList*>& GetHateList() { return hate_list.GetHateList(); }
bool CheckLosFN(Mob* other); bool CheckLosFN(Mob* other);
bool CheckLosFN(float posX, float posY, float posZ, float mobSize); bool CheckLosFN(float posX, float posY, float posZ, float mobSize);
inline void SetChanged() { pLastChange = Timer::GetCurrentTime(); } inline void SetChanged() { pLastChange = Timer::GetCurrentTime(); }
@ -798,7 +798,7 @@ public:
void CheckFlee(); void CheckFlee();
inline bool IsBlind() { return spellbonuses.IsBlind; } inline bool IsBlind() { return spellbonuses.IsBlind; }
inline bool CheckAggro(Mob* other) {return hate_list.IsOnHateList(other);} inline bool CheckAggro(Mob* other) {return hate_list.IsEntOnHateList(other);}
float CalculateHeadingToTarget(float in_x, float in_y); float CalculateHeadingToTarget(float in_x, float in_y);
bool CalculateNewPosition(float x, float y, float z, float speed, bool checkZ = false); bool CalculateNewPosition(float x, float y, float z, float speed, bool checkZ = false);
virtual bool CalculateNewPosition2(float x, float y, float z, float speed, bool checkZ = true); virtual bool CalculateNewPosition2(float x, float y, float z, float speed, bool checkZ = true);

View File

@ -491,7 +491,7 @@ void Mob::AI_Start(uint32 iMoveDelay) {
pAggroRange = 70; pAggroRange = 70;
if (GetAssistRange() == 0) if (GetAssistRange() == 0)
pAssistRange = 70; pAssistRange = 70;
hate_list.Wipe(); hate_list.WipeHateList();
delta_heading = 0; delta_heading = 0;
delta_x = 0; delta_x = 0;
@ -551,7 +551,7 @@ void Mob::AI_Stop() {
safe_delete(AIscanarea_timer); safe_delete(AIscanarea_timer);
safe_delete(AIfeignremember_timer); safe_delete(AIfeignremember_timer);
hate_list.Wipe(); hate_list.WipeHateList();
} }
void NPC::AI_Stop() { void NPC::AI_Stop() {
@ -814,12 +814,12 @@ void Client::AI_Process()
if (engaged) if (engaged)
{ {
if (IsRooted()) if (IsRooted())
SetTarget(hate_list.GetClosest(this)); SetTarget(hate_list.GetClosestEntOnHateList(this));
else else
{ {
if(AItarget_check_timer->Check()) if(AItarget_check_timer->Check())
{ {
SetTarget(hate_list.GetTop(this)); SetTarget(hate_list.GetEntWithMostHateInRange(this));
} }
} }
@ -1039,7 +1039,7 @@ void Mob::AI_Process() {
// //
if(RuleB(Combat, EnableFearPathing)){ if(RuleB(Combat, EnableFearPathing)){
if(curfp) { if(curfp) {
if(IsRooted() || (IsBlind() && CombatRange(hate_list.GetClosest(this)))) { if(IsRooted() || (IsBlind() && CombatRange(hate_list.GetClosestEntOnHateList(this)))) {
//make sure everybody knows were not moving, for appearance sake //make sure everybody knows were not moving, for appearance sake
if(IsMoving()) if(IsMoving())
{ {
@ -1089,18 +1089,18 @@ void Mob::AI_Process() {
// we are prevented from getting here if we are blind and don't have a target in range // we are prevented from getting here if we are blind and don't have a target in range
// from above, so no extra blind checks needed // from above, so no extra blind checks needed
if ((IsRooted() && !GetSpecialAbility(IGNORE_ROOT_AGGRO_RULES)) || IsBlind()) if ((IsRooted() && !GetSpecialAbility(IGNORE_ROOT_AGGRO_RULES)) || IsBlind())
SetTarget(hate_list.GetClosest(this)); SetTarget(hate_list.GetClosestEntOnHateList(this));
else else
{ {
if(AItarget_check_timer->Check()) if(AItarget_check_timer->Check())
{ {
if (IsFocused()) { if (IsFocused()) {
if (!target) { if (!target) {
SetTarget(hate_list.GetTop(this)); SetTarget(hate_list.GetEntWithMostHateInRange(this));
} }
} else { } else {
if (!ImprovedTaunt()) if (!ImprovedTaunt())
SetTarget(hate_list.GetTop(this)); SetTarget(hate_list.GetEntWithMostHateInRange(this));
} }
} }
@ -1374,7 +1374,7 @@ void Mob::AI_Process() {
//underwater stuff only works with water maps in the zone! //underwater stuff only works with water maps in the zone!
if(IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { if(IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if(!zone->watermap->InLiquid(target->GetX(), target->GetY(), target->GetZ())) { if(!zone->watermap->InLiquid(target->GetX(), target->GetY(), target->GetZ())) {
Mob *tar = hate_list.GetTop(this); Mob *tar = hate_list.GetEntWithMostHateInRange(this);
if(tar == target) { if(tar == target) {
WipeHateList(); WipeHateList();
Heal(); Heal();

View File

@ -249,8 +249,8 @@ public:
inline int32 GetNPCFactionID() const { return npc_faction_id; } inline int32 GetNPCFactionID() const { return npc_faction_id; }
inline int32 GetPrimaryFaction() const { return primary_faction; } inline int32 GetPrimaryFaction() const { return primary_faction; }
int32 GetNPCHate(Mob* in_ent) {return hate_list.GetEntHate(in_ent);} int32 GetNPCHate(Mob* in_ent) {return hate_list.GetEntHateAmount(in_ent);}
bool IsOnHatelist(Mob*p) { return hate_list.IsOnHateList(p);} bool IsOnHatelist(Mob*p) { return hate_list.IsEntOnHateList(p);}
void SetNPCFactionID(int32 in) { npc_faction_id = in; database.GetFactionIdsForNPC(npc_faction_id, &faction_list, &primary_faction); } void SetNPCFactionID(int32 in) { npc_faction_id = in; database.GetFactionIdsForNPC(npc_faction_id, &faction_list, &primary_faction); }

View File

@ -40,19 +40,19 @@ XS(XS_HateEntry_GetEnt)
if (items != 1) if (items != 1)
Perl_croak(aTHX_ "Usage: HateEntry::GetData(THIS)"); Perl_croak(aTHX_ "Usage: HateEntry::GetData(THIS)");
{ {
tHateEntry * THIS; struct_HateList * THIS;
Mob * RETVAL; Mob * RETVAL;
if (sv_derived_from(ST(0), "HateEntry")) { if (sv_derived_from(ST(0), "HateEntry")) {
IV tmp = SvIV((SV*)SvRV(ST(0))); IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(tHateEntry *,tmp); THIS = INT2PTR(struct_HateList *,tmp);
} }
else else
Perl_croak(aTHX_ "THIS is not of type tHateEntry"); Perl_croak(aTHX_ "THIS is not of type tHateEntry");
if(THIS == nullptr) if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->ent; RETVAL = THIS->entity_on_hatelist;
ST(0) = sv_newmortal(); ST(0) = sv_newmortal();
sv_setref_pv(ST(0), "Mob", (void*)RETVAL); sv_setref_pv(ST(0), "Mob", (void*)RETVAL);
} }
@ -66,20 +66,20 @@ XS(XS_HateEntry_GetHate)
if (items != 1) if (items != 1)
Perl_croak(aTHX_ "Usage: HateEntry::GetHate(THIS)"); Perl_croak(aTHX_ "Usage: HateEntry::GetHate(THIS)");
{ {
tHateEntry * THIS; struct_HateList * THIS;
int32 RETVAL; int32 RETVAL;
dXSTARG; dXSTARG;
if (sv_derived_from(ST(0), "HateEntry")) { if (sv_derived_from(ST(0), "HateEntry")) {
IV tmp = SvIV((SV*)SvRV(ST(0))); IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(tHateEntry *,tmp); THIS = INT2PTR(struct_HateList *,tmp);
} }
else else
Perl_croak(aTHX_ "THIS is not of type tHateEntry"); Perl_croak(aTHX_ "THIS is not of type tHateEntry");
if(THIS == nullptr) if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->hate; RETVAL = THIS->stored_hate_amount;
XSprePUSH; PUSHi((IV)RETVAL); XSprePUSH; PUSHi((IV)RETVAL);
} }
XSRETURN(1); XSRETURN(1);
@ -92,20 +92,20 @@ XS(XS_HateEntry_GetDamage)
if (items != 1) if (items != 1)
Perl_croak(aTHX_ "Usage: HateEntry::GetDamage(THIS)"); Perl_croak(aTHX_ "Usage: HateEntry::GetDamage(THIS)");
{ {
tHateEntry * THIS; struct_HateList * THIS;
int32 RETVAL; int32 RETVAL;
dXSTARG; dXSTARG;
if (sv_derived_from(ST(0), "HateEntry")) { if (sv_derived_from(ST(0), "HateEntry")) {
IV tmp = SvIV((SV*)SvRV(ST(0))); IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(tHateEntry *,tmp); THIS = INT2PTR(struct_HateList *,tmp);
} }
else else
Perl_croak(aTHX_ "THIS is not of type tHateEntry"); Perl_croak(aTHX_ "THIS is not of type tHateEntry");
if(THIS == nullptr) if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->damage; RETVAL = THIS->hatelist_damage;
XSprePUSH; PUSHi((IV)RETVAL); XSprePUSH; PUSHi((IV)RETVAL);
} }
XSRETURN(1); XSRETURN(1);

View File

@ -5354,7 +5354,7 @@ XS(XS_Mob_SetHate)
damage = (int32)SvIV(ST(3)); damage = (int32)SvIV(ST(3));
} }
THIS->SetHate(other, hate, damage); THIS->SetHateAmountOnEnt(other, hate, damage);
} }
XSRETURN_EMPTY; XSRETURN_EMPTY;
} }
@ -6599,7 +6599,7 @@ XS(XS_Mob_GetHateList)
while(iter != hate_list.end()) while(iter != hate_list.end())
{ {
tHateEntry *entry = (*iter); struct_HateList *entry = (*iter);
ST(0) = sv_newmortal(); ST(0) = sv_newmortal();
sv_setref_pv(ST(0), "HateEntry", (void*)entry); sv_setref_pv(ST(0), "HateEntry", (void*)entry);
XPUSHs(ST(0)); XPUSHs(ST(0));

View File

@ -2662,7 +2662,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
caster->Taunt(this->CastToNPC(), false, static_cast<float>(spell.base[i])); caster->Taunt(this->CastToNPC(), false, static_cast<float>(spell.base[i]));
if (spell.base2[i] > 0) if (spell.base2[i] > 0)
CastToNPC()->SetHate(caster, (CastToNPC()->GetHateAmount(caster) + spell.base2[i])); CastToNPC()->SetHateAmountOnEnt(caster, (CastToNPC()->GetHateAmount(caster) + spell.base2[i]));
} }
break; break;
} }
@ -2693,7 +2693,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
if (new_hate <= 0) if (new_hate <= 0)
new_hate = 1; new_hate = 1;
CastToNPC()->SetHate(caster, new_hate); CastToNPC()->SetHateAmountOnEnt(caster, new_hate);
} }
break; break;
} }
@ -2714,9 +2714,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
}else{ }else{
int32 newhate = GetHateAmount(caster) + effect_value; int32 newhate = GetHateAmount(caster) + effect_value;
if (newhate < 1) if (newhate < 1)
SetHate(caster,1); SetHateAmountOnEnt(caster,1);
else else
SetHate(caster,newhate); SetHateAmountOnEnt(caster,newhate);
} }
} }
break; break;
@ -3546,9 +3546,9 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
}else{ }else{
int32 newhate = GetHateAmount(caster) + effect_value; int32 newhate = GetHateAmount(caster) + effect_value;
if (newhate < 1) { if (newhate < 1) {
SetHate(caster,1); SetHateAmountOnEnt(caster,1);
} else { } else {
SetHate(caster,newhate); SetHateAmountOnEnt(caster,newhate);
} }
} }
} }
@ -3732,7 +3732,7 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
if (new_hate <= 0) if (new_hate <= 0)
new_hate = 1; new_hate = 1;
CastToNPC()->SetHate(caster, new_hate); CastToNPC()->SetHateAmountOnEnt(caster, new_hate);
} }
break; break;
} }
@ -6424,7 +6424,7 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama
//Limit to amount of pets //Limit to amount of pets
if (value >= 221 && value <= 249){ if (value >= 221 && value <= 249){
int count = hate_list.SummonedPetCount(this); int count = hate_list.GetSummonedPetCountOnHateList(this);
for (int base2_value = 221; base2_value <= 249; ++base2_value){ for (int base2_value = 221; base2_value <= 249; ++base2_value){
if (value == base2_value){ if (value == base2_value){

View File

@ -3658,9 +3658,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r
else{ else{
int32 newhate = spelltar->GetHateAmount(this) + aggro; int32 newhate = spelltar->GetHateAmount(this) + aggro;
if (newhate < 1) { if (newhate < 1) {
spelltar->SetHate(this,1); spelltar->SetHateAmountOnEnt(this,1);
} else { } else {
spelltar->SetHate(this,newhate); spelltar->SetHateAmountOnEnt(this,newhate);
} }
} }
} }
@ -3688,9 +3688,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r
spelltar->AddToHateList(this, aggro_amount); else{ spelltar->AddToHateList(this, aggro_amount); else{
int32 newhate = spelltar->GetHateAmount(this) + aggro_amount; int32 newhate = spelltar->GetHateAmount(this) + aggro_amount;
if (newhate < 1) { if (newhate < 1) {
spelltar->SetHate(this,1); spelltar->SetHateAmountOnEnt(this,1);
} else { } else {
spelltar->SetHate(this,newhate); spelltar->SetHateAmountOnEnt(this,newhate);
} }
} }
} }