Merge branch 'master' into Playerbot

# Conflicts:
#	apps/ci/ci-install-modules.sh
#	src/common/Collision/Management/MMapMgr.cpp
#	src/common/Debugging/Errors.h
#	src/server/game/AI/SmartScripts/SmartScript.cpp
#	src/server/game/Battlegrounds/Arena.cpp
#	src/server/game/Battlegrounds/ArenaScore.h
#	src/server/game/Battlegrounds/Battleground.cpp
#	src/server/game/Battlegrounds/BattlegroundMgr.cpp
#	src/server/game/Battlegrounds/BattlegroundMgr.h
#	src/server/game/Battlegrounds/BattlegroundQueue.cpp
#	src/server/game/Battlegrounds/BattlegroundQueue.h
#	src/server/game/Battlegrounds/Zones/BattlegroundAB.h
#	src/server/game/Battlegrounds/Zones/BattlegroundEY.h
#	src/server/game/Battlegrounds/Zones/BattlegroundIC.h
#	src/server/game/Conditions/ConditionMgr.cpp
#	src/server/game/DataStores/M2Stores.cpp
#	src/server/game/DungeonFinding/LFGMgr.cpp
#	src/server/game/Entities/Creature/Creature.cpp
#	src/server/game/Entities/Creature/CreatureData.h
#	src/server/game/Entities/GameObject/GameObject.cpp
#	src/server/game/Entities/GameObject/GameObject.h
#	src/server/game/Entities/Player/Player.cpp
#	src/server/game/Entities/Player/Player.h
#	src/server/game/Entities/Player/PlayerStorage.cpp
#	src/server/game/Entities/Unit/Unit.cpp
#	src/server/game/Entities/Unit/Unit.h
#	src/server/game/Globals/ObjectMgr.cpp
#	src/server/game/Groups/Group.cpp
#	src/server/game/Groups/Group.h
#	src/server/game/Guilds/Guild.cpp
#	src/server/game/Guilds/Guild.h
#	src/server/game/Handlers/BattleGroundHandler.cpp
#	src/server/game/Handlers/CharacterHandler.cpp
#	src/server/game/Scripting/ScriptDefines/BGScript.cpp
#	src/server/game/Scripting/ScriptDefines/DatabaseScript.cpp
#	src/server/game/Scripting/ScriptDefines/PlayerScript.cpp
#	src/server/game/Scripting/ScriptDefines/ServerScript.cpp
#	src/server/game/Scripting/ScriptMgr.cpp
#	src/server/game/Scripting/ScriptMgrMacros.h
#	src/server/game/Server/Packets/MiscPackets.cpp
#	src/server/game/Server/Packets/MiscPackets.h
#	src/server/game/Server/WorldSession.cpp
#	src/server/game/Spells/SpellEffects.cpp
#	src/server/game/World/IWorld.h
#	src/server/game/World/World.cpp
#	src/server/game/World/World.h
#	src/server/scripts/Commands/cs_npc.cpp
#	src/server/scripts/Commands/cs_server.cpp
#	src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp
#	src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp
#	src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp
#	src/server/scripts/EasternKingdoms/ShadowfangKeep/boss_apothecary_hummel.cpp
#	src/server/scripts/EasternKingdoms/ShadowfangKeep/instance_shadowfang_keep.cpp
#	src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.h
#	src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp
This commit is contained in:
郑佩茹
2022-03-21 13:57:37 -06:00
150 changed files with 9687 additions and 2113 deletions

View File

@@ -412,7 +412,7 @@ public:
return false;
}
Battleground* bg = sBattlegroundMgr->CreateNewBattleground(randomizedArenaBgTypeId, 80, 80, ArenaType(hcnt >= 2 ? hcnt : 2), false);
Battleground* bg = sBattlegroundMgr->CreateNewBattleground(randomizedArenaBgTypeId, GetBattlegroundBracketById(bgt->GetMapId(), bgt->GetBracketId()), ArenaType(hcnt >= 2 ? hcnt : 2), false);
if (!bg)
{
handler->PSendSysMessage("Couldn't create arena map!");

View File

@@ -224,7 +224,6 @@ public:
{
ObjectGuid::LowType guid = sObjectMgr->GenerateCreatureSpawnId();
CreatureData& data = sObjectMgr->NewOrExistCreatureData(guid);
data.spawnId = guid;
data.id1 = id;
data.phaseMask = chr->GetPhaseMaskForSpawn();
data.posX = chr->GetTransOffsetX();

View File

@@ -215,7 +215,7 @@ public:
static bool HandleReloadBattlegroundTemplate(ChatHandler* handler)
{
LOG_INFO("server.loading", "Re-Loading Battleground Templates...");
sBattlegroundMgr->CreateInitialBattlegrounds();
sBattlegroundMgr->LoadBattlegroundTemplates();
handler->SendGlobalGMSysMessage("DB table `battleground_template` reloaded.");
return true;
}

View File

@@ -224,6 +224,10 @@ public:
handler->PSendSysMessage("CharacterDatabase queue size: %zu", CharacterDatabase.QueueSize());
handler->PSendSysMessage("WorldDatabase queue size: %zu", WorldDatabase.QueueSize());
if (Acore::Module::GetEnableModulesList().empty())
handler->SendSysMessage("No modules enabled");
else
handler->SendSysMessage("> List enable modules:");
#ifdef MOD_PLAYERBOTS
handler->PSendSysMessage("PlayerbotsDatabase queue size: %zu", PlayerbotsDatabase.QueueSize());
#endif

View File

@@ -20,7 +20,7 @@
#include "CreatureAIImpl.h"
uint32 const EncounterCount = 8;
constexpr uint32 EncounterCount = 8;
#define BWLScriptName "instance_blackwing_lair"
#define DataHeader "BWL"
@@ -59,7 +59,22 @@ enum BWLCreatureIds
NPC_FLAMEGOR = 11981,
NPC_CHROMAGGUS = 14020,
NPC_VICTOR_NEFARIUS = 10162,
NPC_NEFARIAN = 11583
NPC_NEFARIAN = 11583,
// Nefarian fight
NPC_BLACK_SPAWNER = 14307,
NPC_RED_SPAWNER = 14309,
NPC_GREEN_SPAWNER = 14310,
NPC_BRONZE_SPAWNER = 14311,
NPC_BLUE_SPAWNER = 14312,
NPC_BRONZE_DRAKONID = 14263,
NPC_BLUE_DRAKONID = 14261,
NPC_RED_DRAKONID = 14264,
NPC_GREEN_DRAKONID = 14262,
NPC_BLACK_DRAKONID = 14265,
NPC_CHROMATIC_DRAKONID = 14302,
NPC_BONE_CONSTRUCT = 14605
};
enum BWLGameObjectIds
@@ -90,7 +105,12 @@ enum BWLMisc
DATA_EGG_EVENT = 2,
TALK_EGG_BROKEN_RAND = 3,
SAY_NEFARIAN_VAEL_INTRO = 14
SAY_NEFARIAN_VAEL_INTRO = 14,
// Nefarian fight
DATA_NEFARIAN_LEFT_TUNNEL = 15,
DATA_NEFARIAN_RIGHT_TUNNEL = 16,
ACTION_NEFARIUS_ADD_KILLED = 2
};
template <class AI, class T>

View File

