Skip to content

Instantly share code, notes, and snippets.

@sirikfoll
Last active February 21, 2018 03:56
Show Gist options
  • Save sirikfoll/16c1d9f9f2ab856bb83f to your computer and use it in GitHub Desktop.
Save sirikfoll/16c1d9f9f2ab856bb83f to your computer and use it in GitHub Desktop.
Quest The Balance of Light and Shadow support (npc eris havenfire, npc fleeing peasant/plagued peasant)
enum ErisHavenfireSays
{
SAY_DEATH = 0,
SAY_SPAWN = 1,
SAY_SAVED = 2,
SAY_EMPOWER = 0,
SAY_COMPLETE = 1,
SAY_FAILED1 = 2,
SAY_FAILED2 = 3
};
enum ErisHavenfireMisc
{
QUEST_THE_BALANCE_OF_LIGHT_AND_SHADOW = 7622,
NPC_INJURED_PEASANT = 14484,
NPC_SCOURGE_ARCHER = 14489,
NPC_SCOURGE_FOOTSOLDIER = 14486,
NPC_PLAGUED_PEASANT = 14485,
SPELL_BLESSING_OF_NORDRASSIL = 23108,
SPELL_DEATH_DOOR = 23127,
SPELL_SEETHING_PLAGUE = 23072,
SPELL_ENTER_THE_LIGHT_DND = 23107,
SPELL_SHOOT = 23073,
ACTION_START_SPAWN = 0,
ACTION_SEARCH_TARGETS = 1,
SUCCESS = 50,
FAILED = 15,
MAX_PEASANTS = 12,
MAX_ARCHERS = 8,
};
Position const ArcherPositions[11] =
{
// Archers
{ 3327.42f, -3021.11f, 170.57f, 6.01f },
{ 3335.4f, -3054.3f, 173.63f, 0.49f },
{ 3351.3f, -3079.08f, 178.67f, 1.15f },
{ 3358.93f, -3076.1f, 174.87f, 1.57f },
{ 3371.58f, -3069.24f, 175.20f, 1.99f },
{ 3369.46f, -3023.11f, 171.83f, 3.69f },
{ 3383.25f, -3057.01f, 181.53f, 2.21f },
{ 3380.03f, -3062.73f, 181.90f, 2.31f },
// Footsoldiers
{ 3347.603271f, -3045.536377f, 164.029877f, 1.814429f },
{ 3363.609131f, -3037.187256f, 163.541885f, 2.277649f },
{ 3349.105469f, -3056.500977f, 168.079468f, 1.857460f },
};
Position const PeasantMoveLoc = { 3335.0f, -2994.04f, 161.14f };
Position const PeasantsPos[12] =
{
{ 3364.47f, -3048.50f, 165.17f, 1.86f },
{ 3363.24f, -3052.06f, 165.26f, 2.095f },
{ 3362.33f, -3049.37f, 165.23f, 1.54f },
{ 3360.13f, -3052.63f, 165.31f, 1.88f },
{ 3361.05f, -3055.49f, 165.31f, 2.041f },
{ 3363.92f, -3046.96f, 165.09f, 2.13f },
{ 3366.83f, -3052.23f, 165.41f, 2.044f },
{ 3367.79f, -3047.80f, 165.16f, 2.08f },
{ 3358.76f, -3050.37f, 165.21f, 2.05f },
{ 3366.63f, -3045.29f, 164.99f, 2.19f },
{ 3357.45f, -3052.82f, 165.50f, 2.006f },
{ 3363.00f, -3044.21f, 164.80f, 2.182f }
};
struct npc_eris_havenfire : public ScriptedAI
{
npc_eris_havenfire(Creature* creature) : ScriptedAI(creature), _summons(me) { }
void Reset()
{
_scheduler.CancelAll();
_summons.DespawnAll();
_failCounter = 0;
_winCounter = 0;
_eventActive = false;
}
void JustSummoned(Creature* summon) override
{
_summons.Summon(summon);
}
void FinishQuest(bool success)
{
if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
{
if (Group* group = player->GetGroup())
{
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
if (Player* member = itr->GetSource())
{
if (success)
member->CompleteQuest(QUEST_THE_BALANCE_OF_LIGHT_AND_SHADOW);
else if (player->GetQuestStatus(QUEST_THE_BALANCE_OF_LIGHT_AND_SHADOW) == QUEST_STATUS_INCOMPLETE)
member->FailQuest(QUEST_THE_BALANCE_OF_LIGHT_AND_SHADOW);
}
}
else if (success)
player->CompleteQuest(QUEST_THE_BALANCE_OF_LIGHT_AND_SHADOW);
else if (player->GetQuestStatus(QUEST_THE_BALANCE_OF_LIGHT_AND_SHADOW) == QUEST_STATUS_INCOMPLETE)
player->FailQuest(QUEST_THE_BALANCE_OF_LIGHT_AND_SHADOW);
}
if (success)
{
Talk(SAY_COMPLETE);
Reset();
}
else
{
Talk(SAY_FAILED1);
Talk(SAY_FAILED2);
//me->DespawnOrUnsummon(Seconds(2));
}
}
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
{
if (summon->GetEntry() == NPC_INJURED_PEASANT || summon->GetEntry() == NPC_PLAGUED_PEASANT)
++_failCounter;
if (_failCounter >= FAILED)
FinishQuest(false);
}
void SetData(uint32 /*data*/, uint32 /*value*/) override
{
++_winCounter;
if (_winCounter >= SUCCESS)
FinishQuest(true);
}
void DoAction(int32 action) override
{
if (!_eventActive && action == ACTION_START_SPAWN)
{
_eventActive = true;
for (uint8 i = 0; i < MAX_ARCHERS; i++)
if (Creature* archer = me->SummonCreature(NPC_SCOURGE_ARCHER, ArcherPositions[i], TEMPSUMMON_TIMED_DESPAWN, 5 * MINUTE * IN_MILLISECONDS))
{
archer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_1);
}
_scheduler.Schedule(Seconds(10), [this](TaskContext waves)
{
if (waves.GetRepeatCounter() > 5)
_scheduler.CancelAll();
for (uint8 i = 0; i <= MAX_PEASANTS; i++)
if (Creature* peasant = me->SummonCreature(roll_chance_i(70) ? NPC_INJURED_PEASANT : NPC_PLAGUED_PEASANT, PeasantsPos[i], TEMPSUMMON_DEAD_DESPAWN))
if (peasant->GetEntry() == NPC_PLAGUED_PEASANT)
peasant->CastSpell(peasant, roll_chance_i(70) ? SPELL_SEETHING_PLAGUE : SPELL_DEATH_DOOR, true);
if (Creature* peasant = me->FindNearestCreature(NPC_INJURED_PEASANT, 100.0f, true))
peasant->AI()->Talk(SAY_SPAWN);
EntryCheckPredicate pred(NPC_SCOURGE_ARCHER);
_summons.DoAction(ACTION_SEARCH_TARGETS, pred);
waves.Repeat(Seconds(60));
});
_scheduler.Schedule(Seconds(72), [this](TaskContext soldiers)
{
for (uint8 i = 0; i < urand(2, 3); ++i)
if (Creature* soldier = me->SummonCreature(NPC_SCOURGE_FOOTSOLDIER, PeasantsPos[urand(0, 11)], TEMPSUMMON_CORPSE_DESPAWN))
{
if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
soldier->AI()->AttackStart(player);
}
soldiers.Repeat(Seconds(20), Seconds(40));
});
_scheduler.Schedule(Seconds(2), [this](TaskContext heal)
{
heal.Repeat();
if (Player* priest = ObjectAccessor::GetPlayer(*me, _playerGUID))
if (priest->IsAlive())
{
if (!priest->HasAuraEffect(SPELL_BLESSING_OF_NORDRASSIL, EFFECT_0) && priest->GetMaxPower(POWER_MANA) && (100.0f * priest->GetPower(POWER_MANA) / priest->GetMaxPower(POWER_MANA)) < 35.0f)
{
me->CastSpell(priest, SPELL_BLESSING_OF_NORDRASSIL, true);
Talk(SAY_EMPOWER);
}
}
else
FinishQuest(false);
});
}
}
void UpdateAI(uint32 diff) override
{
if (!_eventActive)
return;
_scheduler.Update(diff);
}
void QuestAccept(Player* player, Quest const* quest) override
{
if (!_eventActive && quest->GetQuestId() == QUEST_THE_BALANCE_OF_LIGHT_AND_SHADOW)
{
DoAction(ACTION_START_SPAWN);
_playerGUID = player->GetGUID();
}
}
private:
SummonList _summons;
uint32 _failCounter;
uint32 _winCounter;
bool _eventActive;
TaskScheduler _scheduler;
ObjectGuid _playerGUID;
};
class ArcherTargetSelector
{
public:
ArcherTargetSelector() { }
bool operator()(WorldObject* target) const
{
return target->GetTypeId() != TYPEID_PLAYER;
}
};
struct npc_scourge_archer : public ScriptedAI
{
npc_scourge_archer(Creature *creature) : ScriptedAI(creature)
{
SetCombatMovement(false);
me->SetReactState(REACT_AGGRESSIVE);
}
void DoAction(int32 action) override
{
if (action == ACTION_SEARCH_TARGETS)
{
ResetThreatList();
std::vector<Creature*> peasants;
me->GetCreatureListWithEntryInGrid(peasants, NPC_PLAGUED_PEASANT, 48.0f);
me->GetCreatureListWithEntryInGrid(peasants, NPC_INJURED_PEASANT, 48.0f);
for (Creature* peasant : peasants)
{
me->GetThreatManager().AddThreat(peasant, 1.0f);
}
}
}
void Reset() override
{
_scheduler.Schedule(Seconds(1), [this](TaskContext shoot)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, ArcherTargetSelector()))
{
DoCast(target, SPELL_SHOOT, true);
}
shoot.Repeat(Milliseconds(1517));
});
}
void EnterEvadeMode(EvadeReason why) override
{
std::cout << "\n Evade";
}
void UpdateAI(uint32 diff) override
{
UpdateVictim();
_scheduler.Update(diff);
}
private:
TaskScheduler _scheduler;
};
struct npc_fleeing_peasant : public ScriptedAI
{
npc_fleeing_peasant(Creature *creature) : ScriptedAI(creature) { }
void Reset()
{
me->SetWalk(true);
me->SetSpeed(MOVE_WALK, 0.45f);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
me->SetReactState(REACT_PASSIVE);
me->GetMotionMaster()->MovePoint(1, PeasantMoveLoc);
}
void MovementInform(uint32 type, uint32 point) override
{
if (type != POINT_MOTION_TYPE && point != 1)
return;
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->RemoveAllAuras();
DoCastSelf(SPELL_ENTER_THE_LIGHT_DND);
Talk(SAY_SAVED);
me->DespawnOrUnsummon(Seconds(2));
if (Creature* eris = me->FindNearestCreature(14494, 200.0f, true))
eris->ToCreature()->AI()->SetData(1, 1);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
}
};
@sirikfoll
Copy link
Author

