mirror of
https://github.com/araxiaonline/AzerothCore-wotlk-with-NPCBots-2025.git
synced 2026-06-13 03:22:24 -04:00
NPCBots: Implement saving per-bot settings: Rogue poisons, Shaman enchants, Paladin aura, Hunter pet type, Warlock pet type. Fix weapon enchants set by player disappearing on Rogues / Shamans after server restart
(cherry picked from commit 8dc82c25e2203d2272ff7aa6e57564ee1686732f) # Conflicts: # data/sql/custom/db_characters/2024_11_21_00_characters_npcbot.sql
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
--
|
||||
ALTER TABLE `characters_npcbot` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
ALTER TABLE `characters_npcbot` ADD `miscvalues` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL AFTER `spells_disabled`;
|
||||
@@ -630,6 +630,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
PrepareStatement(CHAR_UPD_NPCBOT_FACTION, "UPDATE characters_npcbot SET faction = ? WHERE entry = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_NPCBOT_SPEC, "UPDATE characters_npcbot SET spec = ? WHERE entry = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_NPCBOT_DISABLED_SPELLS, "UPDATE characters_npcbot SET spells_disabled = ? WHERE entry = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_NPCBOT_MISCVALUES, "UPDATE characters_npcbot SET miscvalues = ? WHERE entry = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_NPCBOT_STATS, "REPLACE INTO characters_npcbot_stats "
|
||||
"(entry, maxhealth, maxpower, strength, agility, stamina, intellect, spirit, armor, defense, resHoly, resFire, resNature, resFrost, resShadow, resArcane, blockPct, dodgePct, parryPct, critPct, attackPower, spellPower, spellPen, hastePct, hitBonusPct, expertise, armorPenPct) VALUES "
|
||||
"(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
@@ -538,6 +538,7 @@ enum CharacterDatabaseStatements : uint32
|
||||
CHAR_UPD_NPCBOT_FACTION,
|
||||
CHAR_UPD_NPCBOT_SPEC,
|
||||
CHAR_UPD_NPCBOT_DISABLED_SPELLS,
|
||||
CHAR_UPD_NPCBOT_MISCVALUES,
|
||||
CHAR_REP_NPCBOT_STATS,
|
||||
CHAR_REP_NPCBOT_TRANSMOG,
|
||||
CHAR_DEL_NPCBOT_TRANSMOG,
|
||||
|
||||
@@ -240,6 +240,8 @@ bot_ai::bot_ai(Creature* creature) : CreatureAI(creature)
|
||||
|
||||
_saveDisabledSpellsTimer = 0;
|
||||
_saveDisabledSpells = false;
|
||||
_saveMiscValuesTimer = 0;
|
||||
_saveMiscValues = false;
|
||||
|
||||
_deathsCount = 0;
|
||||
_killsCount = 0;
|
||||
@@ -615,6 +617,8 @@ void bot_ai::ResetBotAI(uint8 resetType)
|
||||
|
||||
if ((resetType == BOTAI_RESET_DISMISS || resetType == BOTAI_RESET_LOGOUT) && !IsTempBot())
|
||||
{
|
||||
if (resetType == BOTAI_RESET_DISMISS)
|
||||
ResetAllMiscValues();
|
||||
EnableAllSpells(resetType == BOTAI_RESET_DISMISS);
|
||||
InitRoles();
|
||||
}
|
||||
@@ -13137,13 +13141,13 @@ BotEquipResult bot_ai::_equip(uint8 slot, Item* newItem, ObjectGuid receiver, bo
|
||||
if (slot == BOT_SLOT_MAINHAND)
|
||||
{
|
||||
SetAIMiscValue(BOTAI_MISC_DAGGER_MAINHAND, proto->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER);
|
||||
SetAIMiscValue(BOTAI_MISC_ENCHANT_CAN_EXPIRE_MH, newItem->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT));
|
||||
SetAIMiscValue(BOTAI_MISC_ENCHANT_TIMER_MH, uint32(newItem->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT) ? 0 : 1));
|
||||
SetAIMiscValue(BOTAI_MISC_WEAPON_SPEC, proto->SubClass);
|
||||
}
|
||||
if (slot == BOT_SLOT_OFFHAND)
|
||||
{
|
||||
SetAIMiscValue(BOTAI_MISC_DAGGER_OFFHAND, proto->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER);
|
||||
SetAIMiscValue(BOTAI_MISC_ENCHANT_CAN_EXPIRE_OH, newItem->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT));
|
||||
SetAIMiscValue(BOTAI_MISC_ENCHANT_TIMER_OH, uint32(newItem->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT) ? 0 : 1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13547,7 +13551,7 @@ void bot_ai::RemoveItemClassEnchantment(uint8 slot)
|
||||
{
|
||||
uint8 eslot = TEMP_ENCHANTMENT_SLOT;
|
||||
|
||||
if (!GetAIMiscValue(slot == BOT_SLOT_MAINHAND ? BOTAI_MISC_ENCHANT_CAN_EXPIRE_MH : BOTAI_MISC_ENCHANT_CAN_EXPIRE_OH))
|
||||
if (!GetAIMiscValue(slot == BOT_SLOT_MAINHAND ? BOTAI_MISC_ENCHANT_TIMER_MH : BOTAI_MISC_ENCHANT_TIMER_OH))
|
||||
return;
|
||||
|
||||
Item* weap = _equips[slot];
|
||||
@@ -14806,6 +14810,7 @@ void bot_ai::DefaultInit()
|
||||
InitFaction();
|
||||
InitOwner();
|
||||
InitEquips();
|
||||
InitMiscValues();
|
||||
}
|
||||
|
||||
firstspawn = false;
|
||||
@@ -17834,6 +17839,18 @@ bool bot_ai::GlobalUpdate(uint32 diff)
|
||||
BotDataMgr::UpdateNpcBotData(me->GetEntry(), NPCBOT_UPDATE_DISABLED_SPELLS, &npcBotData->disabled_spells);
|
||||
}
|
||||
}
|
||||
// 2) miscavalues
|
||||
if (_saveMiscValues && _saveMiscValuesTimer <= diff)
|
||||
{
|
||||
_saveMiscValues = false;
|
||||
_saveMiscValuesTimer = 5000;
|
||||
|
||||
if (!IsTempBot())
|
||||
{
|
||||
NpcBotData* npcBotData = const_cast<NpcBotData*>(BotDataMgr::SelectNpcBotData(me->GetEntry()));
|
||||
BotDataMgr::UpdateNpcBotData(me->GetEntry(), NPCBOT_UPDATE_MISCVALUES, &npcBotData->miscvalues);
|
||||
}
|
||||
}
|
||||
|
||||
if (_updateTimerEx2 <= diff)
|
||||
{
|
||||
@@ -18628,6 +18645,7 @@ void bot_ai::CommonTimers(uint32 diff)
|
||||
if (_updateTimerEx2 > diff) _updateTimerEx2 -= diff;
|
||||
|
||||
if (_saveDisabledSpellsTimer > diff) _saveDisabledSpellsTimer -= diff;
|
||||
if (_saveMiscValuesTimer > diff) _saveMiscValuesTimer -= diff;
|
||||
}
|
||||
|
||||
void bot_ai::UpdateReviveTimer(uint32 diff)
|
||||
@@ -20996,6 +21014,59 @@ uint8 bot_ai::GetBotComboPoints() const
|
||||
return me->GetVehicle() ? vehcomboPoints : uint8(GetAIMiscValue(BOTAI_MISC_COMBO_POINTS));
|
||||
}
|
||||
|
||||
void bot_ai::SetAIMiscValue(uint32 data, uint32 value)
|
||||
{
|
||||
if (data >= BOT_MISCVALUE_SAVED_FIRST && data <= BOT_MISCVALUE_SAVED_LAST)
|
||||
{
|
||||
NpcBotData* npcBotData = const_cast<NpcBotData*>(BotDataMgr::SelectNpcBotData(me->GetEntry()));
|
||||
if (auto it = npcBotData->miscvalues.find(data); it == npcBotData->miscvalues.end() || it->second != value)
|
||||
{
|
||||
npcBotData->miscvalues[data] = value;
|
||||
_saveMiscValues = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bot_ai::ResetAllMiscValues()
|
||||
{
|
||||
NpcBotData* npcBotData = const_cast<NpcBotData*>(BotDataMgr::SelectNpcBotData(me->GetEntry()));
|
||||
|
||||
for (uint32 miscval = BOT_MISCVALUE_SAVED_FIRST; miscval <= BOT_MISCVALUE_SAVED_LAST; ++miscval)
|
||||
{
|
||||
switch (miscval)
|
||||
{
|
||||
case BOTAI_MISC_ENCHANT_IS_AUTO_MH:
|
||||
case BOTAI_MISC_ENCHANT_IS_AUTO_OH:
|
||||
SetAIMiscValue(miscval, uint32(true));
|
||||
break;
|
||||
case BOTAI_MISC_ENCHANT_TIMER_MH:
|
||||
case BOTAI_MISC_ENCHANT_TIMER_OH:
|
||||
SetAIMiscValue(miscval, uint32(1));
|
||||
break;
|
||||
case BOTAI_MISC_ENCHANT_CURRENT_MH:
|
||||
case BOTAI_MISC_ENCHANT_CURRENT_OH:
|
||||
case BOTAI_MISC_PET_TYPE:
|
||||
case BOTAI_MISC_AURA_TYPE:
|
||||
SetAIMiscValue(miscval, uint32(0));
|
||||
break;
|
||||
default:
|
||||
BOT_LOG_ERROR("npcbots", "ResetMiscValues: unknown saved miscvalue {} reset for bot {} (current: {})!", miscval, me->GetEntry(), GetAIMiscValue(miscval));
|
||||
SetAIMiscValue(miscval, uint32(0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
npcBotData->miscvalues.clear();
|
||||
_saveMiscValues = true;
|
||||
}
|
||||
|
||||
void bot_ai::InitMiscValues()
|
||||
{
|
||||
NpcBotData const* npcBotData = BotDataMgr::SelectNpcBotData(me->GetEntry());
|
||||
for (auto const& p : npcBotData->miscvalues)
|
||||
SetAIMiscValue(p.first, p.second);
|
||||
}
|
||||
|
||||
float bot_ai::GetBotAmmoDPS() const
|
||||
{
|
||||
if (CanUseAmmo())
|
||||
|
||||
@@ -263,8 +263,10 @@ class bot_ai : public CreatureAI
|
||||
bool CanChangeEquip(uint8 slot) const;
|
||||
virtual bool CanSeeEveryone() const { return false; }
|
||||
virtual float GetBotArmorPenetrationCoef() const { return armor_pen; }
|
||||
void InitMiscValues();
|
||||
void ResetAllMiscValues();
|
||||
virtual uint32 GetAIMiscValue(uint32 /*data*/) const { return 0; }
|
||||
virtual void SetAIMiscValue(uint32 /*data*/, uint32 /*value*/) {}
|
||||
virtual void SetAIMiscValue(uint32 data, uint32 value);
|
||||
uint8 GetBotComboPoints() const;
|
||||
float GetBotAmmoDPS() const;
|
||||
|
||||
@@ -714,6 +716,7 @@ class bot_ai : public CreatureAI
|
||||
uint32 _groupUpdateTimer;
|
||||
//save timers
|
||||
uint32 _saveDisabledSpellsTimer;
|
||||
uint32 _saveMiscValuesTimer;
|
||||
|
||||
uint32 _lastZoneId, _lastAreaId, _lastWMOAreaId;
|
||||
uint32 _selfrez_spell_id;
|
||||
@@ -755,6 +758,7 @@ class bot_ai : public CreatureAI
|
||||
|
||||
//save flags
|
||||
bool _saveDisabledSpells;
|
||||
bool _saveMiscValues;
|
||||
|
||||
TeleportHomeEvent* teleHomeEvent;
|
||||
TeleportFinishEvent* teleFinishEvent;
|
||||
|
||||
@@ -108,16 +108,6 @@ enum HunterPassives
|
||||
|
||||
enum HunterSpecial
|
||||
{
|
||||
ASPECT_NONE = 0,
|
||||
ASPECT_MONKEY = 1,
|
||||
ASPECT_HAWK = 2,
|
||||
ASPECT_CHEETAH = 3,
|
||||
ASPECT_VIPER = 4,
|
||||
ASPECT_BEAST = 5,
|
||||
ASPECT_PACK = 6,
|
||||
ASPECT_WILD = 7,
|
||||
ASPECT_DRAGONHAWK = 8,
|
||||
|
||||
SPECIFIC_ASPECT_MONKEY = 0x001,
|
||||
SPECIFIC_ASPECT_HAWK = 0x002,
|
||||
SPECIFIC_ASPECT_CHEETAH = 0x004,
|
||||
@@ -225,6 +215,8 @@ public:
|
||||
{
|
||||
_botclass = BOT_CLASS_HUNTER;
|
||||
|
||||
myPetType = 0;
|
||||
|
||||
InitUnitFlags();
|
||||
}
|
||||
|
||||
@@ -247,7 +239,7 @@ public:
|
||||
void KilledUnit(Unit* u) override { bot_ai::KilledUnit(u); }
|
||||
void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER) override { bot_ai::EnterEvadeMode(why); }
|
||||
void MoveInLineOfSight(Unit* u) override { bot_ai::MoveInLineOfSight(u); }
|
||||
void JustDied(Unit* u) override { Aspect = 0; UnsummonAll(false); bot_ai::JustDied(u); }
|
||||
void JustDied(Unit* u) override { _myaspect = 0; UnsummonAll(false); bot_ai::JustDied(u); }
|
||||
void DoNonCombatActions(uint32 /*diff*/) { }
|
||||
|
||||
void CheckAspects(uint32 diff)
|
||||
@@ -257,7 +249,7 @@ public:
|
||||
|
||||
aspectTimer = urand(5000, 10000);
|
||||
|
||||
if (Aspect == ASPECT_VIPER && GetManaPCT(me) < 50)
|
||||
if (_myaspect == ASPECT_OF_THE_VIPER_1 && GetManaPCT(me) < 50)
|
||||
return;
|
||||
|
||||
uint32 ASPECT_OF_THE_MONKEY = GetSpell(ASPECT_OF_THE_MONKEY_1);
|
||||
@@ -272,7 +264,7 @@ public:
|
||||
std::map<uint32 /*baseid*/, uint32 /*curid*/> idMap;
|
||||
uint32 mask = _getAspectsMask(idMap);
|
||||
|
||||
if (Aspect == ASPECT_WILD) //manual
|
||||
if (_myaspect == ASPECT_OF_THE_WILD_1) //manual
|
||||
{
|
||||
if (idMap[ASPECT_OF_THE_WILD_1] != ASPECT_OF_THE_WILD)
|
||||
if (doCast(me, ASPECT_OF_THE_WILD))
|
||||
@@ -289,10 +281,10 @@ public:
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (Aspect == ASPECT_VIPER && GetManaPCT(me) > 50)
|
||||
else if (_myaspect == ASPECT_OF_THE_VIPER_1 && GetManaPCT(me) > 50)
|
||||
{
|
||||
me->RemoveAurasDueToSpell(ASPECT_OF_THE_VIPER_1, me->GetGUID());
|
||||
Aspect = ASPECT_NONE;
|
||||
_myaspect = 0;
|
||||
}
|
||||
|
||||
if (IAmFree())
|
||||
@@ -304,7 +296,7 @@ public:
|
||||
(me->IsInCombat() || !map_allows_mount || !IsOutdoors() || IsFlagCarrier(me)) :
|
||||
!me->IsWithinDist(me->GetVictim(), 8.0f + GetSpellAttackRange(true))))
|
||||
{
|
||||
if (ASPECT_OF_THE_CHEETAH && !(mask & (SPECIFIC_ASPECT_CHEETAH | SPECIFIC_ASPECT_PACK)) && Aspect != ASPECT_CHEETAH)
|
||||
if (ASPECT_OF_THE_CHEETAH && !(mask & (SPECIFIC_ASPECT_CHEETAH | SPECIFIC_ASPECT_PACK)) && _myaspect != ASPECT_OF_THE_CHEETAH_1)
|
||||
{
|
||||
if (doCast(me, ASPECT_OF_THE_CHEETAH))
|
||||
return;
|
||||
@@ -312,10 +304,10 @@ public:
|
||||
|
||||
return;
|
||||
}
|
||||
else if (Aspect == ASPECT_CHEETAH)
|
||||
else if (_myaspect == ASPECT_OF_THE_CHEETAH_1)
|
||||
{
|
||||
me->RemoveAurasDueToSpell(ASPECT_OF_THE_CHEETAH_1, me->GetGUID());
|
||||
Aspect = ASPECT_NONE;
|
||||
_myaspect = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -335,7 +327,7 @@ public:
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ASPECT_OF_THE_CHEETAH && Aspect != ASPECT_CHEETAH)
|
||||
if (ASPECT_OF_THE_CHEETAH && _myaspect != ASPECT_OF_THE_CHEETAH_1)
|
||||
{
|
||||
movFlags = me->m_movementInfo.GetMovementFlags();
|
||||
if ((movFlags & MOVEMENTFLAG_FORWARD) && !(movFlags & (MOVEMENTFLAG_FALLING_FAR)) &&
|
||||
@@ -349,33 +341,33 @@ public:
|
||||
|
||||
return;
|
||||
}
|
||||
else if (Aspect == ASPECT_PACK)
|
||||
else if (_myaspect == ASPECT_OF_THE_PACK_1)
|
||||
{
|
||||
me->RemoveAurasDueToSpell(ASPECT_OF_THE_PACK_1, me->GetGUID());
|
||||
Aspect = ASPECT_NONE;
|
||||
_myaspect = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((Aspect == ASPECT_DRAGONHAWK && idMap[ASPECT_OF_THE_DRAGONHAWK_1] == ASPECT_OF_THE_DRAGONHAWK) ||
|
||||
(!ASPECT_OF_THE_DRAGONHAWK && ((Aspect == ASPECT_HAWK && idMap[ASPECT_OF_THE_HAWK_1] == ASPECT_OF_THE_HAWK) ||
|
||||
Aspect == ASPECT_MONKEY)))
|
||||
if ((_myaspect == ASPECT_OF_THE_DRAGONHAWK_1 && idMap[ASPECT_OF_THE_DRAGONHAWK_1] == ASPECT_OF_THE_DRAGONHAWK) ||
|
||||
(!ASPECT_OF_THE_DRAGONHAWK && ((_myaspect == ASPECT_OF_THE_HAWK_1 && idMap[ASPECT_OF_THE_HAWK_1] == ASPECT_OF_THE_HAWK) ||
|
||||
_myaspect == ASPECT_OF_THE_MONKEY_1)))
|
||||
return;
|
||||
|
||||
if (ASPECT_OF_THE_DRAGONHAWK &&
|
||||
(Aspect != ASPECT_DRAGONHAWK || idMap[ASPECT_OF_THE_DRAGONHAWK_1] != ASPECT_OF_THE_DRAGONHAWK))
|
||||
(_myaspect != ASPECT_OF_THE_DRAGONHAWK_1 || idMap[ASPECT_OF_THE_DRAGONHAWK_1] != ASPECT_OF_THE_DRAGONHAWK))
|
||||
{
|
||||
if (doCast(me, ASPECT_OF_THE_DRAGONHAWK))
|
||||
return;
|
||||
return;
|
||||
}
|
||||
if (ASPECT_OF_THE_HAWK && (!IsTank() || (!ASPECT_OF_THE_MONKEY && !ASPECT_OF_THE_DRAGONHAWK)) &&
|
||||
(Aspect != ASPECT_HAWK || idMap[ASPECT_OF_THE_HAWK_1] != ASPECT_OF_THE_HAWK))
|
||||
(_myaspect != ASPECT_OF_THE_HAWK_1 || idMap[ASPECT_OF_THE_HAWK_1] != ASPECT_OF_THE_HAWK))
|
||||
{
|
||||
if (doCast(me, ASPECT_OF_THE_HAWK))
|
||||
return;
|
||||
return;
|
||||
}
|
||||
if (ASPECT_OF_THE_MONKEY && Aspect != ASPECT_MONKEY)
|
||||
if (ASPECT_OF_THE_MONKEY && _myaspect != ASPECT_OF_THE_MONKEY_1)
|
||||
{
|
||||
if (doCast(me, ASPECT_OF_THE_MONKEY))
|
||||
return;
|
||||
@@ -1553,28 +1545,14 @@ public:
|
||||
switch (baseId)
|
||||
{
|
||||
case ASPECT_OF_THE_MONKEY_1:
|
||||
Aspect = ASPECT_MONKEY;
|
||||
break;
|
||||
case ASPECT_OF_THE_HAWK_1:
|
||||
Aspect = ASPECT_HAWK;
|
||||
break;
|
||||
case ASPECT_OF_THE_CHEETAH_1:
|
||||
Aspect = ASPECT_CHEETAH;
|
||||
break;
|
||||
case ASPECT_OF_THE_VIPER_1:
|
||||
Aspect = ASPECT_VIPER;
|
||||
break;
|
||||
case ASPECT_OF_THE_BEAST_1:
|
||||
Aspect = ASPECT_BEAST;
|
||||
break;
|
||||
case ASPECT_OF_THE_PACK_1:
|
||||
Aspect = ASPECT_PACK;
|
||||
break;
|
||||
case ASPECT_OF_THE_WILD_1:
|
||||
Aspect = ASPECT_WILD;
|
||||
break;
|
||||
case ASPECT_OF_THE_DRAGONHAWK_1:
|
||||
Aspect = ASPECT_DRAGONHAWK;
|
||||
_myaspect = baseId;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -1970,19 +1948,22 @@ public:
|
||||
case BOTAI_MISC_PET_AVAILABLE_4:
|
||||
return BOT_PET_TENACITY_START;
|
||||
case BOTAI_MISC_PET_AVAILABLE_5:
|
||||
return me->GetLevel() >= 80 ? BOT_PET_SILITHID : 0;
|
||||
return _spec == BOT_SPEC_HUNTER_BEASTMASTERY && me->GetLevel() >= 80 ? BOT_PET_SILITHID : 0;
|
||||
case BOTAI_MISC_PET_AVAILABLE_6:
|
||||
return me->GetLevel() >= 80 ? BOT_PET_CHIMAERA : 0;
|
||||
return _spec == BOT_SPEC_HUNTER_BEASTMASTERY && me->GetLevel() >= 80 ? BOT_PET_CHIMAERA : 0;
|
||||
case BOTAI_MISC_PET_AVAILABLE_7:
|
||||
return me->GetLevel() >= 80 ? BOT_PET_SPIRITBEAST : 0;
|
||||
return _spec == BOT_SPEC_HUNTER_BEASTMASTERY && me->GetLevel() >= 80 ? BOT_PET_SPIRITBEAST : 0;
|
||||
case BOTAI_MISC_PET_AVAILABLE_8:
|
||||
return me->GetLevel() >= 80 ? BOT_PET_COREHOUND : 0;
|
||||
return _spec == BOT_SPEC_HUNTER_BEASTMASTERY && me->GetLevel() >= 80 ? BOT_PET_COREHOUND : 0;
|
||||
case BOTAI_MISC_PET_AVAILABLE_9:
|
||||
return me->GetLevel() >= 80 ? BOT_PET_DEVILSAUR : 0;
|
||||
return _spec == BOT_SPEC_HUNTER_BEASTMASTERY && me->GetLevel() >= 80 ? BOT_PET_DEVILSAUR : 0;
|
||||
case BOTAI_MISC_PET_AVAILABLE_10:
|
||||
return me->GetLevel() >= 80 ? BOT_PET_RHINO : 0;
|
||||
return _spec == BOT_SPEC_HUNTER_BEASTMASTERY && me->GetLevel() >= 80 ? BOT_PET_RHINO : 0;
|
||||
case BOTAI_MISC_PET_AVAILABLE_11:
|
||||
return me->GetLevel() >= 80 ? BOT_PET_WORM : 0;
|
||||
return _spec == BOT_SPEC_HUNTER_BEASTMASTERY && me->GetLevel() >= 80 ? BOT_PET_WORM : 0;
|
||||
case BOTAI_MISC_AURA_TYPE:
|
||||
return _myaspect;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -1999,14 +1980,14 @@ public:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
bot_ai::SetAIMiscValue(data, value);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
UnsummonAll(false);
|
||||
|
||||
myPetType = 0;
|
||||
|
||||
trapTimer = 0;
|
||||
stingTimer = 0;
|
||||
aspectTimer = 0;
|
||||
@@ -2016,7 +1997,7 @@ public:
|
||||
|
||||
petSummonTimer = 5000;
|
||||
|
||||
Aspect = 0;
|
||||
_myaspect = 0;
|
||||
|
||||
DefaultInit();
|
||||
}
|
||||
@@ -2169,17 +2150,17 @@ public:
|
||||
void FillAbilitiesSpecifics(Player const* player, std::list<std::string> &specList) override
|
||||
{
|
||||
uint32 textId;
|
||||
switch (Aspect)
|
||||
switch (_myaspect)
|
||||
{
|
||||
case ASPECT_MONKEY: textId = BOT_TEXT_MONKEY; break;
|
||||
case ASPECT_HAWK: textId = BOT_TEXT_HAWK; break;
|
||||
case ASPECT_CHEETAH: textId = BOT_TEXT_CHEETAH; break;
|
||||
case ASPECT_VIPER: textId = BOT_TEXT_VIPER; break;
|
||||
case ASPECT_BEAST: textId = BOT_TEXT_BEAST; break;
|
||||
case ASPECT_PACK: textId = BOT_TEXT_PACK; break;
|
||||
case ASPECT_WILD: textId = BOT_TEXT_WILD; break;
|
||||
case ASPECT_DRAGONHAWK: textId = BOT_TEXT_DRAGONHAWK; break;
|
||||
default: textId = BOT_TEXT_NOASPECT; break;
|
||||
case ASPECT_OF_THE_MONKEY_1: textId = BOT_TEXT_MONKEY; break;
|
||||
case ASPECT_OF_THE_HAWK_1: textId = BOT_TEXT_HAWK; break;
|
||||
case ASPECT_OF_THE_CHEETAH_1: textId = BOT_TEXT_CHEETAH; break;
|
||||
case ASPECT_OF_THE_VIPER_1: textId = BOT_TEXT_VIPER; break;
|
||||
case ASPECT_OF_THE_BEAST_1: textId = BOT_TEXT_BEAST; break;
|
||||
case ASPECT_OF_THE_PACK_1: textId = BOT_TEXT_PACK; break;
|
||||
case ASPECT_OF_THE_WILD_1: textId = BOT_TEXT_WILD; break;
|
||||
case ASPECT_OF_THE_DRAGONHAWK_1: textId = BOT_TEXT_DRAGONHAWK; break;
|
||||
default: textId = BOT_TEXT_NOASPECT; break;
|
||||
}
|
||||
specList.push_back(LocalizedNpcText(player, BOT_TEXT_ASPECT) + ": " + LocalizedNpcText(player, textId));
|
||||
}
|
||||
@@ -2203,7 +2184,7 @@ public:
|
||||
|
||||
private:
|
||||
uint32 trapTimer, stingTimer, aspectTimer, flareTimer, misdirectionTimer, checkMendTimer;
|
||||
uint8 Aspect;
|
||||
uint32 _myaspect;
|
||||
//Pet
|
||||
uint32 myPetType;
|
||||
uint32 petSummonTimer;
|
||||
|
||||
@@ -143,15 +143,6 @@ enum PaladinPassives
|
||||
|
||||
enum PaladinSpecial
|
||||
{
|
||||
NOAURA = 0,
|
||||
DEVOTIONAURA = 1,
|
||||
CONCENTRATIONAURA = 2,
|
||||
FIRERESAURA = 3,
|
||||
FROSTRESAURA = 4,
|
||||
SHADOWRESAURA = 5,
|
||||
RETRIBUTIONAURA = 6,
|
||||
CRUSADERAURA = 7,
|
||||
|
||||
SPECIFIC_BLESSING_WISDOM = 0x01,
|
||||
SPECIFIC_BLESSING_KINGS = 0x02,
|
||||
SPECIFIC_BLESSING_SANCTUARY = 0x04,
|
||||
@@ -263,6 +254,8 @@ public:
|
||||
{
|
||||
_botclass = BOT_CLASS_PALADIN;
|
||||
|
||||
_myaura = 0;
|
||||
|
||||
InitUnitFlags();
|
||||
}
|
||||
|
||||
@@ -712,7 +705,7 @@ public:
|
||||
xphploss > _heals[HOLY_LIGHT_1])
|
||||
{
|
||||
//Aura Mastery
|
||||
if (hp < 60 && _aura == CONCENTRATIONAURA && IsSpellReady(AURA_MASTERY_1, diff, false) && Rand() < 90 &&
|
||||
if (hp < 60 && _myaura == CONCENTRATION_AURA_1 && IsSpellReady(AURA_MASTERY_1, diff, false) && Rand() < 90 &&
|
||||
((!me->getAttackers().empty() && (*me->getAttackers().begin())->GetTypeId() == TYPEID_PLAYER) ||
|
||||
me->GetMap()->Instanceable() || tanking))
|
||||
if (doCast(me, GetSpell(AURA_MASTERY_1)))
|
||||
@@ -931,6 +924,11 @@ public:
|
||||
return;
|
||||
|
||||
//TODO: priority?
|
||||
if (_myaura && GetSpell(_myaura) && (!idMap.contains(_myaura) || idMap[_myaura] < GetSpell(_myaura)))
|
||||
{
|
||||
if (doCast(me, GetSpell(_myaura)))
|
||||
return;
|
||||
}
|
||||
if (DEVOTION_AURA &&
|
||||
(!(mask & SPECIFIC_AURA_DEVOTION) || idMap[DEVOTION_AURA_1] < DEVOTION_AURA) &&
|
||||
(!RETRIBUTION_AURA || IsTank(master) || isProt))
|
||||
@@ -2076,20 +2074,20 @@ public:
|
||||
//Aura Helper
|
||||
if (caster == me)
|
||||
{
|
||||
if (baseId == DEVOTION_AURA_1)
|
||||
_aura = DEVOTIONAURA;
|
||||
if (baseId == CONCENTRATION_AURA_1)
|
||||
_aura = CONCENTRATIONAURA;
|
||||
if (baseId == FIRE_RESISTANCE_AURA_1)
|
||||
_aura = FIRERESAURA;
|
||||
if (baseId == FROST_RESISTANCE_AURA_1)
|
||||
_aura = FROSTRESAURA;
|
||||
if (baseId == SHADOW_RESISTANCE_AURA_1)
|
||||
_aura = SHADOWRESAURA;
|
||||
if (baseId == RETRIBUTION_AURA_1)
|
||||
_aura = RETRIBUTIONAURA;
|
||||
if (baseId == CRUSADER_AURA_1)
|
||||
_aura = CRUSADERAURA;
|
||||
switch (baseId)
|
||||
{
|
||||
case DEVOTION_AURA_1:
|
||||
case CONCENTRATION_AURA_1:
|
||||
case FIRE_RESISTANCE_AURA_1:
|
||||
case FROST_RESISTANCE_AURA_1:
|
||||
case SHADOW_RESISTANCE_AURA_1:
|
||||
case RETRIBUTION_AURA_1:
|
||||
case CRUSADER_AURA_1:
|
||||
SetAIMiscValue(BOTAI_MISC_AURA_TYPE, baseId);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//immunity markers
|
||||
@@ -2166,6 +2164,31 @@ public:
|
||||
return longRange ? CalcSpellMaxRange(GetSpell(EXORCISM_1) ? EXORCISM_1 : JUDGEMENT_OF_LIGHT_1) : 10.f;
|
||||
}
|
||||
|
||||
uint32 GetAIMiscValue(uint32 data) const override
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case BOTAI_MISC_AURA_TYPE:
|
||||
return _myaura;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SetAIMiscValue(uint32 data, uint32 value) override
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case BOTAI_MISC_AURA_TYPE:
|
||||
_myaura = value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
bot_ai::SetAIMiscValue(data, value);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
checkAuraTimer = 0;
|
||||
@@ -2174,7 +2197,6 @@ public:
|
||||
checkBeaconTimer = 0;
|
||||
avDelayTimer = 0;
|
||||
shieldDelayTimer = 0;
|
||||
_aura = NOAURA;
|
||||
_sacDamage = 0;
|
||||
|
||||
CLEANSE = 0;
|
||||
@@ -2365,19 +2387,13 @@ public:
|
||||
case HOLY_SHOCK_1:
|
||||
return HasRole(BOT_ROLE_HEAL);
|
||||
case DEVOTION_AURA_1:
|
||||
return _aura != DEVOTIONAURA;
|
||||
case CONCENTRATION_AURA_1:
|
||||
return _aura != CONCENTRATIONAURA;
|
||||
case FIRE_RESISTANCE_AURA_1:
|
||||
return _aura != FIRERESAURA;
|
||||
case FROST_RESISTANCE_AURA_1:
|
||||
return _aura != FROSTRESAURA;
|
||||
case SHADOW_RESISTANCE_AURA_1:
|
||||
return _aura != SHADOWRESAURA;
|
||||
case RETRIBUTION_AURA_1:
|
||||
return _aura != RETRIBUTIONAURA;
|
||||
case CRUSADER_AURA_1:
|
||||
return _aura != CRUSADERAURA;
|
||||
return _myaura != basespell;
|
||||
case PURIFY_1:
|
||||
return !GetSpell(CLEANSE_1);
|
||||
default:
|
||||
@@ -2389,16 +2405,16 @@ public:
|
||||
void FillAbilitiesSpecifics(Player const* player, std::list<std::string> &specList) override
|
||||
{
|
||||
uint32 textId;
|
||||
switch (_aura)
|
||||
switch (_myaura)
|
||||
{
|
||||
case DEVOTIONAURA: textId = BOT_TEXT_DEVOTION; break;
|
||||
case CONCENTRATIONAURA: textId = BOT_TEXT_CONCENTRATION; break;
|
||||
case FIRERESAURA: textId = BOT_TEXT_FIRERESISTANCE; break;
|
||||
case FROSTRESAURA: textId = BOT_TEXT_FROSTRESISTANCE; break;
|
||||
case SHADOWRESAURA: textId = BOT_TEXT_SHADOWRESISTANCE; break;
|
||||
case RETRIBUTIONAURA: textId = BOT_TEXT_RETRIBUTION; break;
|
||||
case CRUSADERAURA: textId = BOT_TEXT_CRUSADER; break;
|
||||
case NOAURA: default: textId = BOT_TEXT_NOAURA; break;
|
||||
case DEVOTION_AURA_1: textId = BOT_TEXT_DEVOTION; break;
|
||||
case CONCENTRATION_AURA_1: textId = BOT_TEXT_CONCENTRATION; break;
|
||||
case FIRE_RESISTANCE_AURA_1: textId = BOT_TEXT_FIRERESISTANCE; break;
|
||||
case FROST_RESISTANCE_AURA_1: textId = BOT_TEXT_FROSTRESISTANCE; break;
|
||||
case SHADOW_RESISTANCE_AURA_1: textId = BOT_TEXT_SHADOWRESISTANCE; break;
|
||||
case RETRIBUTION_AURA_1: textId = BOT_TEXT_RETRIBUTION; break;
|
||||
case CRUSADER_AURA_1: textId = BOT_TEXT_CRUSADER; break;
|
||||
default: textId = BOT_TEXT_NOAURA; break;
|
||||
}
|
||||
specList.push_back(LocalizedNpcText(player, BOT_TEXT_AURA) + ": " + LocalizedNpcText(player, textId));
|
||||
}
|
||||
@@ -2454,7 +2470,7 @@ public:
|
||||
//Timers
|
||||
/*misc*/uint32 checkAuraTimer, checkSealTimer, checkShieldTimer, checkBeaconTimer, avDelayTimer, shieldDelayTimer;
|
||||
//Special
|
||||
/*misc*/uint8 _aura;
|
||||
/*misc*/uint32 _myaura;
|
||||
/*misc*/int32 _sacDamage;
|
||||
|
||||
typedef std::unordered_map<uint32 /*baseId*/, int32 /*amount*/> HealMap;
|
||||
|
||||
@@ -219,6 +219,13 @@ public:
|
||||
{
|
||||
_botclass = BOT_CLASS_ROGUE;
|
||||
|
||||
mhEnchantExpireTimer = 1;
|
||||
ohEnchantExpireTimer = 1;
|
||||
mhEnchant = 0;
|
||||
ohEnchant = 0;
|
||||
needChooseMHEnchant = true;
|
||||
needChooseOHEnchant = true;
|
||||
|
||||
InitUnitFlags();
|
||||
}
|
||||
|
||||
@@ -1735,9 +1742,9 @@ public:
|
||||
return needChooseMHEnchant;
|
||||
case BOTAI_MISC_ENCHANT_IS_AUTO_OH:
|
||||
return needChooseOHEnchant;
|
||||
case BOTAI_MISC_ENCHANT_CAN_EXPIRE_MH:
|
||||
case BOTAI_MISC_ENCHANT_TIMER_MH:
|
||||
return mhEnchantExpireTimer;
|
||||
case BOTAI_MISC_ENCHANT_CAN_EXPIRE_OH:
|
||||
case BOTAI_MISC_ENCHANT_TIMER_OH:
|
||||
return ohEnchantExpireTimer;
|
||||
case BOTAI_MISC_ENCHANT_CURRENT_MH:
|
||||
return mhEnchant;
|
||||
@@ -1770,25 +1777,33 @@ public:
|
||||
case BOTAI_MISC_DAGGER_OFFHAND:
|
||||
isdaggerOH = bool(value);
|
||||
break;
|
||||
case BOTAI_MISC_ENCHANT_CAN_EXPIRE_MH:
|
||||
if (value)
|
||||
mhEnchantExpireTimer = 0;
|
||||
case BOTAI_MISC_ENCHANT_IS_AUTO_MH:
|
||||
needChooseMHEnchant = bool(value);
|
||||
break;
|
||||
case BOTAI_MISC_ENCHANT_CAN_EXPIRE_OH:
|
||||
if (value)
|
||||
ohEnchantExpireTimer = 0;
|
||||
case BOTAI_MISC_ENCHANT_IS_AUTO_OH:
|
||||
needChooseOHEnchant = bool(value);
|
||||
break;
|
||||
case BOTAI_MISC_ENCHANT_TIMER_MH:
|
||||
if (value == 0)
|
||||
mhEnchantExpireTimer = value;
|
||||
break;
|
||||
case BOTAI_MISC_ENCHANT_TIMER_OH:
|
||||
if (value == 0)
|
||||
ohEnchantExpireTimer = value;
|
||||
break;
|
||||
case BOTAI_MISC_ENCHANT_CURRENT_MH:
|
||||
mhEnchant = value;
|
||||
needChooseMHEnchant = value ? false : true;
|
||||
SetAIMiscValue(BOTAI_MISC_ENCHANT_IS_AUTO_MH, value ? false : true);
|
||||
break;
|
||||
case BOTAI_MISC_ENCHANT_CURRENT_OH:
|
||||
ohEnchant = value;
|
||||
needChooseOHEnchant = value ? false : true;
|
||||
SetAIMiscValue(BOTAI_MISC_ENCHANT_IS_AUTO_OH, value ? false : true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
bot_ai::SetAIMiscValue(data, value);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
@@ -1803,11 +1818,6 @@ public:
|
||||
|
||||
DefaultInit();
|
||||
|
||||
mhEnchant = 0;
|
||||
ohEnchant = 0;
|
||||
needChooseMHEnchant = true;
|
||||
needChooseOHEnchant = true;
|
||||
|
||||
//after InitEquips
|
||||
Item const* mh = GetEquips(BOT_SLOT_MAINHAND);
|
||||
Item const* oh = GetEquips(BOT_SLOT_OFFHAND);
|
||||
|
||||
@@ -315,6 +315,13 @@ public:
|
||||
{
|
||||
_botclass = BOT_CLASS_SHAMAN;
|
||||
|
||||
mhEnchantExpireTimer = 1;
|
||||
ohEnchantExpireTimer = 1;
|
||||
mhEnchant = 0;
|
||||
ohEnchant = 0;
|
||||
needChooseMHEnchant = true;
|
||||
needChooseOHEnchant = true;
|
||||
|
||||
InitUnitFlags();
|
||||
}
|
||||
|
||||
@@ -2389,9 +2396,9 @@ public:
|
||||
return needChooseMHEnchant;
|
||||
case BOTAI_MISC_ENCHANT_IS_AUTO_OH:
|
||||
return needChooseOHEnchant;
|
||||
case BOTAI_MISC_ENCHANT_CAN_EXPIRE_MH:
|
||||
case BOTAI_MISC_ENCHANT_TIMER_MH:
|
||||
return mhEnchantExpireTimer;
|
||||
case BOTAI_MISC_ENCHANT_CAN_EXPIRE_OH:
|
||||
case BOTAI_MISC_ENCHANT_TIMER_OH:
|
||||
return ohEnchantExpireTimer;
|
||||
case BOTAI_MISC_ENCHANT_CURRENT_MH:
|
||||
return mhEnchant;
|
||||
@@ -2418,25 +2425,33 @@ public:
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case BOTAI_MISC_ENCHANT_CAN_EXPIRE_MH:
|
||||
if (value)
|
||||
mhEnchantExpireTimer = 0;
|
||||
case BOTAI_MISC_ENCHANT_IS_AUTO_MH:
|
||||
needChooseMHEnchant = bool(value);
|
||||
break;
|
||||
case BOTAI_MISC_ENCHANT_CAN_EXPIRE_OH:
|
||||
if (value)
|
||||
ohEnchantExpireTimer = 0;
|
||||
case BOTAI_MISC_ENCHANT_IS_AUTO_OH:
|
||||
needChooseOHEnchant = bool(value);
|
||||
break;
|
||||
case BOTAI_MISC_ENCHANT_TIMER_MH:
|
||||
if (value == 0)
|
||||
mhEnchantExpireTimer = value;
|
||||
break;
|
||||
case BOTAI_MISC_ENCHANT_TIMER_OH:
|
||||
if (value == 0)
|
||||
ohEnchantExpireTimer = value;
|
||||
break;
|
||||
case BOTAI_MISC_ENCHANT_CURRENT_MH:
|
||||
mhEnchant = value;
|
||||
needChooseMHEnchant = value ? false : true;
|
||||
SetAIMiscValue(BOTAI_MISC_ENCHANT_IS_AUTO_MH, value ? false : true);
|
||||
break;
|
||||
case BOTAI_MISC_ENCHANT_CURRENT_OH:
|
||||
ohEnchant = value;
|
||||
needChooseOHEnchant = value ? false : true;
|
||||
SetAIMiscValue(BOTAI_MISC_ENCHANT_IS_AUTO_OH, value ? false : true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
bot_ai::SetAIMiscValue(data, value);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
@@ -2463,15 +2478,10 @@ public:
|
||||
Earthy = false;
|
||||
maelUseUp = false;
|
||||
|
||||
mhEnchantExpireTimer = 1;
|
||||
ohEnchantExpireTimer = 1;
|
||||
mhEnchantExpireTimer = std::min<uint32>(mhEnchantExpireTimer, 1);
|
||||
ohEnchantExpireTimer = std::min<uint32>(ohEnchantExpireTimer, 1);
|
||||
|
||||
DefaultInit();
|
||||
|
||||
mhEnchant = 0;
|
||||
ohEnchant = 0;
|
||||
needChooseMHEnchant = true;
|
||||
needChooseOHEnchant = true;
|
||||
}
|
||||
|
||||
void ReduceCD(uint32 diff) override
|
||||
|
||||
@@ -226,6 +226,8 @@ public:
|
||||
{
|
||||
_botclass = BOT_CLASS_WARLOCK;
|
||||
|
||||
myPetType = 0;
|
||||
|
||||
InitUnitFlags();
|
||||
}
|
||||
|
||||
@@ -1885,14 +1887,14 @@ public:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
bot_ai::SetAIMiscValue(data, value);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
UnsummonAll(false);
|
||||
|
||||
myPetType = 0;
|
||||
|
||||
fearTimer = 0;
|
||||
banishTimer = 0;
|
||||
unbanishTimer = 0;
|
||||
|
||||
@@ -1907,7 +1907,7 @@ public:
|
||||
OnOwnerDamagedBy(u);
|
||||
}
|
||||
|
||||
void SetAIMiscValue(uint32 data, uint32 /*value*/) override
|
||||
void SetAIMiscValue(uint32 data, uint32 value) override
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
@@ -1920,6 +1920,8 @@ public:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
bot_ai::SetAIMiscValue(data, value);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
|
||||
@@ -133,23 +133,38 @@ enum BotCommonValues
|
||||
GAME_EVENT_WINTER_VEIL = 2,
|
||||
//COMMON FACTIONS
|
||||
FACTION_TEMPLATE_HATES_EVERYTHING_1 = 2150, //faction 966 - Monster spar buddy
|
||||
//COMMON AI MISC VALUES
|
||||
BOTAI_MISC_COMBO_POINTS = 1,
|
||||
BOTAI_MISC_DAGGER_MAINHAND,
|
||||
BOTAI_MISC_DAGGER_OFFHAND,
|
||||
BOTAI_MISC_ENCHANT_IS_AUTO_MH,
|
||||
BOTAI_MISC_ENCHANT_IS_AUTO_OH,
|
||||
BOTAI_MISC_ENCHANT_CAN_EXPIRE_MH,
|
||||
BOTAI_MISC_ENCHANT_CAN_EXPIRE_OH,
|
||||
BOTAI_MISC_ENCHANT_CURRENT_MH,
|
||||
BOTAI_MISC_ENCHANT_CURRENT_OH,
|
||||
//SOUNDS
|
||||
SOUND_FREEZE_IMPACT_WINDWALK = 29,
|
||||
SOUND_AXE_2H_IMPACT_FLESH_CRIT = 158,
|
||||
SOUND_ABSORB_GET_HIT = 3334,
|
||||
SOUND_MISS_WHOOSH_2H = 7081,
|
||||
|
||||
//UNUSED
|
||||
|
||||
//MAX_LOOT_ITEMS = 18 // Client limitation 3.3.5 code confirmed
|
||||
};
|
||||
|
||||
enum BotMiscValues : uint32
|
||||
{
|
||||
//SAVED
|
||||
BOTAI_MISC_ENCHANT_IS_AUTO_MH = 1,
|
||||
BOTAI_MISC_ENCHANT_IS_AUTO_OH = 2,
|
||||
BOTAI_MISC_ENCHANT_TIMER_MH = 3,
|
||||
BOTAI_MISC_ENCHANT_TIMER_OH = 4,
|
||||
BOTAI_MISC_ENCHANT_CURRENT_MH = 5,
|
||||
BOTAI_MISC_ENCHANT_CURRENT_OH = 6,
|
||||
BOTAI_MISC_PET_TYPE = 7,
|
||||
BOTAI_MISC_AURA_TYPE = 8,
|
||||
//INTERNAL
|
||||
BOTAI_MISC_ENCHANT_AVAILABLE_1,
|
||||
BOTAI_MISC_ENCHANT_AVAILABLE_2,
|
||||
BOTAI_MISC_ENCHANT_AVAILABLE_3,
|
||||
BOTAI_MISC_ENCHANT_AVAILABLE_4,
|
||||
BOTAI_MISC_ENCHANT_AVAILABLE_5,
|
||||
BOTAI_MISC_ENCHANT_AVAILABLE_6,
|
||||
BOTAI_MISC_PET_TYPE,
|
||||
BOTAI_MISC_COMBO_POINTS,
|
||||
BOTAI_MISC_DAGGER_MAINHAND,
|
||||
BOTAI_MISC_DAGGER_OFFHAND,
|
||||
BOTAI_MISC_PET_AVAILABLE_1,
|
||||
BOTAI_MISC_PET_AVAILABLE_2,
|
||||
BOTAI_MISC_PET_AVAILABLE_3,
|
||||
@@ -169,15 +184,9 @@ enum BotCommonValues
|
||||
BOTPETAI_MISC_CARRY,
|
||||
BOTPETAI_MISC_CAPACITY,
|
||||
BOTPETAI_MISC_MAX_ATTACKERS,
|
||||
//SOUNDS
|
||||
SOUND_FREEZE_IMPACT_WINDWALK = 29,
|
||||
SOUND_AXE_2H_IMPACT_FLESH_CRIT = 158,
|
||||
SOUND_ABSORB_GET_HIT = 3334,
|
||||
SOUND_MISS_WHOOSH_2H = 7081,
|
||||
|
||||
//UNUSED
|
||||
|
||||
//MAX_LOOT_ITEMS = 18 // Client limitation 3.3.5 code confirmed
|
||||
BOT_MISCVALUE_SAVED_FIRST = BOTAI_MISC_ENCHANT_IS_AUTO_MH,
|
||||
BOT_MISCVALUE_SAVED_LAST = BOTAI_MISC_AURA_TYPE
|
||||
};
|
||||
|
||||
enum BotClasses : uint8
|
||||
|
||||
@@ -848,11 +848,13 @@ void BotDataMgr::LoadNpcBots(bool spawn)
|
||||
BOT_LOG_INFO("server.loading", ">> Bots transmog data is not loaded. Table `characters_npcbot_transmog` is empty!");
|
||||
|
||||
// 0 1 2 3 4 5
|
||||
result = CharacterDatabase.Query("SELECT entry, owner, roles, spec, faction, UNIX_TIMESTAMP(hire_time),"
|
||||
result = CharacterDatabase.Query("SELECT entry, owner, roles, spec, faction, UNIX_TIMESTAMP(hire_time), "
|
||||
// 6 7 8 9 10 11 12 13 14
|
||||
"equipMhEx, equipOhEx, equipRhEx, equipHead, equipShoulders, equipChest, equipWaist, equipLegs, equipFeet,"
|
||||
// 15 16 17 18 19 20 21 22 23 24
|
||||
"equipWrist, equipHands, equipBack, equipBody, equipFinger1, equipFinger2, equipTrinket1, equipTrinket2, equipNeck, spells_disabled FROM characters_npcbot");
|
||||
"equipMhEx, equipOhEx, equipRhEx, equipHead, equipShoulders, equipChest, equipWaist, equipLegs, equipFeet, "
|
||||
// 15 16 17 18 19 20 21 22 23
|
||||
"equipWrist, equipHands, equipBack, equipBody, equipFinger1, equipFinger2, equipTrinket1, equipTrinket2, equipNeck, "
|
||||
// 24 25
|
||||
"spells_disabled, miscvalues FROM characters_npcbot");
|
||||
|
||||
std::vector<uint32> entryList;
|
||||
if (result)
|
||||
@@ -896,6 +898,17 @@ void BotDataMgr::LoadNpcBots(bool spawn)
|
||||
botData->disabled_spells.insert(*(Bcore::StringTo<uint32>(tok[i])));
|
||||
}
|
||||
|
||||
std::string miscvalues_str = field[++index].Get<std::string>();
|
||||
if (!miscvalues_str.empty())
|
||||
{
|
||||
std::vector<std::string_view> tok = Bcore::Tokenize(miscvalues_str, ' ', false);
|
||||
for (std::vector<std::string_view>::size_type i = 0; i != tok.size(); ++i)
|
||||
{
|
||||
std::vector<std::string_view> tok2 = Bcore::Tokenize(tok[i], ':', false);
|
||||
botData->miscvalues.emplace(*(Bcore::StringTo<uint32>(tok2[0])), *(Bcore::StringTo<uint32>(tok2[1])));
|
||||
}
|
||||
}
|
||||
|
||||
entryList.push_back(entry);
|
||||
_botsData[entry] = botData;
|
||||
++datacounter;
|
||||
@@ -2706,6 +2719,20 @@ void BotDataMgr::UpdateNpcBotData(uint32 entry, NpcBotDataUpdateType updateType,
|
||||
CharacterDatabase.Execute(bstmt);
|
||||
break;
|
||||
}
|
||||
case NPCBOT_UPDATE_MISCVALUES:
|
||||
{
|
||||
NpcBotData::MiscValuesContainer const* miscvals = (NpcBotData::MiscValuesContainer const*)(data);
|
||||
std::ostringstream ss;
|
||||
for (NpcBotData::MiscValuesContainer::const_iterator citr = miscvals->cbegin(); citr != miscvals->cend(); ++citr)
|
||||
ss << citr->first << ':' << citr->second << ' ';
|
||||
|
||||
bstmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_NPCBOT_MISCVALUES);
|
||||
//"UPDATE characters_npcbot SET miscvalues = ? WHERE entry = ?", CONNECTION_ASYNCH
|
||||
bstmt->SetData(0, ss.str());
|
||||
bstmt->SetData(1, entry);
|
||||
CharacterDatabase.Execute(bstmt);
|
||||
break;
|
||||
}
|
||||
case NPCBOT_UPDATE_EQUIPS:
|
||||
{
|
||||
Item** items = (Item**)(data);
|
||||
|
||||
@@ -59,6 +59,7 @@ enum NpcBotDataUpdateType
|
||||
NPCBOT_UPDATE_ROLES,
|
||||
NPCBOT_UPDATE_SPEC,
|
||||
NPCBOT_UPDATE_DISABLED_SPELLS,
|
||||
NPCBOT_UPDATE_MISCVALUES,
|
||||
NPCBOT_UPDATE_FACTION,
|
||||
NPCBOT_UPDATE_EQUIPS,
|
||||
NPCBOT_UPDATE_ERASE,
|
||||
@@ -69,6 +70,7 @@ enum NpcBotDataUpdateType
|
||||
struct NpcBotData
|
||||
{
|
||||
typedef std::set<uint32> DisabledSpellsContainer;
|
||||
typedef std::map<uint32, uint32> MiscValuesContainer;
|
||||
|
||||
friend class BotDataMgr;
|
||||
friend struct WanderingBotsGenerator;
|
||||
@@ -80,6 +82,7 @@ public:
|
||||
uint8 spec;
|
||||
uint32 equips[BOT_INVENTORY_SIZE];
|
||||
DisabledSpellsContainer disabled_spells;
|
||||
MiscValuesContainer miscvalues;
|
||||
|
||||
private:
|
||||
explicit NpcBotData(uint32 iroles, uint32 ifaction, uint8 ispec = 1) : owner(0), hire_time(0), roles(iroles), faction(ifaction), spec(ispec)
|
||||
|
||||
Reference in New Issue
Block a user