Correct DoLosChecks

This commit is contained in:
nytmyr
2025-01-26 09:44:46 -06:00
parent 764715f625
commit fbb2341fca
10 changed files with 113 additions and 42 deletions
+10 -7
View File
@@ -2272,7 +2272,6 @@ void Bot::AI_Process()
// This causes conflicts with default pet handler (bounces between targets)
if (NOT_PULLING_BOT && HasPet() && (GetClass() != Class::Enchanter || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) {
// We don't add to hate list here because it's assumed to already be on the list
GetPet()->SetTarget(tar);
}
@@ -2316,7 +2315,7 @@ void Bot::AI_Process()
if (GetPullingFlag()) {
if (!TargetValidation(tar)) { return; }
if (!DoLosChecks(this, tar)) {
if (!DoLosChecks(tar)) {
return;
}
@@ -3196,7 +3195,7 @@ bool Bot::IsValidTarget(
(!Charmed() && tar->GetUltimateOwner()->IsOfClientBotMerc()) ||
lo_distance > leash_distance ||
tar_distance > leash_distance ||
(!GetAttackingFlag() && !CheckLosCheat(this, tar) && !CheckLosCheat(leash_owner, tar)) ||
(!GetAttackingFlag() && !CheckLosCheat(tar) && !leash_owner->CheckLosCheat(tar)) ||
!IsAttackAllowed(tar)
) {
invalid_target_state = true;
@@ -9382,6 +9381,10 @@ void Bot::DoItemClick(const EQ::ItemData *item, uint16 slot_id)
bool is_casting_bard_song = false;
Mob* tar = (GetOwner()->GetTarget() ? GetOwner()->GetTarget() : this);
if (!DoLosChecks(tar)) {
return;
}
if (IsCasting()) {
InterruptSpell();
}
@@ -10252,7 +10255,7 @@ bool Bot::IsValidMezTarget(Mob* owner, Mob* npc, uint16 spell_id) {
return false;
}
if (!DoLosChecks(this, npc)) {
if (!DoLosChecks(npc)) {
return false;
}
@@ -11084,7 +11087,7 @@ bool Bot::AttemptAACastSpell(Mob* tar, uint16 spell_id, AA::Rank* rank) {
tar = this;
}
if (!DoLosChecks(this, tar)) {
if (!DoLosChecks(tar)) {
return false;
}
@@ -11219,7 +11222,7 @@ bool Bot::AttemptForcedCastSpell(Mob* tar, uint16 spell_id, bool is_disc) {
return false;
}
if (!DoLosChecks(this, tar)) {
if (!DoLosChecks(tar)) {
return false;
}
@@ -11712,7 +11715,7 @@ bool Bot::HasRequiredLoSForPositioning(Mob* tar) {
return true;
}
if (RequiresLoSForPositioning() && !DoLosChecks(this, tar)) {
if (RequiresLoSForPositioning() && !DoLosChecks(tar)) {
return false;
}
+1 -1
View File
@@ -803,7 +803,7 @@ void helper_send_usage_required_bots(Client *bot_owner, uint16 spell_type)
auto& spell_map = bot->GetCommandedSpellTypesMinLevels();
if (spell_map.empty()) {
bot_owner->Message(Chat::Yellow, "No bots are capable of casting this spell type"); //deleteme
bot_owner->Message(Chat::Yellow, "No bots are capable of casting this spell type");
return;
}
+7 -2
View File
@@ -18,7 +18,12 @@ void bot_command_attack(Client *c, const Seperator *sep)
if (!target_mob) {
c->Message(Chat::White, "You must <target> an enemy to use this command");
c->Message(Chat::Yellow, "You must <target> an enemy to use this command");
return;
}
if (!c->DoLosChecks(target_mob)) {
c->Message(Chat::Red, "You must have Line of Sight to use this command.");
return;
}
@@ -71,7 +76,7 @@ void bot_command_attack(Client *c, const Seperator *sep)
);
} else {
c->Message(
Chat::White,
Chat::PetResponse,
fmt::format(
"{} of your bots are attacking {}.",
sbl.size(),
+11
View File
@@ -47,11 +47,22 @@ void bot_command_click_item(Client* c, const Seperator* sep)
sbl.erase(std::remove(sbl.begin(), sbl.end(), nullptr), sbl.end());
Mob* tar = c->GetTarget();
for (auto my_bot : sbl) {
if (my_bot->BotPassiveCheck()) {
continue;
}
if (
tar &&
tar != c &&
tar->GetOwner() != c &&
!c->DoLosChecks(tar)
) {
continue;
}
if (RuleI(Bots, BotsClickItemsMinLvl) > my_bot->GetLevel()) {
c->Message(Chat::White, "%s must be level %i to use clickable items.", my_bot->GetCleanName(), RuleI(Bots, BotsClickItemsMinLvl));
continue;
+9 -2
View File
@@ -5,15 +5,22 @@ void bot_command_precombat(Client* c, const Seperator* sep)
if (helper_command_alias_fail(c, "bot_command_precombat", sep->arg[0], "precombat")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s ([set | clear])", sep->arg[0]);
return;
}
if (!c->GetTarget() || !c->IsAttackAllowed(c->GetTarget())) {
c->Message(Chat::White, "This command requires an attackable target.");
return;
}
if (!c->DoLosChecks(c->GetTarget())) {
c->Message(Chat::Red, "You must have Line of Sight to use this command.");
return;
}
+7 -1
View File
@@ -48,6 +48,12 @@ void bot_command_pull(Client *c, const Seperator *sep)
return;
}
if (!c->DoLosChecks(target_mob)) {
c->Message(Chat::Red, "You must have Line of Sight to use this command.");
return;
}
if (target_mob->IsNPC() && target_mob->GetHateList().size()) {
c->Message(Chat::White, "Your current target is already engaged!");
@@ -55,8 +61,8 @@ void bot_command_pull(Client *c, const Seperator *sep)
}
Bot* bot_puller = nullptr;
for (auto bot_iter : sbl) {
for (auto bot_iter : sbl) {
if (bot_iter->GetAppearance() == eaDead || bot_iter->GetBotStance() == Stance::Passive) {
continue;
}
+1 -1
View File
@@ -65,7 +65,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 chance, uint16 spell_type, uint16 sub_targ
bot_spell.ManaCost = 0;
if (BotSpellTypeRequiresLoS(spell_type) && tar != this) {
SetHasLoS(DoLosChecks(this, tar));
SetHasLoS(DoLosChecks(tar));
}
else {
SetHasLoS(true);
+15 -1
View File
@@ -11091,10 +11091,17 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
case PET_ATTACK: {
if (!target)
break;
if (!DoLosChecks(target)) {
mypet->SayString(this, NOT_LEGAL_TARGET);
break;
}
if (target->IsMezzed()) {
MessageString(Chat::NPCQuestSay, CANNOT_WAKE, mypet->GetCleanName(), target->GetCleanName());
break;
}
if (mypet->IsFeared())
break; //prevent pet from attacking stuff while feared
@@ -11149,8 +11156,15 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
if (mypet->IsFeared())
break; //prevent pet from attacking stuff while feared
if (!GetTarget())
if (!GetTarget()) {
break;
}
if (!DoLosChecks(GetTarget())) {
mypet->SayString(this, NOT_LEGAL_TARGET);
break;
}
if (GetTarget()->IsMezzed()) {
MessageString(Chat::NPCQuestSay, CANNOT_WAKE, mypet->GetCleanName(), GetTarget()->GetCleanName());
break;
+49 -24
View File
@@ -8679,33 +8679,54 @@ bool Mob::IsInGroupOrRaid(Mob* other, bool same_raid_group) {
return group && group == other_group;
}
bool Mob::DoLosChecks(Mob* who, Mob* other) {
if (!who->CheckLosFN(other) || !who->CheckWaterLoS(other)) {
if (who->CheckLosCheatExempt(who, other)) {
return true;
}
if (CheckLosCheat(who, other)) {
bool Mob::DoLosChecks(Mob* other) {
if (!CheckLosFN(other) || !CheckWaterLoS(other)) {
if (CheckLosCheatExempt(other)) {
return true;
}
return false;
}
if (!CheckLosCheat(other)) {
return false;
}
return true;
}
bool Mob::CheckLosCheat(Mob* who, Mob* other) {
bool Mob::CheckLosCheat(Mob* other) {
if (RuleB(Map, CheckForLoSCheat)) {
for (auto itr : entity_list.GetDoorsList()) {
Doors* d = itr.second;
if (d && !d->IsDoorOpen() && (d->GetTriggerType() == 255 || d->GetLockpick() != 0 || d->GetKeyItem() != 0 || d->GetNoKeyring() != 0)) {
if (DistanceNoZ(who->GetPosition(), d->GetPosition()) <= 50) {
auto who_to_door = DistanceNoZ(who->GetPosition(), d->GetPosition());
auto other_to_door = DistanceNoZ(other->GetPosition(), d->GetPosition());
auto who_to_other = DistanceNoZ(who->GetPosition(), other->GetPosition());
auto distance_difference = who_to_other - (who_to_door + other_to_door);
if (
!d->IsDoorOpen() &&
(
d->GetKeyItem() ||
d->GetLockpick() ||
d->IsDoorOpen() ||
d->IsDoorBlacklisted() ||
d->GetNoKeyring() != 0 ||
d->GetDoorParam() > 0
)
) {
// If the door is a trigger door, check if the trigger door is open
if (d->GetTriggerDoorID() > 0) {
auto td = entity_list.GetDoorsByDoorID(d->GetTriggerDoorID());
if (td) {
if (Strings::RemoveNumbers(d->GetDoorName()) != Strings::RemoveNumbers(td->GetDoorName())) {
continue;
}
}
}
if (DistanceNoZ(GetPosition(), d->GetPosition()) <= 50) {
auto who_to_door = DistanceNoZ(GetPosition(), d->GetPosition());
auto other_to_door = DistanceNoZ(other->GetPosition(), d->GetPosition());
auto who_to_other = DistanceNoZ(GetPosition(), other->GetPosition());
auto distance_difference = who_to_other - (who_to_door + other_to_door);
if (distance_difference >= (-1 * RuleR(Maps, RangeCheckForLoSCheat)) && distance_difference <= RuleR(Maps, RangeCheckForLoSCheat)) {
return false;
}
@@ -8717,19 +8738,23 @@ bool Mob::CheckLosCheat(Mob* who, Mob* other) {
return true;
}
bool Mob::CheckLosCheatExempt(Mob* who, Mob* other) {
bool Mob::CheckLosCheatExempt(Mob* other) {
if (RuleB(Map, EnableLoSCheatExemptions)) {
/* This is an exmaple of how to configure exemptions for LoS checks.
glm::vec4 exempt_check_who;
glm::vec4 exempt_check_other;
/* This is an exmaple of how to configure exemptions for LoS checks.
if (zone->GetZoneID() == 222) { //PoEarthB
exempt_check_who.x = 2051; exempt_check_who.y = 407; exempt_check_who.z = -219; //Middle of councilman spawns
//check to be sure the player and the target are in the pit to PoEarthB
//if the player is inside the cove they cannot be higher than the ceiling (no exploiting from uptop)
//otherwise they can pass LoS checks even if they don't have true LoS
if (who->GetZ() <= -171 && other->GetZ() <= -171 && DistanceNoZ(other->GetPosition(), exempt_check_who) <= 800 && DistanceNoZ(who->GetPosition(), exempt_check_who) <= 800) {
return true;
}
switch (zone->GetZoneID()) {
case POEARTHB:
exempt_check_who.x = 2051; exempt_check_who.y = 407; exempt_check_who.z = -219; //Middle of councilman spawns
//exempt_check_other.x = 1455; exempt_check_other.y = 415; exempt_check_other.z = -242;
//check to be sure the player and the target are outside of the councilman area
//if the player is inside the cove they cannot be higher than the ceiling (no exploiting from uptop)
if (GetZ() <= -171 && other->GetZ() <= -171 && DistanceNoZ(other->GetPosition(), exempt_check_who) <= 800 && DistanceNoZ(GetPosition(), exempt_check_who) <= 800) {
return true;
}
default:
return false;
}
*/
}
+3 -3
View File
@@ -872,9 +872,9 @@ public:
static bool CheckLosFN(glm::vec3 posWatcher, float sizeWatcher, glm::vec3 posTarget, float sizeTarget);
virtual bool CheckWaterLoS(Mob* m);
bool CheckPositioningLosFN(Mob* other, float posX, float posY, float posZ);
bool CheckLosCheat(Mob* who, Mob* other);
bool CheckLosCheatExempt(Mob* who, Mob* other);
bool DoLosChecks(Mob* who, Mob* other);
bool CheckLosCheat(Mob* other);
bool CheckLosCheatExempt(Mob* other);
bool DoLosChecks(Mob* other);
bool TargetValidation(Mob* other);
inline void SetLastLosState(bool value) { last_los_check = value; }
inline bool CheckLastLosState() const { return last_los_check; }