latest github + bot fix
This commit is contained in:
@@ -14,11 +14,11 @@ class mxwow_bosskill : public PlayerScript
|
||||
|
||||
public:
|
||||
|
||||
mxwow_bosskill() : PlayerScript("mxwow_bosskill") { }
|
||||
mxwow_bosskill() : PlayerScript("mxwow_bosskill") {}
|
||||
|
||||
void OnPlayerLogin(Player* player) override
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void OnPlayerCreatureKill(Player* player, Creature* boss) {
|
||||
@@ -39,37 +39,94 @@ public:
|
||||
float pLife;
|
||||
bool pGrouped;
|
||||
if (boss->isWorldBoss() || boss->IsDungeonBoss()) {
|
||||
if (boss->isWorldBoss()) { mType = "Raid"; } else { mType = "Donjon"; }
|
||||
if (boss->isWorldBoss()) { mType = "Raid"; }
|
||||
else { mType = "Donjon"; }
|
||||
uint32 contentDifId;
|
||||
bName = boss->GetName();
|
||||
map = player->GetMap();
|
||||
pName = player->GetName();
|
||||
piLevel = player->GetAverageItemLevelForDF();
|
||||
pMapName = map->GetMapName();
|
||||
pGrouped = player->GetGroup();
|
||||
pLife = player->GetHealthPct();
|
||||
int RandIndex = rand() % 8;
|
||||
int RandIndex = rand() % 8;
|
||||
if (player->GetMap()->IsHeroic()) {
|
||||
contentDifficulty = "|cffff0000";
|
||||
contentDifName = "|cffff0000Heroic";
|
||||
contentDifId = 1;
|
||||
}
|
||||
else {
|
||||
contentDifficulty = "|cff00ff00";
|
||||
contentDifName = "|cff00ff00Normal";
|
||||
contentDifId = 0;
|
||||
}
|
||||
|
||||
if (sConfigMgr->GetOption<bool>("MxWoW_BossKill.Enabled", true))
|
||||
{
|
||||
if (!pGrouped) {
|
||||
KillManager(player, boss, map);
|
||||
//ss << "|cffabeeff[MxW] [" << GetPlayerColor(player) << pName << "|cffabeeff][iL"<< piLevel <<"][" << pLife << "%] a tué [|cffff1100" << bName << "|cffabeeff][" << contentDifficulty << pMapName << "|cffabeeff]";
|
||||
/*pName = p->GetName();
|
||||
line00 << "|cffabeeff[MxW][" << mType << "]";
|
||||
line01 << "|cffabeeff[" << contentDifficulty << ""<< pMapName <<"|cffabeeff]["<< contentDifName <<"|cffabeeff]";
|
||||
line02 << "|cffabeeff["<< GetPlayerColor(player)<< pName <<"|cffabeeff][iL"<< piLevel <<"]["<< pLife <<"%]";
|
||||
line03 << "|cffabeeff[|cffff1100"<< bName <<"|cffabeeff] "<< GenKillMessage(RandIndex) <<".";
|
||||
line01 << "|cffabeeff[" << contentDifficulty << "" << pMapName << "|cffabeeff][" << contentDifName << "|cffabeeff]";
|
||||
line02 << "|cffabeeff[" << GetPlayerColor(player) << pName << "|cffabeeff][iL" << piLevel << "][" << pLife << "%]";
|
||||
line03 << "|cffabeeff[|cffff1100" << bName << "|cffabeeff] " << GenKillMessage(RandIndex) << ".";
|
||||
sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, line00.str().c_str());
|
||||
sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, line01.str().c_str());
|
||||
sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, line02.str().c_str());
|
||||
sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, line03.str().c_str());
|
||||
ChatHandler(p->GetSession()).PSendSysMessage(ss.str().c_str());*/
|
||||
}
|
||||
}
|
||||
else {
|
||||
Group* group = player->GetGroup();
|
||||
Group::MemberSlotList const& groupSlot = group->GetMemberSlots();
|
||||
for (Group::member_citerator itr = groupSlot.begin(); itr != groupSlot.end(); itr++)
|
||||
{
|
||||
Player* p = ObjectAccessor::FindPlayer(itr->guid);
|
||||
KillManager(p, boss, map);
|
||||
/*pName = p->GetName();
|
||||
line00 << "|cffabeeff[MxW][" << mType << "]";
|
||||
line01 << "|cffabeeff[" << contentDifficulty << "" << pMapName << "|cffabeeff][" << contentDifName << "|cffabeeff]";
|
||||
line02 << "|cffabeeff[" << GetPlayerColor(player) << pName << "|cffabeeff][iL" << piLevel << "][" << pLife << "%]";
|
||||
line03 << "|cffabeeff[|cffff1100" << bName << "|cffabeeff] " << GenKillMessage(RandIndex) << ".";
|
||||
sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, line00.str().c_str());
|
||||
sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, line01.str().c_str());
|
||||
sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, line02.str().c_str());
|
||||
sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, line03.str().c_str());
|
||||
ChatHandler(p->GetSession()).PSendSysMessage(ss.str().c_str());*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KillManager(Player* player, Creature* boss, Map* map) {
|
||||
uint32 aId = player->GetSession()->GetAccountId();
|
||||
uint32 pId = player->GetGUID().GetRawValue();
|
||||
uint32 mapId = map->GetId();
|
||||
uint32 cId = boss->GetCreatureTemplate()->Entry;
|
||||
uint32 contentDifId;
|
||||
if (player->GetMap()->IsHeroic()) {
|
||||
contentDifId = 1;
|
||||
}
|
||||
else {
|
||||
contentDifId = 0;
|
||||
}
|
||||
QueryResult queryBossKill = LoginDatabase.Query("SELECT * FROM mxw_boss_kill WHERE accountid = {} AND charid = {} AND creatureid = {} AND instanceid = {} AND difficulty = {}", aId, pId, cId, mapId, contentDifId);
|
||||
if (queryBossKill) {
|
||||
uint32 killCount = (*queryBossKill)[5].Get<uint32>();
|
||||
killCount++;
|
||||
LoginDatabase.Execute("UPDATE mxw_boss_kill SET killcount = {} WHERE accountid = {} AND charid = {} AND creatureid = {} AND instanceid = {} AND difficulty = {}", killCount, aId, pId, cId, mapId, contentDifId);
|
||||
}
|
||||
else {
|
||||
LoginDatabase.Execute("INSERT INTO mxw_boss_kill (accountid,charid,creatureid,instanceid,difficulty,killcount) VALUES ({}, {}, {}, {}, {}, {})", aId, pId, cId, mapId, contentDifId, 1);
|
||||
}
|
||||
|
||||
QueryResult queryInstanceKill = LoginDatabase.Query("SELECT * FROM mxw_boss_instance WHERE instanceid = {} AND difficulty = {} AND bossid = {}", mapId, contentDifId, cId);
|
||||
if (queryInstanceKill) {
|
||||
uint32 killCount = (*queryInstanceKill)[3].Get<uint32>();
|
||||
killCount++;
|
||||
LoginDatabase.Execute("UPDATE mxw_boss_instance SET killcount = {} WHERE instanceid = {} AND difficulty = {} AND bossid = {} ", killCount, mapId, contentDifId, cId);
|
||||
}
|
||||
else {
|
||||
LoginDatabase.Execute("INSERT INTO mxw_boss_instance (instanceid,difficulty,bossid,killcount) VALUES ({}, {}, {}, {})", mapId, contentDifId, cId, 1);
|
||||
}
|
||||
}
|
||||
|
||||
std::string GenKillMessage(const int i)
|
||||
|
||||
@@ -1,19 +1,7 @@
|
||||
[worldserver]
|
||||
#####################################################################################################
|
||||
# #
|
||||
# MxWoW - Boss Kill (Enable / Disable) #
|
||||
# Description: Enables or disable the script for mxwow_bosskill #
|
||||
# Default: 1 (Enable) #
|
||||
# 0 (Disable) #
|
||||
# #
|
||||
## MxWoW - Bounty (Enable / Disable)
|
||||
MxWoW_Bounty.Enabled = 1
|
||||
#####################################################################################################
|
||||
#####################################################################################################
|
||||
# #
|
||||
# MxWoW - Boss Kill (Enable / Disable) #
|
||||
# Description: Enables or disable the script for mxwow_bosskill #
|
||||
# Default: 1 (Enable) #
|
||||
# 0 (Disable) #
|
||||
# #
|
||||
MxWoW_Bounty.Base.Copper = 100
|
||||
#####################################################################################################
|
||||
## Value in copper for bounty reward.
|
||||
MxWoW_Bounty.Base.Copper = 1250
|
||||
## Hour for daily bounty reset (0,23 / 6 = 6am / 20 = 8pm)
|
||||
MxWoW_Bounty.Daily.ResetHour = 6
|
||||
@@ -8,6 +8,8 @@
|
||||
#include "Player.h"
|
||||
#include "Chat.h"
|
||||
#include <WorldSessionMgr.h>
|
||||
#include <ZoneManager.h>
|
||||
#include <EventManager.h>
|
||||
|
||||
class mxwow_bounty : public PlayerScript
|
||||
{
|
||||
@@ -18,7 +20,18 @@ mxwow_bounty() : PlayerScript("mxwow_bounty") { }
|
||||
|
||||
void OnPlayerLogin(Player* player) override
|
||||
{
|
||||
|
||||
std::ostringstream ss;
|
||||
uint32 randZone = rand() % 9;
|
||||
ss << "Random Zone: " << ZoneManager::RandomZoneId(randZone) << " / " << ZoneManager::RandomZoneNameLocale_frFR(randZone);
|
||||
ChatHandler(player->GetSession()).PSendSysMessage(ss.str().c_str());
|
||||
//EventManager::CreateNewEvent(player);
|
||||
}
|
||||
|
||||
void OnPlayerSave(Player* player) {
|
||||
/*if (EventManager::CheckBountyReset()) {
|
||||
EventManager::CleanLastEvent();
|
||||
EventManager::CreateNewEvent(player);
|
||||
}*/
|
||||
}
|
||||
|
||||
void OnPlayerCreatureKill(Player* player, Creature* creature) {
|
||||
|
||||
@@ -73,7 +73,7 @@ public:
|
||||
expMulti = 10;
|
||||
break;
|
||||
}
|
||||
amount = amount * expMulti;
|
||||
amount *= expMulti;
|
||||
if (sConfigMgr->GetOption<bool>("MxWoW_ToonMaster.Verbose", true) && plevel < 80)
|
||||
{
|
||||
ss << "|cffabeeff[MxW][ToonMaster]["<< cMPL <<"xNiv.80] Bonus: EXPx"<<expMulti;
|
||||
|
||||
@@ -544,6 +544,8 @@ AiPlayerbot.DisableDeathKnightLogin = 0
|
||||
# Default: 0
|
||||
AiPlayerbot.LimitTalentsExpansion = 0
|
||||
|
||||
# Allow random bots to trade
|
||||
AiPlayerbot.EnableRandomBotTrading = 1
|
||||
#
|
||||
#
|
||||
#
|
||||
@@ -636,10 +638,10 @@ AiPlayerbot.HunterWolfPet = 0
|
||||
#
|
||||
#
|
||||
# Specify percent of active bots
|
||||
# The default is 10. With 10% of all bots going active or inactive each minute. Regardless
|
||||
# This value is only applied to inactive areas where no real-players are detected, when
|
||||
# real-players are nearby, friend, group, guild, bg, instances etc the value is always
|
||||
# enforced to 100%
|
||||
# The default is 100%, but would be automatically adjusted if botActiveAloneSmartScale
|
||||
# is enabled. Regardless, this value is only applied to inactive areas where no real-players
|
||||
# are detected. When real-players are nearby, friend, group, guild, BGs, instances etc,
|
||||
# the value is always enforced to 100%
|
||||
AiPlayerbot.BotActiveAlone = 100
|
||||
|
||||
# Force botActiveAlone when bot is ... of real player
|
||||
|
||||
@@ -374,7 +374,9 @@ void PlayerbotAI::UpdateAIGroupMembership()
|
||||
PlayerbotAI* leaderAI = GET_PLAYERBOT_AI(leader);
|
||||
if (leaderAI && !leaderAI->IsRealPlayer())
|
||||
{
|
||||
bot->RemoveFromGroup();
|
||||
WorldPacket* packet = new WorldPacket(CMSG_GROUP_DISBAND);
|
||||
bot->GetSession()->QueuePacket(packet);
|
||||
// bot->RemoveFromGroup();
|
||||
ResetStrategies();
|
||||
}
|
||||
}
|
||||
@@ -399,7 +401,9 @@ void PlayerbotAI::UpdateAIGroupMembership()
|
||||
}
|
||||
if (!hasRealPlayer)
|
||||
{
|
||||
bot->RemoveFromGroup();
|
||||
WorldPacket* packet = new WorldPacket(CMSG_GROUP_DISBAND);
|
||||
bot->GetSession()->QueuePacket(packet);
|
||||
// bot->RemoveFromGroup();
|
||||
ResetStrategies();
|
||||
}
|
||||
}
|
||||
@@ -1534,7 +1538,7 @@ void PlayerbotAI::ApplyInstanceStrategies(uint32 mapId, bool tellMaster)
|
||||
strategyName = "wotlk-hol"; // Halls of Lightning
|
||||
break;
|
||||
case 603:
|
||||
strategyName = "uld";
|
||||
strategyName = "uld"; // Ulduar
|
||||
break;
|
||||
case 604:
|
||||
strategyName = "wotlk-gd"; // Gundrak
|
||||
@@ -1551,8 +1555,11 @@ void PlayerbotAI::ApplyInstanceStrategies(uint32 mapId, bool tellMaster)
|
||||
case 619:
|
||||
strategyName = "wotlk-ok"; // Ahn'kahet: The Old Kingdom
|
||||
break;
|
||||
case 624:
|
||||
strategyName = "voa"; // Vault of Archavon
|
||||
break;
|
||||
case 631:
|
||||
strategyName = "icc";
|
||||
strategyName = "icc"; // Icecrown Citadel
|
||||
break;
|
||||
case 632:
|
||||
strategyName = "wotlk-fos"; // The Forge of Souls
|
||||
|
||||
@@ -505,6 +505,7 @@ bool PlayerbotAIConfig::Initialize()
|
||||
limitGearExpansion = sConfigMgr->GetOption<int32>("AiPlayerbot.LimitGearExpansion", 1);
|
||||
randombotStartingLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.RandombotStartingLevel", 5);
|
||||
enablePeriodicOnlineOffline = sConfigMgr->GetOption<bool>("AiPlayerbot.EnablePeriodicOnlineOffline", false);
|
||||
enableRandomBotTrading = sConfigMgr->GetOption<bool>("AiPlayerbot.EnableRandomBotTrading", true);
|
||||
periodicOnlineOfflineRatio = sConfigMgr->GetOption<float>("AiPlayerbot.PeriodicOnlineOfflineRatio", 2.0);
|
||||
gearscorecheck = sConfigMgr->GetOption<bool>("AiPlayerbot.GearScoreCheck", false);
|
||||
randomBotPreQuests = sConfigMgr->GetOption<bool>("AiPlayerbot.PreQuests", true);
|
||||
|
||||
@@ -313,6 +313,7 @@ public:
|
||||
bool autoLearnQuestSpells;
|
||||
bool autoTeleportForLevel;
|
||||
bool randomBotGroupNearby;
|
||||
bool enableRandomBotTrading;
|
||||
uint32 tweakValue; // Debugging config
|
||||
|
||||
uint32 randomBotArenaTeamCount;
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#include "raids/obsidiansanctum/RaidOsActionContext.h"
|
||||
#include "raids/obsidiansanctum/RaidOsTriggerContext.h"
|
||||
#include "raids/eyeofeternity/RaidEoEActionContext.h"
|
||||
#include "raids/vaultofarchavon/RaidVoATriggerContext.h"
|
||||
#include "raids/vaultofarchavon/RaidVoAActionContext.h"
|
||||
#include "raids/eyeofeternity/RaidEoETriggerContext.h"
|
||||
#include "raids/moltencore/RaidMcActionContext.h"
|
||||
#include "raids/moltencore/RaidMcTriggerContext.h"
|
||||
@@ -54,6 +56,7 @@ AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
|
||||
actionContexts.Add(new RaidNaxxActionContext());
|
||||
actionContexts.Add(new RaidOsActionContext());
|
||||
actionContexts.Add(new RaidEoEActionContext());
|
||||
actionContexts.Add(new RaidVoAActionContext());
|
||||
actionContexts.Add(new RaidUlduarActionContext());
|
||||
actionContexts.Add(new RaidIccActionContext());
|
||||
actionContexts.Add(new WotlkDungeonUKActionContext());
|
||||
@@ -79,6 +82,7 @@ AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
|
||||
triggerContexts.Add(new RaidNaxxTriggerContext());
|
||||
triggerContexts.Add(new RaidOsTriggerContext());
|
||||
triggerContexts.Add(new RaidEoETriggerContext());
|
||||
triggerContexts.Add(new RaidVoATriggerContext());
|
||||
triggerContexts.Add(new RaidUlduarTriggerContext());
|
||||
triggerContexts.Add(new RaidIccTriggerContext());
|
||||
triggerContexts.Add(new WotlkDungeonUKTriggerContext());
|
||||
|
||||
@@ -31,7 +31,10 @@ bool AttackEnemyFlagCarrierAction::isUseful()
|
||||
|
||||
bool AttackAnythingAction::isUseful()
|
||||
{
|
||||
if (!botAI->AllowActivity(GRIND_ACTIVITY)) // Bot not allowed to be active
|
||||
if (!bot || !botAI) // Prevents invalid accesses
|
||||
return false;
|
||||
|
||||
if (!botAI->AllowActivity(GRIND_ACTIVITY)) // Bot cannot be active
|
||||
return false;
|
||||
|
||||
if (botAI->HasStrategy("stay", BOT_STATE_NON_COMBAT))
|
||||
@@ -41,19 +44,17 @@ bool AttackAnythingAction::isUseful()
|
||||
return false;
|
||||
|
||||
Unit* target = GetTarget();
|
||||
|
||||
if (!target)
|
||||
if (!target || !target->IsInWorld()) // Checks if the target is valid and in the world
|
||||
return false;
|
||||
|
||||
std::string const name = std::string(target->GetName());
|
||||
// Check for invalid targets: Dummy, Charge Target, Melee Target, Ranged Target
|
||||
if (!name.empty() &&
|
||||
(name.find("Dummy") != std::string::npos ||
|
||||
name.find("Charge Target") != std::string::npos ||
|
||||
name.find("Melee Target") != std::string::npos ||
|
||||
name.find("Ranged Target") != std::string::npos))
|
||||
{
|
||||
return false; // Target is one of the disallowed types
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -53,6 +53,9 @@ bool InviteNearbyToGroupAction::Execute(Event event)
|
||||
if (!player)
|
||||
continue;
|
||||
|
||||
if (!player->GetMapId() != bot->GetMapId())
|
||||
continue;
|
||||
|
||||
if (player->GetGroup())
|
||||
continue;
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "Opcodes.h"
|
||||
#include "Playerbots.h"
|
||||
#include "World.h"
|
||||
#include "WorldPacket.h"
|
||||
|
||||
using namespace lfg;
|
||||
|
||||
@@ -179,9 +180,12 @@ bool LfgRoleCheckAction::Execute(Event event)
|
||||
// if (currentRoles == newRoles)
|
||||
// return false;
|
||||
|
||||
sLFGMgr->SetRoles(bot->GetGUID(), newRoles);
|
||||
|
||||
sLFGMgr->UpdateRoleCheck(group->GetGUID(), bot->GetGUID(), newRoles);
|
||||
|
||||
WorldPacket* packet = new WorldPacket(CMSG_LFG_SET_ROLES);
|
||||
*packet << (uint8)newRoles;
|
||||
bot->GetSession()->QueuePacket(packet);
|
||||
// sLFGMgr->SetRoles(bot->GetGUID(), newRoles);
|
||||
// sLFGMgr->UpdateRoleCheck(group->GetGUID(), bot->GetGUID(), newRoles);
|
||||
|
||||
LOG_INFO("playerbots", "Bot {} {}:{} <{}>: LFG roles checked", bot->GetGUID().ToString().c_str(),
|
||||
bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->GetLevel(), bot->GetName().c_str());
|
||||
@@ -206,11 +210,13 @@ bool LfgAcceptAction::Execute(Event event)
|
||||
|
||||
if (bot->IsInCombat() || bot->isDead())
|
||||
{
|
||||
/// @FIXME: Race condition
|
||||
LOG_INFO("playerbots", "Bot {} {}:{} <{}> is in combat and refuses LFG proposal {}",
|
||||
bot->GetGUID().ToString().c_str(), bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->GetLevel(),
|
||||
bot->GetName().c_str(), id);
|
||||
sLFGMgr->UpdateProposal(id, bot->GetGUID(), true);
|
||||
WorldPacket* packet = new WorldPacket(CMSG_LFG_PROPOSAL_RESULT);
|
||||
*packet << (uint32)id << (bool)false;
|
||||
bot->GetSession()->QueuePacket(packet);
|
||||
// sLFGMgr->UpdateProposal(id, bot->GetGUID(), true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -220,8 +226,10 @@ bool LfgAcceptAction::Execute(Event event)
|
||||
botAI->GetAiObjectContext()->GetValue<uint32>("lfg proposal")->Set(0);
|
||||
|
||||
bot->ClearUnitState(UNIT_STATE_ALL_STATE);
|
||||
/// @FIXME: Race condition
|
||||
sLFGMgr->UpdateProposal(id, bot->GetGUID(), true);
|
||||
WorldPacket* packet = new WorldPacket(CMSG_LFG_PROPOSAL_RESULT);
|
||||
*packet << (uint32)id << (bool)true;
|
||||
bot->GetSession()->QueuePacket(packet);
|
||||
// sLFGMgr->UpdateProposal(id, bot->GetGUID(), true);
|
||||
|
||||
if (sRandomPlayerbotMgr->IsRandomBot(bot) && !bot->GetGroup())
|
||||
{
|
||||
@@ -259,7 +267,9 @@ bool LfgLeaveAction::Execute(Event event)
|
||||
if (sLFGMgr->GetState(bot->GetGUID()) > LFG_STATE_QUEUED)
|
||||
return false;
|
||||
|
||||
sLFGMgr->LeaveLfg(bot->GetGUID());
|
||||
WorldPacket* packet = new WorldPacket(CMSG_LFG_LEAVE);
|
||||
bot->GetSession()->QueuePacket(packet);
|
||||
// sLFGMgr->LeaveLfg(bot->GetGUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -278,7 +288,10 @@ bool LfgTeleportAction::Execute(Event event)
|
||||
|
||||
bot->ClearUnitState(UNIT_STATE_ALL_STATE);
|
||||
|
||||
sLFGMgr->TeleportPlayer(bot, out);
|
||||
WorldPacket* packet = new WorldPacket(CMSG_LFG_TELEPORT);
|
||||
*packet << out;
|
||||
bot->GetSession()->QueuePacket(packet);
|
||||
// sLFGMgr->TeleportPlayer(bot, out);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,12 @@ bool TradeStatusAction::Execute(Event event)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sPlayerbotAIConfig->enableRandomBotTrading && sRandomPlayerbotMgr->IsRandomBot(bot))
|
||||
{
|
||||
bot->Whisper("Trading is disabled", LANG_UNIVERSAL, trader);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allow trades from group members or bots
|
||||
if ((!bot->GetGroup() || !bot->GetGroup()->IsMember(trader->GetGUID())) &&
|
||||
(trader != master || !botAI->GetSecurity()->CheckLevelFor(PLAYERBOT_SECURITY_ALLOW_ALL, true, master)) &&
|
||||
@@ -49,7 +55,7 @@ bool TradeStatusAction::Execute(Event event)
|
||||
uint32 status;
|
||||
p >> status;
|
||||
|
||||
if (status == TRADE_STATUS_TRADE_ACCEPT)
|
||||
if (status == TRADE_STATUS_TRADE_ACCEPT || (status == TRADE_STATUS_BACK_TO_TRADE && trader->GetTradeData() && trader->GetTradeData()->IsAccepted()))
|
||||
{
|
||||
WorldPacket p;
|
||||
uint32 status = 0;
|
||||
@@ -122,12 +128,13 @@ bool TradeStatusAction::Execute(Event event)
|
||||
|
||||
void TradeStatusAction::BeginTrade()
|
||||
{
|
||||
Player* trader = bot->GetTrader();
|
||||
if (!trader || GET_PLAYERBOT_AI(bot->GetTrader()))
|
||||
return;
|
||||
|
||||
WorldPacket p;
|
||||
bot->GetSession()->HandleBeginTradeOpcode(p);
|
||||
|
||||
if (GET_PLAYERBOT_AI(bot->GetTrader()))
|
||||
return;
|
||||
|
||||
ListItemsVisitor visitor;
|
||||
IterateItems(&visitor);
|
||||
|
||||
@@ -149,7 +156,7 @@ void TradeStatusAction::BeginTrade()
|
||||
bool TradeStatusAction::CheckTrade()
|
||||
{
|
||||
Player* trader = bot->GetTrader();
|
||||
if (!bot->GetTradeData() || !trader->GetTradeData())
|
||||
if (!bot->GetTradeData() || !trader || !trader->GetTradeData())
|
||||
return false;
|
||||
|
||||
if (!botAI->HasActivePlayerMaster() && GET_PLAYERBOT_AI(bot->GetTrader()))
|
||||
|
||||
@@ -48,8 +48,8 @@ bool UseMeetingStoneAction::Execute(Event event)
|
||||
return false;
|
||||
|
||||
GameObjectTemplate const* goInfo = gameObject->GetGOInfo();
|
||||
if (!goInfo || goInfo->type != GAMEOBJECT_TYPE_SUMMONING_RITUAL)
|
||||
return false;
|
||||
if (!goInfo || goInfo->entry != 179944)
|
||||
return false;
|
||||
|
||||
return Teleport(master, bot);
|
||||
}
|
||||
@@ -217,7 +217,11 @@ bool SummonAction::Teleport(Player* summoner, Player* player)
|
||||
|
||||
if (bot->isDead() && revive)
|
||||
{
|
||||
if (!botAI->IsSafe(player) || !botAI->IsSafe(summoner))
|
||||
return false;
|
||||
|
||||
bot->ResurrectPlayer(1.0f, false);
|
||||
bot->SpawnCorpseBones();
|
||||
botAI->TellMasterNoFacing("I live, again!");
|
||||
botAI->GetAiObjectContext()->GetValue<GuidVector>("prioritized targets")->Reset();
|
||||
}
|
||||
@@ -240,6 +244,7 @@ bool SummonAction::Teleport(Player* summoner, Player* player)
|
||||
}
|
||||
}
|
||||
|
||||
botAI->TellError("Not enough place to summon");
|
||||
if(summoner != player)
|
||||
botAI->TellError("Not enough place to summon");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ bool MoveFromWhirlwindAction::Execute(Event event)
|
||||
{
|
||||
Unit* boss = nullptr;
|
||||
uint8 faction = bot->GetTeamId();
|
||||
float targetDist = 10.0f; // Whirlwind has range of 8, add a couple for safety buffer
|
||||
|
||||
float targetDist = 10.0f; // Whirlwind has a range of 8, adding a safety buffer
|
||||
|
||||
switch (bot->GetMap()->GetDifficulty())
|
||||
{
|
||||
case DUNGEON_DIFFICULTY_NORMAL:
|
||||
@@ -15,7 +15,7 @@ bool MoveFromWhirlwindAction::Execute(Event event)
|
||||
{
|
||||
boss = AI_VALUE2(Unit*, "find target", "horde commander");
|
||||
}
|
||||
else //if (faction == TEAM_HORDE)
|
||||
else // TEAM_HORDE
|
||||
{
|
||||
boss = AI_VALUE2(Unit*, "find target", "alliance commander");
|
||||
}
|
||||
@@ -25,7 +25,7 @@ bool MoveFromWhirlwindAction::Execute(Event event)
|
||||
{
|
||||
boss = AI_VALUE2(Unit*, "find target", "commander kolurg");
|
||||
}
|
||||
else //if (faction == TEAM_HORDE)
|
||||
else // TEAM_HORDE
|
||||
{
|
||||
boss = AI_VALUE2(Unit*, "find target", "commander stoutbeard");
|
||||
}
|
||||
@@ -33,11 +33,22 @@ bool MoveFromWhirlwindAction::Execute(Event event)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
float bossDistance = bot->GetExactDist2d(boss->GetPosition());
|
||||
if (!boss || bossDistance > targetDist)
|
||||
|
||||
// Ensure boss is valid before accessing its methods
|
||||
if (!boss)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
float bossDistance = bot->GetExactDist2d(boss->GetPosition());
|
||||
|
||||
// Check if the bot is already at a safe distance
|
||||
if (bossDistance > targetDist)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Move away from the boss to avoid Whirlwind
|
||||
return MoveAway(boss, targetDist - bossDistance);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "RaidMcStrategy.h"
|
||||
#include "RaidAq20Strategy.h"
|
||||
#include "RaidIccStrategy.h"
|
||||
#include "RaidVoAStrategy.h"
|
||||
|
||||
class RaidStrategyContext : public NamedObjectContext<Strategy>
|
||||
{
|
||||
@@ -25,6 +26,7 @@ public:
|
||||
creators["naxx"] = &RaidStrategyContext::naxx;
|
||||
creators["wotlk-os"] = &RaidStrategyContext::wotlk_os;
|
||||
creators["wotlk-eoe"] = &RaidStrategyContext::wotlk_eoe;
|
||||
creators["voa"] = &RaidStrategyContext::voa;
|
||||
creators["uld"] = &RaidStrategyContext::uld;
|
||||
creators["icc"] = &RaidStrategyContext::icc;
|
||||
}
|
||||
@@ -36,6 +38,7 @@ private:
|
||||
static Strategy* naxx(PlayerbotAI* botAI) { return new RaidNaxxStrategy(botAI); }
|
||||
static Strategy* wotlk_os(PlayerbotAI* botAI) { return new RaidOsStrategy(botAI); }
|
||||
static Strategy* wotlk_eoe(PlayerbotAI* botAI) { return new RaidEoEStrategy(botAI); }
|
||||
static Strategy* voa(PlayerbotAI* botAI) { return new RaidVoAStrategy(botAI); }
|
||||
static Strategy* uld(PlayerbotAI* botAI) { return new RaidUlduarStrategy(botAI); }
|
||||
static Strategy* icc(PlayerbotAI* botAI) { return new RaidIccStrategy(botAI); }
|
||||
};
|
||||
|
||||
@@ -1255,32 +1255,36 @@ bool HodirMoveSnowpackedIcicleAction::Execute(Event event)
|
||||
|
||||
bool HodirBitingColdJumpAction::Execute(Event event)
|
||||
{
|
||||
// This needs improving but maybe it should be done in the playerbot core.
|
||||
|
||||
int mapId = bot->GetMap()->GetId();
|
||||
int x = bot->GetPositionX();
|
||||
int y = bot->GetPositionY();
|
||||
int z = bot->GetPositionZ() + 3.98f;
|
||||
float speed = 7.96f;
|
||||
|
||||
UpdateMovementState();
|
||||
if (!IsMovingAllowed(mapId, x, y, z))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
MovementPriority priority;
|
||||
if (IsWaitingForLastMove(priority))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
MotionMaster& mm = *bot->GetMotionMaster();
|
||||
mm.Clear();
|
||||
mm.MoveJump(x, y, z, speed, speed, 1, AI_VALUE(Unit*, "current target"));
|
||||
mm.MoveFall(0, true);
|
||||
AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), 1000, priority);
|
||||
bot->RemoveAurasDueToSpell(SPELL_BITING_COLD_PLAYER_AURA);
|
||||
|
||||
return true;
|
||||
|
||||
// Backup when the overall strategy without cheat will be more vialable
|
||||
|
||||
// int mapId = bot->GetMap()->GetId();
|
||||
// int x = bot->GetPositionX();
|
||||
// int y = bot->GetPositionY();
|
||||
// int z = bot->GetPositionZ() + 3.98f;
|
||||
// float speed = 7.96f;
|
||||
|
||||
// UpdateMovementState();
|
||||
// if (!IsMovingAllowed(mapId, x, y, z))
|
||||
//{
|
||||
// return false;
|
||||
// }
|
||||
// MovementPriority priority;
|
||||
// if (IsWaitingForLastMove(priority))
|
||||
//{
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// MotionMaster& mm = *bot->GetMotionMaster();
|
||||
// mm.Clear();
|
||||
// mm.MoveJump(x, y, z, speed, speed, 1, AI_VALUE(Unit*, "current target"));
|
||||
// mm.MoveFall(0, true);
|
||||
// AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), 1000, priority);
|
||||
|
||||
// return true;
|
||||
}
|
||||
|
||||
bool FreyaMoveAwayNatureBombAction::isUseful()
|
||||
|
||||
@@ -287,13 +287,12 @@ bool HodirBitingColdTrigger::IsActive()
|
||||
return false;
|
||||
}
|
||||
|
||||
// Override if boss is casting Flash Freeze
|
||||
if (!boss->HasUnitState(UNIT_STATE_CASTING) || !boss->FindCurrentSpellBySpellId(SPELL_FLASH_FREEZE))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Player* master = botAI->GetMaster();
|
||||
if (!master || !master->IsAlive())
|
||||
return false;
|
||||
|
||||
return boss && botAI->GetAura("biting cold", bot, false, false, 2);
|
||||
return botAI->GetAura("biting cold", bot, false, false, 2) &&
|
||||
!botAI->GetAura("biting cold", master, false, false, 2);
|
||||
}
|
||||
|
||||
//Snowpacked Icicle Target
|
||||
|
||||
@@ -21,6 +21,7 @@ enum UlduarIDs
|
||||
NPC_SNOWPACKED_ICICLE = 33174,
|
||||
NPC_TOASTY_FIRE = 33342,
|
||||
SPELL_FLASH_FREEZE = 61968,
|
||||
SPELL_BITING_COLD_PLAYER_AURA = 62039,
|
||||
|
||||
// Freya
|
||||
NPC_EONARS_GIFT = 33228,
|
||||
|
||||
@@ -242,7 +242,7 @@ bool NewRpgMoveNpcAction::Execute(Event event)
|
||||
}
|
||||
|
||||
WorldObject* object = ObjectAccessor::GetWorldObject(*bot, info.near_npc.npcOrGo);
|
||||
if (object && bot->GetDistance(object) <= INTERACTION_DISTANCE)
|
||||
if (object && IsWithinInteractionDist(object))
|
||||
{
|
||||
if (!info.near_npc.lastReach)
|
||||
{
|
||||
|
||||
@@ -247,6 +247,134 @@ bool NewRpgBaseAction::InteractWithNpcOrGameObjectForQuest(ObjectGuid guid)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NewRpgBaseAction::CanInteractWithQuestGiver(Object* questGiver)
|
||||
{
|
||||
// This is a variant of Player::CanInteractWithQuestGiver
|
||||
// that removes the distance check and keeps all other checks
|
||||
switch (questGiver->GetTypeId())
|
||||
{
|
||||
case TYPEID_UNIT:
|
||||
{
|
||||
ObjectGuid guid = questGiver->GetGUID();
|
||||
uint32 npcflagmask = UNIT_NPC_FLAG_QUESTGIVER;
|
||||
// unit checks
|
||||
if (!guid)
|
||||
return false;
|
||||
|
||||
if (!bot->IsInWorld())
|
||||
return false;
|
||||
|
||||
if (bot->IsInFlight())
|
||||
return false;
|
||||
|
||||
// exist (we need look pets also for some interaction (quest/etc)
|
||||
Creature* creature = ObjectAccessor::GetCreatureOrPetOrVehicle(*bot, guid);
|
||||
if (!creature)
|
||||
return false;
|
||||
|
||||
// Deathstate checks
|
||||
if (!bot->IsAlive() && !(creature->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_VISIBLE_TO_GHOSTS))
|
||||
return false;
|
||||
|
||||
// alive or spirit healer
|
||||
if (!creature->IsAlive() && !(creature->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_INTERACT_WHILE_DEAD))
|
||||
return false;
|
||||
|
||||
// appropriate npc type
|
||||
if (npcflagmask && !creature->HasNpcFlag(NPCFlags(npcflagmask)))
|
||||
return false;
|
||||
|
||||
// not allow interaction under control, but allow with own pets
|
||||
if (creature->GetCharmerGUID())
|
||||
return false;
|
||||
|
||||
// xinef: perform better check
|
||||
if (creature->GetReactionTo(bot) <= REP_UNFRIENDLY)
|
||||
return false;
|
||||
|
||||
// pussywizard: many npcs have missing conditions for class training and rogue trainer can for eg. train dual wield to a shaman :/ too many to change in sql and watch in the future
|
||||
// pussywizard: this function is not used when talking, but when already taking action (buy spell, reset talents, show spell list)
|
||||
if (npcflagmask & (UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_TRAINER_CLASS) && creature->GetCreatureTemplate()->trainer_type == TRAINER_TYPE_CLASS && !bot->IsClass((Classes)creature->GetCreatureTemplate()->trainer_class, CLASS_CONTEXT_CLASS_TRAINER))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
case TYPEID_GAMEOBJECT:
|
||||
{
|
||||
ObjectGuid guid = questGiver->GetGUID();
|
||||
GameobjectTypes type = GAMEOBJECT_TYPE_QUESTGIVER;
|
||||
if (GameObject* go = bot->GetMap()->GetGameObject(guid))
|
||||
{
|
||||
if (go->GetGoType() == type)
|
||||
{
|
||||
// Players cannot interact with gameobjects that use the "Point" icon
|
||||
if (go->GetGOInfo()->IconName == "Point")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// unused for now
|
||||
// case TYPEID_PLAYER:
|
||||
// return bot->IsAlive() && questGiver->ToPlayer()->IsAlive();
|
||||
// case TYPEID_ITEM:
|
||||
// return bot->IsAlive();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NewRpgBaseAction::IsWithinInteractionDist(Object* questGiver)
|
||||
{
|
||||
// This is a variant of Player::CanInteractWithQuestGiver
|
||||
// that only keep the distance check
|
||||
switch (questGiver->GetTypeId())
|
||||
{
|
||||
case TYPEID_UNIT:
|
||||
{
|
||||
ObjectGuid guid = questGiver->GetGUID();
|
||||
// unit checks
|
||||
if (!guid)
|
||||
return false;
|
||||
|
||||
// exist (we need look pets also for some interaction (quest/etc)
|
||||
Creature* creature = ObjectAccessor::GetCreatureOrPetOrVehicle(*bot, guid);
|
||||
if (!creature)
|
||||
return false;
|
||||
|
||||
if (!creature->IsWithinDistInMap(bot, INTERACTION_DISTANCE))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
case TYPEID_GAMEOBJECT:
|
||||
{
|
||||
ObjectGuid guid = questGiver->GetGUID();
|
||||
GameobjectTypes type = GAMEOBJECT_TYPE_QUESTGIVER;
|
||||
if (GameObject* go = bot->GetMap()->GetGameObject(guid))
|
||||
{
|
||||
if (go->IsWithinDistInMap(bot))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// case TYPEID_PLAYER:
|
||||
// return bot->IsAlive() && questGiver->ToPlayer()->IsAlive();
|
||||
// case TYPEID_ITEM:
|
||||
// return bot->IsAlive();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NewRpgBaseAction::AcceptQuest(Quest const* quest, ObjectGuid guid)
|
||||
{
|
||||
WorldPacket p(CMSG_QUESTGIVER_ACCEPT_QUEST);
|
||||
@@ -283,7 +411,7 @@ bool NewRpgBaseAction::TurnInQuest(Quest const* quest, ObjectGuid guid)
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 bestId = BestReward(quest);
|
||||
uint32 bestId = BestRewardIndex(quest);
|
||||
p << bestId;
|
||||
bot->GetSession()->HandleQuestgiverChooseRewardOpcode(p);
|
||||
}
|
||||
@@ -291,7 +419,7 @@ bool NewRpgBaseAction::TurnInQuest(Quest const* quest, ObjectGuid guid)
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 NewRpgBaseAction::BestReward(Quest const* quest)
|
||||
uint32 NewRpgBaseAction::BestRewardIndex(Quest const* quest)
|
||||
{
|
||||
ItemIds returnIds;
|
||||
ItemUsage bestUsage = ITEM_USAGE_NONE;
|
||||
@@ -486,7 +614,7 @@ ObjectGuid NewRpgBaseAction::ChooseNpcOrGameObjectToInteract(bool questgiverOnly
|
||||
if (distanceLimit && bot->GetDistance(object) > distanceLimit)
|
||||
continue;
|
||||
|
||||
if (HasQuestToAcceptOrReward(object))
|
||||
if (CanInteractWithQuestGiver(object) && HasQuestToAcceptOrReward(object))
|
||||
{
|
||||
if (!nearestObject || bot->GetExactDist(nearestObject) > bot->GetExactDist(object))
|
||||
nearestObject = object;
|
||||
@@ -504,7 +632,7 @@ ObjectGuid NewRpgBaseAction::ChooseNpcOrGameObjectToInteract(bool questgiverOnly
|
||||
if (distanceLimit && bot->GetDistance(object) > distanceLimit)
|
||||
continue;
|
||||
|
||||
if (HasQuestToAcceptOrReward(object))
|
||||
if (CanInteractWithQuestGiver(object) && HasQuestToAcceptOrReward(object))
|
||||
{
|
||||
if (!nearestObject || bot->GetExactDist(nearestObject) > bot->GetExactDist(object))
|
||||
nearestObject = object;
|
||||
|
||||
@@ -32,16 +32,19 @@ protected:
|
||||
bool MoveRandomNear(float moveStep = 50.0f, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL);
|
||||
bool ForceToWait(uint32 duration, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL);
|
||||
|
||||
// QUEST RELATED
|
||||
bool SearchQuestGiverAndAcceptOrReward();
|
||||
// QUEST RELATED CHECK
|
||||
ObjectGuid ChooseNpcOrGameObjectToInteract(bool questgiverOnly = false, float distanceLimit = 0.0f);
|
||||
bool HasQuestToAcceptOrReward(WorldObject* object);
|
||||
bool InteractWithNpcOrGameObjectForQuest(ObjectGuid guid);
|
||||
bool AcceptQuest(Quest const* quest, ObjectGuid guid);
|
||||
bool TurnInQuest(Quest const* quest, ObjectGuid guid);
|
||||
uint32 BestReward(Quest const* quest);
|
||||
bool CanInteractWithQuestGiver(Object* questGiver);
|
||||
bool IsWithinInteractionDist(Object* object);
|
||||
uint32 BestRewardIndex(Quest const* quest);
|
||||
bool IsQuestWorthDoing(Quest const* quest);
|
||||
bool IsQuestCapableDoing(Quest const* quest);
|
||||
// QUEST RELATED ACTION
|
||||
bool SearchQuestGiverAndAcceptOrReward();
|
||||
bool AcceptQuest(Quest const* quest, ObjectGuid guid);
|
||||
bool TurnInQuest(Quest const* quest, ObjectGuid guid);
|
||||
bool OrganizeQuestLog();
|
||||
|
||||
protected:
|
||||
|
||||
@@ -21,6 +21,9 @@ Unit* FlagCarrierValue::Calculate()
|
||||
{
|
||||
BattlegroundWS* bg = (BattlegroundWS*)botAI->GetBot()->GetBattleground();
|
||||
|
||||
if (!bg)
|
||||
return nullptr;
|
||||
|
||||
if ((!sameTeam && bot->GetTeamId() == TEAM_HORDE || (sameTeam && bot->GetTeamId() == TEAM_ALLIANCE)) &&
|
||||
!bg->GetFlagPickerGUID(TEAM_HORDE).IsEmpty())
|
||||
carrier = ObjectAccessor::GetPlayer(bg->GetBgMap(), bg->GetFlagPickerGUID(TEAM_HORDE));
|
||||
@@ -44,6 +47,9 @@ Unit* FlagCarrierValue::Calculate()
|
||||
{
|
||||
BattlegroundEY* bg = (BattlegroundEY*)botAI->GetBot()->GetBattleground();
|
||||
|
||||
if (!bg)
|
||||
return nullptr;
|
||||
|
||||
if (bg->GetFlagPickerGUID().IsEmpty())
|
||||
return nullptr;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user