sirikfoll commented Feb 28, 2017

UPDATE `creature_template` SET `flags_extra`=0 ,`ScriptName`='npc_fleeing_peasant', `RegenHealth`=0 WHERE `entry` IN (14484,14485);
UPDATE `creature_template` SET `ScriptName`='npc_eris_havenfire' WHERE `entry`=14494;
UPDATE `creature_template` SET `ScriptName`='npc_scourge_archer' WHERE `entry`=14489;

DELETE FROM `creature_text` WHERE `CreatureID` IN (14484,14494);
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(14484, 0, 0, 'Death take me! I cannot go on! I have nothing left...', 12, 0, 100, 0, 0, 0, 9683, 0, 'Fleeing Peasant'),
(14484, 0, 1, 'Should I live through this, I shall make it my live\'s sole ambition to destroy Arthas...', 12, 0, 100, 0, 0, 0, 9682, 0, 'Fleeing Peasant'),
(14484, 0, 2, 'The pain is unbearable!', 12, 0, 100, 0, 0, 0, 9681, 0, 'Fleeing Peasant'),
(14484, 0, 3, 'I won\'t make it... go... go on without me...', 12, 0, 100, 0, 0, 0, 9680, 0, 'Fleeing Peasant'),
(14484, 1, 0, 'The Scourge is uppon us! Run! Run for your lives!', 12, 0, 100, 0, 0, 0, 9712, 0, 'Fleeing Peasant'),
(14484, 1, 1, 'Please help us! The Prince has gone mad!', 12, 0, 100, 0, 0, 0, 9713, 0, 'Fleeing Peasant'),
(14484, 1, 2, 'Seek sanctuary in Hearthglen! It is our only hope!', 12, 0, 100, 0, 0, 0, 9714, 0, 'Fleeing Peasant'),
(14484, 2, 0, 'Thank you, kind stranger. May your heroism never be forgotten.', 12, 0, 100, 0, 0, 0, 9651, 0, 'Fleeing Peasant'),
(14484, 2, 1, 'The power of the light is truly great and merciful.', 12, 0, 100, 0, 0, 0, 9654, 0, 'Fleeing Peasant'),
(14484, 2, 2, 'Stranger, find the fallen Prince Menethil and end his reign of terror.', 12, 0, 100, 0, 0, 0, 9653, 0, 'Fleeing Peasant'),

(14494, 0, 0, 'Be healed!', 14, 0, 100, 0, 0, 0, 9655, 0, 'Eris Havenfire'),
(14494, 1, 0, 'We are saved! The peasants have escaped the Scourge!', 12, 0, 100, 0, 0, 0, 9728, 0, 'Eris Havenfire');

DELETE FROM `creature_template_addon` WHERE `entry`=14494;
INSERT INTO `creature_template_addon` (`entry`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `auras`) VALUES
(14494, 0, 0, 0, 1, 0, 23196);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment