Merge branch 'master' of https://github.com/EQEmu/Server into item_link

Conflicts:
	changelog.txt
This commit is contained in:
Uleat 2014-12-28 11:57:51 -05:00
commit 4fb1a3ff3f
29 changed files with 440 additions and 442 deletions

View File

@ -1,5 +1,13 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50)
-------------------------------------------------------
== 12/27/2014 ==
Akkadius: Add option to automatic database upgrade script 5) Download latest Opcodes from Github
Trevius: (RoF2) Fixed dropping items on the ground so they go to ground level instead of camera height.
Trevius: Show Helm Option should be functional again.
Kayen: Implemened npc special ability (43) CASTING_RESIST_DIFF which sets innate resist modifier on
ALL spells used by that NPC. Ie. 43,1,-200 will set a -200 innate resist diff, so if your npc cast
a spell that has a -10 resist modifier the final resist diff would be -210.
== 12/25/2014 ==
Uleat: Updated 'links' code for all clients

View File

@ -1994,17 +1994,17 @@ namespace RoF2
outapp->WriteUInt32(emu->drakkin_tattoo);
outapp->WriteUInt32(emu->drakkin_details);
outapp->WriteUInt8(0); // Unknown
outapp->WriteUInt8(0); // Unknown
outapp->WriteUInt8(0); // Unknown
outapp->WriteUInt8(0); // Unknown
outapp->WriteUInt8(0); // Unknown
outapp->WriteUInt8(0); // Unknown 0
outapp->WriteUInt8(0xff); // Unknown 0xff
outapp->WriteUInt8(1); // Unknown 1
outapp->WriteUInt8(0xff); // Unknown 0xff
outapp->WriteUInt8(1); // Unknown 1
outapp->WriteFloat(5.0f); // Height ?
outapp->WriteFloat(5.0f); // Height
outapp->WriteFloat(3.0f); // Unknown
outapp->WriteFloat(2.5f); // Unknown
outapp->WriteFloat(5.5f); // Unknown
outapp->WriteFloat(3.0f); // Unknown 3.0
outapp->WriteFloat(2.5f); // Unknown 2.5
outapp->WriteFloat(5.5f); // Unknown 5.5
outapp->WriteUInt32(0); // Primary ?
outapp->WriteUInt32(0); // Secondary ?
@ -2330,7 +2330,7 @@ namespace RoF2
outapp->WriteUInt64(emu->exp); // int32 in client
outapp->WriteUInt8(0); // Unknown - Seen 5 on Live
outapp->WriteUInt8(5); // Unknown - Seen 5 on Live - Eye Height?
outapp->WriteUInt32(emu->platinum_bank);
outapp->WriteUInt32(emu->gold_bank);

View File

@ -155,6 +155,7 @@ sub ShowMenuPrompt {
2 => \&database_dump_compress,
3 => \&Run_Database_Check,
4 => \&AA_Fetch,
5 => \&OpCodes_Fetch,
0 => \&Exit,
);
@ -204,6 +205,7 @@ Database Management Menu (Please Select):
Ideal to perform before performing updates
3) $option[3]
4) AAs - Get Latest AA's from PEQ (This deletes AA's already in the database)
5) OPCodes - Download latest opcodes from repository
0) Exit
EO_MENU
@ -305,6 +307,36 @@ sub AA_Fetch{
print "\nDone...\n\n";
}
#::: Fetch Latest Opcodes
sub OpCodes_Fetch{
print "Pulling down latest opcodes...\n";
%opcodes = (
1 => ["opcodes", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/opcodes.conf"],
2 => ["mail_opcodes", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/mail_opcodes.conf"],
3 => ["Titanium", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_Titanium.conf"],
4 => ["Secrets of Faydwer", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_SoF.conf"],
5 => ["Seeds of Destruction", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_SoD.conf"],
6 => ["Underfoot", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_Underfoot.conf"],
7 => ["Rain of Fear", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF.conf"],
8 => ["Rain of Fear 2", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF2.conf"],
);
$loop = 1;
while($opcodes{$loop}[0]){
#::: Split the URL by the patches folder to get the file name from URL
@real_file = split("patches/", $opcodes{$loop}[1]);
$find = 0;
while($real_file[$find]){
$file_name = $real_file[$find];
$find++;
}
print "\nDownloading (" . $opcodes{$loop}[0] . ") File: '" . $file_name . "'...\n\n";
GetRemoteFile($opcodes{$loop}[1], $file_name);
$loop++;
}
print "\nDone...\n\n";
}
#::: Responsible for Database Upgrade Routines
sub Run_Database_Check{
#::: Run 2 - Running pending updates...

View File

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

View File

@ -1518,7 +1518,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
}
entity_list.RemoveFromTargets(this);
hate_list.RemoveEnt(this);
hate_list.RemoveEntFromHateList(this);
RemoveAutoXTargets();
//remove ourself from all proximities
@ -2076,12 +2076,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.AddEntToHateList(killerMob, damage);
}
safe_delete(app);
Mob *give_exp = hate_list.GetDamageTop(this);
Mob *give_exp = hate_list.GetDamageTopOnHateList(this);
if(give_exp == nullptr)
give_exp = killer;
@ -2400,7 +2400,8 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
return true;
}
void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic) {
void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, bool iYellForHelp /*= true*/, bool bFrenzy /*= false*/, bool iBuffTic /*= false*/)
{
assert(other != nullptr);
@ -2413,7 +2414,7 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
bool wasengaged = IsEngaged();
Mob* owner = other->GetOwner();
Mob* mypet = this->GetPet();
Mob* mypet = this->GetPet();
Mob* myowner = this->GetOwner();
Mob* targetmob = this->GetTarget();
@ -2488,7 +2489,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.AddEntToHateList(other, hate, damage, bFrenzy, !iBuffTic);
if(other->IsClient())
other->CastToClient()->AddAutoXTarget(this);
@ -2500,8 +2501,8 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
AddFeignMemory(other->CastToBot()->GetBotOwner()->CastToClient());
}
else {
if(!hate_list.IsOnHateList(other->CastToBot()->GetBotOwner()))
hate_list.Add(other->CastToBot()->GetBotOwner(), 0, 0, false, true);
if(!hate_list.IsEntOnHateList(other->CastToBot()->GetBotOwner()))
hate_list.AddEntToHateList(other->CastToBot()->GetBotOwner(), 0, 0, false, true);
}
}
#endif //BOTS
@ -2512,8 +2513,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.IsEntOnHateList(other->CastToMerc()->GetMercOwner()))
hate_list.AddEntToHateList(other->CastToMerc()->GetMercOwner(), 0, 0, false, true);
}
} //MERC
@ -2528,7 +2529,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.AddEntToHateList(owner, 0, 0, false, !iBuffTic);
if(owner->IsClient())
owner->CastToClient()->AddAutoXTarget(this);
}
@ -2537,10 +2538,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.AddEntToHateList(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.AddEntToHateList(other, 0, 0, bFrenzy);
}
if (other->GetTempPetCount())

