Reverting some hate stuff so things work again

This commit is contained in:
Akkadius 2014-12-27 23:19:48 -06:00
parent 8983953d7d
commit 4f65066274
3 changed files with 388 additions and 311 deletions

View File

@ -48,10 +48,10 @@ HateList::~HateList()
void HateList::IsEntityInFrenzyMode() 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)->entity_on_hatelist->GetHPRatio() >= 20)
(*iterator)->is_entity_frenzy = false; (*iterator)->is_entity_frenzy = false;
}
++iterator; ++iterator;
} }
} }
@ -59,49 +59,51 @@ void HateList::IsEntityInFrenzyMode()
void HateList::WipeHateList() 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; Mob* m = (*iterator)->entity_on_hatelist;
if (m) { 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::IsEntOnHateList(Mob *mob) bool HateList::IsEntOnHateList(Mob *mob)
{ {
if (Find(mob)) { if (Find(mob))
return true; return true;
}
return false; return false;
} }
struct_HateList *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)->entity_on_hatelist == ent)
return (*iterator); return (*iterator);
}
++iterator; ++iterator;
} }
return nullptr; return nullptr;
} }
void HateList::SetHateAmountOnEnt(Mob* other, uint32 in_hate, uint32 in_damage) void HateList::SetHateAmountOnEnt(Mob* other, uint32 in_hate, uint32 in_dam)
{ {
struct_HateList *hate_list = Find(other); struct_HateList *p = Find(other);
if (hate_list) { if (p)
if (in_damage > 0) { {
hate_list->hatelist_damage = in_damage; if (in_dam > 0)
} p->hatelist_damage = in_dam;
if (in_hate > 0) { if (in_hate > 0)
hate_list->stored_hate_amount = in_hate; p->stored_hate_amount = in_hate;
}
} }
} }
@ -111,25 +113,36 @@ Mob* HateList::GetDamageTopOnHateList(Mob* hater)
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)->entity_on_hatelist && (*iterator)->entity_on_hatelist->IsClient()){
r = entity_list.GetRaidByClient((*iterator)->entity_on_hatelist->CastToClient()); r = entity_list.GetRaidByClient((*iterator)->entity_on_hatelist->CastToClient());
} }
grp = entity_list.GetGroupByMob((*iterator)->entity_on_hatelist); grp = entity_list.GetGroupByMob((*iterator)->entity_on_hatelist);
if ((*iterator)->entity_on_hatelist && r){ if ((*iterator)->entity_on_hatelist && r){
if (r->GetTotalRaidDamage(hater) >= dmg_amt) { if (r->GetTotalRaidDamage(hater) >= dmg_amt)
{
current = (*iterator)->entity_on_hatelist; current = (*iterator)->entity_on_hatelist;
dmg_amt = r->GetTotalRaidDamage(hater); dmg_amt = r->GetTotalRaidDamage(hater);
} }
} else if ((*iterator)->entity_on_hatelist != nullptr && grp != nullptr) { }
if (grp->GetTotalGroupDamage(hater) >= dmg_amt) { else if ((*iterator)->entity_on_hatelist != nullptr && grp != nullptr)
{
if (grp->GetTotalGroupDamage(hater) >= dmg_amt)
{
current = (*iterator)->entity_on_hatelist; current = (*iterator)->entity_on_hatelist;
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)->entity_on_hatelist != nullptr && (uint32)(*iterator)->hatelist_damage >= dmg_amt)
{
current = (*iterator)->entity_on_hatelist; current = (*iterator)->entity_on_hatelist;
dmg_amt = (*iterator)->hatelist_damage; dmg_amt = (*iterator)->hatelist_damage;
} }
@ -138,285 +151,323 @@ Mob* HateList::GetDamageTopOnHateList(Mob* hater)
return current; return current;
} }
Mob* HateList::GetClosestEntOnHateList(Mob *hater) Mob* HateList::GetClosestEntOnHateList(Mob *hater) {
{ Mob* close = nullptr;
Mob* close_entity = nullptr; float closedist = 99999.9f;
float close_distance = 99999.9f; float thisdist;
float this_distance;
auto iterator = list.begin(); auto iterator = list.begin();
while (iterator != list.end()) { while (iterator != list.end()) {
this_distance = (*iterator)->entity_on_hatelist->DistNoRootNoZ(*hater); thisdist = (*iterator)->entity_on_hatelist->DistNoRootNoZ(*hater);
if ((*iterator)->entity_on_hatelist != nullptr && this_distance <= close_distance) { if ((*iterator)->entity_on_hatelist != nullptr && thisdist <= closedist) {
close_distance = this_distance; closedist = thisdist;
close_entity = (*iterator)->entity_on_hatelist; close = (*iterator)->entity_on_hatelist;
} }
++iterator; ++iterator;
} }
if ((!close_entity && hater->IsNPC()) || (close_entity && close_entity->DivineAura())) {
close_entity = hater->CastToNPC()->GetHateTop(); if ((!close && hater->IsNPC()) || (close && close->DivineAura()))
} close = hater->CastToNPC()->GetHateTop();
return close_entity;
return close;
} }
// #include <iostream>
void HateList::AddEntToHateList(Mob *in_entity, uint32 in_hate, int32 in_damage, bool in_is_entity_frenzy, bool iAddIfNotExist) // a few comments added, rearranged code for readability
void HateList::AddEntToHateList(Mob *ent, int32 in_hate, int32 in_dam, bool bFrenzy, bool iAddIfNotExist)
{ {
// std::cout << "AddEntToHateList name: " << owner->GetCleanName() << " in_hate " << in_hate << " in_damage " << in_damage << std::endl; if (!ent)
return;
if (!in_entity) { if (ent->IsCorpse())
return; return;
}
if (in_entity->IsCorpse()) {
return;
}
if (in_entity->IsClient() && in_entity->CastToClient()->IsDead()) {
return;
}
struct_HateList *hate_list = Find(in_entity);
if (hate_list) {
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;
} else if (iAddIfNotExist) {
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::RemoveEntFromHateList(Mob *in_entity) if (ent->IsClient() && ent->CastToClient()->IsDead())
return;
struct_HateList *p = Find(ent);
if (p)
{ {
if (!in_entity) { p->hatelist_damage += (in_dam >= 0) ? in_dam : 0;
p->stored_hate_amount += in_hate;
p->is_entity_frenzy = bFrenzy;
}
else if (iAddIfNotExist) {
p = new struct_HateList;
p->entity_on_hatelist = ent;
p->hatelist_damage = (in_dam >= 0) ? in_dam : 0;
p->stored_hate_amount = in_hate;
p->is_entity_frenzy = bFrenzy;
list.push_back(p);
parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), ent, "1", 0);
if (ent->IsClient()) {
if (owner->CastToNPC()->IsRaidTarget())
ent->CastToClient()->SetEngagedRaidTarget(true);
ent->CastToClient()->IncrementAggroCount();
}
}
}
bool HateList::RemoveEntFromHateList(Mob *ent)
{
if (!ent)
return false; return false;
}
bool found = false; bool found = false;
auto iterator = list.begin(); auto iterator = list.begin();
while (iterator != list.end()) {
if ((*iterator)->entity_on_hatelist == in_entity) { while (iterator != list.end())
if (in_entity) { {
parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), in_entity, "0", 0); if ((*iterator)->entity_on_hatelist == ent)
} {
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 {
++iterator;
} }
else
++iterator;
} }
return found; return found;
} }
void HateList::DoFactionHits(int32 npc_faction_level_id) void HateList::DoFactionHits(int32 nfl_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; {
if ((*iterator)->entity_on_hatelist && (*iterator)->entity_on_hatelist->IsClient()) { Client *p;
client = (*iterator)->entity_on_hatelist->CastToClient();
} else { if ((*iterator)->entity_on_hatelist && (*iterator)->entity_on_hatelist->IsClient())
client = nullptr; p = (*iterator)->entity_on_hatelist->CastToClient();
} else
if (client) { p = nullptr;
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::GetSummonedPetCountOnHateList(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)->entity_on_hatelist != nullptr && (*iterator)->entity_on_hatelist->IsNPC() && ((*iterator)->entity_on_hatelist->CastToNPC()->IsPet() || ((*iterator)->entity_on_hatelist->CastToNPC()->GetSwarmOwner() > 0)))
{
++petcount; ++petcount;
} }
++iterator; ++iterator;
} }
return petcount; return petcount;
} }
Mob *HateList::GetEntWithMostHateInRange(Mob *entity_as_center) Mob *HateList::GetEntWithMostHateInRange(Mob *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* entity_with_most_hate = nullptr; Mob* top = nullptr;
int32 hate_status = -1; int32 hate = -1;
uint32 temp_hate_tracker = 0;
if (entity_as_center == nullptr) { if (center == nullptr)
return nullptr; return nullptr;
}
if (RuleB(Aggro, SmartAggroList)){ if (RuleB(Aggro, SmartAggroList)){
Mob* top_client_type_in_range = nullptr; Mob* topClientTypeInRange = nullptr;
int32 hate_client_type_in_range = -1; int32 hateClientTypeInRange = -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); {
int16 aggro_mod = 0; struct_HateList *cur = (*iterator);
if (!hate_list) { int16 aggroMod = 0;
if (!cur){
++iterator; ++iterator;
continue; continue;
} }
if (!hate_list->entity_on_hatelist) {
if (!cur->entity_on_hatelist){
++iterator; ++iterator;
continue; continue;
} }
if (entity_as_center->IsNPC() && entity_as_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 (center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if (!zone->watermap->InLiquid(cur->entity_on_hatelist->GetX(), cur->entity_on_hatelist->GetY(), cur->entity_on_hatelist->GetZ())) {
skipped_count++; skipped_count++;
++iterator; ++iterator;
continue; continue;
} }
} }
if (hate_list->entity_on_hatelist->Sanctuary()) {
if (hate_status == -1) { if (cur->entity_on_hatelist->Sanctuary()) {
entity_with_most_hate = hate_list->entity_on_hatelist; if (hate == -1)
hate_status = 1; {
top = cur->entity_on_hatelist;
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 (hate_status == -1) { if (cur->entity_on_hatelist->DivineAura() || cur->entity_on_hatelist->IsMezzed() || cur->entity_on_hatelist->IsFeared()){
entity_with_most_hate = hate_list->entity_on_hatelist; if (hate == -1)
hate_status = 0; {
top = cur->entity_on_hatelist;
hate = 0;
} }
++iterator; ++iterator;
continue; continue;
} }
uint32 current_stored_hate = hate_list->stored_hate_amount;
if (hate_list->entity_on_hatelist->IsClient()) { int32 currentHate = cur->stored_hate_amount;
if (hate_list->entity_on_hatelist->CastToClient()->IsSitting()) {
aggro_mod += RuleI(Aggro, SittingAggroMod); if (cur->entity_on_hatelist->IsClient()){
if (cur->entity_on_hatelist->CastToClient()->IsSitting()){
aggroMod += RuleI(Aggro, SittingAggroMod);
} }
if (entity_as_center) {
if (entity_as_center->GetTarget() == hate_list->entity_on_hatelist) { if (center){
aggro_mod += RuleI(Aggro, CurrentTargetAggroMod); if (center->GetTarget() == cur->entity_on_hatelist)
} aggroMod += RuleI(Aggro, CurrentTargetAggroMod);
if (RuleI(Aggro, MeleeRangeAggroMod) != 0) { if (RuleI(Aggro, MeleeRangeAggroMod) != 0)
if (entity_as_center->CombatRange(hate_list->entity_on_hatelist)) { {
aggro_mod += RuleI(Aggro, MeleeRangeAggroMod); if (center->CombatRange(cur->entity_on_hatelist)){
if (current_stored_hate > hate_client_type_in_range || hate_list->is_entity_frenzy) { aggroMod += RuleI(Aggro, MeleeRangeAggroMod);
hate_client_type_in_range = current_stored_hate;
top_client_type_in_range = hate_list->entity_on_hatelist; if (currentHate > hateClientTypeInRange || cur->is_entity_frenzy){
hateClientTypeInRange = currentHate;
topClientTypeInRange = cur->entity_on_hatelist;
} }
} }
} }
} }
} }
else{ else{
if (entity_as_center) { if (center){
if (entity_as_center->GetTarget() == hate_list->entity_on_hatelist) { if (center->GetTarget() == cur->entity_on_hatelist)
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->entity_on_hatelist)){
aggro_mod += RuleI(Aggro, MeleeRangeAggroMod); aggroMod += RuleI(Aggro, MeleeRangeAggroMod);
} }
} }
} }
} }
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 (cur->entity_on_hatelist->GetMaxHP() != 0 && ((cur->entity_on_hatelist->GetHP() * 100 / cur->entity_on_hatelist->GetMaxHP()) < 20)){
aggroMod += RuleI(Aggro, CriticallyWoundedAggroMod);
} }
if (aggro_mod) {
current_stored_hate += (current_stored_hate * aggro_mod / 100); if (aggroMod){
currentHate += (currentHate * aggroMod / 100);
} }
if (current_stored_hate > temp_hate_tracker || hate_list->is_entity_frenzy) {
temp_hate_tracker = current_stored_hate; if (currentHate > hate || cur->is_entity_frenzy){
entity_with_most_hate = hate_list->entity_on_hatelist; hate = currentHate;
top = cur->entity_on_hatelist;
} }
++iterator; ++iterator;
} }
if (top_client_type_in_range != nullptr && entity_with_most_hate != nullptr) {
bool is_top_client_type = entity_with_most_hate->IsClient(); if (topClientTypeInRange != nullptr && top != nullptr) {
bool isTopClientType = top->IsClient();
#ifdef BOTS #ifdef BOTS
if (!is_top_client_type) { if (!isTopClientType) {
if (entity_with_most_hate->IsBot()) { if (top->IsBot()) {
is_top_client_type = true; isTopClientType = true;
top_client_type_in_range = entity_with_most_hate; topClientTypeInRange = top;
} }
} }
#endif //BOTS #endif //BOTS
if (!is_top_client_type) {
if (entity_with_most_hate->IsMerc()) { if (!isTopClientType) {
is_top_client_type = true; if (top->IsMerc()) {
top_client_type_in_range = entity_with_most_hate; isTopClientType = true;
topClientTypeInRange = top;
} }
} }
if (!is_top_client_type) {
if (entity_with_most_hate->GetSpecialAbility(ALLOW_TO_TANK)) { if (!isTopClientType) {
is_top_client_type = true; if (top->GetSpecialAbility(ALLOW_TO_TANK)){
top_client_type_in_range = entity_with_most_hate; isTopClientType = true;
topClientTypeInRange = top;
} }
} }
if (!is_top_client_type) {
return top_client_type_in_range ? top_client_type_in_range : nullptr; if (!isTopClientType)
return topClientTypeInRange ? topClientTypeInRange : nullptr;
return top ? top : nullptr;
} }
return entity_with_most_hate ? entity_with_most_hate : nullptr; else {
} else { 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 entity_with_most_hate ? entity_with_most_hate : nullptr; return top ? top : nullptr;
} }
} }
/* Process not so smart aggro list */
else{ 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); {
if (entity_as_center->IsNPC() && entity_as_center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { struct_HateList *cur = (*iterator);
if (!zone->watermap->InLiquid(hate_list->entity_on_hatelist->GetX(), hate_list->entity_on_hatelist->GetY(), hate_list->entity_on_hatelist->GetZ())) { if (center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if (!zone->watermap->InLiquid(cur->entity_on_hatelist->GetX(), cur->entity_on_hatelist->GetY(), cur->entity_on_hatelist->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 )) {
entity_with_most_hate = hate_list->entity_on_hatelist; if (cur->entity_on_hatelist != nullptr && ((cur->stored_hate_amount > hate) || cur->is_entity_frenzy))
temp_hate_tracker = hate_list->stored_hate_amount; {
top = cur->entity_on_hatelist;
hate = cur->stored_hate_amount;
} }
++iterator; ++iterator;
} }
if (entity_with_most_hate == nullptr && skipped_count > 0) { if (top == nullptr && skipped_count > 0) {
return entity_as_center->GetTarget() ? entity_as_center->GetTarget() : nullptr; return center->GetTarget() ? center->GetTarget() : nullptr;
} }
return entity_with_most_hate ? entity_with_most_hate : nullptr; return top ? top : nullptr;
} }
return nullptr; return nullptr;
} }
Mob *HateList::GetEntWithMostHateOnList() Mob *HateList::GetEntWithMostHateInRange(){
{
Mob* top = nullptr; Mob* top = nullptr;
uint32 hate = 0; int32 hate = -1;
auto iterator = list.begin(); auto iterator = list.begin();
while (iterator != list.end()) { while (iterator != list.end())
{
struct_HateList *cur = (*iterator); struct_HateList *cur = (*iterator);
if (cur->entity_on_hatelist != nullptr && (cur->stored_hate_amount > hate)) { if (cur->entity_on_hatelist != nullptr && (cur->stored_hate_amount > hate))
{
top = cur->entity_on_hatelist; top = cur->entity_on_hatelist;
hate = cur->stored_hate_amount; hate = cur->stored_hate_amount;
} }
@ -429,94 +480,107 @@ Mob *HateList::GetEntWithMostHateOnList()
Mob *HateList::GetRandomEntOnHateList() 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())->entity_on_hatelist;
}
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)->entity_on_hatelist; return (*iterator)->entity_on_hatelist;
} }
uint32 HateList::GetEntHateAmount(Mob *ent, bool damage /*= false*/) int32 HateList::GetEntHateAmount(Mob *ent, bool damage)
{ {
struct_HateList *hate_list; struct_HateList *p;
hate_list = Find(ent);
if ( hate_list && damage) { p = Find(ent);
return hate_list->hatelist_damage;
} else if (hate_list) { if (p && damage)
return hate_list->stored_hate_amount; return p->hatelist_damage;
} else { else if (p)
return p->stored_hate_amount;
else
return 0; return 0;
} }
}
bool HateList::IsHateListEmpty() //looking for any mob with hate > -1
{ bool HateList::IsHateListEmpty() {
return(list.size() == 0); return(list.size() == 0);
} }
// Prints hate list to a client
void HateList::PrintHateListToClient(Client *c) void HateList::PrintHateListToClient(Client *c)
{ {
auto iterator = list.begin(); auto iterator = list.begin();
while (iterator != list.end()) { while (iterator != list.end())
struct_HateList *hate_list = (*iterator); {
struct_HateList *e = (*iterator);
c->Message(0, "- name: %s, damage: %d, hate: %d", 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)", (e->entity_on_hatelist && e->entity_on_hatelist->GetName()) ? e->entity_on_hatelist->GetName() : "(null)",
hate_list->hatelist_damage, hate_list->stored_hate_amount); e->hatelist_damage, e->stored_hate_amount);
++iterator; ++iterator;
} }
} }
int HateList::AreaRampage(Mob *in_caster, Mob *in_target, int in_count, ExtraAttackOptions *options) int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts)
{ {
if (!in_target || !in_caster) { if (!target || !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); struct_HateList *h = (*iterator);
++iterator; ++iterator;
if (h && h->entity_on_hatelist && h->entity_on_hatelist != in_caster) { if (h && h->entity_on_hatelist && h->entity_on_hatelist != caster)
if (in_caster->CombatRange(h->entity_on_hatelist)) { {
if (caster->CombatRange(h->entity_on_hatelist))
{
id_list.push_back(h->entity_on_hatelist->GetID()); id_list.push_back(h->entity_on_hatelist->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) { {
in_caster->Attack(cur, MainPrimary, false, false, false, options); for (int i = 0; i < count; ++i) {
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
@ -526,27 +590,34 @@ 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); struct_HateList *h = (*iterator);
if (range > 0) { if (range > 0)
{
dist_targ = center->DistNoRoot(*h->entity_on_hatelist); dist_targ = center->DistNoRoot(*h->entity_on_hatelist);
if (dist_targ <= range && dist_targ >= min_range2) { if (dist_targ <= range && dist_targ >= min_range2)
{
id_list.push_back(h->entity_on_hatelist->GetID()); id_list.push_back(h->entity_on_hatelist->GetID());
h->entity_on_hatelist->CalcSpellPowerDistanceMod(spell_id, dist_targ); h->entity_on_hatelist->CalcSpellPowerDistanceMod(spell_id, dist_targ);
} }
} else { }
else
{
id_list.push_back(h->entity_on_hatelist->GetID()); id_list.push_back(h->entity_on_hatelist->GetID());
h->entity_on_hatelist->CalcSpellPowerDistanceMod(spell_id, 0, caster); h->entity_on_hatelist->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-2015 EQEMu Development Team (http://eqemu.org) Copyright (C) 2001-2002 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,10 +25,10 @@ class Mob;
class Raid; class Raid;
struct ExtraAttackOptions; struct ExtraAttackOptions;
struct struct_HateList { struct struct_HateList
{
Mob *entity_on_hatelist; Mob *entity_on_hatelist;
uint32 hatelist_damage; int32 hatelist_damage, stored_hate_amount;
uint32 stored_hate_amount;
bool is_entity_frenzy; bool is_entity_frenzy;
}; };
@ -38,41 +38,47 @@ class HateList
HateList(); HateList();
~HateList(); ~HateList();
Mob *GetClosestEntOnHateList(Mob *hater); // adds a mob to the hatelist
Mob *GetDamageTopOnHateList(Mob *hater); void AddEntToHateList(Mob *ent, int32 in_hate = 0, int32 in_dam = 0, bool bFrenzy = false, bool iAddIfNotExist = true);
Mob *GetRandomEntOnHateList(); // sets existing hate
Mob *GetEntWithMostHateInRange(Mob *center); void SetHateAmountOnEnt(Mob *other, uint32 in_hate, uint32 in_dam);
Mob* GetEntWithMostHateOnList(); // removes mobs from hatelist
bool IsEntOnHateList(Mob *mob);
bool IsHateListEmpty();
bool RemoveEntFromHateList(Mob *ent); bool RemoveEntFromHateList(Mob *ent);
// Remove all
int AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts); void WipeHateList();
// ???
void DoFactionHits(int32 nfl_id);
// Gets Hate amount for mob
int32 GetEntHateAmount(Mob *ent, bool damage = false);
// gets top hated mob
Mob *GetEntWithMostHateInRange(Mob *center);
// gets any on the list
Mob *GetRandomEntOnHateList();
// get closest mob or nullptr if list empty
Mob *GetClosestEntOnHateList(Mob *hater);
// gets top mob or nullptr if hate list empty
Mob *GetDamageTopOnHateList(Mob *hater);
// used to check if mob is on hatelist
bool IsEntOnHateList(Mob *);
// used to remove or add frenzy hate
void IsEntityInFrenzyMode();
//Gets the target with the most hate regardless of things like frenzy etc.
Mob* GetEntWithMostHateInRange();
// Count 'Summoned' pets on hatelist
int GetSummonedPetCountOnHateList(Mob *hater); int GetSummonedPetCountOnHateList(Mob *hater);
uint32 GetEntHateAmount(Mob *in_entity, bool damage = false); int AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts);
void AddEntToHateList(Mob *in_entity, uint32 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 IsHateListEmpty();
void PrintHateListToClient(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<struct_HateList*>& GetHateList() std::list<struct_HateList*>& GetHateList() { return list; }
{
return list;
}
/* Setting owner*/ //setting owner
void SetOwner(Mob *new_owner) void SetOwner(Mob *newOwner) { owner = newOwner; }
{
owner = new_owner;
}
protected: protected:
struct_HateList* Find(Mob *ent); struct_HateList* Find(Mob *ent);

View File

@ -463,7 +463,7 @@ public:
Mob* GetHateTop() { return hate_list.GetEntWithMostHateInRange(this);} Mob* GetHateTop() { return hate_list.GetEntWithMostHateInRange(this);}
Mob* GetHateDamageTop(Mob* other) { return hate_list.GetDamageTopOnHateList(other);} Mob* GetHateDamageTop(Mob* other) { return hate_list.GetDamageTopOnHateList(other);}
Mob* GetHateRandom() { return hate_list.GetRandomEntOnHateList();} Mob* GetHateRandom() { return hate_list.GetRandomEntOnHateList();}
Mob* GetHateMost() { return hate_list.GetEntWithMostHateOnList();} Mob* GetHateMost() { return hate_list.GetEntWithMostHateInRange();}
bool IsEngaged() { return(!hate_list.IsHateListEmpty()); } bool IsEngaged() { return(!hate_list.IsHateListEmpty()); }
bool HateSummon(); bool HateSummon();
void FaceTarget(Mob* MobToFace = 0); void FaceTarget(Mob* MobToFace = 0);