Merge branch 'azerothcore:master' into Playerbot

This commit is contained in:
ZhengPeiRu21
2022-03-25 10:48:58 -06:00
committed by GitHub
10 changed files with 499 additions and 185 deletions

View File

@@ -21,6 +21,7 @@
#include "Common.h"
#include "Creature.h"
#include "UnitAI.h"
#include "EventMap.h"
class WorldObject;
class Unit;
@@ -67,6 +68,8 @@ class CreatureAI : public UnitAI
protected:
Creature* const me;
EventMap events;
bool UpdateVictim();
bool UpdateVictimWithGaze();

View File

@@ -20,6 +20,7 @@
#include "DBCFileLoader.h"
#include "DBCfmt.h"
#include "Errors.h"
#include "LFGMgr.h"
#include "Log.h"
#include "SharedDefines.h"
#include "SpellMgr.h"
@@ -529,7 +530,7 @@ void LoadDBCStores(const std::string& dataPath)
for (uint32 i = 1; i < sTaxiPathStore.GetNumRows(); ++i)
if (TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(i))
sTaxiPathSetBySource[entry->from][entry->to] = TaxiPathBySourceAndDestination(entry->ID, entry->price);
sTaxiPathSetBySource[entry->from][entry->to] = entry;
// Calculate path nodes count
uint32 pathCount = sTaxiPathStore.GetNumRows();
@@ -578,7 +579,7 @@ void LoadDBCStores(const std::string& dataPath)
for (TaxiPathSetForSource::const_iterator dest_i = src_i->second.begin(); dest_i != src_i->second.end(); ++dest_i)
{
// not spell path
if (dest_i->second.price || spellPaths.find(dest_i->second.ID) == spellPaths.end())
if (dest_i->second->price || spellPaths.find(dest_i->second->ID) == spellPaths.end())
{
ok = true;
break;
@@ -871,6 +872,19 @@ LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty)
return nullptr;
}
LFGDungeonEntry const* GetZoneLFGDungeonEntry(std::string const& zoneName, LocaleConstant locale)
{
for (LFGDungeonEntry const* dungeon : sLFGDungeonStore)
{
if (dungeon->type == lfg::LFG_TYPE_ZONE && zoneName.find(dungeon->name[locale]) != std::string::npos)
{
return dungeon;
}
}
return nullptr;
}
uint32 GetDefaultMapLight(uint32 mapId)
{
for (int32 i = sLightStore.GetNumRows(); i >= 0; --i)

View File

@@ -66,6 +66,8 @@ CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, ui
CharSectionsEntry const* GetCharSectionEntry(uint8 race, CharSectionType genType, uint8 gender, uint8 type, uint8 color);
LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty);
LFGDungeonEntry const* GetZoneLFGDungeonEntry(std::string const& zoneName, LocaleConstant locale);
uint32 GetDefaultMapLight(uint32 mapId);
typedef std::unordered_multimap<uint32, SkillRaceClassInfoEntry const*> SkillRaceClassInfoMap;

View File

@@ -69,6 +69,7 @@ namespace lfg
LFG_TYPE_NONE = 0,
LFG_TYPE_DUNGEON = 1,
LFG_TYPE_RAID = 2,
LFG_TYPE_ZONE = 4,
LFG_TYPE_HEROIC = 5,
LFG_TYPE_RANDOM = 6
};

View File

@@ -6435,8 +6435,8 @@ void ObjectMgr::GetTaxiPath(uint32 source, uint32 destination, uint32& path, uin
return;
}
cost = dest_i->second.price;
path = dest_i->second.ID;
cost = dest_i->second->price;
path = dest_i->second->ID;
}
uint32 ObjectMgr::GetTaxiMountDisplayId(uint32 id, TeamId teamId, bool allowed_alt_team /* = false */)

View File