View File

@ -3422,9 +3422,9 @@ void Bot::AI_Process() {
rest_timer.Disable();
if(IsRooted())
SetTarget(hate_list.GetClosest(this));
SetTarget(hate_list.GetClosestEntOnHateList(this));
else
SetTarget(hate_list.GetTop(this));
SetTarget(hate_list.GetEntWithMostHateOnList(this));
if(!GetTarget())
return;
@ -3791,9 +3791,9 @@ void Bot::PetAIProcess() {
if (IsEngaged()) {
if (botPet->IsRooted())
botPet->SetTarget(hate_list.GetClosest(botPet));
botPet->SetTarget(hate_list.GetClosestEntOnHateList(botPet));
else
botPet->SetTarget(hate_list.GetTop(botPet));
botPet->SetTarget(hate_list.GetEntWithMostHateOnList(botPet));
// Let's check if we have a los with our target.
// 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();
Mob *give_exp = hate_list.GetDamageTop(this);
Mob *give_exp = hate_list.GetDamageTopOnHateList(this);
Client *give_exp_client = nullptr;
if(give_exp && give_exp->IsClient())
@ -6008,7 +6008,7 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillUseTypes attack_
}
}
void Bot::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic)
void Bot::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, bool iYellForHelp /*= true*/, bool bFrenzy /*= false*/, bool iBuffTic /*= false*/)
{
Mob::AddToHateList(other, hate, damage, iYellForHelp, bFrenzy, iBuffTic);
}

View File

@ -208,7 +208,7 @@ public:
bool DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, uint16 slot, bool &stopLogic);
void SendBotArcheryWearChange(uint8 material_slot, uint32 material, uint32 color);
void Camp(bool databaseSave = true);
virtual void AddToHateList(Mob* other, int32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false);
virtual void AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false);
virtual void SetTarget(Mob* mob);
virtual void Zone();
std::vector<AISpells_Struct> GetBotSpells() { return AIspells; }

View File

