diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 83963f520..798114399 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -98,7 +98,6 @@ SET(zone_sources mob.cpp mob_ai.cpp mob_appearance.cpp - mob_bot.cpp mob_movement_manager.cpp mob_info.cpp npc.cpp diff --git a/zone/bot.cpp b/zone/bot.cpp index 1436cd363..078785520 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -108,7 +108,6 @@ Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm SetCastedSpellType(UINT16_MAX); SetCommandedSpell(false); SetPullingSpell(false); - //DisableBotSpellTimers(); // Do this once and only in this constructor GenerateAppearance(); @@ -3267,6 +3266,14 @@ Mob* Bot::GetBotTarget(Client* bot_owner) return t; } +bool Bot::TargetValidation(Mob* other) { + if (!other || GetAppearance() == eaDead) { + return false; + } + + return true; +} + bool Bot::ReturningFlagChecks(Client* bot_owner, Mob* leash_owner, float fm_distance) { if ( (NOT_GUARDING && fm_distance <= GetFollowDistance()) || @@ -3646,14 +3653,6 @@ bool Bot::Spawn(Client* botCharacterOwner) { m_auto_save_timer.Start(RuleI(Bots, AutosaveIntervalSeconds) * 1000); m_dont_heal_me_before = 0; - m_dont_regular_heal_me_before = 0; - m_dont_very_fast_heal_me_before = 0; - m_dont_fast_heal_me_before = 0; - m_dont_complete_heal_me_before = 0; - m_dont_hot_heal_me_before = 0; - m_dont_group_heal_me_before = 0; - m_dont_group_hot_heal_me_before = 0; - m_dont_group_complete_heal_me_before = 0; m_dont_buff_me_before = Timer::GetCurrentTime() + 400; m_dont_dot_me_before = 0; m_dont_root_me_before = 0; @@ -9674,7 +9673,7 @@ bool Bot::CastChecks(uint16 spell_id, Mob* tar, uint16 spell_type, bool precheck return false; } - if (tar->IsImmuneToBotSpell(spell_id, this)) { + if (tar->CastToBot()->IsImmuneToBotSpell(spell_id, this)) { LogBotSpellChecksDetail("{} says, 'Cancelling cast of {} on {} due to IsImmuneToBotSpell.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName()); return false; } @@ -10104,7 +10103,7 @@ bool Bot::DoResistCheck(Mob* tar, uint16 spell_id, int32 resist_limit) { default: return true; } - //LogBotSpellChecksDetail("DoResistCheck on {} for {} - TarResist [{}] LMod [{}] ResistDiff [{}] - Adjust [{}] > ResistLim [{}]", tar->GetCleanName(), GetSpellName(spell_id), target_resist, level_mod, resist_difficulty, (target_resist + level_mod - resist_difficulty), resist_limit); + if ((target_resist + level_mod - resist_difficulty) > resist_limit) { return false; } @@ -10548,10 +10547,20 @@ void Bot::SetBotSpellRecastTimer(uint16 spell_type, Mob* tar, bool precast) { } if (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot()) { - return tar->GetOwner()->SetSpellTypeRecastTimer(spell_type, (GetUltimateSpellDelay(spell_type, tar) + added_delay)); + if (tar->IsClient()) { + tar->GetOwner()->CastToClient()->SetSpellTypeRecastTimer(spell_type, (GetUltimateSpellDelay(spell_type, tar) + added_delay)); + } + else { + tar->GetOwner()->CastToBot()->SetSpellTypeRecastTimer(spell_type, (GetUltimateSpellDelay(spell_type, tar) + added_delay)); + } } else if (IsBotSpellTypeOtherBeneficial(spell_type)) { - tar->SetSpellTypeRecastTimer(spell_type, (GetUltimateSpellDelay(spell_type, tar) + added_delay)); + if (tar->IsClient()) { + tar->CastToClient()->SetSpellTypeRecastTimer(spell_type, (GetUltimateSpellDelay(spell_type, tar) + added_delay)); + } + else { + tar->CastToBot()->SetSpellTypeRecastTimer(spell_type, (GetUltimateSpellDelay(spell_type, tar) + added_delay)); + } } else { SetSpellTypeRecastTimer(spell_type, (GetUltimateSpellDelay(spell_type, tar) + added_delay)); @@ -10671,6 +10680,134 @@ int Bot::GetSetting(uint16 setting_category, uint16 setting_type) { } } +bool Bot::GetDefaultSpellHold(uint16 spell_type, uint8 stance) { + uint8 bot_class = GetClass(); + + switch (spell_type) { + case BotSpellTypes::FastHeals: + case BotSpellTypes::VeryFastHeals: + case BotSpellTypes::Pet: + case BotSpellTypes::Escape: + case BotSpellTypes::Lifetap: + case BotSpellTypes::Buff: + case BotSpellTypes::PetBuffs: + case BotSpellTypes::InCombatBuff: + case BotSpellTypes::PreCombatBuff: + case BotSpellTypes::DamageShields: + case BotSpellTypes::ResistBuffs: + return false; + case BotSpellTypes::GroupCompleteHeals: + case BotSpellTypes::GroupHeals: + case BotSpellTypes::GroupHoTHeals: + case BotSpellTypes::HoTHeals: + case BotSpellTypes::CompleteHeal: + case BotSpellTypes::PetFastHeals: + case BotSpellTypes::PetRegularHeals: + case BotSpellTypes::PetVeryFastHeals: + case BotSpellTypes::RegularHeal: + switch (stance) { + case Stance::Aggressive: + case Stance::AEBurn: + case Stance::Burn: + return true; + default: + return false; + } + case BotSpellTypes::Cure: + case BotSpellTypes::GroupCures: + switch (stance) { + case Stance::Aggressive: + case Stance::AEBurn: + case Stance::Burn: + return true; + default: + return false; + } + case BotSpellTypes::InCombatBuffSong: + case BotSpellTypes::OutOfCombatBuffSong: + case BotSpellTypes::PreCombatBuffSong: + if (bot_class == Class::Bard) { + return false; + } + else { + return true; + } + case BotSpellTypes::Nuke: + case BotSpellTypes::DOT: + case BotSpellTypes::Stun: + switch (stance) { + case Stance::Assist: + return true; + default: + return false; + } + case BotSpellTypes::AENukes: + case BotSpellTypes::AERains: + case BotSpellTypes::AEStun: + case BotSpellTypes::AEDoT: + case BotSpellTypes::AELifetap: + case BotSpellTypes::PBAENuke: + switch (stance) { + case Stance::AEBurn: + return false; + default: + return true; + } + case BotSpellTypes::Mez: + case BotSpellTypes::AEMez: + case BotSpellTypes::Debuff: + case BotSpellTypes::AEDebuff: + case BotSpellTypes::Slow: + case BotSpellTypes::AESlow: + case BotSpellTypes::HateRedux: + switch (stance) { + case Stance::AEBurn: + case Stance::Burn: + return true; + default: + return false; + } + case BotSpellTypes::Snare: + switch (stance) { + case Stance::AEBurn: + case Stance::Burn: + case Stance::Assist: + return true; + default: + return false; + } + case BotSpellTypes::HateLine: + if (bot_class == Class::ShadowKnight || bot_class == Class::Paladin) { + switch (stance) { + case Stance::Aggressive: + return false; + default: + return true; + } + } + else { + return true; + } + case BotSpellTypes::Charm: + case BotSpellTypes::Resurrect: + case BotSpellTypes::AESnare: + case BotSpellTypes::AERoot: + case BotSpellTypes::Root: + case BotSpellTypes::AEDispel: + case BotSpellTypes::Dispel: + case BotSpellTypes::AEFear: + case BotSpellTypes::Fear: + case BotSpellTypes::AEHateLine: + case BotSpellTypes::PetCures: + case BotSpellTypes::PetHoTHeals: + case BotSpellTypes::PetCompleteHeals: + case BotSpellTypes::PetDamageShields: + case BotSpellTypes::PetResistBuffs: + default: + return true; + } +} + uint16 Bot::GetDefaultSpellTypePriority(uint16 spell_type, uint8 priority_type, uint8 bot_class, uint8 stance) { switch (priority_type) { case BotPriorityCategories::Idle: @@ -10840,7 +10977,7 @@ uint16 Bot::GetDefaultSpellTypeEngagedPriority(uint16 spell_type, uint8 bot_clas case BotSpellTypes::InCombatBuffSong: return 44; default: - return 0; + return 0; //unused } } @@ -10893,7 +11030,7 @@ uint16 Bot::GetDefaultSpellTypePursuePriority(uint16 spell_type, uint8 bot_class case BotSpellTypes::PetCures: return 23; default: - return 0; + return 0; //unused } } @@ -10983,7 +11120,19 @@ uint16 Bot::GetDefaultSpellTypeAEOrGroupTargetCount(uint16 spell_type, uint8 sta return RuleI(Bots, MinTargetsForGroupSpell); } - return 0; + return 1; +} + +bool Bot::GetUltimateSpellHold(uint16 spell_type, Mob* tar) { + if (!tar) { + return GetSpellHold(spell_type); + } + + if (tar->IsPet() && tar->GetOwner() && tar->IsPetOwnerBot()) { + return tar->GetOwner()->CastToBot()->GetSpellHold(GetPetBotSpellType(spell_type)); + } + + return GetSpellHold(spell_type); } void Bot::SetSpellTypePriority(uint16 spell_type, uint8 priority_type, uint16 priority) { @@ -11002,34 +11151,6 @@ void Bot::SetSpellTypePriority(uint16 spell_type, uint8 priority_type, uint16 pr } } -void Bot::SetSpellTypeResistLimit(uint16 spell_type, uint16 resist_limit) { - m_bot_spell_settings[spell_type].resist_limit = resist_limit; -} - -void Bot::SetSpellTypeAggroCheck(uint16 spell_type, bool aggro_check) { - m_bot_spell_settings[spell_type].aggro_check = aggro_check; -} - -void Bot::SetSpellTypeMinManaLimit(uint16 spell_type, uint8 mana_limit) { - m_bot_spell_settings[spell_type].min_mana_pct = mana_limit; -} - -void Bot::SetSpellTypeMaxManaLimit(uint16 spell_type, uint8 mana_limit) { - m_bot_spell_settings[spell_type].max_mana_pct = mana_limit; -} - -void Bot::SetSpellTypeMinHPLimit(uint16 spell_type, uint8 hp_limit) { - m_bot_spell_settings[spell_type].min_hp_pct = hp_limit; -} - -void Bot::SetSpellTypeMaxHPLimit(uint16 spell_type, uint8 hp_limit) { - m_bot_spell_settings[spell_type].max_hp_pct = hp_limit; -} - -void Bot::SetSpellTypeAEOrGroupTargetCount(uint16 spell_type, uint16 target_count) { - m_bot_spell_settings[spell_type].ae_or_group_target_count = target_count; -} - std::list Bot::GetSpellTypesPrioritized(uint8 priority_type) { std::list cast_order; std::list temp_cast_order; @@ -11391,6 +11512,13 @@ uint16 Bot::GetParentSpellType(uint16 spell_type) { return spell_type; } +bool Bot::IsValidBotSpellType(uint16 spell_type) { + return ( + EQ::ValueWithin(spell_type, BotSpellTypes::START, BotSpellTypes::END) || + EQ::ValueWithin(spell_type, BotSpellTypes::COMMANDED_START, BotSpellTypes::COMMANDED_END) + ); +} + bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) { if (IsAEBotSpellType(spell_type) && !IsAnyAESpell(spell_id)) { return false; @@ -11712,6 +11840,85 @@ void Bot::DoCombatPositioning( return; } +bool Bot::PlotBotPositionAroundTarget(Mob* target, float& x_dest, float& y_dest, float& z_dest, float min_distance, float max_distance, bool behind_only, bool front_only, bool bypass_los) { + bool Result = false; + + if (target) { + float look_heading = 0; + + min_distance = min_distance; + max_distance = max_distance; + float temp_x = 0; + float temp_y = 0; + float temp_z = target->GetZ(); + float best_z = 0; + auto offset = GetZOffset(); + const float tar_x = target->GetX(); + const float tar_y = target->GetY(); + float tar_distance = 0; + + glm::vec3 temp_z_Position; + glm::vec4 temp_m_Position; + + const uint16 max_iterations_allowed = 50; + uint16 counter = 0; + + while (counter < max_iterations_allowed) { + temp_x = tar_x + zone->random.Real(-max_distance, max_distance); + temp_y = tar_y + zone->random.Real(-max_distance, max_distance); + + temp_z_Position.x = temp_z; + temp_z_Position.y = temp_y; + temp_z_Position.z = temp_z; + best_z = GetFixedZ(temp_z_Position); + + if (best_z != BEST_Z_INVALID) { + temp_z = best_z; + } + else { + counter++; + continue; + } + + temp_m_Position.x = temp_x; + temp_m_Position.y = temp_y; + temp_m_Position.z = temp_z; + + tar_distance = Distance(target->GetPosition(), temp_m_Position); + + if (tar_distance > max_distance || tar_distance < min_distance) { + counter++; + continue; + } + + if (front_only && !InFrontMob(target, temp_x, temp_y)) { + counter++; + continue; + } + else if (behind_only && !BehindMob(target, temp_x, temp_y)) { + counter++; + continue; + } + + if (!bypass_los && CastToBot()->RequiresLoSForPositioning() && !CheckPositioningLosFN(target, temp_x, temp_y, temp_z)) { + counter++; + continue; + } + + Result = true; + break; + } + + if (Result) { + x_dest = temp_x; + y_dest = temp_y; + z_dest = temp_z; + } + } + + return Result; +} + bool Bot::CheckDoubleRangedAttack() { int32 chance = spellbonuses.DoubleRangedAttack + itembonuses.DoubleRangedAttack + aabonuses.DoubleRangedAttack; @@ -12394,6 +12601,55 @@ void Bot::AssignBotSpellsToTypes(std::vector& AIBot_spells, std::unor } } +std::vector Bot::GatherSpellTargets(bool entire_raid, Mob* target, bool no_clients, bool no_bots, bool no_pets) { + std::vector valid_spell_targets; + + auto is_valid_target = [no_clients, no_bots](Mob* member) { + return member && + ((member->IsClient() && !no_clients) || (member->IsBot() && !no_bots)); + }; + + if (IsRaidGrouped()) { + Raid* raid = IsBot() ? CastToBot()->GetStoredRaid() : GetRaid(); + + if (raid) { + if (entire_raid) { + for (const auto& m : raid->members) { + if (is_valid_target(m.member) && m.group_number != RAID_GROUPLESS) { + valid_spell_targets.emplace_back(m.member); + } + } + } + else { + auto group_name = target ? raid->GetGroup(target->GetName()) : raid->GetGroup(GetName()); + auto raid_group = raid->GetRaidGroupMembers(group_name); + + for (const auto& m : raid_group) { + if (is_valid_target(m.member) && m.group_number != RAID_GROUPLESS) { + valid_spell_targets.emplace_back(m.member); + } + } + } + } + } + else if (IsGrouped()) { + Group* group = GetGroup(); + + if (group) { + for (const auto& m : group->members) { + if (is_valid_target(m)) { + valid_spell_targets.emplace_back(m); + } + } + } + } + else { + valid_spell_targets.emplace_back(this); + } + + return valid_spell_targets; +} + std::vector Bot::GetBuffTargets(Mob* spellTarget) { if (RuleB(Bots, RaidBuffing)) { return GetSpellTargetList(); @@ -12401,3 +12657,536 @@ std::vector Bot::GetBuffTargets(Mob* spellTarget) { return GatherSpellTargets(false, spellTarget); } + +uint8 Bot::GetHPRatioForSpellType(uint16 spell_type, Mob* tar) { + switch (spell_type) { + case BotSpellTypes::Escape: + case BotSpellTypes::HateRedux: + case BotSpellTypes::InCombatBuff: + case BotSpellTypes::InCombatBuffSong: + case BotSpellTypes::AELifetap: + case BotSpellTypes::Lifetap: + case BotSpellTypes::OutOfCombatBuffSong: + case BotSpellTypes::Pet: + case BotSpellTypes::PreCombatBuff: + case BotSpellTypes::PreCombatBuffSong: + return GetHPRatio(); + default: + return tar->GetHPRatio(); + } + + return tar->GetHPRatio(); +} + +uint16 Bot::GetPetBotSpellType(uint16 spell_type) { + switch (spell_type) { + case BotSpellTypes::VeryFastHeals: + return BotSpellTypes::PetVeryFastHeals; + case BotSpellTypes::FastHeals: + return BotSpellTypes::PetFastHeals; + case BotSpellTypes::RegularHeal: + return BotSpellTypes::PetRegularHeals; + case BotSpellTypes::CompleteHeal: + return BotSpellTypes::PetCompleteHeals; + case BotSpellTypes::HoTHeals: + return BotSpellTypes::PetHoTHeals; + case BotSpellTypes::Buff: + return BotSpellTypes::PetBuffs; + case BotSpellTypes::Cure: + return BotSpellTypes::PetCures; + case BotSpellTypes::DamageShields: + return BotSpellTypes::PetDamageShields; + case BotSpellTypes::ResistBuffs: + return BotSpellTypes::PetResistBuffs; + default: + break; + } + + return spell_type; +} + +uint16 Bot::GetSpellTypeIDByShortName(std::string spell_type_string) { + + for (int i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) { + if (!Strings::ToLower(spell_type_string).compare(GetSpellTypeShortNameByID(i))) { + return i; + } + } + + for (int i = BotSpellTypes::COMMANDED_START; i <= BotSpellTypes::COMMANDED_END; ++i) { + if (!Strings::ToLower(spell_type_string).compare(GetSpellTypeShortNameByID(i))) { + return i; + } + } + + return UINT16_MAX; +} + +bool Bot::IsValidBotSpellCategory(uint8 setting_type) { + return EQ::ValueWithin(setting_type, BotSettingCategories::START, BotSettingCategories::END_FULL); +} + +std::string Bot::GetBotSpellCategoryName(uint8 setting_type) { + return Bot::IsValidBotBaseSetting(setting_type) ? botSpellCategory_names[setting_type] : "UNKNOWN CATEGORY"; +} + +uint16 Bot::GetBotSpellCategoryIDByShortName(std::string setting_string) { + for (int i = BotSettingCategories::START; i <= BotSettingCategories::END; ++i) { + if (!Strings::ToLower(setting_string).compare(Strings::ToLower(GetBotSpellCategoryName(i)))) { + return i; + } + } + + return UINT16_MAX; +} + +bool Bot::IsValidBotBaseSetting(uint16 setting_type) { + return EQ::ValueWithin(setting_type, BotBaseSettings::START_ALL, BotBaseSettings::END); +} + +std::string Bot::GetBotSettingCategoryName(uint16 setting_type) { + return Bot::IsValidBotBaseSetting(setting_type) ? botBaseSettings_names[setting_type] : "UNKNOWN SETTING"; +} + +uint16 Bot::GetBaseSettingIDByShortName(std::string setting_string) { + for (int i = BotSettingCategories::START; i <= BotSettingCategories::END; ++i) { + if (!Strings::ToLower(setting_string).compare(Strings::ToLower(GetBotSettingCategoryName(i)))) { + return i; + } + } + + return UINT16_MAX; +} + +std::string Bot::GetSpellTypeShortNameByID(uint16 spell_type) { + return IsValidBotSpellType(spell_type) ? spellType_shortNames[spell_type] : "UNKNOWN SPELLTYPE"; +} + +std::string Bot::GetSpellTypeNameByID(uint16 spell_type) { + return IsValidBotSpellType(spell_type) ? spellType_names[spell_type] : "UNKNOWN SPELLTYPE"; +} + +bool Bot::IsValidSubType(uint16 sub_type) { + return EQ::ValueWithin(sub_type, CommandedSubTypes::START, CommandedSubTypes::END); +} + +std::string Bot::GetSubTypeNameByID(uint16 sub_type) { + return IsValidBotSpellType(sub_type) ? botSubType_names[sub_type] : "UNKNOWN SUBTYPE"; +} + +uint16 Bot::GetDefaultSpellDelay(uint16 spell_type, uint8 stance) { + switch (spell_type) { + case BotSpellTypes::VeryFastHeals: + case BotSpellTypes::PetVeryFastHeals: + return 1500; + case BotSpellTypes::FastHeals: + case BotSpellTypes::PetFastHeals: + return 2500; + case BotSpellTypes::GroupHeals: + case BotSpellTypes::RegularHeal: + case BotSpellTypes::PetRegularHeals: + return 4000; + case BotSpellTypes::CompleteHeal: + case BotSpellTypes::GroupCompleteHeals: + case BotSpellTypes::PetCompleteHeals: + return 8000; + case BotSpellTypes::GroupHoTHeals: + case BotSpellTypes::HoTHeals: + case BotSpellTypes::PetHoTHeals: + return 22000; + case BotSpellTypes::Cure: + return 2000; + case BotSpellTypes::GroupCures: + return 3000; + case BotSpellTypes::PetCures: + return 5000; + case BotSpellTypes::AEDoT: + case BotSpellTypes::DOT: + switch (stance) { + case Stance::AEBurn: + case Stance::Burn: + return 1; + case Stance::Aggressive: + return 2000; + case Stance::Efficient: + return 8000; + default: + return 4000; + } + case BotSpellTypes::AENukes: + case BotSpellTypes::AERains: + case BotSpellTypes::PBAENuke: + case BotSpellTypes::Nuke: + case BotSpellTypes::AESnare: + case BotSpellTypes::Snare: + case BotSpellTypes::AEDebuff: + case BotSpellTypes::Debuff: + case BotSpellTypes::AESlow: + case BotSpellTypes::Slow: + case BotSpellTypes::AEStun: + case BotSpellTypes::Stun: + switch (stance) { + case Stance::AEBurn: + case Stance::Burn: + return 1; + case Stance::Aggressive: + return 3000; + case Stance::Efficient: + return 10000; + default: + return 6000; + } + case BotSpellTypes::AERoot: + case BotSpellTypes::Root: + return 8000; + case BotSpellTypes::Fear: + case BotSpellTypes::AEFear: + return 15000; + default: + return 1; + } +} + +uint8 Bot::GetDefaultSpellMinThreshold(uint16 spell_type, uint8 stance) { + switch (spell_type) { + case BotSpellTypes::AEDebuff: + case BotSpellTypes::Debuff: + case BotSpellTypes::AEDispel: + case BotSpellTypes::Dispel: + case BotSpellTypes::AESlow: + case BotSpellTypes::Slow: + switch (stance) { + case Stance::AEBurn: + case Stance::Burn: + case Stance::Aggressive: + return 0; + default: + return 20; + } + case BotSpellTypes::AENukes: + case BotSpellTypes::AERains: + case BotSpellTypes::PBAENuke: + case BotSpellTypes::Nuke: + switch (stance) { + case Stance::AEBurn: + case Stance::Burn: + case Stance::Aggressive: + return 0; + default: + return 5; + } + case BotSpellTypes::AEDoT: + case BotSpellTypes::DOT: + switch (stance) { + case Stance::AEBurn: + case Stance::Burn: + case Stance::Aggressive: + return 0; + case Stance::Efficient: + return 40; + default: + return 25; + } + case BotSpellTypes::Mez: + case BotSpellTypes::AEMez: + return 85; + default: + return 0; + } +} + +uint8 Bot::GetDefaultSpellMaxThreshold(uint16 spell_type, uint8 stance) { + uint8 bot_class = GetClass(); + + switch (spell_type) { + case BotSpellTypes::Escape: + case BotSpellTypes::VeryFastHeals: + case BotSpellTypes::PetVeryFastHeals: + switch (stance) { + case Stance::AEBurn: + case Stance::Burn: + case Stance::Aggressive: + return 40; + case Stance::Efficient: + default: + return 25; + } + case BotSpellTypes::AELifetap: + case BotSpellTypes::Lifetap: + case BotSpellTypes::FastHeals: + case BotSpellTypes::PetFastHeals: + switch (stance) { + case Stance::AEBurn: + case Stance::Burn: + case Stance::Aggressive: + return 55; + case Stance::Efficient: + return 35; + default: + return 40; + } + case BotSpellTypes::GroupHeals: + case BotSpellTypes::RegularHeal: + case BotSpellTypes::PetRegularHeals: + switch (stance) { + case Stance::AEBurn: + case Stance::Burn: + case Stance::Aggressive: + return 70; + case Stance::Efficient: + return 50; + default: + return 60; + } + case BotSpellTypes::CompleteHeal: + case BotSpellTypes::GroupCompleteHeals: + case BotSpellTypes::PetCompleteHeals: + switch (stance) { + case Stance::AEBurn: + case Stance::Burn: + case Stance::Aggressive: + return 90; + case Stance::Efficient: + return 65; + default: + return 80; + } + case BotSpellTypes::AENukes: + case BotSpellTypes::AERains: + case BotSpellTypes::PBAENuke: + case BotSpellTypes::AEStun: + case BotSpellTypes::Nuke: + case BotSpellTypes::AEDoT: + case BotSpellTypes::DOT: + case BotSpellTypes::AERoot: + case BotSpellTypes::Root: + case BotSpellTypes::AESlow: + case BotSpellTypes::Slow: + case BotSpellTypes::AESnare: + case BotSpellTypes::Snare: + case BotSpellTypes::AEFear: + case BotSpellTypes::Fear: + case BotSpellTypes::AEDispel: + case BotSpellTypes::Dispel: + case BotSpellTypes::AEDebuff: + case BotSpellTypes::Debuff: + case BotSpellTypes::Stun: + switch (stance) { + case Stance::AEBurn: + case Stance::Burn: + return 100; + case Stance::Aggressive: + return 100; + case Stance::Efficient: + return 90; + default: + return 99; + } + case BotSpellTypes::GroupHoTHeals: + case BotSpellTypes::HoTHeals: + case BotSpellTypes::PetHoTHeals: + if (bot_class == Class::Necromancer || bot_class == Class::Shaman) { + return 60; + } + else { + switch (stance) { + case Stance::AEBurn: + case Stance::Burn: + case Stance::Aggressive: + return 95; + case Stance::Efficient: + return 80; + default: + return 90; + } + } + case BotSpellTypes::Buff: + case BotSpellTypes::Charm: + case BotSpellTypes::Cure: + case BotSpellTypes::GroupCures: + case BotSpellTypes::PetCures: + case BotSpellTypes::DamageShields: + case BotSpellTypes::HateRedux: + case BotSpellTypes::InCombatBuff: + case BotSpellTypes::InCombatBuffSong: + case BotSpellTypes::Mez: + case BotSpellTypes::AEMez: + case BotSpellTypes::OutOfCombatBuffSong: + case BotSpellTypes::Pet: + case BotSpellTypes::PetBuffs: + case BotSpellTypes::PreCombatBuff: + case BotSpellTypes::PreCombatBuffSong: + case BotSpellTypes::PetDamageShields: + case BotSpellTypes::PetResistBuffs: + case BotSpellTypes::ResistBuffs: + case BotSpellTypes::Resurrect: + case BotSpellTypes::HateLine: + case BotSpellTypes::AEHateLine: + default: + return 100; + } +} + +uint16 Bot::GetUltimateSpellDelay(uint16 spell_type, Mob* tar) { + if (!tar) { + return GetSpellDelay(spell_type); + } + + if (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot()) { + return tar->IsClient() ? tar->GetOwner()->CastToClient()->GetSpellDelay(GetPetBotSpellType(spell_type)) : tar->GetOwner()->CastToBot()->GetSpellDelay(GetPetBotSpellType(spell_type)); + } + + if (IsBotSpellTypeOtherBeneficial(spell_type) && tar->IsOfClientBot()) { + return tar->IsClient() ? tar->CastToClient()->GetSpellDelay(spell_type) : tar->CastToBot()->GetSpellDelay(spell_type); + } + + return GetSpellDelay(spell_type); +} + +bool Bot::GetUltimateSpellDelayCheck(uint16 spell_type, Mob* tar) { + if (!tar) { + return SpellTypeRecastCheck(spell_type); + } + + if (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot()) { + return tar->IsClient() ? tar->GetOwner()->CastToClient()->SpellTypeRecastCheck(GetPetBotSpellType(spell_type)) : tar->GetOwner()->CastToBot()->SpellTypeRecastCheck(GetPetBotSpellType(spell_type)); + } + + if (IsBotSpellTypeOtherBeneficial(spell_type) && tar->IsOfClientBot()) { + return tar->IsClient() ? tar->CastToClient()->SpellTypeRecastCheck(spell_type) : tar->CastToBot()->SpellTypeRecastCheck(spell_type); + } + + return SpellTypeRecastCheck(spell_type); +} + +uint8 Bot::GetUltimateSpellMinThreshold(uint16 spell_type, Mob* tar) { + if (!tar) { + return GetSpellMinThreshold(spell_type); + } + + if (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot()) { + return tar->IsClient() ? tar->GetOwner()->CastToClient()->GetSpellMinThreshold(GetPetBotSpellType(spell_type)) : tar->GetOwner()->CastToBot()->GetSpellMinThreshold(GetPetBotSpellType(spell_type)); + } + + if (IsBotSpellTypeOtherBeneficial(spell_type) && tar->IsOfClientBot()) { + return tar->IsClient() ? tar->CastToClient()->GetSpellMinThreshold(spell_type) : tar->CastToBot()->GetSpellMinThreshold(spell_type); + } + + return GetSpellMinThreshold(spell_type); +} + +uint8 Bot::GetUltimateSpellMaxThreshold(uint16 spell_type, Mob* tar) { + if (!tar) { + return GetSpellMaxThreshold(spell_type); + } + + if (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot()) { + return tar->IsClient() ? tar->GetOwner()->CastToClient()->GetSpellMaxThreshold(GetPetBotSpellType(spell_type)) : tar->GetOwner()->CastToBot()->GetSpellMaxThreshold(GetPetBotSpellType(spell_type)); + } + + if (IsBotSpellTypeOtherBeneficial(spell_type) && tar->IsOfClientBot()) { + return tar->IsClient() ? tar->CastToClient()->GetSpellMaxThreshold(spell_type) : tar->CastToBot()->GetSpellMaxThreshold(spell_type); + } + + return GetSpellMaxThreshold(spell_type); +} + +bool Bot::IsImmuneToBotSpell(uint16 spell_id, Mob* caster) { + int effect_index; + + if (!caster) { + return false; + } + + LogSpells("Checking to see if we are immune to spell [{}] cast by [{}]", spell_id, caster->GetName()); + + if (!IsValidSpell(spell_id)) { + return true; + } + + if (GetSpecialAbility(SpecialAbility::DispellImmunity) && IsDispelSpell(spell_id)) { + return true; + } + + if (GetSpecialAbility(SpecialAbility::PacifyImmunity) && IsHarmonySpell(spell_id)) { + return true; + } + + if (!GetSpecialAbility(SpecialAbility::MesmerizeImmunity) && IsMesmerizeSpell(spell_id)) { + // check max level for spell + effect_index = GetSpellEffectIndex(spell_id, SE_Mez); + assert(effect_index >= 0); + // NPCs get to ignore the max level + if ( + (GetLevel() > spells[spell_id].max_value[effect_index]) && + (!caster->IsNPC() || (caster->IsNPC() && !RuleB(Spells, NPCIgnoreBaseImmunity))) + ) { + return true; + } + } + + // slow and haste spells + if (GetSpecialAbility(SpecialAbility::SlowImmunity) && IsEffectInSpell(spell_id, SE_AttackSpeed)) { + return true; + } + + // client vs client fear + if (!GetSpecialAbility(SpecialAbility::FearImmunity) && IsEffectInSpell(spell_id, SE_Fear)) { + effect_index = GetSpellEffectIndex(spell_id, SE_Fear); + + if (IsClient() && caster->IsClient() && (caster->CastToClient()->GetGM() == false)) { + LogSpells("Clients cannot fear eachother!"); + caster->MessageString(Chat::Red, IMMUNE_FEAR); // need to verify message type, not in MQ2Cast for easy look up + return true; + } + else if (GetLevel() > spells[spell_id].max_value[effect_index] && spells[spell_id].max_value[effect_index] != 0) { + return true; + } + else if (CheckAATimer(aaTimerWarcry)) { + return true; + } + } + + if (!GetSpecialAbility(SpecialAbility::CharmImmunity) && IsCharmSpell(spell_id)) { + + if (this == caster) { + return true; + } + + //let npcs cast whatever charm on anyone + if (!caster->IsNPC()) { + // check level limit of charm spell + effect_index = GetSpellEffectIndex(spell_id, SE_Charm); + assert(effect_index >= 0); + if (GetLevel() > spells[spell_id].max_value[effect_index] && spells[spell_id].max_value[effect_index] != 0) { + return true; + } + } + } + + if ( + GetSpecialAbility(SpecialAbility::SnareImmunity) && + ( + IsEffectInSpell(spell_id, SE_Root) || + IsEffectInSpell(spell_id, SE_MovementSpeed) + ) + ) { + if (GetSpecialAbility(SpecialAbility::SnareImmunity)) { + return true; + } + } + + if (IsLifetapSpell(spell_id)) { + if (this == caster) { + return true; + } + } + + if (IsSacrificeSpell(spell_id)) { + if (this == caster) { + return true; + } + } + + return false; +} diff --git a/zone/bot.h b/zone/bot.h index 870eac312..67618f9cf 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -113,7 +113,7 @@ namespace BotSettingCategories { // Update GetBotSpellCategoryName as needed constexpr uint16 START = BotSettingCategories::BaseSetting; constexpr uint16 START_NO_BASE = BotSettingCategories::SpellHold; - constexpr uint16 START_CLIENT = BotSettingCategories::SpellHold; + constexpr uint16 START_CLIENT = BotSettingCategories::SpellDelay; constexpr uint16 END_CLIENT = BotSettingCategories::SpellMaxThreshold; constexpr uint16 END = BotSettingCategories::SpellTypeAEOrGroupTargetCount; constexpr uint16 END_FULL = BotSettingCategories::SpellTypeRecastDelay; @@ -527,47 +527,51 @@ public: { return Mob::Attack(other, Hand, FromRiposte, IsStrikethrough, IsFromSpell, opts); } void DoAttackRounds(Mob* target, int hand); - bool PrecastChecks(Mob* tar, uint16 spell_type); - bool CastChecks(uint16 spell_id, Mob* tar, uint16 spell_type, bool prechecks = false, bool ae_check = false); - bool CanCastSpellType(uint16 spell_type, uint16 spell_id, Mob* tar); - bool BotHasEnoughMana(uint16 spell_id); - std::vector GetSpellTargetList() { return _spellTargetList; } - void SetSpellTargetList(std::vector spell_target_list) { _spellTargetList = spell_target_list; } - std::vector GetGroupSpellTargetList() { return _groupSpellTargetList; } - void SetGroupSpellTargetList(std::vector spell_target_list) { _groupSpellTargetList = spell_target_list; } - std::vector GetBuffTargets(Mob* spellTarget); + bool BotPassiveCheck(); Raid* GetStoredRaid() { return _storedRaid; } void SetStoredRaid(Raid* stored_raid) { _storedRaid = stored_raid; } bool GetVerifiedRaid() { return _verifiedRaid; } void SetVerifiedRaid(bool status) { _verifiedRaid = status; } uint16 GetTempSpellType() { return _tempSpellType; } void SetTempSpellType(uint16 spell_type) { _tempSpellType = spell_type; } - void AssignBotSpellsToTypes(std::vector& AIBot_spells, std::unordered_map>& AIBot_spells_by_type); + bool IsMobEngagedByAnyone(Mob* tar); + void SetBotTimers(std::vector timers) { bot_timers = timers; } + + // Targeting + std::vector GatherSpellTargets(bool entireRaid = false, Mob* target = nullptr, bool no_clients = false, bool no_bots = false, bool no_pets = false); + bool HasValidAETarget(Bot* caster, uint16 spell_id, uint16 spell_type, Mob* tar); + void SetHasLoS(bool has_los) { _hasLoS = has_los; } + bool HasLoS() const { return _hasLoS; } + bool IsValidMezTarget(Mob* owner, Mob* npc, uint16 spell_id); + + // Cast checks + bool PrecastChecks(Mob* tar, uint16 spell_type); + bool CastChecks(uint16 spell_id, Mob* tar, uint16 spell_type, bool prechecks = false, bool ae_check = false); + bool IsImmuneToBotSpell(uint16 spell_id, Mob* caster); + bool CanCastSpellType(uint16 spell_type, uint16 spell_id, Mob* tar); + bool BotHasEnoughMana(uint16 spell_id); bool IsTargetAlreadyReceivingSpell(Mob* tar, uint16 spell_id); bool DoResistCheck(Mob* target, uint16 spell_id, int32 resist_limit); bool DoResistCheckBySpellType(Mob* tar, uint16 spell_id, uint16 spell_type); bool IsValidTargetType(uint16 spell_id, int target_type, uint8 body_type); - bool IsMobEngagedByAnyone(Mob* tar); - void SetBotSetting(uint8 setting_type, uint16 bot_setting, int setting_value); - void CopySettings(Bot* to, uint8 setting_type, uint16 spell_type = UINT16_MAX); - void CopyBotSpellSettings(Bot* to); - void ResetBotSpellSettings(); - void CopyBotBlockedBuffs(Bot* to); - void CopyBotBlockedPetBuffs(Bot* to); - int GetBotBaseSetting(uint16 bot_setting); - int GetDefaultBotBaseSetting(uint16 bot_setting, uint8 stance = Stance::Balanced); - void SetBotBaseSetting(uint16 bot_setting, int setting_value); - void LoadDefaultBotSettings(); - void SetBotSpellRecastTimer(uint16 spell_type, Mob* spelltar, bool pre_cast = false); - uint16 GetSpellByAA(int id, AA::Rank* &rank); - void CleanBotBlockedBuffs(); - void ClearBotBlockedBuffs() { bot_blocked_buffs.clear(); } - bool IsBlockedBuff(int32 spell_id) override; - bool IsBlockedPetBuff(int32 spell_id) override; - void SetBotBlockedBuff(uint16 spell_id, bool block); - void SetBotBlockedPetBuff(uint16 spell_id, bool block); + // Spell checks + static bool IsValidBotSpellType(uint16 spell_type); + uint16 GetPetBotSpellType(uint16 spell_type); + + // Movement checks + bool PlotBotPositionAroundTarget(Mob* target, float& x_dest, float& y_dest, float& z_dest, float min_distance, float max_distance, bool behind_only = false, bool front_only = false, bool bypass_los = false); + std::vector GetSpellTargetList() { return _spellTargetList; } + void SetSpellTargetList(std::vector spell_target_list) { _spellTargetList = spell_target_list; } + std::vector GetGroupSpellTargetList() { return _groupSpellTargetList; } + void SetGroupSpellTargetList(std::vector spell_target_list) { _groupSpellTargetList = spell_target_list; } + std::vector GetBuffTargets(Mob* spellTarget); + + // Bot settings + void LoadDefaultBotSettings(); int GetDefaultSetting(uint16 setting_category, uint16 setting_type, uint8 stance = Stance::Balanced); + int GetDefaultBotBaseSetting(uint16 bot_setting, uint8 stance = Stance::Balanced); + bool GetDefaultSpellHold(uint16 spell_type, uint8 stance = Stance::Balanced); uint16 GetDefaultSpellTypePriority(uint16 spell_type, uint8 priority_type, uint8 bot_class, uint8 stance = Stance::Balanced); uint16 GetDefaultSpellTypeIdlePriority(uint16 spell_type, uint8 bot_class, uint8 stance = Stance::Balanced); uint16 GetDefaultSpellTypeEngagedPriority(uint16 spell_type, uint8 bot_class, uint8 stance = Stance::Balanced); @@ -580,25 +584,66 @@ public: uint8 GetDefaultSpellTypeMaxHPLimit(uint16 spell_type, uint8 stance = Stance::Balanced); uint16 GetDefaultSpellTypeAEOrGroupTargetCount(uint16 spell_type, uint8 stance = Stance::Balanced); + static bool IsValidBotBaseSetting(uint16 setting_type); + static std::string GetBotSettingCategoryName(uint16 setting_type); + uint16 GetBaseSettingIDByShortName(std::string setting_string); + int GetBotBaseSetting(uint16 bot_setting); + void SetBotBaseSetting(uint16 bot_setting, int setting_value); int GetSetting(uint16 setting_category, uint16 setting_type); + void SetBotSetting(uint8 setting_type, uint16 bot_setting, int setting_value); + void CopySettings(Bot* to, uint8 setting_type, uint16 spell_type = UINT16_MAX); + void CopyBotSpellSettings(Bot* to); + void ResetBotSpellSettings(); + + void CopyBotBlockedBuffs(Bot* to); + void CopyBotBlockedPetBuffs(Bot* to); + void CleanBotBlockedBuffs(); + void ClearBotBlockedBuffs() { bot_blocked_buffs.clear(); } + bool IsBlockedBuff(int32 spell_id) override; + bool IsBlockedPetBuff(int32 spell_id) override; + void SetBotBlockedBuff(uint16 spell_id, bool block); + void SetBotBlockedPetBuff(uint16 spell_id, bool block); + std::vector GetBotBlockedBuffs() { return bot_blocked_buffs; } + void SetBotBlockedBuffs(std::vector blocked_buffs) { bot_blocked_buffs = blocked_buffs; } + + void SetBotSpellRecastTimer(uint16 spell_type, Mob* spelltar, bool pre_cast = false); + inline bool GetSpellHold(uint16 spell_type) const { return m_bot_spell_settings[spell_type].hold; } + inline void SetSpellHold(uint16 spell_type, bool value) { m_bot_spell_settings[spell_type].hold = value; } + bool GetUltimateSpellHold(uint16 spell_type, Mob* tar); uint16 GetSpellTypePriority(uint16 spell_type, uint8 priority_type); void SetSpellTypePriority(uint16 spell_type, uint8 priority_type, uint16 priority); inline uint16 GetSpellTypeResistLimit(uint16 spell_type) const { return m_bot_spell_settings[spell_type].resist_limit; } - void SetSpellTypeResistLimit(uint16 spell_type, uint16 resist_limit); + inline void SetSpellTypeResistLimit(uint16 spell_type, uint16 value) { m_bot_spell_settings[spell_type].resist_limit = value; } inline bool GetSpellTypeAggroCheck(uint16 spell_type) const { return m_bot_spell_settings[spell_type].aggro_check; } - void SetSpellTypeAggroCheck(uint16 spell_type, bool aggro_check); + inline void SetSpellTypeAggroCheck(uint16 spell_type, bool value) { m_bot_spell_settings[spell_type].aggro_check = value; } + uint8 GetHPRatioForSpellType(uint16 spell_type, Mob* tar); inline uint8 GetSpellTypeMinManaLimit(uint16 spell_type) const { return m_bot_spell_settings[spell_type].min_mana_pct; } inline uint8 GetSpellTypeMaxManaLimit(uint16 spell_type) const { return m_bot_spell_settings[spell_type].max_mana_pct; } - void SetSpellTypeMinManaLimit(uint16 spell_type, uint8 mana_limit); - void SetSpellTypeMaxManaLimit(uint16 spell_type, uint8 mana_limit); + inline void SetSpellTypeMinManaLimit(uint16 spell_type, uint8 value) { m_bot_spell_settings[spell_type].min_mana_pct = value; } + inline void SetSpellTypeMaxManaLimit(uint16 spell_type, uint8 value) { m_bot_spell_settings[spell_type].max_mana_pct = value; } inline uint8 GetSpellTypeMinHPLimit(uint16 spell_type) const { return m_bot_spell_settings[spell_type].min_hp_pct; } inline uint8 GetSpellTypeMaxHPLimit(uint16 spell_type) const { return m_bot_spell_settings[spell_type].max_hp_pct; } - void SetSpellTypeMinHPLimit(uint16 spell_type, uint8 hp_limit); - void SetSpellTypeMaxHPLimit(uint16 spell_type, uint8 hp_limit); + inline void SetSpellTypeMinHPLimit(uint16 spell_type, uint8 value) { m_bot_spell_settings[spell_type].min_hp_pct = value; } + inline void SetSpellTypeMaxHPLimit(uint16 spell_type, uint8 value) { m_bot_spell_settings[spell_type].max_hp_pct = value; } inline uint16 GetSpellTypeAEOrGroupTargetCount(uint16 spell_type) const { return m_bot_spell_settings[spell_type].ae_or_group_target_count; } - void SetSpellTypeAEOrGroupTargetCount(uint16 spell_type, uint16 target_count); - bool BotPassiveCheck(); - + inline void SetSpellTypeAEOrGroupTargetCount(uint16 spell_type, uint16 value) { m_bot_spell_settings[spell_type].ae_or_group_target_count = value; } + inline uint16 GetSpellDelay(uint16 spell_type) const { return m_bot_spell_settings[spell_type].delay; } + inline void SetSpellDelay(uint16 spell_type, uint16 delay_value) { m_bot_spell_settings[spell_type].delay = delay_value; } + inline uint8 GetSpellMinThreshold(uint16 spell_type) const { return m_bot_spell_settings[spell_type].min_threshold; } + inline void SetSpellMinThreshold(uint16 spell_type, uint8 threshold_value) { m_bot_spell_settings[spell_type].min_threshold = threshold_value; } + inline uint8 GetSpellMaxThreshold(uint16 spell_type) const { return m_bot_spell_settings[spell_type].max_threshold; } + inline void SetSpellMaxThreshold(uint16 spell_type, uint8 threshold_value) { m_bot_spell_settings[spell_type].max_threshold = threshold_value; } + inline bool SpellTypeRecastCheck(uint16 spellType) { return !m_bot_spell_settings[spellType].recast_timer.GetRemainingTime(); } + void SetSpellTypeRecastTimer(uint16 spell_type, uint32 recast_time) { m_bot_spell_settings[spell_type].recast_timer.Start(recast_time); } + uint16 GetDefaultSpellDelay(uint16 spell_type, uint8 stance = Stance::Balanced); + uint8 GetDefaultSpellMinThreshold(uint16 spell_type, uint8 stance = Stance::Balanced); + uint8 GetDefaultSpellMaxThreshold(uint16 spell_type, uint8 stance = Stance::Balanced); + uint16 GetUltimateSpellDelay(uint16 spell_type, Mob* tar); + bool GetUltimateSpellDelayCheck(uint16 spell_type, Mob* tar); + uint8 GetUltimateSpellMinThreshold(uint16 spell_type, Mob* tar); + uint8 GetUltimateSpellMaxThreshold(uint16 spell_type, Mob* tar); + void SetIllusionBlock(bool value) { _illusionBlock = value; } + bool GetIllusionBlock() const { return _illusionBlock; } bool GetShowHelm() const { return _showHelm; } void SetShowHelm(bool show_helm) { _showHelm = show_helm; } bool GetBehindMob() const { return _behindMobStatus; } @@ -615,20 +660,29 @@ public: void SetSitHPPct(uint8 value) { _SitHPPct = value; } uint8 GetSitManaPct() const { return _SitManaPct; } void SetSitManaPct(uint8 value) { _SitManaPct = value; } - void SetHasLoS(bool has_los) { _hasLoS = has_los; } - bool HasLoS() const { return _hasLoS; } + // Spell lists + void CheckBotSpells(); + void MapSpellTypeLevels(); + const std::map>& GetCommandedSpellTypesMinLevels() { return commanded_spells_min_level; } std::list GetSpellTypesPrioritized(uint8 priority_type); uint16 GetParentSpellType(uint16 spell_type); bool IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id); inline uint16 GetCastedSpellType() const { return _castedSpellType; } void SetCastedSpellType(uint16 spell_type); bool IsValidSpellTypeSubType(uint16 spell_type, uint16 sub_type, uint16 spell_id); + bool IsValidBotSpellCategory(uint8 setting_type); + static std::string GetBotSpellCategoryName(uint8 setting_type); + static uint16 GetBotSpellCategoryIDByShortName(std::string setting_string); + void AssignBotSpellsToTypes(std::vector& AIBot_spells, std::unordered_map>& AIBot_spells_by_type); + uint16 GetSpellByAA(int id, AA::Rank*& rank); - bool HasValidAETarget(Bot* caster, uint16 spell_id, uint16 spell_type, Mob* tar); - - void CheckBotSpells(); - void MapSpellTypeLevels(); + // Spell Type + static uint16 GetSpellTypeIDByShortName(std::string spellType_string); + static std::string GetSpellTypeNameByID(uint16 spell_type); + static std::string GetSpellTypeShortNameByID(uint16 spell_type); + bool IsValidSubType(uint16 sub_type); + static std::string GetSubTypeNameByID(uint16 sub_type); [[nodiscard]] int GetMaxBuffSlots() const final { return EQ::spells::LONG_BUFFS; } [[nodiscard]] int GetMaxSongSlots() const final { return EQ::spells::SHORT_BUFFS; } @@ -693,7 +747,6 @@ public: static BotSpell GetBestBotSpellForGroupHeal(Bot* caster, Mob* tar, uint16 spell_type = BotSpellTypes::RegularHeal); static Mob* GetFirstIncomingMobToMez(Bot* caster, int16 spell_id, uint16 spell_type, bool AE); - bool IsValidMezTarget(Mob* owner, Mob* npc, uint16 spell_id); static BotSpell GetBestBotSpellForMez(Bot* caster, uint16 spell_type = BotSpellTypes::Mez); static BotSpell GetBestBotMagicianPetSpell(Bot* caster, uint16 spell_type = BotSpellTypes::Pet); static std::string GetBotMagicianPetType(Bot* caster); @@ -968,10 +1021,6 @@ public: // New accessors for BotDatabase access bool DeleteBot(); std::vector GetBotTimers() { return bot_timers; } - void SetBotTimers(std::vector timers) { bot_timers = timers; } - std::vector GetBotBlockedBuffs() { return bot_blocked_buffs; } - void SetBotBlockedBuffs(std::vector blocked_buffs) { bot_blocked_buffs = blocked_buffs; } - const std::map>& GetCommandedSpellTypesMinLevels() { return commanded_spells_min_level; } uint32 GetLastZoneID() const { return _lastZoneId; } int32 GetBaseAC() const { return _baseAC; } int32 GetBaseATK() const { return _baseATK; } @@ -1020,6 +1069,7 @@ public: Mob* tar, float tar_distance ); + bool TargetValidation(Mob* other); bool PullingFlagChecks(Client* bot_owner); bool ReturningFlagChecks(Client* bot_owner, Mob* leash_owner, float fm_distance); @@ -1158,7 +1208,9 @@ private: bool _hasLoS; bool _commandedSpell; bool _pullingSpell; - + + bool _illusionBlock; + std::vector m_bot_spell_settings; std::vector _spellTargetList; std::vector _groupSpellTargetList; Raid* _storedRaid; diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 2398538cc..bc5c8c45d 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -907,9 +907,9 @@ void SendSpellTypeWindow(Client* c, const Seperator* sep) { } popup_text += DialogueWindow::TableRow( - DialogueWindow::TableCell(DialogueWindow::ColorMessage(forest_green, c->GetSpellTypeNameByID(i))) + DialogueWindow::TableCell(DialogueWindow::ColorMessage(forest_green, Bot::GetSpellTypeNameByID(i))) + - DialogueWindow::TableCell((!arg0.compare("^spelltypeids") ? DialogueWindow::ColorMessage(slate_blue, std::to_string(i)) : DialogueWindow::ColorMessage(slate_blue, c->GetSpellTypeShortNameByID(i)))) + DialogueWindow::TableCell((!arg0.compare("^spelltypeids") ? DialogueWindow::ColorMessage(slate_blue, std::to_string(i)) : DialogueWindow::ColorMessage(slate_blue, Bot::GetSpellTypeShortNameByID(i)))) ); } diff --git a/zone/bot_commands/blocked_buffs.cpp b/zone/bot_commands/blocked_buffs.cpp index 8aa767368..b604ef59d 100644 --- a/zone/bot_commands/blocked_buffs.cpp +++ b/zone/bot_commands/blocked_buffs.cpp @@ -251,7 +251,7 @@ void bot_command_blocked_pet_buffs(Client* c, const Seperator* sep) fmt::format( "{} add 202", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Nuke) ) }; p.examples_two = diff --git a/zone/bot_commands/bot.cpp b/zone/bot_commands/bot.cpp index a8346a267..186ef3958 100644 --- a/zone/bot_commands/bot.cpp +++ b/zone/bot_commands/bot.cpp @@ -1739,7 +1739,7 @@ void bot_command_toggle_ranged(Client *c, const Seperator *sep) fmt::format( "{} says, 'I {} ranged.'", first_found->GetCleanName(), - first_found->GetIllusionBlock() ? "am now" : "am no longer" + first_found->IsBotRanged() ? "am now" : "am no longer" ).c_str() ); } @@ -1904,7 +1904,7 @@ void bot_command_toggle_helm(Client *c, const Seperator *sep) fmt::format( "{} says, 'I {} show my helm.'", first_found->GetCleanName(), - first_found->GetIllusionBlock() ? "will now" : "will no longer" + first_found->GetShowHelm() ? "will now" : "will no longer" ).c_str() ); } diff --git a/zone/bot_commands/cast.cpp b/zone/bot_commands/cast.cpp index 74176788a..6f5c13c26 100644 --- a/zone/bot_commands/cast.cpp +++ b/zone/bot_commands/cast.cpp @@ -34,7 +34,7 @@ void bot_command_cast(Client* c, const Seperator* sep) fmt::format( "{} {}", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Nuke) ), fmt::format( "{} {}", @@ -208,7 +208,7 @@ void bot_command_cast(Client* c, const Seperator* sep) if (sep->IsNumber(1)) { spell_type = atoi(sep->arg[1]); - if (!c->IsValidSpellType(spell_type)) { + if (!Bot::IsValidBotSpellType(spell_type)) { c->Message( Chat::Yellow, fmt::format( @@ -223,8 +223,8 @@ void bot_command_cast(Client* c, const Seperator* sep) } } else { - if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { - spell_type = c->GetSpellTypeIDByShortName(arg1); + if (Bot::GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { + spell_type = Bot::GetSpellTypeIDByShortName(arg1); } else { c->Message( @@ -347,7 +347,7 @@ void bot_command_cast(Client* c, const Seperator* sep) fmt::format( "[{}] is an invalid target. {} requires a pet to be targeted.", tar->GetCleanName(), - tar->GetSpellTypeNameByID(spell_type) + Bot::GetSpellTypeNameByID(spell_type) ).c_str() ); @@ -589,10 +589,10 @@ void bot_command_cast(Client* c, const Seperator* sep) } else { if (sub_type == UINT16_MAX) { - type = c->GetSpellTypeNameByID(spell_type); + type = Bot::GetSpellTypeNameByID(spell_type); } else { - type = c->GetSubTypeNameByID(sub_type); + type = Bot::GetSubTypeNameByID(sub_type); } } diff --git a/zone/bot_commands/copy_settings.cpp b/zone/bot_commands/copy_settings.cpp index 53d03486c..66564926a 100644 --- a/zone/bot_commands/copy_settings.cpp +++ b/zone/bot_commands/copy_settings.cpp @@ -19,7 +19,7 @@ void bot_command_copy_settings(Client* c, const Seperator* sep) { "- You can put a spell type ID or shortname after any option except [all], [misc] and [spellsettings] to restore that specifc spell type only" }; - p.example_format = { fmt::format("{} [from] [to] [option]", sep->arg[0]) }; + p.example_format = { fmt::format("{} [from] [to] [option] [optional: spelltype id/short name]", sep->arg[0]) }; p.examples_one = { "To copy all settings from BotA to BotB:", @@ -31,12 +31,12 @@ void bot_command_copy_settings(Client* c, const Seperator* sep) fmt::format( "{} BotA BotB spelltypesettings {}", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Nuke) ), fmt::format( "{} BotA BotB spelltypesettings {}", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Nuke) ), }; p.examples_three = @@ -52,7 +52,7 @@ void bot_command_copy_settings(Client* c, const Seperator* sep) ), }; p.actionables = { "target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned" }; - p.options = { "all, misc, spellsettings, spelltypesettings, holds, delays, minthresholds, maxthresholds, minmanapct, maxmanapct, minhppct, maxhppct, idlepriority, engagedpriority, pursuepriority, aggrochecks, targetcounts, blockedbuffs, blockedpetbuffs" }; + p.options = { "all, misc, spellsettings, spelltypesettings, spellholds, spelldelays, spellminthresholds, spellmaxthresholds, spellminmanapct, spellmaxmanapct, spellminhppct, spellmaxhppct, spellidlepriority, spellengagedpriority, spellpursuepriority, spellaggrochecks, spelltargetcounts, spellresistlimits, blockedbuffs, blockedpetbuffs" }; p.options_one = { "[spellsettings] will copy ^spellsettings options", @@ -109,7 +109,8 @@ void bot_command_copy_settings(Client* c, const Seperator* sep) "spellengagedpriority", "spellpursuepriority", "spellaggrochecks", - "spelltargetcounts", + "spelltargetcounts", + "spellresistlimits", "blockedbuffs", "blockedpetbuffs" }; @@ -117,7 +118,7 @@ void bot_command_copy_settings(Client* c, const Seperator* sep) if (sep->IsNumber(spell_type_arg_int)) { spell_type = atoi(sep->arg[spell_type_arg_int]); - if (!c->IsValidSpellType(spell_type)) { + if (!Bot::IsValidBotSpellType(spell_type)) { c->Message( Chat::Yellow, fmt::format( @@ -132,8 +133,8 @@ void bot_command_copy_settings(Client* c, const Seperator* sep) } } else if (!spell_type_arg.empty()) { - if (c->GetSpellTypeIDByShortName(spell_type_arg) != UINT16_MAX) { - spell_type = c->GetSpellTypeIDByShortName(spell_type_arg); + if (Bot::GetSpellTypeIDByShortName(spell_type_arg) != UINT16_MAX) { + spell_type = Bot::GetSpellTypeIDByShortName(spell_type_arg); } else { c->Message( @@ -152,7 +153,7 @@ void bot_command_copy_settings(Client* c, const Seperator* sep) for (int i = 0; i < options.size(); i++) { if (sep->arg[3] == options[i]) { - setting_type = c->GetBotSpellCategoryIDByShortName(sep->arg[3]); + setting_type = Bot::GetBotSpellCategoryIDByShortName(sep->arg[3]); valid_option = true; break; } @@ -236,7 +237,7 @@ void bot_command_copy_settings(Client* c, const Seperator* sep) } } - output = from->GetBotSpellCategoryName(setting_type); + output = Bot::GetBotSpellCategoryName(setting_type); } else { if (!strcasecmp(sep->arg[3], "misc")) { @@ -355,7 +356,7 @@ void bot_command_copy_settings(Client* c, const Seperator* sep) ( spell_type != UINT16_MAX ? fmt::format(" [{}] ", - c->GetSpellTypeNameByID(spell_type) + Bot::GetSpellTypeNameByID(spell_type) ) : " " ), diff --git a/zone/bot_commands/default_settings.cpp b/zone/bot_commands/default_settings.cpp index a0dd3f01c..36fc7a060 100644 --- a/zone/bot_commands/default_settings.cpp +++ b/zone/bot_commands/default_settings.cpp @@ -13,7 +13,7 @@ void bot_command_default_settings(Client* c, const Seperator* sep) p.description = { "Restores a bot's setting(s) to defaults" }; p.notes = { "- You can put a spell type ID or shortname after any option except [all], [misc] and [spellsettings] to restore that specifc spell type only"}; - p.example_format = { fmt::format("{} [option] [actionable]", sep->arg[0]) }; + p.example_format = { fmt::format("{} [option] [optional: spelltype id/short name] [actionable]", sep->arg[0]) }; p.examples_one = { "To restore delays for Clerics:", @@ -29,7 +29,7 @@ void bot_command_default_settings(Client* c, const Seperator* sep) fmt::format( "{} delays {} byname BotA", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Snare) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Snare) ), fmt::format( "{} delays {} byname BotA", @@ -38,7 +38,7 @@ void bot_command_default_settings(Client* c, const Seperator* sep) ) }; p.actionables = { "target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned" }; - p.options = { "all, misc, spellsettings, spelltypesettings, spellholds, spelldelays, spellminthresholds, spellmaxthresholds, spellminmanapct, spellmaxmanapct, spellminhppct, spellmaxhppct, spellidlepriority, spellengagedpriority, spellpursuepriority, spellaggrocheck, spelltargetcounts" }; + p.options = { "all, misc, spellsettings, spelltypesettings, spellholds, spelldelays, spellminthresholds, spellmaxthresholds, spellminmanapct, spellmaxmanapct, spellminhppct, spellmaxhppct, spellidlepriority, spellengagedpriority, spellpursuepriority, spellaggrocheck, spelltargetcounts, spellresistlimits" }; p.options_one = { "[spellsettings] will restore ^spellsettings options", @@ -99,7 +99,8 @@ void bot_command_default_settings(Client* c, const Seperator* sep) "spellengagedpriority", "spellpursuepriority", "spellaggrochecks", - "spelltargetcounts" + "spelltargetcounts", + "spellresistlimits" }; if (sep->IsNumber(spell_type_arg_int)) { @@ -122,8 +123,8 @@ void bot_command_default_settings(Client* c, const Seperator* sep) ++ab_arg; } else if (!spell_type_arg.empty()) { - if (c->GetSpellTypeIDByShortName(spell_type_arg) != UINT16_MAX) { - spell_type = c->GetSpellTypeIDByShortName(spell_type_arg); + if (Bot::GetSpellTypeIDByShortName(spell_type_arg) != UINT16_MAX) { + spell_type = Bot::GetSpellTypeIDByShortName(spell_type_arg); } else { c->Message( @@ -143,7 +144,7 @@ void bot_command_default_settings(Client* c, const Seperator* sep) for (int i = 0; i < options.size(); i++) { if (sep->arg[1] == options[i]) { - setting_type = c->GetBotSpellCategoryIDByShortName(sep->arg[1]); + setting_type = Bot::GetBotSpellCategoryIDByShortName(sep->arg[1]); valid_option = true; break; @@ -202,7 +203,7 @@ void bot_command_default_settings(Client* c, const Seperator* sep) } } - output = (spell_type != UINT16_MAX ? c->GetSpellTypeNameByID(spell_type) : ""); + output = (spell_type != UINT16_MAX ? Bot::GetSpellTypeNameByID(spell_type) : ""); output += sep->arg[3]; } else if (!strcasecmp(sep->arg[1], "misc")) { @@ -448,7 +449,7 @@ void bot_command_default_settings(Client* c, const Seperator* sep) ( spell_type != UINT16_MAX ? fmt::format("My [{}] ", - c->GetSpellTypeNameByID(spell_type) + Bot::GetSpellTypeNameByID(spell_type) ) : "My " ), @@ -465,7 +466,7 @@ void bot_command_default_settings(Client* c, const Seperator* sep) ( spell_type != UINT16_MAX ? fmt::format(" [{}] ", - c->GetSpellTypeNameByID(spell_type) + Bot::GetSpellTypeNameByID(spell_type) ) : " " ), diff --git a/zone/bot_commands/spell_aggro_checks.cpp b/zone/bot_commands/spell_aggro_checks.cpp index 1c5a34e02..41ae40444 100644 --- a/zone/bot_commands/spell_aggro_checks.cpp +++ b/zone/bot_commands/spell_aggro_checks.cpp @@ -23,7 +23,7 @@ void bot_command_spell_aggro_checks(Client* c, const Seperator* sep) fmt::format( "{} {} 1 spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Nuke) ), fmt::format( "{} {} 1 spawned", @@ -37,7 +37,7 @@ void bot_command_spell_aggro_checks(Client* c, const Seperator* sep) fmt::format( "{} {} 0 byclass {}", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Snare), + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Snare), Class::ShadowKnight ), fmt::format( @@ -53,7 +53,7 @@ void bot_command_spell_aggro_checks(Client* c, const Seperator* sep) fmt::format( "{} {} current spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::DOT) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::DOT) ), fmt::format( "{} {} current spawned", @@ -109,8 +109,8 @@ void bot_command_spell_aggro_checks(Client* c, const Seperator* sep) } } else { - if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { - spell_type = c->GetSpellTypeIDByShortName(arg1); + if (Bot::GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { + spell_type = Bot::GetSpellTypeIDByShortName(arg1); } else { c->Message( @@ -185,7 +185,7 @@ void bot_command_spell_aggro_checks(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] aggro check is currently [{}].'", my_bot->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), my_bot->GetSpellTypeAggroCheck(spell_type) ? "enabled" : "disabled" ).c_str() ); @@ -202,7 +202,7 @@ void bot_command_spell_aggro_checks(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] aggro check was [{}].'", first_found->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), first_found->GetSpellTypeAggroCheck(spell_type) ? "enabled" : "disabled" ).c_str() ); @@ -213,7 +213,7 @@ void bot_command_spell_aggro_checks(Client* c, const Seperator* sep) fmt::format( "{} of your bots [{}] their [{}] aggro check.", success_count, - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), type_value ? "enabled" : "disabled" ).c_str() ); diff --git a/zone/bot_commands/spell_delays.cpp b/zone/bot_commands/spell_delays.cpp index a28431660..1f0f19fa6 100644 --- a/zone/bot_commands/spell_delays.cpp +++ b/zone/bot_commands/spell_delays.cpp @@ -30,7 +30,7 @@ void bot_command_spell_delays(Client* c, const Seperator* sep) { fmt::format( "{} {} 8000 byclass {}", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::DOT), + Bot::GetSpellTypeShortNameByID(BotSpellTypes::DOT), Class::Necromancer ), fmt::format( @@ -46,7 +46,7 @@ void bot_command_spell_delays(Client* c, const Seperator* sep) { fmt::format( "{} {} 2500 byclass {}", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals), + Bot::GetSpellTypeShortNameByID(BotSpellTypes::FastHeals), Class::Warrior ), fmt::format( @@ -62,7 +62,7 @@ void bot_command_spell_delays(Client* c, const Seperator* sep) { fmt::format( "{} {} current spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Nuke) ), fmt::format( "{} {} current spawned", @@ -127,8 +127,8 @@ void bot_command_spell_delays(Client* c, const Seperator* sep) { } } else { - if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { - spell_type = c->GetSpellTypeIDByShortName(arg1); + if (Bot::GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { + spell_type = Bot::GetSpellTypeIDByShortName(arg1); if (clientSetting && !IsClientBotSpellType(spell_type)) { c->Message(Chat::Yellow, "Invalid spell type for clients."); @@ -219,7 +219,7 @@ void bot_command_spell_delays(Client* c, const Seperator* sep) { fmt::format( "{} says, 'My [{}] spell delay is currently [{}] seconds.'", my_bot->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), my_bot->GetSpellDelay(spell_type) / 1000.00 ).c_str() ); @@ -237,7 +237,7 @@ void bot_command_spell_delays(Client* c, const Seperator* sep) { fmt::format( "{} says, 'My [{}] spell delay was set to [{}] seconds.'", first_found->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), first_found->GetSpellDelay(spell_type) / 1000.00 ).c_str() ); @@ -248,7 +248,7 @@ void bot_command_spell_delays(Client* c, const Seperator* sep) { fmt::format( "{} of your bots set their [{}] spell delay to [{}] seconds.", success_count, - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), type_value / 1000.00 ).c_str() ); @@ -261,7 +261,7 @@ void bot_command_spell_delays(Client* c, const Seperator* sep) { Chat::Green, fmt::format( "Your [{}] spell delay is currently [{}] seconds.", - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), c->GetSpellDelay(spell_type) / 1000.00 ).c_str() ); @@ -273,7 +273,7 @@ void bot_command_spell_delays(Client* c, const Seperator* sep) { Chat::Green, fmt::format( "Your [{}] spell delay was set to [{}] seconds.", - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), c->GetSpellDelay(spell_type) / 1000.00 ).c_str() ); diff --git a/zone/bot_commands/spell_engaged_priority.cpp b/zone/bot_commands/spell_engaged_priority.cpp index d01366178..2d6d0b17b 100644 --- a/zone/bot_commands/spell_engaged_priority.cpp +++ b/zone/bot_commands/spell_engaged_priority.cpp @@ -28,7 +28,7 @@ void bot_command_spell_engaged_priority(Client* c, const Seperator* sep) fmt::format( "{} {} 1 byclass {}", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Slow), + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Slow), Class::Shaman ), fmt::format( @@ -44,7 +44,7 @@ void bot_command_spell_engaged_priority(Client* c, const Seperator* sep) fmt::format( "{} {} 0 spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Snare) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Snare) ), fmt::format( "{} {} 0 spawned", @@ -58,7 +58,7 @@ void bot_command_spell_engaged_priority(Client* c, const Seperator* sep) fmt::format( "{} {} current spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Dispel) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Dispel) ), fmt::format( "{} {} current spawned", @@ -106,8 +106,8 @@ void bot_command_spell_engaged_priority(Client* c, const Seperator* sep) } } else { - if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { - spell_type = c->GetSpellTypeIDByShortName(arg1); + if (Bot::GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { + spell_type = Bot::GetSpellTypeIDByShortName(arg1); } else if (!arg1.compare("list")) { ++ab_arg; @@ -186,7 +186,7 @@ void bot_command_spell_engaged_priority(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] engaged cast priority is currently [{}].'", my_bot->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), my_bot->GetSpellTypePriority(spell_type, BotPriorityCategories::Engaged) ).c_str() ); @@ -200,7 +200,7 @@ void bot_command_spell_engaged_priority(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] engaged cast priority for is currently [{}].'", my_bot->GetCleanName(), - c->GetSpellTypeNameByID(current_cast.spellType), + Bot::GetSpellTypeNameByID(current_cast.spellType), (current_cast.priority == 0 ? "disabled (0)" : std::to_string(current_cast.priority)) ).c_str() ); @@ -228,7 +228,7 @@ void bot_command_spell_engaged_priority(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] engaged cast priority was set to [{}].'", first_found->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), first_found->GetSpellTypePriority(spell_type, BotPriorityCategories::Engaged) ).c_str() ); @@ -239,7 +239,7 @@ void bot_command_spell_engaged_priority(Client* c, const Seperator* sep) fmt::format( "{} of your bots set their [{}] engaged cast priority to [{}].", success_count, - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), type_value ).c_str() ); diff --git a/zone/bot_commands/spell_holds.cpp b/zone/bot_commands/spell_holds.cpp index 5b5815fb5..d83274d39 100644 --- a/zone/bot_commands/spell_holds.cpp +++ b/zone/bot_commands/spell_holds.cpp @@ -24,7 +24,7 @@ void bot_command_spell_holds(Client* c, const Seperator* sep) fmt::format( "{} {} 1 spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::DOT) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::DOT) ), fmt::format( "{} {} 1 spawned", @@ -38,7 +38,7 @@ void bot_command_spell_holds(Client* c, const Seperator* sep) fmt::format( "{} {} current spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::DOT) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::DOT) ), fmt::format( "{} {} current spawned", @@ -85,8 +85,8 @@ void bot_command_spell_holds(Client* c, const Seperator* sep) } } else { - if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { - spell_type = c->GetSpellTypeIDByShortName(arg1); + if (Bot::GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { + spell_type = Bot::GetSpellTypeIDByShortName(arg1); } else { c->Message( @@ -156,7 +156,7 @@ void bot_command_spell_holds(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] spell hold is currently [{}].'", my_bot->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), my_bot->GetSpellHold(spell_type) ? "enabled" : "disabled" ).c_str() ); @@ -173,7 +173,7 @@ void bot_command_spell_holds(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] spell hold was [{}].'", first_found->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), first_found->GetSpellHold(spell_type) ? "enabled" : "disabled" ).c_str() ); @@ -185,7 +185,7 @@ void bot_command_spell_holds(Client* c, const Seperator* sep) "{} of your bots [{}] their [{}] spell hold.", success_count, type_value ? "enabled" : "disabled", - c->GetSpellTypeNameByID(spell_type) + Bot::GetSpellTypeNameByID(spell_type) ).c_str() ); } diff --git a/zone/bot_commands/spell_idle_priority.cpp b/zone/bot_commands/spell_idle_priority.cpp index 4ae827639..a37e035df 100644 --- a/zone/bot_commands/spell_idle_priority.cpp +++ b/zone/bot_commands/spell_idle_priority.cpp @@ -28,7 +28,7 @@ void bot_command_spell_idle_priority(Client* c, const Seperator* sep) fmt::format( "{} {} 3 byclass {}", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals), + Bot::GetSpellTypeShortNameByID(BotSpellTypes::FastHeals), Class::Cleric ), fmt::format( @@ -44,7 +44,7 @@ void bot_command_spell_idle_priority(Client* c, const Seperator* sep) fmt::format( "{} {} 0 spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Cure) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Cure) ), fmt::format( "{} {} 0 spawned", @@ -58,7 +58,7 @@ void bot_command_spell_idle_priority(Client* c, const Seperator* sep) fmt::format( "{} {} current spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Buff) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Buff) ), fmt::format( "{} {} current spawned", @@ -106,8 +106,8 @@ void bot_command_spell_idle_priority(Client* c, const Seperator* sep) } } else { - if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { - spell_type = c->GetSpellTypeIDByShortName(arg1); + if (Bot::GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { + spell_type = Bot::GetSpellTypeIDByShortName(arg1); } else if (!arg1.compare("list")) { ++ab_arg; @@ -186,7 +186,7 @@ void bot_command_spell_idle_priority(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] idle cast priority is currently [{}].'", my_bot->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), my_bot->GetSpellTypePriority(spell_type, BotPriorityCategories::Idle) ).c_str() ); @@ -200,7 +200,7 @@ void bot_command_spell_idle_priority(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] idle cast priority for is currently [{}].'", my_bot->GetCleanName(), - c->GetSpellTypeNameByID(current_cast.spellType), + Bot::GetSpellTypeNameByID(current_cast.spellType), (current_cast.priority == 0 ? "disabled (0)" : std::to_string(current_cast.priority)) ).c_str() ); @@ -228,7 +228,7 @@ void bot_command_spell_idle_priority(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] idle cast priority was set to [{}].'", first_found->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), first_found->GetSpellTypePriority(spell_type, BotPriorityCategories::Idle) ).c_str() ); @@ -239,7 +239,7 @@ void bot_command_spell_idle_priority(Client* c, const Seperator* sep) fmt::format( "{} of your bots set their [{}] idle cast priority to [{}].", success_count, - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), type_value ).c_str() ); diff --git a/zone/bot_commands/spell_max_hp_pct.cpp b/zone/bot_commands/spell_max_hp_pct.cpp index 5bc42a7ad..249e9179d 100644 --- a/zone/bot_commands/spell_max_hp_pct.cpp +++ b/zone/bot_commands/spell_max_hp_pct.cpp @@ -23,7 +23,7 @@ void bot_command_spell_max_hp_pct(Client* c, const Seperator* sep) fmt::format( "{} {} 100 spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Snare) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Snare) ), fmt::format( "{} {} 10 spawned", @@ -37,7 +37,7 @@ void bot_command_spell_max_hp_pct(Client* c, const Seperator* sep) fmt::format( "{} {} 30 byname BotA", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::FastHeals) ), fmt::format( "{} {} 30 byname BotA", @@ -51,7 +51,7 @@ void bot_command_spell_max_hp_pct(Client* c, const Seperator* sep) fmt::format( "{} {} current spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Stun) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Stun) ), fmt::format( "{} {} current spawned", @@ -98,8 +98,8 @@ void bot_command_spell_max_hp_pct(Client* c, const Seperator* sep) } } else { - if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { - spell_type = c->GetSpellTypeIDByShortName(arg1); + if (Bot::GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { + spell_type = Bot::GetSpellTypeIDByShortName(arg1); } else { c->Message( @@ -174,7 +174,7 @@ void bot_command_spell_max_hp_pct(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] maximum HP is currently [{}%%].'", my_bot->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), my_bot->GetSpellTypeMaxHPLimit(spell_type) ).c_str() ); @@ -191,7 +191,7 @@ void bot_command_spell_max_hp_pct(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] maximum HP was set to [{}%%].'", first_found->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), first_found->GetSpellTypeMaxHPLimit(spell_type) ).c_str() ); @@ -202,7 +202,7 @@ void bot_command_spell_max_hp_pct(Client* c, const Seperator* sep) fmt::format( "{} of your bots set their [{}] maximum HP to [{}%%].", success_count, - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), type_value ).c_str() ); diff --git a/zone/bot_commands/spell_max_mana_pct.cpp b/zone/bot_commands/spell_max_mana_pct.cpp index 0e526ab8e..ab42ce8a5 100644 --- a/zone/bot_commands/spell_max_mana_pct.cpp +++ b/zone/bot_commands/spell_max_mana_pct.cpp @@ -23,7 +23,7 @@ void bot_command_spell_max_mana_pct(Client* c, const Seperator* sep) fmt::format( "{} {} 10 spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Snare) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Snare) ), fmt::format( "{} {} 10 spawned", @@ -37,7 +37,7 @@ void bot_command_spell_max_mana_pct(Client* c, const Seperator* sep) fmt::format( "{} {} 90 byname BotA", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::FastHeals) ), fmt::format( "{} {} 90 byname BotA", @@ -51,7 +51,7 @@ void bot_command_spell_max_mana_pct(Client* c, const Seperator* sep) fmt::format( "{} {} current spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Stun) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Stun) ), fmt::format( "{} {} current spawned", @@ -98,8 +98,8 @@ void bot_command_spell_max_mana_pct(Client* c, const Seperator* sep) } } else { - if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { - spell_type = c->GetSpellTypeIDByShortName(arg1); + if (Bot::GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { + spell_type = Bot::GetSpellTypeIDByShortName(arg1); } else { c->Message( @@ -174,7 +174,7 @@ void bot_command_spell_max_mana_pct(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] maximum mana is currently [{}%%].'", my_bot->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), my_bot->GetSpellTypeMaxManaLimit(spell_type) ).c_str() ); @@ -191,7 +191,7 @@ void bot_command_spell_max_mana_pct(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] maximum mana was set to [{}%%].'", first_found->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), first_found->GetSpellTypeMaxManaLimit(spell_type) ).c_str() ); @@ -202,7 +202,7 @@ void bot_command_spell_max_mana_pct(Client* c, const Seperator* sep) fmt::format( "{} of your bots set their [{}] maximum mana to [{}%%].", success_count, - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), type_value ).c_str() ); diff --git a/zone/bot_commands/spell_max_thresholds.cpp b/zone/bot_commands/spell_max_thresholds.cpp index ec4faca4e..4ef30d2ad 100644 --- a/zone/bot_commands/spell_max_thresholds.cpp +++ b/zone/bot_commands/spell_max_thresholds.cpp @@ -30,7 +30,7 @@ void bot_command_spell_max_thresholds(Client* c, const Seperator* sep) { fmt::format( "{} {} 99 spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Snare) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Snare) ), fmt::format( "{} {} 99 spawned", @@ -44,7 +44,7 @@ void bot_command_spell_max_thresholds(Client* c, const Seperator* sep) { fmt::format( "{} {} 99 byname Enchbot", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Debuff) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Debuff) ), fmt::format( "{} {} 99 byname Enchbot", @@ -58,7 +58,7 @@ void bot_command_spell_max_thresholds(Client* c, const Seperator* sep) { fmt::format( "{} {} current spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Nuke) ), fmt::format( "{} {} current spawned", @@ -123,8 +123,8 @@ void bot_command_spell_max_thresholds(Client* c, const Seperator* sep) { } } else { - if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { - spell_type = c->GetSpellTypeIDByShortName(arg1); + if (Bot::GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { + spell_type = Bot::GetSpellTypeIDByShortName(arg1); if (clientSetting && !IsClientBotSpellType(spell_type)) { c->Message(Chat::Yellow, "Invalid spell type for clients."); @@ -215,7 +215,7 @@ void bot_command_spell_max_thresholds(Client* c, const Seperator* sep) { fmt::format( "{} says, 'My [{}] maximum threshold is currently [{}%%].'", my_bot->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), my_bot->GetSpellMaxThreshold(spell_type) ).c_str() ); @@ -233,7 +233,7 @@ void bot_command_spell_max_thresholds(Client* c, const Seperator* sep) { fmt::format( "{} says, 'My [{}] maximum threshold was set to [{}%%].'", first_found->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), first_found->GetSpellMaxThreshold(spell_type) ).c_str() ); @@ -244,7 +244,7 @@ void bot_command_spell_max_thresholds(Client* c, const Seperator* sep) { fmt::format( "{} of your bots set their [{}] maximum threshold to [{}%%].", success_count, - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), type_value ).c_str() ); @@ -257,7 +257,7 @@ void bot_command_spell_max_thresholds(Client* c, const Seperator* sep) { Chat::Green, fmt::format( "Your [{}] maximum threshold is currently [{}%%].", - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), c->GetSpellMaxThreshold(spell_type) ).c_str() ); @@ -269,7 +269,7 @@ void bot_command_spell_max_thresholds(Client* c, const Seperator* sep) { Chat::Green, fmt::format( "Your [{}] maximum threshold was set to [{}%%].", - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), c->GetSpellMaxThreshold(spell_type) ).c_str() ); diff --git a/zone/bot_commands/spell_min_hp_pct.cpp b/zone/bot_commands/spell_min_hp_pct.cpp index 11da31ac8..61d6313e3 100644 --- a/zone/bot_commands/spell_min_hp_pct.cpp +++ b/zone/bot_commands/spell_min_hp_pct.cpp @@ -23,7 +23,7 @@ void bot_command_spell_min_hp_pct(Client* c, const Seperator* sep) fmt::format( "{} {} 10 spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Snare) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Snare) ), fmt::format( "{} {} 10 spawned", @@ -37,7 +37,7 @@ void bot_command_spell_min_hp_pct(Client* c, const Seperator* sep) fmt::format( "{} {} 30 byname BotA", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::FastHeals) ), fmt::format( "{} {} 30 byname BotA", @@ -51,7 +51,7 @@ void bot_command_spell_min_hp_pct(Client* c, const Seperator* sep) fmt::format( "{} {} current spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Stun) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Stun) ), fmt::format( "{} {} current spawned", @@ -98,8 +98,8 @@ void bot_command_spell_min_hp_pct(Client* c, const Seperator* sep) } } else { - if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { - spell_type = c->GetSpellTypeIDByShortName(arg1); + if (Bot::GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { + spell_type = Bot::GetSpellTypeIDByShortName(arg1); } else { c->Message( @@ -174,7 +174,7 @@ void bot_command_spell_min_hp_pct(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] minimum HP is currently [{}%%].'", my_bot->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), my_bot->GetSpellTypeMinHPLimit(spell_type) ).c_str() ); @@ -191,7 +191,7 @@ void bot_command_spell_min_hp_pct(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] minimum HP was set to [{}%%].'", first_found->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), first_found->GetSpellTypeMinHPLimit(spell_type) ).c_str() ); @@ -202,7 +202,7 @@ void bot_command_spell_min_hp_pct(Client* c, const Seperator* sep) fmt::format( "{} of your bots set their [{}] minimum HP to [{}%%].", success_count, - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), type_value ).c_str() ); diff --git a/zone/bot_commands/spell_min_mana_pct.cpp b/zone/bot_commands/spell_min_mana_pct.cpp index 4fa3405df..71672cee9 100644 --- a/zone/bot_commands/spell_min_mana_pct.cpp +++ b/zone/bot_commands/spell_min_mana_pct.cpp @@ -23,7 +23,7 @@ void bot_command_spell_min_mana_pct(Client* c, const Seperator* sep) fmt::format( "{} {} 10 spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Snare) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Snare) ), fmt::format( "{} {} 10 spawned", @@ -37,7 +37,7 @@ void bot_command_spell_min_mana_pct(Client* c, const Seperator* sep) fmt::format( "{} {} 30 byname BotA", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::FastHeals) ), fmt::format( "{} {} 30 byname BotA", @@ -51,7 +51,7 @@ void bot_command_spell_min_mana_pct(Client* c, const Seperator* sep) fmt::format( "{} {} current spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Stun) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Stun) ), fmt::format( "{} {} current spawned", @@ -98,8 +98,8 @@ void bot_command_spell_min_mana_pct(Client* c, const Seperator* sep) } } else { - if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { - spell_type = c->GetSpellTypeIDByShortName(arg1); + if (Bot::GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { + spell_type = Bot::GetSpellTypeIDByShortName(arg1); } else { c->Message( @@ -174,7 +174,7 @@ void bot_command_spell_min_mana_pct(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] minimum mana is currently [{}%%].'", my_bot->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), my_bot->GetSpellTypeMinManaLimit(spell_type) ).c_str() ); @@ -191,7 +191,7 @@ void bot_command_spell_min_mana_pct(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] minimum mana was set to [{}%%].'", first_found->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), first_found->GetSpellTypeMinManaLimit(spell_type) ).c_str() ); @@ -202,7 +202,7 @@ void bot_command_spell_min_mana_pct(Client* c, const Seperator* sep) fmt::format( "{} of your bots set their [{}] minimum mana to [{}%%].", success_count, - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), type_value ).c_str() ); diff --git a/zone/bot_commands/spell_min_thresholds.cpp b/zone/bot_commands/spell_min_thresholds.cpp index 6fcd43bed..85d72a553 100644 --- a/zone/bot_commands/spell_min_thresholds.cpp +++ b/zone/bot_commands/spell_min_thresholds.cpp @@ -30,7 +30,7 @@ void bot_command_spell_min_thresholds(Client* c, const Seperator* sep) { fmt::format( "{} {} 10 spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Debuff) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Debuff) ), fmt::format( "{} {} 10 spawned", @@ -44,7 +44,7 @@ void bot_command_spell_min_thresholds(Client* c, const Seperator* sep) { fmt::format( "{} {} 15 byclass {}", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::DOT), + Bot::GetSpellTypeShortNameByID(BotSpellTypes::DOT), Class::Druid ), fmt::format( @@ -60,7 +60,7 @@ void bot_command_spell_min_thresholds(Client* c, const Seperator* sep) { fmt::format( "{} {} current spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::FastHeals) ), fmt::format( "{} {} current spawned", @@ -125,8 +125,8 @@ void bot_command_spell_min_thresholds(Client* c, const Seperator* sep) { } } else { - if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { - spell_type = c->GetSpellTypeIDByShortName(arg1); + if (Bot::GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { + spell_type = Bot::GetSpellTypeIDByShortName(arg1); if (clientSetting && !IsClientBotSpellType(spell_type)) { c->Message(Chat::Yellow, "Invalid spell type for clients."); @@ -217,7 +217,7 @@ void bot_command_spell_min_thresholds(Client* c, const Seperator* sep) { fmt::format( "{} says, 'My [{}] minimum threshold is currently [{}%%].'", my_bot->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), my_bot->GetSpellMinThreshold(spell_type) ).c_str() ); @@ -235,7 +235,7 @@ void bot_command_spell_min_thresholds(Client* c, const Seperator* sep) { fmt::format( "{} says, 'My [{}] minimum threshold was set to [{}%%].'", first_found->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), first_found->GetSpellMinThreshold(spell_type) ).c_str() ); @@ -246,7 +246,7 @@ void bot_command_spell_min_thresholds(Client* c, const Seperator* sep) { fmt::format( "{} of your bots set their [{}] minimum threshold to [{}%%].", success_count, - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), type_value ).c_str() ); @@ -259,7 +259,7 @@ void bot_command_spell_min_thresholds(Client* c, const Seperator* sep) { Chat::Green, fmt::format( "Your [{}] minimum threshold is currently [{}%%].", - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), c->GetSpellMinThreshold(spell_type) ).c_str() ); @@ -271,7 +271,7 @@ void bot_command_spell_min_thresholds(Client* c, const Seperator* sep) { Chat::Green, fmt::format( "Your [{}] minimum threshold was set to [{}%%].", - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), c->GetSpellMinThreshold(spell_type) ).c_str() ); diff --git a/zone/bot_commands/spell_pursue_priority.cpp b/zone/bot_commands/spell_pursue_priority.cpp index feb08fbe2..526701214 100644 --- a/zone/bot_commands/spell_pursue_priority.cpp +++ b/zone/bot_commands/spell_pursue_priority.cpp @@ -28,7 +28,7 @@ void bot_command_spell_pursue_priority(Client* c, const Seperator* sep) fmt::format( "{} {} 1 spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Nuke) ), fmt::format( "{} {} 1 spawned", @@ -42,7 +42,7 @@ void bot_command_spell_pursue_priority(Client* c, const Seperator* sep) fmt::format( "{} {} 0 byclass {}", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Cure), + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Cure), Class::Shaman ), fmt::format( @@ -58,7 +58,7 @@ void bot_command_spell_pursue_priority(Client* c, const Seperator* sep) fmt::format( "{} {} current spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::Buff) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::Buff) ), fmt::format( "{} {} current spawned", @@ -106,8 +106,8 @@ void bot_command_spell_pursue_priority(Client* c, const Seperator* sep) } } else { - if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { - spell_type = c->GetSpellTypeIDByShortName(arg1); + if (Bot::GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { + spell_type = Bot::GetSpellTypeIDByShortName(arg1); } else if (!arg1.compare("list")) { ++ab_arg; @@ -186,7 +186,7 @@ void bot_command_spell_pursue_priority(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] pursue cast priority is currently [{}].'", my_bot->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), my_bot->GetSpellTypePriority(spell_type, BotPriorityCategories::Pursue) ).c_str() ); @@ -200,7 +200,7 @@ void bot_command_spell_pursue_priority(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] pursue cast priority for is currently [{}].'", my_bot->GetCleanName(), - c->GetSpellTypeNameByID(current_cast.spellType), + Bot::GetSpellTypeNameByID(current_cast.spellType), (current_cast.priority == 0 ? "disabled (0)" : std::to_string(current_cast.priority)) ).c_str() ); @@ -228,7 +228,7 @@ void bot_command_spell_pursue_priority(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] pursue cast priority was set to [{}].'", first_found->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), first_found->GetSpellTypePriority(spell_type, BotPriorityCategories::Pursue) ).c_str() ); @@ -239,7 +239,7 @@ void bot_command_spell_pursue_priority(Client* c, const Seperator* sep) fmt::format( "{} of your bots set their [{}] pursue cast priority to [{}].", success_count, - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), type_value ).c_str() ); diff --git a/zone/bot_commands/spell_target_count.cpp b/zone/bot_commands/spell_target_count.cpp index 322de0d2d..ad938d9b5 100644 --- a/zone/bot_commands/spell_target_count.cpp +++ b/zone/bot_commands/spell_target_count.cpp @@ -23,7 +23,7 @@ void bot_command_spell_target_count(Client* c, const Seperator* sep) fmt::format( "{} {} 5 spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::AEMez) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::AEMez) ), fmt::format( "{} {} 5 spawned", @@ -35,14 +35,16 @@ void bot_command_spell_target_count(Client* c, const Seperator* sep) { "To set Wizards to require 5 targets for AENukes:", fmt::format( - "{} {} 3 byname BotA", + "{} {} byclass {}", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::AENukes) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::AENukes), + Class::Wizard ), fmt::format( - "{} {} 3 byname BotA", + "{} {} byclass {}", sep->arg[0], - BotSpellTypes::AENukes + BotSpellTypes::AENukes, + Class::Wizard ) }; p.examples_three = @@ -51,7 +53,7 @@ void bot_command_spell_target_count(Client* c, const Seperator* sep) fmt::format( "{} {} current spawned", sep->arg[0], - c->GetSpellTypeShortNameByID(BotSpellTypes::AESlow) + Bot::GetSpellTypeShortNameByID(BotSpellTypes::AESlow) ), fmt::format( "{} {} current spawned", @@ -98,8 +100,8 @@ void bot_command_spell_target_count(Client* c, const Seperator* sep) } } else { - if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { - spell_type = c->GetSpellTypeIDByShortName(arg1); + if (Bot::GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { + spell_type = Bot::GetSpellTypeIDByShortName(arg1); } else { c->Message( @@ -119,6 +121,7 @@ void bot_command_spell_target_count(Client* c, const Seperator* sep) if (sep->IsNumber(2)) { type_value = atoi(sep->arg[2]); ++ab_arg; + if (type_value < 1 || type_value > 100) { c->Message(Chat::Yellow, "You must enter a value between 1-100."); @@ -174,7 +177,7 @@ void bot_command_spell_target_count(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] target count is currently [{}].'", my_bot->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), my_bot->GetSpellTypeAEOrGroupTargetCount(spell_type) ).c_str() ); @@ -191,7 +194,7 @@ void bot_command_spell_target_count(Client* c, const Seperator* sep) fmt::format( "{} says, 'My [{}] target count was set to [{}].'", first_found->GetCleanName(), - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), first_found->GetSpellTypeAEOrGroupTargetCount(spell_type) ).c_str() ); @@ -202,7 +205,7 @@ void bot_command_spell_target_count(Client* c, const Seperator* sep) fmt::format( "{} of your bots set their [{}] target count to [{}].", success_count, - c->GetSpellTypeNameByID(spell_type), + Bot::GetSpellTypeNameByID(spell_type), type_value ).c_str() ); diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 6acd29f00..d4131a349 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -2241,7 +2241,7 @@ bool BotDatabase::LoadBotSettings(Mob* m) if (e.setting_type == BotSettingCategories::BaseSetting) { LogBotSettings("[{}] says, 'Loading {} [{}] - setting to [{}].", m->GetCleanName(), - m->GetBotSettingCategoryName(e.setting_type), + Bot::GetBotSettingCategoryName(e.setting_type), e.setting_type, e.value ); @@ -2249,15 +2249,20 @@ bool BotDatabase::LoadBotSettings(Mob* m) else { LogBotSettings("[{}] says, 'Loading {} [{}], {} [{}] - setting to [{}].", m->GetCleanName(), - m->GetBotSpellCategoryName(e.setting_type), + Bot::GetBotSpellCategoryName(e.setting_type), e.setting_type, - m->GetSpellTypeNameByID(e.setting_id), + Bot::GetSpellTypeNameByID(e.setting_id), e.setting_id, e.value ); } - m->SetBotSetting(e.setting_type, e.setting_id, e.value); + if (m->IsClient()) { + m->CastToClient()->SetBotSetting(e.setting_type, e.setting_id, e.value); + } + else { + m->CastToBot()->SetBotSetting(e.setting_type, e.setting_id, e.value); + } } return true; @@ -2294,7 +2299,7 @@ bool BotDatabase::SaveBotSettings(Mob* m) BotSettingsRepository::DeleteWhere(database, query); std::vector v; - + if (m->IsBot()) { uint8 bot_stance = m->CastToBot()->GetBotStance(); @@ -2307,13 +2312,13 @@ bool BotDatabase::SaveBotSettings(Mob* m) .setting_id = static_cast(i), .setting_type = static_cast(BotSettingCategories::BaseSetting), .value = static_cast(m->CastToBot()->GetBotBaseSetting(i)), - .category_name = m->GetBotSpellCategoryName(BotSettingCategories::BaseSetting), - .setting_name = m->GetBotSettingCategoryName(i) + .category_name = Bot::GetBotSpellCategoryName(BotSettingCategories::BaseSetting), + .setting_name = Bot::GetBotSettingCategoryName(i) }; v.emplace_back(e); - LogBotSettings("{} says, 'Saving {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), m->GetBotSettingCategoryName(i), i, e.value, m->CastToBot()->GetDefaultBotBaseSetting(i)); + LogBotSettings("{} says, 'Saving {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), Bot::GetBotSettingCategoryName(i), i, e.value, m->CastToBot()->GetDefaultBotBaseSetting(i)); } } @@ -2327,39 +2332,39 @@ bool BotDatabase::SaveBotSettings(Mob* m) .setting_id = static_cast(x), .setting_type = static_cast(i), .value = m->CastToBot()->GetSetting(i, x), - .category_name = m->GetBotSpellCategoryName(i), - .setting_name = m->CastToBot()->GetSpellTypeNameByID(x) + .category_name = Bot::GetBotSpellCategoryName(i), + .setting_name = Bot::GetSpellTypeNameByID(x) }; v.emplace_back(e); - LogBotSettings("{} says, 'Saving {} {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), m->GetBotSpellCategoryName(i), m->GetSpellTypeNameByID(x), x, e.value, m->CastToBot()->GetDefaultSetting(i, x, bot_stance)); + LogBotSettings("{} says, 'Saving {} {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), Bot::GetBotSpellCategoryName(i), Bot::GetSpellTypeNameByID(x), x, e.value, m->CastToBot()->GetDefaultSetting(i, x, bot_stance)); } } } } if (m->IsClient()) { - if (m->CastToClient()->GetDefaultBotSettings(BotSettingCategories::BaseSetting, BotBaseSettings::IllusionBlock) != m->GetIllusionBlock()) { // Only illusion block supported + if (m->CastToClient()->GetDefaultBotSettings(BotSettingCategories::BaseSetting, BotBaseSettings::IllusionBlock) != m->CastToClient()->GetIllusionBlock()) { // Only illusion block supported auto e = BotSettingsRepository::BotSettings{ .character_id = character_id, .bot_id = bot_id, .stance = stance_id, .setting_id = static_cast(BotBaseSettings::IllusionBlock), .setting_type = static_cast(BotSettingCategories::BaseSetting), - .value = m->GetIllusionBlock(), - .category_name = m->GetBotSpellCategoryName(BotSettingCategories::BaseSetting), - .setting_name = m->GetBotSettingCategoryName(BotBaseSettings::IllusionBlock) + .value = m->CastToClient()->GetIllusionBlock(), + .category_name = Bot::GetBotSpellCategoryName(BotSettingCategories::BaseSetting), + .setting_name = Bot::GetBotSettingCategoryName(BotBaseSettings::IllusionBlock) }; v.emplace_back(e); - LogBotSettings("{} says, 'Saving {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), m->GetBotSettingCategoryName(BotBaseSettings::IllusionBlock), BotBaseSettings::IllusionBlock, e.value, m->GetIllusionBlock()); + LogBotSettings("{} says, 'Saving {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), Bot::GetBotSettingCategoryName(BotBaseSettings::IllusionBlock), BotBaseSettings::IllusionBlock, e.value, m->CastToClient()->GetIllusionBlock()); } for (uint16 i = BotSettingCategories::START_CLIENT; i <= BotSettingCategories::END_CLIENT; ++i) { for (uint16 x = BotSpellTypes::START; x <= BotSpellTypes::END; ++x) { - LogBotSettings("{} says, 'Checking {} {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), m->GetBotSpellCategoryName(i), m->CastToBot()->GetSpellTypeNameByID(x), x, m->CastToClient()->GetBotSetting(i, x), m->CastToClient()->GetDefaultBotSettings(i, x)); + LogBotSettings("{} says, 'Checking {} {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), Bot::GetBotSpellCategoryName(i), Bot::GetSpellTypeNameByID(x), x, m->CastToClient()->GetBotSetting(i, x), m->CastToClient()->GetDefaultBotSettings(i, x)); if (m->CastToClient()->GetBotSetting(i, x) != m->CastToClient()->GetDefaultBotSettings(i, x)) { auto e = BotSettingsRepository::BotSettings{ .character_id = character_id, @@ -2368,13 +2373,13 @@ bool BotDatabase::SaveBotSettings(Mob* m) .setting_id = static_cast(x), .setting_type = static_cast(i), .value = m->CastToClient()->GetBotSetting(i, x), - .category_name = m->GetBotSpellCategoryName(i), - .setting_name = m->CastToBot()->GetSpellTypeNameByID(x) + .category_name = Bot::GetBotSpellCategoryName(i), + .setting_name = Bot::GetSpellTypeNameByID(x) }; v.emplace_back(e); - LogBotSettings("{} says, 'Saving {} {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), m->GetBotSpellCategoryName(i), m->CastToBot()->GetSpellTypeNameByID(x), x, e.value, m->CastToClient()->GetDefaultBotSettings(i, x)); + LogBotSettings("{} says, 'Saving {} {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), Bot::GetBotSpellCategoryName(i), Bot::GetSpellTypeNameByID(x), x, e.value, m->CastToClient()->GetDefaultBotSettings(i, x)); } } } diff --git a/zone/bot_structs.h b/zone/bot_structs.h index c40e820b8..e3bcc8678 100644 --- a/zone/bot_structs.h +++ b/zone/bot_structs.h @@ -110,6 +110,27 @@ struct BotTimer { uint32 item_id; }; +struct BotSpellSettings { + uint16 spell_type; // type ID of bot category + std::string short_name; // type short name of bot category + std::string name; // type name of bot category + bool hold; // 0 = allow spell type, 1 = hold spell type + uint16 delay; // delay between casts of spell type, 1ms-60,000ms + uint8 min_threshold; // minimum target health threshold to allow casting of spell type + uint8 max_threshold; // maximum target health threshold to allow casting of spell type + uint16 resist_limit; // resist limit to skip spell type + bool aggro_check; // whether or not to check for possible aggro before casting + uint8 min_mana_pct; // lower mana percentage limit to allow spell cast + uint8 max_mana_pct; // upper mana percentage limit to allow spell cast + uint8 min_hp_pct; // lower HP percentage limit to allow spell cast + uint8 max_hp_pct; // upper HP percentage limit to allow spell cast + uint16 idle_priority; // idle priority of the spell type + uint16 engaged_priority; // engaged priority of the spell type + uint16 pursue_priority; // pursue priority of the spell type + uint16 ae_or_group_target_count; // require target count to cast an AE or Group spell type + Timer recast_timer; // recast timer based off delay +}; + struct BotSpellTypeOrder { uint16 spellType; uint16 priority; diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index 25982f7f4..344669a97 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -3013,7 +3013,7 @@ void Bot::MapSpellTypeLevels() { auto end = std::max({ BotSpellTypes::END, BotSpellTypes::COMMANDED_END, BotSpellTypes::DISCIPLINE_END }); for (int i = start; i <= end; ++i) { - if (!Bot::IsValidSpellType(i)) { + if (!Bot::IsValidBotSpellType(i)) { continue; } @@ -3036,7 +3036,7 @@ void Bot::MapSpellTypeLevels() { if ( !EQ::ValueWithin(bot_class, Class::Warrior, Class::Berserker) || - !Bot::IsValidSpellType(spell_type) + !Bot::IsValidBotSpellType(spell_type) ) { continue; } diff --git a/zone/client.h b/zone/client.h index 52e4788b6..3e4162d40 100644 --- a/zone/client.h +++ b/zone/client.h @@ -74,6 +74,8 @@ namespace EQ #include "../common/repositories/buyer_buy_lines_repository.h" #include "../common/repositories/character_evolving_items_repository.h" +#include "bot_structs.h" + #ifdef _WINDOWS // since windows defines these within windef.h (which windows.h include) // we are required to undefine these to use min and max from @@ -2279,14 +2281,30 @@ public: void LoadDefaultBotSettings(); int GetDefaultBotSettings(uint8 setting_type, uint16 bot_setting); int GetBotSetting(uint8 setting_type, uint16 bot_setting); - void SetBotSetting(uint8 setting_type, uint16 bot_setting, uint32 setting_value); + void SetBotSetting(uint8 setting_type, uint16 bot_setting, uint32 setting_value); + + uint16 GetDefaultSpellDelay(uint16 spell_type, uint8 stance = Stance::Balanced); + uint8 GetDefaultSpellMinThreshold(uint16 spell_type, uint8 stance = Stance::Balanced); + uint8 GetDefaultSpellMaxThreshold(uint16 spell_type, uint8 stance = Stance::Balanced); + inline uint16 GetSpellDelay(uint16 spell_type) const { return m_bot_spell_settings[spell_type].delay; } + inline void SetSpellDelay(uint16 spell_type, uint16 delay_value) { m_bot_spell_settings[spell_type].delay = delay_value; } + inline uint8 GetSpellMinThreshold(uint16 spell_type) const { return m_bot_spell_settings[spell_type].min_threshold; } + inline void SetSpellMinThreshold(uint16 spell_type, uint8 threshold_value) { m_bot_spell_settings[spell_type].min_threshold = threshold_value; } + inline uint8 GetSpellMaxThreshold(uint16 spell_type) const { return m_bot_spell_settings[spell_type].max_threshold; } + inline void SetSpellMaxThreshold(uint16 spell_type, uint8 threshold_value) { m_bot_spell_settings[spell_type].max_threshold = threshold_value; } + inline bool SpellTypeRecastCheck(uint16 spellType) { return !m_bot_spell_settings[spellType].recast_timer.GetRemainingTime(); } + void SetSpellTypeRecastTimer(uint16 spell_type, uint32 recast_time) { m_bot_spell_settings[spell_type].recast_timer.Start(recast_time); } + + void SetIllusionBlock(bool value) { _illusionBlock = value; } + bool GetIllusionBlock() const { return _illusionBlock; } private: bool bot_owner_options[_booCount]; bool m_bot_pulling; bool m_bot_precombat; - uint32 bot_assistee; + std::vector m_bot_spell_settings; + bool _illusionBlock; bool CanTradeFVNoDropItem(); void SendMobPositions(); diff --git a/zone/client_bot.cpp b/zone/client_bot.cpp index e10b3d42a..1711503f9 100644 --- a/zone/client_bot.cpp +++ b/zone/client_bot.cpp @@ -231,9 +231,8 @@ void Client::LoadDefaultBotSettings() { BotSpellSettings t; t.spell_type = i; - t.short_name = GetSpellTypeShortNameByID(i); - t.name = GetSpellTypeNameByID(i); - t.hold = GetDefaultSpellHold(i); + t.short_name = Bot::GetSpellTypeShortNameByID(i); + t.name = Bot::GetSpellTypeNameByID(i); t.delay = GetDefaultSpellDelay(i); t.min_threshold = GetDefaultSpellMinThreshold(i); t.max_threshold = GetDefaultSpellMaxThreshold(i); @@ -242,16 +241,14 @@ void Client::LoadDefaultBotSettings() { m_bot_spell_settings.push_back(t); LogBotSettingsDetail("{} says, 'Setting defaults for {} ({}) [#{}]'", GetCleanName(), t.name, t.short_name, t.spell_type); - LogBotSettingsDetail("{} says, 'Hold = [{}] | Delay = [{}ms] | MinThreshold = [{}\%] | MaxThreshold = [{}\%]'", GetCleanName(), GetDefaultSpellHold(i), GetDefaultSpellDelay(i), GetDefaultSpellMinThreshold(i), GetDefaultSpellMaxThreshold(i)); + LogBotSettingsDetail("{} says, 'Delay = [{}ms] | MinThreshold = [{}\%] | MaxThreshold = [{}\%]'", GetCleanName(), GetDefaultSpellDelay(i), GetDefaultSpellMinThreshold(i), GetDefaultSpellMaxThreshold(i)); } } int Client::GetDefaultBotSettings(uint8 setting_type, uint16 bot_setting) { switch (setting_type) { case BotSettingCategories::BaseSetting: - return false; - case BotSettingCategories::SpellHold: - return GetDefaultSpellHold(bot_setting); + return false; // only setting supported currently is illusion block case BotSettingCategories::SpellDelay: return GetDefaultSpellDelay(bot_setting); case BotSettingCategories::SpellMinThreshold: @@ -263,8 +260,8 @@ int Client::GetDefaultBotSettings(uint8 setting_type, uint16 bot_setting) { int Client::GetBotSetting(uint8 setting_type, uint16 bot_setting) { switch (setting_type) { - case BotSettingCategories::SpellHold: - return GetSpellHold(bot_setting); + case BotSettingCategories::BaseSetting: + return GetIllusionBlock(); // only setting supported currently case BotSettingCategories::SpellDelay: return GetSpellDelay(bot_setting); case BotSettingCategories::SpellMinThreshold: @@ -277,10 +274,7 @@ int Client::GetBotSetting(uint8 setting_type, uint16 bot_setting) { void Client::SetBotSetting(uint8 setting_type, uint16 bot_setting, uint32 setting_value) { switch (setting_type) { case BotSettingCategories::BaseSetting: - SetBaseSetting(bot_setting, setting_value); - break; - case BotSettingCategories::SpellHold: - SetSpellHold(bot_setting, setting_value); + SetIllusionBlock(setting_value); // only setting supported currently break; case BotSettingCategories::SpellDelay: SetSpellDelay(bot_setting, setting_value); @@ -353,3 +347,125 @@ void Client::SendSpellTypePrompts(bool commanded_types, bool client_only_types) return; } + +uint16 Client::GetDefaultSpellDelay(uint16 spell_type, uint8 stance) { + switch (spell_type) { + case BotSpellTypes::VeryFastHeals: + case BotSpellTypes::PetVeryFastHeals: + return 1500; + case BotSpellTypes::FastHeals: + case BotSpellTypes::PetFastHeals: + return 2500; + case BotSpellTypes::GroupHeals: + case BotSpellTypes::RegularHeal: + case BotSpellTypes::PetRegularHeals: + return 4000; + case BotSpellTypes::CompleteHeal: + case BotSpellTypes::GroupCompleteHeals: + case BotSpellTypes::PetCompleteHeals: + return 8000; + case BotSpellTypes::GroupHoTHeals: + case BotSpellTypes::HoTHeals: + case BotSpellTypes::PetHoTHeals: + return 22000; + case BotSpellTypes::Cure: + return 2000; + case BotSpellTypes::GroupCures: + return 3000; + case BotSpellTypes::PetCures: + return 5000; + default: + return 1; + } +} + +uint8 Client::GetDefaultSpellMinThreshold(uint16 spell_type, uint8 stance) { + switch (spell_type) { + default: + return 0; + } +} + +uint8 Client::GetDefaultSpellMaxThreshold(uint16 spell_type, uint8 stance) { + uint8 bot_class = GetClass(); + + switch (spell_type) { + case BotSpellTypes::VeryFastHeals: + case BotSpellTypes::PetVeryFastHeals: + switch (stance) { + case Stance::AEBurn: + case Stance::Burn: + case Stance::Aggressive: + return 40; + case Stance::Efficient: + default: + return 25; + } + case BotSpellTypes::FastHeals: + case BotSpellTypes::PetFastHeals: + switch (stance) { + case Stance::AEBurn: + case Stance::Burn: + case Stance::Aggressive: + return 55; + case Stance::Efficient: + return 35; + default: + return 40; + } + case BotSpellTypes::GroupHeals: + case BotSpellTypes::RegularHeal: + case BotSpellTypes::PetRegularHeals: + switch (stance) { + case Stance::AEBurn: + case Stance::Burn: + case Stance::Aggressive: + return 70; + case Stance::Efficient: + return 50; + default: + return 60; + } + case BotSpellTypes::CompleteHeal: + case BotSpellTypes::GroupCompleteHeals: + case BotSpellTypes::PetCompleteHeals: + switch (stance) { + case Stance::AEBurn: + case Stance::Burn: + case Stance::Aggressive: + return 90; + case Stance::Efficient: + return 65; + default: + return 80; + } + case BotSpellTypes::GroupHoTHeals: + case BotSpellTypes::HoTHeals: + case BotSpellTypes::PetHoTHeals: + if (bot_class == Class::Necromancer || bot_class == Class::Shaman) { + return 60; + } + else { + switch (stance) { + case Stance::AEBurn: + case Stance::Burn: + case Stance::Aggressive: + return 95; + case Stance::Efficient: + return 80; + default: + return 90; + } + } + case BotSpellTypes::Buff: + case BotSpellTypes::Cure: + case BotSpellTypes::GroupCures: + case BotSpellTypes::PetCures: + case BotSpellTypes::PetBuffs: + case BotSpellTypes::PetDamageShields: + case BotSpellTypes::PetResistBuffs: + case BotSpellTypes::ResistBuffs: + default: + return 100; + } +} diff --git a/zone/gm_commands/illusion_block.cpp b/zone/gm_commands/illusion_block.cpp index 1715c0f8f..67c3afa31 100644 --- a/zone/gm_commands/illusion_block.cpp +++ b/zone/gm_commands/illusion_block.cpp @@ -37,17 +37,17 @@ void command_illusion_block(Client* c, const Seperator* sep) int set_status = atoi(sep->arg[1]); if (set_status == 0 || set_status == 1) { c->SetIllusionBlock(set_status); - c->Message(Chat::White, "Your Illusion Block has been %s.", (set_status ? "enabled" : "disabled")); + c->Message(Chat::Green, "Your Illusion Block has been %s.", (set_status ? "enabled" : "disabled")); } else { - c->Message(Chat::White, "You must enter 0 for disabled or 1 for enabled."); + c->Message(Chat::Yellow, "You must enter 0 for disabled or 1 for enabled."); return; } } else if (!strcasecmp(sep->arg[1], "current")) { - c->Message(Chat::White, "You're currently %s illusions.", (c->GetIllusionBlock() ? "blocking" : "allowing")); + c->Message(Chat::Green, "You're currently %s illusions.", (c->GetIllusionBlock() ? "blocking" : "allowing")); } else { - c->Message(Chat::White, "Incorrect argument, use %s help for a list of options.", sep->arg[0]); + c->Message(Chat::Yellow , "Incorrect argument, use %s help for a list of options.", sep->arg[0]); } } diff --git a/zone/mob.h b/zone/mob.h index cb6f2ff0b..961a0abfd 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -93,27 +93,6 @@ struct AppearanceStruct { uint8 texture = UINT8_MAX; }; -struct BotSpellSettings { - uint16 spell_type; // type ID of bot category - std::string short_name; // type short name of bot category - std::string name; // type name of bot category - bool hold; // 0 = allow spell type, 1 = hold spell type - uint16 delay; // delay between casts of spell type, 1ms-60,000ms - uint8 min_threshold; // minimum target health threshold to allow casting of spell type - uint8 max_threshold; // maximum target health threshold to allow casting of spell type - uint16 resist_limit; // resist limit to skip spell type - bool aggro_check; // whether or not to check for possible aggro before casting - uint8 min_mana_pct; // lower mana percentage limit to allow spell cast - uint8 max_mana_pct; // upper mana percentage limit to allow spell cast - uint8 min_hp_pct; // lower HP percentage limit to allow spell cast - uint8 max_hp_pct; // upper HP percentage limit to allow spell cast - uint16 idle_priority; // idle priority of the spell type - uint16 engaged_priority; // engaged priority of the spell type - uint16 pursue_priority; // pursue priority of the spell type - uint16 ae_or_group_target_count; // require target count to cast an AE or Group spell type - Timer recast_timer; // recast timer based off delay -}; - class DataBucketKey; class Mob : public Entity { public: @@ -231,8 +210,6 @@ public: // Bot attack flag Timer bot_attack_flag_timer; - std::vector m_bot_spell_settings; - //Somewhat sorted: needs documenting! //Attack @@ -429,59 +406,6 @@ public: virtual bool CheckSpellLevelRestriction(Mob *caster, uint16 spell_id); virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster); - // Bot functions - bool PlotBotPositionAroundTarget(Mob* target, float& x_dest, float& y_dest, float& z_dest, float min_distance, float max_distance, bool behind_only = false, bool front_only = false, bool bypass_los = false); - virtual bool IsImmuneToBotSpell(uint16 spell_id, Mob* caster); - std::vector GatherSpellTargets(bool entireRaid = false, Mob* target = nullptr, bool no_clients = false, bool no_bots = false, bool no_pets = false); - inline bool SpellTypeRecastCheck(uint16 spellType) { return !m_bot_spell_settings[spellType].recast_timer.GetRemainingTime(); } - uint16 GetSpellTypeIDByShortName(std::string spellType_string); - bool IsValidBotSpellCategory(uint8 setting_type); - std::string GetBotSpellCategoryName(uint8 setting_type); - uint16 GetBotSpellCategoryIDByShortName(std::string setting_string); - bool IsValidBotBaseSetting(uint16 setting_type); - std::string GetBotSettingCategoryName(uint16 setting_type); - uint16 GetBaseSettingIDByShortName(std::string setting_string); - bool IsValidSpellType(uint16 spell_type); - std::string GetSpellTypeNameByID(uint16 spell_type); - std::string GetSpellTypeShortNameByID(uint16 spell_type); - bool IsValidSubType(uint16 sub_type); - std::string GetSubTypeNameByID(uint16 sub_type); - - bool GetDefaultSpellHold(uint16 spell_type, uint8 stance = Stance::Balanced); - uint16 GetDefaultSpellDelay(uint16 spell_type, uint8 stance = Stance::Balanced); - uint8 GetDefaultSpellMinThreshold(uint16 spell_type, uint8 stance = Stance::Balanced); - uint8 GetDefaultSpellMaxThreshold(uint16 spell_type, uint8 stance = Stance::Balanced); - - inline bool GetSpellHold(uint16 spell_type) const { return m_bot_spell_settings[spell_type].hold; } - void SetSpellHold(uint16 spell_type, bool hold_status); - inline uint16 GetSpellDelay(uint16 spell_type) const { return m_bot_spell_settings[spell_type].delay; } - void SetSpellDelay(uint16 spell_type, uint16 delay_value); - inline uint8 GetSpellMinThreshold(uint16 spell_type) const { return m_bot_spell_settings[spell_type].min_threshold; } - void SetSpellMinThreshold(uint16 spell_type, uint8 threshold_value); - inline uint8 GetSpellMaxThreshold(uint16 spell_type) const { return m_bot_spell_settings[spell_type].max_threshold; } - void SetSpellMaxThreshold(uint16 spell_type, uint8 threshold_value); - - inline uint16 GetSpellTypeRecastTimer(uint16 spell_type) { return m_bot_spell_settings[spell_type].recast_timer.GetRemainingTime(); } - void SetSpellTypeRecastTimer(uint16 spell_type, uint32 recast_time); - - uint8 GetHPRatioForSpellType(uint16 spell_type, Mob* tar); - bool GetUltimateSpellHold(uint16 spell_type, Mob* tar); - uint16 GetUltimateSpellDelay(uint16 spell_type, Mob* tar); - bool GetUltimateSpellDelayCheck(uint16 spell_type, Mob* tar); - uint8 GetUltimateSpellMinThreshold(uint16 spell_type, Mob* tar); - uint8 GetUltimateSpellMaxThreshold(uint16 spell_type, Mob* tar); - - uint16 GetPetBotSpellType(uint16 spell_type); - - void DisableBotSpellTimers(); - void StartBotSpellTimers(); - - void SetBotSetting(uint8 spell_type, uint16 bot_setting, int setting_value); - void SetBaseSetting(uint16 base_setting, int setting_value); - - void SetIllusionBlock(bool value) { _illusionBlock = value; } - bool GetIllusionBlock() const { return _illusionBlock; } - virtual float GetAOERange(uint16 spell_id); void InterruptSpell(uint16 spellid = SPELL_UNKNOWN); void InterruptSpell(uint16, uint16, uint16 spellid = SPELL_UNKNOWN); @@ -875,7 +799,6 @@ public: bool CheckLosCheat(Mob* other); //door skipping checks for LoS bool CheckLosCheatExempt(Mob* other); //exemptions to bypass los bool DoLosChecks(Mob* other); - bool TargetValidation(Mob* other); inline void SetLastLosState(bool value) { last_los_check = value; } inline bool CheckLastLosState() const { return last_los_check; } std::string GetMobDescription(); @@ -1946,14 +1869,6 @@ protected: bool pause_timer_complete; bool DistractedFromGrid; uint32 m_dont_heal_me_before; - uint32 m_dont_group_heal_me_before; - uint32 m_dont_group_hot_heal_me_before; - uint32 m_dont_regular_heal_me_before; - uint32 m_dont_very_fast_heal_me_before; - uint32 m_dont_fast_heal_me_before; - uint32 m_dont_complete_heal_me_before; - uint32 m_dont_group_complete_heal_me_before; - uint32 m_dont_hot_heal_me_before; uint32 m_dont_buff_me_before; uint32 m_dont_dot_me_before; uint32 m_dont_root_me_before; @@ -1976,9 +1891,6 @@ protected: //bot attack flags std::vector bot_attack_flags; - //bot related settings - bool _illusionBlock; - glm::vec3 m_TargetRing; GravityBehavior flymode; diff --git a/zone/mob_bot.cpp b/zone/mob_bot.cpp deleted file mode 100644 index 297c9f6a1..000000000 --- a/zone/mob_bot.cpp +++ /dev/null @@ -1,778 +0,0 @@ -#include "bot.h" -#include "mob.h" - -bool Mob::PlotBotPositionAroundTarget(Mob* target, float& x_dest, float& y_dest, float& z_dest, float min_distance, float max_distance, bool behind_only, bool front_only, bool bypass_los) { - bool Result = false; - - if (target) { - float look_heading = 0; - - min_distance = min_distance; - max_distance = max_distance; - float temp_x = 0; - float temp_y = 0; - float temp_z = target->GetZ(); - float best_z = 0; - auto offset = GetZOffset(); - const float tar_x = target->GetX(); - const float tar_y = target->GetY(); - float tar_distance = 0; - - glm::vec3 temp_z_Position; - glm::vec4 temp_m_Position; - - const uint16 max_iterations_allowed = 50; - uint16 counter = 0; - - while (counter < max_iterations_allowed) { - temp_x = tar_x + zone->random.Real(-max_distance, max_distance); - temp_y = tar_y + zone->random.Real(-max_distance, max_distance); - - temp_z_Position.x = temp_z; - temp_z_Position.y = temp_y; - temp_z_Position.z = temp_z; - best_z = GetFixedZ(temp_z_Position); - - if (best_z != BEST_Z_INVALID) { - temp_z = best_z; - } - else { - counter++; - continue; - } - - temp_m_Position.x = temp_x; - temp_m_Position.y = temp_y; - temp_m_Position.z = temp_z; - - tar_distance = Distance(target->GetPosition(), temp_m_Position); - - if (tar_distance > max_distance || tar_distance < min_distance) { - counter++; - continue; - } - - if (front_only && !InFrontMob(target, temp_x, temp_y)) { - counter++; - continue; - } - else if (behind_only && !BehindMob(target, temp_x, temp_y)) { - counter++; - continue; - } - - if (!bypass_los && CastToBot()->RequiresLoSForPositioning() && !CheckPositioningLosFN(target, temp_x, temp_y, temp_z)) { - counter++; - continue; - } - - Result = true; - break; - } - - if (Result) { - x_dest = temp_x; - y_dest = temp_y; - z_dest = temp_z; - } - } - - return Result; -} - -std::vector Mob::GatherSpellTargets(bool entire_raid, Mob* target, bool no_clients, bool no_bots, bool no_pets) { - std::vector valid_spell_targets; - - auto is_valid_target = [no_clients, no_bots](Mob* member) { - return member && - ((member->IsClient() && !no_clients) || (member->IsBot() && !no_bots)); - }; - - if (IsRaidGrouped()) { - Raid* raid = IsBot() ? CastToBot()->GetStoredRaid() : GetRaid(); - - if (raid) { - if (entire_raid) { - for (const auto& m : raid->members) { - if (is_valid_target(m.member) && m.group_number != RAID_GROUPLESS) { - valid_spell_targets.emplace_back(m.member); - } - } - } - else { - auto group_name = target ? raid->GetGroup(target->GetName()) : raid->GetGroup(GetName()); - auto raid_group = raid->GetRaidGroupMembers(group_name); - - for (const auto& m : raid_group) { - if (is_valid_target(m.member) && m.group_number != RAID_GROUPLESS) { - valid_spell_targets.emplace_back(m.member); - } - } - } - } - } - else if (IsGrouped()) { - Group* group = GetGroup(); - - if (group) { - for (const auto& m : group->members) { - if (is_valid_target(m)) { - valid_spell_targets.emplace_back(m); - } - } - } - } - else { - valid_spell_targets.emplace_back(this); - } - - return valid_spell_targets; -} - -uint16 Mob::GetSpellTypeIDByShortName(std::string spell_type_string) { - - for (int i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) { - if (!Strings::ToLower(spell_type_string).compare(GetSpellTypeShortNameByID(i))) { - return i; - } - } - - for (int i = BotSpellTypes::COMMANDED_START; i <= BotSpellTypes::COMMANDED_END; ++i) { - if (!Strings::ToLower(spell_type_string).compare(GetSpellTypeShortNameByID(i))) { - return i; - } - } - - return UINT16_MAX; -} - -bool Mob::IsValidBotSpellCategory(uint8 setting_type) { - return EQ::ValueWithin(setting_type, BotSettingCategories::START, BotSettingCategories::END_FULL); -} - -std::string Mob::GetBotSpellCategoryName(uint8 setting_type) { - return IsValidBotBaseSetting(setting_type) ? botSpellCategory_names[setting_type] : "UNKNOWN CATEGORY"; -} - -uint16 Mob::GetBotSpellCategoryIDByShortName(std::string setting_string) { - for (int i = BotSettingCategories::START; i <= BotSettingCategories::END; ++i) { - if (!Strings::ToLower(setting_string).compare(Strings::ToLower(GetBotSpellCategoryName(i)))) { - return i; - } - } - - return UINT16_MAX; -} - -bool Mob::IsValidBotBaseSetting(uint16 setting_type) { - return EQ::ValueWithin(setting_type, BotBaseSettings::START_ALL, BotBaseSettings::END); -} - -std::string Mob::GetBotSettingCategoryName(uint16 setting_type) { - return IsValidBotBaseSetting(setting_type) ? botBaseSettings_names[setting_type] : "UNKNOWN SETTING"; -} - -uint16 Mob::GetBaseSettingIDByShortName(std::string setting_string) { - for (int i = BotSettingCategories::START; i <= BotSettingCategories::END; ++i) { - if (!Strings::ToLower(setting_string).compare(Strings::ToLower(GetBotSettingCategoryName(i)))) { - return i; - } - } - - return UINT16_MAX; -} - -bool Mob::IsValidSpellType(uint16 spell_type) { - return ( - EQ::ValueWithin(spell_type, BotSpellTypes::START, BotSpellTypes::END) || - EQ::ValueWithin(spell_type, BotSpellTypes::COMMANDED_START, BotSpellTypes::COMMANDED_END) - ); -} - -std::string Mob::GetSpellTypeShortNameByID(uint16 spell_type) { - return IsValidSpellType(spell_type) ? spellType_shortNames[spell_type] : "UNKNOWN SPELLTYPE"; -} - -std::string Mob::GetSpellTypeNameByID(uint16 spell_type) { - return IsValidSpellType(spell_type) ? spellType_names[spell_type] : "UNKNOWN SPELLTYPE"; -} - -bool Mob::IsValidSubType(uint16 sub_type) { - return EQ::ValueWithin(sub_type, CommandedSubTypes::START, CommandedSubTypes::END); -} - -std::string Mob::GetSubTypeNameByID(uint16 sub_type) { - return IsValidSpellType(sub_type) ? botSubType_names[sub_type] : "UNKNOWN SUBTYPE"; -} - -bool Mob::GetDefaultSpellHold(uint16 spell_type, uint8 stance) { - uint8 bot_class = GetClass(); - - switch (spell_type) { - case BotSpellTypes::FastHeals: - case BotSpellTypes::VeryFastHeals: - case BotSpellTypes::Pet: - case BotSpellTypes::Escape: - case BotSpellTypes::Lifetap: - case BotSpellTypes::Buff: - case BotSpellTypes::PetBuffs: - case BotSpellTypes::InCombatBuff: - case BotSpellTypes::PreCombatBuff: - case BotSpellTypes::DamageShields: - case BotSpellTypes::ResistBuffs: - return false; - case BotSpellTypes::GroupCompleteHeals: - case BotSpellTypes::GroupHeals: - case BotSpellTypes::GroupHoTHeals: - case BotSpellTypes::HoTHeals: - case BotSpellTypes::CompleteHeal: - case BotSpellTypes::PetFastHeals: - case BotSpellTypes::PetRegularHeals: - case BotSpellTypes::PetVeryFastHeals: - case BotSpellTypes::RegularHeal: - switch (stance) { - case Stance::Aggressive: - case Stance::AEBurn: - case Stance::Burn: - return true; - default: - return false; - } - case BotSpellTypes::Cure: - case BotSpellTypes::GroupCures: - switch (stance) { - case Stance::Aggressive: - case Stance::AEBurn: - case Stance::Burn: - return true; - default: - return false; - } - case BotSpellTypes::InCombatBuffSong: - case BotSpellTypes::OutOfCombatBuffSong: - case BotSpellTypes::PreCombatBuffSong: - if (bot_class == Class::Bard) { - return false; - } - else { - return true; - } - case BotSpellTypes::Nuke: - case BotSpellTypes::DOT: - case BotSpellTypes::Stun: - switch (stance) { - case Stance::Assist: - return true; - default: - return false; - } - case BotSpellTypes::AENukes: - case BotSpellTypes::AERains: - case BotSpellTypes::AEStun: - case BotSpellTypes::AEDoT: - case BotSpellTypes::AELifetap: - case BotSpellTypes::PBAENuke: - switch (stance) { - case Stance::AEBurn: - return false; - default: - return true; - } - case BotSpellTypes::Mez: - case BotSpellTypes::AEMez: - case BotSpellTypes::Debuff: - case BotSpellTypes::AEDebuff: - case BotSpellTypes::Slow: - case BotSpellTypes::AESlow: - case BotSpellTypes::HateRedux: - switch (stance) { - case Stance::AEBurn: - case Stance::Burn: - return true; - default: - return false; - } - case BotSpellTypes::Snare: - switch (stance) { - case Stance::AEBurn: - case Stance::Burn: - case Stance::Assist: - return true; - default: - return false; - } - case BotSpellTypes::HateLine: - if (bot_class == Class::ShadowKnight || bot_class == Class::Paladin) { - switch (stance) { - case Stance::Aggressive: - return false; - default: - return true; - } - } - else { - return true; - } - case BotSpellTypes::Charm: - case BotSpellTypes::Resurrect: - case BotSpellTypes::AESnare: - case BotSpellTypes::AERoot: - case BotSpellTypes::Root: - case BotSpellTypes::AEDispel: - case BotSpellTypes::Dispel: - case BotSpellTypes::AEFear: - case BotSpellTypes::Fear: - case BotSpellTypes::AEHateLine: - case BotSpellTypes::PetCures: - case BotSpellTypes::PetHoTHeals: - case BotSpellTypes::PetCompleteHeals: - case BotSpellTypes::PetDamageShields: - case BotSpellTypes::PetResistBuffs: - default: - return true; - } -} - -uint16 Mob::GetDefaultSpellDelay(uint16 spell_type, uint8 stance) { - switch (spell_type) { - case BotSpellTypes::VeryFastHeals: - case BotSpellTypes::PetVeryFastHeals: - return 1500; - case BotSpellTypes::FastHeals: - case BotSpellTypes::PetFastHeals: - return 2500; - case BotSpellTypes::GroupHeals: - case BotSpellTypes::RegularHeal: - case BotSpellTypes::PetRegularHeals: - return 4000; - case BotSpellTypes::CompleteHeal: - case BotSpellTypes::GroupCompleteHeals: - case BotSpellTypes::PetCompleteHeals: - return 8000; - case BotSpellTypes::GroupHoTHeals: - case BotSpellTypes::HoTHeals: - case BotSpellTypes::PetHoTHeals: - return 22000; - case BotSpellTypes::Cure: - return 2000; - case BotSpellTypes::GroupCures: - return 3000; - case BotSpellTypes::PetCures: - return 5000; - case BotSpellTypes::AEDoT: - case BotSpellTypes::DOT: - switch (stance) { - case Stance::AEBurn: - case Stance::Burn: - return 1; - case Stance::Aggressive: - return 2000; - case Stance::Efficient: - return 8000; - default: - return 4000; - } - case BotSpellTypes::AENukes: - case BotSpellTypes::AERains: - case BotSpellTypes::PBAENuke: - case BotSpellTypes::Nuke: - case BotSpellTypes::AESnare: - case BotSpellTypes::Snare: - case BotSpellTypes::AEDebuff: - case BotSpellTypes::Debuff: - case BotSpellTypes::AESlow: - case BotSpellTypes::Slow: - case BotSpellTypes::AEStun: - case BotSpellTypes::Stun: - switch (stance) { - case Stance::AEBurn: - case Stance::Burn: - return 1; - case Stance::Aggressive: - return 3000; - case Stance::Efficient: - return 10000; - default: - return 6000; - } - case BotSpellTypes::AERoot: - case BotSpellTypes::Root: - return 8000; - case BotSpellTypes::Fear: - case BotSpellTypes::AEFear: - return 15000; - default: - return 1; - } -} - -uint8 Mob::GetDefaultSpellMinThreshold(uint16 spell_type, uint8 stance) { - switch (spell_type) { - case BotSpellTypes::AEDebuff: - case BotSpellTypes::Debuff: - case BotSpellTypes::AEDispel: - case BotSpellTypes::Dispel: - case BotSpellTypes::AESlow: - case BotSpellTypes::Slow: - switch (stance) { - case Stance::AEBurn: - case Stance::Burn: - case Stance::Aggressive: - return 0; - default: - return 20; - } - case BotSpellTypes::AENukes: - case BotSpellTypes::AERains: - case BotSpellTypes::PBAENuke: - case BotSpellTypes::Nuke: - switch (stance) { - case Stance::AEBurn: - case Stance::Burn: - case Stance::Aggressive: - return 0; - default: - return 5; - } - case BotSpellTypes::AEDoT: - case BotSpellTypes::DOT: - switch (stance) { - case Stance::AEBurn: - case Stance::Burn: - case Stance::Aggressive: - return 0; - case Stance::Efficient: - return 40; - default: - return 25; - } - case BotSpellTypes::Mez: - case BotSpellTypes::AEMez: - return 85; - default: - return 0; - } -} - -uint8 Mob::GetDefaultSpellMaxThreshold(uint16 spell_type, uint8 stance) { - uint8 bot_class = GetClass(); - - switch (spell_type) { - case BotSpellTypes::Escape: - case BotSpellTypes::VeryFastHeals: - case BotSpellTypes::PetVeryFastHeals: - switch (stance) { - case Stance::AEBurn: - case Stance::Burn: - case Stance::Aggressive: - return 40; - case Stance::Efficient: - default: - return 25; - } - case BotSpellTypes::AELifetap: - case BotSpellTypes::Lifetap: - case BotSpellTypes::FastHeals: - case BotSpellTypes::PetFastHeals: - switch (stance) { - case Stance::AEBurn: - case Stance::Burn: - case Stance::Aggressive: - return 55; - case Stance::Efficient: - return 35; - default: - return 40; - } - case BotSpellTypes::GroupHeals: - case BotSpellTypes::RegularHeal: - case BotSpellTypes::PetRegularHeals: - switch (stance) { - case Stance::AEBurn: - case Stance::Burn: - case Stance::Aggressive: - return 70; - case Stance::Efficient: - return 50; - default: - return 60; - } - case BotSpellTypes::CompleteHeal: - case BotSpellTypes::GroupCompleteHeals: - case BotSpellTypes::PetCompleteHeals: - switch (stance) { - case Stance::AEBurn: - case Stance::Burn: - case Stance::Aggressive: - return 90; - case Stance::Efficient: - return 65; - default: - return 80; - } - case BotSpellTypes::AENukes: - case BotSpellTypes::AERains: - case BotSpellTypes::PBAENuke: - case BotSpellTypes::AEStun: - case BotSpellTypes::Nuke: - case BotSpellTypes::AEDoT: - case BotSpellTypes::DOT: - case BotSpellTypes::AERoot: - case BotSpellTypes::Root: - case BotSpellTypes::AESlow: - case BotSpellTypes::Slow: - case BotSpellTypes::AESnare: - case BotSpellTypes::Snare: - case BotSpellTypes::AEFear: - case BotSpellTypes::Fear: - case BotSpellTypes::AEDispel: - case BotSpellTypes::Dispel: - case BotSpellTypes::AEDebuff: - case BotSpellTypes::Debuff: - case BotSpellTypes::Stun: - switch (stance) { - case Stance::AEBurn: - case Stance::Burn: - return 100; - case Stance::Aggressive: - return 100; - case Stance::Efficient: - return 90; - default: - return 99; - } - case BotSpellTypes::GroupHoTHeals: - case BotSpellTypes::HoTHeals: - case BotSpellTypes::PetHoTHeals: - if (bot_class == Class::Necromancer || bot_class == Class::Shaman) { - return 60; - } - else { - switch (stance) { - case Stance::AEBurn: - case Stance::Burn: - case Stance::Aggressive: - return 95; - case Stance::Efficient: - return 80; - default: - return 90; - } - } - case BotSpellTypes::Buff: - case BotSpellTypes::Charm: - case BotSpellTypes::Cure: - case BotSpellTypes::GroupCures: - case BotSpellTypes::PetCures: - case BotSpellTypes::DamageShields: - case BotSpellTypes::HateRedux: - case BotSpellTypes::InCombatBuff: - case BotSpellTypes::InCombatBuffSong: - case BotSpellTypes::Mez: - case BotSpellTypes::AEMez: - case BotSpellTypes::OutOfCombatBuffSong: - case BotSpellTypes::Pet: - case BotSpellTypes::PetBuffs: - case BotSpellTypes::PreCombatBuff: - case BotSpellTypes::PreCombatBuffSong: - case BotSpellTypes::PetDamageShields: - case BotSpellTypes::PetResistBuffs: - case BotSpellTypes::ResistBuffs: - case BotSpellTypes::Resurrect: - case BotSpellTypes::HateLine: - case BotSpellTypes::AEHateLine: - default: - return 100; - } -} - -void Mob::SetSpellHold(uint16 spell_type, bool hold_status) { - m_bot_spell_settings[spell_type].hold = hold_status; -} - -void Mob::SetSpellDelay(uint16 spell_type, uint16 delay_value) { - m_bot_spell_settings[spell_type].delay = delay_value; -} - -void Mob::SetSpellMinThreshold(uint16 spell_type, uint8 threshold_value) { - m_bot_spell_settings[spell_type].min_threshold = threshold_value; -} - -void Mob::SetSpellMaxThreshold(uint16 spell_type, uint8 threshold_value) { - m_bot_spell_settings[spell_type].max_threshold = threshold_value; -} - -void Mob::SetSpellTypeRecastTimer(uint16 spell_type, uint32 recast_time) { - m_bot_spell_settings[spell_type].recast_timer.Start(recast_time); -} - -void Mob::StartBotSpellTimers() { - for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) { - m_bot_spell_settings[i].recast_timer.Start(); - } -} - -void Mob::DisableBotSpellTimers() { - for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) { - m_bot_spell_settings[i].recast_timer.Disable(); - } -} - -bool Mob::GetUltimateSpellHold(uint16 spell_type, Mob* tar) { - if (!tar) { - return GetSpellHold(spell_type); - } - - if (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot()) { - return tar->GetOwner()->GetSpellHold(GetPetBotSpellType(spell_type)); - } - - return GetSpellHold(spell_type); -} - -uint16 Mob::GetUltimateSpellDelay(uint16 spell_type, Mob* tar) { - if (!tar) { - return GetSpellDelay(spell_type); - } - - if (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot()) { - return tar->GetOwner()->GetSpellDelay(GetPetBotSpellType(spell_type)); - } - - if (IsBotSpellTypeOtherBeneficial(spell_type) && tar->IsOfClientBot()) { - return tar->GetSpellDelay(spell_type); - } - - return GetSpellDelay(spell_type); -} - -bool Mob::GetUltimateSpellDelayCheck(uint16 spell_type, Mob* tar) { - if (!tar) { - return SpellTypeRecastCheck(spell_type); - } - - if (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot()) { - return tar->GetOwner()->SpellTypeRecastCheck(GetPetBotSpellType(spell_type)); - } - - if (IsBotSpellTypeOtherBeneficial(spell_type) && tar->IsOfClientBot()) { - return tar->SpellTypeRecastCheck(spell_type); - } - - return SpellTypeRecastCheck(spell_type); -} - -uint8 Mob::GetUltimateSpellMinThreshold(uint16 spell_type, Mob* tar) { - if (!tar) { - return GetSpellMinThreshold(spell_type); - } - - if (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot()) { - return tar->GetOwner()->GetSpellMinThreshold(GetPetBotSpellType(spell_type)); - } - - if (IsBotSpellTypeOtherBeneficial(spell_type) && tar->IsOfClientBot()) { - return tar->GetSpellMinThreshold(spell_type); - } - - return GetSpellMinThreshold(spell_type); -} - -uint8 Mob::GetUltimateSpellMaxThreshold(uint16 spell_type, Mob* tar) { - if (!tar) { - return GetSpellMaxThreshold(spell_type); - } - - if (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot()) { - return tar->GetOwner()->GetSpellMaxThreshold(GetPetBotSpellType(spell_type)); - } - - if (IsBotSpellTypeOtherBeneficial(spell_type) && tar->IsOfClientBot()) { - return tar->GetSpellMaxThreshold(spell_type); - } - - return GetSpellMaxThreshold(spell_type); -} - -uint16 Mob::GetPetBotSpellType(uint16 spell_type) { - switch (spell_type) { - case BotSpellTypes::VeryFastHeals: - return BotSpellTypes::PetVeryFastHeals; - case BotSpellTypes::FastHeals: - return BotSpellTypes::PetFastHeals; - case BotSpellTypes::RegularHeal: - return BotSpellTypes::PetRegularHeals; - case BotSpellTypes::CompleteHeal: - return BotSpellTypes::PetCompleteHeals; - case BotSpellTypes::HoTHeals: - return BotSpellTypes::PetHoTHeals; - case BotSpellTypes::Buff: - return BotSpellTypes::PetBuffs; - case BotSpellTypes::Cure: - return BotSpellTypes::PetCures; - case BotSpellTypes::DamageShields: - return BotSpellTypes::PetDamageShields; - case BotSpellTypes::ResistBuffs: - return BotSpellTypes::PetResistBuffs; - default: - break; - } - - return spell_type; -} - -uint8 Mob::GetHPRatioForSpellType(uint16 spell_type, Mob* tar) { - switch (spell_type) { - case BotSpellTypes::Escape: - case BotSpellTypes::HateRedux: - case BotSpellTypes::InCombatBuff: - case BotSpellTypes::InCombatBuffSong: - case BotSpellTypes::AELifetap: - case BotSpellTypes::Lifetap: - case BotSpellTypes::OutOfCombatBuffSong: - case BotSpellTypes::Pet: - case BotSpellTypes::PreCombatBuff: - case BotSpellTypes::PreCombatBuffSong: - return GetHPRatio(); - default: - return tar->GetHPRatio(); - } - - return tar->GetHPRatio(); -} - -void Mob::SetBotSetting(uint8 setting_type, uint16 bot_setting, int setting_value) { - if (!IsOfClientBot()) { - return; - } - - if (IsClient()) { - CastToClient()->SetBotSetting(setting_type, bot_setting, setting_value); - return; - } - - if (IsBot()) { - CastToBot()->SetBotSetting(setting_type, bot_setting, setting_value); - return; - } - - return; -} - -void Mob::SetBaseSetting(uint16 base_setting, int setting_value) { - switch (base_setting) { - case BotBaseSettings::IllusionBlock: - SetIllusionBlock(setting_value); - break; - default: - break; - } -} - -bool Mob::TargetValidation(Mob* other) { - if (!other || GetAppearance() == eaDead) { - return false; - } - - return true; -} diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index df0f74542..5bd2484b3 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1483,8 +1483,17 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Illusion: race %d", effect_value); #endif - if (caster && caster->IsOfClientBot() && GetIllusionBlock()) { - break; + if (caster && caster->IsOfClientBot()) { + if (IsClient()) { + if (CastToClient()->GetIllusionBlock()) { + break; + } + } + else { + if (CastToBot()->GetIllusionBlock()) { + break; + } + } } ApplySpellEffectIllusion(spell_id, caster, buffslot, spells[spell_id].base_value[i], spells[spell_id].limit_value[i], spells[spell_id].max_value[i]); @@ -1496,8 +1505,17 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Illusion Copy"); #endif - if (caster && caster->IsOfClientBot() && GetIllusionBlock()) { - break; + if (caster && caster->IsOfClientBot()) { + if (IsClient()) { + if (CastToClient()->GetIllusionBlock()) { + break; + } + } + else { + if (CastToBot()->GetIllusionBlock()) { + break; + } + } } if(caster && caster->GetTarget()){ diff --git a/zone/spells.cpp b/zone/spells.cpp index e5dc8e1dd..f1da3f0e1 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -7568,108 +7568,3 @@ bool Mob::CheckWaterLoS(Mob* m) zone->watermap->InLiquid(m->GetPosition()) ); } - -bool Mob::IsImmuneToBotSpell(uint16 spell_id, Mob* caster) -{ - int effect_index; - - if (!caster) { - return false; - } - - //TODO: this function loops through the effect list for - //this spell like 10 times, this could easily be consolidated - //into one loop through with a switch statement. - - LogSpells("Checking to see if we are immune to spell [{}] cast by [{}]", spell_id, caster->GetName()); - - if (!IsValidSpell(spell_id)) { - return true; - } - - if (GetSpecialAbility(SpecialAbility::DispellImmunity) && IsDispelSpell(spell_id)) { - return true; - } - - if (GetSpecialAbility(SpecialAbility::PacifyImmunity) && IsHarmonySpell(spell_id)) { - return true; - } - - if (!GetSpecialAbility(SpecialAbility::MesmerizeImmunity) && IsMesmerizeSpell(spell_id)) { - // check max level for spell - effect_index = GetSpellEffectIndex(spell_id, SE_Mez); - assert(effect_index >= 0); - // NPCs get to ignore the max level - if ( - (GetLevel() > spells[spell_id].max_value[effect_index]) && - (!caster->IsNPC() || (caster->IsNPC() && !RuleB(Spells, NPCIgnoreBaseImmunity))) - ) { - return true; - } - } - - // slow and haste spells - if (GetSpecialAbility(SpecialAbility::SlowImmunity) && IsEffectInSpell(spell_id, SE_AttackSpeed)) { - return true; - } - - // client vs client fear - if (!GetSpecialAbility(SpecialAbility::FearImmunity) && IsEffectInSpell(spell_id, SE_Fear)) { - effect_index = GetSpellEffectIndex(spell_id, SE_Fear); - - if (IsClient() && caster->IsClient() && (caster->CastToClient()->GetGM() == false)) { - LogSpells("Clients cannot fear eachother!"); - caster->MessageString(Chat::Red, IMMUNE_FEAR); // need to verify message type, not in MQ2Cast for easy look up - return true; - } - else if (GetLevel() > spells[spell_id].max_value[effect_index] && spells[spell_id].max_value[effect_index] != 0) { - return true; - } - else if (CheckAATimer(aaTimerWarcry)) { - return true; - } - } - - if (!GetSpecialAbility(SpecialAbility::CharmImmunity) && IsCharmSpell(spell_id)) { - - if (this == caster) { - return true; - } - - //let npcs cast whatever charm on anyone - if (!caster->IsNPC()) { - // check level limit of charm spell - effect_index = GetSpellEffectIndex(spell_id, SE_Charm); - assert(effect_index >= 0); - if (GetLevel() > spells[spell_id].max_value[effect_index] && spells[spell_id].max_value[effect_index] != 0) { - return true; - } - } - } - - if ( - GetSpecialAbility(SpecialAbility::SnareImmunity) && - ( - IsEffectInSpell(spell_id, SE_Root) || - IsEffectInSpell(spell_id, SE_MovementSpeed) - ) - ) { - if (GetSpecialAbility(SpecialAbility::SnareImmunity)) { - return true; - } - } - - if (IsLifetapSpell(spell_id)) { - if (this == caster) { - return true; - } - } - - if (IsSacrificeSpell(spell_id)) { - if (this == caster) { - return true; - } - } - - return false; -}