mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-25 06:36:24 +00:00
Merge branch 'master' into Playerbot
This commit is contained in:
@@ -1139,7 +1139,22 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
}
|
||||
case SMART_ACTION_DIE:
|
||||
{
|
||||
if (me && !me->isDead())
|
||||
if (e.action.die.milliseconds)
|
||||
{
|
||||
if (me && !me->isDead())
|
||||
{
|
||||
me->m_Events.AddEventAtOffset([&]
|
||||
{
|
||||
// We need to check again to see if we didn't die in the process.
|
||||
if (me && !me->isDead())
|
||||
{
|
||||
me->KillSelf();
|
||||
LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_DIE: Creature {}", me->GetGUID().ToString());
|
||||
}
|
||||
}, Milliseconds(e.action.die.milliseconds));
|
||||
}
|
||||
}
|
||||
else if (me && !me->isDead())
|
||||
{
|
||||
me->KillSelf();
|
||||
LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_DIE: Creature {}", me->GetGUID().ToString());
|
||||
|
||||
@@ -641,7 +641,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
|
||||
case SMART_ACTION_SET_INST_DATA: return sizeof(SmartAction::setInstanceData);
|
||||
case SMART_ACTION_SET_INST_DATA64: return sizeof(SmartAction::setInstanceData64);
|
||||
case SMART_ACTION_UPDATE_TEMPLATE: return sizeof(SmartAction::updateTemplate);
|
||||
case SMART_ACTION_DIE: return NO_PARAMS;
|
||||
case SMART_ACTION_DIE: return sizeof(SmartAction::die);
|
||||
case SMART_ACTION_SET_IN_COMBAT_WITH_ZONE: return NO_PARAMS;
|
||||
case SMART_ACTION_CALL_FOR_HELP: return sizeof(SmartAction::callHelp);
|
||||
case SMART_ACTION_SET_SHEATH: return sizeof(SmartAction::setSheath);
|
||||
|
||||
@@ -559,7 +559,7 @@ enum SMART_ACTION
|
||||
SMART_ACTION_SET_INST_DATA = 34, // Field, Data
|
||||
SMART_ACTION_SET_INST_DATA64 = 35, // Field,
|
||||
SMART_ACTION_UPDATE_TEMPLATE = 36, // Entry, UpdateLevel
|
||||
SMART_ACTION_DIE = 37, // No Params
|
||||
SMART_ACTION_DIE = 37, // Milliseconds
|
||||
SMART_ACTION_SET_IN_COMBAT_WITH_ZONE = 38, // Range (if outside of dungeon)
|
||||
SMART_ACTION_CALL_FOR_HELP = 39, // Radius, With Emote
|
||||
SMART_ACTION_SET_SHEATH = 40, // Sheath (0-unarmed, 1-melee, 2-ranged)
|
||||
@@ -925,6 +925,11 @@ struct SmartAction
|
||||
SAIBool updateLevel;
|
||||
} updateTemplate;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 milliseconds;
|
||||
} die;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 range;
|
||||
|
||||
@@ -12482,32 +12482,6 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
|
||||
|
||||
switch (spellProto->SpellFamilyName)
|
||||
{
|
||||
case SPELLFAMILY_DRUID:
|
||||
{
|
||||
// Nourish vs Idol of the Flourishing Life
|
||||
if (spellProto->SpellFamilyFlags[1] & 0x02000000)
|
||||
{
|
||||
if (AuraEffect const* relicAurEff = GetAuraEffect(64949, EFFECT_0))
|
||||
{
|
||||
DoneAdvertisedBenefit += relicAurEff->GetAmount();
|
||||
}
|
||||
}
|
||||
|
||||
// Lifebloom vs Idol of Lush Moss/Increased Lifebloom Periodic
|
||||
if (spellProto->SpellFamilyFlags[1] & 00000010)
|
||||
{
|
||||
if (AuraEffect const* relicAurEff = GetAuraEffect(60779, EFFECT_0))
|
||||
{
|
||||
DoneAdvertisedBenefit += relicAurEff->GetAmount();
|
||||
}
|
||||
|
||||
if (AuraEffect const* relicAurEff = GetAuraEffect(34246, EFFECT_0))
|
||||
{
|
||||
DoneAdvertisedBenefit += relicAurEff->GetAmount();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPELLFAMILY_DEATHKNIGHT:
|
||||
{
|
||||
// Impurity
|
||||
|
||||
@@ -439,6 +439,13 @@ void SpellMgr::LoadSpellInfoCorrections()
|
||||
spellInfo->Effects[EFFECT_0].SpellClassMask = flag96(0x00000040, 0x00000000, 0x00000000);
|
||||
});
|
||||
|
||||
// Idol of the Flourishing Life
|
||||
ApplySpellFix({ 64949 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
spellInfo->Effects[EFFECT_0].SpellClassMask = flag96(0x00000000, 0x02000000, 0x00000000);
|
||||
spellInfo->Effects[EFFECT_0].ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER;
|
||||
});
|
||||
|
||||
ApplySpellFix({
|
||||
34231, // Libram of the Lightbringer
|
||||
60792, // Libram of Tolerance
|
||||
|
||||
@@ -63,9 +63,9 @@ enum Events
|
||||
EVENT_PYROBLAST = 6,
|
||||
// Hack due to trigger spell not in dbc
|
||||
EVENT_FIRE_SHIELD = 7,
|
||||
// Make sure all players have aura from altar
|
||||
EVENT_PLAYER_CHECK = 8,
|
||||
EVENT_ENTER_COMBAT = 9
|
||||
EVENT_PRE_ENTER_COMBAT_1 = 8,
|
||||
EVENT_PRE_ENTER_COMBAT_2 = 9,
|
||||
EVENT_ENTER_COMBAT = 10
|
||||
};
|
||||
|
||||
class boss_pyroguard_emberseer : public CreatureScript
|
||||
@@ -101,7 +101,8 @@ public:
|
||||
switch (data)
|
||||
{
|
||||
case 1:
|
||||
events.ScheduleEvent(EVENT_PLAYER_CHECK, 5s);
|
||||
events.ScheduleEvent(EVENT_PRE_FIGHT_1, 2s);
|
||||
instance->SetBossState(DATA_PYROGAURD_EMBERSEER, IN_PROGRESS);
|
||||
break;
|
||||
case 2:
|
||||
// Close these two doors on Blackhand Incarcerators aggro
|
||||
@@ -153,14 +154,12 @@ public:
|
||||
|
||||
if (me->GetAuraCount(SPELL_EMBERSEER_GROWING_TRIGGER) == 20)
|
||||
{
|
||||
me->RemoveAura(SPELL_ENCAGED_EMBERSEER);
|
||||
me->RemoveAura(SPELL_FREEZE_ANIM);
|
||||
me->CastSpell(me, SPELL_EMBERSEER_FULL_STRENGTH);
|
||||
Talk(EMOTE_FREE_OF_BONDS);
|
||||
Talk(YELL_FREE_OF_BONDS);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetImmuneToPC(false);
|
||||
events.ScheduleEvent(EVENT_ENTER_COMBAT, 2s);
|
||||
events.CancelEvent(EVENT_FIRE_SHIELD); // temporarily cancel fire shield to keep it from interrupting combat start
|
||||
|
||||
// Schedule out the pre-combat scene
|
||||
events.ScheduleEvent(EVENT_PRE_ENTER_COMBAT_1, 0s);
|
||||
events.ScheduleEvent(EVENT_PRE_ENTER_COMBAT_2, 2s);
|
||||
events.ScheduleEvent(EVENT_ENTER_COMBAT, 5s);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -235,7 +234,7 @@ public:
|
||||
if (Creature* creature = *itr)
|
||||
creature->AI()->SetData(1, 1);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_PRE_FIGHT_2, 32s);
|
||||
events.ScheduleEvent(EVENT_PRE_FIGHT_2, 2s);
|
||||
break;
|
||||
}
|
||||
case EVENT_PRE_FIGHT_2:
|
||||
@@ -248,25 +247,21 @@ public:
|
||||
DoCast(me, SPELL_FIRE_SHIELD);
|
||||
events.ScheduleEvent(EVENT_FIRE_SHIELD, 3s);
|
||||
break;
|
||||
case EVENT_PLAYER_CHECK:
|
||||
{
|
||||
// Check to see if all players in instance have aura SPELL_EMBERSEER_START before starting event
|
||||
bool _hasAura = false;
|
||||
Map::PlayerList const& players = me->GetMap()->GetPlayers();
|
||||
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
|
||||
if (Player* player = itr->GetSource()->ToPlayer())
|
||||
if (player->HasAura(SPELL_EMBERSEER_OBJECT_VISUAL))
|
||||
_hasAura = true;
|
||||
|
||||
if (_hasAura)
|
||||
{
|
||||
events.ScheduleEvent(EVENT_PRE_FIGHT_1, 1s);
|
||||
instance->SetBossState(DATA_PYROGAURD_EMBERSEER, IN_PROGRESS);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EVENT_PRE_ENTER_COMBAT_1:
|
||||
me->RemoveAura(SPELL_ENCAGED_EMBERSEER);
|
||||
me->RemoveAura(SPELL_FREEZE_ANIM);
|
||||
me->CastSpell(me, SPELL_EMBERSEER_FULL_STRENGTH);
|
||||
Talk(EMOTE_FREE_OF_BONDS);
|
||||
break;
|
||||
case EVENT_PRE_ENTER_COMBAT_2:
|
||||
Talk(YELL_FREE_OF_BONDS);
|
||||
break;
|
||||
case EVENT_ENTER_COMBAT:
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetImmuneToPC(false);
|
||||
DoZoneInCombat();
|
||||
// re-enable fire shield
|
||||
events.ScheduleEvent(EVENT_FIRE_SHIELD, 0s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -347,11 +342,6 @@ public:
|
||||
_fleedForAssistance = false;
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
me->DespawnOrUnsummon(10000);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*type*/, SpellSchoolMask /*school*/) override
|
||||
{
|
||||
if (!_fleedForAssistance && me->HealthBelowPctDamaged(30, damage))
|
||||
@@ -392,7 +382,6 @@ public:
|
||||
}
|
||||
|
||||
_events.ScheduleEvent(EVENT_STRIKE, 8s, 16s);
|
||||
_events.ScheduleEvent(EVENT_ENCAGE, 10s, 20s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
|
||||
@@ -34,107 +34,70 @@ enum Spells
|
||||
SPELL_DARK_SHELL = 32358
|
||||
};
|
||||
|
||||
enum Events
|
||||
enum Groups
|
||||
{
|
||||
EVENT_VOID_BLAST = 1,
|
||||
EVENT_DARK_SHELL
|
||||
GROUP_VOID_BLAST = 1
|
||||
};
|
||||
|
||||
class boss_pandemonius : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_pandemonius() : CreatureScript("boss_pandemonius") { }
|
||||
constexpr uint8 MAX_VOID_BLAST = 5;
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
struct boss_pandemonius : public BossAI
|
||||
{
|
||||
boss_pandemonius(Creature* creature) : BossAI(creature, DATA_PANDEMONIUS)
|
||||
{
|
||||
return GetManaTombsAI<boss_pandemoniusAI>(creature);
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
struct boss_pandemoniusAI : public ScriptedAI
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
boss_pandemoniusAI(Creature* creature) : ScriptedAI(creature) { }
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
EventMap events;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
VoidBlastCounter = 0;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit*) override
|
||||
{
|
||||
me->SetInCombatWithZone();
|
||||
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
events.ScheduleEvent(EVENT_DARK_SHELL, 20000);
|
||||
events.ScheduleEvent(EVENT_VOID_BLAST, urand(8000, 23000));
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
scheduler.
|
||||
Schedule(20s, GROUP_VOID_BLAST, [this](TaskContext context)
|
||||
{
|
||||
case EVENT_VOID_BLAST:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
|
||||
{
|
||||
DoCast(target, SPELL_VOID_BLAST);
|
||||
++VoidBlastCounter;
|
||||
}
|
||||
if (me->IsNonMeleeSpellCast(false))
|
||||
{
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
}
|
||||
|
||||
if (VoidBlastCounter == 5)
|
||||
Talk(EMOTE_DARK_SHELL);
|
||||
DoCastSelf(SPELL_DARK_SHELL);
|
||||
context.Repeat();
|
||||
})
|
||||
.Schedule(8s, 23s, [this](TaskContext context)
|
||||
{
|
||||
if (!(context.GetRepeatCounter() % (MAX_VOID_BLAST + 1)))
|
||||
{
|
||||
VoidBlastCounter = 0;
|
||||
events.RescheduleEvent(EVENT_VOID_BLAST, urand(15000, 25000));
|
||||
context.Repeat(15s, 25s);
|
||||
}
|
||||
else
|
||||
{
|
||||
events.RescheduleEvent(EVENT_VOID_BLAST, 500);
|
||||
events.DelayEvents(EVENT_DARK_SHELL, 500);
|
||||
}
|
||||
break;
|
||||
case EVENT_DARK_SHELL:
|
||||
if (me->IsNonMeleeSpellCast(false))
|
||||
{
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
DoCastRandomTarget(SPELL_VOID_BLAST);
|
||||
context.Repeat(500ms);
|
||||
context.DelayGroup(GROUP_VOID_BLAST, 500ms);
|
||||
}
|
||||
});
|
||||
|
||||
Talk(EMOTE_DARK_SHELL);
|
||||
DoCast(me, SPELL_DARK_SHELL);
|
||||
events.RescheduleEvent(EVENT_DARK_SHELL, 20000);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
BossAI::JustEngagedWith(who);
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 VoidBlastCounter;
|
||||
};
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_pandemonius()
|
||||
{
|
||||
new boss_pandemonius();
|
||||
RegisterManaTombsCreatureAI(boss_pandemonius);
|
||||
}
|
||||
|
||||
@@ -104,7 +104,14 @@ struct boss_talon_king_ikiss : public BossAI
|
||||
context.Repeat(7s, 12s);
|
||||
}).Schedule(8s, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_POLYMORPH);
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_POLYMORPH);
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, [&](Unit* target) -> bool
|
||||
{
|
||||
return target && !target->IsImmunedToSpell(spellInfo);
|
||||
}))
|
||||
{
|
||||
DoCast(target, SPELL_POLYMORPH);
|
||||
}
|
||||
context.Repeat(15s, 17500ms);
|
||||
});
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ struct boss_grand_warlock_nethekurse : public BossAI
|
||||
|
||||
if (!_canAggro)
|
||||
{
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->SetImmuneToAll(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,11 +235,13 @@ struct boss_grand_warlock_nethekurse : public BossAI
|
||||
me->SetInCombatWithZone();
|
||||
return;
|
||||
}
|
||||
else if (action == ACTION_START_INTRO)
|
||||
else if (action == ACTION_START_INTRO && !_introStarted)
|
||||
{
|
||||
// Hack: Prevent from pulling from behind door
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->SetImmuneToAll(false);
|
||||
_canAggro = true;
|
||||
// Bit of a hack to make sure it can't be started with the areatrigger AND the door opening
|
||||
_introStarted = true;
|
||||
|
||||
std::list<Creature*> creatureList;
|
||||
GetCreatureListWithEntryInGrid(creatureList, me, NPC_PEON, 60.0f);
|
||||
@@ -247,7 +249,7 @@ struct boss_grand_warlock_nethekurse : public BossAI
|
||||
{
|
||||
if (creature)
|
||||
{
|
||||
creature->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
creature->SetImmuneToAll(false);
|
||||
}
|
||||
}
|
||||
IntroRP();
|
||||
@@ -258,6 +260,21 @@ struct boss_grand_warlock_nethekurse : public BossAI
|
||||
{
|
||||
scheduler.Update(diff);
|
||||
|
||||
// this should never be called if the action to start intro has been called
|
||||
if (!_introStarted)
|
||||
{
|
||||
// find the door that is nearest to the entrance
|
||||
if (GameObject* nethekursedoor = GetClosestGameObjectWithEntry(me, GO_GRAND_WARLOCK_CHAMBER_DOOR_1, 100.0f))
|
||||
{
|
||||
// check if door is openened
|
||||
//this should only happen before the intro, if the door is picked by someone
|
||||
if(nethekursedoor->GetGoState() == 0)
|
||||
{
|
||||
DoAction(ACTION_START_INTRO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
@@ -272,6 +289,7 @@ private:
|
||||
uint8 PeonEngagedCount = 0;
|
||||
uint8 PeonKilledCount = 0;
|
||||
bool _canAggro = false;
|
||||
bool _introStarted = false;
|
||||
};
|
||||
|
||||
class spell_tsh_shadow_bolt : public SpellScript
|
||||
|
||||
@@ -54,6 +54,24 @@ struct boss_nethermancer_sepethrea : public BossAI
|
||||
});
|
||||
}
|
||||
|
||||
bool CanAIAttack(Unit const* target) const override
|
||||
{
|
||||
if (me->GetThreatMgr().GetThreatListSize() > 1)
|
||||
{
|
||||
ThreatContainer::StorageType::const_iterator lastRef = me->GetThreatMgr().GetOnlineContainer().GetThreatList().end();
|
||||
--lastRef;
|
||||
if (Unit* lastTarget = (*lastRef)->getTarget())
|
||||
{
|
||||
if (lastTarget != target)
|
||||
{
|
||||
return !target->HasAura(SPELL_DRAGONS_BREATH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
|
||||
@@ -500,6 +500,31 @@ class spell_dru_glyph_of_starfire : public SpellScript
|
||||
}
|
||||
};
|
||||
|
||||
// 34246 - Idol of the Emerald Queen
|
||||
// 60779 - Idol of Lush Moss
|
||||
class spell_dru_idol_lifebloom : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_dru_idol_lifebloom);
|
||||
|
||||
void HandleEffectCalcSpellMod(AuraEffect const* aurEff, SpellModifier*& spellMod)
|
||||
{
|
||||
if (!spellMod)
|
||||
{
|
||||
spellMod = new SpellModifier(GetAura());
|
||||
spellMod->op = SPELLMOD_DOT;
|
||||
spellMod->type = SPELLMOD_FLAT;
|
||||
spellMod->spellId = GetId();
|
||||
spellMod->mask = aurEff->GetSpellInfo()->Effects[aurEff->GetEffIndex()].SpellClassMask;
|
||||
}
|
||||
spellMod->value = aurEff->GetAmount() / 7;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoEffectCalcSpellMod += AuraEffectCalcSpellModFn(spell_dru_idol_lifebloom::HandleEffectCalcSpellMod, EFFECT_0, SPELL_AURA_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 29166 - Innervate
|
||||
class spell_dru_innervate : public AuraScript
|
||||
{
|
||||
@@ -1158,6 +1183,7 @@ void AddSC_druid_spell_scripts()
|
||||
RegisterSpellScript(spell_dru_dash);
|
||||
RegisterSpellScript(spell_dru_enrage);
|
||||
RegisterSpellScript(spell_dru_glyph_of_starfire);
|
||||
RegisterSpellScript(spell_dru_idol_lifebloom);
|
||||
RegisterSpellScript(spell_dru_innervate);
|
||||
RegisterSpellScript(spell_dru_lifebloom);
|
||||
RegisterSpellScript(spell_dru_living_seed);
|
||||
|
||||
@@ -990,7 +990,7 @@ public:
|
||||
Reset();
|
||||
}
|
||||
|
||||
void PatientSaved(Creature* /*soldier*/, Player* player, Location* point)
|
||||
void PatientSaved(Creature* savedPatient, Player* player, Location* point)
|
||||
{
|
||||
if (player && PlayerGUID == player->GetGUID())
|
||||
{
|
||||
@@ -1004,8 +1004,9 @@ public:
|
||||
{
|
||||
for (ObjectGuid const& guid : Patients)
|
||||
{
|
||||
if (Creature* patient = ObjectAccessor::GetCreature(*me, guid))
|
||||
patient->setDeathState(JUST_DIED);
|
||||
if (guid != savedPatient->GetGUID()) // Don't kill the last guy we just saved
|
||||
if (Creature* patient = ObjectAccessor::GetCreature(*me, guid))
|
||||
patient->setDeathState(JUST_DIED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1069,6 +1070,9 @@ public:
|
||||
//no regen health
|
||||
me->SetUnitFlag(UNIT_FLAG_IN_COMBAT);
|
||||
|
||||
//prevent using normal bandages
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_BANDAGE, true);
|
||||
|
||||
//to make them lay with face down
|
||||
me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD);
|
||||
|
||||
@@ -1078,18 +1082,26 @@ public:
|
||||
{
|
||||
//lower max health
|
||||
case 12923:
|
||||
case 12938: //Injured Soldier
|
||||
me->SetHealth(me->CountPctFromMaxHealth(75));
|
||||
case 12938: //Injured Soldier, 65 seconds to die
|
||||
me->SetHealth(me->CountPctFromMaxHealth(65));
|
||||
break;
|
||||
case 12924:
|
||||
case 12936: //Badly injured Soldier
|
||||
me->SetHealth(me->CountPctFromMaxHealth(50));
|
||||
case 12936: //Badly injured Soldier, 35 seconds to die
|
||||
me->SetHealth(me->CountPctFromMaxHealth(35));
|
||||
break;
|
||||
case 12925:
|
||||
case 12937: //Critically injured Soldier
|
||||
case 12937: //Critically injured Soldier, 25 seconds to die
|
||||
me->SetHealth(me->CountPctFromMaxHealth(25));
|
||||
break;
|
||||
}
|
||||
|
||||
// Schedule health reduction every 1 second
|
||||
_scheduler.Schedule(1s, [this](TaskContext context)
|
||||
{
|
||||
// Reduction of 1% per second, matching WotLK Classic timing
|
||||
me->ModifyHealth(me->CountPctFromMaxHealth(1) * -1);
|
||||
context.Repeat(1s);
|
||||
});
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override { }
|
||||
@@ -1134,13 +1146,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 /*diff*/) override
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//lower HP on every world tick makes it a useful counter, not officlone though
|
||||
if (me->IsAlive() && me->GetHealth() > 6)
|
||||
me->ModifyHealth(-5);
|
||||
|
||||
if (me->IsAlive() && me->GetHealth() <= 6)
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me->IsAlive() && me->GetHealth() < me->CountPctFromMaxHealth(1))
|
||||
{
|
||||
me->RemoveUnitFlag(UNIT_FLAG_IN_COMBAT);
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
@@ -1152,6 +1163,10 @@ public:
|
||||
CAST_AI(npc_doctor::npc_doctorAI, doctor->AI())->PatientDied(Coord);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
@@ -1162,7 +1177,7 @@ public:
|
||||
|
||||
void npc_doctor::npc_doctorAI::UpdateAI(uint32 diff)
|
||||
{
|
||||
if (Event && SummonPatientCount >= 20)
|
||||
if (Event && SummonPatientCount >= 24) // Need to keep the event going long enough to save the last few patients
|
||||
{
|
||||
Reset();
|
||||
return;
|
||||
@@ -1170,7 +1185,7 @@ void npc_doctor::npc_doctorAI::UpdateAI(uint32 diff)
|
||||
|
||||
if (Event)
|
||||
{
|
||||
if (SummonPatientTimer <= diff)
|
||||
if (SummonPatientTimer <= diff || SummonPatientCount < 6) // Starts with 6 beds filled for both factions
|
||||
{
|
||||
if (Coordinates.empty())
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user