@ -1817,45 +1817,8 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
}
ns->spawn.size = 0; // Changing size works, but then movement stops! (wth?)
ns->spawn.runspeed = (gmspeed == 0) ? runspeed : 3.125f;
if (!m_pp.showhelm) ns->spawn.showhelm = 0;
ns->spawn.showhelm = m_pp.showhelm ? 1 : 0;
/*
// Equipment/Weapons already set from Mob::FillSpawnStruct
// Commenting this out for now
const Item_Struct* item = nullptr;
const ItemInst* inst = nullptr;
int16 invslot;
for (uint32 matslot = 0; matslot < _MaterialCount; matslot++)
{
// Only Player Races Wear Armor
if (IsPlayerRace(race) || matslot > 6)
{
invslot = Inventory::CalcSlotFromMaterial(matslot);
if (invslot == INVALID_INDEX)
continue;
if ((inst = m_inv[invslot]) && inst->IsType(ItemClassCommon))
{
item = inst->GetItem();
if (matslot > 6)
{
// Weapon Models
ns->spawn.equipment[matslot].material = GetEquipmentMaterial(matslot);
}
else
{
// Armor Materials/Models
ns->spawn.equipment[matslot].material = item->Material;
ns->spawn.equipment[matslot].elitematerial = item->EliteMaterial;
ns->spawn.equipment[matslot].heroforgemodel = GetHerosForgeModel(matslot);
ns->spawn.colors[matslot].color = m_pp.item_tint[matslot].rgb.use_tint ? m_pp.item_tint[matslot].color : item->Color;
}
}
}
}
*/
}
bool Client::GMHideMe(Client* client) {

View File

@ -5227,7 +5227,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.RemoveEntFromHateList(this->CastToMob());
Disconnect();
return;

View File

@ -8655,8 +8655,8 @@ void command_aggrozone(Client *c, const Seperator *sep) {
if (!m)
return;
int hate = atoi(sep->arg[1]); //should default to 0 if we don't enter anything
entity_list.AggroZone(m,hate);
uint32 hate = atoi(sep->arg[1]); //should default to 0 if we don't enter anything
entity_list.AggroZone(m, hate);
c->Message(0, "Train to you! Last chance to go invulnerable...");
}

View File

@ -135,7 +135,8 @@ enum {
NPC_CHASE_DISTANCE = 40,
ALLOW_TO_TANK = 41,
IGNORE_ROOT_AGGRO_RULES = 42,
MAX_SPECIAL_ATTACK = 43
CASTING_RESIST_DIFF = 43,
MAX_SPECIAL_ATTACK = 44
};
typedef enum { //fear states

View File

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

View File

@ -355,7 +355,7 @@ public:
void ClearAggro(Mob* targ);
void ClearFeignAggro(Mob* targ);
void ClearZoneFeignAggro(Client* targ);
void AggroZone(Mob* who, int hate = 0);
void AggroZone(Mob* who, uint32 hate = 0);
bool Fighting(Mob* targ);
void RemoveFromHateLists(Mob* mob, bool settoone = false);

View File

@ -1,19 +1,19 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2002 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
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
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
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "client.h"
@ -36,7 +36,7 @@ extern Zone *zone;
HateList::HateList()
{
owner = nullptr;
hate_owner = nullptr;
}
HateList::~HateList()
@ -45,29 +45,29 @@ HateList::~HateList()
// added for frenzy support
// checks if target still is in frenzy mode
void HateList::CheckFrenzyHate()
void HateList::IsEntityInFrenzyMode()
{
auto iterator = list.begin();
while(iterator != list.end())
while (iterator != list.end())
{
if ((*iterator)->ent->GetHPRatio() >= 20)
(*iterator)->bFrenzy = false;
if ((*iterator)->entity_on_hatelist->GetHPRatio() >= 20)
(*iterator)->is_entity_frenzy = false;
++iterator;
}
}
void HateList::Wipe()
void HateList::WipeHateList()
{
auto iterator = list.begin();
while(iterator != list.end())
while (iterator != list.end())
{
Mob* m = (*iterator)->ent;
if(m)
Mob* m = (*iterator)->entity_on_hatelist;
if (m)
{
parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), m, "0", 0);
parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), m, "0", 0);
if(m->IsClient())
if (m->IsClient())
m->CastToClient()->DecrementAggroCount();
}
delete (*iterator);
@ -76,38 +76,38 @@ void HateList::Wipe()
}
}
bool HateList::IsOnHateList(Mob *mob)
bool HateList::IsEntOnHateList(Mob *mob)
{
if(Find(mob))
if (Find(mob))
return true;
return false;
}
tHateEntry *HateList::Find(Mob *ent)
struct_HateList *HateList::Find(Mob *in_entity)
{
auto iterator = list.begin();
while(iterator != list.end())
while (iterator != list.end())
{
if((*iterator)->ent == ent)
if ((*iterator)->entity_on_hatelist == in_entity)
return (*iterator);
++iterator;
}
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);
if(p)
struct_HateList *entity = Find(other);
if (entity)
{
if(in_dam > 0)
p->damage = in_dam;
if(in_hate > 0)
p->hate = in_hate;
if (in_damage > 0)
entity->hatelist_damage = in_damage;
if (in_hate > 0)
entity->stored_hate_amount = in_hate;
}
}
Mob* HateList::GetDamageTop(Mob* hater)
Mob* HateList::GetDamageTopOnHateList(Mob* hater)
{
Mob* current = nullptr;
Group* grp = nullptr;
@ -115,119 +115,117 @@ Mob* HateList::GetDamageTop(Mob* hater)
uint32 dmg_amt = 0;
auto iterator = list.begin();
while(iterator != list.end())
while (iterator != list.end())
{
grp = nullptr;
r = nullptr;
if((*iterator)->ent && (*iterator)->ent->IsClient()){
r = entity_list.GetRaidByClient((*iterator)->ent->CastToClient());
if ((*iterator)->entity_on_hatelist && (*iterator)->entity_on_hatelist->IsClient()){
r = entity_list.GetRaidByClient((*iterator)->entity_on_hatelist->CastToClient());
}
grp = entity_list.GetGroupByMob((*iterator)->ent);
grp = entity_list.GetGroupByMob((*iterator)->entity_on_hatelist);
if((*iterator)->ent && r){
if(r->GetTotalRaidDamage(hater) >= dmg_amt)
if ((*iterator)->entity_on_hatelist && r){
if (r->GetTotalRaidDamage(hater) >= dmg_amt)
{
current = (*iterator)->ent;
current = (*iterator)->entity_on_hatelist;
dmg_amt = r->GetTotalRaidDamage(hater);
}
}
else if ((*iterator)->ent != nullptr && grp != nullptr)
else if ((*iterator)->entity_on_hatelist != nullptr && grp != nullptr)
{
if (grp->GetTotalGroupDamage(hater) >= dmg_amt)
{
current = (*iterator)->ent;
current = (*iterator)->entity_on_hatelist;
dmg_amt = grp->GetTotalGroupDamage(hater);
}
}
else if ((*iterator)->ent != nullptr && (uint32)(*iterator)->damage >= dmg_amt)
else if ((*iterator)->entity_on_hatelist != nullptr && (uint32)(*iterator)->hatelist_damage >= dmg_amt)
{
current = (*iterator)->ent;
dmg_amt = (*iterator)->damage;
current = (*iterator)->entity_on_hatelist;
dmg_amt = (*iterator)->hatelist_damage;
}
++iterator;
}
return current;
}
Mob* HateList::GetClosest(Mob *hater) {
Mob* close = nullptr;
float closedist = 99999.9f;
float thisdist;
Mob* HateList::GetClosestEntOnHateList(Mob *hater) {
Mob* close_entity = nullptr;
float close_distance = 99999.9f;
float this_distance;
auto iterator = list.begin();
while(iterator != list.end()) {
thisdist = (*iterator)->ent->DistNoRootNoZ(*hater);
if((*iterator)->ent != nullptr && thisdist <= closedist) {
closedist = thisdist;
close = (*iterator)->ent;
while (iterator != list.end()) {
this_distance = (*iterator)->entity_on_hatelist->DistNoRootNoZ(*hater);
if ((*iterator)->entity_on_hatelist != nullptr && this_distance <= close_distance) {
close_distance = this_distance;
close_entity = (*iterator)->entity_on_hatelist;
}
++iterator;
}
if ((!close && hater->IsNPC()) || (close && close->DivineAura()))
close = hater->CastToNPC()->GetHateTop();
if ((!close_entity && hater->IsNPC()) || (close_entity && close_entity->DivineAura()))
close_entity = hater->CastToNPC()->GetHateTop();
return close;
return close_entity;
}
// a few comments added, rearranged code for readability
void HateList::Add(Mob *ent, int32 in_hate, int32 in_dam, bool bFrenzy, bool iAddIfNotExist)
void HateList::AddEntToHateList(Mob *in_entity, int32 in_hate, int32 in_damage, bool in_is_entity_frenzied, bool iAddIfNotExist)
{
if(!ent)
if (!in_entity)
return;
if(ent->IsCorpse())
if (in_entity->IsCorpse())
return;
if(ent->IsClient() && ent->CastToClient()->IsDead())
if (in_entity->IsClient() && in_entity->CastToClient()->IsDead())
return;
tHateEntry *p = Find(ent);
if (p)
struct_HateList *entity = Find(in_entity);
if (entity)
{
p->damage+=(in_dam>=0)?in_dam:0;
p->hate+=in_hate;
p->bFrenzy = bFrenzy;
entity->hatelist_damage += (in_damage >= 0) ? in_damage : 0;
entity->stored_hate_amount += in_hate;
entity->is_entity_frenzy = in_is_entity_frenzied;
}
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);
entity = new struct_HateList;
entity->entity_on_hatelist = in_entity;
entity->hatelist_damage = (in_damage >= 0) ? in_damage : 0;
entity->stored_hate_amount = in_hate;
entity->is_entity_frenzy = in_is_entity_frenzied;
list.push_back(entity);
parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), in_entity, "1", 0);
if (ent->IsClient()) {
if (owner->CastToNPC()->IsRaidTarget())
ent->CastToClient()->SetEngagedRaidTarget(true);
ent->CastToClient()->IncrementAggroCount();
if (in_entity->IsClient()) {
if (hate_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;
bool found = false;
bool is_found = false;
auto iterator = list.begin();
while(iterator != list.end())
while (iterator != list.end())
{
if((*iterator)->ent == ent)
if ((*iterator)->entity_on_hatelist == in_entity)
{
if(ent)
parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), ent, "0", 0);
found = true;
if (in_entity)
parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), in_entity, "0", 0);
is_found = true;
if(ent && ent->IsClient())
ent->CastToClient()->DecrementAggroCount();
if (in_entity && in_entity->IsClient())
in_entity->CastToClient()->DecrementAggroCount();
delete (*iterator);
iterator = list.erase(iterator);
@ -236,127 +234,127 @@ bool HateList::RemoveEnt(Mob *ent)
else
++iterator;
}
return found;
return is_found;
}
void HateList::DoFactionHits(int32 nfl_id) {
if (nfl_id <= 0)
void HateList::DoFactionHits(int32 npc_faction_level_id) {
if (npc_faction_level_id <= 0)
return;
auto iterator = list.begin();
while(iterator != list.end())
while (iterator != list.end())
{
Client *p;
Client *client;
if ((*iterator)->ent && (*iterator)->ent->IsClient())
p = (*iterator)->ent->CastToClient();
if ((*iterator)->entity_on_hatelist && (*iterator)->entity_on_hatelist->IsClient())
client = (*iterator)->entity_on_hatelist->CastToClient();
else
p = nullptr;
client = nullptr;
if (p)
p->SetFactionLevel(p->CharacterID(), nfl_id, p->GetBaseClass(), p->GetBaseRace(), p->GetDeity());
if (client)
client->SetFactionLevel(client->CharacterID(), npc_faction_level_id, client->GetBaseClass(), client->GetBaseRace(), client->GetDeity());
++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 pet_count = 0;
auto iterator = list.begin();
while(iterator != list.end()) {
while (iterator != list.end()) {
if((*iterator)->ent != nullptr && (*iterator)->ent->IsNPC() && ((*iterator)->ent->CastToNPC()->IsPet() || ((*iterator)->ent->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;
++pet_count;
}
++iterator;
}
return petcount;
return pet_count;
}
Mob *HateList::GetTop(Mob *center)
Mob *HateList::GetEntWithMostHateOnList(Mob *center)
{
// hack fix for zone shutdown crashes on some servers
if (!zone->IsLoaded())
return nullptr;
Mob* top = nullptr;
Mob* top_hate = nullptr;
int32 hate = -1;
if(center == nullptr)
if (center == nullptr)
return nullptr;
if (RuleB(Aggro,SmartAggroList)){
Mob* topClientTypeInRange = nullptr;
int32 hateClientTypeInRange = -1;
if (RuleB(Aggro, SmartAggroList)){
Mob* top_client_type_in_range = nullptr;
int32 hate_client_type_in_range = -1;
int skipped_count = 0;
auto iterator = list.begin();
while(iterator != list.end())
while (iterator != list.end())
{
tHateEntry *cur = (*iterator);
int16 aggroMod = 0;
struct_HateList *cur = (*iterator);
int16 aggro_mod = 0;
if(!cur){
if (!cur){
++iterator;
continue;
}
if(!cur->ent){
if (!cur->entity_on_hatelist){
++iterator;
continue;
}
if(center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if(!zone->watermap->InLiquid(cur->ent->GetX(), cur->ent->GetY(), cur->ent->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++;
++iterator;
continue;
}
}
if (cur->ent->Sanctuary()) {
if(hate == -1)
if (cur->entity_on_hatelist->Sanctuary()) {
if (hate == -1)
{
top = cur->ent;
top_hate = cur->entity_on_hatelist;
hate = 1;
}
++iterator;
continue;
}
if(cur->ent->DivineAura() || cur->ent->IsMezzed() || cur->ent->IsFeared()){
if(hate == -1)
if (cur->entity_on_hatelist->DivineAura() || cur->entity_on_hatelist->IsMezzed() || cur->entity_on_hatelist->IsFeared()){
if (hate == -1)
{
top = cur->ent;
top_hate = cur->entity_on_hatelist;
hate = 0;
}
++iterator;
continue;
}
int32 currentHate = cur->hate;
int32 current_hate = cur->stored_hate_amount;
if(cur->ent->IsClient()){
if (cur->entity_on_hatelist->IsClient()){
if(cur->ent->CastToClient()->IsSitting()){
aggroMod += RuleI(Aggro, SittingAggroMod);
if (cur->entity_on_hatelist->CastToClient()->IsSitting()){
aggro_mod += RuleI(Aggro, SittingAggroMod);
}
if(center){
if(center->GetTarget() == cur->ent)
aggroMod += RuleI(Aggro, CurrentTargetAggroMod);
if(RuleI(Aggro, MeleeRangeAggroMod) != 0)
if (center){
if (center->GetTarget() == cur->entity_on_hatelist)
aggro_mod += RuleI(Aggro, CurrentTargetAggroMod);
if (RuleI(Aggro, MeleeRangeAggroMod) != 0)
{
if(center->CombatRange(cur->ent)){
aggroMod += RuleI(Aggro, MeleeRangeAggroMod);
if (center->CombatRange(cur->entity_on_hatelist)){
aggro_mod += RuleI(Aggro, MeleeRangeAggroMod);
if(currentHate > hateClientTypeInRange || cur->bFrenzy){
hateClientTypeInRange = currentHate;
topClientTypeInRange = cur->ent;
if (current_hate > hate_client_type_in_range || cur->is_entity_frenzy){
hate_client_type_in_range = current_hate;
top_client_type_in_range = cur->entity_on_hatelist;
}
}
}
@ -364,112 +362,112 @@ Mob *HateList::GetTop(Mob *center)
}
else{
if(center){
if(center->GetTarget() == cur->ent)
aggroMod += RuleI(Aggro, CurrentTargetAggroMod);
if(RuleI(Aggro, MeleeRangeAggroMod) != 0)
if (center){
if (center->GetTarget() == cur->entity_on_hatelist)
aggro_mod += RuleI(Aggro, CurrentTargetAggroMod);
if (RuleI(Aggro, MeleeRangeAggroMod) != 0)
{
if(center->CombatRange(cur->ent)){
aggroMod += RuleI(Aggro, MeleeRangeAggroMod);
if (center->CombatRange(cur->entity_on_hatelist)){
aggro_mod += RuleI(Aggro, MeleeRangeAggroMod);
}
}
}
}
if(cur->ent->GetMaxHP() != 0 && ((cur->ent->GetHP()*100/cur->ent->GetMaxHP()) < 20)){
aggroMod += RuleI(Aggro, CriticallyWoundedAggroMod);
if (cur->entity_on_hatelist->GetMaxHP() != 0 && ((cur->entity_on_hatelist->GetHP() * 100 / cur->entity_on_hatelist->GetMaxHP()) < 20)){
aggro_mod += RuleI(Aggro, CriticallyWoundedAggroMod);
}
if(aggroMod){
currentHate += (currentHate * aggroMod / 100);
if (aggro_mod){
current_hate += (current_hate * aggro_mod / 100);
}
if(currentHate > hate || cur->bFrenzy){
hate = currentHate;
top = cur->ent;
if (current_hate > hate || cur->is_entity_frenzy){
hate = current_hate;
top_hate = cur->entity_on_hatelist;
}
++iterator;
}
if(topClientTypeInRange != nullptr && top != nullptr) {
bool isTopClientType = top->IsClient();
if (top_client_type_in_range != nullptr && top_hate != nullptr) {
bool isTopClientType = top_hate->IsClient();
#ifdef BOTS
if(!isTopClientType) {
if(top->IsBot()) {
if (!isTopClientType) {
if (top_hate->IsBot()) {
isTopClientType = true;
topClientTypeInRange = top;
top_client_type_in_range = top_hate;
}
}
#endif //BOTS
if(!isTopClientType) {
if(top->IsMerc()) {
if (!isTopClientType) {
if (top_hate->IsMerc()) {
isTopClientType = true;
topClientTypeInRange = top;
top_client_type_in_range = top_hate;
}
}
if (!isTopClientType) {
if (top->GetSpecialAbility(ALLOW_TO_TANK)){
if (top_hate->GetSpecialAbility(ALLOW_TO_TANK)){
isTopClientType = true;
topClientTypeInRange = top;
top_client_type_in_range = top_hate;
}
}
if(!isTopClientType)
return topClientTypeInRange ? topClientTypeInRange : nullptr;
if (!isTopClientType)
return top_client_type_in_range ? top_client_type_in_range : nullptr;
return top ? top : nullptr;
return top_hate ? top_hate : nullptr;
}
else {
if(top == nullptr && skipped_count > 0) {
if (top_hate == nullptr && skipped_count > 0) {
return center->GetTarget() ? center->GetTarget() : nullptr;
}
return top ? top : nullptr;
return top_hate ? top_hate : nullptr;
}
}
else{
auto iterator = list.begin();
int skipped_count = 0;
while(iterator != list.end())
while (iterator != list.end())
{
tHateEntry *cur = (*iterator);
if(center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if(!zone->watermap->InLiquid(cur->ent->GetX(), cur->ent->GetY(), cur->ent->GetZ())) {
struct_HateList *cur = (*iterator);
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++;
++iterator;
continue;
}
}
if(cur->ent != nullptr && ((cur->hate > hate) || cur->bFrenzy ))
if (cur->entity_on_hatelist != nullptr && ((cur->stored_hate_amount > hate) || cur->is_entity_frenzy))
{
top = cur->ent;
hate = cur->hate;
top_hate = cur->entity_on_hatelist;
hate = cur->stored_hate_amount;
}
++iterator;
}
if(top == nullptr && skipped_count > 0) {
if (top_hate == nullptr && skipped_count > 0) {
return center->GetTarget() ? center->GetTarget() : nullptr;
}
return top ? top : nullptr;
return top_hate ? top_hate : nullptr;
}
return nullptr;
}
Mob *HateList::GetMostHate(){
Mob *HateList::GetEntWithMostHateOnList(){
Mob* top = nullptr;
int32 hate = -1;
auto iterator = list.begin();
while(iterator != list.end())
while (iterator != list.end())
{
tHateEntry *cur = (*iterator);
if(cur->ent != nullptr && (cur->hate > hate))
struct_HateList *cur = (*iterator);
if (cur->entity_on_hatelist != nullptr && (cur->stored_hate_amount > hate))
{
top = cur->ent;
hate = cur->hate;
top = cur->entity_on_hatelist;
hate = cur->stored_hate_amount;
}
++iterator;
}
@ -477,16 +475,16 @@ Mob *HateList::GetMostHate(){
}
Mob *HateList::GetRandom()
Mob *HateList::GetRandomEntOnHateList()
{
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;
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...
return (*list.begin())->ent;
if (*list.begin()) // Just in case tHateEntry is invalidated somehow...
return (*list.begin())->entity_on_hatelist;
return NULL;
}
@ -496,38 +494,36 @@ Mob *HateList::GetRandom()
for (int i = 0; i < random; i++)
++iterator;
return (*iterator)->ent;
return (*iterator)->entity_on_hatelist;
}
int32 HateList::GetEntHate(Mob *ent, bool damage)
int32 HateList::GetEntHateAmount(Mob *in_entity, bool damage)
{
tHateEntry *p;
struct_HateList *entity;
p = Find(ent);
entity = Find(in_entity);
if ( p && damage)
return p->damage;
else if (p)
return p->hate;
if (entity && damage)
return entity->hatelist_damage;
else if (entity)
return entity->stored_hate_amount;
else
return 0;
}
//looking for any mob with hate > -1
bool HateList::IsEmpty() {
bool HateList::IsHateListEmpty() {
return(list.size() == 0);
}
// Prints hate list to a client
void HateList::PrintToClient(Client *c)
void HateList::PrintHateListToClient(Client *c)
{
auto iterator = list.begin();
while (iterator != list.end())
{
tHateEntry *e = (*iterator);
struct_HateList *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->entity_on_hatelist && e->entity_on_hatelist->GetName()) ? e->entity_on_hatelist->GetName() : "(null)",
e->hatelist_damage, e->stored_hate_amount);
++iterator;
}
@ -535,7 +531,7 @@ void HateList::PrintToClient(Client *c)
int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts)
{
if(!target || !caster)
if (!target || !caster)
return 0;
int ret = 0;
@ -543,25 +539,25 @@ int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOption
auto iterator = list.begin();
while (iterator != list.end())
{
tHateEntry *h = (*iterator);
struct_HateList *h = (*iterator);
++iterator;
if(h && h->ent && h->ent != caster)
if (h && h->entity_on_hatelist && h->entity_on_hatelist != caster)
{
if(caster->CombatRange(h->ent))
if (caster->CombatRange(h->entity_on_hatelist))
{
id_list.push_back(h->ent->GetID());
id_list.push_back(h->entity_on_hatelist->GetID());
++ret;
}
}
}
std::list<uint32>::iterator iter = id_list.begin();
while(iter != id_list.end())
while (iter != id_list.end())
{
Mob *cur = entity_list.GetMobID((*iter));
if(cur)
if (cur)
{
for(int i = 0; i < count; ++i) {
for (int i = 0; i < count; ++i) {
caster->Attack(cur, MainPrimary, false, false, false, opts);
}
}
@ -573,7 +569,7 @@ int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOption
void HateList::SpellCast(Mob *caster, uint32 spell_id, float range, Mob* ae_center)
{
if(!caster)
if (!caster)
return;
Mob* center = caster;
@ -592,33 +588,32 @@ void HateList::SpellCast(Mob *caster, uint32 spell_id, float range, Mob* ae_cent
auto iterator = list.begin();
while (iterator != list.end())
{
tHateEntry *h = (*iterator);
if(range > 0)
struct_HateList *h = (*iterator);
if (range > 0)
{
dist_targ = center->DistNoRoot(*h->ent);
if(dist_targ <= range && dist_targ >= min_range2)
dist_targ = center->DistNoRoot(*h->entity_on_hatelist);
if (dist_targ <= range && dist_targ >= min_range2)
{
id_list.push_back(h->ent->GetID());
h->ent->CalcSpellPowerDistanceMod(spell_id, dist_targ);
id_list.push_back(h->entity_on_hatelist->GetID());
h->entity_on_hatelist->CalcSpellPowerDistanceMod(spell_id, dist_targ);
}
}
else
{
id_list.push_back(h->ent->GetID());
h->ent->CalcSpellPowerDistanceMod(spell_id, 0, caster);
id_list.push_back(h->entity_on_hatelist->GetID());
h->entity_on_hatelist->CalcSpellPowerDistanceMod(spell_id, 0, caster);
}
++iterator;
}
std::list<uint32>::iterator iter = id_list.begin();
while(iter != id_list.end())
while (iter != id_list.end())
{
Mob *cur = entity_list.GetMobID((*iter));
if(cur)
if (cur)
{
caster->SpellOnTarget(spell_id, cur);
}
iter++;
}
}

View File

@ -1,19 +1,19 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2002 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
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
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
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef HATELIST_H
@ -25,11 +25,12 @@ class Mob;
class Raid;
struct ExtraAttackOptions;
struct tHateEntry
struct struct_HateList
{
Mob *ent;
int32 damage, hate;
bool bFrenzy;
Mob *entity_on_hatelist;
int32 hatelist_damage;
uint32 stored_hate_amount;
bool is_entity_frenzy;
};
class HateList
@ -38,53 +39,38 @@ 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 *);
// 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);
Mob *GetClosestEntOnHateList(Mob *hater);
Mob *GetDamageTopOnHateList(Mob *hater);
Mob *GetEntWithMostHateOnList(Mob *center);
Mob *GetRandomEntOnHateList();
Mob* GetEntWithMostHateOnList();
bool IsEntOnHateList(Mob *mob);
bool IsHateListEmpty();
bool RemoveEntFromHateList(Mob *ent);
int AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts);
int GetSummonedPetCountOnHateList(Mob *hater);
void SpellCast(Mob *caster, uint32 spell_id, float range, Mob *ae_center = nullptr);
int32 GetEntHateAmount(Mob *ent, bool in_damage = false);
bool IsEmpty();
void PrintToClient(Client *c);
std::list<struct_HateList*>& GetHateList() { return list; }
//For accessing the hate list via perl; don't use for anything else
std::list<tHateEntry*>& GetHateList() { return list; }
void AddEntToHateList(Mob *ent, 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_damage);
void SetHateOwner(Mob *new_hate_owner) { hate_owner = new_hate_owner; }
void SpellCast(Mob *caster, uint32 spell_id, float range, Mob *ae_center = nullptr);
void WipeHateList();
//setting owner
void SetOwner(Mob *newOwner) { owner = newOwner; }
protected:
tHateEntry* Find(Mob *ent);
struct_HateList* Find(Mob *ent);
private:
std::list<tHateEntry*> list;
Mob *owner;
std::list<struct_HateList*> list;
Mob *hate_owner;
};
#endif
#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->entity_on_hatelist);
}
void Lua_HateEntry::SetEnt(Lua_Mob e) {
Lua_Safe_Call_Void();
self->ent = e;
self->entity_on_hatelist = e;
}
int Lua_HateEntry::GetDamage() {
Lua_Safe_Call_Int();
return self->damage;
return self->hatelist_damage;
}
void Lua_HateEntry::SetDamage(int value) {
Lua_Safe_Call_Void();
self->damage = value;
self->hatelist_damage = value;
}
int Lua_HateEntry::GetHate() {
Lua_Safe_Call_Int();
return self->hate;
return self->stored_hate_amount;
}
void Lua_HateEntry::SetHate(int value) {
Lua_Safe_Call_Void();
self->hate = value;
self->stored_hate_amount = value;
}
int Lua_HateEntry::GetFrenzy() {
Lua_Safe_Call_Int();
return self->bFrenzy;
return self->is_entity_frenzy;
}
void Lua_HateEntry::SetFrenzy(bool value) {
Lua_Safe_Call_Void();
self->bFrenzy = value;
self->is_entity_frenzy = value;
}
luabind::scope lua_register_hate_entry() {

View File

@ -5,17 +5,17 @@
#include "lua_ptr.h"
class Lua_Mob;
struct tHateEntry;
struct struct_HateList;
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<struct_HateList>
{
typedef tHateEntry NativeType;
typedef struct_HateList NativeType;
public:
Lua_HateEntry() : Lua_Ptr(nullptr) { }
Lua_HateEntry(tHateEntry *d) : Lua_Ptr(d) { }
Lua_HateEntry(struct_HateList *d) : Lua_Ptr(d) { }
virtual ~Lua_HateEntry() { }
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) {
Lua_Safe_Call_Void();
self->SetHate(other);
self->SetHateAmountOnEnt(other);
}
void Lua_Mob::SetHate(Lua_Mob other, int hate) {
Lua_Safe_Call_Void();
self->SetHate(other, hate);
self->SetHateAmountOnEnt(other, hate);
}
void Lua_Mob::SetHate(Lua_Mob other, int hate, int damage) {
Lua_Safe_Call_Void();
self->SetHate(other, hate, damage);
self->SetHateAmountOnEnt(other, hate, damage);
}
void Lua_Mob::HalveAggro(Lua_Mob other) {

View File

@ -1385,7 +1385,7 @@ void Merc::AI_Process() {
rest_timer.Disable();
if(IsRooted())
SetTarget(hate_list.GetClosest(this));
SetTarget(hate_list.GetClosestEntOnHateList(this));
else
FindTarget();
@ -2454,11 +2454,11 @@ void Merc::CheckHateList() {
Mob* groupMember = g->members[counter];
if(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);
range *= range;
if(npc->DistNoRootNoZ(*this) < range) {
hate_list.Add(npc, 1);
hate_list.AddEntToHateList(npc, 1);
}
}
}

View File

@ -401,7 +401,7 @@ Mob::Mob(const char* in_name,
PathingRouteUpdateTimerLong = new Timer(RuleI(Pathing, RouteUpdateFrequencyLong));
DistractedFromGrid = false;
PathingTraversedNodes = 0;
hate_list.SetOwner(this);
hate_list.SetHateOwner(this);
m_AllowBeneficial = false;
m_DisableMelee = false;
@ -2556,8 +2556,8 @@ bool Mob::RemoveFromHateList(Mob* mob)
bool bFound = false;
if(IsEngaged())
{
bFound = hate_list.RemoveEnt(mob);
if(hate_list.IsEmpty())
bFound = hate_list.RemoveEntFromHateList(mob);
if(hate_list.IsHateListEmpty())
{
AI_Event_NoLongerEngaged();
zone->DelAggroMob();
@ -2565,7 +2565,7 @@ bool Mob::RemoveFromHateList(Mob* mob)
}
if(GetTarget() == mob)
{
SetTarget(hate_list.GetTop(this));
SetTarget(hate_list.GetEntWithMostHateOnList(this));
}
return bFound;
@ -2575,12 +2575,12 @@ void Mob::WipeHateList()
{
if(IsEngaged())
{
hate_list.Wipe();
hate_list.WipeHateList();
AI_Event_NoLongerEngaged();
}
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){
int count = hate_list.SummonedPetCount(this);
int count = hate_list.GetSummonedPetCountOnHateList(this);
if ((base2 >= 220 && base2 <= 250) && count >= (base2 - 220)){
use_spell = true;
}

View File

@ -452,19 +452,19 @@ public:
static uint32 GetLevelCon(uint8 mylevel, uint8 iOtherLevel);
inline uint32 GetLevelCon(uint8 iOtherLevel) const {
return this ? GetLevelCon(GetLevel(), iOtherLevel) : CON_GREEN; }
virtual void AddToHateList(Mob* other, int32 hate = 0, int32 damage = 0, bool iYellForHelp = true,
virtual void AddToHateList(Mob* other, uint32 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 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()); }
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); SetHateAmountOnEnt(other, (in_hate > 1 ? 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.GetEntHateAmount(tmob,is_dam);}
uint32 GetDamageAmount(Mob* tmob) { return hate_list.GetEntHateAmount(tmob, true);}
Mob* GetHateTop() { return hate_list.GetEntWithMostHateOnList(this);}
Mob* GetHateDamageTop(Mob* other) { return hate_list.GetDamageTopOnHateList(other);}
Mob* GetHateRandom() { return hate_list.GetRandomEntOnHateList();}
Mob* GetHateMost() { return hate_list.GetEntWithMostHateOnList();}
bool IsEngaged() { return(!hate_list.IsHateListEmpty()); }
bool HateSummon();
void FaceTarget(Mob* MobToFace = 0);
void SetHeading(float iHeading) { if(heading != iHeading) { pLastChange = Timer::GetCurrentTime();
@ -473,8 +473,8 @@ public:
void AddFeignMemory(Client* attacker);
void RemoveFromFeignMemory(Client* attacker);
void ClearFeignMemory();
void PrintHateListToClient(Client *who) { hate_list.PrintToClient(who); }
std::list<tHateEntry*>& GetHateList() { return hate_list.GetHateList(); }
void PrintHateListToClient(Client *who) { hate_list.PrintHateListToClient(who); }
std::list<struct_HateList*>& 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(); }
@ -798,7 +798,7 @@ public:
void CheckFlee();
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);
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

@ -491,7 +491,7 @@ void Mob::AI_Start(uint32 iMoveDelay) {
pAggroRange = 70;
if (GetAssistRange() == 0)
pAssistRange = 70;
hate_list.Wipe();
hate_list.WipeHateList();
delta_heading = 0;
delta_x = 0;
@ -551,7 +551,7 @@ void Mob::AI_Stop() {
safe_delete(AIscanarea_timer);
safe_delete(AIfeignremember_timer);
hate_list.Wipe();
hate_list.WipeHateList();
}
void NPC::AI_Stop() {
@ -814,12 +814,12 @@ void Client::AI_Process()
if (engaged)
{
if (IsRooted())
SetTarget(hate_list.GetClosest(this));
SetTarget(hate_list.GetClosestEntOnHateList(this));
else
{
if(AItarget_check_timer->Check())
{
SetTarget(hate_list.GetTop(this));
SetTarget(hate_list.GetEntWithMostHateOnList(this));
}
}
@ -1039,7 +1039,7 @@ void Mob::AI_Process() {
//
if(RuleB(Combat, EnableFearPathing)){
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
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
// from above, so no extra blind checks needed
if ((IsRooted() && !GetSpecialAbility(IGNORE_ROOT_AGGRO_RULES)) || IsBlind())
SetTarget(hate_list.GetClosest(this));
SetTarget(hate_list.GetClosestEntOnHateList(this));
else
{
if(AItarget_check_timer->Check())
{
if (IsFocused()) {
if (!target) {
SetTarget(hate_list.GetTop(this));
SetTarget(hate_list.GetEntWithMostHateOnList(this));
}
} else {
if (!ImprovedTaunt())
SetTarget(hate_list.GetTop(this));
SetTarget(hate_list.GetEntWithMostHateOnList(this));
}
}
@ -1374,7 +1374,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.GetEntWithMostHateOnList(this);
if(tar == target) {
WipeHateList();
Heal();

View File

@ -249,8 +249,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.GetEntHateAmount(in_ent);}
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); }

View File

@ -118,7 +118,15 @@ Object::Object(Client* client, const ItemInst* inst)
m_data.heading = client->GetHeading();
m_data.x = client->GetX();
m_data.y = client->GetY();
m_data.z = client->GetZ();
if (client->GetClientVersion() >= EQClientRoF2)
{
// RoF2 places items at player's Z, which is 0.625 of their height.
m_data.z = client->GetZ() - (client->GetSize() * 0.625f);
}
else
{
m_data.z = client->GetZ();
}
m_data.zone_id = zone->GetZoneID();
decay_timer.Start();

View File

@ -40,19 +40,19 @@ XS(XS_HateEntry_GetEnt)
if (items != 1)
Perl_croak(aTHX_ "Usage: HateEntry::GetData(THIS)");
{
tHateEntry * THIS;
struct_HateList * THIS;
Mob * RETVAL;
if (sv_derived_from(ST(0), "HateEntry")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(tHateEntry *,tmp);
THIS = INT2PTR(struct_HateList *,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->entity_on_hatelist;
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;
struct_HateList * THIS;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "HateEntry")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(tHateEntry *,tmp);
THIS = INT2PTR(struct_HateList *,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->stored_hate_amount;
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;
struct_HateList * THIS;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "HateEntry")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(tHateEntry *,tmp);
THIS = INT2PTR(struct_HateList *,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->hatelist_damage;
XSprePUSH; PUSHi((IV)RETVAL);
}
XSRETURN(1);

View File

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

View File

@ -106,7 +106,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage,
if(who->GetInvul() || who->GetSpecialAbility(IMMUNE_MELEE) || who->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE))
return; //-5?
int32 hate = max_damage;
uint32 hate = max_damage;
if(hate_override > -1)
hate = hate_override;
@ -583,7 +583,7 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime)
int32 ndamage = 0;
int32 max_hit = 0;
int32 min_hit = 0;
int32 hate = 0;
uint32 hate = 0;
int32 primaryweapondamage = 0;
int32 backstab_dmg = 0;
@ -889,7 +889,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
if (HeadShot_Dmg)
HeadShot = true;
int32 hate = 0;
uint32 hate = 0;
int32 TotalDmg = 0;
int16 WDmg = 0;
int16 ADmg = 0;
@ -2354,7 +2354,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
skillinuse = SkillOffense;
int damage = 0;
int32 hate = 0;
uint32 hate = 0;
int Hand = MainPrimary;
if (hate == 0 && weapon_damage > 1) hate = weapon_damage;

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]));
if (spell.base2[i] > 0)
CastToNPC()->SetHate(caster, (CastToNPC()->GetHateAmount(caster) + spell.base2[i]));
CastToNPC()->SetHateAmountOnEnt(caster, (CastToNPC()->GetHateAmount(caster) + spell.base2[i]));
}
break;
}
@ -2693,7 +2693,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
if (new_hate <= 0)
new_hate = 1;
CastToNPC()->SetHate(caster, new_hate);
CastToNPC()->SetHateAmountOnEnt(caster, new_hate);
}
break;
}
@ -2714,9 +2714,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
}else{
int32 newhate = GetHateAmount(caster) + effect_value;
if (newhate < 1)
SetHate(caster,1);
SetHateAmountOnEnt(caster,1);
else
SetHate(caster,newhate);
SetHateAmountOnEnt(caster,newhate);
}
}
break;
@ -3546,9 +3546,9 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
}else{
int32 newhate = GetHateAmount(caster) + effect_value;
if (newhate < 1) {
SetHate(caster,1);
SetHateAmountOnEnt(caster,1);
} else {
SetHate(caster,newhate);
SetHateAmountOnEnt(caster,newhate);
}
}
}
@ -3728,11 +3728,11 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
case SE_AddHateOverTimePct:
{
if (IsNPC()){
int32 new_hate = CastToNPC()->GetHateAmount(caster) * (100 + spell.base[i]) / 100;
uint32 new_hate = CastToNPC()->GetHateAmount(caster) * (100 + spell.base[i]) / 100;
if (new_hate <= 0)
new_hate = 1;
CastToNPC()->SetHate(caster, new_hate);
CastToNPC()->SetHateAmountOnEnt(caster, new_hate);
}
break;
}
@ -6424,7 +6424,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.GetSummonedPetCountOnHateList(this);
for (int base2_value = 221; base2_value <= 249; ++base2_value){
if (value == base2_value){

View File

@ -3656,11 +3656,11 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r
spelltar->AddToHateList(this, aggro);
}
else{
int32 newhate = spelltar->GetHateAmount(this) + aggro;
uint32 newhate = spelltar->GetHateAmount(this) + aggro;
if (newhate < 1) {
spelltar->SetHate(this,1);
spelltar->SetHateAmountOnEnt(this,1);
} 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{
int32 newhate = spelltar->GetHateAmount(this) + aggro_amount;
if (newhate < 1) {
spelltar->SetHate(this,1);
spelltar->SetHateAmountOnEnt(this,1);
} else {
spelltar->SetHate(this,newhate);
spelltar->SetHateAmountOnEnt(this,newhate);
}
}
}
@ -4206,6 +4206,10 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
//Get resist modifier and adjust it based on focus 2 resist about eq to 1% resist chance
int resist_modifier = (use_resist_override) ? resist_override : spells[spell_id].ResistDiff;
if(caster->GetSpecialAbility(CASTING_RESIST_DIFF))
resist_modifier += caster->GetSpecialAbilityParam(CASTING_RESIST_DIFF, 0);
int focus_resist = caster->GetFocusEffect(focusResistRate, spell_id);
resist_modifier -= 2 * focus_resist;