Merge branch 'azerothcore:master' into Playerbot

This commit is contained in:
ZhengPeiRu21
2022-05-06 16:13:01 -06:00
committed by GitHub
16 changed files with 371 additions and 103 deletions

View File

@@ -106,7 +106,7 @@ float UnitAI::DoGetSpellMaxRange(uint32 spellId, bool positive)
return spellInfo ? spellInfo->GetMaxRange(positive) : 0;
}
void UnitAI::DoAddAuraToAllHostilePlayers(uint32 spellid)
SpellCastResult UnitAI::DoAddAuraToAllHostilePlayers(uint32 spellid)
{
if (me->IsInCombat())
{
@@ -114,13 +114,22 @@ void UnitAI::DoAddAuraToAllHostilePlayers(uint32 spellid)
for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
{
if (Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()))
{
if (unit->GetTypeId() == TYPEID_PLAYER)
{
me->AddAura(spellid, unit);
return SPELL_CAST_OK;
}
}
else
return SPELL_FAILED_BAD_TARGETS;
}
}
return SPELL_FAILED_CUSTOM_ERROR;
}
void UnitAI::DoCastToAllHostilePlayers(uint32 spellid, bool triggered)
SpellCastResult UnitAI::DoCastToAllHostilePlayers(uint32 spellid, bool triggered)
{
if (me->IsInCombat())
{
@@ -128,13 +137,19 @@ void UnitAI::DoCastToAllHostilePlayers(uint32 spellid, bool triggered)
for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
{
if (Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()))
{
if (unit->GetTypeId() == TYPEID_PLAYER)
me->CastSpell(unit, spellid, triggered);
return me->CastSpell(unit, spellid, triggered);
}
else
return SPELL_FAILED_BAD_TARGETS;
}
}
return SPELL_FAILED_CUSTOM_ERROR;
}
void UnitAI::DoCast(uint32 spellId)
SpellCastResult UnitAI::DoCast(uint32 spellId)
{
Unit* target = nullptr;
@@ -149,10 +164,11 @@ void UnitAI::DoCast(uint32 spellId)
break;
case AITARGET_ENEMY:
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
bool playerOnly = spellInfo->HasAttribute(SPELL_ATTR3_ONLY_ON_PLAYER);
//float range = GetSpellMaxRange(spellInfo, false);
target = SelectTarget(SelectTargetMethod::Random, 0, spellInfo->GetMaxRange(false), playerOnly);
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId))
{
bool playerOnly = spellInfo->HasAttribute(SPELL_ATTR3_ONLY_ON_PLAYER);
target = SelectTarget(SelectTargetMethod::Random, 0, spellInfo->GetMaxRange(false), playerOnly);
}
break;
}
case AITARGET_ALLY:
@@ -163,59 +179,63 @@ void UnitAI::DoCast(uint32 spellId)
break;
case AITARGET_DEBUFF:
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
bool playerOnly = spellInfo->HasAttribute(SPELL_ATTR3_ONLY_ON_PLAYER);
float range = spellInfo->GetMaxRange(false);
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId))
{
bool playerOnly = spellInfo->HasAttribute(SPELL_ATTR3_ONLY_ON_PLAYER);
float range = spellInfo->GetMaxRange(false);
DefaultTargetSelector targetSelector(me, range, playerOnly, -(int32)spellId);
if (!(spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_VICTIM)
&& targetSelector(me->GetVictim()))
target = me->GetVictim();
else
target = SelectTarget(SelectTargetMethod::Random, 0, targetSelector);
DefaultTargetSelector targetSelector(me, range, playerOnly, -(int32)spellId);
if (!(spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_VICTIM)
&& targetSelector(me->GetVictim()))
target = me->GetVictim();
else
target = SelectTarget(SelectTargetMethod::Random, 0, targetSelector);
}
break;
}
}
if (target)
me->CastSpell(target, spellId, false);
return SPELL_FAILED_BAD_TARGETS;
}
void UnitAI::DoCast(Unit* victim, uint32 spellId, bool triggered)
SpellCastResult UnitAI::DoCast(Unit* victim, uint32 spellId, bool triggered)
{
if (!victim || (me->HasUnitState(UNIT_STATE_CASTING) && !triggered))
return;
if (!victim)
return SPELL_FAILED_BAD_TARGETS;
me->CastSpell(victim, spellId, triggered);
if (me->HasUnitState(UNIT_STATE_CASTING) && !triggered)
return SPELL_FAILED_SPELL_IN_PROGRESS;
return me->CastSpell(victim, spellId, triggered);
}
void UnitAI::DoCastVictim(uint32 spellId, bool triggered)
SpellCastResult UnitAI::DoCastVictim(uint32 spellId, bool triggered)
{
if (!me->GetVictim() || (me->HasUnitState(UNIT_STATE_CASTING) && !triggered))
return;
if (Unit* victim = me->GetVictim())
return DoCast(victim, spellId, triggered);
me->CastSpell(me->GetVictim(), spellId, triggered);
return SPELL_FAILED_BAD_TARGETS;
}
void UnitAI::DoCastAOE(uint32 spellId, bool triggered)
SpellCastResult UnitAI::DoCastAOE(uint32 spellId, bool triggered)
{
if (!triggered && me->HasUnitState(UNIT_STATE_CASTING))
return;
return SPELL_FAILED_SPELL_IN_PROGRESS;
me->CastSpell((Unit*)nullptr, spellId, triggered);
return me->CastSpell((Unit*)nullptr, spellId, triggered);
}
void UnitAI::DoCastRandomTarget(uint32 spellId, uint32 threatTablePosition, float dist, bool playerOnly, bool triggered)
SpellCastResult UnitAI::DoCastRandomTarget(uint32 spellId, uint32 threatTablePosition, float dist, bool playerOnly, bool triggered)
{
if (!triggered && me->HasUnitState(UNIT_STATE_CASTING))
{
return;
}
if (Unit* target = SelectTarget(SelectTargetMethod::Random, threatTablePosition, dist, playerOnly))
{
me->CastSpell(target, spellId, triggered);
return DoCast(target, spellId, triggered);
}
return SPELL_FAILED_BAD_TARGETS;
}
#define UPDATE_TARGET(a) {if (AIInfo->target<a) AIInfo->target=a;}

