mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 10:31:29 +00:00
Merge branch 'master' of https://github.com/EQEmu/Server into item_link
Conflicts: changelog.txt
This commit is contained in:
commit
4fb1a3ff3f
@ -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
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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...
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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())
|
||||
|
||||
12
zone/bot.cpp
12
zone/bot.cpp
@ -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);
|
||||
}
|
||||
|
||||
@ -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; }
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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...");
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
@ -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() {
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
14
zone/mob.cpp
14
zone/mob.cpp
@ -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;
|
||||
}
|
||||
|
||||
28
zone/mob.h
28
zone/mob.h
@ -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);
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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); }
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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){
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user