mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 02:11:30 +00:00
Use GetSmartMobList in AESpell
This commit is contained in:
parent
6b465c576d
commit
ec5faea9b1
328
zone/effects.cpp
328
zone/effects.cpp
@ -716,15 +716,20 @@ void EntityList::AESpell(
|
|||||||
int *max_targets
|
int *max_targets
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Mob *current_mob = nullptr;
|
|
||||||
bool is_detrimental_spell = IsDetrimentalSpell(spell_id);
|
|
||||||
bool is_npc = caster_mob->IsNPC();
|
|
||||||
|
|
||||||
const auto &cast_target_position =
|
const auto &cast_target_position =
|
||||||
spells[spell_id].targettype == ST_Ring ?
|
spells[spell_id].targettype == ST_Ring ?
|
||||||
caster_mob->GetTargetRingLocation() :
|
caster_mob->GetTargetRingLocation() :
|
||||||
static_cast<glm::vec3>(center_mob->GetPosition());
|
static_cast<glm::vec3>(center_mob->GetPosition());
|
||||||
|
|
||||||
|
Mob *current_mob = nullptr;
|
||||||
|
bool is_detrimental_spell = IsDetrimentalSpell(spell_id);
|
||||||
|
bool is_npc = caster_mob->IsNPC();
|
||||||
|
float distance = caster_mob->GetAOERange(spell_id);
|
||||||
|
float distance_squared = distance * distance;
|
||||||
|
float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range;
|
||||||
|
glm::vec2 min = {cast_target_position.x - distance, cast_target_position.y - distance};
|
||||||
|
glm::vec2 max = {cast_target_position.x + distance, cast_target_position.y + distance};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If using Old Rain Targets - there is no max target limitation
|
* If using Old Rain Targets - there is no max target limitation
|
||||||
*/
|
*/
|
||||||
@ -748,7 +753,6 @@ void EntityList::AESpell(
|
|||||||
|
|
||||||
int target_hit_counter = 0;
|
int target_hit_counter = 0;
|
||||||
float distance_to_target = 0;
|
float distance_to_target = 0;
|
||||||
float distance = caster_mob->GetAOERange(spell_id);
|
|
||||||
|
|
||||||
LogAoeCast(
|
LogAoeCast(
|
||||||
"Close scan distance [{}] cast distance [{}]",
|
"Close scan distance [{}] cast distance [{}]",
|
||||||
@ -756,66 +760,129 @@ void EntityList::AESpell(
|
|||||||
distance
|
distance
|
||||||
);
|
);
|
||||||
|
|
||||||
if (distance <= RuleI(Range, MobCloseScanDistance)) {
|
for (auto &it : entity_list.GetCloseMobList(caster_mob, distance)) {
|
||||||
|
current_mob = it.second;
|
||||||
|
|
||||||
LogAoeCast("Using close scan mob list");
|
if (!current_mob) {
|
||||||
|
continue;
|
||||||
for (auto &it : caster_mob->close_mobs) {
|
|
||||||
current_mob = it.second;
|
|
||||||
|
|
||||||
if (!current_mob) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
LogAoeCast("Checking against close scan mob [{}]", current_mob->GetCleanName());
|
|
||||||
|
|
||||||
if (!AESpellFilterCriteria(
|
|
||||||
current_mob,
|
|
||||||
caster_mob,
|
|
||||||
center_mob,
|
|
||||||
spell_id,
|
|
||||||
max_targets,
|
|
||||||
max_targets_allowed,
|
|
||||||
target_hit_counter,
|
|
||||||
distance_to_target,
|
|
||||||
cast_target_position,
|
|
||||||
affect_caster,
|
|
||||||
resist_adjust
|
|
||||||
)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
current_mob->CalcSpellPowerDistanceMod(spell_id, distance_to_target);
|
|
||||||
caster_mob->SpellOnTarget(spell_id, current_mob, false, true, resist_adjust);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
|
|
||||||
LogAoeCast("Using full entity mob list");
|
LogAoeCast("Checking AOE against mob [{}]", current_mob->GetCleanName());
|
||||||
|
|
||||||
for (auto &it : mob_list) {
|
if (current_mob->IsClient() && !current_mob->CastToClient()->ClientFinishedLoading()) {
|
||||||
current_mob = it.second;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
LogAoeCast("Checking against full zone scan mob [{}]", current_mob->GetCleanName());
|
if (current_mob == caster_mob && !affect_caster) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!AESpellFilterCriteria(
|
if (spells[spell_id].targettype == ST_TargetAENoPlayersPets && current_mob->IsPetOwnerClient()) {
|
||||||
current_mob,
|
continue;
|
||||||
caster_mob,
|
}
|
||||||
center_mob,
|
|
||||||
spell_id,
|
if (spells[spell_id].targettype == ST_AreaClientOnly && !current_mob->IsClient()) {
|
||||||
max_targets,
|
continue;
|
||||||
max_targets_allowed,
|
}
|
||||||
target_hit_counter,
|
|
||||||
distance_to_target,
|
if (spells[spell_id].targettype == ST_AreaNPCOnly && !current_mob->IsNPC()) {
|
||||||
cast_target_position,
|
continue;
|
||||||
affect_caster,
|
}
|
||||||
resist_adjust
|
|
||||||
)) {
|
/**
|
||||||
|
* Check PC / NPC
|
||||||
|
* 1 = PC
|
||||||
|
* 2 = NPC
|
||||||
|
*/
|
||||||
|
if (spells[spell_id].pcnpc_only_flag == 1 && !current_mob->IsClient() && !current_mob->IsMerc()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spells[spell_id].pcnpc_only_flag == 2 && (current_mob->IsClient() || current_mob->IsMerc())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsWithinAxisAlignedBox(static_cast<glm::vec2>(current_mob->GetPosition()), min, max)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
distance_to_target = DistanceSquared(current_mob->GetPosition(), cast_target_position);
|
||||||
|
|
||||||
|
if (distance_to_target > distance_squared) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (distance_to_target < min_range2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_npc && current_mob->IsNPC() &&
|
||||||
|
spells[spell_id].targettype != ST_AreaNPCOnly) { //check npc->npc casting
|
||||||
|
FACTION_VALUE faction_value = current_mob->GetReverseFactionCon(caster_mob);
|
||||||
|
if (is_detrimental_spell) {
|
||||||
|
//affect mobs that are on our hate list, or
|
||||||
|
//which have bad faction with us
|
||||||
|
if (
|
||||||
|
!(caster_mob->CheckAggro(current_mob) ||
|
||||||
|
faction_value == FACTION_THREATENLY ||
|
||||||
|
faction_value == FACTION_SCOWLS)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//only affect mobs we would assist.
|
||||||
|
if (!(faction_value <= FACTION_AMIABLE)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finally, make sure they are within range
|
||||||
|
*/
|
||||||
|
if (is_detrimental_spell) {
|
||||||
|
if (!caster_mob->IsAttackAllowed(current_mob, true)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (center_mob && !spells[spell_id].npc_no_los && !center_mob->CheckLosFN(current_mob)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!center_mob && !spells[spell_id].npc_no_los && !caster_mob->CheckLosFN(
|
||||||
|
caster_mob->GetTargetRingX(),
|
||||||
|
caster_mob->GetTargetRingY(),
|
||||||
|
caster_mob->GetTargetRingZ(),
|
||||||
|
current_mob->GetSize())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
current_mob->CalcSpellPowerDistanceMod(spell_id, distance_to_target);
|
|
||||||
caster_mob->SpellOnTarget(spell_id, current_mob, false, true, resist_adjust);
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check to stop casting beneficial ae buffs (to wit: bard songs) on enemies...
|
||||||
|
* This does not check faction for beneficial AE buffs... only agro and attackable.
|
||||||
|
* I've tested for spells that I can find without problem, but a faction-based
|
||||||
|
* check may still be needed. Any changes here should also reflect in BardAEPulse()
|
||||||
|
*/
|
||||||
|
if (caster_mob->IsAttackAllowed(current_mob, true)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (caster_mob->CheckAggro(current_mob)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increment hit count if max targets
|
||||||
|
*/
|
||||||
|
if (max_targets_allowed) {
|
||||||
|
target_hit_counter++;
|
||||||
|
if (target_hit_counter >= max_targets_allowed) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
current_mob->CalcSpellPowerDistanceMod(spell_id, distance_to_target);
|
||||||
|
caster_mob->SpellOnTarget(spell_id, current_mob, false, true, resist_adjust);
|
||||||
}
|
}
|
||||||
|
|
||||||
LogAoeCast("Done iterating [{}]", caster_mob->GetCleanName());
|
LogAoeCast("Done iterating [{}]", caster_mob->GetCleanName());
|
||||||
@ -825,155 +892,6 @@ void EntityList::AESpell(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param caster_mob
|
|
||||||
* @param center_mob
|
|
||||||
* @param spell_id
|
|
||||||
* @param affect_caster
|
|
||||||
* @param resist_adjust
|
|
||||||
* @param max_targets
|
|
||||||
*/
|
|
||||||
bool EntityList::AESpellFilterCriteria(
|
|
||||||
Mob *current_mob,
|
|
||||||
Mob *caster_mob,
|
|
||||||
Mob *center_mob,
|
|
||||||
uint16 spell_id,
|
|
||||||
int *max_targets,
|
|
||||||
int &max_targets_allowed,
|
|
||||||
int &target_hit_counter,
|
|
||||||
float &distance_to_target,
|
|
||||||
const glm::vec3 &cast_target_position,
|
|
||||||
bool affect_caster,
|
|
||||||
int16 resist_adjust
|
|
||||||
) {
|
|
||||||
|
|
||||||
if (!current_mob) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_npc = caster_mob->IsNPC();
|
|
||||||
float distance = caster_mob->GetAOERange(spell_id);
|
|
||||||
float distance_squared = distance * distance;
|
|
||||||
float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range;
|
|
||||||
bool is_detrimental_spell = IsDetrimentalSpell(spell_id);
|
|
||||||
glm::vec2 min = {cast_target_position.x - distance, cast_target_position.y - distance};
|
|
||||||
glm::vec2 max = {cast_target_position.x + distance, cast_target_position.y + distance};
|
|
||||||
|
|
||||||
if (current_mob->IsClient() && !current_mob->CastToClient()->ClientFinishedLoading()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_mob == caster_mob && !affect_caster) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spells[spell_id].targettype == ST_TargetAENoPlayersPets && current_mob->IsPetOwnerClient()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spells[spell_id].targettype == ST_AreaClientOnly && !current_mob->IsClient()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spells[spell_id].targettype == ST_AreaNPCOnly && !current_mob->IsNPC()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check PC / NPC
|
|
||||||
* 1 = PC
|
|
||||||
* 2 = NPC
|
|
||||||
*/
|
|
||||||
if (spells[spell_id].pcnpc_only_flag == 1 && !current_mob->IsClient() && !current_mob->IsMerc()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spells[spell_id].pcnpc_only_flag == 2 && (current_mob->IsClient() || current_mob->IsMerc())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsWithinAxisAlignedBox(static_cast<glm::vec2>(current_mob->GetPosition()), min, max)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
distance_to_target = DistanceSquared(current_mob->GetPosition(), cast_target_position);
|
|
||||||
|
|
||||||
if (distance_to_target > distance_squared) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (distance_to_target < min_range2) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_npc && current_mob->IsNPC() &&
|
|
||||||
spells[spell_id].targettype != ST_AreaNPCOnly) { //check npc->npc casting
|
|
||||||
FACTION_VALUE faction_value = current_mob->GetReverseFactionCon(caster_mob);
|
|
||||||
if (is_detrimental_spell) {
|
|
||||||
//affect mobs that are on our hate list, or
|
|
||||||
//which have bad faction with us
|
|
||||||
if (
|
|
||||||
!(caster_mob->CheckAggro(current_mob) ||
|
|
||||||
faction_value == FACTION_THREATENLY ||
|
|
||||||
faction_value == FACTION_SCOWLS)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//only affect mobs we would assist.
|
|
||||||
if (!(faction_value <= FACTION_AMIABLE)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finally, make sure they are within range
|
|
||||||
*/
|
|
||||||
if (is_detrimental_spell) {
|
|
||||||
if (!caster_mob->IsAttackAllowed(current_mob, true)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (center_mob && !spells[spell_id].npc_no_los && !center_mob->CheckLosFN(current_mob)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!center_mob && !spells[spell_id].npc_no_los && !caster_mob->CheckLosFN(
|
|
||||||
caster_mob->GetTargetRingX(),
|
|
||||||
caster_mob->GetTargetRingY(),
|
|
||||||
caster_mob->GetTargetRingZ(),
|
|
||||||
current_mob->GetSize())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check to stop casting beneficial ae buffs (to wit: bard songs) on enemies...
|
|
||||||
* This does not check faction for beneficial AE buffs... only agro and attackable.
|
|
||||||
* I've tested for spells that I can find without problem, but a faction-based
|
|
||||||
* check may still be needed. Any changes here should also reflect in BardAEPulse()
|
|
||||||
*/
|
|
||||||
if (caster_mob->IsAttackAllowed(current_mob, true)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (caster_mob->CheckAggro(current_mob)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Increment hit count if max targets
|
|
||||||
*/
|
|
||||||
if (max_targets_allowed) {
|
|
||||||
target_hit_counter++;
|
|
||||||
if (target_hit_counter >= max_targets_allowed) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EntityList::MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster)
|
void EntityList::MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster)
|
||||||
{
|
{
|
||||||
Mob *curmob = nullptr;
|
Mob *curmob = nullptr;
|
||||||
|
|||||||
@ -5030,3 +5030,18 @@ void EntityList::ReloadMerchants() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mob
|
||||||
|
* @param distance
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
std::unordered_map<uint16, Mob *> &EntityList::GetCloseMobList(Mob *mob, float distance)
|
||||||
|
{
|
||||||
|
if (distance <= RuleI(Range, MobCloseScanDistance)) {
|
||||||
|
return mob->close_mobs;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mob_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -412,19 +412,6 @@ public:
|
|||||||
int16 resist_adjust = 0,
|
int16 resist_adjust = 0,
|
||||||
int *max_targets = nullptr
|
int *max_targets = nullptr
|
||||||
);
|
);
|
||||||
static bool AESpellFilterCriteria(
|
|
||||||
Mob *current_mob,
|
|
||||||
Mob *caster_mob,
|
|
||||||
Mob *center_mob,
|
|
||||||
uint16 spell_id,
|
|
||||||
int *max_targets,
|
|
||||||
int &max_targets_allowed,
|
|
||||||
int &target_hit_counter,
|
|
||||||
float &distance_to_target,
|
|
||||||
const glm::vec3 &cast_target_position,
|
|
||||||
bool affect_caster = true,
|
|
||||||
int16 resist_adjust = 0
|
|
||||||
);
|
|
||||||
void MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true);
|
void MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true);
|
||||||
void AEBardPulse(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true);
|
void AEBardPulse(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true);
|
||||||
|
|
||||||
@ -525,6 +512,8 @@ public:
|
|||||||
inline const std::unordered_map<uint16, Object *> &GetObjectList() { return object_list; }
|
inline const std::unordered_map<uint16, Object *> &GetObjectList() { return object_list; }
|
||||||
inline const std::unordered_map<uint16, Doors *> &GetDoorsList() { return door_list; }
|
inline const std::unordered_map<uint16, Doors *> &GetDoorsList() { return door_list; }
|
||||||
|
|
||||||
|
std::unordered_map<uint16, Mob *> &GetCloseMobList(Mob *mob, float distance);
|
||||||
|
|
||||||
void DepopAll(int NPCTypeID, bool StartSpawnTimer = true);
|
void DepopAll(int NPCTypeID, bool StartSpawnTimer = true);
|
||||||
|
|
||||||
uint16 GetFreeID();
|
uint16 GetFreeID();
|
||||||
@ -537,6 +526,7 @@ public:
|
|||||||
bool IsTrapGroupSpawned(uint32 trap_id, uint8 group);
|
bool IsTrapGroupSpawned(uint32 trap_id, uint8 group);
|
||||||
void UpdateAllTraps(bool respawn, bool repopnow = false);
|
void UpdateAllTraps(bool respawn, bool repopnow = false);
|
||||||
void ClearTrapPointers();
|
void ClearTrapPointers();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class Zone;
|
friend class Zone;
|
||||||
void Depop(bool StartSpawnTimer = false);
|
void Depop(bool StartSpawnTimer = false);
|
||||||
@ -592,6 +582,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
std::list<Bot*> bot_list;
|
std::list<Bot*> bot_list;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class BulkZoneSpawnPacket {
|
class BulkZoneSpawnPacket {
|
||||||
|
|||||||
@ -171,6 +171,7 @@ public:
|
|||||||
void DisplayInfo(Mob *mob);
|
void DisplayInfo(Mob *mob);
|
||||||
|
|
||||||
std::unordered_map<uint16, Mob *> close_mobs;
|
std::unordered_map<uint16, Mob *> close_mobs;
|
||||||
|
std::unordered_map<uint16, Mob *>& GetSmartMobList(float distance = 0);
|
||||||
Timer mob_scan_close;
|
Timer mob_scan_close;
|
||||||
Timer mob_check_moving_timer;
|
Timer mob_check_moving_timer;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user