View File

@@ -317,14 +317,14 @@ public:
void AttackStartCaster(Unit* victim, float dist);
void DoAddAuraToAllHostilePlayers(uint32 spellid);
void DoCast(uint32 spellId);
void DoCast(Unit* victim, uint32 spellId, bool triggered = false);
inline void DoCastSelf(uint32 spellId, bool triggered = false) { DoCast(me, spellId, triggered); }
void DoCastToAllHostilePlayers(uint32 spellid, bool triggered = false);
void DoCastVictim(uint32 spellId, bool triggered = false);
void DoCastAOE(uint32 spellId, bool triggered = false);
void DoCastRandomTarget(uint32 spellId, uint32 threatTablePosition = 0, float dist = 0.0f, bool playerOnly = true, bool triggered = false);
SpellCastResult DoAddAuraToAllHostilePlayers(uint32 spellid);
SpellCastResult DoCast(uint32 spellId);
SpellCastResult DoCast(Unit* victim, uint32 spellId, bool triggered = false);
SpellCastResult DoCastSelf(uint32 spellId, bool triggered = false) { return DoCast(me, spellId, triggered); }
SpellCastResult DoCastToAllHostilePlayers(uint32 spellid, bool triggered = false);
SpellCastResult DoCastVictim(uint32 spellId, bool triggered = false);
SpellCastResult DoCastAOE(uint32 spellId, bool triggered = false);
SpellCastResult DoCastRandomTarget(uint32 spellId, uint32 threatTablePosition = 0, float dist = 0.0f, bool playerOnly = true, bool triggered = false);
float DoGetSpellMaxRange(uint32 spellId, bool positive = false);

View File

@@ -1417,6 +1417,7 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
trans->Append(stmt);
WorldDatabase.CommitTransaction(trans);
sScriptMgr->OnCreatureSaveToDB(this);
}
void Creature::SelectLevel(bool changelevel)

View File

