Merge pull request #546 from liyunfan1223/icc_gunship

Icecrown gunship cannon usage
This commit is contained in:
Yunfan Li
2024-09-23 19:35:02 +08:00
committed by GitHub
19 changed files with 357 additions and 40 deletions

View File

@@ -15,7 +15,7 @@ jobs:
fail-fast: false
matrix:
os:
- macos-12
- macos-14
runs-on: ${{ matrix.os }}
name: ${{ matrix.os }}
steps:

View File

@@ -43,6 +43,7 @@
#include "SharedDefines.h"
#include "SocialMgr.h"
#include "SpellAuraEffects.h"
#include "Transport.h"
#include "Unit.h"
#include "UpdateTime.h"
#include "Vehicle.h"
@@ -324,6 +325,30 @@ void PlayerbotAI::UpdateAI(uint32 elapsed, bool minimal)
return;
}
if (nextTransportCheck > elapsed)
nextTransportCheck -= elapsed;
else
nextTransportCheck = 0;
if (!nextTransportCheck)
{
nextTransportCheck = 1000;
Transport* newTransport = bot->GetMap()->GetTransportForPos(bot->GetPhaseMask(), bot->GetPositionX(),
bot->GetPositionY(), bot->GetPositionZ(), bot);
if (newTransport != bot->GetTransport())
{
LOG_DEBUG("playerbots", "Bot {} is on a transport", bot->GetName());
if (bot->GetTransport())
bot->GetTransport()->RemovePassenger(bot, true);
if (newTransport)
newTransport->AddPassenger(bot, true);
bot->StopMovingOnCurrentPos();
}
}
if (!CanUpdateAI())
return;
@@ -1488,20 +1513,23 @@ void PlayerbotAI::ApplyInstanceStrategies(uint32 mapId, bool tellMaster)
std::string strategyName;
switch (mapId)
{
case 409:
strategyName = "mc";
break;
case 469:
strategyName = "bwl";
break;
case 509:
strategyName = "aq20";
break;
case 533:
strategyName = "naxx";
break;
case 603:
strategyName = "uld";
break;
case 469:
strategyName = "bwl";
break;
case 409:
strategyName = "mc";
break;
case 509:
strategyName = "aq20";
case 631:
strategyName = "icc";
break;
default:
break;

View File

@@ -603,6 +603,7 @@ protected:
bool inCombat = false;
BotCheatMask cheatMask = BotCheatMask::none;
Position jumpDestination = Position();
uint32 nextTransportCheck = 0;
};
#endif

View File

@@ -9,6 +9,8 @@
#include "ChatActionContext.h"
#include "ChatTriggerContext.h"
#include "Playerbots.h"
#include "RaidIccActionContext.h"
#include "RaidIccTriggerContext.h"
#include "RaidUlduarTriggerContext.h"
#include "RaidUlduarActionContext.h"
#include "SharedValueContext.h"
@@ -38,20 +40,22 @@ AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
actionContexts.Add(new ActionContext());
actionContexts.Add(new ChatActionContext());
actionContexts.Add(new WorldPacketActionContext());
actionContexts.Add(new RaidMcActionContext());
actionContexts.Add(new RaidBwlActionContext());
actionContexts.Add(new RaidAq20ActionContext());
actionContexts.Add(new RaidNaxxActionContext());
actionContexts.Add(new RaidUlduarActionContext());
actionContexts.Add(new RaidMcActionContext());
actionContexts.Add(new RaidAq20ActionContext());
actionContexts.Add(new RaidIccActionContext());
triggerContexts.Add(new TriggerContext());
triggerContexts.Add(new ChatTriggerContext());
triggerContexts.Add(new WorldPacketTriggerContext());
triggerContexts.Add(new RaidMcTriggerContext());
triggerContexts.Add(new RaidBwlTriggerContext());
triggerContexts.Add(new RaidAq20TriggerContext());
triggerContexts.Add(new RaidNaxxTriggerContext());
triggerContexts.Add(new RaidUlduarTriggerContext());
triggerContexts.Add(new RaidMcTriggerContext());
triggerContexts.Add(new RaidAq20TriggerContext());
triggerContexts.Add(new RaidIccTriggerContext());
valueContexts.Add(new ValueContext());

