Code QA/Refactoring in hate_list

This commit is contained in:
Drajor 2014-06-10 20:21:41 +10:00
parent 2937bdcee5
commit aeb13b285f
14 changed files with 293 additions and 298 deletions

View File

@ -491,7 +491,7 @@ void Mob::AI_Start(uint32 iMoveDelay) {
pAggroRange = 70;
if (GetAssistRange() == 0)
pAssistRange = 70;
hate_list.Wipe();
hate_list.clear();
delta_heading = 0;
delta_x = 0;
@ -548,7 +548,7 @@ void Mob::AI_Stop() {
safe_delete(AItarget_check_timer)
safe_delete(AIscanarea_timer);
safe_delete(AIfeignremember_timer);
hate_list.Wipe();
hate_list.clear();
}
void NPC::AI_Stop() {
@ -784,12 +784,12 @@ void Client::AI_Process()
if (engaged)
{
if (IsRooted())
SetTarget(hate_list.GetClosest(this));
SetTarget(hate_list.getClosest(this));
else
{
if(AItarget_check_timer->Check())
{
SetTarget(hate_list.GetTop(this));
SetTarget(hate_list.getHighestHate(this));
}
}
@ -1057,18 +1057,18 @@ void Mob::AI_Process() {
if (engaged)
{
if (IsRooted())
SetTarget(hate_list.GetClosest(this));
SetTarget(hate_list.getClosest(this));
else
{
if(AItarget_check_timer->Check())
{
if (IsFocused()) {
if (!target) {
SetTarget(hate_list.GetTop(this));
SetTarget(hate_list.getHighestHate(this));
}
} else {
if (!ImprovedTaunt())
SetTarget(hate_list.GetTop(this));
SetTarget(hate_list.getHighestHate(this));
}
}
@ -1334,7 +1334,7 @@ void Mob::AI_Process() {
//underwater stuff only works with water maps in the zone!
if(IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if(!zone->watermap->InLiquid(target->GetX(), target->GetY(), target->GetZ())) {
Mob *tar = hate_list.GetTop(this);
Mob *tar = hate_list.getHighestHate(this);
if(tar == target) {
WipeHateList();
Heal();

View File

@ -1553,7 +1553,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
}
entity_list.RemoveFromTargets(this);
hate_list.RemoveEnt(this);
hate_list.clear(this);
RemoveAutoXTargets();
@ -2142,12 +2142,12 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
if (killerMob) {
if(GetClass() != LDON_TREASURE)
hate_list.Add(killerMob, damage);
hate_list.add(killerMob, damage);
}
safe_delete(app);
Mob *give_exp = hate_list.GetDamageTop(this);
Mob *give_exp = hate_list.getHighestDamage(this);
if(give_exp == nullptr)
give_exp = killer;
@ -2526,7 +2526,7 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
&& other && (buffs[spellbonuses.ImprovedTaunt[2]].casterid != other->GetID()))
hate = (hate*spellbonuses.ImprovedTaunt[1])/100;
hate_list.Add(other, hate, damage, bFrenzy, !iBuffTic);
hate_list.add(other, hate, damage, bFrenzy, !iBuffTic);
if(other->IsClient())
other->CastToClient()->AddAutoXTarget(this);
@ -2537,8 +2537,8 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
AddFeignMemory(other->CastToMerc()->GetMercOwner()->CastToClient());
}
else {
if(!hate_list.IsOnHateList(other->CastToMerc()->GetMercOwner()))
hate_list.Add(other->CastToMerc()->GetMercOwner(), 0, 0, false, true);
if(!hate_list.isHated(other->CastToMerc()->GetMercOwner()))
hate_list.add(other->CastToMerc()->GetMercOwner(), 0, 0, false, true);
}
} //MERC
@ -2553,7 +2553,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
if(!owner->GetSpecialAbility(IMMUNE_AGGRO))
{
hate_list.Add(owner, 0, 0, false, !iBuffTic);
hate_list.add(owner, 0, 0, false, !iBuffTic);
if(owner->IsClient())
owner->CastToClient()->AddAutoXTarget(this);
}
@ -2562,10 +2562,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->IsFamiliar() && !mypet->GetSpecialAbility(IMMUNE_AGGRO))
mypet->hate_list.Add(other, 0, 0, bFrenzy);
mypet->hate_list.add(other, 0, 0, bFrenzy);
} else if (myowner) { // I am a pet, add other to owner if it's NPC/LD
if (myowner->IsAIControlled() && !myowner->GetSpecialAbility(IMMUNE_AGGRO))
myowner->hate_list.Add(other, 0, 0, bFrenzy);
myowner->hate_list.add(other, 0, 0, bFrenzy);
}
if (!wasengaged) {
if(IsNPC() && other->IsClient() && other->CastToClient())

View File

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

View File

@ -31,122 +31,112 @@
extern Zone *zone;
HateList::HateList()
HateList::HateList() : mOwner(nullptr) { }
HateList::~HateList() { }
void HateList::clear()
{
owner = nullptr;
}
HateList::~HateList()
{
}
void HateList::Wipe()
{
auto iterator = list.begin();
while(iterator != list.end())
auto i = mEntries.begin();
while(i != mEntries.end())
{
Mob* m = (*iterator)->ent;
Mob* m = (*i)->mMOB;
if(m)
{
parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), m, "0", 0);
parse->EventNPC(EVENT_HATE_LIST, mOwner->CastToNPC(), m, "0", 0);
if(m->IsClient())
m->CastToClient()->DecrementAggroCount();
}
delete (*iterator);
iterator = list.erase(iterator);
delete (*i);
i = mEntries.erase(i);
}
}
bool HateList::IsOnHateList(Mob *mob)
bool HateList::isHated(Mob* pMOB)
{
if(Find(mob))
return true;
return false;
return find(pMOB) != nullptr;
}
tHateEntry *HateList::Find(Mob *ent)
HateEntry* HateList::find(Mob* pMOB)
{
auto iterator = list.begin();
while(iterator != list.end())
{
if((*iterator)->ent == ent)
return (*iterator);
++iterator;
}
for (auto i = mEntries.begin(); i != mEntries.end(); i++)
if ((*i)->mMOB == pMOB) return *i;
return nullptr;
}
void HateList::Set(Mob* other, uint32 in_hate, uint32 in_dam)
void HateList::set(Mob* pMob, uint32 pHate, uint32 pDamage)
{
tHateEntry *p = Find(other);
if(p)
HateEntry *entry = find(pMob);
if (entry)
{
if(in_dam > 0)
p->damage = in_dam;
if(in_hate > 0)
p->hate = in_hate;
if(pDamage > 0)
entry->mDamage = pDamage;
if(pHate > 0)
entry->mHate = pHate;
}
}
Mob* HateList::GetDamageTop(Mob* hater)
Mob* HateList::getHighestDamage(Mob* hater)
{
/*
This is called in NPC::Death
It calls this on it's own HateList, passing itself as the hater parameter.
-- Under the circumstances where there were 40 people in a raid it would calculate the total raid damage 80 times.
*/
Mob* current = nullptr;
Group* grp = nullptr;
Raid* r = nullptr;
uint32 dmg_amt = 0;
auto iterator = list.begin();
while(iterator != list.end())
auto iterator = mEntries.begin();
while(iterator != mEntries.end())
{
grp = nullptr;
r = nullptr;
if((*iterator)->ent && (*iterator)->ent->IsClient()){
r = entity_list.GetRaidByClient((*iterator)->ent->CastToClient());
if((*iterator)->mMOB && (*iterator)->mMOB->IsClient()){
r = entity_list.GetRaidByClient((*iterator)->mMOB->CastToClient());
}
grp = entity_list.GetGroupByMob((*iterator)->ent);
grp = entity_list.GetGroupByMob((*iterator)->mMOB);
if((*iterator)->ent && r){
if((*iterator)->mMOB && r){
if(r->GetTotalRaidDamage(hater) >= dmg_amt)
{
current = (*iterator)->ent;
current = (*iterator)->mMOB;
dmg_amt = r->GetTotalRaidDamage(hater);
}
}
else if ((*iterator)->ent != nullptr && grp != nullptr)
else if ((*iterator)->mMOB != nullptr && grp != nullptr)
{
if (grp->GetTotalGroupDamage(hater) >= dmg_amt)
{
current = (*iterator)->ent;
current = (*iterator)->mMOB;
dmg_amt = grp->GetTotalGroupDamage(hater);
}
}
else if ((*iterator)->ent != nullptr && (uint32)(*iterator)->damage >= dmg_amt)
else if ((*iterator)->mMOB != nullptr && (uint32)(*iterator)->mDamage >= dmg_amt)
{
current = (*iterator)->ent;
dmg_amt = (*iterator)->damage;
current = (*iterator)->mMOB;
dmg_amt = (*iterator)->mDamage;
}
++iterator;
}
return current;
}
Mob* HateList::GetClosest(Mob *hater) {
Mob* HateList::getClosest(Mob *hater) {
Mob* close = nullptr;
float closedist = 99999.9f;
float thisdist;
auto iterator = list.begin();
while(iterator != list.end()) {
thisdist = (*iterator)->ent->DistNoRootNoZ(*hater);
if((*iterator)->ent != nullptr && thisdist <= closedist) {
auto iterator = mEntries.begin();
while(iterator != mEntries.end()) {
thisdist = (*iterator)->mMOB->DistNoRootNoZ(*hater);
if((*iterator)->mMOB != nullptr && thisdist <= closedist) {
closedist = thisdist;
close = (*iterator)->ent;
close = (*iterator)->mMOB;
}
++iterator;
}
@ -157,78 +147,65 @@ Mob* HateList::GetClosest(Mob *hater) {
return close;
}
void HateList::Add(Mob *ent, int32 in_hate, int32 in_dam, bool bFrenzy, bool iAddIfNotExist)
void HateList::add(Mob* pMOB, int32 pHate, int32 pDamage, bool pFrenzy, bool iAddIfNotExist)
{
if(!ent)
return;
if (!pMOB) return;
if(ent->IsCorpse())
return;
// Do not add corpses to HateList.
if (pMOB->IsCorpse()) return;
if(ent->IsClient() && ent->CastToClient()->IsDead())
return;
// Do not add dead dead players to HateList.
if (pMOB->IsClient() && pMOB->CastToClient()->IsDead()) return;
tHateEntry *p = Find(ent);
if (p)
// Where pMOB is already on the HateList, increase Hate/Damage values.
HateEntry *entry = find(pMOB);
if (entry)
{
p->damage+=(in_dam>=0)?in_dam:0;
p->hate+=in_hate;
p->bFrenzy = bFrenzy;
entry->mDamage += (pDamage >= 0) ? pDamage : 0;
entry->mHate += pHate;
entry->mFrenzy = pFrenzy;
}
// Where pMOB is not on the HateList, add it.
else if (iAddIfNotExist) {
p = new tHateEntry;
p->ent = ent;
p->damage = (in_dam>=0)?in_dam:0;
p->hate = in_hate;
p->bFrenzy = bFrenzy;
list.push_back(p);
parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), ent, "1", 0);
entry = new HateEntry(pMOB, (pDamage >= 0) ? pDamage : 0, pHate, pFrenzy);
mEntries.push_back(entry);
parse->EventNPC(EVENT_HATE_LIST, mOwner->CastToNPC(), pMOB, "1", 0);
if(ent->IsClient())
ent->CastToClient()->IncrementAggroCount();
// Where pMOB is client, update 'Aggro Count'.
if (pMOB->IsClient())
pMOB->CastToClient()->IncrementAggroCount();
}
}
bool HateList::RemoveEnt(Mob *ent)
bool HateList::clear(Mob* pMOB)
{
if (!ent)
return false;
if (!pMOB) return false;
bool found = false;
auto iterator = list.begin();
while(iterator != list.end())
{
if((*iterator)->ent == ent)
{
if(ent)
parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), ent, "0", 0);
found = true;
if(ent && ent->IsClient())
ent->CastToClient()->DecrementAggroCount();
delete (*iterator);
iterator = list.erase(iterator);
for (auto i = mEntries.begin(); i != mEntries.end(); i++) {
if ((*i)->mMOB == pMOB) {
parse->EventNPC(EVENT_HATE_LIST, mOwner->CastToNPC(), pMOB, "0", 0);
pMOB->CastToClient()->DecrementAggroCount();
// Clean up.
delete *i;
mEntries.erase(i);
return true;
}
else
++iterator;
}
return found;
return false;
}
void HateList::DoFactionHits(int32 nfl_id) {
if (nfl_id <= 0)
return;
auto iterator = list.begin();
while(iterator != list.end())
auto iterator = mEntries.begin();
while(iterator != mEntries.end())
{
Client *p;
if ((*iterator)->ent && (*iterator)->ent->IsClient())
p = (*iterator)->ent->CastToClient();
if ((*iterator)->mMOB && (*iterator)->mMOB->IsClient())
p = (*iterator)->mMOB->CastToClient();
else
p = nullptr;
@ -238,26 +215,18 @@ void HateList::DoFactionHits(int32 nfl_id) {
}
}
int HateList::SummonedPetCount(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;
auto iterator = list.begin();
while(iterator != list.end()) {
if((*iterator)->ent != nullptr && (*iterator)->ent->IsNPC() && ((*iterator)->ent->CastToNPC()->IsPet() || ((*iterator)->ent->CastToNPC()->GetSwarmOwner() > 0)))
{
++petcount;
}
++iterator;
int HateList::getSummonedPetCount() {
int count = 0;
for (auto i = mEntries.begin(); i != mEntries.end(); i++) {
Mob* entryMOB = (*i)->mMOB;
if (entryMOB && entryMOB->IsNPC() && (entryMOB->CastToNPC()->IsPet() || (entryMOB->CastToNPC()->GetSwarmOwner() > 0)))
count++;
}
return petcount;
return count;
}
Mob *HateList::GetTop(Mob *center)
Mob *HateList::getHighestHate(Mob *center)
{
Mob* top = nullptr;
int32 hate = -1;
@ -270,10 +239,10 @@ Mob *HateList::GetTop(Mob *center)
int32 hateClientTypeInRange = -1;
int skipped_count = 0;
auto iterator = list.begin();
while(iterator != list.end())
auto iterator = mEntries.begin();
while(iterator != mEntries.end())
{
tHateEntry *cur = (*iterator);
HateEntry *cur = (*iterator);
int16 aggroMod = 0;
if(!cur){
@ -281,48 +250,48 @@ Mob *HateList::GetTop(Mob *center)
continue;
}
if(!cur->ent){
if(!cur->mMOB){
++iterator;
continue;
}
if(center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if(!zone->watermap->InLiquid(cur->ent->GetX(), cur->ent->GetY(), cur->ent->GetZ())) {
if(!zone->watermap->InLiquid(cur->mMOB->GetX(), cur->mMOB->GetY(), cur->mMOB->GetZ())) {
skipped_count++;
++iterator;
continue;
}
}
if(cur->ent->DivineAura() || cur->ent->IsMezzed() || cur->ent->IsFeared()){
if(cur->mMOB->DivineAura() || cur->mMOB->IsMezzed() || cur->mMOB->IsFeared()){
if(hate == -1)
{
top = cur->ent;
top = cur->mMOB;
hate = 0;
}
++iterator;
continue;
}
int32 currentHate = cur->hate;
int32 currentHate = cur->mHate;
if(cur->ent->IsClient()){
if(cur->mMOB->IsClient()){
if(cur->ent->CastToClient()->IsSitting()){
if(cur->mMOB->CastToClient()->IsSitting()){
aggroMod += RuleI(Aggro, SittingAggroMod);
}
if(center){
if(center->GetTarget() == cur->ent)
if(center->GetTarget() == cur->mMOB)
aggroMod += RuleI(Aggro, CurrentTargetAggroMod);
if(RuleI(Aggro, MeleeRangeAggroMod) != 0)
{
if(center->CombatRange(cur->ent)){
if(center->CombatRange(cur->mMOB)){
aggroMod += RuleI(Aggro, MeleeRangeAggroMod);
if(currentHate > hateClientTypeInRange || cur->bFrenzy){
if(currentHate > hateClientTypeInRange || cur->mFrenzy){
hateClientTypeInRange = currentHate;
topClientTypeInRange = cur->ent;
topClientTypeInRange = cur->mMOB;
}
}
}
@ -331,18 +300,18 @@ Mob *HateList::GetTop(Mob *center)
}
else{
if(center){
if(center->GetTarget() == cur->ent)
if(center->GetTarget() == cur->mMOB)
aggroMod += RuleI(Aggro, CurrentTargetAggroMod);
if(RuleI(Aggro, MeleeRangeAggroMod) != 0)
{
if(center->CombatRange(cur->ent)){
if(center->CombatRange(cur->mMOB)){
aggroMod += RuleI(Aggro, MeleeRangeAggroMod);
}
}
}
}
if(cur->ent->GetMaxHP() != 0 && ((cur->ent->GetHP()*100/cur->ent->GetMaxHP()) < 20)){
if(cur->mMOB->GetMaxHP() != 0 && ((cur->mMOB->GetHP()*100/cur->mMOB->GetMaxHP()) < 20)){
aggroMod += RuleI(Aggro, CriticallyWoundedAggroMod);
}
@ -350,9 +319,9 @@ Mob *HateList::GetTop(Mob *center)
currentHate += (currentHate * aggroMod / 100);
}
if(currentHate > hate || cur->bFrenzy){
if(currentHate > hate || cur->mFrenzy){
hate = currentHate;
top = cur->ent;
top = cur->mMOB;
}
++iterator;
@ -381,23 +350,23 @@ Mob *HateList::GetTop(Mob *center)
}
}
else{
auto iterator = list.begin();
auto iterator = mEntries.begin();
int skipped_count = 0;
while(iterator != list.end())
while(iterator != mEntries.end())
{
tHateEntry *cur = (*iterator);
HateEntry *cur = (*iterator);
if(center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if(!zone->watermap->InLiquid(cur->ent->GetX(), cur->ent->GetY(), cur->ent->GetZ())) {
if(!zone->watermap->InLiquid(cur->mMOB->GetX(), cur->mMOB->GetY(), cur->mMOB->GetZ())) {
skipped_count++;
++iterator;
continue;
}
}
if(cur->ent != nullptr && ((cur->hate > hate) || cur->bFrenzy ))
if(cur->mMOB != nullptr && ((cur->mHate > hate) || cur->mFrenzy ))
{
top = cur->ent;
hate = cur->hate;
top = cur->mMOB;
hate = cur->mHate;
}
++iterator;
}
@ -409,18 +378,18 @@ Mob *HateList::GetTop(Mob *center)
return nullptr;
}
Mob *HateList::GetMostHate(){
Mob *HateList::getMostHate(){
Mob* top = nullptr;
int32 hate = -1;
auto iterator = list.begin();
while(iterator != list.end())
auto iterator = mEntries.begin();
while(iterator != mEntries.end())
{
tHateEntry *cur = (*iterator);
if(cur->ent != nullptr && (cur->hate > hate))
HateEntry *cur = (*iterator);
if(cur->mMOB != nullptr && (cur->mHate > hate))
{
top = cur->ent;
hate = cur->hate;
top = cur->mMOB;
hate = cur->mHate;
}
++iterator;
}
@ -428,57 +397,62 @@ Mob *HateList::GetMostHate(){
}
Mob *HateList::GetRandom()
Mob *HateList::getRandom()
{
int count = list.size();
int count = mEntries.size();
if(count == 0) //If we don't have any entries it'll crash getting a random 0, -1 position.
return NULL;
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...
return (*list.begin())->ent;
if(*mEntries.begin()) // Just in case tHateEntry is invalidated somehow...
return (*mEntries.begin())->mMOB;
return NULL;
}
auto iterator = list.begin();
auto iterator = mEntries.begin();
int random = MakeRandomInt(0, count - 1);
for (int i = 0; i < random; i++)
++iterator;
return (*iterator)->ent;
return (*iterator)->mMOB;
}
int32 HateList::GetEntHate(Mob *ent, bool damage)
int32 HateList::getHate(Mob* pMOB, bool pDamage)
{
tHateEntry *p;
HateEntry* entry = find(pMOB);
if (entry) {
if (pDamage) return entry->mDamage;
return entry->mHate;
}
p = Find(ent);
if ( p && damage)
return p->damage;
else if (p)
return p->hate;
else
return 0;
return 0;
}
//looking for any mob with hate > -1
bool HateList::IsEmpty() {
return(list.size() == 0);
int32 HateList::getDamage(Mob* pMOB)
{
HateEntry* entry = find(pMOB);
if (entry) return entry->mDamage;
return 0;
}
bool HateList::isEmpty() {
return mEntries.size() == 0;
}
// Prints hate list to a client
void HateList::PrintToClient(Client *c)
{
auto iterator = list.begin();
while (iterator != list.end())
auto iterator = mEntries.begin();
while (iterator != mEntries.end())
{
tHateEntry *e = (*iterator);
HateEntry *e = (*iterator);
c->Message(0, "- name: %s, damage: %d, hate: %d",
(e->ent && e->ent->GetName()) ? e->ent->GetName() : "(null)",
e->damage, e->hate);
(e->mMOB && e->mMOB->GetName()) ? e->mMOB->GetName() : "(null)",
e->mDamage, e->mHate);
++iterator;
}
@ -491,16 +465,16 @@ int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOption
int ret = 0;
std::list<uint32> id_list;
auto iterator = list.begin();
while (iterator != list.end())
auto iterator = mEntries.begin();
while (iterator != mEntries.end())
{
tHateEntry *h = (*iterator);
HateEntry *h = (*iterator);
++iterator;
if(h && h->ent && h->ent != caster)
if(h && h->mMOB && h->mMOB != caster)
{
if(caster->CombatRange(h->ent))
if(caster->CombatRange(h->mMOB))
{
id_list.push_back(h->ent->GetID());
id_list.push_back(h->mMOB->GetID());
++ret;
}
}
@ -535,20 +509,20 @@ void HateList::SpellCast(Mob *caster, uint32 spell_id, float range)
//So keep a list of entity ids and look up after
std::list<uint32> id_list;
range = range * range;
auto iterator = list.begin();
while (iterator != list.end())
auto iterator = mEntries.begin();
while (iterator != mEntries.end())
{
tHateEntry *h = (*iterator);
HateEntry *h = (*iterator);
if(range > 0)
{
if(caster->DistNoRoot(*h->ent) <= range)
if(caster->DistNoRoot(*h->mMOB) <= range)
{
id_list.push_back(h->ent->GetID());
id_list.push_back(h->mMOB->GetID());
}
}
else
{
id_list.push_back(h->ent->GetID());
id_list.push_back(h->mMOB->GetID());
}
++iterator;
}

View File

@ -19,11 +19,16 @@
#ifndef HATELIST_H
#define HATELIST_H
struct tHateEntry
class Mob;
// TODO: Later fix pre-declarations. There is some crazy shit going on with include order in other files obviously.
struct HateEntry
{
Mob *ent;
int32 damage, hate;
bool bFrenzy;
HateEntry(Mob* pMOB, int32 pDamage, int32 pHate, bool pFrenzy) : mMOB(pMOB), mDamage(pDamage), mHate(pHate), mFrenzy(pFrenzy) {}
Mob *mMOB;
int32 mDamage;
int32 mHate;
bool mFrenzy;
};
class HateList
@ -32,52 +37,68 @@ public:
HateList();
~HateList();
// adds a mob to the hatelist
void Add(Mob *ent, int32 in_hate=0, int32 in_dam=0, bool bFrenzy = false, bool iAddIfNotExist = true);
// sets existing hate
void Set(Mob *other, uint32 in_hate, uint32 in_dam);
// removes mobs from hatelist
bool RemoveEnt(Mob *ent);
// Remove all
void Wipe();
// ???
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 *);
// Set the owner of the HateList.
void setOwner(Mob* pOwner) { mOwner = pOwner; }
// Returns whether the HateList is empty.
bool isEmpty();
// Returns the number of pets on the HateList.
int getSummonedPetCount();
// Removes a specific MOB from the HateList.
bool clear(Mob* pMOB);
// Removes all MOBs from the HateList.
void clear();
// Adds a MOB to the HateList.
// TODO: Look more into parameter 'iAddIfNotExist' .. I can't think of circumstances where this would be needed.
void add(Mob* pMOB, int32 pHate = 0, int32 pDamage = 0, bool pFrenzy = false, bool iAddIfNotExist = true);
// Sets a MOBs hate.
void set(Mob* pMOB, uint32 pHate, uint32 pDamage);
// Returns the hate value of a specific MOB. (Or Damage for fun under some circumstances...)
// TODO: Remove the 'damage' parameter and use getDamage where appropriate.
int32 getHate(Mob * pMOB, bool damage = false);
// Returns the damage value of a specific MOB.
int32 getDamage(Mob* pMOB);
// Returns the MOB with the highest hate value or null if none.
Mob *getHighestHate(Mob* pCenter);
// Returns the MOB with the highest damage value or null if none.
Mob *getHighestDamage(Mob* pHater);
// Returns a random MOB on the HateList.
Mob* getRandom();
// Returns the closest MOB.
Mob* getClosest(Mob* pHater);
// Returns whether the specific MOB is on the HateList.
bool isHated(Mob * pMOB);
//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);
void SpellCast(Mob *caster, uint32 spell_id, float range);
bool IsEmpty();
void PrintToClient(Client *c);
Mob* getMostHate();
//For accessing the hate list via perl; don't use for anything else
std::list<tHateEntry*>& GetHateList() { return list; }
std::list<HateEntry*>& GetHateList() { return mEntries; }
//setting owner
void SetOwner(Mob *newOwner) { owner = newOwner; }
protected:
tHateEntry* Find(Mob *ent);
// TODO: Remove, this functionality does not belong here.
void DoFactionHits(int32 nfl_id);
// TODO: Remove, this functionality does not belong here.
int AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts);
// TODO: Remove, this functionality does not belong here.
void SpellCast(Mob *caster, uint32 spell_id, float range);
// TODO: Remove, this functionality does not belong here.
void PrintToClient(Client *c);
private:
std::list<tHateEntry*> list;
Mob *owner;
HateEntry* find(Mob* pMOB);
std::list<HateEntry*> mEntries;
Mob* mOwner;
};
#endif

View File

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

View File

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

View File

@ -1498,7 +1498,7 @@ void Merc::AI_Process() {
rest_timer.Disable();
if(IsRooted())
SetTarget(hate_list.GetClosest(this));
SetTarget(hate_list.getClosest(this));
else
FindTarget();
@ -2552,11 +2552,11 @@ void Merc::CheckHateList() {
Mob* groupMember = g->members[counter];
if(groupMember) {
if(npc->IsOnHatelist(groupMember)) {
if(!hate_list.IsOnHateList(npc)) {
if(!hate_list.isHated(npc)) {
float range = g->HasRole(groupMember, RolePuller) ? RuleI(Mercs, AggroRadiusPuller) : RuleI(Mercs, AggroRadius);
range *= range;
if(npc->DistNoRootNoZ(*this) < range) {
hate_list.Add(npc, 1);
hate_list.add(npc, 1);
}
}
}
@ -4751,7 +4751,7 @@ bool Merc::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attac
Save();
Mob *give_exp = hate_list.GetDamageTop(this);
Mob *give_exp = hate_list.getHighestDamage(this);
Client *give_exp_client = nullptr;
if(give_exp && give_exp->IsClient())

View File

@ -375,7 +375,7 @@ Mob::Mob(const char* in_name,
PathingRouteUpdateTimerLong = new Timer(RuleI(Pathing, RouteUpdateFrequencyLong));
DistractedFromGrid = false;
PathingTraversedNodes = 0;
hate_list.SetOwner(this);
hate_list.setOwner(this);
m_AllowBeneficial = false;
m_DisableMelee = false;
@ -2443,8 +2443,8 @@ bool Mob::RemoveFromHateList(Mob* mob)
bool bFound = false;
if(IsEngaged())
{
bFound = hate_list.RemoveEnt(mob);
if(hate_list.IsEmpty())
bFound = hate_list.clear(mob);
if(hate_list.isEmpty())
{
AI_Event_NoLongerEngaged();
zone->DelAggroMob();
@ -2452,7 +2452,7 @@ bool Mob::RemoveFromHateList(Mob* mob)
}
if(GetTarget() == mob)
{
SetTarget(hate_list.GetTop(this));
SetTarget(hate_list.getHighestHate(this));
}
return bFound;
@ -2462,12 +2462,12 @@ void Mob::WipeHateList()
{
if(IsEngaged())
{
hate_list.Wipe();
hate_list.clear();
AI_Event_NoLongerEngaged();
}
else
{
hate_list.Wipe();
hate_list.clear();
}
}
@ -3283,7 +3283,7 @@ void Mob::TryTriggerOnValueAmount(bool IsHP, bool IsMana, bool IsEndur, bool IsP
}
else if (IsPet){
int count = hate_list.SummonedPetCount(this);
int count = hate_list.getSummonedPetCount();
if ((base2 >= 220 && base2 <= 250) && count >= (base2 - 220)){
use_spell = true;
}

View File

@ -427,16 +427,16 @@ public:
virtual void AddToHateList(Mob* other, int32 hate = 0, int32 damage = 0, bool iYellForHelp = true,
bool bFrenzy = false, bool iBuffTic = false);
bool RemoveFromHateList(Mob* mob);
void SetHate(Mob* other, int32 hate = 0, int32 damage = 0) { hate_list.Set(other,hate,damage);}
void SetHate(Mob* other, int32 hate = 0, int32 damage = 0) { hate_list.set(other,hate,damage);}
void HalveAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHate(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)); }
uint32 GetHateAmount(Mob* tmob, bool is_dam = false) { return hate_list.GetEntHate(tmob,is_dam);}
uint32 GetDamageAmount(Mob* tmob) { return hate_list.GetEntHate(tmob, true);}
Mob* GetHateTop() { return hate_list.GetTop(this);}
Mob* GetHateDamageTop(Mob* other) { return hate_list.GetDamageTop(other);}
Mob* GetHateRandom() { return hate_list.GetRandom();}
Mob* GetHateMost() { return hate_list.GetMostHate();}
bool IsEngaged() { return(!hate_list.IsEmpty()); }
uint32 GetHateAmount(Mob* tmob, bool is_dam = false) { return hate_list.getHate(tmob,is_dam);}
uint32 GetDamageAmount(Mob* tmob) { return hate_list.getHate(tmob, true);}
Mob* GetHateTop() { return hate_list.getHighestHate(this);}
Mob* GetHateDamageTop(Mob* other) { return hate_list.getHighestDamage(other);}
Mob* GetHateRandom() { return hate_list.getRandom();}
Mob* GetHateMost() { return hate_list.getMostHate();}
bool IsEngaged() { return(!hate_list.isEmpty()); }
bool HateSummon();
void FaceTarget(Mob* MobToFace = 0);
void SetHeading(float iHeading) { if(heading != iHeading) { pLastChange = Timer::GetCurrentTime();
@ -446,7 +446,7 @@ public:
void RemoveFromFeignMemory(Client* attacker);
void ClearFeignMemory();
void PrintHateListToClient(Client *who) { hate_list.PrintToClient(who); }
std::list<tHateEntry*>& GetHateList() { return hate_list.GetHateList(); }
std::list<HateEntry*>& GetHateList() { return hate_list.GetHateList(); }
bool CheckLosFN(Mob* other);
bool CheckLosFN(float posX, float posY, float posZ, float mobSize);
inline void SetChanged() { pLastChange = Timer::GetCurrentTime(); }
@ -748,7 +748,7 @@ public:
void ProcessFlee();
void CheckFlee();
inline bool CheckAggro(Mob* other) {return hate_list.IsOnHateList(other);}
inline bool CheckAggro(Mob* other) {return hate_list.isHated(other);}
float CalculateHeadingToTarget(float in_x, float in_y);
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);

View File

@ -234,8 +234,8 @@ public:
inline int32 GetNPCFactionID() const { return npc_faction_id; }
inline int32 GetPrimaryFaction() const { return primary_faction; }
int32 GetNPCHate(Mob* in_ent) {return hate_list.GetEntHate(in_ent);}
bool IsOnHatelist(Mob*p) { return hate_list.IsOnHateList(p);}
int32 GetNPCHate(Mob* in_ent) {return hate_list.getHate(in_ent);}
bool IsOnHatelist(Mob*p) { return hate_list.isHated(p);}
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)
Perl_croak(aTHX_ "Usage: HateEntry::GetData(THIS)");
{
tHateEntry * THIS;
HateEntry * THIS;
Mob * RETVAL;
if (sv_derived_from(ST(0), "HateEntry")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(tHateEntry *,tmp);
THIS = INT2PTR(HateEntry *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type tHateEntry");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->ent;
RETVAL = THIS->mMOB;
ST(0) = sv_newmortal();
sv_setref_pv(ST(0), "Mob", (void*)RETVAL);
}
@ -66,20 +66,20 @@ XS(XS_HateEntry_GetHate)
if (items != 1)
Perl_croak(aTHX_ "Usage: HateEntry::GetHate(THIS)");
{
tHateEntry * THIS;
HateEntry * THIS;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "HateEntry")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(tHateEntry *,tmp);
THIS = INT2PTR(HateEntry *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type tHateEntry");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->hate;
RETVAL = THIS->mHate;
XSprePUSH; PUSHi((IV)RETVAL);
}
XSRETURN(1);
@ -92,20 +92,20 @@ XS(XS_HateEntry_GetDamage)
if (items != 1)
Perl_croak(aTHX_ "Usage: HateEntry::GetDamage(THIS)");
{
tHateEntry * THIS;
HateEntry * THIS;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "HateEntry")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(tHateEntry *,tmp);
THIS = INT2PTR(HateEntry *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type tHateEntry");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->damage;
RETVAL = THIS->mDamage;
XSprePUSH; PUSHi((IV)RETVAL);
}
XSRETURN(1);

View File

@ -6581,7 +6581,7 @@ XS(XS_Mob_GetHateList)
while(iter != hate_list.end())
{
tHateEntry *entry = (*iter);
HateEntry *entry = (*iter);
ST(0) = sv_newmortal();
sv_setref_pv(ST(0), "HateEntry", (void*)entry);
XPUSHs(ST(0));

View File

@ -6006,7 +6006,7 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama
//Limit to amount of pets
if (value >= 221 && value <= 249){
int count = hate_list.SummonedPetCount(this);
int count = hate_list.getSummonedPetCount();
for (int base2_value = 221; base2_value <= 249; ++base2_value){
if (value == base2_value){