mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-13 09:17:18 +00:00
Merge branch 'azerothcore:master' into Playerbot
This commit is contained in:
@@ -287,7 +287,7 @@ bool DBUpdater<T>::Update(DatabaseWorkerPool<T>& pool, std::string_view modulesL
|
||||
|
||||
if (!is_directory(sourceDirectory))
|
||||
{
|
||||
LOG_ERROR("sql.updates", "DBUpdater: The given source directory {} does not exist, change the path to the directory where your sql directory exists (for example c:\\source\\trinitycore). Shutting down.",
|
||||
LOG_ERROR("sql.updates", "DBUpdater: The given source directory {} does not exist, change the path to the directory where your sql directory exists (for example c:\\source\\azerothcore). Shutting down.",
|
||||
sourceDirectory.generic_string());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -811,20 +811,6 @@ void SmartAI::JustSummoned(Creature* creature)
|
||||
{
|
||||
GetScript()->ProcessEventsFor(SMART_EVENT_SUMMONED_UNIT, creature);
|
||||
GetScript()->AddCreatureSummon(creature->GetGUID());
|
||||
|
||||
if (me->IsEngaged() && !creature->IsInEvadeMode())
|
||||
{
|
||||
if (Unit* victim = me->GetVictim())
|
||||
{
|
||||
creature->SetInCombatWith(victim);
|
||||
victim->SetInCombatWith(creature);
|
||||
|
||||
if (creature->CanHaveThreatList())
|
||||
{
|
||||
creature->AddThreat(victim, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SmartAI::SummonedCreatureDies(Creature* summon, Unit* /*killer*/)
|
||||
|
||||
@@ -1613,7 +1613,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
e.GetTargetType() == SMART_TARGET_CLOSEST_CREATURE || e.GetTargetType() == SMART_TARGET_CLOSEST_GAMEOBJECT ||
|
||||
e.GetTargetType() == SMART_TARGET_OWNER_OR_SUMMONER || e.GetTargetType() == SMART_TARGET_ACTION_INVOKER ||
|
||||
e.GetTargetType() == SMART_TARGET_CLOSEST_ENEMY || e.GetTargetType() == SMART_TARGET_CLOSEST_FRIENDLY ||
|
||||
e.GetTargetType() == SMART_TARGET_SELF || e.GetTargetType() == SMART_TARGET_STORED) // Xinef: bieda i rozpierdol TC)*/
|
||||
e.GetTargetType() == SMART_TARGET_SELF || e.GetTargetType() == SMART_TARGET_STORED)) */
|
||||
{
|
||||
// we want to move to random element
|
||||
if (!targets.empty())
|
||||
@@ -2688,6 +2688,31 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_SET_GUID:
|
||||
{
|
||||
for (WorldObject* target : targets)
|
||||
{
|
||||
ObjectGuid guidToSend = me ? me->GetGUID() : go->GetGUID();
|
||||
|
||||
if (e.action.setGuid.invokerGUID)
|
||||
{
|
||||
if (Unit* invoker = GetLastInvoker())
|
||||
{
|
||||
guidToSend = invoker->GetGUID();
|
||||
}
|
||||
}
|
||||
|
||||
if (Creature* creature = target->ToCreature())
|
||||
{
|
||||
creature->AI()->SetGUID(guidToSend, e.action.setGuid.index);
|
||||
}
|
||||
else if (GameObject* object = target->ToGameObject())
|
||||
{
|
||||
object->AI()->SetGUID(guidToSend, e.action.setGuid.index);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry {} SourceType {}, Event {}, Unhandled Action type {}", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
|
||||
break;
|
||||
@@ -4302,7 +4327,17 @@ void SmartScript::GetScript()
|
||||
e = sSmartScriptMgr->GetScript(-((int32)me->GetSpawnId()), mScriptType);
|
||||
if (e.empty())
|
||||
e = sSmartScriptMgr->GetScript((int32)me->GetEntry(), mScriptType);
|
||||
|
||||
FillScript(e, me, nullptr);
|
||||
|
||||
if (CreatureTemplate const* cInfo = me->GetCreatureTemplate())
|
||||
{
|
||||
if (cInfo->HasFlagsExtra(CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI))
|
||||
{
|
||||
e = sSmartScriptMgr->GetScript((int32)me->GetEntry(), mScriptType);
|
||||
FillScript(e, me, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (go)
|
||||
{
|
||||
|
||||
@@ -288,7 +288,6 @@ void SmartAIMgr::LoadSmartAIFromDB()
|
||||
break;
|
||||
}
|
||||
|
||||
// xinef: rozpierdol tc, niedojeby ze szok
|
||||
if (temp.action.type == SMART_ACTION_MOVE_TO_POS)
|
||||
if (temp.target.type == SMART_TARGET_SELF && (std::fabs(temp.target.x) > 200.0f || std::fabs(temp.target.y) > 200.0f || std::fabs(temp.target.z) > 200.0f))
|
||||
temp.target.type = SMART_TARGET_POSITION;
|
||||
@@ -762,6 +761,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
|
||||
case SMART_ACTION_ZONE_UNDER_ATTACK: return NO_PARAMS;
|
||||
case SMART_ACTION_LOAD_GRID: return NO_PARAMS;
|
||||
case SMART_ACTION_MUSIC: return sizeof(SmartAction::music);
|
||||
case SMART_ACTION_SET_GUID: return sizeof(SmartAction::setGuid);
|
||||
default:
|
||||
LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using an action with no unused params specified in SmartAIMgr::CheckUnusedActionParams(), please report this.",
|
||||
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
|
||||
@@ -1914,6 +1914,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
case SMART_ACTION_SET_CORPSE_DELAY:
|
||||
case SMART_ACTION_ATTACK_STOP:
|
||||
case SMART_ACTION_PLAY_CINEMATIC:
|
||||
case SMART_ACTION_SET_GUID:
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("sql.sql", "SmartAIMgr: Not handled action_type({}), event_type({}), Entry {} SourceType {} Event {}, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id);
|
||||
|
||||
@@ -692,8 +692,9 @@ enum SMART_ACTION
|
||||
SMART_ACTION_CU_ENCOUNTER_START = 222, // Resets cooldowns on all targets and removes Heroism debuff(s)
|
||||
SMART_ACTION_DO_ACTION = 223, // ActionId
|
||||
SMART_ACTION_ATTACK_STOP = 224, //
|
||||
SMART_ACTION_SET_GUID = 225, // Sends the invoker's or the base object's own ObjectGuid to target
|
||||
|
||||
SMART_ACTION_AC_END = 225, // placeholder
|
||||
SMART_ACTION_AC_END = 226, // placeholder
|
||||
};
|
||||
|
||||
enum class SmartActionSummonCreatureFlags
|
||||
@@ -1357,6 +1358,12 @@ struct SmartAction
|
||||
{
|
||||
uint32 entry;
|
||||
} cinematic;
|
||||
|
||||
struct
|
||||
{
|
||||
SAIBool invokerGUID;
|
||||
uint32 index;
|
||||
} setGuid;
|
||||
//! Note for any new future actions
|
||||
//! All parameters must have type uint32
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ static ChatSubCommandMap COMMAND_MAP;
|
||||
if (std::holds_alternative<std::monostate>(cmd->_help))
|
||||
cmd->_help.emplace<std::string>(help);
|
||||
else
|
||||
LOG_ERROR("sql.sql", "Table `command` contains legacy help text for command '{}', which uses `trinity_string`. Skipped.", name);
|
||||
LOG_ERROR("sql.sql", "Table `command` contains legacy help text for command '{}', which uses `acore_string`. Skipped.", name);
|
||||
} while (result->NextRow());
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ enum CreatureFlagsExtra : uint32
|
||||
CREATURE_FLAG_EXTRA_NO_DODGE = 0x00800000, // xinef: target cannot dodge
|
||||
CREATURE_FLAG_EXTRA_MODULE = 0x01000000,
|
||||
CREATURE_FLAG_EXTRA_IGNORE_ASSISTANCE_CALL = 0x02000000, // Creatures are not aggroed by other mobs assistance functions
|
||||
CREATURE_FLAG_EXTRA_UNUSED_27 = 0x04000000,
|
||||
CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI = 0x04000000, // Load both ENTRY and GUID specific SAI
|
||||
CREATURE_FLAG_EXTRA_UNUSED_28 = 0x08000000,
|
||||
CREATURE_FLAG_EXTRA_DUNGEON_BOSS = 0x10000000, // creature is a dungeon boss (SET DYNAMICALLY, DO NOT ADD IN DB)
|
||||
CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING = 0x20000000, // creature ignore pathfinding
|
||||
@@ -80,7 +80,7 @@ enum CreatureFlagsExtra : uint32
|
||||
CREATURE_FLAG_EXTRA_HARD_RESET = 0x80000000,
|
||||
|
||||
// Masks
|
||||
CREATURE_FLAG_EXTRA_UNUSED = (CREATURE_FLAG_EXTRA_UNUSED_12 | CREATURE_FLAG_EXTRA_UNUSED_27 | CREATURE_FLAG_EXTRA_UNUSED_28), // SKIP
|
||||
CREATURE_FLAG_EXTRA_UNUSED = (CREATURE_FLAG_EXTRA_UNUSED_12 | CREATURE_FLAG_EXTRA_UNUSED_28), // SKIP
|
||||
|
||||
CREATURE_FLAG_EXTRA_DB_ALLOWED = (0xFFFFFFFF & ~(CREATURE_FLAG_EXTRA_UNUSED | CREATURE_FLAG_EXTRA_DUNGEON_BOSS)) // SKIP
|
||||
};
|
||||
|
||||
@@ -57,7 +57,7 @@ AC_API_EXPORT EnumText EnumUtils<CreatureFlagsExtra>::ToString(CreatureFlagsExtr
|
||||
case CREATURE_FLAG_EXTRA_NO_DODGE: return { "CREATURE_FLAG_EXTRA_NO_DODGE", "CREATURE_FLAG_EXTRA_NO_DODGE", "xinef: target cannot dodge" };
|
||||
case CREATURE_FLAG_EXTRA_MODULE: return { "CREATURE_FLAG_EXTRA_MODULE", "CREATURE_FLAG_EXTRA_MODULE", "Used by module creatures to avoid blizzlike checks." };
|
||||
case CREATURE_FLAG_EXTRA_IGNORE_ASSISTANCE_CALL: return { "CREATURE_FLAG_EXTRA_IGNORE_ASSISTANCE_CALL", "Creatures are not aggroed by other mobs assistance functions", "" };
|
||||
case CREATURE_FLAG_EXTRA_UNUSED_27: return { "CREATURE_FLAG_EXTRA_UNUSED_27", "CREATURE_FLAG_EXTRA_UNUSED_27", "" };
|
||||
case CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI: return { "CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI", "Creature entry SAI won't be overriden by GUID SAI", "" };
|
||||
case CREATURE_FLAG_EXTRA_UNUSED_28: return { "CREATURE_FLAG_EXTRA_UNUSED_28", "CREATURE_FLAG_EXTRA_UNUSED_28", "" };
|
||||
case CREATURE_FLAG_EXTRA_DUNGEON_BOSS: return { "CREATURE_FLAG_EXTRA_DUNGEON_BOSS", "CREATURE_FLAG_EXTRA_DUNGEON_BOSS", "creature is a dungeon boss (SET DYNAMICALLY, DO NOT ADD IN DB)" };
|
||||
case CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING: return { "CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING", "CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING", "creature ignore pathfinding" };
|
||||
@@ -101,7 +101,7 @@ AC_API_EXPORT CreatureFlagsExtra EnumUtils<CreatureFlagsExtra>::FromIndex(size_t
|
||||
case 23: return CREATURE_FLAG_EXTRA_NO_DODGE;
|
||||
case 24: return CREATURE_FLAG_EXTRA_MODULE;
|
||||
case 25: return CREATURE_FLAG_EXTRA_IGNORE_ASSISTANCE_CALL;
|
||||
case 26: return CREATURE_FLAG_EXTRA_UNUSED_27;
|
||||
case 26: return CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI;
|
||||
case 27: return CREATURE_FLAG_EXTRA_UNUSED_28;
|
||||
case 28: return CREATURE_FLAG_EXTRA_DUNGEON_BOSS;
|
||||
case 29: return CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING;
|
||||
@@ -142,7 +142,7 @@ AC_API_EXPORT size_t EnumUtils<CreatureFlagsExtra>::ToIndex(CreatureFlagsExtra v
|
||||
case CREATURE_FLAG_EXTRA_NO_DODGE: return 23;
|
||||
case CREATURE_FLAG_EXTRA_MODULE: return 24;
|
||||
case CREATURE_FLAG_EXTRA_IGNORE_ASSISTANCE_CALL: return 25;
|
||||
case CREATURE_FLAG_EXTRA_UNUSED_27: return 26;
|
||||
case CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI: return 26;
|
||||
case CREATURE_FLAG_EXTRA_UNUSED_28: return 27;
|
||||
case CREATURE_FLAG_EXTRA_DUNGEON_BOSS: return 28;
|
||||
case CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING: return 29;
|
||||
|
||||
@@ -642,7 +642,7 @@ void Unit::UpdateSplinePosition()
|
||||
transport->CalculatePassengerPosition(loc.x, loc.y, loc.z, &loc.orientation);
|
||||
}
|
||||
|
||||
// Xinef: this is bullcrap, if we had spline running update orientation along with position
|
||||
// Xinef: if we had spline running update orientation along with position
|
||||
//if (HasUnitState(UNIT_STATE_CANNOT_TURN))
|
||||
// loc.orientation = GetOrientation();
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ void WorldSession::HandlePetAction(WorldPacket& recvData)
|
||||
// xinef: allow to dissmis dead pets
|
||||
if ((*itr)->GetEntry() == pet->GetEntry() && ((*itr)->IsAlive() || (flag == ACT_COMMAND && spellId == COMMAND_ABANDON)))
|
||||
controlled.push_back(*itr);
|
||||
// xinef: mirror image blizzard crappness
|
||||
// xinef: mirror image blizzard
|
||||
else if ((*itr)->GetEntry() == NPC_MIRROR_IMAGE && flag == ACT_COMMAND && spellId == COMMAND_FOLLOW)
|
||||
{
|
||||
(*itr)->InterruptNonMeleeSpells(false);
|
||||
|
||||
@@ -55,7 +55,7 @@ class Aura;
|
||||
// AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK set - aura is recalculated or is just applied/removed - need to redo all things related to m_amount
|
||||
// AURA_EFFECT_HANDLE_CHANGE_AMOUNT_SEND_FOR_CLIENT_MASK - logical or of above conditions
|
||||
// AURA_EFFECT_HANDLE_STAT - set when stats are reapplied
|
||||
// such checks will Speedup trinity change amount/send for client operations
|
||||
// such checks will Speedup azerothcore change amount/send for client operations
|
||||
// because for change amount operation packets will not be send
|
||||
// aura effect handlers shouldn't contain any AuraEffect or Aura object modifications
|
||||
|
||||
|
||||
@@ -891,7 +891,7 @@ public:
|
||||
}
|
||||
|
||||
// Original TC Notes from Refactor vvv
|
||||
//ToDo: use a new trinity_string for this commands
|
||||
//ToDo: use a new acore_string for this commands
|
||||
handler->PSendSysMessage(LANG_COMMAND_IMPORT_SUCCESS);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -587,7 +587,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// tc use updateAI, while we have movementinform :)
|
||||
// tc use updateAI, while we have movementinform
|
||||
void MovementInform(uint32 type, uint32 /*param*/) override
|
||||
{
|
||||
if (type == POINT_MOTION_TYPE)
|
||||
@@ -787,7 +787,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// tc they use updateAI, while we have movementinform :)
|
||||
// tc they use updateAI, while we have movementinform
|
||||
void MovementInform(uint32 type, uint32 /*param*/) override
|
||||
{
|
||||
if (type == POINT_MOTION_TYPE)
|
||||
|
||||
@@ -42,217 +42,194 @@ enum eEnums
|
||||
SOUND_INTRO = 9349
|
||||
};
|
||||
|
||||
class boss_ambassador_hellmaw : public CreatureScript
|
||||
struct boss_ambassador_hellmaw : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_ambassador_hellmaw() : CreatureScript("boss_ambassador_hellmaw") { }
|
||||
boss_ambassador_hellmaw(Creature* creature) : BossAI(creature, TYPE_HELLMAW) { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
bool isBanished;
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
return GetShadowLabyrinthAI<boss_ambassador_hellmawAI>(creature);
|
||||
}
|
||||
Reset();
|
||||
|
||||
struct boss_ambassador_hellmawAI : public ScriptedAI
|
||||
{
|
||||
boss_ambassador_hellmawAI(Creature* creature) : ScriptedAI(creature)
|
||||
if (instance->GetData(TYPE_RITUALISTS) != DONE)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
isBanished = true;
|
||||
me->SetImmuneToAll(true);
|
||||
|
||||
me->m_Events.AddEventAtOffset([this]()
|
||||
{
|
||||
DoCastSelf(SPELL_BANISH, true);
|
||||
}, 500ms);
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
EventMap events;
|
||||
bool isBanished;
|
||||
|
||||
void InitializeAI() override
|
||||
else
|
||||
{
|
||||
Reset();
|
||||
|
||||
if (instance && instance->GetData(TYPE_RITUALISTS) != DONE)
|
||||
{
|
||||
isBanished = true;
|
||||
me->SetImmuneToAll(true);
|
||||
|
||||
me->m_Events.AddEventAtOffset([this]()
|
||||
{
|
||||
DoCastSelf(SPELL_BANISH, true);
|
||||
}, 500ms);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->GetMotionMaster()->MovePath(PATH_ID_START, false);
|
||||
}
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
isBanished = false;
|
||||
me->SetImmuneToAll(false);
|
||||
if (instance)
|
||||
{
|
||||
instance->SetData(TYPE_HELLMAW, NOT_STARTED);
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 param) override
|
||||
{
|
||||
if (param != 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
me->RemoveAurasDueToSpell(SPELL_BANISH);
|
||||
Talk(SAY_INTRO);
|
||||
DoPlaySoundToSet(me, SOUND_INTRO);
|
||||
isBanished = false;
|
||||
me->SetImmuneToAll(false);
|
||||
me->GetMotionMaster()->MovePath(PATH_ID_START, false);
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit*) override
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
isBanished = false;
|
||||
me->SetImmuneToAll(false);
|
||||
}
|
||||
|
||||
void DoAction(int32 param) override
|
||||
{
|
||||
if (param != 1)
|
||||
{
|
||||
if (isBanished)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Talk(SAY_AGGRO);
|
||||
events.ScheduleEvent(EVENT_SPELL_CORROSIVE, urand(5000, 10000));
|
||||
events.ScheduleEvent(EVENT_SPELL_FEAR, urand(15000, 20000));
|
||||
if (IsHeroic())
|
||||
{
|
||||
events.ScheduleEvent(EVENT_SPELL_ENRAGE, 180000);
|
||||
}
|
||||
|
||||
if (instance)
|
||||
{
|
||||
instance->SetData(TYPE_HELLMAW, IN_PROGRESS);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (isBanished)
|
||||
{
|
||||
return;
|
||||
}
|
||||
me->RemoveAurasDueToSpell(SPELL_BANISH);
|
||||
Talk(SAY_INTRO);
|
||||
DoPlaySoundToSet(me, SOUND_INTRO);
|
||||
isBanished = false;
|
||||
me->SetImmuneToAll(false);
|
||||
me->GetMotionMaster()->MovePath(PATH_ID_START, false);
|
||||
}
|
||||
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
void JustEngagedWith(Unit*) override
|
||||
{
|
||||
if (isBanished)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (isBanished)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Talk(SAY_AGGRO);
|
||||
events.ScheduleEvent(EVENT_SPELL_CORROSIVE, urand(5000, 10000));
|
||||
|
||||
ScriptedAI::AttackStart(who);
|
||||
scheduler.Schedule(5s, 10s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_CORROSIVE_ACID);
|
||||
context.Repeat(15s, 25s);
|
||||
}).Schedule(15s, 20s, [this](TaskContext context)
|
||||
{
|
||||
DoCastAOE(SPELL_FEAR);
|
||||
context.Repeat(20s, 35s);
|
||||
});
|
||||
|
||||
if (IsHeroic())
|
||||
{
|
||||
scheduler.Schedule(5min, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_ENRAGE, true);
|
||||
});
|
||||
}
|
||||
|
||||
void PathEndReached(uint32 pathId) override
|
||||
_JustEngagedWith();
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (isBanished)
|
||||
{
|
||||
if (pathId == PATH_ID_START)
|
||||
return;
|
||||
}
|
||||
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (isBanished)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void PathEndReached(uint32 pathId) override
|
||||
{
|
||||
if (pathId == PATH_ID_START)
|
||||
{
|
||||
me->m_Events.AddEventAtOffset([this]()
|
||||
{
|
||||
me->m_Events.AddEventAtOffset([this]()
|
||||
me->GetMotionMaster()->MovePath(PATH_ID_PATHING, true);
|
||||
}, 20s);
|
||||
}
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->IsPlayer() && urand(0, 1))
|
||||
{
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
bool CanAIAttack(Unit const* /*unit*/) const override
|
||||
{
|
||||
return !isBanished;
|
||||
}
|
||||
|
||||
void DoMeleeAttackIfReady(bool ignoreCasting)
|
||||
{
|
||||
if (!ignoreCasting && me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Unit* victim = me->GetVictim();
|
||||
if (!victim || !victim->IsInWorld())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!me->IsWithinMeleeRange(victim))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//Make sure our attack is ready and we aren't currently casting before checking distance
|
||||
if (me->isAttackReady())
|
||||
{
|
||||
// xinef: prevent base and off attack in same time, delay attack at 0.2 sec
|
||||
if (me->haveOffhandWeapon())
|
||||
{
|
||||
if (me->getAttackTimer(OFF_ATTACK) < ATTACK_DISPLAY_DELAY)
|
||||
{
|
||||
me->GetMotionMaster()->MovePath(PATH_ID_PATHING, true);
|
||||
}, 20s);
|
||||
}
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER && urand(0, 1))
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
if (instance)
|
||||
instance->SetData(TYPE_HELLMAW, DONE);
|
||||
}
|
||||
|
||||
bool CanAIAttack(Unit const* /*unit*/) const override
|
||||
{
|
||||
return !isBanished;
|
||||
}
|
||||
|
||||
void DoMeleeAttackIfReady(bool ignoreCasting)
|
||||
{
|
||||
if (!ignoreCasting && me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Unit* victim = me->GetVictim();
|
||||
if (!victim || !victim->IsInWorld())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!me->IsWithinMeleeRange(victim))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//Make sure our attack is ready and we aren't currently casting before checking distance
|
||||
if (me->isAttackReady())
|
||||
{
|
||||
// xinef: prevent base and off attack in same time, delay attack at 0.2 sec
|
||||
if (me->haveOffhandWeapon())
|
||||
{
|
||||
if (me->getAttackTimer(OFF_ATTACK) < ATTACK_DISPLAY_DELAY)
|
||||
{
|
||||
me->setAttackTimer(OFF_ATTACK, ATTACK_DISPLAY_DELAY);
|
||||
}
|
||||
me->setAttackTimer(OFF_ATTACK, ATTACK_DISPLAY_DELAY);
|
||||
}
|
||||
|
||||
me->AttackerStateUpdate(victim, BASE_ATTACK, false, ignoreCasting);
|
||||
me->resetAttackTimer();
|
||||
}
|
||||
|
||||
if (me->haveOffhandWeapon() && me->isAttackReady(OFF_ATTACK))
|
||||
{
|
||||
// xinef: delay main hand attack if both will hit at the same time (players code)
|
||||
if (me->getAttackTimer(BASE_ATTACK) < ATTACK_DISPLAY_DELAY)
|
||||
{
|
||||
me->setAttackTimer(BASE_ATTACK, ATTACK_DISPLAY_DELAY);
|
||||
}
|
||||
|
||||
me->AttackerStateUpdate(victim, OFF_ATTACK, false, ignoreCasting);
|
||||
me->resetAttackTimer(OFF_ATTACK);
|
||||
}
|
||||
me->AttackerStateUpdate(victim, BASE_ATTACK, false, ignoreCasting);
|
||||
me->resetAttackTimer();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
if (me->haveOffhandWeapon() && me->isAttackReady(OFF_ATTACK))
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
switch (events.ExecuteEvent())
|
||||
// xinef: delay main hand attack if both will hit at the same time (players code)
|
||||
if (me->getAttackTimer(BASE_ATTACK) < ATTACK_DISPLAY_DELAY)
|
||||
{
|
||||
case EVENT_SPELL_CORROSIVE:
|
||||
me->CastSpell(me->GetVictim(), SPELL_CORROSIVE_ACID, false);
|
||||
events.RepeatEvent(urand(15000, 25000));
|
||||
break;
|
||||
case EVENT_SPELL_FEAR:
|
||||
me->CastSpell(me, SPELL_FEAR, false);
|
||||
events.RepeatEvent(urand(20000, 35000));
|
||||
break;
|
||||
case EVENT_SPELL_ENRAGE:
|
||||
me->CastSpell(me->GetVictim(), SPELL_ENRAGE, false);
|
||||
break;
|
||||
me->setAttackTimer(BASE_ATTACK, ATTACK_DISPLAY_DELAY);
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady(me->FindCurrentSpellBySpellId(SPELL_CORROSIVE_ACID) != nullptr);
|
||||
me->AttackerStateUpdate(victim, OFF_ATTACK, false, ignoreCasting);
|
||||
me->resetAttackTimer(OFF_ATTACK);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady(me->FindCurrentSpellBySpellId(SPELL_CORROSIVE_ACID) != nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_ambassador_hellmaw()
|
||||
{
|
||||
new boss_ambassador_hellmaw();
|
||||
RegisterShadowLabyrinthCreatureAI(boss_ambassador_hellmaw);
|
||||
}
|
||||
|
||||
@@ -50,4 +50,6 @@ inline AI* GetShadowLabyrinthAI(T* obj)
|
||||
return GetInstanceAI<AI>(obj, ShadowLabyrinthScriptName);
|
||||
}
|
||||
|
||||
#define RegisterShadowLabyrinthCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetShadowLabyrinthAI)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -126,9 +126,9 @@ struct boss_high_king_maulgar : public BossAI
|
||||
_JustEngagedWith();
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
events.ScheduleEvent(EVENT_ARCING_SMASH, 6s);
|
||||
events.ScheduleEvent(EVENT_MIGHTY_BLOW, 20s);
|
||||
events.ScheduleEvent(EVENT_WHIRLWIND, 30s);
|
||||
events.ScheduleEvent(EVENT_ARCING_SMASH, 10s);
|
||||
events.ScheduleEvent(EVENT_MIGHTY_BLOW, 15s);
|
||||
events.ScheduleEvent(EVENT_WHIRLWIND, 54s);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH, 500ms);
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ struct boss_high_king_maulgar : public BossAI
|
||||
break;
|
||||
case EVENT_MIGHTY_BLOW:
|
||||
me->CastSpell(me->GetVictim(), SPELL_MIGHTY_BLOW, false);
|
||||
events.ScheduleEvent(EVENT_MIGHTY_BLOW, 16s);
|
||||
events.ScheduleEvent(EVENT_MIGHTY_BLOW, 15s);
|
||||
break;
|
||||
case EVENT_WHIRLWIND:
|
||||
events.DelayEvents(15s);
|
||||
@@ -214,9 +214,9 @@ struct boss_olm_the_summoner : public ScriptedAI
|
||||
me->SetInCombatWithZone();
|
||||
instance->SetBossState(DATA_MAULGAR, IN_PROGRESS);
|
||||
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 10s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 15s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 20s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 500ms);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 5s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 6500ms);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -241,19 +241,18 @@ struct boss_olm_the_summoner : public ScriptedAI
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_ADD_ABILITY1:
|
||||
DoCastVictim(SPELL_DARK_DECAY);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 7s);
|
||||
me->CastSpell(me, SPELL_SUMMON_WFH, false);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 50s);
|
||||
break;
|
||||
case EVENT_ADD_ABILITY2:
|
||||
me->CastSpell(me, SPELL_SUMMON_WFH, false);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 30s);
|
||||
DoCastVictim(SPELL_DARK_DECAY);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 6500ms);
|
||||
break;
|
||||
case EVENT_ADD_ABILITY3:
|
||||
DoCastRandomTarget(SPELL_DEATH_COIL);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 20s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 7s);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
@@ -279,9 +278,9 @@ struct boss_kiggler_the_crazed : public ScriptedAI
|
||||
me->SetInCombatWithZone();
|
||||
instance->SetBossState(DATA_MAULGAR, IN_PROGRESS);
|
||||
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 5s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 10s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 20s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 1500ms);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 5s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 25s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY4, 30s);
|
||||
}
|
||||
|
||||
@@ -302,20 +301,23 @@ struct boss_kiggler_the_crazed : public ScriptedAI
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_ADD_ABILITY1:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1))
|
||||
me->CastSpell(target, SPELL_GREATER_POLYMORPH, false);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 20s);
|
||||
DoCastVictim(SPELL_LIGHTNING_BOLT);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 1500ms);
|
||||
break;
|
||||
case EVENT_ADD_ABILITY2:
|
||||
DoCastVictim(SPELL_LIGHTNING_BOLT);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 1500ms);
|
||||
DoCastVictim(SPELL_ARCANE_SHOCK);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 5s);
|
||||
break;
|
||||
case EVENT_ADD_ABILITY3:
|
||||
DoCastVictim(SPELL_ARCANE_SHOCK);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 20s);
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1)) //target method should perhaps change
|
||||
me->CastSpell(target, SPELL_GREATER_POLYMORPH, false);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 11s);
|
||||
break;
|
||||
case EVENT_ADD_ABILITY4:
|
||||
DoCastAOE(SPELL_ARCANE_EXPLOSION);
|
||||
if (me->SelectNearestPlayer(30.0f))
|
||||
{
|
||||
DoCastAOE(SPELL_ARCANE_EXPLOSION);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY4, 30s);
|
||||
break;
|
||||
}
|
||||
@@ -345,9 +347,9 @@ struct boss_blindeye_the_seer : public ScriptedAI
|
||||
me->SetInCombatWithZone();
|
||||
instance->SetBossState(DATA_MAULGAR, IN_PROGRESS);
|
||||
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 1700ms);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 10s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 20s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 11s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 30s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 31s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -367,15 +369,15 @@ struct boss_blindeye_the_seer : public ScriptedAI
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_ADD_ABILITY1:
|
||||
DoCastSelf(SPELL_GREATER_PW_SHIELD);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 30s);
|
||||
break;
|
||||
case EVENT_ADD_ABILITY2:
|
||||
if (Unit* target = DoSelectLowestHpFriendly(60.0f, 50000))
|
||||
{
|
||||
DoCast(target, SPELL_HEAL);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 25s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 6s);
|
||||
break;
|
||||
case EVENT_ADD_ABILITY2:
|
||||
DoCastSelf(SPELL_GREATER_PW_SHIELD);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 30s);
|
||||
break;
|
||||
case EVENT_ADD_ABILITY3:
|
||||
me->CastSpell(me, SPELL_PRAYER_OH, false);
|
||||
@@ -417,9 +419,9 @@ struct boss_krosh_firehand : public ScriptedAI
|
||||
me->SetInCombatWithZone();
|
||||
instance->SetBossState(DATA_MAULGAR, IN_PROGRESS);
|
||||
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 1s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 5s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 20s);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 1500ms); //spellshield
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 3500ms); //greater fireball
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 8s); //blast wave (needs to check for players in range)
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -439,16 +441,19 @@ struct boss_krosh_firehand : public ScriptedAI
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_ADD_ABILITY1:
|
||||
DoCastVictim(SPELL_GREATER_FIREBALL);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 3500ms);
|
||||
DoCastSelf(SPELL_SPELLSHIELD);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY1, 30s);
|
||||
break;
|
||||
case EVENT_ADD_ABILITY2:
|
||||
DoCastSelf(SPELL_SPELLSHIELD);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 40s);
|
||||
DoCastVictim(SPELL_GREATER_FIREBALL);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY2, 1s);
|
||||
break;
|
||||
case EVENT_ADD_ABILITY3:
|
||||
DoCastAOE(SPELL_BLAST_WAVE);
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 20s);
|
||||
if (me->SelectNearestPlayer(15.0f))
|
||||
{
|
||||
DoCastAOE(SPELL_BLAST_WAVE);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_ADD_ABILITY3, 8s);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user