View File

@@ -30,6 +30,7 @@ bool ChangeTalentsAction::Execute(Event event)
{
bot->ActivateSpec(0);
out << "Active first talent";
botAI->ResetStrategies();
}
else if (param.find("switch 2") != std::string::npos)
{
@@ -40,6 +41,7 @@ bool ChangeTalentsAction::Execute(Event event)
}
bot->ActivateSpec(1);
out << "Active second talent";
botAI->ResetStrategies();
}
}
else if (param.find("autopick") != std::string::npos)
@@ -47,6 +49,7 @@ bool ChangeTalentsAction::Execute(Event event)
PlayerbotFactory factory(bot, bot->GetLevel());
factory.InitTalentsTree(true);
out << "Auto pick talents";
botAI->ResetStrategies();
}
else if (param.find("spec list") != std::string::npos)
{

View File

@@ -963,20 +963,6 @@ void MovementAction::UpdateMovementState()
{
bot->RemoveUnitMovementFlag(MOVEMENTFLAG_FLYING);
}
Transport* newTransport = bot->GetMap()->GetTransportForPos(bot->GetPhaseMask(), bot->GetPositionX(),
bot->GetPositionY(), bot->GetPositionZ(), bot);
if (newTransport != bot->GetTransport())
{
LOG_DEBUG("playerbots", "Bot {} is on a transport", bot->GetName());
if (bot->GetTransport())
bot->GetTransport()->RemovePassenger(bot, true);
if (newTransport)
newTransport->AddPassenger(bot, true);
bot->StopMovingOnCurrentPos();
}
bot->SendMovementFlagUpdate();
// Temporary speed increase in group

View File

@@ -7,6 +7,7 @@
#include "RaidNaxxStrategy.h"
#include "RaidMcStrategy.h"
#include "RaidAq20Strategy.h"
#include "RaidIccStrategy.h"
class RaidStrategyContext : public NamedObjectContext<Strategy>
{
@@ -16,19 +17,21 @@ public:
// TODO should we give these prefixes (eg: "naxx" -> "raid naxx")? because if we don't it's going to end up
// very crowded (with possible conflicts) once we have strats for all raids and some dungeons
// (mc already very similiar to nc)
creators["naxx"] = &RaidStrategyContext::naxx;
creators["bwl"] = &RaidStrategyContext::bwl;
creators["uld"] = &RaidStrategyContext::uld;
creators["mc"] = &RaidStrategyContext::mc;
creators["bwl"] = &RaidStrategyContext::bwl;
creators["aq20"] = &RaidStrategyContext::aq20;
creators["naxx"] = &RaidStrategyContext::naxx;
creators["uld"] = &RaidStrategyContext::uld;
creators["icc"] = &RaidStrategyContext::icc;
}
private:
static Strategy* naxx(PlayerbotAI* botAI) { return new RaidNaxxStrategy(botAI); }
static Strategy* bwl(PlayerbotAI* botAI) { return new RaidBwlStrategy(botAI); }
static Strategy* uld(PlayerbotAI* botAI) { return new RaidUlduarStrategy(botAI); }
static Strategy* mc(PlayerbotAI* botAI) { return new RaidMcStrategy(botAI); }
static Strategy* bwl(PlayerbotAI* botAI) { return new RaidBwlStrategy(botAI); }
static Strategy* aq20(PlayerbotAI* botAI) { return new RaidAq20Strategy(botAI); }
static Strategy* naxx(PlayerbotAI* botAI) { return new RaidNaxxStrategy(botAI); }
static Strategy* uld(PlayerbotAI* botAI) { return new RaidUlduarStrategy(botAI); }
static Strategy* icc(PlayerbotAI* botAI) { return new RaidIccStrategy(botAI); }
};
#endif

View File

