mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
feat: rndbot teleport, grind, stuck problem etc.
This commit is contained in:
@@ -549,7 +549,8 @@ AiPlayerbot.PvpProhibitedZoneIds = "2255,656,2361,2362,2363,976,35,2268,3425,392
|
|||||||
AiPlayerbot.RandomBotSpellIds = "54197"
|
AiPlayerbot.RandomBotSpellIds = "54197"
|
||||||
|
|
||||||
# Level diff between random bots and nearby creatures for random teleports
|
# Level diff between random bots and nearby creatures for random teleports
|
||||||
AiPlayerbot.RandomBotTeleLevel = 3
|
AiPlayerbot.randomBotTeleLowerLevel = 3
|
||||||
|
AiPlayerbot.randomBotTeleHigerLevel = 1
|
||||||
|
|
||||||
# ID of spell to open lootable chests
|
# ID of spell to open lootable chests
|
||||||
AiPlayerbot.OpenGoSpell = 6477
|
AiPlayerbot.OpenGoSpell = 6477
|
||||||
|
|||||||
@@ -137,7 +137,8 @@ bool PlayerbotAIConfig::Initialize()
|
|||||||
randomBotMinLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotMinLevel", 1);
|
randomBotMinLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotMinLevel", 1);
|
||||||
randomBotMaxLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotMaxLevel", 80);
|
randomBotMaxLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotMaxLevel", 80);
|
||||||
randomBotLoginAtStartup = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotLoginAtStartup", true);
|
randomBotLoginAtStartup = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotLoginAtStartup", true);
|
||||||
randomBotTeleLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotTeleLevel", 5);
|
randomBotTeleLowerLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotTeleLowerLevel", 3);
|
||||||
|
randomBotTeleHigerLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotTeleHigerLevel", 1);
|
||||||
openGoSpell = sConfigMgr->GetOption<int32>("AiPlayerbot.OpenGoSpell", 6477);
|
openGoSpell = sConfigMgr->GetOption<int32>("AiPlayerbot.OpenGoSpell", 6477);
|
||||||
|
|
||||||
randomChangeMultiplier = sConfigMgr->GetOption<float>("AiPlayerbot.RandomChangeMultiplier", 1.0);
|
randomChangeMultiplier = sConfigMgr->GetOption<float>("AiPlayerbot.RandomChangeMultiplier", 1.0);
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ class PlayerbotAIConfig
|
|||||||
bool randomBotJoinBG;
|
bool randomBotJoinBG;
|
||||||
bool randomBotAutoJoinBG;
|
bool randomBotAutoJoinBG;
|
||||||
bool randomBotLoginAtStartup;
|
bool randomBotLoginAtStartup;
|
||||||
uint32 randomBotTeleLevel;
|
uint32 randomBotTeleLowerLevel, randomBotTeleHigerLevel;
|
||||||
bool logInGroupOnly, logValuesPerTick;
|
bool logInGroupOnly, logValuesPerTick;
|
||||||
bool fleeingEnabled;
|
bool fleeingEnabled;
|
||||||
bool summonAtInnkeepersEnabled;
|
bool summonAtInnkeepersEnabled;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "ArenaTeamMgr.h"
|
#include "ArenaTeamMgr.h"
|
||||||
#include "GuildMgr.h"
|
#include "GuildMgr.h"
|
||||||
#include "MapMgr.h"
|
#include "MapMgr.h"
|
||||||
|
#include "PetDefines.h"
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
#include "PerformanceMonitor.h"
|
#include "PerformanceMonitor.h"
|
||||||
#include "PlayerbotDbStore.h"
|
#include "PlayerbotDbStore.h"
|
||||||
@@ -322,6 +323,7 @@ void PlayerbotFactory::Randomize(bool incremental)
|
|||||||
pmo->finish();
|
pmo->finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bot->RemovePet(nullptr, PET_SAVE_AS_CURRENT, true);
|
||||||
if (bot->getLevel() >= 10)
|
if (bot->getLevel() >= 10)
|
||||||
{
|
{
|
||||||
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Pet");
|
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Pet");
|
||||||
@@ -588,37 +590,6 @@ void PlayerbotFactory::InitPet()
|
|||||||
pet->InitTalentForLevel();
|
pet->InitTalentForLevel();
|
||||||
|
|
||||||
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
|
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
|
||||||
// bot->PetSpellInitialize();
|
|
||||||
// if (!pet->Create(guid, bot->GetMap(), bot->GetPhaseMask(), co->Entry, pet_number))
|
|
||||||
// {
|
|
||||||
// delete pet;
|
|
||||||
// pet = nullptr;
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pet->Relocate(bot);
|
|
||||||
// pet->SetOwnerGUID(bot->GetGUID());
|
|
||||||
// pet->SetGuidValue(UNIT_FIELD_CREATEDBY, bot->GetGUID());
|
|
||||||
// pet->SetFaction(bot->GetFaction());
|
|
||||||
// pet->SetLevel(bot->getLevel());
|
|
||||||
// pet->InitStatsForLevel(bot->getLevel());
|
|
||||||
// pet->SetPower(POWER_HAPPINESS, HAPPINESS_LEVEL_SIZE * 2);
|
|
||||||
// pet->GetCharmInfo()->SetPetNumber(sObjectMgr->GeneratePetNumber(), true);
|
|
||||||
// pet->GetMap()->AddToMap(pet->ToCreature());
|
|
||||||
|
|
||||||
// // bot->PetSpellInitialize();
|
|
||||||
|
|
||||||
// bot->InitTamedPet(pet, bot->getLevel(), 0);
|
|
||||||
// pet->InitTalentForLevel();
|
|
||||||
// pet->CastPetAuras(true);
|
|
||||||
// pet->UpdateAllStats();
|
|
||||||
|
|
||||||
// PetStable& petStable = bot->GetOrInitPetStable();
|
|
||||||
// pet->FillPetInfo(&petStable.CurrentPet.emplace());
|
|
||||||
|
|
||||||
// LOG_INFO("playerbots", "Bot {}: assign pet {} ({} level)", bot->GetName().c_str(), co->Entry, bot->getLevel());
|
|
||||||
// pet->SavePetToDB(PET_SAVE_AS_CURRENT);
|
|
||||||
// // bot->PetSpellInitialize();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -634,7 +605,7 @@ void PlayerbotFactory::InitPet()
|
|||||||
{
|
{
|
||||||
LOG_ERROR("playerbots", "Cannot create pet for bot {}", bot->GetName().c_str());
|
LOG_ERROR("playerbots", "Cannot create pet for bot {}", bot->GetName().c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// LOG_INFO("playerbots", "Start make spell auto cast for {} spells. {} already auto casted.", pet->m_spells.size(), pet->GetPetAutoSpellSize());
|
// LOG_INFO("playerbots", "Start make spell auto cast for {} spells. {} already auto casted.", pet->m_spells.size(), pet->GetPetAutoSpellSize());
|
||||||
for (PetSpellMap::const_iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end(); ++itr)
|
for (PetSpellMap::const_iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end(); ++itr)
|
||||||
@@ -1215,6 +1186,9 @@ void PlayerbotFactory::InitEquipment(bool incremental)
|
|||||||
for (ItemTemplateContainer::const_iterator i = itemTemplates->begin(); i != itemTemplates->end(); ++i)
|
for (ItemTemplateContainer::const_iterator i = itemTemplates->begin(); i != itemTemplates->end(); ++i)
|
||||||
{
|
{
|
||||||
uint32 itemId = i->first;
|
uint32 itemId = i->first;
|
||||||
|
if (sRandomItemMgr->IsTestItem(itemId)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
ItemTemplate const* proto = &i->second;
|
ItemTemplate const* proto = &i->second;
|
||||||
if (!proto)
|
if (!proto)
|
||||||
continue;
|
continue;
|
||||||
@@ -1364,7 +1338,6 @@ void PlayerbotFactory::InitSecondEquipmentSet()
|
|||||||
ItemTemplate const* proto = &itr.second;
|
ItemTemplate const* proto = &itr.second;
|
||||||
if (!proto)
|
if (!proto)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!CanEquipItem(proto, desiredQuality))
|
if (!CanEquipItem(proto, desiredQuality))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@@ -946,7 +946,10 @@ void RandomItemMgr::BuildItemInfoCache()
|
|||||||
strstr(proto->Name1.c_str(), "[PH]") ||
|
strstr(proto->Name1.c_str(), "[PH]") ||
|
||||||
strstr(proto->Name1.c_str(), "(OLD)")
|
strstr(proto->Name1.c_str(), "(OLD)")
|
||||||
)
|
)
|
||||||
|
{
|
||||||
|
itemForTest.insert(proto->ItemId);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// skip items with rank/rep requirements
|
// skip items with rank/rep requirements
|
||||||
/*if (proto->RequiredHonorRank > 0 ||
|
/*if (proto->RequiredHonorRank > 0 ||
|
||||||
|
|||||||
@@ -164,8 +164,8 @@ class RandomItemMgr
|
|||||||
float GetItemRarity(uint32 itemId);
|
float GetItemRarity(uint32 itemId);
|
||||||
uint32 GetQuestIdForItem(uint32 itemId);
|
uint32 GetQuestIdForItem(uint32 itemId);
|
||||||
std::vector<uint32> GetQuestIdsForItem(uint32 itemId);
|
std::vector<uint32> GetQuestIdsForItem(uint32 itemId);
|
||||||
|
|
||||||
static bool IsUsedBySkill(ItemTemplate const* proto, uint32 skillId);
|
static bool IsUsedBySkill(ItemTemplate const* proto, uint32 skillId);
|
||||||
|
bool IsTestItem(uint32 itemId) { return itemForTest.find(itemId) != itemForTest.end(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void BuildRandomItemCache();
|
void BuildRandomItemCache();
|
||||||
@@ -195,7 +195,7 @@ class RandomItemMgr
|
|||||||
std::map<std::string, uint32 > weightStatLink;
|
std::map<std::string, uint32 > weightStatLink;
|
||||||
std::map<std::string, uint32 > weightRatingLink;
|
std::map<std::string, uint32 > weightRatingLink;
|
||||||
std::map<uint32, ItemInfoEntry> itemInfoCache;
|
std::map<uint32, ItemInfoEntry> itemInfoCache;
|
||||||
|
std::set<uint32> itemForTest;
|
||||||
static std::set<uint32> itemCache;
|
static std::set<uint32> itemCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -871,6 +871,25 @@ bool RandomPlayerbotMgr::ProcessBot(Player* player)
|
|||||||
|
|
||||||
//if (player->isDead())
|
//if (player->isDead())
|
||||||
//return false;
|
//return false;
|
||||||
|
if (player->isDead())
|
||||||
|
{
|
||||||
|
if (!GetEventValue(bot, "dead"))
|
||||||
|
{
|
||||||
|
uint32 randomTime = urand(sPlayerbotAIConfig->minRandomBotReviveTime, sPlayerbotAIConfig->maxRandomBotReviveTime);
|
||||||
|
LOG_INFO("playerbots", "Mark bot {} as dead, will be revived in {}s.", player->GetName().c_str(), randomTime);
|
||||||
|
SetEventValue(bot, "dead", 1, sPlayerbotAIConfig->maxRandomBotInWorldTime);
|
||||||
|
SetEventValue(bot, "revive", 1, randomTime);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetEventValue(bot, "revive"))
|
||||||
|
{
|
||||||
|
Revive(player);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//GET_PLAYERBOT_AI(player)->GetAiObjectContext()->GetValue<bool>("random bot update")->Set(false);
|
//GET_PLAYERBOT_AI(player)->GetAiObjectContext()->GetValue<bool>("random bot update")->Set(false);
|
||||||
|
|
||||||
@@ -946,17 +965,13 @@ void RandomPlayerbotMgr::Revive(Player* player)
|
|||||||
{
|
{
|
||||||
uint32 bot = player->GetGUID().GetCounter();
|
uint32 bot = player->GetGUID().GetCounter();
|
||||||
|
|
||||||
//LOG_INFO("playerbots", "Bot {} revived", bot);
|
LOG_INFO("playerbots", "Bot {} revived", player->GetName().c_str());
|
||||||
SetEventValue(bot, "dead", 0, 0);
|
SetEventValue(bot, "dead", 0, 0);
|
||||||
SetEventValue(bot, "revive", 0, 0);
|
SetEventValue(bot, "revive", 0, 0);
|
||||||
|
|
||||||
if (player->getDeathState() == CORPSE)
|
|
||||||
RandomTeleport(player);
|
RandomTeleportForLevel(player);
|
||||||
else
|
Refresh(player);
|
||||||
{
|
|
||||||
RandomTeleportForLevel(player);
|
|
||||||
Refresh(player);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector<WorldLocation>& locs, bool hearth)
|
void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector<WorldLocation>& locs, bool hearth)
|
||||||
@@ -985,8 +1000,7 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector<WorldLocation>&
|
|||||||
std::vector<WorldPosition> tlocs;
|
std::vector<WorldPosition> tlocs;
|
||||||
for (auto& loc : locs)
|
for (auto& loc : locs)
|
||||||
tlocs.push_back(WorldPosition(loc));
|
tlocs.push_back(WorldPosition(loc));
|
||||||
// LOG_INFO("playerbots", "Locs {} collected.", tlocs.size());
|
// Do not teleport to maps disabled in config
|
||||||
//Do not teleport to maps disabled in config
|
|
||||||
tlocs.erase(std::remove_if(tlocs.begin(), tlocs.end(), [bot](WorldPosition l)
|
tlocs.erase(std::remove_if(tlocs.begin(), tlocs.end(), [bot](WorldPosition l)
|
||||||
{
|
{
|
||||||
std::vector<uint32>::iterator i = find(sPlayerbotAIConfig->randomBotMaps.begin(), sPlayerbotAIConfig->randomBotMaps.end(), l.getMapId());
|
std::vector<uint32>::iterator i = find(sPlayerbotAIConfig->randomBotMaps.begin(), sPlayerbotAIConfig->randomBotMaps.end(), l.getMapId());
|
||||||
@@ -1031,23 +1045,23 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector<WorldLocation>&
|
|||||||
{
|
{
|
||||||
WorldLocation loc = tlocs[urand(0, tlocs.size() - 1)];
|
WorldLocation loc = tlocs[urand(0, tlocs.size() - 1)];
|
||||||
|
|
||||||
float x = loc.GetPositionX() + (attemtps > 0 ? urand(0, sPlayerbotAIConfig->grindDistance) - sPlayerbotAIConfig->grindDistance / 2 : 0);
|
float x = loc.GetPositionX(); // + (attemtps > 0 ? urand(0, sPlayerbotAIConfig->grindDistance) - sPlayerbotAIConfig->grindDistance / 2 : 0);
|
||||||
float y = loc.GetPositionY() + (attemtps > 0 ? urand(0, sPlayerbotAIConfig->grindDistance) - sPlayerbotAIConfig->grindDistance / 2 : 0);
|
float y = loc.GetPositionY(); // + (attemtps > 0 ? urand(0, sPlayerbotAIConfig->grindDistance) - sPlayerbotAIConfig->grindDistance / 2 : 0);
|
||||||
float z = loc.GetPositionZ();
|
float z = loc.GetPositionZ();
|
||||||
|
|
||||||
Map* map = sMapMgr->FindMap(loc.GetMapId(), 0);
|
Map* map = sMapMgr->FindMap(loc.GetMapId(), 0);
|
||||||
if (!map)
|
if (!map)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
AreaTableEntry const* area = sAreaTableStore.LookupEntry(map->GetAreaId(bot->GetPhaseMask(), x, y, z));
|
AreaTableEntry const* zone = sAreaTableStore.LookupEntry(map->GetZoneId(bot->GetPhaseMask(), x, y, z));
|
||||||
if (!area)
|
if (!zone)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Do not teleport to enemy zones if level is low
|
// Do not teleport to enemy zones if level is low
|
||||||
if (area->team == 4 && bot->GetTeamId() == TEAM_ALLIANCE && bot->getLevel() < 40)
|
if (zone->team == 4 && bot->GetTeamId() == TEAM_ALLIANCE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (area->team == 2 && bot->GetTeamId() == TEAM_HORDE && bot->getLevel() < 40)
|
if (zone->team == 2 && bot->GetTeamId() == TEAM_HORDE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (map->IsInWater(bot->GetPhaseMask(), x, y, z, bot->GetCollisionHeight()))
|
if (map->IsInWater(bot->GetPhaseMask(), x, y, z, bot->GetCollisionHeight()))
|
||||||
@@ -1060,11 +1074,11 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector<WorldLocation>&
|
|||||||
z = 0.05f + ground;
|
z = 0.05f + ground;
|
||||||
|
|
||||||
LOG_INFO("playerbots", "Random teleporting bot {} to {} {},{},{} ({}/{} locations)",
|
LOG_INFO("playerbots", "Random teleporting bot {} to {} {},{},{} ({}/{} locations)",
|
||||||
bot->GetName().c_str(), area->area_name[0], x, y, z, attemtps, tlocs.size());
|
bot->GetName().c_str(), zone->area_name[0], x, y, z, attemtps, tlocs.size());
|
||||||
|
|
||||||
if (hearth)
|
if (hearth)
|
||||||
{
|
{
|
||||||
bot->SetHomebind(loc, area->ID);
|
bot->SetHomebind(loc, zone->ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
bot->GetMotionMaster()->Clear();
|
bot->GetMotionMaster()->Clear();
|
||||||
@@ -1093,66 +1107,66 @@ void RandomPlayerbotMgr::PrepareTeleportCache()
|
|||||||
if (maxLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
|
if (maxLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
|
||||||
maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL);
|
maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL);
|
||||||
|
|
||||||
if (PreparedQueryResult result = PlayerbotsDatabase.Query(PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_TELE_CACHE)))
|
LOG_INFO("playerbots", "Preparing random teleport caches for {} levels...", maxLevel);
|
||||||
{
|
QueryResult results = WorldDatabase.Query(
|
||||||
LOG_INFO("playerbots", "Loading random teleport caches for {} levels...", maxLevel);
|
"WITH GroupedData AS ( "
|
||||||
|
"SELECT "
|
||||||
|
"MIN( c.guid ) guid, "
|
||||||
|
"( "
|
||||||
|
"AVG( t.maxlevel ) + AVG( t.minlevel )) / 2 lvl "
|
||||||
|
"FROM "
|
||||||
|
"creature c "
|
||||||
|
"INNER JOIN creature_template t ON c.id1 = t.entry "
|
||||||
|
"WHERE "
|
||||||
|
"t.npcflag = 0 "
|
||||||
|
"AND t.lootid != 0 "
|
||||||
|
"AND t.unit_flags != 768 "
|
||||||
|
"AND map IN ({}) "
|
||||||
|
"AND t.maxlevel != 1 "
|
||||||
|
"GROUP BY "
|
||||||
|
"map, "
|
||||||
|
"ROUND( position_x / 250 ) * 250, "
|
||||||
|
"ROUND( position_y / 250 ) * 250, "
|
||||||
|
"ROUND( position_z / 5 ) * 5 "
|
||||||
|
"HAVING "
|
||||||
|
"count(*) > 10 "
|
||||||
|
"AND MAX( t.maxlevel ) - MIN( t.minlevel ) < 5 "
|
||||||
|
"ORDER BY "
|
||||||
|
"lvl "
|
||||||
|
") "
|
||||||
|
"SELECT "
|
||||||
|
"map, "
|
||||||
|
"position_x, "
|
||||||
|
"position_y, "
|
||||||
|
"position_z, "
|
||||||
|
"t.maxlevel "
|
||||||
|
"FROM "
|
||||||
|
"GroupedData g "
|
||||||
|
"INNER JOIN creature c ON g.guid = c.guid "
|
||||||
|
"INNER JOIN creature_template t on c.id1 = t.entry;", sPlayerbotAIConfig->randomBotMapsAsString.c_str());
|
||||||
|
|
||||||
|
if (results)
|
||||||
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
Field* fields = result->Fetch();
|
Field* fields = results->Fetch();
|
||||||
uint32 mapId = fields[0].Get<uint32>();
|
uint16 mapId = fields[0].Get<uint16>();
|
||||||
float x = fields[1].Get<float>();
|
float x = fields[1].Get<float>();
|
||||||
float y = fields[2].Get<float>();
|
float y = fields[2].Get<float>();
|
||||||
float z = fields[3].Get<float>();
|
float z = fields[3].Get<float>();
|
||||||
uint8 level = fields[4].Get<uint8>();
|
uint32 avg_level = fields[4].Get<uint32>();
|
||||||
|
|
||||||
WorldLocation loc(mapId, x, y, z, 0);
|
WorldLocation loc(mapId, x, y, z, 0);
|
||||||
locsPerLevelCache[level].push_back(std::move(loc));
|
LOG_INFO("playerbots", "get location {} {} {} {}, level: {}", mapId, x, y, z, avg_level);
|
||||||
}
|
for (int32 level = (int32)avg_level - (int32)sPlayerbotAIConfig->randomBotTeleHigerLevel; level <= (int32)avg_level + (int32)sPlayerbotAIConfig->randomBotTeleLowerLevel; level++) {
|
||||||
while (result->NextRow());
|
if (level < 1 || level > maxLevel) {
|
||||||
}
|
continue;
|
||||||
else
|
}
|
||||||
{
|
locsPerLevelCache[(uint8)level].push_back(loc);
|
||||||
LOG_INFO("playerbots", "Preparing random teleport caches for {} levels...", maxLevel);
|
|
||||||
|
|
||||||
for (uint8 level = 1; level <= maxLevel; level++)
|
|
||||||
{
|
|
||||||
QueryResult results = WorldDatabase.Query("SELECT map, position_x, position_y, position_z "
|
|
||||||
"FROM (SELECT map, position_x, position_y, position_z, AVG(t.maxlevel), AVG(t.minlevel), {} - (AVG(t.maxlevel) + AVG(t.minlevel)) / 2 delta "
|
|
||||||
"FROM creature c INNER JOIN creature_template t ON c.id1 = t.entry WHERE t.npcflag = 0 AND t.lootid != 0 AND t.unit_flags != 768 GROUP BY t.entry, map, position_x, position_y, position_z HAVING COUNT(*) > 1) q "
|
|
||||||
"WHERE delta >= 0 AND delta <= {} AND map IN ('{}') AND NOT EXISTS (SELECT map, position_x, position_y, position_z FROM "
|
|
||||||
"(SELECT map, c.position_x, c.position_y, c.position_z, AVG(t.maxlevel), AVG(t.minlevel), {} - (AVG(t.maxlevel) + AVG(t.minlevel)) / 2 delta "
|
|
||||||
"FROM creature c INNER JOIN creature_template t ON c.id1 = t.entry WHERE t.npcflag = 0 AND t.lootid != 0 GROUP BY t.entry, map, position_x, position_y, position_z) q1 WHERE abs(delta) > {} and q1.map = q.map AND SQRT("
|
|
||||||
"(q1.position_x - q.position_x) * (q1.position_x - q.position_x) + (q1.position_y - q.position_y) * (q1.position_y - q.position_y) + "
|
|
||||||
"(q1.position_z - q.position_z) * (q1.position_z - q.position_z)) < {})", level, sPlayerbotAIConfig->randomBotTeleLevel, sPlayerbotAIConfig->randomBotMapsAsString.c_str(),
|
|
||||||
level, sPlayerbotAIConfig->randomBotTeleLevel, (uint32) sPlayerbotAIConfig->sightDistance);
|
|
||||||
if (results)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
Field* fields = results->Fetch();
|
|
||||||
uint16 mapId = fields[0].Get<uint16>();
|
|
||||||
float x = fields[1].Get<float>();
|
|
||||||
float y = fields[2].Get<float>();
|
|
||||||
float z = fields[3].Get<float>();
|
|
||||||
WorldLocation loc(mapId, x, y, z, 0);
|
|
||||||
locsPerLevelCache[level].push_back(std::move(loc));
|
|
||||||
|
|
||||||
PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_INS_TELE_CACHE);
|
|
||||||
stmt->SetData(0, level);
|
|
||||||
stmt->SetData(1, mapId);
|
|
||||||
stmt->SetData(2, x);
|
|
||||||
stmt->SetData(3, y);
|
|
||||||
stmt->SetData(4, z);
|
|
||||||
PlayerbotsDatabase.Execute(stmt);
|
|
||||||
} while (results->NextRow());
|
|
||||||
}
|
}
|
||||||
}
|
} while (results->NextRow());
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO("playerbots", "Preparing RPG teleport caches for {} factions...", sFactionTemplateStore.GetNumRows());
|
LOG_INFO("playerbots", "Preparing RPG teleport caches for {} factions...", sFactionTemplateStore.GetNumRows());
|
||||||
|
results = WorldDatabase.Query("SELECT map, position_x, position_y, position_z, r.race, r.minl, r.maxl FROM creature c INNER JOIN playerbots_rpg_races r ON c.id1 = r.entry "
|
||||||
QueryResult results = WorldDatabase.Query("SELECT map, position_x, position_y, position_z, r.race, r.minl, r.maxl FROM creature c INNER JOIN playerbots_rpg_races r ON c.id1 = r.entry "
|
|
||||||
"WHERE r.race < 15");
|
"WHERE r.race < 15");
|
||||||
if (results)
|
if (results)
|
||||||
{
|
{
|
||||||
@@ -1190,9 +1204,8 @@ void RandomPlayerbotMgr::RandomTeleportForLevel(Player* bot)
|
|||||||
|
|
||||||
uint32 level = bot->getLevel();
|
uint32 level = bot->getLevel();
|
||||||
uint8 race = bot->getRace();
|
uint8 race = bot->getRace();
|
||||||
LOG_INFO("playerbots", "Random teleporting bot {} for level ({} locations available)", bot->GetName().c_str(), rpgLocsCacheLevel[race][level].size());
|
LOG_INFO("playerbots", "Random teleporting bot {} for level {} ({} locations available)", bot->GetName().c_str(), bot->GetLevel(), locsPerLevelCache[level].size());
|
||||||
RandomTeleport(bot, rpgLocsCacheLevel[race][level]);
|
RandomTeleport(bot, locsPerLevelCache[level]);
|
||||||
// Refresh(bot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RandomPlayerbotMgr::RandomTeleport(Player* bot)
|
void RandomPlayerbotMgr::RandomTeleport(Player* bot)
|
||||||
@@ -1248,7 +1261,7 @@ void RandomPlayerbotMgr::Randomize(Player* bot)
|
|||||||
else {
|
else {
|
||||||
RandomizeFirst(bot);
|
RandomizeFirst(bot);
|
||||||
}
|
}
|
||||||
//RandomTeleportForRpg(bot);
|
RandomTeleportForLevel(bot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RandomPlayerbotMgr::IncreaseLevel(Player* bot)
|
void RandomPlayerbotMgr::IncreaseLevel(Player* bot)
|
||||||
@@ -1296,7 +1309,7 @@ void RandomPlayerbotMgr::RandomizeFirst(Player* bot)
|
|||||||
level = maxLevel;
|
level = maxLevel;
|
||||||
|
|
||||||
if (bot->getClass() == CLASS_DEATH_KNIGHT)
|
if (bot->getClass() == CLASS_DEATH_KNIGHT)
|
||||||
level = urand(sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL), std::max(sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL), maxLevel));
|
level = urand(std::max(sPlayerbotAIConfig->randomBotMinLevel, sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL)), std::max(sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL), maxLevel));
|
||||||
}
|
}
|
||||||
|
|
||||||
SetValue(bot, "level", level);
|
SetValue(bot, "level", level);
|
||||||
@@ -1710,11 +1723,11 @@ bool RandomPlayerbotMgr::HandlePlayerbotConsoleCommand(ChatHandler* handler, cha
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> messages = sRandomPlayerbotMgr->HandlePlayerbotCommand(args);
|
// std::vector<std::string> messages = sRandomPlayerbotMgr->HandlePlayerbotCommand(args);
|
||||||
for (std::vector<std::string>::iterator i = messages.begin(); i != messages.end(); ++i)
|
// for (std::vector<std::string>::iterator i = messages.begin(); i != messages.end(); ++i)
|
||||||
{
|
// {
|
||||||
LOG_INFO("playerbots", "{}", i->c_str());
|
// LOG_INFO("playerbots", "{}", i->c_str());
|
||||||
}
|
// }
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2219,8 +2232,9 @@ void RandomPlayerbotMgr::ChangeStrategyOnce(Player* player)
|
|||||||
void RandomPlayerbotMgr::RandomTeleportForRpg(Player* bot)
|
void RandomPlayerbotMgr::RandomTeleportForRpg(Player* bot)
|
||||||
{
|
{
|
||||||
uint32 race = bot->getRace();
|
uint32 race = bot->getRace();
|
||||||
LOG_INFO("playerbots", "Random teleporting bot {} for RPG ({} locations available)", bot->GetName().c_str(), rpgLocsCache[race].size());
|
uint32 level = bot->GetLevel();
|
||||||
RandomTeleport(bot, rpgLocsCache[race], true);
|
LOG_INFO("playerbots", "Random teleporting bot {} for RPG ({} locations available)", bot->GetName().c_str(), rpgLocsCacheLevel[race].size());
|
||||||
|
RandomTeleport(bot, rpgLocsCacheLevel[race][level], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RandomPlayerbotMgr::Remove(Player* bot)
|
void RandomPlayerbotMgr::Remove(Player* bot)
|
||||||
@@ -2291,14 +2305,14 @@ ObjectGuid const RandomPlayerbotMgr::GetBattleMasterGUID(Player* bot, Battlegrou
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
AreaTableEntry const* area = sAreaTableStore.LookupEntry(Bm->GetAreaId());
|
AreaTableEntry const* zone = sAreaTableStore.LookupEntry(Bm->GetZoneId());
|
||||||
if (!area)
|
if (!zone)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (area->team == 4 && bot->GetTeamId() == TEAM_ALLIANCE)
|
if (zone->team == 4 && bot->GetTeamId() == TEAM_ALLIANCE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (area->team == 2 && bot->GetTeamId() == TEAM_HORDE)
|
if (zone->team == 2 && bot->GetTeamId() == TEAM_HORDE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (Bm->getDeathState() == DEAD)
|
if (Bm->getDeathState() == DEAD)
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ class RandomPlayerbotMgr : public PlayerbotHolder
|
|||||||
std::vector<Player*> players;
|
std::vector<Player*> players;
|
||||||
uint32 processTicks;
|
uint32 processTicks;
|
||||||
std::map<uint8, std::vector<WorldLocation>> locsPerLevelCache;
|
std::map<uint8, std::vector<WorldLocation>> locsPerLevelCache;
|
||||||
std::map<uint32, std::vector<WorldLocation>> rpgLocsCache;
|
// std::map<uint32, std::vector<WorldLocation>> rpgLocsCache;
|
||||||
std::map<uint32, std::map<uint32, std::vector<WorldLocation>>> rpgLocsCacheLevel;
|
std::map<uint32, std::map<uint32, std::vector<WorldLocation>>> rpgLocsCacheLevel;
|
||||||
std::map<TeamId, std::map<BattlegroundTypeId, std::vector<uint32>>> BattleMastersCache;
|
std::map<TeamId, std::map<BattlegroundTypeId, std::vector<uint32>>> BattleMastersCache;
|
||||||
std::map<uint32, std::map<std::string, CachedEvent>> eventCache;
|
std::map<uint32, std::map<std::string, CachedEvent>> eventCache;
|
||||||
|
|||||||
@@ -33,9 +33,12 @@ bool AttackAnythingAction::isUseful()
|
|||||||
if (!AI_VALUE(bool, "can move around"))
|
if (!AI_VALUE(bool, "can move around"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (context->GetValue<TravelTarget*>("travel target")->Get()->isTraveling() && ChooseRpgTargetAction::isFollowValid(bot, *context->GetValue<TravelTarget*>("travel target")->Get()->getPosition())) //Bot is traveling
|
if (context->GetValue<TravelTarget*>("travel target")->Get()->isTraveling() &&
|
||||||
|
ChooseRpgTargetAction::isFollowValid(bot, *context->GetValue<TravelTarget*>("travel target")->Get()->getPosition())) //Bot is traveling
|
||||||
return false;
|
return false;
|
||||||
|
if (bot->IsInCombat()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
Unit* target = GetTarget();
|
Unit* target = GetTarget();
|
||||||
|
|
||||||
if (!target)
|
if (!target)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ bool FollowAction::Execute(Event event)
|
|||||||
if (Formation::IsNullLocation(loc) || loc.GetMapId() == -1)
|
if (Formation::IsNullLocation(loc) || loc.GetMapId() == -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
moved = MoveTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ() + 2.0f);
|
moved = MoveTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Pet* pet = bot->GetPet())
|
if (Pet* pet = bot->GetPet())
|
||||||
@@ -33,11 +33,14 @@ bool FollowAction::Execute(Event event)
|
|||||||
if (CreatureAI* creatureAI = ((Creature*)pet)->AI())
|
if (CreatureAI* creatureAI = ((Creature*)pet)->AI())
|
||||||
{
|
{
|
||||||
pet->SetReactState(REACT_PASSIVE);
|
pet->SetReactState(REACT_PASSIVE);
|
||||||
pet->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW);
|
pet->GetCharmInfo()->SetIsCommandFollow(true);
|
||||||
pet->GetCharmInfo()->SetIsFollowing(true);
|
|
||||||
pet->AttackStop();
|
|
||||||
pet->GetCharmInfo()->IsReturning();
|
pet->GetCharmInfo()->IsReturning();
|
||||||
pet->GetMotionMaster()->MoveFollow(bot, PET_FOLLOW_DIST, pet->GetFollowAngle());
|
pet->GetMotionMaster()->MoveFollow(bot, PET_FOLLOW_DIST, pet->GetFollowAngle());
|
||||||
|
// pet->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW);
|
||||||
|
// pet->GetCharmInfo()->SetIsFollowing(true);
|
||||||
|
// pet->AttackStop();
|
||||||
|
// pet->GetCharmInfo()->IsReturning();
|
||||||
|
// pet->GetMotionMaster()->MoveFollow(bot, PET_FOLLOW_DIST, pet->GetFollowAngle());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//if (moved)
|
//if (moved)
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
|
|
||||||
#include "MovementActions.h"
|
#include "MovementActions.h"
|
||||||
#include "MovementGenerator.h"
|
#include "MovementGenerator.h"
|
||||||
|
#include "ObjectGuid.h"
|
||||||
#include "PlayerbotAIConfig.h"
|
#include "PlayerbotAIConfig.h"
|
||||||
|
#include "SharedDefines.h"
|
||||||
#include "TargetedMovementGenerator.h"
|
#include "TargetedMovementGenerator.h"
|
||||||
#include "Event.h"
|
#include "Event.h"
|
||||||
#include "LastMovementValue.h"
|
#include "LastMovementValue.h"
|
||||||
@@ -15,6 +17,7 @@
|
|||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
#include "ServerFacade.h"
|
#include "ServerFacade.h"
|
||||||
#include "Transport.h"
|
#include "Transport.h"
|
||||||
|
#include "Unit.h"
|
||||||
#include "Vehicle.h"
|
#include "Vehicle.h"
|
||||||
#include "WaypointMovementGenerator.h"
|
#include "WaypointMovementGenerator.h"
|
||||||
|
|
||||||
@@ -128,10 +131,17 @@ bool MovementAction::MoveToLOS(WorldObject* target, bool ranged)
|
|||||||
|
|
||||||
bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, bool react)
|
bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, bool react)
|
||||||
{
|
{
|
||||||
if (!IsMovingAllowed(mapId, x, y, z))
|
if (!IsMovingAllowed(mapId, x, y, z)) {
|
||||||
return false;
|
return false;
|
||||||
bot->UpdateGroundPositionZ(x, y, z);
|
}
|
||||||
|
// if (bot->HasUnitMovementFlag(MOVEMENTFLAG_FALLING | MOVEMENTFLAG_FALLING_FAR)) {
|
||||||
|
// bot->Yell("I'm falling!", LANG_UNIVERSAL);
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// bot->UpdateGroundPositionZ(x, y, z);
|
||||||
|
z += 15.0f;
|
||||||
|
bot->UpdateAllowedPositionZ(x, y, z);
|
||||||
|
z += 0.5f;
|
||||||
float distance = bot->GetDistance2d(x, y);
|
float distance = bot->GetDistance2d(x, y);
|
||||||
if (distance > sPlayerbotAIConfig->contactDistance)
|
if (distance > sPlayerbotAIConfig->contactDistance)
|
||||||
{
|
{
|
||||||
@@ -159,8 +169,8 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
|
|||||||
return false;
|
return false;
|
||||||
// UpdateMovementState();
|
// UpdateMovementState();
|
||||||
// // LOG_DEBUG("playerbots", "IsMovingAllowed {}", IsMovingAllowed());
|
// // LOG_DEBUG("playerbots", "IsMovingAllowed {}", IsMovingAllowed());
|
||||||
// if (!IsMovingAllowed())
|
// bot->AddUnitMovementFlag()
|
||||||
// return false;
|
|
||||||
|
|
||||||
// bool isVehicle = false;
|
// bool isVehicle = false;
|
||||||
// Unit* mover = bot;
|
// Unit* mover = bot;
|
||||||
@@ -663,7 +673,7 @@ bool MovementAction::MoveTo(Unit* target, float distance)
|
|||||||
|
|
||||||
float dx = cos(angle) * needToGo + bx;
|
float dx = cos(angle) * needToGo + bx;
|
||||||
float dy = sin(angle) * needToGo + by;
|
float dy = sin(angle) * needToGo + by;
|
||||||
|
float dz = bz + (tz - bz) * (needToGo / distanceToTarget); // calc accurate z postion to avoid stuck
|
||||||
return MoveTo(target->GetMapId(), dx, dy, tz);
|
return MoveTo(target->GetMapId(), dx, dy, tz);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1265,9 +1275,7 @@ bool FleeWithPetAction::Execute(Event event)
|
|||||||
if (CreatureAI* creatureAI = ((Creature*)pet)->AI())
|
if (CreatureAI* creatureAI = ((Creature*)pet)->AI())
|
||||||
{
|
{
|
||||||
pet->SetReactState(REACT_PASSIVE);
|
pet->SetReactState(REACT_PASSIVE);
|
||||||
pet->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW);
|
pet->GetCharmInfo()->SetIsCommandFollow(true);
|
||||||
pet->GetCharmInfo()->SetIsFollowing(true);
|
|
||||||
pet->AttackStop();
|
|
||||||
pet->GetCharmInfo()->IsReturning();
|
pet->GetCharmInfo()->IsReturning();
|
||||||
pet->GetMotionMaster()->MoveFollow(bot, PET_FOLLOW_DIST, pet->GetFollowAngle());
|
pet->GetMotionMaster()->MoveFollow(bot, PET_FOLLOW_DIST, pet->GetFollowAngle());
|
||||||
}
|
}
|
||||||
@@ -1384,17 +1392,27 @@ bool MoveOutOfCollisionAction::isUseful()
|
|||||||
|
|
||||||
bool MoveRandomAction::Execute(Event event)
|
bool MoveRandomAction::Execute(Event event)
|
||||||
{
|
{
|
||||||
//uint32 randnum = bot->GetGUID().GetCounter(); // Semi-random but fixed number for each bot.
|
float distance = sPlayerbotAIConfig->tooCloseDistance + sPlayerbotAIConfig->grindDistance * urand(3, 10) / 10.0f;
|
||||||
//uint32 cycle = floor(getMSTime() / (1000 * 60)); // Semi-random number adds 1 each minute.
|
|
||||||
|
|
||||||
//randnum = ((randnum + cycle) % 1000) + 1;
|
Map* map = bot->GetMap();
|
||||||
|
for (int i = 0; i < 10; ++i)
|
||||||
|
{
|
||||||
|
float x = bot->GetPositionX();
|
||||||
|
float y = bot->GetPositionY();
|
||||||
|
float z = bot->GetPositionZ();
|
||||||
|
x += urand(0, distance) - distance / 2;
|
||||||
|
y += urand(0, distance) - distance / 2;
|
||||||
|
bot->UpdateGroundPositionZ(x, y, z);
|
||||||
|
|
||||||
uint32 randnum = urand(1, 2000);
|
if (map->IsInWater(bot->GetPhaseMask(), x, y, z, bot->GetCollisionHeight()))
|
||||||
|
continue;
|
||||||
|
|
||||||
float angle = M_PI * (float)randnum / 1000; //urand(1, 1000);
|
bool moved = MoveTo(bot->GetMapId(), x, y, z);
|
||||||
float distance = urand(20, 200);
|
if (moved)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return MoveTo(bot->GetMapId(), bot->GetPositionX() + cos(angle) * distance, bot->GetPositionY() + sin(angle) * distance, bot->GetPositionZ());
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MoveRandomAction::isUseful()
|
bool MoveRandomAction::isUseful()
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ bool DrinkAction::Execute(Event event)
|
|||||||
if (sPlayerbotAIConfig->freeFood)
|
if (sPlayerbotAIConfig->freeFood)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (bot->IsNonMeleeSpellCast(true))
|
// if (bot->IsNonMeleeSpellCast(true))
|
||||||
return false;
|
// return false;
|
||||||
|
|
||||||
bot->ClearUnitState(UNIT_STATE_CHASE);
|
bot->ClearUnitState(UNIT_STATE_CHASE);
|
||||||
bot->ClearUnitState(UNIT_STATE_FOLLOW);
|
bot->ClearUnitState(UNIT_STATE_FOLLOW);
|
||||||
@@ -70,8 +70,8 @@ bool EatAction::Execute(Event event)
|
|||||||
|
|
||||||
if (sPlayerbotAIConfig->freeFood)
|
if (sPlayerbotAIConfig->freeFood)
|
||||||
{
|
{
|
||||||
if (bot->IsNonMeleeSpellCast(true))
|
// if (bot->IsNonMeleeSpellCast(true))
|
||||||
return false;
|
// return false;
|
||||||
|
|
||||||
bot->ClearUnitState(UNIT_STATE_CHASE);
|
bot->ClearUnitState(UNIT_STATE_CHASE);
|
||||||
bot->ClearUnitState(UNIT_STATE_FOLLOW);
|
bot->ClearUnitState(UNIT_STATE_FOLLOW);
|
||||||
@@ -107,7 +107,7 @@ bool EatAction::Execute(Event event)
|
|||||||
|
|
||||||
bool EatAction::isUseful()
|
bool EatAction::isUseful()
|
||||||
{
|
{
|
||||||
return UseItemAction::isUseful() && AI_VALUE2(uint8, "health", "self target") < sPlayerbotAIConfig->lowHealth;
|
return UseItemAction::isUseful() && AI_VALUE2(uint8, "health", "self target") < 85;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EatAction::isPossible()
|
bool EatAction::isPossible()
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "MapMgr.h"
|
#include "MapMgr.h"
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
#include "PlayerbotFactory.h"
|
#include "PlayerbotFactory.h"
|
||||||
|
#include "RandomPlayerbotMgr.h"
|
||||||
#include "ServerFacade.h"
|
#include "ServerFacade.h"
|
||||||
|
|
||||||
bool ReviveFromCorpseAction::Execute(Event event)
|
bool ReviveFromCorpseAction::Execute(Event event)
|
||||||
@@ -89,10 +90,11 @@ bool FindCorpseAction::Execute(Event event)
|
|||||||
{
|
{
|
||||||
if (dCount >= 5)
|
if (dCount >= 5)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("playerbots", "Bot {} {}:{} <{}>: died too many times and was sent to an inn",
|
LOG_INFO("playerbots", "Bot {} {}:{} <{}>: died too many times, was revived and teleported",
|
||||||
bot->GetGUID().ToString().c_str(), bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->getLevel(), bot->GetName().c_str());
|
bot->GetGUID().ToString().c_str(), bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->getLevel(), bot->GetName().c_str());
|
||||||
context->GetValue<uint32>("death count")->Set(0);
|
context->GetValue<uint32>("death count")->Set(0);
|
||||||
sRandomPlayerbotMgr->RandomTeleportForLevel(bot);
|
// sRandomPlayerbotMgr->RandomTeleportForLevel(bot);
|
||||||
|
sRandomPlayerbotMgr->Revive(bot);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ NextAction** GrindingStrategy::getDefaultActions()
|
|||||||
|
|
||||||
void GrindingStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
void GrindingStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||||
{
|
{
|
||||||
|
triggers.push_back(new TriggerNode("medium mana", NextAction::array(0, new NextAction("drink", 7.0f), nullptr)));
|
||||||
|
triggers.push_back(new TriggerNode("medium health", NextAction::array(0, new NextAction("food", 6.0f), nullptr)));
|
||||||
triggers.push_back(new TriggerNode("no target", NextAction::array(0, new NextAction("attack anything", 5.0f), nullptr)));
|
triggers.push_back(new TriggerNode("no target", NextAction::array(0, new NextAction("attack anything", 5.0f), nullptr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Arrow.h"
|
#include "Arrow.h"
|
||||||
|
#include "Map.h"
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
|
|
||||||
WorldLocation ArrowFormation::GetLocationInternal()
|
WorldLocation ArrowFormation::GetLocationInternal()
|
||||||
@@ -47,8 +48,8 @@ WorldLocation ArrowFormation::GetLocationInternal()
|
|||||||
float ground = master->GetMap()->GetHeight(x, y, z + 0.5f);
|
float ground = master->GetMap()->GetHeight(x, y, z + 0.5f);
|
||||||
if (ground <= INVALID_HEIGHT)
|
if (ground <= INVALID_HEIGHT)
|
||||||
return Formation::NullLocation;
|
return Formation::NullLocation;
|
||||||
|
// master->UpdateGroundPositionZ(x, y, z);
|
||||||
return WorldLocation(master->GetMapId(), x, y, 0.05f + ground);
|
return WorldLocation(master->GetMapId(), x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArrowFormation::Build()
|
void ArrowFormation::Build()
|
||||||
|
|||||||
Reference in New Issue
Block a user