mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-25 22:56:24 +00:00
Merge branch 'master' into Playerbot
This commit is contained in:
@@ -887,7 +887,7 @@ void Player::FailQuest(uint32 questId)
|
||||
{
|
||||
QuestStatus qStatus = GetQuestStatus(questId);
|
||||
// xinef: if quest is marked as failed, dont do it again
|
||||
if ((qStatus != QUEST_STATUS_INCOMPLETE) && (!quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED)))
|
||||
if ((qStatus != QUEST_STATUS_INCOMPLETE) && (!quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_CAN_FAIL_IN_ANY_STATE)))
|
||||
return;
|
||||
|
||||
SetQuestStatus(questId, QUEST_STATUS_FAILED);
|
||||
|
||||
@@ -108,6 +108,14 @@ bool ChaseMovementGenerator<T>::DoUpdate(T* owner, uint32 time_diff)
|
||||
mutualChase = true;
|
||||
}
|
||||
|
||||
// Prevent almost infinite spinning for pets with mutualTarget
|
||||
// _mutualChase is false for previous check
|
||||
if (angle && !mutualChase && !_mutualChase && mutualTarget && chaseRange < meleeRange && cOwner && cOwner->IsPet())
|
||||
{
|
||||
angle = Optional<ChaseAngle>();
|
||||
mutualChase = true;
|
||||
}
|
||||
|
||||
// periodically check if we're already in the expected range...
|
||||
i_recheckDistance.Update(time_diff);
|
||||
if (i_recheckDistance.Passed())
|
||||
|
||||
@@ -157,23 +157,25 @@ enum QuestSpecialFlags
|
||||
{
|
||||
QUEST_SPECIAL_FLAGS_NONE = 0x000,
|
||||
// Trinity flags for set SpecialFlags in DB if required but used only at server
|
||||
QUEST_SPECIAL_FLAGS_REPEATABLE = 0x001, // Set by 1 in SpecialFlags from DB
|
||||
QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT = 0x002, // Set by 2 in SpecialFlags from DB (if required area explore, spell SPELL_EFFECT_QUEST_COMPLETE casting, table `FECT_QUEST_COMPLETE casting, table `*_script` command SCRIPT_COMMAND_QUEST_EXPLORED use, set from script)
|
||||
QUEST_SPECIAL_FLAGS_AUTO_ACCEPT = 0x004, // Set by 4 in SpecialFlags in DB if the quest is to be auto-accepted.
|
||||
QUEST_SPECIAL_FLAGS_DF_QUEST = 0x008, // Set by 8 in SpecialFlags in DB if the quest is used by Dungeon Finder.
|
||||
QUEST_SPECIAL_FLAGS_MONTHLY = 0x010, // Set by 16 in SpecialFlags in DB if the quest is reset at the begining of the month
|
||||
QUEST_SPECIAL_FLAGS_CAST = 0x020, // Set by 32 in SpecialFlags in DB if the quest requires RequiredOrNpcGo killcredit but NOT kill (a spell cast)
|
||||
QUEST_SPECIAL_FLAGS_NO_REP_SPILLOVER = 0x040, // Set by 64 in SpecialFlags in DB if the quest does not share rewarded reputation with other allied factions
|
||||
QUEST_SPECIAL_FLAGS_REPEATABLE = 0x0001, // Set by 1 in SpecialFlags from DB
|
||||
QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT = 0x0002, // Set by 2 in SpecialFlags from DB (if required area explore, spell SPELL_EFFECT_QUEST_COMPLETE casting, table `FECT_QUEST_COMPLETE casting, table `*_script` command SCRIPT_COMMAND_QUEST_EXPLORED use, set from script)
|
||||
QUEST_SPECIAL_FLAGS_AUTO_ACCEPT = 0x0004, // Set by 4 in SpecialFlags in DB if the quest is to be auto-accepted.
|
||||
QUEST_SPECIAL_FLAGS_DF_QUEST = 0x0008, // Set by 8 in SpecialFlags in DB if the quest is used by Dungeon Finder.
|
||||
QUEST_SPECIAL_FLAGS_MONTHLY = 0x0010, // Set by 16 in SpecialFlags in DB if the quest is reset at the begining of the month
|
||||
QUEST_SPECIAL_FLAGS_CAST = 0x0020, // Set by 32 in SpecialFlags in DB if the quest requires RequiredOrNpcGo killcredit but NOT kill (a spell cast)
|
||||
QUEST_SPECIAL_FLAGS_NO_REP_SPILLOVER = 0x0040, // Set by 64 in SpecialFlags in DB if the quest does not share rewarded reputation with other allied factions
|
||||
QUEST_SPECIAL_FLAGS_CAN_FAIL_IN_ANY_STATE = 0x0080, // Set by 128 in SpecialFlags in DB if the quest is allowed to fail in Player::FailQuest() independant of its current state
|
||||
// room for more custom flags
|
||||
|
||||
QUEST_SPECIAL_FLAGS_DB_ALLOWED = QUEST_SPECIAL_FLAGS_REPEATABLE | QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT | QUEST_SPECIAL_FLAGS_AUTO_ACCEPT |
|
||||
QUEST_SPECIAL_FLAGS_DF_QUEST | QUEST_SPECIAL_FLAGS_MONTHLY | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_NO_REP_SPILLOVER,
|
||||
QUEST_SPECIAL_FLAGS_DF_QUEST | QUEST_SPECIAL_FLAGS_MONTHLY | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_NO_REP_SPILLOVER |
|
||||
QUEST_SPECIAL_FLAGS_CAN_FAIL_IN_ANY_STATE,
|
||||
|
||||
QUEST_SPECIAL_FLAGS_DELIVER = 0x080, // Internal flag computed only
|
||||
QUEST_SPECIAL_FLAGS_SPEAKTO = 0x100, // Internal flag computed only
|
||||
QUEST_SPECIAL_FLAGS_KILL = 0x200, // Internal flag computed only
|
||||
QUEST_SPECIAL_FLAGS_TIMED = 0x400, // Internal flag computed only
|
||||
QUEST_SPECIAL_FLAGS_PLAYER_KILL = 0x800 // Internal flag computed only
|
||||
QUEST_SPECIAL_FLAGS_DELIVER = 0x0100, // Internal flag computed only
|
||||
QUEST_SPECIAL_FLAGS_SPEAKTO = 0x0200, // Internal flag computed only
|
||||
QUEST_SPECIAL_FLAGS_KILL = 0x0400, // Internal flag computed only
|
||||
QUEST_SPECIAL_FLAGS_TIMED = 0x0800, // Internal flag computed only
|
||||
QUEST_SPECIAL_FLAGS_PLAYER_KILL = 0x1000 // Internal flag computed only
|
||||
};
|
||||
|
||||
struct QuestLocale
|
||||
|
||||
@@ -3710,6 +3710,7 @@ void Spell::cancel(bool bySelf)
|
||||
return;
|
||||
|
||||
uint32 oldState = m_spellState;
|
||||
bool autoRepeat = m_autoRepeat;
|
||||
m_spellState = SPELL_STATE_FINISHED;
|
||||
|
||||
m_autoRepeat = false;
|
||||
@@ -3724,9 +3725,11 @@ void Spell::cancel(bool bySelf)
|
||||
}
|
||||
[[fallthrough]];
|
||||
case SPELL_STATE_DELAYED:
|
||||
SendInterrupted(SPELL_FAILED_INTERRUPTED);
|
||||
SendInterrupted(0);
|
||||
// xinef: fixes bugged gcd reset in some cases
|
||||
if (!autoRepeat)
|
||||
SendCastResult(SPELL_FAILED_INTERRUPTED);
|
||||
break;
|
||||
|
||||
case SPELL_STATE_CASTING:
|
||||
if (!bySelf)
|
||||
{
|
||||
|
||||
@@ -676,10 +676,10 @@ struct npc_midsummer_ribbon_pole_target : public ScriptedAI
|
||||
}
|
||||
|
||||
// prevent duplicates
|
||||
if (std::find(_dancerList.begin(), _dancerList.end(), dancer) != _dancerList.end())
|
||||
if (std::find(_dancerList.begin(), _dancerList.end(), dancer->GetGUID()) != _dancerList.end())
|
||||
return;
|
||||
|
||||
_dancerList.push_back(dancer);
|
||||
_dancerList.push_back(dancer->GetGUID());
|
||||
}
|
||||
|
||||
void LocateRibbonPole()
|
||||
@@ -707,10 +707,11 @@ struct npc_midsummer_ribbon_pole_target : public ScriptedAI
|
||||
return;
|
||||
|
||||
// remove non-dancing players from list
|
||||
std::erase_if(_dancerList, [](Player* dancer)
|
||||
{
|
||||
return !dancer->HasAura(SPELL_RIBBON_POLE_PERIODIC_VISUAL);
|
||||
});
|
||||
std::erase_if(_dancerList, [this](ObjectGuid dancerGUID)
|
||||
{
|
||||
Player* dancer = ObjectAccessor::GetPlayer(*me, dancerGUID);
|
||||
return !dancer || !dancer->HasAura(SPELL_RIBBON_POLE_PERIODIC_VISUAL);
|
||||
});
|
||||
}
|
||||
|
||||
void DoFlameCircleChecks()
|
||||
@@ -788,9 +789,7 @@ struct npc_midsummer_ribbon_pole_target : public ScriptedAI
|
||||
|
||||
for (uint8 i = 0; (i < MAX_COUNT_SPEW_LAVA_TARGETS) && (i < _dancerList.size()); i++)
|
||||
{
|
||||
Player* dancerTarget = _dancerList[i];
|
||||
|
||||
if (dancerTarget)
|
||||
if (Player* dancerTarget = ObjectAccessor::GetPlayer(*me, _dancerList[i]))
|
||||
{
|
||||
Creature* fireSpiralBunny = dancerTarget->SummonCreature(NPC_RIBBON_POLE_FIRE_SPIRAL_BUNNY, dancerTarget->GetPositionX(), dancerTarget->GetPositionY(), dancerTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000);
|
||||
if (fireSpiralBunny)
|
||||
@@ -823,7 +822,7 @@ struct npc_midsummer_ribbon_pole_target : public ScriptedAI
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Player*> _dancerList;
|
||||
GuidVector _dancerList;
|
||||
GameObject* _ribbonPole;
|
||||
Creature* _bunny;
|
||||
};
|
||||
|
||||
@@ -530,7 +530,7 @@ public:
|
||||
}
|
||||
|
||||
context.Repeat(timerptr[_currentWave]);
|
||||
if (++_currentWave < maxWaves && _bossWave)
|
||||
if (++_currentWave < maxWaves && _bossWave != TO_BE_DECIDED)
|
||||
{
|
||||
DoUpdateWorldState(WORLD_STATE_WAVES, _currentWave);
|
||||
DoUpdateWorldState(WORLD_STATE_ENEMY, 1);
|
||||
|
||||
@@ -153,6 +153,8 @@ enum ThrallWarchief : uint32
|
||||
AREA_CAMP_TAURAJO = 378,
|
||||
AREA_CROSSROADS = 380,
|
||||
|
||||
GO_UNADORNED_SPIKE = 175787,
|
||||
|
||||
// What the Wind Carries (ID: 6566)
|
||||
QUEST_WHAT_THE_WIND_CARRIES = 6566,
|
||||
GOSSIP_MENU_THRALL = 3664,
|
||||
@@ -246,35 +248,50 @@ public:
|
||||
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
me->GetMap()->LoadGrid(heraldOfThrallPos.GetPositionX(), heraldOfThrallPos.GetPositionY());
|
||||
me->SummonCreature(NPC_HERALD_OF_THRALL, heraldOfThrallPos, TEMPSUMMON_TIMED_DESPAWN, 20 * IN_MILLISECONDS);
|
||||
_scheduler.Schedule(2s, [this](TaskContext /*context*/)
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR);
|
||||
scheduler.Schedule(1s, [this](TaskContext /*context*/)
|
||||
{
|
||||
if (GameObject* spike = me->FindNearestGameObject(GO_UNADORNED_SPIKE, 10.0f))
|
||||
{
|
||||
Talk(SAY_THRALL_ON_QUEST_REWARD_0);
|
||||
})
|
||||
.Schedule(13s, [this](TaskContext /*context*/)
|
||||
spike->SetGoState(GO_STATE_ACTIVE);
|
||||
}
|
||||
}).Schedule(2s, [this](TaskContext /*context*/)
|
||||
{
|
||||
Talk(SAY_THRALL_ON_QUEST_REWARD_0);
|
||||
}).Schedule(9s, [this](TaskContext /*context*/)
|
||||
{
|
||||
Talk(SAY_THRALL_ON_QUEST_REWARD_1);
|
||||
DoCastAOE(SPELL_WARCHIEF_BLESSING, true);
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
me->GetMap()->DoForAllPlayers([&](Player* player)
|
||||
{
|
||||
Talk(SAY_THRALL_ON_QUEST_REWARD_1);
|
||||
})
|
||||
.Schedule(15s, [this](TaskContext /*context*/)
|
||||
{
|
||||
DoCastAOE(SPELL_WARCHIEF_BLESSING, true);
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
me->GetMap()->DoForAllPlayers([&](Player* p)
|
||||
if (player->IsAlive() && !player->IsGameMaster())
|
||||
{
|
||||
if (player->GetAreaId() == AREA_ORGRIMMAR)
|
||||
{
|
||||
if (p->IsAlive() && !p->IsGameMaster())
|
||||
{
|
||||
if (p->GetAreaId() == AREA_ORGRIMMAR || p->GetAreaId() == AREA_RAZOR_HILL || p->GetAreaId() == AREA_CROSSROADS || p->GetAreaId() == AREA_CAMP_TAURAJO)
|
||||
{
|
||||
p->CastSpell(p, SPELL_WARCHIEF_BLESSING, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
player->CastSpell(player, SPELL_WARCHIEF_BLESSING, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}).Schedule(19s, [this](TaskContext /*context*/)
|
||||
{
|
||||
me->GetMap()->DoForAllPlayers([&](Player* player)
|
||||
{
|
||||
if (player->IsAlive() && !player->IsGameMaster())
|
||||
{
|
||||
if (player->GetAreaId() == AREA_CROSSROADS)
|
||||
{
|
||||
player->CastSpell(player, SPELL_WARCHIEF_BLESSING, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_scheduler.Update(diff);
|
||||
scheduler.Update(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
@@ -295,9 +312,6 @@ public:
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
protected:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -158,7 +158,9 @@ enum Points
|
||||
|
||||
enum Misc
|
||||
{
|
||||
MAX_FLAMECALLERS = 3
|
||||
MAX_FLAMECALLERS = 3,
|
||||
QUEST_SUMMON_AHUNE = 11691,
|
||||
ITEM_MAGMA_TOTEM = 34953
|
||||
};
|
||||
|
||||
Position const SummonPositions[] =
|
||||
@@ -307,8 +309,8 @@ struct npc_frozen_core : public ScriptedAI
|
||||
if (Creature* ahune = _instance->GetCreature(DATA_AHUNE))
|
||||
Unit::Kill(me, ahune);
|
||||
|
||||
DoCast(SPELL_SUMMON_LOOT_MISSILE);
|
||||
DoCast(SPELL_MINION_DESPAWNER);
|
||||
DoCastSelf(SPELL_SUMMON_LOOT_MISSILE, true);
|
||||
DoCastSelf(SPELL_MINION_DESPAWNER, true);
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
@@ -662,6 +664,9 @@ struct go_ahune_ice_stone : public GameObjectAI
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
|
||||
player->DestroyItemCount(ITEM_MAGMA_TOTEM, 1, true, false);
|
||||
player->AreaExploredOrEventHappens(QUEST_SUMMON_AHUNE); //auto rewarded
|
||||
|
||||
if (Creature* ahuneBunny = _instance->GetCreature(DATA_AHUNE_BUNNY))
|
||||
ahuneBunny->AI()->DoAction(ACTION_START_EVENT);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user