@@ -0,0 +1,22 @@
#ifndef _PLAYERBOT_RAIDICCACTIONCONTEXT_H
#define _PLAYERBOT_RAIDICCACTIONCONTEXT_H
#include "Action.h"
#include "NamedObjectContext.h"
#include "RaidIccActions.h"
class RaidIccActionContext : public NamedObjectContext<Action>
{
public:
RaidIccActionContext()
{
creators["icc cannon fire"] = &RaidIccActionContext::icc_cannon_fire;
creators["icc gunship enter cannon"] = &RaidIccActionContext::icc_gunship_enter_cannon;
}
private:
static Action* icc_cannon_fire(PlayerbotAI* ai) { return new IccCannonFireAction(ai); }
static Action* icc_gunship_enter_cannon(PlayerbotAI* ai) { return new IccGunshipEnterCannonAction(ai); }
};
#endif

View File

@@ -0,0 +1,136 @@
#include "RaidIccActions.h"
#include "Playerbots.h"
#include "Timer.h"
#include "Vehicle.h"
enum CreatureIds {
NPC_KOR_KRON_BATTLE_MAGE = 37117,
NPC_KOR_KRON_AXETHROWER = 36968,
NPC_KOR_KRON_ROCKETEER = 36982,
NPC_SKYBREAKER_SORCERER = 37116,
NPC_SKYBREAKER_RIFLEMAN = 36969,
NPC_SKYBREAKER_MORTAR_SOLDIER = 36978,
NPC_IGB_HIGH_OVERLORD_SAURFANG = 36939,
NPC_IGB_MURADIN_BRONZEBEARD = 36948,
};
const std::vector<uint32> availableTargets = {
NPC_KOR_KRON_AXETHROWER, NPC_KOR_KRON_ROCKETEER, NPC_KOR_KRON_BATTLE_MAGE,
NPC_IGB_HIGH_OVERLORD_SAURFANG, NPC_SKYBREAKER_RIFLEMAN, NPC_SKYBREAKER_MORTAR_SOLDIER,
NPC_SKYBREAKER_SORCERER, NPC_IGB_MURADIN_BRONZEBEARD
};
bool IccCannonFireAction::Execute(Event event)
{
Unit* vehicleBase = bot->GetVehicleBase();
Vehicle* vehicle = bot->GetVehicle();
if (!vehicleBase || !vehicle)
return false;
GuidVector attackers = AI_VALUE(GuidVector, "possible targets no los");
Unit* target = nullptr;
for (auto i = attackers.begin(); i != attackers.end(); ++i)
{
Unit* unit = botAI->GetUnit(*i);
if (!unit)
continue;
for (uint32 entry : availableTargets)
{
if (unit->GetEntry() == entry) {
target = unit;
break;
}
}
if (target)
break;
}
if (!target)
return false;
if (vehicleBase->GetPower(POWER_ENERGY) >= 90) {
uint32 spellId = AI_VALUE2(uint32, "vehicle spell id", "incinerating blast");
if (botAI->CanCastVehicleSpell(spellId, target) && botAI->CastVehicleSpell(spellId, target)) {
vehicleBase->AddSpellCooldown(spellId, 0, 1000);
return true;
}
}
uint32 spellId = AI_VALUE2(uint32, "vehicle spell id", "cannon blast");
if (botAI->CanCastVehicleSpell(spellId, target) && botAI->CastVehicleSpell(spellId, target)) {
vehicleBase->AddSpellCooldown(spellId, 0, 1000);
return true;
}
return false;
}
bool IccGunshipEnterCannonAction::Execute(Event event)
{
// do not switch vehicles yet
if (bot->GetVehicle())
return false;
Unit* vehicleToEnter = nullptr;
GuidVector npcs = AI_VALUE(GuidVector, "nearest vehicles");
for (GuidVector::iterator i = npcs.begin(); i != npcs.end(); i++)
{
Unit* vehicleBase = botAI->GetUnit(*i);
if (!vehicleBase)
continue;
if (vehicleBase->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE))
continue;
if (!vehicleBase->IsFriendlyTo(bot))
continue;
if (!vehicleBase->GetVehicleKit() || !vehicleBase->GetVehicleKit()->GetAvailableSeatCount())
continue;
uint32 entry = vehicleBase->GetEntry();
if (entry != 36838 && entry != 36839)
continue;
if (vehicleBase->HasAura(69704) || vehicleBase->HasAura(69705))
continue;
if (!vehicleToEnter || bot->GetExactDist(vehicleToEnter) > bot->GetExactDist(vehicleBase))
vehicleToEnter = vehicleBase;
}
if (!vehicleToEnter)
return false;
if (EnterVehicle(vehicleToEnter, true))
return true;
return false;
}
bool IccGunshipEnterCannonAction::EnterVehicle(Unit* vehicleBase, bool moveIfFar)
{
float dist = bot->GetDistance(vehicleBase);
if (dist > INTERACTION_DISTANCE && !moveIfFar)
return false;
if (dist > INTERACTION_DISTANCE)
return MoveTo(vehicleBase);
botAI->RemoveShapeshift();
bot->GetMotionMaster()->Clear();
bot->StopMoving();
vehicleBase->HandleSpellClick(bot);
if (!bot->IsOnVehicle(vehicleBase))
return false;
// dismount because bots can enter vehicle on mount
WorldPacket emptyPacket;
bot->GetSession()->HandleCancelMountAuraOpcode(emptyPacket);
return true;
}