@@ -30,7 +30,8 @@
enum Events
{
// Victor Nefarius
EVENT_SPAWN_ADD = 1,
EVENT_SPAWN_ADDS = 1,
EVENT_CHECK_PHASE_2,
EVENT_START_EVENT,
EVENT_SHADOW_BOLT,
EVENT_FEAR,
@@ -53,7 +54,8 @@ enum Events
EVENT_SUCCESS_3,
ACTION_RESET = 0,
ACTION_KILLED = 1
ACTION_KILLED = 1,
ACTION_ADD_KILLED = 2
};
enum Says
@@ -106,13 +108,6 @@ enum GameObjects
enum Creatures
{
NPC_BRONZE_DRAKANOID = 14263,
NPC_BLUE_DRAKANOID = 14261,
NPC_RED_DRAKANOID = 14264,
NPC_GREEN_DRAKANOID = 14262,
NPC_BLACK_DRAKANOID = 14265,
NPC_CHROMATIC_DRAKANOID = 14302,
NPC_BONE_CONSTRUCT = 14605,
NPC_TOTEM_C_FIRE_NOVA = 14662,
NPC_TOTEM_C_STONESKIN = 14663,
NPC_TOTEM_C_HEALING = 14664,
@@ -137,6 +132,14 @@ enum Spells
SPELL_NEFARIANS_BARRIER = 22663,
// Drakonid Spawner
SPELL_SPAWN_BLACK_DRAKONID = 22654,
SPELL_SPAWN_RED_DRAKONID = 22655,
SPELL_SPAWN_GREEN_DRAKONID = 22656,
SPELL_SPAWN_BRONZE_DRAKONID = 22657,
SPELL_SPAWN_BLUE_DRAKONID = 22658,
SPELL_SPAWN_CHROMATIC_DRAKONID = 22680,
// Nefarian
SPELL_SHADOWFLAME_INITIAL = 22992,
SPELL_SHADOWFLAME = 22539,
@@ -168,15 +171,27 @@ enum Spells
SPELL_CORRUPTED_WINDFURY_TOTEM = 23423
};
Position const DrakeSpawnLoc[2] = // drakonid
enum Misc
{
{-7591.151855f, -1204.051880f, 476.800476f, 3.0f},
{-7514.598633f, -1150.448853f, 476.796570f, 3.0f}
MAX_DRAKONID_KILLED = 42
};
Position const spawnerPositions[2] = // drakonid
{
{-7599.32f, -1191.72f, 475.545f, 3.05f},
{-7526.27f, -1135.04f, 473.445f, 5.76f}
};
Position const NefarianSpawn = { -7348.849f, -1495.134f, 552.5152f, 1.798f };
uint32 const Entry[5] = {NPC_BRONZE_DRAKANOID, NPC_BLUE_DRAKANOID, NPC_RED_DRAKANOID, NPC_GREEN_DRAKANOID, NPC_BLACK_DRAKANOID};
std::unordered_map<uint32, uint32> spawnerSpells =
{
{ NPC_BLACK_SPAWNER, SPELL_SPAWN_BLACK_DRAKONID },
{ NPC_BLUE_SPAWNER, SPELL_SPAWN_BLUE_DRAKONID },
{ NPC_BRONZE_SPAWNER, SPELL_SPAWN_BRONZE_DRAKONID },
{ NPC_GREEN_SPAWNER, SPELL_SPAWN_GREEN_DRAKONID },
{ NPC_RED_SPAWNER, SPELL_SPAWN_RED_DRAKONID }
};
class boss_victor_nefarius : public CreatureScript
{
@@ -188,6 +203,25 @@ public:
boss_victor_nefariusAI(Creature* creature) : BossAI(creature, DATA_NEFARIAN)
{
Initialize();
_nefarianLeftTunnel = instance->GetData(DATA_NEFARIAN_LEFT_TUNNEL);
_nefarianRightTunnel = instance->GetData(DATA_NEFARIAN_RIGHT_TUNNEL);
if (!_nefarianLeftTunnel || !_nefarianRightTunnel)
{
// Victor Nefarius weekly mechanic drakonid spawn
// Pick 2 drakonids and keep them for the whole save duration (the drakonids can't be repeated).
std::vector<uint32> nefarianDrakonidSpawners = { NPC_BLACK_SPAWNER, NPC_BLUE_SPAWNER, NPC_BRONZE_SPAWNER, NPC_GREEN_SPAWNER, NPC_RED_SPAWNER };
_nefarianRightTunnel = Acore::Containers::SelectRandomContainerElement(nefarianDrakonidSpawners);
// delete the previous picked one so we don't get any repeated.
nefarianDrakonidSpawners.erase(std::remove(nefarianDrakonidSpawners.begin(), nefarianDrakonidSpawners.end(), _nefarianRightTunnel), nefarianDrakonidSpawners.end());
// Pick another one
_nefarianLeftTunnel = Acore::Containers::SelectRandomContainerElement(nefarianDrakonidSpawners);
// save it to instance
instance->SetData(DATA_NEFARIAN_LEFT_TUNNEL, _nefarianLeftTunnel);
instance->SetData(DATA_NEFARIAN_RIGHT_TUNNEL, _nefarianRightTunnel);
}
}
void Initialize()
@@ -237,6 +271,11 @@ public:
summons.DespawnAll();
}
if (action == ACTION_ADD_KILLED)
{
KilledAdds++;
}
if (action == ACTION_KILLED)
{
Unit::Kill(me, me);
@@ -263,19 +302,8 @@ public:
events.ScheduleEvent(EVENT_FEAR, urand(10000, 20000));
events.ScheduleEvent(EVENT_SILENCE, urand(20000, 25000));
events.ScheduleEvent(EVENT_MIND_CONTROL, urand(30000, 35000));
events.ScheduleEvent(EVENT_SPAWN_ADD, 10000);
}
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
{
if (summon->GetEntry() != NPC_NEFARIAN)
{
summon->UpdateEntry(NPC_BONE_CONSTRUCT);
summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
summon->SetReactState(REACT_PASSIVE);
summon->SetStandState(UNIT_STAND_STATE_DEAD);
++KilledAdds;
}
events.ScheduleEvent(EVENT_SPAWN_ADDS, 10000);
events.ScheduleEvent(EVENT_CHECK_PHASE_2, 10000);
}
void JustSummoned(Creature* summon) override { summons.Summon(summon); }
@@ -348,7 +376,7 @@ public:
}
// Only do this if we haven't spawned nefarian yet
if (UpdateVictim() && KilledAdds <= 42)
if (UpdateVictim() && KilledAdds <= MAX_DRAKONID_KILLED)
{
events.Update(diff);
@@ -390,39 +418,33 @@ public:
DoCastSelf(SPELL_SHADOWBLINK);
events.ScheduleEvent(EVENT_SHADOWBLINK, urand(30000, 40000));
break;
case EVENT_SPAWN_ADD:
for (uint8 i=0; i<2; ++i)
case EVENT_SPAWN_ADDS:
// Spawn the spawners.
me->SummonCreature(_nefarianLeftTunnel, spawnerPositions[0]);
me->SummonCreature(_nefarianRightTunnel, spawnerPositions[1]);
break;
case EVENT_CHECK_PHASE_2:
if (KilledAdds >= MAX_DRAKONID_KILLED)
{
uint32 CreatureID;
if (urand(0, 2) == 0)
CreatureID = NPC_CHROMATIC_DRAKANOID;
else
CreatureID = Entry[urand(0, 4)];
if (Creature* dragon = me->SummonCreature(CreatureID, DrakeSpawnLoc[i]))
if (Creature* nefarian = me->SummonCreature(NPC_NEFARIAN, NefarianSpawn))
{
dragon->SetFaction(FACTION_DRAGONFLIGHT_BLACK);
dragon->AI()->AttackStart(me->GetVictim());
}
if (KilledAdds >= 42)
{
if (Creature* nefarian = me->SummonCreature(NPC_NEFARIAN, NefarianSpawn))
{
nefarian->setActive(true);
nefarian->SetCanFly(true);
nefarian->SetDisableGravity(true);
nefarian->GetMotionMaster()->MovePath(NEFARIAN_PATH, false);
}
events.CancelEvent(EVENT_MIND_CONTROL);
events.CancelEvent(EVENT_FEAR);
events.CancelEvent(EVENT_SHADOW_BOLT);
events.CancelEvent(EVENT_SILENCE);
DoCastSelf(SPELL_ROOT_SELF, true);
me->SetVisible(false);
return;
nefarian->setActive(true);
nefarian->SetCanFly(true);
nefarian->SetDisableGravity(true);
nefarian->GetMotionMaster()->MovePath(NEFARIAN_PATH, false);
}
events.CancelEvent(EVENT_MIND_CONTROL);
events.CancelEvent(EVENT_FEAR);
events.CancelEvent(EVENT_SHADOW_BOLT);
events.CancelEvent(EVENT_SILENCE);
DoCastSelf(SPELL_ROOT_SELF, true);
me->SetVisible(false);
// Despawn the spawners.
summons.DespawnEntry(_nefarianLeftTunnel);
summons.DespawnEntry(_nefarianRightTunnel);
return;
}
events.ScheduleEvent(EVENT_SPAWN_ADD, 4000);
events.ScheduleEvent(EVENT_CHECK_PHASE_2, 1000);
break;
}
@@ -453,6 +475,8 @@ public:
private:
uint32 KilledAdds;
uint32 _nefarianRightTunnel;
uint32 _nefarianLeftTunnel;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -755,12 +779,12 @@ struct npc_corrupted_totem : public ScriptedAI
std::vector<uint32> mobsEntries;
mobsEntries.push_back(NPC_NEFARIAN);
mobsEntries.push_back(NPC_BONE_CONSTRUCT);
mobsEntries.push_back(NPC_BRONZE_DRAKANOID);
mobsEntries.push_back(NPC_BLUE_DRAKANOID);
mobsEntries.push_back(NPC_RED_DRAKANOID);
mobsEntries.push_back(NPC_GREEN_DRAKANOID);
mobsEntries.push_back(NPC_BLACK_DRAKANOID);
mobsEntries.push_back(NPC_CHROMATIC_DRAKANOID);
mobsEntries.push_back(NPC_BRONZE_DRAKONID);
mobsEntries.push_back(NPC_BLUE_DRAKONID);
mobsEntries.push_back(NPC_RED_DRAKONID);
mobsEntries.push_back(NPC_GREEN_DRAKONID);
mobsEntries.push_back(NPC_BLACK_DRAKONID);
mobsEntries.push_back(NPC_CHROMATIC_DRAKONID);
for (auto& entry : mobsEntries)
{
@@ -1155,6 +1179,33 @@ class spell_shadowblink : public SpellScript
}
};
// 22659
class spell_spawn_drakonid : public SpellScript
{
PrepareSpellScript(spell_spawn_drakonid);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_SPAWN_BLACK_DRAKONID, SPELL_SPAWN_BLUE_DRAKONID, SPELL_SPAWN_BRONZE_DRAKONID, SPELL_SPAWN_GREEN_DRAKONID, SPELL_SPAWN_RED_DRAKONID });
}
void HandleDummy(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
if (!caster)
{
return;
}
caster->CastSpell(caster, spawnerSpells[caster->GetEntry()], true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_spawn_drakonid::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
void AddSC_boss_nefarian()
{
new boss_victor_nefarius();
@@ -1167,4 +1218,5 @@ void AddSC_boss_nefarian()
RegisterSpellScript(aura_class_call_berserk);
RegisterSpellScript(spell_corrupted_totems);
RegisterSpellScript(spell_shadowblink);
RegisterSpellScript(spell_spawn_drakonid);
}

View File

@@ -75,6 +75,8 @@ public:
// Razorgore
EggCount = 0;
EggEvent = 0;
NefarianLeftTunnel = 0;
NefarianRightTunnel = 0;
}
void OnCreatureCreate(Creature* creature) override
@@ -102,6 +104,24 @@ public:
case NPC_VICTOR_NEFARIUS:
victorNefariusGUID = creature->GetGUID();
break;
case NPC_BLACK_DRAKONID:
case NPC_BLUE_DRAKONID:
case NPC_BRONZE_DRAKONID:
case NPC_CHROMATIC_DRAKONID:
case NPC_GREEN_DRAKONID:
case NPC_RED_DRAKONID:
if (Creature* nefarius = instance->GetCreature(victorNefariusGUID))
{
if (CreatureAI* nefariusAI = nefarius->AI())
{
nefariusAI->JustSummoned(creature);
}
}
if (creature->AI())
{
creature->AI()->DoZoneInCombat();
}
break;
default:
break;
}
@@ -166,6 +186,21 @@ public:
}
}
uint32 GetData(uint32 data) const override
{
switch (data)
{
case DATA_NEFARIAN_LEFT_TUNNEL:
return NefarianLeftTunnel;
case DATA_NEFARIAN_RIGHT_TUNNEL:
return NefarianRightTunnel;
default:
break;
}
return 0;
}
bool CheckRequiredBosses(uint32 bossId, Player const* /* player */) const override
{
switch (bossId)
@@ -268,6 +303,16 @@ public:
break;
}
}
if (type == DATA_NEFARIAN_LEFT_TUNNEL)
{
NefarianLeftTunnel = data;
}
if (type == DATA_NEFARIAN_RIGHT_TUNNEL)
{
NefarianRightTunnel = data;
}
}
ObjectGuid GetGuidData(uint32 type) const override
@@ -276,6 +321,8 @@ public:
{
case DATA_RAZORGORE_THE_UNTAMED:
return razorgoreGUID;
case DATA_LORD_VICTOR_NEFARIUS:
return victorNefariusGUID;
case DATA_CHROMAGGUS:
return chromaggusGUID;
case DATA_GO_CHROMAGGUS_DOOR:
@@ -292,6 +339,32 @@ public:
//! HACK, needed because of buggy CreatureAI after charm
if (unit->GetEntry() == NPC_RAZORGORE && GetBossState(DATA_RAZORGORE_THE_UNTAMED) != DONE)
SetBossState(DATA_RAZORGORE_THE_UNTAMED, DONE);
switch (unit->GetEntry())
{
case NPC_BLACK_DRAKONID:
case NPC_BLUE_DRAKONID:
case NPC_BRONZE_DRAKONID:
case NPC_CHROMATIC_DRAKONID:
case NPC_GREEN_DRAKONID:
case NPC_RED_DRAKONID:
if (Creature* summon = unit->ToCreature())
{
summon->UpdateEntry(NPC_BONE_CONSTRUCT);
summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
summon->SetReactState(REACT_PASSIVE);
summon->SetStandState(UNIT_STAND_STATE_DEAD);
if (Creature* nefarius = instance->GetCreature(victorNefariusGUID))
{
if (nefarius->AI())
{
nefarius->AI()->DoAction(ACTION_NEFARIUS_ADD_KILLED);
}
}
}
break;
}
}
void Update(uint32 diff) override
@@ -329,6 +402,54 @@ public:
}
}
std::string GetSaveData() override
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << "B W L " << GetBossSaveData() << NefarianLeftTunnel << ' ' << NefarianRightTunnel;
OUT_SAVE_INST_DATA_COMPLETE;
return saveStream.str();
}
void Load(char const* data) override
{
if (!data)
{
OUT_LOAD_INST_DATA_FAIL;
return;
}
OUT_LOAD_INST_DATA(data);
char dataHead1, dataHead2, dataHead3;
std::istringstream loadStream(data);
loadStream >> dataHead1 >> dataHead2 >> dataHead3;
if (dataHead1 == 'B' && dataHead2 == 'W' && dataHead3 == 'L')
{
for (uint32 i = 0; i < EncounterCount; ++i)
{
uint32 tmpState;
loadStream >> tmpState;
if (tmpState == IN_PROGRESS || tmpState == FAIL || tmpState > SPECIAL)
tmpState = NOT_STARTED;
SetBossState(i, EncounterState(tmpState));
}
loadStream >> NefarianLeftTunnel;
loadStream >> NefarianRightTunnel;
}
else
{
OUT_LOAD_INST_DATA_FAIL;
}
OUT_LOAD_INST_DATA_COMPLETE;
}
protected:
ObjectGuid razorgoreGUID;
ObjectGuid chromaggusGUID;
@@ -342,6 +463,10 @@ public:
uint32 EggEvent;
GuidList EggList;
// Nefarian
uint32 NefarianLeftTunnel;
uint32 NefarianRightTunnel;
// Misc
EventMap _events;
};