@@ -33,6 +33,7 @@
#include "InstanceSaveMgr.h"
#include "Language.h"
#include "Log.h"
#include "MapMgr.h"
#include "Metric.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
@@ -2168,33 +2169,97 @@ void WorldSession::HandleCharFactionOrRaceChangeCallback(std::shared_ptr<Charact
if (factionChangeInfo->FactionChange)
{
// Delete all Flypaths
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_TAXI_PATH);
stmt->SetData(0, lowGuid);
trans->Append(stmt);
if (level > 7)
{
// Update Taxi path
// this doesn't seem to be 100% blizzlike... but it can't really be helped.
std::ostringstream taximaskstream;
uint32 numFullTaximasks = level / 7;
// Delete all Flypaths
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_TAXI_PATH);
stmt->SetData(0, lowGuid);
trans->Append(stmt);
if (numFullTaximasks > 11)
numFullTaximasks = 11;
// Update Taxi path
TaxiMask newTaxiMask;
memset(newTaxiMask, 0, sizeof(newTaxiMask));
TaxiMask const& factionMask = newTeam == TEAM_HORDE ? sHordeTaxiNodesMask : sAllianceTaxiNodesMask;
for (uint8 i = 0; i < numFullTaximasks; ++i)
for (auto const& itr : sTaxiPathSetBySource)
{
uint8 deathKnightExtraNode = (playerClass == CLASS_DEATH_KNIGHT) ? sDeathKnightTaxiNodesMask[i] : 0;
taximaskstream << uint32(factionMask[i] | deathKnightExtraNode) << ' ';
auto FillTaxiMask = [&](uint8 field, uint32 mask)
{
if (playerClass == CLASS_DEATH_KNIGHT)
{
newTaxiMask[field] |= uint32(mask | (sDeathKnightTaxiNodesMask[field] & mask));
}
else
{
newTaxiMask[field] |= mask;
}
};
uint32 nodeId = itr.first;
uint8 field = (uint8)((nodeId - 1) / 32);
uint32 submask = 1 << ((nodeId - 1) % 32);
if ((factionMask[field] & submask) == 0)
{
FillTaxiMask(field, 0);
continue;
}
TaxiPathSetForSource const& taxiPaths = itr.second;
if (taxiPaths.empty())
{
FillTaxiMask(field, 0);
continue;
}
TaxiPathEntry const* taxiPath = taxiPaths.begin()->second;
if (!taxiPath)
{
FillTaxiMask(field, 0);
continue;
}
TaxiPathNodeList const& taxiNodePaths = sTaxiPathNodesByPath[taxiPath->ID];
if (taxiNodePaths.empty())
{
FillTaxiMask(field, 0);
continue;
}
TaxiPathNodeEntry const* pathNode = taxiNodePaths.front();
if (!pathNode)
{
FillTaxiMask(field, 0);
continue;
}
AreaTableEntry const* zone = sAreaTableStore.LookupEntry(sMapMgr->GetZoneId(PHASEMASK_NORMAL, pathNode->mapid, pathNode->x, pathNode->y, pathNode->z));
if (!zone)
{
FillTaxiMask(field, 0);
continue;
}
LFGDungeonEntry const* lfgDungeon = GetZoneLFGDungeonEntry(zone->area_name[GetSessionDbLocaleIndex()], GetSessionDbLocaleIndex());
if (!lfgDungeon)
{
FillTaxiMask(field, 0);
continue;
}
// Get level from LFGDungeonEntry because the one from AreaTableEntry is not valid
// If area level is too big, do not add new taxi
if (lfgDungeon->minlevel > level)
{
FillTaxiMask(field, 0);
continue;
}
FillTaxiMask(field, submask);
}
uint32 numEmptyTaximasks = 11 - numFullTaximasks;
for (uint8 i = 0; i < numEmptyTaximasks; ++i)
taximaskstream << "0 ";
taximaskstream << '0';
std::ostringstream taximaskstream;
for (uint8 i = 0; i < TaxiMaskSize; ++i)
taximaskstream << uint32(newTaxiMask[i]) << ' ';
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_TAXIMASK);
stmt->SetData(0, taximaskstream.str());

View File

@@ -111,6 +111,10 @@ public:
break;
case EVENT_LAUNCH:
{
if (Player* player = me->GetCharmerOrOwnerPlayerOrPlayerItself())
{
player->AddAura(SPELL_EYE_OF_ACHERUS_VISUAL, player);
}
me->SetSpeed(MOVE_FLIGHT, 5.0f, true);
const Position EYE_DESTINATION_1 = { me->GetPositionX() - 40.0f, me->GetPositionY(), me->GetPositionZ() + 10.0f, 0.0f };
@@ -118,6 +122,10 @@ public:
me->GetMotionMaster()->MovePoint(EYE_POINT_DESTINATION_1, EYE_DESTINATION_1);
me->GetMotionMaster()->MovePoint(EYE_POINT_DESTINATION_2, EYE_DESTINATION_2);
if (Player* player = me->GetCharmerOrOwnerPlayerOrPlayerItself())
{
player->RemoveAura(SPELL_EYE_OF_ACHERUS_VISUAL);
}
break;
}
case EVENT_REGAIN_CONTROL:

View File

@@ -25,37 +25,37 @@
#include "SpellInfo.h"
#include "SpellScript.h"
// Theirs
// Theirs
/*######
## Quest 12027: Mr. Floppy's Perilous Adventure
######*/
/*######
## Quest 12027: Mr. Floppy's Perilous Adventure
######*/
enum Floppy
{
// Creature
NPC_MRFLOPPY = 26589,
NPC_HUNGRY_WORG = 26586,
NPC_RAVENOUS_WORG = 26590, // RWORG
NPC_EMILY = 26588,
NPC_MRFLOPPY = 26589,
NPC_HUNGRY_WORG = 26586,
NPC_RAVENOUS_WORG = 26590, // RWORG
NPC_EMILY = 26588,
// Quest
QUEST_PERILOUS_ADVENTURE = 12027,
QUEST_PERILOUS_ADVENTURE = 12027,
// Spell
SPELL_MRFLOPPY = 47184, // vehicle aura
SPELL_MRFLOPPY = 47184, // vehicle aura
// Text
SAY_WORGHAGGRO1 = 0, // Um... I think one of those wolves is back...
SAY_WORGHAGGRO2 = 1, // He's going for Mr. Floppy!
SAY_WORGRAGGRO3 = 2, // Oh, no! Look, it's another wolf, and it's a biiiiiig one!
SAY_WORGRAGGRO4 = 3, // He's gonna eat Mr. Floppy! You gotta help Mr. Floppy! You just gotta!
SAY_RANDOMAGGRO = 4, // There's a big meanie attacking Mr. Floppy! Help!
SAY_VICTORY1 = 5, // Let's get out of here before more wolves find us!
SAY_VICTORY2 = 6, // Don't go toward the light, Mr. Floppy!
SAY_VICTORY3 = 7, // Mr. Floppy, you're ok! Thank you so much for saving Mr. Floppy!
SAY_VICTORY4 = 8, // I think I see the camp! We're almost home, Mr. Floppy! Let's go!
TEXT_EMOTE_WP1 = 9, // Mr. Floppy revives
TEXT_EMOTE_AGGRO = 10, // The Ravenous Worg chomps down on Mr. Floppy
SAY_QUEST_ACCEPT = 11, // Are you ready, Mr. Floppy? Stay close to me and watch out for those wolves!
SAY_QUEST_COMPLETE = 12 // Thank you for helping me get back to the camp. Go tell Walter that I'm safe now!
SAY_WORGHAGGRO1 = 0, // Um... I think one of those wolves is back...
SAY_WORGHAGGRO2 = 1, // He's going for Mr. Floppy!
SAY_WORGRAGGRO3 = 2, // Oh, no! Look, it's another wolf, and it's a biiiiiig one!
SAY_WORGRAGGRO4 = 3, // He's gonna eat Mr. Floppy! You gotta help Mr. Floppy! You just gotta!
SAY_RANDOMAGGRO = 4, // There's a big meanie attacking Mr. Floppy! Help!
SAY_VICTORY1 = 5, // Let's get out of here before more wolves find us!
SAY_VICTORY2 = 6, // Don't go toward the light, Mr. Floppy!
SAY_VICTORY3 = 7, // Mr. Floppy, you're ok! Thank you so much for saving Mr. Floppy!
SAY_VICTORY4 = 8, // I think I see the camp! We're almost home, Mr. Floppy! Let's go!
TEXT_EMOTE_WP1 = 9, // Mr. Floppy revives
TEXT_EMOTE_AGGRO = 10, // The Ravenous Worg chomps down on Mr. Floppy
SAY_QUEST_ACCEPT = 11, // Are you ready, Mr. Floppy? Stay close to me and watch out for those wolves!
SAY_QUEST_COMPLETE = 12 // Thank you for helping me get back to the camp. Go tell Walter that I'm safe now!
};
// emily
@@ -84,102 +84,102 @@ public:
switch (waypointId)
{
case 9:
if (Creature* Mrfloppy = GetClosestCreatureWithEntry(me, NPC_MRFLOPPY, 100.0f))
_mrfloppyGUID = Mrfloppy->GetGUID();
break;
case 10:
if (ObjectAccessor::GetCreature(*me, _mrfloppyGUID))
{
Talk(SAY_WORGHAGGRO1);
if (Creature* worg = me->SummonCreature(NPC_HUNGRY_WORG, me->GetPositionX() + 5, me->GetPositionY() + 2, me->GetPositionZ() + 1, 3.229f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000))
if (Creature* Mrfloppy = ObjectAccessor::GetCreature(*me, _mrfloppyGUID))
{
worg->SetReactState(REACT_AGGRESSIVE);
worg->GetAI()->AttackStart(Mrfloppy);
}
}
break;
case 11:
if (Creature* Mrfloppy = ObjectAccessor::GetCreature(*me, _mrfloppyGUID))
Mrfloppy->GetMotionMaster()->MoveFollow(me, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
break;
case 17:
if (Creature* Mrfloppy = ObjectAccessor::GetCreature(*me, _mrfloppyGUID))
Mrfloppy->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ());
Talk(SAY_WORGRAGGRO3);
if (Creature* RWORG = me->SummonCreature(NPC_RAVENOUS_WORG, me->GetPositionX() + 10, me->GetPositionY() + 8, me->GetPositionZ() + 2, 3.229f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000))
{
RWORG->SetReactState(REACT_PASSIVE);
RWORG->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
RWORG->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
_RavenousworgGUID = RWORG->GetGUID();
}
break;
case 18:
if (Creature* Mrfloppy = ObjectAccessor::GetCreature(*me, _mrfloppyGUID))
{
if (Creature* RWORG = ObjectAccessor::GetCreature(*me, _RavenousworgGUID))
RWORG->GetMotionMaster()->MovePoint(0, Mrfloppy->GetPositionX(), Mrfloppy->GetPositionY(), Mrfloppy->GetPositionZ());
me->AddAura(SPELL_MRFLOPPY, Mrfloppy);
}
break;
case 19:
if (Creature* Mrfloppy = ObjectAccessor::GetCreature(*me, _mrfloppyGUID))
{
if (Mrfloppy->HasAura(SPELL_MRFLOPPY))
case 9:
if (Creature* Mrfloppy = GetClosestCreatureWithEntry(me, NPC_MRFLOPPY, 100.0f))
_mrfloppyGUID = Mrfloppy->GetGUID();
break;
case 10:
if (ObjectAccessor::GetCreature(*me, _mrfloppyGUID))
{
Talk(SAY_WORGHAGGRO1);
if (Creature* worg = me->SummonCreature(NPC_HUNGRY_WORG, me->GetPositionX() + 5, me->GetPositionY() + 2, me->GetPositionZ() + 1, 3.229f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000))
if (Creature* Mrfloppy = ObjectAccessor::GetCreature(*me, _mrfloppyGUID))
{
if (Creature* RWORG = ObjectAccessor::GetCreature(*me, _RavenousworgGUID))
Mrfloppy->EnterVehicle(RWORG);
worg->SetReactState(REACT_AGGRESSIVE);
worg->GetAI()->AttackStart(Mrfloppy);
}
}
break;
case 20:
}
break;
case 11:
if (Creature* Mrfloppy = ObjectAccessor::GetCreature(*me, _mrfloppyGUID))
Mrfloppy->GetMotionMaster()->MoveFollow(me, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
break;
case 17:
if (Creature* Mrfloppy = ObjectAccessor::GetCreature(*me, _mrfloppyGUID))
Mrfloppy->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ());
Talk(SAY_WORGRAGGRO3);
if (Creature* RWORG = me->SummonCreature(NPC_RAVENOUS_WORG, me->GetPositionX() + 10, me->GetPositionY() + 8, me->GetPositionZ() + 2, 3.229f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000))
{
RWORG->SetReactState(REACT_PASSIVE);
RWORG->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
RWORG->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
_RavenousworgGUID = RWORG->GetGUID();
}
break;
case 18:
if (Creature* Mrfloppy = ObjectAccessor::GetCreature(*me, _mrfloppyGUID))
{
if (Creature* RWORG = ObjectAccessor::GetCreature(*me, _RavenousworgGUID))
RWORG->HandleEmoteCommand(34);
break;
case 21:
if (Creature* Mrfloppy = ObjectAccessor::GetCreature(*me, _mrfloppyGUID))
RWORG->GetMotionMaster()->MovePoint(0, Mrfloppy->GetPositionX(), Mrfloppy->GetPositionY(), Mrfloppy->GetPositionZ());
me->AddAura(SPELL_MRFLOPPY, Mrfloppy);
}
break;
case 19:
if (Creature* Mrfloppy = ObjectAccessor::GetCreature(*me, _mrfloppyGUID))
{
if (Mrfloppy->HasAura(SPELL_MRFLOPPY))
{
if (Creature* RWORG = ObjectAccessor::GetCreature(*me, _RavenousworgGUID))
{
Unit::Kill(RWORG, Mrfloppy);
Mrfloppy->ExitVehicle();
RWORG->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
RWORG->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
RWORG->AI()->AttackStart(player);
Talk(SAY_VICTORY2);
}
Mrfloppy->EnterVehicle(RWORG);
}
break;
case 22:
if (Creature* Mrfloppy = ObjectAccessor::GetCreature(*me, _mrfloppyGUID))
}
break;
case 20:
if (Creature* RWORG = ObjectAccessor::GetCreature(*me, _RavenousworgGUID))
RWORG->HandleEmoteCommand(34);
break;
case 21:
if (Creature* Mrfloppy = ObjectAccessor::GetCreature(*me, _mrfloppyGUID))
{
if (Creature* RWORG = ObjectAccessor::GetCreature(*me, _RavenousworgGUID))
{
if (Mrfloppy->isDead())
{
me->GetMotionMaster()->MovePoint(0, Mrfloppy->GetPositionX(), Mrfloppy->GetPositionY(), Mrfloppy->GetPositionZ());
Mrfloppy->setDeathState(ALIVE);
Mrfloppy->GetMotionMaster()->MoveFollow(me, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
Talk(SAY_VICTORY3);
}
Unit::Kill(RWORG, Mrfloppy);
Mrfloppy->ExitVehicle();
RWORG->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
RWORG->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
RWORG->AI()->AttackStart(player);
Talk(SAY_VICTORY2);
}
break;
case 24:
if (player)
}
break;
case 22:
if (Creature* Mrfloppy = ObjectAccessor::GetCreature(*me, _mrfloppyGUID))
{
if (Mrfloppy->isDead())
{
player->GroupEventHappens(QUEST_PERILOUS_ADVENTURE, me);
Talk(SAY_QUEST_COMPLETE, player);
me->GetMotionMaster()->MovePoint(0, Mrfloppy->GetPositionX(), Mrfloppy->GetPositionY(), Mrfloppy->GetPositionZ());
Mrfloppy->setDeathState(ALIVE);
Mrfloppy->GetMotionMaster()->MoveFollow(me, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
Talk(SAY_VICTORY3);
}
me->SetWalk(false);
break;
case 25:
Talk(SAY_VICTORY4);
break;
case 27:
me->DisappearAndDie();
if (Creature* Mrfloppy = ObjectAccessor::GetCreature(*me, _mrfloppyGUID))
Mrfloppy->DisappearAndDie();
break;
}
break;
case 24:
if (player)
{
player->GroupEventHappens(QUEST_PERILOUS_ADVENTURE, me);
Talk(SAY_QUEST_COMPLETE, player);
}
me->SetWalk(false);
break;
case 25:
Talk(SAY_VICTORY4);
break;
case 27:
me->DisappearAndDie();
if (Creature* Mrfloppy = ObjectAccessor::GetCreature(*me, _mrfloppyGUID))
Mrfloppy->DisappearAndDie();
break;
}
}
@@ -506,66 +506,204 @@ enum Skirmisher
{
// Quest
QUEST_OVERWHELMED = 12288,
// Spell
SPELL_RENEW_SKIRMISHER = 48812,
SPELL_KILL_CREDIT = 48813,
SPELL_CLEAVE = 15496,
SPELL_HAMSTRING = 9080,
SPELL_MORTAL_STRIKE = 32736,
// Text
SAY_RANDOM = 0
SAY_RANDOM = 0,
// EVENT
EVENT_WOUNDED_MOVE = 1,
EVENT_CLEAVE = 2,
EVENT_HAMSTRING = 3,
EVENT_MORTAL_STRIKE = 4,
// Waypoints
WOUNDED_MOVE_1 = 274630,
WOUNDED_MOVE_2 = 274631,
WOUNDED_MOVE_3 = 274632
};
class npc_wounded_skirmisher : public CreatureScript
struct npc_wounded_skirmisher : public CreatureAI
{
public:
npc_wounded_skirmisher() : CreatureScript("npc_wounded_skirmisher") { }
struct npc_wounded_skirmisherAI : public ScriptedAI
npc_wounded_skirmisher(Creature* creature) : CreatureAI(creature)
{
npc_wounded_skirmisherAI(Creature* creature) : ScriptedAI(creature) { }
Initialize();
}
void Reset() override
{
_despawnTimer = 5000;
_playerGUID.Clear();
}
void Initialize()
{
me->SetReactState(REACT_DEFENSIVE);
}
void MovementInform(uint32, uint32 id) override
{
if (id == 1)
me->DespawnOrUnsummon(_despawnTimer);
}
void Reset() override
{
Initialize();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
}
void SpellHit(Unit* caster, SpellInfo const* spell) override
void EnterCombat(Unit* /*who*/) override
{
events.ScheduleEvent(EVENT_CLEAVE, urand(1000, 7000));
events.ScheduleEvent(EVENT_HAMSTRING, urand(5000, 12000));
events.ScheduleEvent(EVENT_MORTAL_STRIKE, urand(5000, 10000));
}
void SpellHit(Unit* caster, SpellInfo const* spell) override
{
Player* playerCaster = caster->ToPlayer();
if (!playerCaster)
return;
if (spell->Id == SPELL_RENEW_SKIRMISHER && playerCaster->GetQuestStatus(QUEST_OVERWHELMED) == QUEST_STATUS_INCOMPLETE)
{
if (spell->Id == SPELL_RENEW_SKIRMISHER && caster->GetTypeId() == TYPEID_PLAYER
&& caster->ToPlayer()->GetQuestStatus(QUEST_OVERWHELMED) == QUEST_STATUS_INCOMPLETE)
me->SetFacingToObject(caster);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
Talk(SAY_RANDOM, caster);
DoCast(caster, SPELL_KILL_CREDIT);
if (!me->IsStandState())
{
DoCast(caster, SPELL_KILL_CREDIT);
Talk(SAY_RANDOM, caster);
if (me->IsStandState())
me->GetMotionMaster()->MovePoint(1, me->GetPositionX() + 7, me->GetPositionY() + 7, me->GetPositionZ());
else
{
me->SetStandState(UNIT_STAND_STATE_STAND);
me->DespawnOrUnsummon(_despawnTimer);
}
me->SetStandState(UNIT_STAND_STATE_STAND);
me->HandleEmoteCommand(EMOTE_ONESHOT_CHEER);
events.ScheduleEvent(EVENT_WOUNDED_MOVE, 3000);
}
}
}
void UpdateAI(uint32 /*diff*/) override
{
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
private:
ObjectGuid _playerGUID;
uint32 _despawnTimer;
};
CreatureAI* GetAI(Creature* creature) const override
void UpdateAI(uint32 diff) override
{
return new npc_wounded_skirmisherAI(creature);
events.Update(diff);
switch (events.ExecuteEvent())
{
case EVENT_WOUNDED_MOVE:
if (me->GetPositionY() == -2835.11f)
{
me->GetMotionMaster()->MovePath(WOUNDED_MOVE_1, false);
me->DespawnOrUnsummon(20000);
}
if (me->GetPositionY() == -2981.89f)
{
me->GetMotionMaster()->MovePath(WOUNDED_MOVE_3, false);
me->DespawnOrUnsummon(18000);
}
if (me->GetPositionY() == -2934.44f)
{
me->GetMotionMaster()->MovePath(WOUNDED_MOVE_3, false);
me->DespawnOrUnsummon(9000);
}
if (me->GetPositionY() == -3020.99f)
{
me->GetMotionMaster()->MovePath(WOUNDED_MOVE_1, false);
me->DespawnOrUnsummon(22000);
}
if (me->GetPositionY() == -2964.73f)
{
me->GetMotionMaster()->MovePath(WOUNDED_MOVE_2, false);
me->DespawnOrUnsummon(15000);
}
if (me->GetPositionY() == -2940.50f)
{
me->GetMotionMaster()->MovePath(WOUNDED_MOVE_1, false);
me->DespawnOrUnsummon(20000);
}
if (me->GetPositionY() == -2847.93f)
{
me->GetMotionMaster()->MovePath(WOUNDED_MOVE_1, false);
me->DespawnOrUnsummon(30000);
}
if (me->GetPositionY() == -2835.31f)
{
me->GetMotionMaster()->MovePath(WOUNDED_MOVE_1, false);
me->DespawnOrUnsummon(27000);
}
if (me->GetPositionY() == -2822.20f)
{
me->GetMotionMaster()->MovePath(WOUNDED_MOVE_1, false);
me->DespawnOrUnsummon(25000);
}
if (me->GetPositionY() == -2846.31f)
{
me->GetMotionMaster()->MovePath(WOUNDED_MOVE_1, false);
me->DespawnOrUnsummon(21000);
}
if (me->GetPositionY() == -2897.23f)
{
me->GetMotionMaster()->MovePath(WOUNDED_MOVE_3, false);
me->DespawnOrUnsummon(15000);
}
if (me->GetPositionY() == -2886.01f)
{
me->GetMotionMaster()->MovePath(WOUNDED_MOVE_3, false);
me->DespawnOrUnsummon(25000);
}
if (me->GetPositionY() == -2906.89f)
{
me->GetMotionMaster()->MovePath(WOUNDED_MOVE_3, false);
me->DespawnOrUnsummon(25000);
}
if (me->GetPositionY() == -3048.94f)
{
me->GetMotionMaster()->MovePath(WOUNDED_MOVE_2, false);
me->DespawnOrUnsummon(30000);
}
if (me->GetPositionY() == -2961.08f)
{
me->GetMotionMaster()->MovePath(WOUNDED_MOVE_2, false);
me->DespawnOrUnsummon(25000);
}
break;
case EVENT_CLEAVE:
me->CastSpell(me->GetVictim(), SPELL_CLEAVE, false);
events.RepeatEvent(urand(7000, 15000));
break;
case EVENT_HAMSTRING:
me->CastSpell(me->GetVictim(), SPELL_HAMSTRING, false);
events.RepeatEvent(urand(9000, 15000));
break;
case EVENT_MORTAL_STRIKE:
me->CastSpell(me->GetVictim(), SPELL_MORTAL_STRIKE, false);
events.RepeatEvent(urand(10000, 15000));
break;
}
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
};
enum renewskirmisher
{
NPC_WOUNDED_SKIRMISHER = 27463
};
class spell_renew_skirmisher : public SpellScript
{
public:
PrepareSpellScript(spell_renew_skirmisher);
SpellCastResult CheckRequirement()
{
if (Unit* caster = GetCaster())
if (Creature* wounded = caster->FindNearestCreature(NPC_WOUNDED_SKIRMISHER, 5.0f))
if (!wounded->IsInCombat())
return SPELL_CAST_OK;
return SPELL_FAILED_CASTER_AURASTATE;
}
void Register() override
{
OnCheckCast += SpellCheckCastFn(spell_renew_skirmisher::CheckRequirement);
}
};
@@ -1163,7 +1301,8 @@ void AddSC_grizzly_hills()
new npc_outhouse_bunny();
new npc_tallhorn_stag();
new npc_amberpine_woodsman();
new npc_wounded_skirmisher();
RegisterCreatureAI(npc_wounded_skirmisher);
RegisterSpellScript(spell_renew_skirmisher);
new npc_venture_co_straggler();
new npc_lake_frog();
new spell_shredder_delivery();

View File

@@ -2195,15 +2195,7 @@ struct TalentSpellPos
typedef std::map<uint32, TalentSpellPos> TalentSpellPosMap;
struct TaxiPathBySourceAndDestination
{
TaxiPathBySourceAndDestination() = default;
TaxiPathBySourceAndDestination(uint32 _id, uint32 _price) : ID(_id), price(_price) {}
uint32 ID{0};
uint32 price{0};
};
typedef std::map<uint32, TaxiPathBySourceAndDestination> TaxiPathSetForSource;
typedef std::map<uint32, TaxiPathEntry const*> TaxiPathSetForSource;
typedef std::map<uint32, TaxiPathSetForSource> TaxiPathSetBySource;
typedef std::vector<TaxiPathNodeEntry const*> TaxiPathNodeList;