View File

@@ -0,0 +1,25 @@
#ifndef _PLAYERBOT_RAIDICCACTIONS_H
#define _PLAYERBOT_RAIDICCACTIONS_H
#include "MovementActions.h"
#include "PlayerbotAI.h"
#include "Playerbots.h"
class IccCannonFireAction : public Action
{
public:
IccCannonFireAction(PlayerbotAI* botAI, std::string const name = "icc cannon fire")
: Action(botAI, name) {}
bool Execute(Event event) override;
};
class IccGunshipEnterCannonAction : public MovementAction
{
public:
IccGunshipEnterCannonAction(PlayerbotAI* botAI, std::string const name = "icc gunship enter cannon")
: MovementAction(botAI, name) {}
bool Execute(Event event) override;
bool EnterVehicle(Unit* vehicleBase, bool moveIfFar);
};
#endif

View File

@@ -0,0 +1,6 @@
#ifndef _PLAYERBOT_RAIDICCSCRIPTS_H
#define _PLAYERBOT_RAIDICCSCRIPTS_H
#include "../../../../src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h"
#endif

View File

@@ -0,0 +1,14 @@
#include "RaidIccStrategy.h"
#include "Strategy.h"
void RaidIccStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
triggers.push_back(new TriggerNode(
"icc gunship cannon near",
NextAction::array(0, new NextAction("icc gunship enter cannon", ACTION_RAID + 2), nullptr)));
triggers.push_back(
new TriggerNode("icc in cannon",
NextAction::array(0, new NextAction("icc cannon fire", ACTION_RAID), nullptr)));
}

View File

@@ -0,0 +1,17 @@
#ifndef _PLAYERBOT_RAIDICCSTRATEGY_H
#define _PLAYERBOT_RAIDICCSTRATEGY_H
#include "AiObjectContext.h"
#include "Multiplier.h"
#include "Strategy.h"
class RaidIccStrategy : public Strategy
{
public:
RaidIccStrategy(PlayerbotAI* ai) : Strategy(ai) {}
virtual std::string const getName() override { return "icc"; }
virtual void InitTriggers(std::vector<TriggerNode*>& triggers) override;
// virtual void InitMultipliers(std::vector<Multiplier*> &multipliers) override;
};
#endif

View File

@@ -0,0 +1,22 @@
#ifndef _PLAYERBOT_RAIDICCTRIGGERCONTEXT_H
#define _PLAYERBOT_RAIDICCTRIGGERCONTEXT_H
#include "AiObjectContext.h"
#include "NamedObjectContext.h"
#include "RaidIccTriggers.h"
class RaidIccTriggerContext : public NamedObjectContext<Trigger>
{
public:
RaidIccTriggerContext()
{
creators["icc in cannon"] = &RaidIccTriggerContext::icc_in_cannon;
creators["icc gunship cannon near"] = &RaidIccTriggerContext::icc_gunship_cannon_near;
}
private:
static Trigger* icc_in_cannon(PlayerbotAI* ai) { return new IccInCannonTrigger(ai); }
static Trigger* icc_gunship_cannon_near(PlayerbotAI* ai) { return new IccGunshipCannonNearTrigger(ai); }
};
#endif

View File

