diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 0f2fe785..45b98147 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -549,7 +549,8 @@ AiPlayerbot.PvpProhibitedZoneIds = "2255,656,2361,2362,2363,976,35,2268,3425,392 AiPlayerbot.RandomBotSpellIds = "54197" # 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 AiPlayerbot.OpenGoSpell = 6477 diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index 4b11969e..02d565c7 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -137,7 +137,8 @@ bool PlayerbotAIConfig::Initialize() randomBotMinLevel = sConfigMgr->GetOption("AiPlayerbot.RandomBotMinLevel", 1); randomBotMaxLevel = sConfigMgr->GetOption("AiPlayerbot.RandomBotMaxLevel", 80); randomBotLoginAtStartup = sConfigMgr->GetOption("AiPlayerbot.RandomBotLoginAtStartup", true); - randomBotTeleLevel = sConfigMgr->GetOption("AiPlayerbot.RandomBotTeleLevel", 5); + randomBotTeleLowerLevel = sConfigMgr->GetOption("AiPlayerbot.RandomBotTeleLowerLevel", 3); + randomBotTeleHigerLevel = sConfigMgr->GetOption("AiPlayerbot.RandomBotTeleHigerLevel", 1); openGoSpell = sConfigMgr->GetOption("AiPlayerbot.OpenGoSpell", 6477); randomChangeMultiplier = sConfigMgr->GetOption("AiPlayerbot.RandomChangeMultiplier", 1.0); diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index 73971eec..57639f76 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -76,7 +76,7 @@ class PlayerbotAIConfig bool randomBotJoinBG; bool randomBotAutoJoinBG; bool randomBotLoginAtStartup; - uint32 randomBotTeleLevel; + uint32 randomBotTeleLowerLevel, randomBotTeleHigerLevel; bool logInGroupOnly, logValuesPerTick; bool fleeingEnabled; bool summonAtInnkeepersEnabled; diff --git a/src/PlayerbotFactory.cpp b/src/PlayerbotFactory.cpp index b2dd86fc..1b7d0e47 100644 --- a/src/PlayerbotFactory.cpp +++ b/src/PlayerbotFactory.cpp @@ -8,6 +8,7 @@ #include "ArenaTeamMgr.h" #include "GuildMgr.h" #include "MapMgr.h" +#include "PetDefines.h" #include "Playerbots.h" #include "PerformanceMonitor.h" #include "PlayerbotDbStore.h" @@ -322,6 +323,7 @@ void PlayerbotFactory::Randomize(bool incremental) pmo->finish(); } + bot->RemovePet(nullptr, PET_SAVE_AS_CURRENT, true); if (bot->getLevel() >= 10) { pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Pet"); @@ -588,37 +590,6 @@ void PlayerbotFactory::InitPet() pet->InitTalentForLevel(); 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; } } @@ -634,7 +605,7 @@ void PlayerbotFactory::InitPet() { LOG_ERROR("playerbots", "Cannot create pet for bot {}", bot->GetName().c_str()); return; - } +} // 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) @@ -1215,6 +1186,9 @@ void PlayerbotFactory::InitEquipment(bool incremental) for (ItemTemplateContainer::const_iterator i = itemTemplates->begin(); i != itemTemplates->end(); ++i) { uint32 itemId = i->first; + if (sRandomItemMgr->IsTestItem(itemId)) { + continue; + } ItemTemplate const* proto = &i->second; if (!proto) continue; @@ -1364,7 +1338,6 @@ void PlayerbotFactory::InitSecondEquipmentSet() ItemTemplate const* proto = &itr.second; if (!proto) continue; - if (!CanEquipItem(proto, desiredQuality)) continue; diff --git a/src/RandomItemMgr.cpp b/src/RandomItemMgr.cpp index 31f8a3e9..7ca5ff4e 100644 --- a/src/RandomItemMgr.cpp +++ b/src/RandomItemMgr.cpp @@ -945,8 +945,11 @@ void RandomItemMgr::BuildItemInfoCache() strstr(proto->Name1.c_str(), "Monster ") || strstr(proto->Name1.c_str(), "[PH]") || strstr(proto->Name1.c_str(), "(OLD)") - ) + ) + { + itemForTest.insert(proto->ItemId); continue; + } // skip items with rank/rep requirements /*if (proto->RequiredHonorRank > 0 || diff --git a/src/RandomItemMgr.h b/src/RandomItemMgr.h index 3d2e2e44..11b944a5 100644 --- a/src/RandomItemMgr.h +++ b/src/RandomItemMgr.h @@ -164,8 +164,8 @@ class RandomItemMgr float GetItemRarity(uint32 itemId); uint32 GetQuestIdForItem(uint32 itemId); std::vector GetQuestIdsForItem(uint32 itemId); - static bool IsUsedBySkill(ItemTemplate const* proto, uint32 skillId); + bool IsTestItem(uint32 itemId) { return itemForTest.find(itemId) != itemForTest.end(); } private: void BuildRandomItemCache(); @@ -195,7 +195,7 @@ class RandomItemMgr std::map weightStatLink; std::map weightRatingLink; std::map itemInfoCache; - + std::set itemForTest; static std::set itemCache; }; diff --git a/src/RandomPlayerbotMgr.cpp b/src/RandomPlayerbotMgr.cpp index e4b33754..f448e6ea 100644 --- a/src/RandomPlayerbotMgr.cpp +++ b/src/RandomPlayerbotMgr.cpp @@ -871,6 +871,25 @@ bool RandomPlayerbotMgr::ProcessBot(Player* player) //if (player->isDead()) //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("random bot update")->Set(false); @@ -946,17 +965,13 @@ void RandomPlayerbotMgr::Revive(Player* player) { 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, "revive", 0, 0); - if (player->getDeathState() == CORPSE) - RandomTeleport(player); - else - { - RandomTeleportForLevel(player); - Refresh(player); - } + + RandomTeleportForLevel(player); + Refresh(player); } void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector& locs, bool hearth) @@ -985,8 +1000,7 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector& std::vector tlocs; for (auto& loc : locs) 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) { std::vector::iterator i = find(sPlayerbotAIConfig->randomBotMaps.begin(), sPlayerbotAIConfig->randomBotMaps.end(), l.getMapId()); @@ -1031,23 +1045,23 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector& { WorldLocation loc = tlocs[urand(0, tlocs.size() - 1)]; - 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 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 z = loc.GetPositionZ(); Map* map = sMapMgr->FindMap(loc.GetMapId(), 0); if (!map) continue; - - AreaTableEntry const* area = sAreaTableStore.LookupEntry(map->GetAreaId(bot->GetPhaseMask(), x, y, z)); - if (!area) + + AreaTableEntry const* zone = sAreaTableStore.LookupEntry(map->GetZoneId(bot->GetPhaseMask(), x, y, z)); + if (!zone) continue; // 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; - if (area->team == 2 && bot->GetTeamId() == TEAM_HORDE && bot->getLevel() < 40) + if (zone->team == 2 && bot->GetTeamId() == TEAM_HORDE) continue; if (map->IsInWater(bot->GetPhaseMask(), x, y, z, bot->GetCollisionHeight())) @@ -1060,11 +1074,11 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector& z = 0.05f + ground; 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) { - bot->SetHomebind(loc, area->ID); + bot->SetHomebind(loc, zone->ID); } bot->GetMotionMaster()->Clear(); @@ -1093,66 +1107,66 @@ void RandomPlayerbotMgr::PrepareTeleportCache() if (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( + "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) { - LOG_INFO("playerbots", "Loading random teleport caches for {} levels...", maxLevel); - do { - Field* fields = result->Fetch(); - uint32 mapId = fields[0].Get(); + Field* fields = results->Fetch(); + uint16 mapId = fields[0].Get(); float x = fields[1].Get(); float y = fields[2].Get(); float z = fields[3].Get(); - uint8 level = fields[4].Get(); - + uint32 avg_level = fields[4].Get(); WorldLocation loc(mapId, x, y, z, 0); - locsPerLevelCache[level].push_back(std::move(loc)); - } - while (result->NextRow()); - } - else - { - 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(); - float x = fields[1].Get(); - float y = fields[2].Get(); - float z = fields[3].Get(); - 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()); + 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++) { + if (level < 1 || level > maxLevel) { + continue; + } + locsPerLevelCache[(uint8)level].push_back(loc); } - } + } while (results->NextRow()); } - LOG_INFO("playerbots", "Preparing RPG teleport caches for {} factions...", sFactionTemplateStore.GetNumRows()); - - 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 " + 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"); if (results) { @@ -1190,9 +1204,8 @@ void RandomPlayerbotMgr::RandomTeleportForLevel(Player* bot) uint32 level = bot->getLevel(); uint8 race = bot->getRace(); - LOG_INFO("playerbots", "Random teleporting bot {} for level ({} locations available)", bot->GetName().c_str(), rpgLocsCacheLevel[race][level].size()); - RandomTeleport(bot, rpgLocsCacheLevel[race][level]); - // Refresh(bot); + LOG_INFO("playerbots", "Random teleporting bot {} for level {} ({} locations available)", bot->GetName().c_str(), bot->GetLevel(), locsPerLevelCache[level].size()); + RandomTeleport(bot, locsPerLevelCache[level]); } void RandomPlayerbotMgr::RandomTeleport(Player* bot) @@ -1248,7 +1261,7 @@ void RandomPlayerbotMgr::Randomize(Player* bot) else { RandomizeFirst(bot); } - //RandomTeleportForRpg(bot); + RandomTeleportForLevel(bot); } void RandomPlayerbotMgr::IncreaseLevel(Player* bot) @@ -1296,7 +1309,7 @@ void RandomPlayerbotMgr::RandomizeFirst(Player* bot) level = maxLevel; 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); @@ -1710,11 +1723,11 @@ bool RandomPlayerbotMgr::HandlePlayerbotConsoleCommand(ChatHandler* handler, cha return true; } - std::vector messages = sRandomPlayerbotMgr->HandlePlayerbotCommand(args); - for (std::vector::iterator i = messages.begin(); i != messages.end(); ++i) - { - LOG_INFO("playerbots", "{}", i->c_str()); - } + // std::vector messages = sRandomPlayerbotMgr->HandlePlayerbotCommand(args); + // for (std::vector::iterator i = messages.begin(); i != messages.end(); ++i) + // { + // LOG_INFO("playerbots", "{}", i->c_str()); + // } return true; } @@ -2219,8 +2232,9 @@ void RandomPlayerbotMgr::ChangeStrategyOnce(Player* player) void RandomPlayerbotMgr::RandomTeleportForRpg(Player* bot) { uint32 race = bot->getRace(); - LOG_INFO("playerbots", "Random teleporting bot {} for RPG ({} locations available)", bot->GetName().c_str(), rpgLocsCache[race].size()); - RandomTeleport(bot, rpgLocsCache[race], true); + uint32 level = bot->GetLevel(); + 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) @@ -2291,14 +2305,14 @@ ObjectGuid const RandomPlayerbotMgr::GetBattleMasterGUID(Player* bot, Battlegrou break; } - AreaTableEntry const* area = sAreaTableStore.LookupEntry(Bm->GetAreaId()); - if (!area) + AreaTableEntry const* zone = sAreaTableStore.LookupEntry(Bm->GetZoneId()); + if (!zone) continue; - if (area->team == 4 && bot->GetTeamId() == TEAM_ALLIANCE) + if (zone->team == 4 && bot->GetTeamId() == TEAM_ALLIANCE) continue; - if (area->team == 2 && bot->GetTeamId() == TEAM_HORDE) + if (zone->team == 2 && bot->GetTeamId() == TEAM_HORDE) continue; if (Bm->getDeathState() == DEAD) diff --git a/src/RandomPlayerbotMgr.h b/src/RandomPlayerbotMgr.h index 12edcf7b..5af312bc 100644 --- a/src/RandomPlayerbotMgr.h +++ b/src/RandomPlayerbotMgr.h @@ -121,7 +121,7 @@ class RandomPlayerbotMgr : public PlayerbotHolder std::vector players; uint32 processTicks; std::map> locsPerLevelCache; - std::map> rpgLocsCache; + // std::map> rpgLocsCache; std::map>> rpgLocsCacheLevel; std::map>> BattleMastersCache; std::map> eventCache; diff --git a/src/strategy/actions/ChooseTargetActions.cpp b/src/strategy/actions/ChooseTargetActions.cpp index b3d08f20..7810939d 100644 --- a/src/strategy/actions/ChooseTargetActions.cpp +++ b/src/strategy/actions/ChooseTargetActions.cpp @@ -33,9 +33,12 @@ bool AttackAnythingAction::isUseful() if (!AI_VALUE(bool, "can move around")) return false; - if (context->GetValue("travel target")->Get()->isTraveling() && ChooseRpgTargetAction::isFollowValid(bot, *context->GetValue("travel target")->Get()->getPosition())) //Bot is traveling + if (context->GetValue("travel target")->Get()->isTraveling() && + ChooseRpgTargetAction::isFollowValid(bot, *context->GetValue("travel target")->Get()->getPosition())) //Bot is traveling return false; - + if (bot->IsInCombat()) { + return false; + } Unit* target = GetTarget(); if (!target) diff --git a/src/strategy/actions/FollowActions.cpp b/src/strategy/actions/FollowActions.cpp index 93a617f6..fa2f5541 100644 --- a/src/strategy/actions/FollowActions.cpp +++ b/src/strategy/actions/FollowActions.cpp @@ -25,7 +25,7 @@ bool FollowAction::Execute(Event event) if (Formation::IsNullLocation(loc) || loc.GetMapId() == -1) 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()) @@ -33,11 +33,14 @@ bool FollowAction::Execute(Event event) if (CreatureAI* creatureAI = ((Creature*)pet)->AI()) { pet->SetReactState(REACT_PASSIVE); - pet->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW); - pet->GetCharmInfo()->SetIsFollowing(true); - pet->AttackStop(); + pet->GetCharmInfo()->SetIsCommandFollow(true); pet->GetCharmInfo()->IsReturning(); 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) diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 4ac45841..59482805 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -4,7 +4,9 @@ #include "MovementActions.h" #include "MovementGenerator.h" +#include "ObjectGuid.h" #include "PlayerbotAIConfig.h" +#include "SharedDefines.h" #include "TargetedMovementGenerator.h" #include "Event.h" #include "LastMovementValue.h" @@ -15,6 +17,7 @@ #include "Playerbots.h" #include "ServerFacade.h" #include "Transport.h" +#include "Unit.h" #include "Vehicle.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) { - if (!IsMovingAllowed(mapId, x, y, z)) + if (!IsMovingAllowed(mapId, x, y, z)) { 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); if (distance > sPlayerbotAIConfig->contactDistance) { @@ -159,8 +169,8 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, return false; // UpdateMovementState(); // // LOG_DEBUG("playerbots", "IsMovingAllowed {}", IsMovingAllowed()); - // if (!IsMovingAllowed()) - // return false; + // bot->AddUnitMovementFlag() + // bool isVehicle = false; // Unit* mover = bot; @@ -663,7 +673,7 @@ bool MovementAction::MoveTo(Unit* target, float distance) float dx = cos(angle) * needToGo + bx; 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); } @@ -1265,9 +1275,7 @@ bool FleeWithPetAction::Execute(Event event) if (CreatureAI* creatureAI = ((Creature*)pet)->AI()) { pet->SetReactState(REACT_PASSIVE); - pet->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW); - pet->GetCharmInfo()->SetIsFollowing(true); - pet->AttackStop(); + pet->GetCharmInfo()->SetIsCommandFollow(true); pet->GetCharmInfo()->IsReturning(); pet->GetMotionMaster()->MoveFollow(bot, PET_FOLLOW_DIST, pet->GetFollowAngle()); } @@ -1384,17 +1392,27 @@ bool MoveOutOfCollisionAction::isUseful() bool MoveRandomAction::Execute(Event event) { - //uint32 randnum = bot->GetGUID().GetCounter(); // Semi-random but fixed number for each bot. - //uint32 cycle = floor(getMSTime() / (1000 * 60)); // Semi-random number adds 1 each minute. + float distance = sPlayerbotAIConfig->tooCloseDistance + sPlayerbotAIConfig->grindDistance * urand(3, 10) / 10.0f; - //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); - float distance = urand(20, 200); + bool moved = MoveTo(bot->GetMapId(), x, y, z); + 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() diff --git a/src/strategy/actions/NonCombatActions.cpp b/src/strategy/actions/NonCombatActions.cpp index 97db336a..44b2ef54 100644 --- a/src/strategy/actions/NonCombatActions.cpp +++ b/src/strategy/actions/NonCombatActions.cpp @@ -18,8 +18,8 @@ bool DrinkAction::Execute(Event event) if (sPlayerbotAIConfig->freeFood) { - if (bot->IsNonMeleeSpellCast(true)) - return false; + // if (bot->IsNonMeleeSpellCast(true)) + // return false; bot->ClearUnitState(UNIT_STATE_CHASE); bot->ClearUnitState(UNIT_STATE_FOLLOW); @@ -70,8 +70,8 @@ bool EatAction::Execute(Event event) if (sPlayerbotAIConfig->freeFood) { - if (bot->IsNonMeleeSpellCast(true)) - return false; + // if (bot->IsNonMeleeSpellCast(true)) + // return false; bot->ClearUnitState(UNIT_STATE_CHASE); bot->ClearUnitState(UNIT_STATE_FOLLOW); @@ -106,8 +106,8 @@ bool EatAction::Execute(Event event) } 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() diff --git a/src/strategy/actions/ReviveFromCorpseAction.cpp b/src/strategy/actions/ReviveFromCorpseAction.cpp index 7c9fb910..d55ecabc 100644 --- a/src/strategy/actions/ReviveFromCorpseAction.cpp +++ b/src/strategy/actions/ReviveFromCorpseAction.cpp @@ -9,6 +9,7 @@ #include "MapMgr.h" #include "Playerbots.h" #include "PlayerbotFactory.h" +#include "RandomPlayerbotMgr.h" #include "ServerFacade.h" bool ReviveFromCorpseAction::Execute(Event event) @@ -89,10 +90,11 @@ bool FindCorpseAction::Execute(Event event) { 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()); context->GetValue("death count")->Set(0); - sRandomPlayerbotMgr->RandomTeleportForLevel(bot); + // sRandomPlayerbotMgr->RandomTeleportForLevel(bot); + sRandomPlayerbotMgr->Revive(bot); return true; } } diff --git a/src/strategy/generic/GrindingStrategy.cpp b/src/strategy/generic/GrindingStrategy.cpp index ceb746be..a81a8d2d 100644 --- a/src/strategy/generic/GrindingStrategy.cpp +++ b/src/strategy/generic/GrindingStrategy.cpp @@ -12,6 +12,8 @@ NextAction** GrindingStrategy::getDefaultActions() void GrindingStrategy::InitTriggers(std::vector& 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))); } diff --git a/src/strategy/values/Arrow.cpp b/src/strategy/values/Arrow.cpp index d56dd4e1..e51752f9 100644 --- a/src/strategy/values/Arrow.cpp +++ b/src/strategy/values/Arrow.cpp @@ -3,6 +3,7 @@ */ #include "Arrow.h" +#include "Map.h" #include "Playerbots.h" WorldLocation ArrowFormation::GetLocationInternal() @@ -47,8 +48,8 @@ WorldLocation ArrowFormation::GetLocationInternal() float ground = master->GetMap()->GetHeight(x, y, z + 0.5f); if (ground <= INVALID_HEIGHT) return Formation::NullLocation; - - return WorldLocation(master->GetMapId(), x, y, 0.05f + ground); + // master->UpdateGroundPositionZ(x, y, z); + return WorldLocation(master->GetMapId(), x, y, z); } void ArrowFormation::Build()