@@ -1062,6 +1062,7 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask, bool
}
WorldDatabase.CommitTransaction(trans);
sScriptMgr->OnGameObjectSaveToDB(this);
}
bool GameObject::LoadGameObjectFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap)

View File

@@ -38,6 +38,16 @@ void ScriptMgr::OnCreatureRemoveWorld(Creature* creature)
});
}
void ScriptMgr::OnCreatureSaveToDB(Creature* creature)
{
ASSERT(creature);
ExecuteScript<AllCreatureScript>([&](AllCreatureScript* script)
{
script->OnCreatureSaveToDB(creature);
});
}
void ScriptMgr::Creature_SelectLevel(const CreatureTemplate* cinfo, Creature* creature)
{
ExecuteScript<AllCreatureScript>([&](AllCreatureScript* script)

View File

@@ -37,3 +37,13 @@ void ScriptMgr::OnGameObjectRemoveWorld(GameObject* go)
script->OnGameObjectRemoveWorld(go);
});
}
void ScriptMgr::OnGameObjectSaveToDB(GameObject* go)
{
ASSERT(go);
ExecuteScript<AllGameObjectScript>([&](AllGameObjectScript* script)
{
script->OnGameObjectSaveToDB(go);
});
}

View File

@@ -562,6 +562,13 @@ public:
*/
virtual void OnCreatureRemoveWorld(Creature* /*creature*/) { }
/**
* @brief This hook runs after creature has been saved to DB
*
* @param creature Contains information about the Creature
*/
virtual void OnCreatureSaveToDB(Creature* /*creature*/) { }
/**
* @brief This hook called when a player opens a gossip dialog with the creature.
*
@@ -644,7 +651,12 @@ public:
* @param go Contains information about the GameObject
*/
virtual void OnGameObjectAddWorld(GameObject* /*go*/) { }
/**
* @brief This hook runs after the game object iis saved to the database
*
* @param go Contains information about the GameObject
*/
virtual void OnGameObjectSaveToDB(GameObject* /*go*/) { }
/**
* @brief This hook runs after remove game object in world
*
@@ -2433,6 +2445,10 @@ public: /* AllCreatureScript */
//listener function (OnAllCreatureUpdate) is called by OnCreatureUpdate
//void OnAllCreatureUpdate(Creature* creature, uint32 diff);
void Creature_SelectLevel(const CreatureTemplate* cinfo, Creature* creature);
void OnCreatureSaveToDB(Creature* creature);
public: /* AllGameobjectScript */
void OnGameObjectSaveToDB(GameObject* go);
public: /* AllMapScript */
void OnBeforeCreateInstanceScript(InstanceMap* instanceMap, InstanceScript* instanceData, bool load, std::string data, uint32 completedEncounterMask);

View File

@@ -1658,20 +1658,22 @@ public:
{
// output that player don't have any items to destroy
handler->PSendSysMessage(LANG_REMOVEITEM_FAILURE, handler->GetNameLink(playerTarget).c_str(), itemId);
handler->SetSentErrorMessage(true);
return false;
}
else if (!playerTarget->HasItemCount(itemId, -count))
if (!playerTarget->HasItemCount(itemId, -count))
{
// output that player don't have as many items that you want to destroy
handler->PSendSysMessage(LANG_REMOVEITEM_ERROR, handler->GetNameLink(playerTarget).c_str(), itemId);
handler->SetSentErrorMessage(true);
return false;
}
}
else
{
// output successful amount of destroyed items
playerTarget->DestroyItemCount(itemId, -count, true, false);
handler->PSendSysMessage(LANG_REMOVEITEM, itemId, -count, handler->GetNameLink(playerTarget).c_str());
}
// output successful amount of destroyed items
playerTarget->DestroyItemCount(itemId, -count, true, false);
handler->PSendSysMessage(LANG_REMOVEITEM, itemId, -count, handler->GetNameLink(playerTarget).c_str());
return true;
}

View File