@@ -0,0 +1,29 @@
#include "RaidIccTriggers.h"
bool IccInCannonTrigger::IsActive()
{
Unit* vehicleBase = bot->GetVehicleBase();
Vehicle* vehicle = bot->GetVehicle();
if (!vehicleBase || !vehicle)
return false;
uint32 entry = vehicleBase->GetEntry();
return entry == 36838 || entry == 36839;
}
bool IccGunshipCannonNearTrigger::IsActive()
{
if (bot->GetVehicle())
return false;
if (!botAI->IsDps(bot))
return false;
// Player* master = botAI->GetMaster();
// if (!master)
// return false;
// if (!master->GetVehicle())
// return false;
return true;
}

View File

@@ -0,0 +1,23 @@
#ifndef _PLAYERBOT_RAIDICCTRIGGERS_H
#define _PLAYERBOT_RAIDICCTRIGGERS_H
#include "PlayerbotAI.h"
#include "Playerbots.h"
#include "Trigger.h"
class IccInCannonTrigger : public Trigger
{
public:
IccInCannonTrigger(PlayerbotAI* botAI) : Trigger(botAI, "icc in cannon") {}
bool IsActive() override;
};
class IccGunshipCannonNearTrigger : public Trigger
{
public:
IccGunshipCannonNearTrigger(PlayerbotAI* botAI) : Trigger(botAI, "icc in cannon") {}
bool IsActive() override;
};
#endif

View File

@@ -111,7 +111,7 @@ bool FlameLeviathanVehicleAction::DemolisherAction(Unit* target)
if (!target)
return false;
Aura* bluePyrite = target->GetAura(68605);
if (!bluePyrite || (bluePyrite->GetStackAmount() <= 6 && vehicleBase_->GetPower(POWER_ENERGY) > 25) || bluePyrite->GetDuration() <= 5000)
if (!bluePyrite || (vehicleBase_->GetPower(POWER_ENERGY) >= 20) || bluePyrite->GetDuration() <= 5000)
{
uint32 spellId = 62490;
if (botAI->CanCastVehicleSpell(spellId, target))

View File

@@ -1,8 +1,6 @@
#ifndef _PLAYERBOT_RAIDULDUARSCRIPTS_H
#define _PLAYERBOT_RAIDULDUARSCRIPTS_H
// There are no header files for bosses in Ulduar directory
//#include "../../../../src/server/scripts/Northrend/Ulduar/Ulduar/"
#include "../../../../src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h"
#endif

View File

@@ -120,8 +120,8 @@ public:
creators["guild leave"] = &ChatTriggerContext::guild_leave;
creators["rtsc"] = &ChatTriggerContext::rtsc;
creators["drink"] = &ChatTriggerContext::drink;
creators["naxx"] = &ChatTriggerContext::naxx;
creators["bwl"] = &ChatTriggerContext::bwl;
// creators["naxx"] = &ChatTriggerContext::naxx;
// creators["bwl"] = &ChatTriggerContext::bwl;
creators["dps"] = &ChatTriggerContext::dps;
creators["disperse"] = &ChatTriggerContext::disperse;
creators["calc"] = &ChatTriggerContext::calc;
@@ -224,8 +224,8 @@ private:
static Trigger* guild_leave(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "guild leave"); }
static Trigger* rtsc(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "rtsc"); }
static Trigger* drink(PlayerbotAI* ai) { return new ChatCommandTrigger(ai, "drink"); }
static Trigger* naxx(PlayerbotAI* ai) { return new ChatCommandTrigger(ai, "naxx"); }
static Trigger* bwl(PlayerbotAI* ai) { return new ChatCommandTrigger(ai, "bwl"); }
// static Trigger* naxx(PlayerbotAI* ai) { return new ChatCommandTrigger(ai, "naxx"); }
// static Trigger* bwl(PlayerbotAI* ai) { return new ChatCommandTrigger(ai, "bwl"); }
static Trigger* dps(PlayerbotAI* ai) { return new ChatCommandTrigger(ai, "dps"); }
static Trigger* disperse(PlayerbotAI* ai) { return new ChatCommandTrigger(ai, "disperse"); }
static Trigger* calc(PlayerbotAI* ai) { return new ChatCommandTrigger(ai, "calc"); }