View File

@@ -78,7 +78,6 @@ enum Events
EVENT_HAND_OF_RAGNAROS,
EVENT_MIGHT_OF_RAGNAROS,
EVENT_LAVA_BURST,
EVENT_MAGMA_BLAST_MELEE_CHECK,
EVENT_MAGMA_BLAST,
EVENT_SUBMERGE,
EVENT_LAVA_BURST_TRIGGER,
@@ -122,6 +121,7 @@ public:
boss_ragnarosAI(Creature* creature) : BossAI(creature, DATA_RAGNAROS),
_isIntroDone(false),
_hasYelledMagmaBurst(false),
_processingMagmaBurst(false),
_hasSubmergedOnce(false),
_isKnockbackEmoteAllowed(true)
{
@@ -143,6 +143,7 @@ public:
}
_hasYelledMagmaBurst = false;
_processingMagmaBurst = false;
_hasSubmergedOnce = false;
_isKnockbackEmoteAllowed = true;
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
@@ -231,6 +232,28 @@ public:
}
}
void EnterEvadeMode() override
{
if (!me->getThreatMgr().getThreatList().empty())
{
if (!_processingMagmaBurst)
{
// Boss try to evade, but still got some targets on threat list - it means that none of these targets are in melee range - cast magma blast
_processingMagmaBurst = true;
events.ScheduleEvent(EVENT_MAGMA_BLAST, 4000, PHASE_EMERGED, PHASE_EMERGED);
}
}
else
{
BossAI::EnterEvadeMode();
}
}
bool CanAIAttack(Unit const* victim) const override
{
return me->IsWithinMeleeRange(victim);
}
void UpdateAI(uint32 diff) override
{
if (!extraEvents.Empty())
@@ -297,7 +320,10 @@ public:
if (!UpdateVictim())
{
return;
if (!_processingMagmaBurst)
{
return;
}
}
events.Update(diff);
@@ -340,38 +366,10 @@ public:
DoCastAOE(SPELL_LAVA_BURST);
break;
}
case EVENT_MAGMA_BLAST_MELEE_CHECK:
{
if (Unit* target = ObjectAccessor::GetUnit(*me, me->GetTarget()))
{
if (!target->IsAlive())
{
me->SetTarget(ObjectGuid::Empty);
}
}
if (!IsVictimWithinMeleeRange())
{
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 0, [&](Unit* u) { return u && u->IsPlayer() && me->IsWithinMeleeRange(u); }))
{
me->AttackerStateUpdate(target);
me->SetTarget(target->GetGUID());
events.RepeatEvent(500);
}
else
{
events.ScheduleEvent(EVENT_MAGMA_BLAST, 4000, PHASE_EMERGED, PHASE_EMERGED);
}
}
else
{
_hasYelledMagmaBurst = false;
events.RepeatEvent(500);
}
break;
}
case EVENT_MAGMA_BLAST:
{
_processingMagmaBurst = false;
if (!IsVictimWithinMeleeRange())
{
DoCastRandomTarget(SPELL_MAGMA_BLAST);
@@ -383,7 +381,6 @@ public:
}
}
events.RescheduleEvent(EVENT_MAGMA_BLAST_MELEE_CHECK, 500, PHASE_EMERGED, PHASE_EMERGED);
break;
}
case EVENT_MIGHT_OF_RAGNAROS:
@@ -444,6 +441,7 @@ public:
EventMap extraEvents;
bool _isIntroDone;
bool _hasYelledMagmaBurst;
bool _processingMagmaBurst;
bool _hasSubmergedOnce;
bool _isKnockbackEmoteAllowed; // Prevents possible text overlap
@@ -480,7 +478,6 @@ public:
events.RescheduleEvent(EVENT_WRATH_OF_RAGNAROS, 30000, PHASE_EMERGED, PHASE_EMERGED);
events.RescheduleEvent(EVENT_HAND_OF_RAGNAROS, 25000, PHASE_EMERGED, PHASE_EMERGED);
events.RescheduleEvent(EVENT_LAVA_BURST, 10000, PHASE_EMERGED, PHASE_EMERGED);
events.RescheduleEvent(EVENT_MAGMA_BLAST_MELEE_CHECK, 10000, PHASE_EMERGED, PHASE_EMERGED);
events.RescheduleEvent(EVENT_SUBMERGE, 180000, PHASE_EMERGED, PHASE_EMERGED);
events.RescheduleEvent(EVENT_MIGHT_OF_RAGNAROS, 11000, PHASE_EMERGED, PHASE_EMERGED);
}

View File

@@ -71,7 +71,8 @@ enum ApothecaryMisc
NPC_VIAL_BUNNY = 36530,
NPC_CROWN_APOTHECARY = 36885,
PHASE_ALL = 0,
PHASE_INTRO = 1
PHASE_INTRO = 1,
PHASE_COMBAT = 2
};
Position const BaxterMovePos = { -221.4115f, 2206.825f, 79.93151f, 0.0f };
@@ -108,22 +109,21 @@ public:
_deadCount = 0;
_isDead = false;
_phase = PHASE_ALL;
summons.DespawnAll();
me->SetFaction(FACTION_FRIENDLY);
me->SummonCreatureGroup(1);
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
}
void EnterEvadeMode() override
void JustSummoned(Creature* summon) override
{
summons.DespawnAll();
_EnterEvadeMode();
summons.Summon(summon);
}
void DoAction(int32 action) override
{
if (action == ACTION_START_EVENT && events.IsInPhase(PHASE_ALL))
if (action == ACTION_START_EVENT && _phase == PHASE_ALL)
{
events.SetPhase(PHASE_INTRO);
_phase = PHASE_INTRO;
_scheduler.Schedule(1ms, [this](TaskContext /*context*/)
{
@@ -140,6 +140,7 @@ public:
.Schedule(12s, [this](TaskContext context)
{
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
_phase = PHASE_COMBAT;
DoZoneInCombat();
context.Schedule(6s, [this](TaskContext /*context*/) // Call Baxter

View File

@@ -51,6 +51,15 @@ public:
case NPC_DND_CRAZED_APOTHECARY_GENERATOR:
_crazedApothecaryGeneratorGUIDs.push_back(creature->GetGUID());
break;
case NPC_APOTHECARY_HUMMEL:
_apothecaryHummel = creature->GetGUID();
break;
case NPC_CRAZED_APOTHECARY:
if (Creature* hummel = instance->GetCreature(_apothecaryHummel))
{
hummel->AI()->JustSummoned(creature);
}
break;
default:
break;
}
@@ -132,6 +141,7 @@ public:
private:
uint32 _encounters[MAX_ENCOUNTERS];
GuidVector _crazedApothecaryGeneratorGUIDs;
ObjectGuid _apothecaryHummel;
};
};

View File

@@ -36,7 +36,9 @@ enum DataTypes
enum SKCreatures
{
NPC_DND_CRAZED_APOTHECARY_GENERATOR = 36212
NPC_DND_CRAZED_APOTHECARY_GENERATOR = 36212,
NPC_APOTHECARY_HUMMEL = 36296,
NPC_CRAZED_APOTHECARY = 36568
};
enum GameObjects

View File

@@ -426,7 +426,7 @@ public:
bool OnGossipHello(Player* /*player*/, GameObject* go) override
{
if (go->GetInstanceScript())
if (go->GetInstanceScript() && !go->FindNearestCreature(NPC_ARLOKK, 25.0f))
{
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
go->SendCustomAnim(0);

View File

@@ -45,12 +45,6 @@ public:
LoadDoorData(doorData);
}
bool IsEncounterInProgress() const override
{
// not active in Zul'Gurub
return false;
}
void OnCreatureCreate(Creature* creature) override
{
switch (creature->GetEntry())

View File

@@ -1154,8 +1154,15 @@ public:
go->SetGoState(GO_STATE_ACTIVE);
if (!me->GetMap()->GetPlayers().IsEmpty())
{
if (Player* player = me->GetMap()->GetPlayers().getFirst()->GetSource())
player->SummonGameObject(DUNGEON_MODE(GO_MALGANIS_CHEST_N, GO_MALGANIS_CHEST_H), 2288.35f, 1498.73f, 128.414f, -0.994837f, 0, 0, 0, 0, 0);
{
if (GameObject* chest = player->SummonGameObject(DUNGEON_MODE(GO_MALGANIS_CHEST_N, GO_MALGANIS_CHEST_H), 2288.35f, 1498.73f, 128.414f, -0.994837f, 0, 0, 0, 0, 0))
{
chest->SetLootRecipient(me->GetMap());
}
}
}
}
ScheduleNextEvent(currentEvent, 10000);
break;

View File

@@ -280,7 +280,10 @@ public:
{
if (Player* player = me->GetMap()->GetPlayers().getFirst()->GetSource())
{
player->SummonGameObject(RAID_MODE(GO_HORSEMEN_CHEST_10, GO_HORSEMEN_CHEST_25), 2514.8f, -2944.9f, 245.55f, 5.51f, 0, 0, 0, 0, 0);
if (GameObject* chest = player->SummonGameObject(RAID_MODE(GO_HORSEMEN_CHEST_10, GO_HORSEMEN_CHEST_25), 2514.8f, -2944.9f, 245.55f, 5.51f, 0, 0, 0, 0, 0))
{
chest->SetLootRecipient(me);
}
}
}
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetGuidData(DATA_HORSEMEN_GATE)))

View File

@@ -1401,8 +1401,15 @@ public:
break;
case 1:
me->CastSpell(773.98f, 1285.97f, 266.254f, SPELL_ALEXSTRASZA_GIFT, true);
me->SummonGameObject(ALEXSTRASZA_GIFT, 773.98f, 1285.97f, 266.254f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0);
me->SummonGameObject(HEART_OF_MAGIC, 773.98f, 1275.97f, 266.254f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0);
if (GameObject* chest = me->SummonGameObject(ALEXSTRASZA_GIFT, 773.98f, 1285.97f, 266.254f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0))
{
chest->SetLootRecipient(me->GetMap());
}
if (GameObject* heart = me->SummonGameObject(HEART_OF_MAGIC, 773.98f, 1275.97f, 266.254f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0))
{
heart->SetLootRecipient(me->GetMap());
}
Talk(SAY_ALEXSTRASZA_ONE);
events.RescheduleEvent(2, 6000);

View File

@@ -160,7 +160,17 @@ public:
case DATA_EREGOS:
m_auiEncounter[DATA_EREGOS] = data;
if (data == DONE)
{
DoRespawnGameObject(EregosCacheGUID, 7 * DAY);
if (GameObject* cache = instance->GetGameObject(EregosCacheGUID))
{
if (Creature* eregos = instance->GetCreature(uiEregosGUID))
{
cache->SetLootRecipient(eregos);
}
}
}
break;
case DATA_CC_COUNT:
if( CentrifugeCount < 10 )

View File

@@ -739,14 +739,22 @@ public:
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_RENAME);
break;
case EVENT_OUTRO_2:
{
Player* lootRecipent = me->GetLootRecipient();
_EnterEvadeMode();
// LootRecipent is cleared in _EnterEvadeMode, restore it
me->SetLootRecipient(lootRecipent);
me->GetMotionMaster()->MovePoint(POINT_ALGALON_OUTRO, AlgalonOutroPos);
break;
}
case EVENT_OUTRO_3:
me->CastSpell((Unit*)nullptr, SPELL_KILL_CREDIT);
// Summon Chest
if (GameObject* go = me->SummonGameObject(RAID_MODE(GO_ALGALON_CHEST, GO_ALGALON_CHEST_HERO), 1632.1f, -306.561f, 417.321f, 4.69494f, 0, 0, 0, 1, 0))
{
go->SetUInt32Value(GAMEOBJECT_FLAGS, 0);
go->SetLootRecipient(me);
}
break;
case EVENT_OUTRO_4:
me->CastSpell((Unit*)nullptr, SPELL_SUPERMASSIVE_FAIL);

View File

@@ -370,7 +370,10 @@ public:
me->DespawnOrUnsummon(5000);
if (GameObject* go = me->SummonGameObject(chestId, 2345.61f, -71.20f, 425.104f, 3.0f, 0, 0, 0, 0, 0))
{
go->SetUInt32Value(GAMEOBJECT_FLAGS, 0);
go->SetLootRecipient(me->GetMap());
}
// Defeat credit
if (m_pInstance)

View File

@@ -310,6 +310,7 @@ public:
me->RemoveGameObject(go, false);
go->SetSpellId(1); // hack to make it despawn
go->SetUInt32Value(GAMEOBJECT_FLAGS, 0);
go->SetLootRecipient(me);
}
if (Creature* arm = ObjectAccessor::GetCreature(*me, _left))
arm->DespawnOrUnsummon(3000); // visual

View File

@@ -818,9 +818,14 @@ public:
me->Yell(TEXT_VOLTRON_DEATH, LANG_UNIVERSAL);
me->PlayDirectSound(SOUND_VOLTRON_DEATH);
// spawn chest
if( uint32 chestId = (hardmode ? RAID_MODE(GO_MIMIRON_CHEST_HARD, GO_MIMIRON_CHEST_HERO_HARD) : RAID_MODE(GO_MIMIRON_CHEST, GO_MIMIRON_CHEST_HERO)) )
if( GameObject* go = me->SummonGameObject(chestId, 2744.65f, 2569.46f, 364.397f, 0, 0, 0, 0, 0, 0) )
if (uint32 chestId = (hardmode ? RAID_MODE(GO_MIMIRON_CHEST_HARD, GO_MIMIRON_CHEST_HERO_HARD) : RAID_MODE(GO_MIMIRON_CHEST, GO_MIMIRON_CHEST_HERO)))
{
if (GameObject* go = me->SummonGameObject(chestId, 2744.65f, 2569.46f, 364.397f, 0, 0, 0, 0, 0, 0))
{
go->SetUInt32Value(GAMEOBJECT_FLAGS, 0);
go->SetLootRecipient(me->GetMap());
}
}
events.ScheduleEvent(EVENT_DISAPPEAR, 15000);
break;
case EVENT_DISAPPEAR:

View File

@@ -592,7 +592,10 @@ public:
chestId += 1; // hard mode offset
if ((go = me->SummonGameObject(chestId, 2134.73f, -286.32f, 419.51f, 0.0f, 0, 0, 0, 0, 0)))
{
go->SetUInt32Value(GAMEOBJECT_FLAGS, 0);
go->SetLootRecipient(me->GetMap());
}
// Defeat credit
if (m_pInstance)

View File

@@ -634,10 +634,18 @@ public:
{
case TYPE_HODIR:
if (hmHodir)
{
if (GameObject* go = instance->GetGameObject(m_hodirHardmodeChest))
{
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
go->SetLootRecipient(instance);
}
}
if (GameObject* go = instance->GetGameObject(m_hodirNormalChest))
{
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
go->SetLootRecipient(instance);
}
break;
}
}

View File

@@ -1289,7 +1289,8 @@ class spell_gen_adaptive_warding : public AuraScript
45826 - East Frostwolf Warmaster
45828 - Dun Baldar North Marshal
45829 - Dun Baldar South Marshal
45830 - Stonehearth Marshal */
45830 - Stonehearth Marshal
45831 - Icewing Marshal */
class spell_gen_av_drekthar_presence : public AuraScript
{
PrepareAuraScript(spell_gen_av_drekthar_presence);

View File

@@ -664,6 +664,14 @@ class spell_sha_earthliving_weapon : public AuraScript
return false;
}
if (SpellInfo const* spellInfo = eventInfo.GetSpellInfo())
{
if (spellInfo->Id == SPELL_SHAMAN_EARTH_SHIELD_HEAL)
{
return false;
}
}
if (AuraEffect const* aurEff = caster->GetAuraEffectOfRankedSpell(SPELL_SHAMAN_BLESSING_OF_THE_ETERNALS_R1, EFFECT_1, caster->GetGUID()))
{
if (eventInfo.GetProcTarget()->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT))

View File

@@ -660,8 +660,21 @@ class spell_warl_seed_of_corruption : public SpellScript
void FilterTargets(std::list<WorldObject*>& targets)
{
if (GetExplTargetUnit())
targets.remove(GetExplTargetUnit());
targets.remove_if([&](WorldObject const* target)
{
if (Unit const* unitTarget = target->ToUnit())
{
if (WorldLocation const* dest = GetExplTargetDest())
{
if (!unitTarget->IsWithinLOS(dest->GetPositionX(), dest->GetPositionY(), dest->GetPositionZ()))
{
return true;
}
}
}
return false;
});
}
void Register() override

