a whole lot of bugfixes
This commit is contained in:
1 parent
0fc355fb7f
commit
fec36215f6
7 files changed
+5253
-1744
No files matched your search
@@ -0,0 +1,79 @@
|
||||
# This is the CMakeCache file.
|
||||
# For build in directory: /home/wow_admin/wow_cata_server/source/TrinityCore
|
||||
# It was generated by CMake: /usr/bin/cmake
|
||||
# You can edit this file to change values found and used by cmake.
|
||||
# If you do not want to change any of the values, simply exit the editor.
|
||||
# If you do want to change a value, simply edit, save, and exit the editor.
|
||||
# The syntax for the file is as follows:
|
||||
# KEY:TYPE=VALUE
|
||||
# KEY is the name of a variable in the cache.
|
||||
# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!.
|
||||
# VALUE is the current value for the KEY.
|
||||
|
||||
########################
|
||||
# EXTERNAL cache entries
|
||||
########################
|
||||
|
||||
//Value Computed by CMake.
|
||||
CMAKE_FIND_PACKAGE_REDIRECTS_DIR:STATIC=/home/wow_admin/wow_cata_server/source/TrinityCore/CMakeFiles/pkgRedirects
|
||||
|
||||
//Value Computed by CMake
|
||||
CMAKE_PROJECT_DESCRIPTION:STATIC=
|
||||
|
||||
//Value Computed by CMake
|
||||
CMAKE_PROJECT_HOMEPAGE_URL:STATIC=
|
||||
|
||||
//Value Computed by CMake
|
||||
CMAKE_PROJECT_NAME:STATIC=TrinityCore
|
||||
|
||||
//Path to a program.
|
||||
CMAKE_UNAME:FILEPATH=/usr/bin/uname
|
||||
|
||||
//Value Computed by CMake
|
||||
TrinityCore_BINARY_DIR:STATIC=/home/wow_admin/wow_cata_server/source/TrinityCore
|
||||
|
||||
//Value Computed by CMake
|
||||
TrinityCore_IS_TOP_LEVEL:STATIC=ON
|
||||
|
||||
//Value Computed by CMake
|
||||
TrinityCore_SOURCE_DIR:STATIC=/home/wow_admin/wow_cata_server/source/TrinityCore
|
||||
|
||||
|
||||
########################
|
||||
# INTERNAL cache entries
|
||||
########################
|
||||
|
||||
//This is the directory where this CMakeCache.txt was created
|
||||
CMAKE_CACHEFILE_DIR:INTERNAL=/home/wow_admin/wow_cata_server/source/TrinityCore
|
||||
//Major version of cmake used to create the current loaded cache
|
||||
CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3
|
||||
//Minor version of cmake used to create the current loaded cache
|
||||
CMAKE_CACHE_MINOR_VERSION:INTERNAL=28
|
||||
//Patch version of cmake used to create the current loaded cache
|
||||
CMAKE_CACHE_PATCH_VERSION:INTERNAL=3
|
||||
//Path to CMake executable.
|
||||
CMAKE_COMMAND:INTERNAL=/usr/bin/cmake
|
||||
//Path to cpack program executable.
|
||||
CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack
|
||||
//Path to ctest program executable.
|
||||
CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest
|
||||
//Name of external makefile project generator.
|
||||
CMAKE_EXTRA_GENERATOR:INTERNAL=
|
||||
//Name of generator.
|
||||
CMAKE_GENERATOR:INTERNAL=Unix Makefiles
|
||||
//Generator instance identifier.
|
||||
CMAKE_GENERATOR_INSTANCE:INTERNAL=
|
||||
//Name of generator platform.
|
||||
CMAKE_GENERATOR_PLATFORM:INTERNAL=
|
||||
//Name of generator toolset.
|
||||
CMAKE_GENERATOR_TOOLSET:INTERNAL=
|
||||
//Source directory with the top level CMakeLists.txt file for this
|
||||
// project
|
||||
CMAKE_HOME_DIRECTORY:INTERNAL=/home/wow_admin/wow_cata_server/source/TrinityCore
|
||||
//number of local generators
|
||||
CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1
|
||||
//Platform information initialized
|
||||
CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1
|
||||
//Path to CMake installation.
|
||||
CMAKE_ROOT:INTERNAL=/usr/share/cmake-3.28
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
# This file is generated by cmake for dependency checking of the CMakeCache.txt file
|
||||
@@ -21,9 +21,14 @@
|
||||
// VIANO_ADVENTURERS
|
||||
void AddSC_viano_adventurers();
|
||||
|
||||
// Viano Server diagnostics
|
||||
void AddSC_vcore_diagnostics();
|
||||
|
||||
// The name of this function should match:
|
||||
// void Add${NameOfDirectory}Scripts()
|
||||
void AddCustomScripts()
|
||||
{
|
||||
AddSC_viano_adventurers();
|
||||
AddSC_vcore_diagnostics();
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1760,6 +1760,644 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// WOW-PRIVATE-SERVER PATCH: Human Infestation (28138)
|
||||
//
|
||||
// Restores the missing capture logic for the Titanium Shackles.
|
||||
// Spell 88797 used on a Hillsbrad Sentry at <= 35% health grants
|
||||
// quest credit through the Captured Human Proxy and replaces the
|
||||
// sentry with the matching Captured Hillsbrad Human follower.
|
||||
enum HumanInfestation
|
||||
{
|
||||
QUEST_HUMAN_INFESTATION = 28138,
|
||||
|
||||
NPC_HILLSBRAD_MINER = 2269,
|
||||
NPC_HILLSBRAD_SENTRY = 2270,
|
||||
NPC_HILLSBRAD_FOREMAN = 2503,
|
||||
|
||||
NPC_CAPTURED_HUMAN_PROXY = 47697,
|
||||
NPC_CAPTURED_HUMAN_MODEL_3629 = 47689,
|
||||
NPC_CAPTURED_HUMAN_MODEL_3633 = 47693,
|
||||
NPC_CAPTURED_HUMAN_MODEL_3632 = 47694,
|
||||
NPC_CAPTURED_HUMAN_MODEL_5785 = 47695,
|
||||
|
||||
SPELL_TITANIUM_SHACKLES = 88797
|
||||
};
|
||||
|
||||
struct npc_hillsbrad_captured_human : public ScriptedAI
|
||||
{
|
||||
npc_hillsbrad_captured_human(Creature* creature)
|
||||
: ScriptedAI(creature), _checkTimer(1000) { }
|
||||
|
||||
void IsSummonedBy(Unit* summoner) override
|
||||
{
|
||||
Player* player = summoner ? summoner->ToPlayer() : nullptr;
|
||||
if (!player)
|
||||
{
|
||||
me->DespawnOrUnsummon();
|
||||
return;
|
||||
}
|
||||
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->AttackStop();
|
||||
me->CombatStop(true);
|
||||
me->SetFaction(player->GetFaction());
|
||||
|
||||
// Follow slightly behind the player.
|
||||
me->GetMotionMaster()->MoveFollow(player, 2.0f, float(M_PI));
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (_checkTimer > diff)
|
||||
{
|
||||
_checkTimer -= diff;
|
||||
return;
|
||||
}
|
||||
|
||||
_checkTimer = 1000;
|
||||
|
||||
TempSummon* summon = me->ToTempSummon();
|
||||
if (!summon)
|
||||
{
|
||||
me->DespawnOrUnsummon();
|
||||
return;
|
||||
}
|
||||
|
||||
Unit* summoner = summon->GetSummoner();
|
||||
Player* player = summoner ? summoner->ToPlayer() : nullptr;
|
||||
if (!player)
|
||||
{
|
||||
me->DespawnOrUnsummon();
|
||||
return;
|
||||
}
|
||||
|
||||
QuestStatus const status = player->GetQuestStatus(QUEST_HUMAN_INFESTATION);
|
||||
|
||||
// Keep followers while the quest is incomplete or complete-but-not-turned-in.
|
||||
// Remove them after turn-in, abandonment, or failure.
|
||||
if (status == QUEST_STATUS_NONE ||
|
||||
status == QUEST_STATUS_REWARDED ||
|
||||
status == QUEST_STATUS_FAILED)
|
||||
{
|
||||
me->DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 _checkTimer;
|
||||
};
|
||||
|
||||
class spell_hillsbrad_titanium_shackles : public SpellScript
|
||||
{
|
||||
void HandleHit()
|
||||
{
|
||||
Player* player = GetCaster() ? GetCaster()->ToPlayer() : nullptr;
|
||||
Creature* target = GetHitCreature();
|
||||
|
||||
if (!player || !target)
|
||||
return;
|
||||
|
||||
if (player->GetQuestStatus(QUEST_HUMAN_INFESTATION) != QUEST_STATUS_INCOMPLETE)
|
||||
return;
|
||||
|
||||
if (!target->IsAlive())
|
||||
return;
|
||||
|
||||
switch (target->GetEntry())
|
||||
{
|
||||
case NPC_HILLSBRAD_MINER:
|
||||
case NPC_HILLSBRAD_SENTRY:
|
||||
case NPC_HILLSBRAD_FOREMAN:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (target->GetHealthPct() > 35.0f)
|
||||
return;
|
||||
|
||||
uint32 captiveEntry = 0;
|
||||
|
||||
// Preserve the Sentry's visual family where possible:
|
||||
// 3632 <-> 5784 and 5785 <-> 5786 are the two model pairs.
|
||||
switch (target->GetDisplayId())
|
||||
{
|
||||
case 3629:
|
||||
captiveEntry = NPC_CAPTURED_HUMAN_MODEL_3629;
|
||||
break;
|
||||
|
||||
case 3633:
|
||||
captiveEntry = NPC_CAPTURED_HUMAN_MODEL_3633;
|
||||
break;
|
||||
|
||||
case 3632:
|
||||
case 5784:
|
||||
captiveEntry = NPC_CAPTURED_HUMAN_MODEL_3632;
|
||||
break;
|
||||
|
||||
case 5785:
|
||||
case 5786:
|
||||
captiveEntry = NPC_CAPTURED_HUMAN_MODEL_5785;
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
uint32 const capturedHumans[] =
|
||||
{
|
||||
NPC_CAPTURED_HUMAN_MODEL_3629,
|
||||
NPC_CAPTURED_HUMAN_MODEL_3633,
|
||||
NPC_CAPTURED_HUMAN_MODEL_3632,
|
||||
NPC_CAPTURED_HUMAN_MODEL_5785
|
||||
};
|
||||
|
||||
captiveEntry = capturedHumans[urand(0, 3)];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
player->KilledMonsterCredit(NPC_CAPTURED_HUMAN_PROXY);
|
||||
|
||||
// Player-owned summon so logout naturally cleans it up.
|
||||
player->SummonCreature(
|
||||
captiveEntry,
|
||||
target->GetPosition(),
|
||||
TEMPSUMMON_MANUAL_DESPAWN
|
||||
);
|
||||
|
||||
target->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnHit.Register(&spell_hillsbrad_titanium_shackles::HandleHit);
|
||||
}
|
||||
};
|
||||
|
||||
// WOW-PRIVATE-SERVER PATCH: Coastal Delicacies (28146)
|
||||
//
|
||||
// Restores the missing Hungry Mine Creeper companion and feeding sequence.
|
||||
// The companion exists only in the intended Hillsbrad subzones, follows the
|
||||
// quest owner, and only consumes Murlocs actually killed by that owner.
|
||||
enum CoastalDelicacies
|
||||
{
|
||||
QUEST_COASTAL_DELICACIES = 28146,
|
||||
|
||||
NPC_HUNGRY_MINE_CREEPER = 47662,
|
||||
NPC_MURLOC_EATEN_PROXY = 47752,
|
||||
NPC_TORN_FIN_MUCKDWELLER = 2374,
|
||||
NPC_TORN_FIN_COASTRUNNER = 2375,
|
||||
|
||||
AREA_WESTERN_STRAND = 295,
|
||||
AREA_AZURELODE_MINE = 288,
|
||||
|
||||
POINT_COASTAL_FEED_CORPSE = 1,
|
||||
|
||||
COASTAL_STATE_FOLLOWING = 0,
|
||||
COASTAL_STATE_MOVING_TO_CORPSE = 1,
|
||||
COASTAL_STATE_EATING = 2
|
||||
};
|
||||
|
||||
static bool IsCoastalDelicaciesArea(uint32 areaId)
|
||||
{
|
||||
return areaId == AREA_WESTERN_STRAND || areaId == AREA_AZURELODE_MINE;
|
||||
}
|
||||
|
||||
static Creature* FindOwnedHungryMineCreeper(Player* player)
|
||||
{
|
||||
if (!player)
|
||||
return nullptr;
|
||||
|
||||
std::list<Creature*> creepers;
|
||||
GetCreatureListWithEntryInGrid(creepers, player, NPC_HUNGRY_MINE_CREEPER, 120.0f);
|
||||
|
||||
for (Creature* creeper : creepers)
|
||||
{
|
||||
if (!creeper)
|
||||
continue;
|
||||
|
||||
TempSummon* summon = creeper->ToTempSummon();
|
||||
if (!summon)
|
||||
continue;
|
||||
|
||||
if (summon->GetSummoner() == player)
|
||||
return creeper;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void DespawnOwnedHungryMineCreeper(Player* player)
|
||||
{
|
||||
if (Creature* creeper = FindOwnedHungryMineCreeper(player))
|
||||
creeper->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
static void EnsureHungryMineCreeper(Player* player)
|
||||
{
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
if (player->GetQuestStatus(QUEST_COASTAL_DELICACIES) != QUEST_STATUS_INCOMPLETE ||
|
||||
!IsCoastalDelicaciesArea(player->GetAreaId()))
|
||||
{
|
||||
DespawnOwnedHungryMineCreeper(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (FindOwnedHungryMineCreeper(player))
|
||||
return;
|
||||
|
||||
player->SummonCreature(
|
||||
NPC_HUNGRY_MINE_CREEPER,
|
||||
player->GetPosition(),
|
||||
TEMPSUMMON_MANUAL_DESPAWN
|
||||
);
|
||||
}
|
||||
|
||||
struct npc_hillsbrad_hungry_mine_creeper : public ScriptedAI
|
||||
{
|
||||
npc_hillsbrad_hungry_mine_creeper(Creature* creature)
|
||||
: ScriptedAI(creature),
|
||||
_state(COASTAL_STATE_FOLLOWING),
|
||||
_eatTimer(0),
|
||||
_ownerCheckTimer(500) { }
|
||||
|
||||
void IsSummonedBy(Unit* summoner) override
|
||||
{
|
||||
Player* player = summoner ? summoner->ToPlayer() : nullptr;
|
||||
if (!player)
|
||||
{
|
||||
me->DespawnOrUnsummon();
|
||||
return;
|
||||
}
|
||||
|
||||
_ownerGuid = player->GetGUID();
|
||||
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->AttackStop();
|
||||
me->CombatStop(true);
|
||||
me->SetFaction(player->GetFaction());
|
||||
me->SetWalk(false);
|
||||
FollowOwner();
|
||||
}
|
||||
|
||||
void SetGUID(ObjectGuid const& guid, int32 id) override
|
||||
{
|
||||
if (id != POINT_COASTAL_FEED_CORPSE || _state != COASTAL_STATE_FOLLOWING)
|
||||
return;
|
||||
|
||||
Creature* corpse = ObjectAccessor::GetCreature(*me, guid);
|
||||
if (!IsValidFeedCorpse(corpse))
|
||||
return;
|
||||
|
||||
_corpseGuid = guid;
|
||||
_state = COASTAL_STATE_MOVING_TO_CORPSE;
|
||||
|
||||
me->AttackStop();
|
||||
me->CombatStop(true);
|
||||
me->GetMotionMaster()->MovePoint(
|
||||
POINT_COASTAL_FEED_CORPSE,
|
||||
corpse->GetPosition(),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type != POINT_MOTION_TYPE || id != POINT_COASTAL_FEED_CORPSE)
|
||||
return;
|
||||
|
||||
if (_state == COASTAL_STATE_MOVING_TO_CORPSE)
|
||||
BeginEating();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (_ownerCheckTimer > diff)
|
||||
_ownerCheckTimer -= diff;
|
||||
else
|
||||
{
|
||||
_ownerCheckTimer = 500;
|
||||
|
||||
Player* player = GetOwnerPlayer();
|
||||
if (!player ||
|
||||
player->GetQuestStatus(QUEST_COASTAL_DELICACIES) != QUEST_STATUS_INCOMPLETE ||
|
||||
!IsCoastalDelicaciesArea(player->GetAreaId()))
|
||||
{
|
||||
me->DespawnOrUnsummon();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_state == COASTAL_STATE_FOLLOWING)
|
||||
{
|
||||
if (me->GetDistance(player) > 4.0f)
|
||||
FollowOwner();
|
||||
}
|
||||
else if (_state == COASTAL_STATE_MOVING_TO_CORPSE)
|
||||
{
|
||||
Creature* corpse = GetFeedCorpse();
|
||||
if (!IsValidFeedCorpse(corpse))
|
||||
{
|
||||
ResetToFollowing();
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->GetDistance(corpse) <= 2.5f)
|
||||
BeginEating();
|
||||
}
|
||||
}
|
||||
|
||||
if (_state == COASTAL_STATE_EATING)
|
||||
{
|
||||
if (_eatTimer > diff)
|
||||
_eatTimer -= diff;
|
||||
else
|
||||
FinishEating();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Player* GetOwnerPlayer()
|
||||
{
|
||||
return ObjectAccessor::GetPlayer(*me, _ownerGuid);
|
||||
}
|
||||
|
||||
Creature* GetFeedCorpse()
|
||||
{
|
||||
if (_corpseGuid.IsEmpty())
|
||||
return nullptr;
|
||||
|
||||
return ObjectAccessor::GetCreature(*me, _corpseGuid);
|
||||
}
|
||||
|
||||
bool IsValidFeedCorpse(Creature* corpse) const
|
||||
{
|
||||
if (!corpse || corpse->IsAlive())
|
||||
return false;
|
||||
|
||||
return corpse->GetEntry() == NPC_TORN_FIN_MUCKDWELLER ||
|
||||
corpse->GetEntry() == NPC_TORN_FIN_COASTRUNNER;
|
||||
}
|
||||
|
||||
void FollowOwner()
|
||||
{
|
||||
if (Player* player = GetOwnerPlayer())
|
||||
me->GetMotionMaster()->MoveFollow(player, 2.0f, float(M_PI));
|
||||
}
|
||||
|
||||
void BeginEating()
|
||||
{
|
||||
Creature* corpse = GetFeedCorpse();
|
||||
if (!IsValidFeedCorpse(corpse))
|
||||
{
|
||||
ResetToFollowing();
|
||||
return;
|
||||
}
|
||||
|
||||
_state = COASTAL_STATE_EATING;
|
||||
_eatTimer = 2000;
|
||||
|
||||
me->StopMoving();
|
||||
me->SetFacingToObject(corpse);
|
||||
|
||||
// Emote 54 = one-shot special 1H attack in this client build.
|
||||
// For a spider this provides a short generic feeding/attack motion.
|
||||
me->HandleEmoteCommand(54);
|
||||
}
|
||||
|
||||
void FinishEating()
|
||||
{
|
||||
Player* player = GetOwnerPlayer();
|
||||
Creature* corpse = GetFeedCorpse();
|
||||
|
||||
if (!player ||
|
||||
player->GetQuestStatus(QUEST_COASTAL_DELICACIES) != QUEST_STATUS_INCOMPLETE ||
|
||||
!IsValidFeedCorpse(corpse))
|
||||
{
|
||||
ResetToFollowing();
|
||||
return;
|
||||
}
|
||||
|
||||
player->KilledMonsterCredit(NPC_MURLOC_EATEN_PROXY);
|
||||
corpse->DespawnOrUnsummon();
|
||||
|
||||
ResetToFollowing();
|
||||
}
|
||||
|
||||
void ResetToFollowing()
|
||||
{
|
||||
_corpseGuid.Clear();
|
||||
_state = COASTAL_STATE_FOLLOWING;
|
||||
_eatTimer = 0;
|
||||
FollowOwner();
|
||||
}
|
||||
|
||||
ObjectGuid _ownerGuid;
|
||||
ObjectGuid _corpseGuid;
|
||||
uint8 _state;
|
||||
uint32 _eatTimer;
|
||||
uint32 _ownerCheckTimer;
|
||||
};
|
||||
|
||||
class player_hillsbrad_coastal_delicacies : public PlayerScript
|
||||
{
|
||||
public:
|
||||
player_hillsbrad_coastal_delicacies()
|
||||
: PlayerScript("player_hillsbrad_coastal_delicacies") { }
|
||||
|
||||
void OnQuestStatusChange(Player* player, uint32 questId) override
|
||||
{
|
||||
if (!player || questId != QUEST_COASTAL_DELICACIES)
|
||||
return;
|
||||
|
||||
EnsureHungryMineCreeper(player);
|
||||
}
|
||||
|
||||
void OnLogin(Player* player, bool /*firstLogin*/) override
|
||||
{
|
||||
if (player && player->GetQuestStatus(QUEST_COASTAL_DELICACIES) == QUEST_STATUS_INCOMPLETE)
|
||||
EnsureHungryMineCreeper(player);
|
||||
}
|
||||
|
||||
void OnUpdateZone(Player* player, uint32 /*newZone*/, uint32 /*newArea*/) override
|
||||
{
|
||||
if (player && player->GetQuestStatus(QUEST_COASTAL_DELICACIES) == QUEST_STATUS_INCOMPLETE)
|
||||
EnsureHungryMineCreeper(player);
|
||||
else
|
||||
DespawnOwnedHungryMineCreeper(player);
|
||||
}
|
||||
|
||||
void OnMapChanged(Player* player) override
|
||||
{
|
||||
if (player && player->GetQuestStatus(QUEST_COASTAL_DELICACIES) == QUEST_STATUS_INCOMPLETE)
|
||||
EnsureHungryMineCreeper(player);
|
||||
else
|
||||
DespawnOwnedHungryMineCreeper(player);
|
||||
}
|
||||
|
||||
void OnCreatureKill(Player* killer, Creature* killed) override
|
||||
{
|
||||
if (!killer || !killed)
|
||||
return;
|
||||
|
||||
if (killer->GetQuestStatus(QUEST_COASTAL_DELICACIES) != QUEST_STATUS_INCOMPLETE ||
|
||||
!IsCoastalDelicaciesArea(killer->GetAreaId()))
|
||||
return;
|
||||
|
||||
if (killed->GetEntry() != NPC_TORN_FIN_MUCKDWELLER &&
|
||||
killed->GetEntry() != NPC_TORN_FIN_COASTRUNNER)
|
||||
return;
|
||||
|
||||
Creature* creeper = FindOwnedHungryMineCreeper(killer);
|
||||
if (!creeper || !creeper->IsAIEnabled())
|
||||
return;
|
||||
|
||||
creeper->AI()->SetGUID(killed->GetGUID(), POINT_COASTAL_FEED_CORPSE);
|
||||
}
|
||||
};
|
||||
|
||||
// WOW-PRIVATE-SERVER PATCH: Deep Mine Rescue (28156)
|
||||
//
|
||||
// Restores Dumass' missing rescue behavior. Quest acceptance is observed
|
||||
// through PlayerScript because this TrinityCore branch does not expose a
|
||||
// quest-accept hook on CreatureAI/CreatureScript.
|
||||
enum DeepMineRescue
|
||||
{
|
||||
QUEST_DEEP_MINE_RESCUE = 28156,
|
||||
|
||||
NPC_DUMASS_RESCUE = 47681,
|
||||
NPC_CAPTAIN_KEYTON = 47554,
|
||||
|
||||
SPELL_PARALYTIC_POISON = 87969
|
||||
};
|
||||
|
||||
struct npc_hillsbrad_dumass_rescue : public ScriptedAI
|
||||
{
|
||||
npc_hillsbrad_dumass_rescue(Creature* creature)
|
||||
: ScriptedAI(creature), _checkTimer(1000), _active(false), _finished(false) { }
|
||||
|
||||
void StartRescue(Player* player)
|
||||
{
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
_playerGuid = player->GetGUID();
|
||||
_active = true;
|
||||
_finished = false;
|
||||
_checkTimer = 250;
|
||||
|
||||
me->RemoveAurasDueToSpell(SPELL_PARALYTIC_POISON);
|
||||
me->SetReactState(REACT_DEFENSIVE);
|
||||
me->SetWalk(false);
|
||||
me->GetMotionMaster()->MoveFollow(player, 2.0f, float(M_PI));
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (_active && !_finished)
|
||||
{
|
||||
if (_checkTimer > diff)
|
||||
_checkTimer -= diff;
|
||||
else
|
||||
{
|
||||
_checkTimer = 1000;
|
||||
|
||||
Player* player = ObjectAccessor::GetPlayer(*me, _playerGuid);
|
||||
if (!player)
|
||||
{
|
||||
ResetRescue();
|
||||
return;
|
||||
}
|
||||
|
||||
QuestStatus const status = player->GetQuestStatus(QUEST_DEEP_MINE_RESCUE);
|
||||
if (status == QUEST_STATUS_NONE ||
|
||||
status == QUEST_STATUS_REWARDED ||
|
||||
status == QUEST_STATUS_FAILED)
|
||||
{
|
||||
ResetRescue();
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == QUEST_STATUS_INCOMPLETE)
|
||||
{
|
||||
if (Creature* keyton = me->FindNearestCreature(NPC_CAPTAIN_KEYTON, 12.0f, true))
|
||||
{
|
||||
_finished = true;
|
||||
_active = false;
|
||||
|
||||
me->CombatStop(true);
|
||||
me->AttackStop();
|
||||
me->StopMoving();
|
||||
me->SetFacingToObject(keyton);
|
||||
|
||||
player->GroupEventHappens(QUEST_DEEP_MINE_RESCUE, me);
|
||||
|
||||
// Let the original world spawn return through normal respawn handling.
|
||||
me->DespawnOrUnsummon(5s);
|
||||
return;
|
||||
}
|
||||
|
||||
// Combat can interrupt following. Resume once Dumass is free again.
|
||||
if (!me->IsInCombat() && me->GetDistance(player) > 4.0f)
|
||||
me->GetMotionMaster()->MoveFollow(player, 2.0f, float(M_PI));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (UpdateVictim())
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
void ResetRescue()
|
||||
{
|
||||
_active = false;
|
||||
_finished = false;
|
||||
_playerGuid.Clear();
|
||||
|
||||
me->CombatStop(true);
|
||||
me->AttackStop();
|
||||
me->GetMotionMaster()->MoveTargetedHome();
|
||||
|
||||
if (!me->HasAura(SPELL_PARALYTIC_POISON))
|
||||
me->CastSpell(me, SPELL_PARALYTIC_POISON, true);
|
||||
}
|
||||
|
||||
ObjectGuid _playerGuid;
|
||||
uint32 _checkTimer;
|
||||
bool _active;
|
||||
bool _finished;
|
||||
};
|
||||
|
||||
class player_hillsbrad_deep_mine_rescue : public PlayerScript
|
||||
{
|
||||
public:
|
||||
player_hillsbrad_deep_mine_rescue()
|
||||
: PlayerScript("player_hillsbrad_deep_mine_rescue") { }
|
||||
|
||||
void OnQuestStatusChange(Player* player, uint32 questId) override
|
||||
{
|
||||
if (!player || questId != QUEST_DEEP_MINE_RESCUE)
|
||||
return;
|
||||
|
||||
if (player->GetQuestStatus(QUEST_DEEP_MINE_RESCUE) != QUEST_STATUS_INCOMPLETE)
|
||||
return;
|
||||
|
||||
if (Creature* dumass = player->FindNearestCreature(NPC_DUMASS_RESCUE, 50.0f, true))
|
||||
{
|
||||
if (dumass->IsAIEnabled())
|
||||
{
|
||||
if (npc_hillsbrad_dumass_rescue* ai =
|
||||
dynamic_cast<npc_hillsbrad_dumass_rescue*>(dumass->AI()))
|
||||
{
|
||||
ai->StartRescue(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
enum GloriousHarvest
|
||||
{
|
||||
QUEST_GLORIOUS_HARVEST = 28114,
|
||||
@@ -1810,6 +2448,12 @@ void AddSC_hillsbrad_foothills()
|
||||
RegisterCreatureAI(npc_hillsbrad_welcome_steed);
|
||||
RegisterCreatureAI(npc_hillsbrad_welcome_actor);
|
||||
RegisterCreatureAI(npc_hillsbrad_creeper_egg);
|
||||
RegisterCreatureAI(npc_hillsbrad_captured_human);
|
||||
RegisterCreatureAI(npc_hillsbrad_dumass_rescue);
|
||||
RegisterCreatureAI(npc_hillsbrad_hungry_mine_creeper);
|
||||
new player_hillsbrad_deep_mine_rescue();
|
||||
new player_hillsbrad_coastal_delicacies();
|
||||
RegisterSpellScript(spell_hillsbrad_titanium_shackles);
|
||||
RegisterSpellScript(spell_brazie_summon_plant);
|
||||
RegisterSpellScript(spell_brazie_highlight);
|
||||
RegisterSpellScript(spell_brazie_create_random_seed_sack);
|
||||
|
||||
-1744
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user