@@ -532,21 +532,26 @@ public:
break;
case 51:
{
uint32 entries[4] = { 15423, 15424, 15414, 15422 };
for (uint8 i = 0; i < 4; ++i)
std::list<Creature*> constructList;
me->GetCreatureListWithEntryInGrid(constructList, 15423, 100.0f);
me->GetCreatureListWithEntryInGrid(constructList, 15424, 100.0f);
me->GetCreatureListWithEntryInGrid(constructList, 15414, 100.0f);
me->GetCreatureListWithEntryInGrid(constructList, 15422, 100.0f);
if (!constructList.empty())
{
Unit* mob = player->FindNearestCreature(entries[i], 50, me);
while (mob)
for (std::list<Creature*>::const_iterator itr = constructList.begin(); itr != constructList.end(); ++itr)
{
mob->RemoveFromWorld();
mob = player->FindNearestCreature(15423, 50, me);
(*itr)->RemoveFromWorld();
}
}
break;
}
case 52:
Fandral->GetMotionMaster()->MoveCharge(-8028.75f, 1538.795f, 2.61f, 4);
Fandral->AI()->Talk(ANACHRONOS_SAY_9, me);
Talk(ANACHRONOS_SAY_9);
break;
case 53:
Fandral->AI()->Talk(FANDRAL_SAY_6);
@@ -555,7 +560,8 @@ public:
Talk(ANACHRONOS_EMOTE_2);
break;
case 55:
Fandral->SetVisible(false);
//Fandral should not dispear atm.
//Fandral->SetVisible(false);
break;
case 56:
Talk(ANACHRONOS_EMOTE_3);

View File

