Merge branch 'azerothcore:master' into Playerbot

This commit is contained in:
ZhengPeiRu21
2022-03-24 08:28:09 -06:00
committed by GitHub
14 changed files with 251 additions and 33 deletions

View File

@@ -1,5 +1,5 @@
{
"name": "azerothcore-wotlk",
"version": "6.0.0-dev.2",
"version": "6.0.0-dev.3",
"license": "AGPL3"
}

View File

@@ -0,0 +1,35 @@
-- DB update 2022_03_23_02 -> 2022_03_23_03
DROP PROCEDURE IF EXISTS `updateDb`;
DELIMITER //
CREATE PROCEDURE updateDb ()
proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE';
SELECT COUNT(*) INTO @COLEXISTS
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2022_03_23_02';
IF @COLEXISTS = 0 THEN LEAVE proc; END IF;
START TRANSACTION;
ALTER TABLE version_db_world CHANGE COLUMN 2022_03_23_02 2022_03_23_03 bit;
SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1647530609689243500'; IF OK <> 'FALSE' THEN LEAVE proc; END IF;
--
-- START UPDATING QUERIES
--
INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1647530609689243500');
DELETE FROM `creature` WHERE `guid` = 84205 AND `id1` = 14459;
INSERT INTO `creature` (`guid`, `id1`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`,`equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`) VALUES
(84205,14459,469,0,0,1,1,0,-7644.53,-1081.53,408.574,5.2709,10,0,0,42,0,0,0,0,0,'',0);
DELETE FROM `creature_text` WHERE `CreatureID` = 14459;
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration` ,`Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(14459, 0, 0, '%s flee as the controlling power of the orb is drained.', 16, 0, 100, 0, 0, 0, 9592, 3, '');
--
-- END UPDATING QUERIES
--
UPDATE version_db_world SET date = '2022_03_23_03' WHERE sql_rev = '1647530609689243500';
COMMIT;
END //
DELIMITER ;
CALL updateDb();
DROP PROCEDURE IF EXISTS `updateDb`;

View File

@@ -1,3 +1,15 @@
## 6.0.0-dev.3 | Commit: [44b7a0666c78dc99ab0bbc94045abb6685b3ad86
](https://github.com/azerothcore/azerothcore-wotlk/commit/44b7a0666c78dc99ab0bbc94045abb6685b3ad86
### Added
- New hook for OnQuestComputeXP(). The intended use is to change the XP values for certain quests programmatically. The hook is triggered after XP calculation and before rewarding XP or gold to the player.
### How to upgrade
- No special changes needed. The new hook is available for use and should not interfere with any existing hooks or logic.
## 6.0.0-dev.2 | Commit: [680e60c68b1864596bf23d427e9f4742c6437b86
](https://github.com/azerothcore/azerothcore-wotlk/commit/680e60c68b1864596bf23d427e9f4742c6437b86

View File

@@ -334,6 +334,9 @@ public:
static AISpellInfoType* AISpellInfo;
static void FillAISpellInfo();
// Called when a summon reaches a waypoint or point movement finished.
virtual void SummonMovementInform(Creature* /*creature*/, uint32 /*motionType*/, uint32 /*point*/) { }
virtual void sGossipHello(Player* /*player*/) {}
virtual void sGossipSelect(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/) {}
virtual void sGossipSelectCode(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/, char const* /*code*/) {}

View File

@@ -3529,3 +3529,8 @@ void Creature::SetRespawnTime(uint32 respawn)
{
m_respawnTime = respawn ? GameTime::GetGameTime().count() + respawn : 0;
}
void Creature::SetCorpseRemoveTime(uint32 delay)
{
m_corpseRemoveTime = GameTime::GetGameTime().count() + delay;
}

View File

@@ -69,6 +69,7 @@ public:
void GetRespawnPosition(float& x, float& y, float& z, float* ori = nullptr, float* dist = nullptr) const;
void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; }
void SetCorpseRemoveTime(uint32 delay);
[[nodiscard]] uint32 GetCorpseDelay() const { return m_corpseDelay; }
[[nodiscard]] bool IsRacialLeader() const { return GetCreatureTemplate()->RacialLeader; }
[[nodiscard]] bool IsCivilian() const { return GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_CIVILIAN; }
@@ -394,7 +395,7 @@ protected:
ObjectGuid::LowType m_lootRecipientGroup;
/// Timers
time_t m_corpseRemoveTime; // (msecs)timer for death or corpse disappearance
time_t m_corpseRemoveTime; // (secs) timer for death or corpse disappearance
time_t m_respawnTime; // (secs) time of next respawn
time_t m_respawnedTime; // (secs) time when creature respawned
uint32 m_respawnDelay; // (secs) delay between corpse disappearance and respawning

View File

@@ -408,6 +408,22 @@ void InstanceScript::DoRespawnGameObject(ObjectGuid uiGuid, uint32 uiTimeToDespa
}
}
void InstanceScript::DoRespawnCreature(ObjectGuid guid, bool force)
{
if (Creature* creature = instance->GetCreature(guid))
{
creature->Respawn(force);
}
}
void InstanceScript::DoRespawnCreature(uint32 type, bool force)
{
if (Creature* creature = instance->GetCreature(GetObjectGuid(type)))
{
creature->Respawn(force);
}
}
void InstanceScript::DoUpdateWorldState(uint32 uiStateId, uint32 uiStateData)
{
Map::PlayerList const& lPlayers = instance->GetPlayers();

View File

@@ -194,6 +194,12 @@ public:
//Respawns a GO having negative spawntimesecs in gameobject-table
void DoRespawnGameObject(ObjectGuid guid, uint32 timeToDespawn = MINUTE);
// Respawns a creature.
void DoRespawnCreature(ObjectGuid guid, bool force = false);
// Respawns a creature from the creature object storage.
void DoRespawnCreature(uint32 type, bool force = false);
//sends world state update to all players in instance
void DoUpdateWorldState(uint32 worldstateId, uint32 worldstateValue);

View File

@@ -197,6 +197,14 @@ template <> void PointMovementGenerator<Creature>::MovementInform(Creature* unit
{
if (unit->AI())
unit->AI()->MovementInform(POINT_MOTION_TYPE, id);
if (Unit* summoner = unit->GetCharmerOrOwner())
{
if (UnitAI* AI = summoner->GetAI())
{
AI->SummonMovementInform(unit, POINT_MOTION_TYPE, id);
}
}
}
template void PointMovementGenerator<Player>::DoInitialize(Player*);

View File

@@ -256,6 +256,14 @@ void WaypointMovementGenerator<Creature>::MovementInform(Creature* creature)
{
if (creature->AI())
creature->AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode);
if (Unit* owner = creature->GetCharmerOrOwner())
{
if (UnitAI* AI = owner->GetAI())
{
AI->SummonMovementInform(creature, WAYPOINT_MOTION_TYPE, i_currentNode);
}
}
}
//----------------------------------------------------//

View File

@@ -4243,6 +4243,12 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->Effects[EFFECT_0].DieSides = 1250;
});
// Explosion - Razorgore
ApplySpellFix({ 20038 }, [](SpellInfo* spellInfo)
{
spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS);
});
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
{
SpellInfo* spellInfo = mSpellInfoMap[i];

View File

@@ -39,13 +39,18 @@ enum BWLEncounter
// Additional Data
DATA_LORD_VICTOR_NEFARIUS = 8,
DATA_GRETHOK = 9,
DATA_NEFARIAN_TROOPS = 10,
// Doors
DATA_GO_CHROMAGGUS_DOOR = 9
DATA_GO_CHROMAGGUS_DOOR = 11
};
enum BWLCreatureIds
{
NPC_GRETHOK = 12557,
NPC_BLACKWING_GUARDSMAN = 14456,
NPC_NEFARIAN_TROOPS = 14459,
NPC_RAZORGORE = 12435,
NPC_BLACKWING_DRAGON = 12422,
NPC_BLACKWING_TASKMASTER = 12458,

View File

@@ -27,6 +27,8 @@ enum Say
SAY_EGGS_BROKEN2 = 1,
SAY_EGGS_BROKEN3 = 2,
SAY_DEATH = 3,
EMOTE_TROOPS_RETREAT = 0
};
enum Spells
@@ -38,7 +40,12 @@ enum Spells
SPELL_CLEAVE = 19632,
SPELL_WARSTOMP = 24375,
SPELL_FIREBALLVOLLEY = 22425,
SPELL_CONFLAGRATION = 23023
SPELL_CONFLAGRATION = 23023,
SPELL_EXPLODE_ORB = 20037,
SPELL_EXPLOSION = 20038, // Instakill everything.
SPELL_WARMING_FLAMES = 23040,
};
enum Summons
@@ -72,16 +79,19 @@ public:
void Reset() override
{
_Reset();
_died = false;
_charmerGUID.Clear();
secondPhase = false;
summons.DespawnAll();
instance->SetData(DATA_EGG_EVENT, NOT_STARTED);
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
if (secondPhase)
{
_JustDied();
}
}
bool CanAIAttack(Unit const* target) const override
@@ -93,6 +103,11 @@ public:
{
_EnterCombat();
events.ScheduleEvent(EVENT_CLEAVE, 15000);
events.ScheduleEvent(EVENT_STOMP, 35000);
events.ScheduleEvent(EVENT_FIREBALL, 7000);
events.ScheduleEvent(EVENT_CONFLAGRATION, 12000);
instance->SetData(DATA_EGG_EVENT, IN_PROGRESS);
}
@@ -101,12 +116,26 @@ public:
secondPhase = true;
_charmerGUID.Clear();
me->RemoveAllAuras();
me->SetHealth(me->GetMaxHealth());
events.ScheduleEvent(EVENT_CLEAVE, 15000);
events.ScheduleEvent(EVENT_STOMP, 35000);
events.ScheduleEvent(EVENT_FIREBALL, 7000);
events.ScheduleEvent(EVENT_CONFLAGRATION, 12000);
DoCastSelf(SPELL_WARMING_FLAMES, true);
if (Creature* troops = instance->GetCreature(DATA_NEFARIAN_TROOPS))
{
troops->AI()->Talk(EMOTE_TROOPS_RETREAT);
}
for (ObjectGuid const& guid : _summonGUIDS)
{
if (Creature* creature = ObjectAccessor::GetCreature(*me, guid))
{
if (creature->IsAlive())
{
creature->CombatStop(true);
creature->SetReactState(REACT_PASSIVE);
creature->GetMotionMaster()->MovePoint(0, Position(-7560.568848f, -1028.553345f, 408.491211f, 0.523858f));
}
}
}
}
void SetGUID(ObjectGuid const guid, int32 /*id*/) override
@@ -123,6 +152,13 @@ public:
charmer->CastSpell(charmer, SPELL_MIND_EXHAUSTION, true);
}
}
else
{
if (Unit* charmer = ObjectAccessor::GetUnit(*me, _charmerGUID))
{
me->TauntApply(charmer);
}
}
}
void DoAction(int32 action) override
@@ -138,12 +174,41 @@ public:
}
}
void JustSummoned(Creature* summon) override
{
_summonGUIDS.push_back(summon->GetGUID());
summon->SetOwnerGUID(me->GetGUID());
summons.Summon(summon);
}
void SummonMovementInform(Creature* summon, uint32 movementType, uint32 /*pathId*/) override
{
if (movementType == POINT_MOTION_TYPE)
{
summon->DespawnOrUnsummon();
}
}
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (!secondPhase && damage >= me->GetHealth())
if (!secondPhase && damage >= me->GetHealth() && !_died)
{
damage = me->GetHealth() - 1;
EnterEvadeMode();
// This is required because he kills himself with the explosion spell, causing a loop.
_died = true;
Talk(SAY_DEATH);
DoCastAOE(SPELL_EXPLODE_ORB);
DoCastAOE(SPELL_EXPLOSION);
// Respawn shorty in case of failure during phase 1.
me->SetCorpseRemoveTime(25);
me->SetRespawnTime(30);
me->SaveRespawnTime();
// Might not be required, safe measure.
me->SetLootRecipient(nullptr);
instance->SetData(DATA_EGG_EVENT, FAIL);
}
}
@@ -152,7 +217,10 @@ public:
if (!UpdateVictim())
return;
events.Update(diff);
if (!me->IsCharmed())
{
events.Update(diff);
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
@@ -176,18 +244,21 @@ public:
case EVENT_CONFLAGRATION:
DoCastVictim(SPELL_CONFLAGRATION);
if (me->GetVictim() && me->GetVictim()->HasAura(SPELL_CONFLAGRATION))
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100, true))
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1))
me->TauntApply(target);
events.ScheduleEvent(EVENT_CONFLAGRATION, 30000);
break;
}
}
DoMeleeAttackIfReady();
}
private:
bool secondPhase;
bool _died;
ObjectGuid _charmerGUID;
GuidVector _summonGUIDS;
};
CreatureAI* GetAI(Creature* creature) const override

View File

@@ -41,6 +41,12 @@ DoorData const doorData[] =
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE} // END
};
ObjectData const creatureData[] =
{
{ NPC_GRETHOK, DATA_GRETHOK },
{ NPC_NEFARIAN_TROOPS, DATA_NEFARIAN_TROOPS }
};
Position const SummonPosition[8] =
{
{-7661.207520f, -1043.268188f, 407.199554f, 6.280452f},
@@ -67,7 +73,7 @@ public:
//SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadDoorData(doorData);
//LoadObjectData(creatureData, gameObjectData);
LoadObjectData(creatureData, nullptr);
}
void Initialize() override
@@ -98,6 +104,9 @@ public:
if (CreatureAI* razorAI = razor->AI())
razorAI->JustSummoned(creature);
break;
case NPC_BLACKWING_GUARDSMAN:
guardList.push_back(creature->GetGUID());
break;
case NPC_NEFARIAN:
nefarianGUID = creature->GetGUID();
break;
@@ -135,11 +144,14 @@ public:
{
case GO_BLACK_DRAGON_EGG:
if (GetBossState(DATA_FIREMAW) == DONE)
{
go->SetPhaseMask(2, true);
}
else
{
EggList.push_back(go->GetGUID());
}
break;
case GO_PORTCULLIS_RAZORGORE:
case GO_PORTCULLIS_VAELASTRASZ:
case GO_PORTCULLIS_BROODLORD:
@@ -233,10 +245,15 @@ public:
if (state == DONE)
{
for (ObjectGuid const& guid : EggList)
{
// Eggs should be destroyed instead
// @todo: after dynamic spawns
if (GameObject* egg = instance->GetGameObject(guid))
{
egg->SetPhaseMask(2, true);
}
}
}
SetData(DATA_EGG_EVENT, NOT_STARTED);
break;
case DATA_CHROMAGGUS:
if (state == DONE)
@@ -270,7 +287,7 @@ public:
switch (data)
{
case IN_PROGRESS:
_events.ScheduleEvent(EVENT_RAZOR_SPAWN, 45000);
_events.ScheduleEvent(EVENT_RAZOR_SPAWN, 45 * IN_MILLISECONDS);
EggEvent = data;
EggCount = 0;
break;
@@ -278,13 +295,19 @@ public:
_events.CancelEvent(EVENT_RAZOR_SPAWN);
EggEvent = data;
EggCount = 0;
for (ObjectGuid const& guid : EggList)
{
if (GameObject* egg = instance->GetGameObject(guid))
{
egg->Respawn();
}
DoRespawnGameObject(guid, 0);
}
DoRespawnCreature(DATA_GRETHOK);
for (ObjectGuid const& guid : guardList)
{
DoRespawnCreature(guid);
}
break;
case SPECIAL:
if (++EggCount >= EggList.size())
@@ -336,12 +359,22 @@ public:
void OnUnitDeath(Unit* unit) override
{
//! 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_RAZORGORE:
//! HACK, needed because of buggy CreatureAI after charm
if (EggEvent == DONE)
{
if (unit->GetEntry() == NPC_RAZORGORE && GetBossState(DATA_RAZORGORE_THE_UNTAMED) != DONE)
{
SetBossState(DATA_RAZORGORE_THE_UNTAMED, DONE);
}
}
else
{
_events.CancelEvent(EVENT_RAZOR_SPAWN);
}
break;
case NPC_BLACK_DRAKONID:
case NPC_BLUE_DRAKONID:
case NPC_BRONZE_DRAKONID:
@@ -379,10 +412,18 @@ public:
switch (eventId)
{
case EVENT_RAZOR_SPAWN:
for (uint8 i = urand(2, 5); i > 0; --i)
if (Creature* summon = instance->SummonCreature(Entry[urand(0, 2)], SummonPosition[urand(0, 7)]))
summon->AI()->DoZoneInCombat();
_events.ScheduleEvent(EVENT_RAZOR_SPAWN, 12000, 17000);
if (EggEvent == IN_PROGRESS)
{
for (uint8 i = urand(2, 5); i > 0; --i)
{
if (Creature* summon = instance->SummonCreature(Entry[urand(0, 2)], SummonPosition[urand(0, 7)]))
{
summon->AI()->DoZoneInCombat();
}
}
_events.ScheduleEvent(EVENT_RAZOR_SPAWN, 12000, 17000);
}
break;
case EVENT_RAZOR_PHASE_TWO:
_events.CancelEvent(EVENT_RAZOR_SPAWN);
@@ -462,6 +503,7 @@ public:
uint8 EggCount;
uint32 EggEvent;
GuidList EggList;
GuidList guardList;
// Nefarian
uint32 NefarianLeftTunnel;