Use GetSmartMobList in AESpell

This commit is contained in:
Akkadius 2019-12-29 02:42:52 -06:00
parent 6b465c576d
commit ec5faea9b1
4 changed files with 143 additions and 218 deletions

View File

@ -716,15 +716,20 @@ void EntityList::AESpell(
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 =
spells[spell_id].targettype == ST_Ring ?
caster_mob->GetTargetRingLocation() :
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
*/
@ -748,7 +753,6 @@ void EntityList::AESpell(
int target_hit_counter = 0;
float distance_to_target = 0;
float distance = caster_mob->GetAOERange(spell_id);
LogAoeCast(
"Close scan distance [{}] cast distance [{}]",
@ -756,66 +760,129 @@ void EntityList::AESpell(
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");
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);
if (!current_mob) {
continue;
}
} else {
LogAoeCast("Using full entity mob list");
LogAoeCast("Checking AOE against mob [{}]", current_mob->GetCleanName());
for (auto &it : mob_list) {
current_mob = it.second;
if (current_mob->IsClient() && !current_mob->CastToClient()->ClientFinishedLoading()) {
continue;
}
LogAoeCast("Checking against full zone scan mob [{}]", current_mob->GetCleanName());
if (current_mob == caster_mob && !affect_caster) {
continue;
}
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
)) {
if (spells[spell_id].targettype == ST_TargetAENoPlayersPets && current_mob->IsPetOwnerClient()) {
continue;
}
if (spells[spell_id].targettype == ST_AreaClientOnly && !current_mob->IsClient()) {
continue;
}
if (spells[spell_id].targettype == ST_AreaNPCOnly && !current_mob->IsNPC()) {
continue;
}
/**
* 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;
}
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());
@ -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)
{
Mob *curmob = nullptr;

View File

@ -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;
}

View File

@ -412,19 +412,6 @@ public:
int16 resist_adjust = 0,
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 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, Doors *> &GetDoorsList() { return door_list; }
std::unordered_map<uint16, Mob *> &GetCloseMobList(Mob *mob, float distance);
void DepopAll(int NPCTypeID, bool StartSpawnTimer = true);
uint16 GetFreeID();
@ -537,6 +526,7 @@ public:
bool IsTrapGroupSpawned(uint32 trap_id, uint8 group);
void UpdateAllTraps(bool respawn, bool repopnow = false);
void ClearTrapPointers();
protected:
friend class Zone;
void Depop(bool StartSpawnTimer = false);
@ -592,6 +582,7 @@ private:
private:
std::list<Bot*> bot_list;
#endif
};
class BulkZoneSpawnPacket {

View File

@ -171,6 +171,7 @@ public:
void DisplayInfo(Mob *mob);
std::unordered_map<uint16, Mob *> close_mobs;
std::unordered_map<uint16, Mob *>& GetSmartMobList(float distance = 0);
Timer mob_scan_close;
Timer mob_check_moving_timer;