View File

@@ -488,12 +488,12 @@ class spell_warr_bloodthirst_heal : public SpellScript
void HandleHeal(SpellEffIndex /*effIndex*/)
{
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_WARRIOR_BLOODTHIRST_DAMAGE))
SetHitHeal(GetCaster()->CountPctFromMaxHealth(spellInfo->Effects[EFFECT_1].CalcValue(GetCaster())));
SetEffectValue(GetCaster()->CountPctFromMaxHealth(spellInfo->Effects[EFFECT_1].CalcValue(GetCaster())));
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_warr_bloodthirst_heal::HandleHeal, EFFECT_0, SPELL_EFFECT_HEAL);
OnEffectLaunchTarget += SpellEffectFn(spell_warr_bloodthirst_heal::HandleHeal, EFFECT_0, SPELL_EFFECT_HEAL);
}
};

View File

@@ -18,7 +18,7 @@
/* ScriptData
SDName: Npc_Professions
SD%Complete: 80
SDComment: Provides learn/unlearn/relearn-options for professions. Not supported: Unlearn engineering, re-learn engineering, re-learn leatherworking.
SDComment: Provides learn/unlearn/relearn-options for professions. Not supported: Unlearn engineering, re-learn engineering.
SDCategory: NPCs
EndScriptData */
@@ -86,10 +86,6 @@ there is no difference here (except that default text is chosen with `gameobject
#define BOX_UNLEARN_WEAPON_SPEC "Do you really want to unlearn your weaponsmith specialty and lose all associated recipes? \n Cost: "
#define GOSSIP_LEARN_DRAGON "I wish to learn Dragonscale Leatherworking"
#define GOSSIP_LEARN_ELEMENTAL "I wish to learn Elemental Leatherworking"
#define GOSSIP_LEARN_TRIBAL "I wish to learn Tribal Leatherworking"
#define GOSSIP_LEARN_SPELLFIRE "Please teach me how to become a Spellcloth tailor"
#define GOSSIP_UNLEARN_SPELLFIRE "I wish to unlearn Spellfire Tailoring"
#define GOSSIP_LEARN_MOONCLOTH "Please teach me how to become a Mooncloth tailor"
@@ -230,6 +226,37 @@ enum SpecializationQuests
Q_MASTER_POTION = 10897,
};
// All referred to gossips (menu, menu_opt, actions)
enum Gossips
{
// Leatherworking
GOSSIP_MENU_PETER_GALEN = 3067,
GOSSIP_MENU_THORKAF_DRAGONEYE = 3068,
GOSSIP_MENU_BRUMN_WINTERHOOF = 3069,
GOSSIP_MENU_SARAH_TANNER = 3070,
GOSSIP_MENU_CARYSSIA_MOONHUNTER = 3072,
GOSSIP_MENU_SEJIB = 3073,
GOSSIP_MENU_UNLEARN_CONFIRM_DRAGONSCALE = 3075,
GOSSIP_MENU_UNLEARN_CONFIRM_ELEMENTAL = 3076,
GOSSIP_MENU_UNLEARN_CONFIRM_TRIBAL = 3077,
GOSSIP_MENU_OPTION_TRAIN = 0,
GOSSIP_MENU_OPTION_CONFIRM_UNLEARN_DRAGONSCALE = 1,
GOSSIP_MENU_OPTION_CONFIRM_UNLEARN_ELEMENTAL = 1,
GOSSIP_MENU_OPTION_CONFIRM_UNLEARN_TRIBAL = 1,
GOSSIP_TEXT_UNLEARN_CONFIRM_DRAGONSCALE = 10304,
GOSSIP_TEXT_UNLEARN_CONFIRM_ELEMENTAL = 10302,
GOSSIP_TEXT_UNLEARN_CONFIRM_TRIBAL = 10303,
GOSSIP_MENU_GO_SOOTHSAYING_FOR_DUMMIES = 7058,
GOSSIP_MENU_OPTION_GO_LEARN_DRAGONSCALE = 4,
GOSSIP_MENU_OPTION_GO_LEARN_ELEMENTAL = 5,
GOSSIP_MENU_OPTION_GO_LEARN_TRIBAL = 6,
};
/*###
# formulas to calculate unlearning cost
###*/
@@ -347,7 +374,11 @@ void ProfessionUnlearnSpells(Player* player, uint32 type)
player->removeSpell(36259, SPEC_MASK_ALL, false); // Lionheart Executioner
break;
case S_UNLEARN_DRAGON: // S_UNLEARN_DRAGON
player->removeSpell(10619, SPEC_MASK_ALL, false); // Dragonscale Guantlets
player->removeSpell(10650, SPEC_MASK_ALL, false); // Dragonscale Breastplate
player->removeSpell(36076, SPEC_MASK_ALL, false); // Dragonstrike Leggings
player->removeSpell(24655, SPEC_MASK_ALL, false); // Green Dragonscale Gauntlets
player->removeSpell(24654, SPEC_MASK_ALL, false); // Blue Dragonscale Leggings
player->removeSpell(36079, SPEC_MASK_ALL, false); // Golden Dragonstrike Breastplate
player->removeSpell(35576, SPEC_MASK_ALL, false); // Ebon Netherscale Belt
player->removeSpell(35577, SPEC_MASK_ALL, false); // Ebon Netherscale Bracers
@@ -362,6 +393,8 @@ void ProfessionUnlearnSpells(Player* player, uint32 type)
player->removeSpell(35590, SPEC_MASK_ALL, false); // Primalstrike Belt
player->removeSpell(35591, SPEC_MASK_ALL, false); // Primalstrike Bracers
player->removeSpell(35589, SPEC_MASK_ALL, false); // Primalstrike Vest
player->removeSpell(10630, SPEC_MASK_ALL, false); // Gauntlets of the Sea
player->removeSpell(10632, SPEC_MASK_ALL, false); // Helm of Fire
break;
case S_UNLEARN_TRIBAL: // S_UNLEARN_TRIBAL
player->removeSpell(35585, SPEC_MASK_ALL, false); // Windhawk Hauberk
@@ -369,6 +402,8 @@ void ProfessionUnlearnSpells(Player* player, uint32 type)
player->removeSpell(35588, SPEC_MASK_ALL, false); // Windhawk Bracers
player->removeSpell(36075, SPEC_MASK_ALL, false); // Wildfeather Leggings
player->removeSpell(36078, SPEC_MASK_ALL, false); // Living Crystal Breastplate
player->removeSpell(10621, SPEC_MASK_ALL, false); // Wolfshead Helm
player->removeSpell(10647, SPEC_MASK_ALL, false); // Feathered Breastplate
break;
case S_UNLEARN_SPELLFIRE: // S_UNLEARN_SPELLFIRE
player->removeSpell(26752, SPEC_MASK_ALL, false); // Spellfire Belt
@@ -950,44 +985,39 @@ public:
bool OnGossipHello(Player* player, Creature* creature) override
{
ClearGossipMenuFor(player);
if (creature->IsQuestGiver())
{
player->PrepareQuestMenu(creature->GetGUID());
}
if (creature->IsVendor())
AddGossipItemFor(player, GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
// pussywizard: NO UNLEARNING! LEATHERWORKING SPECIALTY IS A PERMANENT DECISION AND CANNOT BE CHANGED IN ANY WAY!
// pussywizard: CAN RE-LEARN ONLY THE ONE FOR WHICH QUEST IS COMPLETED!
if (player->HasSkill(SKILL_LEATHERWORKING) && player->GetBaseSkillValue(SKILL_LEATHERWORKING) >= 250 && player->getLevel() > 49)
if (player->HasSkill(SKILL_LEATHERWORKING) && player->GetBaseSkillValue(SKILL_LEATHERWORKING) >= 225 && player->getLevel() > 40)
{
switch (creature->GetEntry())
{
case N_TRAINER_DRAGON1: //Peter Galen
case N_TRAINER_DRAGON2: //Thorkaf Dragoneye
if (!HasLeatherSpecialty(player) && (player->GetQuestRewardStatus(5141) || player->GetQuestRewardStatus(5145)))
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_LEARN_DRAGON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
case N_TRAINER_DRAGON1: //Peter Galen
case N_TRAINER_DRAGON2: //Thorkaf Dragoneye
if (player->HasSpell(S_DRAGON))
{
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN);
AddGossipItemFor(player, creature->GetEntry() == N_TRAINER_DRAGON1 ? GOSSIP_MENU_PETER_GALEN : GOSSIP_MENU_THORKAF_DRAGONEYE, GOSSIP_MENU_OPTION_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN);
AddGossipItemFor(player, creature->GetEntry() == N_TRAINER_DRAGON1 ? GOSSIP_MENU_PETER_GALEN : GOSSIP_MENU_THORKAF_DRAGONEYE, GOSSIP_MENU_OPTION_CONFIRM_UNLEARN_DRAGONSCALE, GOSSIP_SENDER_MAIN, GOSSIP_MENU_UNLEARN_CONFIRM_DRAGONSCALE);
}
break;
case N_TRAINER_ELEMENTAL1: //Sarah Tanner
case N_TRAINER_ELEMENTAL2: //Brumn Winterhoof
if (!HasLeatherSpecialty(player) && (player->GetQuestRewardStatus(5144) || player->GetQuestRewardStatus(5146)))
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_LEARN_ELEMENTAL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
case N_TRAINER_ELEMENTAL1: //Sarah Tanner
case N_TRAINER_ELEMENTAL2: //Brumn Winterhoof
if (player->HasSpell(S_ELEMENTAL))
{
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN);
AddGossipItemFor(player, creature->GetEntry() == N_TRAINER_ELEMENTAL1 ? GOSSIP_MENU_SARAH_TANNER : GOSSIP_MENU_BRUMN_WINTERHOOF, GOSSIP_MENU_OPTION_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN);
AddGossipItemFor(player, creature->GetEntry() == N_TRAINER_ELEMENTAL1 ? GOSSIP_MENU_SARAH_TANNER : GOSSIP_MENU_BRUMN_WINTERHOOF, GOSSIP_MENU_OPTION_CONFIRM_UNLEARN_ELEMENTAL, GOSSIP_SENDER_MAIN, GOSSIP_MENU_UNLEARN_CONFIRM_ELEMENTAL);
}
break;
case N_TRAINER_TRIBAL1: //Caryssia Moonhunter
case N_TRAINER_TRIBAL2: //Se'Jib
if (!HasLeatherSpecialty(player) && (player->GetQuestRewardStatus(5143) || player->GetQuestRewardStatus(5148)))
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_LEARN_TRIBAL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
case N_TRAINER_TRIBAL1: //Caryssia Moonhunter
case N_TRAINER_TRIBAL2: //Se'Jib
if (player->HasSpell(S_TRIBAL))
{
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN);
AddGossipItemFor(player, creature->GetEntry() == N_TRAINER_TRIBAL1 ? GOSSIP_MENU_CARYSSIA_MOONHUNTER : GOSSIP_MENU_SEJIB, GOSSIP_MENU_OPTION_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN);
AddGossipItemFor(player, creature->GetEntry() == N_TRAINER_TRIBAL1 ? GOSSIP_MENU_CARYSSIA_MOONHUNTER : GOSSIP_MENU_SEJIB, GOSSIP_MENU_OPTION_CONFIRM_UNLEARN_TRIBAL, GOSSIP_SENDER_MAIN, GOSSIP_MENU_UNLEARN_CONFIRM_TRIBAL);
}
break;
}
@@ -997,36 +1027,35 @@ public:
return true;
}
void SendActionMenu(Player* player, Creature* creature, uint32 action)
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
{
ClearGossipMenuFor(player);
switch (action)
{
case GOSSIP_ACTION_TRADE:
player->GetSession()->SendListInventory(creature->GetGUID());
break;
case GOSSIP_ACTION_TRAIN:
player->GetSession()->SendTrainerList(creature->GetGUID());
break;
// Learn Leather
case GOSSIP_MENU_UNLEARN_CONFIRM_DRAGONSCALE:
AddGossipItemFor(player, GOSSIP_MENU_UNLEARN_CONFIRM_DRAGONSCALE, GOSSIP_MENU_OPTION_CONFIRM_UNLEARN_DRAGONSCALE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1, DoMedUnlearnCost(player));
SendGossipMenuFor(player, GOSSIP_TEXT_UNLEARN_CONFIRM_DRAGONSCALE, creature);
break;
case GOSSIP_MENU_UNLEARN_CONFIRM_ELEMENTAL:
AddGossipItemFor(player, GOSSIP_MENU_UNLEARN_CONFIRM_ELEMENTAL, GOSSIP_MENU_OPTION_CONFIRM_UNLEARN_ELEMENTAL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2, DoMedUnlearnCost(player));
SendGossipMenuFor(player, GOSSIP_TEXT_UNLEARN_CONFIRM_ELEMENTAL, creature);
break;
case GOSSIP_MENU_UNLEARN_CONFIRM_TRIBAL:
AddGossipItemFor(player, GOSSIP_MENU_UNLEARN_CONFIRM_TRIBAL, GOSSIP_MENU_OPTION_CONFIRM_UNLEARN_TRIBAL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3, DoMedUnlearnCost(player));
SendGossipMenuFor(player, GOSSIP_TEXT_UNLEARN_CONFIRM_TRIBAL, creature);
break;
case GOSSIP_ACTION_INFO_DEF + 1:
ProcessCastaction(player, creature, S_DRAGON, S_LEARN_DRAGON, 0);
ProcessUnlearnAction(player, creature, S_UNLEARN_DRAGON, 0, DoMedUnlearnCost(player));
break;
case GOSSIP_ACTION_INFO_DEF + 2:
ProcessCastaction(player, creature, S_ELEMENTAL, S_LEARN_ELEMENTAL, 0);
ProcessUnlearnAction(player, creature, S_UNLEARN_ELEMENTAL, 0, DoMedUnlearnCost(player));
break;
case GOSSIP_ACTION_INFO_DEF + 3:
ProcessCastaction(player, creature, S_TRIBAL, S_LEARN_TRIBAL, 0);
break;
}
}
bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action) override
{
ClearGossipMenuFor(player);
switch (sender)
{
case GOSSIP_SENDER_MAIN:
SendActionMenu(player, creature, action);
ProcessUnlearnAction(player, creature, S_UNLEARN_TRIBAL, 0, DoMedUnlearnCost(player));
break;
}
return true;
@@ -1210,9 +1239,14 @@ class go_evil_book_for_dummies : public GameObjectScript
public:
go_evil_book_for_dummies() : GameObjectScript("go_evil_book_for_dummies") { }
inline bool HasLeatherSpecialty(Player* player)
{
return (player->HasSpell(S_DRAGON) || player->HasSpell(S_ELEMENTAL) || player->HasSpell(S_TRIBAL));
}
bool OnGossipHello(Player* player, GameObject* gameobject) override
{
//TAILORING SPEC
//ENGINEERING SPEC
if (player->HasSkill(SKILL_ENGINEERING) && player->GetBaseSkillValue(SKILL_ENGINEERING) >= 225 && player->getLevel() >= 35)
{
if (player->GetQuestRewardStatus(3643) || player->GetQuestRewardStatus(3641) || player->GetQuestRewardStatus(3639))
@@ -1233,6 +1267,17 @@ public:
}
}
//LEATHERWORKING SPEC
if (player->HasSkill(SKILL_LEATHERWORKING) && player->GetBaseSkillValue(SKILL_LEATHERWORKING) >= 225 && player->getLevel() >= 40)
{
if (!HasLeatherSpecialty(player) && (player->GetQuestRewardStatus(5141) || player->GetQuestRewardStatus(5143) || player->GetQuestRewardStatus(5144) || player->GetQuestRewardStatus(5145) || player->GetQuestRewardStatus(5146) || player->GetQuestRewardStatus(5148)))
{
AddGossipItemFor(player, GOSSIP_MENU_GO_SOOTHSAYING_FOR_DUMMIES, GOSSIP_MENU_OPTION_GO_LEARN_DRAGONSCALE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
AddGossipItemFor(player, GOSSIP_MENU_GO_SOOTHSAYING_FOR_DUMMIES, GOSSIP_MENU_OPTION_GO_LEARN_ELEMENTAL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6);
AddGossipItemFor(player, GOSSIP_MENU_GO_SOOTHSAYING_FOR_DUMMIES, GOSSIP_MENU_OPTION_GO_LEARN_TRIBAL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7);
}
}
SendGossipMenuFor(player, player->GetGossipTextId(gameobject), gameobject->GetGUID());
return true;
}
@@ -1257,6 +1302,18 @@ public:
case GOSSIP_ACTION_INFO_DEF + 4:
ProcessUnlearnAction(player, nullptr, S_UNLEARN_GNOMISH, 0, DoHighUnlearnCost(player));
break;
//Learn Dragon
case GOSSIP_ACTION_INFO_DEF + 5:
ProcessCastaction(player, nullptr, S_DRAGON, S_LEARN_DRAGON, 0);
break;
//Learn Elemental
case GOSSIP_ACTION_INFO_DEF + 6:
ProcessCastaction(player, nullptr, S_ELEMENTAL, S_LEARN_ELEMENTAL, 0);
break;
//Learn Tribal
case GOSSIP_ACTION_INFO_DEF + 7:
ProcessCastaction(player, nullptr, S_TRIBAL, S_LEARN_TRIBAL, 0);
break;
}
}