@@ -73,17 +73,6 @@ enum VezaxGOs
// GO_VEZAX_DOOR = 194750,
};
enum VezaxSounds
{
SOUND_VEZAX_AGGRO = 15542,
SOUND_VEZAX_SLAIN_1 = 15543,
SOUND_VEZAX_SLAIN_2 = 15544,
SOUND_VEZAX_SURGE = 15545,
SOUND_VEZAX_DEATH = 15546,
SOUND_VEZAX_BERSERK = 15547,
SOUND_VEZAX_HARDMODE = 15548,
};
enum VezaxEvents
{
EVENT_SPELL_VEZAX_SHADOW_CRASH = 1,
@@ -99,13 +88,23 @@ enum VezaxEvents
EVENT_RESTORE_TARGET = 11,
};
#define TEXT_VEZAX_AGGRO "Your destruction will herald a new age of suffering!"
#define TEXT_VEZAX_SLAIN_1 "You thought to stand before the legions of death... and survive?"
#define TEXT_VEZAX_SLAIN_2 "Defiance... a flaw of mortality."
#define TEXT_VEZAX_SURGE "The black blood of Yogg-Saron courses through me! I. AM. UNSTOPPABLE!"
#define TEXT_VEZAX_BERSERK "Your defeat was inevitable!"
#define TEXT_VEZAX_DEATH "Oh, what horrors await...."
#define TEXT_VEZAX_HARDMODE "Behold, now! Terror, absolute!"
enum VezaxText
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_SURGE_OF_DARKNESS = 2,
SAY_DEATH = 3,
SAY_BERSERK = 4,
SAY_HARDMODE = 5,
SAY_EMOTE_ANIMUS = 6,
SAY_EMOTE_BARRIER = 7,
SAY_EMOTE_SURGE_OF_DARKNESS = 8,
};
enum VaporsText
{
SAY_EMOTE_VAPORS = 0,
};
class boss_vezax : public CreatureScript
{
@@ -165,8 +164,7 @@ public:
events.RescheduleEvent(EVENT_SPELL_SUMMON_SARONITE_VAPORS, 30000);
events.RescheduleEvent(EVENT_BERSERK, 600000);
me->Yell(TEXT_VEZAX_AGGRO, LANG_UNIVERSAL);
me->PlayDirectSound(SOUND_VEZAX_AGGRO, 0);
Talk(SAY_AGGRO);
if (pInstance)
pInstance->SetData(TYPE_VEZAX, IN_PROGRESS);
@@ -226,8 +224,7 @@ public:
case EVENT_BERSERK:
berserk = true;
me->CastSpell(me, SPELL_VEZAX_BERSERK, true);
me->Yell(TEXT_VEZAX_BERSERK, LANG_UNIVERSAL);
me->PlayDirectSound(SOUND_VEZAX_BERSERK, 0);
Talk(SAY_BERSERK);
break;
case EVENT_SPELL_VEZAX_SHADOW_CRASH:
{
@@ -261,8 +258,8 @@ public:
events.RepeatEvent( me->GetMap()->Is25ManRaid() ? 8000 : 15000 );
break;
case EVENT_SPELL_SURGE_OF_DARKNESS:
me->Yell(TEXT_VEZAX_SURGE, LANG_UNIVERSAL);
me->PlayDirectSound(SOUND_VEZAX_SURGE, 0);
Talk(SAY_SURGE_OF_DARKNESS);
Talk(SAY_EMOTE_SURGE_OF_DARKNESS);
me->CastSpell(me, SPELL_SURGE_OF_DARKNESS, false);
events.RepeatEvent(63000);
events.DelayEvents(10000, 1);
@@ -298,7 +295,6 @@ public:
{
vaporsCount++;
me->CastSpell(me, SPELL_SUMMON_SARONITE_VAPORS, false);
me->TextEmote("A cloud of saronite vapors coalesces nearby!", nullptr, true);
if( vaporsCount < 6 || !hardmodeAvailable )
events.RepeatEvent(30000);
@@ -321,7 +317,7 @@ public:
case EVENT_SARONITE_VAPORS_SWIRL:
if (summons.size())
{
me->TextEmote("The saronite vapors mass and swirl violently, merging into a monstrous form!", nullptr, true);
Talk(SAY_EMOTE_ANIMUS);
if( Creature* sv = ObjectAccessor::GetCreature(*me, *(summons.begin())) )
sv->CastSpell(sv, SPELL_SARONITE_ANIMUS_FORMATION_VISUAL, true);
@@ -332,10 +328,8 @@ public:
case EVENT_SPELL_SUMMON_SARONITE_ANIMUS:
if (summons.size())
{
me->TextEmote("A saronite barrier appears around General Vezax!", nullptr, true);
me->Yell(TEXT_VEZAX_HARDMODE, LANG_UNIVERSAL);
me->PlayDirectSound(SOUND_VEZAX_HARDMODE, 0);
Talk(SAY_HARDMODE);
Talk(SAY_EMOTE_BARRIER);
me->CastSpell(me, SPELL_SARONITE_BARRIER, true);
if( Creature* sv = ObjectAccessor::GetCreature(*me, *(summons.begin())) )
sv->CastSpell(sv, SPELL_SUMMON_SARONITE_ANIMUS, true);
@@ -358,8 +352,7 @@ public:
if (pInstance)
pInstance->SetData(TYPE_VEZAX, DONE);
me->Yell(TEXT_VEZAX_DEATH, LANG_UNIVERSAL);
me->PlayDirectSound(SOUND_VEZAX_DEATH, 0);
Talk(SAY_DEATH);
if( GameObject* door = me->FindNearestGameObject(GO_VEZAX_DOOR, 500.0f) )
if( door->GetGoState() != GO_STATE_ACTIVE )
@@ -372,18 +365,7 @@ public:
void KilledUnit(Unit* who) override
{
if( who->GetTypeId() == TYPEID_PLAYER )
{
if( urand(0, 1) )
{
me->Yell(TEXT_VEZAX_SLAIN_1, LANG_UNIVERSAL);
me->PlayDirectSound(SOUND_VEZAX_SLAIN_1, 0);
}
else
{
me->Yell(TEXT_VEZAX_SLAIN_2, LANG_UNIVERSAL);
me->PlayDirectSound(SOUND_VEZAX_SLAIN_2, 0);
}
}
Talk(SAY_SLAY);
}
void MoveInLineOfSight(Unit* /*who*/) override {}
@@ -429,6 +411,11 @@ public:
if( Creature* vezax = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(TYPE_VEZAX)) )
vezax->AI()->DoAction(1);
}
void IsSummonedBy(Unit* /*summoner*/) override
{
Talk(SAY_EMOTE_VAPORS);
}
};
};