From 4c644600b0a9433166084675cf4b09ab86ed1936 Mon Sep 17 00:00:00 2001 From: neckkola <65987027+neckkola@users.noreply.github.com> Date: Wed, 18 May 2022 19:03:37 -0300 Subject: [PATCH] Revert "Merge branch 'master' of https://github.com/neckkola/Server" This reverts commit 18268306378a34a6f0a9015cfcb4f48364bef013, reversing changes made to 7c1a1399918aeee1dc3f6f30e39044d7d1bec4c9. --- .gitignore | 4 +- CMakeSettings.json | 15 - .../base/base_raid_members_repository.h | 33 +- common/ruletypes.h | 3 - common/types.h | 3 - .../sql/git/bots/bots_db_update_manifest.txt | 1 - .../required/2022_02_08_bots_raid_members.sql | 1 - zone/CMakeLists.txt | 1 - zone/bot.h | 19 +- zone/bot_raid.cpp | 2630 ----------------- zone/bot_raid.h | 47 - zone/botspellsai.cpp | 9 +- zone/client.cpp | 9 +- zone/client_packet.cpp | 1200 ++++---- zone/entity.cpp | 50 +- zone/entity.h | 4 - zone/exp.cpp | 4 - zone/groups.cpp | 60 +- zone/main.cpp | 3 +- zone/mob.cpp | 2 +- zone/raids.cpp | 216 +- zone/raids.h | 11 - zone/spawn2.cpp | 2 +- zone/zone.cpp | 1 - 24 files changed, 535 insertions(+), 3793 deletions(-) delete mode 100644 CMakeSettings.json delete mode 100644 utils/sql/git/bots/required/2022_02_08_bots_raid_members.sql delete mode 100644 zone/bot_raid.cpp delete mode 100644 zone/bot_raid.h diff --git a/.gitignore b/.gitignore index be8fccbc3..d835a1ceb 100644 --- a/.gitignore +++ b/.gitignore @@ -54,5 +54,5 @@ bin/ /Win32 /x64 /client_files/**/CMakeFiles/ -submodules/libuv -.idea \ No newline at end of file + +.idea diff --git a/CMakeSettings.json b/CMakeSettings.json deleted file mode 100644 index 9204f06eb..000000000 --- a/CMakeSettings.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "configurations": [ - { - "name": "x64-Debug", - "generator": "Ninja", - "configurationType": "Debug", - "inheritEnvironments": [ "msvc_x64_x64" ], - "buildRoot": "${projectDir}\\out\\build\\${name}", - "installRoot": "${projectDir}\\out\\install\\${name}", - "cmakeCommandArgs": "", - "buildCommandArgs": "", - "ctestCommandArgs": "" - } - ] -} \ No newline at end of file diff --git a/common/repositories/base/base_raid_members_repository.h b/common/repositories/base/base_raid_members_repository.h index 11a77d36b..ed90853f0 100644 --- a/common/repositories/base/base_raid_members_repository.h +++ b/common/repositories/base/base_raid_members_repository.h @@ -28,9 +28,6 @@ public: int isgroupleader; int israidleader; int islooter; -#ifdef BOTS - int isbot; -#endif }; static std::string PrimaryKey() @@ -50,9 +47,6 @@ public: "isgroupleader", "israidleader", "islooter", -#ifdef BOTS - "isbot", -#endif }; } @@ -117,9 +111,6 @@ public: entry.isgroupleader = 0; entry.israidleader = 0; entry.islooter = 0; -#ifdef BOTS - entry.isbot = 0; -#endif return entry; } @@ -163,10 +154,7 @@ public: entry.name = row[5] ? row[5] : ""; entry.isgroupleader = atoi(row[6]); entry.israidleader = atoi(row[7]); - entry.islooter = atoi(row[8]); -#ifdef BOTS - entry.isbot = atoi(row[9]); -#endif + entry.islooter = atoi(row[8]); return entry; } @@ -209,9 +197,6 @@ public: update_values.push_back(columns[6] + " = " + std::to_string(raid_members_entry.isgroupleader)); update_values.push_back(columns[7] + " = " + std::to_string(raid_members_entry.israidleader)); update_values.push_back(columns[8] + " = " + std::to_string(raid_members_entry.islooter)); -#ifdef BOTS - update_values.push_back(columns[9] + " = " + std::to_string(raid_members_entry.isbot)); -#endif auto results = db.QueryDatabase( fmt::format( @@ -242,9 +227,7 @@ public: insert_values.push_back(std::to_string(raid_members_entry.isgroupleader)); insert_values.push_back(std::to_string(raid_members_entry.israidleader)); insert_values.push_back(std::to_string(raid_members_entry.islooter)); -#ifdef BOTS - insert_values.push_back(std::to_string(raid_members_entry.isbot)); -#endif + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", @@ -282,9 +265,7 @@ public: insert_values.push_back(std::to_string(raid_members_entry.isgroupleader)); insert_values.push_back(std::to_string(raid_members_entry.israidleader)); insert_values.push_back(std::to_string(raid_members_entry.islooter)); -#ifdef BOTS - insert_values.push_back(std::to_string(raid_members_entry.isbot)); -#endif + insert_chunks.push_back("(" + implode(",", insert_values) + ")"); } @@ -326,9 +307,7 @@ public: entry.isgroupleader = atoi(row[6]); entry.israidleader = atoi(row[7]); entry.islooter = atoi(row[8]); -#ifdef BOTS - entry.isbot = atoi(row[9]); -#endif + all_entries.push_back(entry); } @@ -361,9 +340,7 @@ public: entry.isgroupleader = atoi(row[6]); entry.israidleader = atoi(row[7]); entry.islooter = atoi(row[8]); -#ifdef BOTS - entry.isbot = atoi(row[9]); -#endif + all_entries.push_back(entry); } diff --git a/common/ruletypes.h b/common/ruletypes.h index 0bb9758b7..d06f9280c 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -622,13 +622,10 @@ RULE_REAL(Bots, LeashDistance, 562500.0f, "Distance a bot is allowed to travel f RULE_BOOL(Bots, AllowApplyPoisonCommand, true, "Allows the use of the bot command 'applypoison'") RULE_BOOL(Bots, AllowApplyPotionCommand, true, "Allows the use of the bot command 'applypotion'") RULE_BOOL(Bots, RestrictApplyPotionToRogue, true, "Restricts the bot command 'applypotion' to rogue-usable potions (i.e., poisons)") -RULE_BOOL(Bots, DisplayHealDamage, false, "Enables the display of bot heal damage to the bot owner client") -RULE_BOOL(Bots, DisplaySpellDamage, false, "Enables the display of bot spell damage to the bot owner client") RULE_BOOL(Bots, OldRaceRezEffects, false, "Older clients had ID 757 for races with high starting STR, but it doesn't seem used anymore") RULE_BOOL(Bots, ResurrectionSickness, true, "Use Resurrection Sickness based on Resurrection spell cast, set to false to disable Resurrection Sickness.") RULE_INT(Bots, OldResurrectionSicknessSpell, 757, "757 is Default Old Resurrection Sickness Spell") RULE_INT(Bots, ResurrectionSicknessSpell, 756, "756 is Default Resurrection Sickness Spell") - RULE_CATEGORY_END() #endif diff --git a/common/types.h b/common/types.h index 2a6355296..b3be97d32 100644 --- a/common/types.h +++ b/common/types.h @@ -57,9 +57,6 @@ typedef const char Const_char; //for perl XS #define safe_delete(d) if(d) { delete d; d=nullptr; } #define safe_delete_array(d) if(d) { delete[] d; d=nullptr; } -//#define safe_delete(d)(_RPTF0(_CRT_WARN,"Testing delete function\n")); -//#define safe_delete(d) if(d) { } -//#define safe_delete_array(d) if(d) { } #define L32(i) ((uint32) i) #define H32(i) ((uint32) (i >> 32)) #define L16(i) ((uint16) i) diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index 114ee942a..221020683 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -27,7 +27,6 @@ 9026|2019_09_09_bots_owner_options_rework.sql|SHOW COLUMNS FROM `bot_owner_options` LIKE 'option_type'|empty| 9027|2020_03_30_bots_view_update.sql|SELECT * FROM db_version WHERE bots_version >= 9027|empty| 9028|2021_06_04_bot_create_combinations.sql|SHOW TABLES LIKE 'bot_create_combinations'|empty| -9029|2022_02_08_bots_raid_members.sql|SELECT * FROM db_version WHERE bots_version >= 9028|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/required/2022_02_08_bots_raid_members.sql b/utils/sql/git/bots/required/2022_02_08_bots_raid_members.sql deleted file mode 100644 index 1f80a1a29..000000000 --- a/utils/sql/git/bots/required/2022_02_08_bots_raid_members.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE `raid_members` ADD COLUMN `isbot` TINYINT(1) NOT NULL DEFAULT 0 COMMENT ''; \ No newline at end of file diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 442c74344..51fc7f875 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -11,7 +11,6 @@ SET(zone_sources beacon.cpp bonuses.cpp bot.cpp - bot_raid.cpp bot_command.cpp bot_database.cpp botspellsai.cpp diff --git a/zone/bot.h b/zone/bot.h index b53128fbd..fa64ae5da 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -35,7 +35,6 @@ #include "../common/global_define.h" #include "guild_mgr.h" #include "worldserver.h" -#include "raids.h" #include @@ -152,8 +151,8 @@ public: ExtraAttackOptions *opts = nullptr); virtual bool HasRaid() { return (GetRaid() ? true : false); } virtual bool HasGroup() { return (GetGroup() ? true : false); } - virtual Raid* GetRaid() { return entity_list.GetRaidByMob(this); } // GetRaidByMob(this); - virtual Group* GetGroup() { return entity_list.GetGroupByMob(this); } // GetGroupByMob; + virtual Raid* GetRaid() { return entity_list.GetRaidByMob(this); } + virtual Group* GetGroup() { return entity_list.GetGroupByMob(this); } // Common, but informal "interfaces" with Client object uint32 CharacterID() { return GetBotID(); } // Just returns the Bot Id @@ -376,15 +375,6 @@ public: static bool CheckDisciplineRecastTimers(Bot *caster, int timer_index); static uint32 GetDisciplineRemainingTime(Bot *caster, int timer_index); - //Raid methods - void PetAIProcess_Raid(); - void AI_Process_Raid(); - bool AICastSpell_Raid(Mob* tar, uint8 iChance, uint32 iSpellTypes); - static void ProcessRaidInvite(Bot* invitee, Client* invitor); - static void ProcessRaidInvite(Client* invitee, Client* invitor); - uint8 GetNumberNeedingHealedInRaidGroup(uint8 hpr, bool includePets); - inline void SetDirtyAutoHaters() { m_dirtyautohaters = true; } - static std::list GetBotSpellsForSpellEffect(Bot* botCaster, int spellEffect); static std::list GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster, int spellEffect, SpellTargetType targetType); static std::list GetBotSpellsBySpellType(Bot* botCaster, uint32 spellType); @@ -620,9 +610,6 @@ public: int32 GetBaseDR() { return _baseDR; } int32 GetBaseCorrup() { return _baseCorrup; } - //Raid additions - Raid* p_raid_instance; - protected: virtual void PetAIProcess(); virtual void BotMeditate(bool isSitting); @@ -687,7 +674,6 @@ private: Timer m_auto_defend_timer; //Timer m_combat_jitter_timer; //bool m_combat_jitter_flag; - bool m_dirtyautohaters; bool m_guard_flag; bool m_hold_flag; bool m_attack_flag; @@ -754,7 +740,6 @@ private: public: static uint8 spell_casting_chances[SPELL_TYPE_COUNT][PLAYER_CLASS_COUNT][EQ::constants::STANCE_TYPE_COUNT][cntHSND]; - }; #endif // BOTS diff --git a/zone/bot_raid.cpp b/zone/bot_raid.cpp deleted file mode 100644 index d7853299a..000000000 --- a/zone/bot_raid.cpp +++ /dev/null @@ -1,2630 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.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 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 -*/ - -#ifdef BOTS - -#include "bot.h" -#include "object.h" -#include "raids.h" -#include "doors.h" -#include "quest_parser_collection.h" -#include "lua_parser.h" -#include "../common/string_util.h" -#include "../common/say_link.h" - -extern volatile bool is_zone_loaded; -extern bool Critical; - -// AI Processing for the Bot object - -constexpr float MAX_CASTER_DISTANCE[PLAYER_CLASS_COUNT] = { - 0, (34 * 34), (24 * 24), (28 * 28), (26 * 26), (42 * 42), 0, (30 * 30), 0, (38 * 38), (54 * 54), (48 * 48), (52 * 52), (50 * 50), (32 * 32), 0 - // W C P R S D M B R S N W M E B B - // A L A N H R N R O H E I A N S E - // R R L G D U K D G M C Z G C T R -}; - -void Bot::AI_Process_Raid() -{ -#define TEST_COMBATANTS() if (!GetTarget() || GetAppearance() == eaDead) { return; } -#define PULLING_BOT (GetPullingFlag() || GetReturningFlag()) -#define NOT_PULLING_BOT (!GetPullingFlag() && !GetReturningFlag()) -#define GUARDING (GetGuardFlag()) -#define NOT_GUARDING (!GetGuardFlag()) -#define HOLDING (GetHoldFlag()) -#define NOT_HOLDING (!GetHoldFlag()) -#define PASSIVE (GetBotStance() == EQ::constants::stancePassive) -#define NOT_PASSIVE (GetBotStance() != EQ::constants::stancePassive) - - Raid* raid = entity_list.GetRaidByBotName(this->GetName()); - Client* bot_owner = (GetBotOwner() && GetBotOwner()->IsClient() ? GetBotOwner()->CastToClient() : nullptr); - uint32 r_group = raid->GetGroup(GetName()); - - LogAI("Bot_Raid: Entered Raid Process() for [{}].", this->GetCleanName()); - - //#pragma region PRIMARY AI SKIP CHECKS - - // Primary reasons for not processing AI - if (!bot_owner || (!raid) || !IsAIControlled()) { - return; - } - - if (bot_owner->IsDead()) { - - SetTarget(nullptr); - SetBotOwner(nullptr); - - return; - } - - // We also need a leash owner and follow mob (subset of primary AI criteria) - Client* leash_owner = nullptr; - if (r_group < 12 && raid->IsGroupLeader(this->GetName())) { - leash_owner = raid->GetLeader(); - } - else if (r_group < 12) { - leash_owner = raid->GetGroupLeader(r_group); - } - else { - leash_owner = bot_owner; - } - - if (!leash_owner) { - return; - } - - //#pragma endregion - - Mob* follow_mob = entity_list.GetMob(GetFollowID()); - if (!follow_mob) { - - follow_mob = leash_owner; - SetFollowID(leash_owner->GetID()); - } - - if (this->mana_timer.Check(false)) { - raid->SendHPManaEndPacketsFrom(this); - } - if (send_hp_update_timer.Check(false)) { - - raid->SendHPManaEndPacketsFrom(this); - - } - // Berserk updates should occur if primary AI criteria are met - if (GetClass() == WARRIOR || GetClass() == BERSERKER) { - - if (!berserk && GetHP() > 0 && GetHPRatio() < 30.0f) { - - entity_list.MessageCloseString(this, false, 200, 0, BERSERK_START, GetName()); - berserk = true; - } - - if (berserk && GetHPRatio() >= 30.0f) { - - entity_list.MessageCloseString(this, false, 200, 0, BERSERK_END, GetName()); - berserk = false; - } - } - - //#pragma region SECONDARY AI SKIP CHECKS - - // Secondary reasons for not processing AI - if (GetPauseAI() || IsStunned() || IsMezzed() || (GetAppearance() == eaDead)) { - - if (IsCasting()) { - InterruptSpell(); - } - - if (IsMyHealRotationSet() || (AmICastingForHealRotation() && m_member_of_heal_rotation->CastingMember() == this)) { - - AdvanceHealRotation(false); - m_member_of_heal_rotation->SetMemberIsCasting(this, false); - } - - return; - } - - //#pragma endregion - - float fm_distance = DistanceSquared(m_Position, follow_mob->GetPosition()); - float lo_distance = DistanceSquared(m_Position, leash_owner->GetPosition()); - float leash_distance = RuleR(Bots, LeashDistance); - - //#pragma region CURRENTLY CASTING CHECKS - - if (IsCasting()) { - - if (IsHealRotationMember() && - m_member_of_heal_rotation->CastingOverride() && - m_member_of_heal_rotation->CastingTarget() != nullptr && - m_member_of_heal_rotation->CastingReady() && - m_member_of_heal_rotation->CastingMember() == this && - !m_member_of_heal_rotation->MemberIsCasting(this)) - { - InterruptSpell(); - } - else if (AmICastingForHealRotation() && m_member_of_heal_rotation->CastingMember() == this) { - - AdvanceHealRotation(false); - return; - } - else if (GetClass() != BARD) { - - if (IsEngaged()) { - return; - } - - if ( - (NOT_GUARDING && fm_distance > GetFollowDistance()) || // Cancel out-of-combat casting if movement to follow mob is required - (GUARDING && DistanceSquared(GetPosition(), GetGuardPoint()) > GetFollowDistance()) // Cancel out-of-combat casting if movement to guard point is required - ) { - InterruptSpell(); - } - - return; - } - } - else if (IsHealRotationMember()) { - m_member_of_heal_rotation->SetMemberIsCasting(this, false); - } - - //#pragma endregion - - // Can't move if rooted... - if (IsRooted() && IsMoving()) { - - StopMoving(); - return; - } - - //#pragma region HEAL ROTATION CASTING CHECKS - - if (IsMyHealRotationSet()) { - - if (AIHealRotation(HealRotationTarget(), UseHealRotationFastHeals())) { - - m_member_of_heal_rotation->SetMemberIsCasting(this); - m_member_of_heal_rotation->UpdateTargetHealingStats(HealRotationTarget()); - AdvanceHealRotation(); - } - else { - - m_member_of_heal_rotation->SetMemberIsCasting(this, false); - AdvanceHealRotation(false); - } - } - - //#pragma endregion - - bool bo_alt_combat = (RuleB(Bots, AllowOwnerOptionAltCombat) && bot_owner->GetBotOption(Client::booAltCombat)); - - //#pragma region ATTACK FLAG - - if (GetAttackFlag()) { // Push owner's target onto our hate list - - if (GetPet() && PULLING_BOT) { - GetPet()->SetPetOrder(m_previous_pet_order); - } - - SetAttackFlag(false); - SetAttackingFlag(false); - SetPullFlag(false); - SetPullingFlag(false); - SetReturningFlag(false); - bot_owner->SetBotPulling(false); - - if (NOT_HOLDING && NOT_PASSIVE) { - - auto attack_target = bot_owner->GetTarget(); - - if (attack_target) { - - InterruptSpell(); - WipeHateList(); - AddToHateList(attack_target, 1); - SetTarget(attack_target); - SetAttackingFlag(); - if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) { - - GetPet()->WipeHateList(); - GetPet()->AddToHateList(attack_target, 1); - GetPet()->SetTarget(attack_target); - } - } - } - } - - //#pragma endregion - - //#pragma region PULL FLAG - - else if (GetPullFlag()) { // Push owner's target onto our hate list and set flags so other bots do not aggro - - SetAttackFlag(false); - SetAttackingFlag(false); - SetPullFlag(false); - SetPullingFlag(false); - SetReturningFlag(false); - bot_owner->SetBotPulling(false); - - if (NOT_HOLDING && NOT_PASSIVE) { - - auto pull_target = bot_owner->GetTarget(); - if (pull_target) { - - Bot::BotGroupSay(this, "Pulling %s to the group..", pull_target->GetCleanName()); - //raid->RaidBotGroupSay(this, 0, 100, "Pulling %s to the group..", pull_target->GetCleanName()); - InterruptSpell(); - WipeHateList(); - AddToHateList(pull_target, 1); - SetTarget(pull_target); - SetPullingFlag(); - bot_owner->SetBotPulling(); - if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 1)) { - - GetPet()->WipeHateList(); - GetPet()->SetTarget(nullptr); - m_previous_pet_order = GetPet()->GetPetOrder(); - GetPet()->SetPetOrder(SPO_Guard); - } - } - } - } - - //#pragma endregion - - //#pragma region ALT COMBAT (ACQUIRE HATE) - - else if (bo_alt_combat && m_alt_combat_hate_timer.Check(false)) { // 'Alt Combat' gives some more 'control' options on how bots process aggro - - // Empty hate list - let's find some aggro - if (!IsEngaged() && NOT_HOLDING && NOT_PASSIVE && (!bot_owner->GetBotPulling() || NOT_PULLING_BOT)) { - - Mob* lo_target = leash_owner->GetTarget(); - if (lo_target && - lo_target->IsNPC() && - !lo_target->IsMezzed() && - ((bot_owner->GetBotOption(Client::booAutoDefend) && lo_target->GetHateAmount(leash_owner)) || leash_owner->AutoAttackEnabled()) && - lo_distance <= leash_distance && - DistanceSquared(m_Position, lo_target->GetPosition()) <= leash_distance && - (CheckLosFN(lo_target) || leash_owner->CheckLosFN(lo_target)) && - IsAttackAllowed(lo_target)) - { - AddToHateList(lo_target, 1); - if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) { - - GetPet()->AddToHateList(lo_target, 1); - GetPet()->SetTarget(lo_target); - } - } - else { - - std::vector raid_group_members = raid->GetRaidGroupMembers(r_group); - for (std::vector::iterator iter = raid_group_members.begin(); iter != raid_group_members.end(); ++iter) { - - Mob* bg_member = iter->member;// bot_group->members[counter]; - if (!bg_member) { - continue; - } - - Mob* bgm_target = bg_member->GetTarget(); - if (!bgm_target || !bgm_target->IsNPC()) { - continue; - } - - if (!bgm_target->IsMezzed() && - ((bot_owner->GetBotOption(Client::booAutoDefend) && bgm_target->GetHateAmount(bg_member)) || leash_owner->AutoAttackEnabled()) && - lo_distance <= leash_distance && - DistanceSquared(m_Position, bgm_target->GetPosition()) <= leash_distance && - (CheckLosFN(bgm_target) || leash_owner->CheckLosFN(bgm_target)) && - IsAttackAllowed(bgm_target)) - { - AddToHateList(bgm_target, 1); - if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) { - - GetPet()->AddToHateList(bgm_target, 1); - GetPet()->SetTarget(bgm_target); - } - - break; - } - } - } - } - } - - //#pragma endregion - - glm::vec3 Goal(0, 0, 0); - - // We have aggro to choose from - if (IsEngaged()) { - - if (rest_timer.Enabled()) { - rest_timer.Disable(); - } - - //#pragma region PULLING FLAG (TARGET VALIDATION) - - if (GetPullingFlag()) { - - if (!GetTarget()) { - - WipeHateList(); - SetTarget(nullptr); - SetPullingFlag(false); - SetReturningFlag(false); - bot_owner->SetBotPulling(false); - if (GetPet()) { - GetPet()->SetPetOrder(m_previous_pet_order); - } - - return; - } - else if (GetTarget()->GetHateList().size()) { - - WipeHateList(); - SetTarget(nullptr); - SetPullingFlag(false); - SetReturningFlag(); - - return; - } - else { - // Default action is to aggress towards enemy - } - } - - //#pragma endregion - - //#pragma region RETURNING FLAG - - else if (GetReturningFlag()) { - - // Need to make it back to group before clearing return flag - if (fm_distance <= GetFollowDistance()) { - - // Once we're back, clear blocking flags so everyone else can join in - SetReturningFlag(false); - bot_owner->SetBotPulling(false); - if (GetPet()) { - GetPet()->SetPetOrder(m_previous_pet_order); - } - } - - // Need to keep puller out of combat until they reach their 'return to' destination - if (HasTargetReflection()) { - - SetTarget(nullptr); - WipeHateList(); - - return; - } - } - - //#pragma endregion - - //#pragma region ALT COMBAT (ACQUIRE TARGET) - - else if (bo_alt_combat && m_alt_combat_hate_timer.Check()) { // Find a mob from hate list to target - - // Raid Group roles can be expounded upon in the future - //r_group is the uint32 group id - auto assist_mob = raid->GetRaidMainAssistOneByName(this->GetName()); - bool find_target = true; - - if (!assist_mob) { - bot_owner->Message(Chat::Yellow, "Assist Mob is nullptr"); - } - - if (assist_mob) { - - if (assist_mob->GetTarget()) { - - if (assist_mob != this) { - - SetTarget(assist_mob->GetTarget()); - if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) { - - // This artificially inflates pet's target aggro..but, less expensive than checking hate each AI process - GetPet()->AddToHateList(assist_mob->GetTarget(), 1); - GetPet()->SetTarget(assist_mob->GetTarget()); - } - } - - find_target = false; - } - else if (assist_mob != this) { - - SetTarget(nullptr); - if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 1)) { - - GetPet()->WipeHateList(); - GetPet()->SetTarget(nullptr); - } - - find_target = false; - } - } - - if (find_target) { - - if (IsRooted()) { - SetTarget(hate_list.GetClosestEntOnHateList(this, true)); - } - else { - - // This will keep bots on target for now..but, future updates will allow for rooting/stunning - SetTarget(hate_list.GetEscapingEntOnHateList(leash_owner, leash_distance)); - if (!GetTarget()) { - SetTarget(hate_list.GetEntWithMostHateOnList(this, nullptr, true)); - } - } - } - } - - //#pragma endregion - - //#pragma region DEFAULT (ACQUIRE TARGET) - - else { - - // Default behavior doesn't have a means of acquiring a target from the bot's hate list.. - // ..that action occurs through commands or out-of-combat checks - // (Use current target, if already in combat) - } - - //#pragma endregion - - //#pragma region VERIFY TARGET AND STANCE - - Mob* tar = GetTarget(); // We should have a target..if not, we're awaiting new orders - if (!tar || PASSIVE) { - - SetTarget(nullptr); - WipeHateList(); - SetAttackFlag(false); - SetAttackingFlag(false); - if (PULLING_BOT) { - - // 'Flags' should only be set on the bot that is pulling - SetPullingFlag(false); - SetReturningFlag(false); - bot_owner->SetBotPulling(false); - if (GetPet()) { - GetPet()->SetPetOrder(m_previous_pet_order); - } - } - - if (GetArchetype() == ARCHETYPE_CASTER) { - BotMeditate(true); - } - - return; - } - - //#pragma endregion - - //#pragma region ATTACKING FLAG (HATE VALIDATION) - - if (GetAttackingFlag() && tar->CheckAggro(this)) { - SetAttackingFlag(false); - } - - //#pragma endregion - - float tar_distance = DistanceSquared(m_Position, tar->GetPosition()); - - //#pragma region TARGET VALIDATION - - // DOUBLE-CHECK THIS CRITERIA - - // Verify that our target has attackable criteria - if (HOLDING || - !tar->IsNPC() || - tar->IsMezzed() || - lo_distance > leash_distance || - tar_distance > leash_distance || - (!GetAttackingFlag() && !CheckLosFN(tar) && !leash_owner->CheckLosFN(tar)) || // This is suppose to keep bots from attacking things behind walls - !IsAttackAllowed(tar) || - (bo_alt_combat && - (!GetAttackingFlag() && NOT_PULLING_BOT && !leash_owner->AutoAttackEnabled() && !tar->GetHateAmount(this) && !tar->GetHateAmount(leash_owner)) - ) - ) - { - // Normally, we wouldn't want to do this without class checks..but, too many issues can arise if we let enchanter animation pets run rampant - if (HasPet()) { - - GetPet()->RemoveFromHateList(tar); - GetPet()->SetTarget(nullptr); - } - - RemoveFromHateList(tar); - SetTarget(nullptr); - - SetAttackFlag(false); - SetAttackingFlag(false); - if (PULLING_BOT) { - - SetPullingFlag(false); - SetReturningFlag(false); - bot_owner->SetBotPulling(false); - if (GetPet()) { - GetPet()->SetPetOrder(m_previous_pet_order); - } - } - - if (IsMoving()) { - StopMoving(); - } - - return; - } - - //#pragma endregion - - // This causes conflicts with default pet handler (bounces between targets) - if (NOT_PULLING_BOT && HasPet() && (GetClass() != 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); - } - - if (DivineAura()) { - return; - } - - if (!(m_PlayerState & static_cast(PlayerState::Aggressive))) { - SendAddPlayerState(PlayerState::Aggressive); - } - - //#pragma region PULLING FLAG (ACTIONABLE RANGE) - - if (GetPullingFlag()) { - - constexpr size_t PULL_AGGRO = 5225; // spells[5225]: 'Throw Stone' - 0 cast time - - if (tar_distance <= (spells[PULL_AGGRO].range * spells[PULL_AGGRO].range)) { - - StopMoving(); - CastSpell(PULL_AGGRO, tar->GetID()); - return; - } - } - - //#pragma endregion - - //#pragma region COMBAT RANGE CALCS - - bool atCombatRange = false; - - const auto* p_item = GetBotItem(EQ::invslot::slotPrimary); - const auto* s_item = GetBotItem(EQ::invslot::slotSecondary); - - bool behind_mob = false; - bool backstab_weapon = false; - if (GetClass() == ROGUE) { - - behind_mob = BehindMob(tar, GetX(), GetY()); // Can be separated for other future use - backstab_weapon = p_item && p_item->GetItemBackstabDamage(); - } - - // Calculate melee distances - float melee_distance_max = 0.0f; - float melee_distance = 0.0f; - { - float size_mod = GetSize(); - float other_size_mod = tar->GetSize(); - - if (GetRace() == RT_DRAGON || GetRace() == RT_WURM || GetRace() == RT_DRAGON_7) { // For races with a fixed size - size_mod = 60.0f; - } - else if (size_mod < 6.0f) { - size_mod = 8.0f; - } - - if (tar->GetRace() == RT_DRAGON || tar->GetRace() == RT_WURM || tar->GetRace() == RT_DRAGON_7) { // For races with a fixed size - other_size_mod = 60.0f; - } - else if (other_size_mod < 6.0f) { - other_size_mod = 8.0f; - } - - if (other_size_mod > size_mod) { - size_mod = other_size_mod; - } - - if (size_mod > 29.0f) { - size_mod *= size_mod; - } - else if (size_mod > 19.0f) { - size_mod *= (size_mod * 2.0f); - } - else { - size_mod *= (size_mod * 4.0f); - } - - // Prevention of ridiculously sized hit boxes - if (size_mod > 10000.0f) { - size_mod = (size_mod / 7.0f); - } - - melee_distance_max = size_mod; - - switch (GetClass()) { - case WARRIOR: - case PALADIN: - case SHADOWKNIGHT: - if (p_item && p_item->GetItem()->IsType2HWeapon()) { - melee_distance = melee_distance_max * 0.45f; - } - else if ((s_item && s_item->GetItem()->IsTypeShield()) || (!p_item && !s_item)) { - melee_distance = melee_distance_max * 0.35f; - } - else { - melee_distance = melee_distance_max * 0.40f; - } - - break; - case NECROMANCER: - case WIZARD: - case MAGICIAN: - case ENCHANTER: - if (p_item && p_item->GetItem()->IsType2HWeapon()) { - melee_distance = melee_distance_max * 0.95f; - } - else { - melee_distance = melee_distance_max * 0.75f; - } - - break; - case ROGUE: - if (behind_mob && backstab_weapon) { - if (p_item->GetItem()->IsType2HWeapon()) { // 'p_item' tested in 'backstab_weapon' check above - melee_distance = melee_distance_max * 0.30f; - } - else { - melee_distance = melee_distance_max * 0.25f; - } - - break; - } - // Fall-through - default: - if (p_item && p_item->GetItem()->IsType2HWeapon()) { - melee_distance = melee_distance_max * 0.70f; - } - else { - melee_distance = melee_distance_max * 0.50f; - } - - break; - } - } - float melee_distance_min = melee_distance / 2.0f; - - // Calculate caster distances - float caster_distance_max = 0.0f; - float caster_distance_min = 0.0f; - float caster_distance = 0.0f; - { - if (GetLevel() >= GetStopMeleeLevel() && GetClass() >= WARRIOR && GetClass() <= BERSERKER) { - caster_distance_max = MAX_CASTER_DISTANCE[(GetClass() - 1)]; - } - - if (caster_distance_max) { - - caster_distance_min = melee_distance_max; - if (caster_distance_max <= caster_distance_min) { - caster_distance_max = caster_distance_min * 1.25f; - } - - caster_distance = ((caster_distance_max + caster_distance_min) / 2); - } - } - - bool atArcheryRange = IsArcheryRange(tar); - - if (GetRangerAutoWeaponSelect()) { - - bool changeWeapons = false; - - if (atArcheryRange && !IsBotArcher()) { - - SetBotArcher(true); - changeWeapons = true; - } - else if (!atArcheryRange && IsBotArcher()) { - - SetBotArcher(false); - changeWeapons = true; - } - - if (changeWeapons) { - ChangeBotArcherWeapons(IsBotArcher()); - } - } - - if (IsBotArcher() && atArcheryRange) { - atCombatRange = true; - } - else if (caster_distance_max && tar_distance <= caster_distance_max) { - atCombatRange = true; - } - else if (tar_distance <= melee_distance) { - atCombatRange = true; - } - - //#pragma endregion - - //#pragma region ENGAGED AT COMBAT RANGE - - // We can fight - if (atCombatRange) { - - //if (IsMoving() || GetCombatJitterFlag()) { // StopMoving() needs to be called so that the jitter timer can be reset - if (IsMoving()) { - - // Since we're using a pseudo-shadowstep for jitter, disregard the combat jitter flag - //if (!GetCombatJitterFlag()) { - StopMoving(CalculateHeadingToTarget(tar->GetX(), tar->GetY())); - //} - - return; - } - - // Combat 'jitter' code - // Note: Combat Jitter is disabled until a working movement solution can be found - if (AI_movement_timer->Check() && (!spellend_timer.Enabled() || GetClass() == BARD)) { - - if (!IsRooted()) { - - if (HasTargetReflection()) { - - if (!tar->IsFeared() && !tar->IsStunned()) { - - if (GetClass() == ROGUE) { - - if (m_evade_timer.Check(false)) { // Attempt to evade - - int timer_duration = (HideReuseTime - GetSkillReuseTime(EQ::skills::SkillHide)) * 1000; - if (timer_duration < 0) { - timer_duration = 0; - } - - m_evade_timer.Start(timer_duration); - if (zone->random.Int(0, 260) < (int)GetSkill(EQ::skills::SkillHide)) { - RogueEvade(tar); - } - - return; - } - } - - //if (tar->IsRooted()) { // Move caster/rogue back from rooted mob - out of combat range, if necessary - - // if (GetArchetype() == ARCHETYPE_CASTER || GetClass() == ROGUE) { - - // if (tar_distance <= melee_distance_max) { - - // if (PlotPositionAroundTarget(this, Goal.x, Goal.y, Goal.z)) { - // //if (PlotPositionBehindMeFacingTarget(tar, Goal.x, Goal.y, Goal.z)) { - - // Teleport(Goal); - // //WalkTo(Goal.x, Goal.y, Goal.z); - // SetCombatJitterFlag(); - - // return; - // } - // } - // } - //} - } - } - //else { - - // if (caster_distance_min && tar_distance < caster_distance_min && !tar->IsFeared()) { // Caster back-off adjustment - - // if (PlotPositionAroundTarget(this, Goal.x, Goal.y, Goal.z)) { - // //if (PlotPositionBehindMeFacingTarget(tar, Goal.x, Goal.y, Goal.z)) { - - // if (DistanceSquared(Goal, tar->GetPosition()) <= caster_distance_max) { - - // Teleport(Goal); - // //WalkTo(Goal.x, Goal.y, Goal.z); - // SetCombatJitterFlag(); - - // return; - // } - // } - // } - // else if (tar_distance < melee_distance_min) { // Melee back-off adjustment - - // if (PlotPositionAroundTarget(this, Goal.x, Goal.y, Goal.z)) { - // //if (PlotPositionBehindMeFacingTarget(tar, Goal.x, Goal.y, Goal.z)) { - - // if (DistanceSquared(Goal, tar->GetPosition()) <= melee_distance_max) { - - // Teleport(Goal); - // //WalkTo(Goal.x, Goal.y, Goal.z); - // SetCombatJitterFlag(); - - // return; - // } - // } - // } - // else if (backstab_weapon && !behind_mob) { // Move the rogue to behind the mob - - // if (PlotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z)) { - // //if (PlotPositionOnArcBehindTarget(tar, Goal.x, Goal.y, Goal.z, melee_distance)) { - - // float distance_squared = DistanceSquared(Goal, tar->GetPosition()); - // if (/*distance_squared >= melee_distance_min && */distance_squared <= melee_distance_max) { - - // Teleport(Goal); - // //RunTo(Goal.x, Goal.y, Goal.z); - // SetCombatJitterFlag(); - - // return; - // } - // } - // } - // else if (m_combat_jitter_timer.Check()) { - - // if (!caster_distance && PlotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z)) { - // //if (!caster_distance && PlotPositionOnArcInFrontOfTarget(tar, Goal.x, Goal.y, Goal.z, melee_distance)) { - - // float distance_squared = DistanceSquared(Goal, tar->GetPosition()); - // if (/*distance_squared >= melee_distance_min && */distance_squared <= melee_distance_max) { - - // Teleport(Goal); - // //WalkTo(Goal.x, Goal.y, Goal.z); - // SetCombatJitterFlag(); - - // return; - // } - // } - // else if (caster_distance && PlotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z)) { - // //else if (caster_distance && PlotPositionOnArcInFrontOfTarget(tar, Goal.x, Goal.y, Goal.z, caster_distance)) { - - // float distance_squared = DistanceSquared(Goal, tar->GetPosition()); - // if (/*distance_squared >= caster_distance_min && */distance_squared <= caster_distance_max) { - - // Teleport(Goal); - // //WalkTo(Goal.x, Goal.y, Goal.z); - // SetCombatJitterFlag(); - - // return; - // } - // } - // } - - // if (!IsFacingMob(tar)) { - - // FaceTarget(tar); - // return; - // } - //} - } - else { - - if (!IsSitting() && !IsFacingMob(tar)) { - - FaceTarget(tar); - return; - } - } - } - - if (!IsBotNonSpellFighter() && AI_EngagedCastCheck()) { - return; - } - - // Up to this point, GetTarget() has been safe to dereference since the initial - // TEST_COMBATANTS() call. Due to the chance of the target dying and our pointer - // being nullified, we need to test it before dereferencing to avoid crashes - - if (IsBotArcher() && ranged_timer.Check(false)) { // Can shoot mezzed, stunned and dead!? - - TEST_COMBATANTS(); - if (GetTarget()->GetHPRatio() <= 99.0f) { - BotRangedAttack(tar); - } - } - else if (!IsBotArcher() && GetLevel() < GetStopMeleeLevel()) { - - // We can't fight if we don't have a target, are stun/mezzed or dead.. - // Stop attacking if the target is enraged - TEST_COMBATANTS(); - if (tar->IsEnraged() && !BehindMob(tar, GetX(), GetY())) { - return; - } - - // First, special attack per class (kick, backstab etc..) - TEST_COMBATANTS(); - DoClassAttacks(tar); - - TEST_COMBATANTS(); - if (attack_timer.Check()) { // Process primary weapon attacks - - Attack(tar, EQ::invslot::slotPrimary); - - TEST_COMBATANTS(); - TriggerDefensiveProcs(tar, EQ::invslot::slotPrimary, false); - - TEST_COMBATANTS(); - //TryWeaponProc(p_item, tar, EQ::invslot::slotPrimary); - TryCombatProcs(p_item, tar, EQ::invslot::slotPrimary); - // bool tripleSuccess = false; - - TEST_COMBATANTS(); - if (CanThisClassDoubleAttack()) { - - if (CheckBotDoubleAttack()) { - Attack(tar, EQ::invslot::slotPrimary, true); - } - - TEST_COMBATANTS(); - if (GetSpecialAbility(SPECATK_TRIPLE) && CheckBotDoubleAttack(true)) { - // tripleSuccess = true; - Attack(tar, EQ::invslot::slotPrimary, true); - } - - TEST_COMBATANTS(); - // quad attack, does this belong here?? - if (GetSpecialAbility(SPECATK_QUAD) && CheckBotDoubleAttack(true)) { - Attack(tar, EQ::invslot::slotPrimary, true); - } - } - - TEST_COMBATANTS(); - // Live AA - Flurry, Rapid Strikes ect (Flurry does not require Triple Attack). - int32 flurrychance = (aabonuses.FlurryChance + spellbonuses.FlurryChance + itembonuses.FlurryChance); - if (flurrychance) { - - if (zone->random.Int(0, 100) < flurrychance) { - - MessageString(Chat::NPCFlurry, YOU_FLURRY); - Attack(tar, EQ::invslot::slotPrimary, false); - - TEST_COMBATANTS(); - Attack(tar, EQ::invslot::slotPrimary, false); - } - } - - TEST_COMBATANTS(); - //int32 ExtraAttackChanceBonus = (spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance); - auto ExtraAttackChanceBonus = - (spellbonuses.ExtraAttackChance[0] + itembonuses.ExtraAttackChance[0] + - aabonuses.ExtraAttackChance[0]); - if (ExtraAttackChanceBonus) { - - if (p_item && p_item->GetItem()->IsType2HWeapon()) { - - if (zone->random.Int(0, 100) < ExtraAttackChanceBonus) { - Attack(tar, EQ::invslot::slotPrimary, false); - } - } - } - } - - TEST_COMBATANTS(); - if (attack_dw_timer.Check() && CanThisClassDualWield()) { // Process secondary weapon attacks - - const EQ::ItemData* s_itemdata = nullptr; - // Can only dual wield without a weapon if you're a monk - if (s_item || (GetClass() == MONK)) { - - if (s_item) { - s_itemdata = s_item->GetItem(); - } - - int weapon_type = 0; // No weapon type. - bool use_fist = true; - if (s_itemdata) { - - weapon_type = s_itemdata->ItemType; - use_fist = false; - } - - if (use_fist || !s_itemdata->IsType2HWeapon()) { - - float DualWieldProbability = 0.0f; - - int32 Ambidexterity = (aabonuses.Ambidexterity + spellbonuses.Ambidexterity + itembonuses.Ambidexterity); - DualWieldProbability = ((GetSkill(EQ::skills::SkillDualWield) + GetLevel() + Ambidexterity) / 400.0f); // 78.0 max - - int32 DWBonus = (spellbonuses.DualWieldChance + itembonuses.DualWieldChance); - DualWieldProbability += (DualWieldProbability * float(DWBonus) / 100.0f); - - float random = zone->random.Real(0, 1); - if (random < DualWieldProbability) { // Max 78% of DW - - Attack(tar, EQ::invslot::slotSecondary); // Single attack with offhand - - TEST_COMBATANTS(); - TryCombatProcs(s_item, tar, EQ::invslot::slotSecondary); - //TryWeaponProc(s_item, tar, EQ::invslot::slotSecondary); - - TEST_COMBATANTS(); - if (CanThisClassDoubleAttack() && CheckBotDoubleAttack()) { - - if (tar->GetHP() > -10) { - Attack(tar, EQ::invslot::slotSecondary); // Single attack with offhand - } - } - } - } - } - } - } - - if (GetAppearance() == eaDead) { - return; - } - } - - //#pragma endregion - - //#pragma region ENGAGED NOT AT COMBAT RANGE - - else { // To far away to fight (GetTarget() validity can be iffy below this point - including outer scopes) - - // This code actually gets processed when we are too far away from target and have not engaged yet, too - if (/*!GetCombatJitterFlag() && */AI_movement_timer->Check() && (!spellend_timer.Enabled() || GetClass() == BARD)) { // Pursue processing - - if (GetTarget() && !IsRooted()) { - - LogAI("Pursuing [{}] while engaged", GetTarget()->GetCleanName()); - Goal = GetTarget()->GetPosition(); - if (DistanceSquared(m_Position, Goal) <= leash_distance) { - RunTo(Goal.x, Goal.y, Goal.z); - } - else { - - WipeHateList(); - SetTarget(nullptr); - if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) { - - GetPet()->WipeHateList(); - GetPet()->SetTarget(nullptr); - } - } - - return; - } - else { - - if (IsMoving()) { - StopMoving(); - } - return; - } - } - - if (GetTarget() && GetTarget()->IsFeared() && !spellend_timer.Enabled() && AI_think_timer->Check()) { - - if (!IsFacingMob(GetTarget())) { - FaceTarget(GetTarget()); - } - - // This is a mob that is fleeing either because it has been feared or is low on hitpoints - AI_PursueCastCheck(); // This appears to always return true..can't trust for success/fail - - return; - } - } // End not in combat range - -//#pragma endregion - - if (!IsMoving() && !spellend_timer.Enabled()) { // This may actually need work... - - if (GetTarget() && AI_EngagedCastCheck()) { - BotMeditate(false); - } - else if (GetArchetype() == ARCHETYPE_CASTER) { - BotMeditate(true); - } - - return; - } - } - else { // Out-of-combat behavior - - SetAttackFlag(false); - SetAttackingFlag(false); - if (!bot_owner->GetBotPulling()) { - - SetPullingFlag(false); - SetReturningFlag(false); - } - - //#pragma region AUTO DEFEND - - // This is as close as I could get without modifying the aggro mechanics and making it an expensive process... - // 'class Client' doesn't make use of hate_list... - if (RuleB(Bots, AllowOwnerOptionAutoDefend) && bot_owner->GetBotOption(Client::booAutoDefend)) { - - if (!m_auto_defend_timer.Enabled()) { - - m_auto_defend_timer.Start(zone->random.Int(250, 1250)); // random timer to simulate 'awareness' (cuts down on scanning overhead) - return; - } - - if (m_auto_defend_timer.Check() && bot_owner->GetAggroCount()) { - - if (NOT_HOLDING && NOT_PASSIVE) { - - auto xhaters = bot_owner->GetXTargetAutoMgr(); - if (xhaters && !xhaters->empty()) { - - for (auto hater_iter : xhaters->get_list()) { - - if (!hater_iter.spawn_id) { - continue; - } - - if (bot_owner->GetBotPulling() && bot_owner->GetTarget() && hater_iter.spawn_id == bot_owner->GetTarget()->GetID()) { - continue; - } - - auto hater = entity_list.GetMob(hater_iter.spawn_id); - if (hater && !hater->IsMezzed() && DistanceSquared(hater->GetPosition(), bot_owner->GetPosition()) <= leash_distance) { - - // This is roughly equivilent to npc attacking a client pet owner - AddToHateList(hater, 1); - SetTarget(hater); - SetAttackingFlag(); - if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) { - - GetPet()->AddToHateList(hater, 1); - GetPet()->SetTarget(hater); - } - - m_auto_defend_timer.Disable(); - - return; - } - } - } - } - } - } - - //#pragma endregion - - SetTarget(nullptr); - - if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 1)) { - - GetPet()->WipeHateList(); - GetPet()->SetTarget(nullptr); - } - - if (m_PlayerState & static_cast(PlayerState::Aggressive)) { - SendRemovePlayerState(PlayerState::Aggressive); - } - - //#pragma region OK TO IDLE - - // Ok to idle - if ((NOT_GUARDING && fm_distance <= GetFollowDistance()) || (GUARDING && DistanceSquared(GetPosition(), GetGuardPoint()) <= GetFollowDistance())) { - - if (!IsMoving() && AI_think_timer->Check() && !spellend_timer.Enabled()) { - - if (NOT_PASSIVE) { - - if (!AI_IdleCastCheck() && !IsCasting() && GetClass() != BARD) { - BotMeditate(true); - } - } - else { - - if (GetClass() != BARD) { - BotMeditate(true); - } - } - - return; - } - } - - // Non-engaged movement checks - if (AI_movement_timer->Check() && (!IsCasting() || GetClass() == BARD)) { - - if (GUARDING) { - Goal = GetGuardPoint(); - } - else { - Goal = follow_mob->GetPosition(); - } - float destination_distance = DistanceSquared(GetPosition(), Goal); - - if ((!bot_owner->GetBotPulling() || PULLING_BOT) && (destination_distance > GetFollowDistance())) { - - if (!IsRooted()) { - - if (rest_timer.Enabled()) { - rest_timer.Disable(); - } - - bool running = true; - - if (destination_distance < GetFollowDistance() + BOT_FOLLOW_DISTANCE_WALK) { - running = false; - } - - if (running) { - RunTo(Goal.x, Goal.y, Goal.z); - } - else { - WalkTo(Goal.x, Goal.y, Goal.z); - } - - return; - } - } - else { - - if (IsMoving()) { - - StopMoving(); - return; - } - } - } - - // Basically, bard bots get a chance to cast idle spells while moving - if (GetClass() == BARD && IsMoving() && NOT_PASSIVE) { - - if (!spellend_timer.Enabled() && AI_think_timer->Check()) { - - AI_IdleCastCheck(); - return; - } - } - - //#pragma endregion - - } - -#undef TEST_COMBATANTS -#undef PULLING_BOT -#undef NOT_PULLING_BOT -#undef GUARDING -#undef NOT_GUARDING -#undef HOLDING -#undef NOT_HOLDING -#undef PASSIVE -#undef NOT_PASSIVE -} - -// AI Processing for a Bot object's pet if Bot is a member of a raid -void Bot::PetAIProcess_Raid() { - if (!HasPet() || !GetPet() || !GetPet()->IsNPC()) - return; - - Mob* BotOwner = this->GetBotOwner(); - NPC* botPet = this->GetPet()->CastToNPC(); - if (!botPet->GetOwner() || !botPet->GetID() || !botPet->GetOwnerID()) { - Kill(); - return; - } - - if (!botPet->IsAIControlled() || botPet->GetAttackTimer().Check(false) || botPet->IsCasting() || !botPet->GetOwner()->IsBot()) - return; - - if (IsEngaged()) { - if (botPet->IsRooted()) - botPet->SetTarget(hate_list.GetClosestEntOnHateList(botPet)); - else - 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. - // It causes some cpu stress but without it, it was causing the bot/pet to aggro behind wall, floor etc... - if (!botPet->CheckLosFN(botPet->GetTarget()) || botPet->GetTarget()->IsMezzed() || !botPet->IsAttackAllowed(GetTarget())) { - botPet->WipeHateList(); - botPet->SetTarget(botPet->GetOwner()); - return; - } - - botPet->FaceTarget(botPet->GetTarget()); - bool is_combat_range = botPet->CombatRange(botPet->GetTarget()); - // Ok, we're engaged, each class type has a special AI - // Only melee class will go to melee. Casters and healers will stay behind, following the leader by default. - // I should probably make the casters staying in place so they can cast.. - - // Ok, we 're a melee or any other class lvl<12. Yes, because after it becomes hard to go in melee for casters.. even for bots.. - if (is_combat_range) { - botPet->GetAIMovementTimer()->Check(); - if (botPet->IsMoving()) { - botPet->SetHeading(botPet->GetTarget()->GetHeading()); - if (moved) { - moved = false; - botPet->SetRunAnimSpeed(0); - } - } - - if (!botPet->IsMoving()) { - float newX = 0; - float newY = 0; - float newZ = 0; - bool petHasAggro = false; - if (botPet->GetTarget() && botPet->GetTarget()->GetHateTop() && botPet->GetTarget()->GetHateTop() == botPet) - petHasAggro = true; - - if (botPet->GetClass() == ROGUE && !petHasAggro && !botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY())) { - // Move the rogue to behind the mob - if (botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ)) { - botPet->RunTo(newX, newY, newZ); - return; - } - } - else if (GetTarget() == botPet->GetTarget() && !petHasAggro && !botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY())) { - // If the bot owner and the bot are fighting the same mob, then move the pet to the rear arc of the mob - if (botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ)) { - botPet->RunTo(newX, newY, newZ); - return; - } - } - else if (DistanceSquaredNoZ(botPet->GetPosition(), botPet->GetTarget()->GetPosition()) < botPet->GetTarget()->GetSize()) { - // Let's try to adjust our melee range so we don't appear to be bunched up - bool isBehindMob = false; - bool moveBehindMob = false; - if (botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY())) - isBehindMob = true; - - if (!isBehindMob && !petHasAggro) - moveBehindMob = true; - - if (botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ, moveBehindMob)) { - botPet->RunTo(newX, newY, newZ); - return; - } - } - } - - // we can't fight if we don't have a target, are stun/mezzed or dead.. - if (botPet->GetTarget() && !botPet->IsStunned() && !botPet->IsMezzed() && (botPet->GetAppearance() != eaDead)) { - // check the delay on the attack - if (botPet->GetAttackTimer().Check()) { - // Stop attacking while we are on a front arc and the target is enraged - if (!botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY()) && botPet->GetTarget()->IsEnraged()) - return; - - if (botPet->Attack(GetTarget(), EQ::invslot::slotPrimary)) // try the main hand - if (botPet->GetTarget()) { - // We're a pet so we re able to dual attack - int32 RandRoll = zone->random.Int(0, 99); - if (botPet->CanThisClassDoubleAttack() && (RandRoll < (botPet->GetLevel() + NPCDualAttackModifier))) { - if (botPet->Attack(botPet->GetTarget(), EQ::invslot::slotPrimary)) {} - } - } - - if (botPet->GetOwner()->IsBot()) { - int aa_chance = 0; - int aa_skill = 0; - // Magician AA - aa_skill += botPet->GetOwner()->GetAA(aaElementalAlacrity); - // Necromancer AA - aa_skill += botPet->GetOwner()->GetAA(aaQuickeningofDeath); - // Beastlord AA - aa_skill += botPet->GetOwner()->GetAA(aaWardersAlacrity); - if (aa_skill >= 1) - aa_chance += ((aa_skill > 5 ? 5 : aa_skill) * 4); - - if (aa_skill >= 6) - aa_chance += ((aa_skill - 5 > 3 ? 3 : aa_skill - 5) * 7); - - if (aa_skill >= 9) - aa_chance += ((aa_skill - 8 > 3 ? 3 : aa_skill - 8) * 3); - - if (aa_skill >= 12) - aa_chance += ((aa_skill - 11) * 1); - - - //aa_chance += botPet->GetOwner()->GetAA(aaCompanionsAlacrity) * 3; - - if (zone->random.Int(1, 100) < aa_chance) - Flurry(nullptr); - } - - // Ok now, let's check pet's offhand. - if (botPet->GetAttackDWTimer().Check() && botPet->GetOwnerID() && botPet->GetOwner() && ((botPet->GetOwner()->GetClass() == MAGICIAN) || (botPet->GetOwner()->GetClass() == NECROMANCER) || (botPet->GetOwner()->GetClass() == SHADOWKNIGHT) || (botPet->GetOwner()->GetClass() == BEASTLORD))) { - if (botPet->GetOwner()->GetLevel() >= 24) { - float DualWieldProbability = ((botPet->GetSkill(EQ::skills::SkillDualWield) + botPet->GetLevel()) / 400.0f); - DualWieldProbability -= zone->random.Real(0, 1); - if (DualWieldProbability < 0) { - botPet->Attack(botPet->GetTarget(), EQ::invslot::slotSecondary); - if (botPet->CanThisClassDoubleAttack()) { - int32 RandRoll = zone->random.Int(0, 99); - if (RandRoll < (botPet->GetLevel() + 20)) - botPet->Attack(botPet->GetTarget(), EQ::invslot::slotSecondary); - } - } - } - } - if (!botPet->GetOwner()) - return; - - // Special attack - botPet->DoClassAttacks(botPet->GetTarget()); - } - // See if the pet can cast any spell - botPet->AI_EngagedCastCheck(); - } - } - else { - // Now, if we cannot reach our target - if (!botPet->HateSummon()) { - if (botPet->GetTarget() && botPet->AI_PursueCastCheck()) {} - else if (botPet->GetTarget() && botPet->GetAIMovementTimer()->Check()) { - botPet->SetRunAnimSpeed(0); - if (!botPet->IsRooted()) { - LogAI("Pursuing [{}] while engaged", botPet->GetTarget()->GetCleanName()); - botPet->RunTo(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ()); - return; - } - else { - botPet->SetHeading(botPet->GetTarget()->GetHeading()); - if (moved) { - moved = false; - StopNavigation(); - botPet->StopNavigation(); - } - } - } - } - } - } - else { - // Ok if we're not engaged, what's happening.. - if (botPet->GetTarget() != botPet->GetOwner()) - botPet->SetTarget(botPet->GetOwner()); - - if (!IsMoving()) - botPet->AI_IdleCastCheck(); - - if (botPet->GetAIMovementTimer()->Check()) { - switch (pStandingPetOrder) { - case SPO_Follow: { - float dist = DistanceSquared(botPet->GetPosition(), botPet->GetTarget()->GetPosition()); - botPet->SetRunAnimSpeed(0); - if (dist > 184) { - botPet->RunTo(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ()); - return; - } - else { - botPet->SetHeading(botPet->GetTarget()->GetHeading()); - if (moved) { - moved = false; - StopNavigation(); - botPet->StopNavigation(); - } - } - break; - } - case SPO_Sit: - botPet->SetAppearance(eaSitting); - break; - case SPO_Guard: - botPet->NextGuardPosition(); - break; - } - } - } -} - -std::vector Raid::GetRaidGroupMembers(uint32 gid) -{ - std::vector raid_group_members; - raid_group_members.clear(); - - for (int i = 0; i < MAX_RAID_MEMBERS; ++i) - { - if (members[i].member && members[i].GroupNumber == gid) - { - raid_group_members.push_back(members[i]); - } - } - return raid_group_members; -} - -bool Bot::AICastSpell_Raid(Mob* tar, uint8 iChance, uint32 iSpellTypes) { - - // Bot AI Raid - - Raid* raid = entity_list.GetRaidByBotName(this->GetName()); - uint32 r_group = raid->GetGroup(GetName()); - if (!raid) - return false; - - if (!tar) { - return false; - } - - if (!AI_HasSpells()) - return false; - - if (iChance < 100) { - if (zone->random.Int(0, 100) > iChance) { - return false; - } - } - - if (tar->GetAppearance() == eaDead) { - if ((tar->IsClient() && tar->CastToClient()->GetFeigned()) || tar->IsBot()) { - // do nothing - } - else { - return false; - } - } - - uint8 botClass = GetClass(); - uint8 botLevel = GetLevel(); - - bool checked_los = false; //we do not check LOS until we are absolutely sure we need to, and we only do it once. - - bool castedSpell = false; - - BotSpell botSpell; - botSpell.SpellId = 0; - botSpell.SpellIndex = 0; - botSpell.ManaCost = 0; - - switch (iSpellTypes) { - case SpellType_Mez: { - if (tar->GetBodyType() != BT_Giant) { - if (!checked_los) { - if (!CheckLosFN(tar)) - break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - - checked_los = true; - } - - //TODO - //Check if single target or AoE mez is best - //if (TARGETS ON MT IS => 3 THEN botSpell = AoEMez) - //if (TARGETS ON MT IS <= 2 THEN botSpell = BestMez) - - botSpell = GetBestBotSpellForMez(this); - - if (botSpell.SpellId == 0) - break; - - Mob* addMob = GetFirstIncomingMobToMez(this, botSpell); - - if (!addMob) { - //Say("!addMob."); - break; - } - - if (!(!addMob->IsImmuneToSpell(botSpell.SpellId, this) && addMob->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) - break; - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, addMob, botSpell.ManaCost); - - if (castedSpell) - BotGroupSay(this, "Attempting to mez %s.", addMob->GetCleanName()); - //raid->RaidBotGroupSay(this, 0, 100, "Attempting to mez %s.", addMob->GetCleanName()); - } - break; - } - case SpellType_Heal: { - if (tar->DontHealMeBefore() < Timer::GetCurrentTime()) { - uint8 hpr = (uint8)tar->GetHPRatio(); - bool hasAggro = false; - bool isPrimaryHealer = false; - - if (this->IsRaidGrouped()) { - isPrimaryHealer = IsGroupHealer(); - } - - if (hpr < 95 || (tar->IsClient() && (hpr < 95)) || (botClass == BARD)) { - if (tar->GetClass() == NECROMANCER) { - // Give necromancers a chance to go lifetap something or cleric can spend too much mana on a necro - if (hpr >= 40) { - break; - } - } - - if (tar->GetClass() == SHAMAN) { - // Give shaman the chance to canni without wasting the cleric's mana - if (hpr >= 80) { - break; - } - } - - // Evaluate the situation - if ((IsEngaged()) && ((botClass == CLERIC) || (botClass == DRUID) || (botClass == SHAMAN) || (botClass == PALADIN))) { - if (tar->GetTarget() && tar->GetTarget()->GetHateTop() && tar->GetTarget()->GetHateTop() == tar) { - hasAggro = true; - } - - if (hpr < 35) { - botSpell = GetBestBotSpellForFastHeal(this); - } - else if (hpr >= 35 && hpr < 70) { - if (GetNumberNeedingHealedInRaidGroup(60, false) >= 3) - botSpell = GetBestBotSpellForGroupHeal(this); - - if (botSpell.SpellId == 0) - botSpell = GetBestBotSpellForPercentageHeal(this); - } - else if (hpr >= 70 && hpr < 95) { - if (GetNumberNeedingHealedInRaidGroup(80, false) >= 3) - botSpell = GetBestBotSpellForGroupHealOverTime(this); - - if (hasAggro) - botSpell = GetBestBotSpellForPercentageHeal(this); - } - else { - if (!tar->FindType(SE_HealOverTime)) - botSpell = GetBestBotSpellForHealOverTime(this); - } - } - else if ((botClass == CLERIC) || (botClass == DRUID) || (botClass == SHAMAN) || (botClass == PALADIN)) { - if (GetNumberNeedingHealedInRaidGroup(40, true) >= 2) { - botSpell = GetBestBotSpellForGroupCompleteHeal(this); - - if (botSpell.SpellId == 0) - botSpell = GetBestBotSpellForGroupHeal(this); - - if (botSpell.SpellId == 0) - botSpell = GetBestBotSpellForGroupHealOverTime(this); - - if (hpr < 40) { - if (botSpell.SpellId == 0) - botSpell = GetBestBotSpellForPercentageHeal(this); - } - } - else if (GetNumberNeedingHealedInRaidGroup(60, true) >= 2) { - botSpell = GetBestBotSpellForGroupHeal(this); - - if (botSpell.SpellId == 0) - botSpell = GetBestBotSpellForGroupHealOverTime(this); - - if (hpr < 40) { - if (botSpell.SpellId == 0) - botSpell = GetBestBotSpellForPercentageHeal(this); - } - } - else if (hpr < 40) - botSpell = GetBestBotSpellForPercentageHeal(this); - else if (hpr >= 40 && hpr < 75) - botSpell = GetBestBotSpellForRegularSingleTargetHeal(this); - else { - if (hpr < 90 && !tar->FindType(SE_HealOverTime)) - botSpell = GetBestBotSpellForHealOverTime(this); - } - } - else { - float hpRatioToCast = 0.0f; - - switch (this->GetBotStance()) { - case EQ::constants::stanceEfficient: - case EQ::constants::stanceAggressive: - hpRatioToCast = isPrimaryHealer ? 90.0f : 50.0f; - break; - case EQ::constants::stanceBalanced: - hpRatioToCast = isPrimaryHealer ? 95.0f : 75.0f; - break; - case EQ::constants::stanceReactive: - hpRatioToCast = isPrimaryHealer ? 100.0f : 90.0f; - break; - case EQ::constants::stanceBurn: - case EQ::constants::stanceBurnAE: - hpRatioToCast = isPrimaryHealer ? 75.0f : 25.0f; - break; - default: - hpRatioToCast = isPrimaryHealer ? 100.0f : 0.0f; - break; - } - - //If we're at specified mana % or below, don't heal as hybrid - if (tar->GetHPRatio() <= hpRatioToCast) - botSpell = GetBestBotSpellForRegularSingleTargetHeal(this); - } - - if (botSpell.SpellId == 0) - botSpell = GetBestBotSpellForRegularSingleTargetHeal(this); - - if (botSpell.SpellId == 0) - botSpell = GetFirstBotSpellForSingleTargetHeal(this); - - if (botSpell.SpellId == 0 && botClass == BARD) { - botSpell = GetFirstBotSpellBySpellType(this, SpellType_Heal); - } - - // If there is still no spell id, then there isn't going to be one so we are done - if (botSpell.SpellId == 0) - break; - - // Can we cast this spell on this target? - if (!(spells[botSpell.SpellId].target_type == ST_GroupTeleport || spells[botSpell.SpellId].target_type == ST_Target || tar == this) - && !(tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) - break; - - uint32 TempDontHealMeBeforeTime = tar->DontHealMeBefore(); - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontHealMeBeforeTime); - - if (castedSpell) { - /*if(TempDontHealMeBeforeTime != tar->DontHealMeBefore()) - tar->SetDontHealMeBefore(TempDontHealMeBeforeTime); - - // For non-HoT heals, do a 4 second delay - // TODO: Replace this code with logic that calculates the delay based on number of clerics in rotation - // and ignores heals for anyone except the main tank - if(!IsHealOverTimeSpell(botSpell.SpellId)) { - if(IsCompleteHealSpell(botSpell.SpellId)) { - // Complete Heal 4 second rotation - tar->SetDontHealMeBefore(Timer::GetCurrentTime() + 4000); - } - else { - tar->SetDontHealMeBefore(Timer::GetCurrentTime() + 1000); - } - }*/ - if (botClass != BARD) { - if (IsGroupSpell(botSpell.SpellId)) { - if (IsRaidGrouped()) { - uint32 r_group = raid->GetGroup(GetName()); - BotGroupSay(this, "Casting %s.", spells[botSpell.SpellId].name); - //raid->RaidBotGroupSay(this, 0, 100, "Casting %s.", spells[botSpell.SpellId].name); - std::vector raid_group_members = raid->GetRaidGroupMembers(r_group); - //for (std::vector::iterator iter = raid_group_members.begin(); iter != raid_group_members.end(); ++iter) { - for (int i = 0; i < raid_group_members.size(); ++i){ - if (raid_group_members.at(i).member && !raid_group_members.at(i).member->qglobal) { - raid_group_members.at(i).member->SetDontHealMeBefore(Timer::GetCurrentTime() + 1000); - } - } - } - } - else { - if (tar != this) //we don't need spam of bots healing themselves - BotGroupSay(this, "Casting %s on %s", spells[botSpell.SpellId].name, tar->GetCleanName()); - tar->SetDontHealMeBefore(Timer::GetCurrentTime() + 2000); - } - } - } - } - } - break; - } - case SpellType_Root: { - if (!tar->IsRooted() && tar->DontRootMeBefore() < Timer::GetCurrentTime()) { - if (!checked_los) { - if (!CheckLosFN(tar)) - break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - - checked_los = true; - } - - // TODO: If there is a ranger in the group then don't allow root spells - - botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); - - if (botSpell.SpellId == 0) - break; - - if (tar->CanBuffStack(botSpell.SpellId, botLevel, true) == 0) - break; - - uint32 TempDontRootMeBefore = tar->DontRootMeBefore(); - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontRootMeBefore); - - if (TempDontRootMeBefore != tar->DontRootMeBefore()) - tar->SetDontRootMeBefore(TempDontRootMeBefore); - } - break; - } - case SpellType_Buff: { - if (tar->DontBuffMeBefore() < Timer::GetCurrentTime()) { - std::list buffSpellList = GetBotSpellsBySpellType(this, SpellType_Buff); - - for (std::list::iterator itr = buffSpellList.begin(); itr != buffSpellList.end(); ++itr) { - BotSpell selectedBotSpell = *itr; - - if (selectedBotSpell.SpellId == 0) - continue; - - // no buffs with illusions.. use #bot command to cast illusions - if (IsEffectInSpell(selectedBotSpell.SpellId, SE_Illusion) && tar != this) - continue; - - //no teleport spells use #bot command to cast teleports - if (IsEffectInSpell(selectedBotSpell.SpellId, SE_Teleport) || IsEffectInSpell(selectedBotSpell.SpellId, SE_Succor)) - continue; - - // can not cast buffs for your own pet only on another pet that isn't yours - if ((spells[selectedBotSpell.SpellId].target_type == ST_Pet) && (tar != this->GetPet())) - continue; - - // Validate target - - if (!((spells[selectedBotSpell.SpellId].target_type == ST_Target || spells[selectedBotSpell.SpellId].target_type == ST_Pet || tar == this || - spells[selectedBotSpell.SpellId].target_type == ST_Group || spells[selectedBotSpell.SpellId].target_type == ST_GroupTeleport || - (botClass == BARD && spells[selectedBotSpell.SpellId].target_type == ST_AEBard)) - && !tar->IsImmuneToSpell(selectedBotSpell.SpellId, this) - && (tar->CanBuffStack(selectedBotSpell.SpellId, botLevel, true) >= 0))) { - continue; - } - - // Put the zone levitate and movement check here since bots are able to bypass the client casting check - if ((IsEffectInSpell(selectedBotSpell.SpellId, SE_Levitate) && !zone->CanLevitate()) - || (IsEffectInSpell(selectedBotSpell.SpellId, SE_MovementSpeed) && !zone->CanCastOutdoor())) { - if (botClass != BARD || !IsSpellUsableThisZoneType(selectedBotSpell.SpellId, zone->GetZoneType())) { - continue; - } - } - - switch (tar->GetArchetype()) - { - case ARCHETYPE_CASTER: - //TODO: probably more caster specific spell effects in here - if (IsEffectInSpell(selectedBotSpell.SpellId, SE_AttackSpeed) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ATK) || - IsEffectInSpell(selectedBotSpell.SpellId, SE_STR) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ReverseDS)) - { - continue; - } - break; - case ARCHETYPE_MELEE: - if (IsEffectInSpell(selectedBotSpell.SpellId, SE_IncreaseSpellHaste) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ManaPool) || - IsEffectInSpell(selectedBotSpell.SpellId, SE_CastingLevel) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ManaRegen_v2) || - IsEffectInSpell(selectedBotSpell.SpellId, SE_CurrentMana)) - { - continue; - } - break; - case ARCHETYPE_HYBRID: - //Hybrids get all buffs - default: - break; - } - - if (botClass == ENCHANTER && IsEffectInSpell(selectedBotSpell.SpellId, SE_Rune)) - { - float manaRatioToCast = 75.0f; - - switch (this->GetBotStance()) { - case EQ::constants::stanceEfficient: - manaRatioToCast = 90.0f; - break; - case EQ::constants::stanceBalanced: - case EQ::constants::stanceAggressive: - manaRatioToCast = 75.0f; - break; - case EQ::constants::stanceReactive: - case EQ::constants::stanceBurn: - case EQ::constants::stanceBurnAE: - manaRatioToCast = 50.0f; - break; - default: - manaRatioToCast = 75.0f; - break; - } - - //If we're at specified mana % or below, don't rune as enchanter - if (this->GetManaRatio() <= manaRatioToCast) - break; - } - - if (CheckSpellRecastTimers(this, itr->SpellIndex)) - { - - uint32 TempDontBuffMeBefore = tar->DontBuffMeBefore(); - - castedSpell = AIDoSpellCast(selectedBotSpell.SpellIndex, tar, selectedBotSpell.ManaCost, &TempDontBuffMeBefore); - - if (TempDontBuffMeBefore != tar->DontBuffMeBefore()) - tar->SetDontBuffMeBefore(TempDontBuffMeBefore); - } - - if (castedSpell) - break; - } - } - break; - } - case SpellType_Escape: { - uint8 hpr = (uint8)GetHPRatio(); - bool mayGetAggro = false; - -#ifdef IPC - if (hpr <= 5 || (IsNPC() && CastToNPC()->IsInteractive() && tar != this)) -#else - if (hpr > 15 && ((botClass == WIZARD) || (botClass == ENCHANTER) || (botClass == RANGER))) - mayGetAggro = HasOrMayGetAggro(); //classes have hate reducing spells - - if (hpr <= 15 || mayGetAggro) -#endif - { - botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); - - if (botSpell.SpellId == 0) - break; - - if (IsInvulnerabilitySpell(botSpell.SpellId)) - tar = this; //target self for invul type spells - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); - } - break; - } - case SpellType_Nuke: { - if ((tar->GetHPRatio() <= 95.0f) || ((botClass == BARD) || (botClass == SHAMAN) || (botClass == ENCHANTER))) - { - if (!checked_los) { - if (!CheckLosFN(tar)) - break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - - checked_los = true; - } - - if (botClass == CLERIC || botClass == ENCHANTER) - { - float manaRatioToCast = 75.0f; - - switch (this->GetBotStance()) { - case EQ::constants::stanceEfficient: - manaRatioToCast = 90.0f; - break; - case EQ::constants::stanceBalanced: - manaRatioToCast = 75.0f; - break; - case EQ::constants::stanceReactive: - case EQ::constants::stanceAggressive: - manaRatioToCast = 50.0f; - break; - case EQ::constants::stanceBurn: - case EQ::constants::stanceBurnAE: - manaRatioToCast = 25.0f; - break; - default: - manaRatioToCast = 50.0f; - break; - } - - //If we're at specified mana % or below, don't nuke as cleric or enchanter - if (this->GetManaRatio() <= manaRatioToCast) - break; - } - - if (botClass == MAGICIAN || botClass == SHADOWKNIGHT || botClass == NECROMANCER || botClass == PALADIN || botClass == RANGER || botClass == DRUID || botClass == CLERIC) { - if (tar->GetBodyType() == BT_Undead || tar->GetBodyType() == BT_SummonedUndead || tar->GetBodyType() == BT_Vampire) - botSpell = GetBestBotSpellForNukeByTargetType(this, ST_Undead); - else if (tar->GetBodyType() == BT_Summoned || tar->GetBodyType() == BT_Summoned2 || tar->GetBodyType() == BT_Summoned3) - botSpell = GetBestBotSpellForNukeByTargetType(this, ST_Summoned); - } - - if (botClass == PALADIN || botClass == DRUID || botClass == CLERIC || botClass == ENCHANTER || botClass == WIZARD) { - if (botSpell.SpellId == 0) { - uint8 stunChance = (tar->IsCasting() ? 30 : 15); - - if (botClass == PALADIN) - stunChance = 50; - - if (!tar->GetSpecialAbility(UNSTUNABLE) && !tar->IsStunned() && (zone->random.Int(1, 100) <= stunChance)) { - botSpell = GetBestBotSpellForStunByTargetType(this, ST_Target); - } - } - } - - if (botClass == WIZARD && botSpell.SpellId == 0) { - botSpell = GetBestBotWizardNukeSpellByTargetResists(this, tar); - } - - if (botSpell.SpellId == 0) - botSpell = GetBestBotSpellForNukeByTargetType(this, ST_Target); - - if (botSpell.SpellId == 0) - break; - - if (!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && (tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0))) - break; - - if (IsFearSpell(botSpell.SpellId)) { - // don't let fear cast if the npc isn't snared or rooted - if (tar->GetSnaredAmount() == -1) { - if (!tar->IsRooted()) - break; - } - } - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); - } - break; - } - case SpellType_Dispel: { - if (tar->GetHPRatio() > 95.0f) { - if (!checked_los) { - if (!CheckLosFN(tar)) - break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - - checked_los = true; - } - - botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); - - if (botSpell.SpellId == 0) - break; - - // TODO: Check target to see if there is anything to dispel - - if (tar->CountDispellableBuffs() > 0) { - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); - } - } - break; - } - case SpellType_Pet: { - //keep mobs from recasting pets when they have them. - if (!IsPet() && !GetPetID() && !IsBotCharmer()) { - if (botClass == WIZARD) { - auto buffs_max = GetMaxBuffSlots(); - auto my_buffs = GetBuffs(); - int familiar_buff_slot = -1; - if (buffs_max && my_buffs) { - for (int index = 0; index < buffs_max; ++index) { - if (IsEffectInSpell(my_buffs[index].spellid, SE_Familiar)) { - MakePet(my_buffs[index].spellid, spells[my_buffs[index].spellid].teleport_zone); - familiar_buff_slot = index; - break; - } - } - } - if (GetPetID()) - break; - - if (familiar_buff_slot >= 0) { - BuffFadeBySlot(familiar_buff_slot); - break; - } - - botSpell = GetFirstBotSpellBySpellType(this, SpellType_Pet); - } - else if (botClass == MAGICIAN) { - botSpell = GetBestBotMagicianPetSpell(this); - } - else { - botSpell = GetFirstBotSpellBySpellType(this, SpellType_Pet); - } - - if (botSpell.SpellId == 0) - break; - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); - } - break; - } - case SpellType_InCombatBuff: { - - if (botClass == SHAMAN) { - checked_los = true; - - std::list inCombatBuffList = GetBotSpellsBySpellType(this, SpellType_InCombatBuff); - - for (std::list::iterator itr = inCombatBuffList.begin(); itr != inCombatBuffList.end(); ++itr) { - BotSpell selectedBotSpell = *itr; - - if (selectedBotSpell.SpellId == 0) - continue; - - if (CheckSpellRecastTimers(this, itr->SpellIndex)) - { - if (!(!tar->IsImmuneToSpell(selectedBotSpell.SpellId, this) && (spells[selectedBotSpell.SpellId].buff_duration < 1 || tar->CanBuffStack(selectedBotSpell.SpellId, botLevel, true) >= 0))) - continue; - - //short duration buffs or other buffs only to be cast during combat. - if (IsSelfConversionSpell(selectedBotSpell.SpellId)) { - if (GetManaRatio() > 90.0f || GetHPRatio() < 50.0f || GetHPRatio() < (GetManaRatio() + 10.0f)) - break; //don't cast if low hp, lots of mana, or if mana is higher than hps - } - - castedSpell = AIDoSpellCast(selectedBotSpell.SpellIndex, tar, selectedBotSpell.ManaCost); - } - - if (castedSpell) - break; - } - } - else if (botClass == BARD) { - if (tar->DontBuffMeBefore() < Timer::GetCurrentTime()) { - std::list inCombatBuffList = GetBotSpellsBySpellType(this, SpellType_InCombatBuff); - - for (std::list::iterator itr = inCombatBuffList.begin(); itr != inCombatBuffList.end(); ++itr) { - BotSpell selectedBotSpell = *itr; - - if (selectedBotSpell.SpellId == 0) - continue; - - if (CheckSpellRecastTimers(this, itr->SpellIndex)) { - uint32 TempDontBuffMeBefore = tar->DontBuffMeBefore(); - - // no buffs with illusions.. use #bot command to cast illusions - if (IsEffectInSpell(selectedBotSpell.SpellId, SE_Illusion) && tar != this) - continue; - - //no teleport spells use #bot command to cast teleports - if (IsEffectInSpell(selectedBotSpell.SpellId, SE_Teleport) || IsEffectInSpell(selectedBotSpell.SpellId, SE_Succor)) - continue; - - // can not cast buffs for your own pet only on another pet that isn't yours - if ((spells[selectedBotSpell.SpellId].target_type == ST_Pet) && (tar != this->GetPet())) - continue; - - // Validate target - - if (!((spells[selectedBotSpell.SpellId].target_type == ST_Target || spells[selectedBotSpell.SpellId].target_type == ST_Pet || tar == this || - spells[selectedBotSpell.SpellId].target_type == ST_Group || spells[selectedBotSpell.SpellId].target_type == ST_GroupTeleport || - (botClass == BARD && spells[selectedBotSpell.SpellId].target_type == ST_AEBard)) - && !tar->IsImmuneToSpell(selectedBotSpell.SpellId, this) - && (tar->CanBuffStack(selectedBotSpell.SpellId, botLevel, true) >= 0))) { - continue; - } - - // Put the zone levitate and movement check here since bots are able to bypass the client casting check - if ((IsEffectInSpell(selectedBotSpell.SpellId, SE_Levitate) && !zone->CanLevitate()) - || (IsEffectInSpell(selectedBotSpell.SpellId, SE_MovementSpeed) && !zone->CanCastOutdoor())) { - if (!IsSpellUsableThisZoneType(selectedBotSpell.SpellId, zone->GetZoneType())) { - continue; - } - } - - if (!IsGroupSpell(selectedBotSpell.SpellId)) { - //Only check archetype if song is not a group spell - switch (tar->GetArchetype()) { - case ARCHETYPE_CASTER: - //TODO: probably more caster specific spell effects in here - if (IsEffectInSpell(selectedBotSpell.SpellId, SE_AttackSpeed) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ATK) || - IsEffectInSpell(selectedBotSpell.SpellId, SE_STR) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ReverseDS)) - { - continue; - } - break; - case ARCHETYPE_MELEE: - if (IsEffectInSpell(selectedBotSpell.SpellId, SE_IncreaseSpellHaste) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ManaPool) || - IsEffectInSpell(selectedBotSpell.SpellId, SE_CastingLevel) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ManaRegen_v2) || - IsEffectInSpell(selectedBotSpell.SpellId, SE_CurrentMana)) - { - continue; - } - break; - case ARCHETYPE_HYBRID: - //Hybrids get all buffs - default: - break; - } - } - - castedSpell = AIDoSpellCast(selectedBotSpell.SpellIndex, tar, selectedBotSpell.ManaCost, &TempDontBuffMeBefore); - - if (TempDontBuffMeBefore != tar->DontBuffMeBefore()) - tar->SetDontBuffMeBefore(TempDontBuffMeBefore); - } - - if (castedSpell) - break; - } - } - } - break; - } - case SpellType_Lifetap: { - if (GetHPRatio() < 90.0f) { - if (!checked_los) { - if (!CheckLosFN(tar)) - break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - - checked_los = true; - } - - botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); - - if (botSpell.SpellId == 0) - break; - - if (!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && (tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0))) - break; - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); - } - break; - } - case SpellType_Snare: { - if (tar->DontSnareMeBefore() < Timer::GetCurrentTime()) { - if (!checked_los) { - if (!CheckLosFN(tar)) - break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - - checked_los = true; - } - - botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); - - if (botSpell.SpellId == 0) - break; - - if (!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) - break; - - uint32 TempDontSnareMeBefore = tar->DontSnareMeBefore(); - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontSnareMeBefore); - - if (TempDontSnareMeBefore != tar->DontSnareMeBefore()) - tar->SetDontSnareMeBefore(TempDontSnareMeBefore); - } - break; - } - case SpellType_DOT: { - if ((tar->GetHPRatio() <= 98.0f) && (tar->DontDotMeBefore() < Timer::GetCurrentTime()) && (tar->GetHPRatio() > 15.0f)) { - if (!checked_los) { - if (!CheckLosFN(tar)) - break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - - checked_los = true; - } - - if (GetClass() == BARD) { - std::list dotList = GetPrioritizedBotSpellsBySpellType(this, SpellType_DOT); - - const int maxDotSelect = 5; - int dotSelectCounter = 0; - - for (std::list::iterator itr = dotList.begin(); itr != dotList.end(); ++itr) { - BotSpell selectedBotSpell = *itr; - - if (selectedBotSpell.SpellId == 0) - continue; - - if (CheckSpellRecastTimers(this, itr->SpellIndex)) - { - - if (!(!tar->IsImmuneToSpell(selectedBotSpell.SpellId, this) && tar->CanBuffStack(selectedBotSpell.SpellId, botLevel, true) >= 0)) - continue; - - uint32 TempDontDotMeBefore = tar->DontDotMeBefore(); - - castedSpell = AIDoSpellCast(selectedBotSpell.SpellIndex, tar, selectedBotSpell.ManaCost, &TempDontDotMeBefore); - - if (TempDontDotMeBefore != tar->DontDotMeBefore()) - tar->SetDontDotMeBefore(TempDontDotMeBefore); - } - - dotSelectCounter++; - - if ((dotSelectCounter == maxDotSelect) || castedSpell) - break; - } - } - else { - std::list dotList = GetBotSpellsBySpellType(this, SpellType_DOT); - - const int maxDotSelect = 5; - int dotSelectCounter = 0; - - for (std::list::iterator itr = dotList.begin(); itr != dotList.end(); ++itr) { - BotSpell selectedBotSpell = *itr; - - if (selectedBotSpell.SpellId == 0) - continue; - - if (CheckSpellRecastTimers(this, itr->SpellIndex)) - { - - if (!(!tar->IsImmuneToSpell(selectedBotSpell.SpellId, this) && tar->CanBuffStack(selectedBotSpell.SpellId, botLevel, true) >= 0)) - continue; - - uint32 TempDontDotMeBefore = tar->DontDotMeBefore(); - - castedSpell = AIDoSpellCast(selectedBotSpell.SpellIndex, tar, selectedBotSpell.ManaCost, &TempDontDotMeBefore); - - if (TempDontDotMeBefore != tar->DontDotMeBefore()) - tar->SetDontDotMeBefore(TempDontDotMeBefore); - } - - dotSelectCounter++; - - if ((dotSelectCounter == maxDotSelect) || castedSpell) - break; - } - } - } - break; - } - case SpellType_Slow: { - if (tar->GetHPRatio() <= 99.0f) { - - if (!checked_los) { - if (!CheckLosFN(tar)) - break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - - checked_los = true; - } - - switch (botClass) { - case BARD: { - // probably needs attackable check - std::list botSongList = GetPrioritizedBotSpellsBySpellType(this, SpellType_Slow); - for (auto iter : botSongList) { - if (!iter.SpellId) - continue; - if (!CheckSpellRecastTimers(this, iter.SpellIndex)) - continue; - if (spells[iter.SpellId].zone_type != -1 && zone->GetZoneType() != -1 && spells[iter.SpellId].zone_type != zone->GetZoneType()) // is this bit or index? - continue; - if (spells[iter.SpellId].target_type != ST_Target) - continue; - if (tar->CanBuffStack(iter.SpellId, botLevel, true) < 0) - continue; - - castedSpell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost); - if (castedSpell) - break; - } - - break; - } - case ENCHANTER: { - botSpell = GetBestBotSpellForMagicBasedSlow(this); - break; - } - case SHAMAN: - case BEASTLORD: { - botSpell = GetBestBotSpellForDiseaseBasedSlow(this); - - if (botSpell.SpellId == 0 || ((tar->GetMR() - 50) < (tar->GetDR() + spells[botSpell.SpellId].resist_difficulty))) - botSpell = GetBestBotSpellForMagicBasedSlow(this); - break; - } - } - - if (botSpell.SpellId == 0) - break; - - if (!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) - break; - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); - - if (castedSpell && GetClass() != BARD) - BotGroupSay(this, "Attempting to slow %s.", tar->GetCleanName()); - } - break; - } - case SpellType_Debuff: { - if ((tar->GetHPRatio() <= 99.0f) || ((botClass == BARD) || (botClass == SHAMAN) || (botClass == ENCHANTER) || (botClass == DRUID)) && (tar->GetHPRatio() > 40.0f)) - { - if (!checked_los) { - if (!CheckLosFN(tar)) - break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - - checked_los = true; - } - - botSpell = GetBestBotSpellForResistDebuff(this, tar); - - if (botSpell.SpellId == 0) - botSpell = GetDebuffBotSpell(this, tar); - - if (botSpell.SpellId == 0) - break; - - if (!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && (tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0))) - break; - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); - } - break; - } - case SpellType_Cure: { - if (GetNeedsCured(tar) && (tar->DontCureMeBefore() < Timer::GetCurrentTime()) && !(GetNumberNeedingHealedInRaidGroup(25, false) > 0) && !(GetNumberNeedingHealedInRaidGroup(40, false) > 2)) - { - botSpell = GetBestBotSpellForCure(this, tar); - - if (botSpell.SpellId == 0) - break; - - uint32 TempDontCureMeBeforeTime = tar->DontCureMeBefore(); - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontCureMeBeforeTime); - - if (castedSpell) { - if (botClass != BARD) { - if (IsGroupSpell(botSpell.SpellId)) { - if (this->IsRaidGrouped()) { - if (r_group) { - std::vector raid_group_members = raid->GetRaidGroupMembers(r_group); - for (std::vector::iterator iter = raid_group_members.begin(); iter != raid_group_members.end(); ++iter) { - if (iter->member && !iter->member->qglobal) { - if (TempDontCureMeBeforeTime != tar->DontCureMeBefore()) - iter->member->SetDontCureMeBefore(Timer::GetCurrentTime() + 4000); - } - } - } - } - } - else { - if (TempDontCureMeBeforeTime != tar->DontCureMeBefore()) - tar->SetDontCureMeBefore(Timer::GetCurrentTime() + 4000); - } - } - } - } - break; - } - case SpellType_Resurrect: - break; - case SpellType_HateRedux: { - // assumed group member at this point - if (GetClass() == BARD) { - std::list botSongList = GetPrioritizedBotSpellsBySpellType(this, SpellType_HateRedux); - for (auto iter : botSongList) { - if (!iter.SpellId) - continue; - if (!CheckSpellRecastTimers(this, iter.SpellIndex)) - continue; - if (spells[iter.SpellId].zone_type != -1 && zone->GetZoneType() != -1 && spells[iter.SpellId].zone_type != zone->GetZoneType()) // is this bit or index? - continue; - if (spells[iter.SpellId].target_type != ST_Target) - continue; - if (tar->CanBuffStack(iter.SpellId, botLevel, true) < 0) - continue; - - castedSpell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost); - if (castedSpell) { - BotGroupSay(this, "Attempting to reduce hate on %s.", tar->GetCleanName()); - break; - } - } - } - - break; - } - case SpellType_InCombatBuffSong: { - if (GetClass() != BARD || tar != this) // In-Combat songs can be cast Out-of-Combat in preparation for battle - break; - - std::list botSongList = GetPrioritizedBotSpellsBySpellType(this, SpellType_InCombatBuffSong); - for (auto iter : botSongList) { - if (!iter.SpellId) - continue; - if (!CheckSpellRecastTimers(this, iter.SpellIndex)) - continue; - if (spells[iter.SpellId].zone_type != -1 && zone->GetZoneType() != -1 && spells[iter.SpellId].zone_type != zone->GetZoneType()) // is this bit or index? - continue; - switch (spells[iter.SpellId].target_type) { - case ST_AEBard: - case ST_AECaster: - case ST_GroupTeleport: - case ST_Group: - case ST_Self: - break; - default: - continue; - } - if (tar->CanBuffStack(iter.SpellId, botLevel, true) < 0) - continue; - - castedSpell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost); - if (castedSpell) - break; - } - - break; - } - case SpellType_OutOfCombatBuffSong: { - if (GetClass() != BARD || tar != this || IsEngaged()) // Out-of-Combat songs can not be cast in combat - break; - - std::list botSongList = GetPrioritizedBotSpellsBySpellType(this, SpellType_OutOfCombatBuffSong); - for (auto iter : botSongList) { - if (!iter.SpellId) - continue; - if (!CheckSpellRecastTimers(this, iter.SpellIndex)) - continue; - if (spells[iter.SpellId].zone_type != -1 && zone->GetZoneType() != -1 && spells[iter.SpellId].zone_type != zone->GetZoneType()) // is this bit or index? - continue; - switch (spells[iter.SpellId].target_type) { - case ST_AEBard: - case ST_AECaster: - case ST_GroupTeleport: - case ST_Group: - case ST_Self: - break; - default: - continue; - } - if (tar->CanBuffStack(iter.SpellId, botLevel, true) < 0) - continue; - - castedSpell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost); - if (castedSpell) - break; - } - - break; - } - case SpellType_PreCombatBuff: { - break; - } - case SpellType_PreCombatBuffSong: { - break; - } - default: - break; - } - - return castedSpell; -} - -void Raid::RaidBotGroupSay(Bot* b, uint8 language, uint8 lang_skill, const char* msg, ...) -{ - if (!b) - return; - - char buf[1000]; - va_list ap; - va_start(ap, msg); - vsnprintf(buf, 1000, msg, ap); - va_end(ap); - - uint32 groupToUse = GetGroup(b->GetName()); - - if (groupToUse > 11) - return; - - auto pack = new ServerPacket(ServerOP_RaidGroupSay, sizeof(ServerRaidMessage_Struct) + strlen(msg) + 1); - ServerRaidMessage_Struct* rga = (ServerRaidMessage_Struct*)pack->pBuffer; - rga->rid = GetID(); - rga->gid = groupToUse; - rga->language = language; - rga->lang_skill = lang_skill; - strn0cpy(rga->from, b->GetName(), 64); - - strcpy(rga->message, buf); // this is safe because we are allocating enough space for the entire msg above - - worldserver.SendPacket(pack); - //safe_delete(pack); -} - -uint8 Bot::GetNumberNeedingHealedInRaidGroup(uint8 hpr, bool includePets) { - uint8 needHealed = 0; - Raid* raid = nullptr; - raid = entity_list.GetRaidByBotName(this->GetName()); - uint32 r_group = raid->GetGroup(this->GetName()); - std::vector raid_group_members = raid->GetRaidGroupMembers(r_group); - //for (std::vector::iterator iter = raid_group_members.begin(); iter != raid_group_members.end(); ++iter) { - for (int i = 0; i< raid_group_members.size(); ++i) { - if (raid_group_members.at(i).member && !raid_group_members.at(i).member->qglobal) { - if (raid_group_members.at(i).member->GetHPRatio() <= hpr) - needHealed++; - - if (includePets) { - if (raid_group_members.at(i).member->GetPet() && raid_group_members.at(i).member->GetPet()->GetHPRatio() <= hpr) - needHealed++; - } - } - } - return needHealed; -} -#endif diff --git a/zone/bot_raid.h b/zone/bot_raid.h deleted file mode 100644 index 66d55bab8..000000000 --- a/zone/bot_raid.h +++ /dev/null @@ -1,47 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.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 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 -*/ - -#ifndef BOT_RAID_H -#define BOT_RAID_H - -#ifdef BOTS - -#include "bot_structs.h" -#include "mob.h" -#include "client.h" -#include "pets.h" -#include "heal_rotation.h" -#include "groups.h" -#include "corpse.h" -#include "zonedb.h" -#include "zone_store.h" -#include "string_ids.h" -#include "../common/misc_functions.h" -#include "../common/global_define.h" -#include "guild_mgr.h" -#include "worldserver.h" - -#include - -extern WorldServer worldserver; - -//void Bot::PetAIProcess_Raid(); - -#endif // BOTS - -#endif // BOT_RAID_H diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index 0cd6a2d52..2653af032 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -3,7 +3,7 @@ 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 ogroupf the License. + 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 @@ -31,13 +31,6 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { - // Bot AI - Raid* raid = entity_list.GetRaidByBotName(this->GetName()); - if (raid) { - return AICastSpell_Raid(tar, iChance, iSpellTypes); - //return true; - } - if (!tar) { return false; } diff --git a/zone/client.cpp b/zone/client.cpp index de602ada7..6324db2a0 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -807,10 +807,9 @@ void Client::QueuePacket(const EQApplicationPacket* app, bool ack_req, CLIENT_CO // todo: save packets for later use AddPacket(app, ack_req); } - else if (eqs) - { - eqs->QueuePacket(app, ack_req); - } + else + if(eqs) + eqs->QueuePacket(app, ack_req); } void Client::FastQueuePacket(EQApplicationPacket** app, bool ack_req, CLIENT_CONN_STATUS required_state) { @@ -821,7 +820,7 @@ void Client::FastQueuePacket(EQApplicationPacket** app, bool ack_req, CLIENT_CON return; } else { - if(eqs) + if(eqs) eqs->FastQueuePacket((EQApplicationPacket **)app, ack_req); else if (app && (*app)) delete *app; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index c3760cdbe..ee66f02b2 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include #include #include -#include "bot.h" #ifdef _WINDOWS #define snprintf _snprintf @@ -73,7 +72,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #ifdef BOTS #include "bot.h" -#include "bot_command.h" #endif extern QueryServ* QServ; @@ -590,31 +588,6 @@ void Client::CompleteConnect() if (raid) { SetRaidGrouped(true); raid->LearnMembers(); -#ifdef BOTS - std::list bots_list; - database.botdb.LoadBotsList(this->CharacterID(), bots_list); - std::vector r_members = raid->GetMembers(); - for (const RaidMember& iter : r_members) { - if (iter.membername) { - for (const BotsAvailableList& b_iter : bots_list) - { - if (strcmp(iter.membername, b_iter.Name) == 0) - { - char buffer[71] = "^spawn "; - strcat(buffer, iter.membername); - bot_command_real_dispatch(this, buffer); - Bot* b = entity_list.GetBotByBotName(iter.membername); - if (b) - { - b->SetRaidGrouped(true); - b->p_raid_instance = raid; - //b->SetFollowID(this->GetID()); - } - } - } - } - } -#endif raid->VerifyRaid(); raid->GetRaidDetails(); /* @@ -6993,12 +6966,7 @@ void Client::Handle_OP_GroupInvite2(const EQApplicationPacket *app) } #ifdef BOTS else if (Invitee->IsBot()) { - Client* inviter = entity_list.GetClientByName(gis->inviter_name); - //Bot* invitee = entity_list.GetBotByBotName(gis->invitee_name); - if (inviter->IsRaidGrouped()) - Bot::ProcessRaidInvite(Invitee->CastToBot(), inviter); - else - Bot::ProcessBotGroupInvite(this, std::string(Invitee->GetName())); + Bot::ProcessBotGroupInvite(this, std::string(Invitee->GetName())); } #endif } @@ -11437,7 +11405,7 @@ void Client::Handle_OP_QueryUCSServerStatus(const EQApplicationPacket *app) } } -void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app) +void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app) { if (app->size < sizeof(RaidGeneral_Struct)) { LogError("Wrong size: OP_RaidCommand, size=[{}], expected at least [{}]", app->size, sizeof(RaidGeneral_Struct)); @@ -11445,256 +11413,218 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app) return; } - RaidGeneral_Struct* raid_command_packet = (RaidGeneral_Struct*)app->pBuffer; + RaidGeneral_Struct *raid_command_packet = (RaidGeneral_Struct*)app->pBuffer; switch (raid_command_packet->action) { - case RaidCommandInviteIntoExisting: - case RaidCommandInvite: { + case RaidCommandInviteIntoExisting: + case RaidCommandInvite: { -#ifdef BOTS + Client *player_to_invite = entity_list.GetClientByName(raid_command_packet->player_name); - Bot* player_to_invite = nullptr; - Client* player_to_invite_owner = nullptr; + if (!player_to_invite) + break; - if (entity_list.GetBotByBotName(raid_command_packet->player_name)) { - Bot* player_to_invite = entity_list.GetBotByBotName(raid_command_packet->player_name); - Client* player_to_invite_owner = player_to_invite->GetOwner()->CastToClient(); - Group* player_to_invite_group = player_to_invite->GetGroup(); + Group *player_to_invite_group = player_to_invite->GetGroup(); - if (!player_to_invite) { + if (player_to_invite->HasRaid()) { + Message(Chat::Red, "%s is already in a raid.", player_to_invite->GetName()); break; } - //Not allowed: Invite a bot that is already within a raid. - if (player_to_invite->IsRaidGrouped()) { - MessageString(Chat::White, ALREADY_IN_RAID, GetName()); //must invite members not in raid... - return; - } - - // Not allowed: Invite a bot that is not owned by the invitor - if (player_to_invite->IsBot() && - player_to_invite->CastToBot()->GetOwner()->CastToClient()->CharacterID() != - player_to_invite_owner->CharacterID()) { - Message(Chat::Red, "%s is not your Bot. You can only invite your Bots, or players grouped with bots.", player_to_invite->GetName()); - } - - // Not allowed: Invite a bot that is in a group but the bot is not the group leader - if (player_to_invite_group && !player_to_invite_group->IsLeader(player_to_invite->CastToMob())) { - Message(Chat::Red, "You can only invite group leaders or ungrouped bots. Try %s instead.", player_to_invite_group->GetLeader()->GetName()); + if (player_to_invite_group && player_to_invite_group->IsGroupMember(this)) { + MessageString(Chat::Red, ALREADY_IN_PARTY); break; } - Bot::ProcessRaidInvite(player_to_invite, player_to_invite_owner); - break; - } - else - { -#endif - Client* player_to_invite = entity_list.GetClientByName(raid_command_packet->player_name); - - if (!player_to_invite) - break; - - Group* player_to_invite_group = player_to_invite->GetGroup(); - - if (player_to_invite->HasRaid()) { - Message(Chat::Red, "%s is already in a raid.", player_to_invite->GetName()); - break; - } - - if (player_to_invite_group && player_to_invite_group->IsGroupMember(this)) { - MessageString(Chat::Red, ALREADY_IN_PARTY); - break; - } - // Not allowed: Invite a client that is in a group but not the groupleader - if (player_to_invite_group && !player_to_invite_group->IsLeader(player_to_invite)) { - Message(Chat::Red, "You can only invite an ungrouped player or group leader to join your raid."); - break; - } - - /* Send out invite to the client */ - auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); - RaidGeneral_Struct* raid_command = (RaidGeneral_Struct*)outapp->pBuffer; - - strn0cpy(raid_command->leader_name, raid_command_packet->leader_name, 64); - strn0cpy(raid_command->player_name, raid_command_packet->player_name, 64); - - raid_command->parameter = 0; - raid_command->action = 20; - - player_to_invite->QueuePacket(outapp); - - safe_delete(outapp); - + if (player_to_invite_group && !player_to_invite_group->IsLeader(player_to_invite)) { + Message(Chat::Red, "You can only invite an ungrouped player or group leader to join your raid."); break; } -#ifdef BOTS - } -#endif - case RaidCommandAcceptInvite: { - Client* player_accepting_invite = entity_list.GetClientByName(raid_command_packet->player_name); + /* Send out invite to the client */ + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); + RaidGeneral_Struct *raid_command = (RaidGeneral_Struct*)outapp->pBuffer; -#ifdef BOTS - // If the accepting client is in a group with a Bot or the invitor is in a group with a Bot, send the invite to Bot:ProcessRaidInvite - // instead of remaining here. - Bot* b = nullptr; - Client* invitee = entity_list.GetClientByName(raid_command_packet->leader_name); - Client* invitor = entity_list.GetClientByName(raid_command_packet->player_name); - Group* g_invitee = invitee->GetGroup(); - Group* g_invitor = invitor->GetGroup(); + strn0cpy(raid_command->leader_name, raid_command_packet->leader_name, 64); + strn0cpy(raid_command->player_name, raid_command_packet->player_name, 64); - if (invitee && invitee->IsRaidGrouped()) { - invitor->MessageString(Chat::White, ALREADY_IN_RAID, GetName()); //group failed, must invite members not in raid... - return; - } + raid_command->parameter = 0; + raid_command->action = 20; - bool invitor_has_bot = false; - bool invitee_has_bot = false; + player_to_invite->QueuePacket(outapp); + + safe_delete(outapp); - if (g_invitor && g_invitor->IsLeader(invitor)) - { - for (int x = 0; x < 6; x++) - { - if (g_invitor->members[x] && g_invitor->members[x]->IsBot()) - { - b = entity_list.GetBotByBotName(g_invitor->members[x]->GetName()); - invitee_has_bot = true; - } - } - } - if (g_invitee && g_invitee->IsLeader(invitee)) - { - for (int x = 0; x < 6; x++) - { - if (g_invitee->members[x] && g_invitee->members[x]->IsBot()) - { - b = entity_list.GetBotByBotName(g_invitee->members[x]->GetName()); - invitee_has_bot = true; - break; - } - } - } - if (invitor_has_bot || invitee_has_bot) { - Bot::ProcessRaidInvite(invitee, invitor); //two clients with one or both having groups with bots break; } - else if (invitee && invitee->IsBot()) - { - Bot::ProcessRaidInvite(b, player_accepting_invite); //client inviting a bot - break; - } - -#endif - if (player_accepting_invite) { - if (IsRaidGrouped()) { - player_accepting_invite->MessageString(Chat::White, ALREADY_IN_RAID, GetName()); //group failed, must invite members not in raid... - return; - } - Raid* raid = entity_list.GetRaidByClient(player_accepting_invite); - if (raid) { - raid->VerifyRaid(); - Group* group = GetGroup(); - if (group) { - if (group->GroupCount() + raid->RaidCount() > MAX_RAID_MEMBERS) { - player_accepting_invite->Message(Chat::Red, "Invite failed, group invite would create a raid larger than the maximum number of members allowed."); - return; - } + case RaidCommandAcceptInvite: { + Client *player_accepting_invite = entity_list.GetClientByName(raid_command_packet->player_name); + if (player_accepting_invite) { + if (IsRaidGrouped()) { + player_accepting_invite->MessageString(Chat::White, ALREADY_IN_RAID, GetName()); //group failed, must invite members not in raid... + return; } - else { - if (1 + raid->RaidCount() > MAX_RAID_MEMBERS) { - player_accepting_invite->Message(Chat::Red, "Invite failed, member invite would create a raid larger than the maximum number of members allowed."); - return; - } - } - if (group) {//add us all - uint32 free_group_id = raid->GetFreeGroup(); - Client* addClient = nullptr; - for (int x = 0; x < 6; x++) { - if (group->members[x]) { - Client* c = nullptr; - if (group->members[x]->IsClient()) - c = group->members[x]->CastToClient(); - else - continue; - - if (!addClient) - { - addClient = c; - raid->SetGroupLeader(addClient->GetName()); - } - - raid->SendRaidCreate(c); - raid->SendMakeLeaderPacketTo(raid->leadername, c); - if (group->IsLeader(group->members[x])) - raid->AddMember(c, free_group_id, false, true); - else - raid->AddMember(c, free_group_id); - raid->SendBulkRaid(c); - if (raid->IsLocked()) { - raid->SendRaidLockTo(c); - } + Raid *raid = entity_list.GetRaidByClient(player_accepting_invite); + if (raid) { + raid->VerifyRaid(); + Group *group = GetGroup(); + if (group) { + if (group->GroupCount() + raid->RaidCount() > MAX_RAID_MEMBERS) { + player_accepting_invite->Message(Chat::Red, "Invite failed, group invite would create a raid larger than the maximum number of members allowed."); + return; } } - group->JoinRaidXTarget(raid); - group->DisbandGroup(true); - raid->GroupUpdate(free_group_id); - } - else { - raid->SendRaidCreate(this); - raid->SendMakeLeaderPacketTo(raid->leadername, this); - raid->AddMember(this); - raid->SendBulkRaid(this); - if (raid->IsLocked()) { - raid->SendRaidLockTo(this); + else { + if (1 + raid->RaidCount() > MAX_RAID_MEMBERS) { + player_accepting_invite->Message(Chat::Red, "Invite failed, member invite would create a raid larger than the maximum number of members allowed."); + return; + } + } + if (group) {//add us all + uint32 free_group_id = raid->GetFreeGroup(); + Client *addClient = nullptr; + for (int x = 0; x < 6; x++) { + if (group->members[x]) { + Client *c = nullptr; + if (group->members[x]->IsClient()) + c = group->members[x]->CastToClient(); + else + continue; + + if (!addClient) + { + addClient = c; + raid->SetGroupLeader(addClient->GetName()); + } + + raid->SendRaidCreate(c); + raid->SendMakeLeaderPacketTo(raid->leadername, c); + if (group->IsLeader(group->members[x])) + raid->AddMember(c, free_group_id, false, true); + else + raid->AddMember(c, free_group_id); + raid->SendBulkRaid(c); + if (raid->IsLocked()) { + raid->SendRaidLockTo(c); + } + } + } + group->JoinRaidXTarget(raid); + group->DisbandGroup(true); + raid->GroupUpdate(free_group_id); + } + else { + raid->SendRaidCreate(this); + raid->SendMakeLeaderPacketTo(raid->leadername, this); + raid->AddMember(this); + raid->SendBulkRaid(this); + if (raid->IsLocked()) { + raid->SendRaidLockTo(this); + } } } - } - else - { - Group* player_invited_group = player_accepting_invite->GetGroup(); - Group* group = GetGroup(); - if (group) //if our target has a group + else { - raid = new Raid(player_accepting_invite); - entity_list.AddRaid(raid); - raid->SetRaidDetails(); + Group *player_invited_group = player_accepting_invite->GetGroup(); + Group *group = GetGroup(); + if (group) //if our target has a group + { + raid = new Raid(player_accepting_invite); + entity_list.AddRaid(raid); + raid->SetRaidDetails(); - uint32 raid_free_group_id = raid->GetFreeGroup(); + uint32 raid_free_group_id = raid->GetFreeGroup(); - /* If we already have a group then cycle through adding us... */ - if (player_invited_group) { - Client* client_to_be_leader = nullptr; - for (int x = 0; x < 6; x++) { - if (player_invited_group->members[x]) { - if (!client_to_be_leader) { - if (player_invited_group->members[x]->IsClient()) { - client_to_be_leader = player_invited_group->members[x]->CastToClient(); - raid->SetGroupLeader(client_to_be_leader->GetName()); + /* If we already have a group then cycle through adding us... */ + if (player_invited_group) { + Client *client_to_be_leader = nullptr; + for (int x = 0; x < 6; x++) { + if (player_invited_group->members[x]) { + if (!client_to_be_leader) { + if (player_invited_group->members[x]->IsClient()) { + client_to_be_leader = player_invited_group->members[x]->CastToClient(); + raid->SetGroupLeader(client_to_be_leader->GetName()); + } + } + if (player_invited_group->IsLeader(player_invited_group->members[x])) { + Client *c = nullptr; + + if (player_invited_group->members[x]->IsClient()) + c = player_invited_group->members[x]->CastToClient(); + else + continue; + + raid->SendRaidCreate(c); + raid->SendMakeLeaderPacketTo(raid->leadername, c); + raid->AddMember(c, raid_free_group_id, true, true, true); + raid->SendBulkRaid(c); + + if (raid->IsLocked()) { + raid->SendRaidLockTo(c); + } + } + else { + Client *c = nullptr; + + if (player_invited_group->members[x]->IsClient()) + c = player_invited_group->members[x]->CastToClient(); + else + continue; + + raid->SendRaidCreate(c); + raid->SendMakeLeaderPacketTo(raid->leadername, c); + raid->AddMember(c, raid_free_group_id); + raid->SendBulkRaid(c); + + if (raid->IsLocked()) { + raid->SendRaidLockTo(c); + } } } - if (player_invited_group->IsLeader(player_invited_group->members[x])) { - Client* c = nullptr; + } + player_invited_group->JoinRaidXTarget(raid, true); + player_invited_group->DisbandGroup(true); + raid->GroupUpdate(raid_free_group_id); + raid_free_group_id = raid->GetFreeGroup(); + } + else { + raid->SendRaidCreate(player_accepting_invite); + raid->AddMember(player_accepting_invite, 0xFFFFFFFF, true, false, true); + } - if (player_invited_group->members[x]->IsClient()) - c = player_invited_group->members[x]->CastToClient(); + Client *client_to_add = nullptr; + /* Add client to an existing group */ + for (int x = 0; x < 6; x++) { + if (group->members[x]) { + if (!client_to_add) { + if (group->members[x]->IsClient()) { + client_to_add = group->members[x]->CastToClient(); + raid->SetGroupLeader(client_to_add->GetName()); + } + } + if (group->IsLeader(group->members[x])) { + Client *c = nullptr; + + if (group->members[x]->IsClient()) + c = group->members[x]->CastToClient(); else continue; raid->SendRaidCreate(c); raid->SendMakeLeaderPacketTo(raid->leadername, c); - raid->AddMember(c, raid_free_group_id, true, true, true); + raid->AddMember(c, raid_free_group_id, false, true); raid->SendBulkRaid(c); if (raid->IsLocked()) { raid->SendRaidLockTo(c); } } - else { - Client* c = nullptr; + else + { + Client *c = nullptr; - if (player_invited_group->members[x]->IsClient()) - c = player_invited_group->members[x]->CastToClient(); + if (group->members[x]->IsClient()) + c = group->members[x]->CastToClient(); else continue; @@ -11709,536 +11639,396 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app) } } } - player_invited_group->JoinRaidXTarget(raid, true); - player_invited_group->DisbandGroup(true); + group->JoinRaidXTarget(raid); + group->DisbandGroup(true); + raid->GroupUpdate(raid_free_group_id); - raid_free_group_id = raid->GetFreeGroup(); } + /* Target does not have a group */ else { - raid->SendRaidCreate(player_accepting_invite); - raid->AddMember(player_accepting_invite, 0xFFFFFFFF, true, false, true); - } + if (player_invited_group) { - Client* client_to_add = nullptr; - /* Add client to an existing group */ - for (int x = 0; x < 6; x++) { - if (group->members[x]) { - if (!client_to_add) { - if (group->members[x]->IsClient()) { - client_to_add = group->members[x]->CastToClient(); - raid->SetGroupLeader(client_to_add->GetName()); - } - } - if (group->IsLeader(group->members[x])) { - Client* c = nullptr; + raid = new Raid(player_accepting_invite); - if (group->members[x]->IsClient()) - c = group->members[x]->CastToClient(); - else - continue; - - raid->SendRaidCreate(c); - raid->SendMakeLeaderPacketTo(raid->leadername, c); - raid->AddMember(c, raid_free_group_id, false, true); - raid->SendBulkRaid(c); - - if (raid->IsLocked()) { - raid->SendRaidLockTo(c); - } - } - else - { - Client* c = nullptr; - - if (group->members[x]->IsClient()) - c = group->members[x]->CastToClient(); - else - continue; - - raid->SendRaidCreate(c); - raid->SendMakeLeaderPacketTo(raid->leadername, c); - raid->AddMember(c, raid_free_group_id); - raid->SendBulkRaid(c); - - if (raid->IsLocked()) { - raid->SendRaidLockTo(c); - } - } - } - } - group->JoinRaidXTarget(raid); - group->DisbandGroup(true); - - raid->GroupUpdate(raid_free_group_id); - } - /* Target does not have a group */ - else { - if (player_invited_group) { - - raid = new Raid(player_accepting_invite); - - entity_list.AddRaid(raid); - raid->SetRaidDetails(); - Client* addClientig = nullptr; - for (int x = 0; x < 6; x++) { - if (player_invited_group->members[x]) { - if (!addClientig) { - if (player_invited_group->members[x]->IsClient()) { - addClientig = player_invited_group->members[x]->CastToClient(); - raid->SetGroupLeader(addClientig->GetName()); + entity_list.AddRaid(raid); + raid->SetRaidDetails(); + Client *addClientig = nullptr; + for (int x = 0; x < 6; x++) { + if (player_invited_group->members[x]) { + if (!addClientig) { + if (player_invited_group->members[x]->IsClient()) { + addClientig = player_invited_group->members[x]->CastToClient(); + raid->SetGroupLeader(addClientig->GetName()); + } } - } - if (player_invited_group->IsLeader(player_invited_group->members[x])) { - Client* c = nullptr; + if (player_invited_group->IsLeader(player_invited_group->members[x])) { + Client *c = nullptr; - if (player_invited_group->members[x]->IsClient()) - c = player_invited_group->members[x]->CastToClient(); + if (player_invited_group->members[x]->IsClient()) + c = player_invited_group->members[x]->CastToClient(); + else + continue; + + raid->SendRaidCreate(c); + raid->SendMakeLeaderPacketTo(raid->leadername, c); + raid->AddMember(c, 0, true, true, true); + raid->SendBulkRaid(c); + + if (raid->IsLocked()) { + raid->SendRaidLockTo(c); + } + } else - continue; + { + Client *c = nullptr; + if (player_invited_group->members[x]->IsClient()) + c = player_invited_group->members[x]->CastToClient(); + else + continue; - raid->SendRaidCreate(c); - raid->SendMakeLeaderPacketTo(raid->leadername, c); - raid->AddMember(c, 0, true, true, true); - raid->SendBulkRaid(c); - - if (raid->IsLocked()) { - raid->SendRaidLockTo(c); - } - } - else - { - Client* c = nullptr; - if (player_invited_group->members[x]->IsClient()) - c = player_invited_group->members[x]->CastToClient(); - else - continue; - - raid->SendRaidCreate(c); - raid->SendMakeLeaderPacketTo(raid->leadername, c); - raid->AddMember(c, 0); - raid->SendBulkRaid(c); - if (raid->IsLocked()) { - raid->SendRaidLockTo(c); + raid->SendRaidCreate(c); + raid->SendMakeLeaderPacketTo(raid->leadername, c); + raid->AddMember(c, 0); + raid->SendBulkRaid(c); + if (raid->IsLocked()) { + raid->SendRaidLockTo(c); + } } } } + raid->SendRaidCreate(this); + raid->SendMakeLeaderPacketTo(raid->leadername, this); + raid->SendBulkRaid(this); + player_invited_group->JoinRaidXTarget(raid, true); + raid->AddMember(this); + player_invited_group->DisbandGroup(true); + raid->GroupUpdate(0); + if (raid->IsLocked()) { + raid->SendRaidLockTo(this); + } } - raid->SendRaidCreate(this); - raid->SendMakeLeaderPacketTo(raid->leadername, this); - raid->SendBulkRaid(this); - player_invited_group->JoinRaidXTarget(raid, true); - raid->AddMember(this); - player_invited_group->DisbandGroup(true); - raid->GroupUpdate(0); - if (raid->IsLocked()) { - raid->SendRaidLockTo(this); - } - } - else { // neither has a group - raid = new Raid(player_accepting_invite); - entity_list.AddRaid(raid); - raid->SetRaidDetails(); - raid->SendRaidCreate(player_accepting_invite); - raid->SendRaidCreate(this); - raid->SendMakeLeaderPacketTo(raid->leadername, this); - raid->AddMember(player_accepting_invite, 0xFFFFFFFF, true, false, true); - raid->SendBulkRaid(this); - raid->AddMember(this); - if (raid->IsLocked()) { - raid->SendRaidLockTo(this); + else { // neither has a group + raid = new Raid(player_accepting_invite); + entity_list.AddRaid(raid); + raid->SetRaidDetails(); + raid->SendRaidCreate(player_accepting_invite); + raid->SendRaidCreate(this); + raid->SendMakeLeaderPacketTo(raid->leadername, this); + raid->AddMember(player_accepting_invite, 0xFFFFFFFF, true, false, true); + raid->SendBulkRaid(this); + raid->AddMember(this); + if (raid->IsLocked()) { + raid->SendRaidLockTo(this); + } } } } } + break; } - break; - } - case RaidCommandDisband: { - Raid* raid = entity_list.GetRaidByClient(this); - Client* c_to_disband = entity_list.GetClientByName(raid_command_packet->leader_name); - Client* c_doing_disband = entity_list.GetClientByName(raid_command_packet->player_name); -#ifdef BOTS - Bot* b_to_disband = entity_list.GetBotByBotName(raid_command_packet->leader_name); -#endif + case RaidCommandDisband: { + Raid *raid = entity_list.GetRaidByClient(this); + if (raid) { + uint32 group = raid->GetGroup(raid_command_packet->leader_name); - if (raid) { - uint32 group = raid->GetGroup(raid_command_packet->leader_name); + if (group < 12) { + uint32 i = raid->GetPlayerIndex(raid_command_packet->leader_name); + if (raid->members[i].IsGroupLeader) { //assign group leader to someone else + for (int x = 0; x < MAX_RAID_MEMBERS; x++) { + if (strlen(raid->members[x].membername) > 0 && i != x) { + if (raid->members[x].GroupNumber == group) { + raid->SetGroupLeader(raid_command_packet->leader_name, false); + raid->SetGroupLeader(raid->members[x].membername); + raid->UpdateGroupAAs(group); + break; + } + } + } -#ifdef BOTS - //Added to remove all bots if the Bot_Owner is removed from the Raid - //Does not camp the Bots, just removes from the raid - std::vector raid_members_bots; - if (c_to_disband) - { - // Determine if the client has any BOTS in the raid - uint32 owner_id = c_to_disband->CharacterID(); - for (int i = 0; i < MAX_RAID_MEMBERS; ++i) - { - if (raid->members[i].member && raid->members[i].member->IsBot() && raid->members[i].member->CastToBot()->GetOwner()->CastToClient()->CharacterID() == owner_id) - { - raid_members_bots.emplace_back(raid->members[i].member->CastToBot()); } - } - // If any of the bots are a group leader then re-create the botgroup on disband, dropping any clients - for (auto bot_iter : raid_members_bots) { - if (bot_iter && raid->IsRaidMember(bot_iter->GetName()) && raid->IsGroupLeader(bot_iter->GetName())) - { - // Remove the entire BOT group in this case - uint32 gid = raid->GetGroup(bot_iter->GetName()); - - std::vector r_group_members = raid->GetRaidGroupMembers(gid); - Group* group_inst = new Group(bot_iter); - entity_list.AddGroup(group_inst); - database.SetGroupID(bot_iter->GetCleanName(), group_inst->GetID(), bot_iter->GetBotID()); - database.SetGroupLeaderName(group_inst->GetID(), bot_iter->GetCleanName()); - for (auto member_iter : r_group_members) { - if (!member_iter.member->IsClient() && strcmp(member_iter.membername, bot_iter->GetName()) == 0) - bot_iter->SetFollowID(owner_id); - - else - Bot::AddBotToGroup(member_iter.member->CastToBot(), group_inst); - raid->RemoveMember(bot_iter->GetName()); - } - } - else if (bot_iter && raid->IsRaidMember(bot_iter->GetName())) - { - raid->RemoveMember(bot_iter->GetName()); - } - } - } - else if (b_to_disband) - { - uint32 gid = raid->GetGroup(b_to_disband->GetName()); - if (gid < 12 && raid->IsGroupLeader(b_to_disband->GetName())) - { - // If any of the bots are a group leader then re-create the botgroup on disband, dropping any clients - std::vector r_group_members = raid->GetRaidGroupMembers(gid); - uint32 owner_id = b_to_disband->CastToBot()->GetOwner()->CastToClient()->CharacterID(); - if (raid->IsGroupLeader(b_to_disband->GetName())) - { - // Remove the entire BOT group in this case - Group* group_inst = new Group(b_to_disband); - entity_list.AddGroup(group_inst); - database.SetGroupID(b_to_disband->GetCleanName(), group_inst->GetID(), b_to_disband->GetBotID()); - database.SetGroupLeaderName(group_inst->GetID(), b_to_disband->GetCleanName()); - for (auto member_iter : r_group_members) { - if (!member_iter.member->IsClient() && strcmp(member_iter.membername, b_to_disband->GetName()) == 0) - b_to_disband->SetFollowID(owner_id); - else - Bot::AddBotToGroup(member_iter.member->CastToBot(), group_inst); - raid->RemoveMember(member_iter.member->CastToBot()->GetName()); - } - } - break; - } - else if (gid <12 && raid->GetGroupLeader(gid)->IsBot()) - { - c_doing_disband->Message(Chat::Yellow, "%s is in a Bot Group. Please disband %s instead to remove the entire Bot group.", - raid_command_packet->leader_name, raid->GetGroupLeader(gid)->CastToBot()->GetName()); - break; - } - } -#endif - if (group < 12) { - uint32 i = raid->GetPlayerIndex(raid_command_packet->leader_name); - if (raid->members[i].IsGroupLeader) { //assign group leader to someone else - for (int x = 0; x < MAX_RAID_MEMBERS; x++) { - if (strlen(raid->members[x].membername) > 0 && i != x) { - if (raid->members[x].GroupNumber == group) { - raid->SetGroupLeader(raid_command_packet->leader_name, false); - raid->SetGroupLeader(raid->members[x].membername); - raid->UpdateGroupAAs(group); + if (raid->members[i].IsRaidLeader) { + for (int x = 0; x < MAX_RAID_MEMBERS; x++) { + if (strlen(raid->members[x].membername) > 0 && strcmp(raid->members[x].membername, raid->members[i].membername) != 0) + { + raid->SetRaidLeader(raid->members[i].membername, raid->members[x].membername); + raid->UpdateRaidAAs(); + raid->SendAllRaidLeadershipAA(); break; } } } - } - if (raid->members[i].IsRaidLeader) { - for (int x = 0; x < MAX_RAID_MEMBERS; x++) { - if (strlen(raid->members[x].membername) > 0 && strcmp(raid->members[x].membername, raid->members[i].membername) != 0) - { - raid->SetRaidLeader(raid->members[i].membername, raid->members[x].membername); - raid->UpdateRaidAAs(); - raid->SendAllRaidLeadershipAA(); - break; - } - } - } - } - raid->RemoveMember(raid_command_packet->leader_name); - Client* c = entity_list.GetClientByName(raid_command_packet->leader_name); - if (c) { - raid->SendGroupDisband(c); + raid->RemoveMember(raid_command_packet->leader_name); + Client *c = entity_list.GetClientByName(raid_command_packet->leader_name); + if (c) + raid->SendGroupDisband(c); + else { + auto pack = + new ServerPacket(ServerOP_RaidGroupDisband, sizeof(ServerRaidGeneralAction_Struct)); + ServerRaidGeneralAction_Struct* rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; + rga->rid = GetID(); + rga->zoneid = zone->GetZoneID(); + rga->instance_id = zone->GetInstanceID(); + strn0cpy(rga->playername, raid_command_packet->leader_name, 64); + worldserver.SendPacket(pack); + safe_delete(pack); + } + //r->SendRaidGroupRemove(ri->leader_name, grp); + raid->GroupUpdate(group);// break + //} } - else { - auto pack = - new ServerPacket(ServerOP_RaidGroupDisband, sizeof(ServerRaidGeneralAction_Struct)); - ServerRaidGeneralAction_Struct* rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; - rga->rid = GetID(); - rga->zoneid = zone->GetZoneID(); - rga->instance_id = zone->GetInstanceID(); - strn0cpy(rga->playername, raid_command_packet->leader_name, 64); - worldserver.SendPacket(pack); - safe_delete(pack); - } - //r->SendRaidGroupRemove(ri->leader_name, grp); - raid->GroupUpdate(group);// break - if (!raid->RaidCount()) - raid->DisbandRaid(); + break; } - break; - } - case RaidCommandMoveGroup: - { - Raid* raid = entity_list.GetRaidByClient(this); - if (raid) { - /* Moving to group */ - if (raid_command_packet->parameter < 12) { - uint8 group_count = raid->GroupCount(raid_command_packet->parameter); + case RaidCommandMoveGroup: + { + Raid *raid = entity_list.GetRaidByClient(this); + if (raid) { + /* Moving to group */ + if (raid_command_packet->parameter < 12) { + uint8 group_count = raid->GroupCount(raid_command_packet->parameter); - if (group_count < 6) { - Client* c = entity_list.GetClientByName(raid_command_packet->leader_name); - uint32 old_group = raid->GetGroup(raid_command_packet->leader_name); - if (raid_command_packet->parameter == old_group) //don't rejoin grp if we order to join same group. - break; + if (group_count < 6) { + Client *c = entity_list.GetClientByName(raid_command_packet->leader_name); + uint32 old_group = raid->GetGroup(raid_command_packet->leader_name); + if (raid_command_packet->parameter == old_group) //don't rejoin grp if we order to join same group. + break; - if (raid->members[raid->GetPlayerIndex(raid_command_packet->leader_name)].IsGroupLeader) { - raid->SetGroupLeader(raid_command_packet->leader_name, false); + if (raid->members[raid->GetPlayerIndex(raid_command_packet->leader_name)].IsGroupLeader) { + raid->SetGroupLeader(raid_command_packet->leader_name, false); - /* We were the leader of our old group */ - if (old_group < 12) { - /* Assign new group leader if we can */ - for (int x = 0; x < MAX_RAID_MEMBERS; x++) { - if (raid->members[x].GroupNumber == old_group) { - if (strcmp(raid_command_packet->leader_name, raid->members[x].membername) != 0 && strlen(raid_command_packet->leader_name) > 0) { - raid->SetGroupLeader(raid->members[x].membername); - raid->UpdateGroupAAs(old_group); + /* We were the leader of our old group */ + if (old_group < 12) { + /* Assign new group leader if we can */ + for (int x = 0; x < MAX_RAID_MEMBERS; x++) { + if (raid->members[x].GroupNumber == old_group) { + if (strcmp(raid_command_packet->leader_name, raid->members[x].membername) != 0 && strlen(raid_command_packet->leader_name) > 0) { + raid->SetGroupLeader(raid->members[x].membername); + raid->UpdateGroupAAs(old_group); - Client* client_to_update = entity_list.GetClientByName(raid->members[x].membername); - if (client_to_update) { - raid->SendRaidRemove(raid->members[x].membername, client_to_update); - raid->SendRaidCreate(client_to_update); - raid->SendMakeLeaderPacketTo(raid->leadername, client_to_update); - raid->SendRaidAdd(raid->members[x].membername, client_to_update); - raid->SendBulkRaid(client_to_update); - if (raid->IsLocked()) { - raid->SendRaidLockTo(client_to_update); + Client *client_to_update = entity_list.GetClientByName(raid->members[x].membername); + if (client_to_update) { + raid->SendRaidRemove(raid->members[x].membername, client_to_update); + raid->SendRaidCreate(client_to_update); + raid->SendMakeLeaderPacketTo(raid->leadername, client_to_update); + raid->SendRaidAdd(raid->members[x].membername, client_to_update); + raid->SendBulkRaid(client_to_update); + if (raid->IsLocked()) { + raid->SendRaidLockTo(client_to_update); + } } + else { + auto pack = new ServerPacket(ServerOP_RaidChangeGroup, sizeof(ServerRaidGeneralAction_Struct)); + ServerRaidGeneralAction_Struct *raid_command_packet = (ServerRaidGeneralAction_Struct*)pack->pBuffer; + + raid_command_packet->rid = raid->GetID(); + raid_command_packet->zoneid = zone->GetZoneID(); + raid_command_packet->instance_id = zone->GetInstanceID(); + strn0cpy(raid_command_packet->playername, raid->members[x].membername, 64); + + worldserver.SendPacket(pack); + + safe_delete(pack); + } + break; } - else { - auto pack = new ServerPacket(ServerOP_RaidChangeGroup, sizeof(ServerRaidGeneralAction_Struct)); - ServerRaidGeneralAction_Struct* raid_command_packet = (ServerRaidGeneralAction_Struct*)pack->pBuffer; - - raid_command_packet->rid = raid->GetID(); - raid_command_packet->zoneid = zone->GetZoneID(); - raid_command_packet->instance_id = zone->GetInstanceID(); - strn0cpy(raid_command_packet->playername, raid->members[x].membername, 64); - - worldserver.SendPacket(pack); - - safe_delete(pack); - } - break; } } } } - } - if (group_count == 0) { - raid->SetGroupLeader(raid_command_packet->leader_name); - raid->UpdateGroupAAs(raid_command_packet->parameter); - } + if (group_count == 0) { + raid->SetGroupLeader(raid_command_packet->leader_name); + raid->UpdateGroupAAs(raid_command_packet->parameter); + } - raid->MoveMember(raid_command_packet->leader_name, raid_command_packet->parameter); + raid->MoveMember(raid_command_packet->leader_name, raid_command_packet->parameter); + if (c) { + raid->SendGroupDisband(c); + } + else { + auto pack = new ServerPacket(ServerOP_RaidGroupDisband, sizeof(ServerRaidGeneralAction_Struct)); + ServerRaidGeneralAction_Struct* raid_command = (ServerRaidGeneralAction_Struct*)pack->pBuffer; + raid_command->rid = raid->GetID(); + raid_command->zoneid = zone->GetZoneID(); + raid_command->instance_id = zone->GetInstanceID(); + strn0cpy(raid_command->playername, raid_command_packet->leader_name, 64); + worldserver.SendPacket(pack); + safe_delete(pack); + } + + /* Send group update to our new group */ + raid->GroupUpdate(raid_command_packet->parameter); + + /* If our old was a group send update there too */ + if (old_group < 12) + raid->GroupUpdate(old_group); + + } + } + /* Move player to ungrouped bank */ + else { + Client *c = entity_list.GetClientByName(raid_command_packet->leader_name); + uint32 oldgrp = raid->GetGroup(raid_command_packet->leader_name); + if (raid->members[raid->GetPlayerIndex(raid_command_packet->leader_name)].IsGroupLeader) { + raid->SetGroupLeader(raid_command_packet->leader_name, false); + for (int x = 0; x < MAX_RAID_MEMBERS; x++) { + if (raid->members[x].GroupNumber == oldgrp && strlen(raid->members[x].membername) > 0 && strcmp(raid->members[x].membername, raid_command_packet->leader_name) != 0){ + + raid->SetGroupLeader(raid->members[x].membername); + raid->UpdateGroupAAs(oldgrp); + + Client *client_leaving_group = entity_list.GetClientByName(raid->members[x].membername); + if (client_leaving_group) { + raid->SendRaidRemove(raid->members[x].membername, client_leaving_group); + raid->SendRaidCreate(client_leaving_group); + raid->SendMakeLeaderPacketTo(raid->leadername, client_leaving_group); + raid->SendRaidAdd(raid->members[x].membername, client_leaving_group); + raid->SendBulkRaid(client_leaving_group); + if (raid->IsLocked()) { + raid->SendRaidLockTo(client_leaving_group); + } + } + else { + auto pack = new ServerPacket( ServerOP_RaidChangeGroup, sizeof(ServerRaidGeneralAction_Struct)); + ServerRaidGeneralAction_Struct *raid_command = (ServerRaidGeneralAction_Struct*)pack->pBuffer; + + raid_command->rid = raid->GetID(); + strn0cpy(raid_command->playername, raid->members[x].membername, 64); + raid_command->zoneid = zone->GetZoneID(); + raid_command->instance_id = zone->GetInstanceID(); + + worldserver.SendPacket(pack); + safe_delete(pack); + } + break; + } + } + } + raid->MoveMember(raid_command_packet->leader_name, 0xFFFFFFFF); if (c) { raid->SendGroupDisband(c); } else { auto pack = new ServerPacket(ServerOP_RaidGroupDisband, sizeof(ServerRaidGeneralAction_Struct)); ServerRaidGeneralAction_Struct* raid_command = (ServerRaidGeneralAction_Struct*)pack->pBuffer; + raid_command->rid = raid->GetID(); raid_command->zoneid = zone->GetZoneID(); raid_command->instance_id = zone->GetInstanceID(); strn0cpy(raid_command->playername, raid_command_packet->leader_name, 64); + worldserver.SendPacket(pack); + safe_delete(pack); } - /* Send group update to our new group */ - raid->GroupUpdate(raid_command_packet->parameter); - - /* If our old was a group send update there too */ - if (old_group < 12) - raid->GroupUpdate(old_group); - + raid->GroupUpdate(oldgrp); } } - /* Move player to ungrouped bank */ - else { - Client* c = entity_list.GetClientByName(raid_command_packet->leader_name); - uint32 oldgrp = raid->GetGroup(raid_command_packet->leader_name); - if (raid->members[raid->GetPlayerIndex(raid_command_packet->leader_name)].IsGroupLeader) { - raid->SetGroupLeader(raid_command_packet->leader_name, false); - for (int x = 0; x < MAX_RAID_MEMBERS; x++) { - if (raid->members[x].GroupNumber == oldgrp && strlen(raid->members[x].membername) > 0 && strcmp(raid->members[x].membername, raid_command_packet->leader_name) != 0) { - raid->SetGroupLeader(raid->members[x].membername); - raid->UpdateGroupAAs(oldgrp); + Client *client_moved = entity_list.GetClientByName(raid_command_packet->leader_name); - Client* client_leaving_group = entity_list.GetClientByName(raid->members[x].membername); - if (client_leaving_group) { - raid->SendRaidRemove(raid->members[x].membername, client_leaving_group); - raid->SendRaidCreate(client_leaving_group); - raid->SendMakeLeaderPacketTo(raid->leadername, client_leaving_group); - raid->SendRaidAdd(raid->members[x].membername, client_leaving_group); - raid->SendBulkRaid(client_leaving_group); - if (raid->IsLocked()) { - raid->SendRaidLockTo(client_leaving_group); - } - } - else { - auto pack = new ServerPacket(ServerOP_RaidChangeGroup, sizeof(ServerRaidGeneralAction_Struct)); - ServerRaidGeneralAction_Struct* raid_command = (ServerRaidGeneralAction_Struct*)pack->pBuffer; + if (client_moved && client_moved->GetRaid()) { + client_moved->GetRaid()->SendHPManaEndPacketsTo(client_moved); + client_moved->GetRaid()->SendHPManaEndPacketsFrom(client_moved); - raid_command->rid = raid->GetID(); - strn0cpy(raid_command->playername, raid->members[x].membername, 64); - raid_command->zoneid = zone->GetZoneID(); - raid_command->instance_id = zone->GetInstanceID(); - - worldserver.SendPacket(pack); - safe_delete(pack); - } - break; - } - } - } - raid->MoveMember(raid_command_packet->leader_name, 0xFFFFFFFF); - if (c) { - raid->SendGroupDisband(c); - } - else { - auto pack = new ServerPacket(ServerOP_RaidGroupDisband, sizeof(ServerRaidGeneralAction_Struct)); - ServerRaidGeneralAction_Struct* raid_command = (ServerRaidGeneralAction_Struct*)pack->pBuffer; - - raid_command->rid = raid->GetID(); - raid_command->zoneid = zone->GetZoneID(); - raid_command->instance_id = zone->GetInstanceID(); - strn0cpy(raid_command->playername, raid_command_packet->leader_name, 64); - - worldserver.SendPacket(pack); - - safe_delete(pack); - } - - raid->GroupUpdate(oldgrp); + Log(Logs::General, Logs::HPUpdate, + "Client::Handle_OP_RaidCommand :: %s sending and recieving HP/Mana/End updates", + client_moved->GetCleanName() + ); } - } - Client* client_moved = entity_list.GetClientByName(raid_command_packet->leader_name); - - if (client_moved && client_moved->GetRaid()) { - client_moved->GetRaid()->SendHPManaEndPacketsTo(client_moved); - client_moved->GetRaid()->SendHPManaEndPacketsFrom(client_moved); - - Log(Logs::General, Logs::HPUpdate, - "Client::Handle_OP_RaidCommand :: %s sending and recieving HP/Mana/End updates", - client_moved->GetCleanName() - ); - } - - break; - } - case RaidCommandRaidLock: - { - Raid* raid = entity_list.GetRaidByClient(this); - if (raid) { - if (!raid->IsLocked()) - raid->LockRaid(true); - else - raid->SendRaidLockTo(this); - } - break; - } - case RaidCommandRaidUnlock: - { - Raid* raid = entity_list.GetRaidByClient(this); - if (raid) - { - if (raid->IsLocked()) - raid->LockRaid(false); - else - raid->SendRaidUnlockTo(this); - } - break; - } - case RaidCommandLootType2: - case RaidCommandLootType: - { - Raid* raid = entity_list.GetRaidByClient(this); - if (raid) { - Message(Chat::Yellow, "Loot type changed to: %d.", raid_command_packet->parameter); - raid->ChangeLootType(raid_command_packet->parameter); - } - break; - } - - case RaidCommandAddLooter2: - case RaidCommandAddLooter: - { - Raid* raid = entity_list.GetRaidByClient(this); - if (raid) { - Message(Chat::Yellow, "Adding %s as a raid looter.", raid_command_packet->leader_name); - raid->AddRaidLooter(raid_command_packet->leader_name); - } - break; - } - - case RaidCommandRemoveLooter2: - case RaidCommandRemoveLooter: - { - Raid* raid = entity_list.GetRaidByClient(this); - if (raid) { - Message(Chat::Yellow, "Removing %s as a raid looter.", raid_command_packet->leader_name); - raid->RemoveRaidLooter(raid_command_packet->leader_name); - } - break; - } - - case RaidCommandMakeLeader: - { - Raid* raid = entity_list.GetRaidByClient(this); - if (raid) { - if (strcmp(raid->leadername, GetName()) == 0) { - raid->SetRaidLeader(GetName(), raid_command_packet->leader_name); - raid->UpdateRaidAAs(); - raid->SendAllRaidLeadershipAA(); - } - } - break; - } - - case RaidCommandSetMotd: - { - Raid* raid = entity_list.GetRaidByClient(this); - if (!raid) break; - // we don't use the RaidGeneral here! - RaidMOTD_Struct* motd = (RaidMOTD_Struct*)app->pBuffer; - raid->SetRaidMOTD(std::string(motd->motd)); - raid->SaveRaidMOTD(); - raid->SendRaidMOTDToWorld(); - break; - } + } + case RaidCommandRaidLock: + { + Raid *raid = entity_list.GetRaidByClient(this); + if (raid) { + if (!raid->IsLocked()) + raid->LockRaid(true); + else + raid->SendRaidLockTo(this); + } + break; + } + case RaidCommandRaidUnlock: + { + Raid *raid = entity_list.GetRaidByClient(this); + if (raid) + { + if (raid->IsLocked()) + raid->LockRaid(false); + else + raid->SendRaidUnlockTo(this); + } + break; + } + case RaidCommandLootType2: + case RaidCommandLootType: + { + Raid *raid = entity_list.GetRaidByClient(this); + if (raid) { + Message(Chat::Yellow, "Loot type changed to: %d.", raid_command_packet->parameter); + raid->ChangeLootType(raid_command_packet->parameter); + } + break; + } - default: { - Message(Chat::Red, "Raid command (%d) NYI", raid_command_packet->action); - break; - } + case RaidCommandAddLooter2: + case RaidCommandAddLooter: + { + Raid *raid = entity_list.GetRaidByClient(this); + if (raid) { + Message(Chat::Yellow, "Adding %s as a raid looter.", raid_command_packet->leader_name); + raid->AddRaidLooter(raid_command_packet->leader_name); + } + break; + } + + case RaidCommandRemoveLooter2: + case RaidCommandRemoveLooter: + { + Raid *raid = entity_list.GetRaidByClient(this); + if (raid) { + Message(Chat::Yellow, "Removing %s as a raid looter.", raid_command_packet->leader_name); + raid->RemoveRaidLooter(raid_command_packet->leader_name); + } + break; + } + + case RaidCommandMakeLeader: + { + Raid *raid = entity_list.GetRaidByClient(this); + if (raid) { + if (strcmp(raid->leadername, GetName()) == 0) { + raid->SetRaidLeader(GetName(), raid_command_packet->leader_name); + raid->UpdateRaidAAs(); + raid->SendAllRaidLeadershipAA(); + } + } + break; + } + + case RaidCommandSetMotd: + { + Raid *raid = entity_list.GetRaidByClient(this); + if (!raid) + break; + // we don't use the RaidGeneral here! + RaidMOTD_Struct *motd = (RaidMOTD_Struct *)app->pBuffer; + raid->SetRaidMOTD(std::string(motd->motd)); + raid->SaveRaidMOTD(); + raid->SendRaidMOTDToWorld(); + break; + } + + default: { + Message(Chat::Red, "Raid command (%d) NYI", raid_command_packet->action); + break; + } } } - + void Client::Handle_OP_RandomReq(const EQApplicationPacket *app) { if (app->size != sizeof(RandomReq_Struct)) { diff --git a/zone/entity.cpp b/zone/entity.cpp index a98dbfba5..1f786cb4c 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2137,17 +2137,17 @@ Raid *EntityList::GetRaidByID(uint32 id) return nullptr; } -Raid* EntityList::GetRaidByClient(Client* client) +Raid *EntityList::GetRaidByClient(Client* client) { if (client->p_raid_instance) { return client->p_raid_instance; } - std::list::iterator iterator; + std::list::iterator iterator; iterator = raid_list.begin(); while (iterator != raid_list.end()) { - for (auto& member : (*iterator)->members) { + for (auto &member : (*iterator)->members) { if (member.member) { if (member.member == client) { client->p_raid_instance = *iterator; @@ -2161,50 +2161,6 @@ Raid* EntityList::GetRaidByClient(Client* client) return nullptr; } -#ifdef BOTS -Raid* EntityList::GetRaidByBotName(const char* name) -{ - - std::list::iterator iterator; - iterator = raid_list.begin(); - - while (iterator != raid_list.end()) { - for (auto& member : (*iterator)->members) { - if (member.membername) { - if (strcmp(member.membername, name) == 0) { - //client->p_raid_instance = *iterator; - return *iterator; - } - } - } - - ++iterator; - } - - return nullptr; -} -#endif - -#ifdef BOTS -Raid* EntityList::GetRaidByBot(Bot* bot) -{ - - std::list::iterator iterator; - iterator = raid_list.begin(); - - while (iterator != raid_list.end()) { - for (auto& member : (*iterator)->members) { - if (member.member && member.member->CastToBot() == bot) { - bot->p_raid_instance = *iterator; - return *iterator; - } - } - ++iterator; - } - return nullptr; -} -#endif - Raid *EntityList::GetRaidByMob(Mob *mob) { diff --git a/zone/entity.h b/zone/entity.h index 06e2ca401..f06e26119 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -200,10 +200,6 @@ public: Raid *GetRaidByClient(Client* client); Raid *GetRaidByID(uint32 id); Raid *GetRaidByLeaderName(const char *leader); -#ifdef BOTS - Raid* GetRaidByBotName(const char* name); - Raid* GetRaidByBot(Bot* bot); -#endif Corpse *GetCorpseByOwner(Client* client); Corpse *GetCorpseByOwnerWithinRange(Client* client, Mob* center, int range); diff --git a/zone/exp.cpp b/zone/exp.cpp index 2badce051..aad0f141b 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -1097,11 +1097,7 @@ void Raid::SplitExp(uint32 exp, Mob* other) { return; for (unsigned int x = 0; x < MAX_RAID_MEMBERS; x++) { -#ifdef BOTS - if (members[x].member != nullptr && !members[x].IsBot) // If Group Member is Client -#else if (members[x].member != nullptr) // If Group Member is Client -#endif { Client *cmember = members[x].member; // add exp + exp cap diff --git a/zone/groups.cpp b/zone/groups.cpp index 5b365b158..c82e56406 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -248,24 +248,10 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte uint32 i = 0; for (i = 0; i < MAX_GROUP_MEMBERS; ++i) { -#ifdef BOTSS - if (newmember->IsBot() && !newmember->HasGroup() && !strcasecmp(membername[i], NewMemberName)) // Mitch - { - //Bot::RemoveBotFromGroup(newmember->CastToBot(), members[0]->GetGroup()); - //Group::DelMember(newmember); - memset(membername[i], 0, 64); - members[i] = nullptr; - } - else if (!strcasecmp(membername[i], NewMemberName)) + if(!strcasecmp(membername[i], NewMemberName)) { return false; } -#else - if (!strcasecmp(membername[i], NewMemberName)) - { - return false; - } -#endif } // Put them in the group @@ -1154,13 +1140,7 @@ void Group::TeleportGroup(Mob* sender, uint32 zoneID, uint16 instance_id, float } bool Group::LearnMembers() { - //std::string query = StringFormat("SELECT name FROM group_id WHERE groupid = %lu", (unsigned long)GetID()); - std::string query = StringFormat("SELECT name FROM group_id " - "WHERE group_id.groupid = %lu AND group_id.name NOT " - "IN(SELECT group_leaders.leadername FROM group_leaders WHERE gid = %lu)" - , (unsigned long)GetID() - , (unsigned long)GetID()); - + std::string query = StringFormat("SELECT name FROM group_id WHERE groupid = %lu", (unsigned long)GetID()); auto results = database.QueryDatabase(query); if (!results.Success()) return false; @@ -1175,7 +1155,7 @@ bool Group::LearnMembers() { return false; } - int memberIndex = 1; //starts at 1 becasuse leader [0] is done specifically + int memberIndex = 0; for(auto row = results.begin(); row != results.end(); ++row) { if(!row[0]) continue; @@ -1185,24 +1165,7 @@ bool Group::LearnMembers() { memberIndex++; } - // for leader only [0] /Mitch - query = StringFormat("SELECT leadername FROM group_leaders WHERE group_leaders.gid = %lu", (unsigned long)GetID()); - auto results2 = database.QueryDatabase(query); - if (!results2.Success()) - return false; - if (results2.RowCount() == 0) { - LogError( - "Error getting group leader for group [{}]: [{}]", - (unsigned long)GetID(), - results2.ErrorMessage().c_str() - ); - - return false; - } - auto row2 = results2.begin(); - members[0] = nullptr; - strn0cpy(membername[0], row2[0], 64); return true; } @@ -1213,22 +1176,6 @@ void Group::VerifyGroup() { Only called every once in a while (on member re-join for now). */ - // To do - // Reset the membername array to match the group_id database records? - // When doing this manually, it seem to have resolved the issue. - // Only want to do this when the database Name does not match the array - // Could this be done from the LearnGroup method? - // reset the members and membername array for this group - // Mitch - for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { - members[i] = nullptr; - memset(membername[i],'\0',64); - //membername[i][0] == '\0'); - } - // repopulate the membername array from the database to ensure the local zone instance has accurate information - - Group::LearnMembers(); - uint32 i; for (i = 0; i < MAX_GROUP_MEMBERS; i++) { if (membername[i][0] == '\0') { @@ -1249,7 +1196,6 @@ void Group::VerifyGroup() { continue; } - if(them != nullptr && members[i] != them) { //our pointer is out of date... not so good. #if EQDEBUG >= 5 LogDebug("Member of group [{}] named [{}] had an out of date pointer!!", (unsigned long)GetID(), membername[i]); diff --git a/zone/main.cpp b/zone/main.cpp index 3dcba3b86..f92ea9ea8 100644 --- a/zone/main.cpp +++ b/zone/main.cpp @@ -88,7 +88,6 @@ volatile bool RunLoops = true; #endif extern volatile bool is_zone_loaded; -extern bool Critical = false; EntityList entity_list; WorldServer worldserver; @@ -579,7 +578,7 @@ int main(int argc, char** argv) { EQ::Timer process_timer(loop_fn); process_timer.Start(32, true); - + EQ::EventLoop::Get().Run(); entity_list.Clear(); diff --git a/zone/mob.cpp b/zone/mob.cpp index bbc0c5cb3..dc0032256 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3987,7 +3987,7 @@ void Mob::QuestJournalledSay(Client *QuestInitiator, const char *str, Journal::O const char *Mob::GetCleanName() { - if (!strlen(clean_name)) { + if (!strlen(clean_name)) { CleanMobName(GetName(), clean_name); } diff --git a/zone/raids.cpp b/zone/raids.cpp index e66092867..db57a4eed 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -24,7 +24,6 @@ #include "groups.h" #include "mob.h" #include "raids.h" -#include "bot.h" #include "worldserver.h" @@ -96,22 +95,13 @@ void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bo if(!c) return; -#ifdef BOTS std::string query = StringFormat("INSERT INTO raid_members SET raidid = %lu, charid = %lu, " "groupid = %lu, _class = %d, level = %d, name = '%s', " - "isgroupleader = %d, israidleader = %d, islooter = %d, isbot = 0", + "isgroupleader = %d, israidleader = %d, islooter = %d", (unsigned long)GetID(), (unsigned long)c->CharacterID(), (unsigned long)group, c->GetClass(), c->GetLevel(), c->GetName(), groupleader, rleader, looter); -#else - std::string query = StringFormat("INSERT INTO raid_members SET raidid = %lu, charid = %lu, " - "groupid = %lu, _class = %d, level = %d, name = '%s', " - "isgroupleader = %d, israidleader = %d, islooter = %d", - (unsigned long)GetID(), (unsigned long)c->CharacterID(), - (unsigned long)group, c->GetClass(), c->GetLevel(), - c->GetName(), groupleader, rleader, looter); -#endif - auto results = database.QueryDatabase(query); + auto results = database.QueryDatabase(query); if(!results.Success()) { LogError("Error inserting into raid members: [{}]", results.ErrorMessage().c_str()); @@ -119,14 +109,6 @@ void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bo LearnMembers(); VerifyRaid(); - -#ifdef BOTS - if (rleader) { - database.SetRaidGroupLeaderInfo(group, GetID()); - UpdateRaidAAs(); - } - else -#endif if (rleader) { database.SetRaidGroupLeaderInfo(RAID_GROUPLESS, GetID()); UpdateRaidAAs(); @@ -181,65 +163,12 @@ void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bo safe_delete(pack); } -#ifdef BOTS -void Raid::AddBot(Bot* b, uint32 group, bool rleader, bool groupleader, bool looter) { - if (!b) - return; - - std::string query = StringFormat("INSERT INTO raid_members SET raidid = %lu, charid = %lu, " - "groupid = %lu, _class = %d, level = %d, name = '%s', " - "isgroupleader = %d, israidleader = %d, islooter = %d, isbot = 1", - (unsigned long)GetID(), (unsigned long)b->GetBotID(), - (unsigned long)group, b->GetClass(), b->GetLevel(), - b->GetName(), groupleader, rleader, looter); - auto results = database.QueryDatabase(query); - - if (!results.Success()) { - LogError("Error inserting into raid members: [{}]", results.ErrorMessage().c_str()); - } - - LearnMembers(); - VerifyRaid(); - - if (group < 12) //Jan22 - GroupUpdate(group); //Jan22 - else // get raid AAs, GroupUpdate will handles it otherwise Jan 22 - SendGroupLeadershipAA(b->GetOwner()->CastToClient(), RAID_GROUPLESS); //Is this needed for bots? Jan 22 - SendRaidAddAll(b->GetName()); - - b->SetRaidGrouped(true); - b->p_raid_instance = this; - - - auto pack = new ServerPacket(ServerOP_RaidAdd, sizeof(ServerRaidGeneralAction_Struct)); - ServerRaidGeneralAction_Struct* rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; - rga->rid = GetID(); - strn0cpy(rga->playername, b->GetName(), 64); - rga->zoneid = zone->GetZoneID(); - rga->instance_id = zone->GetInstanceID(); - worldserver.SendPacket(pack); - safe_delete(pack); -} -#endif - - void Raid::RemoveMember(const char *characterName) { std::string query = StringFormat("DELETE FROM raid_members where name='%s'", characterName); auto results = database.QueryDatabase(query); Client *client = entity_list.GetClientByName(characterName); -#ifdef BOTS - Bot* bot = entity_list.GetBotByBotName(characterName); - - if (bot) { - bot->SetFollowID(bot->GetOwner()->CastToClient()->GetID()); - bot->SetGrouped(false); - bot->SetTarget(nullptr); - bot->SetRaidGrouped(false); - } -#endif - disbandCheck = true; SendRaidRemoveAll(characterName); SendRaidDisband(client); @@ -1054,12 +983,12 @@ void Raid::SendRaidAdd(const char *who, Client *to) void Raid::SendRaidAddAll(const char *who) { - for (int x = 0; x < MAX_RAID_MEMBERS; x++) + for(int x = 0; x < MAX_RAID_MEMBERS; x++) { - if (strcmp(members[x].membername, who) == 0 ) + if(strcmp(members[x].membername, who) == 0) { auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidAddMember_Struct)); - RaidAddMember_Struct* ram = (RaidAddMember_Struct*)outapp->pBuffer; + RaidAddMember_Struct *ram = (RaidAddMember_Struct*)outapp->pBuffer; ram->raidGen.action = raidAdd; ram->raidGen.parameter = members[x].GroupNumber; strcpy(ram->raidGen.leader_name, members[x].membername); @@ -1070,7 +999,6 @@ void Raid::SendRaidAddAll(const char *who) QueuePacket(outapp); safe_delete(outapp); return; - } } } @@ -1183,16 +1111,11 @@ void Raid::SendBulkRaid(Client *to) if(!to) return; -#ifdef BOTS - if (members[GetPlayerIndex(to)].IsBot) - return; -#endif - for(int x = 0; x < MAX_RAID_MEMBERS; x++) { - if(members[x].member && strlen(members[x].membername) > 0 && (strcmp(members[x].membername, to->GetName()) != 0)) //don't send ourself + if(strlen(members[x].membername) > 0 && (strcmp(members[x].membername, to->GetName()) != 0)) //don't send ourself { - SendRaidAdd(members[x].membername, to); + SendRaidAdd(members[x].membername, to); } } } @@ -1201,11 +1124,7 @@ void Raid::QueuePacket(const EQApplicationPacket *app, bool ack_req) { for(int x = 0; x < MAX_RAID_MEMBERS; x++) { -#ifdef BOTS - if(members[x].member && !members[x].IsBot) -#else if(members[x].member) -#endif { members[x].member->QueuePacket(app, ack_req); } @@ -1214,12 +1133,6 @@ void Raid::QueuePacket(const EQApplicationPacket *app, bool ack_req) void Raid::SendMakeLeaderPacket(const char *who) //30 { - -#ifdef BOTS - if (entity_list.GetBotByBotName(who) && members[GetPlayerIndex(who)].IsBot) - return; -#endif - auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidLeadershipUpdate_Struct)); RaidLeadershipUpdate_Struct *rg = (RaidLeadershipUpdate_Struct*)outapp->pBuffer; rg->action = raidMakeLeader; @@ -1235,11 +1148,6 @@ void Raid::SendMakeLeaderPacketTo(const char *who, Client *to) if(!to) return; -#ifdef BOTS - if (members[GetPlayerIndex(who)].IsBot) - return; -#endif - auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidLeadershipUpdate_Struct)); RaidLeadershipUpdate_Struct *rg = (RaidLeadershipUpdate_Struct*)outapp->pBuffer; rg->action = raidMakeLeader; @@ -1270,11 +1178,6 @@ void Raid::SendGroupUpdate(Client *to) if(!to) return; -#ifdef BOTS - if (members[GetPlayerIndex(to)].IsBot) - return; -#endif - auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupUpdate2_Struct)); GroupUpdate2_Struct* gu = (GroupUpdate2_Struct*)outapp->pBuffer; gu->action = groupActUpdate; @@ -1321,7 +1224,7 @@ void Raid::GroupUpdate(uint32 gid, bool initial) { if(strlen(members[x].membername) > 0){ if(members[x].GroupNumber == gid){ - if (members[x].member) { + if(members[x].member) { SendGroupUpdate(members[x].member); SendGroupLeadershipAA(members[x].member, gid); } @@ -1463,11 +1366,6 @@ void Raid::SendRaidMOTDToWorld() void Raid::SendGroupLeadershipAA(Client *c, uint32 gid) { -#ifdef BOTS - if (members[GetPlayerIndex(c)].IsBot) - return; -#endif - auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidLeadershipUpdate_Struct)); RaidLeadershipUpdate_Struct *rlaa = (RaidLeadershipUpdate_Struct *)outapp->pBuffer; rlaa->action = raidSetLeaderAbilities; @@ -1483,26 +1381,17 @@ void Raid::SendGroupLeadershipAA(Client *c, uint32 gid) void Raid::SendGroupLeadershipAA(uint32 gid) { for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++) -#ifdef BOTS - if (members[i].member && members[i].GroupNumber == gid && !members[i].IsBot) -#else if (members[i].member && members[i].GroupNumber == gid) -#endif SendGroupLeadershipAA(members[i].member, gid); } void Raid::SendAllRaidLeadershipAA() { for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++) -#ifdef BOTS - if (members[i].member && !members[i].IsBot) -#else if (members[i].member) -#endif - SendGroupLeadershipAA(members[i].member, members[i].GroupNumber); + SendGroupLeadershipAA(members[i].member, members[i].GroupNumber); } - void Raid::LockRaid(bool lockFlag) { std::string query = StringFormat("UPDATE raid_details SET locked = %d WHERE raidid = %lu", @@ -1568,18 +1457,11 @@ bool Raid::LearnMembers() { memset(members, 0, (sizeof(RaidMember)*MAX_RAID_MEMBERS)); -#ifdef BOTS std::string query = StringFormat("SELECT name, groupid, _class, level, " - "isgroupleader, israidleader, islooter, isbot " + "isgroupleader, israidleader, islooter " "FROM raid_members WHERE raidid = %lu", (unsigned long)GetID()); -#else - std::string query = StringFormat("SELECT name, groupid, _class, level, " - "isgroupleader, israidleader, islooter " - "FROM raid_members WHERE raidid = %lu", - (unsigned long)GetID()); -#endif - auto results = database.QueryDatabase(query); + auto results = database.QueryDatabase(query); if (!results.Success()) return false; @@ -1607,10 +1489,7 @@ bool Raid::LearnMembers() members[index].IsGroupLeader = atoi(row[4]); members[index].IsRaidLeader = atoi(row[5]); members[index].IsLooter = atoi(row[6]); -#ifdef BOTS - members[index].IsBot = atoi(row[7]); -#endif - ++index; + ++index; } return true; @@ -1625,32 +1504,14 @@ void Raid::VerifyRaid() } else{ Client *c = entity_list.GetClientByName(members[x].membername); -#ifdef BOTS - Bot* b = entity_list.GetBotByBotName(members[x].membername); -#endif if(c){ members[x].member = c; -#ifdef BOTS - members[x].IsBot = false; -#endif } -#ifdef BOTS - else if(b){ - //Raid requires client* we are forcing it here to be a BOT. Care is needed here as any client function that - //does not exist within the Bot Class will likely corrupt memory for the member object. Good practice to test the IsBot - //attribute before calling a client function or casting to client. - members[x].member = b->CastToClient(); - members[x].IsBot = true; //Used to identify those members who are Bots - } -#endif - else { + else{ members[x].member = nullptr; -#ifdef BOTS - members[x].IsBot = false; -#endif } } - if(members[x].IsRaidLeader){ + if(members[x].IsRaidLeader){ if(strlen(members[x].membername) > 0){ SetLeader(members[x].member); strn0cpy(leadername, members[x].membername, 64); @@ -1700,11 +1561,7 @@ void Raid::SendHPManaEndPacketsTo(Client *client) EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); for(int x = 0; x < MAX_RAID_MEMBERS; x++) { -#ifdef BOTS - if(members[x].member && !members[x].IsBot) { -#else - if (members[x].member) { -#endif + if(members[x].member) { if((members[x].member != client) && (members[x].GroupNumber == group_id)) { members[x].member->CreateHPPacket(&hp_packet); @@ -1746,11 +1603,7 @@ void Raid::SendHPManaEndPacketsFrom(Mob *mob) mob->CreateHPPacket(&hpapp); for(int x = 0; x < MAX_RAID_MEMBERS; x++) { -#ifdef BOTS - if(members[x].member && !members[x].IsBot) { -#else - if (members[x].member) { -#endif + if(members[x].member) { if(!mob->IsClient() || ((members[x].member != mob->CastToClient()) && (members[x].GroupNumber == group_id))) { members[x].member->QueuePacket(&hpapp, false); if (members[x].member->ClientVersion() >= EQ::versions::ClientVersion::SoD) { @@ -1783,11 +1636,7 @@ void Raid::SendManaPacketFrom(Mob *mob) EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); for (int x = 0; x < MAX_RAID_MEMBERS; x++) { -#ifdef BOTS - if (members[x].member && !members[x].IsBot) { -#else if (members[x].member) { -#endif if (!mob->IsClient() || ((members[x].member != mob->CastToClient()) && (members[x].GroupNumber == group_id))) { if (members[x].member->ClientVersion() >= EQ::versions::ClientVersion::SoD) { outapp.SetOpcode(OP_MobManaUpdate); @@ -1814,11 +1663,7 @@ void Raid::SendEndurancePacketFrom(Mob *mob) EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); for (int x = 0; x < MAX_RAID_MEMBERS; x++) { -#ifdef BTOS - if (members[x].member && !members[x].IsBot) { -#else if (members[x].member) { -#endif if (!mob->IsClient() || ((members[x].member != mob->CastToClient()) && (members[x].GroupNumber == group_id))) { if (members[x].member->ClientVersion() >= EQ::versions::ClientVersion::SoD) { outapp.SetOpcode(OP_MobEnduranceUpdate); @@ -1925,18 +1770,9 @@ void Raid::CheckGroupMentor(uint32 group_id, Client *c) void Raid::SetDirtyAutoHaters() { for (int i = 0; i < MAX_RAID_MEMBERS; ++i) -#ifdef BOTS - if (members[i].member && members[i].IsBot) - { - members[i].member->CastToBot()->SetDirtyAutoHaters(); - } - else if (members[i].member && !members[i].IsBot) -#else if (members[i].member) -#endif - { members[i].member->SetDirtyAutoHaters(); - } + } void Raid::QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_required /*= true*/, bool ignore_sender /*= true*/, float distance /*= 0*/, bool group_only /*= true*/) { @@ -1955,10 +1791,6 @@ void Raid::QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_re if (!members[i].member->IsClient()) continue; -#ifdef BOTS - if (members[i].IsBot) - continue; -#endif if (ignore_sender && members[i].member == sender) continue; @@ -2021,17 +1853,3 @@ bool Raid::DoesAnyMemberHaveExpeditionLockout( return Expedition::HasLockoutByCharacterName(raid_member.membername, expedition_name, event_name); }); } -#ifdef BOTS -Mob* Raid::GetRaidMainAssistOneByName(const char* name) -{ - Raid* raid = entity_list.GetRaidByBotName(name); - std::vector raid_members = raid->GetMembers(); - - for (RaidMember iter : raid_members) - { - if (iter.IsRaidMainAssistOne) - return iter.member->CastToMob(); - } - return nullptr; -} -#endif diff --git a/zone/raids.h b/zone/raids.h index 141fd17ca..e1d1cadb3 100644 --- a/zone/raids.h +++ b/zone/raids.h @@ -88,10 +88,6 @@ struct RaidMember{ bool IsGroupLeader; bool IsRaidLeader; bool IsLooter; -#ifdef BOTS - bool IsBot = false; - bool IsRaidMainAssistOne = false; -#endif }; struct GroupMentor { @@ -116,11 +112,6 @@ public: bool IsRaid() { return true; } void AddMember(Client *c, uint32 group = 0xFFFFFFFF, bool rleader=false, bool groupleader=false, bool looter=false); -#ifdef BOTS - void AddBot(Bot* b, uint32 group = 0xFFFFFFFF, bool rleader=false, bool groupleader=false, bool looter=false); - void RaidBotGroupSay(Bot* b, uint8 language, uint8 lang_skill, const char* msg, ...); //Not yet implemented - Mob* GetRaidMainAssistOneByName(const char* name); -#endif void RemoveMember(const char *c); void DisbandRaid(); void MoveMember(const char *name, uint32 newGroup); @@ -130,7 +121,6 @@ public: bool IsGroupLeader(const char *who); bool IsRaidMember(const char *name); void UpdateLevel(const char *name, int newLevel); - uint32 GetFreeGroup(); uint8 GroupCount(uint32 gid); @@ -251,7 +241,6 @@ public: bool DoesAnyMemberHaveExpeditionLockout(const std::string& expedition_name, const std::string& event_name, int max_check_count = 0); std::vector GetMembers() const; - std::vector GetRaidGroupMembers(uint32 gid); RaidMember members[MAX_RAID_MEMBERS]; char leadername[64]; diff --git a/zone/spawn2.cpp b/zone/spawn2.cpp index 3b6d1b94a..d314137bd 100644 --- a/zone/spawn2.cpp +++ b/zone/spawn2.cpp @@ -154,7 +154,7 @@ bool Spawn2::Process() { return true; } - if (timer.Check() && zone->spawn2_timer.Enabled()) { + if (timer.Check()) { timer.Disable(); LogSpawns("Spawn2 [{}]: Timer has triggered", spawn2_id); diff --git a/zone/zone.cpp b/zone/zone.cpp index 7e0f2fc06..f796b8416 100755 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -1742,7 +1742,6 @@ bool Zone::Depop(bool StartSpawnTimer) { itr = npctable.begin(); delete itr->second; itr->second = nullptr; - npctable.erase(itr); }