Icecrown gunship strategy

This commit is contained in:
Yunfan Li
2024-09-23 13:58:59 +08:00
parent 2cb6f14dad
commit b87ca9da4c
18 changed files with 344 additions and 39 deletions

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,124 @@
#include "RaidIccActions.h"
#include "Playerbots.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;
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();
// Use HandleSpellClick instead of Unit::EnterVehicle to handle special vehicle script (ulduar)
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